diff options
| author | gingerBill <ginger.bill.22@gmail.com> | 2016-07-09 00:31:57 +0100 |
|---|---|---|
| committer | gingerBill <ginger.bill.22@gmail.com> | 2016-07-09 00:31:57 +0100 |
| commit | f7a669d342c96451a3e0be84e2e51af8631f90ec (patch) | |
| tree | c0c81ed66c8229c182bac13ef8107ca642debd74 /src/checker/expression.cpp | |
| parent | 9ba2a6d02cab3feff9d70f7bb9c2e8eb72bc5533 (diff) | |
Initial release version
* Code cleanup
* Fix some TODOs
* Reduce heap allocation use and replace with arena allocation
Diffstat (limited to 'src/checker/expression.cpp')
| -rw-r--r-- | src/checker/expression.cpp | 113 |
1 files changed, 71 insertions, 42 deletions
diff --git a/src/checker/expression.cpp b/src/checker/expression.cpp index fbb213dfa..cc098bf5b 100644 --- a/src/checker/expression.cpp +++ b/src/checker/expression.cpp @@ -1,4 +1,5 @@ void check_assignment (Checker *c, Operand *operand, Type *type, String context_name); +b32 check_is_assignable_to (Checker *c, Operand *operand, Type *type); void check_expression (Checker *c, Operand *operand, AstNode *expression); void check_multi_expression (Checker *c, Operand *operand, AstNode *expression); void check_expression_or_type(Checker *c, Operand *operand, AstNode *expression); @@ -31,8 +32,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { } } - Entity **fields = gb_alloc_array(gb_arena_allocator(&c->entity_arena), - Entity *, st->field_count); + Entity **fields = gb_alloc_array(c->allocator, Entity *, st->field_count); isize field_index = 0; for (AstNode *field = st->field_list; field != NULL; field = field->next) { Type *type = check_type(c, field->field.type_expression); @@ -60,10 +60,9 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel if (field_list == NULL || field_count == 0) return NULL; - Type *tuple = make_type_tuple(); + Type *tuple = make_type_tuple(c->allocator); - Entity **variables = gb_alloc_array(gb_arena_allocator(&c->entity_arena), - Entity *, field_count); + Entity **variables = gb_alloc_array(c->allocator, Entity *, field_count); isize variable_index = 0; for (AstNode *field = field_list; field != NULL; field = field->next) { GB_ASSERT(field->kind == AstNode_Field); @@ -87,10 +86,9 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_count) { if (list == NULL) return NULL; - Type *tuple = make_type_tuple(); + Type *tuple = make_type_tuple(c->allocator); - Entity **variables = gb_alloc_array(gb_arena_allocator(&c->entity_arena), - Entity *, list_count); + Entity **variables = gb_alloc_array(c->allocator, Entity *, list_count); isize variable_index = 0; for (AstNode *item = list; item != NULL; item = item->next) { Type *type = check_type(c, item); @@ -143,7 +141,7 @@ void check_identifier(Checker *c, Operand *operand, AstNode *n, Type *named_type scope_lookup_parent_entity(c->curr_scope, n->identifier.token.string, NULL, &e); if (e == NULL) { print_checker_error(c, n->identifier.token, - "Undeclared type/identifier: %.*s", LIT(n->identifier.token.string)); + "Undeclared type/identifier `%.*s`", LIT(n->identifier.token.string)); return; } add_entity_use(c, n, e); @@ -247,32 +245,33 @@ Type *check_type_expression_extra(Checker *c, AstNode *expression, Type *named_t case AstNode_ArrayType: if (expression->array_type.count != NULL) { - Type *t = make_type_array(check_type(c, expression->array_type.element), + Type *t = make_type_array(c->allocator, + check_type(c, expression->array_type.element), check_array_count(c, expression->array_type.count)); set_base_type(named_type, t); return t; } else { - Type *t = make_type_slice(check_type(c, expression->array_type.element)); + Type *t = make_type_slice(c->allocator, check_type(c, expression->array_type.element)); set_base_type(named_type, t); return t; } break; case AstNode_StructType: { - Type *t = make_type_structure(); + Type *t = make_type_structure(c->allocator); set_base_type(named_type, t); check_struct_type(c, t, expression); return t; } break; case AstNode_PointerType: { - Type *t = make_type_pointer(check_type(c, expression->pointer_type.type_expression)); + Type *t = make_type_pointer(c->allocator, check_type(c, expression->pointer_type.type_expression)); set_base_type(named_type, t); return t; } break; case AstNode_ProcedureType: { - Type *t = alloc_type(Type_Procedure); + Type *t = alloc_type(c->allocator, Type_Procedure); set_base_type(named_type, t); check_open_scope(c, expression); check_procedure_type(c, t, expression); @@ -338,31 +337,32 @@ Type *check_type(Checker *c, AstNode *expression, Type *named_type) { case AstNode_ArrayType: { if (expression->array_type.count != NULL) { - type = make_type_array(check_type(c, expression->array_type.element), + type = make_type_array(c->allocator, + check_type(c, expression->array_type.element), check_array_count(c, expression->array_type.count)); set_base_type(named_type, type); } else { - type = make_type_slice(check_type(c, expression->array_type.element)); + type = make_type_slice(c->allocator, check_type(c, expression->array_type.element)); set_base_type(named_type, type); } goto end; } break; case AstNode_StructType: { - type = make_type_structure(); + type = make_type_structure(c->allocator); set_base_type(named_type, type); check_struct_type(c, type, expression); goto end; } break; case AstNode_PointerType: { - type = make_type_pointer(check_type(c, expression->pointer_type.type_expression)); + type = make_type_pointer(c->allocator, check_type(c, expression->pointer_type.type_expression)); set_base_type(named_type, type); goto end; } break; case AstNode_ProcedureType: { - type = alloc_type(Type_Procedure); + type = alloc_type(c->allocator, Type_Procedure); set_base_type(named_type, type); check_procedure_type(c, type, expression); goto end; @@ -482,7 +482,7 @@ b32 check_value_is_expressible(Checker *c, Value in_value, Type *type, Value *ou return false; if (out_value) *out_value = in_value; i64 i = in_value.value_integer; - i64 s = 8*type_size_of(c->sizes, gb_arena_allocator(&c->entity_arena), type); + i64 s = 8*type_size_of(c->sizes, c->allocator, type); u64 umax = ~0ull; if (s < 64) umax = (1ull << s) - 1ull; @@ -570,7 +570,7 @@ void check_unary_expression(Checker *c, Operand *operand, Token op, AstNode *nod return; } operand->mode = Addressing_Value; - operand->type = make_type_pointer(operand->type); + operand->type = make_type_pointer(c->allocator, operand->type); return; } @@ -584,7 +584,7 @@ void check_unary_expression(Checker *c, Operand *operand, Token op, AstNode *nod GB_ASSERT(type->kind == Type_Basic); i32 precision = 0; if (is_type_unsigned(type)) - precision = cast(i32)(8 * type_size_of(c->sizes, gb_arena_allocator(&c->entity_arena), type)); + precision = cast(i32)(8 * type_size_of(c->sizes, c->allocator, type)); operand->value = unary_operator_value(op, operand->value, precision); if (is_type_typed(type)) { @@ -598,14 +598,12 @@ void check_unary_expression(Checker *c, Operand *operand, Token op, AstNode *nod operand->mode = Addressing_Value; } -b32 check_assignable_to(Checker *c, Operand *operand, Type *type); - void check_comparison(Checker *c, Operand *x, Operand *y, Token op) { gbString err_str = NULL; defer (gb_string_free(err_str)); - if (check_assignable_to(c, x, y->type) || - check_assignable_to(c, y, x->type)) { + if (check_is_assignable_to(c, x, y->type) || + check_is_assignable_to(c, y, x->type)) { b32 defined = false; switch (op.kind) { case Token_CmpEq: @@ -787,7 +785,7 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) { if (operand->mode == Addressing_Constant) { if (operand->value.value_integer == 0) { - // NOTE(bill): Doesn't matter what the type is as it's still zero + // NOTE(bill): Doesn't matter what the type is as it's still zero in the union extra_text = " - Did you want `null`?"; } } @@ -927,7 +925,8 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) { type = get_base_type(type->pointer.element); String field_str = field_node->identifier.token.string; - if (type->kind == Type_Structure) { + switch (type->kind) { + case Type_Structure: for (isize i = 0; i < type->structure.field_count; i++) { Entity *f = type->structure.fields[i]; GB_ASSERT(f->kind == Entity_Variable && f->variable.is_field); @@ -937,6 +936,10 @@ Entity *lookup_field(Type *type, AstNode *field_node, isize *index = NULL) { return f; } } + break; + // TODO(bill): Other types and extra "hidden" fields (e.g. introspection stuff) + // TODO(bill): Allow for access of field through index? e.g. `x.3` will get member of index 3 + // Or is this only suitable if tuples are first-class? } return NULL; @@ -995,15 +998,15 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProcedure_size_of: case BuiltinProcedure_align_of: case BuiltinProcedure_offset_of: + // NOTE(bill): The first arg is a Type, this will be checked case by case break; default: check_multi_expression(c, operand, ce->arg_list); } - gbAllocator allocator = gb_arena_allocator(&c->entity_arena); - switch (id) { case BuiltinProcedure_size_of: { + // size_of :: proc(Type) Type *type = check_type(c, ce->arg_list); if (!type) { print_checker_error(c, ast_node_token(ce->arg_list), "Expected a type for `size_of`"); @@ -1011,43 +1014,47 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } operand->mode = Addressing_Constant; - operand->value = make_value_integer(type_size_of(c->sizes, allocator, type)); + operand->value = make_value_integer(type_size_of(c->sizes, c->allocator, type)); operand->type = &basic_types[Basic_int]; } break; case BuiltinProcedure_size_of_val: + // size_of_val :: proc(val) check_assignment(c, operand, NULL, make_string("argument of `size_of`")); if (operand->mode == Addressing_Invalid) return false; operand->mode = Addressing_Constant; - operand->value = make_value_integer(type_size_of(c->sizes, allocator, operand->type)); + operand->value = make_value_integer(type_size_of(c->sizes, c->allocator, operand->type)); operand->type = &basic_types[Basic_int]; break; case BuiltinProcedure_align_of: { + // align_of :: proc(Type) Type *type = check_type(c, ce->arg_list); if (!type) { print_checker_error(c, ast_node_token(ce->arg_list), "Expected a type for `align_of`"); return false; } operand->mode = Addressing_Constant; - operand->value = make_value_integer(type_align_of(c->sizes, allocator, type)); + operand->value = make_value_integer(type_align_of(c->sizes, c->allocator, type)); operand->type = &basic_types[Basic_int]; } break; case BuiltinProcedure_align_of_val: + // align_of_val :: proc(val) check_assignment(c, operand, NULL, make_string("argument of `align_of`")); if (operand->mode == Addressing_Invalid) return false; operand->mode = Addressing_Constant; - operand->value = make_value_integer(type_align_of(c->sizes, allocator, operand->type)); + operand->value = make_value_integer(type_align_of(c->sizes, c->allocator, operand->type)); operand->type = &basic_types[Basic_int]; break; case BuiltinProcedure_offset_of: { + // offset_val :: proc(Type, field) Type *type = get_base_type(check_type(c, ce->arg_list)); AstNode *field_arg = unparen_expression(ce->arg_list->next); if (type) { @@ -1072,11 +1079,12 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } operand->mode = Addressing_Constant; - operand->value = make_value_integer(type_offset_of(c->sizes, allocator, type, index)); + operand->value = make_value_integer(type_offset_of(c->sizes, c->allocator, type, index)); operand->type = &basic_types[Basic_int]; } break; case BuiltinProcedure_offset_of_val: { + // offset_val :: proc(val) AstNode *arg = unparen_expression(ce->arg_list); if (arg->kind != AstNode_SelectorExpression) { gbString str = expression_to_string(arg); @@ -1106,12 +1114,13 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } operand->mode = Addressing_Constant; - operand->value = make_value_integer(type_offset_of(c->sizes, allocator, type, index)); + operand->value = make_value_integer(type_offset_of(c->sizes, c->allocator, type, index)); operand->type = &basic_types[Basic_int]; } break; case BuiltinProcedure_static_assert: // static_assert :: proc(cond: bool) + // TODO(bill): Should `static_assert` and `assert` be unified? if (operand->mode != Addressing_Constant || !is_type_boolean(operand->type)) { @@ -1130,6 +1139,7 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } break; + // TODO(bill): Should these be procedures and are their names appropriate? case BuiltinProcedure_len: case BuiltinProcedure_cap: { Type *t = get_base_type(operand->type); @@ -1176,9 +1186,11 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) } break; + // TODO(bill): copy() pointer version? case BuiltinProcedure_copy: { // copy :: proc(x, y: []Type) -> int Type *dest_type = NULL, *src_type = NULL; + Type *d = get_base_type(operand->type); if (d->kind == Type_Slice) dest_type = d->slice.element; @@ -1219,6 +1231,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) case BuiltinProcedure_print: case BuiltinProcedure_println: { for (AstNode *arg = ce->arg_list; arg != NULL; arg = arg->next) { + // TOOD(bill): `check_assignment` doesn't allow tuples at the moment, should it? + // Or should we destruct the tuple and use each element? check_assignment(c, operand, NULL, make_string("argument")); if (operand->mode == Addressing_Invalid) return false; @@ -1358,7 +1372,7 @@ ExpressionKind check_call_expression(Checker *c, Operand *operand, AstNode *call } b32 check_castable_to(Checker *c, Operand *operand, Type *y) { - if (check_assignable_to(c, operand, y)) + if (check_is_assignable_to(c, operand, y)) return true; Type *x = operand->type; @@ -1399,10 +1413,10 @@ b32 check_castable_to(Checker *c, Operand *operand, Type *y) { } void check_cast_expression(Checker *c, Operand *operand, Type *type) { - b32 const_expr = operand->mode == Addressing_Constant; + b32 is_const_expr = operand->mode == Addressing_Constant; b32 can_convert = false; - if (const_expr && is_type_constant_type(type)) { + 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)) { @@ -1575,7 +1589,7 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expr gb_string_free(str); goto error; } - operand->type = make_type_slice(t->array.element); + operand->type = make_type_slice(c->allocator, t->array.element); operand->mode = Addressing_Value; break; @@ -1586,7 +1600,7 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expr case Type_Pointer: valid = true; - operand->type = make_type_slice(get_base_type(t->pointer.element)); + operand->type = make_type_slice(c->allocator, get_base_type(t->pointer.element)); operand->mode = Addressing_Value; break; } @@ -1842,6 +1856,20 @@ gbString write_expression_to_string(gbString str, AstNode *node) { str = gb_string_appendc(str, "]"); break; + case AstNode_SliceExpression: + str = write_expression_to_string(str, node->slice_expression.expression); + str = gb_string_appendc(str, "["); + str = write_expression_to_string(str, node->slice_expression.low); + str = gb_string_appendc(str, ":"); + str = write_expression_to_string(str, node->slice_expression.high); + if (node->slice_expression.triple_indexed) { + str = gb_string_appendc(str, ":"); + str = write_expression_to_string(str, node->slice_expression.max); + } + str = gb_string_appendc(str, "]"); + break; + + case AstNode_CastExpression: str = gb_string_appendc(str, "cast("); str = write_expression_to_string(str, node->cast_expression.type_expression); @@ -1851,7 +1879,7 @@ gbString write_expression_to_string(gbString str, AstNode *node) { case AstNode_PointerType: - str = gb_string_appendc(str, "*"); + str = gb_string_appendc(str, "^"); str = write_expression_to_string(str, node->pointer_type.type_expression); break; case AstNode_ArrayType: @@ -1861,6 +1889,7 @@ gbString write_expression_to_string(gbString str, AstNode *node) { str = write_expression_to_string(str, node->array_type.element); break; + case AstNode_CallExpression: { str = write_expression_to_string(str, node->call_expression.proc); str = gb_string_appendc(str, "("); |