mirror of https://github.com/exaloop/codon
Merge branch 'ir-annotations' into auto-class-deduction
commit
6561294672
|
@ -9,6 +9,8 @@
|
|||
#include "codon/parser/visitors/simplify/simplify.h"
|
||||
#include "codon/parser/visitors/translate/translate.h"
|
||||
#include "codon/parser/visitors/typecheck/typecheck.h"
|
||||
#include "codon/sir/util/irtools.h"
|
||||
#include "codon/sir/util/operator.h"
|
||||
|
||||
namespace codon {
|
||||
|
||||
|
|
|
@ -108,7 +108,6 @@ llvm::Expected<std::string> JIT::exec(const std::string &code) {
|
|||
auto sctx = cache->imports[MAIN_IMPORT].ctx;
|
||||
auto preamble = std::make_shared<ast::SimplifyVisitor::Preamble>();
|
||||
|
||||
|
||||
ast::Cache bCache = *cache;
|
||||
ast::SimplifyContext bSimplify = *sctx;
|
||||
ast::TypeContext bType = *(cache->typeCtx);
|
||||
|
|
|
@ -46,9 +46,8 @@ std::string StaticValue::toString() const {
|
|||
return "";
|
||||
if (!evaluated)
|
||||
return type == StaticValue::STRING ? "str" : "int";
|
||||
return type == StaticValue::STRING
|
||||
? "'" + escape(std::get<std::string>(value)) + "'"
|
||||
: std::to_string(std::get<int64_t>(value));
|
||||
return type == StaticValue::STRING ? "'" + escape(std::get<std::string>(value)) + "'"
|
||||
: std::to_string(std::get<int64_t>(value));
|
||||
}
|
||||
int64_t StaticValue::getInt() const {
|
||||
seqassert(type == StaticValue::INT, "not an int");
|
||||
|
@ -398,11 +397,14 @@ StmtExpr::StmtExpr(std::shared_ptr<Stmt> stmt, std::shared_ptr<Stmt> stmt2,
|
|||
stmts.push_back(std::move(stmt2));
|
||||
}
|
||||
StmtExpr::StmtExpr(const StmtExpr &expr)
|
||||
: Expr(expr), stmts(ast::clone(expr.stmts)), expr(ast::clone(expr.expr)) {}
|
||||
: Expr(expr), stmts(ast::clone(expr.stmts)), expr(ast::clone(expr.expr)),
|
||||
attributes(expr.attributes) {}
|
||||
std::string StmtExpr::toString() const {
|
||||
return wrapType(format("stmt-expr ({}) {}", combine(stmts, " "), expr->toString()));
|
||||
}
|
||||
ACCEPT_IMPL(StmtExpr, ASTVisitor);
|
||||
bool StmtExpr::hasAttr(const std::string &attr) const { return in(attributes, attr); }
|
||||
void StmtExpr::setAttr(const std::string &attr) { attributes.insert(attr); }
|
||||
|
||||
PtrExpr::PtrExpr(ExprPtr expr) : Expr(), expr(std::move(expr)) {}
|
||||
PtrExpr::PtrExpr(const PtrExpr &expr) : Expr(expr), expr(ast::clone(expr.expr)) {}
|
||||
|
|
|
@ -600,6 +600,8 @@ struct RangeExpr : public Expr {
|
|||
struct StmtExpr : public Expr {
|
||||
std::vector<std::shared_ptr<Stmt>> stmts;
|
||||
ExprPtr expr;
|
||||
/// Set of attributes.
|
||||
std::set<std::string> attributes;
|
||||
|
||||
StmtExpr(std::vector<std::shared_ptr<Stmt>> stmts, ExprPtr expr);
|
||||
StmtExpr(std::shared_ptr<Stmt> stmt, ExprPtr expr);
|
||||
|
@ -610,6 +612,10 @@ struct StmtExpr : public Expr {
|
|||
ACCEPT(ASTVisitor);
|
||||
|
||||
const StmtExpr *getStmtExpr() const override { return this; }
|
||||
|
||||
/// Attribute helpers
|
||||
bool hasAttr(const std::string &attr) const;
|
||||
void setAttr(const std::string &attr);
|
||||
};
|
||||
|
||||
/// Pointer expression (__ptr__(expr)).
|
||||
|
|
|
@ -42,6 +42,7 @@ std::string SuiteStmt::toString(int indent) const {
|
|||
}
|
||||
ACCEPT_IMPL(SuiteStmt, ASTVisitor);
|
||||
void SuiteStmt::flatten(StmtPtr s, std::vector<StmtPtr> &stmts) {
|
||||
// WARNING: does not preserve attributes!
|
||||
if (!s)
|
||||
return;
|
||||
auto suite = const_cast<SuiteStmt *>(s->getSuite());
|
||||
|
|
|
@ -170,7 +170,6 @@ struct Cache : public std::enable_shared_from_this<Cache> {
|
|||
/// corresponding Function instance.
|
||||
std::unordered_map<std::string, Function> functions;
|
||||
|
||||
|
||||
struct Overload {
|
||||
/// Canonical name of an overload (e.g. Foo.__init__.1).
|
||||
std::string name;
|
||||
|
@ -189,6 +188,9 @@ struct Cache : public std::enable_shared_from_this<Cache> {
|
|||
std::shared_ptr<TranslateContext> codegenCtx;
|
||||
/// Set of function realizations that are to be translated to IR.
|
||||
std::set<std::pair<std::string, std::string>> pendingRealizations;
|
||||
/// Mapping of partial record names to function pointers and corresponding masks.
|
||||
std::unordered_map<std::string, std::pair<types::FuncTypePtr, std::vector<char>>>
|
||||
partials;
|
||||
|
||||
/// Custom operators
|
||||
std::unordered_map<std::string,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "codon/parser/common.h"
|
||||
#include "codon/parser/peg/peg.h"
|
||||
#include "codon/parser/visitors/simplify/simplify.h"
|
||||
#include "codon/sir/attribute.h"
|
||||
|
||||
using fmt::format;
|
||||
|
||||
|
@ -187,7 +188,9 @@ void SimplifyVisitor::visit(ListExpr *expr) {
|
|||
N<ExprStmt>(N<CallExpr>(N<DotExpr>(clone(var), "append"), clone(it)))));
|
||||
}
|
||||
}
|
||||
resultExpr = N<StmtExpr>(stmts, transform(var));
|
||||
auto e = N<StmtExpr>(stmts, transform(var));
|
||||
e->setAttr(ir::ListLiteralAttribute::AttributeName);
|
||||
resultExpr = e;
|
||||
ctx->popBlock();
|
||||
}
|
||||
|
||||
|
@ -207,7 +210,9 @@ void SimplifyVisitor::visit(SetExpr *expr) {
|
|||
stmts.push_back(transform(
|
||||
N<ExprStmt>(N<CallExpr>(N<DotExpr>(clone(var), "add"), clone(it)))));
|
||||
}
|
||||
resultExpr = N<StmtExpr>(stmts, transform(var));
|
||||
auto e = N<StmtExpr>(stmts, transform(var));
|
||||
e->setAttr(ir::SetLiteralAttribute::AttributeName);
|
||||
resultExpr = e;
|
||||
ctx->popBlock();
|
||||
}
|
||||
|
||||
|
@ -229,7 +234,9 @@ void SimplifyVisitor::visit(DictExpr *expr) {
|
|||
stmts.push_back(transform(N<ExprStmt>(N<CallExpr>(
|
||||
N<DotExpr>(clone(var), "__setitem__"), clone(it.key), clone(it.value)))));
|
||||
}
|
||||
resultExpr = N<StmtExpr>(stmts, transform(var));
|
||||
auto e = N<StmtExpr>(stmts, transform(var));
|
||||
e->setAttr(ir::DictLiteralAttribute::AttributeName);
|
||||
resultExpr = e;
|
||||
ctx->popBlock();
|
||||
}
|
||||
|
||||
|
@ -386,14 +393,13 @@ void SimplifyVisitor::visit(IndexExpr *expr) {
|
|||
// IndexExpr[i1, ..., iN] is internally stored as IndexExpr[TupleExpr[i1, ..., iN]]
|
||||
// for N > 1, so make sure to check that case.
|
||||
|
||||
|
||||
std::vector<ExprPtr> it;
|
||||
if (auto t = index->getTuple())
|
||||
for (auto &i : t->items)
|
||||
it.push_back(i);
|
||||
else
|
||||
it.push_back(index);
|
||||
for (auto &i: it) {
|
||||
for (auto &i : it) {
|
||||
if (auto es = i->getStar())
|
||||
i = N<StarExpr>(transform(es->what));
|
||||
else if (auto ek = CAST(i, KeywordStarExpr))
|
||||
|
@ -689,7 +695,9 @@ void SimplifyVisitor::visit(StmtExpr *expr) {
|
|||
for (auto &s : expr->stmts)
|
||||
stmts.emplace_back(transform(s));
|
||||
auto e = transform(expr->expr);
|
||||
resultExpr = N<StmtExpr>(stmts, e);
|
||||
auto s = N<StmtExpr>(stmts, e);
|
||||
s->attributes = expr->attributes;
|
||||
resultExpr = s;
|
||||
}
|
||||
|
||||
/**************************************************************************************/
|
||||
|
@ -726,8 +734,8 @@ ExprPtr SimplifyVisitor::transformInt(const std::string &value,
|
|||
}
|
||||
/// Custom suffix sfx: use int.__suffix_sfx__(str) call.
|
||||
/// NOTE: you cannot neither use binary (0bXXX) format here.
|
||||
return transform(N<CallExpr>(N<DotExpr>("int", format("__suffix_{}__", suffix)),
|
||||
N<IntExpr>(val)));
|
||||
return transform(
|
||||
N<CallExpr>(N<DotExpr>("int", format("__suffix_{}__", suffix)), N<IntExpr>(val)));
|
||||
}
|
||||
|
||||
ExprPtr SimplifyVisitor::transformFloat(const std::string &value,
|
||||
|
|
|
@ -209,6 +209,10 @@ void TranslateVisitor::visit(StmtExpr *expr) {
|
|||
transform(s);
|
||||
ctx->popSeries();
|
||||
result = make<ir::FlowInstr>(expr, bodySeries, transform(expr->expr));
|
||||
for (auto &a : expr->attributes) {
|
||||
// if (a == ir::ListLiteralAttribute::AttributeName)
|
||||
// result->setAttribute(ir::ListLiteralAttribute);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
|
|
|
@ -304,7 +304,6 @@ private:
|
|||
ExprPtr transformSuper(const CallExpr *expr);
|
||||
std::vector<types::ClassTypePtr> getSuperTypes(const types::ClassTypePtr &cls);
|
||||
|
||||
|
||||
private:
|
||||
types::TypePtr unify(types::TypePtr &a, const types::TypePtr &b,
|
||||
bool undoOnSuccess = false);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "codon/parser/common.h"
|
||||
#include "codon/parser/visitors/simplify/simplify.h"
|
||||
#include "codon/parser/visitors/typecheck/typecheck.h"
|
||||
#include "codon/sir/attribute.h"
|
||||
|
||||
using fmt::format;
|
||||
|
||||
|
@ -741,14 +742,7 @@ ExprPtr TypecheckVisitor::transformStaticTupleIndex(ClassType *tuple, ExprPtr &e
|
|||
if (!tuple->getRecord())
|
||||
return nullptr;
|
||||
if (!startswith(tuple->name, TYPE_TUPLE) && !startswith(tuple->name, TYPE_PARTIAL))
|
||||
// in(std::set<std::string>{"Ptr", "pyobj", "str", "Array"}, tuple->name))
|
||||
// Ptr, pyobj and str are internal types and have only one overloaded __getitem__
|
||||
return nullptr;
|
||||
// if (in(ctx->cache->classes[tuple->name].methods, "__getitem__")) {
|
||||
// ctx->cache->overloads[ctx->cache->classes[tuple->name].methods["__getitem__"]]
|
||||
// .size() != 1)
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
// Extract a static integer value from a compatible expression.
|
||||
auto getInt = [&](int64_t *o, const ExprPtr &e) {
|
||||
|
@ -1123,30 +1117,32 @@ ExprPtr TypecheckVisitor::transformCall(CallExpr *expr, const types::TypePtr &in
|
|||
N<ExprStmt>(N<CallExpr>(N<DotExpr>(clone(var), "__init__"), expr->args))),
|
||||
clone(var)));
|
||||
}
|
||||
} else if (auto pc = callee->getPartial()) {
|
||||
ExprPtr var = N<IdExpr>(partialVar = ctx->cache->getTemporaryVar("pt"));
|
||||
expr->expr = transform(N<StmtExpr>(N<AssignStmt>(clone(var), expr->expr),
|
||||
N<IdExpr>(pc->func->ast->name)));
|
||||
calleeFn = expr->expr->type->getFunc();
|
||||
for (int i = 0, j = 0; i < pc->known.size(); i++)
|
||||
if (pc->func->ast->args[i].generic) {
|
||||
if (pc->known[i])
|
||||
unify(calleeFn->funcGenerics[j].type, pc->func->funcGenerics[j].type);
|
||||
j++;
|
||||
}
|
||||
known = pc->known;
|
||||
seqassert(calleeFn, "not a function: {}", expr->expr->type->toString());
|
||||
} else if (!callee->getFunc()) {
|
||||
// Case 3: callee is not a named function. Route it through a __call__ method.
|
||||
ExprPtr newCall = N<CallExpr>(N<DotExpr>(expr->expr, "__call__"), expr->args);
|
||||
return transform(newCall, false, allowVoidExpr);
|
||||
} else {
|
||||
auto pc = callee->getPartial();
|
||||
if (pc) {
|
||||
ExprPtr var = N<IdExpr>(partialVar = ctx->cache->getTemporaryVar("pt"));
|
||||
expr->expr = transform(N<StmtExpr>(N<AssignStmt>(clone(var), expr->expr),
|
||||
N<IdExpr>(pc->func->ast->name)));
|
||||
calleeFn = expr->expr->type->getFunc();
|
||||
for (int i = 0, j = 0; i < pc->known.size(); i++)
|
||||
if (pc->func->ast->args[i].generic) {
|
||||
if (pc->known[i])
|
||||
unify(calleeFn->funcGenerics[j].type, pc->func->funcGenerics[j].type);
|
||||
j++;
|
||||
}
|
||||
known = pc->known;
|
||||
seqassert(calleeFn, "not a function: {}", expr->expr->type->toString());
|
||||
} else if (!callee->getFunc()) {
|
||||
// Case 3: callee is not a named function. Route it through a __call__ method.
|
||||
ExprPtr newCall = N<CallExpr>(N<DotExpr>(expr->expr, "__call__"), expr->args);
|
||||
return transform(newCall, false, allowVoidExpr);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle named and default arguments
|
||||
std::vector<CallExpr::Arg> args;
|
||||
std::vector<ExprPtr> typeArgs;
|
||||
int typeArgCount = 0;
|
||||
// bool isPartial = false;
|
||||
int ellipsisStage = -1;
|
||||
auto newMask = std::vector<char>(calleeFn->ast->args.size(), 1);
|
||||
auto getPartialArg = [&](int pi) {
|
||||
|
@ -1385,12 +1381,14 @@ ExprPtr TypecheckVisitor::transformCall(CallExpr *expr, const types::TypePtr &in
|
|||
N<CallExpr>(N<IdExpr>(partialTypeName), newArgs)),
|
||||
N<IdExpr>(var));
|
||||
}
|
||||
const_cast<StmtExpr *>(call->getStmtExpr())
|
||||
->setAttr(ir::PartialFunctionAttribute::AttributeName);
|
||||
call = transform(call, false, allowVoidExpr);
|
||||
seqassert(call->type->getRecord() &&
|
||||
startswith(call->type->getRecord()->name, partialTypeName) &&
|
||||
!call->type->getPartial(),
|
||||
"bad partial transformation");
|
||||
call->type = N<PartialType>(call->type->getRecord(), calleeFn, newMask);
|
||||
// seqassert(call->type->getRecord() &&
|
||||
// startswith(call->type->getRecord()->name, partialTypeName) &&
|
||||
// !call->type->getPartial(),
|
||||
// "bad partial transformation");
|
||||
// call->type = N<PartialType>(call->type->getRecord(), calleeFn, newMask);
|
||||
return call;
|
||||
} else {
|
||||
// Case 2. Normal function call.
|
||||
|
@ -1427,7 +1425,7 @@ std::pair<bool, ExprPtr> TypecheckVisitor::transformSpecialCall(CallExpr *expr)
|
|||
auto t = expr->args[1].value->type;
|
||||
auto hierarchy = getSuperTypes(typ->getClass());
|
||||
|
||||
for (auto &tx: hierarchy) {
|
||||
for (auto &tx : hierarchy) {
|
||||
auto unifyOK = tx->unify(t.get(), nullptr) >= 0;
|
||||
if (unifyOK) {
|
||||
return {true, transform(N<BoolExpr>(true))};
|
||||
|
@ -1638,9 +1636,12 @@ std::string TypecheckVisitor::generatePartialStub(const std::vector<char> &mask,
|
|||
else if (!fn->ast->args[i].generic)
|
||||
tupleSize++;
|
||||
auto typeName = format(TYPE_PARTIAL "{}.{}", strMask, fn->ast->name);
|
||||
if (!ctx->find(typeName))
|
||||
if (!ctx->find(typeName)) {
|
||||
ctx->cache->partials[typeName] = {
|
||||
std::static_pointer_cast<types::FuncType>(fn->shared_from_this()), mask};
|
||||
// 2 for .starArgs and .kwstarArgs (empty tuples if fn does not have them)
|
||||
generateTupleStub(tupleSize + 2, typeName, {}, false);
|
||||
}
|
||||
return typeName;
|
||||
}
|
||||
|
||||
|
@ -1712,12 +1713,14 @@ ExprPtr TypecheckVisitor::partializeFunction(ExprPtr expr) {
|
|||
N<CallExpr>(N<IdExpr>(partialTypeName), N<TupleExpr>(),
|
||||
N<CallExpr>(N<IdExpr>(kwName)))),
|
||||
N<IdExpr>(var));
|
||||
const_cast<StmtExpr *>(call->getStmtExpr())
|
||||
->setAttr(ir::PartialFunctionAttribute::AttributeName);
|
||||
call = transform(call, false, allowVoidExpr);
|
||||
seqassert(call->type->getRecord() &&
|
||||
startswith(call->type->getRecord()->name, partialTypeName) &&
|
||||
!call->type->getPartial(),
|
||||
"bad partial transformation");
|
||||
call->type = N<PartialType>(call->type->getRecord(), fn, mask);
|
||||
// seqassert(call->type->getRecord() &&
|
||||
// startswith(call->type->getRecord()->name, partialTypeName) &&
|
||||
// !call->type->getPartial(),
|
||||
// "bad partial transformation");
|
||||
// call->type = N<PartialType>(call->type->getRecord(), fn, mask);
|
||||
return call;
|
||||
}
|
||||
|
||||
|
@ -2023,7 +2026,7 @@ std::vector<ClassTypePtr> TypecheckVisitor::getSuperTypes(const ClassTypePtr &cl
|
|||
return result;
|
||||
result.push_back(cls);
|
||||
int start = 0;
|
||||
for (auto &cand: ctx->cache->classes[cls->name].parentClasses) {
|
||||
for (auto &cand : ctx->cache->classes[cls->name].parentClasses) {
|
||||
auto name = cand.first;
|
||||
int fields = cand.second;
|
||||
auto val = ctx->find(name);
|
||||
|
@ -2037,7 +2040,7 @@ std::vector<ClassTypePtr> TypecheckVisitor::getSuperTypes(const ClassTypePtr &cl
|
|||
unify(t, ft);
|
||||
}
|
||||
start += fields;
|
||||
for (auto &t: getSuperTypes(ftyp))
|
||||
for (auto &t : getSuperTypes(ftyp))
|
||||
result.push_back(t);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -508,6 +508,13 @@ void TypecheckVisitor::visit(ClassStmt *stmt) {
|
|||
else
|
||||
typ = std::make_shared<ClassType>(
|
||||
stmt->name, ctx->cache->reverseIdentifierLookup[stmt->name]);
|
||||
if (stmt->isRecord() && startswith(stmt->name, TYPE_PARTIAL)) {
|
||||
seqassert(in(ctx->cache->partials, stmt->name),
|
||||
"invalid partial initialization: {}", stmt->name);
|
||||
typ = std::make_shared<PartialType>(typ->getRecord(),
|
||||
ctx->cache->partials[stmt->name].first,
|
||||
ctx->cache->partials[stmt->name].second);
|
||||
}
|
||||
typ->setSrcInfo(stmt->getSrcInfo());
|
||||
ctx->add(TypecheckItem::Type, stmt->name, typ);
|
||||
ctx->bases[0].visitedAsts[stmt->name] = {TypecheckItem::Type, typ};
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "value.h"
|
||||
#include "attribute.h"
|
||||
|
||||
#include "codon/sir/func.h"
|
||||
#include "codon/sir/util/cloning.h"
|
||||
#include "codon/sir/value.h"
|
||||
#include "codon/util/fmt/ostream.h"
|
||||
|
||||
namespace codon {
|
||||
|
@ -36,5 +39,136 @@ std::ostream &MemberAttribute::doFormat(std::ostream &os) const {
|
|||
|
||||
const std::string SrcInfoAttribute::AttributeName = "srcInfoAttribute";
|
||||
|
||||
const std::string TupleLiteralAttribute::AttributeName = "tupleLiteralAttribute";
|
||||
|
||||
std::unique_ptr<Attribute> TupleLiteralAttribute::clone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> elementsCloned;
|
||||
for (auto *val : elements)
|
||||
elementsCloned.push_back(cv.clone(val));
|
||||
return std::make_unique<TupleLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::unique_ptr<Attribute>
|
||||
TupleLiteralAttribute::forceClone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> elementsCloned;
|
||||
for (auto *val : elements)
|
||||
elementsCloned.push_back(cv.forceClone(val));
|
||||
return std::make_unique<TupleLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::ostream &TupleLiteralAttribute::doFormat(std::ostream &os) const {
|
||||
std::vector<std::string> strings;
|
||||
for (auto *val : elements)
|
||||
strings.push_back(fmt::format(FMT_STRING("{}"), *val));
|
||||
fmt::print(os, FMT_STRING("({})"), fmt::join(strings.begin(), strings.end(), ","));
|
||||
return os;
|
||||
}
|
||||
|
||||
const std::string ListLiteralAttribute::AttributeName = "listLiteralAttribute";
|
||||
|
||||
std::unique_ptr<Attribute> ListLiteralAttribute::clone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> elementsCloned;
|
||||
for (auto *val : elements)
|
||||
elementsCloned.push_back(cv.clone(val));
|
||||
return std::make_unique<ListLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::unique_ptr<Attribute>
|
||||
ListLiteralAttribute::forceClone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> elementsCloned;
|
||||
for (auto *val : elements)
|
||||
elementsCloned.push_back(cv.forceClone(val));
|
||||
return std::make_unique<ListLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::ostream &ListLiteralAttribute::doFormat(std::ostream &os) const {
|
||||
std::vector<std::string> strings;
|
||||
for (auto *val : elements)
|
||||
strings.push_back(fmt::format(FMT_STRING("{}"), *val));
|
||||
fmt::print(os, FMT_STRING("[{}]"), fmt::join(strings.begin(), strings.end(), ","));
|
||||
return os;
|
||||
}
|
||||
|
||||
const std::string SetLiteralAttribute::AttributeName = "setLiteralAttribute";
|
||||
|
||||
std::unique_ptr<Attribute> SetLiteralAttribute::clone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> elementsCloned;
|
||||
for (auto *val : elements)
|
||||
elementsCloned.push_back(cv.clone(val));
|
||||
return std::make_unique<SetLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::unique_ptr<Attribute>
|
||||
SetLiteralAttribute::forceClone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> elementsCloned;
|
||||
for (auto *val : elements)
|
||||
elementsCloned.push_back(cv.forceClone(val));
|
||||
return std::make_unique<SetLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::ostream &SetLiteralAttribute::doFormat(std::ostream &os) const {
|
||||
std::vector<std::string> strings;
|
||||
for (auto *val : elements)
|
||||
strings.push_back(fmt::format(FMT_STRING("{}"), *val));
|
||||
fmt::print(os, FMT_STRING("set([{}])"),
|
||||
fmt::join(strings.begin(), strings.end(), ","));
|
||||
return os;
|
||||
}
|
||||
|
||||
const std::string DictLiteralAttribute::AttributeName = "dictLiteralAttribute";
|
||||
|
||||
std::unique_ptr<Attribute> DictLiteralAttribute::clone(util::CloneVisitor &cv) const {
|
||||
std::vector<DictLiteralAttribute::KeyValuePair> elementsCloned;
|
||||
for (auto &val : elements)
|
||||
elementsCloned.push_back({cv.clone(val.key), cv.clone(val.value)});
|
||||
return std::make_unique<DictLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::unique_ptr<Attribute>
|
||||
DictLiteralAttribute::forceClone(util::CloneVisitor &cv) const {
|
||||
std::vector<DictLiteralAttribute::KeyValuePair> elementsCloned;
|
||||
for (auto &val : elements)
|
||||
elementsCloned.push_back({cv.forceClone(val.key), cv.forceClone(val.value)});
|
||||
return std::make_unique<DictLiteralAttribute>(elementsCloned);
|
||||
}
|
||||
|
||||
std::ostream &DictLiteralAttribute::doFormat(std::ostream &os) const {
|
||||
std::vector<std::string> strings;
|
||||
for (auto &val : elements)
|
||||
strings.push_back(fmt::format(FMT_STRING("{}:{}"), *val.key, *val.value));
|
||||
fmt::print(os, FMT_STRING("dict([{}])"),
|
||||
fmt::join(strings.begin(), strings.end(), ","));
|
||||
return os;
|
||||
}
|
||||
|
||||
const std::string PartialFunctionAttribute::AttributeName = "partialFunctionAttribute";
|
||||
|
||||
std::unique_ptr<Attribute>
|
||||
PartialFunctionAttribute::clone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> argsCloned;
|
||||
for (auto *val : args)
|
||||
argsCloned.push_back(cv.clone(val));
|
||||
return std::make_unique<PartialFunctionAttribute>(cast<Func>(cv.clone(func)),
|
||||
argsCloned);
|
||||
}
|
||||
|
||||
std::unique_ptr<Attribute>
|
||||
PartialFunctionAttribute::forceClone(util::CloneVisitor &cv) const {
|
||||
std::vector<Value *> argsCloned;
|
||||
for (auto *val : args)
|
||||
argsCloned.push_back(cv.forceClone(val));
|
||||
return std::make_unique<PartialFunctionAttribute>(cast<Func>(cv.forceClone(func)),
|
||||
argsCloned);
|
||||
}
|
||||
|
||||
std::ostream &PartialFunctionAttribute::doFormat(std::ostream &os) const {
|
||||
std::vector<std::string> strings;
|
||||
for (auto *val : args)
|
||||
strings.push_back(val ? fmt::format(FMT_STRING("{}"), *val) : "...");
|
||||
fmt::print(os, FMT_STRING("{}({})"), func->getName(),
|
||||
fmt::join(strings.begin(), strings.end(), ","));
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace codon
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
namespace codon {
|
||||
namespace ir {
|
||||
|
||||
class Func;
|
||||
class Value;
|
||||
|
||||
namespace util {
|
||||
class CloneVisitor;
|
||||
}
|
||||
|
||||
/// Base for SIR attributes.
|
||||
struct Attribute {
|
||||
virtual ~Attribute() noexcept = default;
|
||||
|
@ -26,14 +33,15 @@ struct Attribute {
|
|||
}
|
||||
|
||||
/// @return a clone of the attribute
|
||||
std::unique_ptr<Attribute> clone() const {
|
||||
return std::unique_ptr<Attribute>(doClone());
|
||||
virtual std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const = 0;
|
||||
|
||||
/// @return a clone of the attribute
|
||||
virtual std::unique_ptr<Attribute> forceClone(util::CloneVisitor &cv) const {
|
||||
return clone(cv);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual std::ostream &doFormat(std::ostream &os) const = 0;
|
||||
|
||||
virtual Attribute *doClone() const = 0;
|
||||
};
|
||||
|
||||
/// Attribute containing SrcInfo
|
||||
|
@ -48,10 +56,12 @@ struct SrcInfoAttribute : public Attribute {
|
|||
/// @param info the source info
|
||||
explicit SrcInfoAttribute(codon::SrcInfo info) : info(std::move(info)) {}
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override {
|
||||
return std::make_unique<SrcInfoAttribute>(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override { return os << info; }
|
||||
|
||||
Attribute *doClone() const override { return new SrcInfoAttribute(*this); }
|
||||
};
|
||||
|
||||
/// Attribute containing function information
|
||||
|
@ -76,10 +86,12 @@ struct KeyValueAttribute : public Attribute {
|
|||
/// string if none
|
||||
std::string get(const std::string &key) const;
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override {
|
||||
return std::make_unique<KeyValueAttribute>(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override;
|
||||
|
||||
Attribute *doClone() const override { return new KeyValueAttribute(*this); }
|
||||
};
|
||||
|
||||
/// Attribute containing type member information
|
||||
|
@ -95,10 +107,106 @@ struct MemberAttribute : public Attribute {
|
|||
explicit MemberAttribute(std::map<std::string, SrcInfo> memberSrcInfo)
|
||||
: memberSrcInfo(std::move(memberSrcInfo)) {}
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override {
|
||||
return std::make_unique<MemberAttribute>(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override;
|
||||
};
|
||||
|
||||
Attribute *doClone() const override { return new MemberAttribute(*this); }
|
||||
/// Attribute attached to IR structures corresponding to tuple literals
|
||||
struct TupleLiteralAttribute : public Attribute {
|
||||
static const std::string AttributeName;
|
||||
|
||||
/// values contained in tuple literal
|
||||
std::vector<Value *> elements;
|
||||
|
||||
explicit TupleLiteralAttribute(std::vector<Value *> elements)
|
||||
: elements(std::move(elements)) {}
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override;
|
||||
std::unique_ptr<Attribute> forceClone(util::CloneVisitor &cv) const override;
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override;
|
||||
};
|
||||
|
||||
/// Attribute attached to IR structures corresponding to list literals
|
||||
struct ListLiteralAttribute : public Attribute {
|
||||
static const std::string AttributeName;
|
||||
|
||||
/// values contained in list literal
|
||||
std::vector<Value *> elements;
|
||||
|
||||
explicit ListLiteralAttribute(std::vector<Value *> elements)
|
||||
: elements(std::move(elements)) {}
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override;
|
||||
std::unique_ptr<Attribute> forceClone(util::CloneVisitor &cv) const override;
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override;
|
||||
};
|
||||
|
||||
/// Attribute attached to IR structures corresponding to set literals
|
||||
struct SetLiteralAttribute : public Attribute {
|
||||
static const std::string AttributeName;
|
||||
|
||||
/// values contained in set literal
|
||||
std::vector<Value *> elements;
|
||||
|
||||
explicit SetLiteralAttribute(std::vector<Value *> elements)
|
||||
: elements(std::move(elements)) {}
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override;
|
||||
std::unique_ptr<Attribute> forceClone(util::CloneVisitor &cv) const override;
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override;
|
||||
};
|
||||
|
||||
/// Attribute attached to IR structures corresponding to dict literals
|
||||
struct DictLiteralAttribute : public Attribute {
|
||||
struct KeyValuePair {
|
||||
Value *key;
|
||||
Value *value;
|
||||
};
|
||||
|
||||
static const std::string AttributeName;
|
||||
|
||||
/// keys and values contained in dict literal
|
||||
std::vector<KeyValuePair> elements;
|
||||
|
||||
explicit DictLiteralAttribute(std::vector<KeyValuePair> elements)
|
||||
: elements(std::move(elements)) {}
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override;
|
||||
std::unique_ptr<Attribute> forceClone(util::CloneVisitor &cv) const override;
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override;
|
||||
};
|
||||
|
||||
/// Attribute attached to IR structures corresponding to partial functions
|
||||
struct PartialFunctionAttribute : public Attribute {
|
||||
static const std::string AttributeName;
|
||||
|
||||
/// function being called
|
||||
Func *func;
|
||||
|
||||
/// partial arguments, or null if none
|
||||
/// e.g. "f(a, ..., b)" has elements [a, null, b]
|
||||
std::vector<Value *> args;
|
||||
|
||||
PartialFunctionAttribute(Func *func, std::vector<Value *> args)
|
||||
: func(func), args(std::move(args)) {}
|
||||
|
||||
std::unique_ptr<Attribute> clone(util::CloneVisitor &cv) const override;
|
||||
std::unique_ptr<Attribute> forceClone(util::CloneVisitor &cv) const override;
|
||||
|
||||
private:
|
||||
std::ostream &doFormat(std::ostream &os) const override;
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
for (auto it = other->attributes_begin(); it != other->attributes_end(); ++it) {
|
||||
const auto *attr = other->getAttribute(*it);
|
||||
if (attr->needsClone()) {
|
||||
ctx[id]->setAttribute(attr->clone(), *it);
|
||||
ctx[id]->setAttribute(attr->clone(*this), *it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
for (auto it = other->attributes_begin(); it != other->attributes_end(); ++it) {
|
||||
const auto *attr = other->getAttribute(*it);
|
||||
if (attr->needsClone()) {
|
||||
ctx[id]->setAttribute(attr->clone(), *it);
|
||||
ctx[id]->setAttribute(attr->forceClone(*this), *it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue