From 37504c487a3b6e0799205ee3d72a60c195926601 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 16 Mar 2020 03:19:26 +0100 Subject: [PATCH] cgen: sum types: match --- vlib/v/ast/ast.v | 11 ++++++----- vlib/v/gen/cgen.v | 19 +++++++++++++------ vlib/v/gen/tests/3.c | 35 +++++++++++++++++++++++++++++++++++ vlib/v/gen/tests/3.vv | 25 +++++++++++++++++++++++++ vlib/v/parser/parser.v | 23 +++++++++++++---------- 5 files changed, 92 insertions(+), 21 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 15c8522aba..496fdbfaa5 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -344,12 +344,13 @@ mut: pub struct MatchExpr { pub: - tok_kind token.Kind - cond Expr - branches []MatchBranch - pos token.Position + tok_kind token.Kind + cond Expr + branches []MatchBranch + pos token.Position mut: - expr_type table.Type // type of `x` in `match x {` + expr_type table.Type // type of `x` in `match x {` + is_sum_type bool } pub struct MatchBranch { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index d96a70940e..8fc0a486ee 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -315,7 +315,7 @@ fn (g mut Gen) stmt(node ast.Stmt) { } } ast.TypeDecl { - g.writeln('// type') + g.writeln('// TypeDecl') } ast.UnsafeStmt { g.stmts(it.stmts) @@ -728,7 +728,10 @@ fn (g mut Gen) expr(node ast.Expr) { } g.write('if (') for i, expr in branch.exprs { - if type_sym.kind == .string { + if it.is_sum_type { + g.write('${tmp}.typ == ') + } + else if type_sym.kind == .string { g.write('string_eq($tmp, ') } else { @@ -909,7 +912,10 @@ fn (g mut Gen) expr(node ast.Expr) { g.write(it.field) } ast.Type { - g.write('/* Type */') + // match sum Type + // g.write('/* Type */') + g.write('_type_idx_') + g.write(g.typ(it.typ)) } else { // #printf("node=%d\n", node.typ); @@ -1270,7 +1276,7 @@ fn (g mut Gen) write_sorted_types() { } fn (g mut Gen) write_types(types []table.TypeSymbol) { - for typ in types { + for i, typ in types { if typ.name.starts_with('C.') { continue } @@ -1288,11 +1294,12 @@ fn (g mut Gen) write_types(types []table.TypeSymbol) { // g.definitions.writeln('} $name;\n') // g.definitions.writeln('};\n') + g.typedefs.writeln('#define _type_idx_$name $i') } table.Enum { g.definitions.writeln('typedef enum {') - for i, val in it.vals { - g.definitions.writeln('\t${name}_$val, // $i') + for j, val in it.vals { + g.definitions.writeln('\t${name}_$val, // $j') } g.definitions.writeln('} $name;\n') } diff --git a/vlib/v/gen/tests/3.c b/vlib/v/gen/tests/3.c index abf97d5623..18290c73fd 100644 --- a/vlib/v/gen/tests/3.c +++ b/vlib/v/gen/tests/3.c @@ -1,3 +1,15 @@ +struct IfExpr { +}; + +struct IntegerLiteral { +}; + +// Sum type +typedef struct { + void* obj; + int typ; +} Expr; + struct User { int age; string name; @@ -8,6 +20,9 @@ struct User { typedef Option Option_int; Option_int get_opt(); void User_foo(User* u); +void println(string s); +void handle_expr(Expr e); +// TypeDecl Option_int get_opt() { return opt_ok(& (int []) { 0 }, sizeof(int)); @@ -20,6 +35,26 @@ tos3(""), }), u->age); } +void println(string s) { +} + +void handle_expr(Expr e) { + Expr tmp1 = e; + if (tmp1.typ == _type_idx_IfExpr) { + println(tos3("if")); + + } + else if (tmp1.typ == _type_idx_IntegerLiteral) { + println(tos3("integer")); + + } + else { + println(tos3("else")); + + } + ; +} + int main() { User user = (User){ 0}; diff --git a/vlib/v/gen/tests/3.vv b/vlib/v/gen/tests/3.vv index 4ad37cfa19..c7fec00098 100644 --- a/vlib/v/gen/tests/3.vv +++ b/vlib/v/gen/tests/3.vv @@ -1,3 +1,8 @@ +type Expr = IfExpr | IntegerLiteral + +struct IfExpr{} +struct IntegerLiteral{} + struct User { age int name string @@ -12,6 +17,26 @@ fn (u &User) foo() { zzz := [''].repeat(u.age) } +fn println(s string) {} + +fn handle_expr(e Expr) { + match e { + IfExpr { + println('if') + + + } + IntegerLiteral { + println('integer') + + } + else { + println('else') + } + } + +} + fn main() { user := User{} user.age = 10 diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 124f49f12e..7c10febc96 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -48,7 +48,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt { pref: &pref.Preferences{} scope: scope // scope: &ast.Scope{start_pos: 0, parent: 0} - + } p.init_parse_fns() p.read_first_token() @@ -72,7 +72,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment parent: 0 } // comments_mode: comments_mode - + } p.read_first_token() // p.scope = &ast.Scope{start_pos: p.tok.position(), parent: 0} @@ -610,7 +610,7 @@ pub fn (p mut Parser) name_expr() ast.Expr { p.expr_mod = '' return ast.EnumVal{ enum_name: enum_name // lp.prepend_mod(enum_name) - + val: val pos: p.tok.position() mod: mod @@ -703,7 +703,7 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr { // Map `{"age": 20}` or `{ x | foo:bar, a:10 }` .lcbr { p.next() - if p.tok.kind == .string{ + if p.tok.kind == .string { mut keys := []ast.Expr mut vals := []ast.Expr for p.tok.kind != .rcbr && p.tok.kind != .eof { @@ -941,7 +941,7 @@ fn (p mut Parser) infix_expr(left ast.Expr) ast.Expr { left: left right: right // right_type: typ - + op: op pos: pos } @@ -1055,7 +1055,7 @@ fn (p mut Parser) for_statement() ast.Stmt { p.scope.register_var(ast.Var{ name: var_name // expr: cond - + }) stmts := p.parse_block() // println('nr stmts=$stmts.len') @@ -1150,11 +1150,11 @@ fn (p mut Parser) if_expr() ast.Expr { stmts: stmts else_stmts: else_stmts // typ: typ - + pos: pos has_else: has_else // left: left - + } return node } @@ -1169,7 +1169,7 @@ fn (p mut Parser) string_expr() ast.Expr { return node } // Handle $ interpolation - for p.tok.kind == .string{ + for p.tok.kind == .string { p.next() if p.tok.kind != .str_dollar { continue @@ -1329,7 +1329,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl { fields << ast.Field{ name: name // typ: typ - + } exprs << expr // TODO: once consts are fixed reg here & update in checker @@ -1596,6 +1596,7 @@ fn (p mut Parser) global_decl() ast.GlobalDecl { fn (p mut Parser) match_expr() ast.MatchExpr { p.check(.key_match) is_mut := p.tok.kind == .key_mut + mut is_sum_type := false if is_mut { p.next() } @@ -1626,6 +1627,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr { p.next() p.parse_type() } + is_sum_type = true } else { // Expression match @@ -1653,6 +1655,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr { return ast.MatchExpr{ branches: branches cond: cond + is_sum_type: is_sum_type } }