expr as type; {N}bool is still causing problems

This commit is contained in:
gingerBill
2016-08-14 12:22:31 +01:00
parent c10b46af9f
commit ee00236412
11 changed files with 833 additions and 546 deletions
+137 -107
View File
@@ -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;
+21 -15
View File
@@ -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;
+1 -1
View File
@@ -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);
}
+29 -5
View File
@@ -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"));
+205 -95
View File
@@ -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);
}
}
+58 -83
View File
@@ -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);
if (type->kind != AstNode_StructType &&
type->kind != AstNode_ProcType)
expect_token(f, Token_Semicolon);
return type_decl;
}
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);
AstNode *alias_decl = make_alias_decl(f, token, name, type);
if (type->kind != AstNode_StructType &&
type->kind != AstNode_ProcType)
expect_token(f, Token_Semicolon);
return alias_decl;
}
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);
}
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_type: {
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);
if (type->kind != AstNode_StructType &&
type->kind != AstNode_ProcType) {
expect_token(f, Token_Semicolon);
}
return type_decl;
} break;
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);
AstNode *alias_decl = make_alias_decl(f, token, name, type);
if (type->kind != AstNode_StructType &&
type->kind != AstNode_ProcType) {
expect_token(f, Token_Semicolon);
}
return alias_decl;
} break;
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,
-6
View File
@@ -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");
+16 -10
View File
@@ -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;
}
}
}
}