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 "identifier.h" 17 18#include <binder/scope.h> 19#include <compiler/core/pandagen.h> 20#include <typescript/checker.h> 21#include <ir/astDump.h> 22#include <ir/typeNode.h> 23#include <ir/base/decorator.h> 24#include <ir/base/scriptFunction.h> 25#include <ir/expressions/assignmentExpression.h> 26#include <ir/statements/functionDeclaration.h> 27#include <ir/statements/variableDeclarator.h> 28#include <ir/expression.h> 29 30namespace panda::es2panda::ir { 31 32void Identifier::Iterate(const NodeTraverser &cb) const 33{ 34 if (typeAnnotation_) { 35 cb(typeAnnotation_); 36 } 37} 38 39void Identifier::Dump(ir::AstDumper *dumper) const 40{ 41 dumper->Add({{"type", "Identifier"}, 42 {"name", name_}, 43 {"typeAnnotation", AstDumper::Optional(typeAnnotation_)}, 44 {"optional", AstDumper::Optional(IsOptional())}}); 45} 46 47void Identifier::Compile(compiler::PandaGen *pg) const 48{ 49 binder::ScopeFindResult res = pg->Scope()->Find(name_); 50 if (res.variable) { 51 pg->LoadVar(this, res); 52 return; 53 } 54 55 if (name_.Is("NaN")) { 56 pg->LoadConst(this, compiler::Constant::JS_NAN); 57 return; 58 } 59 60 if (name_.Is("Infinity")) { 61 pg->LoadConst(this, compiler::Constant::JS_INFINITY); 62 return; 63 } 64 65 if (name_.Is("globalThis")) { 66 pg->LoadConst(this, compiler::Constant::JS_GLOBAL); 67 return; 68 } 69 70 if (name_.Is("undefined")) { 71 pg->LoadConst(this, compiler::Constant::JS_UNDEFINED); 72 return; 73 } 74 75 pg->TryLoadGlobalByName(this, name_); 76} 77 78checker::Type *Identifier::Check(checker::Checker *checker) const 79{ 80 if (!Variable()) { 81 if (name_.Is("undefined")) { 82 return checker->GlobalUndefinedType(); 83 } 84 85 checker->ThrowTypeError({"Cannot find name ", name_}, Start()); 86 } 87 88 const binder::Decl *decl = Variable()->Declaration(); 89 90 if (decl->IsTypeAliasDecl() || decl->IsInterfaceDecl()) { 91 checker->ThrowTypeError({name_, " only refers to a type, but is being used as a value here."}, Start()); 92 } 93 94 return checker->GetTypeOfVariable(Variable()); 95} 96 97void Identifier::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) 98{ 99 if (typeAnnotation_) { 100 typeAnnotation_ = std::get<ir::AstNode *>(cb(typeAnnotation_))->AsExpression(); 101 } 102} 103 104} // namespace panda::es2panda::ir 105