Compound Literals - struct, array, slice, vector

This commit is contained in:
gingerBill
2016-08-12 17:21:34 +01:00
parent 84f2bcd885
commit c10b46af9f
9 changed files with 356 additions and 87 deletions
+111 -11
View File
@@ -4,6 +4,7 @@
declare void @llvm.memmove.p0i8.p0i8.i64(i8*, i8*, i64, i32, i1)
%main.Vec2 = type <2 x float>
define void @exec(i64 ()* %p) {
"entry - 0":
%0 = alloca i64 ()*, align 8 ; p
@@ -18,21 +19,119 @@ define void @exec(i64 ()* %p) {
define void @main() {
"entry - 0":
%0 = alloca i8, align 1 ; a
store i8 zeroinitializer, i8* %0
store i8 123, i8* %0
%1 = load i8, i8* %0
%2 = zext i8 %1 to i64
call void @print_int(i64 %2)
%0 = alloca i64, align 8 ; i
store i64 zeroinitializer, i64* %0
store i64 123, i64* %0
%1 = load i64, i64* %0
call void @print_int(i64 %1)
call void @print_rune(i32 128149)
call void @print_rune(i32 10)
call void @exec(i64 ()* @main$cool_beans)
%2 = alloca %main.Vec2, align 2 ; v
store %main.Vec2 zeroinitializer, %main.Vec2* %2
%3 = alloca %main.Vec2, align 2
store %main.Vec2 zeroinitializer, %main.Vec2* %3
%4 = getelementptr inbounds %main.Vec2, %main.Vec2* %3, i64 0, i32 0
store float 0x3ff0000000000000, float* %4
%5 = getelementptr inbounds %main.Vec2, %main.Vec2* %3, i64 0, i32 1
store float 0x4000000000000000, float* %5
%6 = load %main.Vec2, %main.Vec2* %3
store %main.Vec2 %6, %main.Vec2* %2
%7 = alloca [4 x i64], align 8 ; a
store [4 x i64] zeroinitializer, [4 x i64]* %7
%8 = alloca [4 x i64], align 8
store [4 x i64] zeroinitializer, [4 x i64]* %8
%9 = load i64, i64* %0
%10 = getelementptr inbounds [4 x i64], [4 x i64]* %8, i64 0, i32 0
store i64 %9, i64* %10
%11 = getelementptr inbounds [4 x i64], [4 x i64]* %8, i64 0, i32 1
store i64 2, i64* %11
%12 = getelementptr inbounds [4 x i64], [4 x i64]* %8, i64 0, i32 2
store i64 3, i64* %12
%13 = getelementptr inbounds [4 x i64], [4 x i64]* %8, i64 0, i32 3
store i64 7, i64* %13
%14 = load [4 x i64], [4 x i64]* %8
store [4 x i64] %14, [4 x i64]* %7
%15 = alloca [4 x i64], align 8 ; e
store [4 x i64] zeroinitializer, [4 x i64]* %15
%16 = alloca [4 x i64], align 8
store [4 x i64] zeroinitializer, [4 x i64]* %16
%17 = load i64, i64* %0
%18 = getelementptr inbounds [4 x i64], [4 x i64]* %16, i64 0, i32 0
store i64 %17, i64* %18
%19 = getelementptr inbounds [4 x i64], [4 x i64]* %16, i64 0, i32 1
store i64 2, i64* %19
%20 = getelementptr inbounds [4 x i64], [4 x i64]* %16, i64 0, i32 2
store i64 3, i64* %20
%21 = getelementptr inbounds [4 x i64], [4 x i64]* %16, i64 0, i32 3
store i64 7, i64* %21
%22 = load [4 x i64], [4 x i64]* %16
store [4 x i64] %22, [4 x i64]* %15
%23 = alloca {i64*, i64, i64}, align 8 ; s
store {i64*, i64, i64} zeroinitializer, {i64*, i64, i64}* %23
%24 = alloca {i64*, i64, i64}, align 8
store {i64*, i64, i64} zeroinitializer, {i64*, i64, i64}* %24
%25 = alloca [4 x i64], align 8
store [4 x i64] zeroinitializer, [4 x i64]* %25
%26 = load i64, i64* %0
%27 = getelementptr inbounds [4 x i64], [4 x i64]* %25, i64 0, i32 0
store i64 %26, i64* %27
%28 = getelementptr inbounds [4 x i64], [4 x i64]* %25, i64 0, i32 1
store i64 2, i64* %28
%29 = getelementptr inbounds [4 x i64], [4 x i64]* %25, i64 0, i32 2
store i64 3, i64* %29
%30 = getelementptr inbounds [4 x i64], [4 x i64]* %25, i64 0, i32 3
store i64 7, i64* %30
%31 = getelementptr inbounds [4 x i64], [4 x i64]* %25, i64 0, i32 0
%32 = getelementptr inbounds {i64*, i64, i64}, {i64*, i64, i64}* %24, i64 0, i32 0
store i64* %31, i64** %32
%33 = getelementptr inbounds {i64*, i64, i64}, {i64*, i64, i64}* %24, i64 0, i32 1
store i64 4, i64* %33
%34 = getelementptr inbounds {i64*, i64, i64}, {i64*, i64, i64}* %24, i64 0, i32 2
store i64 4, i64* %34
%35 = load {i64*, i64, i64}, {i64*, i64, i64}* %24
store {i64*, i64, i64} %35, {i64*, i64, i64}* %23
%36 = alloca i64, align 8 ; i
store i64 zeroinitializer, i64* %36
store i64 0, i64* %36
br label %"for.loop - 2"
"for.body - 1":
%37 = getelementptr inbounds [4 x i64], [4 x i64]* %7, i64 0, i64 0
%38 = load i64, i64* %36
%39 = getelementptr i64, i64* %37, i64 %38
%40 = load i64, i64* %39
call void @print_int(i64 %40)
%41 = getelementptr inbounds [2 x i8], [2 x i8]* @.str0, i64 0, i64 0
%42 = alloca %.string, align 8
store %.string zeroinitializer, %.string* %42
%43 = getelementptr inbounds %.string, %.string* %42, i64 0, i32 0
%44 = getelementptr inbounds %.string, %.string* %42, i64 0, i32 1
store i8* %41, i8** %43
store i64 2, i64* %44
%45 = load %.string, %.string* %42
call void @print_string(%.string %45)
br label %"for.post - 3"
"for.loop - 2":
%46 = load i64, i64* %36
%47 = icmp slt i64 %46, 4
br i1 %47, label %"for.body - 1", label %"for.done - 4"
"for.post - 3":
%48 = load i64, i64* %36
%49 = add i64 %48, 1
store i64 %49, i64* %36
br label %"for.loop - 2"
"for.done - 4":
call void @print_rune(i32 10)
call void @exec(i64 ()* @main$0)
ret void
}
define i64 @main$cool_beans() {
define i64 @main$0() {
"entry - 0":
%0 = alloca i64, align 8 ; a
%0 = alloca i64, align 8 ; i
store i64 zeroinitializer, i64* %0
store i64 1337, i64* %0
call void @print_rune(i32 128149)
@@ -411,7 +510,7 @@ define void @print_int_base(i64 %i, i64 %base) {
%16 = getelementptr inbounds [21 x i8], [21 x i8]* %2, i64 0, i64 0
%17 = load i64, i64* %3
%18 = getelementptr i8, i8* %16, i64 %17
%19 = getelementptr inbounds [64 x i8], [64 x i8]* @.str0, i64 0, i64 0
%19 = getelementptr inbounds [64 x i8], [64 x i8]* @.str1, i64 0, i64 0
%20 = load i64, i64* %1
%21 = load i64, i64* %0
%22 = srem i64 %21, %20
@@ -494,4 +593,5 @@ define void @print_int_base(i64 %i, i64 %base) {
ret void
}
@.str0 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
@.str0 = global [2 x i8] c"\2C\20"
@.str1 = global [64 x i8] c"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\40$"
+20 -7
View File
@@ -2,24 +2,37 @@ import "basic"
TWO_HEARTS :: '💕';
exec :: proc(p : proc() -> int) {
print_int(p());
print_rune('\n');
}
main :: proc() {
a : u8 = 123;
print_int(cast(int)a);
i := 123;
print_int(i);
print_rune(TWO_HEARTS);
print_rune('\n');
cool_beans :: proc() -> int {
a : int = 1337;
type Vec2: {2}f32;
v := Vec2{1, 2};
a := [4] int{i, 2, 3, 7};
e := [..]int{i, 2, 3, 7};
s := [] int{i, 2, 3, 7};
for i := 0; i < len(a); i++ {
print_int(a[i]);
print_string(", ");
}
print_rune('\n');
exec(proc() -> int {
i : int = 1337;
print_rune('💕');
print_rune('\n');
return a;
}
exec(cool_beans);
return i;
});
}
/*
+26 -5
View File
@@ -18,10 +18,6 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
GB_ASSERT(node->kind == AstNode_StructType);
GB_ASSERT(struct_type->kind == Type_Structure);
ast_node(st, StructType, node);
if (st->field_count == 0) {
error(&c->error_collector, ast_node_token(node), "Empty struct{} definition");
return;
}
Map<Entity *> entity_map = {};
map_init(&entity_map, gb_heap_allocator());
@@ -1759,8 +1755,21 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
case_ast_node(cl, CompoundLit, node);
Type *type = type_hint;
b32 ellipsis_array = false;
if (cl->type != NULL) {
type = check_type(c, cl->type);
type = NULL;
// [..]Type
if (cl->type->kind == AstNode_ArrayType && cl->type->ArrayType.count != NULL) {
if (cl->type->ArrayType.count->kind == AstNode_Ellipsis) {
type = make_type_array(c->allocator, check_type(c, cl->type->ArrayType.elem), -1);
ellipsis_array = true;
}
}
if (type == NULL) {
type = check_type(c, cl->type);
}
}
if (type == NULL) {
@@ -1798,12 +1807,16 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
case Type_Slice:
case Type_Array:
case Type_Vector:
{
Type *elem_type = NULL;
String context_name = {};
if (t->kind == Type_Slice) {
elem_type = t->slice.elem;
context_name = make_string("slice literal");
} else if (t->kind == Type_Vector) {
elem_type = t->vector.elem;
context_name = make_string("vector literal");
} else {
elem_type = t->array.elem;
context_name = make_string("array literal");
@@ -1826,6 +1839,10 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
}
if (max < index)
max = index;
if (t->kind == Type_Array && ellipsis_array) {
t->array.count = max;
}
} break;
default: {
@@ -2277,6 +2294,10 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, ce->expr);
case_end;
case_ast_node(e, Ellipsis, node);
str = gb_string_appendc(str, "..");
case_end;
case_ast_node(pt, PointerType, node);
str = gb_string_appendc(str, "^");
str = write_expr_to_string(str, pt->type);
+2 -1
View File
@@ -60,7 +60,8 @@ void ssa_gen_code(ssaGen *s) {
switch (e->kind) {
case Entity_TypeName: {
ssaValue *t = ssa_make_value_type_name(a, e);
ssaValue *t = ssa_make_value_type_name(a, e->token.string, e->type);
map_set(&m->values, hash_pointer(e), t);
map_set(&m->members, hash_string(name), t);
} break;
+24 -8
View File
@@ -184,6 +184,12 @@ void ssa_print_type(gbFile *f, BaseTypeSizes s, Type *t) {
}
void ssa_print_exact_value(gbFile *f, ssaModule *m, ExactValue value, Type *type) {
if (is_type_float(type)) {
value = exact_value_to_float(value);
} else if (is_type_integer(type)) {
value = exact_value_to_integer(value);
}
switch (value.kind) {
case ExactValue_Bool:
ssa_fprintf(f, (value.value_bool ? "true" : "false"));
@@ -238,7 +244,7 @@ void ssa_print_value(gbFile *f, ssaModule *m, ssaValue *value, Type *type_hint)
ssa_print_exact_value(f, m, value->constant.value, type_hint);
break;
case ssaValue_TypeName:
ssa_print_encoded_local(f, value->type_name.entity->token.string);
ssa_print_encoded_local(f, value->type_name.name);
break;
case ssaValue_Global:
ssa_print_encoded_global(f, value->global.entity->token.string);
@@ -592,16 +598,21 @@ void ssa_print_proc(gbFile *f, ssaModule *m, ssaProcedure *proc) {
ssa_fprintf(f, "}\n\n");
}
gb_for_array(i, proc->anon_procs) {
ssa_print_proc(f, m, proc->anon_procs[i]);
}
gb_for_array(i, proc->nested_procs) {
ssa_print_proc(f, m, proc->nested_procs[i]);
gb_for_array(i, proc->children) {
ssa_print_proc(f, m, proc->children[i]);
}
}
void ssa_print_type_name(gbFile *f, ssaModule *m, ssaValue *v) {
GB_ASSERT(v->kind == ssaValue_TypeName);
ssa_print_encoded_local(f, v->type_name.name);
ssa_fprintf(f, " = type ");
ssa_print_type(f, m->sizes, get_base_type(v->type_name.type));
ssa_fprintf(f, "\n");
}
void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
if (m->layout.len > 0) {
if (m->layout.len > 0) {
ssa_fprintf(f, "target datalayout = %.*s\n", LIT(m->layout));
}
@@ -618,12 +629,17 @@ if (m->layout.len > 0) {
ssa_print_type(f, m->sizes, t_int);
ssa_fprintf(f, ", i32, i1)\n\n");
gb_for_array(i, m->nested_type_names) {
ssaValue *v = m->nested_type_names[i];
ssa_print_type_name(f, m, v);
}
gb_for_array(member_index, m->members.entries) {
auto *entry = &m->members.entries[member_index];
ssaValue *v = entry->value;
switch (v->kind) {
case ssaValue_TypeName: {
ssa_print_encoded_local(f, v->type_name.entity->token.string);
ssa_print_encoded_local(f, v->type_name.name);
ssa_fprintf(f, " = type ");
ssa_print_type(f, m->sizes, get_base_type(v->type_name.type));
ssa_fprintf(f, "\n");
+138 -28
View File
@@ -14,6 +14,7 @@ struct ssaModule {
Map<ssaValue *> values; // Key: Entity *
Map<ssaValue *> members; // Key: String
gbArray(ssaValue *) nested_type_names; // ssaValue_TypeName
i32 global_string_index;
};
@@ -38,6 +39,8 @@ struct ssaTargetList {
struct ssaProcedure {
ssaProcedure *parent;
gbArray(ssaProcedure *) children;
ssaModule * module;
String name;
Type * type;
@@ -47,9 +50,6 @@ struct ssaProcedure {
gbArray(ssaBlock *) blocks;
ssaBlock * curr_block;
ssaTargetList * target_list;
gbArray(ssaProcedure *) anon_procs;
gbArray(ssaProcedure *) nested_procs;
};
@@ -208,7 +208,7 @@ struct ssaValue {
ExactValue value;
} constant;
struct {
Entity *entity;
String name;
Type * type;
} type_name;
struct {
@@ -276,11 +276,13 @@ void ssa_module_init(ssaModule *m, Checker *c) {
map_init(&m->values, m->allocator);
map_init(&m->members, m->allocator);
gb_array_init(m->nested_type_names, m->allocator);
}
void ssa_module_destroy(ssaModule *m) {
map_destroy(&m->values);
map_destroy(&m->members);
gb_array_free(m->nested_type_names);
gb_arena_free(&m->arena);
}
@@ -416,10 +418,10 @@ ssaValue *ssa_alloc_instr(gbAllocator a, ssaInstrKind kind) {
return v;
}
ssaValue *ssa_make_value_type_name(gbAllocator a, Entity *e) {
ssaValue *ssa_make_value_type_name(gbAllocator a, String name, Type *type) {
ssaValue *v = ssa_alloc_value(a, ssaValue_TypeName);
v->type_name.entity = e;
v->type_name.type = e->type;
v->type_name.name = name;
v->type_name.type = type;
return v;
}
@@ -1146,8 +1148,17 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
return value;
if (value->kind == ssaValue_Constant) {
if (dst->kind == Type_Basic)
return ssa_make_value_constant(proc->module->allocator, t, value->constant.value);
if (dst->kind == Type_Basic) {
ExactValue ev = value->constant.value;
if (is_type_float(dst)) {
ev = exact_value_to_float(ev);
} else if (is_type_string(dst)) {
//
} else if (is_type_integer(dst)) {
ev = exact_value_to_integer(ev);
}
return ssa_make_value_constant(proc->module->allocator, t, ev);
}
}
// integer -> integer
@@ -1337,34 +1348,113 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case_end;
case_ast_node(pl, ProcLit, expr);
if (proc->anon_procs == NULL) {
// TODO(bill): Cleanup
gb_array_init(proc->anon_procs, gb_heap_allocator());
if (proc->children == NULL) {
gb_array_init(proc->children, gb_heap_allocator());
}
// NOTE(bill): Generate a new name
// parent$count
isize name_len = proc->name.len + 1 + 8 + 1;
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%d", LIT(proc->name), cast(i32)gb_array_count(proc->anon_procs));
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%d", LIT(proc->name), cast(i32)gb_array_count(proc->children));
String name = make_string(name_text, name_len-1);
// auto **found = map_get(&proc->module->info->definitions,
// hash_pointer(expr))
Type *type = type_of_expr(proc->module->info, expr);
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
proc->module, type, pl->type, pl->body, name);
ssaProcedure *np = &value->proc;
gb_array_append(proc->anon_procs, np);
gb_array_append(proc->children, &value->proc);
ssa_build_proc(value, proc);
return value; // TODO(bill): Is this correct?
return value;
case_end;
case_ast_node(pl, CompoundLit, expr);
GB_PANIC("TODO(bill): ssa_build_single_expr CompoundLit");
case_ast_node(cl, CompoundLit, expr);
Type *type = type_of_expr(proc->module->info, expr);
Type *base_type = get_base_type(type);
ssaValue *v = ssa_add_local_generated(proc, type);
Type *et = NULL;
switch (base_type->kind) {
case Type_Vector: et = base_type->vector.elem; break;
case Type_Array: et = base_type->array.elem; break;
case Type_Slice: et = base_type->slice.elem; break;
}
switch (base_type->kind) {
default: GB_PANIC("Unknown CompoundLit type: %s", type_to_string(type)); break;
case Type_Structure: {
auto *st = &base_type->structure;
isize index = 0;
for (AstNode *elem = cl->elem_list;
elem != NULL;
elem = elem->next) {
ssaValue *field_expr = ssa_build_expr(proc, elem);
Type *t = ssa_value_type(field_expr);
if (t->kind != Type_Tuple) {
Entity *field = st->fields[index];
Type *ft = field->type;
ssaValue *fv = ssa_emit_conv(proc, field_expr, ft);
ssaValue *gep = ssa_emit_struct_gep(proc, v, index, ft);
ssa_emit_store(proc, gep, fv);
index++;
} else {
GB_PANIC("TODO(bill): tuples in struct literals");
}
}
} break;
case Type_Vector:
case Type_Array: {
isize index = 0;
for (AstNode *elem = cl->elem_list;
elem != NULL;
elem = elem->next) {
ssaValue *field_expr = ssa_build_expr(proc, elem);
Type *t = ssa_value_type(field_expr);
if (t->kind != Type_Tuple) {
ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
ssaValue *gep = ssa_emit_struct_gep(proc, v, index, et);
ssa_emit_store(proc, gep, ev);
index++;
} else {
GB_PANIC("TODO(bill): tuples in array literals");
}
}
} break;
case Type_Slice: {
i64 count = cl->elem_count;
ssaValue *array = ssa_add_local_generated(proc, make_type_array(proc->module->allocator, et, count));
isize index = 0;
for (AstNode *elem = cl->elem_list;
elem != NULL;
elem = elem->next) {
ssaValue *field_expr = ssa_build_expr(proc, elem);
Type *t = ssa_value_type(field_expr);
if (t->kind != Type_Tuple) {
ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
ssaValue *gep = ssa_emit_struct_gep(proc, array, index, et);
ssa_emit_store(proc, gep, ev);
index++;
} else {
GB_PANIC("TODO(bill): tuples in array literals");
}
}
ssaValue *elem = ssa_emit_struct_gep(proc, array, v_zero32,
make_type_pointer(proc->module->allocator, et));
ssaValue *len = ssa_array_len(proc, array);
ssaValue *gep = NULL;
gep = ssa_emit_struct_gep(proc, v, v_zero32, ssa_value_type(elem));
ssa_emit_store(proc, gep, elem);
gep = ssa_emit_struct_gep(proc, v, v_one32, t_int);
ssa_emit_store(proc, gep, len);
gep = ssa_emit_struct_gep(proc, v, v_two32, t_int);
ssa_emit_store(proc, gep, len);
} break;
}
return ssa_emit_load(proc, v);
case_end;
case_ast_node(ce, CastExpr, expr);
@@ -1768,9 +1858,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
case_end;
case_ast_node(pd, ProcDecl, node);
if (proc->nested_procs == NULL) {
// TODO(bill): Cleanup
gb_array_init(proc->nested_procs, gb_heap_allocator());
if (proc->children == NULL) {
gb_array_init(proc->children, gb_heap_allocator());
}
// NOTE(bill): Generate a new name
// parent$name
@@ -1780,15 +1869,36 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s$%.*s", LIT(proc->name), LIT(pd_name));
String name = make_string(name_text, name_len-1);
Entity *e = *map_get(&proc->module->info->definitions, hash_pointer(pd->name));
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(pd->name));
GB_ASSERT(found != NULL);
Entity *e = *found;
ssaValue *value = ssa_make_value_procedure(proc->module->allocator,
proc->module, e->type, pd->type, pd->body, name);
ssaProcedure *np = &value->proc;
gb_array_append(proc->nested_procs, np);
ssa_module_add_value(proc->module, e, value);
gb_array_append(proc->children, &value->proc);
ssa_build_proc(value, proc);
case_end;
map_set(&proc->module->values, hash_pointer(e), value);
case_ast_node(td, TypeDecl, node);
// NOTE(bill): Generate a new name
// parent_proc.name
String td_name = td->name->Ident.token.string;
isize name_len = proc->name.len + 1 + td_name.len + 1;
u8 *name_text = gb_alloc_array(proc->module->allocator, u8, name_len);
name_len = gb_snprintf(cast(char *)name_text, name_len, "%.*s.%.*s", LIT(proc->name), LIT(td_name));
String name = make_string(name_text, name_len-1);
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(td->name));
GB_ASSERT(found != NULL);
Entity *e = *found;
ssaValue *value = ssa_make_value_type_name(proc->module->allocator,
name, e->type);
// HACK(bill): Override name of type so printer prints it correctly
e->type->named.name = name;
ssa_module_add_value(proc->module, e, value);
gb_array_append(proc->module->nested_type_names, value);
case_end;
case_ast_node(ids, IncDecStmt, node);
+32 -18
View File
@@ -2,7 +2,6 @@ struct AstNode;
struct Type;
struct AstScope;
enum ParseFileError {
ParseFile_None,
@@ -110,6 +109,7 @@ AST_NODE_KIND(_ExprBegin, struct{}) \
AstNode *low, *high, *max; \
b32 triple_indexed; \
}) \
AST_NODE_KIND(Ellipsis, struct { Token token; }) \
AST_NODE_KIND(_ExprEnd, struct{}) \
AST_NODE_KIND(_StmtBegin, struct{}) \
AST_NODE_KIND(BadStmt, struct { Token begin, end; }) \
@@ -164,7 +164,6 @@ AST_NODE_KIND(_DeclBegin, struct{}) \
isize name_count, value_count; \
}) \
AST_NODE_KIND(ProcDecl, struct { \
DeclKind kind; \
AstNode *name; \
AstNode *type; \
AstNode *body; \
@@ -295,6 +294,8 @@ Token ast_node_token(AstNode *node) {
return node->IndexExpr.open;
case AstNode_SliceExpr:
return node->SliceExpr.open;
case AstNode_Ellipsis:
return node->Ellipsis.token;
case AstNode_CastExpr:
return node->CastExpr.token;
case AstNode_DerefExpr:
@@ -553,6 +554,11 @@ gb_inline AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) {
}
gb_inline AstNode *make_ellipsis(AstFile *f, Token token) {
AstNode *result = make_node(f, AstNode_Ellipsis);
result->Ellipsis.token = token;
return result;
}
gb_inline AstNode *make_basic_lit(AstFile *f, Token basic_lit) {
AstNode *result = make_node(f, AstNode_BasicLit);
result->BasicLit = basic_lit;
@@ -678,7 +684,7 @@ gb_inline AstNode *make_bad_decl(AstFile *f, Token begin, Token end) {
return result;
}
gb_inline AstNode *make_variable_decl(AstFile *f, DeclKind kind, AstNode *name_list, isize name_count, AstNode *type, AstNode *value_list, isize value_count) {
gb_inline AstNode *make_var_decl(AstFile *f, DeclKind kind, AstNode *name_list, isize name_count, AstNode *type, AstNode *value_list, isize value_count) {
AstNode *result = make_node(f, AstNode_VarDecl);
result->VarDecl.kind = kind;
result->VarDecl.name_list = name_list;
@@ -707,9 +713,8 @@ gb_inline AstNode *make_proc_type(AstFile *f, Token token, AstNode *param_list,
return result;
}
gb_inline AstNode *make_procedure_decl(AstFile *f, DeclKind kind, AstNode *name, AstNode *proc_type, AstNode *body, AstNode *tag_list, isize tag_count) {
gb_inline AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, AstNode *tag_list, isize tag_count) {
AstNode *result = make_node(f, AstNode_ProcDecl);
result->ProcDecl.kind = kind;
result->ProcDecl.name = name;
result->ProcDecl.type = proc_type;
result->ProcDecl.body = body;
@@ -1169,7 +1174,6 @@ AstNode *parse_atom_expr(AstFile *f, b32 lhs) {
case Token_OpenBrace: {
if (is_literal_type(operand) && f->expr_level >= 0) {
gb_printf_err("here\n");
if (lhs) {
// TODO(bill): Handle this
}
@@ -1474,8 +1478,12 @@ AstNode *parse_identifier_or_type(AstFile *f) {
Token token = expect_token(f, Token_OpenBracket);
AstNode *count_expr = NULL;
if (f->cursor[0].kind != Token_CloseBracket)
if (f->cursor[0].kind == Token_Ellipsis) {
count_expr = make_ellipsis(f, f->cursor[0]);
next_token(f);
} else if (f->cursor[0].kind != Token_CloseBracket) {
count_expr = parse_expr(f, false);
}
expect_token(f, Token_CloseBracket);
f->expr_level--;
return make_array_type(f, token, count_expr, parse_type(f));
@@ -1596,7 +1604,7 @@ AstNode *parse_body(AstFile *f, AstScope *scope) {
return make_block_stmt(f, statement_list, statement_list_count, open, close);
}
AstNode *parse_procedure_decl(AstFile *f, Token proc_token, AstNode *name, DeclKind kind) {
AstNode *parse_proc_decl(AstFile *f, Token proc_token, AstNode *name) {
AstNode *param_list = NULL;
AstNode *result_list = NULL;
isize param_count = 0;
@@ -1621,7 +1629,7 @@ AstNode *parse_procedure_decl(AstFile *f, Token proc_token, AstNode *name, DeclK
close_ast_scope(f);
AstNode *proc_type = make_proc_type(f, proc_token, param_list, param_count, result_list, result_count);
return make_procedure_decl(f, kind, name, proc_type, body, tag_list, tag_count);
return make_proc_decl(f, name, proc_type, body, tag_list, tag_count);
}
AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) {
@@ -1642,7 +1650,9 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) {
declaration_kind = Declaration_Immutable;
next_token(f);
if (f->cursor[0].kind == Token_proc) { // NOTE(bill): Procedure declarations
if (f->cursor[0].kind == Token_proc &&
declaration_kind == Declaration_Immutable) {
// NOTE(bill): Procedure declarations
Token proc_token = f->cursor[0];
AstNode *name = name_list;
if (name_count != 1) {
@@ -1650,9 +1660,9 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) {
return make_bad_decl(f, name->Ident.token, proc_token);
}
AstNode *procedure_decl = parse_procedure_decl(f, proc_token, name, declaration_kind);
add_ast_entity(f, f->curr_scope, procedure_decl, name_list);
return procedure_decl;
AstNode *proc_decl = parse_proc_decl(f, proc_token, name);
add_ast_entity(f, f->curr_scope, proc_decl, name_list);
return proc_decl;
} else {
value_list = parse_rhs_expr_list(f, &value_count);
@@ -1684,9 +1694,9 @@ AstNode *parse_decl(AstFile *f, AstNode *name_list, isize name_count) {
return make_bad_decl(f, begin, f->cursor[0]);
}
AstNode *variable_decl = make_variable_decl(f, declaration_kind, name_list, name_count, type, value_list, value_count);
add_ast_entity(f, f->curr_scope, variable_decl, name_list);
return variable_decl;
AstNode *var_decl = make_var_decl(f, declaration_kind, name_list, name_count, type, value_list, value_count);
add_ast_entity(f, f->curr_scope, var_decl, name_list);
return var_decl;
}
@@ -1761,7 +1771,8 @@ AstNode *parse_return_stmt(AstFile *f) {
isize result_count = 0;
if (f->cursor[0].kind != Token_Semicolon)
result = parse_rhs_expr_list(f, &result_count);
expect_token(f, Token_Semicolon);
if (f->cursor[0].kind != Token_CloseBrace)
expect_token(f, Token_Semicolon);
return make_return_stmt(f, token, result, result_count);
}
@@ -1899,7 +1910,10 @@ AstNode *parse_stmt(AstFile *f) {
case Token_Xor:
case Token_Not:
s = parse_simple_stmt(f);
if (s->kind != AstNode_ProcDecl && !allow_token(f, Token_Semicolon)) {
if (s->kind != AstNode_ProcDecl &&
!allow_token(f, Token_Semicolon) &&
f->cursor[0].kind == Token_CloseBrace) {
// TODO(bill): Cleanup semicolon handling in parser
ast_file_err(f, f->cursor[0],
"Expected `;` after statement, got `%.*s`",
LIT(token_strings[f->cursor[0].kind]));
+1 -4
View File
@@ -146,10 +146,7 @@ void print_ast(AstNode *node, isize indent) {
break;
case AstNode_ProcDecl:
print_indent(indent);
if (node->ProcDecl.kind == Declaration_Mutable)
gb_printf("(decl:proc,mutable)\n");
else if (node->ProcDecl.kind == Declaration_Immutable)
gb_printf("(decl:proc,immutable)\n");
gb_printf("(decl:proc)\n");
print_ast(node->ProcDecl.type, indent+1);
print_ast(node->ProcDecl.body, indent+1);
print_ast(node->ProcDecl.tag_list, indent+1);
+2 -5
View File
@@ -95,7 +95,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
TOKEN_KIND(Token_Semicolon, ";"), \
TOKEN_KIND(Token_Period, "."), \
TOKEN_KIND(Token_Comma, ","), \
TOKEN_KIND(Token_Ellipsis, "..."), \
TOKEN_KIND(Token_Ellipsis, ".."), \
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
\
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
@@ -741,10 +741,7 @@ Token tokenizer_get_token(Tokenizer *t) {
token = scan_number_to_token(t, true);
} else if (t->curr_rune == '.') { // Could be an ellipsis
advance_to_next_rune(t);
if (t->curr_rune == '.') {
advance_to_next_rune(t);
token.kind = Token_Ellipsis;
}
token.kind = Token_Ellipsis;
}
break;