Skip to content

Commit

Permalink
Merge pull request #45 from edgarfgp/add-generic-records-and-unions
Browse files Browse the repository at this point in the history
Record | Unions Generic Widgets
  • Loading branch information
edgarfgp committed Jun 14, 2023
2 parents fd8834d + 8326e0a commit 09d5f3c
Show file tree
Hide file tree
Showing 22 changed files with 494 additions and 183 deletions.
7 changes: 3 additions & 4 deletions src/Fabulous.AST.Tests/Namespaces/Namespace.fs
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,9 @@ module Fabulous.AST =
let myFields =
props |> Map.toList |> List.map(fun (key, value) -> Field(key, mkType value))

Record(name) { yield! myFields }
|> Tree.compile
|> TypeDefn.Record
|> ModuleDecl.TypeDefn)
let fields = Record(name) { yield! myFields } |> Tree.compile
let record = TypeDefn.Record(fields)
ModuleDecl.TypeDefn(record))

Namespace("Json") {
for recordType in recordTypes do
Expand Down
23 changes: 22 additions & 1 deletion src/Fabulous.AST.Tests/TypeDefinitions/Record.fs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ type Colors =
[<Test>]
let ``Produces a record with TypeParams`` () =
AnonymousModule() {
Record("Colors", [ "'other" ]) {
GenericRecord("Colors", [ "'other" ]) {
Field("Green", Type.FromString "string")
Field("Blue", Type.FromString "'other")
Field("Yellow", Type.FromString "int")
Expand All @@ -208,4 +208,25 @@ type Colors<'other> =
Blue: 'other
Yellow: int }
"""

[<Test>]
let ``Produces a struct record with TypeParams`` () =
AnonymousModule() {
(GenericRecord("Colors", [ "'other" ]) {
Field("Green", Type.FromString "string")
Field("Blue", Type.FromString "'other")
Field("Yellow", Type.FromString "int")
})
.isStruct()
}

|> produces
"""
[<Struct>]
type Colors<'other> =
{ Green: string
Blue: 'other
Yellow: int }
"""
29 changes: 28 additions & 1 deletion src/Fabulous.AST.Tests/TypeDefinitions/Union.fs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ type Colors = | [<Obsolete; Test>] Red
[<Test>]
let ``Produces an union with TypeParams`` () =
AnonymousModule() {
Union("Colors", [ "'other" ]) {
GenericUnion("Colors", [ "'other" ]) {
UnionParameterizedCase("Red") {
Field("a", Type.FromString "string")
Field("b", Type.FromString "'other")
Expand All @@ -225,4 +225,31 @@ type Colors<'other> =
| Blue
| Yellow
"""

[<Test>]
let ``Produces an struct union with TypeParams`` () =
AnonymousModule() {
(GenericUnion("Colors", [ "'other" ]) {
UnionParameterizedCase("Red") {
Field("a", Type.FromString "string")
Field("b", Type.FromString "'other")
}

UnionCase("Green")
UnionCase("Blue")
UnionCase("Yellow")
})
.isStruct()
}

|> produces
"""
[<Struct>]
type Colors<'other> =
| Red of a: string * b: 'other
| Green
| Blue
| Yellow
"""
2 changes: 2 additions & 0 deletions src/Fabulous.AST/Fabulous.AST.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
<Compile Include="Widgets\TypeDefinitions\Enum.fs" />
<Compile Include="Widgets\TypeDefinitions\Abbrev.fs" />
<Compile Include="Widgets\TypeDefinitions\Union.fs" />
<Compile Include="Widgets\TypeDefinitions\GenericUnion.fs" />
<Compile Include="Widgets\TypeDefinitions\Record.fs" />
<Compile Include="Widgets\TypeDefinitions\GenericRecord.fs" />
<Compile Include="Widgets\TypeDefinitions\Interface.fs" />
<Compile Include="Widgets\TypeDefinitions\Class.fs" />
<Compile Include="Widgets\TypeDefinitions\GenericClass.fs" />
Expand Down
10 changes: 10 additions & 0 deletions src/Fabulous.AST/Widgets/Common.fs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ module Auxiliary =
let rightArrow = SingleTextNode.Create "->"
let lefArrow = SingleTextNode.Create "<-"
let star = SingleTextNode.Create "*"
let ``if`` = SingleTextNode.Create "if"
let ``elif`` = SingleTextNode.Create "elif"
let ``then`` = SingleTextNode.Create "then"
let ``else`` = SingleTextNode.Create "else"
let ``let`` = SingleTextNode.Create "let"
let ``private`` = SingleTextNode.Create "private"
let ``internal`` = SingleTextNode.Create "internal"
let ``inline`` = SingleTextNode.Create "inline"
let ``namespace`` = SingleTextNode.Create "namespace"
let ``module`` = SingleTextNode.Create "module"

type IdentifierOrDot =
static member inline CreateIdent(idText: string) =
Expand Down
6 changes: 3 additions & 3 deletions src/Fabulous.AST/Widgets/ControlFlow/IfThen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ module IfThen =
let thenExpr = Helpers.getNodeFromWidget<Expr> widget ThenExpr

ExprIfThenNode(
IfKeywordNode.SingleWord(SingleTextNode("if", Range.Zero)),
IfKeywordNode.SingleWord(SingleTextNode.``if``),
ifExpr,
SingleTextNode("then", Range.Zero),
SingleTextNode.``then``,
thenExpr,
Range.Zero
))

[<AutoOpen>]
module IfThenBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline IfThen(ifExpr: WidgetBuilder<Expr>) =
SingleChildBuilder<ExprIfThenNode, Expr>(
Expand Down
2 changes: 1 addition & 1 deletion src/Fabulous.AST/Widgets/ControlFlow/IfThenElif.fs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module IfThenElif =

let elseExpr =
match elseExpr with
| ValueSome elseExpr -> Some(SingleTextNode("else", Range.Zero), elseExpr)
| ValueSome elseExpr -> Some(SingleTextNode.``else``, elseExpr)
| ValueNone -> None

ExprIfThenElifNode(
Expand Down
8 changes: 4 additions & 4 deletions src/Fabulous.AST/Widgets/ControlFlow/IfThenElse.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ module IfThenElse =
let elseExpr = Helpers.getNodeFromWidget<Expr> widget ElseExpr

ExprIfThenElseNode(
IfKeywordNode.SingleWord(SingleTextNode("if", Range.Zero)),
IfKeywordNode.SingleWord(SingleTextNode.``if``),
ifExpr,
SingleTextNode("then", Range.Zero),
SingleTextNode.``then``,
thenExpr,
SingleTextNode("else", Range.Zero),
SingleTextNode.``else``,
elseExpr,
Range.Zero
))

[<AutoOpen>]
module IfThenElseBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline IfThenElse(ifExpr: WidgetBuilder<Expr>, elseExpr: WidgetBuilder<Expr>) =
SingleChildBuilder<ExprIfThenElseNode, Expr>(
Expand Down
8 changes: 4 additions & 4 deletions src/Fabulous.AST/Widgets/LetBindings/Function.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ type FunctionNode(name, parameters, bodyExpr, isInlined) =
BindingNode(
None,
None,
MultipleTextsNode([ SingleTextNode("let", Range.Zero) ], Range.Zero),
MultipleTextsNode([ SingleTextNode.``let`` ], Range.Zero),
false,
(match isInlined with
| ValueNone
| ValueSome false -> None
| ValueSome true -> Some(SingleTextNode("inline", Range.Zero))),
| ValueSome true -> Some(SingleTextNode.``inline``)),
None,
Choice1Of2(IdentListNode([ IdentifierOrDot.Ident(SingleTextNode(name, Range.Zero)) ], Range.Zero)),
None,
[ for param in parameters do
Pattern.Named(PatNamedNode(None, SingleTextNode(param, Range.Zero), Range.Zero)) ],
None,
SingleTextNode("=", Range.Zero),
SingleTextNode.equals,
bodyExpr,
Range.Zero
)
Expand All @@ -48,7 +48,7 @@ module Function =

[<AutoOpen>]
module FunctionBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline Function(name: string, parameters: string[]) =
SingleChildBuilder<FunctionNode, Expr>(
Expand Down
30 changes: 6 additions & 24 deletions src/Fabulous.AST/Widgets/LetBindings/Literal.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,16 @@ type LiteralNode(xmlDoc: XmlDocNode option, accessControl: SingleTextNode option
inherit
BindingNode(
xmlDoc,
Some(
MultipleAttributeListNode(
[ AttributeListNode(
SingleTextNode("[<", Range.Zero),
[ AttributeNode(
IdentListNode(
[ IdentifierOrDot.Ident(SingleTextNode("Literal", Range.Zero)) ],
Range.Zero
),
None,
None,
Range.Zero
) ],
SingleTextNode(">]", Range.Zero),
Range.Zero
) ],
Range.Zero
)
),
MultipleTextsNode([ SingleTextNode("let", Range.Zero) ], Range.Zero),
Some(MultipleAttributeListNode.Create([ "Literal" ])),
MultipleTextsNode([ SingleTextNode.``let`` ], Range.Zero),
false,
None,
accessControl,
Choice1Of2(IdentListNode([ IdentifierOrDot.Ident(SingleTextNode(name, Range.Zero)) ], Range.Zero)),
None,
List.Empty,
None,
SingleTextNode("=", Range.Zero),
SingleTextNode.equals,
Expr.Constant(Constant.FromText(SingleTextNode(value, Range.Zero))),
Range.Zero
)
Expand All @@ -61,8 +43,8 @@ module Literal =
let accessControl =
match accessControl with
| Public -> None
| Private -> Some(SingleTextNode("private", Range.Zero))
| Internal -> Some(SingleTextNode("internal", Range.Zero))
| Private -> Some(SingleTextNode.``private``)
| Internal -> Some(SingleTextNode.``internal``)

let lines = Helpers.tryGetScalarValue widget XmlDocs

Expand All @@ -75,7 +57,7 @@ module Literal =

[<AutoOpen>]
module LiteralBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline Literal(name: string, value: string) =
WidgetBuilder<LiteralNode>(Literal.WidgetKey, Literal.Name.WithValue(name), Literal.Value.WithValue(value))
Expand Down
4 changes: 2 additions & 2 deletions src/Fabulous.AST/Widgets/Namespaces/Module.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type ModuleNode(identList: IdentListNode, decls: ModuleDecl list) =
ModuleOrNamespaceHeaderNode(
None,
None,
MultipleTextsNode([ SingleTextNode("module", Range.Zero) ], Range.Zero),
MultipleTextsNode([ SingleTextNode.``module`` ], Range.Zero),
None,
false,
Some(identList),
Expand All @@ -42,7 +42,7 @@ module Module =

[<AutoOpen>]
module ModuleBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline Module(identList: WidgetBuilder<#IdentListNode>) =
CollectionBuilder<ModuleNode, ModuleDecl>(
Expand Down
4 changes: 2 additions & 2 deletions src/Fabulous.AST/Widgets/Namespaces/Namespace.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type NamespaceNode(identList: IdentListNode, decls: ModuleDecl list, isRecursive
ModuleOrNamespaceHeaderNode(
None,
None,
MultipleTextsNode([ SingleTextNode("namespace", Range.Zero) ], Range.Zero),
MultipleTextsNode([ SingleTextNode.``namespace`` ], Range.Zero),
None,
isRecursive,
Some(identList),
Expand Down Expand Up @@ -48,7 +48,7 @@ module Namespace =

[<AutoOpen>]
module NamespaceBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline Namespace(identList: WidgetBuilder<#IdentListNode>) =
CollectionBuilder<NamespaceNode, ModuleDecl>(
Expand Down
10 changes: 5 additions & 5 deletions src/Fabulous.AST/Widgets/Namespaces/NestedModule.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ module NestedModule =
let accessControl =
match accessControl with
| Public -> None
| Private -> Some(SingleTextNode("private", Range.Zero))
| Internal -> Some(SingleTextNode("internal", Range.Zero))
| Private -> Some(SingleTextNode.``private``)
| Internal -> Some(SingleTextNode.``internal``)


let nestedModuleNode =
NestedModuleNode(
None,
None,
SingleTextNode("module", Range.Zero),
SingleTextNode.``module``,
accessControl,
isRecursive,
identList,
SingleTextNode("=", Range.Zero),
SingleTextNode.equals,
moduleDecls,
Range.Zero
)
Expand All @@ -53,7 +53,7 @@ module NestedModule =

[<AutoOpen>]
module NestedModuleBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline NestedModule(identList: WidgetBuilder<#IdentListNode>) =
CollectionBuilder<NestedModuleNode, ModuleDecl>(
Expand Down
2 changes: 1 addition & 1 deletion src/Fabulous.AST/Widgets/OpenDirectives/Open.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module Open =

[<AutoOpen>]
module OpenBuilders =
type Fabulous.AST.Ast with
type Ast with

static member inline Open(identList: WidgetBuilder<#IdentListNode>) =
WidgetBuilder<OpenNode>(
Expand Down
4 changes: 2 additions & 2 deletions src/Fabulous.AST/Widgets/TypeDefinitions/Abbrev.fs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ module Abbrev =
TypeNameNode(
None,
None,
SingleTextNode("type", Range.Zero),
SingleTextNode.``type``,
Some(name),
IdentListNode([ IdentifierOrDot.Ident(SingleTextNode("=", Range.Zero)) ], Range.Zero),
IdentListNode([ IdentifierOrDot.Ident(SingleTextNode.equals) ], Range.Zero),
None,
[],
None,
Expand Down
2 changes: 1 addition & 1 deletion src/Fabulous.AST/Widgets/TypeDefinitions/Enum.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module Enum =
TypeNameNode(
None,
multipleAttributes,
SingleTextNode("type", Range.Zero),
SingleTextNode.``type``,
Some(name),
IdentListNode([ IdentifierOrDot.Ident(SingleTextNode("=", Range.Zero)) ], Range.Zero),
None,
Expand Down
2 changes: 1 addition & 1 deletion src/Fabulous.AST/Widgets/TypeDefinitions/EnumCase.fs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ module EnumCase =
None,
multipleAttributes,
name,
SingleTextNode("=", Range.Zero),
SingleTextNode.equals,
Expr.Constant(Constant.FromText(value)),
Range.Zero
))
Expand Down

0 comments on commit 09d5f3c

Please sign in to comment.