Remove len(), cap() and replace with selectors; fix defer in match

This commit is contained in:
Ginger Bill
2016-09-13 14:04:05 +01:00
parent 59fb74d2a2
commit 817ae643c5
11 changed files with 454 additions and 333 deletions
-6
View File
@@ -124,7 +124,6 @@ enum BuiltinProcId {
BuiltinProc_new,
BuiltinProc_new_slice,
BuiltinProc_delete,
BuiltinProc_size_of,
BuiltinProc_size_of_val,
@@ -139,8 +138,6 @@ enum BuiltinProcId {
BuiltinProc_compile_assert,
BuiltinProc_assert,
BuiltinProc_len,
BuiltinProc_cap,
BuiltinProc_copy,
BuiltinProc_append,
@@ -168,7 +165,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("new"), 1, false, Expr_Expr},
{STR_LIT("new_slice"), 2, true, Expr_Expr},
{STR_LIT("delete"), 1, false, Expr_Stmt},
{STR_LIT("size_of"), 1, false, Expr_Expr},
{STR_LIT("size_of_val"), 1, false, Expr_Expr},
@@ -183,8 +179,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("compile_assert"), 1, false, Expr_Stmt},
{STR_LIT("assert"), 1, false, Expr_Stmt},
{STR_LIT("len"), 1, false, Expr_Expr},
{STR_LIT("cap"), 1, false, Expr_Expr},
{STR_LIT("copy"), 2, false, Expr_Expr},
{STR_LIT("append"), 2, false, Expr_Expr},
-67
View File
@@ -2095,21 +2095,6 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->mode = Addressing_Value;
operand->type = make_type_slice(c->allocator, type);
} break;
case BuiltinProc_delete: {
// delete :: proc(ptr: ^T)
Type *type = get_base_type(operand->type);
if (!is_type_pointer(type) && !is_type_slice(type)) {
gbString type_str = type_to_string(operand->type);
defer (gb_string_free(type_str));
error(&c->error_collector, ast_node_token(call),
"Expected a pointer or slice to `delete`, got `%s`",
type_str);
return false;
}
operand->mode = Addressing_NoValue;
operand->type = NULL;
} break;
case BuiltinProc_size_of: {
// size_of :: proc(Type) -> int
@@ -2289,58 +2274,6 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
}
break;
// TODO(bill): Should these be procedures and are their names appropriate?
case BuiltinProc_len:
case BuiltinProc_cap: {
Type *t = get_base_type(operand->type);
AddressingMode mode = Addressing_Invalid;
ExactValue value = {};
switch (t->kind) {
case Type_Basic:
if (id == BuiltinProc_len) {
if (is_type_string(t)) {
if (operand->mode == Addressing_Constant) {
mode = Addressing_Constant;
value = make_exact_value_integer(operand->value.value_string);
} else {
mode = Addressing_Value;
}
}
}
break;
case Type_Array:
mode = Addressing_Constant;
value = make_exact_value_integer(t->Array.count);
break;
case Type_Vector:
mode = Addressing_Constant;
value = make_exact_value_integer(t->Vector.count);
break;
case Type_Slice:
mode = Addressing_Value;
break;
}
if (mode == Addressing_Invalid) {
gbString str = expr_to_string(operand->expr);
error(&c->error_collector, ast_node_token(operand->expr),
"Invalid expression `%s` for `%.*s`",
str, LIT(bp->name));
gb_string_free(str);
return false;
}
operand->mode = mode;
operand->type = t_int;
operand->value = value;
} break;
case BuiltinProc_copy: {
// copy :: proc(x, y: []Type) -> int
Type *dest_type = NULL, *src_type = NULL;
+81 -3
View File
@@ -350,6 +350,7 @@ gb_global Type *t_untyped_rune = &basic_types[Basic_UntypedRune];
gb_global Type *t_byte = &basic_type_aliases[Basic_byte];
gb_global Type *t_rune = &basic_type_aliases[Basic_rune];
gb_global Type *t_type_info = NULL;
gb_global Type *t_type_info_ptr = NULL;
gb_global Type *t_type_info_member = NULL;
@@ -588,7 +589,9 @@ b32 are_types_identical(Type *x, Type *y) {
case TypeRecord_Struct:
case TypeRecord_RawUnion:
case TypeRecord_Union:
if (x->Record.field_count == y->Record.field_count) {
if (x->Record.field_count == y->Record.field_count &&
x->Record.struct_is_packed == y->Record.struct_is_packed &&
x->Record.struct_is_ordered == y->Record.struct_is_ordered) {
for (isize i = 0; i < x->Record.field_count; i++) {
if (!are_types_identical(x->Record.fields[i]->type, y->Record.fields[i]->type)) {
return false;
@@ -709,6 +712,8 @@ void selection_add_index(Selection *s, isize index) {
gb_global Entity *entity__any_type_info = NULL;
gb_global Entity *entity__any_data = NULL;
gb_global Entity *entity__string_data = NULL;
gb_global Entity *entity__string_count = NULL;
Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection sel = empty_selection) {
GB_ASSERT(type_ != NULL);
@@ -717,6 +722,7 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se
return empty_selection;
}
gbAllocator a = gb_heap_allocator();
Type *type = type_deref(type_);
b32 is_ptr = type != type_;
type = get_base_type(type);
@@ -729,12 +735,12 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se
if (entity__any_type_info == NULL) {
Token token = {Token_Identifier};
token.string = type_info_str;
entity__any_type_info = make_entity_field(gb_heap_allocator(), NULL, token, t_type_info_ptr, false, 0);
entity__any_type_info = make_entity_field(a, NULL, token, t_type_info_ptr, false, 0);
}
if (entity__any_data == NULL) {
Token token = {Token_Identifier};
token.string = data_str;
entity__any_data = make_entity_field(gb_heap_allocator(), NULL, token, t_rawptr, false, 1);
entity__any_data = make_entity_field(a, NULL, token, t_rawptr, false, 1);
}
if (are_strings_equal(field_name, type_info_str)) {
@@ -747,9 +753,81 @@ Selection lookup_field(Type *type_, String field_name, b32 is_type, Selection se
return sel;
}
} break;
case Basic_string: {
String data_str = make_string("data");
String count_str = make_string("count");
if (entity__string_data == NULL) {
Token token = {Token_Identifier};
token.string = data_str;
entity__string_data = make_entity_field(a, NULL, token, make_type_pointer(a, t_byte), false, 0);
}
if (entity__string_count == NULL) {
Token token = {Token_Identifier};
token.string = count_str;
entity__string_count = make_entity_field(a, NULL, token, t_int, false, 1);
}
if (are_strings_equal(field_name, data_str)) {
selection_add_index(&sel, 0);
sel.entity = entity__string_data;
return sel;
} else if (are_strings_equal(field_name, count_str)) {
selection_add_index(&sel, 1);
sel.entity = entity__string_count;
return sel;
}
} break;
}
return sel;
} else if (type->kind == Type_Array) {
String count_str = make_string("count");
// NOTE(bill):U nderlying memory address cannot be changed
if (are_strings_equal(field_name, count_str)) {
Token token = {Token_Identifier};
token.string = count_str;
// HACK(bill): Memory leak
sel.entity = make_entity_constant(a, NULL, token, t_int, make_exact_value_integer(type->Array.count));
return sel;
}
} else if (type->kind == Type_Vector) {
String count_str = make_string("count");
// NOTE(bill): Vectors are not addressable
if (are_strings_equal(field_name, count_str)) {
Token token = {Token_Identifier};
token.string = count_str;
// HACK(bill): Memory leak
sel.entity = make_entity_constant(a, NULL, token, t_int, make_exact_value_integer(type->Vector.count));
return sel;
}
} else if (type->kind == Type_Slice) {
String data_str = make_string("data");
String count_str = make_string("count");
String capacity_str = make_string("capacity");
if (are_strings_equal(field_name, data_str)) {
selection_add_index(&sel, 0);
Token token = {Token_Identifier};
token.string = data_str;
// HACK(bill): Memory leak
sel.entity = make_entity_field(a, NULL, token, make_type_pointer(a, type->Slice.elem), false, 0);
return sel;
} else if (are_strings_equal(field_name, count_str)) {
selection_add_index(&sel, 1);
Token token = {Token_Identifier};
token.string = count_str;
// HACK(bill): Memory leak
sel.entity = make_entity_field(a, NULL, token, t_int, false, 1);
return sel;
} else if (are_strings_equal(field_name, capacity_str)) {
selection_add_index(&sel, 2);
Token token = {Token_Identifier};
token.string = capacity_str;
// HACK(bill): Memory leak
sel.entity = make_entity_field(a, NULL, token, t_int, false, 2);
return sel;
}
}
if (type->kind != Type_Record) {
+13 -3
View File
@@ -330,6 +330,13 @@ void ssa_gen_tree(ssaGen *s) {
case TypeRecord_Struct: {
tag = ssa_add_local_generated(proc, t_type_info_struct);
{
ssaValue *packed = ssa_make_const_bool(a, t->Record.struct_is_packed);
ssaValue *ordered = ssa_make_const_bool(a, t->Record.struct_is_ordered);
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_one32, t_bool_ptr), packed);
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_two32, t_bool_ptr), ordered);
}
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet
@@ -456,9 +463,12 @@ void ssa_gen_tree(ssaGen *s) {
ssaValue *results = ssa_emit_struct_gep(proc, tag, v_one32, t_type_info_ptr_ptr);
ssaValue *variadic = ssa_emit_struct_gep(proc, tag, v_two32, t_bool_ptr);
ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params));
ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results));
if (t->Proc.params) {
ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params));
}
if (t->Proc.results) {
ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results));
}
ssa_emit_store(proc, variadic, ssa_make_const_bool(a, t->Proc.variadic));
// TODO(bill): Type_Info for procedures
+1 -1
View File
@@ -121,7 +121,7 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) {
void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope = false) {
ssa_fprintf(f, "@");
if (!global_scope) {
if (!global_scope && !are_strings_equal(name, make_string("main"))) {
ssa_fprintf(f, ".");
}
ssa_print_escape_string(f, name, true);
+51 -105
View File
@@ -1116,10 +1116,16 @@ ssaValue *ssa_emit_deep_field_gep(ssaProcedure *proc, Type *type, ssaValue *e, S
e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, type));
} break;
case Basic_string:
e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, sel.entity->type));
break;
default:
GB_PANIC("un-gep-able type");
break;
}
} else if (type->kind == Type_Slice) {
e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, sel.entity->type));
} else {
GB_PANIC("un-gep-able type");
}
@@ -1159,10 +1165,16 @@ ssaValue *ssa_emit_deep_field_ev(ssaProcedure *proc, Type *type, ssaValue *e, Se
e = ssa_emit_struct_ev(proc, e, index, type);
} break;
case Basic_string:
e = ssa_emit_struct_ev(proc, e, index, sel.entity->type);
break;
default:
GB_PANIC("un-ev-able type");
break;
}
} else if (type->kind == Type_Slice) {
e = ssa_emit_struct_gep(proc, e, index, make_type_pointer(proc->module->allocator, sel.entity->type));
} else {
GB_PANIC("un-ev-able type");
}
@@ -1194,6 +1206,9 @@ isize ssa_type_info_index(CheckerInfo *info, Type *type) {
}
}
}
if (entry_index < 0) {
gb_printf_err("%s\n", type_to_string(type));
}
GB_ASSERT(entry_index >= 0);
return entry_index;
}
@@ -1599,7 +1614,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
ssaValue *result = ssa_add_local_generated(proc, t_any);
ssaValue *data = NULL;
if (false && value->kind == ssaValue_Instr &&
if (value->kind == ssaValue_Instr &&
value->Instr.kind == ssaInstr_Load) {
// NOTE(bill): Addressable value
data = value->Instr.Load.address;
@@ -1704,37 +1719,16 @@ void ssa_array_bounds_check(ssaProcedure *proc, Token token, ssaValue *index, ss
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
return;
}
ssa_emit_comment(proc, make_string("ArrayBoundsCheck"));
index = ssa_emit_conv(proc, index, t_int);
len = ssa_emit_conv(proc, len, t_int);
Token le = {Token_LtEq};
Token lt = {Token_Lt};
Token cmp_and = {Token_And}; // NOTE(bill): Doesn't need to be logical
ssaValue *c0 = ssa_emit_comp(proc, le, v_zero, index);
ssaValue *c1 = ssa_emit_comp(proc, lt, index, len);
ssaValue *cond = ssa_emit_comp(proc, cmp_and, c0, c1);
ssaBlock *then = ssa_add_block(proc, NULL, make_string("abc.then"));
ssaBlock *done = ssa__make_block(proc, NULL, make_string("abc.done"));
ssa_emit_if(proc, cond, done, then);
proc->curr_block = then;
gbAllocator a = proc->module->allocator;
ssaValue **args = gb_alloc_array(a, ssaValue *, 5);
args[0] = ssa_emit_global_string(proc, token.pos.file);
args[1] = ssa_make_const_int(a, token.pos.line);
args[2] = ssa_make_const_int(a, token.pos.column);
args[3] = index;
args[4] = len;
args[3] = ssa_emit_conv(proc, index, t_int);
args[4] = ssa_emit_conv(proc, len, t_int);
ssa_emit_global_call(proc, "__bounds_check_error", args, 5);
ssa_emit_jump(proc, done);
gb_array_append(proc->blocks, done);
proc->curr_block = done;
}
void ssa_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaValue *high, ssaValue *max, b32 is_substring) {
@@ -1742,43 +1736,20 @@ void ssa_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaV
return;
}
low = ssa_emit_conv(proc, low, t_int);
high = ssa_emit_conv(proc, high, t_int);
max = ssa_emit_conv(proc, max, t_int);
Token le = {Token_LtEq};
Token cmp_and = {Token_And}; // NOTE(bill): Doesn't need to be logical
ssaValue *c0 = ssa_emit_comp(proc, le, v_zero, low);
ssaValue *c1 = ssa_emit_comp(proc, le, low, high);
ssaValue *c2 = ssa_emit_comp(proc, le, high, max);
ssaValue *cond = NULL;
cond = ssa_emit_comp(proc, cmp_and, c0, c1);
cond = ssa_emit_comp(proc, cmp_and, cond, c2);
ssaBlock *then = ssa_add_block(proc, NULL, make_string("seb.then"));
ssaBlock *done = ssa__make_block(proc, NULL, make_string("seb.done"));
ssa_emit_if(proc, cond, done, then);
proc->curr_block = then;
gbAllocator a = proc->module->allocator;
ssaValue **args = gb_alloc_array(a, ssaValue *, 6);
args[0] = ssa_emit_global_string(proc, token.pos.file);
args[1] = ssa_make_const_int(a, token.pos.line);
args[2] = ssa_make_const_int(a, token.pos.column);
args[3] = low;
args[4] = high;
args[5] = max;
args[3] = ssa_emit_conv(proc, low, t_int);
args[4] = ssa_emit_conv(proc, high, t_int);
args[5] = ssa_emit_conv(proc, max, t_int);
if (!is_substring) {
ssa_emit_global_call(proc, "__slice_expr_error", args, 6);
} else {
ssa_emit_global_call(proc, "__substring_expr_error", args, 5);
}
ssa_emit_jump(proc, done);
gb_array_append(proc->blocks, done);
proc->curr_block = done;
}
@@ -2109,26 +2080,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
return ssa_emit_load(proc, slice);
} break;
case BuiltinProc_delete: {
ssa_emit_comment(proc, make_string("delete"));
// delete :: proc(ptr: ^Type)
// delete :: proc(slice: []Type)
gbAllocator allocator = proc->module->allocator;
ssaValue *value = ssa_build_expr(proc, ce->args[0]);
if (is_type_slice(ssa_type(value))) {
Type *etp = get_base_type(ssa_type(value));
etp = make_type_pointer(allocator, etp->Slice.elem);
value = ssa_emit(proc, ssa_make_instr_extract_value(proc, value, 0, etp));
}
ssaValue **args = gb_alloc_array(allocator, ssaValue *, 1);
args[0] = ssa_emit_conv(proc, value, t_rawptr, true);
return ssa_emit_global_call(proc, "dealloc", args, 1);
} break;
case BuiltinProc_assert: {
ssa_emit_comment(proc, make_string("assert"));
ssaValue *cond = ssa_build_expr(proc, ce->args[0]);
@@ -2174,25 +2125,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
return NULL;
} break;
case BuiltinProc_len: {
ssa_emit_comment(proc, make_string("len"));
// len :: proc(v: Type) -> int
// NOTE(bill): len of an array is a constant expression
ssaValue *v = ssa_build_expr(proc, ce->args[0]);
Type *t = get_base_type(ssa_type(v));
if (t == t_string)
return ssa_string_len(proc, v);
else if (t->kind == Type_Slice)
return ssa_slice_len(proc, v);
} break;
case BuiltinProc_cap: {
ssa_emit_comment(proc, make_string("cap"));
// cap :: proc(v: Type) -> int
// NOTE(bill): cap of an array is a constant expression
ssaValue *v = ssa_build_expr(proc, ce->args[0]);
Type *t = get_base_type(ssa_type(v));
return ssa_slice_cap(proc, v);
} break;
case BuiltinProc_copy: {
ssa_emit_comment(proc, make_string("copy"));
// copy :: proc(dst, src: []Type) -> int
@@ -3393,9 +3325,15 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
gb_array_append(proc->blocks, body);
}
proc->curr_block = body;
// TODO(bill): Handle fallthrough scope exit correctly
proc->scope_index++;
ssa_push_target_list(proc, done, NULL, fall);
ssa_build_stmt_list(proc, cc->stmts);
ssa_emit_defer_stmts(proc, ssaDefer_Default, body);
ssa_pop_target_list(proc);
proc->scope_index--;
ssa_emit_jump(proc, done);
proc->curr_block = next_cond;
}
@@ -3404,9 +3342,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
ssa_emit_jump(proc, default_block);
gb_array_append(proc->blocks, default_block);
proc->curr_block = default_block;
// TODO(bill): Handle fallthrough scope exit correctly
proc->scope_index++;
ssa_push_target_list(proc, done, NULL, default_fall);
ssa_build_stmt_list(proc, default_stmts);
ssa_emit_defer_stmts(proc, ssaDefer_Default, default_block);
ssa_pop_target_list(proc);
proc->scope_index--;
}
ssa_emit_jump(proc, done);
@@ -3490,9 +3433,14 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
gb_array_append(proc->blocks, body);
proc->curr_block = body;
proc->scope_index++;
ssa_push_target_list(proc, done, NULL, NULL);
ssa_build_stmt_list(proc, cc->stmts);
ssa_emit_defer_stmts(proc, ssaDefer_Default, body);
ssa_pop_target_list(proc);
proc->scope_index--;
ssa_emit_jump(proc, done);
proc->curr_block = next_cond;
}
@@ -3501,9 +3449,13 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
ssa_emit_jump(proc, default_block);
gb_array_append(proc->blocks, default_block);
proc->curr_block = default_block;
proc->scope_index++;
ssa_push_target_list(proc, done, NULL, NULL);
ssa_build_stmt_list(proc, default_stmts);
ssa_emit_defer_stmts(proc, ssaDefer_Default, default_block);
ssa_pop_target_list(proc);
proc->scope_index--;
}
ssa_emit_jump(proc, done);
@@ -3513,24 +3465,18 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
case_ast_node(bs, BranchStmt, node);
ssaBlock *block = NULL;
#define branch_case(x) case GB_JOIN2(Token_, x): \
for (ssaTargetList *t = proc->target_list; t != NULL && block == NULL; t = t->prev) { \
block = GB_JOIN3(t->, x, _); \
} break
switch (bs->token.kind) {
case Token_break: {
for (ssaTargetList *t = proc->target_list; t != NULL && block == NULL; t = t->prev) {
block = t->break_;
}
} break;
case Token_continue: {
for (ssaTargetList *t = proc->target_list; t != NULL && block == NULL; t = t->prev) {
block = t->continue_;
}
} break;
case Token_fallthrough: {
for (ssaTargetList *t = proc->target_list; t != NULL && block == NULL; t = t->prev) {
block = t->fallthrough_;
}
} break;
branch_case(break);
branch_case(continue);
branch_case(fallthrough);
}
if (block != NULL && bs->token.kind != Token_fallthrough) {
// TODO(bill): Handle fallthrough scope exit correctly
// if (block != NULL && bs->token.kind != Token_fallthrough) {
if (block != NULL) {
ssa_emit_defer_stmts(proc, ssaDefer_Branch, block);
}
switch (bs->token.kind) {
+30 -15
View File
@@ -64,6 +64,7 @@ enum ProcTag {
ProcTag_foreign = GB_BIT(2),
ProcTag_inline = GB_BIT(3),
ProcTag_no_inline = GB_BIT(4),
ProcTag_no_context = GB_BIT(5),
};
enum VarDeclTag {
@@ -1173,14 +1174,16 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
next_token(f);
}
} else if (are_strings_equal(tag_name, make_string("inline"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_inline, tag_name);
} else if (are_strings_equal(tag_name, make_string("no_inline"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_no_inline, tag_name);
} else if (are_strings_equal(tag_name, make_string("bounds_check"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_bounds_check, tag_name);
} else if (are_strings_equal(tag_name, make_string("no_bounds_check"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_no_bounds_check, tag_name);
} else if (are_strings_equal(tag_name, make_string("inline"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_inline, tag_name);
} else if (are_strings_equal(tag_name, make_string("no_inline"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_no_inline, tag_name);
} else if (are_strings_equal(tag_name, make_string("no_context"))) {
check_proc_add_tag(f, tag_expr, tags, ProcTag_no_context, tag_name);
} else {
ast_file_err(f, ast_node_token(tag_expr), "Unknown procedure tag");
}
@@ -1490,17 +1493,16 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
}
switch (op.kind) {
// case Token_DoublePrime: {
// AstNode *proc = parse_identifier(f);
// AstNode *right = parse_binary_expr(f, false, prec+1);
// expression->next = right;
// gbArray(AstNode *) args;
// gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
// gb_array_append(args, expression);
// gb_array_append(args, right);
// expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
// continue;
// } break;
case Token_DoublePrime: {
AstNode *proc = parse_identifier(f);
AstNode *right = parse_binary_expr(f, false, prec+1);
gbArray(AstNode *) args;
gb_array_init_reserve(args, gb_arena_allocator(&f->arena), 2);
gb_array_append(args, expression);
gb_array_append(args, right);
expression = make_call_expr(f, proc, args, op, ast_node_token(right), empty_token);
continue;
} break;
case Token_as:
case Token_transmute:
@@ -2074,6 +2076,18 @@ AstNode *parse_decl(AstFile *f, AstNodeArray names) {
AstNodeArray values = NULL;
AstNode *type = NULL;
gb_for_array(i, names) {
AstNode *name = names[i];
if (name->kind == AstNode_Ident) {
String n = name->Ident.string;
// NOTE(bill): Check for reserved identifiers
if (are_strings_equal(n, make_string("context"))) {
ast_file_err(f, ast_node_token(name), "`context` is a reserved identifier");
break;
}
}
}
if (allow_token(f, Token_Colon)) {
if (!allow_token(f, Token_type)) {
type = parse_identifier_or_type(f);
@@ -2449,6 +2463,7 @@ AstNode *parse_stmt(AstFile *f) {
case Token_Rune:
case Token_String:
case Token_OpenParen:
case Token_proc:
// Unary Operators
case Token_Add:
case Token_Sub: