/* * simplify.h --- AST simplification transformation. * * (c) Seq project. All rights reserved. * This file is subject to the terms and conditions defined in * file 'LICENSE', which is part of this source code package. */ #include #include #include #include #include "parser/ast.h" #include "parser/common.h" #include "parser/peg/peg.h" #include "parser/visitors/simplify/simplify.h" #include "parser/visitors/simplify/simplify_ctx.h" using fmt::format; using std::deque; using std::dynamic_pointer_cast; using std::function; using std::get; using std::move; using std::ostream; using std::pair; using std::stack; namespace seq { namespace ast { using namespace types; StmtPtr SimplifyVisitor::apply(shared_ptr cache, const StmtPtr &node, const string &file, const unordered_map &defines, bool barebones) { vector stmts; auto preamble = make_shared(); if (!cache->module) cache->module = new seq::ir::Module("", cache); // Load standard library if it has not been loaded. if (!in(cache->imports, STDLIB_IMPORT)) { // Load the internal module auto stdlib = make_shared(STDLIB_IMPORT, cache); auto stdlibPath = getImportFile(cache->argv0, STDLIB_INTERNAL_MODULE, "", true, cache->module0); if (!stdlibPath || stdlibPath->path.substr(stdlibPath->path.size() - 14) != "__init__.codon") ast::error("cannot load standard library"); if (barebones) stdlibPath->path = stdlibPath->path.substr(0, stdlibPath->path.size() - 7) + "test__.codon"; stdlib->setFilename(stdlibPath->path); cache->imports[STDLIB_IMPORT] = {stdlibPath->path, stdlib}; // Add __internal__ class that will store functions needed by other internal // classes. We will call them as __internal__.fn because directly calling fn will // result in a unresolved dependency cycle. { auto name = "__internal__"; auto canonical = stdlib->generateCanonicalName(name); stdlib->add(SimplifyItem::Type, name, canonical, true); // Generate an AST for each POD type. All of them are tuples. cache->classes[canonical].ast = make_shared(canonical, vector(), nullptr); preamble->globals.emplace_back(clone(cache->classes[canonical].ast)); } // Add simple POD types to the preamble (these types are defined in LLVM and we // cannot properly define them in Seq) for (auto &name : {"void", "bool", "byte", "int", "float", "NoneType"}) { auto canonical = stdlib->generateCanonicalName(name); stdlib->add(SimplifyItem::Type, name, canonical, true); // Generate an AST for each POD type. All of them are tuples. cache->classes[canonical].ast = make_shared( canonical, vector(), nullptr, Attr({Attr::Internal, Attr::Tuple})); preamble->globals.emplace_back(clone(cache->classes[canonical].ast)); } // Add generic POD types to the preamble for (auto &name : vector{"Ptr", "Generator", TYPE_OPTIONAL, "Int", "UInt"}) { auto canonical = stdlib->generateCanonicalName(name); stdlib->add(SimplifyItem::Type, name, canonical, true); vector generics; auto isInt = string(name) == "Int" || string(name) == "UInt"; if (isInt) generics.emplace_back( Param{stdlib->generateCanonicalName("N"), make_shared(make_shared("Static"), make_shared("int")), nullptr, true}); else generics.emplace_back(Param{ stdlib->generateCanonicalName("T"), make_shared("type"), name == TYPE_OPTIONAL ? make_shared("NoneType") : nullptr, true}); cache->classes[canonical].ast = make_shared( canonical, generics, nullptr, Attr({Attr::Internal, Attr::Tuple})); preamble->globals.emplace_back(clone(cache->classes[canonical].ast)); } // Reserve the following static identifiers. for (auto name : {"staticlen", "compile_error", "isinstance", "hasattr", "type", "TypeVar", "Callable"}) stdlib->generateCanonicalName(name); // This code must be placed in a preamble (these are not POD types but are // referenced by the various preamble Function.N and Tuple.N stubs) stdlib->isStdlibLoading = true; stdlib->moduleName = {ImportFile::STDLIB, stdlibPath->path, "__init__"}; auto baseTypeCode = "@__internal__\n@tuple\nclass pyobj:\n p: Ptr[byte]\n" "@__internal__\n@tuple\nclass str:\n ptr: Ptr[byte]\n len: int\n"; SimplifyVisitor(stdlib, preamble) .transform(parseCode(stdlib->cache, stdlibPath->path, baseTypeCode)); // Load the standard library stdlib->setFilename(stdlibPath->path); stmts.push_back(SimplifyVisitor(stdlib, preamble) .transform(parseFile(stdlib->cache, stdlibPath->path))); // Add __argv__ variable as __argv__: Array[str] preamble->globals.push_back( SimplifyVisitor(stdlib, preamble) .transform(make_shared( make_shared(VAR_ARGV), nullptr, make_shared(make_shared("Array"), make_shared("str"))))); stdlib->isStdlibLoading = false; // The whole standard library has the age of zero to allow back-references. cache->age++; } auto ctx = make_shared(file, cache); cache->imports[file].filename = file; cache->imports[file].ctx = ctx; cache->imports[MAIN_IMPORT] = {file, ctx}; ctx->setFilename(file); ctx->moduleName = {ImportFile::PACKAGE, file, MODULE_MAIN}; auto before = make_shared(); // Load the command-line defines. for (auto &d : defines) { before->stmts.push_back(make_shared( make_shared(d.first), make_shared(d.second), make_shared(make_shared("Static"), make_shared("int")))); } // Prepend __name__ = "__main__". before->stmts.push_back(make_shared( make_shared("__name__"), make_shared(MODULE_MAIN))); // Transform the input node. stmts.emplace_back(SimplifyVisitor(ctx, preamble).transform(before)); stmts.emplace_back(SimplifyVisitor(ctx, preamble).transform(node)); auto suite = make_shared(); for (auto &s : preamble->globals) suite->stmts.push_back(s); for (auto &s : preamble->functions) suite->stmts.push_back(s); for (auto &s : stmts) suite->stmts.push_back(s); return suite; } StmtPtr SimplifyVisitor::apply(shared_ptr ctx, const StmtPtr &node, const string &file, int atAge) { vector stmts; int oldAge = ctx->cache->age; if (atAge != -1) ctx->cache->age = atAge; auto preamble = make_shared(); stmts.emplace_back(SimplifyVisitor(ctx, preamble).transform(node)); if (atAge != -1) ctx->cache->age = oldAge; auto suite = make_shared(); for (auto &s : preamble->globals) suite->stmts.push_back(s); for (auto &s : preamble->functions) suite->stmts.push_back(s); for (auto &s : stmts) suite->stmts.push_back(s); return suite; } SimplifyVisitor::SimplifyVisitor(shared_ptr ctx, shared_ptr preamble) : ctx(move(ctx)), preamble(move(preamble)) {} } // namespace ast } // namespace seq