The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ For

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Collections;
  20.     using System.Reflection;
  21.     using System.Reflection.Emit;
  22.    
  23.     internal sealed class For : AST
  24.     {
  25.         private AST initializer;
  26.         private AST condition;
  27.         private AST incrementer;
  28.         private AST body;
  29.         private Completion completion;
  30.        
  31.         internal For(Context context, AST initializer, AST condition, AST incrementer, AST body) : base(context)
  32.         {
  33.             this.initializer = initializer;
  34.             this.condition = condition;
  35.             this.incrementer = incrementer;
  36.             this.body = body;
  37.             this.completion = new Completion();
  38.         }
  39.        
  40.         // no debug info for the for statement iteself
  41.         internal override object Evaluate()
  42.         {
  43.             this.completion.Continue = 0;
  44.             this.completion.Exit = 0;
  45.             this.completion.value = null;
  46.             this.initializer.Evaluate();
  47.             while (Convert.ToBoolean(this.condition.Evaluate()) == true) {
  48.                 Completion c = (Completion)this.body.Evaluate();
  49.                 if (c.value != null)
  50.                     this.completion.value = c.value;
  51.                 if (c.Continue > 1) {
  52.                     this.completion.Continue = c.Continue - 1;
  53.                     break;
  54.                 }
  55.                 if (c.Exit > 0) {
  56.                     this.completion.Exit = c.Exit - 1;
  57.                     break;
  58.                 }
  59.                 if (c.Return)
  60.                     return c;
  61.                 this.incrementer.Evaluate();
  62.             }
  63.             return this.completion;
  64.         }
  65.        
  66.         internal override AST PartiallyEvaluate()
  67.         {
  68.             this.initializer = this.initializer.PartiallyEvaluate();
  69.             ScriptObject current_scope = Globals.ScopeStack.Peek();
  70.             while (current_scope is WithObject)
  71.                 current_scope = current_scope.GetParent();
  72.             if (current_scope is FunctionScope) {
  73.                 FunctionScope scope = (FunctionScope)current_scope;
  74.                 BitArray before = scope.DefinedFlags;
  75.                 this.condition = this.condition.PartiallyEvaluate();
  76.                 //Do not need to clear the defined flags because the condition is always completely executed if the body is reached.
  77.                 this.body = this.body.PartiallyEvaluate();
  78.                 scope.DefinedFlags = before;
  79.                 this.incrementer = this.incrementer.PartiallyEvaluate();
  80.                 scope.DefinedFlags = before;
  81.             }
  82.             else {
  83.                 this.condition = this.condition.PartiallyEvaluate();
  84.                 this.body = this.body.PartiallyEvaluate();
  85.                 this.incrementer = this.incrementer.PartiallyEvaluate();
  86.             }
  87.             IReflect conditiontype = this.condition.InferType(null);
  88.             if (conditiontype is FunctionPrototype || conditiontype == Typeob.ScriptFunction)
  89.                 this.context.HandleError(JSError.SuspectLoopCondition);
  90.             return this;
  91.         }
  92.        
  93.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  94.         {
  95.             //This assumes that rtype == Void.class
  96.             Label body_start = il.DefineLabel();
  97.             Label continue_lab = il.DefineLabel();
  98.             Label first_time = il.DefineLabel();
  99.             Label loop_end = il.DefineLabel();
  100.             bool noCondition = false;
  101.             compilerGlobals.BreakLabelStack.Push(loop_end);
  102.             compilerGlobals.ContinueLabelStack.Push(continue_lab);
  103.             if (!(this.initializer is EmptyLiteral)) {
  104.                 this.initializer.context.EmitLineInfo(il);
  105.                 this.initializer.TranslateToIL(il, Typeob.Void);
  106.             }
  107.             il.MarkLabel(body_start);
  108.             if (!(this.condition is ConstantWrapper) || !(this.condition.Evaluate() is bool) || !((bool)this.condition.Evaluate())) {
  109.                 this.condition.context.EmitLineInfo(il);
  110.                 this.condition.TranslateToConditionalBranch(il, false, loop_end, false);
  111.             }
  112.             else if (this.condition.context.StartPosition + 1 == this.condition.context.EndPosition)
  113.                 // the for does not have a condition specified. If there is no increment as well emit debug info for the whole for
  114.                 noCondition = true;
  115.             this.body.TranslateToIL(il, Typeob.Void);
  116.             il.MarkLabel(continue_lab);
  117.             if (!(this.incrementer is EmptyLiteral)) {
  118.                 this.incrementer.context.EmitLineInfo(il);
  119.                 this.incrementer.TranslateToIL(il, Typeob.Void);
  120.             }
  121.             else if (noCondition) {
  122.                 this.context.EmitLineInfo(il);
  123.             }
  124.             il.Emit(OpCodes.Br, body_start);
  125.             il.MarkLabel(loop_end);
  126.             compilerGlobals.BreakLabelStack.Pop();
  127.             compilerGlobals.ContinueLabelStack.Pop();
  128.         }
  129.        
  130.         internal override void TranslateToILInitializer(ILGenerator il)
  131.         {
  132.             this.initializer.TranslateToILInitializer(il);
  133.             this.condition.TranslateToILInitializer(il);
  134.             this.incrementer.TranslateToILInitializer(il);
  135.             this.body.TranslateToILInitializer(il);
  136.         }
  137.     }
  138.    
  139. }

Developer Fusion