13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include <binder/binder.h>
173af6ab5fSopenharmony_ci#include <ir/base/scriptFunction.h>
183af6ab5fSopenharmony_ci#include <ir/expression.h>
193af6ab5fSopenharmony_ci#include <ir/expressions/arrayExpression.h>
203af6ab5fSopenharmony_ci#include <ir/expressions/callExpression.h>
213af6ab5fSopenharmony_ci#include <ir/expressions/functionExpression.h>
223af6ab5fSopenharmony_ci#include <ir/expressions/identifier.h>
233af6ab5fSopenharmony_ci#include <ir/expressions/memberExpression.h>
243af6ab5fSopenharmony_ci#include <ir/statements/expressionStatement.h>
253af6ab5fSopenharmony_ci#include <ir/statements/blockStatement.h>
263af6ab5fSopenharmony_ci
273af6ab5fSopenharmony_ci#include <string_view>
283af6ab5fSopenharmony_ci#include <vector>
293af6ab5fSopenharmony_ci
303af6ab5fSopenharmony_ci#include "parserImpl.h"
313af6ab5fSopenharmony_ci
323af6ab5fSopenharmony_cinamespace panda::es2panda::parser {
333af6ab5fSopenharmony_cistatic std::vector<std::string_view> cjsMandatoryParams = {binder::Binder::CJS_MANDATORY_PARAM_EXPORTS,
343af6ab5fSopenharmony_ci                                                           binder::Binder::CJS_MANDATORY_PARAM_REQUIRE,
353af6ab5fSopenharmony_ci                                                           binder::Binder::CJS_MANDATORY_PARAM_MODULE,
363af6ab5fSopenharmony_ci                                                           binder::Binder::CJS_MANDATORY_PARAM_FILENAME,
373af6ab5fSopenharmony_ci                                                           binder::Binder::CJS_MANDATORY_PARAM_DIRNAME};
383af6ab5fSopenharmony_ci
393af6ab5fSopenharmony_civoid ParserImpl::AddCommonjsParams(ArenaVector<ir::Expression *> &params)
403af6ab5fSopenharmony_ci{
413af6ab5fSopenharmony_ci    for (auto paramName : cjsMandatoryParams) {
423af6ab5fSopenharmony_ci        ir::Expression *param = AllocNode<ir::Identifier>(paramName);
433af6ab5fSopenharmony_ci        param->AsIdentifier()->SetReference();
443af6ab5fSopenharmony_ci        Binder()->AddParamDecl(param);
453af6ab5fSopenharmony_ci        params.push_back(param);
463af6ab5fSopenharmony_ci    }
473af6ab5fSopenharmony_ci}
483af6ab5fSopenharmony_ci
493af6ab5fSopenharmony_civoid ParserImpl::AddReflectApplyArgs(ArenaVector<ir::Expression *> &args, ir::FunctionExpression *wrapper)
503af6ab5fSopenharmony_ci{
513af6ab5fSopenharmony_ci    ASSERT(wrapper != nullptr);
523af6ab5fSopenharmony_ci    // wrapper
533af6ab5fSopenharmony_ci    args.push_back(wrapper);
543af6ab5fSopenharmony_ci    // thisValue
553af6ab5fSopenharmony_ci    ir::Expression *thisValue = AllocNode<ir::Identifier>(binder::Binder::CJS_MANDATORY_PARAM_EXPORTS);
563af6ab5fSopenharmony_ci    thisValue->AsIdentifier()->SetReference();
573af6ab5fSopenharmony_ci    args.push_back(thisValue);
583af6ab5fSopenharmony_ci    // wrapper's arguments
593af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> elements(Allocator()->Adapter());
603af6ab5fSopenharmony_ci    for (auto argName : cjsMandatoryParams) {
613af6ab5fSopenharmony_ci        ir::Expression *arg = AllocNode<ir::Identifier>(argName);
623af6ab5fSopenharmony_ci        arg->AsIdentifier()->SetReference();
633af6ab5fSopenharmony_ci        elements.push_back(arg);
643af6ab5fSopenharmony_ci    }
653af6ab5fSopenharmony_ci    ir::ArrayExpression *wrapperArgsArray =
663af6ab5fSopenharmony_ci        AllocNode<ir::ArrayExpression>(ir::AstNodeType::ARRAY_EXPRESSION, std::move(elements), false);
673af6ab5fSopenharmony_ci    args.push_back(wrapperArgsArray);
683af6ab5fSopenharmony_ci}
693af6ab5fSopenharmony_ci
703af6ab5fSopenharmony_civoid ParserImpl::ParseCommonjs()
713af6ab5fSopenharmony_ci{
723af6ab5fSopenharmony_ci    // create FunctionExpression as callee
733af6ab5fSopenharmony_ci    ir::FunctionExpression *wrapper = nullptr;
743af6ab5fSopenharmony_ci    {
753af6ab5fSopenharmony_ci        FunctionContext functionContext(this, ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET);
763af6ab5fSopenharmony_ci        FunctionParameterContext funcParamContext(&context_, Binder());
773af6ab5fSopenharmony_ci        auto *funcParamScope = funcParamContext.LexicalScope().GetScope();
783af6ab5fSopenharmony_ci
793af6ab5fSopenharmony_ci        ArenaVector<ir::Expression *> params(Allocator()->Adapter());
803af6ab5fSopenharmony_ci        AddCommonjsParams(params);
813af6ab5fSopenharmony_ci
823af6ab5fSopenharmony_ci        auto functionCtx = binder::LexicalScope<binder::FunctionScope>(Binder());
833af6ab5fSopenharmony_ci        auto *functionScope = functionCtx.GetScope();
843af6ab5fSopenharmony_ci        functionScope->BindParamScope(funcParamScope);
853af6ab5fSopenharmony_ci        funcParamScope->BindFunctionScope(functionScope);
863af6ab5fSopenharmony_ci
873af6ab5fSopenharmony_ci        ParseProgram(ScriptKind::COMMONJS);
883af6ab5fSopenharmony_ci
893af6ab5fSopenharmony_ci        auto *funcNode =
903af6ab5fSopenharmony_ci            AllocNode<ir::ScriptFunction>(functionScope, std::move(params), nullptr, program_.Ast(), nullptr,
913af6ab5fSopenharmony_ci                                          functionContext.Flags(), false, Extension() == ScriptExtension::TS);
923af6ab5fSopenharmony_ci        functionScope->BindNode(funcNode);
933af6ab5fSopenharmony_ci        funcParamScope->BindNode(funcNode);
943af6ab5fSopenharmony_ci
953af6ab5fSopenharmony_ci        wrapper = AllocNode<ir::FunctionExpression>(funcNode);
963af6ab5fSopenharmony_ci    }
973af6ab5fSopenharmony_ci
983af6ab5fSopenharmony_ci    // create CallExpression
993af6ab5fSopenharmony_ci    ArenaVector<ir::Expression *> arguments(Allocator()->Adapter());
1003af6ab5fSopenharmony_ci    AddReflectApplyArgs(arguments, wrapper);
1013af6ab5fSopenharmony_ci
1023af6ab5fSopenharmony_ci    auto *apply = AllocNode<ir::Identifier>("apply");
1033af6ab5fSopenharmony_ci    auto *reflect = AllocNode<ir::Identifier>("Reflect");
1043af6ab5fSopenharmony_ci    auto *reflectApply = AllocNode<ir::MemberExpression>(reflect, apply,
1053af6ab5fSopenharmony_ci        ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false);
1063af6ab5fSopenharmony_ci
1073af6ab5fSopenharmony_ci    auto *callExpr = AllocNode<ir::CallExpression>(reflectApply, std::move(arguments), nullptr, false);
1083af6ab5fSopenharmony_ci    // create ExpressionStatement
1093af6ab5fSopenharmony_ci    auto *exprStatementNode = AllocNode<ir::ExpressionStatement>(callExpr);
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci    ArenaVector<ir::Statement *> statements(Allocator()->Adapter());
1123af6ab5fSopenharmony_ci    statements.push_back(exprStatementNode);
1133af6ab5fSopenharmony_ci
1143af6ab5fSopenharmony_ci    auto *blockStmt = AllocNode<ir::BlockStatement>(Binder()->GetScope(), std::move(statements));
1153af6ab5fSopenharmony_ci    Binder()->GetScope()->BindNode(blockStmt);
1163af6ab5fSopenharmony_ci
1173af6ab5fSopenharmony_ci    program_.SetAst(blockStmt);
1183af6ab5fSopenharmony_ci}
1193af6ab5fSopenharmony_ci}  // namespace panda::es2panda::parser