internal override MSAst.Expression Transform(AstGenerator ag) { if (ag.InFinally) { ag.AddError("'continue' not supported inside 'finally' clause", Span); return null; } else if (ag.InLoop) { return ag.AddDebugInfo(MSAst.Expression.Continue(ag.ContinueLabel), Span); } else { ag.AddError("'continue' not properly in loop", Span); return null; } }
internal override MSAst.Expression Transform(AstGenerator ag) { if (ag.IsGenerator) { if (_expression != null) { // Return statements in Generators can not have an expression. // Generators only return values via the yield keyword. ag.AddError("'return' with argument inside generator", this.Span); // Statements can't return null, so return a rethrow. // Callers should detecet the ag.AddError and avoid trying to execute the tree, // but if they accidentally do, use Throw instead of empty so that // we'll get an exception. return Ast.Throw( Ast.New( typeof(InvalidOperationException).GetConstructor(Type.EmptyTypes) ) ); } return ag.AddDebugInfo(AstUtils.YieldBreak(ag.GeneratorLabel), Span); } return ag.AddDebugInfo( Ast.Return( ag.ReturnLabel, ag.TransformOrConstantNull(_expression, typeof(object)) ), Span ); }
internal override MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, PythonOperationKind op) { if (Items.Length == 0) { ag.AddError("can't assign to ()", Span); return null; } return base.TransformSet(ag, span, right, op); }
internal override MSAst.Expression TransformDelete(AstGenerator ag) { ag.AddError("can't delete function call", Span); return null; }
internal virtual MSAst.Expression TransformDelete(AstGenerator ag) { ag.AddError("can't delete " + NodeName, Span); return null; }
internal virtual MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, Operators op) { ag.AddError("can't assign to " + NodeName, Span); return null; }
internal override MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, Operators op) { ag.AddError(_value == null ? "assignment to None" : "can't assign to literal", Span); return null; }
internal override MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, Operators op) { if (op != Operators.None) { ag.AddError("augmented assign to sequence prohibited", Span); return null; } // if we just have a simple named multi-assignment (e.g. a, b = 1,2) // then go ahead and step over the entire statement at once. If we have a // more complex statement (e.g. a.b, c.d = 1, 2) then we'll step over the // sets individually as they could be property sets the user wants to step // into. TODO: Enable stepping of the right hand side? bool emitIndividualSets = false; foreach (Expression e in _items) { if (IsComplexAssignment(e)) { emitIndividualSets = true; break; } } SourceSpan rightSpan = SourceSpan.None; SourceSpan leftSpan = (Span.Start.IsValid && span.IsValid) ? new SourceSpan(Span.Start, span.End) : SourceSpan.None; SourceSpan totalSpan = SourceSpan.None; if (emitIndividualSets) { rightSpan = span; leftSpan = SourceSpan.None; totalSpan = (Span.Start.IsValid && span.IsValid) ? new SourceSpan(Span.Start, span.End) : SourceSpan.None; } MSAst.Expression[] statements = new MSAst.Expression[4]; // 1. Evaluate the expression and assign the value to the temp. MSAst.ParameterExpression right_temp = ag.GetTemporary("unpacking"); // 2. Add the assignment "right_temp = right" into the suite/block statements[0] = ag.MakeAssignment(right_temp, right); // 3. Call GetEnumeratorValues on the right side (stored in temp) MSAst.Expression enumeratorValues = Ast.Call( AstGenerator.GetHelperMethod("GetEnumeratorValues"), // method // arguments AstUtils.CodeContext(), right_temp, Ast.Constant(_items.Length) ); // 4. Create temporary variable for the array MSAst.ParameterExpression array_temp = ag.GetTemporary("array", typeof(object[])); // 5. Assign the value of the method call (mce) into the array temp // And add the assignment "array_temp = Ops.GetEnumeratorValues(...)" into the block statements[1] = ag.MakeAssignment( array_temp, enumeratorValues, rightSpan ); MSAst.Expression[] sets = new MSAst.Expression[_items.Length + 1]; for (int i = 0; i < _items.Length; i ++) { // target = array_temp[i] Expression target = _items[i]; if (target == null) { continue; } // 6. array_temp[i] MSAst.Expression element = Ast.ArrayAccess( array_temp, // array expression Ast.Constant(i) // index ); // 7. target = array_temp[i], and add the transformed assignment into the list of sets MSAst.Expression set = target.TransformSet( ag, emitIndividualSets ? // span target.Span : SourceSpan.None, element, Operators.None ); if (set == null) { throw PythonOps.SyntaxError(string.Format("can't assign to {0}", target.NodeName), ag.Context.SourceUnit, target.Span, -1); } sets[i] = set; } // 9. add the sets as their own block so they can be marked as a single span, if necessary. sets[_items.Length] = Ast.Empty(); statements[2] = ag.AddDebugInfo(Ast.Block(sets), leftSpan); // 10. Free the temps ag.FreeTemp(array_temp); ag.FreeTemp(right_temp); // 11. Return the suite statement (block) statements[3] = Ast.Empty(); return ag.AddDebugInfo(Ast.Block(statements), totalSpan); }
internal override MSAst.Expression Transform(AstGenerator ag, Type type) { ag.AddError("Error expression encountered", Span); return null; }