Advertisement
Guest User

Untitled

a guest
Apr 22nd, 2015
206
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 5.07 KB | None | 0 0
  1. module ILCreator
  2.  
  3. open System.Reflection
  4. open System.Reflection.Emit
  5. open ILInstructions
  6. open System.Threading
  7. open System
  8. open System.IO
  9.  
  10. let rec evalInstruction env (typeBuilder: TypeBuilder) (il:ILGenerator) instr =
  11.     match instr with
  12.     | PushInt i                 -> il.Emit(OpCodes.Ldc_I4, i); env
  13.     | Add                       -> il.Emit(OpCodes.Add); env
  14.     | Sub                       -> il.Emit(OpCodes.Sub); env
  15.     | Div                       -> il.Emit(OpCodes.Div); env
  16.     | Mul                       -> il.Emit(OpCodes.Mul); env
  17.     | Gt                        -> il.Emit(OpCodes.Cgt); env
  18.     | Lt                        -> il.Emit(OpCodes.Clt); env
  19.     | LoadLocal name            -> evalLoadLocal env il name; env
  20.     | StoreLocal name           -> evalStoreLocal env il name
  21.     | Print                     -> il.EmitCall(OpCodes.Call,typeof<Console>.GetMethod("WriteLine", [| typeof<int> |]), null); env
  22.     | Branch (a, b)             -> evalBranch env typeBuilder il a b; env
  23.     | MethodCall (name, instrs) -> evalMethodCall env typeBuilder il name instrs; env
  24.     | _                         -> failwith "Expected an instruction!"
  25.  
  26. and evalMethodCall env (typeBuilder:TypeBuilder) (il:ILGenerator) methodName instrs =
  27.     evalInstructions env typeBuilder il instrs
  28.     let methodInfo = typeBuilder.GetMethod(methodName)
  29.     il.EmitCall(OpCodes.Call, methodInfo, [| typeof<int> |])
  30.  
  31. and evalLoadLocal env (il:ILGenerator) name =
  32.     let field = Env.tryGetField name env
  33.     match field with
  34.     | Some(Env.Arg index)   -> il.Emit(OpCodes.Ldarg, index)
  35.     | Some(Env.Local index) -> il.Emit(OpCodes.Ldloc, index)
  36.     | None                  -> failwith "Could not find field!"
  37.  
  38. and evalStoreLocal env (il:ILGenerator) name =
  39.     let (updatedEnv, index) = Env.addLocal name env
  40.     il.DeclareLocal(typeof<int>) |> ignore
  41.     il.Emit(OpCodes.Stloc, index) |> ignore
  42.     updatedEnv
  43.  
  44. and evalInstructions env (typeBuilder:TypeBuilder) (il:ILGenerator) instrs =
  45.     List.fold (fun env value -> evalInstruction env typeBuilder il value) env instrs
  46.  
  47. and evalBranch (env : Env.Env) (typeBuilder:TypeBuilder) (il : ILGenerator) thenInstr elseInstr =
  48.     il.Emit(OpCodes.Ldc_I4_0)
  49.     il.Emit(OpCodes.Ceq)
  50.     let afterIfLabel = il.DefineLabel()
  51.     il.Emit(OpCodes.Brtrue_S, afterIfLabel)
  52.     evalInstructions env typeBuilder il thenInstr |> ignore
  53.     let afterElseLabel = il.DefineLabel()
  54.     il.Emit(OpCodes.Br_S, afterElseLabel)
  55.     il.MarkLabel(afterIfLabel)
  56.     evalInstructions env typeBuilder il elseInstr |> ignore
  57.     il.MarkLabel(afterElseLabel)
  58.  
  59. let createAssembly name =
  60.     let assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(name))
  61.     AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save)
  62.    
  63. let createClass (moduleBuilder: ModuleBuilder) name =
  64.     moduleBuilder.DefineType(name, TypeAttributes.Public)
  65.  
  66. let createMethod (typeBuilder : TypeBuilder) name args instructions =
  67.     let defineParam (newMethod : MethodBuilder) i arg =
  68.         newMethod.DefineParameter(i + 1, ParameterAttributes.None, arg) |> ignore
  69.  
  70.     let types = Array.create (List.length args) typeof<int>
  71.  
  72.     let newMethod = typeBuilder.DefineMethod(name, MethodAttributes.Public ||| MethodAttributes.Static, typeof<int>, types)
  73.     List.iteri (defineParam newMethod) args
  74.    
  75.     let ilGenerator = newMethod.GetILGenerator()
  76.     let env = Env.ofArgs args
  77.     evalInstructions env typeBuilder ilGenerator instructions |> ignore
  78.     ilGenerator.Emit(OpCodes.Ret)
  79.     newMethod
  80.  
  81. let rec generateIL moduleBuilder (assemblyBuilder : AssemblyBuilder) constructs =
  82.     match constructs with
  83.         | Class (name, methods) -> let newClass = createClass moduleBuilder name
  84.                                    buildMethods newClass assemblyBuilder methods
  85.                                    newClass.CreateType()
  86.         | _ -> failwith "Expected a class!"
  87.  
  88. and buildMethods sourceClass (assemblyBuilder : AssemblyBuilder) methods =
  89.         match methods with
  90.         | Method (name, args, instructions)::rest       -> createMethod sourceClass name args instructions |> ignore
  91.                                                            buildMethods sourceClass assemblyBuilder rest
  92.         | EntryMethod (name, args, instructions)::rest  -> let newMethod = createMethod sourceClass name args instructions
  93.                                                            assemblyBuilder.SetEntryPoint(newMethod)
  94.                                                            buildMethods sourceClass assemblyBuilder rest
  95.         | [] -> ()
  96.         | _ -> printfn "Expected a method!"
  97.  
  98. let produceIL assemblyName constructs =
  99.     let assemblyBuilder = createAssembly assemblyName
  100.     let moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName)
  101.     generateIL moduleBuilder assemblyBuilder constructs       |> ignore
  102.     moduleBuilder.CreateGlobalFunctions()                     |> ignore
  103.     assemblyBuilder.Save(assemblyName)                        |> ignore
  104.  
  105.  
  106. //let methodBuilderTest (m : MethodBuilder) =
  107. //    m.DefineParameter
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement