1/* 2 * Copyright (c) 2024 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_lib.h" 17#include <memory> 18#include <cstring> 19#include <cstdint> 20#include <variant> 21 22#include "varbinder/varbinder.h" 23#include "varbinder/scope.h" 24#include "varbinder/variable.h" 25#include "public/public.h" 26#include "generated/signatures.h" 27#include "es2panda.h" 28#include "assembler/assembly-program.h" 29#include "varbinder/ETSBinder.h" 30#include "checker/ETSAnalyzer.h" 31#include "checker/ETSchecker.h" 32#include "compiler/core/compileQueue.h" 33#include "compiler/core/ETSCompiler.h" 34#include "compiler/core/ETSemitter.h" 35#include "compiler/core/ETSGen.h" 36#include "compiler/core/regSpiller.h" 37#include "compiler/lowering/phase.h" 38#include "compiler/lowering/checkerPhase.h" 39#include "compiler/lowering/scopesInit/scopesInitPhase.h" 40#include "compiler/core/labelPair.h" 41#include "ir/astNode.h" 42#include "ir/expressions/arrowFunctionExpression.h" 43#include "ir/ts/tsAsExpression.h" 44#include "ir/expressions/assignmentExpression.h" 45#include "ir/expressions/binaryExpression.h" 46#include "ir/statements/blockStatement.h" 47#include "ir/expressions/callExpression.h" 48#include "ir/expressions/chainExpression.h" 49#include "ir/statements/classDeclaration.h" 50#include "ir/base/classDefinition.h" 51#include "ir/base/classElement.h" 52#include "ir/ts/tsClassImplements.h" 53#include "ir/base/classProperty.h" 54#include "ir/base/scriptFunctionSignature.h" 55#include "ir/statements/expressionStatement.h" 56#include "ir/statements/functionDeclaration.h" 57#include "ir/expressions/functionExpression.h" 58#include "ir/ets/etsFunctionType.h" 59#include "ir/expressions/identifier.h" 60#include "ir/statements/ifStatement.h" 61#include "ir/module/importDeclaration.h" 62#include "ir/expressions/importExpression.h" 63#include "ir/module/importSpecifier.h" 64#include "ir/base/methodDefinition.h" 65#include "ir/ets/etsNewClassInstanceExpression.h" 66#include "ir/ets/etsNewArrayInstanceExpression.h" 67#include "ir/ets/etsNewMultiDimArrayInstanceExpression.h" 68#include "ir/expressions/thisExpression.h" 69#include "ir/ts/tsTypeParameter.h" 70#include "ir/ts/tsTypeParameterDeclaration.h" 71#include "ir/ts/tsTypeParameterInstantiation.h" 72#include "ir/statements/variableDeclaration.h" 73#include "ir/statements/variableDeclarator.h" 74#include "parser/ETSparser.h" 75#include "parser/context/parserContext.h" 76#include "parser/program/program.h" 77#include "util/generateBin.h" 78#include "util/language.h" 79#include "util/options.h" 80#include "generated/es2panda_lib/es2panda_lib_include.inc" 81 82// NOLINTBEGIN 83 84namespace ark::es2panda::public_lib { 85 86struct TokenTypeToStr { 87 lexer::TokenType token; 88 char const *str; 89}; 90 91__attribute__((unused)) lexer::TokenType StrToToken(TokenTypeToStr const *table, char const *str) 92{ 93 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 94 for (auto *tp = table; tp->str != nullptr; tp++) { 95 if (strcmp(str, tp->str) == 0) { 96 return tp->token; 97 } 98 } 99 UNREACHABLE(); 100} 101 102__attribute__((unused)) char const *TokenToStr(TokenTypeToStr const *table, lexer::TokenType token) 103{ 104 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 105 for (auto *tp = table; tp->str != nullptr; tp++) { 106 if (tp->token == token) { 107 return tp->str; 108 } 109 } 110 UNREACHABLE(); 111} 112 113__attribute__((unused)) char *StringViewToCString(ArenaAllocator *allocator, util::StringView const sv) 114{ 115 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 116 std::string_view utf8 = sv.Utf8(); 117 if (utf8.data()[utf8.size()] == '\0') { 118 // Avoid superfluous allocation. 119 return const_cast<char *>(utf8.data()); 120 } 121 char *res = reinterpret_cast<char *>(allocator->Alloc(utf8.size() + 1)); 122 [[maybe_unused]] auto err = memmove_s(res, utf8.size() + 1, utf8.cbegin(), utf8.size()); 123 ASSERT(err == EOK); 124 res[utf8.size()] = '\0'; 125 return res; 126 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 127} 128 129char *StringViewToCString(ArenaAllocator *allocator, std::string_view const utf8) 130{ 131 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 132 if (utf8.data()[utf8.size()] == '\0') { 133 // Avoid superfluous allocation. 134 return const_cast<char *>(utf8.data()); 135 } 136 char *res = reinterpret_cast<char *>(allocator->Alloc(utf8.size() + 1)); 137 [[maybe_unused]] auto err = memmove_s(res, utf8.size() + 1, utf8.cbegin(), utf8.size()); 138 ASSERT(err == EOK); 139 res[utf8.size()] = '\0'; 140 return res; 141 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 142} 143 144__attribute__((unused)) char *StdStringToCString(ArenaAllocator *allocator, std::string str) 145{ 146 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 147 char *res = reinterpret_cast<char *>(allocator->Alloc(str.length() + 1)); 148 [[maybe_unused]] auto err = memcpy_s(res, str.length() + 1, str.c_str(), str.length() + 1); 149 ASSERT(err == EOK); 150 return res; 151 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 152} 153 154__attribute__((unused)) es2panda_variantDoubleCharArrayBool EnumMemberResultToEs2pandaVariant( 155 ArenaAllocator *allocator, varbinder::EnumMemberResult variant) 156{ 157 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 158 es2panda_variantDoubleCharArrayBool es2panda_variant; 159 es2panda_variant.index = variant.index(); 160 switch (es2panda_variant.index) { 161 case es2panda_variantIndex::DOUBLE: 162 es2panda_variant.variant.d = std::get<double>(variant); 163 break; 164 case es2panda_variantIndex::CHAR: 165 es2panda_variant.variant.c = StringViewToCString(allocator, std::get<util::StringView>(variant)); 166 break; 167 case es2panda_variantIndex::BOOL: 168 es2panda_variant.variant.b = std::get<bool>(variant); 169 break; 170 default: 171 break; 172 } 173 return es2panda_variant; 174 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-simplify-subscript-expr) 175} 176 177__attribute__((unused)) char const *ArenaStrdup(ArenaAllocator *allocator, char const *src) 178{ 179 size_t len = strlen(src); 180 char *res = reinterpret_cast<char *>(allocator->Alloc(len + 1)); 181 [[maybe_unused]] auto err = memmove_s(res, len + 1, src, len); 182 ASSERT(err == EOK); 183 184 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 185 res[len] = '\0'; 186 return res; 187} 188 189extern "C" es2panda_Config *CreateConfig(int args, char const **argv) 190{ 191 constexpr auto COMPILER_SIZE = 256_MB; 192 193 mem::MemConfig::Initialize(0, 0, COMPILER_SIZE, 0, 0, 0); 194 PoolManager::Initialize(PoolType::MMAP); 195 196 auto *options = new util::Options(); 197 if (!options->Parse(args, argv)) { 198 // NOTE: gogabr. report option errors properly. 199 std::cerr << options->ErrorMsg() << std::endl; 200 return nullptr; 201 } 202 Logger::ComponentMask mask {}; 203 mask.set(Logger::Component::ES2PANDA); 204 Logger::InitializeStdLogging(Logger::LevelFromString(options->LogLevel()), mask); 205 206 auto *res = new ConfigImpl; 207 res->options = options; 208 return reinterpret_cast<es2panda_Config *>(res); 209} 210 211extern "C" void DestroyConfig(es2panda_Config *config) 212{ 213 PoolManager::Finalize(); 214 mem::MemConfig::Finalize(); 215 216 auto *cfg = reinterpret_cast<ConfigImpl *>(config); 217 if (cfg == nullptr) { 218 return; 219 } 220 221 delete cfg->options; 222 delete cfg; 223} 224 225static void CompileJob(public_lib::Context *context, varbinder::FunctionScope *scope, 226 compiler::ProgramElement *programElement) 227{ 228 compiler::StaticRegSpiller regSpiller; 229 ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER, nullptr, true}; 230 compiler::ETSCompiler astCompiler {}; 231 compiler::ETSGen cg {&allocator, ®Spiller, context, std::make_tuple(scope, programElement, &astCompiler)}; 232 compiler::ETSFunctionEmitter funcEmitter {&cg, programElement}; 233 funcEmitter.Generate(); 234} 235 236__attribute__((unused)) static es2panda_Context *CreateContext(es2panda_Config *config, std::string const &&source, 237 std::string const &&fileName) 238{ 239 auto *cfg = reinterpret_cast<ConfigImpl *>(config); 240 auto *res = new Context; 241 res->input = source; 242 res->sourceFileName = fileName; 243 res->config = cfg; 244 245 try { 246 res->sourceFile = new SourceFile(res->sourceFileName, res->input, cfg->options->ParseModule()); 247 res->allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); 248 res->queue = new compiler::CompileQueue(cfg->options->ThreadCount()); 249 250 auto *varbinder = res->allocator->New<varbinder::ETSBinder>(res->allocator); 251 res->parserProgram = new parser::Program(res->allocator, varbinder); 252 res->parserProgram->MarkEntry(); 253 res->parser = 254 new parser::ETSParser(res->parserProgram, cfg->options->CompilerOptions(), parser::ParserStatus::NO_OPTS); 255 res->checker = new checker::ETSChecker(); 256 res->checker->ErrorLogger()->SetOstream(nullptr); 257 res->analyzer = new checker::ETSAnalyzer(res->checker); 258 res->checker->SetAnalyzer(res->analyzer); 259 260 varbinder->SetProgram(res->parserProgram); 261 262 varbinder->SetContext(res); 263 res->codeGenCb = CompileJob; 264 res->phases = compiler::GetPhaseList(ScriptExtension::ETS); 265 res->currentPhase = 0; 266 res->emitter = new compiler::ETSEmitter(res); 267 res->program = nullptr; 268 res->state = ES2PANDA_STATE_NEW; 269 } catch (Error &e) { 270 std::stringstream ss; 271 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 272 res->errorMessage = ss.str(); 273 res->state = ES2PANDA_STATE_ERROR; 274 } 275 return reinterpret_cast<es2panda_Context *>(res); 276} 277 278extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromFile(es2panda_Config *config, 279 char const *sourceFileName) 280{ 281 std::ifstream inputStream; 282 inputStream.open(sourceFileName); 283 if (inputStream.fail()) { 284 auto *res = new Context; 285 res->errorMessage = "Failed to open file: "; 286 res->errorMessage.append(sourceFileName); 287 return reinterpret_cast<es2panda_Context *>(res); 288 } 289 std::stringstream ss; 290 ss << inputStream.rdbuf(); 291 if (inputStream.fail()) { 292 auto *res = new Context; 293 res->errorMessage = "Failed to read file: "; 294 res->errorMessage.append(sourceFileName); 295 return reinterpret_cast<es2panda_Context *>(res); 296 } 297 return CreateContext(config, ss.str(), sourceFileName); 298} 299 300extern "C" __attribute__((unused)) es2panda_Context *CreateContextFromString(es2panda_Config *config, 301 char const *source, char const *fileName) 302{ 303 // NOTE: gogabr. avoid copying source. 304 return CreateContext(config, source, fileName); 305} 306 307__attribute__((unused)) static Context *Parse(Context *ctx) 308{ 309 if (ctx->state != ES2PANDA_STATE_NEW) { 310 ctx->state = ES2PANDA_STATE_ERROR; 311 ctx->errorMessage = "Bad state at entry to Parse, needed NEW"; 312 return ctx; 313 } 314 auto handleError = [ctx](Error const &e) { 315 std::stringstream ss; 316 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 317 ctx->errorMessage = ss.str(); 318 ctx->state = ES2PANDA_STATE_ERROR; 319 }; 320 321 try { 322 ctx->parser->ParseScript(*ctx->sourceFile, ctx->config->options->CompilerOptions().compilationMode == 323 CompilationMode::GEN_STD_LIB); 324 ctx->state = ES2PANDA_STATE_PARSED; 325 if (ctx->parser->ErrorLogger()->IsAnyError()) { 326 handleError(ctx->parser->ErrorLogger()->Log()[0]); 327 } 328 } catch (Error &e) { 329 std::stringstream ss; 330 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 331 ctx->errorMessage = ss.str(); 332 ctx->state = ES2PANDA_STATE_ERROR; 333 } 334 335 return ctx; 336} 337 338__attribute__((unused)) static Context *InitScopes(Context *ctx) 339{ 340 // NOTE: Remove duplicated code in all phases 341 if (ctx->state < ES2PANDA_STATE_PARSED) { 342 ctx = Parse(ctx); 343 } 344 if (ctx->state == ES2PANDA_STATE_ERROR) { 345 return ctx; 346 } 347 348 ASSERT(ctx->state == ES2PANDA_STATE_PARSED); 349 350 try { 351 compiler::InitScopesPhaseETS scopesInit; 352 scopesInit.Perform(ctx, ctx->parserProgram); 353 do { 354 if (ctx->currentPhase >= ctx->phases.size()) { 355 break; 356 } 357 ctx->phases[ctx->currentPhase]->Apply(ctx, ctx->parserProgram); 358 } while (ctx->phases[ctx->currentPhase++]->Name() != compiler::ScopesInitPhase::NAME); 359 ctx->state = ES2PANDA_STATE_SCOPE_INITED; 360 } catch (Error &e) { 361 std::stringstream ss; 362 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 363 ctx->errorMessage = ss.str(); 364 ctx->state = ES2PANDA_STATE_ERROR; 365 } 366 return ctx; 367} 368 369__attribute__((unused)) static Context *Check(Context *ctx) 370{ 371 if (ctx->state < ES2PANDA_STATE_PARSED) { 372 ctx = Parse(ctx); 373 } 374 375 if (ctx->state == ES2PANDA_STATE_ERROR) { 376 return ctx; 377 } 378 379 ASSERT(ctx->state >= ES2PANDA_STATE_PARSED && ctx->state < ES2PANDA_STATE_CHECKED); 380 381 auto handleError = [ctx](Error const &e) { 382 std::stringstream ss; 383 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 384 ctx->errorMessage = ss.str(); 385 ctx->state = ES2PANDA_STATE_ERROR; 386 }; 387 388 try { 389 do { 390 if (ctx->currentPhase >= ctx->phases.size()) { 391 break; 392 } 393 394 ctx->phases[ctx->currentPhase]->Apply(ctx, ctx->parserProgram); 395 } while (ctx->phases[ctx->currentPhase++]->Name() != compiler::CheckerPhase::NAME); 396 if (ctx->checker->ErrorLogger()->IsAnyError()) { 397 handleError(ctx->checker->ErrorLogger()->Log()[0]); 398 } else if (ctx->parser->ErrorLogger()->IsAnyError()) { 399 handleError(ctx->parser->ErrorLogger()->Log()[0]); 400 } else { 401 ctx->state = ES2PANDA_STATE_CHECKED; 402 } 403 } catch (Error &e) { 404 handleError(e); 405 } 406 return ctx; 407} 408 409__attribute__((unused)) static Context *Lower(Context *ctx) 410{ 411 if (ctx->state < ES2PANDA_STATE_CHECKED) { 412 ctx = Check(ctx); 413 } 414 415 if (ctx->state == ES2PANDA_STATE_ERROR) { 416 return ctx; 417 } 418 419 ASSERT(ctx->state == ES2PANDA_STATE_CHECKED); 420 421 try { 422 while (ctx->currentPhase < ctx->phases.size()) { 423 ctx->phases[ctx->currentPhase++]->Apply(ctx, ctx->parserProgram); 424 } 425 426 ctx->state = ES2PANDA_STATE_LOWERED; 427 } catch (Error &e) { 428 std::stringstream ss; 429 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 430 ctx->errorMessage = ss.str(); 431 ctx->state = ES2PANDA_STATE_ERROR; 432 } 433 434 return ctx; 435} 436 437__attribute__((unused)) static Context *GenerateAsm(Context *ctx) 438{ 439 if (ctx->state < ES2PANDA_STATE_LOWERED) { 440 ctx = Lower(ctx); 441 } 442 443 if (ctx->state == ES2PANDA_STATE_ERROR) { 444 return ctx; 445 } 446 447 ASSERT(ctx->state == ES2PANDA_STATE_LOWERED); 448 449 auto *emitter = ctx->emitter; 450 try { 451 emitter->GenAnnotation(); 452 453 // Handle context literals. 454 uint32_t index = 0; 455 for (const auto &buff : ctx->contextLiterals) { 456 emitter->AddLiteralBuffer(buff, index++); 457 } 458 459 emitter->LiteralBufferIndex() += ctx->contextLiterals.size(); 460 461 /* Main thread can also be used instead of idling */ 462 ctx->queue->Schedule(ctx); 463 ctx->queue->Consume(); 464 ctx->queue->Wait( 465 [emitter](compiler::CompileJob *job) { emitter->AddProgramElement(job->GetProgramElement()); }); 466 ASSERT(ctx->program == nullptr); 467 ctx->program = 468 emitter->Finalize(ctx->config->options->CompilerOptions().dumpDebugInfo, compiler::Signatures::ETS_GLOBAL); 469 470 ctx->state = ES2PANDA_STATE_ASM_GENERATED; 471 } catch (Error &e) { 472 std::stringstream ss; 473 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 474 ctx->errorMessage = ss.str(); 475 ctx->state = ES2PANDA_STATE_ERROR; 476 } 477 return ctx; 478} 479 480__attribute__((unused)) Context *GenerateBin(Context *ctx) 481{ 482 if (ctx->state < ES2PANDA_STATE_ASM_GENERATED) { 483 ctx = GenerateAsm(ctx); 484 } 485 486 if (ctx->state == ES2PANDA_STATE_ERROR) { 487 return ctx; 488 } 489 490 ASSERT(ctx->state == ES2PANDA_STATE_ASM_GENERATED); 491 492 try { 493 ASSERT(ctx->program != nullptr); 494 util::GenerateProgram(ctx->program, ctx->config->options, 495 [ctx](const std::string &str) { ctx->errorMessage = str; }); 496 497 ctx->state = ES2PANDA_STATE_BIN_GENERATED; 498 } catch (Error &e) { 499 std::stringstream ss; 500 ss << e.TypeString() << ": " << e.Message() << "[" << e.File() << ":" << e.Line() << "," << e.Col() << "]"; 501 ctx->errorMessage = ss.str(); 502 ctx->state = ES2PANDA_STATE_ERROR; 503 } 504 return ctx; 505} 506 507extern "C" __attribute__((unused)) es2panda_Context *ProceedToState(es2panda_Context *context, 508 es2panda_ContextState state) 509{ 510 auto *ctx = reinterpret_cast<Context *>(context); 511 switch (state) { 512 case ES2PANDA_STATE_NEW: 513 break; 514 case ES2PANDA_STATE_PARSED: 515 ctx = Parse(ctx); 516 break; 517 case ES2PANDA_STATE_SCOPE_INITED: 518 ctx = InitScopes(ctx); 519 break; 520 case ES2PANDA_STATE_CHECKED: 521 ctx = Check(ctx); 522 break; 523 case ES2PANDA_STATE_LOWERED: 524 ctx = Lower(ctx); 525 break; 526 case ES2PANDA_STATE_ASM_GENERATED: 527 ctx = GenerateAsm(ctx); 528 break; 529 case ES2PANDA_STATE_BIN_GENERATED: 530 ctx = GenerateBin(ctx); 531 break; 532 default: 533 ctx->errorMessage = "It does not make sense to request stage"; 534 ctx->state = ES2PANDA_STATE_ERROR; 535 break; 536 } 537 return reinterpret_cast<es2panda_Context *>(ctx); 538} 539 540extern "C" __attribute__((unused)) void DestroyContext(es2panda_Context *context) 541{ 542 auto *ctx = reinterpret_cast<Context *>(context); 543 delete ctx->program; 544 delete ctx->emitter; 545 delete ctx->analyzer; 546 delete ctx->checker; 547 delete ctx->parser; 548 delete ctx->parserProgram; 549 delete ctx->queue; 550 delete ctx->allocator; 551 delete ctx->sourceFile; 552 delete ctx; 553} 554 555extern "C" __attribute__((unused)) es2panda_ContextState ContextState(es2panda_Context *context) 556{ 557 auto *s = reinterpret_cast<Context *>(context); 558 return s->state; 559} 560 561extern "C" __attribute__((unused)) char const *ContextErrorMessage(es2panda_Context *context) 562{ 563 auto *s = reinterpret_cast<Context *>(context); 564 return s->errorMessage.c_str(); 565} 566 567extern "C" __attribute__((unused)) es2panda_Program *ContextProgram(es2panda_Context *context) 568{ 569 auto *ctx = reinterpret_cast<Context *>(context); 570 return reinterpret_cast<es2panda_Program *>(ctx->parserProgram); 571} 572 573extern "C" __attribute__((unused)) es2panda_AstNode *ProgramAst(es2panda_Program *program) 574{ 575 auto *pgm = reinterpret_cast<parser::Program *>(program); 576 return reinterpret_cast<es2panda_AstNode *>(pgm->Ast()); 577} 578 579using ExternalSourceEntry = std::pair<char const *, ArenaVector<parser::Program *> *>; 580 581extern "C" __attribute__((unused)) es2panda_ExternalSource **ProgramExternalSources(es2panda_Program *program, 582 size_t *lenP) 583{ 584 auto *pgm = reinterpret_cast<parser::Program *>(program); 585 auto *allocator = pgm->VarBinder()->Allocator(); 586 auto *vec = allocator->New<ArenaVector<ExternalSourceEntry *>>(allocator->Adapter()); 587 588 for (auto &[e_name, e_programs] : pgm->ExternalSources()) { 589 vec->push_back(allocator->New<ExternalSourceEntry>(StringViewToCString(allocator, e_name), &e_programs)); 590 } 591 592 *lenP = vec->size(); 593 return reinterpret_cast<es2panda_ExternalSource **>(vec->data()); 594} 595 596extern "C" __attribute__((unused)) char const *ExternalSourceName(es2panda_ExternalSource *eSource) 597{ 598 auto *entry = reinterpret_cast<ExternalSourceEntry *>(eSource); 599 return entry->first; 600} 601 602extern "C" __attribute__((unused)) es2panda_Program **ExternalSourcePrograms(es2panda_ExternalSource *eSource, 603 size_t *lenP) 604{ 605 auto *entry = reinterpret_cast<ExternalSourceEntry *>(eSource); 606 *lenP = entry->second->size(); 607 return reinterpret_cast<es2panda_Program **>(entry->second->data()); 608} 609 610extern "C" void AstNodeForEach(es2panda_AstNode *ast, void (*func)(es2panda_AstNode *, void *), void *arg) 611{ 612 auto *node = reinterpret_cast<ir::AstNode *>(ast); 613 func(ast, arg); 614 node->IterateRecursively([=](ir::AstNode *child) { func(reinterpret_cast<es2panda_AstNode *>(child), arg); }); 615} 616 617#define SET_NUMBER_LITERAL_IMPL(name, type) \ 618 extern "C" bool SetNumberLiteral##name(es2panda_AstNode *node, type new_value) \ 619 { \ 620 auto &n = reinterpret_cast<ir::NumberLiteral *>(node)->Number(); \ 621 if (!n.Is##name()) { \ 622 return false; \ 623 } \ 624 n.SetValue<type>(std::move(new_value)); \ 625 return true; \ 626 } 627 628SET_NUMBER_LITERAL_IMPL(Int, int32_t) 629SET_NUMBER_LITERAL_IMPL(Long, int64_t) 630SET_NUMBER_LITERAL_IMPL(Double, double) 631SET_NUMBER_LITERAL_IMPL(Float, float) 632 633#undef SET_NUMBER_LITERAL_IMPL 634 635#include "generated/es2panda_lib/es2panda_lib_impl.inc" 636 637es2panda_Impl g_impl = { 638 ES2PANDA_LIB_VERSION, 639 640 CreateConfig, DestroyConfig, 641 CreateContextFromFile, CreateContextFromString, 642 ProceedToState, DestroyContext, 643 ContextState, ContextErrorMessage, 644 ContextProgram, ProgramAst, 645 ProgramExternalSources, ExternalSourceName, 646 ExternalSourcePrograms, AstNodeForEach, 647 SetNumberLiteralInt, SetNumberLiteralLong, 648 SetNumberLiteralDouble, SetNumberLiteralFloat, 649 650#include "generated/es2panda_lib/es2panda_lib_list.inc" 651 652}; 653 654} // namespace ark::es2panda::public_lib 655 656extern "C" es2panda_Impl const *es2panda_GetImpl(int version) 657{ 658 if (version != ES2PANDA_LIB_VERSION) { 659 return nullptr; 660 } 661 return &ark::es2panda::public_lib::g_impl; 662} 663 664// NOLINTEND 665