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