aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2017-01-25 19:19:25 +0000
committerGinger Bill <bill@gingerbill.org>2017-01-25 19:19:25 +0000
commitb59a052e32b1ed84134e31baad86c8e401f796c6 (patch)
tree9aef601f0d9a25e43fe046f274508bf774dad9a2 /src
parent12498b2d390c95fd49672f8ee1c64b7b254c293c (diff)
Change casting syntax: `cast(T)x` `transmute(T)x` et al.
Diffstat (limited to 'src')
-rw-r--r--src/check_decl.c2
-rw-r--r--src/check_expr.c390
-rw-r--r--src/check_stmt.c21
-rw-r--r--src/checker.c55
-rw-r--r--src/common.c11
-rw-r--r--src/entity.c4
-rw-r--r--src/ir.c123
-rw-r--r--src/ir_opt.c3
-rw-r--r--src/ir_print.c10
-rw-r--r--src/main.c3
-rw-r--r--src/parser.c119
-rw-r--r--src/tokenizer.c5
-rw-r--r--src/types.c4
13 files changed, 437 insertions, 313 deletions
diff --git a/src/check_decl.c b/src/check_decl.c
index 600b4c0d6..a97b1b90e 100644
--- a/src/check_decl.c
+++ b/src/check_decl.c
@@ -372,8 +372,6 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
GB_ASSERT(e->type == NULL);
GB_ASSERT(e->kind == Entity_Variable);
- u32 flags = c->context.decl->var_decl_flags;
-
if (e->flags & EntityFlag_Visited) {
e->type = t_invalid;
return;
diff --git a/src/check_expr.c b/src/check_expr.c
index 4b26ca990..dd92fc38e 100644
--- a/src/check_expr.c
+++ b/src/check_expr.c
@@ -1094,10 +1094,10 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
if (ue->op.kind == Token_Pointer) {
type = make_type_pointer(c->allocator, check_type(c, ue->expr));
goto end;
- } else if (ue->op.kind == Token_Maybe) {
+ } /* else if (ue->op.kind == Token_Maybe) {
type = make_type_maybe(c->allocator, check_type(c, ue->expr));
goto end;
- }
+ } */
case_end;
case_ast_node(ht, HelperType, e);
@@ -1133,7 +1133,7 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
Type *elem = check_type(c, vt->elem);
Type *be = base_type(elem);
i64 count = check_array_count(c, vt->count);
- if (!is_type_boolean(be) && !is_type_numeric(be)) {
+ if (is_type_vector(be) || (!is_type_boolean(be) && !is_type_numeric(be))) {
err_str = type_to_string(elem);
error_node(vt->elem, "Vector element type must be numerical or a boolean, got `%s`", err_str);
}
@@ -2589,10 +2589,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
case BuiltinProc_align_of:
case BuiltinProc_offset_of:
case BuiltinProc_type_info:
-
- case BuiltinProc_transmute:
- case BuiltinProc_union_cast:
- case BuiltinProc_down_cast:
// NOTE(bill): The first arg may be a Type, this will be checked case by case
break;
default:
@@ -2837,186 +2833,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
operand->type = t_type_info_ptr;
} break;
-
- case BuiltinProc_transmute: {
- Type *type = check_type(c, ce->args.e[0]);
- check_expr(c, operand, ce->args.e[1]);
- if (operand->mode == Addressing_Invalid) {
- return false;
- }
-
- if (operand->mode == Addressing_Constant) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Cannot transmute constant expression: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- if (is_type_untyped(operand->type)) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Cannot transmute untyped expression: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- i64 srcz = type_size_of(c->sizes, c->allocator, operand->type);
- i64 dstz = type_size_of(c->sizes, c->allocator, type);
- if (srcz != dstz) {
- gbString expr_str = expr_to_string(operand->expr);
- gbString type_str = type_to_string(type);
- error_node(operand->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
- gb_string_free(type_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- operand->type = type;
- } break;
- case BuiltinProc_union_cast: {
- Type *type = check_type(c, ce->args.e[0]);
- check_expr(c, operand, ce->args.e[1]);
- if (operand->mode == Addressing_Invalid) {
- return false;
- }
-
- if (operand->mode == Addressing_Constant) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Cannot `union_cast` a constant expression: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- if (is_type_untyped(operand->type)) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Cannot `union_cast` an untyped expression: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- bool src_is_ptr = is_type_pointer(operand->type);
- bool dst_is_ptr = is_type_pointer(type);
- Type *src = type_deref(operand->type);
- Type *dst = type_deref(type);
- Type *bsrc = base_type(src);
- Type *bdst = base_type(dst);
-
- if (src_is_ptr != dst_is_ptr) {
- gbString src_type_str = type_to_string(operand->type);
- gbString dst_type_str = type_to_string(type);
- error_node(operand->expr, "Invalid `union_cast` types: `%s` and `%s`", src_type_str, dst_type_str);
- gb_string_free(dst_type_str);
- gb_string_free(src_type_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- if (!is_type_union(src)) {
- error_node(operand->expr, "`union_cast` can only operate on unions");
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- bool ok = false;
- for (isize i = 1; i < bsrc->Record.field_count; i++) {
- Entity *f = bsrc->Record.fields[i];
- if (are_types_identical(f->type, dst)) {
- ok = true;
- break;
- }
- }
-
- if (!ok) {
- gbString expr_str = expr_to_string(operand->expr);
- gbString dst_type_str = type_to_string(type);
- error_node(operand->expr, "Cannot `union_cast` `%s` to `%s`", expr_str, dst_type_str);
- gb_string_free(dst_type_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- Entity **variables = gb_alloc_array(c->allocator, Entity *, 2);
- variables[0] = make_entity_param(c->allocator, NULL, empty_token, type, false, true);
- variables[1] = make_entity_param(c->allocator, NULL, empty_token, t_bool, false, true);
-
- Type *tuple = make_type_tuple(c->allocator);
- tuple->Tuple.variables = variables;
- tuple->Tuple.variable_count = 2;
-
- operand->type = tuple;
- operand->mode = Addressing_Value;
- } break;
- case BuiltinProc_down_cast: {
- Type *type = check_type(c, ce->args.e[0]);
- check_expr(c, operand, ce->args.e[1]);
- if (operand->mode == Addressing_Invalid) {
- return false;
- }
-
- if (operand->mode == Addressing_Constant) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Cannot `down_cast` a constant expression: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- if (is_type_untyped(operand->type)) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Cannot `down_cast` an untyped expression: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- if (!(is_type_pointer(operand->type) && is_type_pointer(type))) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Can only `down_cast` pointers: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- Type *src = type_deref(operand->type);
- Type *dst = type_deref(type);
- Type *bsrc = base_type(src);
- Type *bdst = base_type(dst);
-
- if (!(is_type_struct(bsrc) || is_type_raw_union(bsrc))) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Can only `down_cast` pointer from structs or unions: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- if (!(is_type_struct(bdst) || is_type_raw_union(bdst))) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Can only `down_cast` pointer to structs or unions: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- String param_name = check_down_cast_name(dst, src);
- if (param_name.len == 0) {
- gbString expr_str = expr_to_string(operand->expr);
- error_node(operand->expr, "Illegal `down_cast`: `%s`", expr_str);
- gb_string_free(expr_str);
- operand->mode = Addressing_Invalid;
- return false;
- }
-
- operand->mode = Addressing_Value;
- operand->type = type;
- } break;
-
-
case BuiltinProc_compile_assert:
// compile_assert :: proc(cond: bool)
@@ -3835,6 +3651,13 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
}
if (operand->mode == Addressing_Type) {
+ gbString str = type_to_string(operand->type);
+ error_node(call, "Expected a procedure, got a type `%s`", str);
+ gb_string_free(str);
+ operand->mode = Addressing_Invalid;
+ operand->expr = call;
+ return Expr_Stmt;
+ #if 0
Type *t = operand->type;
gbString str = type_to_string(t);
operand->mode = Addressing_Invalid;
@@ -3852,6 +3675,7 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
gb_string_free(str);
return Expr_Expr;
+ #endif
}
if (operand->mode == Addressing_Builtin) {
@@ -3909,6 +3733,17 @@ ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
return Expr_Stmt;
}
+
+ExprKind check_macro_call_expr(Checker *c, Operand *operand, AstNode *call) {
+ GB_ASSERT(call->kind == AstNode_MacroCallExpr);
+ ast_node(mce, MacroCallExpr, call);
+
+ error_node(call, "Macro call expressions are not yet supported");
+ operand->mode = Addressing_Invalid;
+ operand->expr = call;
+ return Expr_Stmt;
+}
+
void check_expr_with_type_hint(Checker *c, Operand *o, AstNode *e, Type *t) {
check_expr_base(c, o, e, t);
check_not_tuple(c, o);
@@ -4563,6 +4398,183 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
o->expr = node;
case_end;
+ case_ast_node(ce, CastExpr, node);
+ Type *t = check_type(c, ce->type);
+ check_expr(c, o, ce->expr);
+ if (o->mode == Addressing_Invalid) {
+ goto error;
+ }
+ switch (ce->token.kind) {
+ case Token_cast:
+ check_conversion(c, o, t);
+ break;
+ case Token_transmute: {
+ if (o->mode == Addressing_Constant) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Cannot transmute constant expression: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ if (is_type_untyped(o->type)) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Cannot transmute untyped expression: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ i64 srcz = type_size_of(c->sizes, c->allocator, o->type);
+ i64 dstz = type_size_of(c->sizes, c->allocator, t);
+ if (srcz != dstz) {
+ gbString expr_str = expr_to_string(o->expr);
+ gbString type_str = type_to_string(t);
+ error_node(o->expr, "Cannot transmute `%s` to `%s`, %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
+ gb_string_free(type_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ o->type = t;
+ } break;
+
+ case Token_union_cast: {
+ if (o->mode == Addressing_Constant) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Cannot `union_cast` a constant expression: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ if (is_type_untyped(o->type)) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Cannot `union_cast` an untyped expression: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ bool src_is_ptr = is_type_pointer(o->type);
+ bool dst_is_ptr = is_type_pointer(t);
+ Type *src = type_deref(o->type);
+ Type *dst = type_deref(t);
+ Type *bsrc = base_type(src);
+ Type *bdst = base_type(dst);
+
+ if (src_is_ptr != dst_is_ptr) {
+ gbString src_type_str = type_to_string(o->type);
+ gbString dst_type_str = type_to_string(t);
+ error_node(o->expr, "Invalid `union_cast` types: `%s` and `%s`", src_type_str, dst_type_str);
+ gb_string_free(dst_type_str);
+ gb_string_free(src_type_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ if (!is_type_union(src)) {
+ error_node(o->expr, "`union_cast` can only operate on unions");
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ bool ok = false;
+ for (isize i = 1; i < bsrc->Record.field_count; i++) {
+ Entity *f = bsrc->Record.fields[i];
+ if (are_types_identical(f->type, dst)) {
+ ok = true;
+ break;
+ }
+ }
+
+ if (!ok) {
+ gbString expr_str = expr_to_string(o->expr);
+ gbString dst_type_str = type_to_string(t);
+ error_node(o->expr, "Cannot `union_cast` `%s` to `%s`", expr_str, dst_type_str);
+ gb_string_free(dst_type_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ Entity **variables = gb_alloc_array(c->allocator, Entity *, 2);
+ variables[0] = make_entity_param(c->allocator, NULL, empty_token, t, false, true);
+ variables[1] = make_entity_param(c->allocator, NULL, empty_token, t_bool, false, true);
+
+ Type *tuple = make_type_tuple(c->allocator);
+ tuple->Tuple.variables = variables;
+ tuple->Tuple.variable_count = 2;
+
+ o->type = tuple;
+ o->mode = Addressing_Value;
+ } break;
+ case Token_down_cast: {
+ if (o->mode == Addressing_Constant) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Cannot `down_cast` a constant expression: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ if (is_type_untyped(o->type)) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Cannot `down_cast` an untyped expression: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ if (!(is_type_pointer(o->type) && is_type_pointer(t))) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Can only `down_cast` pointers: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ Type *src = type_deref(o->type);
+ Type *dst = type_deref(t);
+ Type *bsrc = base_type(src);
+ Type *bdst = base_type(dst);
+
+ if (!(is_type_struct(bsrc) || is_type_raw_union(bsrc))) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Can only `down_cast` pointer from structs or unions: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ if (!(is_type_struct(bdst) || is_type_raw_union(bdst))) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Can only `down_cast` pointer to structs or unions: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ String param_name = check_down_cast_name(dst, src);
+ if (param_name.len == 0) {
+ gbString expr_str = expr_to_string(o->expr);
+ error_node(o->expr, "Illegal `down_cast`: `%s`", expr_str);
+ gb_string_free(expr_str);
+ o->mode = Addressing_Invalid;
+ goto error;
+ }
+
+ o->mode = Addressing_Value;
+ o->type = t;
+ } break;
+
+
+ default:
+ GB_PANIC("Unknown cast expression");
+ }
+ case_end;
+
case_ast_node(ue, UnaryExpr, node);
check_expr_base(c, o, ue->expr, type_hint);
@@ -4719,6 +4731,10 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
return check_call_expr(c, o, node);
case_end;
+ case_ast_node(ce, MacroCallExpr, node);
+ return check_macro_call_expr(c, o, node);
+ case_end;
+
case_ast_node(de, DerefExpr, node);
check_expr_or_type(c, o, de->expr);
if (o->mode == Addressing_Invalid) {
diff --git a/src/check_stmt.c b/src/check_stmt.c
index 1fa16e0ac..be364559d 100644
--- a/src/check_stmt.c
+++ b/src/check_stmt.c
@@ -1232,12 +1232,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case_ast_node(vd, ValueDecl, node);
+ GB_ASSERT(!c->context.scope->is_file);
if (vd->is_var) {
Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
isize entity_count = 0;
- if (vd->flags&VarDeclFlag_thread_local &&
- !c->context.scope->is_file) {
+ if (vd->flags & VarDeclFlag_thread_local) {
+ vd->flags &= ~VarDeclFlag_thread_local;
error_node(node, "`thread_local` may only be applied to a variable declaration");
}
@@ -1256,7 +1257,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
if (found == NULL) {
entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, vd->flags&VarDeclFlag_immutable);
- add_entity_definition(&c->info, name, entity);
+ entity->identifier = name;
} else {
TokenPos pos = found->token.pos;
error(token,
@@ -1297,10 +1298,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_arity_match(c, vd);
check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
- for_array(i, vd->names) {
- if (entities[i] != NULL) {
- add_entity(c, c->context.scope, vd->names.e[i], entities[i]);
- }
+ for (isize i = 0; i < entity_count; i++) {
+ add_entity(c, c->context.scope, entities[i]->identifier, entities[i]);
}
if ((vd->flags & VarDeclFlag_using) != 0) {
@@ -1315,13 +1314,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (e == NULL) {
continue;
}
- bool is_immutable = false;
- if (e->kind == Entity_Variable) {
- is_immutable = e->Variable.is_immutable;
+ if (e->kind != Entity_Variable) {
+ continue;
}
-
+ bool is_immutable = e->Variable.is_immutable;
String name = e->token.string;
Type *t = base_type(type_deref(e->type));
+
if (is_type_struct(t) || is_type_raw_union(t)) {
Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
GB_ASSERT(found != NULL);
diff --git a/src/checker.c b/src/checker.c
index cc4f310ed..983198f38 100644
--- a/src/checker.c
+++ b/src/checker.c
@@ -62,7 +62,6 @@ typedef struct DeclInfo {
AstNode *type_expr;
AstNode *init_expr;
AstNode *proc_lit; // AstNode_ProcLit
- u32 var_decl_flags;
MapBool deps; // Key: Entity *
} DeclInfo;
@@ -136,10 +135,6 @@ typedef enum BuiltinProcId {
BuiltinProc_type_info,
BuiltinProc_type_info_of_val,
- BuiltinProc_transmute,
- BuiltinProc_union_cast,
- BuiltinProc_down_cast,
-
BuiltinProc_compile_assert,
BuiltinProc_assert,
BuiltinProc_panic,
@@ -183,10 +178,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("type_info"), 1, false, Expr_Expr},
{STR_LIT("type_info_of_val"), 1, false, Expr_Expr},
- {STR_LIT("transmute"), 2, false, Expr_Expr},
- {STR_LIT("union_cast"), 2, false, Expr_Expr},
- {STR_LIT("down_cast"), 2, false, Expr_Expr},
-
{STR_LIT("compile_assert"), 1, false, Expr_Stmt},
{STR_LIT("assert"), 1, false, Expr_Stmt},
{STR_LIT("panic"), 1, false, Expr_Stmt},
@@ -524,8 +515,6 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
Entity *prev = NULL;
if (found) {
prev = *found;
- GB_ASSERT(prev != entity);
-
if (prev->kind != Entity_Procedure &&
entity->kind != Entity_Procedure) {
return prev;
@@ -533,6 +522,9 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
}
if (prev != NULL && entity->kind == Entity_Procedure) {
+ if (s->is_global) {
+ return prev;
+ }
map_entity_multi_insert(&s->elements, key, entity);
} else {
map_entity_set(&s->elements, key, entity);
@@ -797,10 +789,15 @@ void add_entity_definition(CheckerInfo *i, AstNode *identifier, Entity *entity)
bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
String name = entity->token.string;
if (!str_eq(name, str_lit("_"))) {
- Entity *insert_entity = scope_insert_entity(scope, entity);
- if (insert_entity) {
- Entity *up = insert_entity->using_parent;
+ Entity *ie = scope_insert_entity(scope, entity);
+ if (ie) {
+ TokenPos pos = ie->token.pos;
+ Entity *up = ie->using_parent;
if (up != NULL) {
+ if (token_pos_eq(pos, up->token.pos)) {
+ // NOTE(bill): Error should have been handled already
+ return false;
+ }
error(entity->token,
"Redeclararation of `%.*s` in this scope through `using`\n"
"\tat %.*s(%td:%td)",
@@ -808,7 +805,6 @@ bool add_entity(Checker *c, Scope *scope, AstNode *identifier, Entity *entity) {
LIT(up->token.pos.file), up->token.pos.line, up->token.pos.column);
return false;
} else {
- TokenPos pos = insert_entity->token.pos;
if (token_pos_eq(pos, entity->token.pos)) {
// NOTE(bill): Error should have been handled already
return false;
@@ -1374,14 +1370,13 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
break;
}
// NOTE(bill): You need to store the entity information here unline a constant declaration
- isize entity_count = vd->names.count;
- isize entity_index = 0;
- Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
+ isize entity_cap = vd->names.count;
+ isize entity_count = 0;
+ Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_cap);
DeclInfo *di = NULL;
if (vd->values.count > 0) {
di = make_declaration_info(heap_allocator(), c->context.scope);
di->entities = entities;
- di->entity_count = entity_count;
di->type_expr = vd->type;
di->init_expr = vd->values.e[0];
}
@@ -1396,13 +1391,14 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
continue;
}
- Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident, NULL, vd->flags&VarDeclFlag_immutable);
+ Entity *e = make_entity_variable(c->allocator, c->context.scope, name->Ident, NULL, vd->flags & VarDeclFlag_immutable);
+ e->Variable.is_thread_local = vd->flags & VarDeclFlag_thread_local;
e->identifier = name;
- if (vd->flags&VarDeclFlag_using) {
+ if (vd->flags & VarDeclFlag_using) {
vd->flags &= ~VarDeclFlag_using; // NOTE(bill): This error will be only caught once
error_node(name, "`using` is not allowed at the file scope");
}
- entities[entity_index++] = e;
+ entities[entity_count++] = e;
DeclInfo *d = di;
if (d == NULL) {
@@ -1410,12 +1406,15 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
d = make_declaration_info(heap_allocator(), e->scope);
d->type_expr = vd->type;
d->init_expr = init_expr;
- d->var_decl_flags = vd->flags;
}
add_entity_and_decl_info(c, name, e, d);
}
+ if (di != NULL) {
+ di->entity_count = entity_count;
+ }
+
check_arity_match(c, vd);
} else {
for_array(i, vd->names) {
@@ -1434,14 +1433,14 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
Entity *e = NULL;
AstNode *up_init = unparen_expr(init);
- if (init != NULL && is_ast_node_type(up_init)) {
+ if (up_init != NULL && is_ast_node_type(up_init)) {
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
// TODO(bill): What if vd->type != NULL??? How to handle this case?
d->type_expr = init;
d->init_expr = init;
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
- d->proc_lit = init;
+ d->proc_lit = up_init;
d->type_expr = vd->type;
} else {
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, (ExactValue){0});
@@ -1474,7 +1473,11 @@ void check_collect_entities(Checker *c, AstNodeArray nodes, bool is_file_scope)
case_end;
case_ast_node(fl, ForeignLibrary, decl);
if (!c->context.scope->is_file) {
- error_node(decl, "#foreign_library declarations are only allowed in the file scope");
+ if (fl->is_system) {
+ error_node(decl, "#foreign_system_library declarations are only allowed in the file scope");
+ } else {
+ error_node(decl, "#foreign_library declarations are only allowed in the file scope");
+ }
// NOTE(bill): _Should_ be caught by the parser
// TODO(bill): Better error handling if it isn't
continue;
diff --git a/src/common.c b/src/common.c
index a43ee9d32..e2a70f576 100644
--- a/src/common.c
+++ b/src/common.c
@@ -12,6 +12,17 @@ gbAllocator heap_allocator(void) {
gb_global String global_module_path = {0};
gb_global bool global_module_path_set = false;
+gb_global gbScratchMemory scratch_memory = {0};
+
+void init_scratch_memory(isize size) {
+ void *memory = gb_alloc(heap_allocator(), size);
+ gb_scratch_memory_init(&scratch_memory, memory, size);
+}
+
+gbAllocator scratch_allocator(void) {
+ return gb_scratch_allocator(&scratch_memory);
+}
+
i64 next_pow2(i64 n) {
if (n <= 0) {
diff --git a/src/entity.c b/src/entity.c
index aaccad476..4991c8d37 100644
--- a/src/entity.c
+++ b/src/entity.c
@@ -66,6 +66,7 @@ struct Entity {
i32 field_index;
i32 field_src_index;
bool is_immutable;
+ bool is_thread_local;
} Variable;
i32 TypeName;
struct {
@@ -111,6 +112,7 @@ Entity *make_entity_variable(gbAllocator a, Scope *scope, Token token, Type *typ
Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, Type *type) {
GB_ASSERT(parent != NULL);
+ token.pos = parent->token.pos;
Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type);
entity->using_parent = parent;
entity->flags |= EntityFlag_Anonymous;
@@ -132,7 +134,7 @@ Entity *make_entity_type_name(gbAllocator a, Scope *scope, Token token, Type *ty
Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, bool anonymous, bool is_immutable) {
Entity *entity = make_entity_variable(a, scope, token, type, is_immutable);
entity->flags |= EntityFlag_Used;
- entity->flags |= EntityFlag_Anonymous*(anonymous != 0);
+ if (anonymous) entity->flags |= EntityFlag_Anonymous;
entity->flags |= EntityFlag_Param;
return entity;
}
diff --git a/src/ir.c b/src/ir.c
index 5b195958f..81f529d6a 100644
--- a/src/ir.c
+++ b/src/ir.c
@@ -156,11 +156,6 @@ struct irProcedure {
Type * result_type; \
i32 elem_index; \
}) \
- IR_INSTR_KIND(ArrayExtractValue, struct { \
- irValue *address; \
- Type * result_type; \
- i32 index; \
- }) \
IR_INSTR_KIND(StructExtractValue, struct { \
irValue *address; \
Type * result_type; \
@@ -550,8 +545,6 @@ Type *ir_instr_type(irInstr *instr) {
return ir_type(instr->PtrOffset.address);
case irInstr_Phi:
return instr->Phi.type;
- case irInstr_ArrayExtractValue:
- return instr->ArrayExtractValue.result_type;
case irInstr_StructExtractValue:
return instr->StructExtractValue.result_type;
case irInstr_UnionTagPtr:
@@ -851,17 +844,6 @@ irValue *ir_make_instr_ptr_offset(irProcedure *p, irValue *address, irValue *off
-irValue *ir_make_instr_array_extract_value(irProcedure *p, irValue *address, i32 index) {
- irValue *v = ir_alloc_instr(p, irInstr_ArrayExtractValue);
- irInstr *i = &v->Instr;
- i->ArrayExtractValue.address = address;
- i->ArrayExtractValue.index = index;
- Type *t = base_type(ir_type(address));
- GB_ASSERT(is_type_array(t));
- i->ArrayExtractValue.result_type = t->Array.elem;
- return v;
-}
-
irValue *ir_make_instr_struct_extract_value(irProcedure *p, irValue *address, i32 index, Type *result_type) {
irValue *v = ir_alloc_instr(p, irInstr_StructExtractValue);
irInstr *i = &v->Instr;
@@ -1646,13 +1628,6 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
}
-
-irValue *ir_emit_array_ev(irProcedure *proc, irValue *s, i32 index) {
- Type *st = base_type(ir_type(s));
- GB_ASSERT(is_type_array(st));
- return ir_emit(proc, ir_make_instr_array_extract_value(proc, s, index));
-}
-
irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
// NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32
@@ -1913,6 +1888,12 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
Type *src = base_type(base_enum_type(src_type));
Type *dst = base_type(base_enum_type(t));
+
+ // if (is_type_untyped_nil(src) && type_has_nil(dst)) {
+ if (is_type_untyped_nil(src)) {
+ return ir_make_value_nil(proc->module->allocator, t);
+ }
+
if (value->kind == irValue_Constant) {
if (is_type_any(dst)) {
irValue *default_value = ir_add_local_generated(proc, default_type(src_type));
@@ -2147,10 +2128,6 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
return ir_emit_load(proc, result);
}
- if (is_type_untyped_nil(src) && type_has_nil(dst)) {
- return ir_make_value_nil(proc->module->allocator, t);
- }
-
gb_printf_err("ir_emit_conv: src -> dst\n");
gb_printf_err("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
@@ -2718,13 +2695,38 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
return v;
case_end;
+ case_ast_node(ce, CastExpr, expr);
+ Type *type = tv->type;
+ irValue *expr = ir_build_expr(proc, ce->expr);
+ switch (ce->token.kind) {
+ case Token_cast:
+ ir_emit_comment(proc, str_lit("cast - cast"));
+ return ir_emit_conv(proc, expr, type);
+
+ case Token_transmute:
+ ir_emit_comment(proc, str_lit("cast - transmute"));
+ return ir_emit_transmute(proc, expr, type);
+
+ case Token_down_cast:
+ ir_emit_comment(proc, str_lit("cast - down_cast"));
+ return ir_emit_down_cast(proc, expr, type);
+
+ case Token_union_cast:
+ ir_emit_comment(proc, str_lit("cast - union_cast"));
+ return ir_emit_union_cast(proc, expr, type);
+
+ default:
+ GB_PANIC("Unknown cast expression");
+ }
+ case_end;
+
case_ast_node(ue, UnaryExpr, expr);
switch (ue->op.kind) {
case Token_Pointer:
return ir_emit_ptr_offset(proc, ir_build_addr(proc, ue->expr).addr, v_zero); // Make a copy of the pointer
- case Token_Maybe:
- return ir_emit_conv(proc, ir_build_expr(proc, ue->expr), type_of_expr(proc->module->info, expr));
+ // case Token_Maybe:
+ // return ir_emit_conv(proc, ir_build_expr(proc, ue->expr), type_of_expr(proc->module->info, expr));
case Token_Add:
return ir_build_expr(proc, ue->expr);
@@ -2844,24 +2846,6 @@ irValue *ir_build_single_expr(irProcedure *proc, AstNode *expr, TypeAndValue *tv
return ir_type_info(proc, t);
} break;
- case BuiltinProc_transmute: {
- irValue *val = ir_build_expr(proc, ce->args.e[1]);
- ir_emit_comment(proc, str_lit("cast - transmute"));
- return ir_emit_transmute(proc, val, type_of_expr(proc->module->info, ce->args.e[0]));
- }
-
- case BuiltinProc_down_cast: {
- irValue *val = ir_build_expr(proc, ce->args.e[1]);
- ir_emit_comment(proc, str_lit("cast - down_cast"));
- return ir_emit_down_cast(proc, val, type_of_expr(proc->module->info, ce->args.e[0]));
- }
-
- case BuiltinProc_union_cast: {
- irValue *val = ir_build_expr(proc, ce->args.e[1]);
- ir_emit_comment(proc, str_lit("cast - union_cast"));
- return ir_emit_union_cast(proc, val, type_of_expr(proc->module->info, ce->args.e[0]));
- }
-
case BuiltinProc_new: {
ir_emit_comment(proc, str_lit("new"));
// new :: proc(Type) -> ^Type
@@ -3405,6 +3389,29 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
}
case_end;
+ case_ast_node(ce, CastExpr, expr);
+ switch (ce->token.kind) {
+ case Token_cast: {
+ ir_emit_comment(proc, str_lit("Cast - cast"));
+ // NOTE(bill): Needed for dereference of pointer conversion
+ Type *type = type_of_expr(proc->module->info, expr);
+ irValue *v = ir_add_local_generated(proc, type);
+ ir_emit_store(proc, v, ir_emit_conv(proc, ir_build_expr(proc, ce->expr), type));
+ return ir_make_addr(v, expr);
+ }
+ case Token_transmute: {
+ ir_emit_comment(proc, str_lit("Cast - transmute"));
+ // NOTE(bill): Needed for dereference of pointer conversion
+ Type *type = type_of_expr(proc->module->info, expr);
+ irValue *v = ir_add_local_generated(proc, type);
+ ir_emit_store(proc, v, ir_emit_transmute(proc, ir_build_expr(proc, ce->expr), type));
+ return ir_make_addr(v, expr);
+ }
+ default:
+ GB_PANIC("Unknown cast expression");
+ }
+ case_end;
+
case_ast_node(ue, UnaryExpr, expr);
switch (ue->op.kind) {
case Token_Pointer: {
@@ -5304,9 +5311,8 @@ void ir_gen_tree(irGen *s) {
case Entity_Variable: {
irValue *g = ir_make_value_global(a, e, NULL);
- if (decl->var_decl_flags & VarDeclFlag_thread_local) {
- g->Global.is_thread_local = true;
- }
+ g->Global.is_thread_local = e->Variable.is_thread_local;
+
irGlobalVariable var = {0};
var.var = g;
var.decl = decl;
@@ -5509,6 +5515,7 @@ void ir_gen_tree(irGen *s) {
map_ir_value_set(&m->values, hash_pointer(e), p);
map_ir_value_set(&m->members, hash_string(name), p);
+
irProcedure *proc = &p->Proc;
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
@@ -5557,6 +5564,18 @@ void ir_gen_tree(irGen *s) {
CheckerInfo *info = proc->module->info;
+ if (false) {
+ irValue *global_type_infos = ir_find_global_variable(proc, str_lit("__type_infos"));
+ Type *type = base_type(type_deref(ir_type(type_info_data)));
+ GB_ASSERT(is_type_array(type));
+ irValue *array_data = ir_emit_array_epi(proc, type_info_data, 0);
+ irValue *array_count = ir_make_const_int(proc->module->allocator, type->Array.count);
+
+ ir_emit_store(proc, ir_emit_struct_ep(proc, global_type_infos, 0), array_data);
+ ir_emit_store(proc, ir_emit_struct_ep(proc, global_type_infos, 1), array_count);
+ }
+
+
// Useful types
Type *t_i64_slice_ptr = make_type_pointer(a, make_type_slice(a, t_i64));
Type *t_string_slice_ptr = make_type_pointer(a, make_type_slice(a, t_string));
diff --git a/src/ir_opt.c b/src/ir_opt.c
index 66342ee3f..b4c348b2d 100644
--- a/src/ir_opt.c
+++ b/src/ir_opt.c
@@ -27,9 +27,6 @@ void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
array_add(ops, i->PtrOffset.address);
array_add(ops, i->PtrOffset.offset);
break;
- case irInstr_ArrayExtractValue:
- array_add(ops, i->ArrayExtractValue.address);
- break;
case irInstr_StructExtractValue:
array_add(ops, i->StructExtractValue.address);
break;
diff --git a/src/ir_print.c b/src/ir_print.c
index 372e7d6fe..7a3032367 100644
--- a/src/ir_print.c
+++ b/src/ir_print.c
@@ -790,16 +790,6 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_fprintf(f, "\n");
} break;
- case irInstr_ArrayExtractValue: {
- Type *et = ir_type(instr->ArrayExtractValue.address);
- ir_fprintf(f, "%%%d = extractvalue ", value->index);
-
- ir_print_type(f, m, et);
- ir_fprintf(f, " ");
- ir_print_value(f, m, instr->ArrayExtractValue.address, et);
- ir_fprintf(f, ", %d\n", instr->ArrayExtractValue.index);
- } break;
-
case irInstr_StructExtractValue: {
Type *et = ir_type(instr->StructExtractValue.address);
ir_fprintf(f, "%%%d = extractvalue ", value->index);
diff --git a/src/main.c b/src/main.c
index 074b50117..eead1daf3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -92,6 +92,7 @@ int main(int argc, char **argv) {
timings_init(&timings, str_lit("Total Time"), 128);
// defer (timings_destroy(&timings));
init_string_buffer_memory();
+ init_scratch_memory(gb_megabytes(10));
init_global_error_collector();
#if 1
@@ -234,7 +235,7 @@ int main(int argc, char **argv) {
timings_start_section(&timings, str_lit("msvc-link"));
- gbString lib_str = gb_string_make(heap_allocator(), "Kernel32.lib");
+ gbString lib_str = gb_string_make(heap_allocator(), "\"Kernel32.lib\"");
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {0};
for_array(i, checker.info.foreign_libraries) {
diff --git a/src/parser.c b/src/parser.c
index 4223c36fe..7549245f4 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -142,17 +142,26 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
AST_NODE_KIND(IndexExpr, "index expression", struct { AstNode *expr, *index; Token open, close; }) \
AST_NODE_KIND(DerefExpr, "dereference expression", struct { Token op; AstNode *expr; }) \
AST_NODE_KIND(DemaybeExpr, "demaybe expression", struct { Token op; AstNode *expr; }) \
- AST_NODE_KIND(CallExpr, "call expression", struct { \
- AstNode *proc; \
- AstNodeArray args; \
- Token open, close; \
- Token ellipsis; \
- }) \
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
AstNode *expr; \
Token open, close; \
AstNode *low, *high; \
}) \
+ AST_NODE_KIND(CallExpr, "call expression", struct { \
+ AstNode * proc; \
+ AstNodeArray args; \
+ Token open; \
+ Token close; \
+ Token ellipsis; \
+ }) \
+ AST_NODE_KIND(MacroCallExpr, "macro call expression", struct { \
+ AstNode * macro; \
+ Token bang; \
+ AstNodeArray args; \
+ Token open; \
+ Token close; \
+ }) \
+ AST_NODE_KIND(CastExpr, "cast expression", struct { Token token; AstNode *type, *expr; Token open, close; }) \
AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
AST_NODE_KIND(BlockExpr, "block expr", struct { \
AstNodeArray stmts; \
@@ -436,6 +445,8 @@ Token ast_node_token(AstNode *node) {
return node->ParenExpr.open;
case AstNode_CallExpr:
return ast_node_token(node->CallExpr.proc);
+ case AstNode_MacroCallExpr:
+ return ast_node_token(node->MacroCallExpr.macro);
case AstNode_SelectorExpr:
if (node->SelectorExpr.selector != NULL) {
return ast_node_token(node->SelectorExpr.selector);
@@ -447,6 +458,8 @@ Token ast_node_token(AstNode *node) {
return node->SliceExpr.open;
case AstNode_Ellipsis:
return node->Ellipsis.token;
+ case AstNode_CastExpr:
+ return node->CastExpr.token;
case AstNode_FieldValue:
return node->FieldValue.eq;
case AstNode_DerefExpr:
@@ -655,14 +668,25 @@ AstNode *make_paren_expr(AstFile *f, AstNode *expr, Token open, Token close) {
AstNode *make_call_expr(AstFile *f, AstNode *proc, AstNodeArray args, Token open, Token close, Token ellipsis) {
AstNode *result = make_node(f, AstNode_CallExpr);
- result->CallExpr.proc = proc;
- result->CallExpr.args = args;
+ result->CallExpr.proc = proc;
+ result->CallExpr.args = args;
result->CallExpr.open = open;
result->CallExpr.close = close;
result->CallExpr.ellipsis = ellipsis;
return result;
}
+AstNode *make_macro_call_expr(AstFile *f, AstNode *macro, Token bang, AstNodeArray args, Token open, Token close) {
+ AstNode *result = make_node(f, AstNode_MacroCallExpr);
+ result->MacroCallExpr.macro = macro;
+ result->MacroCallExpr.bang = bang;
+ result->MacroCallExpr.args = args;
+ result->MacroCallExpr.open = open;
+ result->MacroCallExpr.close = close;
+ return result;
+}
+
+
AstNode *make_selector_expr(AstFile *f, Token token, AstNode *expr, AstNode *selector) {
AstNode *result = make_node(f, AstNode_SelectorExpr);
result->SelectorExpr.expr = expr;
@@ -755,6 +779,16 @@ AstNode *make_field_value(AstFile *f, AstNode *field, AstNode *value, Token eq)
return result;
}
+AstNode *make_cast_expr(AstFile *f, Token token, AstNode *type, AstNode *expr, Token open, Token close) {
+ AstNode *result = make_node(f, AstNode_CastExpr);
+ result->CastExpr.token = token;
+ result->CastExpr.type = type;
+ result->CastExpr.expr = expr;
+ result->CastExpr.open = open;
+ result->CastExpr.close = close;
+ return result;
+}
+
AstNode *make_compound_lit(AstFile *f, AstNode *type, AstNodeArray elems, Token open, Token close) {
AstNode *result = make_node(f, AstNode_CompoundLit);
result->CompoundLit.type = type;
@@ -1774,8 +1808,12 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
return type;
}
- case Token_OpenBrace: return parse_block_expr(f);
- case Token_if: return parse_if_expr(f);
+ case Token_if:
+ if (lhs) goto error;
+ return parse_if_expr(f);
+ case Token_OpenBrace:
+ if (lhs) goto error;
+ return parse_block_expr(f);
default: {
AstNode *type = parse_identifier_or_type(f);
@@ -1790,6 +1828,7 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
}
}
+error:
Token begin = f->curr_token;
syntax_error(begin, "Expected an operand");
fix_advance_to_next_stmt(f);
@@ -1844,6 +1883,36 @@ AstNode *parse_call_expr(AstFile *f, AstNode *operand) {
return make_call_expr(f, operand, args, open_paren, close_paren, ellipsis);
}
+
+AstNode *parse_macro_call_expr(AstFile *f, AstNode *operand) {
+ AstNodeArray args = make_ast_node_array(f);
+ Token bang, open_paren, close_paren;
+
+ bang = expect_token(f, Token_Not);
+
+ f->expr_level++;
+ open_paren = expect_token(f, Token_OpenParen);
+
+ while (f->curr_token.kind != Token_CloseParen &&
+ f->curr_token.kind != Token_EOF) {
+ if (f->curr_token.kind == Token_Comma) {
+ syntax_error(f->curr_token, "Expected an expression not a ,");
+ }
+
+ AstNode *arg = parse_expr(f, false);
+ array_add(&args, arg);
+
+ if (!allow_token(f, Token_Comma)) {
+ break;
+ }
+ }
+
+ f->expr_level--;
+ close_paren = expect_closing(f, Token_CloseParen, str_lit("argument list"));
+
+ return make_macro_call_expr(f, operand, bang, args, open_paren, close_paren);
+}
+
AstNode *parse_atom_expr(AstFile *f, bool lhs) {
AstNode *operand = parse_operand(f, lhs);
@@ -1853,6 +1922,9 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
case Token_OpenParen:
operand = parse_call_expr(f, operand);
break;
+ case Token_Not:
+ operand = parse_macro_call_expr(f, operand);
+ break;
case Token_Period: {
Token token = f->curr_token;
@@ -1936,6 +2008,20 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
AstNode *parse_unary_expr(AstFile *f, bool lhs) {
switch (f->curr_token.kind) {
+
+ case Token_cast:
+ case Token_transmute:
+ case Token_down_cast:
+ case Token_union_cast:
+ {
+ Token token = f->curr_token; next_token(f);
+ Token open = expect_token(f, Token_OpenParen);
+ AstNode *type = parse_type(f);
+ Token close = expect_token(f, Token_CloseParen);
+ AstNode *expr = parse_unary_expr(f, lhs);
+ return make_cast_expr(f, token, type, expr, open, close);
+ } break;
+
case Token_Pointer: {
Token op = f->curr_token;
next_token(f);
@@ -1945,7 +2031,7 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) {
}
return make_unary_expr(f, op, expr);
} break;
- case Token_Maybe:
+ // case Token_Maybe:
case Token_Add:
case Token_Sub:
case Token_Not:
@@ -2432,10 +2518,10 @@ AstNode *parse_identifier_or_type(AstFile *f) {
AstNode *sel = parse_identifier(f);
e = make_selector_expr(f, token, e, sel);
}
- // if (f->curr_token.kind == Token_OpenParen) {
- // // HACK NOTE(bill): For type_of_val(expr)
- // e = parse_call_expr(f, e);
- // }
+ if (f->curr_token.kind == Token_OpenParen) {
+ // HACK NOTE(bill): For type_of_val(expr) et al.
+ e = parse_call_expr(f, e);
+ }
return e;
}
@@ -2464,8 +2550,7 @@ AstNode *parse_identifier_or_type(AstFile *f) {
bool is_vector = false;
if (f->curr_token.kind == Token_Ellipsis) {
- count_expr = make_ellipsis(f, f->curr_token, NULL);
- next_token(f);
+ count_expr = make_ellipsis(f, expect_token(f, Token_Ellipsis), NULL);
} else if (f->curr_token.kind == Token_vector) {
next_token(f);
if (f->curr_token.kind != Token_CloseBracket) {
diff --git a/src/tokenizer.c b/src/tokenizer.c
index 6f2213ca0..eadfc767d 100644
--- a/src/tokenizer.c
+++ b/src/tokenizer.c
@@ -111,6 +111,10 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_asm, "asm"), \
TOKEN_KIND(Token_push_allocator, "push_allocator"), \
TOKEN_KIND(Token_push_context, "push_context"), \
+ TOKEN_KIND(Token_cast, "cast"), \
+ TOKEN_KIND(Token_transmute, "transmute"), \
+ TOKEN_KIND(Token_down_cast, "down_cast"), \
+ TOKEN_KIND(Token_union_cast, "union_cast"), \
TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
TOKEN_KIND(Token_Count, "")
@@ -149,7 +153,6 @@ bool token_pos_eq(TokenPos a, TokenPos b) {
return token_pos_cmp(a, b) == 0;
}
-// NOTE(bill): Text is UTF-8, thus why u8 and not char
typedef struct Token {
TokenKind kind;
String string;
diff --git a/src/types.c b/src/types.c
index c71f162c4..c49ad4a42 100644
--- a/src/types.c
+++ b/src/types.c
@@ -509,6 +509,7 @@ bool is_type_numeric(Type *t) {
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Numeric) != 0;
}
+ // TODO(bill): Should this be here?
if (t->kind == Type_Vector) {
return is_type_numeric(t->Vector.elem);
}
@@ -1851,8 +1852,7 @@ gbString write_type_to_string(gbString str, Type *type) {
gbString type_to_string(Type *type) {
- gbString str = gb_string_make(gb_heap_allocator(), "");
- return write_type_to_string(str, type);
+ return write_type_to_string(gb_string_make(heap_allocator(), ""), type);
}