public override AstNode ShallowClone() { var res = new AstLet(Source, Start, End); res.Definitions.AddRange(Definitions.AsReadOnlySpan()); return(res); }
AstNode ParseForStatement(Position nodeStart) { Next(); EnterLexicalScope(); Expect(TokenType.ParenL); if (Type == TokenType.Semi) { return(ParseFor(nodeStart, null)); } var isLet = IsLet(); if (Type == TokenType.Var || Type == TokenType.Const || isLet) { var startLoc = Start; var kind = isLet ? VariableKind.Let : ToVariableKind((string)Value); Next(); var declarations = new StructList <AstVarDef>(); ParseVar(ref declarations, true, kind); AstDefinitions init; if (kind == VariableKind.Let) { init = new AstLet(this, startLoc, _lastTokEnd, ref declarations); } else if (kind == VariableKind.Const) { init = new AstConst(this, startLoc, _lastTokEnd, ref declarations); } else { init = new AstVar(this, startLoc, _lastTokEnd, ref declarations); } if ((Type == TokenType.In || Options.EcmaVersion >= 6 && IsContextual("of")) && init.Definitions.Count == 1 && !(kind != VariableKind.Var && init.Definitions[0].Value != null)) { return(ParseForIn(nodeStart, init)); } return(ParseFor(nodeStart, init)); } else { var refDestructuringErrors = new DestructuringErrors(); var init = ParseExpression(true, refDestructuringErrors); if (Type == TokenType.In || Options.EcmaVersion >= 6 && IsContextual("of")) { init = ToAssignable(init); CheckLVal(init, false, null); CheckPatternErrors(refDestructuringErrors, true); return(ParseForIn(nodeStart, init)); } CheckExpressionErrors(refDestructuringErrors, true); return(ParseFor(nodeStart, init)); } }
// Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop. AstIterationStatement ParseForStatement(Position nodeStart) { Next(); var isAwait = EatContextual("await"); EnterLexicalScope(); Expect(TokenType.ParenL); if (Type == TokenType.Semi) { return(ParseFor(nodeStart, null, isAwait)); } var isLet = IsLet(); if (Type is TokenType.Var or TokenType.Const || isLet) { var startLoc = Start; var kind = isLet ? VariableKind.Let : ToVariableKind((string)GetValue()); Next(); var declarations = new StructList <AstVarDef>(); ParseVar(ref declarations, true, kind); AstDefinitions init; if (kind == VariableKind.Let) { init = new AstLet(SourceFile, startLoc, _lastTokEnd, ref declarations); } else if (kind == VariableKind.Const) { init = new AstConst(SourceFile, startLoc, _lastTokEnd, ref declarations); } else { init = new AstVar(SourceFile, startLoc, _lastTokEnd, ref declarations); } if ((Type == TokenType.In || IsContextual("of")) && init.Definitions.Count == 1 && !(kind != VariableKind.Var && init.Definitions[0].Value != null)) { return(ParseForIn(nodeStart, init, isAwait)); } return(ParseFor(nodeStart, init, isAwait)); }
private void CompileLet(AstLet node, Syt syt, StringBuilder sb) { CompileRecursive(node.exprRight, syt, sb); if (node.exprLeft is AstIndex) { var astIndex = (AstIndex) node.exprLeft; CompileRecursive(astIndex.exprLeft, syt, sb); CompileRecursive(astIndex.exprRight, syt, sb); sb.AppendLine("add"); sb.AppendLine("pop pointer 1"); sb.AppendLine("pop that 0"); return; } if (node.exprLeft is AstVarRef) { var nodeVarRef = (AstVarRef) node.exprLeft; var syte = syt.Lookup(nodeVarRef.StName); if(syte.Ksyte.FIn(Ksyte.Field, Ksyte.Arg, Ksyte.Var, Ksyte.Static)) sb.AppendLine("pop {0} {1}".StFormat(StSegment(syte.Ksyte), syte.Isyte)); return; } throw new Erparse(node, "not an lvalue"); }