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 的运行循环。