Files
corelang/print.c

369 lines
8.8 KiB
C

function void expr_print(Expr *expr);
function void typespec_print(Typespec *spec);
global S64 indent;
#define println(...) do{ printf("\n"); print_indent(); printf(__VA_ARGS__); }while(0)
#define AST_CAST(item, T) T *item = (T *)item
#define AST_IterT(parent, name, T) for(T *name = (T *)(parent)->first; name; name=(T *)name->next) // , assert(name->kind == AST_##type
#define AST_Iter(parent,name) AST_IterT(parent,name,AST)
function void
print_indent(){
for(S64 i = 0; i < indent*2; i++)
printf(" ");
}
function void
token_print(Token *token){
printf("%.*s", (S32)token->len, token->str);
}
function void
expr_compound_print(Expr_Compound_Field *field){
switch(field->kind){
case COMPOUND_Default: {
expr_print(field->init);
}break;
case COMPOUND_Named: {
printf(".%s = ", field->name.s.str);
expr_print(field->init);
}break;
case COMPOUND_Index: {
printf("[");
expr_print(field->index);
printf("] = ");
expr_print(field->init);
}break;
default: invalid_codepath;
}
}
function void
expr_print(Expr *expr){
switch(expr->kind) {
case EK_Int:case EK_String:case EK_Identifier: {
token_print(expr->token);
} break;
case EK_SizeExpr:{
printf("sizeof(");
expr_print(expr->size_expr.expr);
printf(")");
}break;
case EK_Compound:{
if(expr->compound.typespec){
printf("(");
typespec_print(expr->compound.typespec);
printf(")");
}
printf("{");
for(Expr_Compound_Field *n = expr->compound.first; n; n=n->next){
expr_compound_print(n);
if(n!=expr->compound.last) printf(",");
}
printf("}");
} break;
case EK_SizeType:{
printf("sizeof(");
typespec_print(expr->size_type.typespec);
printf(")");
}break;
case EK_Paren:{
printf("(");
expr_print(expr->paren.expr);
printf(")");
} break;
case EK_Field:{
expr_print(expr->field.expr);
printf(".%s", expr->field.name.s.str);
} break;
case EK_Binary:{
printf("(");
expr_print(expr->binary.left);
printf("%s", token_kind_string[expr->binary.op]);
expr_print(expr->binary.right);
printf(")");
} break;
case EK_PostfixUnary:{
printf("(");
expr_print(expr->unary.expr);
token_print(expr->token);
printf(")");
} break;
case EK_Unary:{
printf("(");
token_print(expr->token);
expr_print(expr->unary.expr);
printf(")");
} break;
case EK_Ternary:{
printf("(");
expr_print(expr->ternary.cond);
printf("?");
expr_print(expr->ternary.on_true);
printf(":");
expr_print(expr->ternary.on_false);
printf(")");
} break;
case EK_Cast:{
printf("(");
printf("(");
typespec_print(expr->cast.typespec);
printf(")");
expr_print(expr->cast.expr);
printf(")");
} break;
case EK_Index:{
expr_print(expr->index.atom);
printf("[");
expr_print(expr->index.index);
printf("]");
}break;
case EK_Call:{
expr_print(expr->call.atom);
printf("(");
for(Expr_Compound_Field *n = expr->call.first; n; n=n->next){
expr_compound_print(n);
if(n!=expr->call.last) printf(",");
}
printf(")");
}break;
default: {invalid_codepath;} break;
}
}
function void
typespec_print(Typespec *spec){
switch(spec->kind) {
case TS_Name: {
printf("%s", spec->name.s.str);
} break;
case TS_NamedArgument: {
printf("%s: ", spec->named.name.s.str);
typespec_print(spec->named.base);
}break;
case TS_Pointer: {
typespec_print(spec->base);
printf("*");
} break;
case TS_Array: {
typespec_print(spec->arr.base);
printf("[");
expr_print(spec->arr.size);
printf("]");
} break;
case TS_Function: {
printf("(");
for(Typespec *n = spec->func.first; n; n=n->next){
typespec_print(n);
if(n!=spec->func.last)
printf(", ");
}
printf(")");
typespec_print(spec->func.ret);
} break;
default: {invalid_codepath;} break;
}
}
function void
print_assign_expr(Expr *expr){
if(expr){
printf(" = ");
expr_print(expr);
}
}
function void
ast_print(AST *in){
switch(in->kind) {
case AST_Program: {
Program *node = (Program *)in;
for(AST *n = node->first; n; n=n->next){
ast_print(n);
printf("\n");
}
} break;
case AST_Decl_Const:
case AST_Decl_Var:{
Decl_Var *node = (Decl_Var *)in;
println("");
if(node->typespec) typespec_print(node->typespec);
printf(" %s", node->name.s.str);
print_assign_expr(node->expr);
} break;
case AST_Decl_Typedef:{
Decl_Typedef *node = (Decl_Typedef *)in;
println("typedef %s ", node->name.s.str);
typespec_print(node->typespec);
printf(";");
} break;
case AST_Decl_Func:{
Decl_Func *node = (Decl_Func *)in;
println("function ");
typespec_print(node->ret);
printf("\n%s", node->name.s.str);
printf("(");
AST_IterT(node, arg, Decl_Func_Arg){
typespec_print(arg->typespec);
printf(" %s", arg->name.s.str);
if((AST *)arg != node->last)
printf(", ");
}
printf(")");
if(!node->is_incomplete){
ast_print((AST *)node->body);
}
} break;
case AST_Decl_Struct:
case AST_Decl_Union :{
Decl_Struct *node = (Decl_Struct *)in;
const char *struct_name = node->kind==AST_Decl_Struct ? "struct" : "union";
println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:"");
indent++;
for(AST *n = node->first; n; n=n->next){
ast_print(n);
printf(";");
}
indent--;
println("};");
} break;
case AST_Decl_SubStruct:
case AST_Decl_SubUnion :{
Decl_Struct *node = (Decl_Struct *)in;
const char *struct_name = node->kind==AST_Decl_Struct ? "struct" : "union";
println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:"");
indent++;
for(AST *n = node->first; n; n=n->next){
ast_print(n);
}
indent--;
println("};");
} break;
case AST_Decl_Enum:{
Decl_Enum *node = (Decl_Enum *)in;
println("enum %s : ", node->name.s.str);
typespec_print(node->typespec);
printf("{");
indent++;
AST_IterT(node, n, Decl_Enum_Child){
//print_notes(p, n->first_note);
println("%s", n->name.s.str);
print_assign_expr(n->expr);
printf(",");
}
indent--;
println("};");
} break;
case AST_Stmt_Init:{
Stmt_Init *node = (Stmt_Init *)in;
if(node->typespec) typespec_print(node->typespec);
printf(" %s", node->name.s.str);
print_assign_expr(node->expr);
}break;
case AST_Stmt_Assign:{
Stmt_Assign *node = (Stmt_Assign *)in;
expr_print(node->left);
token_print(node->pos);
expr_print(node->right);
}break;
case AST_Stmt_Expr:{
Stmt_Expr *node = (Stmt_Expr *)in;
expr_print(node->expr);
}break;
case AST_Stmt_Defer:{
Stmt_Defer *node = (Stmt_Defer *)in;
printf("defer ");
ast_print((AST *)node->body);
}break;
case AST_Stmt_Return:{
Stmt_Return *node = (Stmt_Return *)in;
printf("return ");
expr_print(node->expr);
}break;
case AST_Stmt_Block:{
Stmt_Block *node = (Stmt_Block *)in;
printf(" {");
indent++;
AST_IterT(node, n, AST){
println("");
ast_print(n);
if(n->kind != AST_Stmt_If && n->kind != AST_Stmt_For && n->kind != AST_Stmt_Else &&
n->kind != AST_Stmt_ElseIf)
printf(";");
}
indent--;
println("}");
}break;
case AST_Stmt_Else:{
Stmt_Else *node = (Stmt_Else *)in;
printf("else ");
ast_print((AST *)node->body);
}break;
case AST_Stmt_ElseIf:{
Stmt_ElseIf *node = (Stmt_ElseIf *)in;
printf("else if ");
expr_print(node->condition);
ast_print((AST *)node->body);
}break;
case AST_Stmt_If:{
Stmt_If *node = (Stmt_If *)in;
printf("if ");
expr_print(node->condition);
ast_print((AST *)node->body);
AST_IterT(node, n, AST){
ast_print(n);
}
}break;
case AST_Stmt_For:{
Stmt_For *node = (Stmt_For *)in;
printf("for(");
if(node->on_begin) ast_print(node->on_begin);
printf(";");
if(node->condition) expr_print(node->condition);
printf(";");
if(node->on_iter) ast_print(node->on_iter);
printf(")");
ast_print((AST *)node->body);
}break;
default: {invalid_codepath;} break;
}
}