mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-17 00:11:25 -07:00
Fix anonymous procedures and their dependencies
This commit is contained in:
+8
-15
@@ -10,22 +10,15 @@ import (
|
||||
"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() {
|
||||
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 (
|
||||
ALLOCATOR_ALLOC Allocator_Mode = iota;
|
||||
ALLOCATOR_FREE;
|
||||
|
||||
+137
-137
@@ -1,158 +1,158 @@
|
||||
#shared_global_scope;
|
||||
|
||||
/*
|
||||
#import "fmt.odin"
|
||||
|
||||
__u128_mod :: proc(a, b: u128) -> u128 #link_name "__umodti3" {
|
||||
_, r := __u128_quo_mod(a, b)
|
||||
return r
|
||||
}
|
||||
// import "fmt.odin";
|
||||
|
||||
__u128_quo :: proc(a, b: u128) -> u128 #link_name "__udivti3" {
|
||||
n, _ := __u128_quo_mod(a, b)
|
||||
return n
|
||||
}
|
||||
// proc __u128_mod(a, b: u128) -> u128 #link_name "__umodti3" {
|
||||
// var _, r := __u128_quo_mod(a, b)
|
||||
// return r
|
||||
// }
|
||||
|
||||
__i128_mod :: proc(a, b: i128) -> i128 #link_name "__modti3" {
|
||||
_, r := __i128_quo_mod(a, b)
|
||||
return r
|
||||
}
|
||||
// proc __u128_quo(a, b: u128) -> u128 #link_name "__udivti3" {
|
||||
// var n, _ := __u128_quo_mod(a, b)
|
||||
// return n
|
||||
// }
|
||||
|
||||
__i128_quo :: proc(a, b: i128) -> i128 #link_name "__divti3" {
|
||||
n, _ := __i128_quo_mod(a, b)
|
||||
return n
|
||||
}
|
||||
// proc __i128_mod(a, b: i128) -> i128 #link_name "__modti3" {
|
||||
// var _, r := __i128_quo_mod(a, b)
|
||||
// return r
|
||||
// }
|
||||
|
||||
__i128_quo_mod :: proc(a, b: i128) -> (i128, i128) #link_name "__divmodti4" {
|
||||
s := b >> 127
|
||||
b = (b ~ s) - s
|
||||
s = a >> 127
|
||||
a = (a ~ s) - s
|
||||
// proc __i128_quo(a, b: i128) -> i128 #link_name "__divti3" {
|
||||
// var n, _ := __i128_quo_mod(a, b)
|
||||
// return n
|
||||
// }
|
||||
|
||||
n, r := __u128_quo_mod(a as u128, b as u128)
|
||||
return (n as i128 ~ s) - s, (r as i128 ~ s) - s
|
||||
}
|
||||
// proc __i128_quo_mod(a, b: i128) -> (i128, i128) #link_name "__divmodti4" {
|
||||
// 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" {
|
||||
clz :: proc(x: u64) -> u64 {
|
||||
clz_u64 :: proc(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.ctlz.i64"
|
||||
return clz_u64(x, false)
|
||||
}
|
||||
ctz :: proc(x: u64) -> u64 {
|
||||
ctz_u64 :: proc(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.cttz.i64"
|
||||
return ctz_u64(x, false)
|
||||
}
|
||||
// proc __u128_quo_mod(a, b: u128) -> (u128, u128) #link_name "__udivmodti4" {
|
||||
// proc clz(x: u64) -> u64 {
|
||||
// proc clz_u64(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.ctlz.i64"
|
||||
// return clz_u64(x, false)
|
||||
// }
|
||||
// proc ctz(x: u64) -> u64 {
|
||||
// proc ctz_u64(x: u64, is_zero_undef: bool) -> u64 #foreign "llvm.cttz.i64"
|
||||
// return ctz_u64(x, false)
|
||||
// }
|
||||
|
||||
|
||||
u128_lo_hi :: raw_union {
|
||||
all: u128
|
||||
using _lohi: struct {lo, hi: u64;}
|
||||
}
|
||||
// u128_lo_hi :: raw_union {
|
||||
// all: u128
|
||||
// using _lohi: struct {lo, hi: u64;}
|
||||
// }
|
||||
|
||||
n, d, q, r: u128_lo_hi
|
||||
sr: u64
|
||||
// n, d, q, r: u128_lo_hi
|
||||
// sr: u64
|
||||
|
||||
n.all = a
|
||||
d.all = b
|
||||
// n.all = a
|
||||
// d.all = b
|
||||
|
||||
if n.hi == 0 {
|
||||
if d.hi == 0 {
|
||||
return (n.lo / d.lo) as u128, (n.lo % d.lo) as u128
|
||||
}
|
||||
return 0, n.lo as u128
|
||||
}
|
||||
if d.lo == 0 {
|
||||
if d.hi == 0 {
|
||||
return (n.hi / d.lo) as u128, (n.hi % d.lo) as u128
|
||||
}
|
||||
if n.lo == 0 {
|
||||
r.hi = n.hi % d.hi
|
||||
r.lo = 0
|
||||
return (n.hi / d.hi) as u128, r.all
|
||||
}
|
||||
if (d.hi & (d.hi-1)) == 0 {
|
||||
r.lo = n.lo
|
||||
r.hi = n.hi & (d.hi-1)
|
||||
return (n.hi >> ctz(d.hi)) as u128, r.all
|
||||
}
|
||||
// if n.hi == 0 {
|
||||
// if d.hi == 0 {
|
||||
// return (n.lo / d.lo) as u128, (n.lo % d.lo) as u128
|
||||
// }
|
||||
// return 0, n.lo as u128
|
||||
// }
|
||||
// if d.lo == 0 {
|
||||
// if d.hi == 0 {
|
||||
// return (n.hi / d.lo) as u128, (n.hi % d.lo) as u128
|
||||
// }
|
||||
// if n.lo == 0 {
|
||||
// r.hi = n.hi % d.hi
|
||||
// r.lo = 0
|
||||
// return (n.hi / d.hi) as u128, r.all
|
||||
// }
|
||||
// if (d.hi & (d.hi-1)) == 0 {
|
||||
// r.lo = n.lo
|
||||
// r.hi = n.hi & (d.hi-1)
|
||||
// return (n.hi >> ctz(d.hi)) as u128, r.all
|
||||
// }
|
||||
|
||||
sr = clz(d.hi) - clz(n.hi)
|
||||
if sr > 64 - 2 {
|
||||
return 0, n.all
|
||||
}
|
||||
sr++
|
||||
q.lo = 0
|
||||
q.hi = n.lo << (64-sr)
|
||||
r.hi = n.hi >> sr
|
||||
r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
} else {
|
||||
if d.hi == 0 {
|
||||
if (d.lo & (d.lo - 1)) == 0 {
|
||||
rem := (n.lo % (d.lo - 1)) as u128
|
||||
if d.lo == 1 {
|
||||
return n.all, rem
|
||||
}
|
||||
sr = ctz(d.lo)
|
||||
q.hi = n.hi >> sr
|
||||
q.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
return q.all, rem
|
||||
}
|
||||
// sr = clz(d.hi) - clz(n.hi)
|
||||
// if sr > 64 - 2 {
|
||||
// return 0, n.all
|
||||
// }
|
||||
// sr++
|
||||
// q.lo = 0
|
||||
// q.hi = n.lo << (64-sr)
|
||||
// r.hi = n.hi >> sr
|
||||
// r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
// } else {
|
||||
// if d.hi == 0 {
|
||||
// if (d.lo & (d.lo - 1)) == 0 {
|
||||
// var rem := (n.lo % (d.lo - 1)) as u128
|
||||
// if d.lo == 1 {
|
||||
// return n.all, rem
|
||||
// }
|
||||
// sr = ctz(d.lo)
|
||||
// q.hi = n.hi >> sr
|
||||
// q.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
// 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)
|
||||
r.all = n.all >> sr
|
||||
if sr == 64 {
|
||||
q.lo = 0
|
||||
q.hi = n.lo
|
||||
r.hi = 0
|
||||
r.lo = n.hi
|
||||
} else if sr < 64 {
|
||||
q.lo = 0
|
||||
q.hi = n.lo << (64-sr)
|
||||
r.hi = n.hi >> sr
|
||||
r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
} else {
|
||||
q.lo = n.lo << (128-sr)
|
||||
q.hi = (n.hi << (128-sr)) | (n.lo >> (sr-64))
|
||||
r.hi = 0
|
||||
r.lo = n.hi >> (sr-64)
|
||||
}
|
||||
} else {
|
||||
sr = clz(d.hi) - clz(n.hi)
|
||||
if sr > 64-1 {
|
||||
return 0, n.all
|
||||
}
|
||||
sr++
|
||||
q.lo = 0
|
||||
q.hi = n.lo << (64-sr)
|
||||
r.all = n.all >> sr
|
||||
if sr < 64 {
|
||||
r.hi = n.hi >> sr
|
||||
r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
} else {
|
||||
r.hi = 0
|
||||
r.lo = n.hi
|
||||
}
|
||||
}
|
||||
}
|
||||
// q.all = n.all << (128-sr)
|
||||
// r.all = n.all >> sr
|
||||
// if sr == 64 {
|
||||
// q.lo = 0
|
||||
// q.hi = n.lo
|
||||
// r.hi = 0
|
||||
// r.lo = n.hi
|
||||
// } else if sr < 64 {
|
||||
// q.lo = 0
|
||||
// q.hi = n.lo << (64-sr)
|
||||
// r.hi = n.hi >> sr
|
||||
// r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
// } else {
|
||||
// q.lo = n.lo << (128-sr)
|
||||
// q.hi = (n.hi << (128-sr)) | (n.lo >> (sr-64))
|
||||
// r.hi = 0
|
||||
// r.lo = n.hi >> (sr-64)
|
||||
// }
|
||||
// } else {
|
||||
// sr = clz(d.hi) - clz(n.hi)
|
||||
// if sr > 64-1 {
|
||||
// return 0, n.all
|
||||
// }
|
||||
// sr++
|
||||
// q.lo = 0
|
||||
// q.hi = n.lo << (64-sr)
|
||||
// r.all = n.all >> sr
|
||||
// if sr < 64 {
|
||||
// r.hi = n.hi >> sr
|
||||
// r.lo = (n.hi << (64-sr)) | (n.lo >> sr)
|
||||
// } else {
|
||||
// r.hi = 0
|
||||
// r.lo = n.hi
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
carry: u64
|
||||
for ; sr > 0; sr-- {
|
||||
r.hi = (r.hi << 1) | (r.lo >> (64-1))
|
||||
r.lo = (r.lo << 1) | (r.hi >> (64-1))
|
||||
q.hi = (q.hi << 1) | (q.lo >> (64-1))
|
||||
q.lo = (q.lo << 1) | carry
|
||||
// carry: u64
|
||||
// for ; sr > 0; sr-- {
|
||||
// r.hi = (r.hi << 1) | (r.lo >> (64-1))
|
||||
// r.lo = (r.lo << 1) | (r.hi >> (64-1))
|
||||
// q.hi = (q.hi << 1) | (q.lo >> (64-1))
|
||||
// q.lo = (q.lo << 1) | carry
|
||||
|
||||
carry = 0
|
||||
if r.all >= d.all {
|
||||
r.all -= d.all
|
||||
carry = 1
|
||||
}
|
||||
}
|
||||
// carry = 0
|
||||
// if r.all >= d.all {
|
||||
// r.all -= d.all
|
||||
// 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_COUNT;
|
||||
);
|
||||
|
||||
)
|
||||
// NOTE(bill): Uses startup to initialize it
|
||||
var (
|
||||
__std_files = [FILE_STANDARD_COUNT]File{
|
||||
|
||||
+8
-6
@@ -8,11 +8,11 @@ const (
|
||||
|
||||
SURROGATE_MIN = 0xd800;
|
||||
SURROGATE_MAX = 0xdfff;
|
||||
);
|
||||
)
|
||||
|
||||
type Accept_Range struct {
|
||||
lo, hi u8;
|
||||
};
|
||||
}
|
||||
|
||||
var (
|
||||
accept_ranges = [5]Accept_Range{
|
||||
@@ -99,10 +99,12 @@ proc decode_rune(s string) -> (rune, int) {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
|
||||
const MASK_X = 0b00111111;
|
||||
const MASK_2 = 0b00011111;
|
||||
const MASK_3 = 0b00001111;
|
||||
const MASK_4 = 0b00000111;
|
||||
const (
|
||||
MASK_X = 0b00111111;
|
||||
MASK_2 = 0b00011111;
|
||||
MASK_3 = 0b00001111;
|
||||
MASK_4 = 0b00000111;
|
||||
)
|
||||
|
||||
if size == 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) {
|
||||
AstNode *spec = gd->specs.e[iota];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(bd, BadDecl, decl);
|
||||
case_end;
|
||||
case_ast_node(is, ImportSpec, spec);
|
||||
if (!parent_scope->is_file) {
|
||||
// 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
|
||||
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);
|
||||
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) {
|
||||
AstNode *spec = gd->specs.e[iota];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(bd, BadDecl, spec);
|
||||
case_end;
|
||||
case_ast_node(vs, ValueSpec, spec);
|
||||
switch (vs->keyword) {
|
||||
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);
|
||||
for_array(decl_index, decls) {
|
||||
AstNode *decl = decls.e[decl_index];
|
||||
if (decl->kind != AstNode_Parameter) {
|
||||
if (decl->kind != AstNode_Field) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ast_node(p, Parameter, decl);
|
||||
Type *base_type = check_type_extra(c, p->type, NULL);
|
||||
ast_node(f, Field, decl);
|
||||
Type *base_type = check_type_extra(c, f->type, NULL);
|
||||
|
||||
for_array(name_index, p->names) {
|
||||
AstNode *name = p->names.e[name_index];
|
||||
for_array(name_index, f->names) {
|
||||
AstNode *name = f->names.e[name_index];
|
||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
||||
continue;
|
||||
}
|
||||
@@ -493,28 +495,28 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
||||
isize field_index = 0;
|
||||
for_array(decl_index, decls) {
|
||||
AstNode *decl = decls.e[decl_index];
|
||||
if (decl->kind != AstNode_Parameter) {
|
||||
if (decl->kind != AstNode_Field) {
|
||||
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 (param->names.count > 1) {
|
||||
error_node(param->names.e[0], "Cannot apply `using` to more than one of the same type");
|
||||
if (f->is_using) {
|
||||
if (f->names.count > 1) {
|
||||
error_node(f->names.e[0], "Cannot apply `using` to more than one of the same type");
|
||||
}
|
||||
}
|
||||
|
||||
for_array(name_index, param->names) {
|
||||
AstNode *name = param->names.e[name_index];
|
||||
for_array(name_index, f->names) {
|
||||
AstNode *name = f->names.e[name_index];
|
||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
if (str_eq(name_token.string, str_lit("_"))) {
|
||||
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));
|
||||
if (!is_type_struct(t) && !is_type_raw_union(t) &&
|
||||
param->names.count >= 1 &&
|
||||
param->names.e[0]->kind == AstNode_Ident) {
|
||||
Token name_token = param->names.e[0]->Ident;
|
||||
f->names.count >= 1 &&
|
||||
f->names.e[0]->kind == AstNode_Ident) {
|
||||
Token name_token = f->names.e[0]->Ident;
|
||||
if (is_type_indexable(t)) {
|
||||
bool ok = true;
|
||||
for_array(emi, entity_map.entries) {
|
||||
Entity *e = entity_map.entries.e[emi].value;
|
||||
if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) {
|
||||
if (is_type_indexable(e->type)) {
|
||||
if (e->identifier != param->names.e[0]) {
|
||||
if (e->identifier != f->names.e[0]) {
|
||||
ok = false;
|
||||
using_index_expr = e;
|
||||
break;
|
||||
@@ -613,8 +615,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) {
|
||||
for_array(field_index, st->fields) {
|
||||
AstNode *field = st->fields.e[field_index];
|
||||
switch (field->kind) {
|
||||
case_ast_node(p, Parameter, field);
|
||||
field_count += p->names.count;
|
||||
case_ast_node(f, Field, field);
|
||||
field_count += f->names.count;
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
@@ -662,8 +664,8 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||
for_array(field_index, ut->fields) {
|
||||
AstNode *field = ut->fields.e[field_index];
|
||||
switch (field->kind) {
|
||||
case_ast_node(p, Parameter, field);
|
||||
field_count += p->names.count;
|
||||
case_ast_node(f, Field, field);
|
||||
field_count += f->names.count;
|
||||
case_end;
|
||||
}
|
||||
}
|
||||
@@ -685,8 +687,8 @@ void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||
for_array(field_index, ut->fields) {
|
||||
AstNode *field = ut->fields.e[field_index];
|
||||
switch (field->kind) {
|
||||
case_ast_node(p, Parameter, field);
|
||||
field_count += p->names.count;
|
||||
case_ast_node(f, Field, field);
|
||||
field_count += f->names.count;
|
||||
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;
|
||||
}
|
||||
|
||||
GB_COMPARE_PROC(cmp_enum_order) {
|
||||
// Rule:
|
||||
// Biggest to smallest alignment
|
||||
// if same alignment: biggest to smallest size
|
||||
// if same size: order by source order
|
||||
Entity *x = *(Entity **)a;
|
||||
Entity *y = *(Entity **)b;
|
||||
GB_ASSERT(x != NULL);
|
||||
GB_ASSERT(y != NULL);
|
||||
GB_ASSERT(x->kind == Entity_Constant);
|
||||
GB_ASSERT(y->kind == Entity_Constant);
|
||||
GB_ASSERT(x->Constant.value.kind == ExactValue_Integer);
|
||||
GB_ASSERT(y->Constant.value.kind == ExactValue_Integer);
|
||||
i64 i = x->Constant.value.value_integer;
|
||||
i64 j = y->Constant.value.value_integer;
|
||||
// GB_COMPARE_PROC(cmp_enum_order) {
|
||||
// // Rule:
|
||||
// // Biggest to smallest alignment
|
||||
// // if same alignment: biggest to smallest size
|
||||
// // if same size: order by source order
|
||||
// Entity *x = *(Entity **)a;
|
||||
// Entity *y = *(Entity **)b;
|
||||
// GB_ASSERT(x != NULL);
|
||||
// GB_ASSERT(y != NULL);
|
||||
// GB_ASSERT(x->kind == Entity_Constant);
|
||||
// GB_ASSERT(y->kind == Entity_Constant);
|
||||
// GB_ASSERT(x->Constant.value.kind == ExactValue_Integer);
|
||||
// GB_ASSERT(y->Constant.value.kind == ExactValue_Integer);
|
||||
// i64 i = x->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_) {
|
||||
if (params.count == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool is_variadic = false;
|
||||
|
||||
Type *tuple = make_type_tuple(c->allocator);
|
||||
|
||||
isize variable_count = 0;
|
||||
for_array(i, params) {
|
||||
AstNode *field = params.e[i];
|
||||
if (!ast_node_expect(field, AstNode_Parameter)) {
|
||||
continue;
|
||||
if (ast_node_expect(field, AstNode_Field)) {
|
||||
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);
|
||||
isize variable_index = 0;
|
||||
for_array(i, params) {
|
||||
if (params.e[i]->kind != AstNode_Parameter) {
|
||||
if (params.e[i]->kind != AstNode_Field) {
|
||||
continue;
|
||||
}
|
||||
ast_node(p, Parameter, params.e[i]);
|
||||
ast_node(p, Field, params.e[i]);
|
||||
AstNode *type_expr = p->type;
|
||||
if (type_expr) {
|
||||
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);
|
||||
}
|
||||
|
||||
Type *tuple = make_type_tuple(c->allocator);
|
||||
tuple->Tuple.variables = variables;
|
||||
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_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);
|
||||
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 {
|
||||
if (proc_type == NULL) {
|
||||
gbString str = expr_to_string(node);
|
||||
error_node(node, "Invalid procedure literal `%s`", str);
|
||||
gb_string_free(str);
|
||||
check_close_scope(c);
|
||||
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_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) {
|
||||
for_array(i, params) {
|
||||
ast_node(p, Parameter, params.e[i]);
|
||||
ast_node(p, Field, params.e[i]);
|
||||
if (i > 0) {
|
||||
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);
|
||||
case_end;
|
||||
|
||||
case_ast_node(p, Parameter, node);
|
||||
case_ast_node(p, Field, node);
|
||||
if (p->is_using) {
|
||||
str = gb_string_appendc(str, "using ");
|
||||
}
|
||||
for_array(i, p->names) {
|
||||
AstNode *name = p->names.e[i];
|
||||
if (i > 0)
|
||||
if (i > 0) {
|
||||
str = gb_string_appendc(str, ", ");
|
||||
}
|
||||
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) {
|
||||
AstNode *spec = gd->specs.e[spec_index];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(bd, BadDecl, spec);
|
||||
case_end;
|
||||
case_ast_node(vs, ValueSpec, spec);
|
||||
switch (vs->keyword) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
gb_printf_err("%s is a tool for managing Odin source code\n", argv0);
|
||||
gb_printf_err("Usage:");
|
||||
gb_printf_err("\n\t%s command [arguments]\n", argv0);
|
||||
gb_printf_err("Commands:");
|
||||
gb_printf_err("\n\tbuild compile .odin file");
|
||||
gb_printf_err("\n\tbuild_dll compile .odin file as dll");
|
||||
gb_printf_err("\n\trun compile and run .odin file");
|
||||
gb_printf_err("\n\tversion print Odin version");
|
||||
gb_printf_err("\n\n");
|
||||
print_usage_line(0, "%s is a tool for managing Odin source code", argv0);
|
||||
print_usage_line(0, "Usage:");
|
||||
print_usage_line(1, "%s command [arguments]", argv0);
|
||||
print_usage_line(0, "Commands:");
|
||||
print_usage_line(1, "build compile .odin file as executable");
|
||||
print_usage_line(1, "build_dll compile .odin file as dll");
|
||||
print_usage_line(1, "run compile and run .odin file");
|
||||
print_usage_line(1, "version print version");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
+116
-88
@@ -57,6 +57,7 @@ typedef struct Parser {
|
||||
Array(ImportedFile) imports;
|
||||
gbAtomic32 import_index;
|
||||
isize total_token_count;
|
||||
isize total_line_count;
|
||||
gbMutex mutex;
|
||||
} Parser;
|
||||
|
||||
@@ -176,52 +177,56 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
||||
AstNodeArray results; \
|
||||
}) \
|
||||
AST_NODE_KIND(ForStmt, "for statement", struct { \
|
||||
Token token; \
|
||||
AstNode *init, *cond, *post; \
|
||||
Token token; \
|
||||
AstNode *init; \
|
||||
AstNode *cond; \
|
||||
AstNode *post; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
AST_NODE_KIND(CaseClause, "case clause", struct { \
|
||||
Token token; \
|
||||
AstNodeArray list, stmts; \
|
||||
Token token; \
|
||||
AstNodeArray list; \
|
||||
AstNodeArray stmts; \
|
||||
}) \
|
||||
AST_NODE_KIND(MatchStmt, "match statement", struct { \
|
||||
Token token; \
|
||||
AstNode *init, *tag; \
|
||||
Token token; \
|
||||
AstNode *init; \
|
||||
AstNode *tag; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeMatchStmt, "type match statement", struct { \
|
||||
Token token; \
|
||||
AstNode *tag, *var; \
|
||||
AstNode *body; \
|
||||
Token token; \
|
||||
AstNode *tag; \
|
||||
AstNode *var; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
AST_NODE_KIND(DeferStmt, "defer statement", struct { Token token; AstNode *stmt; }) \
|
||||
AST_NODE_KIND(BranchStmt, "branch statement", struct { Token token; }) \
|
||||
AST_NODE_KIND(UsingStmt, "using statement", struct { Token token; AstNode *node; }) \
|
||||
AST_NODE_KIND(AsmOperand, "assembly operand", struct { \
|
||||
Token string; \
|
||||
Token string; \
|
||||
AstNode *operand; \
|
||||
}) \
|
||||
AST_NODE_KIND(AsmStmt, "assembly statement", struct { \
|
||||
Token token; \
|
||||
bool is_volatile; \
|
||||
Token open, close; \
|
||||
Token code_string; \
|
||||
AstNode *output_list; \
|
||||
AstNode *input_list; \
|
||||
Token token; \
|
||||
bool is_volatile; \
|
||||
Token open, close; \
|
||||
Token code_string; \
|
||||
AstNode *output_list; \
|
||||
AstNode *input_list; \
|
||||
AstNode *clobber_list; \
|
||||
isize output_count, input_count, clobber_count; \
|
||||
}) \
|
||||
AST_NODE_KIND(PushAllocator, "push_allocator statement", struct { \
|
||||
Token token; \
|
||||
Token token; \
|
||||
AstNode *expr; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
AST_NODE_KIND(PushContext, "push_context statement", struct { \
|
||||
Token token; \
|
||||
Token token; \
|
||||
AstNode *expr; \
|
||||
AstNode *body; \
|
||||
}) \
|
||||
\
|
||||
AST_NODE_KIND(_ComplexStmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_StmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_SpecBegin, "", i32) \
|
||||
@@ -237,12 +242,12 @@ AST_NODE_KIND(_SpecBegin, "", i32) \
|
||||
AstNode *note; \
|
||||
}) \
|
||||
AST_NODE_KIND(ImportSpec, "import specification", struct { \
|
||||
Token relpath; \
|
||||
String fullpath; \
|
||||
Token import_name; \
|
||||
bool is_load; \
|
||||
AstNode *cond; \
|
||||
AstNode *note; \
|
||||
TokenKind keyword; \
|
||||
Token relpath; \
|
||||
String fullpath; \
|
||||
Token import_name; \
|
||||
AstNode *cond; \
|
||||
AstNode *note; \
|
||||
}) \
|
||||
AST_NODE_KIND(_SpecEnd, "", i32) \
|
||||
AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
@@ -270,12 +275,12 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
bool is_system; \
|
||||
}) \
|
||||
AST_NODE_KIND(_DeclEnd, "", i32) \
|
||||
AST_NODE_KIND(_TypeBegin, "", i32) \
|
||||
AST_NODE_KIND(Parameter, "parameter", struct { \
|
||||
AstNodeArray names; \
|
||||
AstNode *type; \
|
||||
bool is_using; \
|
||||
AST_NODE_KIND(Field, "field", struct { \
|
||||
AstNodeArray names; \
|
||||
AstNode * type; \
|
||||
bool is_using; \
|
||||
}) \
|
||||
AST_NODE_KIND(_TypeBegin, "", i32) \
|
||||
AST_NODE_KIND(ProcType, "procedure type", struct { \
|
||||
Token token; \
|
||||
AstNodeArray params; \
|
||||
@@ -477,11 +482,11 @@ Token ast_node_token(AstNode *node) {
|
||||
case AstNode_ImportSpec:
|
||||
return node->ImportSpec.relpath;
|
||||
|
||||
case AstNode_Parameter: {
|
||||
if (node->Parameter.names.count > 0) {
|
||||
return ast_node_token(node->Parameter.names.e[0]);
|
||||
case AstNode_Field: {
|
||||
if (node->Field.names.count > 0) {
|
||||
return ast_node_token(node->Field.names.e[0]);
|
||||
} else {
|
||||
return ast_node_token(node->Parameter.type);
|
||||
return ast_node_token(node->Field.type);
|
||||
}
|
||||
}
|
||||
case AstNode_ProcType:
|
||||
@@ -898,11 +903,11 @@ AstNode *make_bad_decl(AstFile *f, Token begin, Token end) {
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, bool is_using) {
|
||||
AstNode *result = make_node(f, AstNode_Parameter);
|
||||
result->Parameter.names = names;
|
||||
result->Parameter.type = type;
|
||||
result->Parameter.is_using = is_using;
|
||||
AstNode *make_field(AstFile *f, AstNodeArray names, AstNode *type, bool is_using) {
|
||||
AstNode *result = make_node(f, AstNode_Field);
|
||||
result->Field.names = names;
|
||||
result->Field.type = type;
|
||||
result->Field.is_using = is_using;
|
||||
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);
|
||||
result->ImportSpec.keyword = keyword;
|
||||
result->ImportSpec.relpath = relpath;
|
||||
result->ImportSpec.import_name = import_name;
|
||||
result->ImportSpec.cond = cond;
|
||||
result->ImportSpec.is_load = is_load;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1057,6 +1062,21 @@ bool next_token(AstFile *f) {
|
||||
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 prev = f->curr_token;
|
||||
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) {
|
||||
// for_array(i, names) {
|
||||
// AstNode *name = names.e[i];
|
||||
// if (name->kind == AstNode_Ident) {
|
||||
// String n = name->Ident.string;
|
||||
// // NOTE(bill): Check for reserved identifiers
|
||||
// if (str_eq(n, str_lit("context"))) {
|
||||
// syntax_error_node(name, "`context` is a reserved identifier");
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
for_array(i, names) {
|
||||
AstNode *name = names.e[i];
|
||||
if (name->kind == AstNode_Ident) {
|
||||
String n = name->Ident.string;
|
||||
// NOTE(bill): Check for reserved identifiers
|
||||
if (str_eq(n, str_lit("context"))) {
|
||||
syntax_error_node(name, "`context` is a reserved identifier");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
spec = make_bad_decl(f, import_name, file_path);
|
||||
} 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;
|
||||
}
|
||||
@@ -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");
|
||||
spec = make_bad_decl(f, import_name, file_path);
|
||||
} 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;
|
||||
}
|
||||
@@ -2060,11 +2080,7 @@ AstNode *parse_simple_stmt(AstFile *f) {
|
||||
return parse_decl(f);
|
||||
}
|
||||
|
||||
isize lhs_count = 0, rhs_count = 0;
|
||||
AstNodeArray lhs = parse_lhs_expr_list(f);
|
||||
|
||||
|
||||
AstNode *statement = NULL;
|
||||
Token token = f->curr_token;
|
||||
switch (token.kind) {
|
||||
case Token_Eq:
|
||||
@@ -2096,7 +2112,7 @@ AstNode *parse_simple_stmt(AstFile *f) {
|
||||
} break;
|
||||
}
|
||||
|
||||
if (lhs_count > 1) {
|
||||
if (lhs.count > 1) {
|
||||
syntax_error(token, "Expected 1 expression");
|
||||
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");
|
||||
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);
|
||||
return statement;
|
||||
return stmt;
|
||||
}
|
||||
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
AstNode *param = make_parameter(f, names, type, is_using);
|
||||
AstNode *param = make_field(f, names, type, is_using);
|
||||
array_add(¶ms, param);
|
||||
|
||||
|
||||
if (separator == Token_Semicolon) {
|
||||
expect_semicolon(f, param);
|
||||
} 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) {
|
||||
return parse_parameter_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace);
|
||||
AstNodeArray parse_record_fields(AstFile *f, isize *field_count_, bool allow_using, String context) {
|
||||
return parse_field_list(f, field_count_, allow_using, Token_Semicolon, Token_CloseBrace);
|
||||
}
|
||||
|
||||
AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
@@ -2295,7 +2310,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
bool is_packed = false;
|
||||
bool is_ordered = false;
|
||||
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 (is_packed) {
|
||||
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");
|
||||
}
|
||||
|
||||
Token open = expect_token_after(f, Token_OpenBrace, "`struct`");
|
||||
Token open = expect_token_after(f, Token_OpenBrace, "struct");
|
||||
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);
|
||||
|
||||
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: {
|
||||
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;
|
||||
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);
|
||||
|
||||
return make_union_type(f, token, decls, decl_count);
|
||||
@@ -2335,9 +2350,9 @@ AstNode *parse_identifier_or_type(AstFile *f) {
|
||||
|
||||
case 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;
|
||||
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);
|
||||
|
||||
return make_raw_union_type(f, token, decls, decl_count);
|
||||
@@ -2391,7 +2406,7 @@ void parse_proc_signature(AstFile *f,
|
||||
AstNodeArray *params,
|
||||
AstNodeArray *results) {
|
||||
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");
|
||||
*results = parse_results(f);
|
||||
}
|
||||
@@ -2409,8 +2424,14 @@ AstNode *parse_body(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);
|
||||
|
||||
AstNodeArray params = {0};
|
||||
@@ -2426,19 +2447,18 @@ AstNode *parse_proc_decl(AstFile *f) {
|
||||
|
||||
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 ((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);
|
||||
f->curr_proc = curr_proc;
|
||||
} 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);
|
||||
}
|
||||
|
||||
@@ -2958,6 +2978,11 @@ AstNodeArray parse_stmt_list(AstFile *f) {
|
||||
AstNode *stmt = parse_stmt(f);
|
||||
if (stmt && stmt->kind != AstNode_EmptyStmt) {
|
||||
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) {
|
||||
destroy_ast_file(&p->files.e[i]);
|
||||
}
|
||||
#if 1
|
||||
#if 0
|
||||
for_array(i, p->imports) {
|
||||
// gb_free(heap_allocator(), p->imports[i].text);
|
||||
}
|
||||
@@ -3093,21 +3118,23 @@ bool is_import_path_valid(String path) {
|
||||
u8 *start = path.text;
|
||||
u8 *end = path.text + path.len;
|
||||
u8 *curr = start;
|
||||
Rune r = -1;
|
||||
while (curr < end) {
|
||||
isize width = 1;
|
||||
r = curr[0];
|
||||
Rune r = curr[0];
|
||||
if (r >= 0x80) {
|
||||
width = gb_utf8_decode(curr, end-curr, &r);
|
||||
if (r == GB_RUNE_INVALID && width == 1)
|
||||
if (r == GB_RUNE_INVALID && width == 1) {
|
||||
return false;
|
||||
else if (r == GB_RUNE_BOM && curr-start > 0)
|
||||
}
|
||||
else if (r == GB_RUNE_BOM && curr-start > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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));
|
||||
} else {
|
||||
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);
|
||||
file.id = p->files.count;
|
||||
array_add(&p->files, file);
|
||||
p->total_line_count += file.tokenizer.line_count;
|
||||
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) {
|
||||
return ssa_addr_load(proc, ssa_build_addr(proc, expr));
|
||||
}
|
||||
GB_PANIC("nil value for expression from identifier: %.*s", LIT(i->string));
|
||||
return NULL;
|
||||
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);
|
||||
|
||||
value->Proc.tags = pl->tags;
|
||||
value->Proc.parent = proc;
|
||||
|
||||
array_add(&proc->children, &value->Proc);
|
||||
ssa_build_proc(value, proc);
|
||||
array_add(&proc->module->procs_to_generate, value);
|
||||
|
||||
return value;
|
||||
case_end;
|
||||
@@ -2971,32 +2973,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
||||
|
||||
} 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: {
|
||||
ssa_emit_comment(proc, str_lit("slice_ptr"));
|
||||
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
|
||||
ssaValue *value = ssa_build_expr(proc, ce->proc);
|
||||
GB_ASSERT(value != NULL);
|
||||
Type *proc_type_ = base_type(ssa_type(value));
|
||||
GB_ASSERT(proc_type_->kind == 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) {
|
||||
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);
|
||||
@@ -3293,7 +3269,9 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
||||
|
||||
case_ast_node(se, SelectorExpr, expr);
|
||||
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));
|
||||
|
||||
if (type == t_invalid) {
|
||||
@@ -4958,7 +4936,7 @@ void ssa_gen_tree(ssaGen *s) {
|
||||
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);
|
||||
} 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);
|
||||
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);
|
||||
if (map_ssa_value_get(&m->members, hash_name) == NULL) {
|
||||
map_ssa_value_set(&m->members, hash_name, p);
|
||||
|
||||
Reference in New Issue
Block a user