1
0
mirror of https://github.com/exaloop/codon.git synced 2025-06-03 15:03:52 +08:00
2021-09-27 14:02:44 -04:00

442 lines
14 KiB
C++

#include <string>
#include <unordered_set>
#include <vector>
#include "parser/visitors/format/format.h"
using fmt::format;
namespace seq {
namespace ast {
FormatVisitor::FormatVisitor(bool html, shared_ptr<Cache> cache)
: renderType(false), renderHTML(html), indent(0), cache(cache) {
if (renderHTML) {
header = "<html><head><link rel=stylesheet href=code.css/></head>\n<body>";
header += "<div class=code>\n";
footer = "\n</div></body></html>";
nl = "<hr>";
typeStart = "<type>";
typeEnd = "</type>";
nodeStart = "<node>";
nodeEnd = "</node>";
exprStart = "<expr>";
exprEnd = "</expr>";
commentStart = "<b>";
commentEnd = "</b>";
keywordStart = "<b class=comment>";
keywordEnd = "</b>";
space = "&nbsp";
renderType = true;
} else {
space = " ";
}
}
string FormatVisitor::transform(const ExprPtr &expr) { return transform(expr.get()); }
string FormatVisitor::transform(const Expr *expr) {
FormatVisitor v(renderHTML, cache);
if (expr)
const_cast<Expr *>(expr)->accept(v);
return v.result;
}
string FormatVisitor::transform(const StmtPtr &stmt) {
return transform(stmt.get(), 0);
}
string FormatVisitor::transform(Stmt *stmt, int indent) {
FormatVisitor v(renderHTML, cache);
v.indent = this->indent + indent;
if (stmt)
stmt->accept(v);
return (stmt && stmt->getSuite() ? "" : pad(indent)) + v.result + newline();
}
string FormatVisitor::pad(int indent) const {
string s;
for (int i = 0; i < (this->indent + indent) * 2; i++)
s += space;
return s;
}
string FormatVisitor::newline() const { return nl + "\n"; }
string FormatVisitor::keyword(const string &s) const {
return fmt::format("{}{}{}", keywordStart, s, keywordEnd);
}
/*************************************************************************************/
void FormatVisitor::visit(NoneExpr *expr) { result = renderExpr(expr, "None"); }
void FormatVisitor::visit(BoolExpr *expr) {
result = renderExpr(expr, "{}", expr->value ? "True" : "False");
}
void FormatVisitor::visit(IntExpr *expr) {
result = renderExpr(expr, "{}{}", expr->value, expr->suffix);
}
void FormatVisitor::visit(FloatExpr *expr) {
result = renderExpr(expr, "{}{}", expr->value, expr->suffix);
}
void FormatVisitor::visit(StringExpr *expr) {
result = renderExpr(expr, "\"{}\"", escape(expr->getValue()));
}
void FormatVisitor::visit(IdExpr *expr) {
result = renderExpr(expr, "{}", expr->value);
}
void FormatVisitor::visit(StarExpr *expr) {
result = renderExpr(expr, "*{}", transform(expr->what));
}
void FormatVisitor::visit(KeywordStarExpr *expr) {
result = renderExpr(expr, "**{}", transform(expr->what));
}
void FormatVisitor::visit(TupleExpr *expr) {
result = renderExpr(expr, "({})", transform(expr->items));
}
void FormatVisitor::visit(ListExpr *expr) {
result = renderExpr(expr, "[{}]", transform(expr->items));
}
void FormatVisitor::visit(InstantiateExpr *expr) {
result = renderExpr(expr, "{}[{}]", transform(expr->typeExpr),
transform(expr->typeParams));
}
void FormatVisitor::visit(StackAllocExpr *expr) {
result = renderExpr(expr, "__array__[{}]({})", transform(expr->typeExpr),
transform(expr->expr));
}
void FormatVisitor::visit(SetExpr *expr) {
result = renderExpr(expr, "{{{}}}", transform(expr->items));
}
void FormatVisitor::visit(DictExpr *expr) {
vector<string> s;
for (auto &i : expr->items)
s.push_back(fmt::format("{}: {}", transform(i.key), transform(i.value)));
result = renderExpr(expr, "{{{}}}", join(s, ", "));
}
void FormatVisitor::visit(GeneratorExpr *expr) {
string s;
for (auto &i : expr->loops) {
string cond;
for (auto &k : i.conds)
cond += fmt::format(" if {}", transform(k));
s += fmt::format("for {} in {}{}", i.vars->toString(), i.gen->toString(), cond);
}
if (expr->kind == GeneratorExpr::ListGenerator)
result = renderExpr(expr, "[{} {}]", transform(expr->expr), s);
else if (expr->kind == GeneratorExpr::SetGenerator)
result = renderExpr(expr, "{{{} {}}}", transform(expr->expr), s);
else
result = renderExpr(expr, "({} {})", transform(expr->expr), s);
}
void FormatVisitor::visit(DictGeneratorExpr *expr) {
string s;
for (auto &i : expr->loops) {
string cond;
for (auto &k : i.conds)
cond += fmt::format(" if {}", transform(k));
s += fmt::format("for {} in {}{}", i.vars->toString(), i.gen->toString(), cond);
}
result =
renderExpr(expr, "{{{}: {} {}}}", transform(expr->key), transform(expr->expr), s);
}
void FormatVisitor::visit(IfExpr *expr) {
result = renderExpr(expr, "{} if {} else {}", transform(expr->ifexpr),
transform(expr->cond), transform(expr->elsexpr));
}
void FormatVisitor::visit(UnaryExpr *expr) {
result = renderExpr(expr, "{}{}", expr->op, transform(expr->expr));
}
void FormatVisitor::visit(BinaryExpr *expr) {
result = renderExpr(expr, "({} {} {})", transform(expr->lexpr), expr->op,
transform(expr->rexpr));
}
void FormatVisitor::visit(PipeExpr *expr) {
vector<string> items;
for (auto &l : expr->items) {
if (!items.size())
items.push_back(transform(l.expr));
else
items.push_back(l.op + " " + transform(l.expr));
}
result = renderExpr(expr, "({})", join(items, " "));
}
void FormatVisitor::visit(IndexExpr *expr) {
result = renderExpr(expr, "{}[{}]", transform(expr->expr), transform(expr->index));
}
void FormatVisitor::visit(CallExpr *expr) {
vector<string> args;
for (auto &i : expr->args) {
if (i.name == "")
args.push_back(transform(i.value));
else
args.push_back(fmt::format("{}: {}", i.name, transform(i.value)));
}
result = renderExpr(expr, "{}({})", transform(expr->expr), join(args, ", "));
}
void FormatVisitor::visit(DotExpr *expr) {
result = renderExpr(expr, "{} . {}", transform(expr->expr), expr->member);
}
void FormatVisitor::visit(SliceExpr *expr) {
string s;
if (expr->start)
s += transform(expr->start);
s += ":";
if (expr->stop)
s += transform(expr->stop);
s += ":";
if (expr->step)
s += transform(expr->step);
result = renderExpr(expr, "{}", s);
}
void FormatVisitor::visit(EllipsisExpr *expr) { result = renderExpr(expr, "..."); }
void FormatVisitor::visit(PtrExpr *expr) {
result = renderExpr(expr, "__ptr__({})", transform(expr->expr));
}
void FormatVisitor::visit(LambdaExpr *expr) {
result = renderExpr(expr, "{} {}: {}", keyword("lambda"), join(expr->vars, ", "),
transform(expr->expr));
}
void FormatVisitor::visit(YieldExpr *expr) { result = renderExpr(expr, "(yield)"); }
void FormatVisitor::visit(StmtExpr *expr) {
string s;
for (int i = 0; i < expr->stmts.size(); i++)
s += format("{}{}", pad(2), transform(expr->stmts[i].get(), 2));
result = renderExpr(expr, "({}{}{}{}{})", newline(), s, newline(), pad(2),
transform(expr->expr));
}
void FormatVisitor::visit(AssignExpr *expr) {
result = renderExpr(expr, "({} := {})", transform(expr->var), transform(expr->expr));
}
void FormatVisitor::visit(SuiteStmt *stmt) {
for (int i = 0; i < stmt->stmts.size(); i++)
result += transform(stmt->stmts[i]);
if (stmt->ownBlock)
result = fmt::format("{}# block_begin{}{}{}# block_end", pad(), newline(), result,
pad());
}
void FormatVisitor::visit(BreakStmt *stmt) { result = keyword("break"); }
void FormatVisitor::visit(ContinueStmt *stmt) { result = keyword("continue"); }
void FormatVisitor::visit(ExprStmt *stmt) { result = transform(stmt->expr); }
void FormatVisitor::visit(AssignStmt *stmt) {
if (stmt->type) {
result = fmt::format("{}: {} = {}", transform(stmt->lhs), transform(stmt->type),
transform(stmt->rhs));
} else {
result = fmt::format("{} = {}", transform(stmt->lhs), transform(stmt->rhs));
}
}
void FormatVisitor::visit(AssignMemberStmt *stmt) {
result = fmt::format("{}.{} = {}", transform(stmt->lhs), stmt->member,
transform(stmt->rhs));
}
void FormatVisitor::visit(UpdateStmt *stmt) {
result = fmt::format("{} = {} # update", transform(stmt->lhs), transform(stmt->rhs));
}
void FormatVisitor::visit(DelStmt *stmt) {
result = fmt::format("{} {}", keyword("del"), transform(stmt->expr));
}
void FormatVisitor::visit(PrintStmt *stmt) {
result = fmt::format("{} {}", keyword("print"), transform(stmt->items));
}
void FormatVisitor::visit(ReturnStmt *stmt) {
result = fmt::format("{}{}", keyword("return"),
stmt->expr ? " " + transform(stmt->expr) : "");
}
void FormatVisitor::visit(YieldStmt *stmt) {
result = fmt::format("{}{}", keyword("yield"),
stmt->expr ? " " + transform(stmt->expr) : "");
}
void FormatVisitor::visit(AssertStmt *stmt) {
result = fmt::format("{} {}", keyword("assert"), transform(stmt->expr));
}
void FormatVisitor::visit(WhileStmt *stmt) {
result = fmt::format("{} {}:{}{}", keyword("while"), transform(stmt->cond), newline(),
transform(stmt->suite.get(), 1));
}
void FormatVisitor::visit(ForStmt *stmt) {
result = fmt::format("{} {} {} {}:{}{}", keyword("for"), transform(stmt->var),
keyword("in"), transform(stmt->iter), newline(),
transform(stmt->suite.get(), 1));
}
void FormatVisitor::visit(IfStmt *stmt) {
result = fmt::format("{} {}:{}{}{}", keyword("if"), transform(stmt->cond), newline(),
transform(stmt->ifSuite.get(), 1),
stmt->elseSuite ? format("{}:{}{}", keyword("else"), newline(),
transform(stmt->elseSuite.get(), 1))
: "");
}
void FormatVisitor::visit(MatchStmt *stmt) {
string s;
for (auto &c : stmt->cases)
s += fmt::format("{}{}{}{}:{}{}", pad(1), keyword("case"), transform(c.pattern),
c.guard ? " " + (keyword("case") + " " + transform(c.guard)) : "",
newline(), transform(c.suite.get(), 2));
result =
fmt::format("{} {}:{}{}", keyword("match"), transform(stmt->what), newline(), s);
}
void FormatVisitor::visit(ImportStmt *stmt) {
auto as = stmt->as.empty() ? "" : fmt::format(" {} {} ", keyword("as"), stmt->as);
if (!stmt->what)
result += fmt::format("{} {}{}", keyword("import"), transform(stmt->from), as);
else
result += fmt::format("{} {} {} {}{}", keyword("from"), transform(stmt->from),
keyword("import"), transform(stmt->what), as);
}
void FormatVisitor::visit(TryStmt *stmt) {
vector<string> catches;
for (auto &c : stmt->catches) {
catches.push_back(
fmt::format("{} {}{}:{}{}", keyword("catch"), transform(c.exc),
c.var == "" ? "" : fmt::format("{} {}", keyword("as"), c.var),
newline(), transform(c.suite.get(), 1)));
}
result =
fmt::format("{}:{}{}{}{}", keyword("try"), newline(),
transform(stmt->suite.get(), 1), fmt::join(catches, ""),
stmt->finally ? fmt::format("{}:{}{}", keyword("finally"), newline(),
transform(stmt->finally.get(), 1))
: "");
}
void FormatVisitor::visit(GlobalStmt *stmt) {
result = fmt::format("{} {}", keyword("global"), stmt->var);
}
void FormatVisitor::visit(ThrowStmt *stmt) {
result = fmt::format("{} {}", keyword("raise"), transform(stmt->expr));
}
void FormatVisitor::visit(FunctionStmt *fstmt) {
if (cache) {
if (in(cache->functions, fstmt->name)) {
if (!cache->functions[fstmt->name].realizations.empty()) {
for (auto &real : cache->functions[fstmt->name].realizations) {
if (real.first != fstmt->name) {
result += transform(real.second->ast.get(), 0);
}
}
return;
}
fstmt = cache->functions[fstmt->name].ast.get();
}
}
// if (cache && cache->functions.find(fstmt->name) != cache->realizationAsts.end())
// {
// fstmt = (const FunctionStmt *)(cache->realizationAsts[fstmt->name].get());
// } else if (cache && cache->functions[fstmt->name].realizations.size()) {
// for (auto &real : cache->functions[fstmt->name].realizations)
// result += transform(real.second.ast);
// return;
// } else if (cache) {
// fstmt = cache->functions[fstmt->name].ast.get();
// }
vector<string> attrs;
for (auto &a : fstmt->decorators)
attrs.push_back(fmt::format("@{}", transform(a)));
if (!fstmt->attributes.module.empty())
attrs.push_back(fmt::format("@module:{}", fstmt->attributes.parentClass));
if (!fstmt->attributes.parentClass.empty())
attrs.push_back(fmt::format("@parent:{}", fstmt->attributes.parentClass));
vector<string> args;
for (auto &a : fstmt->args)
args.push_back(fmt::format(
"{}{}{}", a.name, a.type ? fmt::format(": {}", transform(a.type)) : "",
a.deflt ? fmt::format(" = {}", transform(a.deflt)) : ""));
auto body = transform(fstmt->suite.get(), 1);
auto name = fmt::format("{}{}{}", typeStart, fstmt->name, typeEnd);
name = fmt::format("{}{}{}", exprStart, name, exprEnd);
result += fmt::format(
"{}{} {}({}){}:{}{}",
attrs.size() ? join(attrs, newline() + pad()) + newline() + pad() : "",
keyword("def"), name, fmt::join(args, ", "),
fstmt->ret ? fmt::format(" -> {}", transform(fstmt->ret)) : "", newline(),
body.empty() ? fmt::format("{}", keyword("pass")) : body);
}
void FormatVisitor::visit(ClassStmt *stmt) {
// if (cache &&
// cache->realizationAsts.find(fstmt->name) != cache->realizationAsts.end()) {
// fstmt = (const FunctionStmt *)(cache->realizationAsts[fstmt->name].get());
// } else if (cache) {
// for (auto &real : cache->realizations[fstmt->name])
// result += simplify(cache->realizationAsts[real.first]);
// return;
// }
vector<string> attrs;
if (!stmt->attributes.has(Attr::Extend))
attrs.push_back("@extend");
if (!stmt->attributes.has(Attr::Tuple))
attrs.push_back("@tuple");
vector<string> args;
string key = stmt->isRecord() ? "type" : "class";
for (auto &a : stmt->args)
args.push_back(fmt::format("{}: {}", a.name, transform(a.type)));
result = fmt::format("{}{} {}({})",
attrs.size() ? join(attrs, newline() + pad()) + newline() + pad()
: "",
keyword(key), stmt->name, fmt::join(args, ", "));
if (stmt->suite)
result += fmt::format(":{}{}", newline(), transform(stmt->suite.get(), 1));
}
void FormatVisitor::visit(YieldFromStmt *stmt) {
result = fmt::format("{} {}", keyword("yield from"), transform(stmt->expr));
}
void FormatVisitor::visit(WithStmt *stmt) {}
} // namespace ast
} // namespace seq