mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Fix anonymous procedures and their dependencies
This commit is contained in:
+8
-15
@@ -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() {
|
||||||
fmt.println("Here");
|
var x = proc() -> int {
|
||||||
|
proc print_here() {
|
||||||
|
fmt.println("Here");
|
||||||
|
}
|
||||||
|
|
||||||
|
print_here();
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
fmt.println(x());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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
@@ -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
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
+116
-88
@@ -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;
|
||||||
|
|
||||||
@@ -176,52 +177,56 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
|||||||
AstNodeArray results; \
|
AstNodeArray results; \
|
||||||
}) \
|
}) \
|
||||||
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 *body; \
|
AstNode *var; \
|
||||||
|
AstNode *body; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
|
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
|
||||||
AST_NODE_KIND(BranchStmt, "branch statement", struct { Token token; }) \
|
AST_NODE_KIND(BranchStmt, "branch statement", struct { Token token; }) \
|
||||||
AST_NODE_KIND(UsingStmt, "using statement", struct { Token token; AstNode *node; }) \
|
AST_NODE_KIND(UsingStmt, "using statement", struct { Token token; AstNode *node; }) \
|
||||||
AST_NODE_KIND(AsmOperand, "assembly operand", struct { \
|
AST_NODE_KIND(AsmOperand, "assembly operand", struct { \
|
||||||
Token string; \
|
Token string; \
|
||||||
AstNode *operand; \
|
AstNode *operand; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(AsmStmt, "assembly statement", struct { \
|
AST_NODE_KIND(AsmStmt, "assembly statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
bool is_volatile; \
|
bool is_volatile; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
Token code_string; \
|
Token code_string; \
|
||||||
AstNode *output_list; \
|
AstNode *output_list; \
|
||||||
AstNode *input_list; \
|
AstNode *input_list; \
|
||||||
AstNode *clobber_list; \
|
AstNode *clobber_list; \
|
||||||
isize output_count, input_count, clobber_count; \
|
isize output_count, input_count, clobber_count; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(PushAllocator, "push_allocator statement", struct { \
|
AST_NODE_KIND(PushAllocator, "push_allocator statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *expr; \
|
AstNode *expr; \
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(PushContext, "push_context statement", struct { \
|
AST_NODE_KIND(PushContext, "push_context statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
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,12 +242,12 @@ AST_NODE_KIND(_SpecBegin, "", i32) \
|
|||||||
AstNode *note; \
|
AstNode *note; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ImportSpec, "import specification", struct { \
|
AST_NODE_KIND(ImportSpec, "import specification", struct { \
|
||||||
Token relpath; \
|
TokenKind keyword; \
|
||||||
String fullpath; \
|
Token relpath; \
|
||||||
Token import_name; \
|
String fullpath; \
|
||||||
bool is_load; \
|
Token import_name; \
|
||||||
AstNode *cond; \
|
AstNode *cond; \
|
||||||
AstNode *note; \
|
AstNode *note; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_SpecEnd, "", i32) \
|
AST_NODE_KIND(_SpecEnd, "", i32) \
|
||||||
AST_NODE_KIND(_DeclBegin, "", i32) \
|
AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||||
@@ -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(¶ms, param);
|
array_add(¶ms, 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,21 +3118,23 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user