checker: stricter rules for C types; C aliases; sokol fixes

This commit is contained in:
Alexander Medvednikov 2023-10-14 18:31:37 +03:00
parent 5f1e6815cd
commit 545ee1ae23
27 changed files with 123 additions and 59 deletions

View file

@ -1,5 +1,5 @@
// Build with
// v -gc none -use-coroutines simple_coroutines.v
// v -use-coroutines simple_coroutines.v
//
import coroutines
import time

View file

@ -329,7 +329,7 @@ fn my_init(mut app App) {
mut pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
color_state := gfx.ColorState{
color_state := gfx.ColorTargetState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha

View file

@ -529,7 +529,7 @@ fn my_init(mut app App) {
mut pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
color_state := gfx.ColorState{
color_state := gfx.ColorTargetState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha

View file

@ -120,7 +120,7 @@ pub fn (mut obj_part ObjPart) create_pipeline(in_part []int, shader gfx.Shader,
// pipdesc.layout.attrs[C.ATTR_vs_a_Texcoord0].format = .short2n // u,v as u16
pipdesc.index_type = .uint32
color_state := gfx.ColorState{
color_state := gfx.ColorTargetState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha

View file

@ -83,7 +83,7 @@ fn init(mut app App) {
mut pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
color_state := gfx.ColorState{
color_state := gfx.ColorTargetState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha

View file

@ -329,7 +329,7 @@ fn app_init(mut app App) {
mut pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&pipdesc, 0, int(sizeof(pipdesc))) }
color_state := gfx.ColorState{
color_state := gfx.ColorTargetState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha

View file

@ -1,6 +1,7 @@
module builtin
// struct C.FILE {}
[typedef]
pub struct C.FILE {}
// <string.h>
fn C.memcpy(dest voidptr, const_src voidptr, n usize) voidptr
@ -226,6 +227,8 @@ fn C.sysctl(name &int, namelen u32, oldp voidptr, oldlenp voidptr, newp voidptr,
[trusted]
fn C._fileno(int) int
struct C.intptr_t {}
fn C._get_osfhandle(fd int) C.intptr_t
fn C.GetModuleFileName(hModule voidptr, lpFilename &u16, nSize u32) u32

View file

@ -120,7 +120,7 @@ fn (mut container PipelineContainer) init_pipeline() {
mut alpha_pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&alpha_pipdesc, 0, int(sizeof(alpha_pipdesc))) }
alpha_pipdesc.label = c'alpha-pipeline'
alpha_pipdesc.colors[0] = gfx.ColorState{
alpha_pipdesc.colors[0] = gfx.ColorTargetState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha
@ -133,7 +133,7 @@ fn (mut container PipelineContainer) init_pipeline() {
mut add_pipdesc := gfx.PipelineDesc{}
unsafe { vmemset(&add_pipdesc, 0, int(sizeof(add_pipdesc))) }
add_pipdesc.label = c'additive-pipeline'
add_pipdesc.colors[0] = gfx.ColorState{
add_pipdesc.colors[0] = gfx.ColorTargetState{
blend: gfx.BlendState{
enabled: true
src_factor_rgb: .src_alpha

View file

@ -38,6 +38,18 @@ $if $pkgconfig('openssl') {
pub struct C.SSL {
}
[typedef]
pub struct C.BIO {
}
[typedef]
pub struct C.SSL_METHOD {
}
[typedef]
pub struct C.X509 {
}
[typedef]
pub struct C.SSL_CTX {
}

View file

@ -217,14 +217,14 @@ pub fn stderr() File {
// eof returns true, when the end of file has been reached
pub fn (f &File) eof() bool {
cfile := &C.FILE(f.cfile)
cfile := unsafe { &C.FILE(f.cfile) }
return C.feof(cfile) != 0
}
// reopen allows a `File` to be reused. It is mostly useful for reopening standard input and output.
pub fn (mut f File) reopen(path string, mode string) ! {
p := fix_windows_path(path)
mut cfile := &C.FILE(0)
mut cfile := &C.FILE(unsafe { nil })
$if windows {
cfile = C._wfreopen(p.to_wide(), mode.to_wide(), f.cfile)
} $else {
@ -242,13 +242,13 @@ pub fn (f &File) read(mut buf []u8) !int {
return Eof{}
}
// the following is needed, because on FreeBSD, C.feof is a macro:
nbytes := int(C.fread(buf.data, 1, buf.len, &C.FILE(f.cfile)))
nbytes := int(C.fread(buf.data, 1, buf.len, unsafe { &C.FILE(f.cfile) }))
// if no bytes were read, check for errors and end-of-file.
if nbytes <= 0 {
if C.feof(&C.FILE(f.cfile)) != 0 {
if C.feof(unsafe { &C.FILE(f.cfile) }) != 0 {
return Eof{}
}
if C.ferror(&C.FILE(f.cfile)) != 0 {
if C.ferror(unsafe { &C.FILE(f.cfile) }) != 0 {
return NotExpected{
cause: 'unexpected error from fread'
code: -1
@ -466,7 +466,7 @@ pub fn (f &File) read_bytes_into_newline(mut buf []u8) !int {
mut buf_ptr := 0
mut nbytes := 0
stream := &C.FILE(f.cfile)
stream := unsafe { &C.FILE(f.cfile) }
for (buf_ptr < buf.len) {
c = C.getc(stream)
match c {

View file

@ -335,7 +335,7 @@ pub fn fileno(cfile voidptr) int {
$if windows {
return C._fileno(cfile)
} $else {
mut cfile_casted := &C.FILE(0) // FILE* cfile_casted = 0;
mut cfile_casted := &C.FILE(unsafe { nil }) // FILE* cfile_casted = 0;
cfile_casted = cfile
// Required on FreeBSD/OpenBSD/NetBSD as stdio.h defines fileno(..) with a macro
// that performs a field access on its argument without casting from void*.

View file

@ -14,6 +14,9 @@ struct C.vm_statistics64_data_t {
external_page_count u32
}
[typedef]
struct C.host_t {}
fn C.mach_host_self() C.host_t
fn C.host_page_size(host C.host_t, out_page_size &C.vm_size_t) int
fn C.host_statistics64(host C.host_t, flavor int, host_info_out &int, host_info_outCnt &u32) int

View file

@ -216,7 +216,7 @@ pub enum VertexFormat as u32 {
float3
float4
byte4
byte4n
byte4n // normalized
ubyte4
ubyte4n
short2
@ -266,11 +266,11 @@ pub enum CullMode as u32 {
// FaceWindin is C.sg_face_winding
pub enum FaceWinding as u32 {
_facewinding_default // value 0 reserved for default-init
facewinding_ccw
facewinding_cw
_facewinding_num
_force_u32 = 0x7FFFFFFF
default // value 0 reserved for default-init
ccw
cw
num
force_u32 = 0x7FFFFFFF
}
pub enum CompareFunc as u32 {

View file

@ -52,12 +52,12 @@ fn C.sg_query_limits() C.sg_limits
fn C.sg_query_pixelformat(fmt PixelFormat) C.sg_pixelformat_info
// get current state of a resource (INITIAL, ALLOC, VALID, FAILED, INVALID)
fn C.sg_query_buffer_state(buf C.sg_buffer) C.sg_resource_state
fn C.sg_query_image_state(img C.sg_image) C.sg_resource_state
fn C.sg_query_sampler_state(smp C.sg_sampler) C.sg_sampler_state
fn C.sg_query_shader_state(shd C.sg_shader) C.sg_resource_state
fn C.sg_query_pipeline_state(pip C.sg_pipeline) C.sg_resource_state
fn C.sg_query_pass_state(pass C.sg_pass) C.sg_resource_state
fn C.sg_query_buffer_state(buf C.sg_buffer) ResourceState
fn C.sg_query_image_state(img C.sg_image) ResourceState
fn C.sg_query_sampler_state(smp C.sg_sampler) ResourceState
fn C.sg_query_shader_state(shd C.sg_shader) ResourceState
fn C.sg_query_pipeline_state(pip C.sg_pipeline) ResourceState
fn C.sg_query_pass_state(pass C.sg_pass) ResourceState
// get runtime information about a resource
fn C.sg_query_buffer_info(buf C.sg_buffer) C.sg_buffer_info

View file

@ -67,16 +67,16 @@ pub mut:
blend BlendState
}
pub type ColorState = C.sg_color_target_state
pub type ColorTargetState = C.sg_color_target_state
pub struct C.sg_pipeline_desc {
pub mut:
shader Shader
layout LayoutDesc
layout VertexLayoutState
depth DepthState
stencil StencilState
color_count int
colors [4]ColorState // C.SG_MAX_COLOR_ATTACHMENTS
colors [4]ColorTargetState // C.SG_MAX_COLOR_ATTACHMENTS
primitive_type PrimitiveType
index_type IndexType
cull_mode CullMode
@ -109,12 +109,14 @@ pub fn (mut p C.sg_pipeline) free() {
struct C.sg_bindings {
pub mut:
_start_canary u32
vertex_buffers [8]Buffer
vertex_buffer_offsets [8]int
index_buffer Buffer
index_buffer_offset int
vs StageBindings
fs StageBindings
_end_canary u32
// vs_images [8]Image // old
// fs_images [8]Image // old
}
@ -553,11 +555,11 @@ pub type Limits = C.sg_limits
pub struct C.sg_vertex_layout_state {
pub mut:
buffers [8]BufferLayoutDesc
buffers [8]VertexBufferLayoutState
attrs [16]VertexAttrDesc
}
pub type LayoutDesc = C.sg_vertex_layout_state
pub type VertexLayoutState = C.sg_vertex_layout_state
pub struct C.sg_vertex_buffer_layout_state {
pub mut:
@ -566,7 +568,7 @@ pub mut:
step_rate int
}
pub type BufferLayoutDesc = C.sg_vertex_buffer_layout_state
pub type VertexBufferLayoutState = C.sg_vertex_buffer_layout_state
pub struct C.sg_vertex_attr_state {
pub mut:
@ -695,3 +697,8 @@ pub:
}
pub type CommitListener = C.sg_commit_listener
pub struct C.sg_trace_hooks {}
// pub struct C.sg_resource_state {} enum
pub struct C.sg_sampler_info {}

View file

@ -2,11 +2,11 @@ module sgl
// SglError is C.sgl_error_t
pub enum SglError {
no_error = C.SGL_NO_ERROR // 0
vertices_full = C.SGL_ERROR_VERTICES_FULL
uniforms_full = C.SGL_ERROR_UNIFORMS_FULL
commands_full = C.SGL_ERROR_COMMANDS_FULL
stack_overflow = C.SGL_ERROR_STACK_OVERFLOW
stack_underfloat = C.SGL_ERROR_STACK_UNDERFLOW
no_context = C.SGL_ERROR_NO_CONTEXT
no_error = C.SGL_NO_ERROR // 0
vertices_full = C.SGL_ERROR_VERTICES_FULL
uniforms_full = C.SGL_ERROR_UNIFORMS_FULL
commands_full = C.SGL_ERROR_COMMANDS_FULL
stack_overflow = C.SGL_ERROR_STACK_OVERFLOW
stack_underflow = C.SGL_ERROR_STACK_UNDERFLOW
no_context = C.SGL_ERROR_NO_CONTEXT
}

View file

@ -3,8 +3,8 @@ module sgl
// setup/shutdown/misc
fn C.sgl_setup(desc &C.sgl_desc_t)
fn C.sgl_shutdown()
fn C.sgl_error() C.sgl_error_t
fn C.sgl_context_error(ctx C.sgl_context) C.sgl_error_t
fn C.sgl_error() SglError
fn C.sgl_context_error(ctx C.sgl_context) SglError
fn C.sgl_rad(deg f32) f32
fn C.sgl_deg(rad f32) f32

View file

@ -31,6 +31,9 @@ pub enum Direction {
push
}
[typedef]
struct C.atomic_uintptr_t {}
pub struct Channel {
ringbuf &u8 = unsafe { nil } // queue for buffered channels
statusbuf &u8 = unsafe { nil } // flags to synchronize write/read in ringbuf

View file

@ -61,6 +61,9 @@ struct RwMutexAttr {
attr C.pthread_rwlockattr_t
}
[typedef]
struct C.pthread_condattr_t {}
struct CondAttr {
attr C.pthread_condattr_t
}

View file

@ -22,9 +22,16 @@ type MHANDLE = voidptr
// Semaphore HANDLE
type SHANDLE = voidptr
[typedef]
struct C.SRWLOCK {}
[typedef]
struct C.CONDITION_VARIABLE {}
//[init_with=new_mutex] // TODO: implement support for this struct attribute, and disallow Mutex{} from outside the sync.new_mutex() function.
// `SRWLOCK` is much more performant that `Mutex` on Windows, so use that in both cases since we don't want to share with other processes
// `SRWLOCK` is much more performant that `Mutex` on Windows, so use that in both cases since we don't
// want to share with other processes
[heap]
pub struct Mutex {
mut:

View file

@ -14,6 +14,10 @@ pub struct C.timeval {
fn C.localtime(t &C.time_t) &C.tm
fn C.localtime_r(t &C.time_t, tm &C.tm)
// struct C.time_t {}
// type C.time_t = i64
fn C.time(t &C.time_t) C.time_t
fn C.gmtime(t &C.time_t) &C.tm

View file

@ -26,7 +26,7 @@ fn C.timegm(&C.tm) C.time_t
fn C.localtime_r(t &C.time_t, tm &C.tm)
fn make_unix_time(t C.tm) i64 {
return i64(C.timegm(&t))
return unsafe { i64(C.timegm(&t)) }
}
// local returns t with the location set to local time.

View file

@ -54,9 +54,9 @@ struct C.timespec {
tv_nsec i64
}
fn C.QueryPerformanceCounter(&u64) C.BOOL
fn C.QueryPerformanceCounter(&u64) bool
fn C.QueryPerformanceFrequency(&u64) C.BOOL
fn C.QueryPerformanceFrequency(&u64) bool
fn make_unix_time(t C.tm) i64 {
return portable_timegm(&t)

View file

@ -760,8 +760,10 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
c.error('enums can only be assigned `int` values', right.pos())
}
} else {
if !var_option || (var_option && right_type_unwrapped != ast.none_type) {
c.error('cannot assign to `${left}`: ${err.msg()}', right.pos())
if right_type_unwrapped != ast.void_type {
if !var_option || (var_option && right_type_unwrapped != ast.none_type) {
c.error('cannot assign to `${left}`: ${err.msg()}', right.pos())
}
}
}
}

View file

@ -500,9 +500,9 @@ fn (mut c Checker) type_decl(node ast.TypeDecl) {
fn (mut c Checker) alias_type_decl(node ast.AliasTypeDecl) {
// TODO Remove when `u8` isn't an alias in builtin anymore
if c.file.mod.name != 'builtin' {
c.check_valid_pascal_case(node.name, 'type alias', node.pos)
}
// if c.file.mod.name != 'builtin' {
// c.check_valid_pascal_case(node.name, 'type alias', node.pos)
//}
if !c.ensure_type_exists(node.parent_type, node.type_pos) {
return
}
@ -4700,10 +4700,23 @@ fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) bool {
}
match sym.kind {
.placeholder {
if sym.language == .v && !sym.name.starts_with('C.') {
if sym.language == .c && sym.name == 'C.time_t' {
// TODO temporary hack until we can define C aliases
return true
}
// if sym.language == .v && !sym.name.starts_with('C.') {
// if sym.language in [.v, .c] {
if sym.language == .v {
c.error(util.new_suggestion(sym.name, c.table.known_type_names()).say('unknown type `${sym.name}`'),
pos)
return false
} else if sym.language == .c {
c.warn(util.new_suggestion(sym.name, c.table.known_type_names()).say('unknown type `${sym.name}` (all virtual C types must be defined, this will be an error soon)'),
pos)
// dump(sym)
// for _, t in c.table.type_symbols {
// println(t.name)
//}
}
}
.int_literal, .float_literal {

View file

@ -4127,11 +4127,18 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
if p.disallow_declarations_in_script_mode() {
return ast.SumTypeDecl{}
}
name := p.check_name()
mut name := p.check_name()
mut language := ast.Language.v
if name.len == 1 && name[0].is_capital() {
p.error_with_pos('single letter capital names are reserved for generic template types',
name_pos)
return ast.FnTypeDecl{}
if name == 'C' && p.tok.kind == .dot {
p.next() // .
name = 'C.' + p.check_name()
language = .c
} else {
p.error_with_pos('1single letter capital names are reserved for generic template types',
name_pos)
return ast.FnTypeDecl{}
}
}
if name in p.imported_symbols {
p.error_with_pos('cannot register alias `${name}`, this type was already imported',
@ -4216,7 +4223,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
parent_sym := p.table.sym(parent_type)
pidx := parent_type.idx()
p.check_for_impure_v(parent_sym.language, decl_pos)
prepend_mod_name := p.prepend_mod(name)
prepend_mod_name := if language == .v { p.prepend_mod(name) } else { name } // `C.time_t`, not `time.C.time_t`
idx := p.table.register_sym(ast.TypeSymbol{
kind: .alias
name: prepend_mod_name

View file

@ -20,7 +20,7 @@ fn C.pthread_self() u64
// windows:
fn C.GetCurrentThreadId() u32
fn C.QueryPerformanceCounter(&u64) C.BOOL
fn C.QueryPerformanceCounter(&u64) bool
[markused]
pub fn on_call(fname string) {