将Snail脚本编译成EXE文件的原型框架,其主要原理是利用Reflection.Emit逐一转换Snail的每条语句。之所以称为原型框架,是因为目前版本只支持:将一个变量赋值为整数,然后将这个整数变量输出。
a = 1001 print(a)利用上面的两条语句生成一个exe文件,同时将结果输出,得到的exe文件大小只有2k。实现了这个原型之后,其他内容的实现就是时间和体力的问题了。
public TransToCIL()
{
string assemblyName = "SnailCilAsm";
modName = "SnailCil.exe";
string typeName = "SnailCilType";
string methodName = "Main";
AssemblyName name = new AssemblyName(assemblyName);
AppDomain domain = System.Threading.Thread.GetDomain();
builder = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
module = builder.DefineDynamicModule(modName, true);
typeBuilder = module.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class);
methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.Static, typeof(void), new[] { typeof(string[]) });
}public dynamic ToCil(Node n)
{
switch (n.Name)
{
case "Script":
{
foreach (var node in n.Nodes)
{
ToCil(node);
}
return 0;
}
case "Expression":
return 0;
case "Identifier":
{
int index = Script.GlobleEnv.CIL_GetIndex(n.Text);
if (index == -1)throw new Exception("不存在变量"+n.Text);
return index;
}
case "AssignExpr":
{
string varname = n[0].Text;
if (Script.GlobleEnv.CIL_SetVar(varname))
{
IL.DeclareLocal(typeof(int));
}
int index = Script.GlobleEnv.CIL_GetIndex(varname); //变量的索引
var right = ToCil(n[1]); //变量将要赋成的值
IL.Emit(OpCodes.Ldc_I4, (Int32)right);
IL.Emit(OpCodes.Stloc, index);
return 0;
}
case "Integer":
{
return Int64.Parse(n.Text);
}
case "PrintExpr":
{
int index = (int)ToCil(n[0]);
IL.Emit(OpCodes.Ldloc, index);
IL.EmitCall(OpCodes.Call, WriteLine, null);
return 0;
}
default:
throw new Exception("还没有实现"+n.Name);
}
}case "AssignExpr": 实现了对一个局部变量的赋值。最后转成两句Cil:
IL.Emit(OpCodes.Ldc_I4, (Int32)right);
IL.Emit(OpCodes.Stloc, index);
case "PrintExpr": 将相应变量的值(通过索引)压入栈中,然后调用WriteLine输出。
case "Identifier": 负责记录变量名及其索引值。
public string Excute()
{
Process p = new Process();
p.StartInfo.FileName = "SnailCil.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
string s = p.StandardOutput.ReadToEnd();
p.WaitForExit();
p.Close();
return s;
}
执行时请先在编译-> 生成EXE前面打勾(默认已经置上)
http://download.csdn.net/detail/u012813593/6867833
测试代码:
a = 100
print(a)
原文:http://blog.csdn.net/snlscript/article/details/18559763