我正在使用 C# 编写一个 PLC 语言解释器。该 PLC 语言包含 20 多种数据类型和 25 条左右的指令。一旦我开始生成代码,我就会平衡两种不同的方式来编写指令:
1) 每种指令都表示在一个类中,该类包含一个 bigswitch
以便选择数据类型。例子:
public class ADD : Instruction
{
private string type;
public ADD(string type)
{
this.type = type;
}
public bool Exec(Context c)
{
switch (type)
{
case "INT":
short valor2 = c.PopINT();
short valor = c.PopINT();
short result = (short)(valor + valor2);
c.PushINT(result);
break;
case "DINT":
int valor4 = c.PopDINT();
int valor3 = c.PopDINT();
int result2 = (int)(valor4 + valor3);
c.PushDINT(result2);
break;
case "BOOL":
// Implement BOOL
break;
// Implement other types...
default:
break;
}
c.IP++;
return false; ;
}
}
2) 每个类代表具有单一数据类型的单一指令。这种方式避免了大的switch
。例子:
public class ADDi : Instruction
{
public bool Exec(Context c)
{
short valor = c.PopINT();
short valor2 = c.PopINT();
short result = (short)(valor + valor2);
c.PushINT(result);
c.IP++;
return false;
}
}
我正在使用 COMMAND 设计模式 ( Exec()
) 来编写指令。我认为第二个选择更好,因为避免了大开关,但该选择涉及编写超过 400 条指令。
请始终牢记,在这种情况下,执行性能比翻译性能更重要。
所以,我的确切问题如下:有没有其他方法来分解指令和数据类型?我正在寻找在不影响性能的情况下编写较少量的指令。
编辑:
这张图片显示了我的类型层次结构:
这是 INT 类实现:
public class INT : ANY_INT
{
public override string DefaultInitValue()
{
return "0";
}
public override int GetBytes()
{
return 2;
}
public override string GetLastType()
{
return this.ToString();
}
public override string ToString()
{
return "INT";
}
}
有些类更复杂(结构、数组、...)。
操作 Push 和 Pop 定义如下:
public void PushINT(short value)
{
//SP -> Stack Pointer
resMem.WriteINT(SP, value);
SP += 2;
}
public short PopINT()
{
SP -= 2;
short value = resMem.ReadINT(SP);
return value;
}
最后,在内存中进行读写操作。
public void WriteINT(int index, short entero)
{
SetCapacity(index + 2); // Memory grows up dinamically
memory[index] = (sbyte)((ushort)entero >> 8 & 0x00FF);
memory[index + 1] = (sbyte)((ushort)entero >> 0 & 0x00FF);
}
public short ReadINT(int index)
{
return (short)(((short)(memory[index]) << 8 & 0xFF00) |
((short)(memory[index + 1]) & 0x00FF));
}
我希望这些信息有所帮助。谢谢你。