1/* 2 * Copyright (c) 2022 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 "concurrent.h" 17 18#include <binder/scope.h> 19#include <compiler/core/compilerContext.h> 20#include <compiler/core/pandagen.h> 21#include <ir/astNode.h> 22#include <ir/base/scriptFunction.h> 23#include <ir/expressions/literals/stringLiteral.h> 24#include <ir/statements/blockStatement.h> 25#include <ir/statements/expressionStatement.h> 26#include <lexer/token/sourceLocation.h> 27#include <parser/module/sourceTextModuleRecord.h> 28 29namespace panda::es2panda::util { 30 31void Concurrent::SetConcurrent(ir::ScriptFunction *func, const ir::AstNode * node, const lexer::LineIndex &lineIndex) 32{ 33 // concurrent function should only be function declaration 34 if (!func->CanBeConcurrent()) { 35 ThrowInvalidConcurrentFunction(lineIndex, node, ConcurrentInvalidFlag::NOT_ORDINARY_FUNCTION); 36 } 37 38 func->AddFlag(ir::ScriptFunctionFlags::CONCURRENT); 39} 40 41void Concurrent::ThrowInvalidConcurrentFunction(const lexer::LineIndex &lineIndex, const ir::AstNode *expr, 42 ConcurrentInvalidFlag errFlag, util::StringView varName) 43{ 44 auto line = expr->Range().start.line; 45 auto column = (const_cast<lexer::LineIndex &>(lineIndex)).GetLocation(expr->Range().start).col - 1; 46 switch (errFlag) { 47 case ConcurrentInvalidFlag::NOT_ORDINARY_FUNCTION: { 48 throw Error {ErrorType::GENERIC, "Concurrent function should only be function declaration", line, 49 column}; 50 break; 51 } 52 case ConcurrentInvalidFlag::NOT_IMPORT_VARIABLE: { 53 std::stringstream ss; 54 ss << "Concurrent function should only use import variable or local variable, '" << varName 55 << "' is not one of them"; 56 throw Error {ErrorType::GENERIC, ss.str(), line, column}; 57 break; 58 } 59 default: 60 break; 61 } 62} 63 64void Concurrent::ProcessConcurrent(const lexer::LineIndex &lineIndex, const ir::AstNode *node, 65 const binder::ScopeFindResult &result, parser::Program *program) 66{ 67 if (!result.concurrentFunc) { 68 return; 69 } 70 71 if (result.variable->IsModuleVariable() && result.variable->Declaration()->IsImportDecl()) { 72 CollectRelativeModule(result, program); 73 return; 74 } 75 76 ThrowInvalidConcurrentFunction(lineIndex, node, ConcurrentInvalidFlag::NOT_IMPORT_VARIABLE, 77 result.variable->Declaration()->Name()); 78} 79 80void Concurrent::CollectRelativeModule(const binder::ScopeFindResult &result, parser::Program *program) 81{ 82 int moduleRequestIdx = program->ModuleRecord()->GetModuleRequestIdx(result.variable->Name()); 83 if (moduleRequestIdx != parser::SourceTextModuleRecord::INVALID_MODULEREQUEST_ID) { 84 result.concurrentFunc->AddConcurrentModuleRequest(moduleRequestIdx); 85 } 86} 87 88} // namespace panda::es2panda::util