diff --git a/core_ast.cpp b/core_ast.cpp index 19e8158..cd74d2f 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -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{ diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index 4f69a53..fa83ef2 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -271,13 +271,19 @@ enum { }; function void -gen_pointer_to_lvalue(Ast_Expr *expr){ - gen("&("); - gen_simple_decl(expr->resolved_type); - gen(")"); - gen("{"); - gen_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 @@ -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)){ diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 5c0cc9b..f55a118 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -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(); } diff --git a/examples/dynamic_typing.core b/examples/dynamic_typing.core index 8decd1f..778e740 100644 --- a/examples/dynamic_typing.core +++ b/examples/dynamic_typing.core @@ -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 \ No newline at end of file diff --git a/examples/using_multimedia.core b/examples/using_multimedia.core index 40fbdbb..90c3099 100644 --- a/examples/using_multimedia.core +++ b/examples/using_multimedia.core @@ -1,4 +1,4 @@ -#load "Multimedia.core" +#import "Multimedia.core" main :: (): int StartMultimedia(title = "Hello people!")