v2: remove unresolved types; handle types in checker; add ast.scope
parent
c2c6260ba2
commit
dc90f4f4a6
|
@ -70,6 +70,7 @@ pub struct Field {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
// type_idx int
|
// type_idx int
|
||||||
|
mut:
|
||||||
typ table.Type
|
typ table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +198,7 @@ pub:
|
||||||
mod Module
|
mod Module
|
||||||
imports []Import
|
imports []Import
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
|
scope Scope
|
||||||
unresolved []Expr
|
unresolved []Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,9 +294,10 @@ pub:
|
||||||
cond Expr
|
cond Expr
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
else_stmts []Stmt
|
else_stmts []Stmt
|
||||||
typ table.Type
|
|
||||||
left Expr // `a` in `a := if ...`
|
left Expr // `a` in `a := if ...`
|
||||||
pos token.Position
|
pos token.Position
|
||||||
|
mut:
|
||||||
|
typ table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MatchExpr {
|
pub struct MatchExpr {
|
||||||
|
@ -303,8 +306,9 @@ pub:
|
||||||
cond Expr
|
cond Expr
|
||||||
blocks []StmtBlock
|
blocks []StmtBlock
|
||||||
match_exprs []Expr
|
match_exprs []Expr
|
||||||
typ table.Type
|
|
||||||
pos token.Position
|
pos token.Position
|
||||||
|
mut:
|
||||||
|
typ table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CompIf {
|
pub struct CompIf {
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module ast
|
||||||
|
|
||||||
|
pub struct Scope {
|
||||||
|
mut:
|
||||||
|
parent &Scope
|
||||||
|
children []&Scope
|
||||||
|
start_pos int
|
||||||
|
end_pos int
|
||||||
|
//vars map[string]table.Var
|
||||||
|
vars map[string]VarDecl
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_scope(parent &Scope, start_pos int) &Scope {
|
||||||
|
return &Scope{
|
||||||
|
parent: parent
|
||||||
|
start_pos: start_pos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (s &Scope) find_scope_and_var(name string) ?(&Scope,VarDecl) {
|
||||||
|
if name in s.vars {
|
||||||
|
return s,s.vars[name]
|
||||||
|
}
|
||||||
|
for sc := s; !isnil(sc.parent); sc = sc.parent {
|
||||||
|
if name in sc.vars {
|
||||||
|
return sc,sc.vars[name]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error('not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (s &Scope) find_var(name string) ?VarDecl {
|
||||||
|
//pub fn (s &Scope) find_var(name string) ?table.Var {
|
||||||
|
if name in s.vars {
|
||||||
|
return s.vars[name]
|
||||||
|
}
|
||||||
|
for sc := s; !isnil(sc.parent); sc = sc.parent {
|
||||||
|
if name in sc.vars {
|
||||||
|
return sc.vars[name]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error('not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
[inline]
|
||||||
|
pub fn (s &Scope) find_var2(name string, pos int) ?VarDecl {
|
||||||
|
return find_var_in_scope(name, pos, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn find_var_in_scope(name string, pos int, scope &Scope) ?VarDecl {
|
||||||
|
if pos != 0 && (pos < scope.start_pos || pos > scope.end_pos) {
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
if name in scope.vars {
|
||||||
|
return scope.vars[name]
|
||||||
|
}
|
||||||
|
for child in scope.children {
|
||||||
|
//if pos < child.start_pos || pos > child.end_pos {
|
||||||
|
// continue
|
||||||
|
//}
|
||||||
|
var := find_var_in_scope(name, pos, child) or {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return var
|
||||||
|
//return find_var_in_scope(name, pos, child)
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//pub fn (s mut Scope) register_var(var table.Var) {
|
||||||
|
[inline]
|
||||||
|
pub fn (s mut Scope) register_var(var VarDecl) {
|
||||||
|
if x := s.find_var(var.name) {
|
||||||
|
println('existing var: $var.name')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.vars[var.name] = var
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (s &Scope) innermost(pos int) ?&Scope {
|
||||||
|
if s.contains(pos) {
|
||||||
|
/*
|
||||||
|
for s1 in s.children {
|
||||||
|
if s1.contains(pos) {
|
||||||
|
return s1.innermost(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
*/
|
||||||
|
// binary search
|
||||||
|
mut first := 0
|
||||||
|
mut last := s.children.len-1
|
||||||
|
mut middle := last/2
|
||||||
|
for first <= last {
|
||||||
|
//println('FIRST: $first, LAST: $last, LEN: $s.children.len-1')
|
||||||
|
s1 := s.children[middle]
|
||||||
|
if s1.end_pos < pos {
|
||||||
|
first = middle+1
|
||||||
|
}
|
||||||
|
else if s1.contains(pos) {
|
||||||
|
return s1.innermost(pos)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last = middle-1
|
||||||
|
}
|
||||||
|
middle = (first+last)/2
|
||||||
|
if first > last {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
//return error('none')
|
||||||
|
//return none
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn (s &Scope) contains(pos int) bool {
|
||||||
|
return pos > s.start_pos && pos < s.end_pos
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_scope_vars(sc &Scope, level int) {
|
||||||
|
mut indent := ''
|
||||||
|
for _ in 0..level*4 {
|
||||||
|
indent += ' '
|
||||||
|
}
|
||||||
|
println('$indent# $sc.start_pos - $sc.end_pos')
|
||||||
|
for _, var in sc.vars {
|
||||||
|
println('$indent * $var.name - $var.typ')
|
||||||
|
}
|
||||||
|
for child in sc.children {
|
||||||
|
print_scope_vars(child, level+1)
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,10 @@ pub fn (b mut Builder) gen_c(v_files []string) string {
|
||||||
b.parsed_files = parser.parse_files(v_files, b.table)
|
b.parsed_files = parser.parse_files(v_files, b.table)
|
||||||
b.parse_imports()
|
b.parse_imports()
|
||||||
b.checker.check_files(b.parsed_files)
|
b.checker.check_files(b.parsed_files)
|
||||||
|
//println('=======================')
|
||||||
|
//ast.print_scope_vars(&b.parsed_files[0].scope, 0)
|
||||||
|
//println('=======================')
|
||||||
|
//return gen.cgen(b.parsed_files, b.table)
|
||||||
return gen.cgen(b.parsed_files, b.table)
|
return gen.cgen(b.parsed_files, b.table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,6 +58,9 @@ pub fn (b mut Builder) build_x64(v_files []string, out_file string) {
|
||||||
parse_time := t1 - t0
|
parse_time := t1 - t0
|
||||||
println('PARSE: ${parse_time}ms')
|
println('PARSE: ${parse_time}ms')
|
||||||
b.checker.check_files(b.parsed_files)
|
b.checker.check_files(b.parsed_files)
|
||||||
|
//println('=======================')
|
||||||
|
//ast.print_scope_vars(&b.parsed_files[0].scope, 0)
|
||||||
|
//println('=======================')
|
||||||
t2 := time.ticks()
|
t2 := time.ticks()
|
||||||
check_time := t2 - t1
|
check_time := t2 - t1
|
||||||
println('CHECK: ${check_time}ms')
|
println('CHECK: ${check_time}ms')
|
||||||
|
|
|
@ -14,6 +14,7 @@ pub struct Checker {
|
||||||
table &table.Table
|
table &table.Table
|
||||||
mut:
|
mut:
|
||||||
file_name string
|
file_name string
|
||||||
|
scope ast.Scope
|
||||||
resolved []table.Type
|
resolved []table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,109 +26,49 @@ pub fn new_checker(table &table.Table) Checker {
|
||||||
|
|
||||||
pub fn (c mut Checker) check(ast_file ast.File) {
|
pub fn (c mut Checker) check(ast_file ast.File) {
|
||||||
c.file_name = ast_file.path
|
c.file_name = ast_file.path
|
||||||
// if ast_file.unresolved.len != c.resolved.len {
|
c.scope = ast_file.scope
|
||||||
// c.resolve_exprs(file)
|
|
||||||
// }
|
|
||||||
c.complete_types()
|
|
||||||
for stmt in ast_file.stmts {
|
for stmt in ast_file.stmts {
|
||||||
c.stmt(stmt)
|
c.stmt(stmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c mut Checker) check_files(ast_files []ast.File) {
|
pub fn (c mut Checker) check_files(ast_files []ast.File) {
|
||||||
// this cant be moved to check() for multiple
|
|
||||||
// files this muse be done first. TODO: optimize
|
|
||||||
for file in ast_files {
|
|
||||||
c.file_name = file.path
|
|
||||||
c.resolve_expr_types(file.unresolved)
|
|
||||||
}
|
|
||||||
for file in ast_files {
|
for file in ast_files {
|
||||||
c.check(file)
|
c.check(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve type of unresolved expressions
|
pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type {
|
||||||
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() {
|
|
||||||
for idx, t in c.table.types {
|
|
||||||
// skip builtin types
|
|
||||||
if idx <= table.map_type_idx {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// println('Resolve type: $t.name')
|
|
||||||
if t.kind == .array {
|
|
||||||
mut info := t.array_info()
|
|
||||||
if table.type_is_unresolved(info.elem_type) {
|
|
||||||
info.elem_type = c.resolve(info.elem_type)
|
|
||||||
elem_type_sym := c.table.get_type_symbol(info.elem_type)
|
|
||||||
mut t1 := &c.table.types[idx]
|
|
||||||
t1.name = table.array_name(elem_type_sym, info.nr_dims)
|
|
||||||
t1.info = info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if t.kind == .map {
|
|
||||||
mut info := t.map_info()
|
|
||||||
mut updated := false
|
|
||||||
if table.type_is_unresolved(info.key_type) {
|
|
||||||
info.key_type = c.resolve(info.key_type)
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
if table.type_is_unresolved(info.value_type) {
|
|
||||||
info.value_type = c.resolve(info.value_type)
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
if updated {
|
|
||||||
mut t1 := &c.table.types[idx]
|
|
||||||
key_type_sym := c.table.get_type_symbol(info.key_type)
|
|
||||||
value_type_sym := c.table.get_type_symbol(info.value_type)
|
|
||||||
t1.name = table.map_name(key_type_sym, value_type_sym)
|
|
||||||
t1.info = info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if t.kind == .multi_return {
|
|
||||||
mut info := t.mr_info()
|
|
||||||
mut types := info.types
|
|
||||||
mut updated := false
|
|
||||||
for i, ut in types {
|
|
||||||
if table.type_is_unresolved(ut) {
|
|
||||||
types[i] = c.resolve(ut)
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if updated {
|
|
||||||
mut t1 := &c.table.types[idx]
|
|
||||||
info.types = types
|
|
||||||
t1.info = info
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the resolved Type from unresovled Type
|
|
||||||
pub fn (c &Checker) resolve(unresolved table.Type) table.Type {
|
|
||||||
return c.resolved[-table.type_idx(unresolved) - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.Type {
|
|
||||||
// typ := c.table.find_type(struct_init.typ.typ.name) or {
|
// typ := c.table.find_type(struct_init.typ.typ.name) or {
|
||||||
// c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos)
|
// c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos)
|
||||||
// panic('')
|
// panic('')
|
||||||
// }
|
// }
|
||||||
typ := c.table.get_type_symbol(struct_init.typ)
|
typ_sym := c.table.get_type_symbol(struct_init.typ)
|
||||||
match typ.kind {
|
match typ_sym.kind {
|
||||||
.placeholder {
|
.placeholder {
|
||||||
c.error('unknown struct: $typ.name', struct_init.pos)
|
c.error('unknown struct: $typ_sym.name', struct_init.pos)
|
||||||
}
|
}
|
||||||
.struct_ {
|
.struct_ {
|
||||||
info := typ.info as table.Struct
|
info := typ_sym.info as table.Struct
|
||||||
|
if struct_init.exprs.len > info.fields.len {
|
||||||
|
c.error('too many fields', struct_init.pos)
|
||||||
|
}
|
||||||
for i, expr in struct_init.exprs {
|
for i, expr in struct_init.exprs {
|
||||||
field := info.fields[i]
|
//struct_field info.
|
||||||
|
field_name := struct_init.fields[i]
|
||||||
|
mut field := info.fields[i]
|
||||||
|
mut found_field := false
|
||||||
|
for f in info.fields {
|
||||||
|
if f.name == field_name {
|
||||||
|
field = f
|
||||||
|
found_field = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found_field {
|
||||||
|
c.error('struct init: no such field `$field_name` for struct `$typ_sym.name`', struct_init.pos)
|
||||||
|
}
|
||||||
expr_type := c.expr(expr)
|
expr_type := c.expr(expr)
|
||||||
expr_type_sym := c.table.get_type_symbol(expr_type)
|
expr_type_sym := c.table.get_type_symbol(expr_type)
|
||||||
field_type_sym := c.table.get_type_symbol(field.typ)
|
field_type_sym := c.table.get_type_symbol(field.typ)
|
||||||
|
@ -141,7 +82,7 @@ pub fn (c &Checker) check_struct_init(struct_init ast.StructInit) table.Type {
|
||||||
return struct_init.typ
|
return struct_init.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
|
pub fn (c mut Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
|
||||||
left_type := c.expr(infix_expr.left)
|
left_type := c.expr(infix_expr.left)
|
||||||
right_type := c.expr(infix_expr.right)
|
right_type := c.expr(infix_expr.right)
|
||||||
if !c.table.check(right_type, left_type) {
|
if !c.table.check(right_type, left_type) {
|
||||||
|
@ -157,7 +98,7 @@ pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
|
||||||
return left_type
|
return left_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c &Checker) check_assign_expr(assign_expr ast.AssignExpr) {
|
fn (c mut Checker) check_assign_expr(assign_expr ast.AssignExpr) {
|
||||||
left_type := c.expr(assign_expr.left)
|
left_type := c.expr(assign_expr.left)
|
||||||
right_type := c.expr(assign_expr.val)
|
right_type := c.expr(assign_expr.val)
|
||||||
if !c.table.check(right_type, left_type) {
|
if !c.table.check(right_type, left_type) {
|
||||||
|
@ -167,7 +108,7 @@ fn (c &Checker) check_assign_expr(assign_expr ast.AssignExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
pub fn (c mut Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
||||||
fn_name := call_expr.name
|
fn_name := call_expr.name
|
||||||
if f := c.table.find_fn(fn_name) {
|
if f := c.table.find_fn(fn_name) {
|
||||||
// return_ti := f.return_ti
|
// return_ti := f.return_ti
|
||||||
|
@ -195,7 +136,7 @@ pub fn (c &Checker) call_expr(call_expr ast.CallExpr) table.Type {
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type {
|
pub fn (c mut Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr) table.Type {
|
||||||
typ := c.expr(method_call_expr.expr)
|
typ := c.expr(method_call_expr.expr)
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
if method := typ_sym.find_method(method_call_expr.name) {
|
if method := typ_sym.find_method(method_call_expr.name) {
|
||||||
|
@ -211,7 +152,7 @@ pub fn (c &Checker) check_method_call_expr(method_call_expr ast.MethodCallExpr)
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.Type {
|
pub fn (c mut Checker) selector_expr(selector_expr ast.SelectorExpr) table.Type {
|
||||||
typ := c.expr(selector_expr.expr)
|
typ := c.expr(selector_expr.expr)
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
field_name := selector_expr.field
|
field_name := selector_expr.field
|
||||||
|
@ -221,9 +162,6 @@ pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.Type {
|
||||||
// check parent
|
// check parent
|
||||||
if !isnil(typ_sym.parent) {
|
if !isnil(typ_sym.parent) {
|
||||||
if field := typ_sym.parent.find_field(field_name) {
|
if field := typ_sym.parent.find_field(field_name) {
|
||||||
if table.type_is_unresolved(field.typ) {
|
|
||||||
return c.resolved[field.typ]
|
|
||||||
}
|
|
||||||
return field.typ
|
return field.typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,7 +175,7 @@ pub fn (c &Checker) selector_expr(selector_expr ast.SelectorExpr) table.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: non deferred
|
// TODO: non deferred
|
||||||
pub fn (c &Checker) return_stmt(return_stmt ast.Return) {
|
pub fn (c mut Checker) return_stmt(return_stmt ast.Return) {
|
||||||
mut got_types := []table.Type
|
mut got_types := []table.Type
|
||||||
if return_stmt.exprs.len == 0 {
|
if return_stmt.exprs.len == 0 {
|
||||||
return
|
return
|
||||||
|
@ -268,8 +206,14 @@ pub fn (c &Checker) return_stmt(return_stmt ast.Return) {
|
||||||
|
|
||||||
pub fn (c &Checker) assign_stmt(assign_stmt ast.AssignStmt) {}
|
pub fn (c &Checker) assign_stmt(assign_stmt ast.AssignStmt) {}
|
||||||
|
|
||||||
pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.Type {
|
pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
|
||||||
mut elem_type := table.void_type
|
mut elem_type := table.void_type
|
||||||
|
|
||||||
|
// a = []
|
||||||
|
if array_init.exprs.len == 0 {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
for i, expr in array_init.exprs {
|
for i, expr in array_init.exprs {
|
||||||
c.expr(expr)
|
c.expr(expr)
|
||||||
typ := c.expr(expr)
|
typ := c.expr(expr)
|
||||||
|
@ -283,10 +227,21 @@ pub fn (c &Checker) array_init(array_init ast.ArrayInit) table.Type {
|
||||||
c.error('expected array element with type `$elem_type_sym.name`', array_init.pos)
|
c.error('expected array element with type `$elem_type_sym.name`', array_init.pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//idx := if is_fixed { p.table.find_or_register_array_fixed(val_type, fixed_size, 1) } else { p.table.find_or_register_array(val_type, 1) }
|
||||||
|
is_fixed := false
|
||||||
|
fixed_size := 1
|
||||||
|
idx := if is_fixed {
|
||||||
|
c.table.find_or_register_array_fixed(elem_type, fixed_size, 1)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c.table.find_or_register_array(elem_type, 1)
|
||||||
|
}
|
||||||
|
array_type := table.new_type(idx)
|
||||||
|
array_init.typ = array_type
|
||||||
return array_init.typ
|
return array_init.typ
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c &Checker) stmt(node ast.Stmt) {
|
fn (c mut Checker) stmt(node ast.Stmt) {
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
for stmt in it.stmts {
|
for stmt in it.stmts {
|
||||||
|
@ -299,14 +254,29 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
||||||
ast.AssignStmt {
|
ast.AssignStmt {
|
||||||
c.assign_stmt(it)
|
c.assign_stmt(it)
|
||||||
}
|
}
|
||||||
ast.VarDecl {
|
ast.ConstDecl {
|
||||||
typ := c.expr(it.expr)
|
for i, expr in it.exprs {
|
||||||
// println('checker: var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')
|
mut field := it.fields[i]
|
||||||
// if typ.typ.kind != .void {
|
typ := c.expr(expr)
|
||||||
if table.type_idx(typ) != table.void_type_idx {
|
mut xconst := c.table.consts[field.name]
|
||||||
it.typ = typ
|
//if xconst.typ == 0 {
|
||||||
|
xconst.typ = typ
|
||||||
|
c.table.consts[field.name] = xconst
|
||||||
|
//}
|
||||||
|
field.typ = typ
|
||||||
|
it.fields[i] = field
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast.VarDecl {
|
||||||
|
println('VARDECL')
|
||||||
|
typ := c.expr(it.expr)
|
||||||
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
|
//println('var $it.name - $typ - $it.typ')
|
||||||
|
//if it.typ == 0 {
|
||||||
|
// it.typ = typ
|
||||||
|
//}
|
||||||
|
it.typ = typ
|
||||||
|
}
|
||||||
ast.ForStmt {
|
ast.ForStmt {
|
||||||
typ := c.expr(it.cond)
|
typ := c.expr(it.cond)
|
||||||
// typ_sym := c.table.get_type_symbol(typ)
|
// typ_sym := c.table.get_type_symbol(typ)
|
||||||
|
@ -334,7 +304,7 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
pub fn (c mut Checker) expr(node ast.Expr) table.Type {
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.AssignExpr {
|
ast.AssignExpr {
|
||||||
c.check_assign_expr(it)
|
c.check_assign_expr(it)
|
||||||
|
@ -342,7 +312,9 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
return table.int_type
|
return table.int_type
|
||||||
}
|
}
|
||||||
// ast.FloatLiteral {}
|
ast.FloatLiteral{
|
||||||
|
return table.f64_type
|
||||||
|
}
|
||||||
ast.PostfixExpr {
|
ast.PostfixExpr {
|
||||||
return c.postfix_expr(it)
|
return c.postfix_expr(it)
|
||||||
}
|
}
|
||||||
|
@ -351,7 +323,6 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||||
c.expr(it.left)
|
c.expr(it.left)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
|
@ -371,26 +342,59 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||||
return c.check_method_call_expr(it)
|
return c.check_method_call_expr(it)
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
return c.array_init(it)
|
return c.array_init(mut it)
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
|
//println('IDENT: $it.name - $it.pos.pos')
|
||||||
if it.kind == .variable {
|
if it.kind == .variable {
|
||||||
mut info := it.info as ast.IdentVar
|
//println('===========================')
|
||||||
if table.type_is_unresolved(info.typ) {
|
//ast.print_scope_vars(&c.scope, 0)
|
||||||
typ := c.resolve(info.typ)
|
//println('===========================')
|
||||||
info.typ = typ
|
info := it.info as ast.IdentVar
|
||||||
it.info = info
|
if info.typ != 0 {
|
||||||
|
return info.typ
|
||||||
|
}
|
||||||
|
if inner := c.scope.innermost(it.pos.pos) {
|
||||||
|
mut found := true
|
||||||
|
mut varscope, var := inner.find_scope_and_var(it.name) or {
|
||||||
|
//ast.print_scope_vars(inner, 0)
|
||||||
|
found = false
|
||||||
|
c.error('not found: $it.name - POS: $it.pos.pos', it.pos)
|
||||||
|
panic('')
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
mut typ := var.typ
|
||||||
|
// set var type on first use
|
||||||
|
if var.typ == 0 {
|
||||||
|
typ = c.expr(var.expr)
|
||||||
|
mut v1 := var
|
||||||
|
v1.typ = typ
|
||||||
|
varscope.vars[var.name] = v1
|
||||||
|
}
|
||||||
|
// update ident
|
||||||
|
it.kind = .variable
|
||||||
|
it.info = ast.IdentVar{
|
||||||
|
typ: typ
|
||||||
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
return info.typ
|
}
|
||||||
}
|
}
|
||||||
// Handle indents with unresolved types during the parsing step
|
// Handle indents with unresolved types during the parsing step
|
||||||
// (declared after first usage)
|
// (declared after first usage)
|
||||||
else if it.kind == .blank_ident {
|
else if it.kind == .constant {
|
||||||
if constant := c.table.find_const(it.name) {
|
if constant := c.table.find_const(it.name) {
|
||||||
return constant.typ
|
return constant.typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if it.kind == .blank_ident {
|
||||||
|
println('CONST A: $it.name')
|
||||||
|
if constant := c.table.find_const(it.name) {
|
||||||
|
println('CONST: $it.name')
|
||||||
|
|
||||||
|
return constant.typ
|
||||||
|
}
|
||||||
|
}
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
ast.BoolLiteral {
|
ast.BoolLiteral {
|
||||||
|
@ -403,20 +407,10 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||||
return c.index_expr(it)
|
return c.index_expr(it)
|
||||||
}
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
typ := c.expr(it.cond)
|
return c.if_expr(mut it)
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
|
||||||
// if typ_sym.kind != .bool {
|
|
||||||
if table.type_idx(typ) != table.bool_type_idx {
|
|
||||||
c.error('non-bool (`$typ_sym.name`) used as if condition', it.pos)
|
|
||||||
}
|
|
||||||
for i, stmt in it.stmts {
|
|
||||||
c.stmt(stmt)
|
|
||||||
}
|
|
||||||
if it.else_stmts.len > 0 {
|
|
||||||
for stmt in it.else_stmts {
|
|
||||||
c.stmt(stmt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ast.MatchExpr {
|
||||||
|
return c.match_expr(mut it)
|
||||||
}
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
return it.typ
|
return it.typ
|
||||||
|
@ -426,7 +420,70 @@ pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
|
||||||
|
t := c.expr(node.cond)
|
||||||
|
for i, block in node.blocks {
|
||||||
|
match_expr := node.match_exprs[i]
|
||||||
|
c.expr(match_expr)
|
||||||
|
for stmt in block.stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
// If the last statement is an expression, return its type
|
||||||
|
if block.stmts.len > 0 {
|
||||||
|
match block.stmts[block.stmts.len - 1] {
|
||||||
|
ast.ExprStmt {
|
||||||
|
// TODO: ask alex about this
|
||||||
|
//typ := c.expr(it.expr)
|
||||||
|
//type_sym := c.table.get_type_symbol(typ)
|
||||||
|
//p.warn('match expr ret $type_sym.name')
|
||||||
|
//node.typ = typ
|
||||||
|
//return typ
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.typ = t
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
|
||||||
|
typ := c.expr(node.cond)
|
||||||
|
node.typ = typ
|
||||||
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
|
// if typ_sym.kind != .bool {
|
||||||
|
if table.type_idx(typ) != table.bool_type_idx {
|
||||||
|
c.error('non-bool (`$typ_sym.name`) used as if condition', node.pos)
|
||||||
|
}
|
||||||
|
for i, stmt in node.stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
if node.else_stmts.len > 0 {
|
||||||
|
for stmt in node.else_stmts {
|
||||||
|
c.stmt(stmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.stmts.len > 0 {
|
||||||
|
match node.stmts[node.stmts.len - 1] {
|
||||||
|
ast.ExprStmt {
|
||||||
|
//type_sym := p.table.get_type_symbol(it.typ)
|
||||||
|
//p.warn('if expr ret $type_sym.name')
|
||||||
|
//typ = it.typ
|
||||||
|
//return it.typ
|
||||||
|
t := c.expr(it.expr)
|
||||||
|
node.typ = t
|
||||||
|
return t
|
||||||
|
// return node,it.ti
|
||||||
|
// left =
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return typ
|
||||||
|
//return table.void_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (c mut Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
||||||
/*
|
/*
|
||||||
match node.expr {
|
match node.expr {
|
||||||
ast.IdentVar {
|
ast.IdentVar {
|
||||||
|
@ -444,7 +501,16 @@ pub fn (c &Checker) postfix_expr(node ast.PostfixExpr) table.Type {
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) index_expr(node ast.IndexExpr) table.Type {
|
pub fn (c mut Checker) index_expr(node ast.IndexExpr) table.Type {
|
||||||
|
/*
|
||||||
|
mut typ := left_type
|
||||||
|
left_type_sym := p.table.get_type_symbol(left_type)
|
||||||
|
if left_type_sym.kind == .array {
|
||||||
|
info := left_type_sym.info as table.Array
|
||||||
|
typ = info.elem_type
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
mut typ := c.expr(node.left)
|
mut typ := c.expr(node.left)
|
||||||
mut is_range := false // TODO is_range := node.index is ast.RangeExpr
|
mut is_range := false // TODO is_range := node.index is ast.RangeExpr
|
||||||
match node.index {
|
match node.index {
|
||||||
|
|
|
@ -112,12 +112,12 @@ void println(string s) {
|
||||||
|
|
||||||
void matches() {
|
void matches() {
|
||||||
int a = 100;
|
int a = 100;
|
||||||
int tmp2 = a;
|
int tmp3 = a;
|
||||||
if tmp2 == 10{
|
if tmp3 == 10{
|
||||||
println(tos3("10"));
|
println(tos3("10"));
|
||||||
|
|
||||||
}
|
}
|
||||||
if tmp2 == 20{
|
if tmp3 == 20{
|
||||||
int k = a + 1;
|
int k = a + 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -310,6 +310,7 @@ pub fn (g mut Gen) call_fn(name string) {
|
||||||
|
|
||||||
fn (g mut Gen) stmt(node ast.Stmt) {
|
fn (g mut Gen) stmt(node ast.Stmt) {
|
||||||
match node {
|
match node {
|
||||||
|
ast.ConstDecl {}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
is_main := it.name == 'main'
|
is_main := it.name == 'main'
|
||||||
if is_main {
|
if is_main {
|
||||||
|
|
|
@ -8,17 +8,15 @@ import (
|
||||||
v.table
|
v.table
|
||||||
)
|
)
|
||||||
|
|
||||||
pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
|
pub fn (p mut Parser) call_expr() ast.CallExpr {
|
||||||
tok := p.tok
|
tok := p.tok
|
||||||
fn_name := p.check_name()
|
fn_name := p.check_name()
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
// mut return_ti := types.void_ti
|
|
||||||
args := p.call_args()
|
args := p.call_args()
|
||||||
node := ast.CallExpr{
|
node := ast.CallExpr{
|
||||||
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 {
|
||||||
|
@ -26,10 +24,9 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) {
|
||||||
p.parse_block()
|
p.parse_block()
|
||||||
}
|
}
|
||||||
if f := p.table.find_fn(fn_name) {
|
if f := p.table.find_fn(fn_name) {
|
||||||
return node,f.return_type
|
return node
|
||||||
}
|
}
|
||||||
typ := p.add_unresolved('${fn_name}()', node)
|
return node
|
||||||
return node,typ
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) call_args() []ast.Expr {
|
pub fn (p mut Parser) call_args() []ast.Expr {
|
||||||
|
@ -49,12 +46,13 @@ pub fn (p mut Parser) call_args() []ast.Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) fn_decl() ast.FnDecl {
|
fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
p.table.clear_vars()
|
//p.table.clear_vars()
|
||||||
|
p.open_scope()
|
||||||
is_pub := p.tok.kind == .key_pub
|
is_pub := p.tok.kind == .key_pub
|
||||||
if is_pub {
|
if is_pub {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
p.table.clear_vars()
|
//p.table.clear_vars()
|
||||||
p.check(.key_fn)
|
p.check(.key_fn)
|
||||||
// C.
|
// C.
|
||||||
is_c := p.tok.kind == .name && p.tok.lit == 'C'
|
is_c := p.tok.kind == .name && p.tok.lit == 'C'
|
||||||
|
@ -74,7 +72,11 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
rec_type = p.parse_type()
|
rec_type = p.parse_type()
|
||||||
p.table.register_var(table.Var{
|
//p.table.register_var(table.Var{
|
||||||
|
// name: rec_name
|
||||||
|
// typ: rec_type
|
||||||
|
//})
|
||||||
|
p.scope.register_var(ast.VarDecl{
|
||||||
name: rec_name
|
name: rec_name
|
||||||
typ: rec_type
|
typ: rec_type
|
||||||
})
|
})
|
||||||
|
@ -101,7 +103,11 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
typ: ast_arg.typ
|
typ: ast_arg.typ
|
||||||
}
|
}
|
||||||
args << var
|
args << var
|
||||||
p.table.register_var(var)
|
p.scope.register_var(ast.VarDecl{
|
||||||
|
name: ast_arg.name
|
||||||
|
typ: ast_arg.typ
|
||||||
|
})
|
||||||
|
//p.table.register_var(var)
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
/*
|
/*
|
||||||
|
@ -149,6 +155,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
if p.tok.kind == .lcbr {
|
if p.tok.kind == .lcbr {
|
||||||
stmts = p.parse_block()
|
stmts = p.parse_block()
|
||||||
}
|
}
|
||||||
|
p.close_scope()
|
||||||
return ast.FnDecl{
|
return ast.FnDecl{
|
||||||
name: name
|
name: name
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
|
|
@ -78,6 +78,13 @@ pub fn (p mut Parser) parse_fn_type() table.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) parse_type() table.Type {
|
pub fn (p mut Parser) parse_type() table.Type {
|
||||||
|
// optional
|
||||||
|
mut is_optional := false
|
||||||
|
if p.tok.kind == .question {
|
||||||
|
p.next()
|
||||||
|
is_optional = true
|
||||||
|
}
|
||||||
|
// &Type
|
||||||
mut nr_muls := 0
|
mut nr_muls := 0
|
||||||
for p.tok.kind == .amp {
|
for p.tok.kind == .amp {
|
||||||
p.check(.amp)
|
p.check(.amp)
|
||||||
|
@ -87,9 +94,6 @@ pub fn (p mut Parser) parse_type() table.Type {
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
}
|
}
|
||||||
if p.tok.kind == .question {
|
|
||||||
p.next()
|
|
||||||
}
|
|
||||||
// `module.Type`
|
// `module.Type`
|
||||||
if p.peek_tok.kind == .dot {
|
if p.peek_tok.kind == .dot {
|
||||||
// /if !(p.tok.lit in p.table.imports) {
|
// /if !(p.tok.lit in p.table.imports) {
|
||||||
|
|
|
@ -43,18 +43,19 @@ mut:
|
||||||
pref &pref.Preferences // Preferences shared from V struct
|
pref &pref.Preferences // Preferences shared from V struct
|
||||||
builtin_mod bool
|
builtin_mod bool
|
||||||
mod string
|
mod string
|
||||||
unresolved []ast.Expr
|
|
||||||
unresolved_offset int
|
|
||||||
expected_type table.Type
|
expected_type table.Type
|
||||||
|
scope &ast.Scope
|
||||||
}
|
}
|
||||||
|
|
||||||
// for tests
|
// for tests
|
||||||
pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
|
pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
|
||||||
s := scanner.new_scanner(text)
|
s := scanner.new_scanner(text)
|
||||||
mut p := Parser{
|
mut p := Parser{
|
||||||
scanner: s
|
scanner: s
|
||||||
table: table
|
table: table
|
||||||
pref: &pref.Preferences{}
|
pref: &pref.Preferences{}
|
||||||
|
scope: scope
|
||||||
|
//scope: &ast.Scope{start_pos: 0, parent: 0}
|
||||||
}
|
}
|
||||||
p.init_parse_fns()
|
p.init_parse_fns()
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
|
@ -72,9 +73,10 @@ 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{}
|
||||||
unresolved_offset: table.unresolved_idxs.size
|
scope: &ast.Scope{start_pos: 0, parent: 0}
|
||||||
}
|
}
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
|
//p.scope = &ast.Scope{start_pos: p.tok.position(), parent: 0}
|
||||||
// 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'
|
||||||
} }
|
} }
|
||||||
|
@ -97,12 +99,15 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
||||||
}
|
}
|
||||||
// println('nr stmts = $stmts.len')
|
// println('nr stmts = $stmts.len')
|
||||||
// println(stmts[0])
|
// println(stmts[0])
|
||||||
|
|
||||||
|
p.scope.end_pos = p.tok.pos
|
||||||
|
|
||||||
return ast.File{
|
return ast.File{
|
||||||
path: path
|
path: path
|
||||||
mod: module_decl
|
mod: module_decl
|
||||||
imports: imports
|
imports: imports
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
unresolved: p.unresolved
|
scope: *p.scope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +131,22 @@ pub fn (p mut Parser) read_first_token() {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn (p mut Parser) open_scope() {
|
||||||
|
p.scope = &ast.Scope{
|
||||||
|
parent: p.scope
|
||||||
|
start_pos: p.tok.pos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Parser) close_scope() {
|
||||||
|
p.scope.end_pos = p.tok.pos
|
||||||
|
p.scope.parent.children << p.scope
|
||||||
|
p.scope = p.scope.parent
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) parse_block() []ast.Stmt {
|
pub fn (p mut Parser) parse_block() []ast.Stmt {
|
||||||
|
p.open_scope()
|
||||||
p.table.open_scope()
|
p.table.open_scope()
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
mut stmts := []ast.Stmt
|
mut stmts := []ast.Stmt
|
||||||
|
@ -140,6 +160,8 @@ pub fn (p mut Parser) parse_block() []ast.Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
|
println('parse block')
|
||||||
|
p.close_scope()
|
||||||
p.table.close_scope()
|
p.table.close_scope()
|
||||||
// println('nr exprs in block = $exprs.len')
|
// println('nr exprs in block = $exprs.len')
|
||||||
return stmts
|
return stmts
|
||||||
|
@ -266,10 +288,11 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
||||||
if p.tok.kind == .name && p.peek_tok.kind in [.comma] {
|
if p.tok.kind == .name && p.peek_tok.kind in [.comma] {
|
||||||
return p.assign_stmt()
|
return p.assign_stmt()
|
||||||
}
|
}
|
||||||
expr,typ := p.expr(0)
|
//expr,typ := p.expr(0)
|
||||||
|
expr,_ := p.expr(0)
|
||||||
return ast.ExprStmt{
|
return ast.ExprStmt{
|
||||||
expr: expr
|
expr: expr
|
||||||
typ: typ
|
//typ: typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,21 +435,21 @@ pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.Type) {
|
||||||
mut ident := ast.Ident{
|
mut ident := ast.Ident{
|
||||||
name: name
|
name: name
|
||||||
is_c: is_c
|
is_c: is_c
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
mut known_var := false
|
mut known_var := false
|
||||||
if var := p.table.find_var(name) {
|
if var := p.scope.find_var(name) {
|
||||||
known_var = true
|
known_var = true
|
||||||
typ = var.typ
|
// typ = var.typ
|
||||||
}
|
}
|
||||||
// variable
|
// variable
|
||||||
if known_var || p.tok.kind in [.comma, .decl_assign, .assign] {
|
if known_var /* || p.tok.kind in [.comma, .decl_assign, .assign]*/ {
|
||||||
// println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx')
|
// println('#### IDENT: $var.name: $var.typ.typ.name - $var.typ.idx')
|
||||||
ident.kind = .variable
|
ident.kind = .variable
|
||||||
ident.info = ast.IdentVar{
|
ident.info = ast.IdentVar{
|
||||||
typ: typ
|
//typ: typ
|
||||||
// name: ident.name
|
// name: ident.name
|
||||||
// expr: p.expr(0)// var.expr
|
// expr: p.expr(0)// var.expr
|
||||||
|
|
||||||
}
|
}
|
||||||
return ident,typ
|
return ident,typ
|
||||||
}
|
}
|
||||||
|
@ -457,6 +480,7 @@ pub fn (p mut Parser) parse_ident(is_c bool) (ast.Ident,table.Type) {
|
||||||
node = ast.Ident{
|
node = ast.Ident{
|
||||||
kind: .blank_ident
|
kind: .blank_ident
|
||||||
name: name
|
name: name
|
||||||
|
//pos: p.tok.position()
|
||||||
}
|
}
|
||||||
return node,typ
|
return node,typ
|
||||||
// p.error('parse_ident: unknown identifier `$name`')
|
// p.error('parse_ident: unknown identifier `$name`')
|
||||||
|
@ -559,9 +583,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
||||||
// fn call
|
// fn call
|
||||||
else {
|
else {
|
||||||
println('calling $p.tok.lit')
|
println('calling $p.tok.lit')
|
||||||
x,ti2 := p.call_expr() // TODO `node,typ :=` should work
|
x := p.call_expr() // TODO `node,typ :=` should work
|
||||||
node = x
|
node = x
|
||||||
typ = ti2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || is_c || p.tok.lit in ['array', 'string', 'ustring', 'mapnode', 'map']) && !p.tok.lit[p.tok.lit.len - 1].is_capital() {
|
else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || is_c || p.tok.lit in ['array', 'string', 'ustring', 'mapnode', 'map']) && !p.tok.lit[p.tok.lit.len - 1].is_capital() {
|
||||||
|
@ -615,7 +638,8 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
.key_match {
|
.key_match {
|
||||||
node,typ = p.match_expr()
|
//node,typ = p.match_expr()
|
||||||
|
node = p.match_expr()
|
||||||
}
|
}
|
||||||
.number {
|
.number {
|
||||||
node,typ = p.parse_number_literal()
|
node,typ = p.parse_number_literal()
|
||||||
|
@ -626,10 +650,11 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
}
|
}
|
||||||
.key_if {
|
.key_if {
|
||||||
node,typ = p.if_expr()
|
node = p.if_expr()
|
||||||
}
|
}
|
||||||
.lsbr {
|
.lsbr {
|
||||||
node,typ = p.array_init()
|
//node,typ = p.array_init()
|
||||||
|
node = p.array_init()
|
||||||
}
|
}
|
||||||
.key_none {
|
.key_none {
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -669,13 +694,15 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
|
||||||
node = p.assign_expr(node)
|
node = p.assign_expr(node)
|
||||||
}
|
}
|
||||||
else if p.tok.kind == .dot {
|
else if p.tok.kind == .dot {
|
||||||
node,typ = p.dot_expr(node, typ)
|
node = p.dot_expr(node, typ)
|
||||||
}
|
}
|
||||||
else if p.tok.kind == .lsbr {
|
else if p.tok.kind == .lsbr {
|
||||||
// node = p.index_expr(node) // , typ)
|
node = p.index_expr(node) // , typ)
|
||||||
|
/*
|
||||||
ie_node,ie_typ := p.index_expr(node, typ)
|
ie_node,ie_typ := p.index_expr(node, typ)
|
||||||
node = ie_node
|
node = ie_node
|
||||||
typ = ie_typ
|
typ = ie_typ
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else if p.tok.kind == .key_as {
|
else if p.tok.kind == .key_as {
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -712,7 +739,7 @@ fn (p mut Parser) prefix_expr() (ast.Expr,table.Type) {
|
||||||
return expr,typ
|
return expr,typ
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) index_expr(left ast.Expr, left_type table.Type) (ast.IndexExpr,table.Type) {
|
fn (p mut Parser) index_expr(left ast.Expr) ast.IndexExpr {
|
||||||
// left == `a` in `a[0]`
|
// left == `a` in `a[0]`
|
||||||
p.next() // [
|
p.next() // [
|
||||||
if p.tok.kind == .dotdot {
|
if p.tok.kind == .dotdot {
|
||||||
|
@ -727,7 +754,7 @@ fn (p mut Parser) index_expr(left ast.Expr, left_type table.Type) (ast.IndexExpr
|
||||||
low: ast.Expr{}
|
low: ast.Expr{}
|
||||||
high: high
|
high: high
|
||||||
}
|
}
|
||||||
},left_type // TODO: return correct type
|
}
|
||||||
}
|
}
|
||||||
expr,_ := p.expr(0) // `[expr]` or `[expr..]`
|
expr,_ := p.expr(0) // `[expr]` or `[expr..]`
|
||||||
if p.tok.kind == .dotdot {
|
if p.tok.kind == .dotdot {
|
||||||
|
@ -745,35 +772,44 @@ fn (p mut Parser) index_expr(left ast.Expr, left_type table.Type) (ast.IndexExpr
|
||||||
low: expr
|
low: expr
|
||||||
high: high
|
high: high
|
||||||
}
|
}
|
||||||
},left_type // TODO: return correct type
|
}
|
||||||
}
|
}
|
||||||
// get the element type
|
// get the element type
|
||||||
|
/*
|
||||||
mut typ := left_type
|
mut typ := left_type
|
||||||
left_type_sym := p.table.get_type_symbol(left_type)
|
left_type_sym := p.table.get_type_symbol(left_type)
|
||||||
if left_type_sym.kind == .array {
|
if left_type_sym.kind == .array {
|
||||||
info := left_type_sym.info as table.Array
|
info := left_type_sym.info as table.Array
|
||||||
typ = info.elem_type
|
typ = info.elem_type
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// [expr]
|
// [expr]
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return ast.IndexExpr{
|
return ast.IndexExpr{
|
||||||
left: left
|
left: left
|
||||||
index: expr
|
index: expr
|
||||||
pos: p.tok.position()
|
pos: p.tok.position()
|
||||||
},typ
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) filter(typ table.Type) {
|
fn (p mut Parser) filter(typ table.Type) {
|
||||||
|
/*
|
||||||
p.table.register_var(table.Var{
|
p.table.register_var(table.Var{
|
||||||
name: 'it'
|
name: 'it'
|
||||||
typ: typ
|
typ: typ
|
||||||
})
|
})
|
||||||
|
*/
|
||||||
|
p.scope.register_var(ast.VarDecl{
|
||||||
|
name: 'it'
|
||||||
|
typ: typ
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) (ast.Expr,table.Type) {
|
fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) ast.Expr {
|
||||||
p.next()
|
p.next()
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
if field_name == 'filter' {
|
if field_name == 'filter' {
|
||||||
|
p.open_scope()
|
||||||
p.table.open_scope()
|
p.table.open_scope()
|
||||||
p.filter(left_type)
|
p.filter(left_type)
|
||||||
}
|
}
|
||||||
|
@ -794,8 +830,8 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) (ast.Expr,table.
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = mcall_expr
|
node = mcall_expr
|
||||||
// typ := p.add_unresolved('${left_type.typ.name}.${field_name}()', mcall_expr)
|
// typ := p.add_unresolved('${left_type.typ.name}.${field_name}()', mcall_expr)
|
||||||
typ := p.add_unresolved('${table.type_idx(left_type)}.${field_name}()', mcall_expr)
|
// typ := p.add_unresolved('${table.type_idx(left_type)}.${field_name}()', mcall_expr)
|
||||||
return node,typ
|
return node
|
||||||
}
|
}
|
||||||
sel_expr := ast.SelectorExpr{
|
sel_expr := ast.SelectorExpr{
|
||||||
expr: left
|
expr: left
|
||||||
|
@ -803,13 +839,14 @@ fn (p mut Parser) dot_expr(left ast.Expr, left_type table.Type) (ast.Expr,table.
|
||||||
pos: p.tok.position()
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
// typ := p.add_unresolved('${left_type.typ.name}.$field_name', sel_expr)
|
// typ := p.add_unresolved('${left_type.typ.name}.$field_name', sel_expr)
|
||||||
typ := p.add_unresolved('${table.type_idx(left_type)}.$field_name', sel_expr)
|
// typ := p.add_unresolved('${table.type_idx(left_type)}.$field_name', sel_expr)
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = sel_expr
|
node = sel_expr
|
||||||
if field_name == 'filter' {
|
if field_name == 'filter' {
|
||||||
|
p.close_scope()
|
||||||
p.table.close_scope()
|
p.table.close_scope()
|
||||||
}
|
}
|
||||||
return node,typ
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.Type) {
|
fn (p mut Parser) infix_expr(left ast.Expr) (ast.Expr,table.Type) {
|
||||||
|
@ -853,11 +890,13 @@ fn (p mut Parser) enum_val() (ast.Expr,table.Type) {
|
||||||
|
|
||||||
fn (p mut Parser) for_statement() ast.Stmt {
|
fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
p.check(.key_for)
|
p.check(.key_for)
|
||||||
|
p.open_scope()
|
||||||
p.table.open_scope()
|
p.table.open_scope()
|
||||||
// defer { p.table.close_scope() }
|
// defer { p.table.close_scope() }
|
||||||
// Infinite loop
|
// Infinite loop
|
||||||
if p.tok.kind == .lcbr {
|
if p.tok.kind == .lcbr {
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
p.close_scope()
|
||||||
p.table.close_scope()
|
p.table.close_scope()
|
||||||
return ast.ForStmt{
|
return ast.ForStmt{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
@ -896,6 +935,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
inc = p.stmt()
|
inc = p.stmt()
|
||||||
}
|
}
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
p.close_scope()
|
||||||
p.table.close_scope()
|
p.table.close_scope()
|
||||||
return ast.ForCStmt{
|
return ast.ForCStmt{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
@ -910,7 +950,11 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
val_name := p.check_name()
|
val_name := p.check_name()
|
||||||
p.table.register_var(table.Var{
|
//p.table.register_var(table.Var{
|
||||||
|
// name: val_name
|
||||||
|
// typ: table.int_type
|
||||||
|
//})
|
||||||
|
p.scope.register_var(ast.VarDecl{
|
||||||
name: val_name
|
name: val_name
|
||||||
typ: table.int_type
|
typ: table.int_type
|
||||||
})
|
})
|
||||||
|
@ -945,12 +989,17 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
p.check(.dotdot)
|
p.check(.dotdot)
|
||||||
p.expr(0)
|
p.expr(0)
|
||||||
}
|
}
|
||||||
p.table.register_var(table.Var{
|
//p.table.register_var(table.Var{
|
||||||
|
// name: var_name
|
||||||
|
// typ: elem_type
|
||||||
|
//})
|
||||||
|
p.scope.register_var(ast.VarDecl{
|
||||||
name: var_name
|
name: var_name
|
||||||
typ: elem_type
|
typ: elem_type
|
||||||
})
|
})
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
// println('nr stmts=$stmts.len')
|
// println('nr stmts=$stmts.len')
|
||||||
|
p.close_scope()
|
||||||
p.table.close_scope()
|
p.table.close_scope()
|
||||||
return ast.ForStmt{
|
return ast.ForStmt{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
@ -960,6 +1009,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
// `for cond {`
|
// `for cond {`
|
||||||
cond,_ := p.expr(0)
|
cond,_ := p.expr(0)
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
p.close_scope()
|
||||||
p.table.close_scope()
|
p.table.close_scope()
|
||||||
return ast.ForStmt{
|
return ast.ForStmt{
|
||||||
cond: cond
|
cond: cond
|
||||||
|
@ -968,7 +1018,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
fn (p mut Parser) if_expr() ast.Expr {
|
||||||
p.inside_if = true
|
p.inside_if = true
|
||||||
// defer {
|
// defer {
|
||||||
// }
|
// }
|
||||||
|
@ -996,9 +1046,10 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
||||||
else_stmts = p.parse_block()
|
else_stmts = p.parse_block()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mut typ := table.void_type
|
//mut typ := table.void_type
|
||||||
// mut left := ast.Expr{}
|
// mut left := ast.Expr{}
|
||||||
// If the last statement is an expression, return its type
|
// If the last statement is an expression, return its type
|
||||||
|
/*
|
||||||
if stmts.len > 0 {
|
if stmts.len > 0 {
|
||||||
match stmts[stmts.len - 1] {
|
match stmts[stmts.len - 1] {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
|
@ -1011,16 +1062,17 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
node = ast.IfExpr{
|
node = ast.IfExpr{
|
||||||
cond: cond
|
cond: cond
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
else_stmts: else_stmts
|
else_stmts: else_stmts
|
||||||
typ: typ
|
//typ: typ
|
||||||
pos: p.tok.position()
|
pos: p.tok.position()
|
||||||
// left: left
|
// left: left
|
||||||
|
|
||||||
}
|
}
|
||||||
return node,typ
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
|
fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
|
||||||
|
@ -1054,7 +1106,8 @@ fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
|
||||||
return node,table.string_type
|
return node,table.string_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
//fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
||||||
|
fn (p mut Parser) array_init() ast.Expr {
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
// `[]` - empty array with an automatically deduced type
|
// `[]` - empty array with an automatically deduced type
|
||||||
|
@ -1066,6 +1119,7 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* TODO: joe
|
||||||
if p.tok.kind == .rsbr && int(p.expected_type) != 0 && p.table.get_type_symbol(p.expected_type).kind == .array {
|
if p.tok.kind == .rsbr && int(p.expected_type) != 0 && p.table.get_type_symbol(p.expected_type).kind == .array {
|
||||||
// p.warn('[] expr')
|
// p.warn('[] expr')
|
||||||
node = ast.ArrayInit{
|
node = ast.ArrayInit{
|
||||||
|
@ -1076,10 +1130,11 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
return node,p.expected_type
|
return node,p.expected_type
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
mut val_type := table.void_type
|
mut val_type := table.void_type
|
||||||
mut exprs := []ast.Expr
|
mut exprs := []ast.Expr
|
||||||
mut is_fixed := false
|
//mut is_fixed := false
|
||||||
mut fixed_size := 0
|
//mut fixed_size := 0
|
||||||
if p.tok.kind == .rsbr {
|
if p.tok.kind == .rsbr {
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
// []string
|
// []string
|
||||||
|
@ -1104,9 +1159,11 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
line_nr := p.tok.line_nr
|
//line_nr := p.tok.line_nr
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
// Fixed size array? (`[100]byte`)
|
// Fixed size array? (`[100]byte`)
|
||||||
|
// NOTE: this should be hanled in parse_type() ?
|
||||||
|
/*
|
||||||
if exprs.len == 1 && p.tok.kind == .name && p.tok.line_nr == line_nr {
|
if exprs.len == 1 && p.tok.kind == .name && p.tok.line_nr == line_nr {
|
||||||
is_fixed = true
|
is_fixed = true
|
||||||
val_type = p.parse_type()
|
val_type = p.parse_type()
|
||||||
|
@ -1118,15 +1175,16 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
||||||
}
|
}
|
||||||
p.warn('fixed size array')
|
p.warn('fixed size array')
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
idx := if is_fixed { p.table.find_or_register_array_fixed(val_type, fixed_size, 1) } else { p.table.find_or_register_array(val_type, 1) }
|
//idx := if is_fixed { p.table.find_or_register_array_fixed(val_type, fixed_size, 1) } else { p.table.find_or_register_array(val_type, 1) }
|
||||||
array_type := table.new_type(idx)
|
//array_type := table.new_type(idx)
|
||||||
node = ast.ArrayInit{
|
node = ast.ArrayInit{
|
||||||
typ: array_type
|
//typ: array_type
|
||||||
exprs: exprs
|
exprs: exprs
|
||||||
pos: p.tok.position()
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
return node,array_type
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) parse_number_literal() (ast.Expr,table.Type) {
|
fn (p mut Parser) parse_number_literal() (ast.Expr,table.Type) {
|
||||||
|
@ -1363,26 +1421,37 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
||||||
}
|
}
|
||||||
name := p.check_name()
|
name := p.check_name()
|
||||||
p.next()
|
p.next()
|
||||||
expr,typ := p.expr(0)
|
//expr,typ := p.expr(0)
|
||||||
if _ := p.table.find_var(name) {
|
expr,_ := p.expr(0)
|
||||||
|
//if _ := p.table.find_var(name) {
|
||||||
|
// p.error('redefinition of `$name`')
|
||||||
|
//}
|
||||||
|
//p.table.register_var(table.Var{
|
||||||
|
// name: name
|
||||||
|
// is_mut: is_mut
|
||||||
|
// typ: typ
|
||||||
|
//})
|
||||||
|
if _ := p.scope.find_var(name) {
|
||||||
p.error('redefinition of `$name`')
|
p.error('redefinition of `$name`')
|
||||||
}
|
}
|
||||||
p.table.register_var(table.Var{
|
//p.scope.register_var(table.Var{
|
||||||
name: name
|
// name: name
|
||||||
is_mut: is_mut
|
// is_mut: is_mut
|
||||||
typ: typ
|
// typ: typ
|
||||||
})
|
//})
|
||||||
typ_sym := p.table.get_type_symbol(typ)
|
|
||||||
p.warn('var decl name=$name typ=$typ_sym.name')
|
//typ_sym := p.table.get_type_symbol(typ)
|
||||||
|
//p.warn('var decl name=$name typ=$typ_sym.name')
|
||||||
// println(p.table.names)
|
// println(p.table.names)
|
||||||
node := ast.VarDecl{
|
node := ast.VarDecl{
|
||||||
name: name
|
name: name
|
||||||
expr: expr // p.expr(token.lowest_prec)
|
expr: expr // p.expr(token.lowest_prec)
|
||||||
|
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
typ: typ
|
//typ: typ
|
||||||
pos: p.tok.position()
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
|
p.scope.register_var(node)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1427,19 +1496,19 @@ fn (p mut Parser) global_decl() ast.GlobalDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
|
fn (p mut Parser) match_expr() ast.Expr {
|
||||||
p.check(.key_match)
|
p.check(.key_match)
|
||||||
is_mut := p.tok.kind == .key_mut
|
is_mut := p.tok.kind == .key_mut
|
||||||
if is_mut {
|
if is_mut {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
cond,typ := p.expr(0)
|
cond,_ := p.expr(0)
|
||||||
// sym := p.table.get_type_symbol(typ)
|
// sym := p.table.get_type_symbol(typ)
|
||||||
// p.warn('match typ $sym.name')
|
// p.warn('match typ $sym.name')
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
mut blocks := []ast.StmtBlock
|
mut blocks := []ast.StmtBlock
|
||||||
mut match_exprs := []ast.Expr
|
mut match_exprs := []ast.Expr
|
||||||
mut return_type := table.void_type
|
//mut return_type := table.void_type
|
||||||
for {
|
for {
|
||||||
// Sum type match
|
// Sum type match
|
||||||
if p.tok.kind == .name && (p.tok.lit[0].is_capital() || p.peek_tok.kind == .dot) {
|
if p.tok.kind == .name && (p.tok.lit[0].is_capital() || p.peek_tok.kind == .dot) {
|
||||||
|
@ -1475,6 +1544,7 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the last statement is an expression, return its type
|
// If the last statement is an expression, return its type
|
||||||
|
/*
|
||||||
if stmts.len > 0 {
|
if stmts.len > 0 {
|
||||||
match stmts[stmts.len - 1] {
|
match stmts[stmts.len - 1] {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
|
@ -1485,6 +1555,8 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if p.tok.kind == .rcbr {
|
if p.tok.kind == .rcbr {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -1494,10 +1566,11 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
|
||||||
node = ast.MatchExpr{
|
node = ast.MatchExpr{
|
||||||
blocks: blocks
|
blocks: blocks
|
||||||
match_exprs: match_exprs
|
match_exprs: match_exprs
|
||||||
typ: typ
|
//typ: typ
|
||||||
cond: cond
|
cond: cond
|
||||||
}
|
}
|
||||||
return node,return_type
|
return node
|
||||||
|
//return node,return_type
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) enum_decl() ast.EnumDecl {
|
fn (p mut Parser) enum_decl() ast.EnumDecl {
|
||||||
|
@ -1562,18 +1635,6 @@ fn (p mut Parser) type_decl() ast.TypeDecl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.Type {
|
|
||||||
mut idx := p.unresolved_offset + p.unresolved.len
|
|
||||||
if key in p.table.unresolved_idxs {
|
|
||||||
idx = p.table.unresolved_idxs[key]
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
p.table.unresolved_idxs[key] = idx
|
|
||||||
p.unresolved << expr
|
|
||||||
}
|
|
||||||
return table.new_type((-idx) - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verror(s string) {
|
fn verror(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
|
@ -32,20 +32,26 @@ fn test_eval() {
|
||||||
'20',
|
'20',
|
||||||
//
|
//
|
||||||
]
|
]
|
||||||
|
/*
|
||||||
table := table.new_table()
|
table := table.new_table()
|
||||||
|
mut scope := ast.Scope{start_pos: 0, parent: 0}
|
||||||
mut stmts := []ast.Stmt
|
mut stmts := []ast.Stmt
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
stmts << parse_stmt(input, table)
|
stmts << parse_stmt(input, table, &scope)
|
||||||
}
|
}
|
||||||
file := ast.File{
|
file := ast.File{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
scope: &scope
|
||||||
}
|
}
|
||||||
|
mut checker := checker.new_checker(table)
|
||||||
|
checker.check(file)
|
||||||
mut ev := eval.Eval{}
|
mut ev := eval.Eval{}
|
||||||
s := ev.eval(file, table)
|
s := ev.eval(file, table)
|
||||||
println('eval done')
|
println('eval done')
|
||||||
println(s)
|
println(s)
|
||||||
assert s == expected.join('\n')
|
assert s == expected.join('\n')
|
||||||
// exit(0)
|
// exit(0)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_parse_file() {
|
fn test_parse_file() {
|
||||||
|
@ -65,6 +71,8 @@ x := 10
|
||||||
'
|
'
|
||||||
table := &table.Table{}
|
table := &table.Table{}
|
||||||
prog := parse_file(s, table)
|
prog := parse_file(s, table)
|
||||||
|
mut checker := checker.new_checker(table)
|
||||||
|
checker.check(prog)
|
||||||
res := gen.cgen([prog], table)
|
res := gen.cgen([prog], table)
|
||||||
println(res)
|
println(res)
|
||||||
}
|
}
|
||||||
|
@ -79,14 +87,21 @@ fn test_one() {
|
||||||
]
|
]
|
||||||
expected := 'int a = 10;int b = -a;int c = 20;'
|
expected := 'int a = 10;int b = -a;int c = 20;'
|
||||||
table := table.new_table()
|
table := table.new_table()
|
||||||
|
mut scope := ast.Scope{start_pos: 0, parent: 0}
|
||||||
mut e := []ast.Stmt
|
mut e := []ast.Stmt
|
||||||
for line in input {
|
for line in input {
|
||||||
e << parse_stmt(line, table)
|
e << parse_stmt(line, table, &scope)
|
||||||
}
|
}
|
||||||
program := ast.File{
|
program := ast.File{
|
||||||
stmts: e
|
stmts: e
|
||||||
|
scope: scope
|
||||||
}
|
}
|
||||||
|
mut checker := checker.new_checker(table)
|
||||||
|
checker.check(program)
|
||||||
|
//ast.print_scope_vars(scope, 0)
|
||||||
|
//ast.print_scope_vars(program.scope, 0)
|
||||||
res := gen.cgen([program], table).replace('\n', '').trim_space()
|
res := gen.cgen([program], table).replace('\n', '').trim_space()
|
||||||
|
println(res)
|
||||||
ok := expected == res
|
ok := expected == res
|
||||||
println(res)
|
println(res)
|
||||||
assert ok
|
assert ok
|
||||||
|
@ -166,12 +181,14 @@ fn test_parse_expr() {
|
||||||
mut e := []ast.Stmt
|
mut e := []ast.Stmt
|
||||||
table := table.new_table()
|
table := table.new_table()
|
||||||
mut checker := checker.new_checker(table)
|
mut checker := checker.new_checker(table)
|
||||||
|
mut scope := ast.Scope{start_pos: 0, parent: 0}
|
||||||
for s in input {
|
for s in input {
|
||||||
println('\n\nst="$s"')
|
println('\n\nst="$s"')
|
||||||
e << parse_stmt(s, table)
|
e << parse_stmt(s, table, &scope)
|
||||||
}
|
}
|
||||||
program := ast.File{
|
program := ast.File{
|
||||||
stmts: e
|
stmts: e
|
||||||
|
scope: scope
|
||||||
}
|
}
|
||||||
checker.check(program)
|
checker.check(program)
|
||||||
res := gen.cgen([program], table)
|
res := gen.cgen([program], table)
|
||||||
|
|
|
@ -80,6 +80,7 @@ fn (s &Scanner) scan_res(tok_kind token.Kind, lit string) token.Token {
|
||||||
kind: tok_kind
|
kind: tok_kind
|
||||||
lit: lit
|
lit: lit
|
||||||
line_nr: s.line_nr + 1
|
line_nr: s.line_nr + 1
|
||||||
|
pos: s.pos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ pub mut:
|
||||||
types []TypeSymbol
|
types []TypeSymbol
|
||||||
// type_idxs Hashmap
|
// type_idxs Hashmap
|
||||||
type_idxs map[string]int
|
type_idxs map[string]int
|
||||||
unresolved_idxs map[string]int
|
|
||||||
local_vars []Var
|
local_vars []Var
|
||||||
scope_level int
|
scope_level int
|
||||||
var_idx int
|
var_idx int
|
||||||
|
@ -308,7 +307,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol {
|
||||||
return &t.types[idx]
|
return &t.types[idx]
|
||||||
}
|
}
|
||||||
// this should never happen
|
// this should never happen
|
||||||
panic('get_type_symbol: invalid type $idx')
|
panic('get_type_symbol: invalid type $typ - $idx')
|
||||||
}
|
}
|
||||||
|
|
||||||
// this will override or register builtin type
|
// this will override or register builtin type
|
||||||
|
|
|
@ -6,14 +6,13 @@ module token
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pub:
|
pub:
|
||||||
line_nr int // the line number in the source where the token occured
|
line_nr int // the line number in the source where the token occured
|
||||||
// pos int // the position of the token in scanner text
|
pos int // the position of the token in scanner text
|
||||||
}
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (tok &Token) position() Position {
|
pub fn (tok &Token) position() Position {
|
||||||
return Position{
|
return Position{
|
||||||
line_nr: tok.line_nr - 1
|
line_nr: tok.line_nr - 1
|
||||||
// pos: tok.pos
|
pos: tok.pos
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub:
|
||||||
lit string // literal representation of the token
|
lit string // literal representation of the token
|
||||||
line_nr int // the line number in the source where the token occured
|
line_nr int // the line number in the source where the token occured
|
||||||
// name_idx int // name table index for O(1) lookup
|
// name_idx int // name table index for O(1) lookup
|
||||||
// pos int // the position of the token in scanner text
|
pos int // the position of the token in scanner text
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Kind {
|
pub enum Kind {
|
||||||
|
|
Loading…
Reference in New Issue