blob: 806f5226d6bbcaac5e54a807ed6724ef5a087411 [file] [log] [blame]
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/torque/torque-compiler.h"
#include <fstream>
#include "src/torque/declarable.h"
#include "src/torque/declaration-visitor.h"
#include "src/torque/global-context.h"
#include "src/torque/implementation-visitor.h"
#include "src/torque/torque-parser.h"
#include "src/torque/type-oracle.h"
namespace v8 {
namespace internal {
namespace torque {
namespace {
base::Optional<std::string> ReadFile(const std::string& path) {
std::ifstream file_stream(path);
if (!file_stream.good()) return base::nullopt;
return std::string{std::istreambuf_iterator<char>(file_stream),
std::istreambuf_iterator<char>()};
}
void ReadAndParseTorqueFile(const std::string& path) {
SourceId source_id = SourceFileMap::AddSource(path);
CurrentSourceFile::Scope source_id_scope(source_id);
// path might be either a normal file path or an encoded URI.
auto maybe_content = ReadFile(SourceFileMap::PathFromV8Root(source_id));
if (!maybe_content) {
if (auto maybe_path = FileUriDecode(path)) {
maybe_content = ReadFile(*maybe_path);
}
}
if (!maybe_content) {
Error("Cannot open file path/uri: ", path).Throw();
}
ParseTorque(*maybe_content);
}
void CompileCurrentAst(TorqueCompilerOptions options) {
GlobalContext::Scope global_context(std::move(CurrentAst::Get()));
if (options.collect_language_server_data) {
GlobalContext::SetCollectLanguageServerData();
}
if (options.force_assert_statements) {
GlobalContext::SetForceAssertStatements();
}
TypeOracle::Scope type_oracle;
// Two-step process of predeclaration + resolution allows to resolve type
// declarations independent of the order they are given.
PredeclarationVisitor::Predeclare(GlobalContext::ast());
PredeclarationVisitor::ResolvePredeclarations();
// Process other declarations.
DeclarationVisitor::Visit(GlobalContext::ast());
// A class types' fields are resolved here, which allows two class fields to
// mutually refer to each others.
TypeOracle::FinalizeAggregateTypes();
std::string output_directory = options.output_directory;
ImplementationVisitor implementation_visitor;
implementation_visitor.SetDryRun(output_directory.length() == 0);
implementation_visitor.BeginCSAFiles();
implementation_visitor.VisitAllDeclarables();
ReportAllUnusedMacros();
implementation_visitor.GenerateBuiltinDefinitions(output_directory);
implementation_visitor.GenerateClassFieldOffsets(output_directory);
implementation_visitor.GeneratePrintDefinitions(output_directory);
implementation_visitor.GenerateClassDefinitions(output_directory);
implementation_visitor.GenerateClassVerifiers(output_directory);
implementation_visitor.GenerateExportedMacrosAssembler(output_directory);
implementation_visitor.GenerateCSATypes(output_directory);
implementation_visitor.GenerateInstanceTypes(output_directory);
implementation_visitor.GenerateCppForInternalClasses(output_directory);
implementation_visitor.EndCSAFiles();
implementation_visitor.GenerateImplementation(output_directory);
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::SetGlobalContext(std::move(GlobalContext::Get()));
LanguageServerData::SetTypeOracle(std::move(TypeOracle::Get()));
}
}
} // namespace
TorqueCompilerResult CompileTorque(const std::string& source,
TorqueCompilerOptions options) {
SourceFileMap::Scope source_map_scope(options.v8_root);
CurrentSourceFile::Scope no_file_scope(
SourceFileMap::AddSource("dummy-filename.tq"));
CurrentAst::Scope ast_scope;
TorqueMessages::Scope messages_scope;
LanguageServerData::Scope server_data_scope;
TorqueCompilerResult result;
try {
ParseTorque(source);
CompileCurrentAst(options);
} catch (TorqueAbortCompilation&) {
// Do nothing. The relevant TorqueMessage is part of the
// TorqueMessages contextual.
}
result.source_file_map = SourceFileMap::Get();
result.language_server_data = std::move(LanguageServerData::Get());
result.messages = std::move(TorqueMessages::Get());
return result;
}
TorqueCompilerResult CompileTorque(std::vector<std::string> files,
TorqueCompilerOptions options) {
SourceFileMap::Scope source_map_scope(options.v8_root);
CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid());
CurrentAst::Scope ast_scope;
TorqueMessages::Scope messages_scope;
LanguageServerData::Scope server_data_scope;
TorqueCompilerResult result;
try {
for (const auto& path : files) {
ReadAndParseTorqueFile(path);
}
CompileCurrentAst(options);
} catch (TorqueAbortCompilation&) {
// Do nothing. The relevant TorqueMessage is part of the
// TorqueMessages contextual.
}
result.source_file_map = SourceFileMap::Get();
result.language_server_data = std::move(LanguageServerData::Get());
result.messages = std::move(TorqueMessages::Get());
return result;
}
} // namespace torque
} // namespace internal
} // namespace v8