rayoko/src/ast_printer.zig

427 lines
11 KiB
Zig
Raw Normal View History

2019-09-18 18:59:11 +00:00
const std = @import("std");
const tokens = @import("tokens.zig");
const Token = tokens.Token;
usingnamespace @import("ast.zig");
usingnamespace @import("comp_ctx.zig");
2019-09-18 18:59:11 +00:00
const warn = std.debug.warn;
fn printIdent(ident: usize) void {
var i: usize = 0;
while (i < ident) : (i += 1) {
2020-04-01 19:03:46 +00:00
std.debug.warn("\t", .{});
2019-09-18 18:59:11 +00:00
}
}
fn print(ident: usize, comptime fmt: []const u8, args: ...) void {
printIdent(ident);
std.debug.warn(fmt, args);
}
fn printBlock(ident: usize, block: var, endNewline: bool) void {
2020-04-01 19:03:46 +00:00
std.debug.warn("(\n", .{});
2019-09-18 18:59:11 +00:00
for (block.toSlice()) |stmt| {
printIdent(ident);
2019-09-18 19:53:44 +00:00
printStmt(ident, &stmt);
2020-04-01 19:03:46 +00:00
std.debug.warn("\n", .{});
2019-09-18 18:59:11 +00:00
}
if (endNewline) {
print(ident - 1, ")\n");
} else {
print(ident - 1, ")");
}
}
2019-09-18 19:53:44 +00:00
pub fn printNode(node: *const Node, ident: usize) void {
2019-09-18 18:59:11 +00:00
switch (node.*) {
.FnDecl => |decl| {
const name = decl.func_name.lexeme;
printIdent(ident);
const ret_type = decl.return_type.lexeme;
if (decl.method) |method| {
const vari = method.variable.lexeme;
const typ = method.typ.lexeme;
2020-04-01 19:03:46 +00:00
warn("(method {} {} {} {} (", .{ vari, typ, name, ret_type });
2019-09-18 18:59:11 +00:00
} else {
2020-04-01 19:03:46 +00:00
warn("(fn {} {} (", .{ name, ret_type });
2019-09-18 18:59:11 +00:00
}
for (decl.params.toSlice()) |param| {
2020-04-01 19:03:46 +00:00
warn(" ({} {})", .{ param.name.lexeme, param.typ.lexeme });
2019-09-18 18:59:11 +00:00
}
2020-04-01 19:03:46 +00:00
warn(") ", .{});
2019-09-18 18:59:11 +00:00
printBlock(ident + 1, decl.body, false);
2020-04-01 19:03:46 +00:00
warn("\n", .{});
2019-09-18 18:59:11 +00:00
},
.ConstDecl => |consts| {
print(ident, "(const (\n");
for (consts.toSlice()) |const_decl| {
print(
ident + 1,
"({} ",
const_decl.name.lexeme,
);
printExpr(const_decl.expr);
2020-04-01 19:03:46 +00:00
std.debug.warn(")\n", .{});
2019-09-18 18:59:11 +00:00
}
print(ident, "))\n");
},
.Enum => |decl| {
print(ident, "(enum {} (\n", decl.name.lexeme);
for (decl.fields.toSlice()) |field| {
print(
ident + 1,
"{}\n",
field.lexeme,
);
}
print(ident, "))\n");
},
.Root => {
for (node.Root.toSlice()) |child| {
2019-09-18 19:53:44 +00:00
printNode(&child, ident + 1);
2019-09-18 18:59:11 +00:00
}
},
.Struct => |struc| {
print(ident, "(struct {} (\n", struc.name.lexeme);
for (struc.fields.toSlice()) |field| {
print(ident + 1, "({} {})\n", field.name.lexeme, field.typ.lexeme);
2019-09-18 18:59:11 +00:00
}
print(ident, "))\n");
},
else => {
print(ident, "unknown node: {}\n", node);
},
}
}
2019-09-18 19:53:44 +00:00
fn parenthetize(name: []const u8, exprs: []const Expr) void {
2020-04-01 19:03:46 +00:00
std.debug.warn("({}", .{name});
2019-09-18 18:59:11 +00:00
for (exprs) |expr| {
2020-04-01 19:03:46 +00:00
std.debug.warn(" ", .{});
2019-09-18 19:53:44 +00:00
printExpr(&expr);
2019-09-18 18:59:11 +00:00
}
2020-04-01 19:03:46 +00:00
std.debug.warn(")", .{});
2019-09-18 18:59:11 +00:00
}
2019-09-18 19:53:44 +00:00
fn printTwoExprs(expr_a: *const Expr, expr_b: *const Expr) void {
2020-04-01 19:03:46 +00:00
std.debug.warn(" ", .{});
2019-09-18 19:53:44 +00:00
printExpr(expr_a);
2020-04-01 19:03:46 +00:00
std.debug.warn(" ", .{});
2019-09-18 19:53:44 +00:00
printExpr(expr_b);
}
const operator_tokens = [_][]const u8{
"+", "-", "*", "/", "%", ">", ">=", "<", "<=", "==", "&&", "||",
};
const operator_values = [_]BinaryOperator{
.Add,
.Sub,
.Mul,
.Div,
.Mod,
.Greater,
.GreaterEqual,
.Less,
.LessEqual,
.Equal,
.And,
.Or,
};
fn binOpToStr(op: BinaryOperator) ?[]const u8 {
inline for (operator_values) |val, idx| {
if (val == op) return operator_tokens[idx];
}
return null;
}
fn printBinOp(inner: var) void {
2020-04-01 19:03:46 +00:00
std.debug.warn("({}", .{binOpToStr(inner.op)});
2019-09-18 19:53:44 +00:00
printTwoExprs(inner.left, inner.right);
2020-04-01 19:03:46 +00:00
std.debug.warn(")", .{});
2019-09-18 19:53:44 +00:00
}
const unary_operator_tokens = [_][]const u8{
"!", "-",
};
const unary_operators = [_]UnaryOperator{
.Not, .Negate,
};
fn unOpToStr(op: UnaryOperator) ?[]const u8 {
inline for (unary_operators) |val, idx| {
if (val == op) return unary_operator_tokens[idx];
}
return null;
}
fn printSingleOp(op: UnaryOperator, applied: *const Expr) void {
printSimpleOp(unOpToStr(op), applied);
}
fn printSimpleOp(op: ?[]const u8, applied: *const Expr) void {
2020-04-01 19:03:46 +00:00
std.debug.warn("({}", .{op});
2019-09-18 19:53:44 +00:00
printExpr(applied);
2020-04-01 19:03:46 +00:00
std.debug.warn(")", .{});
2019-09-18 19:53:44 +00:00
}
pub fn printExpr(expr: *const Expr) void {
2019-09-18 18:59:11 +00:00
switch (expr.*) {
.Binary => |binary| printBinOp(binary),
2019-09-18 19:53:44 +00:00
.Unary => |unary| printSingleOp(unary.op, unary.right),
.Grouping => |expr_ptr| printSimpleOp("group", expr_ptr),
2019-09-18 18:59:11 +00:00
.Literal => |literal| {
switch (literal) {
2020-04-01 19:03:46 +00:00
.Bool => |val| std.debug.warn("{}", .{val}),
.Integer32 => |val| std.debug.warn("{}", .{val}),
.Integer64 => |val| std.debug.warn("{}", .{val}),
.Float => |val| std.debug.warn("{}", .{val}),
.String => |val| std.debug.warn("'{}'", .{val}),
2019-09-18 18:59:11 +00:00
.Array => |exprs| {
parenthetize("array", exprs.toSlice());
},
2020-04-01 19:03:46 +00:00
else => |typ| std.debug.warn("UnknownLiteral-{}", .{typ}),
2019-09-18 18:59:11 +00:00
}
},
2020-04-01 19:03:46 +00:00
.Variable => |token| std.debug.warn("{}", .{token.lexeme}),
2019-09-18 18:59:11 +00:00
.Assign => |assign| {
2020-04-01 19:03:46 +00:00
std.debug.warn("(set ", .{});
std.debug.warn("{} ", .{assign.name.lexeme});
2019-09-18 18:59:11 +00:00
printExpr(assign.value);
2020-04-01 19:03:46 +00:00
std.debug.warn(")", .{});
2019-09-18 18:59:11 +00:00
},
.Call => |call| {
2020-04-01 19:03:46 +00:00
std.debug.warn("(", .{});
2019-09-18 18:59:11 +00:00
printExpr(call.callee);
for (call.arguments.toSlice()) |arg| {
2020-04-01 19:03:46 +00:00
std.debug.warn(" ", .{});
2019-09-18 19:53:44 +00:00
printExpr(&arg);
2019-09-18 18:59:11 +00:00
}
2020-04-01 19:03:46 +00:00
std.debug.warn(")", .{});
2019-09-18 18:59:11 +00:00
},
.Struct => |val| {
2020-04-01 19:03:46 +00:00
std.debug.warn("({} (", .{val.name.lexeme});
2019-09-18 18:59:11 +00:00
for (val.inits.toSlice()) |init| {
2020-04-01 19:03:46 +00:00
std.debug.warn(" ({} ", .{init.field.lexeme});
2019-09-18 18:59:11 +00:00
printExpr(init.expr);
2020-04-01 19:03:46 +00:00
std.debug.warn(")", .{});
2019-09-18 18:59:11 +00:00
}
2020-04-01 19:03:46 +00:00
std.debug.warn("))", .{});
2019-09-18 18:59:11 +00:00
},
.Get => |get| {
2020-04-01 19:03:46 +00:00
warn("(", .{});
printExpr(get.target);
2019-09-18 18:59:11 +00:00
warn(".{})", get.name.lexeme);
},
.Set => |set| {
2020-04-01 19:03:46 +00:00
warn("(set ", .{});
2019-09-18 18:59:11 +00:00
printExpr(set.struc);
2020-04-01 19:03:46 +00:00
warn(" {} ", .{set.field.lexeme});
2019-09-18 18:59:11 +00:00
printExpr(set.value);
2020-04-01 19:03:46 +00:00
warn(")", .{});
2019-09-18 18:59:11 +00:00
},
2020-04-01 19:03:46 +00:00
else => std.debug.warn("UnknownExpr-{}", .{@tagName(expr.*)}),
2019-09-18 18:59:11 +00:00
}
}
2019-09-18 19:53:44 +00:00
pub fn printStmt(ident: usize, stmt: *const Stmt) void {
2019-09-18 18:59:11 +00:00
switch (stmt.*) {
.Println => |expr| printSimpleOp("println", expr),
2019-09-18 18:59:11 +00:00
.Expr => |expr| printExpr(expr),
.VarDecl => |decl| {
2020-04-01 19:03:46 +00:00
std.debug.warn("(let {} ", .{decl.name.lexeme});
printExpr(decl.value);
2020-04-01 19:03:46 +00:00
std.debug.warn(")", .{});
},
2019-09-18 18:59:11 +00:00
.If => |ifstmt| {
2020-04-01 19:03:46 +00:00
std.debug.warn("(if ", .{});
2019-09-18 18:59:11 +00:00
printExpr(ifstmt.condition);
2020-04-01 19:03:46 +00:00
std.debug.warn(" ", .{});
2019-09-18 18:59:11 +00:00
printBlock(ident + 1, ifstmt.then_branch, false);
if (ifstmt.else_branch) |else_branch| {
2020-04-01 19:03:46 +00:00
std.debug.warn(" else ", .{});
2019-09-18 18:59:11 +00:00
printBlock(ident + 1, else_branch, false);
}
2020-04-01 19:03:46 +00:00
std.debug.warn(")\n", .{});
2019-09-18 18:59:11 +00:00
},
.Loop => |loop| {
2020-04-01 19:03:46 +00:00
std.debug.warn("(loop ", .{});
2019-09-18 18:59:11 +00:00
if (loop.condition) |cond| {
printExpr(cond);
} else {
2020-04-01 19:03:46 +00:00
std.debug.warn("true", .{});
2019-09-18 18:59:11 +00:00
}
2020-04-01 19:03:46 +00:00
std.debug.warn(" ", .{});
2019-09-18 18:59:11 +00:00
printBlock(ident + 1, loop.then_branch, false);
2020-04-01 19:03:46 +00:00
std.debug.warn(")\n", .{});
2019-09-18 18:59:11 +00:00
},
.For => |forstmt| {
2020-04-01 19:03:46 +00:00
std.debug.warn("(for ", .{});
2019-09-18 18:59:11 +00:00
if (forstmt.index) |index| {
2020-04-01 19:03:46 +00:00
std.debug.warn("({} {}) ", .{ index.lexeme, forstmt.value.lexeme });
2019-09-18 18:59:11 +00:00
} else {
2020-04-01 19:03:46 +00:00
std.debug.warn("{} ", .{forstmt.value.lexeme});
2019-09-18 18:59:11 +00:00
}
2020-04-01 19:03:46 +00:00
std.debug.warn("{} ", .{forstmt.array.lexeme});
2019-09-18 18:59:11 +00:00
printBlock(ident + 1, forstmt.block, false);
2020-04-01 19:03:46 +00:00
std.debug.warn(")\n", .{});
2019-09-18 18:59:11 +00:00
},
.Return => |ret| {
2020-04-01 19:03:46 +00:00
std.debug.warn("(return ", .{});
2019-09-18 18:59:11 +00:00
printExpr(ret.value);
2020-04-01 19:03:46 +00:00
std.debug.warn(")\n", .{});
2019-09-18 18:59:11 +00:00
},
2020-04-01 19:03:46 +00:00
else => std.debug.warn("UnknownStmt-{}", .{@tagName(stmt.*)}),
2019-09-18 18:59:11 +00:00
}
}
// very bad but be like that
fn retWithName(prefix: []const u8, inner: []const u8) []const u8 {
var ret_nam_buf = std.heap.direct_allocator.alloc(u8, 256) catch unreachable;
return std.fmt.bufPrint(ret_nam_buf[0..], "{}({})", prefix, inner) catch unreachable;
}
fn prettyType(typ: SymbolUnderlyingType) []const u8 {
return switch (typ) {
.Integer32 => "i32",
.Integer64 => "i64",
.Bool => "bool",
.Double => "double",
.OpaqueType => |ident| retWithName("opaque", ident),
.Struct => |ident| retWithName("struct", ident),
2019-09-25 14:59:36 +00:00
.Enum => |ident| retWithName("enum", ident),
};
}
pub fn printScope(scope: *Scope, ident: usize) void {
print(ident, "scope '{}' at addr {}\n", scope.id, @ptrToInt(scope));
var it = scope.env.iterator();
while (it.next()) |kv| {
print(ident + 1, "sym: {}, typ: {}\n", kv.key, prettyType(kv.value));
}
for (scope.children.toSlice()) |child| {
printScope(child, ident + 1);
}
}
pub fn printContext(ctx: CompilationContext) void {
var it = ctx.symbol_table.iterator();
while (it.next()) |kv| {
switch (kv.value.*) {
.Function => |fn_sym| {
std.debug.warn(
"function {} returns {}\n",
kv.key,
prettyType(fn_sym.return_type),
);
for (fn_sym.decl.params.toSlice()) |param| {
var param_kv = fn_sym.parameters.get(param.name.lexeme).?;
std.debug.warn(
"\tparameter {} typ {}\n",
param_kv.key,
prettyType(param_kv.value.typ),
);
}
// go through scopes
2020-04-01 19:03:46 +00:00
std.debug.warn("scope info:\n", .{});
printScope(fn_sym.scope, 1);
},
.Struct => |typemap| {
2020-04-01 19:03:46 +00:00
std.debug.warn("struct '{}'\n", .{kv.key});
var map_it = typemap.iterator();
while (map_it.next()) |map_kv| {
std.debug.warn(
"\tfield {} type {}\n",
map_kv.key,
prettyType(map_kv.value),
);
}
},
.Variable => std.debug.warn(
"variable {} type {}\n",
kv.key,
kv.value,
),
2019-09-25 14:59:36 +00:00
.Enum => |identmap| {
2020-04-01 19:03:46 +00:00
std.debug.warn("enum {}:", .{kv.key});
2019-09-25 14:59:36 +00:00
var mapit = identmap.iterator();
while (mapit.next()) |field_kv| {
2020-04-01 19:03:46 +00:00
std.debug.warn("\t{} => {}\n", .{ field_kv.key, field_kv.value });
2019-09-25 14:59:36 +00:00
}
},
.Const => |typ| {
2020-04-01 19:03:46 +00:00
std.debug.warn("const '{}', typ={}\n", .{ kv.key, prettyType(typ) });
},
2019-09-25 14:59:36 +00:00
else => {
2020-04-01 19:03:46 +00:00
std.debug.warn("TODO handle print of {}\n", .{kv.value});
2019-09-25 14:59:36 +00:00
unreachable;
},
}
}
}