handle unknown functions; fix var types
parent
0bd84e8060
commit
e7e07be38c
|
@ -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')
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -17,6 +17,12 @@ void init_user() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
User get_user() {
|
||||||
|
User user = (User){
|
||||||
|
};
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
void puts(string s) {
|
void puts(string s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue