handle unknown functions; fix var types

pull/3299/head
Alexander Medvednikov 2020-01-01 23:15:20 +01:00
parent 0bd84e8060
commit e7e07be38c
6 changed files with 77 additions and 40 deletions

View File

@ -63,7 +63,9 @@ fn (p mut Parser) bool_expression() string {
// `as` cast // `as` cast
// TODO remove copypasta // TODO remove copypasta
if p.tok == .key_as { if p.tok == .key_as {
p.fspace()
p.next() p.next()
p.fspace()
cast_typ := p.get_type() cast_typ := p.get_type()
if typ == cast_typ { if typ == cast_typ {
p.warn('casting `$typ` to `$cast_typ` is not needed') p.warn('casting `$typ` to `$cast_typ` is not needed')

View File

@ -92,8 +92,9 @@ pub:
pub struct CallExpr { pub struct CallExpr {
pub: pub:
name string name string
args []Expr args []Expr
is_unknown bool
} }
pub struct Return { pub struct Return {

View File

@ -17,6 +17,12 @@ void init_user() {
}; };
} }
User get_user() {
User user = (User){
};
return user;
}
void puts(string s) { void puts(string s) {
} }

View File

@ -1,6 +1,7 @@
fn function1() int { fn function1() int {
a := 10 + 1 a := 10 + 1
b := a + 1 b := a + 1
//return a
return 0 return 0
} }
@ -18,6 +19,12 @@ fn init_user() {
} }
} }
fn get_user() User {
user := User{}
return user
}
fn puts(s string) {} fn puts(s string) {}
// comment // comment

View File

@ -34,34 +34,6 @@ pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
return p.stmt() return p.stmt()
} }
pub fn (p mut Parser) get_type() types.Type {
defer {
p.next()
}
match p.tok.lit {
'int' {
return types.int_type
}
'f64' {
return types.f64_type
}
'string' {
return types.string_type
}
'voidptr' {
return types.voidptr_type
}
else {
typ := p.table.types[p.tok.lit]
if isnil(typ.name.str) || typ.name == '' {
p.error('undefined type `$p.tok.lit`')
}
println('RET Typ $typ.name')
return typ
}
}
}
pub fn parse_file(path string, table &table.Table) ast.File { pub fn parse_file(path string, table &table.Table) ast.File {
text := os.read_file(path) or { text := os.read_file(path) or {
panic(err) panic(err)
@ -123,6 +95,33 @@ pub fn parse_files(paths []string, table &table.Table) []ast.File {
return files return files
} }
pub fn (p mut Parser) parse_type() types.Type {
defer {
p.next()
}
match p.tok.lit {
'int' {
return types.int_type
}
'f64' {
return types.f64_type
}
'string' {
return types.string_type
}
'voidptr' {
return types.voidptr_type
}
else {
typ := p.table.types[p.tok.lit]
if isnil(typ.name.str) || typ.name == '' {
p.error('undefined type `$p.tok.lit`')
}
return typ
}
}
}
pub fn (p mut Parser) read_first_token() { pub fn (p mut Parser) read_first_token() {
// need to call next() twice to get peek token and current token // need to call next() twice to get peek token and current token
p.next() p.next()
@ -268,6 +267,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.Type) {
// println('got fn call') // println('got fn call')
fn_name := p.check_name() fn_name := p.check_name()
p.check(.lpar) p.check(.lpar)
mut is_unknown := false
mut args := []ast.Expr mut args := []ast.Expr
if f := p.table.find_fn(fn_name) { if f := p.table.find_fn(fn_name) {
for i, arg in f.args { for i, arg in f.args {
@ -284,12 +284,23 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,types.Type) {
p.error('too many arguments in call to `$fn_name`') p.error('too many arguments in call to `$fn_name`')
} }
}else{ }else{
p.error('unknown function `$fn_name`') is_unknown = true
p.warn('unknown function `$fn_name`')
for p.tok.kind != .rpar {
p.expr(0)
if p.tok.kind != .rpar {
p.check(.comma)
}
}
} }
p.check(.rpar) p.check(.rpar)
node := ast.CallExpr{ node := ast.CallExpr{
name: fn_name name: fn_name
args: args args: args
is_unknown: is_unknown
}
if is_unknown {
p.table.unknown_calls << node
} }
return node,types.int_type return node,types.int_type
} }
@ -317,7 +328,8 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
} }
// struct init // struct init
else if p.peek_tok.kind == .lcbr { else if p.peek_tok.kind == .lcbr {
typ = p.get_type() typ = p.parse_type()
// println('sturct init typ=$typ.name')
p.check(.lcbr) p.check(.lcbr)
mut field_names := []string mut field_names := []string
mut exprs := []ast.Expr mut exprs := []ast.Expr
@ -342,7 +354,12 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
node = ast.Ident{ node = ast.Ident{
name: p.tok.lit name: p.tok.lit
} }
typ = types.int_type var := p.table.find_var(p.tok.lit) or {
p.error('unknown variable `$p.tok.lit`')
exit(0)
}
typ = var.typ
// ///typ = types.int_type
p.next() p.next()
} }
} }
@ -577,7 +594,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
p.check(.colon) p.check(.colon)
} }
field_name := p.check_name() field_name := p.check_name()
typ := p.get_type() typ := p.parse_type()
fields << ast.Field{ fields << ast.Field{
name: field_name name: field_name
typ: typ typ: typ
@ -605,7 +622,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
mut ast_args := []ast.Arg mut ast_args := []ast.Arg
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
arg_name := p.check_name() arg_name := p.check_name()
typ := p.get_type() typ := p.parse_type()
args << table.Var{ args << table.Var{
name: arg_name name: arg_name
typ: typ typ: typ
@ -622,7 +639,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
// Return type // Return type
mut typ := types.void_type mut typ := types.void_type
if p.tok.kind == .name { if p.tok.kind == .name {
typ = p.get_type() typ = p.parse_type()
p.return_type = typ p.return_type = typ
} }
p.table.register_fn(table.Fn{ p.table.register_fn(table.Fn{
@ -642,7 +659,7 @@ fn (p mut Parser) return_stmt() ast.Return {
p.next() p.next()
expr,t := p.expr(0) expr,t := p.expr(0)
if !types.check(p.return_type, t) { if !types.check(p.return_type, t) {
p.error('bad ret type') p.error('cannot use `$t.name` as type `$p.return_type.name` in return argument')
} }
return ast.Return{ return ast.Return{
expr: expr expr: expr
@ -668,6 +685,7 @@ fn (p mut Parser) var_decl() ast.VarDecl {
} }
p.table.register_var(table.Var{ p.table.register_var(table.Var{
name: name name: name
typ: t
is_mut: is_mut is_mut: is_mut
}) })
// println(p.table.names) // println(p.table.names)

View File

@ -2,14 +2,17 @@ module table
import ( import (
v.types v.types
v.ast
) )
pub struct Table { pub struct Table {
pub mut: pub mut:
local_vars []Var local_vars []Var
// fns Hashmap // fns Hashmap
fns map[string]Fn fns map[string]Fn
types map[string]types.Type types map[string]types.Type
//
unknown_calls []ast.CallExpr
} }
pub struct Var { pub struct Var {