diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-02-18 10:41:48 +0000 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-02-18 10:41:48 +0000 |
| commit | d2f9d208330e692f29a2b48dce62a9c5bcab6031 (patch) | |
| tree | 814604ce923e63d8a4c19e9a4c6483e943730597 /src | |
| parent | 71100ed427ee2eec8d8a9d4d9616102738097e80 (diff) | |
Change ternary expression precedence
Diffstat (limited to 'src')
| -rw-r--r-- | src/ir.c | 308 | ||||
| -rw-r--r-- | src/ir_print.c | 54 | ||||
| -rw-r--r-- | src/main.c | 9 | ||||
| -rw-r--r-- | src/parser.c | 80 |
4 files changed, 267 insertions, 184 deletions
@@ -15,13 +15,14 @@ typedef Array(irValue *) irValueArray; #define MAP_NAME MapIrDebugInfo #include "map.c" + typedef struct irModule { CheckerInfo * info; gbArena arena; gbArena tmp_arena; gbAllocator allocator; gbAllocator tmp_allocator; - bool generate_debug_info; + // bool generate_debug_info; u32 stmt_state_flags; @@ -29,20 +30,20 @@ typedef struct irModule { String layout; // String triple; - MapEntity min_dep_map; // Key: Entity * - MapIrValue values; // Key: Entity * - MapIrValue members; // Key: String - MapString type_names; // Key: Type * - MapIrDebugInfo debug_info; // Key: Unique pointer - i32 global_string_index; - i32 global_array_index; // For ConstantSlice + MapEntity min_dep_map; // Key: Entity * + MapIrValue values; // Key: Entity * + MapIrValue members; // Key: String + MapString type_names; // Key: Type * + MapIrDebugInfo debug_info; // Key: Unique pointer + i32 global_string_index; + i32 global_array_index; // For ConstantSlice - Entity * entry_point_entity; + Entity * entry_point_entity; - Array(irProcedure *) procs; // NOTE(bill): All procedures with bodies - irValueArray procs_to_generate; // NOTE(bill): Procedures to generate + Array(irProcedure *) procs; // NOTE(bill): All procedures with bodies + irValueArray procs_to_generate; // NOTE(bill): Procedures to generate - Array(String) foreign_library_paths; // Only the ones that were used + Array(String) foreign_library_paths; // Only the ones that were used } irModule; // NOTE(bill): For more info, see https://en.wikipedia.org/wiki/Dominator_(graph_theory) @@ -121,6 +122,7 @@ struct irProcedure { irTargetList * target_list; irValueArray referrers; + i32 local_count; i32 instr_count; i32 block_count; @@ -134,90 +136,99 @@ struct irProcedure { #define IR_INSTR_KINDS \ - IR_INSTR_KIND(Comment, struct { String text; }) \ - IR_INSTR_KIND(Local, struct { \ - Entity * entity; \ - Type * type; \ - bool zero_initialized; \ - irValueArray referrers; \ - }) \ - IR_INSTR_KIND(ZeroInit, struct { irValue *address; }) \ - IR_INSTR_KIND(Store, struct { irValue *address, *value; }) \ + IR_INSTR_KIND(Comment, struct { String text; }) \ + IR_INSTR_KIND(Local, struct { \ + Entity * entity; \ + Type * type; \ + bool zero_initialized; \ + irValueArray referrers; \ + }) \ + IR_INSTR_KIND(ZeroInit, struct { irValue *address; }) \ + IR_INSTR_KIND(Store, struct { irValue *address, *value; }) \ IR_INSTR_KIND(Load, struct { Type *type; irValue *address; }) \ - IR_INSTR_KIND(PtrOffset, struct { \ - irValue *address; \ - irValue *offset; \ - }) \ - IR_INSTR_KIND(ArrayElementPtr, struct { \ - irValue *address; \ - Type * result_type; \ - irValue *elem_index; \ - }) \ - IR_INSTR_KIND(StructElementPtr, struct { \ - irValue *address; \ - Type * result_type; \ - i32 elem_index; \ - }) \ - IR_INSTR_KIND(StructExtractValue, struct { \ - irValue *address; \ - Type * result_type; \ - i32 index; \ - }) \ - IR_INSTR_KIND(UnionTagPtr, struct { \ - irValue *address; \ - Type *type; /* ^int */ \ - }) \ - IR_INSTR_KIND(UnionTagValue, struct { \ - irValue *address; \ - Type *type; /* int */ \ - }) \ - IR_INSTR_KIND(Conv, struct { \ - irConvKind kind; \ - irValue *value; \ - Type *from, *to; \ - }) \ - IR_INSTR_KIND(Jump, struct { irBlock *block; }) \ - IR_INSTR_KIND(If, struct { \ - irValue *cond; \ - irBlock *true_block; \ - irBlock *false_block; \ + IR_INSTR_KIND(PtrOffset, struct { \ + irValue *address; \ + irValue *offset; \ + }) \ + IR_INSTR_KIND(ArrayElementPtr, struct { \ + irValue *address; \ + Type * result_type; \ + irValue *elem_index; \ + }) \ + IR_INSTR_KIND(StructElementPtr, struct { \ + irValue *address; \ + Type * result_type; \ + i32 elem_index; \ + }) \ + IR_INSTR_KIND(StructExtractValue, struct { \ + irValue *address; \ + Type * result_type; \ + i32 index; \ + }) \ + IR_INSTR_KIND(UnionTagPtr, struct { \ + irValue *address; \ + Type *type; /* ^int */ \ + }) \ + IR_INSTR_KIND(UnionTagValue, struct { \ + irValue *address; \ + Type *type; /* int */ \ + }) \ + IR_INSTR_KIND(Conv, struct { \ + irConvKind kind; \ + irValue *value; \ + Type *from, *to; \ + }) \ + IR_INSTR_KIND(Jump, struct { irBlock *block; }) \ + IR_INSTR_KIND(If, struct { \ + irValue *cond; \ + irBlock *true_block; \ + irBlock *false_block; \ + }) \ + IR_INSTR_KIND(Return, struct { irValue *value; }) \ + IR_INSTR_KIND(Select, struct { \ + irValue *cond; \ + irValue *true_value; \ + irValue *false_value; \ + }) \ + IR_INSTR_KIND(Phi, struct { irValueArray edges; Type *type; }) \ + IR_INSTR_KIND(Unreachable, i32) \ + IR_INSTR_KIND(UnaryOp, struct { \ + Type * type; \ + TokenKind op; \ + irValue * expr; \ + }) \ + IR_INSTR_KIND(BinaryOp, struct { \ + Type * type; \ + TokenKind op; \ + irValue * left, *right; \ + }) \ + IR_INSTR_KIND(Call, struct { \ + Type * type; /* return type */ \ + irValue * value; \ + irValue **args; \ + isize arg_count; \ + }) \ + IR_INSTR_KIND(StartupRuntime, i32) \ + IR_INSTR_KIND(BoundsCheck, struct { \ + TokenPos pos; \ + irValue *index; \ + irValue *len; \ + }) \ + IR_INSTR_KIND(SliceBoundsCheck, struct { \ + TokenPos pos; \ + irValue *low; \ + irValue *high; \ + bool is_substring; \ + }) \ + IR_INSTR_KIND(DebugDeclare, struct { \ + irDebugInfo *debug_info; \ + AstNode * expr; \ + Entity * entity; \ + bool is_addr; \ + irValue * value; \ }) \ - IR_INSTR_KIND(Return, struct { irValue *value; }) \ - IR_INSTR_KIND(Select, struct { \ - irValue *cond; \ - irValue *true_value; \ - irValue *false_value; \ - }) \ - IR_INSTR_KIND(Phi, struct { irValueArray edges; Type *type; }) \ - IR_INSTR_KIND(Unreachable, i32) \ - IR_INSTR_KIND(UnaryOp, struct { \ - Type * type; \ - TokenKind op; \ - irValue *expr; \ - }) \ - IR_INSTR_KIND(BinaryOp, struct { \ - Type * type; \ - TokenKind op; \ - irValue *left, *right; \ - }) \ - IR_INSTR_KIND(Call, struct { \ - Type * type; /* return type */ \ - irValue *value; \ - irValue **args; \ - isize arg_count; \ - }) \ - IR_INSTR_KIND(StartupRuntime, i32) \ - IR_INSTR_KIND(BoundsCheck, struct { \ - TokenPos pos; \ - irValue *index; \ - irValue *len; \ - }) \ - IR_INSTR_KIND(SliceBoundsCheck, struct { \ - TokenPos pos; \ - irValue *low; \ - irValue *high; \ - bool is_substring; \ - }) + + #define IR_CONV_KINDS \ IR_CONV_KIND(trunc) \ @@ -394,7 +405,6 @@ irAddr ir_make_addr_map(irValue *addr, irValue *map_key, Type *map_type, Type *m return v; } - typedef enum irDebugEncoding { irDebugBasicEncoding_Invalid = 0, @@ -519,14 +529,19 @@ struct irDebugInfo { }; }; + + typedef struct irGen { irModule module; - gbFile output_file; - bool opt_called; + gbFile output_file; + bool opt_called; } irGen; + + + Type *ir_type(irValue *value); Type *ir_instr_type(irInstr *instr) { switch (instr->kind) { @@ -948,6 +963,16 @@ irValue *ir_make_instr_slice_bounds_check(irProcedure *p, TokenPos pos, irValue v->Instr.SliceBoundsCheck.is_substring = is_substring; return v; } +irValue *ir_make_instr_debug_declare(irProcedure *p, irDebugInfo *debug_info, AstNode *expr, Entity *entity, bool is_addr, irValue *value) { + irValue *v = ir_alloc_instr(p, irInstr_DebugDeclare); + v->Instr.DebugDeclare.debug_info = debug_info; + v->Instr.DebugDeclare.expr = expr; + v->Instr.DebugDeclare.entity = entity; + v->Instr.DebugDeclare.is_addr = is_addr; + v->Instr.DebugDeclare.value = value; + return v; + +} @@ -967,6 +992,23 @@ irValue *ir_make_value_constant_slice(gbAllocator a, Type *type, irValue *backin return v; } + + +irValue *ir_emit(irProcedure *proc, irValue *instr) { + GB_ASSERT(instr->kind == irValue_Instr); + irBlock *b = proc->curr_block; + instr->Instr.parent = b; + if (b != NULL) { + irInstr *i = ir_get_last_instr(b); + if (!ir_is_instr_terminating(i)) { + array_add(&b->instrs, instr); + } + } + return instr; +} + + + irValue *ir_make_const_int(gbAllocator a, i64 i) { return ir_make_value_constant(a, t_int, make_exact_value_integer(i)); } @@ -1166,7 +1208,7 @@ irValue *ir_add_global_string_array(irModule *m, String string) { -irValue *ir_add_local(irProcedure *proc, Entity *e) { +irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr) { irBlock *b = proc->decl_block; // all variables must be in the first block irValue *instr = ir_make_instr_local(proc, e, true); instr->Instr.parent = b; @@ -1178,6 +1220,11 @@ irValue *ir_add_local(irProcedure *proc, Entity *e) { ir_emit_zero_init(proc, instr); // } + if (expr != NULL) { + irDebugInfo *di = *map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity)); + ir_emit(proc, ir_make_instr_debug_declare(proc, di, expr, e, true, instr)); + } + return instr; } @@ -1186,7 +1233,7 @@ irValue *ir_add_local_for_identifier(irProcedure *proc, AstNode *name, bool zero if (found) { Entity *e = *found; ir_emit_comment(proc, e->token.string); - return ir_add_local(proc, e); + return ir_add_local(proc, e, name); } return NULL; } @@ -1202,14 +1249,14 @@ irValue *ir_add_local_generated(irProcedure *proc, Type *type) { scope, empty_token, type, false); - return ir_add_local(proc, e); + return ir_add_local(proc, e, NULL); } -irValue *ir_add_param(irProcedure *proc, Entity *e) { +irValue *ir_add_param(irProcedure *proc, Entity *e, AstNode *expr) { irValue *v = ir_make_value_param(proc->module->allocator, proc, e); #if 1 - irValue *l = ir_add_local(proc, e); + irValue *l = ir_add_local(proc, e, expr); ir_emit_store(proc, l, v); #else @@ -1227,9 +1274,9 @@ irValue *ir_add_param(irProcedure *proc, Entity *e) { //////////////////////////////////////////////////////////////// irDebugInfo *ir_add_debug_info_file(irProcedure *proc, AstFile *file) { - if (!proc->module->generate_debug_info) { - return NULL; - } + // if (!proc->module->generate_debug_info) { + // return NULL; + // } GB_ASSERT(file != NULL); irDebugInfo *di = ir_alloc_debug_info(proc->module->allocator, irDebugInfo_File); @@ -1259,9 +1306,9 @@ irDebugInfo *ir_add_debug_info_file(irProcedure *proc, AstFile *file) { irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String name, irDebugInfo *file) { - if (!proc->module->generate_debug_info) { - return NULL; - } + // if (!proc->module->generate_debug_info) { + // return NULL; + // } GB_ASSERT(entity != NULL); irDebugInfo *di = ir_alloc_debug_info(proc->module->allocator, irDebugInfo_Proc); @@ -1281,18 +1328,7 @@ irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String na //////////////////////////////////////////////////////////////// -irValue *ir_emit(irProcedure *proc, irValue *instr) { - GB_ASSERT(instr->kind == irValue_Instr); - irBlock *b = proc->curr_block; - instr->Instr.parent = b; - if (b != NULL) { - irInstr *i = ir_get_last_instr(b); - if (!ir_is_instr_terminating(i)) { - array_add(&b->instrs, instr); - } - } - return instr; -} + irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) { #if 1 // NOTE(bill): Sanity check @@ -5357,7 +5393,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *tag_var = NULL; if (tag_var_entity != NULL) { - tag_var = ir_add_local(proc, tag_var_entity); + tag_var = ir_add_local(proc, tag_var_entity, NULL); } else { tag_var = ir_add_local_generated(proc, tag_var_type); } @@ -5385,7 +5421,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { irValue *tag_var = NULL; if (tag_var_entity != NULL) { - tag_var = ir_add_local(proc, tag_var_entity); + tag_var = ir_add_local(proc, tag_var_entity, NULL); } else { tag_var = ir_add_local_generated(proc, tag_var_type); } @@ -5558,12 +5594,24 @@ void ir_begin_procedure_body(irProcedure *proc) { ir_start_block(proc, proc->entry_block); if (proc->type->Proc.params != NULL) { + ast_node(pt, ProcType, proc->type_expr); + isize param_index = 0; + isize q_index = 0; + TypeTuple *params = &proc->type->Proc.params->Tuple; for (isize i = 0; i < params->variable_count; i++) { + GB_ASSERT(pt->params.e[0]->kind == AstNode_Field); + if (q_index == pt->params.e[param_index]->Field.names.count) { + q_index = 0; + param_index++; + } + ast_node(field, Field, pt->params.e[param_index]); + AstNode *name = field->names.e[q_index++]; + Entity *e = params->variables[i]; if (!str_eq(e->token.string, str_lit("")) && !str_eq(e->token.string, str_lit("_"))) { - irValue *param = ir_add_param(proc, e); + irValue *param = ir_add_param(proc, e, name); array_add(&proc->params, param); } } @@ -5790,7 +5838,7 @@ bool ir_gen_init(irGen *s, Checker *c) { } ir_init_module(&s->module, c); - s->module.generate_debug_info = false; + // s->module.generate_debug_info = false; // TODO(bill): generate appropriate output name int pos = cast(int)string_extension_position(c->parser->init_fullpath); @@ -6025,7 +6073,9 @@ void ir_gen_tree(irGen *s) { name = pd->link_name; } - irValue *p = ir_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); + AstNode *type_expr = decl->proc_lit->ProcLit.type; + + irValue *p = ir_make_value_procedure(a, m, e, e->type, type_expr, body, name); p->Proc.tags = pd->tags; ir_module_add_value(m, e, p); @@ -6067,7 +6117,6 @@ void ir_gen_tree(irGen *s) { for_array(i, m->debug_info.entries) { MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[i]; irDebugInfo *di = entry->value; - di->id = i; if (di->kind == irDebugInfo_Proc) { array_add(&all_procs->AllProcs.procs, di); } @@ -6619,6 +6668,13 @@ void ir_gen_tree(irGen *s) { ir_build_proc(m->procs_to_generate.e[i], m->procs_to_generate.e[i]->Proc.parent); } + // Number debug info + for_array(i, m->debug_info.entries) { + MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[i]; + irDebugInfo *di = entry->value; + di->id = i; + } + // m->layout = str_lit("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"); } diff --git a/src/ir_print.c b/src/ir_print.c index e1b29a847..a35c4eb36 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -1254,6 +1254,29 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { ir_fprintf(f, ")\n"); } break; + case irInstr_DebugDeclare: { + /* irInstrDebugDeclare *dd = &instr->DebugDeclare; + Type *vt = ir_type(dd->value); + irDebugInfo *di = dd->debug_info; + Entity *e = dd->entity; + String name = e->token.string; + TokenPos pos = e->token.pos; + // gb_printf("debug_declare %.*s\n", LIT(dd->entity->token.string)); + ir_fprintf(f, "call void @llvm.dbg.declare("); + ir_fprintf(f, "metadata "); + ir_print_type(f, m, vt); + ir_fprintf(f, " "); + ir_print_value(f, m, dd->value, vt); + ir_fprintf(f, ", metadata !DILocalVariable(name: \""); + ir_print_escape_string(f, name, false); + ir_fprintf(f, "\", scope: !%d, line: %td)", di->id, pos.line); + ir_fprintf(f, ", metadata !DIExpression()"); + ir_fprintf(f, ")"); + ir_fprintf(f, ", !dbg !DILocation(line: %td, column: %td, scope: !%d)", pos.line, pos.column, di->id); + + ir_fprintf(f, "\n"); */ + } break; + default: { GB_PANIC("<unknown instr> %d\n", instr->kind); @@ -1326,11 +1349,14 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { } - if (proc->module->generate_debug_info && proc->entity != NULL) { + if (proc->entity != NULL) { if (proc->body != NULL) { - irDebugInfo *di = *map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity)); - GB_ASSERT(di->kind == irDebugInfo_Proc); - ir_fprintf(f, "!dbg !%d ", di->id); + irDebugInfo **di_ = map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity)); + if (di_ != NULL) { + irDebugInfo *di = *di_; + GB_ASSERT(di->kind == irDebugInfo_Proc); + // ir_fprintf(f, "!dbg !%d ", di->id); + } } } @@ -1396,6 +1422,8 @@ void print_llvm_ir(irGen *ir) { ir_print_type(f, m, t_rawptr); ir_fprintf(f, "} ; Basic_any\n"); + ir_fprintf(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n"); + for_array(member_index, m->members.entries) { MapIrValueEntry *entry = &m->members.entries.e[member_index]; @@ -1482,9 +1510,18 @@ void print_llvm_ir(irGen *ir) { #if 0 - if (m->generate_debug_info) { + // if (m->generate_debug_info) { + { ir_fprintf(f, "\n"); + + i32 diec = m->debug_info.entries.count; + ir_fprintf(f, "!llvm.dbg.cu = !{!0}\n"); + ir_fprintf(f, "!llvm.ident = !{!%d}\n", diec+3); + ir_fprintf(f, "!%d = !{i32 2, !\"Dwarf Version\", i32 4}\n", diec+0); + ir_fprintf(f, "!%d = !{i32 2, !\"Debug Info Version\", i32 3}\n", diec+1); + ir_fprintf(f, "!%d = !{i32 1, !\"PIC Level\", i32 2}\n", diec+2); + ir_fprintf(f, "!%d = !{!\"clang version 3.9.0 (branches/release_39)\"}\n", diec+3); for_array(di_index, m->debug_info.entries) { MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[di_index]; @@ -1493,19 +1530,18 @@ void print_llvm_ir(irGen *ir) { switch (di->kind) { case irDebugInfo_CompileUnit: { - auto *cu = &di->CompileUnit; - irDebugInfo *file = *map_ir_debug_info_get(&m->debug_info, hash_pointer(cu->file)); + irDebugInfo *file = *map_ir_debug_info_get(&m->debug_info, hash_pointer(di->CompileUnit.file)); ir_fprintf(f, "distinct !DICompileUnit(" "language: DW_LANG_Go, " // Is this good enough? "file: !%d, " - "producer: \"%.*s\", " + "producer: \"clang version 3.9.0 (branches/release_39)\", " "flags: \"\", " "runtimeVersion: 0, " "isOptimized: false, " "emissionKind: FullDebug" ")", - file->id, LIT(cu->producer)); + file->id); } break; case irDebugInfo_File: diff --git a/src/main.c b/src/main.c index 20da798af..233f6ba93 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ extern "C" { #endif + #include "common.c" #include "timings.c" #include "build_settings.c" @@ -216,10 +217,10 @@ int main(int argc, char **argv) { return 1; } - ssa_generate(&checker.info, &build_context); -#endif -#if 1 - + if (!ssa_generate(&checker.info)) { + return 1; + } +#else irGen ir_gen = {0}; if (!ir_gen_init(&ir_gen, &checker)) { return 1; diff --git a/src/parser.c b/src/parser.c index 52343b649..b3c6f7b83 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1949,19 +1949,6 @@ 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; @@ -2016,22 +2003,24 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) { // NOTE(bill): result == priority i32 token_precedence(TokenKind t) { switch (t) { - case Token_CmpOr: + case Token_Question: return 1; - case Token_CmpAnd: + case Token_CmpOr: return 2; + case Token_CmpAnd: + return 3; case Token_CmpEq: case Token_NotEq: case Token_Lt: case Token_Gt: case Token_LtEq: case Token_GtEq: - return 3; + return 4; case Token_Add: case Token_Sub: case Token_Or: case Token_Xor: - return 4; + return 5; case Token_Mul: case Token_Quo: case Token_Mod: @@ -2039,51 +2028,42 @@ i32 token_precedence(TokenKind t) { case Token_AndNot: case Token_Shl: case Token_Shr: - return 5; - // case Token_as: - // case Token_transmute: - // case Token_down_cast: - // case Token_union_cast: - // return 6; + return 6; } return 0; } AstNode *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) { - AstNode *expression = parse_unary_expr(f, lhs); + AstNode *expr = parse_unary_expr(f, lhs); for (i32 prec = token_precedence(f->curr_token.kind); prec >= prec_in; prec--) { for (;;) { - AstNode *right; Token op = f->curr_token; i32 op_prec = token_precedence(op.kind); if (op_prec != prec) { + // NOTE(bill): This will also catch operators that are not valid "binary" operators break; } expect_operator(f); // NOTE(bill): error checks too - if (lhs) { - // TODO(bill): error checking - lhs = false; - } - switch (op.kind) { - /* case Token_as: - case Token_transmute: - case Token_down_cast: - case Token_union_cast: - right = parse_type(f); - break; */ - - default: - right = parse_binary_expr(f, false, prec+1); + if (op.kind == Token_Question) { + AstNode *cond = expr; + // Token_Question + AstNode *x = parse_expr(f, lhs); + Token token_c = expect_token(f, Token_Colon); + AstNode *y = parse_expr(f, lhs); + expr = ast_ternary_expr(f, cond, x, y); + } else { + AstNode *right = parse_binary_expr(f, false, prec+1); if (!right) { - syntax_error(op, "Expected expression on the right hand side of the binary operator"); + syntax_error(op, "Expected expression on the right-hand side of the binary operator"); } - break; + expr = ast_binary_expr(f, op, expr, right); } - expression = ast_binary_expr(f, op, expression, right); + + lhs = false; } } - return expression; + return expr; } AstNode *parse_expr(AstFile *f, bool lhs) { @@ -3458,8 +3438,18 @@ AstNode *parse_stmt(AstFile *f) { return s; } - expect_semicolon(f, s); - return ast_tag_stmt(f, hash_token, name, parse_stmt(f)); + + if (str_eq(tag, str_lit("include"))) { + syntax_error(token, "#include is not a valid import declaration kind. Use #load instead"); + s = ast_bad_stmt(f, token, f->curr_token); + } else { + syntax_error(token, "Unknown tag used: `%.*s`", LIT(tag)); + s = ast_bad_stmt(f, token, f->curr_token); + } + + fix_advance_to_next_stmt(f); + + return s; } break; case Token_OpenBrace: |