diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index 61e10ea..abcebf1 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -354,6 +354,7 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ gen_expr(node->right); return true; } + else if(node->op == TK_Arrow){ gen("("); gen("("); @@ -364,11 +365,22 @@ gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){ return true; } - if(!token_is_assign(node->op)) gen("("); - gen_expr(node->left); - gen("%s", name(node->op)); - gen_expr(node->right); - if(!token_is_assign(node->op)) gen(")"); + else if(node->resolved_operator_overload){ + gen("%Q(", node->resolved_operator_overload->unique_name); + gen_expr(node->left); + gen(", "); + gen_expr(node->right); + gen(")"); + } + + else { + if(!token_is_assign(node->op)) gen("("); + gen_expr(node->left); + gen("%s", name(node->op)); + gen_expr(node->right); + if(!token_is_assign(node->op)) gen(")"); + } + BREAK(); } diff --git a/core_compiler.cpp b/core_compiler.cpp index 3db3768..6335ac4 100644 --- a/core_compiler.cpp +++ b/core_compiler.cpp @@ -1,14 +1,4 @@ -global F64 generating_time_begin; -global F64 generating_time_end; -global F64 resolving_time_begin; -global F64 resolving_time_end; -global F64 total_time; -global F64 init_ctx_time_begin; -global F64 init_ctx_time_end; -//----------------------------------------------------------------------------- -// Constructors -//----------------------------------------------------------------------------- function void lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){ l->arena = token_string_arena; diff --git a/core_globals.cpp b/core_globals.cpp index 72f989e..50610df 100644 --- a/core_globals.cpp +++ b/core_globals.cpp @@ -115,3 +115,14 @@ global Ast_Type *untyped_string = &type__untyped_string; global Ast_Type *untyped_bool = &type__untyped_bool; global Ast_Type *untyped_int = &type__untyped_int; global Ast_Type *untyped_float = &type__untyped_float; + +//----------------------------------------------------------------------------- +// Time records +//----------------------------------------------------------------------------- +global F64 generating_time_begin; +global F64 generating_time_end; +global F64 resolving_time_begin; +global F64 resolving_time_end; +global F64 total_time; +global F64 init_ctx_time_begin; +global F64 init_ctx_time_end; diff --git a/core_main.cpp b/core_main.cpp index 29d3ce0..9a1c1d8 100644 --- a/core_main.cpp +++ b/core_main.cpp @@ -1,10 +1,12 @@ /* +- [ ] Cleanup + - [ ] Remove tuple stuff or cleanup, in the future might replace it with a better implementation + - [ ] '.' Operator doesn't handle expressions inside the dot chain, no good, so casts don't work + - [ ] Basic - [ ] Introduce List to reduce heap allocations and make it more arena friendly, can we get rid of heap completly? - [ ] Detecting if return was called - - [ ] '.' Operator doesn't handle expressions inside the dot chain, no good, so casts don't work - - [ ] Combining casts with . operator - [ ] Builtin data structures - [ ] Strings probably should have len() instead of string.len @@ -289,4 +291,5 @@ int main(int argument_count, char **arguments){ compile_file(it.absolute_path, COMPILE_AND_RUN); } } + __debugbreak(); } diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 2e40be9..a829ea1 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -881,6 +881,33 @@ map_operator_to_intern(Token_Kind op){ } } +function String +map_operator_intern_to_identifier_name(Intern_String op){ + if(op.str == op_add.str) return "ADD"_s; + if(op.str == op_mul.str) return "MUL"_s; + if(op.str == op_div.str) return "DIV"_s; + if(op.str == op_sub.str) return "SUB"_s; + if(op.str == op_and.str) return "AND"_s; + if(op.str == op_bitand.str) return "BITAND"_s; + if(op.str == op_or.str) return "OR"_s; + if(op.str == op_bitor.str) return "BITOR"_s; + if(op.str == op_xor.str) return "XOR"_s; + if(op.str == op_equals.str) return "EQUALS"_s; + if(op.str == op_not_equals.str) return "NOT_EQUALS"_s; + if(op.str == op_lesser_then_or_equal.str) return "LESSER_THEN_OR_EQUAL"_s; + if(op.str == op_greater_then_or_equal.str) return "GREATER_THEN_OR_EQUAL"_s; + if(op.str == op_lesser_then.str) return "LESSER_THEN"_s; + if(op.str == op_greater_then.str) return "GREATER_THEN"_s; + if(op.str == op_left_shift.str) return "LEFT_SHIFT"_s; + if(op.str == op_right_shift.str) return "RIGHT_SHIFT"_s; + if(op.str == op_not.str) return "NOT"_s; + if(op.str == op_neg.str) return "NEG"_s; + if(op.str == op_decrement.str) return "DECREMENT"_s; + if(op.str == op_increment.str) return "INCREMENT"_s; + invalid_codepath; + return "INVALID_OPERATOR_OVERLOAD"_s; +} + function Ast_Decl * resolve_operator_overload(Ast_Scope *scope, Token *pos, Token_Kind op, U64 argument_hash){ Intern_String name = map_operator_to_intern(op); @@ -924,7 +951,9 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ search.search_only_current_scope = true; scope_search(&search); if(search.results.len != 0){ - compiler_error(search.results.data[0]->pos, decl->pos, "[%s] is already defined", decl->name.str); + if(!is_flag_set(decl->flags, AST_OPERATOR_OVERLOAD)){ + compiler_error(search.results.data[0]->pos, decl->pos, "[%s] is already defined", decl->name.str); + } } scope->decls.add(decl); @@ -1605,8 +1634,29 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ Operand left = resolve_expr(node->left, AST_CANT_BE_NULL); Operand right = resolve_expr(node->right, AST_CANT_BE_NULL); B32 is_const = left.is_const && right.is_const; - Value value = eval_binary(node->pos, node->op, left.value, right.value, is_const); - node->resolved_type = value.type; + B32 proceed_to_default_operator_handler = true; + + // 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, 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"); + } + + node->resolved_type = operator_overload->type->func.ret; + node->resolved_operator_overload = operator_overload; + } + } + + // Not found or constant then go for default option + Value value = {}; + if(proceed_to_default_operator_handler){ + value = eval_binary(node->pos, node->op, left.value, right.value, is_const); + node->resolved_type = value.type; + } if(is_const){ // We don't need to propagte types for const values cause we are rewritting them @@ -1614,17 +1664,9 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){ return operand_const_rvalue(value); } else { - - - U64 hash = calculate_hash_for_arguments(left.type, right.type); - Ast_Decl *operator_overload = resolve_operator_overload(node->parent_scope, node->pos, node->op, hash); - if(operator_overload){ - __debugbreak(); - } - - try_propagating_resolved_type_to_untyped_literals(node->left, value.type); - try_propagating_resolved_type_to_untyped_literals(node->right, value.type); - return operand_rvalue(value.type); + try_propagating_resolved_type_to_untyped_literals(node->left, node->resolved_type); + try_propagating_resolved_type_to_untyped_literals(node->right, node->resolved_type); + return operand_rvalue(node->resolved_type); } } BREAK(); @@ -1900,12 +1942,17 @@ resolve_decl(Ast_Decl *ast){ try_resolving_lambda_scope(&result, lambda, node->type); node->value = result.value; + Scratch scratch; node->unique_name = node->name; if(!is_flag_set(node->expr->flags, AST_FOREIGN)){ - Scratch scratch; node->unique_name = pctx->intern(string_fmt(scratch, "%Q%d", node->name, pctx->lambda_ids++)); } + if(is_flag_set(node->flags, AST_OPERATOR_OVERLOAD)){ + String n = map_operator_intern_to_identifier_name(node->name); + node->unique_name = pctx->intern(string_fmt(scratch, "CORE_OPERATOR_%Q%d", n, pctx->lambda_ids++)); + } + BREAK(); } diff --git a/examples/function_overloading.kl b/examples/function_overloading.kl deleted file mode 100644 index 0463fc4..0000000 --- a/examples/function_overloading.kl +++ /dev/null @@ -1,14 +0,0 @@ - -Vec3 :: struct;; x: F32; y: F32; z: F32 -"+" :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x+b.x, a.y+b.y, a.z+b.z} - - -main :: (): int - a := Vec3{1,1,1} - b := Vec3{2,3,4} - c := a + b - Assert(a.x == 3) - Assert(a.y == 4) - Assert(a.z == 5) - - return 0 \ No newline at end of file diff --git a/examples/raymarcher.kl b/examples/raymarcher.kl index 4f4bad6..4121c2a 100644 --- a/examples/raymarcher.kl +++ b/examples/raymarcher.kl @@ -39,7 +39,7 @@ Raymarcher_Update :: () hit := true p: Vec3 for i := 0, i < 255, i+=1 - p = Vec3_Add(eye, Vec3_MulF32(dir, t)) + p = eye + dir*t distance := SphereSDF(p) if distance < Epsilon @@ -57,22 +57,22 @@ Raymarcher_Update :: () SphereSDF({p.x, p.y, p.z + Epsilon}) - SphereSDF({p.x, p.y, p.z - Epsilon}), }) - light_to_point := Vec3_Normalize(Vec3_Sub(LightPos, p)) - eye_to_point := Vec3_Normalize(Vec3_Sub(eye, p)) + light_to_point := Vec3_Normalize(LightPos - p) + eye_to_point := Vec3_Normalize(eye - p) reflected_light := Vec3_Normalize(Vec3_Reflect(Vec3_Negate(light_to_point), normal)) ambient :: 0.2 diffuse := Vec3_Dot(normal, light_to_point) - color := Vec3_MulF32(ambient_color, ambient) + color := ambient_color*ambient if diffuse > Epsilon - color = Vec3_Add(color, Vec3_MulF32(diffuse_color, diffuse)) + color = color + diffuse_color*diffuse specular := Vec3_Dot(reflected_light, eye_to_point) if specular > Epsilon specular = specular*specular*specular*specular - color = Vec3_Add(color, Vec3_MulF32(specular_color, specular*0.2)) - color = Vec3_MulF32(color, light_intensity) + color = color + specular_color*specular*0.2 + color = color * light_intensity // Gamma correction color.x = sqrtf(color.x) diff --git a/modules/math.kl b/modules/math.kl index afd5619..334d77e 100644 --- a/modules/math.kl +++ b/modules/math.kl @@ -16,19 +16,14 @@ Vec3_Cross :: (a: Vec3, b: Vec3): Vec3 Vec3_Normalize :: (a: Vec3): Vec3 length := Vec3_Length(a) - result := Vec3{ - a.x / length, - a.y / length, - a.z / length, - } + result := a / length return result Vec3_Reflect :: (a: Vec3, normal: Vec3): Vec3 an := Vec3_Dot(a, normal)*2 - result := Vec3_Sub(a, Vec3_MulF32(a, an)) + result := a - a * an return result - Vec3_ConvertToARGB :: (a: Vec3): U32 a.x = F32_Clamp(0, a.x, 1) a.y = F32_Clamp(0, a.y, 1) @@ -42,11 +37,12 @@ Vec3_ConvertToARGB :: (a: Vec3): U32 Vec3_Length :: (a: Vec3): F32 ;; return sqrtf(a.x*a.x + a.y*a.y + a.z*a.z) Vec3_Negate :: (a: Vec3): Vec3 ;; return Vec3{-a.x, -a.y, -a.z} Vec3_Dot :: (a: Vec3, b: Vec3): F32 ;; return a.x*b.x + a.y*b.y + a.z*b.z -Vec3_Mul :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x*b.x, a.y*b.y, a.z*b.z} -Vec3_MulF32 :: (a: Vec3, b: F32) : Vec3 ;; return Vec3{a.x*b, a.y*b, a.z*b} -Vec3_Add :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x+b.x, a.y+b.y, a.z+b.z} -Vec3_Div :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x/b.x, a.y/b.y, a.z/b.z} -Vec3_Sub :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x-b.x, a.y-b.y, a.z-b.z} +"*" :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x*b.x, a.y*b.y, a.z*b.z} +"*" :: (a: Vec3, b: F32) : Vec3 ;; return Vec3{a.x*b, a.y*b, a.z*b} +"+" :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x+b.x, a.y+b.y, a.z+b.z} +"/" :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x/b.x, a.y/b.y, a.z/b.z} +"/" :: (a: Vec3, b: F32): Vec3 ;; return Vec3{a.x/b, a.y/b, a.z/b} +"-" :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x-b.x, a.y-b.y, a.z-b.z} F32_Clamp :: (min: F32, value: F32, max: F32): F32 if value > max;; return max