From 71100ed427ee2eec8d8a9d4d9616102738097e80 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Tue, 14 Feb 2017 19:26:32 +0000 Subject: [PATCH] Ternary expression (removed if and block expression) --- code/demo.odin | 15 ++- core/fmt.odin | 12 ++- src/check_expr.c | 228 +++++------------------------------------ src/check_stmt.c | 11 -- src/checker.c | 4 +- src/ir.c | 88 ++++++---------- src/parser.c | 256 ++++++++++++++++++++++------------------------- 7 files changed, 188 insertions(+), 426 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index 438488045..a3fee1555 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -9,18 +9,14 @@ main :: proc() { - x := type_info(int); - t1, ok := union_cast(^Type_Info.Integer)x; - _, ok = union_cast(^Type_Info.Integer)x; - t2 := union_cast(^Type_Info.Integer)x; - - + x: f32 = false ? 123 : 55; + fmt.println("Ternary:", x); /* /* Version 0.1.1 Added: - * Dynamic Arrays `[...]Type` + * Dynamic Arrays [dynamic]Type` * Dynamic Maps `map[Key]Value` * Dynamic array and map literals * Custom struct alignemnt `struct #align 8 { bar: i8 }` @@ -32,6 +28,7 @@ main :: proc() { * enum types have an implict `names` field, a []string of all the names in that enum * immutable variables are "completely immutable" - rules need a full explanation * `slice_to_bytes` - convert any slice to a slice of bytes + * `union_cast` allows for optional ok check Removed: * Maybe/option types @@ -101,7 +98,7 @@ main :: proc() { } { - x: [...]f64; + x: [dynamic]f64; reserve(x, 16); defer free(x); append(x, 2_000_000.500_000, 3, 5, 7); @@ -114,7 +111,7 @@ main :: proc() { } { - x := [...]f64{2_000_000.500_000, 3, 5, 7}; + x := [dynamic]f64{2_000_000.500_000, 3, 5, 7}; defer free(x); fmt.println(x); } diff --git a/core/fmt.odin b/core/fmt.odin index 32c369dbe..22e7eddd4 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -116,7 +116,11 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) { case ti == type_info(int): buffer_write_string(buf, "int"); case ti == type_info(uint): buffer_write_string(buf, "uint"); default: - buffer_write_string(buf, if info.signed { give "i" } else { give "u"}); + if info.signed { + buffer_write_string(buf, "i"); + } else { + buffer_write_string(buf, "u"); + } fi := Fmt_Info{buf = buf}; fmt_int(^fi, cast(u64)(8*info.size), false, 'd'); } @@ -392,7 +396,11 @@ fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) { fmt_bool :: proc(using fi: ^Fmt_Info, b: bool, verb: rune) { match verb { case 't', 'v': - buffer_write_string(buf, if b { give "true" } else { give "false" }); + if b { + buffer_write_string(buf, "true"); + } else { + buffer_write_string(buf, "false"); + } default: fmt_bad_verb(fi, verb); } diff --git a/src/check_expr.c b/src/check_expr.c index 4461a4def..687f4ebea 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1114,11 +1114,12 @@ i64 check_array_or_map_count(Checker *c, AstNode *e, bool is_map) { } Type *make_optional_ok_type(gbAllocator a, Type *value) { + bool typed = true; Type *t = make_type_tuple(a); t->Tuple.variables = gb_alloc_array(a, Entity *, 2); t->Tuple.variable_count = 2; t->Tuple.variables[0] = make_entity_field(a, NULL, blank_token, value, false, 0); - t->Tuple.variables[1] = make_entity_field(a, NULL, blank_token, t_bool, false, 1); + t->Tuple.variables[1] = make_entity_field(a, NULL, blank_token, typed ? t_bool : t_untyped_bool, false, 1); return t; } @@ -2113,6 +2114,7 @@ void check_cast(Checker *c, Operand *x, Type *type) { gb_string_free(from_type); gb_string_free(to_type); gb_string_free(expr_str); + x->mode = Addressing_Invalid; return; } @@ -3831,7 +3833,8 @@ int valid_proc_and_score_cmp(void const *a, void const *b) { typedef Array(Operand) ArrayOperand; -void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray rhs, bool allow_ok) { +bool check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, AstNodeArray rhs, bool allow_ok) { + bool optional_ok = false; for_array(i, rhs) { Operand o = {0}; check_multi_expr(c, &o, rhs.e[i]); @@ -3849,6 +3852,8 @@ void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, ok.type = t_bool; array_add(operands, val); array_add(operands, ok); + + optional_ok = true; } else { array_add(operands, o); } @@ -3860,6 +3865,8 @@ void check_unpack_arguments(Checker *c, isize lhs_count, ArrayOperand *operands, } } } + + return optional_ok; } Type *check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) { @@ -4162,40 +4169,6 @@ bool check_set_index_data(Operand *o, Type *type, bool indirection, i64 *max_cou return false; } - -bool check_is_giving(AstNode *node, AstNode **give_expr) { - switch (node->kind) { - case_ast_node(es, ExprStmt, node); - if (es->expr->kind == AstNode_GiveExpr) { - if (give_expr) *give_expr = es->expr; - return true; - } - case_end; - - case_ast_node(ge, GiveExpr, node); - if (give_expr) *give_expr = node; - return true; - case_end; - - case_ast_node(be, BlockExpr, node); - // Iterate backwards - for (isize n = be->stmts.count-1; n >= 0; n--) { - AstNode *stmt = be->stmts.e[n]; - if (stmt->kind == AstNode_EmptyStmt) { - continue; - } - if (stmt->kind == AstNode_ExprStmt && stmt->ExprStmt.expr->kind == AstNode_GiveExpr) { - if (give_expr) *give_expr = stmt->ExprStmt.expr; - return true; - } - } - case_end; - } - - if (give_expr) *give_expr = NULL; - return false; -} - ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint) { ExprKind kind = Expr_Stmt; @@ -4297,177 +4270,30 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint o->type = type; case_end; - case_ast_node(ge, GiveExpr, node); + case_ast_node(te, TernaryExpr, node); if (c->proc_stack.count == 0) { - error_node(node, "A give expression is only allowed within a procedure"); + error_node(node, "A ternary expression is only allowed within a procedure"); goto error; } - - if (ge->results.count == 0) { - error_node(node, "`give` has no results"); - goto error; - } - - gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - - Array(Operand) operands; - array_init_reserve(&operands, c->tmp_allocator, 2*ge->results.count); - - for_array(i, ge->results) { - AstNode *rhs = ge->results.e[i]; - Operand o = {0}; - check_multi_expr(c, &o, rhs); - if (!is_operand_value(o)) { - error_node(rhs, "Expected a value for a `give`"); - continue; - } - if (o.type->kind != Type_Tuple) { - array_add(&operands, o); - } else { - TypeTuple *tuple = &o.type->Tuple; - for (isize j = 0; j < tuple->variable_count; j++) { - o.type = tuple->variables[j]->type; - array_add(&operands, o); - } - } - } - - if (operands.count == 0) { - error_node(node, "`give` has no value"); - gb_temp_arena_memory_end(tmp); - goto error; - } else if (operands.count == 1) { - Operand operand = operands.e[0]; - Type *th = type_hint != NULL ? type_hint : c->context.type_hint; - if (th != NULL) { - convert_to_typed(c, &operand, th, 0); - } - // IMPORTANT NOTE(bill): This type could be untyped!!! - o->type = default_type(operand.type); - o->mode = Addressing_Value; - } else { - Type *tuple = make_type_tuple(c->allocator); - - Entity **variables = gb_alloc_array(c->allocator, Entity *, operands.count); - isize variable_index = 0; - for_array(i, operands) { - Operand operand = operands.e[i]; - // Type *type = default_type(operand.type); - Type *type = operand.type; - switch (operand.mode) { - case Addressing_Constant: - variables[variable_index++] = make_entity_constant(c->allocator, NULL, empty_token, type, operand.value); - break; - default: - variables[variable_index++] = make_entity_param(c->allocator, NULL, empty_token, type, false, true); - break; - } - } - tuple->Tuple.variables = variables; - tuple->Tuple.variable_count = operands.count; - - o->type = tuple; - o->mode = Addressing_Value; - } - gb_temp_arena_memory_end(tmp); - case_end; - - case_ast_node(be, BlockExpr, node); - if (c->proc_stack.count == 0) { - error_node(node, "A block expression is only allowed within a procedure"); - goto error; - } - - for (isize i = be->stmts.count-1; i >= 0; i--) { - if (be->stmts.e[i]->kind != AstNode_EmptyStmt) { - break; - } - be->stmts.count--; - } - - if (be->stmts.count == 0) { - error_node(node, "Empty block expression"); - goto error; - } - - CheckerContext prev_context = c->context; - c->context.type_hint = type_hint; - check_open_scope(c, node); - check_stmt_list(c, be->stmts, Stmt_GiveAllowed); - check_close_scope(c); - - c->context = prev_context; - - AstNode *give_node = NULL; - if (!check_is_giving(node, &give_node) || give_node == NULL) { - error_node(node, "Missing give statement at end of block expression"); - goto error; - } - - GB_ASSERT(give_node != NULL && give_node->kind == AstNode_GiveExpr); - be->give_node = give_node; - - Type *type = type_of_expr(&c->info, give_node); - if (type == NULL) { - goto error; - } else if (type == t_invalid) { - o->type = t_invalid; - o->mode = Addressing_Invalid; - } else { - o->type = type; - o->mode = Addressing_Value; - } - case_end; - - case_ast_node(ie, IfExpr, node); - if (c->proc_stack.count == 0) { - error_node(node, "An if expression is only allowed within a procedure"); - goto error; - } - - check_open_scope(c, node); - - if (ie->init != NULL) { - check_stmt(c, ie->init, 0); - } - Operand operand = {Addressing_Invalid}; - check_expr(c, &operand, ie->cond); + check_expr(c, &operand, te->cond); if (operand.mode != Addressing_Invalid && !is_type_boolean(operand.type)) { - error_node(ie->cond, "Non-boolean condition in if expression"); + error_node(te->cond, "Non-boolean condition in if expression"); } Operand x = {Addressing_Invalid}; Operand y = {Addressing_Invalid}; - Type *if_type = NULL; - Type *else_type = NULL; - if (type_hint) { - gb_printf_err("here\n"); - } - check_expr_with_type_hint(c, &x, ie->body, type_hint); - if_type = x.type; + check_expr_with_type_hint(c, &x, te->x, type_hint); - if (ie->else_expr != NULL) { - switch (ie->else_expr->kind) { - case AstNode_IfExpr: - case AstNode_BlockExpr: - check_expr_with_type_hint(c, &y, ie->else_expr, if_type); - else_type = y.type; - break; - default: - error_node(ie->else_expr, "Invalid else expression in if expression"); - break; - } + if (te->y != NULL) { + check_expr_with_type_hint(c, &y, te->y, type_hint); } else { - error_node(ie->else_expr, "An if expression must have an else expression"); - check_close_scope(c); + error_node(node, "A ternary expression must have an else clause"); goto error; } - check_close_scope(c); - - if (if_type == NULL || if_type == t_invalid || - else_type == NULL || else_type == t_invalid) { + if (x.type == NULL || x.type == t_invalid || + y.type == NULL || y.type == t_invalid) { goto error; } @@ -4482,16 +4308,16 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint } - if (!are_types_identical(if_type, else_type)) { - gbString its = type_to_string(if_type); - gbString ets = type_to_string(else_type); - error_node(node, "Mismatched types in if expression, %s vs %s", its, ets); + if (!are_types_identical(x.type, y.type)) { + gbString its = type_to_string(x.type); + gbString ets = type_to_string(y.type); + error_node(node, "Mismatched types in ternary expression, %s vs %s", its, ets); gb_string_free(ets); gb_string_free(its); goto error; } - o->type = if_type; + o->type = x.type; o->mode = Addressing_Value; case_end; @@ -5371,12 +5197,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, "}"); case_end; - case_ast_node(be, BlockExpr, node); - str = gb_string_appendc(str, "block expression"); - case_end; - case_ast_node(ie, IfExpr, node); - str = gb_string_appendc(str, "if expression"); - case_end; case_ast_node(te, TagExpr, node); str = gb_string_appendc(str, "#"); diff --git a/src/check_stmt.c b/src/check_stmt.c index 138e1277e..7315f80ee 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -30,11 +30,6 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) { case AstNode_ReturnStmt: error_node(n, "Statements after this `return` are never executed"); break; - case AstNode_ExprStmt: - if (n->ExprStmt.expr->kind == AstNode_GiveExpr) { - error_node(n, "A `give` must be the last statement in a block"); - } - break; } } @@ -413,12 +408,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { if (operand.expr->kind == AstNode_CallExpr) { return; } - if (operand.expr->kind == AstNode_GiveExpr) { - if ((flags&Stmt_GiveAllowed) != 0) { - return; - } - error_node(node, "Illegal use of `give`"); - } gbString expr_str = expr_to_string(operand.expr); error_node(node, "Expression is not used: `%s`", expr_str); gb_string_free(expr_str); diff --git a/src/checker.c b/src/checker.c index 9fbf3d36d..0b3c66166 100644 --- a/src/checker.c +++ b/src/checker.c @@ -400,9 +400,7 @@ void check_open_scope(Checker *c, AstNode *node) { node = unparen_expr(node); GB_ASSERT(node->kind == AstNode_Invalid || is_ast_node_stmt(node) || - is_ast_node_type(node) || - node->kind == AstNode_BlockExpr || - node->kind == AstNode_IfExpr ); + is_ast_node_type(node)); Scope *scope = make_scope(c->context.scope, c->allocator); add_scope(c, node, scope); if (node->kind == AstNode_ProcType) { diff --git a/src/ir.c b/src/ir.c index e6bf588de..ad6f65fea 100644 --- a/src/ir.c +++ b/src/ir.c @@ -2851,25 +2851,40 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv return ir_addr_load(proc, ir_build_addr(proc, expr)); case_end; - case_ast_node(be, BlockExpr, expr); - ir_emit_comment(proc, str_lit("BlockExpr")); + case_ast_node(te, TernaryExpr, expr); + ir_emit_comment(proc, str_lit("TernaryExpr")); + + irValueArray edges = {0}; + array_init_reserve(&edges, proc->module->allocator, 2); + + GB_ASSERT(te->y != NULL); + irBlock *then = ir_new_block(proc, NULL, "if.then"); + irBlock *done = ir_new_block(proc, NULL, "if.done"); // NOTE(bill): Append later + irBlock *else_ = ir_new_block(proc, NULL, "if.else"); + + irValue *cond = ir_build_cond(proc, te->cond, then, else_); + ir_start_block(proc, then); + ir_open_scope(proc); - - AstNodeArray stmts = be->stmts; - stmts.count--; - ir_build_stmt_list(proc, stmts); - - AstNode *give_stmt = be->stmts.e[be->stmts.count-1]; - GB_ASSERT(give_stmt->kind == AstNode_ExprStmt); - AstNode *give_expr = give_stmt->ExprStmt.expr; - GB_ASSERT(give_expr->kind == AstNode_GiveExpr); - irValue *value = ir_build_expr(proc, give_expr); - + array_add(&edges, ir_build_expr(proc, te->x)); ir_close_scope(proc, irDeferExit_Default, NULL); - return value; + ir_emit_jump(proc, done); + ir_start_block(proc, else_); + + ir_open_scope(proc); + array_add(&edges, ir_build_expr(proc, te->y)); + ir_close_scope(proc, irDeferExit_Default, NULL); + + ir_emit_jump(proc, done); + ir_start_block(proc, done); + + Type *type = type_of_expr(proc->module->info, expr); + + return ir_emit(proc, ir_make_instr_phi(proc, edges, type)); case_end; +#if 0 case_ast_node(ie, IfExpr, expr); ir_emit_comment(proc, str_lit("IfExpr")); if (ie->init != NULL) { @@ -2908,50 +2923,7 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv return ir_emit(proc, ir_make_instr_phi(proc, edges, type)); case_end; - - case_ast_node(ge, GiveExpr, expr); - ir_emit_comment(proc, str_lit("GiveExpr")); - - irValue *v = NULL; - Type *give_type = type_of_expr(proc->module->info, expr); - GB_ASSERT(give_type != NULL); - if (give_type->kind != Type_Tuple) { - v = ir_emit_conv(proc, ir_build_expr(proc, ge->results.e[0]), give_type); - } else { - TypeTuple *tuple = &give_type->Tuple; - gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena); - - irValueArray results; - array_init_reserve(&results, proc->module->tmp_allocator, tuple->variable_count); - - for_array(res_index, ge->results) { - irValue *res = ir_build_expr(proc, ge->results.e[res_index]); - Type *t = ir_type(res); - if (t->kind == Type_Tuple) { - for (isize i = 0; i < t->Tuple.variable_count; i++) { - Entity *e = t->Tuple.variables[i]; - irValue *v = ir_emit_struct_ev(proc, res, i); - array_add(&results, v); - } - } else { - array_add(&results, res); - } - } - - v = ir_add_local_generated(proc, give_type); - for_array(i, results) { - Entity *e = tuple->variables[i]; - irValue *res = ir_emit_conv(proc, results.e[i], e->type); - irValue *field = ir_emit_struct_ep(proc, v, i); - ir_emit_store(proc, field, res); - } - v = ir_emit_load(proc, v); - - gb_temp_arena_memory_end(tmp); - } - - return v; - case_end; +#endif case_ast_node(ce, CastExpr, expr); Type *type = tv->type; diff --git a/src/parser.c b/src/parser.c index 987022068..52343b649 100644 --- a/src/parser.c +++ b/src/parser.c @@ -168,24 +168,9 @@ AST_NODE_KIND(_ExprBegin, "", i32) \ Token open; \ Token close; \ }) \ - AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \ - AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \ - AST_NODE_KIND(BlockExpr, "block expr", struct { \ - AstNodeArray stmts; \ - Token open, close; \ - AstNode *give_node; \ - }) \ - AST_NODE_KIND(GiveExpr, "give expression", struct { \ - Token token; \ - AstNodeArray results; \ - }) \ - AST_NODE_KIND(IfExpr, "if expression", struct { \ - Token token; \ - AstNode *init; \ - AstNode *cond; \ - AstNode *body; \ - AstNode *else_expr; \ - }) \ + AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \ + AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \ + AST_NODE_KIND(TernaryExpr, "ternary expression", struct { AstNode *cond, *x, *y; }) \ AST_NODE_KIND(IntervalExpr, "interval expression", struct { Token op; AstNode *left, *right; }) \ AST_NODE_KIND(_ExprEnd, "", i32) \ AST_NODE_KIND(_StmtBegin, "", i32) \ @@ -465,9 +450,7 @@ Token ast_node_token(AstNode *node) { case AstNode_CastExpr: return node->CastExpr.token; case AstNode_FieldValue: return node->FieldValue.eq; case AstNode_DerefExpr: return node->DerefExpr.op; - case AstNode_BlockExpr: return node->BlockExpr.open; - case AstNode_GiveExpr: return node->GiveExpr.token; - case AstNode_IfExpr: return node->IfExpr.token; + case AstNode_TernaryExpr: return ast_node_token(node->TernaryExpr.cond); case AstNode_IntervalExpr: return ast_node_token(node->IntervalExpr.left); case AstNode_BadStmt: return node->BadStmt.begin; @@ -768,29 +751,11 @@ AstNode *ast_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token o return result; } - -AstNode *ast_block_expr(AstFile *f, AstNodeArray stmts, Token open, Token close) { - AstNode *result = make_ast_node(f, AstNode_BlockExpr); - result->BlockExpr.stmts = stmts; - result->BlockExpr.open = open; - result->BlockExpr.close = close; - return result; -} - -AstNode *ast_give_expr(AstFile *f, Token token, AstNodeArray results) { - AstNode *result = make_ast_node(f, AstNode_GiveExpr); - result->GiveExpr.token = token; - result->GiveExpr.results = results; - return result; -} - -AstNode *ast_if_expr(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body, AstNode *else_expr) { - AstNode *result = make_ast_node(f, AstNode_IfExpr); - result->IfExpr.token = token; - result->IfExpr.init = init; - result->IfExpr.cond = cond; - result->IfExpr.body = body; - result->IfExpr.else_expr = else_expr; +AstNode *ast_ternary_expr(AstFile *f, AstNode *cond, AstNode *x, AstNode *y) { + AstNode *result = make_ast_node(f, AstNode_TernaryExpr); + result->TernaryExpr.cond = cond; + result->TernaryExpr.x = x; + result->TernaryExpr.y = y; return result; } @@ -1321,13 +1286,13 @@ void expect_semicolon(AstFile *f, AstNode *s) { return; } } else { - switch (s->kind) { - case AstNode_GiveExpr: - if (f->curr_token.kind == Token_CloseBrace) { - return; - } - break; - } + // switch (s->kind) { + // case AstNode_GiveExpr: + // if (f->curr_token.kind == Token_CloseBrace) { + // return; + // } + // break; + // } } syntax_error(prev_token, "Expected `;` after %.*s, got %.*s", LIT(ast_node_strings[s->kind]), LIT(token_strings[prev_token.kind])); @@ -1612,72 +1577,72 @@ AstNode *convert_stmt_to_expr(AstFile *f, AstNode *statement, String kind) { -AstNode *parse_block_expr(AstFile *f) { - AstNodeArray stmts = {0}; - Token open, close; - open = expect_token(f, Token_OpenBrace); - f->expr_level++; - stmts = parse_stmt_list(f); - f->expr_level--; - close = expect_token(f, Token_CloseBrace); - return ast_block_expr(f, stmts, open, close); -} +// AstNode *parse_block_expr(AstFile *f) { +// AstNodeArray stmts = {0}; +// Token open, close; +// open = expect_token(f, Token_OpenBrace); +// f->expr_level++; +// stmts = parse_stmt_list(f); +// f->expr_level--; +// close = expect_token(f, Token_CloseBrace); +// return ast_block_expr(f, stmts, open, close); +// } -AstNode *parse_if_expr(AstFile *f) { - if (f->curr_proc == NULL) { - syntax_error(f->curr_token, "You cannot use an if expression in the file scope"); - return ast_bad_stmt(f, f->curr_token, f->curr_token); - } +// AstNode *parse_if_expr(AstFile *f) { +// if (f->curr_proc == NULL) { +// syntax_error(f->curr_token, "You cannot use an if expression in the file scope"); +// return ast_bad_stmt(f, f->curr_token, f->curr_token); +// } - Token token = expect_token(f, Token_if); - AstNode *init = NULL; - AstNode *cond = NULL; - AstNode *body = NULL; - AstNode *else_expr = NULL; +// Token token = expect_token(f, Token_if); +// AstNode *init = NULL; +// AstNode *cond = NULL; +// AstNode *body = NULL; +// AstNode *else_expr = NULL; - isize prev_level = f->expr_level; - f->expr_level = -1; +// isize prev_level = f->expr_level; +// f->expr_level = -1; - if (allow_token(f, Token_Semicolon)) { - cond = parse_expr(f, false); - } else { - init = parse_simple_stmt(f, false); - if (allow_token(f, Token_Semicolon)) { - cond = parse_expr(f, false); - } else { - cond = convert_stmt_to_expr(f, init, str_lit("boolean expression")); - init = NULL; - } - } +// if (allow_token(f, Token_Semicolon)) { +// cond = parse_expr(f, false); +// } else { +// init = parse_simple_stmt(f, false); +// if (allow_token(f, Token_Semicolon)) { +// cond = parse_expr(f, false); +// } else { +// cond = convert_stmt_to_expr(f, init, str_lit("boolean expression")); +// init = NULL; +// } +// } - f->expr_level = prev_level; +// f->expr_level = prev_level; - if (cond == NULL) { - syntax_error(f->curr_token, "Expected condition for if statement"); - } +// if (cond == NULL) { +// syntax_error(f->curr_token, "Expected condition for if statement"); +// } - body = parse_block_expr(f); +// body = parse_block_expr(f); - if (allow_token(f, Token_else)) { - switch (f->curr_token.kind) { - case Token_if: - else_expr = parse_if_expr(f); - break; - case Token_OpenBrace: - else_expr = parse_block_expr(f); - break; - default: - syntax_error(f->curr_token, "Expected if expression block statement"); - else_expr = ast_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]); - break; - } - } else { - syntax_error(f->curr_token, "An if expression must have an else clause"); - return ast_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]); - } +// if (allow_token(f, Token_else)) { +// switch (f->curr_token.kind) { +// case Token_if: +// else_expr = parse_if_expr(f); +// break; +// case Token_OpenBrace: +// else_expr = parse_block_expr(f); +// break; +// default: +// syntax_error(f->curr_token, "Expected if expression block statement"); +// else_expr = ast_bad_expr(f, f->curr_token, f->tokens.e[f->curr_token_index+1]); +// break; +// } +// } else { +// syntax_error(f->curr_token, "An if expression must have an else clause"); +// return ast_bad_stmt(f, f->curr_token, f->tokens.e[f->curr_token_index+1]); +// } - return ast_if_expr(f, token, init, cond, body, else_expr); -} +// return ast_if_expr(f, token, init, cond, body, else_expr); +// } AstNode *parse_operand(AstFile *f, bool lhs) { AstNode *operand = NULL; // Operand @@ -1791,16 +1756,16 @@ AstNode *parse_operand(AstFile *f, bool lhs) { return type; } - case Token_if: - if (!lhs && f->expr_level >= 0) { - return parse_if_expr(f); - } - break; - case Token_OpenBrace: - if (!lhs && f->expr_level >= 0) { - return parse_block_expr(f); - } - break; + // case Token_if: + // if (!lhs && f->expr_level >= 0) { + // return parse_if_expr(f); + // } + // break; + // case Token_OpenBrace: + // if (!lhs && f->expr_level >= 0) { + // return parse_block_expr(f); + // } + // break; default: { AstNode *type = parse_type_or_ident(f); @@ -1984,6 +1949,19 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) { } break; + case Token_Question: + if (!lhs && operand != NULL && f->expr_level >= 0) { + AstNode *cond = operand; + Token token_q = expect_token(f, Token_Question); + AstNode *x = parse_expr(f, false); + Token token_c = expect_token(f, Token_Colon); + AstNode *y = parse_expr(f, false); + operand = ast_ternary_expr(f, cond, x, y); + } else { + loop = false; + } + break; + default: loop = false; break; @@ -2925,27 +2903,27 @@ AstNode *parse_return_stmt(AstFile *f) { } -AstNode *parse_give_stmt(AstFile *f) { - if (f->curr_proc == NULL) { - syntax_error(f->curr_token, "You cannot use a give statement in the file scope"); - return ast_bad_stmt(f, f->curr_token, f->curr_token); - } - if (f->expr_level == 0) { - syntax_error(f->curr_token, "A give statement must be used within an expression"); - return ast_bad_stmt(f, f->curr_token, f->curr_token); - } +// AstNode *parse_give_stmt(AstFile *f) { +// if (f->curr_proc == NULL) { +// syntax_error(f->curr_token, "You cannot use a give statement in the file scope"); +// return ast_bad_stmt(f, f->curr_token, f->curr_token); +// } +// if (f->expr_level == 0) { +// syntax_error(f->curr_token, "A give statement must be used within an expression"); +// return ast_bad_stmt(f, f->curr_token, f->curr_token); +// } - Token token = expect_token(f, Token_give); - AstNodeArray results; - if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) { - results = parse_rhs_expr_list(f); - } else { - results = make_ast_node_array(f); - } - AstNode *ge = ast_give_expr(f, token, results); - expect_semicolon(f, ge); - return ast_expr_stmt(f, ge); -} +// Token token = expect_token(f, Token_give); +// AstNodeArray results; +// if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) { +// results = parse_rhs_expr_list(f); +// } else { +// results = make_ast_node_array(f); +// } +// AstNode *ge = ast_give_expr(f, token, results); +// expect_semicolon(f, ge); +// return ast_expr_stmt(f, ge); +// } AstNode *parse_for_stmt(AstFile *f) { if (f->curr_proc == NULL) { @@ -3227,7 +3205,7 @@ AstNode *parse_stmt(AstFile *f) { case Token_defer: return parse_defer_stmt(f); case Token_asm: return parse_asm_stmt(f); case Token_return: return parse_return_stmt(f); - case Token_give: return parse_give_stmt(f); + // case Token_give: return parse_give_stmt(f); case Token_break: case Token_continue: