mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
when ODIN_OS == "windows" {
|
when ODIN_OS == "windows" {
|
||||||
import win32 "core:sys/windows.odin"
|
import win32 "core:sys/windows.odin"
|
||||||
}
|
}
|
||||||
_ :: compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
#assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
||||||
|
|
||||||
|
|
||||||
yield_thread :: proc() { win32.mm_pause(); }
|
yield_thread :: proc() { win32.mm_pause(); }
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ c_double :: f64;
|
|||||||
c_complex_float :: complex64;
|
c_complex_float :: complex64;
|
||||||
c_complex_double :: complex128;
|
c_complex_double :: complex128;
|
||||||
|
|
||||||
_ :: compile_assert(size_of(uintptr) == size_of(int));
|
#assert(size_of(uintptr) == size_of(int));
|
||||||
|
|
||||||
c_size_t :: uint;
|
c_size_t :: uint;
|
||||||
c_ssize_t :: int;
|
c_ssize_t :: int;
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ when ODIN_OS == "windows" {
|
|||||||
|
|
||||||
export "core:opengl_constants.odin"
|
export "core:opengl_constants.odin"
|
||||||
|
|
||||||
_ := compile_assert(ODIN_OS != "osx");
|
(ODIN_OS != "osx");
|
||||||
|
|
||||||
@(default_calling_convention="c", link_prefix="gl")
|
@(default_calling_convention="c", link_prefix="gl")
|
||||||
foreign lib {
|
foreign lib {
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
_ :: compile_assert(ODIN_OS == "windows");
|
#assert(ODIN_OS == "windows");
|
||||||
|
|
||||||
when ODIN_OS == "windows" {
|
when ODIN_OS == "windows" {
|
||||||
import win32 "core:sys/windows.odin"
|
import win32 "core:sys/windows.odin"
|
||||||
|
|||||||
+4
-3
@@ -101,13 +101,13 @@ general_stuff :: proc() {
|
|||||||
// If the type expression is `struct`, `union`, `enum`, `proc`, or `bit_field`, the types will always been distinct.
|
// If the type expression is `struct`, `union`, `enum`, `proc`, or `bit_field`, the types will always been distinct.
|
||||||
|
|
||||||
Int32 :: i32;
|
Int32 :: i32;
|
||||||
compile_assert(Int32 == i32);
|
#assert(Int32 == i32);
|
||||||
|
|
||||||
My_Int32 :: distinct i32;
|
My_Int32 :: distinct i32;
|
||||||
compile_assert(My_Int32 != i32);
|
#assert(My_Int32 != i32);
|
||||||
|
|
||||||
My_Struct :: struct{x: int};
|
My_Struct :: struct{x: int};
|
||||||
compile_assert(My_Struct != struct{x: int});
|
#assert(My_Struct != struct{x: int});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,6 +760,7 @@ complete_switch :: proc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
when true {
|
when true {
|
||||||
general_stuff();
|
general_stuff();
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ miscellany :: proc() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// assert(false)
|
// assert(false)
|
||||||
// compile_assert(false)
|
// #assert(false)
|
||||||
// panic("Panic message goes here")
|
// panic("Panic message goes here")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -171,8 +171,8 @@ new_builtins :: proc() {
|
|||||||
{
|
{
|
||||||
// Compile time assert
|
// Compile time assert
|
||||||
COND :: true;
|
COND :: true;
|
||||||
compile_assert(COND);
|
#assert(COND);
|
||||||
// compile_assert(!COND)
|
// #assert(!COND)
|
||||||
|
|
||||||
// Runtime assert
|
// Runtime assert
|
||||||
x := true;
|
x := true;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ syntax :: proc() {
|
|||||||
Thing2 :: struct {x: f32, y: int, z: ^[]int};
|
Thing2 :: struct {x: f32, y: int, z: ^[]int};
|
||||||
|
|
||||||
// Slice interals are now just a `ptr+len+cap`
|
// Slice interals are now just a `ptr+len+cap`
|
||||||
slice: []int; compile_assert(size_of(slice) == 3*size_of(int));
|
slice: []int; #assert(size_of(slice) == 3*size_of(int));
|
||||||
|
|
||||||
// Helper type - Help the reader understand what it is quicker
|
// Helper type - Help the reader understand what it is quicker
|
||||||
My_Int :: #type int;
|
My_Int :: #type int;
|
||||||
@@ -218,7 +218,7 @@ loops :: proc() {
|
|||||||
name := "你好,世界";
|
name := "你好,世界";
|
||||||
fmt.println(name);
|
fmt.println(name);
|
||||||
for r in name {
|
for r in name {
|
||||||
compile_assert(type_of(r) == rune);
|
#assert(type_of(r) == rune);
|
||||||
fmt.printf("%r\n", r);
|
fmt.printf("%r\n", r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ when true {
|
|||||||
* ..< and ... removed and replace with .. (half-closed range)
|
* ..< and ... removed and replace with .. (half-closed range)
|
||||||
|
|
||||||
Changed:
|
Changed:
|
||||||
* `compile_assert` and `assert` return the value of the condition for semantic reasons
|
* `#assert` and `assert` return the value of the condition for semantic reasons
|
||||||
* thread_local -> #thread_local
|
* thread_local -> #thread_local
|
||||||
* #include -> #load
|
* #include -> #load
|
||||||
* Files only get checked if they are actually used
|
* Files only get checked if they are actually used
|
||||||
@@ -159,8 +159,8 @@ when true {
|
|||||||
fmt.println(i);
|
fmt.println(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
compile_assert(size_of([vector 7]bool) >= size_of([7]bool));
|
#assert(size_of([vector 7]bool) >= size_of([7]bool));
|
||||||
compile_assert(size_of([vector 7]i32) >= size_of([7]i32));
|
#assert(size_of([vector 7]i32) >= size_of([7]i32));
|
||||||
// align_of([vector 7]i32) != align_of([7]i32) // this may be the case
|
// align_of([vector 7]i32) != align_of([7]i32) // this may be the case
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ memory_copy :: proc(dst, src: rawptr, n: int) #inline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v128b :: type {4}u32
|
v128b :: type {4}u32
|
||||||
compile_assert(align_of(v128b) == 16)
|
#assert(align_of(v128b) == 16)
|
||||||
|
|
||||||
d, s: ^byte = dst, src
|
d, s: ^byte = dst, src
|
||||||
|
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ general_stuff :: proc() {
|
|||||||
foo := Foo{123, 0.513, "A string"};
|
foo := Foo{123, 0.513, "A string"};
|
||||||
x, y, z := expand_to_tuple(foo);
|
x, y, z := expand_to_tuple(foo);
|
||||||
fmt.println(x, y, z);
|
fmt.println(x, y, z);
|
||||||
compile_assert(type_of(x) == int);
|
#assert(type_of(x) == int);
|
||||||
compile_assert(type_of(y) == f32);
|
#assert(type_of(y) == f32);
|
||||||
compile_assert(type_of(z) == string);
|
#assert(type_of(z) == string);
|
||||||
|
|
||||||
|
|
||||||
// By default, all variables are zeroed
|
// By default, all variables are zeroed
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ CANVAS_SCALE :: 3;
|
|||||||
FRAME_TIME :: 1.0/30.0;
|
FRAME_TIME :: 1.0/30.0;
|
||||||
WINDOW_TITLE :: "Punity\x00";
|
WINDOW_TITLE :: "Punity\x00";
|
||||||
|
|
||||||
_ :: compile_assert(CANVAS_WIDTH % 16 == 0);
|
#assert(CANVAS_WIDTH % 16 == 0);
|
||||||
|
|
||||||
|
|
||||||
WINDOW_WIDTH :: CANVAS_WIDTH * CANVAS_SCALE;
|
WINDOW_WIDTH :: CANVAS_WIDTH * CANVAS_SCALE;
|
||||||
|
|||||||
+48
-43
@@ -2813,28 +2813,49 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
case BuiltinProc_DIRECTIVE: {
|
case BuiltinProc_DIRECTIVE: {
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
String name = bd->name;
|
String name = bd->name;
|
||||||
GB_ASSERT(name == "location");
|
if (name == "location") {
|
||||||
if (ce->args.count > 1) {
|
if (ce->args.count > 1) {
|
||||||
error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count);
|
error(ce->args[0], "'#location' expects either 0 or 1 arguments, got %td", ce->args.count);
|
||||||
}
|
|
||||||
if (ce->args.count > 0) {
|
|
||||||
AstNode *arg = ce->args[0];
|
|
||||||
Entity *e = nullptr;
|
|
||||||
Operand o = {};
|
|
||||||
if (arg->kind == AstNode_Ident) {
|
|
||||||
e = check_ident(c, &o, arg, nullptr, nullptr, true);
|
|
||||||
} else if (arg->kind == AstNode_SelectorExpr) {
|
|
||||||
e = check_selector(c, &o, arg, nullptr);
|
|
||||||
}
|
}
|
||||||
if (e == nullptr) {
|
if (ce->args.count > 0) {
|
||||||
error(ce->args[0], "'#location' expected a valid entity name");
|
AstNode *arg = ce->args[0];
|
||||||
|
Entity *e = nullptr;
|
||||||
|
Operand o = {};
|
||||||
|
if (arg->kind == AstNode_Ident) {
|
||||||
|
e = check_ident(c, &o, arg, nullptr, nullptr, true);
|
||||||
|
} else if (arg->kind == AstNode_SelectorExpr) {
|
||||||
|
e = check_selector(c, &o, arg, nullptr);
|
||||||
|
}
|
||||||
|
if (e == nullptr) {
|
||||||
|
error(ce->args[0], "'#location' expected a valid entity name");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operand->type = t_source_code_location;
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
} else if (name == "assert") {
|
||||||
|
if (ce->args.count != 1) {
|
||||||
|
error(call, "'#assert' expects at 1 argument, got %td", ce->args.count);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) {
|
||||||
|
gbString str = expr_to_string(ce->args[0]);
|
||||||
|
error(call, "'%s' is not a constant boolean", str);
|
||||||
|
gb_string_free(str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!operand->value.value_bool) {
|
||||||
|
gbString arg = expr_to_string(ce->args[0]);
|
||||||
|
error(call, "Compile time assertion: %s", arg);
|
||||||
|
gb_string_free(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
operand->type = t_untyped_bool;
|
||||||
|
operand->mode = Addressing_Constant;
|
||||||
|
} else {
|
||||||
|
GB_PANIC("Unhandled #%.*s", LIT(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
operand->type = t_source_code_location;
|
|
||||||
operand->mode = Addressing_Value;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3321,25 +3342,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BuiltinProc_compile_assert:
|
|
||||||
// proc compile_assert(cond: bool) -> bool
|
|
||||||
|
|
||||||
if (!is_type_boolean(operand->type) && operand->mode != Addressing_Constant) {
|
|
||||||
gbString str = expr_to_string(ce->args[0]);
|
|
||||||
error(call, "'%s' is not a constant boolean", str);
|
|
||||||
gb_string_free(str);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!operand->value.value_bool) {
|
|
||||||
gbString str = expr_to_string(ce->args[0]);
|
|
||||||
error(call, "Compile time assertion: '%s'", str);
|
|
||||||
gb_string_free(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
operand->mode = Addressing_Constant;
|
|
||||||
operand->type = t_untyped_bool;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BuiltinProc_swizzle: {
|
case BuiltinProc_swizzle: {
|
||||||
// proc swizzle(v: [N]T, ...int) -> [M]T
|
// proc swizzle(v: [N]T, ...int) -> [M]T
|
||||||
Type *type = base_type(operand->type);
|
Type *type = base_type(operand->type);
|
||||||
@@ -4805,12 +4807,15 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
|||||||
ce->proc->kind == AstNode_BasicDirective) {
|
ce->proc->kind == AstNode_BasicDirective) {
|
||||||
ast_node(bd, BasicDirective, ce->proc);
|
ast_node(bd, BasicDirective, ce->proc);
|
||||||
String name = bd->name;
|
String name = bd->name;
|
||||||
GB_ASSERT(name == "location");
|
if (name == "location" || name == "assert") {
|
||||||
operand->mode = Addressing_Builtin;
|
operand->mode = Addressing_Builtin;
|
||||||
operand->builtin_id = BuiltinProc_DIRECTIVE;
|
operand->builtin_id = BuiltinProc_DIRECTIVE;
|
||||||
operand->expr = ce->proc;
|
operand->expr = ce->proc;
|
||||||
operand->type = t_invalid;
|
operand->type = t_invalid;
|
||||||
add_type_and_value(&c->info, ce->proc, operand->mode, operand->type, operand->value);
|
add_type_and_value(&c->info, ce->proc, operand->mode, operand->type, operand->value);
|
||||||
|
} else {
|
||||||
|
GB_PANIC("Unhandled #%.*s", LIT(name));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
check_expr_or_type(c, operand, ce->proc);
|
check_expr_or_type(c, operand, ce->proc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "entity.cpp"
|
#include "entity.cpp"
|
||||||
#include "types.cpp"
|
#include "types.cpp"
|
||||||
|
|
||||||
|
void check_expr(Checker *c, Operand *operand, AstNode *expression);
|
||||||
|
|
||||||
|
|
||||||
bool is_operand_value(Operand o) {
|
bool is_operand_value(Operand o) {
|
||||||
switch (o.mode) {
|
switch (o.mode) {
|
||||||
@@ -272,6 +274,7 @@ void destroy_scope(Scope *scope) {
|
|||||||
map_destroy(&scope->elements);
|
map_destroy(&scope->elements);
|
||||||
array_free(&scope->shared);
|
array_free(&scope->shared);
|
||||||
array_free(&scope->delayed_file_decls);
|
array_free(&scope->delayed_file_decls);
|
||||||
|
array_free(&scope->delayed_asserts);
|
||||||
ptr_set_destroy(&scope->implicit);
|
ptr_set_destroy(&scope->implicit);
|
||||||
ptr_set_destroy(&scope->imported);
|
ptr_set_destroy(&scope->imported);
|
||||||
ptr_set_destroy(&scope->exported);
|
ptr_set_destroy(&scope->exported);
|
||||||
@@ -444,6 +447,7 @@ GB_COMPARE_PROC(entity_variable_pos_cmp) {
|
|||||||
return token_pos_cmp(x->token.pos, y->token.pos);
|
return token_pos_cmp(x->token.pos, y->token.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_scope_usage(Checker *c, Scope *scope) {
|
void check_scope_usage(Checker *c, Scope *scope) {
|
||||||
// TODO(bill): Use this?
|
// TODO(bill): Use this?
|
||||||
#if 0
|
#if 0
|
||||||
@@ -2678,6 +2682,14 @@ bool collect_file_decls(Checker *c, Array<AstNode *> decls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(ce, CallExpr, decl);
|
||||||
|
if (ce->proc->kind == AstNode_BasicDirective &&
|
||||||
|
ce->proc->BasicDirective.name == "assert") {
|
||||||
|
Operand o = {};
|
||||||
|
check_expr(c, &o, decl);
|
||||||
|
}
|
||||||
|
case_end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-4
@@ -90,8 +90,6 @@ enum BuiltinProcId {
|
|||||||
BuiltinProc_type_of,
|
BuiltinProc_type_of,
|
||||||
BuiltinProc_type_info_of,
|
BuiltinProc_type_info_of,
|
||||||
|
|
||||||
BuiltinProc_compile_assert,
|
|
||||||
|
|
||||||
BuiltinProc_swizzle,
|
BuiltinProc_swizzle,
|
||||||
|
|
||||||
BuiltinProc_complex,
|
BuiltinProc_complex,
|
||||||
@@ -134,8 +132,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
|||||||
{STR_LIT("type_of"), 1, false, Expr_Expr},
|
{STR_LIT("type_of"), 1, false, Expr_Expr},
|
||||||
{STR_LIT("type_info_of"), 1, false, Expr_Expr},
|
{STR_LIT("type_info_of"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("compile_assert"), 1, false, Expr_Expr},
|
|
||||||
|
|
||||||
{STR_LIT("swizzle"), 1, true, Expr_Expr},
|
{STR_LIT("swizzle"), 1, true, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("complex"), 2, false, Expr_Expr},
|
{STR_LIT("complex"), 2, false, Expr_Expr},
|
||||||
@@ -221,6 +217,7 @@ struct Scope {
|
|||||||
|
|
||||||
Array<Scope *> shared;
|
Array<Scope *> shared;
|
||||||
Array<AstNode *> delayed_file_decls;
|
Array<AstNode *> delayed_file_decls;
|
||||||
|
Array<AstNode *> delayed_asserts;
|
||||||
PtrSet<Scope *> imported;
|
PtrSet<Scope *> imported;
|
||||||
PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too
|
PtrSet<Scope *> exported; // NOTE(bhall): Contains 'using import' too
|
||||||
bool is_proc;
|
bool is_proc;
|
||||||
|
|||||||
@@ -303,8 +303,6 @@ Entity *make_entity_label(gbAllocator a, Scope *scope, Token token, Type *type,
|
|||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Entity *make_entity_dummy_variable(gbAllocator a, Scope *scope, Token token) {
|
Entity *make_entity_dummy_variable(gbAllocator a, Scope *scope, Token token) {
|
||||||
token.string = str_lit("_");
|
token.string = str_lit("_");
|
||||||
return make_entity_variable(a, scope, token, nullptr, false);
|
return make_entity_variable(a, scope, token, nullptr, false);
|
||||||
|
|||||||
+16
-6
@@ -1358,6 +1358,7 @@ void expect_semicolon(AstFile *f, AstNode *s) {
|
|||||||
switch (f->curr_token.kind) {
|
switch (f->curr_token.kind) {
|
||||||
case Token_CloseBrace:
|
case Token_CloseBrace:
|
||||||
case Token_CloseParen:
|
case Token_CloseParen:
|
||||||
|
case Token_else:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1658,6 +1659,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
} else if (name.string == "location") {
|
} else if (name.string == "location") {
|
||||||
AstNode *tag = ast_basic_directive(f, token, name.string);
|
AstNode *tag = ast_basic_directive(f, token, name.string);
|
||||||
return parse_call_expr(f, tag);
|
return parse_call_expr(f, tag);
|
||||||
|
} else if (name.string == "assert") {
|
||||||
|
AstNode *tag = ast_basic_directive(f, token, name.string);
|
||||||
|
return parse_call_expr(f, tag);
|
||||||
} else {
|
} else {
|
||||||
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
||||||
}
|
}
|
||||||
@@ -3175,7 +3179,7 @@ AstNode *parse_when_stmt(AstFile *f) {
|
|||||||
break;
|
break;
|
||||||
case Token_do: {
|
case Token_do: {
|
||||||
Token arrow = expect_token(f, Token_do);
|
Token arrow = expect_token(f, Token_do);
|
||||||
body = convert_stmt_to_body(f, parse_stmt(f));
|
else_stmt = convert_stmt_to_body(f, parse_stmt(f));
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
syntax_error(f->curr_token, "Expected when statement block statement");
|
syntax_error(f->curr_token, "Expected when statement block statement");
|
||||||
@@ -3184,11 +3188,6 @@ AstNode *parse_when_stmt(AstFile *f) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (f->curr_proc == nullptr && f->when_level > 1) {
|
|
||||||
// syntax_error(token, "Nested when statements are not currently supported at the file scope");
|
|
||||||
// return ast_bad_stmt(f, token, f->curr_token);
|
|
||||||
// }
|
|
||||||
|
|
||||||
return ast_when_stmt(f, token, cond, body, else_stmt);
|
return ast_when_stmt(f, token, cond, body, else_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3739,6 +3738,9 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
|
} else if (tag == "assert") {
|
||||||
|
AstNode *t = ast_basic_directive(f, hash_token, tag);
|
||||||
|
return parse_call_expr(f, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag == "include") {
|
if (tag == "include") {
|
||||||
@@ -4062,6 +4064,14 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, Array<AstNod
|
|||||||
node->kind != AstNode_EmptyStmt &&
|
node->kind != AstNode_EmptyStmt &&
|
||||||
node->kind != AstNode_WhenStmt) {
|
node->kind != AstNode_WhenStmt) {
|
||||||
// NOTE(bill): Sanity check
|
// NOTE(bill): Sanity check
|
||||||
|
|
||||||
|
if (node->kind == AstNode_CallExpr &&
|
||||||
|
node->CallExpr.proc->kind == AstNode_BasicDirective &&
|
||||||
|
node->CallExpr.proc->BasicDirective.name == "assert") {
|
||||||
|
// NOTE(bill): Okay!
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
syntax_error(node, "Only declarations are allowed at file scope, got %.*s", LIT(ast_node_strings[node->kind]));
|
syntax_error(node, "Only declarations are allowed at file scope, got %.*s", LIT(ast_node_strings[node->kind]));
|
||||||
} else if (node->kind == AstNode_ImportDecl) {
|
} else if (node->kind == AstNode_ImportDecl) {
|
||||||
ast_node(id, ImportDecl, node);
|
ast_node(id, ImportDecl, node);
|
||||||
|
|||||||
Reference in New Issue
Block a user