if
勿庸质疑,说到控制结构,首先会想到if。其实现应如下所示:
public class IfThen : ControlFlow{ public Expression.ExpressionNode Condition; public Block ThenClause { get { return Children.Count > 0 ? Children.First() as Block: null; } } public Block ElseClause { get { return Children.Count > 1 ? Children.Last() as Block: null; } }
运行时处理则应该如下:
public override void Run(Context ctx){ Debug.WriteLine("if(" + Condition.ToString() + ")"); Expression.Operand.Operand condVal = Condition.Evaluate(this); Debug.WriteLine("Condition=" + condVal.GetValue(this).ToString()); if (condVal.GetValue(this).AsInt != 0) { if (ThenClause != null) { Debug.WriteLine("Then"); ThenClause.Run(this); } } else { if (ElseClause != null) { Debug.WriteLine("Else"); ElseClause.Run(this); } }}
看起来相当简单。
loop
循环具有类似的结构:条件判断,循环体。其基类如下所示:
public class Loop : ControlFlow{ public Expression.ExpressionNode Condition; public virtual Block Body { get { return Children.Count > 0 ? Children.Last() as Block : null; } } public bool NeedBreak = false; public bool NeedContinue = false;
最简单的循环莫过于while,或do..while。好了,已经将while循环都列举了。
先看while循环的运行代码:
public override void Run(Context ctx){ Debug.WriteLine("Begin While."); base.Run(ctx); while (true) { if (Condition != null) { Expression.Operand.Value condVal = Condition.Evaluate(this).GetValue(this); Debug.WriteLine(string.Format("Condition: [{0}] = {1}", Condition.ToString(), condVal.ToString())); if (condVal.AsInt == 0) { break; } } Body.Run(this); if (NeedBreak) break; } // while Debug.WriteLine("End While.");}
do...while与while不同的部分在于,先运行循环体,再运行判断:
public override void Run(Context ctx){ Debug.WriteLine("Begin Do...While."); base.Run(ctx); while(true) { Body.Run(this); if (NeedBreak) break; if (Condition != null) { Expression.Operand.Value val = Condition.Evaluate(this).GetValue(this); Debug.WriteLine(string.Format("Condition : {0} = {1}", Condition.ToString(), val.ToString())); if (val.AsInt == 0) { break; } } } // while Debug.WriteLine("End Do...While.");}
复杂一点的是for循环,比其它循环结构多出初始化部分和迭代部分:
public class ForLoop : Loop{ public Context Initializer { get { return Children.Count > 0 ? Children.First() : null; } } public Expression.ExpressionNode Iterator;
由于初始化部分可以定义循环变量,形如:for(int i = 0; ....)。所以,还需要重载以下两个方法:
public override bool HasDefined(string str){ if (FindByName(str) == null) return base.HasDefined(str); else return true;}public override Context FindByName(string str){ Context res = null; if (Initializer != null) { Initializer.Parent = null; res = Initializer.FindByName(str); Initializer.Parent = this; } if (res == null) return this.Parent.FindByName(str); else return res;}
然后就可以确定for循环的运行代码:
public override void Run(Context ctx){ Debug.WriteLine("Begin For."); if (Initializer != null) Initializer.Run(this); base.Run(ctx); while (true) { if (Condition != null) { Expression.Operand.Value val = Condition.Evaluate(this).GetValue(this); Debug.WriteLine(string.Format("Condition: [{0}] = {1}", Condition.ToString(), val.ToString())); if (val.AsInt == 0) { break; } } Body.Run(this); if (NeedBreak) break; if (Iterator != null) Iterator.Evaluate(this); } // while if (Initializer != null) { Initializer.FreeLocalVariables(); } Debug.WriteLine("End For.");}
switch
鲜有解释器(或编译器)实现了switch控制。无它,唯复杂尔。SharpC将switch划分为两个部分实现:switch(表达式)和case。先看Case的实现,由条件值和执行部分组成:
public class Case : ControlFlow{ public Expression.Operand.Value Value; public Block Body { get { return Children.Count > 0 ? Children.First() as Block : null; } }}
为简化实现,用Block作为case的执行部分。副作用是多了一层,略微影响效率。再看switch的实现:
public class Switch : ControlFlow{ private Dictionary<int, int> m_caseDict; public Expression.ExpressionNode Condition; public Block Body { get { return Children.Count > 0 ? Children.First() as Block : null; } } public Case Default { get { return Body != null ? Body.Children.Last() as Case : null; } } public List<Context> CaseSet { get { return Body != null ? Body.Children.Count > 1 ? Body.Children.GetRange(0, Body.Children.Count - 1) : null : null; } }
switch的执行部分亦为一个block。同时Default是最后一个Case。再看switch的执行部分:
public override void Run(Context ctx){ Debug.WriteLine("Begin Switch."); bool needBreak = false; if (IsFirstRunning) { m_caseDict = new Dictionary<int, int>(); int idx = 0; Body.OnReturn += delegate(Context stx, Return ret) { Debug.WriteLine("Return"); needBreak = true; Block parentBlock = this.ParentBlock; if (parentBlock != null && parentBlock.OnReturn != null) parentBlock.OnReturn(stx, ret); }; Body.OnBreak = delegate(Context stx) { Debug.WriteLine("Break."); needBreak = true; }; foreach (Context item in CaseSet) { Case stxCase = item as Case; m_caseDict.Add(stxCase.Value.AsInt, idx++); stxCase.Body.OnBreak += Body.OnBreak; } IsFirstRunning = false; } Expression.Operand.Value val = Condition.Evaluate(this).GetValue(ctx); Debug.WriteLine(string.Format("Condition: [{0}] = {1}", Condition, val)); if (m_caseDict.ContainsKey(val.AsInt)) { int idx = m_caseDict[val.AsInt]; IEnumerator<Context> caseEnum = CaseSet.GetEnumerator(); int i = 0; while (caseEnum.MoveNext()) { if (i++ < idx) continue; Debug.WriteLine(string.Format("case {0}", (caseEnum.Current as Case).Value.AsInt)); (caseEnum.Current as Case).Body.Run(this); if (needBreak) break; } // while } else { Debug.WriteLine("Default"); Default.Run(this); }}
在第一次执行的时候先建立case字典,希望下次运行的时候能够加快速度。然后,运行与表达式相匹配的case,并从该case开始,依次运行下一个case,直到运行到break为止。
Break, Continue and Return
这三种控制结构都必须结合上下文环境共同作用。看起来它们更像是一种标记。因此上,它们的实现也相当简单:
break
public class Break : ControlFlow{ public override void Print(int tabs = 0) { Debug.WriteLine(new string('\t', tabs) + "break;"); }}
continue
public class Continue : ControlFlow{ public override void Print(int tabs = 0) { Debug.WriteLine(new string('\t', tabs) + "continue;"); }}
return
return多了一个返回值的表达式:
public class Return : ControlFlow{ public Expression.ExpressionNode Expression; public override void Print(int tabs = 0) { if (Expression == null) Debug.WriteLine(new string('\t', tabs) + "return ;"); else { Debug.WriteLine(new string('\t', tabs) + "return " + Expression.ToString()); } }}
一切需要回溯到Block,在Block运行时,会检测这三种控制结构:
public override void Run(Context ctx){ if (IsFirstRunning) { Block parentBlock = this.ParentBlock; if (parentBlock != null) { this.OnReturn += parentBlock.OnReturn; this.OnBreak += parentBlock.OnBreak; this.OnContinue += parentBlock.OnContinue; } IsFirstRunning = false; } foreach (Context stx in Children) { if (stx is ControlFlow.ControlFlow) { if (!ExecuteControlFlow(stx)) break;
再看ExecuteControlFlow():
private bool ExecuteControlFlow(Context stx){ if (stx is ControlFlow.Return) { if (OnReturn != null) OnReturn(this, stx as ControlFlow.Return); return false; } else { if (stx is ControlFlow.Break) { if (OnBreak != null) OnBreak(this); return false; } else if (stx is ControlFlow.Continue) { if (OnContinue != null) OnContinue(this); return false; } else stx.Run(this); } return true;}
通过返回false来立即中止上层Block的运行循环。