Advertisement
Guest User

Untitled

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