From c51f464446d815b1099a3e7fd862ba1d64e847e3 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 27 Feb 2020 00:12:37 +0100 Subject: [PATCH] v2: fix `mod.Enum.val` and `x = .val` --- vlib/v/checker/checker.v | 30 ++++++++++++++++++++++++++---- vlib/v/parser/parse_type.v | 5 ++++- vlib/v/parser/parser.v | 35 +++++++++++++++++++++++++++-------- vlib/v/table/table.v | 4 ++-- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9c627f6367..568b806203 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -35,6 +35,13 @@ pub fn (c mut Checker) check(ast_file ast.File) { for stmt in ast_file.stmts { c.stmt(stmt) } + /* + println('all types:') + for t in c.table.types { + println(t.name + ' - ' + t.kind.str()) + } + */ + if c.nr_errors > 0 { exit(1) } @@ -105,7 +112,7 @@ pub fn (c mut Checker) check_struct_init(struct_init ast.StructInit) table.Type expr_type_sym := c.table.get_type_symbol(expr_type) field_type_sym := c.table.get_type_symbol(field.typ) if !c.table.check(expr_type, field.typ) { - c.error('cannot assign $expr_type_sym.name as $field_type_sym.name for field $field.name', struct_init.pos) + c.error('cannot assign `$expr_type_sym.name` as `$field_type_sym.name` for field `$field.name`', struct_init.pos) } } } @@ -132,6 +139,7 @@ pub fn (c mut Checker) infix_expr(infix_expr ast.InfixExpr) table.Type { } // if !c.table.check(&infix_expr.right_type, &infix_expr.right_type) { // c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos) + // ltyp := typeof(infix_expr.left) c.error('infix expr: cannot use `$right.name` (right) as `$left.name`', infix_expr.pos) } if infix_expr.op.is_relational() { @@ -142,6 +150,9 @@ pub fn (c mut Checker) infix_expr(infix_expr ast.InfixExpr) table.Type { fn (c mut Checker) check_assign_expr(assign_expr ast.AssignExpr) { left_type := c.expr(assign_expr.left) + c.expected_type = left_type + // t := c.table.get_type_symbol(left_type) + // println('setting exp type to $c.expected_type $t.name') right_type := c.expr(assign_expr.val) if !c.table.check(right_type, left_type) { left_type_sym := c.table.get_type_symbol(left_type) @@ -272,7 +283,11 @@ pub fn (c mut Checker) return_stmt(return_stmt ast.Return) { } } -pub fn (c &Checker) assign_stmt(assign_stmt ast.AssignStmt) {} +/* +pub fn (c mut Checker) assign_stmt(assign_stmt ast.AssignStmt) { +} +*/ + pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { mut elem_type := table.void_type @@ -305,6 +320,7 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type { } fn (c mut Checker) stmt(node ast.Stmt) { + // c.expected_type = table.void_type match mut node { ast.FnDecl { for stmt in it.stmts { @@ -314,9 +330,12 @@ fn (c mut Checker) stmt(node ast.Stmt) { ast.Return { c.return_stmt(it) } + /* ast.AssignStmt { c.assign_stmt(it) } + */ + ast.ConstDecl { for i, expr in it.exprs { mut field := it.fields[i] @@ -653,10 +672,13 @@ pub fn (c mut Checker) index_expr(node ast.IndexExpr) table.Type { // If a short form is used, `expected_type` needs to be an enum // with this value. pub fn (c mut Checker) enum_val(node ast.EnumVal) table.Type { - typ_idx := if node.enum_name == '' { c.expected_type } else { c.table.find_type_idx(node.enum_name) } + // println('checker: enum: $node.enum_name') + typ_idx := if node.enum_name == '' { c.expected_type } else { // + c.table.find_type_idx(node.enum_name) } typ := c.table.get_type_symbol(table.Type(typ_idx)) - // println('checker: enum val $c.expected_type $typ.name') info := typ.info as table.Enum + // rintln('checker: x = $info.x enum val $c.expected_type $typ.name') + // println(info.vals) if !(node.val in info.vals) { c.error('enum `$typ.name` does not have a value `$node.val`', node.pos) } diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index dec5b0c62c..b0ada67f73 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -118,6 +118,9 @@ pub fn (p mut Parser) parse_any_type(is_ptr bool) table.Type { // prefix with full module name = '${p.imports[name]}.$p.tok.lit' } + else if p.expr_mod != '' { + name = p.expr_mod + '.' + name + } // `Foo` in module `mod` means `mod.Foo` else if !(p.mod in ['builtin', 'main']) && !(name in table.builtin_type_names) { name = p.mod + '.' + name @@ -208,7 +211,7 @@ pub fn (p mut Parser) parse_any_type(is_ptr bool) table.Type { // println('NOT FOUND: $name - adding placeholder - $idx') return table.new_type(idx) } - } + } } } } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index f32dbf362b..a15c1209a9 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -42,6 +42,7 @@ mut: pref &pref.Preferences // Preferences shared from V struct builtin_mod bool mod string + expr_mod string expected_type table.Type scope &ast.Scope imports map[string]string @@ -551,6 +552,13 @@ pub fn (p mut Parser) name_expr() ast.Expr { mut node := ast.Expr{} is_c := p.tok.lit == 'C' mut mod := '' + // p.warn('resetting') + p.expr_mod = '' + // `map[string]int` initialization + if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr { + map_type := p.parse_map_type() + return node + } if p.peek_tok.kind == .dot && (is_c || p.known_import(p.tok.lit)) { if !is_c { // prepend the full import @@ -558,11 +566,7 @@ pub fn (p mut Parser) name_expr() ast.Expr { } p.next() p.check(.dot) - } - // `map[string]int` initialization - if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr { - map_type := p.parse_map_type() - return node + p.expr_mod = mod } // p.warn('name expr $p.tok.lit $p.peek_tok.str()') // fn call or type cast @@ -586,6 +590,7 @@ pub fn (p mut Parser) name_expr() ast.Expr { typ: to_typ expr: expr } + p.expr_mod = '' return node } // fn call @@ -606,13 +611,24 @@ pub fn (p mut Parser) name_expr() ast.Expr { return p.struct_init() } else if p.peek_tok.kind == .dot && p.tok.lit[0].is_capital() { - enum_name := p.check_name() + // `Color.green` + mut enum_name := p.check_name() + if mod != '' { + enum_name = mod + '.' + enum_name + } + else { + enum_name = p.prepend_mod(enum_name) + } + // p.warn('Color.green $enum_name ' + p.prepend_mod(enum_name) + 'mod=$mod') p.check(.dot) val := p.check_name() // println('enum val $enum_name . $val') + p.expr_mod = '' return ast.EnumVal{ - enum_name: enum_name + enum_name: enum_name // lp.prepend_mod(enum_name) + val: val + pos: p.tok.position() } } else { @@ -620,6 +636,7 @@ pub fn (p mut Parser) name_expr() ast.Expr { ident = p.parse_ident(is_c) node = ident } + p.expr_mod = '' return node } @@ -956,6 +973,7 @@ fn (p mut Parser) enum_val() ast.EnumVal { return ast.EnumVal{ val: val + pos: p.tok.position() } } @@ -1452,6 +1470,7 @@ fn (p mut Parser) struct_decl() ast.StructDecl { if ret == -1 { p.error('cannot register type `$name`, another type with this name exists') } + p.expr_mod = '' return ast.StructDecl{ name: name is_pub: is_pub @@ -1708,7 +1727,7 @@ fn (p mut Parser) enum_decl() ast.EnumDecl { p.check(.rcbr) p.table.register_type_symbol(table.TypeSymbol{ kind: .enum_ - name: name + name: p.prepend_mod(name) info: table.Enum{ vals: vals } diff --git a/vlib/v/table/table.v b/vlib/v/table/table.v index 6bc9c841e6..0b697a1d09 100644 --- a/vlib/v/table/table.v +++ b/vlib/v/table/table.v @@ -56,7 +56,7 @@ pub fn (t mut Table) register_global(name string, typ Type) { // mod: p.mod // is_mut: true // idx: -1 - + } } @@ -186,7 +186,7 @@ pub fn (t &Table) get_type_symbol(typ Type) &TypeSymbol { return &t.types[idx] } // this should never happen - panic('get_type_symbol: invalid type $typ - ${idx}. This should neer happen') + panic('get_type_symbol: invalid type (typ=$typ idx=${idx}). This should neer happen') } // this will override or register builtin type