Working on slices, builtin stuff feels wanky, rewrite gen_simple_decl to
generate string
This commit is contained in:
3
ast.cpp
3
ast.cpp
@@ -65,7 +65,8 @@ struct Ast{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Type;
|
struct Ast_Type;
|
||||||
struct Ast_Expr:Ast{ };
|
struct Ast_Expr:Ast{
|
||||||
|
};
|
||||||
|
|
||||||
#define VALUE_FIELDS \
|
#define VALUE_FIELDS \
|
||||||
Ast_Type *type; \
|
Ast_Type *type; \
|
||||||
|
|||||||
177
ccodegen.cpp
177
ccodegen.cpp
@@ -3,9 +3,10 @@
|
|||||||
#define genln(...) do{gen("\n"); gen_indent(); gen(__VA_ARGS__); }while(0)
|
#define genln(...) do{gen("\n"); gen_indent(); gen(__VA_ARGS__); }while(0)
|
||||||
global S32 global_indent;
|
global S32 global_indent;
|
||||||
global S32 is_inside_struct;
|
global S32 is_inside_struct;
|
||||||
|
global B32 should_gen_scope_name = false;
|
||||||
|
|
||||||
function void gen_ast(Ast *ast);
|
function void gen_ast(Ast *ast);
|
||||||
function bool gen_expr(Ast_Expr *ast);
|
function bool gen_expr(Ast_Expr *ast, Ast_Type *type_of_var = 0);
|
||||||
|
|
||||||
function void
|
function void
|
||||||
gen_indent(){
|
gen_indent(){
|
||||||
@@ -18,10 +19,20 @@ gen_line(Ast *node){
|
|||||||
genln("#line %d", node->pos->line+1);
|
genln("#line %d", node->pos->line+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function String
|
||||||
|
string_scope_name(Allocator *a, Ast_Scope *scope){
|
||||||
|
String string = {};
|
||||||
|
if(!should_gen_scope_name) return string;
|
||||||
|
if(scope->parent_scope) string = string_scope_name(a, scope->parent_scope);
|
||||||
|
if(scope->name.str) string_fmt(a, "%Q%s_", string, scope->name.str);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
gen_scope_name(Ast_Scope *scope){
|
gen_scope_name(Ast_Scope *scope){
|
||||||
if(scope->parent_scope) gen_scope_name(scope->parent_scope);
|
Scratch scratch;
|
||||||
if(scope->name.str) gen("%s_", scope->name.str);
|
String string = string_scope_name(scratch, scope);
|
||||||
|
gen("%.*s", (int)string.len, string.str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo: Gen complicated decl
|
// @todo: Gen complicated decl
|
||||||
@@ -33,62 +44,91 @@ gen_scope_name(Ast_Scope *scope){
|
|||||||
// 3 Going backwards add arrays and pointers in parens
|
// 3 Going backwards add arrays and pointers in parens
|
||||||
// 4 Add type name on the left side
|
// 4 Add type name on the left side
|
||||||
|
|
||||||
function void
|
function String
|
||||||
gen_simple_decl_prefix(Ast_Type *ast, bool scope_names){
|
string_simple_decl_prefix(Allocator *a, Ast_Type *ast, bool scope_names){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
case TYPE_POINTER: gen_simple_decl_prefix(ast->base, scope_names); gen("*"); break;
|
case TYPE_POINTER:{
|
||||||
case TYPE_ARRAY: gen_simple_decl_prefix(ast->base, scope_names); break;
|
String string = string_simple_decl_prefix(a, ast->base, scope_names);
|
||||||
case TYPE_LAMBDA:break;
|
string = string_fmt(a, "%Q*", string);
|
||||||
case TYPE_ENUM:{
|
return string;
|
||||||
gen_simple_decl_prefix(ast->base, scope_names); break;
|
}break;
|
||||||
|
case TYPE_LAMBDA: return {}; break;
|
||||||
|
case TYPE_ENUM:
|
||||||
|
case TYPE_ARRAY: {
|
||||||
|
return string_simple_decl_prefix(a, ast->base, scope_names);
|
||||||
|
}break;
|
||||||
|
case TYPE_SLICE:{
|
||||||
|
String string = string_simple_decl_prefix(a, ast->base, true);
|
||||||
|
string = string_fmt(a, "SliceOf%Q", string);
|
||||||
|
return string;
|
||||||
}break;
|
}break;
|
||||||
case TYPE_STRUCT: {
|
case TYPE_STRUCT: {
|
||||||
auto constant = (Ast_Decl *)ast->ast;
|
auto constant = (Ast_Decl *)ast->ast;
|
||||||
auto name = constant->name;
|
auto name = constant->name;
|
||||||
if(scope_names) gen_scope_name(constant->parent_scope);
|
String string = string_fmt(a, "%Q ", name);
|
||||||
gen("%s ", name.str);
|
String sc = {};
|
||||||
|
if(scope_names) sc = string_scope_name(a, constant->parent_scope);
|
||||||
|
return string_fmt(a, "%Q%Q", sc, string);
|
||||||
}break;
|
}break;
|
||||||
default: {
|
default: {
|
||||||
gen("%s ", name(ast));
|
String string = string_fmt(a, "%s ", name(ast));
|
||||||
|
return string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function String
|
||||||
gen_simple_decl_postfix(Ast_Type *ast, bool scope_names){
|
string_simple_decl_postfix(Allocator *a, Ast_Type *ast, bool scope_names){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
case TYPE_POINTER: gen_simple_decl_postfix(ast->base, scope_names); break;
|
case TYPE_POINTER:
|
||||||
case TYPE_ARRAY:
|
return string_simple_decl_postfix(a, ast->base, scope_names);
|
||||||
gen("[");
|
break;
|
||||||
if(ast->arr.size != ARRAY_SIZE_SLICE)
|
case TYPE_ARRAY:{
|
||||||
gen("%d", (int)ast->arr.size);
|
String result = string_simple_decl_postfix(a, ast->arr.base, scope_names);
|
||||||
gen("]");
|
String string = string_fmt(a, "[%d]%Q", ast->arr.size, result);
|
||||||
gen_simple_decl_postfix(ast->arr.base, scope_names); break;
|
return string;
|
||||||
|
}break;
|
||||||
case TYPE_LAMBDA:break;
|
case TYPE_LAMBDA:break;
|
||||||
case TYPE_ENUM: case TYPE_STRUCT:break;
|
case TYPE_SLICE: case TYPE_ENUM: case TYPE_STRUCT:break;
|
||||||
default: name(ast);
|
default:break;
|
||||||
|
// default: return string_from_cstring((char *)name(ast));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function String
|
||||||
|
string_simple_decl(Allocator *a, Ast_Type *ast, Intern_String name = {}, Ast_Scope *scope = 0, bool scope_names = true){
|
||||||
|
if(ast->kind == TYPE_LAMBDA) {
|
||||||
|
String prefix = string_simple_decl_prefix(a, ast->func.ret, scope_names);
|
||||||
|
String string = string_fmt(a, "%Q(*%Q)(", prefix, name);
|
||||||
|
For(ast->func.args){
|
||||||
|
String prefix_arg = string_simple_decl_prefix(a, it, scope_names);
|
||||||
|
string = string_fmt(a, "%Q%Q", string, prefix_arg);
|
||||||
|
if(&it != ast->func.args.end() - 1)
|
||||||
|
string = string_fmt(a, "%Q, ", string);
|
||||||
|
}
|
||||||
|
string = string_fmt(a, "%Q)", string);
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
String string = string_simple_decl_prefix(a, ast, scope_names);
|
||||||
|
if(name.len) {
|
||||||
|
if(scope && scope_names)
|
||||||
|
string = string_fmt(a, "%Q%Q", string, string_scope_name(a, scope));
|
||||||
|
string = string_fmt(a, "%Q%Q", string, name);
|
||||||
|
}
|
||||||
|
String postfix = string_simple_decl_postfix(a, ast, scope_names);
|
||||||
|
string = string_fmt(a, "%Q%Q", string, postfix);
|
||||||
|
return string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
gen_simple_decl(Ast_Type *ast, Intern_String name = {}, Ast_Scope *scope = 0, bool scope_names = true){
|
gen_simple_decl(Ast_Type *ast, Intern_String name = {}, Ast_Scope *scope = 0, bool scope_names = true){
|
||||||
if(ast->kind == TYPE_LAMBDA) {
|
Scratch scratch;
|
||||||
gen_simple_decl_prefix(ast->func.ret, scope_names);
|
String string = string_simple_decl(scratch, ast, name, scope, scope_names);
|
||||||
gen("(*%s)(", name.str);
|
gen("%.*s", (int)string.len, string.str);
|
||||||
For(ast->func.args){
|
|
||||||
gen_simple_decl_prefix(it, scope_names);
|
|
||||||
if(&it != ast->func.args.end() - 1) gen(", ");
|
|
||||||
}
|
|
||||||
gen(")");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
gen_simple_decl_prefix(ast, scope_names);
|
|
||||||
if(name.len) {
|
|
||||||
if(scope && scope_names) gen_scope_name(scope);
|
|
||||||
gen("%s", name.str);
|
|
||||||
}
|
|
||||||
gen_simple_decl_postfix(ast, scope_names);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function B32
|
function B32
|
||||||
@@ -143,7 +183,7 @@ gen_var(Ast_Decl *decl, B32 emit_value, B32 scope_names){
|
|||||||
|
|
||||||
if(decl->expr){
|
if(decl->expr){
|
||||||
gen(" = ");
|
gen(" = ");
|
||||||
gen_expr(decl->expr);
|
gen_expr(decl->expr, decl->type);
|
||||||
} else { // Default zero
|
} else { // Default zero
|
||||||
if(is_numeric(decl->type)){
|
if(is_numeric(decl->type)){
|
||||||
gen(" = 0");
|
gen(" = 0");
|
||||||
@@ -154,7 +194,7 @@ gen_var(Ast_Decl *decl, B32 emit_value, B32 scope_names){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
gen_lambda(Intern_String name, Ast_Lambda *lambda){
|
gen_lambda(Intern_String name, Ast_Lambda *lambda, B32 generate_block = true){
|
||||||
bool is_foreign = is_flag_set(lambda->flags, AST_FOREIGN);
|
bool is_foreign = is_flag_set(lambda->flags, AST_FOREIGN);
|
||||||
if(name == pctx->intern("main"_s)){
|
if(name == pctx->intern("main"_s)){
|
||||||
is_foreign = true;
|
is_foreign = true;
|
||||||
@@ -163,18 +203,19 @@ gen_lambda(Intern_String name, Ast_Lambda *lambda){
|
|||||||
gen("(");
|
gen("(");
|
||||||
For(lambda->args){
|
For(lambda->args){
|
||||||
gen_var(it, DONT_EMIT_VALUE, true);
|
gen_var(it, DONT_EMIT_VALUE, true);
|
||||||
if(&it != (lambda->args.end() - 1)) gen(", ");
|
if(&it != (lambda->args.end() - 1))
|
||||||
|
gen(", ");
|
||||||
}
|
}
|
||||||
gen(")");
|
gen(")");
|
||||||
|
|
||||||
if(lambda->scope){
|
if(generate_block && lambda->scope){
|
||||||
gen_stmt_scope(lambda->scope);
|
gen_stmt_scope(lambda->scope);
|
||||||
}
|
}
|
||||||
else gen(";");
|
else gen(";");
|
||||||
}
|
}
|
||||||
|
|
||||||
function bool
|
function bool
|
||||||
gen_expr(Ast_Expr *ast){
|
gen_expr(Ast_Expr *ast, Ast_Type *type_of_var){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(IDENT, Atom){
|
CASE(IDENT, Atom){
|
||||||
if(node->resolved_decl->kind == AST_MODULE_NAMESPACE || node->resolved_decl->kind == AST_FILE_NAMESPACE)
|
if(node->resolved_decl->kind == AST_MODULE_NAMESPACE || node->resolved_decl->kind == AST_FILE_NAMESPACE)
|
||||||
@@ -184,8 +225,14 @@ gen_expr(Ast_Expr *ast){
|
|||||||
if(is_flag_set(node->resolved_decl->lambda->flags, AST_FOREIGN))
|
if(is_flag_set(node->resolved_decl->lambda->flags, AST_FOREIGN))
|
||||||
print_scope = false;
|
print_scope = false;
|
||||||
}
|
}
|
||||||
if(print_scope) gen_scope_name(node->resolved_decl->parent_scope);
|
if(type_of_var && is_slice(type_of_var) && is_array(node->resolved_decl->type)){
|
||||||
gen("%s", node->intern_val.str);
|
gen("{%d, ", (int)node->resolved_decl->type->arr.size);
|
||||||
|
if(print_scope) gen_scope_name(node->resolved_decl->parent_scope);
|
||||||
|
gen("%s}", node->intern_val.str);
|
||||||
|
} else {
|
||||||
|
if(print_scope) gen_scope_name(node->resolved_decl->parent_scope);
|
||||||
|
gen("%s", node->intern_val.str);
|
||||||
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +303,18 @@ gen_expr(Ast_Expr *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(CALL, Call){
|
CASE(CALL, Call){
|
||||||
|
if(node->name->kind == AST_IDENT){
|
||||||
|
auto ident = (Ast_Atom *)node->name;
|
||||||
|
if(ident->intern_val == pctx->intern("len"_s)){
|
||||||
|
if(is_slice(ident->type)){
|
||||||
|
Ast_Call_Item *arg = node->exprs[0];
|
||||||
|
gen_expr(arg->item);
|
||||||
|
gen(".len");
|
||||||
|
return true;
|
||||||
|
} else invalid_codepath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gen_expr(node->name);
|
gen_expr(node->name);
|
||||||
gen("(");
|
gen("(");
|
||||||
For(node->exprs){
|
For(node->exprs){
|
||||||
@@ -359,7 +418,7 @@ gen_ast(Ast *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(STRUCT, Decl){
|
CASE(STRUCT, Decl){
|
||||||
gen("typedef struct ");
|
gen("struct ");
|
||||||
gen_scope_name(node->parent_scope);
|
gen_scope_name(node->parent_scope);
|
||||||
gen("%s{", node->name.str);
|
gen("%s{", node->name.str);
|
||||||
global_indent++;
|
global_indent++;
|
||||||
@@ -371,15 +430,13 @@ gen_ast(Ast *ast){
|
|||||||
|
|
||||||
is_inside_struct--;
|
is_inside_struct--;
|
||||||
global_indent--;
|
global_indent--;
|
||||||
genln("}");
|
genln("};");
|
||||||
gen_scope_name(node->parent_scope);
|
|
||||||
gen("%s;", node->name.str);
|
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(TYPE, Decl){
|
CASE(TYPE, Decl){
|
||||||
gen("// Type %s = ", node->name.str);
|
gen("// Type %s = ", node->name.str);
|
||||||
gen_expr(node->expr);
|
gen_simple_decl(node->type_val);
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,6 +670,20 @@ typedef struct String{
|
|||||||
|
|
||||||
)==");
|
)==");
|
||||||
#endif
|
#endif
|
||||||
|
For(pctx->ordered_decls){
|
||||||
|
if(it->kind == AST_STRUCT){
|
||||||
|
if(it->type && it->type->kind == TYPE_TYPE && is_slice(it->type_val)){
|
||||||
|
genln("typedef struct struct ");
|
||||||
|
gen_simple_decl(it->type_val);
|
||||||
|
gen(";");
|
||||||
|
} else{
|
||||||
|
genln("typedef struct struct %s;", it->name.str);
|
||||||
|
}
|
||||||
|
} else if(it->kind == AST_LAMBDA){
|
||||||
|
genln("");
|
||||||
|
gen_lambda(it->name, it->lambda, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
For(pctx->ordered_decls){
|
For(pctx->ordered_decls){
|
||||||
genln("");
|
genln("");
|
||||||
|
|||||||
17
compiler.h
17
compiler.h
@@ -3,6 +3,7 @@ struct Ast_Decl;
|
|||||||
struct Ast_File_Namespace;
|
struct Ast_File_Namespace;
|
||||||
struct Ast_File;
|
struct Ast_File;
|
||||||
struct Ast_Module;
|
struct Ast_Module;
|
||||||
|
struct Ast_Type;
|
||||||
function Ast_Module *ast_module(Intern_String filename);
|
function Ast_Module *ast_module(Intern_String filename);
|
||||||
function void insert_builtin_types_into_scope(Ast_Scope *p);
|
function void insert_builtin_types_into_scope(Ast_Scope *p);
|
||||||
|
|
||||||
@@ -221,14 +222,14 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator){
|
parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator){
|
||||||
pctx = ctx;
|
pctx = ctx;
|
||||||
ctx->perm = perm_allocator;
|
ctx->perm = perm_allocator;
|
||||||
ctx->heap = heap_allocator;
|
ctx->heap = heap_allocator;
|
||||||
ctx->gen = {ctx->perm};
|
ctx->gen = {ctx->perm};
|
||||||
ctx->ordered_decls = {ctx->heap};
|
ctx->ordered_decls = {ctx->heap};
|
||||||
ctx->type_map = {ctx->heap};
|
ctx->type_map = {ctx->heap};
|
||||||
ctx->modules = {ctx->heap};
|
ctx->modules = {ctx->heap};
|
||||||
bigint_allocator = ctx->perm;
|
bigint_allocator = ctx->perm;
|
||||||
|
|
||||||
lex_init(ctx->perm, ctx->heap, ctx);
|
lex_init(ctx->perm, ctx->heap, ctx);
|
||||||
|
|
||||||
|
|||||||
@@ -707,7 +707,24 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
if(node->expr){
|
if(node->expr){
|
||||||
node->type = type_array(type.type_val, bigint_as_unsigned(&expr.big_int_val));
|
node->type = type_array(type.type_val, bigint_as_unsigned(&expr.big_int_val));
|
||||||
} else{
|
} else{
|
||||||
node->type = type_slice(type.type_val);
|
node->type = type_slice(type.type_val, node);
|
||||||
|
{ // @c_backend
|
||||||
|
Ast_Scope *scope = ast_decl_scope(0, pctx->heap, (Ast_File *)node->parent_scope->file);
|
||||||
|
|
||||||
|
Ast_Decl *len_var = ast_var(0, 0, pctx->intern("len"_s), 0);
|
||||||
|
len_var->type = type_s64;
|
||||||
|
scope->decls.add(len_var);
|
||||||
|
|
||||||
|
Ast_Decl *pointer_var = ast_var(0, 0, pctx->intern("data"_s), 0);
|
||||||
|
pointer_var->type = type.type_val;
|
||||||
|
scope->decls.add(pointer_var);
|
||||||
|
|
||||||
|
Ast_Decl *struct_decl = ast_struct(0, scope);
|
||||||
|
struct_decl->name = pctx->intern("SliceOf"_s);
|
||||||
|
struct_decl->type = type_type;
|
||||||
|
struct_decl->type_val = node->type;
|
||||||
|
pctx->ordered_decls.add(struct_decl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -847,10 +864,14 @@ resolve_expr(Ast_Expr *ast, Resolve_Flag flags, Ast_Type *compound_context){
|
|||||||
Ast_Call_Item *arg = node->exprs[0];
|
Ast_Call_Item *arg = node->exprs[0];
|
||||||
if(arg->name || arg->index) compiler_error(node->pos, "No named or indexed arguments expected");
|
if(arg->name || arg->index) compiler_error(node->pos, "No named or indexed arguments expected");
|
||||||
Operand op = resolve_expr(arg->item, AST_CANT_BE_NULL);
|
Operand op = resolve_expr(arg->item, AST_CANT_BE_NULL);
|
||||||
|
ident->type = op.type;
|
||||||
|
|
||||||
if(is_array(op.type)){
|
if(is_array(op.type)){
|
||||||
Value val = value_int(op.type->arr.size);
|
Value val = value_int(op.type->arr.size);
|
||||||
rewrite_into_const(node, Ast_Call, val);
|
rewrite_into_const(node, Ast_Call, val);
|
||||||
return operand_const_rvalue(val);
|
return operand_const_rvalue(val);
|
||||||
|
} else if(is_slice(op.type)){
|
||||||
|
return operand_rvalue(type_s64);
|
||||||
} else compiler_error(node->pos, "Invalid argument");
|
} else compiler_error(node->pos, "Invalid argument");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ type_pointer(Ast_Type *base){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Type *
|
function Ast_Type *
|
||||||
type_slice(Ast_Type *base){
|
type_slice(Ast_Type *base, Ast *ast){
|
||||||
U64 hash_base = hash_ptr(base);
|
U64 hash_base = hash_ptr(base);
|
||||||
U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
|
U64 hash = hash_mix(hash_base, hash_u64(ARRAY_SIZE_SLICE));
|
||||||
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
|
||||||
@@ -148,6 +148,7 @@ type_slice(Ast_Type *base){
|
|||||||
result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice));
|
result = type_new(pctx->perm, TYPE_SLICE, sizeof(Slice), alignof(Slice));
|
||||||
result->arr.base = base;
|
result->arr.base = base;
|
||||||
result->arr.slice_hash = hash;
|
result->arr.slice_hash = hash;
|
||||||
|
result->ast = ast;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user