Any semantics, lvalue allocates on stack
This commit is contained in:
@@ -63,6 +63,7 @@ enum{
|
||||
AST_FLAG = bit_flag(11),
|
||||
AST_VAR_IS_CONST = bit_flag(12),
|
||||
AST_OPERATOR_OVERLOAD = bit_flag(13),
|
||||
AST_IS_LVALUE = bit_flag(14),
|
||||
};
|
||||
|
||||
struct Ast{
|
||||
|
||||
@@ -271,14 +271,20 @@ enum {
|
||||
};
|
||||
|
||||
function void
|
||||
gen_pointer_to_lvalue(Ast_Expr *expr){
|
||||
gen("&(");
|
||||
gen_pointer(Ast_Expr *expr){
|
||||
gen("&");
|
||||
if(is_flag_set(expr->flags, AST_IS_LVALUE)){
|
||||
gen_expr(expr);
|
||||
}
|
||||
else{
|
||||
gen("(");
|
||||
gen_simple_decl(expr->resolved_type);
|
||||
gen(")");
|
||||
gen("{");
|
||||
gen_expr(expr);
|
||||
gen("}");
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
gen_try_any_or_slice(Ast_Expr *expr, Ast_Type *decl_type){
|
||||
@@ -287,7 +293,7 @@ gen_try_any_or_slice(Ast_Expr *expr, Ast_Type *decl_type){
|
||||
// but other then that we shouldn't box other Any values
|
||||
if(expr->kind != AST_COMPOUND && is_any(decl_type) && !is_any(expr->resolved_type)){
|
||||
gen("(Any){");
|
||||
gen_pointer_to_lvalue(expr);
|
||||
gen_pointer(expr);
|
||||
gen(", %d}", expr->resolved_type->type_id);
|
||||
}
|
||||
else if(expr->kind == AST_IDENT && is_slice(decl_type)){
|
||||
|
||||
@@ -68,11 +68,12 @@ operand_const_rvalue(Value value){
|
||||
}
|
||||
|
||||
function Operand
|
||||
operand_lvalue(Ast_Type *type){
|
||||
operand_lvalue_set_flag_on_node(Ast_Type *type, Ast *ast){
|
||||
Operand result = {};
|
||||
result.type = type;
|
||||
result.is_const = false;
|
||||
result.is_lvalue = true;
|
||||
set_flag(ast->flags, AST_IS_LVALUE);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1204,14 +1205,14 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
||||
compiler_error(node->expr->pos, "Internal compiler error: type of array is marked as untyped somehow");
|
||||
|
||||
if(is_string(left.type)){
|
||||
return operand_lvalue(type_u8);
|
||||
return operand_lvalue_set_flag_on_node(type_u8, node);
|
||||
}
|
||||
|
||||
if(!is_array(left.type) && !is_pointer(left.type) && !is_slice(left.type)){
|
||||
compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %Q instead", typestring(left.type));
|
||||
}
|
||||
|
||||
return operand_lvalue(node->resolved_type);
|
||||
return operand_lvalue_set_flag_on_node(node->resolved_type, node);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
@@ -1334,7 +1335,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
||||
if(node->op == TK_Pointer){
|
||||
if(value.type->kind == TYPE_POINTER){
|
||||
node->resolved_type = value.type->base;
|
||||
return operand_lvalue(node->resolved_type);
|
||||
return operand_lvalue_set_flag_on_node(node->resolved_type, node);
|
||||
}
|
||||
else if(value.type->kind == TYPE_TYPE){
|
||||
if(!is_flag_set(flags, RESOLVE_TYPESPEC)){
|
||||
@@ -1349,7 +1350,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
||||
}
|
||||
else if(node->op == TK_Dereference){
|
||||
node->resolved_type = type_pointer(value.type);
|
||||
return operand_lvalue(node->resolved_type);
|
||||
return operand_lvalue_set_flag_on_node(node->resolved_type, node);
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -1411,7 +1412,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str
|
||||
compiler_error(node->pos, "Internal compiler error: Invalid type was passed to the compound expression, should have been an array, struct or slice");
|
||||
}
|
||||
|
||||
return operand_lvalue(type);
|
||||
return operand_lvalue_set_flag_on_node(type, node);
|
||||
|
||||
BREAK();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
/*
|
||||
Language enables implementing dynamic typing using operator overloads and
|
||||
the Any type. Any type is a bundle of typeid and a pointer to value.
|
||||
|
||||
Current semantics of the Any dictate that values that get assigned to
|
||||
Any values, they get implicitly converted to a pointer and a type.
|
||||
|
||||
a: Any = 10 // This sentence allocates 10 on the stack
|
||||
a: Any = a + 10 // This also allocates on stack
|
||||
a: Any = a // Does not allocate, takes pointer to a
|
||||
a: Any = array[1] // Does not allocate, takes pointer to value in array
|
||||
|
||||
The general picture you can take from this is that if we are referencing
|
||||
something it will take a pointer to it.
|
||||
If the operation results in a new value it will allocate the result on stack
|
||||
and make a pointer out of it. Have to be mindful of the lifetime.
|
||||
*/
|
||||
|
||||
|
||||
storage: [32]S64
|
||||
len : S64
|
||||
@@ -30,8 +48,8 @@ main :: (): int
|
||||
a: Any = 10
|
||||
b: Any = 20
|
||||
c := a + b
|
||||
// - [ ] DANGEROUS BUG! &(int64_t){32} creates a new value, we shouldn't do this with variables!!!
|
||||
// Assert(c.type == S64 && c == 30)
|
||||
// Assert(a+b+a==c+(5+5))
|
||||
|
||||
Assert(c.type == S64 && c == 30)
|
||||
Assert(a+b+a==c+(5+5))
|
||||
|
||||
return 0
|
||||
@@ -1,4 +1,4 @@
|
||||
#load "Multimedia.core"
|
||||
#import "Multimedia.core"
|
||||
|
||||
main :: (): int
|
||||
StartMultimedia(title = "Hello people!")
|
||||
|
||||
Reference in New Issue
Block a user