From 0e6fe0a4f2b50f294ae23091da159b12bf15ff7c Mon Sep 17 00:00:00 2001 From: hazohelet <48541090+hazohelet@users.noreply.github.com> Date: Fri, 3 Apr 2020 02:39:17 +0900 Subject: [PATCH] V: fix const bugs and pass const_test.v (#4206) * fix const bug in v2 * v2: fix const decl * small comment fix --- vlib/v/ast/ast.v | 1 + vlib/v/checker/checker.v | 58 +++++++++++++++++++++++++++++++++------ vlib/v/parser/parser.v | 2 ++ vlib/v/tests/const_test.v | 2 +- 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 94f086b0f3..91895d3f25 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -110,6 +110,7 @@ mut: pub struct ConstDecl { pub: + pos token.Position fields []Field exprs []Expr is_pub bool diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 9c461f4286..b77d19e0ca 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -150,6 +150,10 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type { if right.kind in [.array, .map] && infix_expr.op == .key_in { return table.bool_type } + // fot type-unresolved consts + if left_type == table.void_type || right_type == table.void_type { + return table.void_type + } c.error('infix expr: cannot use `$right.name` (right) as `$left.name`', infix_expr.pos) } if infix_expr.op.is_relational() { @@ -346,7 +350,6 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type { if arg_typ_sym.kind == .string && typ_sym.has_method('str') { continue } - // TODO const bug if typ_sym.kind == .void && arg_typ_sym.kind == .string { continue } @@ -570,17 +573,56 @@ fn (c mut Checker) stmt(node ast.Stmt) { c.stmts(it.stmts) } ast.ConstDecl { + mut unresolved_num:= 0 // number of type-unresolved consts + mut ordered_exprs := []ast.Expr + mut ordered_fields := []ast.Field for i, expr in it.exprs { mut field := it.fields[i] typ := c.expr(expr) - // TODO: once consts are fixed update here - c.table.register_const(table.Var{ - name: field.name - typ: typ - }) - field.typ = typ - it.fields[i] = field + if typ == table.void_type { + unresolved_num++ + } + else { // succeed in resolving type + c.table.register_const(table.Var{ + name: field.name + typ: typ + }) + field.typ = typ + it.fields[i] = field + ordered_exprs << expr + ordered_fields << field + if unresolved_num == 0 { + continue + } + for j, _expr in it.exprs[0..i]{ + mut _field := it.fields[j] + _typ := c.expr(_expr) + if _field.typ == 0 && _typ != table.void_type { + // succeed in resolving type + c.table.register_const(table.Var{ + name: _field.name + typ: _typ + }) + unresolved_num-- + _field.typ = _typ + it.fields[j] = _field + ordered_exprs << _expr + ordered_fields << _field + } + } + } } + if unresolved_num != 0 { + c.error("$unresolved_num ill-defined consts are in use", it.pos) + } + for i, field in ordered_fields { // set the fields and exprs as ordered + it.fields[i] = field + it.exprs[i] = ordered_exprs[i] + } + /* + it.exprs = ordered_exprs + it.fields = ordered_fields + */ } ast.ExprStmt { c.expr(it.expr) diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index ac7ed728dd..d36e13d07a 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1440,6 +1440,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl { if is_pub { p.next() } + pos := p.tok.position() p.check(.key_const) p.check(.lpar) mut fields := []ast.Field @@ -1463,6 +1464,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl { } p.check(.rpar) return ast.ConstDecl{ + pos : pos fields: fields exprs: exprs is_pub: is_pub diff --git a/vlib/v/tests/const_test.v b/vlib/v/tests/const_test.v index b7a41346e2..c248b264a1 100644 --- a/vlib/v/tests/const_test.v +++ b/vlib/v/tests/const_test.v @@ -1,6 +1,6 @@ pub const ( - // c = a // TODO a = b + c = a + b b = 1 d = (e / 2) + 7 e = 9