mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Maybe types; value, ok := maybe_value(x)
This commit is contained in:
+8
-8
@@ -1,15 +1,15 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin"
|
||||||
|
|
||||||
A :: {2}f32{1, 2}
|
|
||||||
B :: {2}f32{3, 4}
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
Fruit :: union {
|
maybe_print :: proc(x: ?int) {
|
||||||
A: int
|
if v, ok := maybe_value(x); ok {
|
||||||
B: f32
|
fmt.println(v)
|
||||||
C: struct {
|
} else {
|
||||||
x: int
|
fmt.println("nowt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybe_print(123) // 123
|
||||||
|
maybe_print(nil) // nowt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ Type_Info :: union {
|
|||||||
Pointer: struct #ordered {
|
Pointer: struct #ordered {
|
||||||
elem: ^Type_Info
|
elem: ^Type_Info
|
||||||
}
|
}
|
||||||
|
Maybe: struct #ordered {
|
||||||
|
elem: ^Type_Info
|
||||||
|
}
|
||||||
Procedure: struct #ordered {
|
Procedure: struct #ordered {
|
||||||
params: ^Type_Info // Type_Info.Tuple
|
params: ^Type_Info // Type_Info.Tuple
|
||||||
results: ^Type_Info // Type_Info.Tuple
|
results: ^Type_Info // Type_Info.Tuple
|
||||||
|
|||||||
@@ -413,6 +413,13 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
print_pointer_to_buffer(buf, nil)
|
print_pointer_to_buffer(buf, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Maybe:
|
||||||
|
if arg.data != nil {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
print_string_to_buffer(buf, "<nil>")
|
||||||
|
}
|
||||||
|
|
||||||
case Enum:
|
case Enum:
|
||||||
value: i64 = 0
|
value: i64 = 0
|
||||||
match type i : info.base {
|
match type i : info.base {
|
||||||
|
|||||||
+17
-13
@@ -168,6 +168,7 @@ enum BuiltinProcId {
|
|||||||
|
|
||||||
BuiltinProc_enum_to_string,
|
BuiltinProc_enum_to_string,
|
||||||
|
|
||||||
|
BuiltinProc_maybe_value,
|
||||||
|
|
||||||
BuiltinProc_Count,
|
BuiltinProc_Count,
|
||||||
};
|
};
|
||||||
@@ -213,6 +214,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
|||||||
|
|
||||||
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
|
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
|
{STR_LIT("maybe_value"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CheckerContext {
|
struct CheckerContext {
|
||||||
@@ -891,7 +894,7 @@ Map<Entity *> generate_minimum_dependency_map(CheckerInfo *info, Entity *start)
|
|||||||
#include "expr.cpp"
|
#include "expr.cpp"
|
||||||
#include "stmt.cpp"
|
#include "stmt.cpp"
|
||||||
|
|
||||||
void init_runtime_types(Checker *c) {
|
void init_preload_types(Checker *c) {
|
||||||
if (t_type_info == NULL) {
|
if (t_type_info == NULL) {
|
||||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
@@ -900,13 +903,13 @@ void init_runtime_types(Checker *c) {
|
|||||||
}
|
}
|
||||||
t_type_info = e->type;
|
t_type_info = e->type;
|
||||||
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
||||||
|
GB_ASSERT(is_type_union(e->type));
|
||||||
auto *record = &base_type(e->type)->Record;
|
auto *record = &base_type(e->type)->Record;
|
||||||
|
|
||||||
t_type_info_member = record->other_fields[0]->type;
|
t_type_info_member = record->other_fields[0]->type;
|
||||||
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
||||||
|
|
||||||
if (record->field_count != 16) {
|
if (record->field_count != 17) {
|
||||||
compiler_error("Invalid `Type_Info` layout");
|
compiler_error("Invalid `Type_Info` layout");
|
||||||
}
|
}
|
||||||
t_type_info_named = record->fields[ 1]->type;
|
t_type_info_named = record->fields[ 1]->type;
|
||||||
@@ -915,15 +918,16 @@ void init_runtime_types(Checker *c) {
|
|||||||
t_type_info_string = record->fields[ 4]->type;
|
t_type_info_string = record->fields[ 4]->type;
|
||||||
t_type_info_boolean = record->fields[ 5]->type;
|
t_type_info_boolean = record->fields[ 5]->type;
|
||||||
t_type_info_pointer = record->fields[ 6]->type;
|
t_type_info_pointer = record->fields[ 6]->type;
|
||||||
t_type_info_procedure = record->fields[ 7]->type;
|
t_type_info_maybe = record->fields[ 7]->type;
|
||||||
t_type_info_array = record->fields[ 8]->type;
|
t_type_info_procedure = record->fields[ 8]->type;
|
||||||
t_type_info_slice = record->fields[ 9]->type;
|
t_type_info_array = record->fields[ 9]->type;
|
||||||
t_type_info_vector = record->fields[10]->type;
|
t_type_info_slice = record->fields[10]->type;
|
||||||
t_type_info_tuple = record->fields[11]->type;
|
t_type_info_vector = record->fields[11]->type;
|
||||||
t_type_info_struct = record->fields[12]->type;
|
t_type_info_tuple = record->fields[12]->type;
|
||||||
t_type_info_union = record->fields[13]->type;
|
t_type_info_struct = record->fields[13]->type;
|
||||||
t_type_info_raw_union = record->fields[14]->type;
|
t_type_info_union = record->fields[14]->type;
|
||||||
t_type_info_enum = record->fields[15]->type;
|
t_type_info_raw_union = record->fields[15]->type;
|
||||||
|
t_type_info_enum = record->fields[16]->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t_allocator == NULL) {
|
if (t_allocator == NULL) {
|
||||||
@@ -1206,7 +1210,7 @@ void check_parsed_files(Checker *c) {
|
|||||||
|
|
||||||
check_global_entity(c, Entity_TypeName);
|
check_global_entity(c, Entity_TypeName);
|
||||||
|
|
||||||
init_runtime_types(c);
|
init_preload_types(c);
|
||||||
|
|
||||||
check_global_entity(c, Entity_Constant);
|
check_global_entity(c, Entity_Constant);
|
||||||
check_global_entity(c, Entity_Procedure);
|
check_global_entity(c, Entity_Procedure);
|
||||||
|
|||||||
+74
-17
@@ -7,7 +7,7 @@ void check_type_decl (Checker *c, Entity *e, AstNode *type_expr, T
|
|||||||
Entity * check_selector (Checker *c, Operand *operand, AstNode *node);
|
Entity * check_selector (Checker *c, Operand *operand, AstNode *node);
|
||||||
void check_not_tuple (Checker *c, Operand *operand);
|
void check_not_tuple (Checker *c, Operand *operand);
|
||||||
b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value);
|
b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value);
|
||||||
void convert_to_typed (Checker *c, Operand *operand, Type *target_type);
|
void convert_to_typed (Checker *c, Operand *operand, Type *target_type, i32 level = 0);
|
||||||
gbString expr_to_string (AstNode *expression);
|
gbString expr_to_string (AstNode *expression);
|
||||||
void check_entity_decl (Checker *c, Entity *e, DeclInfo *decl, Type *named_type, CycleChecker *cycle_checker = NULL);
|
void check_entity_decl (Checker *c, Entity *e, DeclInfo *decl, Type *named_type, CycleChecker *cycle_checker = NULL);
|
||||||
void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
|
void check_proc_body (Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body);
|
||||||
@@ -88,6 +88,11 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_maybe(dst)) {
|
||||||
|
Type *elem = base_type(dst)->Maybe.elem;
|
||||||
|
return are_types_identical(elem, src);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_type_untyped_nil(src)) {
|
if (is_type_untyped_nil(src)) {
|
||||||
return type_has_nil(dst);
|
return type_has_nil(dst);
|
||||||
}
|
}
|
||||||
@@ -103,6 +108,8 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (dst->kind == Type_Array && src->kind == Type_Array) {
|
if (dst->kind == Type_Array && src->kind == Type_Array) {
|
||||||
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
|
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
|
||||||
return dst->Array.count == src->Array.count;
|
return dst->Array.count == src->Array.count;
|
||||||
@@ -138,9 +145,7 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1048,6 +1053,12 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
|
|||||||
goto end;
|
goto end;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
case_ast_node(mt, MaybeType, e);
|
||||||
|
Type *elem = check_type(c, mt->type);
|
||||||
|
type = make_type_maybe(c->allocator, elem);
|
||||||
|
goto end;
|
||||||
|
case_end;
|
||||||
|
|
||||||
case_ast_node(at, ArrayType, e);
|
case_ast_node(at, ArrayType, e);
|
||||||
if (at->count != NULL) {
|
if (at->count != NULL) {
|
||||||
Type *elem = check_type(c, at->elem, NULL, cycle_checker);
|
Type *elem = check_type(c, at->elem, NULL, cycle_checker);
|
||||||
@@ -1243,8 +1254,10 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value) {
|
b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value) {
|
||||||
if (in_value.kind == ExactValue_Invalid)
|
if (in_value.kind == ExactValue_Invalid) {
|
||||||
|
// NOTE(bill): There's already been an error
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_type_boolean(type)) {
|
if (is_type_boolean(type)) {
|
||||||
return in_value.kind == ExactValue_Bool;
|
return in_value.kind == ExactValue_Bool;
|
||||||
@@ -1252,8 +1265,9 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac
|
|||||||
return in_value.kind == ExactValue_String;
|
return in_value.kind == ExactValue_String;
|
||||||
} else if (is_type_integer(type)) {
|
} else if (is_type_integer(type)) {
|
||||||
ExactValue v = exact_value_to_integer(in_value);
|
ExactValue v = exact_value_to_integer(in_value);
|
||||||
if (v.kind != ExactValue_Integer)
|
if (v.kind != ExactValue_Integer) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
if (out_value) *out_value = v;
|
if (out_value) *out_value = v;
|
||||||
i64 i = v.value_integer;
|
i64 i = v.value_integer;
|
||||||
u64 u = *cast(u64 *)&i;
|
u64 u = *cast(u64 *)&i;
|
||||||
@@ -1287,8 +1301,9 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac
|
|||||||
}
|
}
|
||||||
} else if (is_type_float(type)) {
|
} else if (is_type_float(type)) {
|
||||||
ExactValue v = exact_value_to_float(in_value);
|
ExactValue v = exact_value_to_float(in_value);
|
||||||
if (v.kind != ExactValue_Float)
|
if (v.kind != ExactValue_Float) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (type->Basic.kind) {
|
switch (type->Basic.kind) {
|
||||||
case Basic_f32:
|
case Basic_f32:
|
||||||
@@ -1986,7 +2001,7 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
operand->mode = Addressing_Invalid;
|
operand->mode = Addressing_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level) {
|
||||||
GB_ASSERT_NOT_NULL(target_type);
|
GB_ASSERT_NOT_NULL(target_type);
|
||||||
if (operand->mode == Addressing_Invalid ||
|
if (operand->mode == Addressing_Invalid ||
|
||||||
is_type_typed(operand->type) ||
|
is_type_typed(operand->type) ||
|
||||||
@@ -2018,7 +2033,6 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
}
|
}
|
||||||
update_expr_value(c, operand->expr, operand->value);
|
update_expr_value(c, operand->expr, operand->value);
|
||||||
} else {
|
} else {
|
||||||
// TODO(bill): Is this really needed?
|
|
||||||
switch (operand->type->Basic.kind) {
|
switch (operand->type->Basic.kind) {
|
||||||
case Basic_UntypedBool:
|
case Basic_UntypedBool:
|
||||||
if (!is_type_boolean(target_type)) {
|
if (!is_type_boolean(target_type)) {
|
||||||
@@ -2045,14 +2059,24 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Type_Maybe:
|
||||||
|
if (is_type_untyped_nil(operand->type)) {
|
||||||
|
// Okay
|
||||||
|
} else if (level == 0) {
|
||||||
|
convert_to_typed(c, operand, t->Maybe.elem, level+1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!type_has_nil(target_type)) {
|
if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
|
||||||
convert_untyped_error(c, operand, target_type);
|
convert_untyped_error(c, operand, target_type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
operand->type = target_type;
|
operand->type = target_type;
|
||||||
update_expr_type(c, operand->expr, target_type, true);
|
update_expr_type(c, operand->expr, target_type, true);
|
||||||
}
|
}
|
||||||
@@ -2361,15 +2385,16 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BuiltinProc_offset_of: {
|
case BuiltinProc_offset_of: {
|
||||||
// offset_val :: proc(Type, field) -> int
|
// offset_of :: proc(Type, field) -> int
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
Type *type = base_type(check_type(c, ce->args[0]));
|
Type *bt = check_type(c, ce->args[0]);
|
||||||
if (type != NULL || type == t_invalid) {
|
Type *type = base_type(bt);
|
||||||
|
if (type == NULL || type == t_invalid) {
|
||||||
error(ast_node_token(ce->args[0]), "Expected a type for `offset_of`");
|
error(ast_node_token(ce->args[0]), "Expected a type for `offset_of`");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!is_type_struct(type)) {
|
if (!is_type_struct(type)) {
|
||||||
error(ast_node_token(ce->args[0]), "Expected a structure type for `offset_of`");
|
error(ast_node_token(ce->args[0]), "Expected a struct type for `offset_of`");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2384,7 +2409,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
ast_node(arg, Ident, field_arg);
|
ast_node(arg, Ident, field_arg);
|
||||||
Selection sel = lookup_field(c->allocator, type, arg->string, operand->mode == Addressing_Type);
|
Selection sel = lookup_field(c->allocator, type, arg->string, operand->mode == Addressing_Type);
|
||||||
if (sel.entity == NULL) {
|
if (sel.entity == NULL) {
|
||||||
gbString type_str = type_to_string(type);
|
gbString type_str = type_to_string(bt);
|
||||||
|
defer (gb_string_free(type_str));
|
||||||
error(ast_node_token(ce->args[0]),
|
error(ast_node_token(ce->args[0]),
|
||||||
"`%s` has no field named `%.*s`", type_str, LIT(arg->string));
|
"`%s` has no field named `%.*s`", type_str, LIT(arg->string));
|
||||||
return false;
|
return false;
|
||||||
@@ -2397,7 +2423,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_offset_of_val: {
|
case BuiltinProc_offset_of_val: {
|
||||||
// offset_val :: proc(val: expression) -> int
|
// offset_of_val :: proc(val: expression) -> int
|
||||||
AstNode *arg = unparen_expr(ce->args[0]);
|
AstNode *arg = unparen_expr(ce->args[0]);
|
||||||
if (arg->kind != AstNode_SelectorExpr) {
|
if (arg->kind != AstNode_SelectorExpr) {
|
||||||
gbString str = expr_to_string(arg);
|
gbString str = expr_to_string(arg);
|
||||||
@@ -2418,6 +2444,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_type_struct(type)) {
|
||||||
|
error(ast_node_token(ce->args[0]), "Expected a struct type for `offset_of_val`");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
ast_node(i, Ident, s->selector);
|
ast_node(i, Ident, s->selector);
|
||||||
Selection sel = lookup_field(c->allocator, type, i->string, operand->mode == Addressing_Type);
|
Selection sel = lookup_field(c->allocator, type, i->string, operand->mode == Addressing_Type);
|
||||||
@@ -2677,8 +2708,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
|
|
||||||
if (operand->mode == Addressing_Constant &&
|
if (operand->mode == Addressing_Constant &&
|
||||||
op.mode == Addressing_Constant) {
|
op.mode == Addressing_Constant) {
|
||||||
u8 *ptr = cast(u8 *)operand->value.value_pointer;
|
i64 ptr = operand->value.value_pointer;
|
||||||
isize elem_size = type_size_of(c->sizes, c->allocator, ptr_type->Pointer.elem);
|
i64 elem_size = type_size_of(c->sizes, c->allocator, ptr_type->Pointer.elem);
|
||||||
ptr += elem_size * op.value.value_integer;
|
ptr += elem_size * op.value.value_integer;
|
||||||
operand->value.value_pointer = ptr;
|
operand->value.value_pointer = ptr;
|
||||||
} else {
|
} else {
|
||||||
@@ -2997,6 +3028,31 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
operand->type = t_string;
|
operand->type = t_string;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_maybe_value: {
|
||||||
|
Type *type = operand->type;
|
||||||
|
if (!is_type_maybe(type)) {
|
||||||
|
gbString type_str = type_to_string(operand->type);
|
||||||
|
defer (gb_string_free(type_str));
|
||||||
|
error(ast_node_token(call),
|
||||||
|
"Expected a maybe to `maybe_value`, got `%s`",
|
||||||
|
type_str);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
|
||||||
|
Entity **variables = gb_alloc_array(c->allocator, Entity *, 2);
|
||||||
|
Type *elem = base_type(type)->Maybe.elem;
|
||||||
|
Token t = make_token_ident(make_string(""));
|
||||||
|
variables[0] = make_entity_param(c->allocator, NULL, t, elem, false);
|
||||||
|
variables[1] = make_entity_param(c->allocator, NULL, t, t_bool, false);
|
||||||
|
|
||||||
|
Type *tuple = make_type_tuple(c->allocator);
|
||||||
|
tuple->Tuple.variables = variables;
|
||||||
|
tuple->Tuple.variable_count = 2;
|
||||||
|
operand->type = tuple;
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -3677,6 +3733,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
|
|
||||||
case AstNode_ProcType:
|
case AstNode_ProcType:
|
||||||
case AstNode_PointerType:
|
case AstNode_PointerType:
|
||||||
|
case AstNode_MaybeType:
|
||||||
case AstNode_ArrayType:
|
case AstNode_ArrayType:
|
||||||
case AstNode_VectorType:
|
case AstNode_VectorType:
|
||||||
case AstNode_StructType:
|
case AstNode_StructType:
|
||||||
|
|||||||
+51
-11
@@ -58,11 +58,12 @@ struct BasicType {
|
|||||||
#define TYPE_KINDS \
|
#define TYPE_KINDS \
|
||||||
TYPE_KIND(Invalid), \
|
TYPE_KIND(Invalid), \
|
||||||
TYPE_KIND(Basic), \
|
TYPE_KIND(Basic), \
|
||||||
|
TYPE_KIND(Pointer), \
|
||||||
TYPE_KIND(Array), \
|
TYPE_KIND(Array), \
|
||||||
TYPE_KIND(Vector), \
|
TYPE_KIND(Vector), \
|
||||||
TYPE_KIND(Slice), \
|
TYPE_KIND(Slice), \
|
||||||
|
TYPE_KIND(Maybe), \
|
||||||
TYPE_KIND(Record), \
|
TYPE_KIND(Record), \
|
||||||
TYPE_KIND(Pointer), \
|
|
||||||
TYPE_KIND(Named), \
|
TYPE_KIND(Named), \
|
||||||
TYPE_KIND(Tuple), \
|
TYPE_KIND(Tuple), \
|
||||||
TYPE_KIND(Proc), \
|
TYPE_KIND(Proc), \
|
||||||
@@ -96,6 +97,7 @@ struct Type {
|
|||||||
u32 flags; // See parser.cpp `enum TypeFlag`
|
u32 flags; // See parser.cpp `enum TypeFlag`
|
||||||
union {
|
union {
|
||||||
BasicType Basic;
|
BasicType Basic;
|
||||||
|
struct { Type *elem; } Pointer;
|
||||||
struct {
|
struct {
|
||||||
Type *elem;
|
Type *elem;
|
||||||
i64 count;
|
i64 count;
|
||||||
@@ -107,6 +109,9 @@ struct Type {
|
|||||||
struct {
|
struct {
|
||||||
Type *elem;
|
Type *elem;
|
||||||
} Slice;
|
} Slice;
|
||||||
|
struct {
|
||||||
|
Type *elem;
|
||||||
|
} Maybe;
|
||||||
struct {
|
struct {
|
||||||
TypeRecordKind kind;
|
TypeRecordKind kind;
|
||||||
|
|
||||||
@@ -134,7 +139,6 @@ struct Type {
|
|||||||
Entity **other_fields;
|
Entity **other_fields;
|
||||||
isize other_field_count;
|
isize other_field_count;
|
||||||
} Record;
|
} Record;
|
||||||
struct { Type *elem; } Pointer;
|
|
||||||
struct {
|
struct {
|
||||||
String name;
|
String name;
|
||||||
Type * base;
|
Type * base;
|
||||||
@@ -187,6 +191,18 @@ Type *make_type_basic(gbAllocator a, BasicType basic) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type *make_type_pointer(gbAllocator a, Type *elem) {
|
||||||
|
Type *t = alloc_type(a, Type_Pointer);
|
||||||
|
t->Pointer.elem = elem;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type *make_type_maybe(gbAllocator a, Type *elem) {
|
||||||
|
Type *t = alloc_type(a, Type_Maybe);
|
||||||
|
t->Maybe.elem = elem;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
|
Type *make_type_array(gbAllocator a, Type *elem, i64 count) {
|
||||||
Type *t = alloc_type(a, Type_Array);
|
Type *t = alloc_type(a, Type_Array);
|
||||||
t->Array.elem = elem;
|
t->Array.elem = elem;
|
||||||
@@ -207,6 +223,7 @@ Type *make_type_slice(gbAllocator a, Type *elem) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *make_type_struct(gbAllocator a) {
|
Type *make_type_struct(gbAllocator a) {
|
||||||
Type *t = alloc_type(a, Type_Record);
|
Type *t = alloc_type(a, Type_Record);
|
||||||
t->Record.kind = TypeRecord_Struct;
|
t->Record.kind = TypeRecord_Struct;
|
||||||
@@ -231,11 +248,7 @@ Type *make_type_enum(gbAllocator a) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *make_type_pointer(gbAllocator a, Type *elem) {
|
|
||||||
Type *t = alloc_type(a, Type_Pointer);
|
|
||||||
t->Pointer.elem = elem;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *make_type_named(gbAllocator a, String name, Type *base, Entity *type_name) {
|
Type *make_type_named(gbAllocator a, String name, Type *base, Entity *type_name) {
|
||||||
Type *t = alloc_type(a, Type_Named);
|
Type *t = alloc_type(a, Type_Named);
|
||||||
@@ -357,6 +370,7 @@ gb_global Type *t_type_info_float = NULL;
|
|||||||
gb_global Type *t_type_info_string = NULL;
|
gb_global Type *t_type_info_string = NULL;
|
||||||
gb_global Type *t_type_info_boolean = NULL;
|
gb_global Type *t_type_info_boolean = NULL;
|
||||||
gb_global Type *t_type_info_pointer = NULL;
|
gb_global Type *t_type_info_pointer = NULL;
|
||||||
|
gb_global Type *t_type_info_maybe = NULL;
|
||||||
gb_global Type *t_type_info_procedure = NULL;
|
gb_global Type *t_type_info_procedure = NULL;
|
||||||
gb_global Type *t_type_info_array = NULL;
|
gb_global Type *t_type_info_array = NULL;
|
||||||
gb_global Type *t_type_info_slice = NULL;
|
gb_global Type *t_type_info_slice = NULL;
|
||||||
@@ -468,6 +482,15 @@ b32 is_type_pointer(Type *t) {
|
|||||||
}
|
}
|
||||||
return t->kind == Type_Pointer;
|
return t->kind == Type_Pointer;
|
||||||
}
|
}
|
||||||
|
b32 is_type_maybe(Type *t) {
|
||||||
|
t = base_type(t);
|
||||||
|
return t->kind == Type_Maybe;
|
||||||
|
}
|
||||||
|
b32 is_type_tuple(Type *t) {
|
||||||
|
t = base_type(t);
|
||||||
|
return t->kind == Type_Tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
b32 is_type_int_or_uint(Type *t) {
|
b32 is_type_int_or_uint(Type *t) {
|
||||||
if (t->kind == Type_Basic) {
|
if (t->kind == Type_Basic) {
|
||||||
@@ -671,6 +694,11 @@ b32 are_types_identical(Type *x, Type *y) {
|
|||||||
return are_types_identical(x->Pointer.elem, y->Pointer.elem);
|
return are_types_identical(x->Pointer.elem, y->Pointer.elem);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Type_Maybe:
|
||||||
|
if (y->kind == Type_Maybe)
|
||||||
|
return are_types_identical(x->Maybe.elem, y->Maybe.elem);
|
||||||
|
break;
|
||||||
|
|
||||||
case Type_Named:
|
case Type_Named:
|
||||||
if (y->kind == Type_Named) {
|
if (y->kind == Type_Named) {
|
||||||
return x->Named.base == y->Named.base;
|
return x->Named.base == y->Named.base;
|
||||||
@@ -987,6 +1015,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
return max;
|
return max;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Type_Maybe:
|
||||||
|
return gb_max(type_align_of(s, allocator, t->Maybe.elem), type_align_of(s, allocator, t_bool));
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
switch (t->Record.kind) {
|
||||||
case TypeRecord_Struct:
|
case TypeRecord_Struct:
|
||||||
@@ -1115,6 +1146,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
case Type_Slice: // ptr + len + cap
|
case Type_Slice: // ptr + len + cap
|
||||||
return 3 * s.word_size;
|
return 3 * s.word_size;
|
||||||
|
|
||||||
|
case Type_Maybe: // value + bool
|
||||||
|
return type_size_of(s, allocator, t->Maybe.elem) + type_size_of(s, allocator, t_bool);
|
||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
switch (t->Record.kind) {
|
switch (t->Record.kind) {
|
||||||
case TypeRecord_Struct: {
|
case TypeRecord_Struct: {
|
||||||
@@ -1199,6 +1233,16 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
str = gb_string_append_length(str, type->Basic.name.text, type->Basic.name.len);
|
str = gb_string_append_length(str, type->Basic.name.text, type->Basic.name.len);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Type_Pointer:
|
||||||
|
str = gb_string_appendc(str, "^");
|
||||||
|
str = write_type_to_string(str, type->Pointer.elem);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type_Maybe:
|
||||||
|
str = gb_string_appendc(str, "?");
|
||||||
|
str = write_type_to_string(str, type->Maybe.elem);
|
||||||
|
break;
|
||||||
|
|
||||||
case Type_Array:
|
case Type_Array:
|
||||||
str = gb_string_appendc(str, gb_bprintf("[%td]", type->Array.count));
|
str = gb_string_appendc(str, gb_bprintf("[%td]", type->Array.count));
|
||||||
str = write_type_to_string(str, type->Array.elem);
|
str = write_type_to_string(str, type->Array.elem);
|
||||||
@@ -1266,10 +1310,6 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Pointer:
|
|
||||||
str = gb_string_appendc(str, "^");
|
|
||||||
str = write_type_to_string(str, type->Pointer.elem);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type_Named:
|
case Type_Named:
|
||||||
if (type->Named.type_name != NULL) {
|
if (type->Named.type_name != NULL) {
|
||||||
|
|||||||
@@ -389,6 +389,11 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
|
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
|
||||||
} break;
|
} break;
|
||||||
|
case Type_Maybe: {
|
||||||
|
tag = ssa_add_local_generated(proc, t_type_info_maybe);
|
||||||
|
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Maybe.elem);
|
||||||
|
ssa_emit_store(proc, ssa_emit_struct_gep(proc, tag, v_zero32, t_type_info_ptr_ptr), gep);
|
||||||
|
} break;
|
||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
tag = ssa_add_local_generated(proc, t_type_info_array);
|
tag = ssa_add_local_generated(proc, t_type_info_array);
|
||||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Array.elem);
|
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Array.elem);
|
||||||
|
|||||||
@@ -160,6 +160,17 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
|||||||
case Basic_any: ssa_fprintf(f, "%%..any"); break;
|
case Basic_any: ssa_fprintf(f, "%%..any"); break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Type_Pointer:
|
||||||
|
ssa_print_type(f, m, t->Pointer.elem);
|
||||||
|
ssa_fprintf(f, "*");
|
||||||
|
break;
|
||||||
|
case Type_Maybe:
|
||||||
|
ssa_fprintf(f, "{");
|
||||||
|
ssa_print_type(f, m, t->Maybe.elem);
|
||||||
|
ssa_fprintf(f, ", ");
|
||||||
|
ssa_print_type(f, m, t_bool);
|
||||||
|
ssa_fprintf(f, "}");
|
||||||
|
break;
|
||||||
case Type_Array:
|
case Type_Array:
|
||||||
ssa_fprintf(f, "[%lld x ", t->Array.count);
|
ssa_fprintf(f, "[%lld x ", t->Array.count);
|
||||||
ssa_print_type(f, m, t->Array.elem);
|
ssa_print_type(f, m, t->Array.elem);
|
||||||
@@ -212,10 +223,7 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Pointer:
|
|
||||||
ssa_print_type(f, m, t->Pointer.elem);
|
|
||||||
ssa_fprintf(f, "*");
|
|
||||||
break;
|
|
||||||
case Type_Named:
|
case Type_Named:
|
||||||
if (is_type_struct(t) || is_type_union(t)) {
|
if (is_type_struct(t) || is_type_union(t)) {
|
||||||
String *name = map_get(&m->type_names, hash_pointer(t));
|
String *name = map_get(&m->type_names, hash_pointer(t));
|
||||||
|
|||||||
+38
-1
@@ -561,6 +561,10 @@ Type *ssa_type(ssaValue *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssaDebugInfo *ssa_add_debug_info_file(ssaProcedure *proc, AstFile *file) {
|
ssaDebugInfo *ssa_add_debug_info_file(ssaProcedure *proc, AstFile *file) {
|
||||||
|
if (!proc->module->generate_debug_info) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
GB_ASSERT(file != NULL);
|
GB_ASSERT(file != NULL);
|
||||||
ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_File);
|
ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_File);
|
||||||
di->File.file = file;
|
di->File.file = file;
|
||||||
@@ -589,6 +593,10 @@ ssaDebugInfo *ssa_add_debug_info_file(ssaProcedure *proc, AstFile *file) {
|
|||||||
|
|
||||||
|
|
||||||
ssaDebugInfo *ssa_add_debug_info_proc(ssaProcedure *proc, Entity *entity, String name, ssaDebugInfo *file) {
|
ssaDebugInfo *ssa_add_debug_info_proc(ssaProcedure *proc, Entity *entity, String name, ssaDebugInfo *file) {
|
||||||
|
if (!proc->module->generate_debug_info) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
GB_ASSERT(entity != NULL);
|
GB_ASSERT(entity != NULL);
|
||||||
ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_Proc);
|
ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_Proc);
|
||||||
di->Proc.entity = entity;
|
di->Proc.entity = entity;
|
||||||
@@ -1719,6 +1727,17 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_type_maybe(dst)) {
|
||||||
|
gbAllocator a = proc->module->allocator;
|
||||||
|
Type *elem = base_type(dst)->Maybe.elem;
|
||||||
|
ssaValue *maybe = ssa_add_local_generated(proc, dst);
|
||||||
|
ssaValue *val = ssa_emit_struct_gep(proc, maybe, v_zero32, make_type_pointer(a, elem));
|
||||||
|
ssaValue *set = ssa_emit_struct_gep(proc, maybe, v_one32, make_type_pointer(a, t_bool));
|
||||||
|
ssa_emit_store(proc, val, value);
|
||||||
|
ssa_emit_store(proc, set, v_true);
|
||||||
|
return ssa_emit_load(proc, maybe);
|
||||||
|
}
|
||||||
|
|
||||||
// integer -> integer
|
// integer -> integer
|
||||||
if (is_type_integer(src) && is_type_integer(dst)) {
|
if (is_type_integer(src) && is_type_integer(dst)) {
|
||||||
GB_ASSERT(src->kind == Type_Basic &&
|
GB_ASSERT(src->kind == Type_Basic &&
|
||||||
@@ -2658,7 +2677,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
return ssa_emit_select(proc, cond, neg_x, x);
|
return ssa_emit_select(proc, cond, neg_x, x);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case BuiltinProc_enum_to_string: {
|
case BuiltinProc_enum_to_string: {
|
||||||
ssa_emit_comment(proc, make_string("enum_to_string"));
|
ssa_emit_comment(proc, make_string("enum_to_string"));
|
||||||
ssaValue *x = ssa_build_expr(proc, ce->args[0]);
|
ssaValue *x = ssa_build_expr(proc, ce->args[0]);
|
||||||
@@ -2671,6 +2689,24 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
args[1] = ssa_emit_conv(proc, x, t_i64);
|
args[1] = ssa_emit_conv(proc, x, t_i64);
|
||||||
return ssa_emit_global_call(proc, "__enum_to_string", args, 2);
|
return ssa_emit_global_call(proc, "__enum_to_string", args, 2);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_maybe_value: {
|
||||||
|
ssa_emit_comment(proc, make_string("maybe_value"));
|
||||||
|
ssaValue *maybe = ssa_build_expr(proc, ce->args[0]);
|
||||||
|
Type *t = default_type(type_of_expr(proc->module->info, expr));
|
||||||
|
GB_ASSERT(is_type_tuple(t));
|
||||||
|
|
||||||
|
Type *elem = ssa_type(maybe);
|
||||||
|
GB_ASSERT(is_type_maybe(elem));
|
||||||
|
elem = base_type(elem)->Maybe.elem;
|
||||||
|
|
||||||
|
ssaValue *result = ssa_add_local_generated(proc, t);
|
||||||
|
ssaValue *gep0 = ssa_emit_struct_gep(proc, result, v_zero32, make_type_pointer(proc->module->allocator, elem));
|
||||||
|
ssaValue *gep1 = ssa_emit_struct_gep(proc, result, v_one32, make_type_pointer(proc->module->allocator, t_bool));
|
||||||
|
ssa_emit_store(proc, gep0, ssa_emit_struct_ev(proc, maybe, 0, elem));
|
||||||
|
ssa_emit_store(proc, gep1, ssa_emit_struct_ev(proc, maybe, 1, t_bool));
|
||||||
|
return ssa_emit_load(proc, result);
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3214,6 +3250,7 @@ void ssa_build_cond(ssaProcedure *proc, AstNode *cond, ssaBlock *true_block, ssa
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *expr = ssa_build_expr(proc, cond);
|
ssaValue *expr = ssa_build_expr(proc, cond);
|
||||||
|
expr = ssa_emit_conv(proc, expr, t_bool);
|
||||||
ssa_emit_if(proc, expr, true_block, false_block);
|
ssa_emit_if(proc, expr, true_block, false_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-4
@@ -25,7 +25,7 @@ struct ExactValue {
|
|||||||
String value_string;
|
String value_string;
|
||||||
i64 value_integer;
|
i64 value_integer;
|
||||||
f64 value_float;
|
f64 value_float;
|
||||||
void * value_pointer;
|
i64 value_pointer;
|
||||||
AstNode *value_compound;
|
AstNode *value_compound;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -93,7 +93,7 @@ ExactValue make_exact_value_float(f64 f) {
|
|||||||
|
|
||||||
ExactValue make_exact_value_pointer(void *ptr) {
|
ExactValue make_exact_value_pointer(void *ptr) {
|
||||||
ExactValue result = {ExactValue_Pointer};
|
ExactValue result = {ExactValue_Pointer};
|
||||||
result.value_pointer = ptr;
|
result.value_pointer = cast(i64)cast(intptr)ptr;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,8 +121,14 @@ ExactValue exact_value_to_integer(ExactValue v) {
|
|||||||
switch (v.kind) {
|
switch (v.kind) {
|
||||||
case ExactValue_Integer:
|
case ExactValue_Integer:
|
||||||
return v;
|
return v;
|
||||||
case ExactValue_Float:
|
case ExactValue_Float: {
|
||||||
return make_exact_value_integer(cast(i64)v.value_float);
|
i64 i = cast(i64)v.value_float;
|
||||||
|
f64 f = cast(f64)i;
|
||||||
|
if (f == v.value_float) {
|
||||||
|
return make_exact_value_integer(i);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case ExactValue_Pointer:
|
case ExactValue_Pointer:
|
||||||
return make_exact_value_integer(cast(i64)cast(intptr)v.value_pointer);
|
return make_exact_value_integer(cast(i64)cast(intptr)v.value_pointer);
|
||||||
}
|
}
|
||||||
|
|||||||
+82
-60
@@ -270,6 +270,10 @@ AST_NODE_KIND(_TypeBegin, "", struct{}) \
|
|||||||
Token token; \
|
Token token; \
|
||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
}) \
|
}) \
|
||||||
|
AST_NODE_KIND(MaybeType, "maybe type", struct { \
|
||||||
|
Token token; \
|
||||||
|
AstNode *type; \
|
||||||
|
}) \
|
||||||
AST_NODE_KIND(ArrayType, "array type", struct { \
|
AST_NODE_KIND(ArrayType, "array type", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *count; \
|
AstNode *count; \
|
||||||
@@ -454,6 +458,8 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return node->ProcType.token;
|
return node->ProcType.token;
|
||||||
case AstNode_PointerType:
|
case AstNode_PointerType:
|
||||||
return node->PointerType.token;
|
return node->PointerType.token;
|
||||||
|
case AstNode_MaybeType:
|
||||||
|
return node->MaybeType.token;
|
||||||
case AstNode_ArrayType:
|
case AstNode_ArrayType:
|
||||||
return node->ArrayType.token;
|
return node->ArrayType.token;
|
||||||
case AstNode_VectorType:
|
case AstNode_VectorType:
|
||||||
@@ -477,7 +483,7 @@ HashKey hash_token(Token t) {
|
|||||||
|
|
||||||
|
|
||||||
// NOTE(bill): And this below is why is I/we need a new language! Discriminated unions are a pain in C/C++
|
// NOTE(bill): And this below is why is I/we need a new language! Discriminated unions are a pain in C/C++
|
||||||
gb_inline AstNode *make_node(AstFile *f, AstNodeKind kind) {
|
AstNode *make_node(AstFile *f, AstNodeKind kind) {
|
||||||
gbArena *arena = &f->arena;
|
gbArena *arena = &f->arena;
|
||||||
if (gb_arena_size_remaining(arena, GB_DEFAULT_MEMORY_ALIGNMENT) <= gb_size_of(AstNode)) {
|
if (gb_arena_size_remaining(arena, GB_DEFAULT_MEMORY_ALIGNMENT) <= gb_size_of(AstNode)) {
|
||||||
// NOTE(bill): If a syntax error is so bad, just quit!
|
// NOTE(bill): If a syntax error is so bad, just quit!
|
||||||
@@ -488,14 +494,14 @@ gb_inline AstNode *make_node(AstFile *f, AstNodeKind kind) {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_bad_expr(AstFile *f, Token begin, Token end) {
|
AstNode *make_bad_expr(AstFile *f, Token begin, Token end) {
|
||||||
AstNode *result = make_node(f, AstNode_BadExpr);
|
AstNode *result = make_node(f, AstNode_BadExpr);
|
||||||
result->BadExpr.begin = begin;
|
result->BadExpr.begin = begin;
|
||||||
result->BadExpr.end = end;
|
result->BadExpr.end = end;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_tag_expr(AstFile *f, Token token, Token name, AstNode *expr) {
|
AstNode *make_tag_expr(AstFile *f, Token token, Token name, AstNode *expr) {
|
||||||
AstNode *result = make_node(f, AstNode_TagExpr);
|
AstNode *result = make_node(f, AstNode_TagExpr);
|
||||||
result->TagExpr.token = token;
|
result->TagExpr.token = token;
|
||||||
result->TagExpr.name = name;
|
result->TagExpr.name = name;
|
||||||
@@ -503,7 +509,7 @@ gb_inline AstNode *make_tag_expr(AstFile *f, Token token, Token name, AstNode *e
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_tag_stmt(AstFile *f, Token token, Token name, AstNode *stmt) {
|
AstNode *make_tag_stmt(AstFile *f, Token token, Token name, AstNode *stmt) {
|
||||||
AstNode *result = make_node(f, AstNode_TagStmt);
|
AstNode *result = make_node(f, AstNode_TagStmt);
|
||||||
result->TagStmt.token = token;
|
result->TagStmt.token = token;
|
||||||
result->TagStmt.name = name;
|
result->TagStmt.name = name;
|
||||||
@@ -511,14 +517,14 @@ gb_inline AstNode *make_tag_stmt(AstFile *f, Token token, Token name, AstNode *s
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_unary_expr(AstFile *f, Token op, AstNode *expr) {
|
AstNode *make_unary_expr(AstFile *f, Token op, AstNode *expr) {
|
||||||
AstNode *result = make_node(f, AstNode_UnaryExpr);
|
AstNode *result = make_node(f, AstNode_UnaryExpr);
|
||||||
result->UnaryExpr.op = op;
|
result->UnaryExpr.op = op;
|
||||||
result->UnaryExpr.expr = expr;
|
result->UnaryExpr.expr = expr;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_binary_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
|
AstNode *make_binary_expr(AstFile *f, Token op, AstNode *left, AstNode *right) {
|
||||||
AstNode *result = make_node(f, AstNode_BinaryExpr);
|
AstNode *result = make_node(f, AstNode_BinaryExpr);
|
||||||
|
|
||||||
if (left == NULL) {
|
if (left == NULL) {
|
||||||
@@ -537,7 +543,7 @@ gb_inline AstNode *make_binary_expr(AstFile *f, Token op, AstNode *left, AstNode
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token close) {
|
AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token close) {
|
||||||
AstNode *result = make_node(f, AstNode_ParenExpr);
|
AstNode *result = make_node(f, AstNode_ParenExpr);
|
||||||
result->ParenExpr.expr = expr;
|
result->ParenExpr.expr = expr;
|
||||||
result->ParenExpr.open = open;
|
result->ParenExpr.open = open;
|
||||||
@@ -545,7 +551,7 @@ gb_inline AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNodeArray args, Token open, Token close, Token ellipsis) {
|
AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNodeArray args, Token open, Token close, Token ellipsis) {
|
||||||
AstNode *result = make_node(f, AstNode_CallExpr);
|
AstNode *result = make_node(f, AstNode_CallExpr);
|
||||||
result->CallExpr.proc = proc;
|
result->CallExpr.proc = proc;
|
||||||
result->CallExpr.args = args;
|
result->CallExpr.args = args;
|
||||||
@@ -555,14 +561,14 @@ gb_inline AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNodeArray args,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_selector_expr(AstFile *f, Token token, AstNode *expr, AstNode *selector) {
|
AstNode *make_selector_expr(AstFile *f, Token token, AstNode *expr, AstNode *selector) {
|
||||||
AstNode *result = make_node(f, AstNode_SelectorExpr);
|
AstNode *result = make_node(f, AstNode_SelectorExpr);
|
||||||
result->SelectorExpr.expr = expr;
|
result->SelectorExpr.expr = expr;
|
||||||
result->SelectorExpr.selector = selector;
|
result->SelectorExpr.selector = selector;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, Token close) {
|
AstNode *make_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open, Token close) {
|
||||||
AstNode *result = make_node(f, AstNode_IndexExpr);
|
AstNode *result = make_node(f, AstNode_IndexExpr);
|
||||||
result->IndexExpr.expr = expr;
|
result->IndexExpr.expr = expr;
|
||||||
result->IndexExpr.index = index;
|
result->IndexExpr.index = index;
|
||||||
@@ -572,7 +578,7 @@ gb_inline AstNode *make_index_expr(AstFile *f, AstNode *expr, AstNode *index, To
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, AstNode *low, AstNode *high, AstNode *max, b32 triple_indexed) {
|
AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, AstNode *low, AstNode *high, AstNode *max, b32 triple_indexed) {
|
||||||
AstNode *result = make_node(f, AstNode_SliceExpr);
|
AstNode *result = make_node(f, AstNode_SliceExpr);
|
||||||
result->SliceExpr.expr = expr;
|
result->SliceExpr.expr = expr;
|
||||||
result->SliceExpr.open = open;
|
result->SliceExpr.open = open;
|
||||||
@@ -584,7 +590,7 @@ gb_inline AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) {
|
AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) {
|
||||||
AstNode *result = make_node(f, AstNode_DerefExpr);
|
AstNode *result = make_node(f, AstNode_DerefExpr);
|
||||||
result->DerefExpr.expr = expr;
|
result->DerefExpr.expr = expr;
|
||||||
result->DerefExpr.op = op;
|
result->DerefExpr.op = op;
|
||||||
@@ -592,19 +598,19 @@ gb_inline AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_basic_lit(AstFile *f, Token basic_lit) {
|
AstNode *make_basic_lit(AstFile *f, Token basic_lit) {
|
||||||
AstNode *result = make_node(f, AstNode_BasicLit);
|
AstNode *result = make_node(f, AstNode_BasicLit);
|
||||||
result->BasicLit = basic_lit;
|
result->BasicLit = basic_lit;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_ident(AstFile *f, Token token) {
|
AstNode *make_ident(AstFile *f, Token token) {
|
||||||
AstNode *result = make_node(f, AstNode_Ident);
|
AstNode *result = make_node(f, AstNode_Ident);
|
||||||
result->Ident = token;
|
result->Ident = token;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_ellipsis(AstFile *f, Token token, AstNode *expr) {
|
AstNode *make_ellipsis(AstFile *f, Token token, AstNode *expr) {
|
||||||
AstNode *result = make_node(f, AstNode_Ellipsis);
|
AstNode *result = make_node(f, AstNode_Ellipsis);
|
||||||
result->Ellipsis.token = token;
|
result->Ellipsis.token = token;
|
||||||
result->Ellipsis.expr = expr;
|
result->Ellipsis.expr = expr;
|
||||||
@@ -612,7 +618,7 @@ gb_inline AstNode *make_ellipsis(AstFile *f, Token token, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags) {
|
AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 tags) {
|
||||||
AstNode *result = make_node(f, AstNode_ProcLit);
|
AstNode *result = make_node(f, AstNode_ProcLit);
|
||||||
result->ProcLit.type = type;
|
result->ProcLit.type = type;
|
||||||
result->ProcLit.body = body;
|
result->ProcLit.body = body;
|
||||||
@@ -620,7 +626,7 @@ gb_inline AstNode *make_proc_lit(AstFile *f, AstNode *type, AstNode *body, u64 t
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_field_value(AstFile *f, AstNode *field, AstNode *value, Token eq) {
|
AstNode *make_field_value(AstFile *f, AstNode *field, AstNode *value, Token eq) {
|
||||||
AstNode *result = make_node(f, AstNode_FieldValue);
|
AstNode *result = make_node(f, AstNode_FieldValue);
|
||||||
result->FieldValue.field = field;
|
result->FieldValue.field = field;
|
||||||
result->FieldValue.value = value;
|
result->FieldValue.value = value;
|
||||||
@@ -628,7 +634,7 @@ gb_inline AstNode *make_field_value(AstFile *f, AstNode *field, AstNode *value,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token open, Token close) {
|
AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token open, Token close) {
|
||||||
AstNode *result = make_node(f, AstNode_CompoundLit);
|
AstNode *result = make_node(f, AstNode_CompoundLit);
|
||||||
result->CompoundLit.type = type;
|
result->CompoundLit.type = type;
|
||||||
result->CompoundLit.elems = elems;
|
result->CompoundLit.elems = elems;
|
||||||
@@ -637,33 +643,33 @@ gb_inline AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNodeArray ele
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_bad_stmt(AstFile *f, Token begin, Token end) {
|
AstNode *make_bad_stmt(AstFile *f, Token begin, Token end) {
|
||||||
AstNode *result = make_node(f, AstNode_BadStmt);
|
AstNode *result = make_node(f, AstNode_BadStmt);
|
||||||
result->BadStmt.begin = begin;
|
result->BadStmt.begin = begin;
|
||||||
result->BadStmt.end = end;
|
result->BadStmt.end = end;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_empty_stmt(AstFile *f, Token token) {
|
AstNode *make_empty_stmt(AstFile *f, Token token) {
|
||||||
AstNode *result = make_node(f, AstNode_EmptyStmt);
|
AstNode *result = make_node(f, AstNode_EmptyStmt);
|
||||||
result->EmptyStmt.token = token;
|
result->EmptyStmt.token = token;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_expr_stmt(AstFile *f, AstNode *expr) {
|
AstNode *make_expr_stmt(AstFile *f, AstNode *expr) {
|
||||||
AstNode *result = make_node(f, AstNode_ExprStmt);
|
AstNode *result = make_node(f, AstNode_ExprStmt);
|
||||||
result->ExprStmt.expr = expr;
|
result->ExprStmt.expr = expr;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) {
|
AstNode *make_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) {
|
||||||
AstNode *result = make_node(f, AstNode_IncDecStmt);
|
AstNode *result = make_node(f, AstNode_IncDecStmt);
|
||||||
result->IncDecStmt.op = op;
|
result->IncDecStmt.op = op;
|
||||||
result->IncDecStmt.expr = expr;
|
result->IncDecStmt.expr = expr;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rhs) {
|
AstNode *make_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rhs) {
|
||||||
AstNode *result = make_node(f, AstNode_AssignStmt);
|
AstNode *result = make_node(f, AstNode_AssignStmt);
|
||||||
result->AssignStmt.op = op;
|
result->AssignStmt.op = op;
|
||||||
result->AssignStmt.lhs = lhs;
|
result->AssignStmt.lhs = lhs;
|
||||||
@@ -671,7 +677,7 @@ gb_inline AstNode *make_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstN
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_block_stmt(AstFile *f, AstNodeArray stmts, Token open, Token close) {
|
AstNode *make_block_stmt(AstFile *f, AstNodeArray stmts, Token open, Token close) {
|
||||||
AstNode *result = make_node(f, AstNode_BlockStmt);
|
AstNode *result = make_node(f, AstNode_BlockStmt);
|
||||||
result->BlockStmt.stmts = stmts;
|
result->BlockStmt.stmts = stmts;
|
||||||
result->BlockStmt.open = open;
|
result->BlockStmt.open = open;
|
||||||
@@ -679,7 +685,7 @@ gb_inline AstNode *make_block_stmt(AstFile *f, AstNodeArray stmts, Token open, T
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_if_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body, AstNode *else_stmt) {
|
AstNode *make_if_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body, AstNode *else_stmt) {
|
||||||
AstNode *result = make_node(f, AstNode_IfStmt);
|
AstNode *result = make_node(f, AstNode_IfStmt);
|
||||||
result->IfStmt.token = token;
|
result->IfStmt.token = token;
|
||||||
result->IfStmt.init = init;
|
result->IfStmt.init = init;
|
||||||
@@ -689,14 +695,14 @@ gb_inline AstNode *make_if_stmt(AstFile *f, Token token, AstNode *init, AstNode
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_return_stmt(AstFile *f, Token token, AstNodeArray results) {
|
AstNode *make_return_stmt(AstFile *f, Token token, AstNodeArray results) {
|
||||||
AstNode *result = make_node(f, AstNode_ReturnStmt);
|
AstNode *result = make_node(f, AstNode_ReturnStmt);
|
||||||
result->ReturnStmt.token = token;
|
result->ReturnStmt.token = token;
|
||||||
result->ReturnStmt.results = results;
|
result->ReturnStmt.results = results;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *post, AstNode *body) {
|
AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *post, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_ForStmt);
|
AstNode *result = make_node(f, AstNode_ForStmt);
|
||||||
result->ForStmt.token = token;
|
result->ForStmt.token = token;
|
||||||
result->ForStmt.init = init;
|
result->ForStmt.init = init;
|
||||||
@@ -707,7 +713,7 @@ gb_inline AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, AstNode *body) {
|
AstNode *make_match_stmt(AstFile *f, Token token, AstNode *init, AstNode *tag, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_MatchStmt);
|
AstNode *result = make_node(f, AstNode_MatchStmt);
|
||||||
result->MatchStmt.token = token;
|
result->MatchStmt.token = token;
|
||||||
result->MatchStmt.init = init;
|
result->MatchStmt.init = init;
|
||||||
@@ -717,7 +723,7 @@ gb_inline AstNode *make_match_stmt(AstFile *f, Token token, AstNode *init, AstNo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_type_match_stmt(AstFile *f, Token token, AstNode *tag, AstNode *var, AstNode *body) {
|
AstNode *make_type_match_stmt(AstFile *f, Token token, AstNode *tag, AstNode *var, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_TypeMatchStmt);
|
AstNode *result = make_node(f, AstNode_TypeMatchStmt);
|
||||||
result->TypeMatchStmt.token = token;
|
result->TypeMatchStmt.token = token;
|
||||||
result->TypeMatchStmt.tag = tag;
|
result->TypeMatchStmt.tag = tag;
|
||||||
@@ -726,7 +732,7 @@ gb_inline AstNode *make_type_match_stmt(AstFile *f, Token token, AstNode *tag, A
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_case_clause(AstFile *f, Token token, AstNodeArray list, AstNodeArray stmts) {
|
AstNode *make_case_clause(AstFile *f, Token token, AstNodeArray list, AstNodeArray stmts) {
|
||||||
AstNode *result = make_node(f, AstNode_CaseClause);
|
AstNode *result = make_node(f, AstNode_CaseClause);
|
||||||
result->CaseClause.token = token;
|
result->CaseClause.token = token;
|
||||||
result->CaseClause.list = list;
|
result->CaseClause.list = list;
|
||||||
@@ -735,27 +741,27 @@ gb_inline AstNode *make_case_clause(AstFile *f, Token token, AstNodeArray list,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_defer_stmt(AstFile *f, Token token, AstNode *stmt) {
|
AstNode *make_defer_stmt(AstFile *f, Token token, AstNode *stmt) {
|
||||||
AstNode *result = make_node(f, AstNode_DeferStmt);
|
AstNode *result = make_node(f, AstNode_DeferStmt);
|
||||||
result->DeferStmt.token = token;
|
result->DeferStmt.token = token;
|
||||||
result->DeferStmt.stmt = stmt;
|
result->DeferStmt.stmt = stmt;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_branch_stmt(AstFile *f, Token token) {
|
AstNode *make_branch_stmt(AstFile *f, Token token) {
|
||||||
AstNode *result = make_node(f, AstNode_BranchStmt);
|
AstNode *result = make_node(f, AstNode_BranchStmt);
|
||||||
result->BranchStmt.token = token;
|
result->BranchStmt.token = token;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_using_stmt(AstFile *f, Token token, AstNode *node) {
|
AstNode *make_using_stmt(AstFile *f, Token token, AstNode *node) {
|
||||||
AstNode *result = make_node(f, AstNode_UsingStmt);
|
AstNode *result = make_node(f, AstNode_UsingStmt);
|
||||||
result->UsingStmt.token = token;
|
result->UsingStmt.token = token;
|
||||||
result->UsingStmt.node = node;
|
result->UsingStmt.node = node;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_asm_operand(AstFile *f, Token string, AstNode *operand) {
|
AstNode *make_asm_operand(AstFile *f, Token string, AstNode *operand) {
|
||||||
AstNode *result = make_node(f, AstNode_AsmOperand);
|
AstNode *result = make_node(f, AstNode_AsmOperand);
|
||||||
result->AsmOperand.string = string;
|
result->AsmOperand.string = string;
|
||||||
result->AsmOperand.operand = operand;
|
result->AsmOperand.operand = operand;
|
||||||
@@ -763,7 +769,7 @@ gb_inline AstNode *make_asm_operand(AstFile *f, Token string, AstNode *operand)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_asm_stmt(AstFile *f, Token token, b32 is_volatile, Token open, Token close, Token code_string,
|
AstNode *make_asm_stmt(AstFile *f, Token token, b32 is_volatile, Token open, Token close, Token code_string,
|
||||||
AstNode *output_list, AstNode *input_list, AstNode *clobber_list,
|
AstNode *output_list, AstNode *input_list, AstNode *clobber_list,
|
||||||
isize output_count, isize input_count, isize clobber_count) {
|
isize output_count, isize input_count, isize clobber_count) {
|
||||||
AstNode *result = make_node(f, AstNode_AsmStmt);
|
AstNode *result = make_node(f, AstNode_AsmStmt);
|
||||||
@@ -781,7 +787,7 @@ gb_inline AstNode *make_asm_stmt(AstFile *f, Token token, b32 is_volatile, Token
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_push_allocator(AstFile *f, Token token, AstNode *expr, AstNode *body) {
|
AstNode *make_push_allocator(AstFile *f, Token token, AstNode *expr, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_PushAllocator);
|
AstNode *result = make_node(f, AstNode_PushAllocator);
|
||||||
result->PushAllocator.token = token;
|
result->PushAllocator.token = token;
|
||||||
result->PushAllocator.expr = expr;
|
result->PushAllocator.expr = expr;
|
||||||
@@ -789,7 +795,7 @@ gb_inline AstNode *make_push_allocator(AstFile *f, Token token, AstNode *expr, A
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_push_context(AstFile *f, Token token, AstNode *expr, AstNode *body) {
|
AstNode *make_push_context(AstFile *f, Token token, AstNode *expr, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_PushContext);
|
AstNode *result = make_node(f, AstNode_PushContext);
|
||||||
result->PushContext.token = token;
|
result->PushContext.token = token;
|
||||||
result->PushContext.expr = expr;
|
result->PushContext.expr = expr;
|
||||||
@@ -800,14 +806,14 @@ gb_inline AstNode *make_push_context(AstFile *f, Token token, AstNode *expr, Ast
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_bad_decl(AstFile *f, Token begin, Token end) {
|
AstNode *make_bad_decl(AstFile *f, Token begin, Token end) {
|
||||||
AstNode *result = make_node(f, AstNode_BadDecl);
|
AstNode *result = make_node(f, AstNode_BadDecl);
|
||||||
result->BadDecl.begin = begin;
|
result->BadDecl.begin = begin;
|
||||||
result->BadDecl.end = end;
|
result->BadDecl.end = end;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_var_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
AstNode *make_var_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
||||||
AstNode *result = make_node(f, AstNode_VarDecl);
|
AstNode *result = make_node(f, AstNode_VarDecl);
|
||||||
result->VarDecl.names = names;
|
result->VarDecl.names = names;
|
||||||
result->VarDecl.type = type;
|
result->VarDecl.type = type;
|
||||||
@@ -815,7 +821,7 @@ gb_inline AstNode *make_var_decl(AstFile *f, AstNodeArray names, AstNode *type,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
||||||
AstNode *result = make_node(f, AstNode_ConstDecl);
|
AstNode *result = make_node(f, AstNode_ConstDecl);
|
||||||
result->ConstDecl.names = names;
|
result->ConstDecl.names = names;
|
||||||
result->ConstDecl.type = type;
|
result->ConstDecl.type = type;
|
||||||
@@ -823,7 +829,7 @@ gb_inline AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
|
AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, b32 is_using) {
|
||||||
AstNode *result = make_node(f, AstNode_Parameter);
|
AstNode *result = make_node(f, AstNode_Parameter);
|
||||||
result->Parameter.names = names;
|
result->Parameter.names = names;
|
||||||
result->Parameter.type = type;
|
result->Parameter.type = type;
|
||||||
@@ -831,7 +837,7 @@ gb_inline AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results) {
|
AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params, AstNodeArray results) {
|
||||||
AstNode *result = make_node(f, AstNode_ProcType);
|
AstNode *result = make_node(f, AstNode_ProcType);
|
||||||
result->ProcType.token = token;
|
result->ProcType.token = token;
|
||||||
result->ProcType.params = params;
|
result->ProcType.params = params;
|
||||||
@@ -839,7 +845,7 @@ gb_inline AstNode *make_proc_type(AstFile *f, Token token, AstNodeArray params,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) {
|
AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type, AstNode *body, u64 tags, String foreign_name, String link_name) {
|
||||||
AstNode *result = make_node(f, AstNode_ProcDecl);
|
AstNode *result = make_node(f, AstNode_ProcDecl);
|
||||||
result->ProcDecl.name = name;
|
result->ProcDecl.name = name;
|
||||||
result->ProcDecl.type = proc_type;
|
result->ProcDecl.type = proc_type;
|
||||||
@@ -850,14 +856,21 @@ gb_inline AstNode *make_proc_decl(AstFile *f, AstNode *name, AstNode *proc_type,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type) {
|
AstNode *make_pointer_type(AstFile *f, Token token, AstNode *type) {
|
||||||
AstNode *result = make_node(f, AstNode_PointerType);
|
AstNode *result = make_node(f, AstNode_PointerType);
|
||||||
result->PointerType.token = token;
|
result->PointerType.token = token;
|
||||||
result->PointerType.type = type;
|
result->PointerType.type = type;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
|
AstNode *make_maybe_type(AstFile *f, Token token, AstNode *type) {
|
||||||
|
AstNode *result = make_node(f, AstNode_MaybeType);
|
||||||
|
result->MaybeType.token = token;
|
||||||
|
result->MaybeType.type = type;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *make_array_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
|
||||||
AstNode *result = make_node(f, AstNode_ArrayType);
|
AstNode *result = make_node(f, AstNode_ArrayType);
|
||||||
result->ArrayType.token = token;
|
result->ArrayType.token = token;
|
||||||
result->ArrayType.count = count;
|
result->ArrayType.count = count;
|
||||||
@@ -865,7 +878,7 @@ gb_inline AstNode *make_array_type(AstFile *f, Token token, AstNode *count, AstN
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_vector_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
|
AstNode *make_vector_type(AstFile *f, Token token, AstNode *count, AstNode *elem) {
|
||||||
AstNode *result = make_node(f, AstNode_VectorType);
|
AstNode *result = make_node(f, AstNode_VectorType);
|
||||||
result->VectorType.token = token;
|
result->VectorType.token = token;
|
||||||
result->VectorType.count = count;
|
result->VectorType.count = count;
|
||||||
@@ -873,7 +886,7 @@ gb_inline AstNode *make_vector_type(AstFile *f, Token token, AstNode *count, Ast
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count, b32 is_packed, b32 is_ordered) {
|
AstNode *make_struct_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count, b32 is_packed, b32 is_ordered) {
|
||||||
AstNode *result = make_node(f, AstNode_StructType);
|
AstNode *result = make_node(f, AstNode_StructType);
|
||||||
result->StructType.token = token;
|
result->StructType.token = token;
|
||||||
result->StructType.decls = decls;
|
result->StructType.decls = decls;
|
||||||
@@ -884,7 +897,7 @@ gb_inline AstNode *make_struct_type(AstFile *f, Token token, AstNodeArray decls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_union_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count) {
|
AstNode *make_union_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count) {
|
||||||
AstNode *result = make_node(f, AstNode_UnionType);
|
AstNode *result = make_node(f, AstNode_UnionType);
|
||||||
result->UnionType.token = token;
|
result->UnionType.token = token;
|
||||||
result->UnionType.decls = decls;
|
result->UnionType.decls = decls;
|
||||||
@@ -892,7 +905,7 @@ gb_inline AstNode *make_union_type(AstFile *f, Token token, AstNodeArray decls,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_raw_union_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count) {
|
AstNode *make_raw_union_type(AstFile *f, Token token, AstNodeArray decls, isize decl_count) {
|
||||||
AstNode *result = make_node(f, AstNode_RawUnionType);
|
AstNode *result = make_node(f, AstNode_RawUnionType);
|
||||||
result->RawUnionType.token = token;
|
result->RawUnionType.token = token;
|
||||||
result->RawUnionType.decls = decls;
|
result->RawUnionType.decls = decls;
|
||||||
@@ -901,7 +914,7 @@ gb_inline AstNode *make_raw_union_type(AstFile *f, Token token, AstNodeArray dec
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, AstNodeArray fields) {
|
AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, AstNodeArray fields) {
|
||||||
AstNode *result = make_node(f, AstNode_EnumType);
|
AstNode *result = make_node(f, AstNode_EnumType);
|
||||||
result->EnumType.token = token;
|
result->EnumType.token = token;
|
||||||
result->EnumType.base_type = base_type;
|
result->EnumType.base_type = base_type;
|
||||||
@@ -909,7 +922,7 @@ gb_inline AstNode *make_enum_type(AstFile *f, Token token, AstNode *base_type, A
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) {
|
AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNode *type) {
|
||||||
AstNode *result = make_node(f, AstNode_TypeDecl);
|
AstNode *result = make_node(f, AstNode_TypeDecl);
|
||||||
result->TypeDecl.token = token;
|
result->TypeDecl.token = token;
|
||||||
result->TypeDecl.name = name;
|
result->TypeDecl.name = name;
|
||||||
@@ -917,7 +930,7 @@ gb_inline AstNode *make_type_decl(AstFile *f, Token token, AstNode *name, AstNod
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Token import_name, b32 is_load) {
|
AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Token import_name, b32 is_load) {
|
||||||
AstNode *result = make_node(f, AstNode_ImportDecl);
|
AstNode *result = make_node(f, AstNode_ImportDecl);
|
||||||
result->ImportDecl.token = token;
|
result->ImportDecl.token = token;
|
||||||
result->ImportDecl.relpath = relpath;
|
result->ImportDecl.relpath = relpath;
|
||||||
@@ -926,7 +939,7 @@ gb_inline AstNode *make_import_decl(AstFile *f, Token token, Token relpath, Toke
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline AstNode *make_foreign_system_library(AstFile *f, Token token, Token filepath) {
|
AstNode *make_foreign_system_library(AstFile *f, Token token, Token filepath) {
|
||||||
AstNode *result = make_node(f, AstNode_ForeignSystemLibrary);
|
AstNode *result = make_node(f, AstNode_ForeignSystemLibrary);
|
||||||
result->ForeignSystemLibrary.token = token;
|
result->ForeignSystemLibrary.token = token;
|
||||||
result->ForeignSystemLibrary.filepath = filepath;
|
result->ForeignSystemLibrary.filepath = filepath;
|
||||||
@@ -950,7 +963,7 @@ b32 next_token(AstFile *f) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline 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) {
|
||||||
syntax_error(f->curr_token, "Expected `%.*s`, got `%.*s`",
|
syntax_error(f->curr_token, "Expected `%.*s`, got `%.*s`",
|
||||||
@@ -961,7 +974,7 @@ gb_inline Token expect_token(AstFile *f, TokenKind kind) {
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline Token expect_token_after(AstFile *f, TokenKind kind, char *msg) {
|
Token expect_token_after(AstFile *f, TokenKind kind, char *msg) {
|
||||||
Token prev = f->curr_token;
|
Token prev = f->curr_token;
|
||||||
if (prev.kind != kind) {
|
if (prev.kind != kind) {
|
||||||
syntax_error(f->curr_token, "Expected `%.*s` after %s, got `%.*s`",
|
syntax_error(f->curr_token, "Expected `%.*s` after %s, got `%.*s`",
|
||||||
@@ -974,7 +987,7 @@ gb_inline Token expect_token_after(AstFile *f, TokenKind kind, char *msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gb_inline Token expect_operator(AstFile *f) {
|
Token expect_operator(AstFile *f) {
|
||||||
Token prev = f->curr_token;
|
Token prev = f->curr_token;
|
||||||
if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
|
if (!gb_is_between(prev.kind, Token__OperatorBegin+1, Token__OperatorEnd-1)) {
|
||||||
syntax_error(f->curr_token, "Expected an operator, got `%.*s`",
|
syntax_error(f->curr_token, "Expected an operator, got `%.*s`",
|
||||||
@@ -984,7 +997,7 @@ gb_inline Token expect_operator(AstFile *f) {
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline Token expect_keyword(AstFile *f) {
|
Token expect_keyword(AstFile *f) {
|
||||||
Token prev = f->curr_token;
|
Token prev = f->curr_token;
|
||||||
if (!gb_is_between(prev.kind, Token__KeywordBegin+1, Token__KeywordEnd-1)) {
|
if (!gb_is_between(prev.kind, Token__KeywordBegin+1, Token__KeywordEnd-1)) {
|
||||||
syntax_error(f->curr_token, "Expected a keyword, got `%.*s`",
|
syntax_error(f->curr_token, "Expected a keyword, got `%.*s`",
|
||||||
@@ -994,7 +1007,7 @@ gb_inline Token expect_keyword(AstFile *f) {
|
|||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline b32 allow_token(AstFile *f, TokenKind kind) {
|
b32 allow_token(AstFile *f, TokenKind kind) {
|
||||||
Token prev = f->curr_token;
|
Token prev = f->curr_token;
|
||||||
if (prev.kind == kind) {
|
if (prev.kind == kind) {
|
||||||
next_token(f);
|
next_token(f);
|
||||||
@@ -1986,8 +1999,17 @@ AstNode *parse_identifier_or_type(AstFile *f, u32 flags) {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Token_Pointer:
|
case Token_Pointer: {
|
||||||
return make_pointer_type(f, expect_token(f, Token_Pointer), parse_type(f));
|
Token token = expect_token(f, Token_Pointer);
|
||||||
|
AstNode *elem = parse_type(f);
|
||||||
|
return make_pointer_type(f, token, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Token_Maybe: {
|
||||||
|
Token token = expect_token(f, Token_Maybe);
|
||||||
|
AstNode *elem = parse_type(f);
|
||||||
|
return make_maybe_type(f, token, elem);
|
||||||
|
}
|
||||||
|
|
||||||
case Token_OpenBracket: {
|
case Token_OpenBracket: {
|
||||||
f->expr_level++;
|
f->expr_level++;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
|
|||||||
TOKEN_KIND(Token_Hash, "#"), \
|
TOKEN_KIND(Token_Hash, "#"), \
|
||||||
TOKEN_KIND(Token_At, "@"), \
|
TOKEN_KIND(Token_At, "@"), \
|
||||||
TOKEN_KIND(Token_Pointer, "^"), \
|
TOKEN_KIND(Token_Pointer, "^"), \
|
||||||
|
TOKEN_KIND(Token_Maybe, "?"), \
|
||||||
TOKEN_KIND(Token_Add, "+"), \
|
TOKEN_KIND(Token_Add, "+"), \
|
||||||
TOKEN_KIND(Token_Sub, "-"), \
|
TOKEN_KIND(Token_Sub, "-"), \
|
||||||
TOKEN_KIND(Token_Mul, "*"), \
|
TOKEN_KIND(Token_Mul, "*"), \
|
||||||
@@ -720,6 +721,7 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
case '#': token.kind = Token_Hash; break;
|
case '#': token.kind = Token_Hash; break;
|
||||||
case '@': token.kind = Token_At; break;
|
case '@': token.kind = Token_At; break;
|
||||||
case '^': token.kind = Token_Pointer; break;
|
case '^': token.kind = Token_Pointer; break;
|
||||||
|
case '?': token.kind = Token_Maybe; break;
|
||||||
case ';': token.kind = Token_Semicolon; break;
|
case ';': token.kind = Token_Semicolon; break;
|
||||||
case ',': token.kind = Token_Comma; break;
|
case ',': token.kind = Token_Comma; break;
|
||||||
case '(': token.kind = Token_OpenParen; break;
|
case '(': token.kind = Token_OpenParen; break;
|
||||||
|
|||||||
Reference in New Issue
Block a user