void pointer duck typing
This commit is contained in:
13
ccodegen.cpp
13
ccodegen.cpp
@@ -680,10 +680,13 @@ parse_all_modules(){
|
|||||||
function Ast_Module *
|
function Ast_Module *
|
||||||
add_module(Intern_String filename){
|
add_module(Intern_String filename){
|
||||||
For(pctx->modules){
|
For(pctx->modules){
|
||||||
if(it->name == filename)
|
if(it->name == filename){
|
||||||
|
log_info("Returning registered module: %Q\n", filename);
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info("Adding module: %Q\n", filename);
|
||||||
Ast_Module *result = ast_module(filename);
|
Ast_Module *result = ast_module(filename);
|
||||||
register_ast_file(result->name, result, true);
|
register_ast_file(result->name, result, true);
|
||||||
pctx->modules.add(result);
|
pctx->modules.add(result);
|
||||||
@@ -722,7 +725,7 @@ begin_compilation(){
|
|||||||
global F64 generating_time_begin;
|
global F64 generating_time_begin;
|
||||||
global F64 generating_time_end;
|
global F64 generating_time_end;
|
||||||
function String
|
function String
|
||||||
end_compilation(){
|
get_compilation_result(){
|
||||||
generating_time_begin = os_time();
|
generating_time_begin = os_time();
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
@@ -806,7 +809,11 @@ typedef struct String{
|
|||||||
}
|
}
|
||||||
|
|
||||||
String string_result = string_flatten(pctx->perm, &pctx->gen);
|
String string_result = string_flatten(pctx->perm, &pctx->gen);
|
||||||
exp_destroy(pctx->heap);
|
|
||||||
generating_time_end = os_time();
|
generating_time_end = os_time();
|
||||||
return string_result;
|
return string_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
compiler_cleanup(){
|
||||||
|
exp_destroy(pctx->heap);
|
||||||
|
}
|
||||||
|
|||||||
38
main.cpp
38
main.cpp
@@ -41,12 +41,15 @@ want to export all the symbols, we can namespace them optionally.
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@todo
|
@todo
|
||||||
|
[ ] - Better error messages when type difference
|
||||||
|
[ ] - Casting pointers to and from void should be implicit
|
||||||
|
[ ] - Kilobyte, Megabyte, Gigabyte
|
||||||
|
[ ] - Mixing loads and imports leads to code duplication, is that what we want???
|
||||||
[ ] - Fix field access, cant cast, cant index
|
[ ] - Fix field access, cant cast, cant index
|
||||||
[ ] - Add parent_scope to Ast_Type
|
[ ] - Add parent_scope to Ast_Type
|
||||||
[ ] - Switch
|
[ ] - Switch
|
||||||
[ ] - Some way to take slice of data
|
[ ] - Some way to take slice of data
|
||||||
[ ] - Optional function renaming in codegen
|
[ ] - Optional function renaming in codegen
|
||||||
[ ] - Multiple return values
|
|
||||||
[ ] - Using in structs to embed members, then casting offsets to that embedded member
|
[ ] - Using in structs to embed members, then casting offsets to that embedded member
|
||||||
|
|
||||||
[ ] - Comma notation when declaring variables thing1, thing2: S32
|
[ ] - Comma notation when declaring variables thing1, thing2: S32
|
||||||
@@ -71,6 +74,7 @@ want to export all the symbols, we can namespace them optionally.
|
|||||||
[ ] - Conditional compilation #if
|
[ ] - Conditional compilation #if
|
||||||
|
|
||||||
@donzo
|
@donzo
|
||||||
|
[x] - Multiple return values
|
||||||
[x] - Add c string
|
[x] - Add c string
|
||||||
[-] - Should compound resolution use an algorithm to reorder compounds to initialize all fields in order
|
[-] - Should compound resolution use an algorithm to reorder compounds to initialize all fields in order
|
||||||
[x] - slices should be properly displayed in debugger
|
[x] - slices should be properly displayed in debugger
|
||||||
@@ -157,36 +161,19 @@ int main(int argument_count, char **arguments){
|
|||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if(argument_count > 1){
|
|
||||||
Scratch scratch;
|
|
||||||
String name = string_fmt(scratch, "%s.kl", arguments[1]);
|
|
||||||
String c_filename = string_fmt(scratch, "%s.c", arguments[1]);
|
|
||||||
|
|
||||||
String run_program = string_fmt(scratch, "%s.exe", arguments[1]);
|
|
||||||
|
|
||||||
Array<String> files = {scratch};
|
|
||||||
files.add(name);
|
|
||||||
String result = compile_files(files);
|
|
||||||
|
|
||||||
assert(f);
|
|
||||||
|
|
||||||
|
|
||||||
F64 begin = os_time();
|
|
||||||
system((const char *)compiler_call.str);
|
|
||||||
printf("\nCompile time: %f", os_time() - begin);
|
|
||||||
|
|
||||||
system((const char *)run_program.str);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
emit_line_directives = true;
|
emit_line_directives = true;
|
||||||
|
String program_name = "main.kl"_s;
|
||||||
|
if(argument_count > 1){
|
||||||
|
program_name = string_from_cstring(arguments[1]);
|
||||||
|
}
|
||||||
|
|
||||||
F64 total_time = os_time();
|
F64 total_time = os_time();
|
||||||
begin_compilation();
|
begin_compilation();
|
||||||
Ast_Module *module = add_module(pctx->intern("main.kl"_s));
|
Ast_Module *module = add_module(pctx->intern(program_name));
|
||||||
parse_all_modules();
|
parse_all_modules();
|
||||||
assert(module);
|
assert(module);
|
||||||
resolve_everything_in_module(module);
|
resolve_everything_in_module(module);
|
||||||
String result = end_compilation();
|
String result = get_compilation_result();
|
||||||
assert(os_write_file("program.c"_s, result));
|
assert(os_write_file("program.c"_s, result));
|
||||||
{
|
{
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -200,6 +187,5 @@ int main(int argument_count, char **arguments){
|
|||||||
printf("\nparsing = %f", parsing_time_end - parsing_time_begin);
|
printf("\nparsing = %f", parsing_time_end - parsing_time_begin);
|
||||||
printf("\nresolving = %f", resolving_time_end - resolving_time_begin);
|
printf("\nresolving = %f", resolving_time_end - resolving_time_begin);
|
||||||
printf("\ngeneratin = %f", generating_time_end - generating_time_begin);
|
printf("\ngeneratin = %f", generating_time_end - generating_time_begin);
|
||||||
#endif
|
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -675,11 +675,13 @@ register_ast_file(Intern_String filename, Ast_Module *module, B32 global_implici
|
|||||||
Ast_File *file = 0;
|
Ast_File *file = 0;
|
||||||
For(module->all_loaded_files){
|
For(module->all_loaded_files){
|
||||||
if(it->filename == filename){
|
if(it->filename == filename){
|
||||||
|
log_info("%Q :: Returning registered file: %Q\n", module->name, filename);
|
||||||
file = it;
|
file = it;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!file){
|
if(!file){
|
||||||
|
log_info("%Q :: Registering file: %Q\n", module->name, filename);
|
||||||
AST_NEW(File, FILE, 0, 0);
|
AST_NEW(File, FILE, 0, 0);
|
||||||
file = result;
|
file = result;
|
||||||
file->filename = filename;
|
file->filename = filename;
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
Os :: #import "os.kl"
|
Os :: #import "os.kl"
|
||||||
|
|
||||||
SizeU :: #strict U64
|
SizeU :: #strict U64
|
||||||
|
|
||||||
|
arena_di: U64
|
||||||
|
|
||||||
Arena :: struct
|
Arena :: struct
|
||||||
|
di: U64 // @debug_id
|
||||||
memory: Os.Memory
|
memory: Os.Memory
|
||||||
alignment: U64
|
alignment: U64
|
||||||
len: U64
|
len: U64
|
||||||
|
|
||||||
|
ADDITIONAL_COMMIT_SIZE :: 1024*1024
|
||||||
|
DEFAULT_RESERVE_SIZE :: 1024*1024*1024
|
||||||
|
DEFAULT_ALIGNMENT :: 8
|
||||||
|
|
||||||
clamp_top_sizeu :: (val: SizeU, max: SizeU): SizeU
|
clamp_top_sizeu :: (val: SizeU, max: SizeU): SizeU
|
||||||
if val > max
|
if val > max
|
||||||
return max
|
return max
|
||||||
@@ -22,3 +28,22 @@ get_align_offset :: (size: SizeU, align: SizeU): SizeU
|
|||||||
align_up :: (size: SizeU, align: SizeU): SizeU
|
align_up :: (size: SizeU, align: SizeU): SizeU
|
||||||
result := size + get_align_offset(size, align)
|
result := size + get_align_offset(size, align)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
arena_init :: (a: *Arena)
|
||||||
|
a.memory = Os.reserve(a.DEFAULT_RESERVE_SIZE)
|
||||||
|
a.alignment = a.DEFAULT_ALIGNMENT
|
||||||
|
a.di = arena_di++
|
||||||
|
|
||||||
|
arena_push_size :: (a: *Arena, size: SizeU): *void
|
||||||
|
generous_size := size + a.alignment
|
||||||
|
if a.len + generous_size > a.memory.commit
|
||||||
|
if a.memory.reserve == 0
|
||||||
|
arena_init(a)
|
||||||
|
result := Os.commit(&a.memory, generous_size + a.ADDITIONAL_COMMIT_SIZE)
|
||||||
|
assert(result == true)
|
||||||
|
a.len = align_up(a.len, a.alignment)
|
||||||
|
assert(a.memory.reserve > a.len + a.memory.commit)
|
||||||
|
result: *void = a.memory.data + a.len
|
||||||
|
a.len += size
|
||||||
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#load "os.kl"
|
#load "os.kl"
|
||||||
|
|
||||||
question_mark16 :: 0x003f
|
question_mark16 :: 0x003f
|
||||||
String16 :: struct;; str: *U16; len: S64
|
|
||||||
String32 :: struct;; str: *U32; len: S64
|
String32 :: struct;; str: *U32; len: S64
|
||||||
UTF32_Result :: struct
|
UTF32_Result :: struct
|
||||||
out_str: U32
|
out_str: U32
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ release :: (m: *Memory)
|
|||||||
m.commit = 0
|
m.commit = 0
|
||||||
m.reserve = 0
|
m.reserve = 0
|
||||||
|
|
||||||
|
String16 :: struct;; str: *U16; len: S64
|
||||||
print :: (string: String16)
|
print :: (string: String16)
|
||||||
handle := GetStdHandle(STD_OUTPUT_HANDLE)
|
handle := GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
WriteConsoleW(handle, (string.str)->*void, string.len->DWORD, 0, 0)
|
WriteConsoleW(handle, (string.str)->*void, string.len->DWORD, 0, 0)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Type *new_type){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
make_sure_types_are_compatible(Token *pos, Value *a, Value *b){
|
make_sure_types_are_compatible_for_constant_evaluation(Token *pos, Value *a, Value *b){
|
||||||
if((is_pointer(a->type) && is_int(b->type)) || (is_pointer(b->type) && is_int(a->type))){
|
if((is_pointer(a->type) && is_int(b->type)) || (is_pointer(b->type) && is_int(a->type))){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){
|
|||||||
}
|
}
|
||||||
else if(is_typed(a->type) && is_typed(b->type)){
|
else if(is_typed(a->type) && is_typed(b->type)){
|
||||||
if(a->type != b->type){
|
if(a->type != b->type){
|
||||||
fail: compiler_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type));
|
fail: compiler_error(pos, "Type mismatch in make_sure_types_are_compatible_for_constant_evaluation - left: %s right: %s", docname(a->type), docname(b->type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
|
|||||||
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
||||||
compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
||||||
|
|
||||||
make_sure_types_are_compatible(pos, &a, &b);
|
make_sure_types_are_compatible_for_constant_evaluation(pos, &a, &b);
|
||||||
|
|
||||||
B32 result = 0;
|
B32 result = 0;
|
||||||
if(is_const){
|
if(is_const){
|
||||||
@@ -132,7 +132,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
|
|||||||
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
||||||
compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
||||||
|
|
||||||
make_sure_types_are_compatible(pos, &a, &b);
|
make_sure_types_are_compatible_for_constant_evaluation(pos, &a, &b);
|
||||||
|
|
||||||
Value result = {};
|
Value result = {};
|
||||||
result.type = a.type;
|
result.type = a.type;
|
||||||
@@ -286,6 +286,12 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Type *typ
|
|||||||
assert(type);
|
assert(type);
|
||||||
expr->type = type;
|
expr->type = type;
|
||||||
}
|
}
|
||||||
|
else if(is_void_pointer(type) && is_pointer(expr->type)){
|
||||||
|
expr->type = type;
|
||||||
|
}
|
||||||
|
else if(is_pointer(type) && is_void_pointer(expr->type)){
|
||||||
|
expr->type = type;
|
||||||
|
}
|
||||||
else if(is_untyped(expr->type)){
|
else if(is_untyped(expr->type)){
|
||||||
expr->value = convert_untyped_to_typed(pos, expr->value, type);
|
expr->value = convert_untyped_to_typed(pos, expr->value, type);
|
||||||
}
|
}
|
||||||
@@ -723,7 +729,7 @@ resolve_field_access(Ast_Expr *node, Ast_Scope *context){
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ast_Type *type = decl->type;
|
Ast_Type *type = decl->type;
|
||||||
if(type == type_type && is_enum(decl->type_val)) type = decl->type_val;
|
if(type == type_type && (is_enum(decl->type_val) || is_struct(decl->type_val))) type = decl->type_val;
|
||||||
if(current) current->resolved_type = type;
|
if(current) current->resolved_type = type;
|
||||||
if(is_pointer(type)) type = type->base;
|
if(is_pointer(type)) type = type->base;
|
||||||
|
|
||||||
|
|||||||
@@ -286,4 +286,5 @@ type_complete(Ast_Type *type){
|
|||||||
function void
|
function void
|
||||||
init_type(){
|
init_type(){
|
||||||
type_pointer_to_char = type_pointer(type_char);
|
type_pointer_to_char = type_pointer(type_char);
|
||||||
|
type_pointer_to_void = type_pointer(type_void);
|
||||||
}
|
}
|
||||||
5
types.h
5
types.h
@@ -198,9 +198,10 @@ global Ast_Type type__int = {TYPE_INT, sizeof(int), __alignof(int)};
|
|||||||
global Ast_Type *type_char = &type__char;
|
global Ast_Type *type_char = &type__char;
|
||||||
global Ast_Type *type_int = &type__int;
|
global Ast_Type *type_int = &type__int;
|
||||||
global Ast_Type *type_pointer_to_char; // Needs to be inited at runtime
|
global Ast_Type *type_pointer_to_char; // Needs to be inited at runtime
|
||||||
|
global Ast_Type *type_void = &type__void;
|
||||||
|
global Ast_Type *type_pointer_to_void; // Needs to be inited at runtime
|
||||||
|
|
||||||
global Ast_Type *type_type = &type__type;
|
global Ast_Type *type_type = &type__type;
|
||||||
global Ast_Type *type_void = &type__void;
|
|
||||||
global Ast_Type *type_string = &type__string;
|
global Ast_Type *type_string = &type__string;
|
||||||
global Ast_Type *type_bool = &type__bool;
|
global Ast_Type *type_bool = &type__bool;
|
||||||
|
|
||||||
@@ -232,6 +233,8 @@ force_inline B32 is_slice(Ast_Type *a){return a->kind == TYPE_SLICE;}
|
|||||||
force_inline B32 is_tuple(Ast_Type *a){return a->kind == TYPE_TUPLE;}
|
force_inline B32 is_tuple(Ast_Type *a){return a->kind == TYPE_TUPLE;}
|
||||||
force_inline B32 is_enum(Ast_Type *a){return a->kind == TYPE_ENUM;}
|
force_inline B32 is_enum(Ast_Type *a){return a->kind == TYPE_ENUM;}
|
||||||
force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;}
|
force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;}
|
||||||
|
force_inline B32 is_void(Ast_Type *a){return a->kind == TYPE_VOID;}
|
||||||
|
force_inline B32 is_void_pointer(Ast_Type *a){return a == type_pointer_to_void;}
|
||||||
force_inline B32 is_string(Ast_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING || a == type_pointer_to_char;}
|
force_inline B32 is_string(Ast_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING || a == type_pointer_to_char;}
|
||||||
force_inline B32 is_untyped_int(Ast_Type *a){return a->kind == TYPE_UNTYPED_INT;}
|
force_inline B32 is_untyped_int(Ast_Type *a){return a->kind == TYPE_UNTYPED_INT;}
|
||||||
force_inline B32 is_typed_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8);}
|
force_inline B32 is_typed_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8);}
|
||||||
|
|||||||
Reference in New Issue
Block a user