aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-02-18 10:41:48 +0000
committerGinger Bill <bill@gingerbill.org>2017-02-18 10:41:48 +0000
commitd2f9d208330e692f29a2b48dce62a9c5bcab6031 (patch)
tree814604ce923e63d8a4c19e9a4c6483e943730597 /src
parent71100ed427ee2eec8d8a9d4d9616102738097e80 (diff)
Change ternary expression precedence
Diffstat (limited to 'src')
-rw-r--r--src/ir.c308
-rw-r--r--src/ir_print.c54
-rw-r--r--src/main.c9
-rw-r--r--src/parser.c80
4 files changed, 267 insertions, 184 deletions
diff --git a/src/ir.c b/src/ir.c
index ad6f65fea..18832a8b6 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -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: