diff options
| author | gingerBill <ginger.bill.22@gmail.com> | 2016-08-14 12:22:31 +0100 |
|---|---|---|
| committer | gingerBill <ginger.bill.22@gmail.com> | 2016-08-14 12:22:31 +0100 |
| commit | ee002364120a773753d37cf5575baa6e86d0502c (patch) | |
| tree | d96feebc57be31d385909a0b9e4df2c0aef50a6b /src | |
| parent | c10b46af9feb76a9839efa292c5288ec4684055e (diff) | |
expr as type; {N}bool is still causing problems
Diffstat (limited to 'src')
| -rw-r--r-- | src/checker/expr.cpp | 244 | ||||
| -rw-r--r-- | src/checker/type.cpp | 36 | ||||
| -rw-r--r-- | src/codegen/codegen.cpp | 2 | ||||
| -rw-r--r-- | src/codegen/print_llvm.cpp | 34 | ||||
| -rw-r--r-- | src/codegen/ssa.cpp | 300 | ||||
| -rw-r--r-- | src/parser.cpp | 133 | ||||
| -rw-r--r-- | src/printer.cpp | 6 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 26 |
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; + } } } } |