Advertisement
Guest User

Untitled

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