home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 40 / IOPROG_40.ISO / SOFT / NETFrameworkSDK.exe / comsdk.cab / samples1.exe / CLisp / CodeGen.cs < prev    next >
Encoding:
Text File  |  2000-06-23  |  9.1 KB  |  382 lines

  1.  
  2. using System;
  3. using System.Reflection;
  4. using System.Reflection.Emit;
  5. using System.Collections;
  6. using System.Threading;
  7. using Absyn;
  8.  
  9.  
  10. class CodeGen : IExpVisitor
  11. {
  12.     ExpList expr;
  13.     TypeBuilder tb;
  14.     MethodBuilder methodb;
  15.     Hashtable Functions;
  16.     Hashtable GlobalVars;
  17.     Hashtable DoVars;
  18.     
  19.     ILGenerator il;
  20.     
  21.     public CodeGen(ExpList ex, Hashtable f, Hashtable g)
  22.     {
  23.     expr = ex;
  24.     Functions = new Hashtable();
  25.     GlobalVars = new Hashtable();
  26.     DoVars = new Hashtable();
  27.     }
  28.     
  29.     void Init()
  30.     {
  31.     
  32.     }
  33.  
  34.     public void IntExp(IntExp e)
  35.     {
  36.         switch(e.Value){
  37.         case 0:
  38.         il.Emit(OpCodes.Ldc_I4_0);
  39.         break;
  40.         case 1:
  41.             il.Emit(OpCodes.Ldc_I4_1);
  42.             break;
  43.         case 2:
  44.             il.Emit(OpCodes.Ldc_I4_2);
  45.             break;
  46.         case 3:
  47.             il.Emit(OpCodes.Ldc_I4_3);
  48.             break;
  49.         case 4:
  50.             il.Emit(OpCodes.Ldc_I4_4);
  51.             break;
  52.         case 5:
  53.             il.Emit(OpCodes.Ldc_I4_5);
  54.             break;
  55.         case 6:
  56.             il.Emit(OpCodes.Ldc_I4_6);
  57.             break;
  58.         case 7:
  59.             il.Emit(OpCodes.Ldc_I4_7);
  60.             break;
  61.         case 8:
  62.             il.Emit(OpCodes.Ldc_I4_8);
  63.             break;
  64.         default:
  65.             if (e.Value > -128 && e.Value < 127)
  66.             il.Emit(OpCodes.Ldc_I4_S, (byte)e.Value);
  67.             else if (e.Value > Int32.MinValue && e.Value < Int32.MaxValue)
  68.             il.Emit(OpCodes.Ldc_I4, (int)e.Value);
  69.             else 
  70.             il.Emit(OpCodes.Ldc_I8, e.Value);
  71.             break;
  72.         }
  73.     }
  74.     
  75.     public void BinopExp(BinopExp e)
  76.     {
  77.     e.Left.Visit(this);
  78.     e.Right.Visit(this);
  79.     switch(e.Oper){
  80.     case Operator.ADD:
  81.         il.Emit(OpCodes.Add);
  82.         break;
  83.     case Operator.SUB:
  84.         il.Emit(OpCodes.Sub);
  85.         break;
  86.     case Operator.MUL:
  87.         il.Emit(OpCodes.Mul);
  88.         break;
  89.     case Operator.DIVIDE:
  90.         il.Emit(OpCodes.Div);
  91.         break;
  92.     }
  93.     }
  94.  
  95.     public void CompareExp(CompareExp e)
  96.     {
  97.     Label TrueLabel = il.DefineLabel();
  98.     Label EndLabel = il.DefineLabel();
  99.     e.Left.Visit(this);
  100.     e.Right.Visit(this);
  101.     switch(e.Oper){
  102.     case Operator.LT:
  103.         il.Emit(OpCodes.Blt, TrueLabel);
  104.         break;
  105.     case Operator.GT:
  106.         il.Emit(OpCodes.Bgt, TrueLabel);
  107.         break;
  108.     case Operator.EQ:
  109.         il.Emit(OpCodes.Beq, TrueLabel);
  110.         break;
  111.     case Operator.LE:
  112.         il.Emit(OpCodes.Ble, TrueLabel);
  113.         break;
  114.     case Operator.GE:
  115.         il.Emit(OpCodes.Bge, TrueLabel);
  116.         break;
  117.  
  118.     }
  119.     il.Emit(OpCodes.Ldc_I4_0);
  120.     il.Emit(OpCodes.Br, EndLabel);
  121.     il.MarkLabel(TrueLabel);
  122.     il.Emit(OpCodes.Ldc_I4_1);
  123.     il.MarkLabel(EndLabel);
  124.     
  125.     }
  126.     
  127.  
  128.     public void CallExp(CallExp e)
  129.     {
  130.     for(int i = 0; i < e.Params.Length; i++){
  131.         e.Params[i].Visit(this);
  132.     }
  133.     if(e.System){
  134.         il.Emit(OpCodes.Call, ((typeof(LispRuntime)).GetMethod(e.FunctionName)));
  135.     }
  136.     else{
  137.         il.Emit(OpCodes.Call, (MethodInfo)Functions[e.FunctionName]);
  138.     }
  139.     
  140.     }
  141.     
  142.     public void CarExp(CarExp e)
  143.     {
  144.     e.Left.Visit(this);
  145.     il.Emit(OpCodes.Call, ((typeof(LispRuntime)).GetMethod("Car")));
  146.     }
  147.     
  148.     public void IsNullExp(IsNullExp e)
  149.     {
  150.     }
  151.  
  152.     public void ToIntExp(ToIntExp e)
  153.     {
  154.     e.Value.Visit(this);
  155.     il.Emit(OpCodes.Call, ((typeof(LispRuntime)).GetMethod("ToInt")));
  156.     }
  157.  
  158.     public void ToListExp(ToListExp e)
  159.     {
  160.     e.Value.Visit(this);
  161.     il.Emit(OpCodes.Call, ((typeof(LispRuntime)).GetMethod("ToList")));
  162.     }
  163.     
  164.     
  165.     public void StringExp(StringExp e)
  166.     {
  167.     il.Emit(OpCodes.Ldstr, (e.Value));
  168.     il.Emit(OpCodes.Call, ((typeof(LispRuntime)).GetMethod("Init")));
  169.     }
  170.     
  171.     public void VarExp(VarExp e)
  172.     {
  173.     switch(e.Pos){
  174.     case 0:
  175.         il.Emit(OpCodes.Ldarg_0);
  176.         break;
  177.     case 1:
  178.         il.Emit(OpCodes.Ldarg_1);
  179.         break;
  180.     case 2:
  181.         il.Emit(OpCodes.Ldarg_2);
  182.         break;
  183.     case 3:
  184.         il.Emit(OpCodes.Ldarg_3);
  185.         break;
  186.     default:
  187.         if(e.Pos > -128 && e.Pos < 127)
  188.         il.Emit(OpCodes.Ldarg_S, e.Pos);
  189.         else 
  190.         il.Emit(OpCodes.Ldarg, e.Pos);
  191.     }
  192.     }
  193.     
  194.     public void GlobalVarExp(GlobalVarExp e)
  195.     {
  196.         il.Emit(OpCodes.Ldsfld, (FieldInfo)GlobalVars[e.Name]);    
  197.     }
  198.     
  199.     public void IfExp(IfExp e)
  200.     {
  201.     Label FalseLabel, EndLabel;
  202.     FalseLabel = il.DefineLabel();
  203.     EndLabel = il.DefineLabel();
  204.     e.EvalExp.Visit(this);
  205.     il.Emit(OpCodes.Brfalse, FalseLabel);
  206.     e.ThenExp.Visit(this);
  207.     il.Emit(OpCodes.Br, EndLabel);
  208.     il.MarkLabel(FalseLabel);
  209.     e.ElseExp.Visit(this);
  210.     il.MarkLabel(EndLabel);
  211.     
  212.     }
  213.  
  214.     public void DoExp(DoExp e)
  215.     {
  216.     Label l1 = il.DefineLabel();
  217.     Label l2 = il.DefineLabel();
  218.     Label EndLabel = il.DefineLabel();
  219.     
  220.     for (ExpList el = e.Vars; el != null; el = el.Tail){
  221.         el.Head.Visit(this);
  222.     }
  223.     il.Emit(OpCodes.Br, l1);
  224.     il.MarkLabel(l2);
  225.     for (ExpList el = e.Vars; el != null; el = el.Tail){
  226.         DoVarIter((DoVarDef)el.Head);
  227.     }
  228.     il.MarkLabel(l1);
  229.     
  230.     for (ExpList el = e.Conds; el != null; el = el.Tail){
  231.         ((DoCondExp)el.Head).EndLabel = EndLabel;
  232.         el.Head.Visit(this);
  233.     }
  234.     il.Emit(OpCodes.Br, l2);
  235.     
  236.     il.MarkLabel(EndLabel);
  237.     
  238.     }
  239.  
  240.     public void DoVarIter(DoVarDef e)
  241.     {
  242.     e.Iter.Visit(this);
  243.     il.Emit(OpCodes.Stloc, (LocalBuilder)DoVars[e.Pos]);
  244.     }
  245.     
  246.  
  247.     public void DoVarExp(DoVarExp e)
  248.     {
  249.         il.Emit(OpCodes.Ldloc, (LocalBuilder)DoVars[e.Pos]);
  250.     }
  251.     
  252.     public void DoCondExp(DoCondExp e)
  253.     {
  254.     Label FalseLabel;
  255.     FalseLabel = il.DefineLabel();
  256.  
  257.     e.Cond.Visit(this);
  258.     il.Emit(OpCodes.Brfalse, FalseLabel);
  259.     e.Ret.Visit(this);
  260.     il.Emit(OpCodes.Br, e.EndLabel);
  261.     
  262.     il.MarkLabel(FalseLabel);
  263.     
  264.     }
  265.     
  266.     public void DoVarDef(DoVarDef e)
  267.     {
  268.     LocalBuilder lt = il.DeclareLocal(e.Init.ExpType);
  269.     DoVars.Add(e.Pos, lt);
  270.     e.Init.Visit(this);
  271.     il.Emit(OpCodes.Stloc, lt);
  272.     }
  273.     
  274.     
  275.     public void FunctionDef(FunctionDef e)
  276.     {
  277.     Type[] param = new Type[e.Count];
  278.     DoVars = new Hashtable();
  279.     
  280.     for (int i = 0; i < e.Count; i++){
  281.         param[i] = (Type)e.Params[i];
  282.     }
  283.     
  284.     //DescriptorInfo di = new DescriptorInfo(param);
  285.     //di.SetReturnType(e.ExpType);
  286.     //di.MethodAttributes = MethodAttributes.Static | MethodAttributes.Public;
  287.     methodb = tb.DefineMethod(e.Name, MethodAttributes.Static | MethodAttributes.Public, e.ExpType, param);
  288.     Functions.Add(e.Name, methodb);
  289.     ILGenerator ilmain = il;
  290.     il = methodb.GetILGenerator();
  291.  
  292.     e.Body.Visit(this);
  293.     
  294.     il.Emit(OpCodes.Ret);
  295.     il = ilmain;
  296.     }
  297.     
  298.     public void GlobalVarDef(GlobalVarDef e)
  299.     {
  300.     FieldInfo fi = tb.DefineField(e.Name, e.ExpType, FieldAttributes.Static);
  301.     GlobalVars.Add(e.Name, fi);
  302.  
  303.     e.Value.Visit(this);
  304.     il.Emit(OpCodes.Stsfld, fi);
  305.     }
  306.     
  307.     public void Generate(String filename)
  308.     {
  309.     AppDomain ad = Thread.GetDomain(); //AppDomain.CreateDomain("First", null, null);
  310.     AssemblyName an = new AssemblyName();
  311.     an.Name = filename + ".exe"; //AssemblyName.CreateSimpleName(filename + ".exe", "LispExe", "Lisp Executable", "default_alias");
  312.     AssemblyBuilder ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
  313.     ModuleBuilder mb = ab.DefineDynamicModule(filename + ".exe", filename + ".exe");
  314.     MethodBuilder methodb;
  315.     //DescriptorInfo di = new DescriptorInfo(0);
  316.     tb = mb.DefineType(filename);
  317.     
  318.     //di.SetReturnType(typeof(Void));
  319.     //di.MethodAttributes = MethodAttributes.Static | MethodAttributes.Public;
  320.     methodb = tb.DefineMethod("Main", MethodAttributes.Static | MethodAttributes.Public, typeof(Void), null);
  321.     il = methodb.GetILGenerator();
  322.  
  323.     do{
  324.         expr.Head.Visit(this);
  325.             if (expr.Head is FunctionDef)
  326.             GenerateDefStub(((FunctionDef)expr.Head).Name);
  327.              else if (expr.Head is GlobalVarDef)
  328.             GenerateDefStub(((GlobalVarDef)expr.Head).Name);
  329.          else if (expr.Head.ExpType == typeof(int))
  330.           GenerateNumericExpStub();
  331.             else if (expr.Head.ExpType == typeof(bool))
  332.         GenerateBoolExpStub();
  333.             else if (expr.Head.ExpType == typeof(CList)) 
  334.             GenerateListExpStub();
  335. //            else if (expr.Head is FunctionDef)
  336. //            GenerateFuncDefStub((FunctionDef)expr.Head, il);
  337.         
  338.         expr = expr.Tail;
  339.     }while(expr != null);
  340.     
  341.     il.Emit(OpCodes.Ret);
  342.     tb.CreateType();
  343.     
  344.     mb.SetEntryPoint(methodb);
  345.     ab.SetEntryPoint((mb.GetType(filename)).GetMethod("Main"));
  346. //     mb.EmitPEFile(filename + ".exe");
  347.     ab.Save(filename + ".exe");
  348.     }
  349.  
  350.     void GenerateNumericExpStub()
  351.     {
  352.       Type[] type = new Type[1];
  353.       type[0] = Type.GetType("System.Int32");
  354.       il.Emit(OpCodes.Call, ((typeof(System.Console)).GetMethod("WriteLine", type)));
  355.     }
  356.  
  357.     void GenerateListExpStub()
  358.     {
  359.       il.Emit(OpCodes.Call, ((typeof(LispRuntime)).GetMethod("Print")));
  360.       Type[] type = new Type[1];
  361.       type[0] = Type.GetType("System.String");
  362.     il.Emit(OpCodes.Ldstr, "");                //This is just to do a WriteLine after the Print.
  363.       il.Emit(OpCodes.Call, ((typeof(System.Console)).GetMethod("WriteLine", type)));
  364.     
  365.     }
  366.  
  367.     void GenerateDefStub(String Name)
  368.     {
  369.       Type[] type = new Type[1];
  370.       type[0] = Type.GetType("System.String");
  371.     il.Emit(OpCodes.Ldstr, Name);
  372.       il.Emit(OpCodes.Call, ((typeof(System.Console)).GetMethod("WriteLine", type)));
  373.     
  374.     }
  375.  
  376.     void GenerateBoolExpStub()
  377.     {
  378.     il.Emit(OpCodes.Call, ((typeof(LispRuntime)).GetMethod("PrintBool")));
  379.     }
  380.     
  381. }
  382.