Fix anonymous procedures and their dependencies

This commit is contained in:
Ginger Bill
2016-12-21 15:20:33 +00:00
parent d0e1efe622
commit 923b039cf6
11 changed files with 367 additions and 354 deletions
+7 -14
View File
@@ -10,22 +10,15 @@ import (
"utf8.odin"; "utf8.odin";
) )
type Byte_Size f64;
const (
_ = iota; // ignore first value by assigning to blank identifier
KB Byte_Size = 1 << (10 * iota);
// Because there is no type or expression, the previous one is used but
// with `iota` incremented by one
MB;
GB;
TB;
PB;
EB;
)
proc main() { proc main() {
var x = proc() -> int {
proc print_here() {
fmt.println("Here"); fmt.println("Here");
}
print_here();
return 1;
};
fmt.println(x());
} }
+1 -1
View File
@@ -112,7 +112,7 @@ proc fmuladd64(a, b, c f64) -> f64 #foreign "llvm.fmuladd.f64"
type Allocator_Mode int; type Allocator_Mode u8;
const ( const (
ALLOCATOR_ALLOC Allocator_Mode = iota; ALLOCATOR_ALLOC Allocator_Mode = iota;
ALLOCATOR_FREE; ALLOCATOR_FREE;
+137 -137
View File
@@ -1,158 +1,158 @@
#shared_global_scope; #shared_global_scope;
/*
#import "fmt.odin"
__u128_mod :: proc(a, b: u128) -> u128 #link_name "__umodti3" { // import "fmt.odin";
_, r := __u128_quo_mod(a, b)
return r
}
__u128_quo :: proc(a, b: u128) -> u128 #link_name "__udivti3" { // proc __u128_mod(a, b: u128) -> u128 #link_name "__umodti3" {
n, _ := __u128_quo_mod(a, b) // var _, r := __u128_quo_mod(a, b)
return n // return r
} // }
__i128_mod :: proc(a, b: i128) -> i128 #link_name "__modti3" { // proc __u128_quo(a, b: u128) -> u128 #link_name "__udivti3" {
_, r := __i128_quo_mod(a, b) // var n, _ := __u128_quo_mod(a, b)
return r // return n
} // }
__i128_quo :: proc(a, b: i128) -> i128 #link_name "__divti3" { // proc __i128_mod(a, b: i128) -> i128 #link_name "__modti3" {
n, _ := __i128_quo_mod(a, b) // var _, r := __i128_quo_mod(a, b)
return n // return r
} // }
__i128_quo_mod :: proc(a, b: i128) -> (i128, i128) #link_name "__divmodti4" { // proc __i128_quo(a, b: i128) -> i128 #link_name "__divti3" {
s := b >> 127 // var n, _ := __i128_quo_mod(a, b)
b = (b ~ s) - s // return n
s = a >> 127 // }
a = (a ~ s) - s
n, r := __u128_quo_mod(a as u128, b as u128) // proc __i128_quo_mod(a, b: i128) -> (i128, i128) #link_name "__divmodti4" {
return (n as i128 ~ s) - s, (r as i128 ~ s) - s // var s := b >> 127
} // b = (b ~ s) - s
// s = a >> 127
// a = (a ~ s) - s
// var n, r := __u128_quo_mod(a as u128, b as u128)
// return (n as i128 ~ s) - s, (r as i128 ~ s) - s
// }
__u128_quo_mod :: proc(a, b: u128) -> (u128, u128) #link_name "__udivmodti4" { // proc __u128_quo_mod(a, b: u128) -> (u128, u128) #link_name "__udivmodti4" {
clz :: proc(x: u64) -> u64 { // proc clz(x: u64) -> u64 {
clz_u64 :: proc(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.ctlz.i64" // proc clz_u64(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.ctlz.i64"
return clz_u64(x, false) // return clz_u64(x, false)
} // }
ctz :: proc(x: u64) -> u64 { // proc ctz(x: u64) -> u64 {
ctz_u64 :: proc(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.cttz.i64" // proc ctz_u64(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.cttz.i64"
return ctz_u64(x, false) // return ctz_u64(x, false)
} // }
u128_lo_hi :: raw_union { // u128_lo_hi :: raw_union {
all: u128 // all: u128
using _lohi: struct {lo, hi: u64;} // using _lohi: struct {lo, hi: u64;}
} // }
n, d, q, r: u128_lo_hi // n, d, q, r: u128_lo_hi
sr: u64 // sr: u64
n.all = a // n.all = a
d.all = b // d.all = b
if n.hi == 0 { // if n.hi == 0 {
if d.hi == 0 { // if d.hi == 0 {
return (n.lo / d.lo) as u128, (n.lo % d.lo) as u128 // return (n.lo / d.lo) as u128, (n.lo % d.lo) as u128
} // }
return 0, n.lo as u128 // return 0, n.lo as u128
} // }
if d.lo == 0 { // if d.lo == 0 {
if d.hi == 0 { // if d.hi == 0 {
return (n.hi / d.lo) as u128, (n.hi % d.lo) as u128 // return (n.hi / d.lo) as u128, (n.hi % d.lo) as u128
} // }
if n.lo == 0 { // if n.lo == 0 {
r.hi = n.hi % d.hi // r.hi = n.hi % d.hi
r.lo = 0 // r.lo = 0
return (n.hi / d.hi) as u128, r.all // return (n.hi / d.hi) as u128, r.all
} // }
if (d.hi & (d.hi-1)) == 0 { // if (d.hi & (d.hi-1)) == 0 {
r.lo = n.lo // r.lo = n.lo
r.hi = n.hi & (d.hi-1) // r.hi = n.hi & (d.hi-1)
return (n.hi >> ctz(d.hi)) as u128, r.all // return (n.hi >> ctz(d.hi)) as u128, r.all
} // }
sr = clz(d.hi) - clz(n.hi) // sr = clz(d.hi) - clz(n.hi)
if sr > 64 - 2 { // if sr > 64 - 2 {
return 0, n.all // return 0, n.all
} // }
sr++ // sr++
q.lo = 0 // q.lo = 0
q.hi = n.lo << (64-sr) // q.hi = n.lo << (64-sr)
r.hi = n.hi >> sr // r.hi = n.hi >> sr
r.lo = (n.hi << (64-sr)) | (n.lo >> sr) // r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
} else { // } else {
if d.hi == 0 { // if d.hi == 0 {
if (d.lo & (d.lo - 1)) == 0 { // if (d.lo & (d.lo - 1)) == 0 {
rem := (n.lo % (d.lo - 1)) as u128 // var rem := (n.lo % (d.lo - 1)) as u128
if d.lo == 1 { // if d.lo == 1 {
return n.all, rem // return n.all, rem
} // }
sr = ctz(d.lo) // sr = ctz(d.lo)
q.hi = n.hi >> sr // q.hi = n.hi >> sr
q.lo = (n.hi << (64-sr)) | (n.lo >> sr) // q.lo = (n.hi << (64-sr)) | (n.lo >> sr)
return q.all, rem // return q.all, rem
} // }
sr = 1 + 64 + clz(d.lo) - clz(n.hi) // sr = 1 + 64 + clz(d.lo) - clz(n.hi)
q.all = n.all << (128-sr) // q.all = n.all << (128-sr)
r.all = n.all >> sr // r.all = n.all >> sr
if sr == 64 { // if sr == 64 {
q.lo = 0 // q.lo = 0
q.hi = n.lo // q.hi = n.lo
r.hi = 0 // r.hi = 0
r.lo = n.hi // r.lo = n.hi
} else if sr < 64 { // } else if sr < 64 {
q.lo = 0 // q.lo = 0
q.hi = n.lo << (64-sr) // q.hi = n.lo << (64-sr)
r.hi = n.hi >> sr // r.hi = n.hi >> sr
r.lo = (n.hi << (64-sr)) | (n.lo >> sr) // r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
} else { // } else {
q.lo = n.lo << (128-sr) // q.lo = n.lo << (128-sr)
q.hi = (n.hi << (128-sr)) | (n.lo >> (sr-64)) // q.hi = (n.hi << (128-sr)) | (n.lo >> (sr-64))
r.hi = 0 // r.hi = 0
r.lo = n.hi >> (sr-64) // r.lo = n.hi >> (sr-64)
} // }
} else { // } else {
sr = clz(d.hi) - clz(n.hi) // sr = clz(d.hi) - clz(n.hi)
if sr > 64-1 { // if sr > 64-1 {
return 0, n.all // return 0, n.all
} // }
sr++ // sr++
q.lo = 0 // q.lo = 0
q.hi = n.lo << (64-sr) // q.hi = n.lo << (64-sr)
r.all = n.all >> sr // r.all = n.all >> sr
if sr < 64 { // if sr < 64 {
r.hi = n.hi >> sr // r.hi = n.hi >> sr
r.lo = (n.hi << (64-sr)) | (n.lo >> sr) // r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
} else { // } else {
r.hi = 0 // r.hi = 0
r.lo = n.hi // r.lo = n.hi
} // }
} // }
} // }
carry: u64 // carry: u64
for ; sr > 0; sr-- { // for ; sr > 0; sr-- {
r.hi = (r.hi << 1) | (r.lo >> (64-1)) // r.hi = (r.hi << 1) | (r.lo >> (64-1))
r.lo = (r.lo << 1) | (r.hi >> (64-1)) // r.lo = (r.lo << 1) | (r.hi >> (64-1))
q.hi = (q.hi << 1) | (q.lo >> (64-1)) // q.hi = (q.hi << 1) | (q.lo >> (64-1))
q.lo = (q.lo << 1) | carry // q.lo = (q.lo << 1) | carry
carry = 0 // carry = 0
if r.all >= d.all { // if r.all >= d.all {
r.all -= d.all // r.all -= d.all
carry = 1 // carry = 1
} // }
} // }
// q.all = (q.all << 1) | (carry as u128)
// return q.all, r.all
// }
q.all = (q.all << 1) | (carry as u128)
return q.all, r.all
}
*/
+1 -2
View File
@@ -93,8 +93,7 @@ const (
FILE_STANDARD_ERROR; FILE_STANDARD_ERROR;
FILE_STANDARD_COUNT; FILE_STANDARD_COUNT;
); )
// NOTE(bill): Uses startup to initialize it // NOTE(bill): Uses startup to initialize it
var ( var (
__std_files = [FILE_STANDARD_COUNT]File{ __std_files = [FILE_STANDARD_COUNT]File{
+8 -6
View File
@@ -8,11 +8,11 @@ const (
SURROGATE_MIN = 0xd800; SURROGATE_MIN = 0xd800;
SURROGATE_MAX = 0xdfff; SURROGATE_MAX = 0xdfff;
); )
type Accept_Range struct { type Accept_Range struct {
lo, hi u8; lo, hi u8;
}; }
var ( var (
accept_ranges = [5]Accept_Range{ accept_ranges = [5]Accept_Range{
@@ -99,10 +99,12 @@ proc decode_rune(s string) -> (rune, int) {
return RUNE_ERROR, 1; return RUNE_ERROR, 1;
} }
const MASK_X = 0b00111111; const (
const MASK_2 = 0b00011111; MASK_X = 0b00111111;
const MASK_3 = 0b00001111; MASK_2 = 0b00011111;
const MASK_4 = 0b00000111; MASK_3 = 0b00001111;
MASK_4 = 0b00000111;
)
if size == 2 { if size == 2 {
return (b0&MASK_2) as rune <<6 | (b1&MASK_X) as rune, 2; return (b0&MASK_2) as rune <<6 | (b1&MASK_X) as rune, 2;
+3 -1
View File
@@ -1142,6 +1142,8 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
for_array(iota, gd->specs) { for_array(iota, gd->specs) {
AstNode *spec = gd->specs.e[iota]; AstNode *spec = gd->specs.e[iota];
switch (spec->kind) { switch (spec->kind) {
case_ast_node(bd, BadDecl, decl);
case_end;
case_ast_node(is, ImportSpec, spec); case_ast_node(is, ImportSpec, spec);
if (!parent_scope->is_file) { if (!parent_scope->is_file) {
// NOTE(bill): _Should_ be caught by the parser // NOTE(bill): _Should_ be caught by the parser
@@ -1347,7 +1349,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
} }
// NOTE(bill): Do not add other imported entities // NOTE(bill): Do not add other imported entities
add_entity(c, parent_scope, NULL, e); add_entity(c, parent_scope, NULL, e);
if (!id->is_load) { // `#import`ed entities don't get exported if (id->keyword == Token_import) { // `#import`ed entities don't get exported
HashKey key = hash_string(e->token.string); HashKey key = hash_string(e->token.string);
map_entity_set(&parent_scope->implicit, key, e); map_entity_set(&parent_scope->implicit, key, e);
} }
+63 -63
View File
@@ -87,6 +87,8 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
for_array(iota, gd->specs) { for_array(iota, gd->specs) {
AstNode *spec = gd->specs.e[iota]; AstNode *spec = gd->specs.e[iota];
switch (spec->kind) { switch (spec->kind) {
case_ast_node(bd, BadDecl, spec);
case_end;
case_ast_node(vs, ValueSpec, spec); case_ast_node(vs, ValueSpec, spec);
switch (vs->keyword) { switch (vs->keyword) {
case Token_var: case Token_var:
@@ -453,15 +455,15 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL); fields[field_index++] = make_entity_type_name(c->allocator, c->context.scope, empty_token, NULL);
for_array(decl_index, decls) { for_array(decl_index, decls) {
AstNode *decl = decls.e[decl_index]; AstNode *decl = decls.e[decl_index];
if (decl->kind != AstNode_Parameter) { if (decl->kind != AstNode_Field) {
continue; continue;
} }
ast_node(p, Parameter, decl); ast_node(f, Field, decl);
Type *base_type = check_type_extra(c, p->type, NULL); Type *base_type = check_type_extra(c, f->type, NULL);
for_array(name_index, p->names) { for_array(name_index, f->names) {
AstNode *name = p->names.e[name_index]; AstNode *name = f->names.e[name_index];
if (!ast_node_expect(name, AstNode_Ident)) { if (!ast_node_expect(name, AstNode_Ident)) {
continue; continue;
} }
@@ -493,28 +495,28 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
isize field_index = 0; isize field_index = 0;
for_array(decl_index, decls) { for_array(decl_index, decls) {
AstNode *decl = decls.e[decl_index]; AstNode *decl = decls.e[decl_index];
if (decl->kind != AstNode_Parameter) { if (decl->kind != AstNode_Field) {
continue; continue;
} }
ast_node(param, Parameter, decl); ast_node(f, Field, decl);
Type *type = check_type_extra(c, param->type, NULL); Type *type = check_type_extra(c, f->type, NULL);
if (param->is_using) { if (f->is_using) {
if (param->names.count > 1) { if (f->names.count > 1) {
error_node(param->names.e[0], "Cannot apply `using` to more than one of the same type"); error_node(f->names.e[0], "Cannot apply `using` to more than one of the same type");
} }
} }
for_array(name_index, param->names) { for_array(name_index, f->names) {
AstNode *name = param->names.e[name_index]; AstNode *name = f->names.e[name_index];
if (!ast_node_expect(name, AstNode_Ident)) { if (!ast_node_expect(name, AstNode_Ident)) {
continue; continue;
} }
Token name_token = name->Ident; Token name_token = name->Ident;
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, param->is_using, cast(i32)field_index); Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, f->is_using, cast(i32)field_index);
e->identifier = name; e->identifier = name;
if (str_eq(name_token.string, str_lit("_"))) { if (str_eq(name_token.string, str_lit("_"))) {
fields[field_index++] = e; fields[field_index++] = e;
@@ -533,19 +535,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
} }
if (param->is_using) { if (f->is_using) {
Type *t = base_type(type_deref(type)); Type *t = base_type(type_deref(type));
if (!is_type_struct(t) && !is_type_raw_union(t) && if (!is_type_struct(t) && !is_type_raw_union(t) &&
param->names.count >= 1 && f->names.count >= 1 &&
param->names.e[0]->kind == AstNode_Ident) { f->names.e[0]->kind == AstNode_Ident) {
Token name_token = param->names.e[0]->Ident; Token name_token = f->names.e[0]->Ident;
if (is_type_indexable(t)) { if (is_type_indexable(t)) {
bool ok = true; bool ok = true;
for_array(emi, entity_map.entries) { for_array(emi, entity_map.entries) {
Entity *e = entity_map.entries.e[emi].value; Entity *e = entity_map.entries.e[emi].value;
if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) { if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
if (is_type_indexable(e->type)) { if (is_type_indexable(e->type)) {
if (e->identifier != param->names.e[0]) { if (e->identifier != f->names.e[0]) {
ok = false; ok = false;
using_index_expr = e; using_index_expr = e;
break; break;
@@ -613,8 +615,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
for_array(field_index, st->fields) { for_array(field_index, st->fields) {
AstNode *field = st->fields.e[field_index]; AstNode *field = st->fields.e[field_index];
switch (field->kind) { switch (field->kind) {
case_ast_node(p, Parameter, field); case_ast_node(f, Field, field);
field_count += p->names.count; field_count += f->names.count;
case_end; case_end;
} }
} }
@@ -662,8 +664,8 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
for_array(field_index, ut->fields) { for_array(field_index, ut->fields) {
AstNode *field = ut->fields.e[field_index]; AstNode *field = ut->fields.e[field_index];
switch (field->kind) { switch (field->kind) {
case_ast_node(p, Parameter, field); case_ast_node(f, Field, field);
field_count += p->names.count; field_count += f->names.count;
case_end; case_end;
} }
} }
@@ -685,8 +687,8 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
for_array(field_index, ut->fields) { for_array(field_index, ut->fields) {
AstNode *field = ut->fields.e[field_index]; AstNode *field = ut->fields.e[field_index];
switch (field->kind) { switch (field->kind) {
case_ast_node(p, Parameter, field); case_ast_node(f, Field, field);
field_count += p->names.count; field_count += f->names.count;
case_end; case_end;
} }
} }
@@ -699,51 +701,47 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
union_type->Record.field_count = field_count; union_type->Record.field_count = field_count;
} }
GB_COMPARE_PROC(cmp_enum_order) { // GB_COMPARE_PROC(cmp_enum_order) {
// Rule: // // Rule:
// Biggest to smallest alignment // // Biggest to smallest alignment
// if same alignment: biggest to smallest size // // if same alignment: biggest to smallest size
// if same size: order by source order // // if same size: order by source order
Entity *x = *(Entity **)a; // Entity *x = *(Entity **)a;
Entity *y = *(Entity **)b; // Entity *y = *(Entity **)b;
GB_ASSERT(x != NULL); // GB_ASSERT(x != NULL);
GB_ASSERT(y != NULL); // GB_ASSERT(y != NULL);
GB_ASSERT(x->kind == Entity_Constant); // GB_ASSERT(x->kind == Entity_Constant);
GB_ASSERT(y->kind == Entity_Constant); // GB_ASSERT(y->kind == Entity_Constant);
GB_ASSERT(x->Constant.value.kind == ExactValue_Integer); // GB_ASSERT(x->Constant.value.kind == ExactValue_Integer);
GB_ASSERT(y->Constant.value.kind == ExactValue_Integer); // GB_ASSERT(y->Constant.value.kind == ExactValue_Integer);
i64 i = x->Constant.value.value_integer; // i64 i = x->Constant.value.value_integer;
i64 j = y->Constant.value.value_integer; // i64 j = y->Constant.value.value_integer;
return i < j ? -1 : i > j; // return i < j ? -1 : i > j;
} // }
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_variadic_) { Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_variadic_) {
if (params.count == 0) { if (params.count == 0) {
return NULL; return NULL;
} }
bool is_variadic = false;
Type *tuple = make_type_tuple(c->allocator);
isize variable_count = 0; isize variable_count = 0;
for_array(i, params) { for_array(i, params) {
AstNode *field = params.e[i]; AstNode *field = params.e[i];
if (!ast_node_expect(field, AstNode_Parameter)) { if (ast_node_expect(field, AstNode_Field)) {
continue; ast_node(f, Field, field);
variable_count += f->names.count;
} }
ast_node(p, Parameter, field);
variable_count += p->names.count;
} }
bool is_variadic = false;
Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count); Entity **variables = gb_alloc_array(c->allocator, Entity *, variable_count);
isize variable_index = 0; isize variable_index = 0;
for_array(i, params) { for_array(i, params) {
if (params.e[i]->kind != AstNode_Parameter) { if (params.e[i]->kind != AstNode_Field) {
continue; continue;
} }
ast_node(p, Parameter, params.e[i]); ast_node(p, Field, params.e[i]);
AstNode *type_expr = p->type; AstNode *type_expr = p->type;
if (type_expr) { if (type_expr) {
if (type_expr->kind == AstNode_Ellipsis) { if (type_expr->kind == AstNode_Ellipsis) {
@@ -777,6 +775,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_v
end->type = make_type_slice(c->allocator, end->type); end->type = make_type_slice(c->allocator, end->type);
} }
Type *tuple = make_type_tuple(c->allocator);
tuple->Tuple.variables = variables; tuple->Tuple.variables = variables;
tuple->Tuple.variable_count = variable_count; tuple->Tuple.variable_count = variable_count;
@@ -3687,21 +3686,21 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
case_end; case_end;
case_ast_node(pl, ProcLit, node); case_ast_node(pl, ProcLit, node);
check_open_scope(c, pl->type);
c->context.decl = make_declaration_info(c->allocator, c->context.scope);
Type *proc_type = check_type(c, pl->type); Type *proc_type = check_type(c, pl->type);
if (proc_type != NULL) { if (proc_type == NULL) {
check_proc_body(c, empty_token, c->context.decl, proc_type, pl->body);
o->mode = Addressing_Value;
o->type = proc_type;
check_close_scope(c);
} else {
gbString str = expr_to_string(node); gbString str = expr_to_string(node);
error_node(node, "Invalid procedure literal `%s`", str); error_node(node, "Invalid procedure literal `%s`", str);
gb_string_free(str); gb_string_free(str);
check_close_scope(c); check_close_scope(c);
goto error; goto error;
} }
check_open_scope(c, pl->type);
check_proc_body(c, empty_token, c->context.decl, proc_type, pl->body);
check_close_scope(c);
o->mode = Addressing_Value;
o->type = proc_type;
case_end; case_end;
case_ast_node(cl, CompoundLit, node); case_ast_node(cl, CompoundLit, node);
@@ -4240,7 +4239,7 @@ gbString write_expr_to_string(gbString str, AstNode *node);
gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) { gbString write_params_to_string(gbString str, AstNodeArray params, char *sep) {
for_array(i, params) { for_array(i, params) {
ast_node(p, Parameter, params.e[i]); ast_node(p, Field, params.e[i]);
if (i > 0) { if (i > 0) {
str = gb_string_appendc(str, sep); str = gb_string_appendc(str, sep);
} }
@@ -4390,14 +4389,15 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, vt->elem); str = write_expr_to_string(str, vt->elem);
case_end; case_end;
case_ast_node(p, Parameter, node); case_ast_node(p, Field, node);
if (p->is_using) { if (p->is_using) {
str = gb_string_appendc(str, "using "); str = gb_string_appendc(str, "using ");
} }
for_array(i, p->names) { for_array(i, p->names) {
AstNode *name = p->names.e[i]; AstNode *name = p->names.e[i];
if (i > 0) if (i > 0) {
str = gb_string_appendc(str, ", "); str = gb_string_appendc(str, ", ");
}
str = write_expr_to_string(str, name); str = write_expr_to_string(str, name);
} }
+2
View File
@@ -1088,6 +1088,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
for_array(spec_index, gd->specs) { for_array(spec_index, gd->specs) {
AstNode *spec = gd->specs.e[spec_index]; AstNode *spec = gd->specs.e[spec_index];
switch (spec->kind) { switch (spec->kind) {
case_ast_node(bd, BadDecl, spec);
case_end;
case_ast_node(vs, ValueSpec, spec); case_ast_node(vs, ValueSpec, spec);
switch (vs->keyword) { switch (vs->keyword) {
case Token_let: case Token_let:
+18 -9
View File
@@ -59,17 +59,26 @@ i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
return exit_code; return exit_code;
} }
void print_usage_line(i32 indent, char *fmt, ...) {
while (indent --> 0) {
gb_printf_err("\t");
}
va_list va;
va_start(va, fmt);
gb_printf_err_va(fmt, va);
va_end(va);
gb_printf_err("\n");
}
void usage(char *argv0) { void usage(char *argv0) {
gb_printf_err("%s is a tool for managing Odin source code\n", argv0); print_usage_line(0, "%s is a tool for managing Odin source code", argv0);
gb_printf_err("Usage:"); print_usage_line(0, "Usage:");
gb_printf_err("\n\t%s command [arguments]\n", argv0); print_usage_line(1, "%s command [arguments]", argv0);
gb_printf_err("Commands:"); print_usage_line(0, "Commands:");
gb_printf_err("\n\tbuild compile .odin file"); print_usage_line(1, "build compile .odin file as executable");
gb_printf_err("\n\tbuild_dll compile .odin file as dll"); print_usage_line(1, "build_dll compile .odin file as dll");
gb_printf_err("\n\trun compile and run .odin file"); print_usage_line(1, "run compile and run .odin file");
gb_printf_err("\n\tversion print Odin version"); print_usage_line(1, "version print version");
gb_printf_err("\n\n");
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
+94 -66
View File
@@ -57,6 +57,7 @@ typedef struct Parser {
Array(ImportedFile) imports; Array(ImportedFile) imports;
gbAtomic32 import_index; gbAtomic32 import_index;
isize total_token_count; isize total_token_count;
isize total_line_count;
gbMutex mutex; gbMutex mutex;
} Parser; } Parser;
@@ -177,21 +178,26 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
}) \ }) \
AST_NODE_KIND(ForStmt, "for statement", struct { \ AST_NODE_KIND(ForStmt, "for statement", struct { \
Token token; \ Token token; \
AstNode *init, *cond, *post; \ AstNode *init; \
AstNode *cond; \
AstNode *post; \
AstNode *body; \ AstNode *body; \
}) \ }) \
AST_NODE_KIND(CaseClause, "case clause", struct { \ AST_NODE_KIND(CaseClause, "case clause", struct { \
Token token; \ Token token; \
AstNodeArray list, stmts; \ AstNodeArray list; \
AstNodeArray stmts; \
}) \ }) \
AST_NODE_KIND(MatchStmt, "match statement", struct { \ AST_NODE_KIND(MatchStmt, "match statement", struct { \
Token token; \ Token token; \
AstNode *init, *tag; \ AstNode *init; \
AstNode *tag; \
AstNode *body; \ AstNode *body; \
}) \ }) \
AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \ AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \
Token token; \ Token token; \
AstNode *tag, *var; \ AstNode *tag; \
AstNode *var; \
AstNode *body; \ AstNode *body; \
}) \ }) \
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \ AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
@@ -221,7 +227,6 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
AstNode *expr; \ AstNode *expr; \
AstNode *body; \ AstNode *body; \
}) \ }) \
\
AST_NODE_KIND(_ComplexStmtEnd, "", i32) \ AST_NODE_KIND(_ComplexStmtEnd, "", i32) \
AST_NODE_KIND(_StmtEnd, "", i32) \ AST_NODE_KIND(_StmtEnd, "", i32) \
AST_NODE_KIND(_SpecBegin, "", i32) \ AST_NODE_KIND(_SpecBegin, "", i32) \
@@ -237,10 +242,10 @@ AST_NODE_KIND(_SpecBegin, "", i32) \
AstNode *note; \ AstNode *note; \
}) \ }) \
AST_NODE_KIND(ImportSpec, "import specification", struct { \ AST_NODE_KIND(ImportSpec, "import specification", struct { \
TokenKind keyword; \
Token relpath; \ Token relpath; \
String fullpath; \ String fullpath; \
Token import_name; \ Token import_name; \
bool is_load; \
AstNode *cond; \ AstNode *cond; \
AstNode *note; \ AstNode *note; \
}) \ }) \
@@ -270,12 +275,12 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
bool is_system; \ bool is_system; \
}) \ }) \
AST_NODE_KIND(_DeclEnd, "", i32) \ AST_NODE_KIND(_DeclEnd, "", i32) \
AST_NODE_KIND(_TypeBegin, "", i32) \ AST_NODE_KIND(Field, "field", struct { \
AST_NODE_KIND(Parameter, "parameter", struct { \
AstNodeArray names; \ AstNodeArray names; \
AstNode * type; \ AstNode * type; \
bool is_using; \ bool is_using; \
}) \ }) \
AST_NODE_KIND(_TypeBegin, "", i32) \
AST_NODE_KIND(ProcType, "procedure type", struct { \ AST_NODE_KIND(ProcType, "procedure type", struct { \
Token token; \ Token token; \
AstNodeArray params; \ AstNodeArray params; \
@@ -477,11 +482,11 @@ Token ast_node_token(AstNode *node) {
case AstNode_ImportSpec: case AstNode_ImportSpec:
return node->ImportSpec.relpath; return node->ImportSpec.relpath;
case AstNode_Parameter: { case AstNode_Field: {
if (node->Parameter.names.count > 0) { if (node->Field.names.count > 0) {
return ast_node_token(node->Parameter.names.e[0]); return ast_node_token(node->Field.names.e[0]);
} else { } else {
return ast_node_token(node->Parameter.type); return ast_node_token(node->Field.type);
} }
} }
case AstNode_ProcType: case AstNode_ProcType:
@@ -898,11 +903,11 @@ AstNode *make_bad_decl(AstFile *f, Token begin, Token end) {
return result; return result;
} }
AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, bool is_using) { AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, bool is_using) {
AstNode *result = make_node(f, AstNode_Parameter); AstNode *result = make_node(f, AstNode_Field);
result->Parameter.names = names; result->Field.names = names;
result->Parameter.type = type; result->Field.type = type;
result->Parameter.is_using = is_using; result->Field.is_using = is_using;
return result; return result;
} }
@@ -1030,12 +1035,12 @@ AstNode *make_type_spec(AstFile *f, AstNode *name, AstNode *type) {
} }
AstNode *make_import_spec(AstFile *f, Token relpath, Token import_name, AstNode *cond, bool is_load) { AstNode *make_import_spec(AstFile *f, TokenKind keyword, Token relpath, Token import_name, AstNode *cond) {
AstNode *result = make_node(f, AstNode_ImportSpec); AstNode *result = make_node(f, AstNode_ImportSpec);
result->ImportSpec.keyword = keyword;
result->ImportSpec.relpath = relpath; result->ImportSpec.relpath = relpath;
result->ImportSpec.import_name = import_name; result->ImportSpec.import_name = import_name;
result->ImportSpec.cond = cond; result->ImportSpec.cond = cond;
result->ImportSpec.is_load = is_load;
return result; return result;
} }
@@ -1057,6 +1062,21 @@ bool next_token(AstFile *f) {
return false; return false;
} }
TokenKind look_ahead_token_kind(AstFile *f, isize amount) {
GB_ASSERT(amount > 0);
TokenKind kind = Token_Invalid;
isize index = f->curr_token_index;
while (amount > 0) {
index++;
kind = f->tokens.e[index].kind;
if (kind != Token_Comment) {
amount--;
}
}
return kind;
}
Token expect_token(AstFile *f, TokenKind kind) { Token expect_token(AstFile *f, TokenKind kind) {
Token prev = f->curr_token; Token prev = f->curr_token;
if (prev.kind != kind) { if (prev.kind != kind) {
@@ -1859,17 +1879,17 @@ AstNodeArray parse_identfier_list(AstFile *f) {
} }
void parse_check_name_list_for_reserves(AstFile *f, AstNodeArray names) { void parse_check_name_list_for_reserves(AstFile *f, AstNodeArray names) {
// for_array(i, names) { for_array(i, names) {
// AstNode *name = names.e[i]; AstNode *name = names.e[i];
// if (name->kind == AstNode_Ident) { if (name->kind == AstNode_Ident) {
// String n = name->Ident.string; String n = name->Ident.string;
// // NOTE(bill): Check for reserved identifiers // NOTE(bill): Check for reserved identifiers
// if (str_eq(n, str_lit("context"))) { if (str_eq(n, str_lit("context"))) {
// syntax_error_node(name, "`context` is a reserved identifier"); syntax_error_node(name, "`context` is a reserved identifier");
// break; break;
// } }
// } }
// } }
} }
AstNode *parse_type_attempt(AstFile *f) { AstNode *parse_type_attempt(AstFile *f) {
@@ -1998,7 +2018,7 @@ PARSE_SPEC_PROC(parse_import_spec) {
syntax_error(import_name, "You cannot use `import` within a procedure. This must be done at the file scope"); syntax_error(import_name, "You cannot use `import` within a procedure. This must be done at the file scope");
spec = make_bad_decl(f, import_name, file_path); spec = make_bad_decl(f, import_name, file_path);
} else { } else {
spec = make_import_spec(f, file_path, import_name, cond, false); spec = make_import_spec(f, Token_import, file_path, import_name, cond);
} }
return spec; return spec;
} }
@@ -2017,7 +2037,7 @@ PARSE_SPEC_PROC(parse_include_spec) {
syntax_error(import_name, "You cannot use `include` within a procedure. This must be done at the file scope"); syntax_error(import_name, "You cannot use `include` within a procedure. This must be done at the file scope");
spec = make_bad_decl(f, import_name, file_path); spec = make_bad_decl(f, import_name, file_path);
} else { } else {
spec = make_import_spec(f, file_path, import_name, cond, true); spec = make_import_spec(f, Token_include, file_path, import_name, cond);
} }
return spec; return spec;
} }
@@ -2060,11 +2080,7 @@ AstNode *parse_simple_stmt(AstFile *f) {
return parse_decl(f); return parse_decl(f);
} }
isize lhs_count = 0, rhs_count = 0;
AstNodeArray lhs = parse_lhs_expr_list(f); AstNodeArray lhs = parse_lhs_expr_list(f);
AstNode *statement = NULL;
Token token = f->curr_token; Token token = f->curr_token;
switch (token.kind) { switch (token.kind) {
case Token_Eq: case Token_Eq:
@@ -2096,7 +2112,7 @@ AstNode *parse_simple_stmt(AstFile *f) {
} break; } break;
} }
if (lhs_count > 1) { if (lhs.count > 1) {
syntax_error(token, "Expected 1 expression"); syntax_error(token, "Expected 1 expression");
return make_bad_stmt(f, token, f->curr_token); return make_bad_stmt(f, token, f->curr_token);
} }
@@ -2109,9 +2125,9 @@ AstNode *parse_simple_stmt(AstFile *f) {
syntax_error(f->curr_token, "You cannot use a simple statement in the file scope"); syntax_error(f->curr_token, "You cannot use a simple statement in the file scope");
return make_bad_stmt(f, f->curr_token, f->curr_token); return make_bad_stmt(f, f->curr_token, f->curr_token);
} }
statement = make_inc_dec_stmt(f, token, lhs.e[0]); AstNode *stmt = make_inc_dec_stmt(f, token, lhs.e[0]);
next_token(f); next_token(f);
return statement; return stmt;
} }
return make_expr_stmt(f, lhs.e[0]); return make_expr_stmt(f, lhs.e[0]);
@@ -2155,7 +2171,7 @@ AstNode *parse_proc_type(AstFile *f) {
} }
AstNodeArray parse_parameter_list(AstFile *f, isize *name_count_, bool allow_using, TokenKind separator, TokenKind follow) { AstNodeArray parse_field_list(AstFile *f, isize *name_count_, bool allow_using, TokenKind separator, TokenKind follow) {
AstNodeArray params = make_ast_node_array(f); AstNodeArray params = make_ast_node_array(f);
isize name_count = 0; isize name_count = 0;
@@ -2210,10 +2226,9 @@ AstNodeArray parse_parameter_list(AstFile *f, isize *name_count_, bool allow_usi
syntax_error(f->curr_token, "Expected a type for this parameter declaration"); syntax_error(f->curr_token, "Expected a type for this parameter declaration");
} }
AstNode *param = make_parameter(f, names, type, is_using); AstNode *param = make_field(f, names, type, is_using);
array_add(&params, param); array_add(&params, param);
if (separator == Token_Semicolon) { if (separator == Token_Semicolon) {
expect_semicolon(f, param); expect_semicolon(f, param);
} else { } else {
@@ -2229,8 +2244,8 @@ AstNodeArray parse_parameter_list(AstFile *f, isize *name_count_, bool allow_usi
} }
AstNodeArray parse_record_params(AstFile *f, isize *field_count_, bool allow_using, String context) { AstNodeArray parse_record_fields(AstFile *f, isize *field_count_, bool allow_using, String context) {
return parse_parameter_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace); return parse_field_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace);
} }
AstNode *parse_identifier_or_type(AstFile *f) { AstNode *parse_identifier_or_type(AstFile *f) {
@@ -2295,7 +2310,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
bool is_packed = false; bool is_packed = false;
bool is_ordered = false; bool is_ordered = false;
while (allow_token(f, Token_Hash)) { while (allow_token(f, Token_Hash)) {
Token tag = expect_token_after(f, Token_Ident, "`#`"); Token tag = expect_token_after(f, Token_Ident, "#");
if (str_eq(tag.string, str_lit("packed"))) { if (str_eq(tag.string, str_lit("packed"))) {
if (is_packed) { if (is_packed) {
syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string)); syntax_error(tag, "Duplicate struct tag `#%.*s`", LIT(tag.string));
@@ -2315,9 +2330,9 @@ AstNode *parse_identifier_or_type(AstFile *f) {
syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering"); syntax_error(token, "`#ordered` is not needed with `#packed` which implies ordering");
} }
Token open = expect_token_after(f, Token_OpenBrace, "`struct`"); Token open = expect_token_after(f, Token_OpenBrace, "struct");
isize decl_count = 0; isize decl_count = 0;
AstNodeArray decls = parse_record_params(f, &decl_count, true, str_lit("struct")); AstNodeArray decls = parse_record_fields(f, &decl_count, true, str_lit("struct"));
Token close = expect_token(f, Token_CloseBrace); Token close = expect_token(f, Token_CloseBrace);
return make_struct_type(f, token, decls, decl_count, is_packed, is_ordered); return make_struct_type(f, token, decls, decl_count, is_packed, is_ordered);
@@ -2325,9 +2340,9 @@ AstNode *parse_identifier_or_type(AstFile *f) {
case Token_union: { case Token_union: {
Token token = expect_token(f, Token_union); Token token = expect_token(f, Token_union);
Token open = expect_token_after(f, Token_OpenBrace, "`union`"); Token open = expect_token_after(f, Token_OpenBrace, "union");
isize decl_count = 0; isize decl_count = 0;
AstNodeArray decls = parse_record_params(f, &decl_count, false, str_lit("union")); AstNodeArray decls = parse_record_fields(f, &decl_count, false, str_lit("union"));
Token close = expect_token(f, Token_CloseBrace); Token close = expect_token(f, Token_CloseBrace);
return make_union_type(f, token, decls, decl_count); return make_union_type(f, token, decls, decl_count);
@@ -2335,9 +2350,9 @@ AstNode *parse_identifier_or_type(AstFile *f) {
case Token_raw_union: { case Token_raw_union: {
Token token = expect_token(f, Token_raw_union); Token token = expect_token(f, Token_raw_union);
Token open = expect_token_after(f, Token_OpenBrace, "`raw_union`"); Token open = expect_token_after(f, Token_OpenBrace, "raw_union");
isize decl_count = 0; isize decl_count = 0;
AstNodeArray decls = parse_record_params(f, &decl_count, true, str_lit("raw_union")); AstNodeArray decls = parse_record_fields(f, &decl_count, true, str_lit("raw_union"));
Token close = expect_token(f, Token_CloseBrace); Token close = expect_token(f, Token_CloseBrace);
return make_raw_union_type(f, token, decls, decl_count); return make_raw_union_type(f, token, decls, decl_count);
@@ -2391,7 +2406,7 @@ void parse_proc_signature(AstFile *f,
AstNodeArray *params, AstNodeArray *params,
AstNodeArray *results) { AstNodeArray *results) {
expect_token(f, Token_OpenParen); expect_token(f, Token_OpenParen);
*params = parse_parameter_list(f, NULL, true, Token_Comma, Token_CloseParen); *params = parse_field_list(f, NULL, true, Token_Comma, Token_CloseParen);
expect_token_after(f, Token_CloseParen, "parameter list"); expect_token_after(f, Token_CloseParen, "parameter list");
*results = parse_results(f); *results = parse_results(f);
} }
@@ -2409,8 +2424,14 @@ AstNode *parse_body(AstFile *f) {
AstNode *parse_proc_decl(AstFile *f) { AstNode *parse_proc_decl(AstFile *f) {
Token proc_token = expect_token(f, Token_proc); if (look_ahead_token_kind(f, 1) == Token_OpenParen) {
// NOTE(bill): It's an anonymous procedure
// NOTE(bill): This look-ahead technically makes the grammar LALR(2)
// but is that a problem in practice?
return make_expr_stmt(f, parse_expr(f, true));
}
Token proc_token = expect_token(f, Token_proc);
AstNode *name = parse_identifier(f); AstNode *name = parse_identifier(f);
AstNodeArray params = {0}; AstNodeArray params = {0};
@@ -2426,19 +2447,18 @@ AstNode *parse_proc_decl(AstFile *f) {
parse_proc_tags(f, &tags, &foreign_name, &link_name); parse_proc_tags(f, &tags, &foreign_name, &link_name);
AstNode *curr_proc = f->curr_proc;
f->curr_proc = proc_type;
if (f->curr_token.kind == Token_OpenBrace) { if (f->curr_token.kind == Token_OpenBrace) {
if ((tags & ProcTag_foreign) != 0) { if ((tags & ProcTag_foreign) != 0) {
syntax_error_node(name, "A procedure tagged as `#foreign` cannot have a body"); syntax_error(proc_token, "A procedure tagged as `#foreign` cannot have a body");
} }
AstNode *curr_proc = f->curr_proc;
f->curr_proc = proc_type;
body = parse_body(f); body = parse_body(f);
f->curr_proc = curr_proc;
} else if ((tags & ProcTag_foreign) == 0) { } else if ((tags & ProcTag_foreign) == 0) {
syntax_error_node(name, "Only a procedure tagged as `#foreign` cannot have a body"); syntax_error(proc_token, "Only a procedure tagged as `#foreign` cannot have a body");
} }
f->curr_proc = curr_proc;
return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name); return make_proc_decl(f, name, proc_type, body, tags, foreign_name, link_name);
} }
@@ -2958,6 +2978,11 @@ AstNodeArray parse_stmt_list(AstFile *f) {
AstNode *stmt = parse_stmt(f); AstNode *stmt = parse_stmt(f);
if (stmt && stmt->kind != AstNode_EmptyStmt) { if (stmt && stmt->kind != AstNode_EmptyStmt) {
array_add(&list, stmt); array_add(&list, stmt);
if (stmt->kind == AstNode_ExprStmt &&
stmt->ExprStmt.expr != NULL &&
stmt->ExprStmt.expr->kind == AstNode_ProcLit) {
syntax_error_node(stmt, "Procedure literal evaluated but not used");
}
} }
} }
@@ -3031,7 +3056,7 @@ void destroy_parser(Parser *p) {
for_array(i, p->files) { for_array(i, p->files) {
destroy_ast_file(&p->files.e[i]); destroy_ast_file(&p->files.e[i]);
} }
#if 1 #if 0
for_array(i, p->imports) { for_array(i, p->imports) {
// gb_free(heap_allocator(), p->imports[i].text); // gb_free(heap_allocator(), p->imports[i].text);
} }
@@ -3093,22 +3118,24 @@ bool is_import_path_valid(String path) {
u8 *start = path.text; u8 *start = path.text;
u8 *end = path.text + path.len; u8 *end = path.text + path.len;
u8 *curr = start; u8 *curr = start;
Rune r = -1;
while (curr < end) { while (curr < end) {
isize width = 1; isize width = 1;
r = curr[0]; Rune r = curr[0];
if (r >= 0x80) { if (r >= 0x80) {
width = gb_utf8_decode(curr, end-curr, &r); width = gb_utf8_decode(curr, end-curr, &r);
if (r == GB_RUNE_INVALID && width == 1) if (r == GB_RUNE_INVALID && width == 1) {
return false; return false;
else if (r == GB_RUNE_BOM && curr-start > 0) }
else if (r == GB_RUNE_BOM && curr-start > 0) {
return false; return false;
} }
}
for (isize i = 0; i < gb_count_of(illegal_import_runes); i++) { for (isize i = 0; i < gb_count_of(illegal_import_runes); i++) {
if (r == illegal_import_runes[i]) if (r == illegal_import_runes[i]) {
return false; return false;
} }
}
curr += width; curr += width;
} }
@@ -3135,7 +3162,7 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, AstNodeArray
String file_str = is->relpath.string; String file_str = is->relpath.string;
if (!is_import_path_valid(file_str)) { if (!is_import_path_valid(file_str)) {
if (is->is_load) { if (is->keyword == Token_include) {
syntax_error_node(node, "Invalid #include path: `%.*s`", LIT(file_str)); syntax_error_node(node, "Invalid #include path: `%.*s`", LIT(file_str));
} else { } else {
syntax_error_node(node, "Invalid #import path: `%.*s`", LIT(file_str)); syntax_error_node(node, "Invalid #import path: `%.*s`", LIT(file_str));
@@ -3266,6 +3293,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
gb_mutex_lock(&p->mutex); gb_mutex_lock(&p->mutex);
file.id = p->files.count; file.id = p->files.count;
array_add(&p->files, file); array_add(&p->files, file);
p->total_line_count += file.tokenizer.line_count;
gb_mutex_unlock(&p->mutex); gb_mutex_unlock(&p->mutex);
} }
} }
+10 -32
View File
@@ -2607,6 +2607,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
} else if (e != NULL && e->kind == Entity_Variable) { } else if (e != NULL && e->kind == Entity_Variable) {
return ssa_addr_load(proc, ssa_build_addr(proc, expr)); return ssa_addr_load(proc, ssa_build_addr(proc, expr));
} }
GB_PANIC("nil value for expression from identifier: %.*s", LIT(i->string));
return NULL; return NULL;
case_end; case_end;
@@ -2714,9 +2715,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
proc->module, NULL, type, pl->type, pl->body, name); proc->module, NULL, type, pl->type, pl->body, name);
value->Proc.tags = pl->tags; value->Proc.tags = pl->tags;
value->Proc.parent = proc;
array_add(&proc->children, &value->Proc); array_add(&proc->children, &value->Proc);
ssa_build_proc(value, proc); array_add(&proc->module->procs_to_generate, value);
return value; return value;
case_end; case_end;
@@ -2971,32 +2973,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
} break; } break;
#if 0
case BuiltinProc_ptr_offset: {
ssa_emit_comment(proc, str_lit("ptr_offset"));
ssaValue *ptr = ssa_build_expr(proc, ce->args.e[0]);
ssaValue *offset = ssa_build_expr(proc, ce->args.e[1]);
return ssa_emit_ptr_offset(proc, ptr, offset);
} break;
case BuiltinProc_ptr_sub: {
ssa_emit_comment(proc, str_lit("ptr_sub"));
ssaValue *ptr_a = ssa_build_expr(proc, ce->args.e[0]);
ssaValue *ptr_b = ssa_build_expr(proc, ce->args.e[1]);
Type *ptr_type = base_type(ssa_type(ptr_a));
GB_ASSERT(ptr_type->kind == Type_Pointer);
isize elem_size = type_size_of(proc->module->sizes, proc->module->allocator, ptr_type->Pointer.elem);
ssaValue *v = ssa_emit_arith(proc, Token_Sub, ptr_a, ptr_b, t_int);
if (elem_size > 1) {
ssaValue *ez = ssa_make_const_int(proc->module->allocator, elem_size);
v = ssa_emit_arith(proc, Token_Quo, v, ez, t_int);
}
return v;
} break;
#endif
case BuiltinProc_slice_ptr: { case BuiltinProc_slice_ptr: {
ssa_emit_comment(proc, str_lit("slice_ptr")); ssa_emit_comment(proc, str_lit("slice_ptr"));
ssaValue *ptr = ssa_build_expr(proc, ce->args.e[0]); ssaValue *ptr = ssa_build_expr(proc, ce->args.e[0]);
@@ -3095,9 +3071,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
} }
} }
// NOTE(bill): Regular call // NOTE(bill): Regular call
ssaValue *value = ssa_build_expr(proc, ce->proc); ssaValue *value = ssa_build_expr(proc, ce->proc);
GB_ASSERT(value != NULL);
Type *proc_type_ = base_type(ssa_type(value)); Type *proc_type_ = base_type(ssa_type(value));
GB_ASSERT(proc_type_->kind == Type_Proc); GB_ASSERT(proc_type_->kind == Type_Proc);
TypeProc *type = &proc_type_->Proc; TypeProc *type = &proc_type_->Proc;
@@ -3269,7 +3245,7 @@ ssaAddr ssa_build_addr_from_entity(ssaProcedure *proc, Entity *e, AstNode *expr)
} }
if (v == NULL) { if (v == NULL) {
GB_PANIC("Unknown value: %s, entity: %p %.*s\n", expr_to_string(expr), e, LIT(entity_strings[e->kind])); GB_PANIC("Unknown value: %.*s, entity: %p %.*s\n", LIT(e->token.string), e, LIT(entity_strings[e->kind]));
} }
return ssa_make_addr(v, expr); return ssa_make_addr(v, expr);
@@ -3293,7 +3269,9 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
case_ast_node(se, SelectorExpr, expr); case_ast_node(se, SelectorExpr, expr);
ssa_emit_comment(proc, str_lit("SelectorExpr")); ssa_emit_comment(proc, str_lit("SelectorExpr"));
String selector = unparen_expr(se->selector)->Ident.string; AstNode *sel = unparen_expr(se->selector);
GB_ASSERT(sel->kind == AstNode_Ident);
String selector = sel->Ident.string;
Type *type = base_type(type_of_expr(proc->module->info, se->expr)); Type *type = base_type(type_of_expr(proc->module->info, se->expr));
if (type == t_invalid) { if (type == t_invalid) {
@@ -4958,7 +4936,7 @@ void ssa_gen_tree(ssaGen *s) {
array_add(&global_variables, var); array_add(&global_variables, var);
} }
map_ssa_value_set(&m->values, hash_pointer(e), g); ssa_module_add_value(m, e, g);
map_ssa_value_set(&m->members, hash_string(name), g); map_ssa_value_set(&m->members, hash_string(name), g);
} break; } break;
@@ -4978,7 +4956,7 @@ void ssa_gen_tree(ssaGen *s) {
ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name); ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name);
p->Proc.tags = pd->tags; p->Proc.tags = pd->tags;
map_ssa_value_set(&m->values, hash_pointer(e), p); ssa_module_add_value(m, e, p);
HashKey hash_name = hash_string(name); HashKey hash_name = hash_string(name);
if (map_ssa_value_get(&m->members, hash_name) == NULL) { if (map_ssa_value_get(&m->members, hash_name) == NULL) {
map_ssa_value_set(&m->members, hash_name, p); map_ssa_value_set(&m->members, hash_name, p);