• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-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
16import { VReg } from "./irnodes";
17import {
18    InitStatus,
19    LoopScope,
20    VariableScope
21} from "./scope";
22
23export enum VarDeclarationKind {
24    NONE,
25    LET,
26    CONST,
27    VAR,
28    FUNCTION,
29    MODULE,
30    CLASS
31}
32
33export abstract class Variable {
34    private vreg: VReg | undefined;
35    private name: string;
36    private typeIndex: number;
37    isLexVar: boolean = false;
38    idxLex: number = 0;
39    constructor(
40        readonly declKind: VarDeclarationKind,
41        name: string
42    ) {
43        this.name = name;
44        this.vreg = undefined;
45        this.typeIndex = 0;
46    }
47
48    bindVreg(vreg: VReg) {
49        this.vreg = vreg;
50        this.vreg.setTypeIndex(this.typeIndex);
51        this.vreg.setVariableName(this.name);
52    }
53
54    hasAlreadyBinded(): boolean {
55        return this.vreg !== undefined;
56    }
57
58    getVreg(): VReg {
59        if (!this.vreg) {
60            throw new Error("variable has not been binded")
61        }
62        return this.vreg;
63    }
64
65    getName() {
66        return this.name;
67    }
68
69    getTypeIndex() {
70        return this.typeIndex;
71    }
72
73    setTypeIndex(typeIndex: number) {
74        return this.typeIndex = typeIndex;
75    }
76
77    setLexVar(scope: VariableScope | LoopScope) {
78        this.idxLex = scope.getLexVarIdx()
79        scope.pendingCreateEnv();
80        this.isLexVar = true;
81        return this.idxLex;
82    }
83
84    clearLexVar() {
85        this.isLexVar = false;
86        this.idxLex = 0;
87    }
88
89    isLet(): boolean {
90        return this.declKind == VarDeclarationKind.LET;
91    }
92
93    isConst(): boolean {
94        return this.declKind == VarDeclarationKind.CONST;
95    }
96
97    isLetOrConst(): boolean {
98        return this.declKind == VarDeclarationKind.LET || this.declKind == VarDeclarationKind.CONST;
99    }
100
101    isVar(): boolean {
102        return this.declKind == VarDeclarationKind.VAR;
103    }
104
105    isNone(): boolean {
106        return this.declKind == VarDeclarationKind.NONE;
107    }
108
109    isClass(): boolean {
110        return this.declKind == VarDeclarationKind.CLASS;
111    }
112}
113
114export class LocalVariable extends Variable {
115    status: InitStatus | null;
116    isExport: boolean = false;
117    exportedName: string = "";
118
119    constructor(declKind: VarDeclarationKind, name: string, status?: InitStatus) {
120        super(declKind, name);
121        this.status = status ? status : null;
122    }
123
124    initialize() {
125        this.status = InitStatus.INITIALIZED;
126    }
127
128    isInitialized() {
129        if (this.status != null) {
130            return this.status == InitStatus.INITIALIZED;
131        }
132        return true;
133    }
134
135    setExport() {
136        this.isExport = true;
137    }
138
139    isExportVar() {
140        return this.isExport;
141    }
142
143    setExportedName(name: string) {
144        this.exportedName = name;
145    }
146
147    getExportedName() {
148        if (!this.exportedName) {
149            throw new Error("Exported Variable " + this.getName() + " doesn't have exported name");
150        }
151        return this.exportedName;
152    }
153}
154
155export class GlobalVariable extends Variable {
156    constructor(declKind: VarDeclarationKind, name: string) {
157        super(declKind, name);
158    }
159}