v2: lots of small fixes parent method/field resolution

pull/3687/head
joe-conigliaro 2020-02-08 19:50:12 +11:00 committed by GitHub
parent ea9961a8fb
commit 9e9bdc32ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 123 additions and 88 deletions

View File

@ -111,12 +111,13 @@ pub:
pub struct FnDecl {
pub:
name string
stmts []Stmt
typ table.TypeRef
args []Arg
is_pub bool
receiver Field
name string
stmts []Stmt
typ table.TypeRef
args []Arg
is_pub bool
is_variadic bool
receiver Field
}
pub struct BranchStmt {

View File

@ -28,7 +28,7 @@ pub fn (c mut Checker) check(ast_file ast.File) {
// if ast_file.unresolved.len != c.resolved.len {
// c.resolve_exprs(file)
// }
c.complete_types(ast_file)
c.complete_types()
for stmt in ast_file.stmts {
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
for file in ast_files {
c.file_name = file.path
c.resolve_expr_types(file)
c.resolve_expr_types(file.unresolved)
}
for file in ast_files {
c.check(file)
@ -47,14 +47,14 @@ pub fn (c mut Checker) check_files(ast_files []ast.File) {
}
// resolve type of unresolved expressions
fn (c mut Checker) resolve_expr_types(f ast.File) {
for x in f.unresolved {
fn (c mut Checker) resolve_expr_types(exprs []ast.Expr) {
for x in exprs {
c.resolved << c.expr(x)
}
}
// 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 {
// println('Resolve type: $t.name')
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)
}
}
// 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 {
arg_expr := call_expr.args[i]
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)
}
}
}
return f.return_type
}
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) {
return method.return_type
}
if typ.typ.kind == .array {
a := c.table.find_type('array') or {
exit(1)
}
if method := a.find_method(method_call_expr.name) {
// check parent
if !isnil(typ.typ.parent) {
if method := typ.typ.parent.find_method(method_call_expr.name) {
return method.return_type
}
}
@ -201,13 +210,17 @@ pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.TypeRef
}
return field.typ
}
.array {
if field_name == 'len' {
return c.table.type_ref(table.int_type_idx)
}
}
.string {}
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)
}
}
@ -439,6 +452,8 @@ pub fn (c &Checker) error(s string, pos token.Position) {
path = path.replace(workdir, '')
}
final_msg_line := '$path:$pos.line_nr: checker error: $s'
// sometimes eprintln wasnt working?
println(final_msg_line)
eprintln(final_msg_line)
/*
if colored_output {

View File

@ -72,8 +72,12 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.definitions.write('$it.typ.typ.name ${it.name}(')
}
for i, arg in it.args {
g.write(arg.typ.typ.name + ' ' + arg.name)
g.definitions.write(arg.typ.typ.name + ' ' + arg.name)
mut arg_type := arg.typ.typ.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 {
g.write(', ')
g.definitions.write(', ')

View File

@ -18,7 +18,6 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.TypeRef) {
name: fn_name
args: args
// tok: tok
pos: tok.position()
}
if p.tok.kind == .key_orelse {
@ -93,6 +92,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
}
// println('fn decl $name')
p.check(.lpar)
mut is_variadic := false
// Args
mut args := []table.Var
mut ast_args := []ast.Arg
@ -102,12 +102,32 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
p.peek_tok.kind == .rpar
if types_only {
p.warn('types only')
mut arg_no := 1
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 is_variadic {
p.error('cannot use ...(variadic) with non-final parameter no $arg_no')
}
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 {
for p.tok.kind != .rpar {
@ -120,6 +140,10 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
if p.tok.kind == .key_mut {
p.check(.key_mut)
}
if p.tok.kind == .ellipsis {
p.check(.ellipsis)
is_variadic = true
}
typ := p.parse_type()
for arg_name in arg_names {
arg := table.Var{
@ -129,10 +153,11 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
args << arg
p.table.register_var(arg)
ast_args << ast.Arg{
typ: typ
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')
}
}
@ -167,6 +192,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
name: name
args: args
return_type: typ
is_variadic: is_variadic
is_c: is_c
})
}
@ -180,6 +206,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
typ: typ
args: ast_args
is_pub: is_pub
is_variadic: is_variadic
receiver: ast.Field{
name: rec_name
typ: rec_type

View File

@ -62,13 +62,6 @@ pub fn (p mut Parser) parse_multi_return_ti() table.TypeRef {
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 {
// p.check(.key_fn)
p.fn_decl()
@ -105,13 +98,6 @@ pub fn (p mut Parser) parse_type() table.TypeRef {
}
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 {
defer {
p.next()

View File

@ -71,12 +71,13 @@ pub fn parse_file(path string, table &table.Table) ast.File {
table: table
file_name: path
pref: &pref.Preferences{}
builtin_mod: true
}
p.read_first_token()
// module decl
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
mut imports := []ast.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 {
name := p.tok.lit
// type cast. TODO: finish
if name in p.table.type_idxs {
if name in table.builtin_type_names {
// ['byte', 'string', 'int']
// SKIP FOR NOW
mut par_d := 0
@ -1054,26 +1055,30 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
}
fields << table.Field{
name: field_name
// type_idx: ti.idx
typ: typ
}
// println('struct field $ti.name $field_name')
}
p.check(.rcbr)
if name != 'string' {
ret := p.table.register_type(table.Type{
parent: 0
kind: .struct_
name: name
info: table.Struct{
fields: fields
}
})
if ret == -1 {
p.error('cannot register type `$name`, another type with this name exists')
t := table.Type{
parent: 0
kind: .struct_
name: name
info: table.Struct{
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 {
p.error('cannot register type `$name`, another type with this name exists')
}
return ast.StructDecl{
name: name
is_pub: is_pub

View File

@ -3,7 +3,7 @@
// that can be found in the LICENSE file.
module table
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Variadic
pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn
pub struct Type {
pub:
@ -47,6 +47,13 @@ pub const (
// 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 {
placeholder
void
@ -66,14 +73,13 @@ pub enum Kind {
char
byte
bool
const_
enum_
//const_
//enum_
struct_
array
array_fixed
map
multi_return
variadic
unresolved
}
@ -371,9 +377,6 @@ pub fn (k Kind) str() string {
.multi_return{
'multi_return'
}
.variadic{
'variadic'
}
else {
'unknown'}
}
@ -407,6 +410,7 @@ pub mut:
pub struct Field {
pub:
name string
mut:
typ TypeRef
// type_idx int
}
@ -447,11 +451,6 @@ mut:
types []TypeRef
}
pub struct Variadic {
pub:
typ TypeRef
}
[inline]
pub fn (t &Table) get_type(idx int) &Type {
if idx == 0 {

View File

@ -27,6 +27,7 @@ pub:
name string
args []Var
return_type TypeRef
is_variadic bool
is_c bool
}
@ -279,6 +280,19 @@ pub fn (t &Table) find_type(name string) ?Type {
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]
pub fn (t mut Table) register_type(typ Type) int {
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)
}
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 {
ph_type := Type{
parent: 0
@ -433,6 +428,9 @@ pub fn (t &Table) check(got, expected &TypeRef) bool {
if expected.typ.kind == .voidptr {
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 {
return true
}