codon/compiler/parser/parser.cpp

160 lines
5.0 KiB
C++

/*
* parser.cpp --- Seq AST parser.
*
* (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 <chrono>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "parser/cache.h"
#include "parser/parser.h"
#include "parser/peg/peg.h"
#include "parser/visitors/doc/doc.h"
#include "parser/visitors/format/format.h"
#include "parser/visitors/simplify/simplify.h"
#include "parser/visitors/translate/translate.h"
#include "parser/visitors/typecheck/typecheck.h"
#include "sir/sir.h"
#include "util/fmt/format.h"
#include "sir/util/format.h"
#include <fstream>
int _ocaml_time = 0;
int _ll_time = 0;
int _level = 0;
int _dbg_level = 0;
bool _isTest = false;
namespace seq {
ir::Module *parse(const string &argv0, const string &file, const string &code,
bool isCode, int isTest, int startLine,
const std::unordered_map<std::string, std::string> &defines) {
try {
auto d = getenv("CODON_DEBUG");
if (d) {
auto s = string(d);
_dbg_level |= s.find('t') != string::npos ? (1 << 0) : 0; // time
_dbg_level |= s.find('r') != string::npos ? (1 << 2) : 0; // realize
_dbg_level |= s.find('T') != string::npos ? (1 << 4) : 0; // type-check
_dbg_level |= s.find('L') != string::npos ? (1 << 5) : 0; // lexer
_dbg_level |= s.find('i') != string::npos ? (1 << 6) : 0; // IR
_dbg_level |= s.find('l') != string::npos ? (1 << 7) : 0; // User-level debugging
}
char abs[PATH_MAX + 1] = {'-', 0};
if (file != "-")
realpath(file.c_str(), abs);
auto cache = make_shared<ast::Cache>(argv0);
ast::StmtPtr codeStmt = isCode ? ast::parseCode(cache, abs, code, startLine)
: ast::parseFile(cache, abs);
if (_dbg_level) {
auto fo = fopen("_dump.sexp", "w");
fmt::print(fo, "{}\n", codeStmt->toString(0));
fclose(fo);
}
using namespace std::chrono;
cache->module0 = file;
if (isTest)
cache->testFlags = isTest;
auto t = high_resolution_clock::now();
auto transformed =
ast::SimplifyVisitor::apply(cache, move(codeStmt), abs, defines, (isTest > 1));
if (!isTest) {
LOG_TIME("[T] ocaml = {:.1f}", _ocaml_time / 1000.0);
LOG_TIME("[T] simplify = {:.1f}",
(duration_cast<milliseconds>(high_resolution_clock::now() - t).count() -
_ocaml_time) /
1000.0);
if (_dbg_level) {
auto fo = fopen("_dump_simplify.sexp", "w");
fmt::print(fo, "{}\n", transformed->toString(0));
fclose(fo);
fo = fopen("_dump_simplify.seq", "w");
fmt::print(fo, "{}", ast::FormatVisitor::apply(transformed, cache));
fclose(fo);
}
}
t = high_resolution_clock::now();
auto typechecked = ast::TypecheckVisitor::apply(cache, move(transformed));
if (!isTest) {
LOG_TIME("[T] typecheck = {:.1f}",
duration_cast<milliseconds>(high_resolution_clock::now() - t).count() /
1000.0);
if (_dbg_level) {
auto fo = fopen("_dump_typecheck.seq", "w");
fmt::print(fo, "{}", ast::FormatVisitor::apply(typechecked, cache));
fclose(fo);
fo = fopen("_dump_typecheck.sexp", "w");
fmt::print(fo, "{}\n", typechecked->toString(0));
for (auto &f : cache->functions)
for (auto &r : f.second.realizations)
fmt::print(fo, "{}\n", r.second->ast->toString(0));
fclose(fo);
}
}
t = high_resolution_clock::now();
auto *module = ast::TranslateVisitor::apply(cache, move(typechecked));
module->setSrcInfo({abs, 0, 0, 0});
if (!isTest)
LOG_TIME("[T] translate = {:.1f}",
duration_cast<milliseconds>(high_resolution_clock::now() - t).count() /
1000.0);
if (_dbg_level) {
auto out = seq::ir::util::format(module);
std::ofstream os("_dump_sir.lisp");
os << out;
os.close();
os.close();
}
_isTest = isTest;
return module;
} catch (exc::ParserException &e) {
for (int i = 0; i < e.messages.size(); i++)
if (!e.messages[i].empty()) {
if (isTest) {
_level = 0;
LOG("{}", e.messages[i]);
} else {
compilationError(e.messages[i], e.locations[i].file, e.locations[i].line,
e.locations[i].col, /*terminate=*/false);
}
}
return nullptr;
}
}
void generateDocstr(const string &argv0) {
vector<string> files;
string s;
while (std::getline(std::cin, s))
files.push_back(s);
try {
auto j = ast::DocVisitor::apply(argv0, files);
fmt::print("{}\n", j->toString());
} catch (exc::ParserException &e) {
for (int i = 0; i < e.messages.size(); i++)
if (!e.messages[i].empty()) {
compilationError(e.messages[i], e.locations[i].file, e.locations[i].line,
e.locations[i].col, /*terminate=*/false);
}
}
}
} // namespace seq