Advertisement
Guest User

Untitled

a guest
May 13th, 2014
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
F# 6.71 KB | None | 0 0
  1. namespace codegenfs
  2.  
  3. type mlist<'a> =
  4.  System.Collections.Generic.List<'a>
  5.  
  6. type File (indentToken : string) =
  7.  
  8.   let sb = new System.Text.StringBuilder(1024)
  9.   let mutable indent = 0
  10.  
  11.   member x.Emit (s:string) =
  12.     sb.Append(s) |> ignore
  13.  
  14.   member x.EmitLineStart () =
  15.     for i in 1 .. indent do
  16.       sb.Append(indentToken) |> ignore
  17.      
  18.   member x.EmitLineStart (s:string) =
  19.     x.EmitLineStart()
  20.     x.Emit(s)
  21.  
  22.   member x.EmitLineEnd () =
  23.     sb.Append(System.Environment.NewLine) |> ignore
  24.    
  25.   member x.EmitLineEnd (s:string) =
  26.     x.Emit(s)
  27.     x.EmitLineEnd()
  28.  
  29.   member x.EmitLine (s:string) =
  30.     x.EmitLineStart()
  31.     x.Emit(s)
  32.     x.EmitLineEnd()
  33.  
  34.   member x.Indent (f) =
  35.     indent <- indent + 1
  36.     f()
  37.     indent <- indent - 1
  38.  
  39.   member x.EmitBlock (f) =  
  40.     x.EmitLine("{")
  41.     x.Indent(f)
  42.     x.EmitLine("}")
  43.  
  44.   override x.ToString () =
  45.     sb.ToString()
  46.  
  47. type BinaryOp =
  48.   | Add
  49.   | AddAssign
  50.   | Sub
  51.   | SubAssign
  52.   | Mul
  53.   | MulAssign
  54.   | Div
  55.   | DivAssign
  56.   | Assign
  57.   | Equals
  58.   | NotEquals
  59.   | LessThan
  60.   | LessThanEqual
  61.   | GreaterThan
  62.   | GreaterThanEqual
  63.  
  64. type Modifiers =
  65.   | Public = 1
  66.   | Protected = 2
  67.   | Private = 4
  68.   | Internal = 8
  69.   | Abstract = 16
  70.   | Virtual = 32
  71.   | Override = 64
  72.   | Sealed = 128
  73.   | Static = 256
  74.   | Partial = 512
  75.  
  76. type CType = {
  77.   Name : string
  78. } with  
  79.   static member Object = {CType.Name = "System.Object"}
  80.   static member op_Implicit(t:System.Type) =
  81.     let rec getName (t:System.Type) =
  82.       let name = t.FullName.Replace('+', '.')
  83.       let args = t.GetGenericArguments()
  84.  
  85.       if args.Length = 0 then name else
  86.         System.Text.RegularExpressions.Regex.Match(name, "[^`]+").Value
  87.         + "<"
  88.         + (args |> Seq.map getName |> String.concat ", ")
  89.         + ">"
  90.  
  91.     {CType.Name = getName t}
  92.  
  93. type Field = {
  94.   Type : CType
  95.   Name : string
  96.   Modifiers : Modifiers
  97.   Initialize : Source option
  98. }
  99.  
  100. and Property = {
  101.   Type : CType
  102.   Name : string
  103.   Modifiers : Modifiers
  104.   Get : Source option
  105.   Set : Source option
  106. }
  107.  
  108. and Class = {
  109.   Name : string
  110.   BaseType : CType
  111.   Interfaces : CType mlist
  112.   Modifiers : Modifiers
  113.   Fields : Field mlist
  114.   Properties : Property mlist
  115. } with
  116.   member x.AllBaseTypes =
  117.     seq {
  118.       yield x.BaseType.Name;
  119.       yield! [for i in x.Interfaces -> i.Name]
  120.     } |> String.concat ","
  121.  
  122.   member x.AsCType =
  123.     {CType.Name = x.Name}
  124.  
  125.   static member New (mods, name, baseType, interfaces) =
  126.     {
  127.       Class.Name = name
  128.       Class.Modifiers = mods
  129.       Class.BaseType = baseType
  130.       Class.Interfaces = if interfaces = null then new mlist<_>() else interfaces
  131.       Class.Fields = new mlist<_>()
  132.       Class.Properties = new mlist<_>()
  133.     }
  134.    
  135. and Source =
  136.   | Raw of string
  137.   | Stmt of Source
  138.   | Class of Class
  139.   | Block of Source array
  140.   | While of Source * Source
  141.   | For of Source * Source * Source * Source
  142.   | IfElse of Source * Source * Source option
  143.   | Binary of Source * BinaryOp * Source
  144.   | Namespace of string * Source mlist
  145.  
  146.   static member op_Implicit (s:string) = Raw(s)
  147.   static member op_Implicit (l:Source mlist) = Block(l.ToArray())
  148.   static member op_Implicit (a:Source array) = Block(a)
  149.   static member op_Implicit (s:Source seq) = Block(Seq.toArray s)
  150.   static member op_Implicit (s:Source) = Some(s)
  151.   static member op_Implicit (c:Class) = Class(c)
  152.  
  153.   static member Null = Raw("null")
  154.   static member This = Raw("this")
  155.   static member Base = Raw("base")
  156.   static member True = Raw("true")
  157.   static member False = Raw("false")
  158.  
  159.   static member NewRawStmt (s:string) =
  160.     Stmt(Raw s)
  161.  
  162.   static member NewBlockSimple ([<System.ParamArray>] s:Source array) =
  163.     Block s
  164.  
  165.   static member NewForSimple (var:string, condition:Source, body:Source) =  
  166.     For(
  167.       Binary(Raw ("int " + var), BinaryOp.Assign, Raw "0"),
  168.       Binary(Raw var, BinaryOp.LessThan, condition),
  169.       Binary(Raw var, BinaryOp.AddAssign, Raw "1"),
  170.       body
  171.     )
  172.  
  173.   static member private ToString (op:BinaryOp) =
  174.     match op with
  175.     | Add -> "+"
  176.     | AddAssign -> "+="
  177.     | Sub -> "-"
  178.     | SubAssign -> "-="
  179.     | Mul -> "*"
  180.     | MulAssign -> "*="
  181.     | Div -> "/"
  182.     | DivAssign -> "/="
  183.     | Equals -> "=="
  184.     | NotEquals -> "!="
  185.     | Assign -> "="
  186.     | LessThan -> "<"
  187.     | LessThanEqual -> "<="
  188.     | GreaterThan -> ">"
  189.     | GreaterThanEqual -> ">="
  190.  
  191.   static member private ToString (mods:Modifiers) =
  192.     "public"
  193.  
  194.   static member private Emit (f:Field, file:File) =
  195.     let mods = Source.ToString(f.Modifiers)
  196.    
  197.     file.EmitLineStart()
  198.     file.Emit(sprintf "%s %s %s" mods f.Type.Name f.Name)
  199.  
  200.     f.Initialize |> Option.iter (fun s -> file.Emit(" = "); Source.Emit(s, file))
  201.  
  202.     file.Emit(";")
  203.     file.EmitLineEnd()
  204.    
  205.   static member private Emit (p:Property, file:File) =
  206.     let mods = Source.ToString(p.Modifiers)
  207.    
  208.     file.EmitLine(sprintf "%s %s %s" mods p.Type.Name p.Name)
  209.     file.EmitBlock(fun () ->
  210.       p.Get |> Option.iter (fun g -> file.EmitLine("get"); Source.Emit (Block [|g|], file))
  211.       p.Set |> Option.iter (fun s -> file.EmitLine("set"); Source.Emit (Block [|s|], file))
  212.     )
  213.  
  214.   static member private EmitBlock (src:Source, file:File) =
  215.     match src with
  216.     | Block _ -> Source.Emit(src, file)
  217.     | s -> Source.Emit(Block [|s|], file)
  218.  
  219.   static member Emit (src:Source, file:File) =
  220.     match src with
  221.     | Raw s ->
  222.       file.Emit(s)
  223.  
  224.     | Stmt s ->
  225.       file.EmitLineStart()
  226.       Source.Emit(s, file)
  227.       file.Emit(";")
  228.       file.EmitLineEnd()
  229.  
  230.     | Block b ->
  231.       file.EmitBlock(fun () -> for s in b do Source.Emit(s, file))
  232.  
  233.     | For (init, cond, incr, body) ->
  234.       file.EmitLineStart("for (")
  235.       Source.Emit(init, file)
  236.       file.Emit("; ")
  237.       Source.Emit(cond, file)
  238.       file.Emit("; ")
  239.       Source.Emit(incr, file)
  240.       file.EmitLineEnd(")")
  241.       Source.EmitBlock(body, file)
  242.  
  243.     | Binary (left, op, right) ->
  244.       file.Emit("(")
  245.       Source.Emit(left, file)
  246.       file.Emit(Source.ToString(op))
  247.       Source.Emit(right, file)
  248.       file.Emit(")")
  249.  
  250.     | IfElse (expr, if', else') ->
  251.       // test
  252.       file.EmitLineStart("if (")
  253.       Source.Emit(expr, file)
  254.       file.EmitLineEnd(")")
  255.  
  256.       // if-body
  257.       Source.EmitBlock(if', file)
  258.  
  259.      // else-body
  260.      else' |> Option.iter (fun s ->
  261.         file.EmitLine("else")
  262.         Source.EmitBlock(s, file)
  263.       )
  264.  
  265.     | Class c ->
  266.       let mods = Source.ToString(c.Modifiers)
  267.       file.EmitLine(sprintf "%s class %s : %s" mods c.Name c.AllBaseTypes)
  268.       file.EmitBlock(fun () ->
  269.         for f in c.Fields do Source.Emit(f, file)
  270.         for p in c.Properties do Source.Emit(p, file)
  271.       )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement