F32 is default float, operator overloads turn literals into default types
This commit is contained in:
@@ -114,7 +114,7 @@ Dot :: (a: Vec3, b: Vec3): F32 ;; return a.x*b.x + a.y*b.y + a.z*b.z
|
|||||||
|
|
||||||
- [ ] Polymorphism
|
- [ ] Polymorphism
|
||||||
- [x] C like void type
|
- [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
|
- [ ] Generics aka compile time polymorphism aka parametric polymorphism
|
||||||
- [ ] Something akin to inheritence
|
- [ ] Something akin to inheritence
|
||||||
- [ ] Something akin to C unions or Rust's enums
|
- [ ] Something akin to C unions or Rust's enums
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
pushd %~dp0
|
pushd %~dp0
|
||||||
rem cl main.cpp -I.. user32.lib
|
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
|
popd
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ enum{
|
|||||||
AST_STRICT = bit_flag(3),
|
AST_STRICT = bit_flag(3),
|
||||||
AST_AGGREGATE = bit_flag(4),
|
AST_AGGREGATE = bit_flag(4),
|
||||||
AST_AGGREGATE_CHILD = bit_flag(5),
|
AST_AGGREGATE_CHILD = bit_flag(5),
|
||||||
AST_ANY_VARGS = bit_flag(6),
|
|
||||||
AST_ATOM = bit_flag(7),
|
AST_ATOM = bit_flag(7),
|
||||||
AST_FOREIGN = bit_flag(8),
|
AST_FOREIGN = bit_flag(8),
|
||||||
AST_DECL = bit_flag(9),
|
AST_DECL = bit_flag(9),
|
||||||
|
|||||||
@@ -796,12 +796,8 @@ compile_to_c_code(){
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifndef Panic
|
|
||||||
#define Panic(...) (*(volatile int *)0 = 0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Assert
|
#ifndef Assert
|
||||||
#define Assert(x) do{if(!(x))Panic();}while(0)
|
#define Assert(x) do{if(!(x))(*(volatile int *)0 = 0);}while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef AssertMessage
|
#ifndef AssertMessage
|
||||||
|
|||||||
@@ -444,15 +444,9 @@ parse_lambda(Token *token){
|
|||||||
Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL);
|
Ast_Decl *param = ast_new(Ast_Decl, AST_VAR, name, AST_DECL);
|
||||||
param->name = name->intern_val;
|
param->name = name->intern_val;
|
||||||
|
|
||||||
if(token_match(TK_TwoDots)){
|
|
||||||
set_flag(param->flags, AST_ANY_VARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
else{
|
|
||||||
param->typespec = parse_expr();
|
param->typespec = parse_expr();
|
||||||
if(token_match(TK_Assign))
|
if(token_match(TK_Assign))
|
||||||
param->expr = parse_expr();
|
param->expr = parse_expr();
|
||||||
}
|
|
||||||
|
|
||||||
params.add(param);
|
params.add(param);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ get_default_type_from_untyped(Ast_Type *type){
|
|||||||
case TYPE_UNTYPED_INT: return type_s64; break;
|
case TYPE_UNTYPED_INT: return type_s64; break;
|
||||||
case TYPE_UNTYPED_BOOL: return type_bool; break;
|
case TYPE_UNTYPED_BOOL: return type_bool; break;
|
||||||
case TYPE_UNTYPED_STRING: return type_string; 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;
|
default: invalid_codepath;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -891,24 +891,12 @@ resolve_lambda_type(Ast_Lambda *lambda){
|
|||||||
}
|
}
|
||||||
|
|
||||||
For(lambda->args){
|
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");
|
|
||||||
|
|
||||||
it->type = type_slice(type_any, it);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
else {
|
|
||||||
Ast_Type *type = resolve_typespec(it->typespec, AST_CANT_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);
|
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);
|
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
||||||
|
|
||||||
it->type = type;
|
it->type = type;
|
||||||
try_propagating_resolved_type_to_untyped_literals(it->expr, it->type);
|
try_propagating_resolved_type_to_untyped_literals(it->expr, it->type);
|
||||||
}
|
|
||||||
|
|
||||||
args.add(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
|
// Try finding a operator overload
|
||||||
if(!is_const){
|
if(!is_const){
|
||||||
U64 hash = calculate_hash_for_arguments(left.type, right.type);
|
Value left_copy = left.value;
|
||||||
Ast_Decl *operator_overload = resolve_operator_overload(node->parent_scope, left.type, right.type, node->pos, node->op, hash);
|
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){
|
if(operator_overload){
|
||||||
proceed_to_default_operator_handler = false;
|
proceed_to_default_operator_handler = false;
|
||||||
if(operator_overload->lambda->ret.len != 1){
|
if(operator_overload->lambda->ret.len != 1){
|
||||||
compiler_error(operator_overload->pos, "Operator overload is required to have exactly 1 return value");
|
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_type = operator_overload->type->func.ret;
|
||||||
node->resolved_operator_overload = operator_overload;
|
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){
|
if(item){
|
||||||
set_flag(item->call_flags, CALL_INCLUDED);
|
set_flag(item->call_flags, CALL_INCLUDED);
|
||||||
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type, field_access_scope);
|
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);
|
make_sure_value_is_compatible_with_type(item->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED);
|
||||||
item->resolved_type = lambda_arg->type;
|
item->resolved_type = lambda_arg->type;
|
||||||
}
|
|
||||||
|
|
||||||
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
|
try_propagating_resolved_type_to_untyped_literals(item->item, item->resolved_type);
|
||||||
item->resolved_index = lambda->args.get_index(&lambda_arg);
|
item->resolved_index = lambda->args.get_index(&lambda_arg);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
VariadicArguments :: (string: *char, args: ..): Any
|
VariadicArguments :: (string: *char, args: []Any): Any
|
||||||
return args[0]
|
return args[0]
|
||||||
|
|
||||||
AnyArguments :: (values: []Any)
|
AnyArguments :: (values: []Any)
|
||||||
@@ -39,8 +39,6 @@ IntegerToString :: (value: S64, result: *U8, base: S64): *U8
|
|||||||
*ptr1++ = tmp_char
|
*ptr1++ = tmp_char
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StringToDouble :: (s: String): F64
|
StringToDouble :: (s: String): F64
|
||||||
sign: F64 = 1.0
|
sign: F64 = 1.0
|
||||||
i := 0
|
i := 0
|
||||||
@@ -56,7 +54,7 @@ StringToDouble :: (s: String): F64
|
|||||||
|
|
||||||
return 0
|
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
|
// @todo(krzosa): Add consideration of buffer SIZE! Add some function to handle this OutStr or something
|
||||||
arg_counter := 0
|
arg_counter := 0
|
||||||
out_buffer_len := 0
|
out_buffer_len := 0
|
||||||
|
|||||||
@@ -8,9 +8,29 @@ len : S64
|
|||||||
*(result.data->*S64) = *(a.data->*S64) + *(b.data->*S64)
|
*(result.data->*S64) = *(a.data->*S64) + *(b.data->*S64)
|
||||||
return result
|
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
|
main :: (): int
|
||||||
a: Any = 10
|
a: Any = 10
|
||||||
b: Any = 20
|
b: Any = 20
|
||||||
c := a + b
|
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
|
return 0
|
||||||
@@ -29,13 +29,13 @@ main :: (): int
|
|||||||
|
|
||||||
// We can also tell the compiler to infer the type
|
// We can also tell the compiler to infer the type
|
||||||
this_is_s64_by_default := 10
|
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"
|
this_is_string_by_default := "Thing"
|
||||||
|
|
||||||
// Reassigning values is exactly like in other languages
|
// Reassigning values is exactly like in other languages
|
||||||
this_is_s64_by_default = 20
|
this_is_s64_by_default = 20
|
||||||
this_is_string_by_default = "Other_Thing"
|
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!!!
|
// @todo: Add type_of operator!!!
|
||||||
// Assert(type_of(this_is_string_by_default) == String)
|
// 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
|
// When it comes to runtime variables it's a bit different
|
||||||
// To do this we need a cast
|
// 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(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')
|
Assert(string_val[0] == 'S')
|
||||||
@@ -59,7 +59,7 @@ main :: (): int
|
|||||||
Assert(signed_variable == 10 && unsigned_variable == 10)
|
Assert(signed_variable == 10 && unsigned_variable == 10)
|
||||||
Assert(INT_VALUE == 10)
|
Assert(INT_VALUE == 10)
|
||||||
Assert(FLOAT_VALUE == 124.125)
|
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)
|
Assert(combining_types == 15.1255 + 20)
|
||||||
|
|
||||||
// Compound statements
|
// Compound statements
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ WinMain :: (hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: LPSTR, nS
|
|||||||
window_dc := GetDC(window)
|
window_dc := GetDC(window)
|
||||||
bitmap := CreateBitmap(screen_size)
|
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_start_time := Time()
|
||||||
frame_number: S64
|
frame_number: S64
|
||||||
for AppIsRunning
|
for AppIsRunning
|
||||||
|
|||||||
Reference in New Issue
Block a user