mirror of https://github.com/exaloop/codon.git
160 lines
5.0 KiB
C++
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
|