aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <ginger.bill.22@gmail.com>2016-08-14 12:22:31 +0100
committergingerBill <ginger.bill.22@gmail.com>2016-08-14 12:22:31 +0100
commitee002364120a773753d37cf5575baa6e86d0502c (patch)
treed96feebc57be31d385909a0b9e4df2c0aef50a6b /src
parentc10b46af9feb76a9839efa292c5288ec4684055e (diff)
expr as type; {N}bool is still causing problems
Diffstat (limited to 'src')
-rw-r--r--src/checker/expr.cpp244
-rw-r--r--src/checker/type.cpp36
-rw-r--r--src/codegen/codegen.cpp2
-rw-r--r--src/codegen/print_llvm.cpp34
-rw-r--r--src/codegen/ssa.cpp300
-rw-r--r--src/parser.cpp133
-rw-r--r--src/printer.cpp6
-rw-r--r--src/tokenizer.cpp26
8 files changed, 463 insertions, 318 deletions
diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp
index 77854a603..a4931ed94 100644
--- a/src/checker/expr.cpp
+++ b/src/checker/expr.cpp
@@ -384,11 +384,9 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type) {
Type *elem = check_type(c, vt->elem);
Type *be = get_base_type(elem);
i64 count = check_array_count(c, vt->count);
- if (!is_type_vector(be) &&
- !(is_type_boolean(be) || is_type_numeric(be))) {
+ if (!is_type_boolean(be) && !is_type_numeric(be)) {
err_str = type_to_string(elem);
- error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be a boolean, numerical, or vector. Got `%s`", err_str);
- } else {
+ error(&c->error_collector, ast_node_token(vt->elem), "Vector element type must be numerical or a boolean. Got `%s`", err_str);
}
type = make_type_vector(c->allocator, elem, count);
set_base_type(named_type, type);
@@ -433,7 +431,7 @@ end:
b32 check_unary_op(Checker *c, Operand *o, Token op) {
// TODO(bill): Handle errors correctly
- Type *type = get_base_type(base_vector_type(o->type));
+ Type *type = get_base_type(base_vector_type(get_base_type(o->type)));
gbString str = NULL;
defer (gb_string_free(str));
switch (op.kind) {
@@ -702,13 +700,11 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
update_expr_type(c, y->expr, default_type(y->type), true);
}
- if (is_type_vector(x->type)) {
- Type *vec_bool = NULL;
- do {
- } while (is_type_vector(x->type->vector.elem));
+ if (is_type_vector(get_base_type(y->type))) {
+ x->type = make_type_vector(c->allocator, t_bool, get_base_type(y->type)->vector.count);
+ } else {
+ x->type = t_untyped_bool;
}
- x->type = t_untyped_bool;
-
}
void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
@@ -805,6 +801,101 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
x->mode = Addressing_Value;
}
+b32 check_castable_to(Checker *c, Operand *operand, Type *y) {
+ if (check_is_assignable_to(c, operand, y))
+ return true;
+
+ Type *x = operand->type;
+ Type *xb = get_base_type(x);
+ Type *yb = get_base_type(y);
+ if (are_types_identical(xb, yb))
+ return true;
+
+
+ // Cast between booleans and integers
+ if (is_type_boolean(x) || is_type_integer(x)) {
+ if (is_type_boolean(y) || is_type_integer(y))
+ return true;
+ }
+
+ // Cast between numbers
+ if (is_type_integer(x) || is_type_float(x)) {
+ if (is_type_integer(y) || is_type_float(y))
+ return true;
+ }
+
+ // Cast between pointers
+ if (is_type_pointer(x)) {
+ if (is_type_pointer(y))
+ return true;
+ }
+
+ // untyped integers -> pointers
+ if (is_type_untyped(xb) && is_type_integer(xb)) {
+ if (is_type_pointer(yb))
+ return true;
+ }
+
+ // (u)int <-> pointer
+ if (is_type_pointer(xb) || is_type_int_or_uint(xb)) {
+ if (is_type_pointer(yb))
+ return true;
+ }
+ if (is_type_pointer(xb)) {
+ if (is_type_pointer(yb) || is_type_int_or_uint(yb))
+ return true;
+ }
+
+ // []byte/[]u8 <-> string
+ if (is_type_u8_slice(xb) && is_type_string(yb)) {
+ return true;
+ }
+ if (is_type_string(xb) && is_type_u8_slice(yb)) {
+ return true;
+ }
+
+ return false;
+}
+
+void check_cast_expr(Checker *c, Operand *operand, Type *type) {
+ b32 is_const_expr = operand->mode == Addressing_Constant;
+ b32 can_convert = false;
+
+ if (is_const_expr && is_type_constant_type(type)) {
+ Type *t = get_base_type(type);
+ if (t->kind == Type_Basic) {
+ if (check_value_is_expressible(c, operand->value, t, &operand->value)) {
+ can_convert = true;
+ }
+ }
+ } else if (check_castable_to(c, operand, type)) {
+ operand->mode = Addressing_Value;
+ can_convert = true;
+ }
+
+ if (!can_convert) {
+ gbString expr_str = expr_to_string(operand->expr);
+ gbString type_str = type_to_string(type);
+ defer (gb_string_free(expr_str));
+ defer (gb_string_free(type_str));
+ error(&c->error_collector, ast_node_token(operand->expr), "Cannot cast `%s` to `%s`", expr_str, type_str);
+
+ operand->mode = Addressing_Invalid;
+ return;
+ }
+
+ if (is_type_untyped(operand->type)) {
+ Type *final_type = type;
+ if (is_const_expr && !is_type_constant_type(type)) {
+ final_type = default_type(operand->type);
+ }
+ update_expr_type(c, operand->expr, final_type, true);
+ }
+
+ operand->type = type;
+}
+
+
void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
GB_ASSERT(node->kind == AstNode_BinaryExpr);
Operand y_ = {}, *y = &y_;
@@ -813,6 +904,15 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
ast_node(be, BinaryExpr, node);
+ if (be->op.kind == Token_as) {
+ check_expr(c, x, be->left);
+ Type *cast_type = check_type(c, be->right);
+ if (x->mode == Addressing_Invalid)
+ return;
+ check_cast_expr(c, x, cast_type);
+ return;
+ }
+
check_expr(c, x, be->left);
check_expr(c, y, be->right);
if (x->mode == Addressing_Invalid) {
@@ -890,7 +990,7 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
}
if (x->mode == Addressing_Constant &&
- y->mode == Addressing_Constant) {
+ y->mode == Addressing_Constant) {
ExactValue a = x->value;
ExactValue b = y->value;
@@ -943,7 +1043,18 @@ void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) {
found->type = get_base_type(type);
map_set(&c->info.untyped, key, *found);
} else {
+ ExpressionInfo old = *found;
map_remove(&c->info.untyped, key);
+
+ if (old.is_lhs && !is_type_integer(type)) {
+ gbString expr_str = expr_to_string(e);
+ gbString type_str = type_to_string(type);
+ defer (gb_string_free(expr_str));
+ defer (gb_string_free(type_str));
+ error(&c->error_collector, ast_node_token(e), "Shifted operand %s must be an integer, got %s", expr_str, type_str);
+ return;
+ }
+
add_type_and_value(&c->info, e, found->mode, type, found->value);
}
}
@@ -1349,6 +1460,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
value = make_exact_value_integer(t->array.count);
break;
+ case Type_Vector:
+ mode = Addressing_Constant;
+ value = make_exact_value_integer(t->vector.count);
+ break;
+
case Type_Slice:
mode = Addressing_Value;
break;
@@ -1600,85 +1716,6 @@ ExpressionKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
return Expression_Statement;
}
-b32 check_castable_to(Checker *c, Operand *operand, Type *y) {
- if (check_is_assignable_to(c, operand, y))
- return true;
-
- Type *x = operand->type;
- Type *xb = get_base_type(x);
- Type *yb = get_base_type(y);
- if (are_types_identical(xb, yb))
- return true;
-
- // Cast between numbers
- if (is_type_integer(x) || is_type_float(x)) {
- if (is_type_integer(y) || is_type_float(y))
- return true;
- }
-
- // Cast between pointers
- if (is_type_pointer(x)) {
- if (is_type_pointer(y))
- return true;
- }
-
- // untyped integers -> pointers
- if (is_type_untyped(xb) && is_type_integer(xb)) {
- if (is_type_pointer(yb))
- return true;
- }
-
- // (u)int <-> pointer
- if (is_type_pointer(xb) || is_type_int_or_uint(xb)) {
- if (is_type_pointer(yb))
- return true;
- }
- if (is_type_pointer(xb)) {
- if (is_type_pointer(yb) || is_type_int_or_uint(yb))
- return true;
- }
-
- // []byte/[]u8 <-> string
- if (is_type_u8_slice(xb) && is_type_string(yb)) {
- return true;
- }
- if (is_type_string(xb) && is_type_u8_slice(yb)) {
- return true;
- }
-
- return false;
-}
-
-void check_cast_expr(Checker *c, Operand *operand, Type *type) {
- b32 is_const_expr = operand->mode == Addressing_Constant;
- b32 can_convert = false;
-
- if (is_const_expr && is_type_constant_type(type)) {
- Type *t = get_base_type(type);
- if (t->kind == Type_Basic) {
- if (check_value_is_expressible(c, operand->value, t, &operand->value)) {
- can_convert = true;
- }
- }
- } else if (check_castable_to(c, operand, type)) {
- operand->mode = Addressing_Value;
- can_convert = true;
- }
-
- if (!can_convert) {
- gbString expr_str = expr_to_string(operand->expr);
- gbString type_str = type_to_string(type);
- defer (gb_string_free(expr_str));
- defer (gb_string_free(type_str));
- error(&c->error_collector, ast_node_token(operand->expr), "Cannot cast `%s` to `%s`", expr_str, type_str);
-
- operand->mode = Addressing_Invalid;
- return;
- }
-
- operand->type = type;
-}
-
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);
@@ -1924,6 +1961,15 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
o->type = t->array.elem;
break;
+ case Type_Vector:
+ valid = true;
+ max_count = t->vector.count;
+ if (o->mode != Addressing_Variable)
+ o->mode = Addressing_Value;
+ o->type = t->vector.elem;
+ break;
+
+
case Type_Slice:
valid = true;
o->type = t->slice.elem;
@@ -2039,15 +2085,6 @@ ExpressionKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *typ
case_end;
- case_ast_node(ce, CastExpr, node);
- Type *cast_type = check_type(c, ce->type);
- check_expr_or_type(c, o, ce->expr);
- if (o->mode != Addressing_Invalid)
- check_cast_expr(c, o, cast_type);
-
- case_end;
-
-
case_ast_node(ce, CallExpr, node);
return check_call_expr(c, o, node);
case_end;
@@ -2287,13 +2324,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = gb_string_appendc(str, "]");
case_end;
- case_ast_node(ce, CastExpr, node);
- str = gb_string_appendc(str, "cast(");
- str = write_expr_to_string(str, ce->type);
- str = gb_string_appendc(str, ")");
- str = write_expr_to_string(str, ce->expr);
- case_end;
-
case_ast_node(e, Ellipsis, node);
str = gb_string_appendc(str, "..");
case_end;
diff --git a/src/checker/type.cpp b/src/checker/type.cpp
index 368e276af..12a96e1a5 100644
--- a/src/checker/type.cpp
+++ b/src/checker/type.cpp
@@ -39,11 +39,12 @@ enum BasicFlag : u32 {
BasicFlag_Float = GB_BIT(3),
BasicFlag_Pointer = GB_BIT(4),
BasicFlag_String = GB_BIT(5),
- BasicFlag_Untyped = GB_BIT(6),
+ BasicFlag_Rune = GB_BIT(6),
+ BasicFlag_Untyped = GB_BIT(7),
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float,
BasicFlag_Ordered = BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
- BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer,
+ BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_Pointer | BasicFlag_String | BasicFlag_Rune,
};
struct BasicType {
@@ -130,10 +131,11 @@ struct Type {
Type *get_base_type(Type *t) {
while (t->kind == Type_Named || t->kind == Type_Alias) {
- if (t->kind == Type_Named)
+ if (t->kind == Type_Named) {
t = t->named.base;
- else
+ } else {
t = t->alias.base;
+ }
}
return t;
}
@@ -381,8 +383,8 @@ b32 is_type_vector(Type *t) {
return t->kind == Type_Vector;
}
Type *base_vector_type(Type *t) {
- while (is_type_vector(t)) {
- t = t->vector.elem;
+ if (is_type_vector(t)) {
+ return t->vector.elem;
}
return t;
}
@@ -520,7 +522,7 @@ struct BaseTypeSizes {
// TODO(bill): Change
gb_global i64 basic_type_sizes[] = {
0, // Basic_Invalid
- 1, // Basic_bool // TODO(bill): What size should this be? And should I have different booleans?
+ 1, // Basic_bool
1, // Basic_i8
2, // Basic_i16
4, // Basic_i32
@@ -531,13 +533,10 @@ gb_global i64 basic_type_sizes[] = {
4, // Basic_u32
8, // Basic_u64
16, // Basic_u128
- 2, // Basic_f16
4, // Basic_f32
8, // Basic_f64
- 16, // Basic_f128
};
-
i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
@@ -635,11 +634,18 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
i64 count = t->vector.count;
if (count == 0)
return 0;
- count = next_pow2(count);
- i64 align = type_align_of(s, allocator, t->vector.elem);
- i64 size = type_size_of(s, allocator, t->vector.elem);
- i64 alignment = align_formula(size, align);
- return alignment*(count-1) + size;
+ // i64 align = type_align_of(s, allocator, t->vector.elem);
+ i64 bit_size = 8*type_size_of(s, allocator, t->vector.elem);
+ if (is_type_boolean(t->vector.elem)) {
+ bit_size = 1; // NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
+ // Silly LLVM spec
+ }
+ i64 total_size_in_bits = bit_size * count;
+ i64 total_size = (total_size_in_bits+7)/8;
+ return total_size;
+
+ // i64 alignment = align_formula(size, align);
+ // return alignment*(count-1) + size;
} break;
diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp
index c530b350b..4cb4a98be 100644
--- a/src/codegen/codegen.cpp
+++ b/src/codegen/codegen.cpp
@@ -94,7 +94,7 @@ void ssa_gen_code(ssaGen *s) {
ssa_build_proc(v, NULL);
}
- // m->layout = make_string("e-p:64:64:64");
+ // m->layout = make_string("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
ssa_print_llvm_ir(&s->output_file, &s->module);
}
diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp
index d05cd0272..1535638b0 100644
--- a/src/codegen/print_llvm.cpp
+++ b/src/codegen/print_llvm.cpp
@@ -393,10 +393,10 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
case ssaInstr_BinaryOp: {
auto *bo = &value->instr.binary_op;
- Type *type = ssa_value_type(bo->left);
+ Type *type = get_base_type(ssa_value_type(bo->left));
Type *elem_type = type;
while (elem_type->kind == Type_Vector) {
- elem_type = elem_type->vector.elem;
+ elem_type = get_base_type(elem_type->vector.elem);
}
ssa_fprintf(f, "%%%d = ", value->id);
@@ -535,13 +535,37 @@ void ssa_print_instr(gbFile *f, ssaModule *m, ssaValue *value) {
vol_str = "true";
}
ssa_fprintf(f, ", i32 %d, i1 %s)\n", instr->copy_memory.align, vol_str);
+ } break;
+
+
+ case ssaInstr_InsertElement: {
+ auto *ie = &instr->insert_element;
+ Type *vt = ssa_value_type(ie->vector);
+ ssa_fprintf(f, "%%%d = insertelement ", value->id);
+
+ ssa_print_type(f, m->sizes, vt);
+ ssa_fprintf(f, " ");
+ ssa_print_value(f, m, ie->vector, vt);
+ ssa_fprintf(f, ", ");
+
+ ssa_print_type(f, m->sizes, ssa_value_type(ie->elem));
+ ssa_fprintf(f, " ");
+ ssa_print_value(f, m, ie->elem, ssa_value_type(ie->elem));
+ ssa_fprintf(f, ", ");
+
+ ssa_print_type(f, m->sizes, ssa_value_type(ie->index));
+ ssa_fprintf(f, " ");
+ ssa_print_value(f, m, ie->index, ssa_value_type(ie->index));
+
+ ssa_fprintf(f, "\n");
} break;
- default:
+
+ default: {
GB_PANIC("<unknown instr> %d\n", instr->kind);
ssa_fprintf(f, "; <unknown instr> %d\n", instr->kind);
- break;
+ } break;
}
}
@@ -613,7 +637,7 @@ void ssa_print_type_name(gbFile *f, ssaModule *m, ssaValue *v) {
void ssa_print_llvm_ir(gbFile *f, ssaModule *m) {
if (m->layout.len > 0) {
- ssa_fprintf(f, "target datalayout = %.*s\n", LIT(m->layout));
+ ssa_fprintf(f, "target datalayout = \"%.*s\"\n", LIT(m->layout));
}
ssa_print_encoded_local(f, make_string(".string"));
diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp
index c229156b7..42e7046cf 100644
--- a/src/codegen/ssa.cpp
+++ b/src/codegen/ssa.cpp
@@ -69,6 +69,9 @@ struct ssaProcedure {
SSA_INSTR_KIND(BinaryOp), \
SSA_INSTR_KIND(Call), \
SSA_INSTR_KIND(CopyMemory), \
+ SSA_INSTR_KIND(ExtractElement), \
+ SSA_INSTR_KIND(InsertElement), \
+ SSA_INSTR_KIND(ShuffleVector), \
SSA_INSTR_KIND(Count),
enum ssaInstrKind {
@@ -178,6 +181,16 @@ struct ssaInstr {
i32 align;
b32 is_volatile;
} copy_memory;
+
+ struct {
+ ssaValue *vector;
+ ssaValue *index;
+ } extract_element;
+ struct {
+ ssaValue *vector;
+ ssaValue *elem;
+ ssaValue *index;
+ } insert_element;
};
};
@@ -236,36 +249,16 @@ gb_global ssaValue *v_two32 = NULL;
gb_global ssaValue *v_false = NULL;
gb_global ssaValue *v_true = NULL;
-enum ssaLvalueKind {
- ssaLvalue_Blank,
- ssaLvalue_Address,
-
- ssaLvalue_Count,
-};
-
struct ssaLvalue {
- ssaLvalueKind kind;
- union {
- struct {} blank;
- struct {
- ssaValue *value;
- AstNode *expr;
- } address;
- };
-};
-
-
-
-
-
-ssaLvalue ssa_make_lvalue_address(ssaValue *value, AstNode *expr) {
- ssaLvalue lval = {ssaLvalue_Address};
- lval.address.value = value;
- lval.address.expr = expr;
- return lval;
+ ssaValue *address;
+ AstNode *expr;};
+ssaLvalue ssa_make_lvalue(ssaValue *address, AstNode *expr) {
+ ssaLvalue v = {address, expr};
+ return v;
}
+
void ssa_module_init(ssaModule *m, Checker *c) {
isize token_count = c->parser->total_token_count;
isize arena_size = 3 * token_count * gb_size_of(ssaValue);
@@ -323,6 +316,13 @@ Type *ssa_instr_type(ssaInstr *instr) {
}
case ssaInstr_CopyMemory:
return t_int;
+
+ case ssaInstr_ExtractElement: {
+ Type *vt = ssa_value_type(instr->extract_element.vector);
+ return base_vector_type(get_base_type(vt));
+ } break;
+ case ssaInstr_InsertElement:
+ return ssa_value_type(instr->insert_element.vector);
}
return NULL;
}
@@ -477,8 +477,8 @@ ssaValue *ssa_make_instr_load(ssaProcedure *p, ssaValue *address) {
}
ssaValue *ssa_make_instr_get_element_ptr(ssaProcedure *p, ssaValue *address,
- ssaValue *index0, ssaValue *index1, isize index_count,
- b32 inbounds) {
+ ssaValue *index0, ssaValue *index1, isize index_count,
+ b32 inbounds) {
ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_GetElementPtr);
ssaInstr *i = &v->instr;
i->get_element_ptr.address = address;
@@ -598,6 +598,34 @@ ssaValue *ssa_make_instr_conv(ssaProcedure *p, ssaConvKind kind, ssaValue *value
return v;
}
+ssaValue *ssa_make_instr_extract_element(ssaProcedure *p, ssaValue *vector, ssaValue *index) {
+ ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_ExtractElement);
+ v->instr.extract_element.vector = vector;
+ v->instr.extract_element.index = index;
+ if (p->curr_block) {
+ gb_array_append(p->curr_block->values, v);
+ }
+ return v;
+}
+
+ssaValue *ssa_make_instr_insert_element(ssaProcedure *p, ssaValue *vector, ssaValue *elem, ssaValue *index) {
+ ssaValue *v = ssa_alloc_instr(p->module->allocator, ssaInstr_InsertElement);
+ v->instr.insert_element.vector = vector;
+ v->instr.insert_element.elem = elem;
+ v->instr.insert_element.index = index;
+ if (p->curr_block) {
+ gb_array_append(p->curr_block->values, v);
+ }
+ return v;
+}
+
+
+
+
+
+
+
+
@@ -714,36 +742,23 @@ ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) {
ssaValue *ssa_lvalue_store(ssaLvalue lval, ssaProcedure *p, ssaValue *value) {
- switch (lval.kind) {
- case ssaLvalue_Address:
- return ssa_emit_store(p, lval.address.value, value);
+ if (lval.address != NULL) {
+ return ssa_emit_store(p, lval.address, value);
}
return NULL;
}
ssaValue *ssa_lvalue_load(ssaLvalue lval, ssaProcedure *p) {
- switch (lval.kind) {
- case ssaLvalue_Address:
- return ssa_emit_load(p, lval.address.value);
+ if (lval.address != NULL) {
+ return ssa_emit_load(p, lval.address);
}
GB_PANIC("Illegal lvalue load");
return NULL;
}
-
-ssaValue *ssa_lvalue_address(ssaLvalue lval, ssaProcedure *p) {
- switch (lval.kind) {
- case ssaLvalue_Address:
- return lval.address.value;
- }
- return NULL;
-}
-
Type *ssa_lvalue_type(ssaLvalue lval) {
- switch (lval.kind) {
- case ssaLvalue_Address:
- // return type_deref(ssa_value_type(lval.address.value));
- return ssa_value_type(lval.address.value);
+ if (lval.address != NULL) {
+ return type_deref(ssa_value_type(lval.address));
}
return NULL;
}
@@ -921,7 +936,11 @@ ssaValue *ssa_emit_comp(ssaProcedure *proc, Token op, ssaValue *left, ssaValue *
}
ssaValue *v = ssa_make_instr_binary_op(proc, op, left, right);
- ssa_value_set_type(v, t_bool);
+ Type *result = t_bool;
+ if (is_type_vector(a)) {
+ result = make_type_vector(proc->module->allocator, t_bool, a->vector.count);
+ }
+ ssa_value_set_type(v, result);
return ssa_emit(proc, v);
}
@@ -935,6 +954,15 @@ ssaValue *ssa_emit_ptr_offset(ssaProcedure *proc, ssaValue *ptr, ssaValue *offse
return ssa_emit(proc, gep);
}
+ssaValue *ssa_emit_zero_gep(ssaProcedure *proc, ssaValue *s) {
+ ssaValue *gep = NULL;
+ // NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32
+ gep = ssa_make_instr_get_element_ptr(proc, s, NULL, NULL, 0, true);
+ gep->instr.get_element_ptr.elem_type = ssa_value_type(s);
+ gep->instr.get_element_ptr.result_type = ssa_value_type(s);
+ return ssa_emit(proc, gep);
+}
+
ssaValue *ssa_emit_struct_gep(ssaProcedure *proc, ssaValue *s, ssaValue *index, Type *result_type) {
ssaValue *gep = NULL;
// NOTE(bill): For some weird legacy reason in LLVM, structure elements must be accessed as an i32
@@ -1139,14 +1167,17 @@ ssaValue *ssa_emit_string(ssaProcedure *proc, ssaValue *elem, ssaValue *len) {
ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
Type *src_type = ssa_value_type(value);
- if (are_types_identical(t, src_type))
+ if (are_types_identical(t, src_type)) {
return value;
+ }
Type *src = get_base_type(src_type);
Type *dst = get_base_type(t);
if (are_types_identical(t, src_type))
return value;
+
+
if (value->kind == ssaValue_Constant) {
if (dst->kind == Type_Basic) {
ExactValue ev = value->constant.value;
@@ -1163,21 +1194,34 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
// integer -> integer
if (is_type_integer(src) && is_type_integer(dst)) {
- i64 sz = basic_type_sizes[src->basic.kind];
- i64 dz = basic_type_sizes[dst->basic.kind];
- ssaConvKind kind = ssaConv_trunc;
- if (dz >= sz) {
- kind = ssaConv_zext;
- }
-
+ GB_ASSERT(src->kind == Type_Basic &&
+ dst->kind == Type_Basic);
+ i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
+ i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
if (sz == dz) {
// NOTE(bill): In LLVM, all integers are signed and rely upon 2's compliment
return value;
}
+ ssaConvKind kind = ssaConv_trunc;
+ if (dz >= sz) {
+ kind = ssaConv_zext;
+ }
return ssa_emit(proc, ssa_make_instr_conv(proc, kind, value, src, dst));
}
+ // boolean -> integer
+ if (is_type_boolean(src) && is_type_integer(dst)) {
+ return ssa_emit(proc, ssa_make_instr_conv(proc, ssaConv_zext, value, src, dst));
+ }
+
+ // integer -> boolean
+ if (is_type_integer(src) && is_type_boolean(dst)) {
+ Token op = {Token_NotEq};
+ return ssa_emit_comp(proc, op, value, v_zero);
+ }
+
+
// float -> float
if (is_type_float(src) && is_type_float(dst)) {
i64 sz = basic_type_sizes[src->basic.kind];
@@ -1238,6 +1282,9 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
}
+ gb_printf("Not Identical %s != %s\n", type_to_string(src_type), type_to_string(t));
+
+
GB_PANIC("Invalid type conversion: `%s` to `%s`", type_to_string(src_type), type_to_string(t));
return NULL;
@@ -1285,8 +1332,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case_ast_node(ue, UnaryExpr, expr);
switch (ue->op.kind) {
case Token_Pointer: {
- ssaLvalue lval = ssa_build_addr(proc, ue->expr);
- return ssa_lvalue_address(lval, proc);
+ ssaValue *v = ssa_emit_zero_gep(proc, ssa_build_addr(proc, ue->expr).address);
+ ssa_value_set_type(v, type_of_expr(proc->module->info, expr));
+ return v;
}
case Token_Add:
return ssa_build_expr(proc, ue->expr);
@@ -1341,6 +1389,9 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
return ssa_emit_conv(proc, cmp, default_type(tv->type));
} break;
+ case Token_as:
+ return ssa_emit_conv(proc, ssa_build_expr(proc, be->left), tv->type);
+
default:
GB_PANIC("Invalid binary expression");
break;
@@ -1404,7 +1455,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
}
} break;
- case Type_Vector:
case Type_Array: {
isize index = 0;
for (AstNode *elem = cl->elem_list;
@@ -1422,6 +1472,25 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
}
}
} break;
+ case Type_Vector: {
+ isize index = 0;
+ ssaValue *result = ssa_emit_load(proc, v);
+ for (AstNode *elem = cl->elem_list;
+ elem != NULL;
+ elem = elem->next) {
+ ssaValue *field_expr = ssa_build_expr(proc, elem);
+ Type *t = ssa_value_type(field_expr);
+ if (t->kind != Type_Tuple) {
+ ssaValue *ev = ssa_emit_conv(proc, field_expr, et);
+ ssaValue *i = ssa_make_value_constant(proc->module->allocator, t_int, make_exact_value_integer(index));
+ result = ssa_emit(proc, ssa_make_instr_insert_element(proc, result, ev, i));
+ index++;
+ } else {
+ GB_PANIC("TODO(bill): tuples in vector literals");
+ }
+ }
+ return result;
+ } break;
case Type_Slice: {
i64 count = cl->elem_count;
ssaValue *array = ssa_add_local_generated(proc, make_type_array(proc->module->allocator, et, count));
@@ -1457,10 +1526,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
return ssa_emit_load(proc, v);
case_end;
- case_ast_node(ce, CastExpr, expr);
- return ssa_emit_conv(proc, ssa_build_expr(proc, ce->expr), tv->type);
- case_end;
-
case_ast_node(ce, CallExpr, expr);
AstNode *p = unparen_expr(ce->proc);
if (p->kind == AstNode_Ident) {
@@ -1471,7 +1536,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case BuiltinProc_len: {
// len :: proc(Type) -> int
// NOTE(bill): len of an array is a constant expression
- ssaValue *v = ssa_lvalue_address(ssa_build_addr(proc, ce->arg_list), proc);
+ ssaValue *v = ssa_build_addr(proc, ce->arg_list).address;
Type *t = get_base_type(ssa_value_type(v));
if (t == t_string)
return ssa_string_len(proc, v);
@@ -1481,7 +1546,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case BuiltinProc_cap: {
// cap :: proc(Type) -> int
// NOTE(bill): cap of an array is a constant expression
- ssaValue *v = ssa_lvalue_address(ssa_build_addr(proc, ce->arg_list), proc);
+ ssaValue *v = ssa_build_addr(proc, ce->arg_list).address;
Type *t = get_base_type(ssa_value_type(v));
return ssa_slice_cap(proc, v);
} break;
@@ -1489,8 +1554,8 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
// copy :: proc(dst, src: []Type) -> int
AstNode *dst_node = ce->arg_list;
AstNode *src_node = ce->arg_list->next;
- ssaValue *dst_slice = ssa_lvalue_address(ssa_build_addr(proc, dst_node), proc);
- ssaValue *src_slice = ssa_lvalue_address(ssa_build_addr(proc, src_node), proc);
+ ssaValue *dst_slice = ssa_build_addr(proc, dst_node).address;
+ ssaValue *src_slice = ssa_build_addr(proc, src_node).address;
Type *slice_type = get_base_type(ssa_value_type(dst_slice));
GB_ASSERT(slice_type->kind == Type_Slice);
Type *elem_type = slice_type->slice.elem;
@@ -1564,11 +1629,21 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
case_end;
case_ast_node(se, SliceExpr, expr);
- return ssa_emit_load(proc, ssa_lvalue_address(ssa_build_addr(proc, expr), proc));
+ return ssa_emit_load(proc, ssa_build_addr(proc, expr).address);
case_end;
case_ast_node(ie, IndexExpr, expr);
- return ssa_emit_load(proc, ssa_lvalue_address(ssa_build_addr(proc, expr), proc));
+ Type *type = type_of_expr(proc->module->info, ie->expr);
+ type = get_base_type(type);
+ if (is_type_vector(type)) {
+ GB_PANIC("HERE\n");
+ // NOTE(bill): For vectors, use ExtractElement
+ ssaValue *vector = ssa_emit_load(proc, ssa_build_addr(proc, ie->expr).address);
+ ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
+ return ssa_emit(proc, ssa_make_instr_extract_element(proc, vector, index));
+ } else {
+ return ssa_emit_load(proc, ssa_build_addr(proc, expr).address);
+ }
case_end;
}
@@ -1608,7 +1683,7 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
switch (expr->kind) {
case_ast_node(i, Ident, expr);
if (ssa_is_blank_ident(expr)) {
- ssaLvalue val = {ssaLvalue_Blank};
+ ssaLvalue val = {};
return val;
}
@@ -1616,7 +1691,7 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
ssaValue *v = NULL;
ssaValue **found = map_get(&proc->module->values, hash_pointer(e));
if (found) v = *found;
- return ssa_make_lvalue_address(v, expr);
+ return ssa_make_lvalue(v, expr);
case_end;
case_ast_node(pe, ParenExpr, expr);
@@ -1630,7 +1705,7 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
Entity *entity = lookup_field(type, unparen_expr(se->selector), &field_index);
GB_ASSERT(entity != NULL);
- ssaValue *e = ssa_lvalue_address(ssa_build_addr(proc, se->expr), proc);
+ ssaValue *e = ssa_build_addr(proc, se->expr).address;
if (type->kind == Type_Pointer) {
// NOTE(bill): Allow x^.y and x.y to be the same
@@ -1639,7 +1714,37 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
}
ssaValue *v = ssa_emit_struct_gep(proc, e, field_index, entity->type);
- return ssa_make_lvalue_address(v, expr);
+ return ssa_make_lvalue(v, expr);
+ case_end;
+
+ case_ast_node(ue, UnaryExpr, expr);
+ switch (ue->op.kind) {
+ case Token_Pointer: {
+ ssaLvalue lval = ssa_build_addr(proc, ue->expr);
+ // ssaValue *v = ssa_emit_zero_gep(proc, lval.address);
+ // Type *t = ssa_value_type(lval.address);
+ // ssa_value_set_type(lval.address, make_type_pointer(proc->module->allocator, t));
+ // return ssa_make_lvalue(v, expr);
+ return lval;
+ }
+ default:
+ GB_PANIC("Invalid unary expression for ssa_build_addr");
+ }
+ case_end;
+
+ case_ast_node(be, BinaryExpr, expr);
+ switch (be->op.kind) {
+ case Token_as: {
+ // NOTE(bill): Needed for dereference of pointer conversion
+ Type *type = type_of_expr(proc->module->info, expr);
+ ssaValue *v = ssa_add_local_generated(proc, type);
+ ssa_emit_store(proc, v, ssa_emit_conv(proc, ssa_build_expr(proc, be->left), type));
+ return ssa_make_lvalue(v, expr);
+ }
+ default:
+ GB_PANIC("Invalid binary expression for ssa_build_addr: %.*s\n", LIT(be->op.string));
+ break;
+ }
case_end;
case_ast_node(ie, IndexExpr, expr);
@@ -1648,34 +1753,39 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
ssaValue *elem = NULL;
switch (t->kind) {
case Type_Array: {
- ssaValue *array = ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc);
+ ssaValue *array = ssa_build_addr(proc, ie->expr).address;
elem = ssa_array_elem(proc, array);
} break;
case Type_Slice: {
- ssaValue *slice = ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc);
+ ssaValue *slice = ssa_build_addr(proc, ie->expr).address;
elem = ssa_slice_elem(proc, slice);
} break;
+ case Type_Vector: {
+ ssaValue *vector = ssa_build_addr(proc, ie->expr).address;
+ Type *t_ptr = make_type_pointer(proc->module->allocator, t->vector.elem);
+ elem = ssa_emit_struct_gep(proc, vector, v_zero32, t_ptr);
+ } break;
case Type_Basic: { // Basic_string
TypeAndValue *tv = map_get(&proc->module->info->types, hash_pointer(ie->expr));
if (tv->mode == Addressing_Constant) {
ssaValue *array = ssa_add_global_string_array(proc, tv->value);
elem = ssa_array_elem(proc, array);
} else {
- ssaLvalue lval = ssa_build_addr(proc, ie->expr);
- ssaValue *str = ssa_lvalue_address(lval, proc);
- elem = ssa_string_elem(proc, str);
+ elem = ssa_string_elem(proc, ssa_build_addr(proc, ie->expr).address);
}
} break;
case Type_Pointer: {
- elem = ssa_emit_load(proc, ssa_lvalue_address(ssa_build_addr(proc, ie->expr), proc));
+ elem = ssa_emit_load(proc, ssa_build_addr(proc, ie->expr).address);
} break;
}
ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
v = ssa_emit_ptr_offset(proc, elem, index);
- ssa_value_set_type(v, type_deref(ssa_value_type(v)));
- return ssa_make_lvalue_address(v, expr);
+ Type *lval_type = type_deref(ssa_value_type(v));
+ // gb_printf("%s\n", type_to_string(lval_type));
+ ssa_value_set_type(v, lval_type);
+ return ssa_make_lvalue(v, expr);
case_end;
case_ast_node(se, SliceExpr, expr);
@@ -1691,13 +1801,13 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
switch (type->kind) {
case Type_Slice:
case Type_Array: {
- ssaValue *base = ssa_lvalue_address(ssa_build_addr(proc, se->expr), proc);
- return ssa_make_lvalue_address(ssa_emit_slice(proc, type, base, low, high, max), expr);
+ ssaValue *base = ssa_build_addr(proc, se->expr).address;
+ return ssa_make_lvalue(ssa_emit_slice(proc, type, base, low, high, max), expr);
} break;
case Type_Basic: {
// NOTE(bill): max is not needed
- ssaValue *base = ssa_lvalue_address(ssa_build_addr(proc, se->expr), proc);
- return ssa_make_lvalue_address(ssa_emit_substring(proc, base, low, high), expr);
+ ssaValue *base = ssa_build_addr(proc, se->expr).address;
+ return ssa_make_lvalue(ssa_emit_substring(proc, base, low, high), expr);
} break;
}
@@ -1705,21 +1815,21 @@ ssaLvalue ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
case_end;
case_ast_node(de, DerefExpr, expr);
- ssaValue *e = ssa_emit_load(proc, ssa_lvalue_address(ssa_build_addr(proc, de->expr), proc));
+ ssaValue *e = ssa_emit_load(proc, ssa_build_addr(proc, de->expr).address);
ssaValue *gep = ssa_make_instr_get_element_ptr(proc, e, NULL, NULL, 0, false);
Type *t = type_deref(get_base_type(ssa_value_type(e)));
gep->instr.get_element_ptr.result_type = t;
gep->instr.get_element_ptr.elem_type = t;
ssaValue *v = ssa_emit(proc, gep);
- return ssa_make_lvalue_address(v, expr);
+ return ssa_make_lvalue(v, expr);
case_end;
}
GB_PANIC("Unexpected address expression\n"
"\tAstNode: %.*s\n", LIT(ast_node_strings[expr->kind]));
- ssaLvalue blank = {ssaLvalue_Blank};
- return blank;
+
+ return ssa_make_lvalue(NULL, NULL);
}
void ssa_build_assign_op(ssaProcedure *proc, ssaLvalue lhs, ssaValue *value, Token op) {
@@ -1787,11 +1897,11 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
defer (gb_array_free(inits));
for (AstNode *name = vd->name_list; name != NULL; name = name->next) {
- ssaLvalue lval = {ssaLvalue_Blank};
+ ssaLvalue lval = ssa_make_lvalue(NULL, NULL);
if (!ssa_is_blank_ident(name)) {
ssa_add_local_for_identifier(proc, name);
lval = ssa_build_addr(proc, name);
- GB_ASSERT(lval.address.value != NULL);
+ GB_ASSERT(lval.address != NULL);
}
gb_array_append(lvals, lval);
@@ -1804,8 +1914,8 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
gb_for_array(i, inits) {
- if (lvals[i].kind != ssaLvalue_Blank) {
- ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_lvalue_type(lvals[i]));
+ if (lvals[i].address != NULL) {
+ ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_value_type(lvals[i].address));
ssa_lvalue_store(lvals[i], proc, v);
}
}
@@ -1825,7 +1935,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
defer (gb_array_free(inits));
for (AstNode *name = vd->name_list; name != NULL; name = name->next) {
- ssaLvalue lval = {ssaLvalue_Blank};
+ ssaLvalue lval = ssa_make_lvalue(NULL, NULL);
if (!ssa_is_blank_ident(name)) {
ssa_add_local_for_identifier(proc, name);
lval = ssa_build_addr(proc, name);
@@ -1850,7 +1960,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
gb_for_array(i, inits) {
- ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_lvalue_type(lvals[i]));
+ ssaValue *v = ssa_emit_conv(proc, inits[i], ssa_value_type(lvals[i].address));
ssa_lvalue_store(lvals[i], proc, v);
}
}
diff --git a/src/parser.cpp b/src/parser.cpp
index 62d6ea35e..40a970fc6 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -96,7 +96,6 @@ AST_NODE_KIND(_ExprBegin, struct{}) \
AST_NODE_KIND(ParenExpr, struct { AstNode *expr; Token open, close; }) \
AST_NODE_KIND(SelectorExpr, struct { Token token; AstNode *expr, *selector; }) \
AST_NODE_KIND(IndexExpr, struct { AstNode *expr, *index; Token open, close; }) \
- AST_NODE_KIND(CastExpr, struct { Token token; AstNode *type, *expr; }) \
AST_NODE_KIND(DerefExpr, struct { Token op; AstNode *expr; }) \
AST_NODE_KIND(CallExpr, struct { \
AstNode *proc, *arg_list; \
@@ -296,8 +295,6 @@ 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_DerefExpr:
return node->DerefExpr.op;
case AstNode_BadStmt:
@@ -537,15 +534,6 @@ gb_inline AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token
return result;
}
-gb_inline AstNode *make_cast_expr(AstFile *f, Token token, AstNode *type, AstNode *expr) {
- AstNode *result = make_node(f, AstNode_CastExpr);
- result->CastExpr.token = token;
- result->CastExpr.type = type;
- result->CastExpr.expr = expr;
- return result;
-}
-
-
gb_inline AstNode *make_deref_expr(AstFile *f, AstNode *expr, Token op) {
AstNode *result = make_node(f, AstNode_DerefExpr);
result->DerefExpr.expr = expr;
@@ -858,6 +846,7 @@ gb_internal void add_ast_entity(AstFile *f, AstScope *scope, AstNode *declaratio
void fix_advance_to_next_stmt(AstFile *f) {
+ // TODO(bill): fix_advance_to_next_stmt
#if 0
for (;;) {
Token t = f->cursor[0];
@@ -1209,17 +1198,6 @@ AstNode *parse_unary_expr(AstFile *f, b32 lhs) {
operand = parse_unary_expr(f, false);
return make_unary_expr(f, op, operand);
} break;
-
- case Token_cast: {
- AstNode *type, *operand;
- Token token = f->cursor[0];
- next_token(f);
- expect_token(f, Token_OpenParen);
- type = parse_type(f);
- expect_token(f, Token_CloseParen);
- operand = parse_unary_expr(f, false);
- return make_cast_expr(f, token, type, operand);
- } break;
}
return parse_atom_expr(f, lhs);
@@ -1234,15 +1212,25 @@ AstNode *parse_binary_expr(AstFile *f, b32 lhs, i32 prec_in) {
i32 op_prec = token_precedence(op);
if (op_prec != prec)
break;
- expect_operator(f); // NOTE(bill): error checks too
+ if (op.kind != Token_as) {
+ expect_operator(f); // NOTE(bill): error checks too
+ }
if (lhs) {
// TODO(bill): error checking
lhs = false;
}
- right = parse_binary_expr(f, false, prec+1);
- if (!right)
- ast_file_err(f, op, "Expected expression on the right hand side of the binary operator");
+
+ if (op.kind == Token_as) {
+ next_token(f);
+ right = parse_type(f);
+ } else {
+ right = parse_binary_expr(f, false, prec+1);
+ if (!right) {
+ ast_file_err(f, op, "Expected expression on the right hand side of the binary operator");
+ }
+ }
expression = make_binary_expr(f, op, expression, right);
+
}
}
return expression;
@@ -1731,12 +1719,8 @@ AstNode *parse_if_stmt(AstFile *f) {
}
}
-
f->expr_level = prev_level;
-
-
-
if (cond == NULL) {
ast_file_err(f, f->cursor[0], "Expected condition for if statement");
}
@@ -1846,56 +1830,51 @@ AstNode *parse_defer_stmt(AstFile *f) {
return make_defer_stmt(f, token, statement);
}
-AstNode *parse_type_decl(AstFile *f) {
- Token token = expect_token(f, Token_type);
- AstNode *name = parse_identifier(f);
- expect_token(f, Token_Colon);
- AstNode *type = parse_type(f);
-
- AstNode *type_decl = make_type_decl(f, token, name, type);
+AstNode *parse_stmt(AstFile *f) {
+ AstNode *s = NULL;
+ Token token = f->cursor[0];
+ switch (token.kind) {
+ case Token_type: {
+ Token token = expect_token(f, Token_type);
+ AstNode *name = parse_identifier(f);
+ expect_token(f, Token_Colon);
+ AstNode *type = parse_type(f);
- if (type->kind != AstNode_StructType &&
- type->kind != AstNode_ProcType)
- expect_token(f, Token_Semicolon);
+ AstNode *type_decl = make_type_decl(f, token, name, type);
- return type_decl;
-}
+ if (type->kind != AstNode_StructType &&
+ type->kind != AstNode_ProcType) {
+ expect_token(f, Token_Semicolon);
+ }
-AstNode *parse_alias_decl(AstFile *f) {
- Token token = expect_token(f, Token_alias);
- AstNode *name = parse_identifier(f);
- expect_token(f, Token_Colon);
- AstNode *type = parse_type(f);
+ return type_decl;
+ } break;
- AstNode *alias_decl = make_alias_decl(f, token, name, type);
+ case Token_alias: {
+ Token token = expect_token(f, Token_alias);
+ AstNode *name = parse_identifier(f);
+ expect_token(f, Token_Colon);
+ AstNode *type = parse_type(f);
- if (type->kind != AstNode_StructType &&
- type->kind != AstNode_ProcType)
- expect_token(f, Token_Semicolon);
+ AstNode *alias_decl = make_alias_decl(f, token, name, type);
- return alias_decl;
-}
+ if (type->kind != AstNode_StructType &&
+ type->kind != AstNode_ProcType) {
+ expect_token(f, Token_Semicolon);
+ }
-AstNode *parse_import_decl(AstFile *f) {
- Token token = expect_token(f, Token_import);
- Token filepath = expect_token(f, Token_String);
- if (f->curr_scope == f->file_scope) {
- return make_import_decl(f, token, filepath);
- }
- ast_file_err(f, token, "You cannot `import` within a procedure. This must be done at the file scope.");
- return make_bad_decl(f, token, filepath);
-}
+ return alias_decl;
+ } break;
-AstNode *parse_stmt(AstFile *f) {
- AstNode *s = NULL;
- Token token = f->cursor[0];
- switch (token.kind) {
- case Token_type:
- return parse_type_decl(f);
- case Token_alias:
- return parse_alias_decl(f);
- case Token_import:
- return parse_import_decl(f);
+ case Token_import: {
+ Token token = expect_token(f, Token_import);
+ Token filepath = expect_token(f, Token_String);
+ if (f->curr_scope == f->file_scope) {
+ return make_import_decl(f, token, filepath);
+ }
+ ast_file_err(f, token, "You cannot `import` within a procedure. This must be done at the file scope.");
+ return make_bad_decl(f, token, filepath);
+ } break;
// Operands
case Token_Identifier:
@@ -1910,10 +1889,8 @@ AstNode *parse_stmt(AstFile *f) {
case Token_Xor:
case Token_Not:
s = parse_simple_stmt(f);
- if (s->kind != AstNode_ProcDecl &&
- !allow_token(f, Token_Semicolon) &&
- f->cursor[0].kind == Token_CloseBrace) {
- // TODO(bill): Cleanup semicolon handling in parser
+ if (s->kind != AstNode_ProcDecl && !allow_token(f, Token_Semicolon)) {
+ // CLEANUP(bill): Semicolon handling in parser
ast_file_err(f, f->cursor[0],
"Expected `;` after statement, got `%.*s`",
LIT(token_strings[f->cursor[0].kind]));
@@ -1946,8 +1923,6 @@ AstNode *parse_stmt(AstFile *f) {
s = make_empty_stmt(f, token);
next_token(f);
return s;
-
-
}
ast_file_err(f, token,
diff --git a/src/printer.cpp b/src/printer.cpp
index 8dd61e0ca..465714783 100644
--- a/src/printer.cpp
+++ b/src/printer.cpp
@@ -70,12 +70,6 @@ void print_ast(AstNode *node, isize indent) {
print_ast(node->IndexExpr.expr, indent+1);
print_ast(node->IndexExpr.index, indent+1);
break;
- case AstNode_CastExpr:
- print_indent(indent);
- gb_printf("(cast)\n");
- print_ast(node->CastExpr.type, indent+1);
- print_ast(node->CastExpr.expr, indent+1);
- break;
case AstNode_DerefExpr:
print_indent(indent);
gb_printf("(deref)\n");
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 6f319959c..d025d0879 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -54,6 +54,7 @@ TOKEN_KIND(Token__OperatorBegin, "_OperatorBegin"), \
TOKEN_KIND(Token_AndNot, "&~"), \
TOKEN_KIND(Token_Shl, "<<"), \
TOKEN_KIND(Token_Shr, ">>"), \
+ TOKEN_KIND(Token_as, "as"), \
TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
TOKEN_KIND(Token_AddEq, "+="), \
TOKEN_KIND(Token_SubEq, "-="), \
@@ -71,6 +72,7 @@ TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
TOKEN_KIND(Token_Decrement, "--"), \
TOKEN_KIND(Token_ArrowRight, "->"), \
TOKEN_KIND(Token_ArrowLeft, "<-"), \
+\
TOKEN_KIND(Token_CmpAnd, "&&"), \
TOKEN_KIND(Token_CmpOr, "||"), \
TOKEN_KIND(Token_CmpAndEq, "&&="), \
@@ -113,7 +115,6 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_defer, "defer"), \
TOKEN_KIND(Token_return, "return"), \
TOKEN_KIND(Token_import, "import"), \
- TOKEN_KIND(Token_cast, "cast"), \
TOKEN_KIND(Token_struct, "struct"), \
TOKEN_KIND(Token_union, "union"), \
TOKEN_KIND(Token_enum, "enum"), \
@@ -199,9 +200,10 @@ gb_no_inline void warning(Token token, char *fmt, ...) {
i32 token_precedence(Token t) {
switch (t.kind) {
- case Token_CmpOr: return 1;
- case Token_CmpAnd: return 2;
-
+ case Token_CmpOr:
+ return 1;
+ case Token_CmpAnd:
+ return 2;
case Token_CmpEq:
case Token_NotEq:
case Token_Lt:
@@ -209,13 +211,11 @@ i32 token_precedence(Token t) {
case Token_LtEq:
case Token_GtEq:
return 3;
-
case Token_Add:
case Token_Sub:
case Token_Or:
case Token_Xor:
return 4;
-
case Token_Mul:
case Token_Quo:
case Token_Mod:
@@ -224,6 +224,8 @@ i32 token_precedence(Token t) {
case Token_Shl:
case Token_Shr:
return 5;
+ case Token_as:
+ return 6;
}
return 0;
@@ -641,10 +643,14 @@ Token tokenizer_get_token(Tokenizer *t) {
// NOTE(bill): ALL identifiers are > 1
if (token.string.len > 1) {
- for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
- if (are_strings_equal(token.string, token_strings[k])) {
- token.kind = cast(TokenKind)k;
- break;
+ if (are_strings_equal(token.string, token_strings[Token_as])) {
+ token.kind = Token_as;
+ } else {
+ for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
+ if (are_strings_equal(token.string, token_strings[k])) {
+ token.kind = cast(TokenKind)k;
+ break;
+ }
}
}
}