v2: lots of small fixes parent method/field resolution
parent
ea9961a8fb
commit
9e9bdc32ea
|
@ -116,6 +116,7 @@ pub:
|
||||||
typ table.TypeRef
|
typ table.TypeRef
|
||||||
args []Arg
|
args []Arg
|
||||||
is_pub bool
|
is_pub bool
|
||||||
|
is_variadic bool
|
||||||
receiver Field
|
receiver Field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub fn (c mut Checker) check(ast_file ast.File) {
|
||||||
// if ast_file.unresolved.len != c.resolved.len {
|
// if ast_file.unresolved.len != c.resolved.len {
|
||||||
// c.resolve_exprs(file)
|
// c.resolve_exprs(file)
|
||||||
// }
|
// }
|
||||||
c.complete_types(ast_file)
|
c.complete_types()
|
||||||
for stmt in ast_file.stmts {
|
for stmt in ast_file.stmts {
|
||||||
c.stmt(stmt)
|
c.stmt(stmt)
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ pub fn (c mut Checker) check_files(ast_files []ast.File) {
|
||||||
// files this muse be done first. TODO: optimize
|
// files this muse be done first. TODO: optimize
|
||||||
for file in ast_files {
|
for file in ast_files {
|
||||||
c.file_name = file.path
|
c.file_name = file.path
|
||||||
c.resolve_expr_types(file)
|
c.resolve_expr_types(file.unresolved)
|
||||||
}
|
}
|
||||||
for file in ast_files {
|
for file in ast_files {
|
||||||
c.check(file)
|
c.check(file)
|
||||||
|
@ -47,14 +47,14 @@ pub fn (c mut Checker) check_files(ast_files []ast.File) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve type of unresolved expressions
|
// resolve type of unresolved expressions
|
||||||
fn (c mut Checker) resolve_expr_types(f ast.File) {
|
fn (c mut Checker) resolve_expr_types(exprs []ast.Expr) {
|
||||||
for x in f.unresolved {
|
for x in exprs {
|
||||||
c.resolved << c.expr(x)
|
c.resolved << c.expr(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// update any types chich contain unresolved sub types
|
// update any types chich contain unresolved sub types
|
||||||
fn (c &Checker) complete_types(f ast.File) {
|
fn (c &Checker) complete_types() {
|
||||||
for idx, t in c.table.types {
|
for idx, t in c.table.types {
|
||||||
// println('Resolve type: $t.name')
|
// println('Resolve type: $t.name')
|
||||||
if t.kind == .array {
|
if t.kind == .array {
|
||||||
|
@ -160,6 +160,16 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.TypeRef {
|
||||||
c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos)
|
c.error('too many arguments in call to `$fn_name` ($call_expr.args.len instead of $f.args.len)', call_expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// for debugging
|
||||||
|
if f.name == 'backtrace_symbols_fd' {
|
||||||
|
println('ARGS FOR: backtrace_symbols_fd:')
|
||||||
|
for i, arg_expr in call_expr.args {
|
||||||
|
typ := c.expr(arg_expr)
|
||||||
|
println(' -- $i - $typ.typ.name')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: variadic
|
||||||
|
if fn_name != 'printf' && f.args.len > 0 {
|
||||||
for i, arg in f.args {
|
for i, arg in f.args {
|
||||||
arg_expr := call_expr.args[i]
|
arg_expr := call_expr.args[i]
|
||||||
typ := c.expr(arg_expr)
|
typ := c.expr(arg_expr)
|
||||||
|
@ -167,6 +177,7 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.TypeRef {
|
||||||
c.error('!cannot use type `$typ.typ.name` as type `$arg.typ.typ.name` in argument to `$fn_name`', call_expr.pos)
|
c.error('!cannot use type `$typ.typ.name` as type `$arg.typ.typ.name` in argument to `$fn_name`', call_expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return f.return_type
|
return f.return_type
|
||||||
}
|
}
|
||||||
c.error('unknown fn: $fn_name', call_expr.pos)
|
c.error('unknown fn: $fn_name', call_expr.pos)
|
||||||
|
@ -178,11 +189,9 @@ pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr)
|
||||||
if method := typ.typ.find_method(method_call_expr.name) {
|
if method := typ.typ.find_method(method_call_expr.name) {
|
||||||
return method.return_type
|
return method.return_type
|
||||||
}
|
}
|
||||||
if typ.typ.kind == .array {
|
// check parent
|
||||||
a := c.table.find_type('array') or {
|
if !isnil(typ.typ.parent) {
|
||||||
exit(1)
|
if method := typ.typ.parent.find_method(method_call_expr.name) {
|
||||||
}
|
|
||||||
if method := a.find_method(method_call_expr.name) {
|
|
||||||
return method.return_type
|
return method.return_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,13 +210,17 @@ pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.TypeRef
|
||||||
}
|
}
|
||||||
return field.typ
|
return field.typ
|
||||||
}
|
}
|
||||||
.array {
|
|
||||||
if field_name == 'len' {
|
|
||||||
return c.table.type_ref(table.int_type_idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.string {}
|
|
||||||
else {
|
else {
|
||||||
|
// types with parent struct (array/maps) handled here
|
||||||
|
if !isnil(typ.typ.parent) && typ.typ.parent.kind == .struct_ {
|
||||||
|
parent := typ.typ.parent
|
||||||
|
if field := c.table.struct_find_field(parent, field_name) {
|
||||||
|
if field.typ.typ.kind == .unresolved {
|
||||||
|
return c.resolved[field.typ.idx]
|
||||||
|
}
|
||||||
|
return field.typ
|
||||||
|
}
|
||||||
|
}
|
||||||
c.error('`$typ.typ.name` is not a struct', selector_expr.pos)
|
c.error('`$typ.typ.name` is not a struct', selector_expr.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,6 +452,8 @@ pub fn (c &Checker) error(s string, pos token.Position) {
|
||||||
path = path.replace(workdir, '')
|
path = path.replace(workdir, '')
|
||||||
}
|
}
|
||||||
final_msg_line := '$path:$pos.line_nr: checker error: $s'
|
final_msg_line := '$path:$pos.line_nr: checker error: $s'
|
||||||
|
// sometimes eprintln wasnt working?
|
||||||
|
println(final_msg_line)
|
||||||
eprintln(final_msg_line)
|
eprintln(final_msg_line)
|
||||||
/*
|
/*
|
||||||
if colored_output {
|
if colored_output {
|
||||||
|
|
|
@ -72,8 +72,12 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
g.definitions.write('$it.typ.typ.name ${it.name}(')
|
g.definitions.write('$it.typ.typ.name ${it.name}(')
|
||||||
}
|
}
|
||||||
for i, arg in it.args {
|
for i, arg in it.args {
|
||||||
g.write(arg.typ.typ.name + ' ' + arg.name)
|
mut arg_type := arg.typ.typ.name
|
||||||
g.definitions.write(arg.typ.typ.name + ' ' + arg.name)
|
if i == it.args.len-1 && it.is_variadic {
|
||||||
|
arg_type = 'variadic_$arg.typ.typ.name'
|
||||||
|
}
|
||||||
|
g.write(arg_type + ' ' + arg.name)
|
||||||
|
g.definitions.write(arg_type + ' ' + arg.name)
|
||||||
if i < it.args.len - 1 {
|
if i < it.args.len - 1 {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
g.definitions.write(', ')
|
g.definitions.write(', ')
|
||||||
|
|
|
@ -18,7 +18,6 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.TypeRef) {
|
||||||
name: fn_name
|
name: fn_name
|
||||||
args: args
|
args: args
|
||||||
// tok: tok
|
// tok: tok
|
||||||
|
|
||||||
pos: tok.position()
|
pos: tok.position()
|
||||||
}
|
}
|
||||||
if p.tok.kind == .key_orelse {
|
if p.tok.kind == .key_orelse {
|
||||||
|
@ -93,6 +92,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
}
|
}
|
||||||
// println('fn decl $name')
|
// println('fn decl $name')
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
|
mut is_variadic := false
|
||||||
// Args
|
// Args
|
||||||
mut args := []table.Var
|
mut args := []table.Var
|
||||||
mut ast_args := []ast.Arg
|
mut ast_args := []ast.Arg
|
||||||
|
@ -102,12 +102,32 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
p.peek_tok.kind == .rpar
|
p.peek_tok.kind == .rpar
|
||||||
if types_only {
|
if types_only {
|
||||||
p.warn('types only')
|
p.warn('types only')
|
||||||
|
mut arg_no := 1
|
||||||
for p.tok.kind != .rpar {
|
for p.tok.kind != .rpar {
|
||||||
p.parse_type()
|
arg_name := 'arg_$arg_no'
|
||||||
|
if p.tok.kind == .ellipsis {
|
||||||
|
p.check(.ellipsis)
|
||||||
|
is_variadic = true
|
||||||
|
}
|
||||||
|
arg_type := p.parse_type()
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
|
if is_variadic {
|
||||||
|
p.error('cannot use ...(variadic) with non-final parameter no $arg_no')
|
||||||
|
}
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
|
arg := table.Var{
|
||||||
|
name: arg_name
|
||||||
|
typ: arg_type
|
||||||
}
|
}
|
||||||
|
args << arg
|
||||||
|
//p.table.register_var(arg)
|
||||||
|
ast_args << ast.Arg{
|
||||||
|
name: arg_name
|
||||||
|
typ: arg_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
arg_no++
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for p.tok.kind != .rpar {
|
for p.tok.kind != .rpar {
|
||||||
|
@ -120,6 +140,10 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
p.check(.key_mut)
|
p.check(.key_mut)
|
||||||
}
|
}
|
||||||
|
if p.tok.kind == .ellipsis {
|
||||||
|
p.check(.ellipsis)
|
||||||
|
is_variadic = true
|
||||||
|
}
|
||||||
typ := p.parse_type()
|
typ := p.parse_type()
|
||||||
for arg_name in arg_names {
|
for arg_name in arg_names {
|
||||||
arg := table.Var{
|
arg := table.Var{
|
||||||
|
@ -129,10 +153,11 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
args << arg
|
args << arg
|
||||||
p.table.register_var(arg)
|
p.table.register_var(arg)
|
||||||
ast_args << ast.Arg{
|
ast_args << ast.Arg{
|
||||||
typ: typ
|
|
||||||
name: arg_name
|
name: arg_name
|
||||||
|
typ: typ
|
||||||
}
|
}
|
||||||
if typ.typ.kind == .variadic && p.tok.kind == .comma {
|
//if typ.typ.kind == .variadic && p.tok.kind == .comma {
|
||||||
|
if is_variadic && p.tok.kind == .comma {
|
||||||
p.error('cannot use ...(variadic) with non-final parameter $arg_name')
|
p.error('cannot use ...(variadic) with non-final parameter $arg_name')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,6 +192,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
name: name
|
name: name
|
||||||
args: args
|
args: args
|
||||||
return_type: typ
|
return_type: typ
|
||||||
|
is_variadic: is_variadic
|
||||||
is_c: is_c
|
is_c: is_c
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -180,6 +206,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
typ: typ
|
typ: typ
|
||||||
args: ast_args
|
args: ast_args
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
|
is_variadic: is_variadic
|
||||||
receiver: ast.Field{
|
receiver: ast.Field{
|
||||||
name: rec_name
|
name: rec_name
|
||||||
typ: rec_type
|
typ: rec_type
|
||||||
|
|
|
@ -62,13 +62,6 @@ pub fn (p mut Parser) parse_multi_return_ti() table.TypeRef {
|
||||||
return p.table.type_ref(idx)
|
return p.table.type_ref(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) parse_variadic_ti() table.TypeRef {
|
|
||||||
p.check(.ellipsis)
|
|
||||||
variadic_type := p.parse_type()
|
|
||||||
idx := p.table.find_or_register_variadic(variadic_type)
|
|
||||||
return p.table.type_ref(idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (p mut Parser) parse_fn_type() table.TypeRef {
|
pub fn (p mut Parser) parse_fn_type() table.TypeRef {
|
||||||
// p.check(.key_fn)
|
// p.check(.key_fn)
|
||||||
p.fn_decl()
|
p.fn_decl()
|
||||||
|
@ -105,13 +98,6 @@ pub fn (p mut Parser) parse_type() table.TypeRef {
|
||||||
}
|
}
|
||||||
return p.parse_multi_return_ti()
|
return p.parse_multi_return_ti()
|
||||||
}
|
}
|
||||||
// variadic
|
|
||||||
.ellipsis {
|
|
||||||
if nr_muls > 0 {
|
|
||||||
p.error('parse_ti: unexpected `&` before variadic')
|
|
||||||
}
|
|
||||||
return p.parse_variadic_ti()
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
defer {
|
defer {
|
||||||
p.next()
|
p.next()
|
||||||
|
|
|
@ -71,12 +71,13 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
||||||
table: table
|
table: table
|
||||||
file_name: path
|
file_name: path
|
||||||
pref: &pref.Preferences{}
|
pref: &pref.Preferences{}
|
||||||
builtin_mod: true
|
|
||||||
}
|
}
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
// module decl
|
// module decl
|
||||||
module_decl := if p.tok.kind == .key_module { p.module_decl() } else { ast.Module{name: 'main'
|
module_decl := if p.tok.kind == .key_module { p.module_decl() } else { ast.Module{name: 'main'
|
||||||
} }
|
} }
|
||||||
|
p.mod = module_decl.name
|
||||||
|
p.builtin_mod = p.mod == 'builtin'
|
||||||
// imports
|
// imports
|
||||||
mut imports := []ast.Import
|
mut imports := []ast.Import
|
||||||
for p.tok.kind == .key_import {
|
for p.tok.kind == .key_import {
|
||||||
|
@ -471,7 +472,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.TypeRef) {
|
||||||
if p.peek_tok.kind == .lpar {
|
if p.peek_tok.kind == .lpar {
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
// type cast. TODO: finish
|
// type cast. TODO: finish
|
||||||
if name in p.table.type_idxs {
|
if name in table.builtin_type_names {
|
||||||
// ['byte', 'string', 'int']
|
// ['byte', 'string', 'int']
|
||||||
// SKIP FOR NOW
|
// SKIP FOR NOW
|
||||||
mut par_d := 0
|
mut par_d := 0
|
||||||
|
@ -1054,26 +1055,30 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
}
|
}
|
||||||
fields << table.Field{
|
fields << table.Field{
|
||||||
name: field_name
|
name: field_name
|
||||||
// type_idx: ti.idx
|
|
||||||
|
|
||||||
typ: typ
|
typ: typ
|
||||||
}
|
}
|
||||||
// println('struct field $ti.name $field_name')
|
// println('struct field $ti.name $field_name')
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
if name != 'string' {
|
t := table.Type{
|
||||||
ret := p.table.register_type(table.Type{
|
|
||||||
parent: 0
|
parent: 0
|
||||||
kind: .struct_
|
kind: .struct_
|
||||||
name: name
|
name: name
|
||||||
info: table.Struct{
|
info: table.Struct{
|
||||||
fields: fields
|
fields: fields
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
mut ret := 0
|
||||||
|
if p.builtin_mod && t.name in table.builtin_type_names {
|
||||||
|
// this allows overiding the builtins type
|
||||||
|
// with the real struct type info parsed from builtin
|
||||||
|
ret = p.table.register_builtin_type(t)
|
||||||
|
} else {
|
||||||
|
ret = p.table.register_type(t)
|
||||||
|
}
|
||||||
if ret == -1 {
|
if ret == -1 {
|
||||||
p.error('cannot register type `$name`, another type with this name exists')
|
p.error('cannot register type `$name`, another type with this name exists')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return ast.StructDecl{
|
return ast.StructDecl{
|
||||||
name: name
|
name: name
|
||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module table
|
module table
|
||||||
|
|
||||||
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Variadic
|
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn
|
||||||
|
|
||||||
pub struct Type {
|
pub struct Type {
|
||||||
pub:
|
pub:
|
||||||
|
@ -47,6 +47,13 @@ pub const (
|
||||||
// map_type_idx = 18
|
// map_type_idx = 18
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pub const (
|
||||||
|
builtin_type_names = [
|
||||||
|
'void', 'voidptr', 'charptr', 'byteptr', 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64',
|
||||||
|
'f32' ,'f64', 'string', 'char', 'byte' ,'bool', 'struct', 'array', 'array_fixed', 'map'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
placeholder
|
placeholder
|
||||||
void
|
void
|
||||||
|
@ -66,14 +73,13 @@ pub enum Kind {
|
||||||
char
|
char
|
||||||
byte
|
byte
|
||||||
bool
|
bool
|
||||||
const_
|
//const_
|
||||||
enum_
|
//enum_
|
||||||
struct_
|
struct_
|
||||||
array
|
array
|
||||||
array_fixed
|
array_fixed
|
||||||
map
|
map
|
||||||
multi_return
|
multi_return
|
||||||
variadic
|
|
||||||
unresolved
|
unresolved
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,9 +377,6 @@ pub fn (k Kind) str() string {
|
||||||
.multi_return{
|
.multi_return{
|
||||||
'multi_return'
|
'multi_return'
|
||||||
}
|
}
|
||||||
.variadic{
|
|
||||||
'variadic'
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
'unknown'}
|
'unknown'}
|
||||||
}
|
}
|
||||||
|
@ -407,6 +410,7 @@ pub mut:
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
|
mut:
|
||||||
typ TypeRef
|
typ TypeRef
|
||||||
// type_idx int
|
// type_idx int
|
||||||
}
|
}
|
||||||
|
@ -447,11 +451,6 @@ mut:
|
||||||
types []TypeRef
|
types []TypeRef
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Variadic {
|
|
||||||
pub:
|
|
||||||
typ TypeRef
|
|
||||||
}
|
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t &Table) get_type(idx int) &Type {
|
pub fn (t &Table) get_type(idx int) &Type {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
|
|
|
@ -27,6 +27,7 @@ pub:
|
||||||
name string
|
name string
|
||||||
args []Var
|
args []Var
|
||||||
return_type TypeRef
|
return_type TypeRef
|
||||||
|
is_variadic bool
|
||||||
is_c bool
|
is_c bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,6 +280,19 @@ pub fn (t &Table) find_type(name string) ?Type {
|
||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this will override or register builtin type
|
||||||
|
// allows prexisitng types added in register_builtins
|
||||||
|
// to be overriden with their real type info
|
||||||
|
[inline]
|
||||||
|
pub fn (t mut Table) register_builtin_type(typ Type) int {
|
||||||
|
existing_idx := t.type_idxs[typ.name]
|
||||||
|
if existing_idx > 0 {
|
||||||
|
t.types[existing_idx] = typ
|
||||||
|
return existing_idx
|
||||||
|
}
|
||||||
|
return t.register_type(typ)
|
||||||
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (t mut Table) register_type(typ Type) int {
|
pub fn (t mut Table) register_type(typ Type) int {
|
||||||
existing_idx := t.type_idxs[typ.name]
|
existing_idx := t.type_idxs[typ.name]
|
||||||
|
@ -399,25 +413,6 @@ pub fn (t mut Table) find_or_register_multi_return(mr_typs []TypeRef) int {
|
||||||
return t.register_type(mr_type)
|
return t.register_type(mr_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) find_or_register_variadic(variadic_typ TypeRef) int {
|
|
||||||
name := 'variadic_$variadic_typ.typ.name'
|
|
||||||
// existing
|
|
||||||
existing_idx := t.type_idxs[name]
|
|
||||||
if existing_idx > 0 {
|
|
||||||
return existing_idx
|
|
||||||
}
|
|
||||||
// register
|
|
||||||
variadic_type := Type{
|
|
||||||
parent: 0
|
|
||||||
kind: .variadic
|
|
||||||
name: name
|
|
||||||
info: Variadic{
|
|
||||||
typ: variadic_typ
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return t.register_type(variadic_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (t mut Table) add_placeholder_type(name string) int {
|
pub fn (t mut Table) add_placeholder_type(name string) int {
|
||||||
ph_type := Type{
|
ph_type := Type{
|
||||||
parent: 0
|
parent: 0
|
||||||
|
@ -433,6 +428,9 @@ pub fn (t &Table) check(got, expected &TypeRef) bool {
|
||||||
if expected.typ.kind == .voidptr {
|
if expected.typ.kind == .voidptr {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if expected.typ.kind in [.voidptr, .byteptr, .charptr] && got.typ.kind == .int {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if expected.typ.kind == .byteptr && got.typ.kind == .voidptr {
|
if expected.typ.kind == .byteptr && got.typ.kind == .voidptr {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue