Compound arrays

This commit is contained in:
Krzosa Karol
2022-06-11 09:54:35 +02:00
parent bcddf7f721
commit b76b9c605a
8 changed files with 236 additions and 156 deletions

26
ast.cpp
View File

@@ -60,17 +60,17 @@ struct Ast{
Ast_Flag flags; Ast_Flag flags;
}; };
struct Ast_Resolved_Type; struct Ast_Type;
struct Ast_Expr:Ast{ }; struct Ast_Expr:Ast{ };
#define VALUE_FIELDS \ #define VALUE_FIELDS \
Ast_Resolved_Type *type; \ Ast_Type *type; \
union{ \ union{ \
bool bool_val; \ bool bool_val; \
F64 f64_val; \ F64 f64_val; \
Intern_String intern_val; \ Intern_String intern_val; \
BigInt big_int_val;\ BigInt big_int_val;\
Ast_Resolved_Type *type_val; \ Ast_Type *type_val; \
}; };
#define INLINE_VALUE_FIELDS union{Value value; struct{VALUE_FIELDS};} #define INLINE_VALUE_FIELDS union{Value value; struct{VALUE_FIELDS};}
struct Value{VALUE_FIELDS}; struct Value{VALUE_FIELDS};
@@ -82,7 +82,7 @@ struct Ast_Atom: Ast_Expr{
}; };
struct Ast_Call_Item: Ast_Expr{ struct Ast_Call_Item: Ast_Expr{
Ast_Atom *name; Ast_Atom *name; // for calls only name, for compounds name | index
Ast_Expr *item; Ast_Expr *item;
Ast_Expr *index; Ast_Expr *index;
}; };
@@ -93,27 +93,27 @@ struct Ast_Call: Ast_Expr{
Ast_Expr *typespec; Ast_Expr *typespec;
}; };
Array<Ast_Call_Item *> exprs; Array<Ast_Call_Item *> exprs;
Ast_Resolved_Type *type; Ast_Type *type;
}; };
struct Ast_Unary: Ast_Expr{ struct Ast_Unary: Ast_Expr{
Token_Kind op; Token_Kind op;
Ast_Expr *expr; Ast_Expr *expr;
Ast_Resolved_Type *type; Ast_Type *type;
U64 padding[2]; // For folding constants into atoms U64 padding[2]; // For folding constants into atoms
}; };
struct Ast_Cast: Ast_Expr{ struct Ast_Cast: Ast_Expr{
Ast_Expr *expr; Ast_Expr *expr;
Ast_Expr *typespec; Ast_Expr *typespec;
Ast_Resolved_Type *before_type; Ast_Type *before_type;
Ast_Resolved_Type *after_type; Ast_Type *after_type;
}; };
struct Ast_Index: Ast_Expr{ struct Ast_Index: Ast_Expr{
Ast_Expr *expr; Ast_Expr *expr;
Ast_Expr *index; Ast_Expr *index;
Ast_Resolved_Type *original_type; Ast_Type *original_type;
}; };
struct Ast_Binary: Ast_Expr{ struct Ast_Binary: Ast_Expr{
@@ -121,7 +121,7 @@ struct Ast_Binary: Ast_Expr{
Ast_Expr *left; Ast_Expr *left;
Ast_Expr *right; Ast_Expr *right;
Ast_Resolved_Type *type; Ast_Type *type;
}; };
// Problem: We are parsing out of order, in the middle of parsing a function // Problem: We are parsing out of order, in the middle of parsing a function
@@ -157,13 +157,13 @@ struct Ast_Lambda : Ast_Expr {
Array<Ast_Decl *> args; Array<Ast_Decl *> args;
Ast_Expr *ret; Ast_Expr *ret;
Ast_Scope *scope; Ast_Scope *scope;
Ast_Resolved_Type *type; Ast_Type *type;
}; };
struct Ast_Array: Ast_Expr{ struct Ast_Array: Ast_Expr{
Ast_Expr *base; Ast_Expr *base;
Ast_Expr *expr; Ast_Expr *expr;
Ast_Resolved_Type *type; Ast_Type *type;
}; };
/* /*
@@ -466,7 +466,7 @@ ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
} }
function Ast_Decl * function Ast_Decl *
ast_type(Token *pos, Intern_String name, Ast_Resolved_Type *type){ ast_type(Token *pos, Intern_String name, Ast_Type *type){
AST_NEW(Decl, TYPE, pos, AST_DECL); AST_NEW(Decl, TYPE, pos, AST_DECL);
result->type = type_type; result->type = type_type;
result->type_val = type; result->type_val = type;

View File

@@ -28,7 +28,7 @@ gen_line(Ast *node){
// 4 Add type name on the left side // 4 Add type name on the left side
function void function void
gen_simple_decl_prefix(Ast_Resolved_Type *ast){ gen_simple_decl_prefix(Ast_Type *ast){
switch(ast->kind){ switch(ast->kind){
case TYPE_POINTER: gen_simple_decl_prefix(ast->base); gen("*"); break; case TYPE_POINTER: gen_simple_decl_prefix(ast->base); gen("*"); break;
case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break; case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break;
@@ -46,7 +46,7 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){
} }
function void function void
gen_simple_decl_postfix(Ast_Resolved_Type *ast){ gen_simple_decl_postfix(Ast_Type *ast){
switch(ast->kind){ switch(ast->kind){
case TYPE_POINTER: gen_simple_decl_postfix(ast->base); break; case TYPE_POINTER: gen_simple_decl_postfix(ast->base); break;
case TYPE_ARRAY: case TYPE_ARRAY:
@@ -62,7 +62,7 @@ gen_simple_decl_postfix(Ast_Resolved_Type *ast){
} }
function void function void
gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){ gen_simple_decl(Ast_Type *ast, Intern_String name = {}){
if(ast->kind == TYPE_LAMBDA) { if(ast->kind == TYPE_LAMBDA) {
gen_simple_decl_prefix(ast->func.ret); gen_simple_decl_prefix(ast->func.ret);
gen("(*%s)(", name.str); gen("(*%s)(", name.str);
@@ -117,7 +117,7 @@ enum {
}; };
function void function void
gen_var(Intern_String name, Ast_Resolved_Type *type, Ast_Expr *expr, B32 emit_value){ gen_var(Intern_String name, Ast_Type *type, Ast_Expr *expr, B32 emit_value){
gen_simple_decl(type, name); gen_simple_decl(type, name);
if(emit_value == DONT_EMIT_VALUE){ if(emit_value == DONT_EMIT_VALUE){
@@ -211,7 +211,7 @@ gen_expr(Ast_Expr *ast){
CASE(CAST, Cast){ CASE(CAST, Cast){
gen("("); gen("(");
gen("("); gen("(");
gen_simple_decl(node->after_type, {}); gen_simple_decl(node->after_type);
gen(")"); gen(")");
gen_expr(node->expr); gen_expr(node->expr);
gen(")"); gen(")");
@@ -234,6 +234,19 @@ gen_expr(Ast_Expr *ast){
BREAK(); BREAK();
} }
CASE(COMPOUND, Call){
gen("(");
gen_simple_decl(node->type);
gen(")");
gen("{");
For(node->exprs){
gen_expr(it->item);
if(!node->exprs.is_last(&it)) gen(", ");
}
gen("}");
BREAK();
}
invalid_default_case; invalid_default_case;
} }
} }

View File

@@ -22,7 +22,7 @@ Boolean: Bool = true
// Compound expressions // Compound expressions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
array1: [4]S64 = {1,2,3,4} array1: [4]S64 = {1,2,3,4}
imp_array := [5]S64{1,2}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Pointers // Pointers

View File

@@ -218,7 +218,7 @@ constexpr S128 U8_max() {return {0, U8MAX};}
constexpr S128 U8_min() {return {};} constexpr S128 U8_min() {return {};}
function B32 function B32
is_out_of_bounds(S128 value, Ast_Resolved_Type *type){ is_out_of_bounds(S128 value, Ast_Type *type){
#define BOUNDS_CASE(T) case TYPE_##T: return (value < T##_min()) || (value > T##_max()) #define BOUNDS_CASE(T) case TYPE_##T: return (value < T##_min()) || (value > T##_max())
switch(type->kind){ switch(type->kind){
BOUNDS_CASE(S8); BOUNDS_CASE(S8);

View File

@@ -77,6 +77,7 @@ Expr:
@todo @todo
[ ] - Remodel compound from call to {}
[ ] - Switch [ ] - Switch
[ ] - Add c string [ ] - Add c string
[ ] - Some way to take slice of data [ ] - Some way to take slice of data
@@ -86,14 +87,7 @@ Expr:
[ ] - Array of inferred size [ ] - Array of inferred size
[ ] - Add single line lambda expressions [ ] - Add single line lambda expressions
[ ] - Ternary operator [ ] - Ternary operator
[ ] - Remodel compound from call to {} [ ] - Disable ability to parse inner structs, functions, constants etc. ?
[ ] - Scope
[ ] - Field access rewrite
[ ] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix
[ ] - Order independent constants in structs
[ ] - Fix recursive lambdas in structs
[ ] - Fixing access to functions/structs, in C we cant have functons inside of structs / functions so we need to rewrite the tree
[ ] - Write up on order independent declarations [ ] - Write up on order independent declarations
[ ] - Casting to basic types by call S64(x) [ ] - Casting to basic types by call S64(x)
@@ -111,6 +105,12 @@ Expr:
[ ] - Conditional compilation #if [ ] - Conditional compilation #if
@donzo @donzo
[x] - Scope
[x] - Field access rewrite
[-] - Constants embeded in structs should be able to refer to other constants in that namespace without prefix
[-] - Order independent constants in structs
[-] - Fix recursive lambdas in structs
[-] - Fixing access to functions/structs, in C we cant have functons inside of structs / functions so we need to rewrite the tree
[x] - Emitting #line [x] - Emitting #line
[x] - Making sure debugger works [x] - Making sure debugger works
[x] - We need ++ -- operators [x] - We need ++ -- operators
@@ -203,13 +203,13 @@ int main(int argument_count, char **arguments){
#endif #endif
Scratch scratch; Scratch scratch;
Array<String> files = {scratch}; Array<String> files = {scratch};
files.add("lambdas.kl"_s); // files.add("lambdas.kl"_s);
files.add("order1.kl"_s); // files.add("order1.kl"_s);
files.add("order2.kl"_s); // files.add("order2.kl"_s);
files.add("new_types.kl"_s); // files.add("new_types.kl"_s);
files.add("enums.kl"_s); // files.add("enums.kl"_s);
files.add("globals.kl"_s); files.add("globals.kl"_s);
files.add("euler.kl"_s); // files.add("euler.kl"_s);
String result = compile_files(files); String result = compile_files(files);
printf("%s", result.str); printf("%s", result.str);
__debugbreak(); __debugbreak();

View File

@@ -16,7 +16,7 @@ check_value_bounds(Token *pos, Value *a){
} }
function Value function Value
convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){ convert_untyped_to_typed(Token *pos, Value a, Ast_Type *new_type){
assert(new_type); assert(new_type);
if(a.type == 0) return a; if(a.type == 0) return a;
if(is_typed(a.type)) return a; if(is_typed(a.type)) return a;
@@ -193,7 +193,7 @@ digit_count(const Value *a){
function void function void
eval_unary(Token *pos, Token_Kind op, Operand *operand){ eval_unary(Token *pos, Token_Kind op, Operand *operand){
Value *a = &operand->value; Value *a = &operand->value;
Ast_Resolved_Type *type = a->type; Ast_Type *type = a->type;
if(!is_numeric(type)) if(!is_numeric(type))
compiler_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type)); compiler_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type));
@@ -268,7 +268,7 @@ enum{
}; };
function void function void
make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Resolved_Type *type, U64 debug_flag){ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Type *type, U64 debug_flag){
if(type == expr->type){ if(type == expr->type){
assert(type); assert(type);
assert(expr->type); assert(expr->type);
@@ -359,7 +359,7 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
} }
function void function void
insert_type_into_package(Ast_Package *p, String name, Ast_Resolved_Type *type){ insert_type_into_package(Ast_Package *p, String name, Ast_Type *type){
Intern_String string = pctx->intern(name); Intern_String string = pctx->intern(name);
Ast_Decl *decl = ast_type(&null_token, string, type); Ast_Decl *decl = ast_type(&null_token, string, type);
decl->parent_scope = p; decl->parent_scope = p;
@@ -384,12 +384,12 @@ insert_builtin_types_into_package(Ast_Package *p){
insert_type_into_package(p, "F64"_s, type_f64); insert_type_into_package(p, "F64"_s, type_f64);
} }
function Ast_Resolved_Type * function Ast_Type *
resolve_typespec(Ast_Expr *ast, Resolve_Flag flags){ resolve_typespec(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context = 0){
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) if(!ast && is_flag_set(flags, AST_CAN_BE_NULL))
return 0; return 0;
Operand resolved = resolve_expr(ast, flags); Operand resolved = resolve_expr(ast, flags, compound_context);
if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE)) if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE))
type_complete(resolved.type); type_complete(resolved.type);
if(resolved.type != type_type) if(resolved.type != type_type)
@@ -398,14 +398,14 @@ resolve_typespec(Ast_Expr *ast, Resolve_Flag flags){
} }
function Operand function Operand
resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags){ resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags, Ast_Type *compound_context = 0){
if(!expr){ if(!expr){
if(flags == AST_CAN_BE_NULL) if(flags == AST_CAN_BE_NULL)
return {}; return {};
else compiler_error(0, "Compiler error: Null expression"); else compiler_error(0, "Compiler error: Null expression");
} }
Operand op = resolve_expr(expr, flags); Operand op = resolve_expr(expr, flags, compound_context);
if(!is_bool(op.type)){ if(!is_bool(op.type)){
compiler_error(expr->pos, "Expected type [Bool] got instead type %s :: %s", docname(op.type), error); compiler_error(expr->pos, "Expected type [Bool] got instead type %s :: %s", docname(op.type), error);
} }
@@ -414,8 +414,8 @@ resolve_and_require_bool(const char *error, Ast_Expr *expr, Resolve_Flag flags){
} }
function Operand function Operand
require_const_int(Ast_Expr *expr, Resolve_Flag flags){ require_const_int(Ast_Expr *expr, Resolve_Flag flags, Ast_Type *compound_context = 0){
Operand op = resolve_expr(expr, flags); Operand op = resolve_expr(expr, flags, compound_context);
if(expr == 0 && flags) if(expr == 0 && flags)
return op; return op;
@@ -433,7 +433,7 @@ require_const_int(Ast_Expr *expr, Resolve_Flag flags){
// @note: Ret is return value of function passed down the stack // @note: Ret is return value of function passed down the stack
// to check if type matches // to check if type matches
function void function void
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ resolve_stmt(Ast *ast, Ast_Type *ret){
if(!ast) return; if(!ast) return;
assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE); assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE);
@@ -496,15 +496,15 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
} }
} }
function Ast_Resolved_Type * function Ast_Type *
resolve_lambda_type(Ast_Lambda *lambda){ resolve_lambda_type(Ast_Lambda *lambda){
Scratch scratch; Scratch scratch;
Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret, AST_CANT_BE_NULL); Ast_Type *ret_type = resolve_typespec(lambda->ret, AST_CANT_BE_NULL);
Array<Ast_Resolved_Type *> args = {scratch}; Array<Ast_Type *> args = {scratch};
For(lambda->args){ For(lambda->args){
Ast_Resolved_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); Operand default_value = resolve_expr(it->expr, AST_CAN_BE_NULL, type);
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;
args.add(type); args.add(type);
@@ -514,7 +514,7 @@ resolve_lambda_type(Ast_Lambda *lambda){
} }
function void function void
try_resolving_lambda_scope(Operand *op, Ast_Lambda *lambda, Ast_Resolved_Type *lambda_type){ try_resolving_lambda_scope(Operand *op, Ast_Lambda *lambda, Ast_Type *lambda_type){
if(lambda->scope){ if(lambda->scope){
For(lambda->args){ For(lambda->args){
insert_into_scope(lambda->scope, it); insert_into_scope(lambda->scope, it);
@@ -534,8 +534,8 @@ try_resolving_lambda_scope(Operand *op, Ast_Lambda *lambda, Ast_Resolved_Type *l
function Operand function Operand
resolve_cast(Ast_Cast *node){ resolve_cast(Ast_Cast *node){
Operand expr = resolve_expr(node->expr, AST_CANT_BE_NULL); Operand expr = resolve_expr(node->expr, AST_CANT_BE_NULL);
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CANT_BE_NULL); Ast_Type *type = resolve_typespec(node->typespec, AST_CANT_BE_NULL);
Ast_Resolved_Type *original_type = expr.type; Ast_Type *original_type = expr.type;
node->before_type = expr.type; node->before_type = expr.type;
switch(expr.type->kind){ switch(expr.type->kind){
@@ -580,6 +580,43 @@ resolve_cast(Ast_Cast *node){
return expr; return expr;
} }
function void
resolve_compound_array(Ast_Call *node, Ast_Type *type){
Ast_Type *item_type = type->arr.base;
S64 size = type->arr.size;
if(node->exprs.len > size)
compiler_error(node->pos, "Too many items in compound expression, expected: %lld got: %lld", size, node->exprs.len);
S64 default_counter = 0;
For(node->exprs){
if(it->name)
compiler_error(it->pos, "Array doesn't have named fields");
if(it->index){
default_counter = -1;
Operand op = require_const_int(it->index, AST_CANT_BE_NULL);
S64 i = bigint_as_signed(&op.value.big_int_val); // @todo: what happens when big num is here???
if(i >= size)
compiler_error(it->pos, "Index %lld is out of range of array of size %lld", i, size);
}
else{
if(default_counter == -1)
compiler_error(it->pos, "Mixing expicit indexes and default is illegal");
}
Operand item = resolve_expr(it->item, AST_CANT_BE_NULL);
make_sure_value_is_compatible_with_type(it->pos, &item, item_type, TYPE_AND_EXPR_REQUIRED);
}
}
function void
resolve_compound_struct(Ast_Call *node, Ast_Type *type){
}
global Ast_Scope *field_access_scope; // @memes global Ast_Scope *field_access_scope; // @memes
function Operand function Operand
@@ -605,7 +642,7 @@ resolve_field_access(Ast_Expr *node, Ast_Scope *context){
field_access_scope = context; field_access_scope = context;
Operand op = resolve_expr(node, AST_CANT_BE_NULL); Operand op = resolve_expr(node, AST_CANT_BE_NULL);
Ast_Resolved_Type *type = op.type; Ast_Type *type = op.type;
if(op.type == type_type && is_enum(op.type_val)) type = op.type_val; if(op.type == type_type && is_enum(op.type_val)) type = op.type_val;
if(current) current->type = type; if(current) current->type = type;
if(is_pointer(type)) type = type->base; if(is_pointer(type)) type = type->base;
@@ -626,7 +663,7 @@ resolve_field_access(Ast_Expr *node, Ast_Scope *context){
} }
function Operand function Operand
resolve_expr(Ast_Expr *ast, Resolve_Flag flags){ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {}; if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {};
assert(is_flag_set(ast->flags, AST_EXPR)); assert(is_flag_set(ast->flags, AST_EXPR));
assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE); assert(ast->parent_scope->kind == AST_SCOPE || ast->parent_scope->kind == AST_PACKAGE);
@@ -769,6 +806,34 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags){
BREAK(); BREAK();
} }
CASE(COMPOUND, Call){
Operand op = resolve_expr(node->typespec, AST_CAN_BE_NULL);
Ast_Type *type = op.type;
if(type){
if(type != type_type)
compiler_error(node->pos, "Expected type [Type] got instead %s", docname(type));
type = op.type_val;
}
if(!type)
type = compound_context;
if(!type)
compiler_error(node->pos, "Couldn't infer type of compound expression");
type_complete(type);
node->type = type;
if(is_array(type)){
resolve_compound_array(node, type);
}
else if(is_struct(type)){
resolve_compound_struct(node, type);
}
return operand_lvalue(type);
BREAK();
}
CASE(CALL, Call){ CASE(CALL, Call){
Operand name = resolve_expr(node->name, AST_CANT_BE_NULL); Operand name = resolve_expr(node->name, AST_CANT_BE_NULL);
if(name.type->kind != TYPE_LAMBDA) if(name.type->kind != TYPE_LAMBDA)
@@ -807,7 +872,7 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags){
if(item){ if(item){
set_flag(item->flags, AST_ITEM_INCLUDED); set_flag(item->flags, AST_ITEM_INCLUDED);
Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL); Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL, lambda_arg->type);
make_sure_value_is_compatible_with_type(node->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED); make_sure_value_is_compatible_with_type(node->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED);
items.add(item); items.add(item);
} }
@@ -868,6 +933,8 @@ resolve_decl(Ast_Decl *ast){
} }
CASE(CONST, Decl){ CASE(CONST, Decl){
// @warning: if in the future we add type here then pass it to resolve expr for
// compound
Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL); Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL);
if(!op.is_const){ if(!op.is_const){
compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration"); compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration");
@@ -883,8 +950,8 @@ resolve_decl(Ast_Decl *ast){
} }
CASE(VAR, Decl){ CASE(VAR, Decl){
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE); Ast_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE);
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL); Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL, type);
assert(op.type != 0 || type != 0); assert(op.type != 0 || type != 0);
make_sure_value_is_compatible_with_type(node->pos, &op, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL); make_sure_value_is_compatible_with_type(node->pos, &op, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL);
@@ -893,7 +960,7 @@ resolve_decl(Ast_Decl *ast){
} }
CASE(ENUM, Decl){ CASE(ENUM, Decl){
Ast_Resolved_Type *type_of_enum = resolve_typespec(node->typespec, AST_CAN_BE_NULL); Ast_Type *type_of_enum = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
node->type = type_type; node->type = type_type;
node->type_val = type_enum(node, type_of_enum); node->type_val = type_enum(node, type_of_enum);

View File

@@ -16,7 +16,7 @@ FLAG32(Search_Flag){
SEARCH_ALSO_FOR_PACKAGE = bit_flag(2), SEARCH_ALSO_FOR_PACKAGE = bit_flag(2),
}; };
function Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags); function Operand resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context = 0);
function void resolve_decl(Ast_Decl *ast); function void resolve_decl(Ast_Decl *ast);
function Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0); function Ast_Decl *resolve_name(Ast_Scope *parent_scope, Token *pos, Intern_String name, Search_Flag search_flags = 0);
@@ -34,7 +34,7 @@ operand(Ast_Decl *sym){
} }
function Operand function Operand
operand_type(Ast_Resolved_Type *type){ operand_type(Ast_Type *type){
Operand result = {}; Operand result = {};
result.type = type_type; result.type = type_type;
result.is_const = true; result.is_const = true;
@@ -64,7 +64,7 @@ operand_str(Intern_String intern_val){
} }
function Operand function Operand
operand_lambda(Ast_Resolved_Type *type){ operand_lambda(Ast_Type *type){
Operand result = {}; Operand result = {};
result.type = type; result.type = type;
result.is_const = true; result.is_const = true;
@@ -81,7 +81,7 @@ operand_const_rvalue(Value value){
} }
function Operand function Operand
operand_lvalue(Ast_Resolved_Type *type){ operand_lvalue(Ast_Type *type){
Operand result = {}; Operand result = {};
result.type = type; result.type = type;
result.is_const = false; result.is_const = false;
@@ -90,7 +90,7 @@ operand_lvalue(Ast_Resolved_Type *type){
} }
function Operand function Operand
operand_rvalue(Ast_Resolved_Type *type){ operand_rvalue(Ast_Type *type){
Operand result = {}; Operand result = {};
result.type = type; result.type = type;
result.is_const = false; result.is_const = false;
@@ -101,25 +101,25 @@ operand_rvalue(Ast_Resolved_Type *type){
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Hash consed types // Hash consed types
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function Ast_Resolved_Type * function Ast_Type *
type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){ type_new(Allocator *allocator, Ast_Type_Kind kind, SizeU size, SizeU align){
Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type, AF_ZeroMemory); Ast_Type *result = exp_alloc_type(allocator, Ast_Type, AF_ZeroMemory);
result->kind = kind; result->kind = kind;
result->size = size; result->size = size;
result->align = align; result->align = align;
return result; return result;
} }
function Ast_Resolved_Type * function Ast_Type *
type_copy(Allocator *a, Ast_Resolved_Type *type){ type_copy(Allocator *a, Ast_Type *type){
Ast_Resolved_Type *result = exp_alloc_type(a, Ast_Resolved_Type); Ast_Type *result = exp_alloc_type(a, Ast_Type);
memory_copy(result, type, sizeof(Ast_Resolved_Type)); memory_copy(result, type, sizeof(Ast_Type));
return result; return result;
} }
function Ast_Resolved_Type * function Ast_Type *
type_pointer(Ast_Resolved_Type *base){ type_pointer(Ast_Type *base){
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base); Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, (void *)base);
if(!result){ if(!result){
result = type_new(pctx->perm, TYPE_POINTER, pointer_size, pointer_align); result = type_new(pctx->perm, TYPE_POINTER, pointer_size, pointer_align);
result->base = base; result->base = base;
@@ -129,15 +129,15 @@ type_pointer(Ast_Resolved_Type *base){
return result; return result;
} }
function Ast_Resolved_Type * function Ast_Type *
type_array(Ast_Resolved_Type *base, B32 size_present, S64 size){ type_array(Ast_Type *base, B32 size_present, S64 size){
if(!size_present){ if(!size_present){
size = ARRAY_SIZE_INFERRED; size = ARRAY_SIZE_INFERRED;
} }
U64 hash_base = hash_ptr(base); U64 hash_base = hash_ptr(base);
U64 hash = hash_mix(hash_base, hash_u64(size)); U64 hash = hash_mix(hash_base, hash_u64(size));
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash); Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
if(result){ if(result){
assert(result->kind == TYPE_ARRAY); assert(result->kind == TYPE_ARRAY);
assert(result->arr.size == size); assert(result->arr.size == size);
@@ -153,11 +153,11 @@ type_array(Ast_Resolved_Type *base, B32 size_present, S64 size){
return result; return result;
} }
function Ast_Resolved_Type * function Ast_Type *
type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){ type_lambda(Ast *ast, Ast_Type *ret, Array<Ast_Type *> args){
U64 hash = hash_ptr(ret); U64 hash = hash_ptr(ret);
For(args) hash = hash_mix(hash, hash_ptr(it)); For(args) hash = hash_mix(hash, hash_ptr(it));
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash); Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
if(result){ if(result){
assert(result->kind == TYPE_LAMBDA); assert(result->kind == TYPE_LAMBDA);
@@ -176,27 +176,27 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
} }
function Ast_Resolved_Type * function Ast_Type *
type_enum(Ast_Decl *ast, Ast_Resolved_Type *type){ type_enum(Ast_Decl *ast, Ast_Type *type){
if(!type){ if(!type){
type = type_s64; type = type_s64;
} }
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_ENUM, type->size, type->align); Ast_Type *result = type_new(pctx->perm, TYPE_ENUM, type->size, type->align);
result->base = type; result->base = type;
result->ast = ast; result->ast = ast;
return result; return result;
} }
function Ast_Resolved_Type * function Ast_Type *
type_incomplete(Ast *ast){ type_incomplete(Ast *ast){
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0); Ast_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);
result->ast = ast; result->ast = ast;
return result; return result;
} }
function void function void
type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){ type_struct_complete(Ast_Type *type, Ast_Decl *node){
assert(node->kind == AST_STRUCT); assert(node->kind == AST_STRUCT);
// @todo: compute size, alignement, offset !!! // @todo: compute size, alignement, offset !!!
// @note: resolve all the struct members first // @note: resolve all the struct members first
@@ -212,7 +212,7 @@ type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){
} }
function void function void
type_complete(Ast_Resolved_Type *type){ type_complete(Ast_Type *type){
if(!type) { if(!type) {
return; return;
} }

136
types.h
View File

@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Resolved Types // Resolved Types
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
enum Ast_Resolved_Type_Kind{ enum Ast_Type_Kind{
TYPE_NONE, TYPE_NONE,
TYPE_COMPLETING, TYPE_COMPLETING,
TYPE_INCOMPLETE, TYPE_INCOMPLETE,
@@ -49,7 +49,7 @@ enum Ast_Resolved_Type_Kind{
#define CASE_UNTYPED case TYPE_UNTYPED_INT: case TYPE_UNTYPED_BOOL: case TYPE_UNTYPED_FLOAT: case TYPE_UNTYPED_STRING #define CASE_UNTYPED case TYPE_UNTYPED_INT: case TYPE_UNTYPED_BOOL: case TYPE_UNTYPED_FLOAT: case TYPE_UNTYPED_STRING
const char *type_names[] = { const char *type_names[] = {
"[Invalid Ast_Resolved_Type]", "[Invalid Ast_Type]",
"[Completing]", "[Completing]",
"[Incomplete]", "[Incomplete]",
@@ -81,24 +81,24 @@ const char *type_names[] = {
}; };
struct Ast; struct Ast;
struct Ast_Resolved_Type; struct Ast_Type;
struct Ast_Resolved_Member{ struct Ast_Resolved_Member{
Ast_Resolved_Type *type; Ast_Type *type;
Intern_String name; Intern_String name;
U64 offset; U64 offset;
}; };
#define ARRAY_SIZE_INFERRED (-1) #define ARRAY_SIZE_INFERRED (-1)
struct Ast_Resolved_Type{ struct Ast_Type{
Ast_Resolved_Type_Kind kind; Ast_Type_Kind kind;
SizeU size; SizeU size;
SizeU align; SizeU align;
Ast *ast; Ast *ast;
union{ union{
Ast_Resolved_Type *base; Ast_Type *base;
struct{ struct{
Ast_Resolved_Type *base; Ast_Type *base;
S64 size; S64 size;
// @note: if you have array with size "[32]" // @note: if you have array with size "[32]"
// you still want to pass that array into // you still want to pass that array into
@@ -110,16 +110,16 @@ struct Ast_Resolved_Type{
Array<Ast_Resolved_Member> members; Array<Ast_Resolved_Member> members;
}agg; }agg;
struct{ struct{
Ast_Resolved_Type *ret; Ast_Type *ret;
Array<Ast_Resolved_Type *> args; Array<Ast_Type *> args;
}func; }func;
}; };
}; };
function const char * function const char *
docname(Ast_Resolved_Type *type){ docname(Ast_Type *type){
switch(type->kind){ switch(type->kind){
case TYPE_NONE: return "[Invalid Ast_Resolved_Type]"; case TYPE_NONE: return "[Invalid Ast_Type]";
case TYPE_COMPLETING: return "[Completing]"; case TYPE_COMPLETING: return "[Completing]";
case TYPE_INCOMPLETE: return "[Incomplete]"; case TYPE_INCOMPLETE: return "[Incomplete]";
case TYPE_UNTYPED_BOOL: return "[Untyped_Bool]"; case TYPE_UNTYPED_BOOL: return "[Untyped_Bool]";
@@ -152,7 +152,7 @@ docname(Ast_Resolved_Type *type){
} }
function const char * function const char *
name(Ast_Resolved_Type *type){ name(Ast_Type *type){
switch(type->kind){ switch(type->kind){
case TYPE_VOID: return "void"; case TYPE_VOID: return "void";
case TYPE_BOOL: return "Bool"; case TYPE_BOOL: return "Bool";
@@ -177,81 +177,81 @@ name(Ast_Resolved_Type *type){
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
const SizeU pointer_size = sizeof(SizeU); const SizeU pointer_size = sizeof(SizeU);
const SizeU pointer_align = __alignof(SizeU); const SizeU pointer_align = __alignof(SizeU);
global Ast_Resolved_Type type__void = {TYPE_VOID}; global Ast_Type type__void = {TYPE_VOID};
global Ast_Resolved_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)}; global Ast_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
global Ast_Resolved_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)}; global Ast_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
global Ast_Resolved_Type type__type = {TYPE_TYPE}; global Ast_Type type__type = {TYPE_TYPE};
global Ast_Resolved_Type type__f32 = {TYPE_F32, sizeof(F32), __alignof(F32)}; global Ast_Type type__f32 = {TYPE_F32, sizeof(F32), __alignof(F32)};
global Ast_Resolved_Type type__f64 = {TYPE_F64, sizeof(F64), __alignof(F64)}; global Ast_Type type__f64 = {TYPE_F64, sizeof(F64), __alignof(F64)};
global Ast_Resolved_Type type__s8 = {TYPE_S8, sizeof(S8), __alignof(S8)}; global Ast_Type type__s8 = {TYPE_S8, sizeof(S8), __alignof(S8)};
global Ast_Resolved_Type type__s16 = {TYPE_S16, sizeof(S16), __alignof(S16)}; global Ast_Type type__s16 = {TYPE_S16, sizeof(S16), __alignof(S16)};
global Ast_Resolved_Type type__s32 = {TYPE_S32, sizeof(S32), __alignof(S32)}; global Ast_Type type__s32 = {TYPE_S32, sizeof(S32), __alignof(S32)};
global Ast_Resolved_Type type__s64 = {TYPE_S64, sizeof(S64), __alignof(S64)}; global Ast_Type type__s64 = {TYPE_S64, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__u8 = {TYPE_U8, sizeof(U8), __alignof(U8)}; global Ast_Type type__u8 = {TYPE_U8, sizeof(U8), __alignof(U8)};
global Ast_Resolved_Type type__u16 = {TYPE_U16, sizeof(U16), __alignof(U16)}; global Ast_Type type__u16 = {TYPE_U16, sizeof(U16), __alignof(U16)};
global Ast_Resolved_Type type__u32 = {TYPE_U32, sizeof(U32), __alignof(U32)}; global Ast_Type type__u32 = {TYPE_U32, sizeof(U32), __alignof(U32)};
global Ast_Resolved_Type type__u64 = {TYPE_U64, sizeof(U64), __alignof(U64)}; global Ast_Type type__u64 = {TYPE_U64, sizeof(U64), __alignof(U64)};
global Ast_Resolved_Type type__untyped_bool = {TYPE_UNTYPED_BOOL, sizeof(bool), __alignof(bool)}; global Ast_Type type__untyped_bool = {TYPE_UNTYPED_BOOL, sizeof(bool), __alignof(bool)};
global Ast_Resolved_Type type__untyped_int = {TYPE_UNTYPED_INT, sizeof(S64), __alignof(S64)}; global Ast_Type type__untyped_int = {TYPE_UNTYPED_INT, sizeof(S64), __alignof(S64)};
global Ast_Resolved_Type type__untyped_string = {TYPE_UNTYPED_STRING, sizeof(String), __alignof(String)}; global Ast_Type type__untyped_string = {TYPE_UNTYPED_STRING, sizeof(String), __alignof(String)};
global Ast_Resolved_Type type__untyped_float = {TYPE_UNTYPED_FLOAT, sizeof(double), __alignof(double)}; global Ast_Type type__untyped_float = {TYPE_UNTYPED_FLOAT, sizeof(double), __alignof(double)};
global Ast_Resolved_Type *type_type = &type__type; global Ast_Type *type_type = &type__type;
global Ast_Resolved_Type *type_void = &type__void; global Ast_Type *type_void = &type__void;
global Ast_Resolved_Type *type_string = &type__string; global Ast_Type *type_string = &type__string;
global Ast_Resolved_Type *type_bool = &type__bool; global Ast_Type *type_bool = &type__bool;
global Ast_Resolved_Type *type_f32 = &type__f32; global Ast_Type *type_f32 = &type__f32;
global Ast_Resolved_Type *type_f64 = &type__f64; global Ast_Type *type_f64 = &type__f64;
global Ast_Resolved_Type *type_s8 = &type__s8 ; global Ast_Type *type_s8 = &type__s8 ;
global Ast_Resolved_Type *type_s16 = &type__s16; global Ast_Type *type_s16 = &type__s16;
global Ast_Resolved_Type *type_s32 = &type__s32; global Ast_Type *type_s32 = &type__s32;
global Ast_Resolved_Type *type_s64 = &type__s64; global Ast_Type *type_s64 = &type__s64;
global Ast_Resolved_Type *type_u8 = &type__u8 ; global Ast_Type *type_u8 = &type__u8 ;
global Ast_Resolved_Type *type_u16 = &type__u16; global Ast_Type *type_u16 = &type__u16;
global Ast_Resolved_Type *type_u32 = &type__u32; global Ast_Type *type_u32 = &type__u32;
global Ast_Resolved_Type *type_u64 = &type__u64; global Ast_Type *type_u64 = &type__u64;
global Ast_Resolved_Type *untyped_string = &type__untyped_string; global Ast_Type *untyped_string = &type__untyped_string;
global Ast_Resolved_Type *untyped_bool = &type__untyped_bool; global Ast_Type *untyped_bool = &type__untyped_bool;
global Ast_Resolved_Type *untyped_int = &type__untyped_int; global Ast_Type *untyped_int = &type__untyped_int;
global Ast_Resolved_Type *untyped_float = &type__untyped_float; global Ast_Type *untyped_float = &type__untyped_float;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Type constructors and utillities // Type constructors and utillities
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
force_inline B32 is_struct(Ast_Resolved_Type *a){return a->kind == TYPE_STRUCT;} force_inline B32 is_struct(Ast_Type *a){return a->kind == TYPE_STRUCT;}
force_inline B32 is_lambda(Ast_Resolved_Type *a){return a->kind == TYPE_LAMBDA;} force_inline B32 is_lambda(Ast_Type *a){return a->kind == TYPE_LAMBDA;}
force_inline B32 is_array(Ast_Resolved_Type *a){return a->kind == TYPE_ARRAY;} force_inline B32 is_array(Ast_Type *a){return a->kind == TYPE_ARRAY;}
force_inline B32 is_enum(Ast_Resolved_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_Resolved_Type *a){return a->kind == TYPE_POINTER;} force_inline B32 is_pointer(Ast_Type *a){return a->kind == TYPE_POINTER;}
force_inline B32 is_string(Ast_Resolved_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING;} force_inline B32 is_string(Ast_Type *a){return a->kind == TYPE_STRING || a->kind == TYPE_UNTYPED_STRING;}
force_inline B32 is_untyped_int(Ast_Resolved_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_Resolved_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);}
force_inline B32 is_int(Ast_Resolved_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT;} force_inline B32 is_int(Ast_Type *a){return (a->kind >= TYPE_S64 && a->kind <= TYPE_U8) || a->kind == TYPE_UNTYPED_INT;}
force_inline B32 is_signed_int(Ast_Resolved_Type *a){return a->kind >= TYPE_S64 && a->kind <= TYPE_S8;} force_inline B32 is_signed_int(Ast_Type *a){return a->kind >= TYPE_S64 && a->kind <= TYPE_S8;}
force_inline B32 is_unsigned_int(Ast_Resolved_Type *a){return a->kind >= TYPE_U64 && a->kind <= TYPE_U8;} force_inline B32 is_unsigned_int(Ast_Type *a){return a->kind >= TYPE_U64 && a->kind <= TYPE_U8;}
force_inline B32 is_float(Ast_Resolved_Type *a){return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT;} force_inline B32 is_float(Ast_Type *a){return a->kind == TYPE_F32 || a->kind == TYPE_F64 || a->kind == TYPE_UNTYPED_FLOAT;}
force_inline B32 is_f32(Ast_Resolved_Type *a){return a->kind == TYPE_F32;} force_inline B32 is_f32(Ast_Type *a){return a->kind == TYPE_F32;}
force_inline B32 is_f64(Ast_Resolved_Type *a){return a->kind == TYPE_F64;} force_inline B32 is_f64(Ast_Type *a){return a->kind == TYPE_F64;}
force_inline B32 is_bool(Ast_Resolved_Type *a){return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL;} force_inline B32 is_bool(Ast_Type *a){return a->kind == TYPE_BOOL || a->kind == TYPE_UNTYPED_BOOL;}
force_inline B32 is_untyped(Ast_Resolved_Type *a){return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST;} force_inline B32 is_untyped(Ast_Type *a){return a->kind >= TYPE_UNTYPED_FIRST && a->kind <= TYPE_UNTYPED_LAST;}
force_inline B32 is_typed(Ast_Resolved_Type *a){return !is_untyped(a);} force_inline B32 is_typed(Ast_Type *a){return !is_untyped(a);}
force_inline B32 force_inline B32
is_numeric(Ast_Resolved_Type *type){ is_numeric(Ast_Type *type){
return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) || return (type->kind >= TYPE_UNTYPED_FIRST_NUMERIC && type->kind <= TYPE_UNTYPED_LAST_NUMERIC) ||
(type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC); (type->kind >= TYPE_FIRST_NUMERIC && type->kind <= TYPE_LAST_NUMERIC);
} }
function U64 function U64
int_type_max(Ast_Resolved_Type *type){ int_type_max(Ast_Type *type){
switch(type->kind){ switch(type->kind){
case TYPE_BOOL: return 1; case TYPE_BOOL: return 1;
case TYPE_UNTYPED_BOOL: return 1; case TYPE_UNTYPED_BOOL: return 1;