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

  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 If : AST
  24.     {
  25.         private AST condition;
  26.         private AST operand1;
  27.         private AST operand2;
  28.         private Completion completion;
  29.        
  30.         internal If(Context context, AST condition, AST true_branch, AST false_branch) : base(context)
  31.         {
  32.             this.condition = condition;
  33.             this.operand1 = true_branch;
  34.             this.operand2 = false_branch;
  35.             this.completion = new Completion();
  36.         }
  37.        
  38.         internal override object Evaluate()
  39.         {
  40.             if (this.operand1 == null && this.operand2 == null)
  41.                 return this.completion;
  42.             Completion c = null;
  43.             if (this.condition != null) {
  44.                 if (Convert.ToBoolean(this.condition.Evaluate()) == true)
  45.                     c = (Completion)this.operand1.Evaluate();
  46.                 else if (this.operand2 != null)
  47.                     c = (Completion)this.operand2.Evaluate();
  48.                 else
  49.                     c = new Completion();
  50.             }
  51.             else if (this.operand1 != null)
  52.                 c = (Completion)this.operand1.Evaluate();
  53.             else
  54.                 c = (Completion)this.operand2.Evaluate();
  55.             this.completion.value = c.value;
  56.             if (c.Continue > 1)
  57.                 this.completion.Continue = c.Continue - 1;
  58.             else
  59.                 this.completion.Continue = 0;
  60.             if (c.Exit > 0)
  61.                 this.completion.Exit = c.Exit - 1;
  62.             else
  63.                 this.completion.Exit = 0;
  64.             if (c.Return)
  65.                 return c;
  66.             return this.completion;
  67.         }
  68.        
  69.         internal override bool HasReturn()
  70.         {
  71.             if (this.operand1 != null) {
  72.                 if (!this.operand1.HasReturn())
  73.                     return false;
  74.                 if (this.operand2 != null)
  75.                     return this.operand2.HasReturn();
  76.                 return false;
  77.             }
  78.             else {
  79.                 if (this.operand2 != null)
  80.                     return this.operand2.HasReturn();
  81.                 return false;
  82.             }
  83.         }
  84.        
  85.         internal override AST PartiallyEvaluate()
  86.         {
  87.             this.condition = this.condition.PartiallyEvaluate();
  88.             if (this.condition is ConstantWrapper) {
  89.                 if (Convert.ToBoolean(this.condition.Evaluate()) == true)
  90.                     this.operand2 = null;
  91.                 else
  92.                     this.operand1 = null;
  93.                 this.condition = null;
  94.             }
  95.             ScriptObject current_scope = Globals.ScopeStack.Peek();
  96.             while (current_scope is WithObject)
  97.                 current_scope = current_scope.GetParent();
  98.             if (current_scope is FunctionScope) {
  99.                 FunctionScope scope = (FunctionScope)current_scope;
  100.                 BitArray before = scope.DefinedFlags;
  101.                 BitArray after1 = before;
  102.                 if (this.operand1 != null) {
  103.                     this.operand1 = this.operand1.PartiallyEvaluate();
  104.                     after1 = scope.DefinedFlags;
  105.                     scope.DefinedFlags = before;
  106.                 }
  107.                 if (this.operand2 != null) {
  108.                     this.operand2 = this.operand2.PartiallyEvaluate();
  109.                     BitArray after2 = scope.DefinedFlags;
  110.                     int n = after1.Length;
  111.                     int m = after2.Length;
  112.                     if (n < m)
  113.                         after1.Length = m;
  114.                     if (m < n)
  115.                         after2.Length = n;
  116.                     before = after1.And(after2);
  117.                 }
  118.                 scope.DefinedFlags = before;
  119.             }
  120.             else {
  121.                 if (this.operand1 != null)
  122.                     this.operand1 = this.operand1.PartiallyEvaluate();
  123.                 if (this.operand2 != null)
  124.                     this.operand2 = this.operand2.PartiallyEvaluate();
  125.             }
  126.             return this;
  127.         }
  128.        
  129.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  130.         {
  131.             //This assumes that rtype == Void.class
  132.             if (this.operand1 == null && this.operand2 == null)
  133.                 return;
  134.             Label else_label = il.DefineLabel();
  135.             Label endif_label = il.DefineLabel();
  136.             compilerGlobals.BreakLabelStack.Push(endif_label);
  137.             compilerGlobals.ContinueLabelStack.Push(endif_label);
  138.             if (this.condition != null) {
  139.                 this.context.EmitLineInfo(il);
  140.                 if (this.operand2 != null)
  141.                     this.condition.TranslateToConditionalBranch(il, false, else_label, false);
  142.                 else
  143.                     this.condition.TranslateToConditionalBranch(il, false, endif_label, false);
  144.                 if (this.operand1 != null)
  145.                     this.operand1.TranslateToIL(il, Typeob.Void);
  146.                 if (this.operand2 != null) {
  147.                     if (this.operand1 != null && !this.operand1.HasReturn())
  148.                         il.Emit(OpCodes.Br, endif_label);
  149.                     il.MarkLabel(else_label);
  150.                     this.operand2.TranslateToIL(il, Typeob.Void);
  151.                 }
  152.             }
  153.             else {
  154.                 if (this.operand1 != null)
  155.                     this.operand1.TranslateToIL(il, Typeob.Void);
  156.                 else
  157.                     this.operand2.TranslateToIL(il, Typeob.Void);
  158.             }
  159.             il.MarkLabel(endif_label);
  160.             compilerGlobals.BreakLabelStack.Pop();
  161.             compilerGlobals.ContinueLabelStack.Pop();
  162.         }
  163.        
  164.         internal override void TranslateToILInitializer(ILGenerator il)
  165.         {
  166.             if (this.condition != null)
  167.                 this.condition.TranslateToILInitializer(il);
  168.             if (this.operand1 != null)
  169.                 this.operand1.TranslateToILInitializer(il);
  170.             if (this.operand2 != null)
  171.                 this.operand2.TranslateToILInitializer(il);
  172.         }
  173.     }
  174. }

Developer Fusion