Last active
April 17, 2023 16:45
-
-
Save kevmal/5140c30fd6018eb4dfc006e19e5b98a6 to your computer and use it in GitHub Desktop.
Code gen ops
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
open System | |
open System.Runtime.InteropServices | |
open System.Runtime.CompilerServices | |
type CallerInfo = | |
{ | |
Inherited : bool | |
MemberName : string | |
Path : string | |
LineNumber : int | |
} | |
type Str = Str with | |
static member (?)(Str,str) = str | |
let mutable lineSep = "\r\n" | |
let mutable indentString = " " | |
type CodeGenElement = | |
| Block of indent : int * CodeGenElement list * srcInfo : CallerInfo | |
| Line of indent : int * line : string * srcInfo : CallerInfo | |
member x.Indent(n) = | |
match x with | |
| Line(i,l,info) -> Line(i + n, l,info) | |
| Block(i,xs,info) -> Block(i+1,xs,info) | |
member x.Indent() = x.Indent(1) | |
override x.ToString() = | |
match x with | |
| Line(i,str,info) -> (String.replicate i indentString) + str | |
| Block(i,xs,info) -> | |
if i <> 0 then | |
xs | |
|> Seq.map (fun x -> string (x.Indent(i))) | |
|> String.concat lineSep | |
else | |
xs |> Seq.map string |> String.concat lineSep | |
member x.MakeString(f) = | |
match x with | |
| Line(i,str,info) -> f i str info | |
| Block(i,xs,info) -> | |
if i <> 0 then | |
xs | |
|> Seq.map (fun x -> x.Indent(i).MakeString(f)) | |
|> String.concat lineSep | |
else | |
xs |> Seq.map (fun x -> x.MakeString(f)) |> String.concat lineSep | |
member x.MakeString() = x.MakeString(fun i str info -> (String.replicate i indentString) + str) | |
member x.MakeStringDebug(?codeWidth,?includePath) = | |
let codeWidth = defaultArg codeWidth 120 | |
let includePath = defaultArg includePath true | |
let f i str (info : CallerInfo) = | |
let str = ((String.replicate i indentString) + str).PadRight(codeWidth,' ') | |
if includePath then | |
str + sprintf " // %-5d %-20s %s" info.LineNumber info.MemberName (IO.Path.GetFileName(info.Path)) | |
else | |
str + sprintf " // %-5d %-20s" info.LineNumber info.MemberName | |
x.MakeString(f) | |
let stringToLine info (x : string) = | |
let rec loop i (s : string) = | |
if s.StartsWith(indentString) then | |
loop (i + 1) (s.Substring(4)) | |
else | |
Line(i,s,info) | |
loop 0 x | |
let stringToBlock indent info (x : string) = | |
let info2 = {info with Inherited = true} | |
x.Split '\n' | |
|> Array.map (fun x -> x.Trim('\r')) | |
|> Array.map (stringToLine info2) | |
|> Array.toList | |
|> (fun i -> Block(indent,i,info)) | |
let indent i (x:CodeGenElement) = x.Indent(i) | |
let injectInto (filename : string) (markerStart : string) (markerEnd : string) injectTxt = | |
let injectTxt = markerStart + injectTxt | |
let txt = IO.File.ReadAllText(filename) | |
let startIndex = txt.IndexOf(markerStart) | |
let endIndex = txt.IndexOf(markerEnd) | |
if startIndex > 0 && endIndex > startIndex then | |
let newTxt = txt.Substring(0,startIndex) + injectTxt + txt.Substring(endIndex) | |
IO.File.WriteAllText(filename, newTxt) | |
let rec typeStr (t : Type) = | |
if t.IsGenericType then | |
let targs = t.GetGenericArguments() |> Array.map typeStr | |
let name = | |
let name = t.FullName | |
let i = name.IndexOf "`" | |
name.Substring(0,i) | |
sprintf "%s<%s>" name (targs |> String.concat ", ") | |
else | |
t.FullName | |
type Operators() = | |
static member C(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(0, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C_(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(1, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C__(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(2, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C___(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(3, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C____(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(4, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C_____(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(5, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C______(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(6, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C_______(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(7, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member C________(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Line(8, str, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(0, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B_(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(1, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B__(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(2, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B___(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(3, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B____(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(4, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B_____(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(5, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B______(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(6, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B_______(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(7, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member B________(l, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = Block(8, l, { MemberName = memberName; Path = path; LineNumber = line; Inherited = false}) | |
static member P(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = stringToBlock 0 { MemberName = memberName; Path = path; LineNumber = line; Inherited = false} str | |
static member P_(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = stringToBlock 1 { MemberName = memberName; Path = path; LineNumber = line; Inherited = false} str | |
static member P__(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = stringToBlock 2 { MemberName = memberName; Path = path; LineNumber = line; Inherited = false} str | |
static member P___(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = stringToBlock 3 { MemberName = memberName; Path = path; LineNumber = line; Inherited = false} str | |
static member P____(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = stringToBlock 4 { MemberName = memberName; Path = path; LineNumber = line; Inherited = false} str | |
static member P_____(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = stringToBlock 5 { MemberName = memberName; Path = path; LineNumber = line; Inherited = false} str | |
static member P______(str, [<CallerMemberName; Optional; DefaultParameterValue("")>] memberName: string, [<CallerFilePath; Optional; DefaultParameterValue("")>] path: string, [<CallerLineNumber; Optional; DefaultParameterValue(0)>] line: int) = stringToBlock 6 { MemberName = memberName; Path = path; LineNumber = line; Inherited = false} str | |
open type Operators | |
let fieldList = | |
[ | |
"A" | |
"B" | |
"C" | |
] | |
let record name fieldList = | |
B [ | |
C$"type {name} =" | |
C_"{" | |
for name in fieldList do | |
C__$"{name} : string" | |
C_"}" | |
] | |
let codeBlock = record "MyRecord" fieldList | |
codeBlock.MakeStringDebug() | |
//Result: | |
type MyRecord = // 141 record CodeGen.fsx | |
{ // 142 record CodeGen.fsx | |
A : string // 144 record CodeGen.fsx | |
B : string // 144 record CodeGen.fsx | |
C : string // 144 record CodeGen.fsx | |
} | |
/////// | |
let myRecords = | |
B [ | |
record "Record1" ["Cat"; "Dog"] | |
record "Record2" ["Mouse"; "Lamma"] | |
] | |
let myModule = | |
B [ | |
C "module MyModule =" | |
B_ [myRecords] | |
] | |
myModule.MakeStringDebug() | |
//Result: | |
module MyModule = // 168 myModule CodeGen.fsx | |
type Record1 = // 141 record CodeGen.fsx | |
{ // 142 record CodeGen.fsx | |
Cat : string // 144 record CodeGen.fsx | |
Dog : string // 144 record CodeGen.fsx | |
} // 145 record CodeGen.fsx | |
type Record2 = // 141 record CodeGen.fsx | |
{ // 142 record CodeGen.fsx | |
Mouse : string // 144 record CodeGen.fsx | |
Lamma : string // 144 record CodeGen.fsx | |
} // 145 record CodeGen.fsx | |
/////// |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment