• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "es2panda.h"
17 
18 #include <compiler/core/compileQueue.h>
19 #include <compiler/core/compilerContext.h>
20 #include <compiler/core/compilerImpl.h>
21 #include <compiler/core/emitter/emitter.h>
22 #include <parser/parserImpl.h>
23 #include <parser/program/program.h>
24 #include <parser/transformer/transformer.h>
25 #include <typescript/checker.h>
26 #include <util/helpers.h>
27 
28 #include <iostream>
29 
30 namespace panda::es2panda {
31 // Compiler
32 
33 constexpr size_t DEFAULT_THREAD_COUNT = 2;
34 
Compiler(ScriptExtension ext)35 Compiler::Compiler(ScriptExtension ext) : Compiler(ext, DEFAULT_THREAD_COUNT) {}
36 
Compiler(ScriptExtension ext,size_t threadCount)37 Compiler::Compiler(ScriptExtension ext, size_t threadCount)
38     : parser_(new parser::ParserImpl(ext)), compiler_(new compiler::CompilerImpl(threadCount))
39 {
40     if (parser_->Extension() == ScriptExtension::TS) {
41         transformer_ = std::make_unique<parser::Transformer>(parser_->Allocator());
42     }
43 }
44 
~Compiler()45 Compiler::~Compiler()
46 {
47     delete parser_;
48     delete compiler_;
49 }
50 
CreateJsonContentProgram(std::string src,std::string rname,util::Hotfix * hotfixHelper)51 panda::pandasm::Program *CreateJsonContentProgram(std::string src, std::string rname, util::Hotfix *hotfixHelper)
52 {
53     panda::es2panda::compiler::CompilerContext context(nullptr, false, false, false, false, true,
54                                                        src, "", util::StringView(rname), hotfixHelper);
55     return context.GetEmitter()->Finalize(false, nullptr);
56 }
57 
Compile(const SourceFile & input,const CompilerOptions & options,util::SymbolTable * symbolTable)58 panda::pandasm::Program *Compiler::Compile(const SourceFile &input, const CompilerOptions &options,
59     util::SymbolTable *symbolTable)
60 {
61     /* TODO(dbatyai): pass string view */
62     std::string fname(input.fileName);
63     std::string src(input.source);
64     std::string rname(input.recordName);
65     std::string sourcefile(input.sourcefile);
66     std::string pkgName(input.pkgName);
67     parser::ScriptKind kind(input.scriptKind);
68 
69     auto *hotfixHelper = InitHotfixHelper(input, options, symbolTable);
70 
71     if (fname.substr(fname.find_last_of(".") + 1) == "json") {
72         return CreateJsonContentProgram(src, rname, hotfixHelper);
73     }
74 
75     try {
76         auto ast = parser_->Parse(fname, src, rname, kind);
77         ast.Binder()->SetProgram(&ast);
78 
79         if (options.dumpAst) {
80             std::cout << ast.Dump() << std::endl;
81         }
82 
83         if (ast.Extension() == ScriptExtension::TS && options.enableTypeCheck) {
84             ArenaAllocator localAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true);
85             auto checker = std::make_unique<checker::Checker>(&localAllocator, ast.Binder());
86             checker->StartChecker();
87         }
88 
89         if (ast.Extension() == ScriptExtension::TS) {
90             transformer_->Transform(&ast);
91             ast.Binder()->IdentifierAnalysis(binder::ResolveBindingFlags::ALL);
92         }
93 
94         if (options.parseOnly) {
95             return nullptr;
96         }
97 
98         std::string debugInfoSourceFile = options.debugInfoSourceFile.empty() ?
99                                           sourcefile : options.debugInfoSourceFile;
100         auto *prog = compiler_->Compile(&ast, options, debugInfoSourceFile, pkgName);
101 
102         CleanHotfixHelper(hotfixHelper);
103         return prog;
104     } catch (const class Error &e) {
105         error_ = e;
106 
107         CleanHotfixHelper(hotfixHelper);
108         return nullptr;
109     }
110 }
111 
InitHotfixHelper(const SourceFile & input,const CompilerOptions & options,util::SymbolTable * symbolTable)112 util::Hotfix *Compiler::InitHotfixHelper(const SourceFile &input, const CompilerOptions &options,
113                                          util::SymbolTable *symbolTable)
114 {
115     bool needDumpSymbolFile = !options.hotfixOptions.dumpSymbolTable.empty();
116     bool needGeneratePatch = options.hotfixOptions.generatePatch && !options.hotfixOptions.symbolTable.empty();
117     bool isHotReload = options.hotfixOptions.hotReload;
118     util::Hotfix *hotfixHelper = nullptr;
119     if (symbolTable && (needDumpSymbolFile || needGeneratePatch || isHotReload)) {
120         hotfixHelper = new util::Hotfix(needDumpSymbolFile, needGeneratePatch, isHotReload,
121                                         input.recordName, symbolTable);
122         parser_->AddHotfixHelper(hotfixHelper);
123         compiler_->AddHotfixHelper(hotfixHelper);
124     }
125     return hotfixHelper;
126 }
127 
CleanHotfixHelper(const util::Hotfix * hotfixHelper)128 void Compiler::CleanHotfixHelper(const util::Hotfix *hotfixHelper)
129 {
130     if (hotfixHelper) {
131         delete hotfixHelper;
132         hotfixHelper = nullptr;
133     }
134 }
135 
DumpAsm(const panda::pandasm::Program * prog)136 void Compiler::DumpAsm(const panda::pandasm::Program *prog)
137 {
138     compiler::CompilerImpl::DumpAsm(prog);
139 }
140 
CompileFiles(CompilerOptions & options,std::map<std::string,panda::es2panda::util::ProgramCache * > & progsInfo,panda::ArenaAllocator * allocator)141 int Compiler::CompileFiles(CompilerOptions &options,
142     std::map<std::string, panda::es2panda::util::ProgramCache*> &progsInfo, panda::ArenaAllocator *allocator)
143 {
144     util::SymbolTable *symbolTable = nullptr;
145     if (!options.hotfixOptions.symbolTable.empty() || !options.hotfixOptions.dumpSymbolTable.empty()) {
146         symbolTable = new util::SymbolTable(options.hotfixOptions.symbolTable, options.hotfixOptions.dumpSymbolTable);
147         if (!symbolTable->Initialize()) {
148             std::cerr << "Exits due to hot fix initialize failed!" << std::endl;
149             return 1;
150         }
151     }
152 
153     bool failed = false;
154     auto queue = new compiler::CompileFileQueue(options.fileThreadCount, &options, progsInfo, symbolTable, allocator);
155 
156     try {
157         queue->Schedule();
158         queue->Consume();
159         queue->Wait();
160     } catch (const class Error &e) {
161         failed = true;
162     }
163 
164     delete queue;
165     queue = nullptr;
166 
167     if (symbolTable) {
168         delete symbolTable;
169         symbolTable = nullptr;
170     }
171 
172     return failed ? 1 : 0;
173 }
174 
CompileFile(const CompilerOptions & options,SourceFile * src,util::SymbolTable * symbolTable)175 panda::pandasm::Program *Compiler::CompileFile(const CompilerOptions &options, SourceFile *src,
176                                                util::SymbolTable *symbolTable)
177 {
178     if (src->source.empty()) {
179         return nullptr;
180     }
181 
182     auto *program = Compile(*src, options, symbolTable);
183     if (!program) {
184         const auto &err = GetError();
185 
186         if (err.Message().empty() && options.parseOnly) {
187             return nullptr;
188         }
189 
190         std::cerr << err.TypeString() << ": " << err.Message();
191         std::cerr << " [" << util::Helpers::BaseName(src->fileName) << ":"
192                   << err.Line() << ":" << err.Col() << "]" << std::endl;
193         throw err;
194     }
195     return program;
196 }
197 
198 }  // namespace panda::es2panda
199