From 68143b7b220e01841fd28012049fe30962404ef7 Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Fri, 19 Jun 2020 00:33:16 +1000 Subject: [PATCH] parser/checker/gen: match shaddow cond var & as support: p1 --- vlib/v/ast/ast.v | 1 + vlib/v/ast/str.v | 35 ++++++++++++++++--------- vlib/v/checker/check_types.v | 16 ++++++----- vlib/v/checker/checker.v | 14 +++++----- vlib/v/gen/cgen.v | 8 +++++- vlib/v/gen/x64/gen.v | 3 +-- vlib/v/parser/if.v | 51 ++++++++++++++++++++++-------------- vlib/v/parser/pratt.v | 5 ++++ 8 files changed, 84 insertions(+), 49 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 5f3f5ea506..2db63dd1e3 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -442,6 +442,7 @@ pub: branches []MatchBranch pos token.Position is_mut bool // `match mut ast_node {` + var_name string pub mut: is_expr bool // returns a value return_type table.Type diff --git a/vlib/v/ast/str.v b/vlib/v/ast/str.v index d0300700af..848d027306 100644 --- a/vlib/v/ast/str.v +++ b/vlib/v/ast/str.v @@ -126,22 +126,33 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) { } } } + // TODO: remove sponge - put back match if !needs_braces { mut sub_expr := lit.exprs[i] for { - match sub_expr { - Ident { - break - } - SelectorExpr { - sub_expr = it.expr - continue - } - else { - needs_braces = true - break - } + if sub_expr is Ident { break } + else if sub_expr is SelectorExpr { + se := sub_expr as SelectorExpr + sub_expr = se.expr + continue } + else { + needs_braces = true + break + } + // match sub_expr { + // Ident { + // break + // } + // SelectorExpr { + // sub_expr = it.expr + // continue + // } + // else { + // needs_braces = true + // break + // } + // } } } if needs_fspec { diff --git a/vlib/v/checker/check_types.v b/vlib/v/checker/check_types.v index 993e6273f8..7f5aacaf39 100644 --- a/vlib/v/checker/check_types.v +++ b/vlib/v/checker/check_types.v @@ -93,13 +93,15 @@ pub fn (c &Checker) check_basic(got, expected table.Type) bool { return true } // sum type - if got_type_sym.kind == .sum_type { - sum_info := got_type_sym.info as table.SumType - // TODO: handle `match SumType { &PtrVariant {} }` currently just checking base - if expected.set_nr_muls(0) in sum_info.variants { - return true - } - } + // TODO: there is a bug when casting sumtype the other way if its pointer + // so until fixed at least show v (not C) error `x(variant) = y(SumType*)` + // if got_type_sym.kind == .sum_type { + // sum_info := got_type_sym.info as table.SumType + // // TODO: handle `match SumType { &PtrVariant {} }` currently just checking base + // if expected.set_nr_muls(0) in sum_info.variants { + // return true + // } + // } if exp_type_sym.kind == .sum_type { sum_info := exp_type_sym.info as table.SumType // TODO: handle `match SumType { &PtrVariant {} }` currently just checking base diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 18a1fca852..3a772464a7 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -170,19 +170,19 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool { } } ast.TypeDecl { - type_decl := stmt as ast.TypeDecl - if type_decl is ast.AliasTypeDecl { - alias_decl := type_decl as ast.AliasTypeDecl + // type_decl := stmt as ast.TypeDecl + if it is ast.AliasTypeDecl { + alias_decl := it as ast.AliasTypeDecl if alias_decl.is_pub { c.warn('type alias `$alias_decl.name` $no_pub_in_main_warning', alias_decl.pos) } - } else if type_decl is ast.SumTypeDecl { - sum_decl := type_decl as ast.SumTypeDecl + } else if it is ast.SumTypeDecl { + sum_decl := it as ast.SumTypeDecl if sum_decl.is_pub { c.warn('sum type `$sum_decl.name` $no_pub_in_main_warning', sum_decl.pos) } - } else if type_decl is ast.FnTypeDecl { - fn_decl := type_decl as ast.FnTypeDecl + } else if it is ast.FnTypeDecl { + fn_decl := it as ast.FnTypeDecl if fn_decl.is_pub { c.warn('type alias `$fn_decl.name` $no_pub_in_main_warning', fn_decl.pos) } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index e00e02a177..3e48e807b2 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1227,7 +1227,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) { - match val { + // TODO: remove sponge + tmp_val := val + match tmp_val { ast.Ident { mut has_var := false for lx in left { @@ -1987,6 +1989,10 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) { g.write('\t$it_type* it = ($it_type*)') g.expr(node.cond) g.writeln('.obj; // ST it') + if node.var_name.len > 0 { + // for now we just copy it + g.writeln('\t$it_type* $node.var_name = it;') + } } else { verror('match sum type') diff --git a/vlib/v/gen/x64/gen.v b/vlib/v/gen/x64/gen.v index ad239a3cbf..e1e60a83d6 100644 --- a/vlib/v/gen/x64/gen.v +++ b/vlib/v/gen/x64/gen.v @@ -559,8 +559,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) { match expr { ast.IntegerLiteral { // `foo(2)` => `mov edi,0x2` - int_lit := expr as ast.IntegerLiteral - g.mov(fn_arg_registers[i], int_lit.val.int()) + g.mov(fn_arg_registers[i], it.val.int()) } ast.Ident { // `foo(x)` => `mov edi,DWORD PTR [rbp-0x8]` diff --git a/vlib/v/parser/if.v b/vlib/v/parser/if.v index 97ddaedeb6..a1ca04c6cf 100644 --- a/vlib/v/parser/if.v +++ b/vlib/v/parser/if.v @@ -99,6 +99,11 @@ fn (mut p Parser) match_expr() ast.MatchExpr { cond_pos := p.tok.position() cond := p.expr(0) p.inside_match = false + mut var_name := '' + if p.tok.kind == .key_as { + p.next() + var_name = p.check_name() + } p.check(.lcbr) mut branches := []ast.MatchBranch{} for { @@ -114,6 +119,20 @@ fn (mut p Parser) match_expr() ast.MatchExpr { } else if p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot) && (p.tok.lit in table.builtin_type_names || (p.tok.lit[0].is_capital() && !p.tok.lit.is_upper()) || p.peek_tok.kind == .dot) { + if var_name.len == 0 { + match cond { + ast.Ident { + // shadow match cond variable + var_name = it.name + } + // ast.SelectorExpr { + // p.error('expecting `as` (eg. `match user.attribute as user_attr`) when matching struct fields') + // } + else { + // p.error('only variables can be used in sum types matches') + } + } + } // Sum type match typ := p.parse_type() exprs << ast.Type{ @@ -126,32 +145,23 @@ fn (mut p Parser) match_expr() ast.MatchExpr { is_used: true is_mut: is_mut }) + if var_name.len > 0 { + // Register shadow variable or `as` variable with actual type + p.scope.register(var_name, ast.Var{ + name: var_name + typ: typ.to_ptr() + pos: cond_pos + is_used: true + is_mut: is_mut + }) + } // TODO if p.tok.kind == .comma { p.next() p.parse_type() } is_sum_type = true - // Make sure a variable used for the sum type match - mut var_name := '' - match cond { - ast.Ident { - var_name = it.name - } - else { - // p.error('only variables can be used in sum types matches') - } - } - if var_name != '' { - // Register a shadow variable with the actual type - // (this replaces the old `it`) - // TODO doesn't work right now (fixed, uncomment when merging) - // p.scope.register(var_name, ast.Var{ - // name: var_name - // typ: typ.to_ptr() - // }) - // println(var_name) - } + } else { // Expression match for { @@ -200,5 +210,6 @@ fn (mut p Parser) match_expr() ast.MatchExpr { is_sum_type: is_sum_type pos: pos is_mut: is_mut + var_name: var_name } } diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index fa0f4ed1e9..882b4a9cd2 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -166,6 +166,11 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { node = p.index_expr(node) p.is_stmt_ident = is_stmt_ident } else if p.tok.kind == .key_as { + // sum type match `match x as alias` so return early + if p.inside_match { + return node + } + // sum type as cast `x := SumType as Variant` pos := p.tok.position() p.next() typ = p.parse_type()