1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: sum types: match

This commit is contained in:
Alexander Medvednikov 2020-03-16 03:19:26 +01:00
parent 98fc9ab65b
commit 37504c487a
5 changed files with 92 additions and 21 deletions

View File

@ -344,12 +344,13 @@ mut:
pub struct MatchExpr { pub struct MatchExpr {
pub: pub:
tok_kind token.Kind tok_kind token.Kind
cond Expr cond Expr
branches []MatchBranch branches []MatchBranch
pos token.Position pos token.Position
mut: 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 { pub struct MatchBranch {

View File

@ -315,7 +315,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
} }
} }
ast.TypeDecl { ast.TypeDecl {
g.writeln('// type') g.writeln('// TypeDecl')
} }
ast.UnsafeStmt { ast.UnsafeStmt {
g.stmts(it.stmts) g.stmts(it.stmts)
@ -728,7 +728,10 @@ fn (g mut Gen) expr(node ast.Expr) {
} }
g.write('if (') g.write('if (')
for i, expr in branch.exprs { 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, ') g.write('string_eq($tmp, ')
} }
else { else {
@ -909,7 +912,10 @@ fn (g mut Gen) expr(node ast.Expr) {
g.write(it.field) g.write(it.field)
} }
ast.Type { ast.Type {
g.write('/* Type */') // match sum Type
// g.write('/* Type */')
g.write('_type_idx_')
g.write(g.typ(it.typ))
} }
else { else {
// #printf("node=%d\n", node.typ); // #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) { fn (g mut Gen) write_types(types []table.TypeSymbol) {
for typ in types { for i, typ in types {
if typ.name.starts_with('C.') { if typ.name.starts_with('C.') {
continue continue
} }
@ -1288,11 +1294,12 @@ fn (g mut Gen) write_types(types []table.TypeSymbol) {
// g.definitions.writeln('} $name;\n') // g.definitions.writeln('} $name;\n')
// //
g.definitions.writeln('};\n') g.definitions.writeln('};\n')
g.typedefs.writeln('#define _type_idx_$name $i')
} }
table.Enum { table.Enum {
g.definitions.writeln('typedef enum {') g.definitions.writeln('typedef enum {')
for i, val in it.vals { for j, val in it.vals {
g.definitions.writeln('\t${name}_$val, // $i') g.definitions.writeln('\t${name}_$val, // $j')
} }
g.definitions.writeln('} $name;\n') g.definitions.writeln('} $name;\n')
} }

View File

@ -1,3 +1,15 @@
struct IfExpr {
};
struct IntegerLiteral {
};
// Sum type
typedef struct {
void* obj;
int typ;
} Expr;
struct User { struct User {
int age; int age;
string name; string name;
@ -8,6 +20,9 @@ struct User {
typedef Option Option_int; typedef Option Option_int;
Option_int get_opt(); Option_int get_opt();
void User_foo(User* u); void User_foo(User* u);
void println(string s);
void handle_expr(Expr e);
// TypeDecl
Option_int get_opt() { Option_int get_opt() {
return opt_ok(& (int []) { 0 }, sizeof(int)); return opt_ok(& (int []) { 0 }, sizeof(int));
@ -20,6 +35,26 @@ tos3(""),
}), u->age); }), 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() { int main() {
User user = (User){ User user = (User){
0}; 0};

View File

@ -1,3 +1,8 @@
type Expr = IfExpr | IntegerLiteral
struct IfExpr{}
struct IntegerLiteral{}
struct User { struct User {
age int age int
name string name string
@ -12,6 +17,26 @@ fn (u &User) foo() {
zzz := [''].repeat(u.age) 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() { fn main() {
user := User{} user := User{}
user.age = 10 user.age = 10

View File

@ -48,7 +48,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
pref: &pref.Preferences{} pref: &pref.Preferences{}
scope: scope scope: scope
// scope: &ast.Scope{start_pos: 0, parent: 0} // scope: &ast.Scope{start_pos: 0, parent: 0}
} }
p.init_parse_fns() p.init_parse_fns()
p.read_first_token() p.read_first_token()
@ -72,7 +72,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
parent: 0 parent: 0
} }
// comments_mode: comments_mode // comments_mode: comments_mode
} }
p.read_first_token() p.read_first_token()
// p.scope = &ast.Scope{start_pos: p.tok.position(), parent: 0} // 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 = '' p.expr_mod = ''
return ast.EnumVal{ return ast.EnumVal{
enum_name: enum_name // lp.prepend_mod(enum_name) enum_name: enum_name // lp.prepend_mod(enum_name)
val: val val: val
pos: p.tok.position() pos: p.tok.position()
mod: mod 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 }` // Map `{"age": 20}` or `{ x | foo:bar, a:10 }`
.lcbr { .lcbr {
p.next() p.next()
if p.tok.kind == .string{ if p.tok.kind == .string {
mut keys := []ast.Expr mut keys := []ast.Expr
mut vals := []ast.Expr mut vals := []ast.Expr
for p.tok.kind != .rcbr && p.tok.kind != .eof { 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 left: left
right: right right: right
// right_type: typ // right_type: typ
op: op op: op
pos: pos pos: pos
} }
@ -1055,7 +1055,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
p.scope.register_var(ast.Var{ p.scope.register_var(ast.Var{
name: var_name name: var_name
// expr: cond // expr: cond
}) })
stmts := p.parse_block() stmts := p.parse_block()
// println('nr stmts=$stmts.len') // println('nr stmts=$stmts.len')
@ -1150,11 +1150,11 @@ fn (p mut Parser) if_expr() ast.Expr {
stmts: stmts stmts: stmts
else_stmts: else_stmts else_stmts: else_stmts
// typ: typ // typ: typ
pos: pos pos: pos
has_else: has_else has_else: has_else
// left: left // left: left
} }
return node return node
} }
@ -1169,7 +1169,7 @@ fn (p mut Parser) string_expr() ast.Expr {
return node return node
} }
// Handle $ interpolation // Handle $ interpolation
for p.tok.kind == .string{ for p.tok.kind == .string {
p.next() p.next()
if p.tok.kind != .str_dollar { if p.tok.kind != .str_dollar {
continue continue
@ -1329,7 +1329,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl {
fields << ast.Field{ fields << ast.Field{
name: name name: name
// typ: typ // typ: typ
} }
exprs << expr exprs << expr
// TODO: once consts are fixed reg here & update in checker // 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 { fn (p mut Parser) match_expr() ast.MatchExpr {
p.check(.key_match) p.check(.key_match)
is_mut := p.tok.kind == .key_mut is_mut := p.tok.kind == .key_mut
mut is_sum_type := false
if is_mut { if is_mut {
p.next() p.next()
} }
@ -1626,6 +1627,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
p.next() p.next()
p.parse_type() p.parse_type()
} }
is_sum_type = true
} }
else { else {
// Expression match // Expression match
@ -1653,6 +1655,7 @@ fn (p mut Parser) match_expr() ast.MatchExpr {
return ast.MatchExpr{ return ast.MatchExpr{
branches: branches branches: branches
cond: cond cond: cond
is_sum_type: is_sum_type
} }
} }