diff options
Diffstat (limited to 'src/checker/expression.cpp')
| -rw-r--r-- | src/checker/expression.cpp | 160 |
1 files changed, 108 insertions, 52 deletions
diff --git a/src/checker/expression.cpp b/src/checker/expression.cpp index cc098bf5b..072cec859 100644 --- a/src/checker/expression.cpp +++ b/src/checker/expression.cpp @@ -70,10 +70,14 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *field_list, isize fiel if (type_expression) { Type *type = check_type(c, type_expression); for (AstNode *name = field->field.name_list; name != NULL; name = name->next) { - GB_ASSERT(name->kind == AstNode_Identifier); - Entity *param = make_entity_param(c, scope, name->identifier.token, type); - add_entity(c, scope, name, param); - variables[variable_index++] = param; + if (name->kind == AstNode_Identifier) { + Entity *param = make_entity_param(c, scope, name->identifier.token, type); + add_entity(c, scope, name, param); + variables[variable_index++] = param; + } else { + print_checker_error(c, ast_node_token(name), + "Invalid parameter (invalid AST)"); + } } } } @@ -98,6 +102,10 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun Entity *param = make_entity_param(c, scope, token, type); // NOTE(bill): No need to record variables[variable_index++] = param; + + if (get_base_type(type)->kind == Type_Array) { + print_checker_error(c, token, "You cannot return an array from a procedure"); + } } tuple->tuple.variables = variables; tuple->tuple.variable_count = list_count; @@ -107,23 +115,12 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *list, isize list_coun void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) { - isize param_count = 0; - isize result_count = 0; + isize param_count = proc_type_node->procedure_type.param_count; + isize result_count = proc_type_node->procedure_type.result_count; - // NOTE(bill): Each field can store multiple items - for (AstNode *field = proc_type_node->procedure_type.param_list; - field != NULL; - field = field->next) { - param_count += field->field.name_list_count; - } + // gb_printf("%td -> %td\n", param_count, result_count); - for (AstNode *item = proc_type_node->procedure_type.results_list; - item != NULL; - item = item->next) { - result_count++; - } - - Type *params = check_get_params (c, c->curr_scope, proc_type_node->procedure_type.param_list, param_count); + Type *params = check_get_params(c, c->curr_scope, proc_type_node->procedure_type.param_list, param_count); Type *results = check_get_results(c, c->curr_scope, proc_type_node->procedure_type.results_list, result_count); type->procedure.scope = c->curr_scope; @@ -1227,6 +1224,52 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) operand->mode = Addressing_Value; } break; + case BuiltinProcedure_copy_bytes: { + // copy_bytes :: proc(dest, source: rawptr, byte_count: int) + Type *dest_type = NULL, *src_type = NULL; + + Type *d = get_base_type(operand->type); + if (is_type_pointer(d)) + dest_type = d; + + Operand op = {}; + check_expression(c, &op, ce->arg_list->next); + if (op.mode == Addressing_Invalid) + return false; + Type *s = get_base_type(op.type); + if (is_type_pointer(s)) + src_type = s; + + if (dest_type == NULL || src_type == NULL) { + print_checker_error(c, ast_node_token(call), "`copy_bytes` only expects pointers for the destintation and source"); + return false; + } + + check_expression(c, &op, ce->arg_list->next->next); + if (op.mode == Addressing_Invalid) + return false; + + convert_to_typed(c, &op, &basic_types[Basic_int]); + if (op.mode == Addressing_Invalid || + op.type->kind != Type_Basic || + op.type->basic.kind != Basic_int) { + gbString str = type_to_string(op.type); + defer (gb_string_free(str)); + print_checker_error(c, ast_node_token(call), "`copy_bytes` 3rd argument must be of type `int`, a `%s` was given", str); + return false; + } + + if (op.mode == Addressing_Constant) { + if (value_to_integer(op.value).value_integer <= 0) { + print_checker_error(c, ast_node_token(call), "You cannot copy a zero or negative amount of bytes with `copy_bytes`"); + return false; + } + } + + operand->type = NULL; + operand->mode = Addressing_NoValue; + } break; + case BuiltinProcedure_print: case BuiltinProcedure_println: { @@ -1445,62 +1488,69 @@ void check_cast_expression(Checker *c, Operand *operand, Type *type) { -ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expression, Type *type_hint) { +ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *node, Type *type_hint) { ExpressionKind kind = Expression_Statement; operand->mode = Addressing_Invalid; operand->type = &basic_types[Basic_Invalid]; - switch (expression->kind) { + switch (node->kind) { case AstNode_BadExpression: goto error; case AstNode_Identifier: - check_identifier(c, operand, expression, type_hint); + check_identifier(c, operand, node, type_hint); break; case AstNode_BasicLiteral: { - BasicKind kind = Basic_Invalid; - Token lit = expression->basic_literal; + BasicKind basic_kind = Basic_Invalid; + Token lit = node->basic_literal; switch (lit.kind) { - case Token_Integer: kind = Basic_UntypedInteger; break; - case Token_Float: kind = Basic_UntypedFloat; break; - case Token_String: kind = Basic_UntypedString; break; - case Token_Rune: kind = Basic_UntypedRune; break; - default: GB_PANIC("Unknown literal"); break; + case Token_Integer: basic_kind = Basic_UntypedInteger; break; + case Token_Float: basic_kind = Basic_UntypedFloat; break; + case Token_String: basic_kind = Basic_UntypedString; break; + case Token_Rune: basic_kind = Basic_UntypedRune; break; + default: GB_PANIC("Unknown literal"); break; } operand->mode = Addressing_Constant; - operand->type = &basic_types[kind]; + operand->type = &basic_types[basic_kind]; operand->value = make_value_from_basic_literal(lit); } break; case AstNode_ParenExpression: - kind = check_expression_base(c, operand, expression->paren_expression.expression); - operand->expression = expression; + kind = check_expression_base(c, operand, node->paren_expression.expression, type_hint); + operand->expression = node; + break; + + case AstNode_TagExpression: + // TODO(bill): Tag expressions + print_checker_error(c, ast_node_token(node), "Tag expressions are not supported yet"); + kind = check_expression_base(c, operand, node->tag_expression.expression, type_hint); + operand->expression = node; break; case AstNode_UnaryExpression: - check_expression(c, operand, expression->unary_expression.operand); + check_expression(c, operand, node->unary_expression.operand); if (operand->mode == Addressing_Invalid) goto error; - check_unary_expression(c, operand, expression->unary_expression.op, expression); + check_unary_expression(c, operand, node->unary_expression.op, node); if (operand->mode == Addressing_Invalid) goto error; break; case AstNode_BinaryExpression: - check_binary_expression(c, operand, expression); + check_binary_expression(c, operand, node); if (operand->mode == Addressing_Invalid) goto error; break; case AstNode_SelectorExpression: - check_expression_base(c, operand, expression->selector_expression.operand); - check_selector(c, operand, expression); + check_expression_base(c, operand, node->selector_expression.operand); + check_selector(c, operand, node); break; case AstNode_IndexExpression: { - check_expression(c, operand, expression->index_expression.expression); + check_expression(c, operand, node->index_expression.expression); if (operand->mode == Addressing_Invalid) goto error; @@ -1548,7 +1598,7 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expr goto error; } - if (expression->index_expression.value == NULL) { + if (node->index_expression.value == NULL) { gbString str = expression_to_string(operand->expression); print_checker_error(c, ast_node_token(operand->expression), "Missing index for `%s`", str); @@ -1556,12 +1606,12 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expr goto error; } - check_index_value(c, expression->index_expression.value, max_count, NULL); + check_index_value(c, node->index_expression.value, max_count, NULL); } break; case AstNode_SliceExpression: { - auto *se = &expression->slice_expression; + auto *se = &node->slice_expression; check_expression(c, operand, se->expression); if (operand->mode == Addressing_Invalid) goto error; @@ -1584,8 +1634,8 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expr valid = true; max_count = t->array.count; if (operand->mode != Addressing_Variable) { - gbString str = expression_to_string(expression); - print_checker_error(c, ast_node_token(expression), "Cannot slice array `%s`, value is not addressable", str); + gbString str = expression_to_string(node); + print_checker_error(c, ast_node_token(node), "Cannot slice array `%s`, value is not addressable", str); gb_string_free(str); goto error; } @@ -1645,18 +1695,18 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expr } break; case AstNode_CastExpression: { - Type *cast_type = check_type(c, expression->cast_expression.type_expression); - check_expression_or_type(c, operand, expression->cast_expression.operand); + Type *cast_type = check_type(c, node->cast_expression.type_expression); + check_expression_or_type(c, operand, node->cast_expression.operand); if (operand->mode != Addressing_Invalid) check_cast_expression(c, operand, cast_type); } break; case AstNode_CallExpression: - return check_call_expression(c, operand, expression); + return check_call_expression(c, operand, node); case AstNode_DereferenceExpression: - check_expression_or_type(c, operand, expression->dereference_expression.operand); + check_expression_or_type(c, operand, node->dereference_expression.operand); if (operand->mode == Addressing_Invalid) { goto error; } else { @@ -1679,17 +1729,17 @@ ExpressionKind check_expression_base(Checker *c, Operand *operand, AstNode *expr case AstNode_ArrayType: case AstNode_StructType: operand->mode = Addressing_Type; - operand->type = check_type(c, expression); + operand->type = check_type(c, node); break; } kind = Expression_Expression; - operand->expression = expression; + operand->expression = node; goto after_error; error: operand->mode = Addressing_Invalid; - operand->expression = expression; + operand->expression = node; goto after_error; after_error: @@ -1713,9 +1763,9 @@ after_error: if (type) { if (is_type_untyped(type)) { - add_untyped(c, expression, false, operand->mode, type, value); + add_untyped(c, node, false, operand->mode, type, value); } else { - add_type_and_value(c, expression, operand->mode, type, value); + add_type_and_value(c, node, operand->mode, type, value); } } return kind; @@ -1824,6 +1874,12 @@ gbString write_expression_to_string(gbString str, AstNode *node) { str = string_append_token(str, node->basic_literal); break; + case AstNode_TagExpression: + str = gb_string_appendc(str, "#"); + str = string_append_token(str, node->tag_expression.name); + str = write_expression_to_string(str, node->tag_expression.expression); + break; + case AstNode_UnaryExpression: str = string_append_token(str, node->unary_expression.op); str = write_expression_to_string(str, node->unary_expression.operand); |