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");
|
2019-09-25 03:26:30 +00:00
|
|
|
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) {
|
|
|
|
std.debug.warn("\t");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
std.debug.warn("(\n");
|
|
|
|
|
|
|
|
for (block.toSlice()) |stmt| {
|
|
|
|
printIdent(ident);
|
2019-09-18 19:53:44 +00:00
|
|
|
printStmt(ident, &stmt);
|
2019-09-18 18:59:11 +00:00
|
|
|
std.debug.warn("\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (method.mutable) {
|
2019-09-20 16:36:15 +00:00
|
|
|
warn("(method mut {} {} {} {} (", vari, typ, name, ret_type);
|
2019-09-18 18:59:11 +00:00
|
|
|
} else {
|
2019-09-20 16:36:15 +00:00
|
|
|
warn("(method {} {} {} {} (", vari, typ, name, ret_type);
|
2019-09-18 18:59:11 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
warn("(fn {} {} (", name, ret_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (decl.params.toSlice()) |param| {
|
2019-09-20 16:36:15 +00:00
|
|
|
warn(" ({} {})", param.name.lexeme, param.typ.lexeme);
|
2019-09-18 18:59:11 +00:00
|
|
|
}
|
2019-09-20 16:36:15 +00:00
|
|
|
warn(") ");
|
2019-09-18 18:59:11 +00:00
|
|
|
|
|
|
|
printBlock(ident + 1, decl.body, false);
|
2019-09-20 16:36:15 +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);
|
|
|
|
std.debug.warn(")\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
.Stmt => |stmt| {
|
|
|
|
printIdent(ident);
|
|
|
|
printStmt(ident, stmt);
|
|
|
|
std.debug.warn("\n");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Struct => |struc| {
|
|
|
|
print(ident, "(struct {} (\n", struc.name.lexeme);
|
|
|
|
for (struc.fields.toSlice()) |field| {
|
|
|
|
printIdent(ident + 1);
|
|
|
|
if (field.mutable) {
|
|
|
|
std.debug.warn("(mut ");
|
|
|
|
} else {
|
|
|
|
std.debug.warn("(");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (field.public) {
|
|
|
|
std.debug.warn("pub ");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (field.mutable_outside) {
|
|
|
|
std.debug.warn("MUT_OUT ");
|
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn("{} {})\n", field.name.lexeme, field.typ.lexeme);
|
|
|
|
}
|
|
|
|
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 {
|
2019-09-18 18:59:11 +00:00
|
|
|
std.debug.warn("({}", name);
|
|
|
|
|
|
|
|
for (exprs) |expr| {
|
|
|
|
std.debug.warn(" ");
|
2019-09-18 19:53:44 +00:00
|
|
|
printExpr(&expr);
|
2019-09-18 18:59:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn(")");
|
|
|
|
}
|
|
|
|
|
2019-09-18 19:53:44 +00:00
|
|
|
fn printTwoExprs(expr_a: *const Expr, expr_b: *const Expr) void {
|
|
|
|
std.debug.warn(" ");
|
|
|
|
printExpr(expr_a);
|
|
|
|
std.debug.warn(" ");
|
|
|
|
printExpr(expr_b);
|
|
|
|
}
|
|
|
|
|
2019-09-24 02:18:31 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-09-24 16:23:23 +00:00
|
|
|
fn printBinOp(inner: var) void {
|
|
|
|
std.debug.warn("({}", binOpToStr(inner.op));
|
2019-09-18 19:53:44 +00:00
|
|
|
printTwoExprs(inner.left, inner.right);
|
|
|
|
std.debug.warn(")");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn printSingleOp(tok: []const u8, applied: *const Expr) void {
|
|
|
|
std.debug.warn("({}", tok);
|
|
|
|
printExpr(applied);
|
|
|
|
std.debug.warn(")");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn printExpr(expr: *const Expr) void {
|
2019-09-18 18:59:11 +00:00
|
|
|
switch (expr.*) {
|
2019-09-24 16:23:23 +00:00
|
|
|
.Binary => |binary| printBinOp(binary),
|
2019-09-18 19:53:44 +00:00
|
|
|
|
|
|
|
.Unary => |unary| printSingleOp(unary.op.lexeme, unary.right),
|
|
|
|
.Grouping => |expr_ptr| printSingleOp("group", expr_ptr),
|
2019-09-18 18:59:11 +00:00
|
|
|
|
|
|
|
.Literal => |literal| {
|
|
|
|
switch (literal) {
|
|
|
|
.Bool => |val| std.debug.warn("{}", val),
|
|
|
|
.Integer => |val| std.debug.warn("{}", val),
|
|
|
|
.Float => |val| std.debug.warn("{}", val),
|
|
|
|
.String => |val| std.debug.warn("'{}'", val),
|
|
|
|
.Array => |exprs| {
|
|
|
|
parenthetize("array", exprs.toSlice());
|
|
|
|
},
|
|
|
|
else => |typ| std.debug.warn("UnknownLiteral-{}", typ),
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
.Variable => |token| std.debug.warn("{}", token.lexeme),
|
|
|
|
|
|
|
|
.VarDecl => |decl| {
|
|
|
|
if (decl.mutable) {
|
|
|
|
std.debug.warn("(mut ");
|
|
|
|
} else {
|
|
|
|
std.debug.warn("(");
|
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn("let {} ", decl.assign.name.lexeme);
|
|
|
|
printExpr(decl.assign.value);
|
|
|
|
std.debug.warn(")");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Assign => |assign| {
|
|
|
|
std.debug.warn("(set ");
|
|
|
|
std.debug.warn("{} ", assign.name.lexeme);
|
|
|
|
printExpr(assign.value);
|
|
|
|
std.debug.warn(")");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Call => |call| {
|
|
|
|
std.debug.warn("(");
|
|
|
|
printExpr(call.callee);
|
|
|
|
|
|
|
|
for (call.arguments.toSlice()) |arg| {
|
|
|
|
std.debug.warn(" ");
|
2019-09-18 19:53:44 +00:00
|
|
|
printExpr(&arg);
|
2019-09-18 18:59:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn(")");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Struct => |val| {
|
|
|
|
std.debug.warn("({} (", val.name.lexeme);
|
|
|
|
|
|
|
|
for (val.inits.toSlice()) |init| {
|
|
|
|
std.debug.warn(" ({} ", init.field.lexeme);
|
|
|
|
printExpr(init.expr);
|
|
|
|
std.debug.warn(")");
|
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn("))");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Get => |get| {
|
|
|
|
warn("(");
|
|
|
|
printExpr(get.struc);
|
|
|
|
warn(".{})", get.name.lexeme);
|
|
|
|
},
|
|
|
|
|
|
|
|
.Set => |set| {
|
|
|
|
warn("(set ");
|
|
|
|
printExpr(set.struc);
|
|
|
|
warn(" {} ", set.field.lexeme);
|
|
|
|
printExpr(set.value);
|
|
|
|
warn(")");
|
|
|
|
},
|
|
|
|
|
|
|
|
else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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.*) {
|
2019-09-18 19:53:44 +00:00
|
|
|
.Println => |expr| printSingleOp("println", expr),
|
2019-09-18 18:59:11 +00:00
|
|
|
.Expr => |expr| printExpr(expr),
|
|
|
|
|
|
|
|
.If => |ifstmt| {
|
|
|
|
std.debug.warn("(if ");
|
|
|
|
printExpr(ifstmt.condition);
|
|
|
|
std.debug.warn(" ");
|
|
|
|
|
|
|
|
printBlock(ident + 1, ifstmt.then_branch, false);
|
|
|
|
if (ifstmt.else_branch) |else_branch| {
|
|
|
|
std.debug.warn(" else ");
|
|
|
|
printBlock(ident + 1, else_branch, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn(")\n");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Loop => |loop| {
|
|
|
|
std.debug.warn("(loop ");
|
|
|
|
if (loop.condition) |cond| {
|
|
|
|
printExpr(cond);
|
|
|
|
} else {
|
|
|
|
std.debug.warn("true");
|
|
|
|
}
|
|
|
|
std.debug.warn(" ");
|
|
|
|
|
|
|
|
printBlock(ident + 1, loop.then_branch, false);
|
|
|
|
std.debug.warn(")\n");
|
|
|
|
},
|
|
|
|
|
|
|
|
.For => |forstmt| {
|
|
|
|
std.debug.warn("(for ");
|
|
|
|
|
|
|
|
if (forstmt.index) |index| {
|
|
|
|
std.debug.warn("({} {}) ", index.lexeme, forstmt.value.lexeme);
|
|
|
|
} else {
|
|
|
|
std.debug.warn("{} ", forstmt.value.lexeme);
|
|
|
|
}
|
|
|
|
|
|
|
|
std.debug.warn("{} ", forstmt.array.lexeme);
|
|
|
|
|
|
|
|
printBlock(ident + 1, forstmt.block, false);
|
|
|
|
std.debug.warn(")\n");
|
|
|
|
},
|
|
|
|
|
|
|
|
.Return => |ret| {
|
|
|
|
std.debug.warn("(return ");
|
|
|
|
printExpr(ret.value);
|
|
|
|
std.debug.warn(")\n");
|
|
|
|
},
|
|
|
|
|
|
|
|
else => std.debug.warn("UnknownStmt-{}", @tagName(stmt.*)),
|
|
|
|
}
|
|
|
|
}
|
2019-09-25 03:26:30 +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",
|
|
|
|
|
|
|
|
.OpaqueType => |ident| retWithName("opaque", ident),
|
|
|
|
.Struct => |ident| retWithName("struct", ident),
|
|
|
|
|
|
|
|
else => unreachable,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
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),
|
|
|
|
);
|
|
|
|
|
2019-09-25 13:53:10 +00:00
|
|
|
for (fn_sym.decl.params.toSlice()) |param| {
|
|
|
|
var param_kv = fn_sym.parameters.get(param.name.lexeme).?;
|
2019-09-25 03:26:30 +00:00
|
|
|
std.debug.warn(
|
|
|
|
"\tparameter {} typ {}\n",
|
|
|
|
param_kv.key,
|
|
|
|
prettyType(param_kv.value),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
.Struct => |typemap| {
|
|
|
|
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,
|
|
|
|
),
|
|
|
|
else => unreachable,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|