Generating valid c code, more work on null values

This commit is contained in:
Krzosa Karol
2022-05-24 20:33:11 +02:00
parent 236ff0cd64
commit 5176b40204
17 changed files with 698 additions and 1258 deletions

View File

@@ -1,4 +1,4 @@
#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast;
#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast;
#define Ast_End() } break
enum Sym_Kind{
@@ -12,7 +12,7 @@ struct Sym{
Intern_String name;
Sym_Kind kind;
Ast_Decl *decl;
Type *type;
Ast_Resolved_Type *type;
union{
S64 int_val;
Intern_String intern_val;
@@ -20,7 +20,7 @@ struct Sym{
};
struct Operand{
Type *type;
Ast_Resolved_Type *type;
bool is_const;
union {
S64 int_val;
@@ -33,9 +33,9 @@ sym_insert(Sym *sym){
U64 hash = hash_string(sym->name.s);
Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash);
if(is_sym){
parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
}
map_insert_u64(&pctx->global_syms, hash, sym);
}
@@ -46,7 +46,7 @@ sym_get(Intern_String name){
}
function Sym *
sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
sym_new(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Ast_Decl *decl){
Sym *result = exp_alloc_type(pctx->perm, Sym);
result->name = name;
result->kind = kind;
@@ -57,7 +57,7 @@ sym_new(Sym_Kind kind, Intern_String name, Type *type, Ast_Decl *decl){
global Ast_Decl empty_decl = {};
function void
sym_insert_builtin_type(String name, Type *type){
sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
Intern_String string = intern_string(&pctx->interns, name);
Sym *sym = sym_new(SYM_Type, string, type, &empty_decl);
sym_insert(sym);
@@ -69,33 +69,31 @@ sym_insert_builtins(){
sym_insert_builtin_type("bool"_s, type_bool);
sym_insert_builtin_type("int"_s, type_int);
sym_insert_builtin_type("String"_s, type_string);
{
Intern_String string = intern_string(&pctx->interns, "true"_s);
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
sym_insert(sym);
}
{
Intern_String string = intern_string(&pctx->interns, "false"_s);
Sym *sym = sym_new(SYM_Const, string, type_bool, &empty_decl);
sym_insert(sym);
}
{
Intern_String string = intern_string(&pctx->interns, "null"_s);
Sym *sym = sym_new(SYM_Const, string, type_null, &empty_decl);
sym_insert(sym);
}
}
function Operand eval_expr(Ast_Expr *ast, Type *compound_required_type = 0);
function Type *
function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0);
function Ast_Resolved_Type *
eval_typespec(Ast_Typespec *ast){
if(!ast) return 0;
switch(ast->kind){
Ast_Begin(AST_TYPESPEC_IDENT, Ast_Typespec){
Sym *type_sym = sym_get(node->name);
@@ -105,34 +103,36 @@ eval_typespec(Ast_Typespec *ast){
if(type_sym->kind != SYM_Type){
parsing_error(node->pos, "This identifier is not a type");
}
return type_sym->type;
node->resolved_type = type_sym->type;
return node->resolved_type;
Ast_End();
}
Ast_Begin(AST_TYPESPEC_LAMBDA, Ast_Typespec){
Scratch scratch;
Type *ret = eval_typespec(node->lambda->ret);
Array<Type *> params = {scratch};
Ast_Resolved_Type *ret = eval_typespec(node->lambda->ret);
Array<Ast_Resolved_Type *> params = {scratch};
For(node->lambda->params) params.add(eval_typespec(it[0]->lambda_param.typespec));
Type *result = type_lambda(ret, params);
return result;
node->resolved_type = type_lambda(ret, params);
return node->resolved_type;
Ast_End();
}
Ast_Begin(AST_TYPESPEC_POINTER, Ast_Typespec){
Type *type = eval_typespec(node->base);
Type *result = type_pointer(type);
return result;
Ast_Resolved_Type *type = eval_typespec(node->base);
node->resolved_type = type_pointer(type);
return node->resolved_type;
Ast_End();
}
Ast_Begin(AST_TYPESPEC_ARRAY, Ast_Typespec){
Type *type = eval_typespec(node->arr.base);
Ast_Resolved_Type *type = eval_typespec(node->arr.base);
Operand expr = eval_expr(node->arr.expr);
if(!expr.is_const) parsing_error(node->pos, "Array size is not a constant");
if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type int");
Type *result = type_array(type, expr.int_val);
return result;
if(expr.type != type_int) parsing_error(node->pos, "Array size is expected to be of type [Int] is instead of type %s", type_names[expr.type->kind]);
node->resolved_type = type_array(type, expr.int_val);
return node->resolved_type;
Ast_End();
}
invalid_default_case;
@@ -140,43 +140,94 @@ eval_typespec(Ast_Typespec *ast){
return 0;
}
function Type *
resolve_type_pair(Token *pos, Type *a, Type *b){
Type *result = 0;
function Ast_Resolved_Type *
resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
Ast_Resolved_Type *result = 0;
if(!a && b) result = b;
else if(a && !b) result = a;
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are null");
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]");
else{ // a && b
if(b->kind == TYPE_Null) result = a;
else if(a->kind == TYPE_Null) result = b;
else if(a != b) parsing_error(pos, "Expression and type specification are differing");
else if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]);
else result = a; // Types are the same
}
if(result->kind == TYPE_Null) parsing_error(pos, "Couldn't infer type of null value");
return result;
}
function Operand
eval_expr(Ast_Expr *ast, Type *exp_compound_type){
function Operand
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){
switch(ast->kind){
Ast_Begin(AST_INT, Ast_Expr){
Operand result = {type_int, true, {.int_val=(S64)node->int_val}};
return result;
Ast_End();
}
Ast_Begin(AST_STR, Ast_Expr){
Operand result = {type_string, true, {.intern_val = node->intern_val}};
return result;
Ast_End();
}
Ast_Begin(AST_IDENT, Ast_Expr){
Sym *sym = sym_get(node->intern_val);
if(!sym){
parsing_error(node->pos, "Identifier is undefined");
}
// @note: check if null and rewrite the expression to match the expected type
Operand result = {};
if(sym->type->kind == TYPE_Null){
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
result.type = expected_type;
result.is_const = true;
if(expected_type == type_int){
result.int_val = 0;
node->kind = AST_INT;
node->int_val = 0;
}
else if(expected_type->kind == TYPE_Pointer){
result.int_val = 0;
node->kind = AST_IDENT;
node->intern_val = pctx->intern("null_pointer"_s);
}
else if(expected_type->kind == TYPE_Lambda){
result.int_val = 0;
node->kind = AST_IDENT;
node->intern_val = pctx->intern("null_lambda"_s);
}
else if(expected_type == type_bool){
result.int_val = 0;
node->kind = AST_IDENT;
node->intern_val = pctx->intern("false"_s);
}
else if(expected_type == type_string){
result.intern_val = pctx->intern(""_s);
node->kind = AST_STR;
node->intern_val = result.intern_val;
}
}
else{
result.type = sym->type;
result.is_const = sym->kind == SYM_Const ? true : false;
result.int_val = sym->int_val;
}
return result;
Ast_End();
}
Ast_Begin(AST_LAMBDA, Ast_Lambda){
Type *type = eval_typespec(ast_typespec_lambda(0, node));
Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node));
return {type, true};
Ast_End();
}
Ast_Begin(AST_INDEX, Ast_Expr){
Operand left = eval_expr(node->index.expr);
Operand index = eval_expr(node->index.index);
@@ -186,81 +237,71 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
return result;
Ast_End();
}
Ast_Begin(AST_COMPOUND, Ast_Expr){
Type *type = eval_typespec(node->compound.typespec);
Type *variable_type = exp_compound_type;
Ast_Resolved_Type *type = eval_typespec(node->compound.typespec);
Ast_Resolved_Type *variable_type = expected_type;
if(!type && variable_type) type = variable_type;
else if(!variable_type && type);
else if(variable_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
node->compound.type = type;
if(type->kind == TYPE_Array){
if(node->compound.exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
Type *item_type = type->arr.base;
Ast_Resolved_Type *item_type = type->arr.base;
For(node->compound.exprs){
assert(it[0]->kind == AST_COMPOUND_ITEM);
Ast_Expr *i = (Ast_Expr *)it[0];
assert(i->kind == AST_COMPOUND_ITEM);
if(i->compound_item.name) parsing_error(i->pos, "Invalid array indexing in compound expression");
if(i->compound_item.name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
if(i->compound_item.index){
Operand index_op = eval_expr(i->compound_item.index);
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
}
Operand expr = eval_expr(i->compound_item.item);
Operand expr = eval_expr(i->compound_item.item, item_type);
resolve_type_pair(i->pos, expr.type, item_type);
}
}
else parsing_error(node->pos, "Invalid compound expression type");
Operand result = {type, false};
return result;
Ast_End();
}
Ast_Begin(AST_IDENT, Ast_Expr){
Sym *sym = sym_get(node->intern_val);
if(!sym){
parsing_error(node->pos, "Identifier is undefined");
}
Operand result = {sym->type, sym->kind == SYM_Const ? true : false, {.int_val = sym->int_val}};
return result;
Ast_End();
}
Ast_Begin(AST_CAST, Ast_Expr){
Operand expr = eval_expr(node->cast.expr);
Type *type = eval_typespec(node->cast.typespec);
Ast_Resolved_Type *type = eval_typespec(node->cast.typespec);
if(type == expr.type) return expr;
else if(expr.type == type_int && type == type_bool){
expr.type = type_bool;
return expr;
}
else if(expr.type == type_bool && type == type_int){
expr.type = type_int;
return expr;
}
else if(expr.type == type_null){
expr.type = type;
return expr;
}
else parsing_error(node->pos, "Failed to cast, incompatible types");
Ast_End();
}
Ast_Begin(AST_UNARY, Ast_Expr){
Operand value = eval_expr(node->unary.expr);
switch(node->unary.op){
case TK_BitXor:{
case TK_Pointer:{
if(value.type->kind != TYPE_Pointer) parsing_error(node->pos, "Dereferencing a value that is not a pointer");
Operand result = {value.type->base};
return result;
@@ -271,10 +312,10 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
}break;
invalid_default_case; return {};
}
Ast_End();
}
Ast_Begin(AST_BINARY, Ast_Expr){
Operand left = eval_expr(ast->binary.left);
Operand right = eval_expr(ast->binary.right);
@@ -293,51 +334,51 @@ eval_expr(Ast_Expr *ast, Type *exp_compound_type){
}
else parsing_error(node->pos, "Arithmetic on type [TODO] is not supported");
}
return result;
Ast_End();
}
invalid_default_case;
}
return {};
}
function void
eval_decl(Ast *ast){
switch(ast->kind){
Ast_Begin(AST_PACKAGE, Ast_Package){
For(node->decls) eval_decl(*it);
Ast_End();
}
Ast_Begin(AST_VAR, Ast_Decl){
Type *type = eval_typespec(node->var.typespec);
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
sym_insert(sym);
Ast_End();
}
Ast_Begin(AST_CONST, Ast_Decl){
Type *type = eval_typespec(node->var.typespec);
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
if(type && type->kind == TYPE_Pointer) parsing_error(node->pos, "Const cant be a pointer");
Operand expr = eval_expr(node->var.expr);
if(!expr.type) parsing_error(node->pos, "Constant value without expression");
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Const, node->name, resolved_type, node);
if(resolved_type == type_int) sym->int_val = expr.int_val;
else if(resolved_type == type_string) sym->intern_val = expr.intern_val;
sym_insert(sym);
Ast_End();
}
invalid_default_case;
}
}