auto_cast

This commit is contained in:
gingerBill
2018-02-18 15:14:13 +00:00
parent 731dad480d
commit 4c339360e9
6 changed files with 101 additions and 41 deletions
+1
View File
@@ -243,6 +243,7 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
named->Named.base = base_type(bt);
if (!is_distinct) {
e->type = bt;
named->Named.base = bt;
e->TypeName.is_type_alias = true;
}
// if (is_alias) {
+48 -13
View File
@@ -394,7 +394,7 @@ bool find_or_generate_polymorphic_procedure_from_parameters(Checker *c, Entity *
bool check_type_specialization_to(Checker *c, Type *specialization, Type *type, bool compound, bool modify_type);
bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool compound, bool modify_type);
bool check_cast_internal(Checker *c, Operand *x, Type *type);
i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
if (operand->mode == Addressing_Invalid ||
@@ -571,7 +571,15 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
}
}
AstNode *expr = unparen_expr(operand->expr);
if (expr != nullptr && expr->kind == AstNode_AutoCast) {
Operand x = *operand;
x.expr = expr->AutoCast.expr;
bool ok = check_cast_internal(c, &x, type);
if (ok) {
return 10;
}
}
return -1;
}
@@ -1797,13 +1805,7 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
return false;
}
void check_cast(Checker *c, Operand *x, Type *type) {
if (!is_operand_value(*x)) {
error(x->expr, "'cast' can only be applied to values");
x->mode = Addressing_Invalid;
return;
}
bool check_cast_internal(Checker *c, Operand *x, Type *type) {
bool is_const_expr = x->mode == Addressing_Constant;
bool can_convert = false;
@@ -1811,9 +1813,9 @@ void check_cast(Checker *c, Operand *x, Type *type) {
if (is_const_expr && is_type_constant_type(bt)) {
if (core_type(bt)->kind == Type_Basic) {
if (check_representable_as_constant(c, x->value, bt, &x->value)) {
can_convert = true;
return true;
} else if (is_type_pointer(type) && check_is_castable_to(c, x, type)) {
can_convert = true;
return true;
}
}
} else if (check_is_castable_to(c, x, type)) {
@@ -1822,8 +1824,21 @@ void check_cast(Checker *c, Operand *x, Type *type) {
} else if (is_type_slice(type) && is_type_string(x->type)) {
x->mode = Addressing_Value;
}
can_convert = true;
return true;
}
return false;
}
void check_cast(Checker *c, Operand *x, Type *type) {
if (!is_operand_value(*x)) {
error(x->expr, "Only values can be casted");
x->mode = Addressing_Invalid;
return;
}
bool is_const_expr = x->mode == Addressing_Constant;
bool can_convert = check_cast_internal(c, x, type);
if (!can_convert) {
gbString expr_str = expr_to_string(x->expr);
@@ -5767,6 +5782,19 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
return Expr_Expr;
case_end;
case_ast_node(ac, AutoCast, node);
check_expr_base(c, o, ac->expr, type_hint);
if (o->mode == Addressing_Invalid) {
o->expr = node;
return kind;
}
if (type_hint) {
check_cast(c, o, type_hint);
}
o->expr = node;
return Expr_Expr;
case_end;
case_ast_node(ue, UnaryExpr, node);
check_expr_base(c, o, ue->expr, type_hint);
if (o->mode == Addressing_Invalid) {
@@ -6215,7 +6243,8 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, ta->type);
str = gb_string_append_rune(str, ')');
case_end;
case_ast_node(tc, TypeCast, node);
case_ast_node(tc, TypeCast, node);
str = string_append_token(str, tc->token);
str = gb_string_append_rune(str, '(');
str = write_expr_to_string(str, tc->type);
@@ -6223,6 +6252,12 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
str = write_expr_to_string(str, tc->expr);
case_end;
case_ast_node(ac, AutoCast, node);
str = string_append_token(str, ac->token);
str = gb_string_append_rune(str, ' ');
str = write_expr_to_string(str, ac->expr);
case_end;
case_ast_node(ie, IndexExpr, node);
str = write_expr_to_string(str, ie->expr);
str = gb_string_append_rune(str, '[');
+8
View File
@@ -4979,6 +4979,10 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
GB_PANIC("Invalid AST TypeCast");
case_end;
case_ast_node(ac, AutoCast, expr);
return ir_build_expr(proc, ac->expr);
case_end;
case_ast_node(ue, UnaryExpr, expr);
switch (ue->op.kind) {
case Token_And: {
@@ -6052,6 +6056,10 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
ir_emit_store(proc, v, e);
return ir_addr(v);
case_end;
case_ast_node(ac, AutoCast, expr);
return ir_build_addr(proc, ac->expr);
case_end;
}
TokenPos token_pos = ast_node_token(expr).pos;
+42 -28
View File
@@ -25,35 +25,36 @@ Token ast_node_token(AstNode *node) {
return ast_node_token(node->SelectorExpr.selector);
}
return node->SelectorExpr.token;
case AstNode_IndexExpr: return node->IndexExpr.open;
case AstNode_SliceExpr: return node->SliceExpr.open;
case AstNode_Ellipsis: return node->Ellipsis.token;
case AstNode_FieldValue: return node->FieldValue.eq;
case AstNode_DerefExpr: return node->DerefExpr.op;
case AstNode_TernaryExpr: return ast_node_token(node->TernaryExpr.cond);
case AstNode_TypeAssertion: return ast_node_token(node->TypeAssertion.expr);
case AstNode_TypeCast: return node->TypeCast.token;
case AstNode_IndexExpr: return node->IndexExpr.open;
case AstNode_SliceExpr: return node->SliceExpr.open;
case AstNode_Ellipsis: return node->Ellipsis.token;
case AstNode_FieldValue: return node->FieldValue.eq;
case AstNode_DerefExpr: return node->DerefExpr.op;
case AstNode_TernaryExpr: return ast_node_token(node->TernaryExpr.cond);
case AstNode_TypeAssertion: return ast_node_token(node->TypeAssertion.expr);
case AstNode_TypeCast: return node->TypeCast.token;
case AstNode_AutoCast: return node->AutoCast.token;
case AstNode_BadStmt: return node->BadStmt.begin;
case AstNode_EmptyStmt: return node->EmptyStmt.token;
case AstNode_ExprStmt: return ast_node_token(node->ExprStmt.expr);
case AstNode_TagStmt: return node->TagStmt.token;
case AstNode_AssignStmt: return node->AssignStmt.op;
case AstNode_IncDecStmt: return ast_node_token(node->IncDecStmt.expr);
case AstNode_BlockStmt: return node->BlockStmt.open;
case AstNode_IfStmt: return node->IfStmt.token;
case AstNode_WhenStmt: return node->WhenStmt.token;
case AstNode_ReturnStmt: return node->ReturnStmt.token;
case AstNode_ForStmt: return node->ForStmt.token;
case AstNode_RangeStmt: return node->RangeStmt.token;
case AstNode_CaseClause: return node->CaseClause.token;
case AstNode_SwitchStmt: return node->SwitchStmt.token;
case AstNode_TypeSwitchStmt: return node->TypeSwitchStmt.token;
case AstNode_DeferStmt: return node->DeferStmt.token;
case AstNode_BranchStmt: return node->BranchStmt.token;
case AstNode_UsingStmt: return node->UsingStmt.token;
case AstNode_UsingInStmt: return node->UsingInStmt.using_token;
case AstNode_PushContext: return node->PushContext.token;
case AstNode_BadStmt: return node->BadStmt.begin;
case AstNode_EmptyStmt: return node->EmptyStmt.token;
case AstNode_ExprStmt: return ast_node_token(node->ExprStmt.expr);
case AstNode_TagStmt: return node->TagStmt.token;
case AstNode_AssignStmt: return node->AssignStmt.op;
case AstNode_IncDecStmt: return ast_node_token(node->IncDecStmt.expr);
case AstNode_BlockStmt: return node->BlockStmt.open;
case AstNode_IfStmt: return node->IfStmt.token;
case AstNode_WhenStmt: return node->WhenStmt.token;
case AstNode_ReturnStmt: return node->ReturnStmt.token;
case AstNode_ForStmt: return node->ForStmt.token;
case AstNode_RangeStmt: return node->RangeStmt.token;
case AstNode_CaseClause: return node->CaseClause.token;
case AstNode_SwitchStmt: return node->SwitchStmt.token;
case AstNode_TypeSwitchStmt: return node->TypeSwitchStmt.token;
case AstNode_DeferStmt: return node->DeferStmt.token;
case AstNode_BranchStmt: return node->BranchStmt.token;
case AstNode_UsingStmt: return node->UsingStmt.token;
case AstNode_UsingInStmt: return node->UsingInStmt.using_token;
case AstNode_PushContext: return node->PushContext.token;
case AstNode_BadDecl: return node->BadDecl.begin;
case AstNode_Label: return node->Label.token;
@@ -633,6 +634,12 @@ AstNode *ast_type_cast(AstFile *f, Token token, AstNode *type, AstNode *expr) {
result->TypeCast.expr = expr;
return result;
}
AstNode *ast_auto_cast(AstFile *f, Token token, AstNode *expr) {
AstNode *result = make_ast_node(f, AstNode_AutoCast);
result->AutoCast.token = token;
result->AutoCast.expr = expr;
return result;
}
@@ -2195,6 +2202,13 @@ AstNode *parse_unary_expr(AstFile *f, bool lhs) {
AstNode *expr = parse_unary_expr(f, lhs);
return ast_type_cast(f, token, type, expr);
}
case Token_auto_cast: {
Token token = advance_token(f);
AstNode *expr = parse_unary_expr(f, lhs);
return ast_auto_cast(f, token, expr);
}
case Token_Add:
case Token_Sub:
case Token_Not:
+1
View File
@@ -220,6 +220,7 @@ AST_NODE_KIND(_ExprBegin, "", struct {}) \
AST_NODE_KIND(TernaryExpr, "ternary expression", struct { AstNode *cond, *x, *y; }) \
AST_NODE_KIND(TypeAssertion, "type assertion", struct { AstNode *expr; Token dot; AstNode *type; }) \
AST_NODE_KIND(TypeCast, "type cast", struct { Token token; AstNode *type, *expr; }) \
AST_NODE_KIND(AutoCast, "auto_cast", struct { Token token; AstNode *expr; }) \
AST_NODE_KIND(_ExprEnd, "", struct {}) \
AST_NODE_KIND(_StmtBegin, "", struct {}) \
AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
+1
View File
@@ -108,6 +108,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_map, "map"), \
TOKEN_KIND(Token_static, "static"), \
TOKEN_KIND(Token_dynamic, "dynamic"), \
TOKEN_KIND(Token_auto_cast, "auto_cast"), \
TOKEN_KIND(Token_cast, "cast"), \
TOKEN_KIND(Token_transmute, "transmute"), \
TOKEN_KIND(Token_distinct, "distinct"), \