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#ifndef ES2PANDA_UTIL_HELPERS_H
17#define ES2PANDA_UTIL_HELPERS_H
18
19#include <cmath>
20
21#include <mem/arena_allocator.h>
22#include <os/file.h>
23#include <os/library_loader.h>
24
25#include <binder/variableFlags.h>
26#include <programCache.h>
27#include <util/ustring.h>
28
29namespace panda::es2panda::ir {
30class Expression;
31class ScriptFunction;
32class ClassDefinition;
33class ClassProperty;
34class Identifier;
35class AstNode;
36class ObjectExpression;
37class StringLiteral;
38class Statement;
39}  // namespace panda::es2panda::ir
40
41namespace panda::es2panda {
42struct CompilerOptions;
43enum class ErrorType;
44
45struct PkgInfo {
46    std::string packageName {};
47    std::string version {};
48};
49
50struct CompileContextInfo {
51    std::vector<std::string> compileEntries;
52    std::set<std::string> externalPkgNames;
53    std::unordered_map<std::string, PkgInfo> pkgContextInfo;
54    // The key of updateVersionInfo is the package name for an abc file, and the value contains the name of its
55    // dependent pacakge and corresponding package version which need to update version.
56    std::unordered_map<std::string, std::unordered_map<std::string, PkgInfo>> updateVersionInfo;
57};
58}  // namespace panda::es2panda
59
60namespace panda::es2panda::binder {
61class Scope;
62}
63namespace panda::pandasm {
64struct Program;
65}  // namespace panda::pandasm
66
67namespace panda::es2panda::lexer {
68class LineIndex;
69class SourcePosition;
70}
71
72namespace panda::es2panda::parser {
73class Program;
74}
75
76namespace panda::es2panda::util {
77
78enum class SignedNumberLiteral {
79    UNRECOGNIZED = 0,
80    POSITIVE = 1,
81    NEGATIVE = 2
82};
83
84class FileSuffix {
85public:
86    static constexpr std::string_view DLL = ".dll";
87    static constexpr std::string_view SO = ".so";
88    static constexpr std::string_view DYLIB = ".dylib";
89};
90
91using AopTransformFuncDef = int (*)(const char *);
92
93class Helpers {
94public:
95    Helpers() = delete;
96
97    static bool IsGlobalIdentifier(const util::StringView &str);
98    static bool ContainSpreadElement(const ArenaVector<ir::Expression *> &args);
99    static util::StringView LiteralToPropName(ArenaAllocator *allocator, const ir::Expression *lit);
100
101    template <typename T>
102    static bool IsInteger(double number);
103    static bool IsIndex(double number);
104    static int64_t GetIndex(const util::StringView &str);
105
106    static bool FileExtensionIs(std::string_view filePath, std::string_view extension);
107    static bool EndsWith(std::string_view str, std::string_view suffix);
108    static std::string DoubleToString(double number);
109    static int32_t GetIntegerSignificandBitCount(double number, int32_t &numberBitCount, char *significandArray);
110    static void GetScientificNotationForDouble(double number, uint32_t significandBitCount, int32_t &numberBitCount,
111                                               char *significandArray, char *sciNotationArray, uint32_t size);
112    static std::string ToString(double number);
113    static util::StringView ToStringView(ArenaAllocator *allocator, double number);
114    static util::StringView ToStringView(ArenaAllocator *allocator, int32_t number);
115    static util::StringView ToStringView(ArenaAllocator *allocator, uint32_t number);
116
117    static const ir::ScriptFunction *GetContainingConstructor(const ir::AstNode *node);
118    static const ir::ScriptFunction *GetContainingConstructor(const ir::ClassProperty *node);
119    static const ir::ScriptFunction *GetContainingFunction(const ir::AstNode *node);
120    static const ir::ClassDefinition *GetClassDefiniton(const ir::ScriptFunction *node);
121    static bool IsSpecialPropertyKey(const ir::Expression *expr);
122    static bool IsConstantPropertyKey(const ir::Expression *expr, bool isComputed);
123    static bool IsConstantExpr(const ir::Expression *expr);
124    static bool IsBindingPattern(const ir::AstNode *node);
125    static bool IsPattern(const ir::AstNode *node);
126    static std::vector<const ir::Identifier *> CollectBindingNames(const ir::AstNode *node);
127    static util::StringView FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func);
128    static util::StringView GetName(ArenaAllocator *allocator, const ir::AstNode *node);
129    static std::tuple<util::StringView, bool> ParamName(ArenaAllocator *allocator, const ir::AstNode *param,
130                                                        uint32_t index);
131    static bool IsChild(const ir::AstNode *parent, const ir::AstNode *child);
132    static bool IsChildScope(const binder::Scope *parent, const binder::Scope *child);
133    static bool IsObjectPropertyValue(const ArenaVector<ir::Expression *> &properties, const ir::AstNode *ident);
134    static SignedNumberLiteral GetSignedNumberLiteral(const ir::Expression *expr);
135
136    static void SetConstantLocalExportSlots(const std::string &record, const std::unordered_set<uint32_t> &slots);
137    static void AnalysisProgram(panda::pandasm::Program *prog, const std::string &inputFile);
138    static void OptimizeProgram(panda::pandasm::Program *prog, const std::string &inputFile);
139    static bool CheckAopTransformPath(const std::string &libPath);
140    static AopTransformFuncDef LoadAopTransformLibFunc(const std::string &libPath,
141        const std::string &funcName, os::library_loader::LibraryHandle &handler);
142    static bool AopTransform(const std::string &inputFile, const std::string &libPath);
143    template <typename T>
144    static T BaseName(T const &path, T const &delims = std::string(panda::os::file::File::GetPathDelim()));
145    static bool ReadFileToBuffer(const std::string &file, std::stringstream &ss);
146    static void ScanDirectives(ir::ScriptFunction *func, const lexer::LineIndex &lineIndex, bool enableSendableClass,
147                               bool enableSendableFunc);
148    static std::string GetHashString(const std::string &str);
149    static std::wstring Utf8ToUtf16(const std::string &utf8);
150    template <typename T, typename... Args>
151    static T FileStream(const std::string &str, Args &&...args);
152    static void ThrowError(ErrorType type, const parser::Program *program, const lexer::SourcePosition &pos,
153        const std::string_view &msg);
154    static bool IsUseShared(const ir::Statement *statement);
155    static const ir::ClassDefinition *GetContainingSendableClass(const ir::AstNode *node);
156    static bool IsSpecialScopeName(const util::StringView &str);
157    static bool BelongingToRecords(const std::string &name, const std::unordered_set<std::string> &retainRecordSet,
158                                   const std::string &delimiter = std::string(DOT));
159    static void RemoveProgramsRedundantData(std::map<std::string, panda::es2panda::util::ProgramCache*> &progsInfo,
160        const std::map<std::string, std::unordered_set<std::string>> &resolveDepsRelation);
161    static bool IsDefaultApiVersion(int apiVersion, std::string subApiVersion);
162    static bool IsSupportLazyImportVersion(int apiVersion, std::string subApiVersion);
163
164    static const uint32_t MAX_DOUBLE_DIGIT = 310;
165    static const uint32_t MAX_DOUBLE_PRECISION_DIGIT = 17;
166    static const int32_t MAX_DECIMAL_EXPONENT = 21;
167    static const int32_t MIN_DECIMAL_EXPONENT = -6;
168    static const int32_t FAIL_SNPRINTF_S  = -1;
169    static const uint32_t INVALID_INDEX = 4294967295L;
170    static const uint32_t MAX_INT32 = 2147483647;
171    static const uint32_t MAX_INT16 = std::numeric_limits<int16_t>::max();
172    static const uint32_t MAX_INT8 = std::numeric_limits<int8_t>::max();
173    static constexpr std::string_view USE_CONCURRENT = "use concurrent";
174    static constexpr std::string_view USE_SENDABLE = "use sendable";
175    static constexpr std::string_view USE_SHARED = "use shared";
176    static constexpr std::string_view STRING_EMPTY = ""; // Default tag value, or tag of GlobalScope and ModuleScope
177    static constexpr std::string_view CLASS_SCOPE_TAG = "~";
178    static constexpr std::string_view FUNCTION_TAG = "*";
179    static constexpr std::string_view METHOD_TAG = ">";
180    static constexpr std::string_view CTOR_TAG = "=";
181    static constexpr std::string_view NAMESPACE_TAG = "&";
182    static constexpr std::string_view ENUM_TAG = "%";
183    static constexpr std::string_view STATIC_METHOD_TAG = "<";
184    static constexpr std::string_view DUPLICATED_SEPERATOR = "^";
185    static constexpr std::string_view FUNC_NAME_SEPARATOR = "#";
186    static constexpr std::string_view INDEX_NAME_SPICIFIER = "@";
187    static constexpr std::string_view DOT = ".";
188    static constexpr std::string_view BACKSLASH = "\\";
189    static const uint64_t FNV_PRIME = 1099511628211U;
190    static const uint64_t FNV_OFFSET = 14695981039346656037U;
191    static const uint8_t SENDABLE_CLASS_MIN_SUPPORTED_API_VERSION = 11;
192    static const int32_t DEFAULT_TARGET_API_VERSION = 12;
193    static const int32_t ABC_TO_PROGRAM_MIN_SUPPORTED_API_VERSION = 12;
194    static constexpr std::array<uint8_t, panda_file::File::VERSION_SIZE>
195        ABC_TO_PROGRAM_MIN_SUPPORTED_BYTECODE_VERSION {12, 0, 2, 0};
196    static const int32_t SENDABLE_FUNCTION_MIN_SUPPORTED_API_VERSION = 12;
197    static const int32_t LAZY_IMPORT_MIN_SUPPORTED_API_VERSION = 12;
198    static const int32_t SENDABLE_LAZY_LOADING_MIN_SUPPORTED_API_VERSION = 12;
199    static const int8_t SUPER_CALL_OPT_MIN_SUPPORTED_API_VERSION = 15;
200    static constexpr std::string_view SUB_API_VERSION_1 = "beta1";
201    static constexpr std::string_view SUB_API_VERSION_2 = "beta2";
202    static constexpr std::string_view DEFAULT_SUB_API_VERSION = SUB_API_VERSION_1;
203
204private:
205    static bool SetFuncFlagsForDirectives(const ir::StringLiteral *strLit, ir::ScriptFunction *func,
206                                          const lexer::LineIndex &lineIndex, bool enableSendableClass,
207                                          bool enableSendableFunc);
208};
209
210template <typename T>
211bool Helpers::IsInteger(double number)
212{
213    if (std::fabs(number) <= static_cast<double>(std::numeric_limits<T>::max())) {
214        T intNum = static_cast<T>(number);
215
216        if (static_cast<double>(intNum) == number) {
217            return true;
218        }
219    }
220
221    return false;
222}
223
224template <class T>
225T Helpers::BaseName(T const &path, T const &delims)
226{
227    return path.substr(path.find_last_of(delims) + 1);
228}
229
230template <typename T, typename... Args>
231T Helpers::FileStream(const std::string &str, Args &&...args)
232{
233    T fileStream;
234#ifdef PANDA_TARGET_WINDOWS
235    std::wstring filename = Helpers::Utf8ToUtf16(str);
236#else  //for linux and mac
237    std::string filename = str;
238#endif
239    fileStream.open(filename.c_str(), args...);
240    return fileStream;
241}
242
243}  // namespace panda::es2panda::util
244
245#endif
246