• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
16import * as ts from "typescript";
17import { Compiler } from "src/compiler";
18import {
19    CacheList,
20    getVregisterCache
21} from "../base/vregisterCache";
22import { LabelTarget } from "./labelTarget";
23import { Label, VReg } from "../irnodes";
24import { TryBuilderWithForOf } from "./tryStatement";
25import { PandaGen } from "src/pandagen";
26import { LoopScope } from "src/scope";
27
28export enum IteratorType { Normal, Async }
29
30export class IteratorRecord {
31    private type: IteratorType;
32    private object: VReg;
33    private nextMethod: VReg;
34
35    constructor(object: VReg, nextMethod: VReg, type: IteratorType = IteratorType.Normal) {
36        this.type = type;
37        this.object = object;
38        this.nextMethod = nextMethod;
39    }
40
41    getType(): IteratorType {
42        return this.type;
43    }
44
45    getObject(): VReg {
46        return this.object;
47    }
48
49    getNextMethod(): VReg {
50        return this.nextMethod;
51    }
52}
53
54
55export function compileForOfStatement(stmt: ts.ForOfStatement, compiler: Compiler): void {
56    compiler.pushScope(stmt);
57
58    let pandaGen = compiler.getPandaGen();
59    let nextLabel = new Label();
60    let endLabel = new Label();
61
62    let doneReg = pandaGen.getTemp();
63    let method = pandaGen.getTemp();
64    let object = pandaGen.getTemp();
65
66    let loopScope = <LoopScope>compiler.getRecorder().getScopeOfNode(stmt);
67    let needCreateLoopEnv: boolean = loopScope.need2CreateLexEnv();
68    let loopEnv = pandaGen.getTemp();
69
70    // for now Async is not handled.
71    let type: IteratorType = stmt.awaitModifier ? IteratorType.Async : IteratorType.Normal;
72
73    if (needCreateLoopEnv) {
74        pandaGen.createLexEnv(stmt, loopScope);
75        compiler.pushEnv(loopEnv);
76    }
77
78    compiler.compileExpression(stmt.expression);
79    let iterator: IteratorRecord = getIteratorRecord(pandaGen, stmt, method, object, type);
80
81    if (needCreateLoopEnv) {
82        pandaGen.popLexicalEnv(stmt);
83        compiler.popEnv();
84    }
85
86    pandaGen.loadAccumulator(stmt, getVregisterCache(pandaGen, CacheList.FALSE));
87    pandaGen.storeAccumulator(stmt, doneReg);
88
89    let labelTarget = new LabelTarget(stmt, endLabel, nextLabel, needCreateLoopEnv);
90    LabelTarget.pushLabelTarget(labelTarget);
91    LabelTarget.updateName2LabelTarget(stmt.parent, labelTarget);
92
93    let tryBuilderWithForOf = new TryBuilderWithForOf(compiler, pandaGen, stmt, doneReg, iterator, labelTarget,
94                                                      needCreateLoopEnv, needCreateLoopEnv ? loopEnv : undefined);
95    compiler.constructTry(stmt, tryBuilderWithForOf, nextLabel);
96
97    pandaGen.label(stmt, endLabel);
98
99    LabelTarget.popLabelTarget();
100
101    if (needCreateLoopEnv) {
102        pandaGen.popLexicalEnv(stmt);
103        compiler.popEnv();
104    }
105
106    pandaGen.freeTemps(doneReg, method, object, loopEnv);
107    compiler.popScope();
108}
109
110export function getIteratorRecord(pandagen: PandaGen, node: ts.Node, nextMethod: VReg, object: VReg, type: IteratorType): IteratorRecord {
111    getIterator(pandagen, node, type);
112
113    pandagen.storeAccumulator(node, object);
114    pandagen.loadObjProperty(node, object, "next");
115    pandagen.storeAccumulator(node, nextMethod);
116
117    return new IteratorRecord(object, nextMethod, type);
118}
119
120function getIterator(pandagen: PandaGen, node: ts.Node, type: IteratorType): void {
121    if (type === IteratorType.Async) {
122        pandagen.getAsyncIterator(node);
123    } else {
124        pandagen.getIterator(node);
125    }
126}