diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index b49db7eb5b..531ecad7cc 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -8,12 +8,13 @@ import ( v.table ) -pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | -FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | -AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | CastExpr +pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | +FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | +AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | +CastExpr | EnumVal -pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | -ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | +pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | +ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | HashStmt | AssignStmt // | IncDecStmt k // Stand-alone expression in a statement list. @@ -366,6 +367,12 @@ pub: name string } +pub struct EnumVal{ +pub: + name string + +} + pub struct AssignExpr { pub: op token.Kind diff --git a/vlib/v/gen/tests/1.c b/vlib/v/gen/tests/1.c index 68b237596a..72c6dd4327 100644 --- a/vlib/v/gen/tests/1.c +++ b/vlib/v/gen/tests/1.c @@ -92,6 +92,13 @@ multi_return_int_string multi_return() { void variadic(variadic_int a) { int x = path_sep; + int y = if (true) { +1; +} +else { +0; +} +; } void ensure_cap(int required, int cap) { @@ -105,12 +112,12 @@ void println(string s) { void matches() { int a = 100; - int tmp1 = a; - if tmp1 == 10{ + int tmp2 = a; + if tmp2 == 10{ println(tos3("10")); } - if tmp1 == 20{ + if tmp2 == 20{ int k = a + 1; } diff --git a/vlib/v/gen/tests/1.vv b/vlib/v/gen/tests/1.vv index 5e56003f7c..4a0f8f9728 100644 --- a/vlib/v/gen/tests/1.vv +++ b/vlib/v/gen/tests/1.vv @@ -98,6 +98,7 @@ fn multi_return() (int,string) { fn variadic(a ...int) { x := path_sep + y := if true { 1 } else { 0 } // TODO cgen } fn ensure_cap(required int, cap int) { @@ -118,6 +119,13 @@ fn matches() { k := a + 1 } } + /* + n := match a { + 1 { 10 } + 2 { 20 } + else { 30 } + } + */ } const ( diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 2afc9d5d90..7a6578e84c 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -18,6 +18,7 @@ pub fn (p mut Parser) call_expr() (ast.CallExpr,table.Type) { name: fn_name args: args // tok: tok + pos: tok.position() } if p.tok.kind == .key_orelse { @@ -121,7 +122,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { typ: arg_type } args << arg - //p.table.register_var(arg) + // p.table.register_var(arg) ast_args << ast.Arg{ name: arg_name typ: arg_type @@ -156,7 +157,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl { 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') } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index cd36ada4c1..f8504682bd 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -45,6 +45,7 @@ mut: mod string unresolved []ast.Expr unresolved_offset int + expected_type table.Type } // for tests @@ -471,13 +472,13 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { if p.peek_tok.kind == .lpar { name := p.tok.lit // type cast. TODO: finish - //if name in table.builtin_type_names { + // if name in table.builtin_type_names { if name in p.table.type_idxs { to_typ := p.parse_type() p.check(.lpar) mut expr := ast.Expr{} - expr,_ = p.expr(0) - // TODO, string(b, len) + expr,_ = p.expr(0) + // TODO, string(b, len) if table.type_idx(to_typ) == table.string_type_idx && p.tok.kind == .comma { p.check(.comma) p.expr(0) // len @@ -487,7 +488,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) { typ: to_typ expr: expr } - return node, to_typ + return node,to_typ } // fn call else { @@ -540,6 +541,10 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) { .str { node,typ = p.string_expr() } + .dot { + // .enum_val + node,typ = p.enum_val() + } .chartoken { typ = table.byte_type node = ast.CharLiteral{ @@ -562,7 +567,7 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) { p.next() } .key_match { - return p.match_expr() + node,typ = p.match_expr() } .number { node,typ = p.parse_number_literal() @@ -747,7 +752,16 @@ fn (p &Parser) is_addative() bool { return p.tok.kind in [.plus, .minus] && p.peek_tok.kind in [.number, .name] } */ - +// `.green` +fn (p mut Parser) enum_val() (ast.Expr,table.Type) { + p.check(.dot) + name := p.check_name() + mut node := ast.Expr{} + node = ast.EnumVal{ + name: name + } + return node,table.bool_type +} fn (p mut Parser) for_statement() ast.Stmt { p.check(.key_for) @@ -815,7 +829,8 @@ fn (p mut Parser) for_statement() ast.Stmt { } p.check(.key_in) mut elem_type := table.void_type - /*arr_expr*/_,arr_typ := p.expr(0) + // arr_expr + _,arr_typ := p.expr(0) // array / map arr_typ_sym := p.table.get_type_symbol(arr_typ) match arr_typ_sym.info { @@ -826,10 +841,11 @@ fn (p mut Parser) for_statement() ast.Stmt { elem_type = it.value_type } else { - //elem_type_sym := p.table.get_type_symbol(elem_type) - //p.error('cannot loop over type: $elem_type_sym.name') + println(1) + // elem_type_sym := p.table.get_type_symbol(elem_type) + // p.error('cannot loop over type: $elem_type_sym.name') } - } + } // 0 .. 10 // start := p.tok.lit.int() if p.tok.kind == .dotdot { @@ -922,7 +938,7 @@ fn (p mut Parser) string_expr() (ast.Expr,table.Type) { } p.check(.str_dollar) p.expr(0) - if p.tok.kind == .semicolon { + if p.tok.kind == .colon { p.next() } } @@ -945,6 +961,7 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) { // [] else { // TODO ? + println(0) } } else { @@ -966,18 +983,15 @@ fn (p mut Parser) array_init() (ast.Expr,table.Type) { is_fixed = true val_type = p.parse_type() match exprs[0] { - ast.IntegerLiteral { fixed_size = it.val } + ast.IntegerLiteral { + fixed_size = it.val + } else {} - } + } 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) node = ast.ArrayInit{ typ: array_type @@ -1252,19 +1266,19 @@ fn (p mut Parser) global_decl() ast.GlobalDecl { p.table.register_global(name, typ) // p.genln(p.table.cgen_name_type_pair(name, typ)) /* - mut g := p.table.cgen_name_type_pair(name, typ) - if p.tok == .assign { - p.next() - g += ' = ' - _,expr := p.tmp_expr() - g += expr - } - // p.genln('; // global') - g += '; // global' - if !p.cgen.nogen { - p.cgen.consts << g - } - */ + mut g := p.table.cgen_name_type_pair(name, typ) + if p.tok == .assign { + p.next() + g += ' = ' + _,expr := p.tmp_expr() + g += expr + } + // p.genln('; // global') + g += '; // global' + if !p.cgen.nogen { + p.cgen.consts << g + } + */ return ast.GlobalDecl{ name: name @@ -1277,13 +1291,15 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) { p.check(.lcbr) mut blocks := []ast.StmtBlock mut match_exprs := []ast.Expr + mut return_type := table.void_type for { // p.tok.kind != .rcbr { match_expr,_ := p.expr(0) match_exprs << match_expr p.warn('match block') + stmts := p.parse_block() blocks << ast.StmtBlock{ - stmts: p.parse_block() + stmts: stmts } if p.tok.kind == .key_else { p.next() @@ -1291,6 +1307,17 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) { stmts: p.parse_block() } } + // If the last statement is an expression, return its type + if stmts.len > 0 { + match stmts[stmts.len - 1] { + ast.ExprStmt { + type_sym := p.table.get_type_symbol(it.typ) + p.warn('match expr ret $type_sym.name') + return_type = it.typ + } + else {} + } + } if p.tok.kind == .rcbr { break } @@ -1303,7 +1330,7 @@ fn (p mut Parser) match_expr() (ast.Expr,table.Type) { typ: typ cond: cond } - return node,table.void_type + return node,return_type } fn (p mut Parser) add_unresolved(key string, expr ast.Expr) table.Type { diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index d7e6088eed..c41c0f40a7 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -168,6 +168,7 @@ pub fn (p mut Table) clear_vars() { // ///} p.local_vars = [] } + p.tmp_cnt = 0 } pub fn (t &Table) find_fn(name string) ?Fn { @@ -224,7 +225,6 @@ pub fn (t &TypeSymbol) find_method(name string) ?Fn { return none } - pub fn (s &TypeSymbol) has_field(name string) bool { s.find_field(name) or { return false @@ -235,7 +235,7 @@ pub fn (s &TypeSymbol) has_field(name string) bool { pub fn (s &TypeSymbol) find_field(name string) ?Field { match s.info { Struct { - for field in it.fields { + for field in it.fields { if field.name == name { return field } @@ -302,7 +302,8 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol { kind: .unresolved name: 'unresolved-$unresolved_idx' } - } else if idx > 0 { + } + else if idx > 0 { return &t.types[idx] } // this should never happen @@ -319,8 +320,12 @@ pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int { if existing_idx >= string_type_idx { if existing_idx == string_type_idx { existing_type := &t.types[existing_idx] - t.types[existing_idx] = { typ | kind: existing_type.kind } - } else { + t.types[existing_idx] = { + typ | + kind:existing_type.kind + } + } + else { t.types[existing_idx] = typ } } @@ -473,8 +478,7 @@ pub fn (t &Table) check(got, expected Type) bool { if exp_type_sym.kind == .voidptr { return true } - if got_type_sym.kind in [.voidptr, .byteptr, .charptr, .int] && - exp_type_sym.kind in [.voidptr, .byteptr, .charptr] { + if got_type_sym.kind in [.voidptr, .byteptr, .charptr, .int] && exp_type_sym.kind in [.voidptr, .byteptr, .charptr] { return true } if got_type_sym.is_int() && exp_type_sym.is_int() { @@ -489,7 +493,7 @@ pub fn (t &Table) check(got, expected Type) bool { // if expected.name == 'array' { // return true // } - if got_idx != exp_idx /*&& got.typ.name != expected.typ.name*/ { + if got_idx != exp_idx/*&& got.typ.name != expected.typ.name*/ { return false } return true