From 54426fdd69e2598515b84fc0a64256870ecc1c7e Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 9 Oct 2022 14:51:27 +0200 Subject: [PATCH] F32 is default float, operator overloads turn literals into default types --- README.md | 2 +- build.bat | 2 +- core_ast.cpp | 1 - core_codegen_c_language.cpp | 24 ++++++-------- core_parsing.cpp | 12 ++----- core_typechecking.cpp | 49 +++++++++++++---------------- examples/any_and_variadic_args.core | 6 ++-- examples/dynamic_typing.core | 22 ++++++++++++- examples/language_basics.core | 8 ++--- examples/raymarcher.core | 2 +- 10 files changed, 64 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 0b4a91c..89dbd4a 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ Dot :: (a: Vec3, b: Vec3): F32 ;; return a.x*b.x + a.y*b.y + a.z*b.z - [ ] Polymorphism - [x] C like void type - - [x] Any with it's dynamic typing + - [x] Dynamic typing using Any and operator overloading - [ ] Generics aka compile time polymorphism aka parametric polymorphism - [ ] Something akin to inheritence - [ ] Something akin to C unions or Rust's enums diff --git a/build.bat b/build.bat index 6e13611..f23a8be 100644 --- a/build.bat +++ b/build.bat @@ -2,5 +2,5 @@ pushd %~dp0 rem cl main.cpp -I.. user32.lib -clang core_main.cpp -O2 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib +clang core_main.cpp -O0 -Wall -Wno-unused-function -fno-exceptions -fdiagnostics-absolute-paths -g -o main.exe -Wl,user32.lib popd diff --git a/core_ast.cpp b/core_ast.cpp index 1be8162..cbded25 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -56,7 +56,6 @@ enum{ AST_STRICT = bit_flag(3), AST_AGGREGATE = bit_flag(4), AST_AGGREGATE_CHILD = bit_flag(5), - AST_ANY_VARGS = bit_flag(6), AST_ATOM = bit_flag(7), AST_FOREIGN = bit_flag(8), AST_DECL = bit_flag(9), diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index fd7b0a0..4f69a53 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -796,29 +796,25 @@ compile_to_c_code(){ #include #include -#ifndef Panic - #define Panic(...) (*(volatile int *)0 = 0) -#endif - #ifndef Assert -#define Assert(x) do{if(!(x))Panic();}while(0) + #define Assert(x) do{if(!(x))(*(volatile int *)0 = 0);}while(0) #endif #ifndef AssertMessage -#define AssertMessage(x,...) Assert(x) + #define AssertMessage(x,...) Assert(x) #endif #ifndef MemoryCopy -#define MemoryCopy MemoryCopy_ + #define MemoryCopy MemoryCopy_ -static void -MemoryCopy_(void *dst, void *src, size_t size){ - uint8_t *d = (uint8_t*)dst; - uint8_t *s = (uint8_t*)src; - for(size_t i = 0; i < size; i++){ - d[i] = s[i]; + static void + MemoryCopy_(void *dst, void *src, size_t size){ + uint8_t *d = (uint8_t*)dst; + uint8_t *s = (uint8_t*)src; + for(size_t i = 0; i < size; i++){ + d[i] = s[i]; + } } -} #endif #define BufferSize(x) (sizeof(x)/sizeof((x)[0])) diff --git a/core_parsing.cpp b/core_parsing.cpp index 5b3a669..7cfc01a 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -444,15 +444,9 @@ parse_lambda(Token *token){ Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL); param->name = name->intern_val; - if(token_match(TK_TwoDots)){ - set_flag(param->flags, AST_ANY_VARGS); - } - - else{ - param->typespec = parse_expr(); - if(token_match(TK_Assign)) - param->expr = parse_expr(); - } + param->typespec = parse_expr(); + if(token_match(TK_Assign)) + param->expr = parse_expr(); params.add(param); } diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 5b9726f..5c0cc9b 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -91,7 +91,7 @@ get_default_type_from_untyped(Ast_Type *type){ case TYPE_UNTYPED_INT: return type_s64; break; case TYPE_UNTYPED_BOOL: return type_bool; break; case TYPE_UNTYPED_STRING: return type_string; break; - case TYPE_UNTYPED_FLOAT: return type_f64; break; + case TYPE_UNTYPED_FLOAT: return type_f32; break; default: invalid_codepath; } return 0; @@ -891,24 +891,12 @@ resolve_lambda_type(Ast_Lambda *lambda){ } For(lambda->args){ - if(is_flag_set(it->flags, AST_ANY_VARGS)){ - if(it->expr) - compiler_error(it->pos, "Internal compiler error: Default value for .. multiple arguments should be null"); - if(it->typespec) - compiler_error(it->pos, "Internal compiler error: Typespec for .. multiple arguments should be null"); + Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL); + Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type, 0); + make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL); - it->type = type_slice(type_any, it); - } - - - else { - Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_BE_NULL); - Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type, 0); - make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL); - - it->type = type; - try_propagating_resolved_type_to_untyped_literals(it->expr, it->type); - } + it->type = type; + try_propagating_resolved_type_to_untyped_literals(it->expr, it->type); args.add(it->type); } @@ -1290,16 +1278,27 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str // Try finding a operator overload if(!is_const){ - U64 hash = calculate_hash_for_arguments(left.type, right.type); - Ast_Decl *operator_overload = resolve_operator_overload(node->parent_scope, left.type, right.type, node->pos, node->op, hash); + Value left_copy = left.value; + Value right_copy = right.value; + try_converting_untyped_to_default_type(&left_copy); + try_converting_untyped_to_default_type(&right_copy); + U64 hash = calculate_hash_for_arguments(left_copy.type, right_copy.type); + Ast_Decl *operator_overload = resolve_operator_overload(node->parent_scope, left_copy.type, right_copy.type, node->pos, node->op, hash); if(operator_overload){ proceed_to_default_operator_handler = false; if(operator_overload->lambda->ret.len != 1){ compiler_error(operator_overload->pos, "Operator overload is required to have exactly 1 return value"); } + left.value = left_copy; + right.value = right_copy; + node->resolved_type = operator_overload->type->func.ret; node->resolved_operator_overload = operator_overload; + + // We opt out early because we convert all literals to default type + // We don't need to propagate resolved type + return operand_rvalue(node->resolved_type); } } @@ -1529,15 +1528,9 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_and_const_str if(item){ set_flag(item->call_flags, CALL_INCLUDED); Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type, field_access_scope); - if(is_flag_set(lambda_arg->flags, AST_ANY_VARGS)){ - make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type->base, TYPE_AND_EXPR_REQUIRED); - item->resolved_type = expr.type; - } - else{ - make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED); - item->resolved_type = lambda_arg->type; - } + make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED); + item->resolved_type = lambda_arg->type; try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type); item->resolved_index = lambda->args.get_index(&lambda_arg); diff --git a/examples/any_and_variadic_args.core b/examples/any_and_variadic_args.core index 171d597..c4ed756 100644 --- a/examples/any_and_variadic_args.core +++ b/examples/any_and_variadic_args.core @@ -1,5 +1,5 @@ -VariadicArguments :: (string: *char, args: ..): Any +VariadicArguments :: (string: *char, args: []Any): Any return args[0] AnyArguments :: (values: []Any) @@ -39,8 +39,6 @@ IntegerToString :: (value: S64, result: *U8, base: S64): *U8 *ptr1++ = tmp_char return result - - StringToDouble :: (s: String): F64 sign: F64 = 1.0 i := 0 @@ -56,7 +54,7 @@ StringToDouble :: (s: String): F64 return 0 -FormatString :: (buffer: *U8, buffer_len: U64, string: String, args: ..) +FormatString :: (buffer: *U8, buffer_len: U64, string: String, args: []Any) // @todo(krzosa): Add consideration of buffer SIZE! Add some function to handle this OutStr or something arg_counter := 0 out_buffer_len := 0 diff --git a/examples/dynamic_typing.core b/examples/dynamic_typing.core index 6152040..f5557d2 100644 --- a/examples/dynamic_typing.core +++ b/examples/dynamic_typing.core @@ -8,9 +8,29 @@ len : S64 *(result.data->*S64) = *(a.data->*S64) + *(b.data->*S64) return result +"+" :: (a: Any, b: S64): Any + result: Any = storage[len++] + if a.type == S64 + *(result.data->*S64) = *(a.data->*S64) + b + return result + +"==" :: (a: Any, b: S64): Bool + result := false + if a.type == S64 + result = *(a.data->*S64) == b + return result + +"==" :: (a: Any, b: Any): Bool + result := false + if a.type == S64 && b.type == S64 + result = *(a.data->*S64) == *(b.data->*S64) + return result + main :: (): int a: Any = 10 b: Any = 20 c := a + b - Assert(c.type == S64 && *(c.data->*S64) == 30) + 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/language_basics.core b/examples/language_basics.core index 7b43ab1..19ef7df 100644 --- a/examples/language_basics.core +++ b/examples/language_basics.core @@ -29,13 +29,13 @@ main :: (): int // We can also tell the compiler to infer the type this_is_s64_by_default := 10 - this_is_f64_by_default := 10.1251 + this_is_f32_by_default := 10.1251 this_is_string_by_default := "Thing" // Reassigning values is exactly like in other languages this_is_s64_by_default = 20 this_is_string_by_default = "Other_Thing" - this_is_f64_by_default = 15.1255 + this_is_f32_by_default = 15.1255 // @todo: Add type_of operator!!! // Assert(type_of(this_is_string_by_default) == String) @@ -51,7 +51,7 @@ main :: (): int // When it comes to runtime variables it's a bit different // To do this we need a cast - combining_types := this_is_s64_by_default->F64 + this_is_f64_by_default + combining_types := this_is_s64_by_default->F32 + this_is_f32_by_default Assert(s64val == 0 && s32val == 0 && s16val == 0 && s8val == 0 && intval == 0 && u64val == 0 && u32val == 0 && u16val == 0 && u8val == 0 && f64val == 0 && f32val == 0) Assert(string_val[0] == 'S') @@ -59,7 +59,7 @@ main :: (): int Assert(signed_variable == 10 && unsigned_variable == 10) Assert(INT_VALUE == 10) Assert(FLOAT_VALUE == 124.125) - Assert(this_is_f64_by_default == 15.1255) + Assert(this_is_f32_by_default == 15.1255) Assert(combining_types == 15.1255 + 20) // Compound statements diff --git a/examples/raymarcher.core b/examples/raymarcher.core index 6a5cb4b..25a764f 100644 --- a/examples/raymarcher.core +++ b/examples/raymarcher.core @@ -141,7 +141,7 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS window_dc := GetDC(window) bitmap := CreateBitmap(screen_size) - requested_time_per_frame := 1.0 / 60.0 + requested_time_per_frame: F64 = 1.0 / 60.0 frame_start_time := Time() frame_number: S64 for AppIsRunning