-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
570 additions
and
40 deletions.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
...ulla.SourceGenerator.Core/CodeGen/Text.fs → src/Common/CoreFiles/Text.fs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
module Trulla.SourceGenerator.Text | ||
module Trulla.Core.Text | ||
|
||
open System.Text | ||
|
||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
module Trulla.NodeCli.Renderer | ||
|
||
open System | ||
open TheBlunt | ||
open Trulla.Core | ||
open Trulla.Core.Utils | ||
open Trulla.Core.Text | ||
|
||
let [<Literal>] rootIdentifier = "model" | ||
let [<Literal>] dotIntoMember = "." | ||
|
||
module MemberExp = | ||
let getLastSegment = function | ||
| AccessExp accExp -> accExp.memberName | ||
| IdentExp ident -> ident | ||
|
||
let makeTypeName (potentialRecordNames: RecordDef list) tvar = | ||
potentialRecordNames | ||
|> List.find (fun x -> x.id = tvar) | ||
|> fun x -> | ||
match x.name.ToCharArray() |> Array.toList with | ||
| c::cs -> Char.ToUpperInvariant c :: cs | ||
| [] -> failwith "Empty possible record name is not supported." | ||
|> List.toArray | ||
|> String | ||
|
||
// TODO: Make that configurable | ||
let rec toTypeName potentialRecordNames typ = | ||
match typ with | ||
| Mono KnownTypes.string -> "string" | ||
| Mono KnownTypes.bool -> "bool" | ||
| Poly (KnownTypes.sequence, pt) -> $"List<{toTypeName potentialRecordNames pt}>" | ||
| Record tvar -> makeTypeName potentialRecordNames tvar | ||
// TODO: See comments in ModelInference / FinalTyp | ||
//| Var _ -> "obj" | ||
| _ -> failwithf "Unsupported reference for type '%A'." typ | ||
|
||
let rec memberExpToIdent (exp: TVal<MemberExp>) = | ||
match exp.value with | ||
| IdentExp ident -> | ||
let isBound = exp.bindingContext |> Map.containsKey ident | ||
let rootPrefix = if isBound then "" else rootIdentifier + dotIntoMember | ||
rootPrefix + ident | ||
| AccessExp acc -> (memberExpToIdent acc.instanceExp) + dotIntoMember + acc.memberName | ||
|
||
let renderTemplate (solution: Solution) (namespaceName: string) = | ||
do namespaceName |> String.assertLetterDigitUnderscore "namespace" | ||
|
||
let doubleQuotLit = "\"" | ||
|
||
let toStringLiteral (txt: string) = | ||
// TODO: Escape that let txt = Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(txt, false) | ||
let txt = txt | ||
doubleQuotLit + txt + doubleQuotLit | ||
|
||
text { | ||
ln0 $"namespace {namespaceName};" | ||
br | ||
|
||
ln0 "using System;" | ||
ln0 "using System.Collections.Generic;" | ||
ln0 "using System.Linq;" | ||
br | ||
|
||
// render records | ||
let records = solution.records | ||
// TODO: Why this? | ||
//if solution.records |> Map.containsKey Root | ||
//then solution.records | ||
//else solution.records |> Map.add Root [] | ||
for r in records do | ||
let indent = 0 | ||
lni indent $"public record {makeTypeName records r.id} {{" | ||
for field in r.fields do | ||
lni (indent + 1) $"public required {toTypeName records field.typ} {field.name} {{ get; init; }}" | ||
lni indent "}" | ||
br | ||
|
||
lni 0 $"public static class Rendering {{" | ||
lni 1 $"public static string Render(this {makeTypeName solution.records Root} {rootIdentifier}) {{" | ||
|
||
let sbAppend indent (txt: string) = text { | ||
lni indent $"""__sb.Append({txt});""" | ||
} | ||
lni 2 "var __sb = new System.Text.StringBuilder();" | ||
|
||
let rec render indent tree = text { | ||
for texp in tree do | ||
match texp with | ||
| Text txt -> | ||
sbAppend indent (toStringLiteral txt) | ||
| Hole hole -> | ||
sbAppend indent (memberExpToIdent hole) | ||
| For (ident,exp,sep,body) -> | ||
let elems = memberExpToIdent exp | ||
let xIdent = $"x_{indent}" | ||
let idxIdent = $"idx_{indent}" | ||
lni indent $"foreach (var ({idxIdent},{ident.value}) in {elems}.Select(({xIdent},{idxIdent}) => ({idxIdent},{xIdent}))) {{" | ||
render (indent + 1) body | ||
let sep = sep.result |> Option.defaultValue "" | ||
lni (indent + 1) $"""if ({idxIdent} < {elems}.Count - 1) {{""" | ||
sbAppend (indent + 2) (toStringLiteral sep) | ||
lni (indent + 1) "}" | ||
lni indent "}" | ||
| If (cond,body) -> | ||
lni indent $"if ({memberExpToIdent cond}) {{" | ||
render (indent + 1) body | ||
lni indent "}" | ||
| Else (cond,body) -> | ||
lni indent "else {" | ||
render (indent + 1) body | ||
lni indent "}" | ||
} | ||
|
||
//lni (indent + 2) "}" | ||
|
||
render 2 solution.tree | ||
br | ||
lni 2 "return __sb.ToString();" | ||
|
||
lni 1 "}" | ||
|
||
lni 0 "}" | ||
} | ||
|
||
let renderErrors(errors: TrullaError seq) = | ||
let errorList = [ for error in errors do error.ToString() ] | ||
$""" | ||
Errors in Trulla template: | ||
{String.concat "\n\n" errorList}; | ||
""" |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Hello {{user.name}}, how are you? | ||
|
||
Your Orders | ||
=== | ||
|
||
{{for order in orders|---}} | ||
ID: {{order.id}} | ||
({{if order.isActive}}active{{else}}inactive{{end}}) | ||
{{end}} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
#!/usr/bin/env node | ||
import '../lib/trulla.js'; | ||
import '../lib/Trulla.js'; |
Oops, something went wrong.