Files
corelang/core_printer.cpp
Krzosa Karol e70d544029 Core printing
2023-03-31 22:28:18 +02:00

360 lines
10 KiB
C++

// @todo @cleanup ??
// :PrinterCleanup
// Instead of relying on global state, this probably should
// use a String_Builder or some kind of Builder context + macros
CORE_Static String
core_type_to_string(Ast_Type *type) {
switch (type->kind) {
case TYPE_NONE: return "<NONE>"_s; break;
case TYPE_S64: return "S64"_s; break;
case TYPE_S32: return "S32"_s; break;
case TYPE_S16: return "S16"_s; break;
case TYPE_S8: return "S8"_s; break;
case TYPE_INT: return "int"_s; break;
case TYPE_CHAR: return "char"_s; break;
case TYPE_U64: return "U64"_s; break;
case TYPE_U32: return "U32"_s; break;
case TYPE_U16: return "U16"_s; break;
case TYPE_U8: return "U8"_s; break;
case TYPE_F32: return "F32"_s; break;
case TYPE_F64: return "F64"_s; break;
case TYPE_BOOL: return "Bool"_s; break;
case TYPE_STRING: return "String"_s; break;
case TYPE_VOID: return "void"_s; break;
case TYPE_POINTER: {
String base = core_type_to_string(type->base);
return pctx->fmt("*%Q", base);
} break;
case TYPE_LAMBDA: {
String_Builder *b = &pctx->helper_builder;
b->addf("(");
Array<Ast_Type *> &args = type->func.args;
For(args) {
String t = core_type_to_string(it);
b->addf("%Q", t);
if (!args.is_last(&it)) b->addf(", ");
}
b->addf(")");
if (type->func.ret) {
String t = core_type_to_string(type->func.ret);
b->addf("%Q", t);
}
String result = string_flatten(pctx->perm, b);
return result;
} break;
case TYPE_STRUCT:
case TYPE_UNION:
case TYPE_ENUM: {
// @fixme: we probably want a string on Ast_Type
// so that we don't have to reach into Ast_Decl
// for Structs Enums etc.
Ast_Decl *decl = (Ast_Decl *)type->ast;
return decl->name.s;
} break;
case TYPE_ARRAY: {
String base = core_type_to_string(type->base);
return pctx->fmt("[%u]%Q", type->arr.size, base);
} break;
case TYPE_SLICE: {
String base = core_type_to_string(type->base);
return pctx->fmt("[]%Q", base);
} break;
case TYPE_TUPLE: {
invalid_codepath;
} break;
case TYPE_TYPE: return "Type"_s; break;
case TYPE_UNTYPED_BOOL: return "UntypedBool"_s; break;
case TYPE_UNTYPED_INT: return "UntypedInt"_s; break;
case TYPE_UNTYPED_FLOAT: return "UntypedFloat"_s; break;
case TYPE_UNTYPED_STRING: return "UntypedString"_s; break;
case TYPE_COMPLETING: invalid_codepath; break;
case TYPE_INCOMPLETE: invalid_codepath; break;
case TYPE_POLYMORPH:
invalid_codepath;
break;
invalid_default_case;
}
invalid_return;
}
void core__stringify(Ast *ast) {
if (!ast) return;
switch (ast->kind) {
case AST_SCOPE: {
Ast_Scope *n = (Ast_Scope *)ast;
global_indent += 1;
For(n->decls) {
genln("");
core__stringify(it);
}
For(n->stmts) {
genln("");
core__stringify(it);
}
global_indent -= 1;
} break;
case AST_MODULE: invalid_codepath; break;
case AST_FILE: invalid_codepath; break;
case AST_IDENT: {
Ast_Atom *n = (Ast_Atom *)ast;
gen("%Q", n->intern_val);
} break;
case AST_VALUE: {
Ast_Atom *n = (Ast_Atom *)ast;
gen("@%Q", n->pos->string);
} break;
case AST_INDEX: {
Ast_Index *n = (Ast_Index *)ast;
core__stringify(n->expr);
gen("[");
core__stringify(n->index);
gen("]");
} break;
case AST_UNARY: {
Ast_Unary *n = (Ast_Unary *)ast;
gen("%Q", n->pos->string);
core__stringify(n->expr);
} break;
case AST_BINARY: {
Ast_Binary *n = (Ast_Binary *)ast;
core__stringify(n->left);
gen("%Q", n->pos->string);
core__stringify(n->right);
} break;
case AST_CALL_ITEM: {
Ast_Call_Item *n = (Ast_Call_Item *)ast;
if (n->call_flags & CALL_INDEX) {
core__stringify(n->index);
gen(" = ");
}
else if (n->call_flags & CALL_NAME) {
core__stringify(n->name);
gen(" = ");
}
core__stringify(n->item);
} break;
case AST_CALL: {
Ast_Call *n = (Ast_Call *)ast;
core__stringify(n->name);
gen("(");
For(n->exprs) {
core__stringify(it);
if (!n->exprs.is_last(&it)) gen(",");
}
gen(")");
} break;
case AST_COMPOUND: {
Ast_Call *n = (Ast_Call *)ast;
core__stringify(n->name);
gen("{");
global_indent += 1;
For(n->exprs) {
genln("");
core__stringify(it);
gen(",");
}
global_indent -= 1;
genln("}");
} break;
case AST_TYPE_OF:
gen("TypeOf");
goto builtin;
case AST_LENGTH_OF:
gen("LengthOf");
goto builtin;
case AST_ALIGN_OF:
gen("AlignOf");
goto builtin;
case AST_SIZE_OF:
gen("SizeOf");
goto builtin;
case AST_RUNTIME_ASSERT:
gen("Assert");
goto builtin;
case AST_CONSTANT_ASSERT:
gen("#Assert");
goto builtin;
builtin : {
Ast_Builtin *n = (Ast_Builtin *)ast;
gen("(");
core__stringify(n->expr);
gen(")");
} break;
case AST_SWITCH: {
Ast_Switch *n = (Ast_Switch *)ast;
core__stringify(n->value);
For(n->cases) {
core__stringify(it);
}
core__stringify(n->default_scope);
} break;
case AST_SWITCH_CASE: {
Ast_Switch_Case *n = (Ast_Switch_Case *)ast;
For(n->labels) {
core__stringify(it);
}
core__stringify(n->scope);
} break;
case AST_VAR_UNPACK: {
Ast_Var_Unpack *n = (Ast_Var_Unpack *)ast;
For(n->vars) {
core__stringify(it);
if (!n->vars.is_last(&it)) gen(",");
}
gen(" = ");
core__stringify(n->expr);
} break;
case AST_PASS: {
genln("pass");
} break;
case AST_BREAK: {
genln("break");
} break;
case AST_NAMESPACE: {
Ast_Decl *n = (Ast_Decl *)ast;
gen("%Q :: NAMESPACE", n->name);
} break;
case AST_UNION:
case AST_STRUCT: {
Ast_Decl *n = (Ast_Decl *)ast;
genln("%Q :: %s", n->name, n->kind == AST_STRUCT ? "struct" : "union");
core__stringify(n->scope);
} break;
case AST_ENUM: {
Ast_Decl *n = (Ast_Decl *)ast;
genln("%Q :: enum", n->name);
core__stringify(n->scope);
} break;
case AST_LAMBDA: {
Ast_Decl *n = (Ast_Decl *)ast;
genln("%Q :: ", n->name);
core__stringify(n->lambda); // @cleanup
} break;
// @cleanup: what is this used for?
case AST_TYPE: {
invalid_codepath;
} break;
case AST_CONST: {
Ast_Decl *n = (Ast_Decl *)ast;
gen("%Q :: CONST value @todo", n->name);
} break;
case AST_VAR: {
Ast_Decl *n = (Ast_Decl *)ast;
gen("%Q: %Q", n->name, core_type_to_string(n->type));
if (n->expr) {
gen(" = ");
core__stringify(n->expr);
}
} break;
case AST_ARRAY: {
Ast_Array *n = (Ast_Array *)ast;
gen("[");
core__stringify(n->expr);
gen("]");
core__stringify(n->base);
} break;
case AST_FOR: {
Ast_For *n = (Ast_For *)ast;
gen("for ");
core__stringify(n->init);
if (n->cond) gen(", ");
core__stringify(n->cond);
if (n->iter) gen(", ");
core__stringify(n->iter);
core__stringify(n->scope);
} break;
case AST_IF: {
Ast_If *n = (Ast_If *)ast;
int i = 0;
For(n->ifs) {
if (i == 0) gen("if ");
else if (it->expr) gen("elif ");
else gen("else ");
core__stringify(it->expr);
if (it->init) gen(", ");
core__stringify(it->init);
core__stringify(it->scope);
i += 1;
}
} break;
case AST_RETURN: {
Ast_Return *n = (Ast_Return *)ast;
gen("return ");
For(n->expr) {
core__stringify(it);
if (!n->expr.is_last(&it)) gen(", ");
}
} break;
case AST_LAMBDA_EXPR: {
Ast_Lambda *n = (Ast_Lambda *)ast;
gen("(");
For(n->args) {
core__stringify(it);
if (!n->args.is_last(&it)) gen(", ");
}
gen(")");
if (n->ret.len) gen(": ");
For(n->ret) {
core__stringify(it);
if (!n->ret.is_last(&it)) gen(", ");
}
core__stringify(n->scope);
} break;
default: assert(!"Invalid default case");
}
}
String core_stringify(Ast *ast) {
core__stringify(ast);
String result = string_flatten(pctx->perm, &pctx->gen);
pctx->gen.reset();
return result;
}