cgen: if/match expressions and other fixes
parent
3fecf154aa
commit
a011b8951a
|
@ -94,6 +94,7 @@ fn parse_flags(flag string, f mut flag.Instance, prefs mut flag.MainCmdPreferenc
|
|||
println('V error: Error parsing flag. Expected value for `-$flag`.')
|
||||
exit(1)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,6 +313,12 @@ fn (m map) get(key string, out voidptr) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
fn (m &map) get2(key string, out voidptr) voidptr {
|
||||
}
|
||||
*/
|
||||
|
||||
fn (m map) exists(key string) bool {
|
||||
if m.value_bytes == 0 {
|
||||
return false
|
||||
|
|
|
@ -340,6 +340,7 @@ pub:
|
|||
left Expr // `a` in `a := if ...`
|
||||
pos token.Position
|
||||
mut:
|
||||
is_expr bool
|
||||
typ table.Type
|
||||
has_else bool
|
||||
}
|
||||
|
@ -352,6 +353,7 @@ pub:
|
|||
pos token.Position
|
||||
mut:
|
||||
is_expr bool // returns a value
|
||||
return_type table.Type
|
||||
expr_type table.Type // type of `x` in `match x {`
|
||||
is_sum_type bool
|
||||
}
|
||||
|
@ -591,6 +593,7 @@ pub:
|
|||
|
||||
pub struct SizeOf {
|
||||
pub:
|
||||
typ table.Type
|
||||
type_name string
|
||||
}
|
||||
|
||||
|
@ -641,6 +644,7 @@ enum BinaryOp {
|
|||
}
|
||||
*/
|
||||
|
||||
|
||||
[inline]
|
||||
pub fn expr_is_blank_ident(expr Expr) bool {
|
||||
match expr {
|
||||
|
@ -663,7 +667,6 @@ pub fn expr_is_call(expr Expr) bool {
|
|||
true
|
||||
}
|
||||
else {
|
||||
false
|
||||
}
|
||||
false}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -270,6 +270,7 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
|||
|
||||
// TODO: clean this up, remove dupe code & consider merging method/fn call everywhere
|
||||
pub fn (c mut Checker) method_call_expr(method_call_expr mut ast.MethodCallExpr) table.Type {
|
||||
c.expected_type = table.void_type
|
||||
typ := c.expr(method_call_expr.expr)
|
||||
method_call_expr.expr_type = typ
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
|
@ -525,6 +526,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
|||
c.expr(it.expr)
|
||||
}
|
||||
ast.FnDecl {
|
||||
c.expected_type = table.void_type
|
||||
c.fn_return_type = it.return_type
|
||||
for stmt in it.stmts {
|
||||
c.stmt(stmt)
|
||||
|
@ -815,14 +817,25 @@ pub fn (c mut Checker) match_expr(node mut ast.MatchExpr) table.Type {
|
|||
}
|
||||
}
|
||||
}
|
||||
// if ret_type != table.void_type {
|
||||
// node.is_expr = c.expected_type != table.void_type
|
||||
// node.expected_type = c.expected_type
|
||||
// }
|
||||
node.return_type = ret_type
|
||||
node.expr_type = expr_type
|
||||
// println('!m $expr_type')
|
||||
return ret_type
|
||||
}
|
||||
|
||||
pub fn (c mut Checker) if_expr(node mut ast.IfExpr) table.Type {
|
||||
if c.expected_type != 0 {
|
||||
// sym := c.table.get_type_symbol(c.expected_type)
|
||||
// println('$c.file.path $node.pos.line_nr IF: checker exp type = ' + sym.name)
|
||||
node.is_expr = true
|
||||
}
|
||||
typ := c.expr(node.cond)
|
||||
node.typ = typ
|
||||
node.typ = table.void_type
|
||||
// node.typ = typ
|
||||
typ_sym := c.table.get_type_symbol(typ)
|
||||
// if typ_sym.kind != .bool {
|
||||
if table.type_idx(typ) != table.bool_type_idx {
|
||||
|
|
|
@ -22,6 +22,7 @@ mut:
|
|||
is_array_set bool
|
||||
is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&byte(0)` etc
|
||||
optionals []string // to avoid duplicates TODO perf, use map
|
||||
inside_ternary bool // ?: comma separated statements on a single line
|
||||
}
|
||||
|
||||
pub fn cgen(files []ast.File, table &table.Table) string {
|
||||
|
@ -191,9 +192,11 @@ pub fn (g mut Gen) reset_tmp_count() {
|
|||
fn (g mut Gen) stmts(stmts []ast.Stmt) {
|
||||
for stmt in stmts {
|
||||
g.stmt(stmt)
|
||||
if !g.inside_ternary {
|
||||
g.writeln('')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn (g mut Gen) stmt(node ast.Stmt) {
|
||||
// println('cgen.stmt()')
|
||||
|
@ -245,9 +248,11 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||
// no ; after an if expression
|
||||
ast.IfExpr {}
|
||||
else {
|
||||
if !g.inside_ternary {
|
||||
g.writeln(';')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.FnDecl {
|
||||
g.fn_decl = it // &it
|
||||
|
@ -427,7 +432,8 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
|||
g.write(' = ')
|
||||
if !is_decl {
|
||||
g.expr_with_cast(assign_stmt.left_types[i], ident_var_info.typ, val)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
g.expr(val)
|
||||
}
|
||||
}
|
||||
|
@ -811,7 +817,8 @@ fn (g mut Gen) expr(node ast.Expr) {
|
|||
*/
|
||||
|
||||
ast.SizeOf {
|
||||
g.write('sizeof($it.type_name)')
|
||||
styp := g.typ(it.typ)
|
||||
g.write('sizeof($styp)')
|
||||
}
|
||||
ast.StringLiteral {
|
||||
// In C calls we have to generate C strings
|
||||
|
@ -966,6 +973,11 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) {
|
|||
g.writeln('// match 0')
|
||||
return
|
||||
}
|
||||
is_expr := node.return_type != table.void_type
|
||||
if is_expr {
|
||||
g.inside_ternary = true
|
||||
// g.write('/* EM ret type=${g.typ(node.return_type)} */')
|
||||
}
|
||||
type_sym := g.table.get_type_symbol(node.expr_type)
|
||||
mut tmp := ''
|
||||
if type_sym.kind != .void {
|
||||
|
@ -979,13 +991,29 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) {
|
|||
for j, branch in node.branches {
|
||||
if j == node.branches.len - 1 {
|
||||
// last block is an `else{}`
|
||||
if is_expr {
|
||||
// TODO too many branches. maybe separate ?: matches
|
||||
g.write(' : ')
|
||||
}
|
||||
else {
|
||||
g.writeln('else {')
|
||||
}
|
||||
}
|
||||
else {
|
||||
if j > 0 {
|
||||
if is_expr {
|
||||
g.write(' : ')
|
||||
}
|
||||
else {
|
||||
g.write('else ')
|
||||
}
|
||||
}
|
||||
if is_expr {
|
||||
g.write('(')
|
||||
}
|
||||
else {
|
||||
g.write('if (')
|
||||
}
|
||||
for i, expr in branch.exprs {
|
||||
if node.is_sum_type {
|
||||
g.expr(node.cond)
|
||||
|
@ -1013,8 +1041,13 @@ g.write(', ')
|
|||
g.write(' || ')
|
||||
}
|
||||
}
|
||||
if is_expr {
|
||||
g.write(') ? ')
|
||||
}
|
||||
else {
|
||||
g.writeln(') {')
|
||||
}
|
||||
}
|
||||
if node.is_sum_type && branch.exprs.len > 0 {
|
||||
// The first node in expr is an ast.Type
|
||||
// Use it to generate `it` variable.
|
||||
|
@ -1022,7 +1055,10 @@ g.write(', ')
|
|||
match fe {
|
||||
ast.Type {
|
||||
it_type := g.typ(it.typ)
|
||||
g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
||||
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
||||
g.write('$it_type* it = ($it_type*)')
|
||||
g.expr(node.cond)
|
||||
g.writeln('.obj; // ST it')
|
||||
}
|
||||
else {
|
||||
verror('match sum type')
|
||||
|
@ -1030,9 +1066,12 @@ g.write(', ')
|
|||
}
|
||||
}
|
||||
g.stmts(branch.stmts)
|
||||
if !g.inside_ternary {
|
||||
g.writeln('}')
|
||||
}
|
||||
}
|
||||
g.inside_ternary = false
|
||||
}
|
||||
|
||||
fn (g mut Gen) ident(node ast.Ident) {
|
||||
name := node.name.replace('.', '__')
|
||||
|
@ -1067,12 +1106,13 @@ fn (g mut Gen) if_expr(node ast.IfExpr) {
|
|||
}
|
||||
// one line ?:
|
||||
// TODO clean this up once `is` is supported
|
||||
if node.stmts.len == 1 && node.else_stmts.len == 1 && type_sym.kind != .void {
|
||||
if node.is_expr && node.stmts.len == 1 && node.else_stmts.len == 1 && type_sym.kind != .void {
|
||||
cond := node.cond
|
||||
stmt1 := node.stmts[0]
|
||||
else_stmt1 := node.else_stmts[0]
|
||||
match stmt1 {
|
||||
ast.ExprStmt {
|
||||
g.inside_ternary = true
|
||||
g.expr(cond)
|
||||
g.write(' ? ')
|
||||
expr_stmt := stmt1 as ast.ExprStmt
|
||||
|
@ -1096,6 +1136,7 @@ fn (g mut Gen) if_expr(node ast.IfExpr) {
|
|||
g.writeln('if (($guard_ok = ${it.var_name}.ok)) {')
|
||||
}
|
||||
else {
|
||||
g.inside_ternary = false
|
||||
g.write('if (')
|
||||
g.expr(node.cond)
|
||||
g.writeln(') {')
|
||||
|
@ -1113,8 +1154,9 @@ fn (g mut Gen) if_expr(node ast.IfExpr) {
|
|||
g.writeln('}')
|
||||
if node.else_stmts.len > 0 {
|
||||
if is_guard {
|
||||
g.writeln('if !$guard_ok { /* else */')
|
||||
} else {
|
||||
g.writeln('if (!$guard_ok) { /* else */')
|
||||
}
|
||||
else {
|
||||
g.writeln('else { ')
|
||||
}
|
||||
for stmt in node.else_stmts {
|
||||
|
@ -1123,6 +1165,7 @@ fn (g mut Gen) if_expr(node ast.IfExpr) {
|
|||
g.writeln('}')
|
||||
}
|
||||
}
|
||||
g.inside_ternary = false
|
||||
}
|
||||
|
||||
fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
||||
|
@ -1210,6 +1253,10 @@ fn (g mut Gen) index_expr(node ast.IndexExpr) {
|
|||
|
||||
fn (g mut Gen) return_statement(it ast.Return) {
|
||||
g.write('return')
|
||||
if g.fn_decl.name == 'main' {
|
||||
g.writeln(' 0;')
|
||||
return
|
||||
}
|
||||
// multiple returns
|
||||
if it.exprs.len > 1 {
|
||||
typ_sym := g.table.get_type_symbol(g.fn_decl.return_type)
|
||||
|
|
|
@ -55,8 +55,8 @@ fn compare_texts(a, b, path string) bool {
|
|||
println('${path}: got\n$a')
|
||||
println('${term_fail} ${i}')
|
||||
println(term.red('i=$i "$line_a" expected="$line_b"'))
|
||||
// println(lines_b[i + 1])
|
||||
// println(lines_b[i + 2])
|
||||
println(lines_b[i + 1])
|
||||
println(lines_b[i + 2])
|
||||
// exit(1)
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -149,7 +149,6 @@ multi_return_int_string multi_return() {
|
|||
void variadic(varg_int a) {
|
||||
int x = path_sep;
|
||||
int y = true ? 1 : 0;
|
||||
;
|
||||
}
|
||||
|
||||
void ensure_cap(int required, int cap) {
|
||||
|
@ -172,6 +171,9 @@ void matches() {
|
|||
else {
|
||||
}
|
||||
;
|
||||
string x = (a == 10) ? tos3("ten") : (a == 30) ? tos3("thirty") : tos3("unknown");
|
||||
int xx = (a == 10) ? 100 : (a == 30) ? 300 : 0;
|
||||
println((a == 10) ? tos3("ten") : tos3("not ten"));
|
||||
}
|
||||
|
||||
//10
|
||||
|
|
|
@ -156,6 +156,17 @@ fn matches() {
|
|||
}
|
||||
else{}
|
||||
}
|
||||
x := match a {
|
||||
10 { 'ten' }
|
||||
30 { 'thirty' }
|
||||
else { 'unknown' }
|
||||
}
|
||||
xx := match a {
|
||||
10 { 100 }
|
||||
30 { 300 }
|
||||
else { 0 }
|
||||
}
|
||||
println(match a { 10 { 'ten' } else { 'not ten' } })
|
||||
/*
|
||||
n := match a {
|
||||
1 { 10 }
|
||||
|
|
|
@ -40,11 +40,11 @@ void println(string s) {
|
|||
|
||||
void handle_expr(Expr e) {
|
||||
if (e.typ == _type_idx_IfExpr) {
|
||||
IfExpr* it = (IfExpr*)tmp1.obj; // ST it
|
||||
IfExpr* it = (IfExpr*)e.obj; // ST it
|
||||
println(tos3("if"));
|
||||
}
|
||||
else if (e.typ == _type_idx_IntegerLiteral) {
|
||||
IntegerLiteral* it = (IntegerLiteral*)tmp1.obj; // ST it
|
||||
IntegerLiteral* it = (IntegerLiteral*)e.obj; // ST it
|
||||
println(tos3("integer"));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -748,10 +748,13 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
|
|||
if p.tok.kind == .amp {
|
||||
p.next()
|
||||
}
|
||||
type_name := p.check_name()
|
||||
// type_name := p.check_name()
|
||||
sizeof_type := p.parse_type()
|
||||
p.check(.rpar)
|
||||
node = ast.SizeOf{
|
||||
type_name: type_name
|
||||
typ: sizeof_type
|
||||
// type_name: type_name
|
||||
|
||||
}
|
||||
}
|
||||
// Map `{"age": 20}` or `{ x | foo:bar, a:10 }`
|
||||
|
|
Loading…
Reference in New Issue