Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to return IfThenElse expression from a Method #70

Merged
merged 2 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
_No unreleased changes_

## [0.9.0] - 2024-03-12

### Fixed
- Unable to return IfThenElse expression from a Method by @edgarfgp in https://github.com/edgarfgp/Fabulous.AST/pull/70

## [0.8.2] - 2024-03-11

### Changed
Expand Down Expand Up @@ -107,7 +112,8 @@ _No unreleased changes_

- Initial release

[unreleased]: https://github.com/edgarfgp/Fabulous.AST/compare/0.8.2...HEAD
[unreleased]: https://github.com/edgarfgp/Fabulous.AST/compare/0.9.0...HEAD
[0.9.0]: https://github.com/edgarfgp/Fabulous.AST/releases/tag/0.9.0
[0.8.2]: https://github.com/edgarfgp/Fabulous.AST/releases/tag/0.8.2
[0.8.1]: https://github.com/edgarfgp/Fabulous.AST/releases/tag/0.8.1
[0.8.0]: https://github.com/edgarfgp/Fabulous.AST/releases/tag/0.8.0
Expand Down
85 changes: 71 additions & 14 deletions src/Fabulous.AST.Tests/Expressions/Conditionals.fs
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,79 @@ module IfThen =
ExprCompExprBodyNode([ ComputationExpressionStatement.OtherStatement(thenExpr) ], Range.Zero)
)

AnonymousModule() { IfThen(EscapeHatch(ifExp), EscapeHatch(thenExpr)) }
AnonymousModule() { IfThenExpr(EscapeHatch(ifExp), EscapeHatch(thenExpr)) }
|> produces
"""

if x = 12 then
()
"""

[<Fact>]
let ``Produces if-then expression on a let binding``() =
let ifThenExpr =
IfThenExpr(
InfixAppExpr(ConstantExpr("x", false), "=", ConstantExpr("12", false)),
ConstantExpr(ConstantUnit())
)

AnonymousModule() {
Value("res", ifThenExpr)

Value(
"res2",
IfThenElseExpr(
InfixAppExpr(ConstantExpr(Constant("x", false)), "=", ConstantExpr(Constant("12", false))),
ConstantExpr(ConstantUnit()),
ConstantExpr(ConstantUnit())
)
)

Value(
"res3",
IfThenElifExpr(ConstantExpr(ConstantUnit())) {
IfThenExpr(
InfixAppExpr(ConstantExpr("x", false), "=", ConstantExpr("12", false)),
ConstantExpr(ConstantUnit())
)

ElIfThenExpr(
InfixAppExpr(ConstantExpr(Constant("x", false)), "=", ConstantExpr("11", false)),
ConstantExpr(ConstantUnit())
)
}
)

}
|> produces
"""

let res =
if x = 12 then
()

let res2 = if x = 12 then () else ()

let res3 =
if x = 12 then ()
elif x = 11 then ()
else ()
"""

[<Fact>]
let ``Produces if-then expression with expr widgets``() =
AnonymousModule() { IfThen(InfixAppExpr("x", "=", "12"), ConstantExpr(ConstantUnit())) }
AnonymousModule() {
IfThenExpr(InfixAppExpr("x", "=", "12"), ConstantExpr(ConstantUnit()))
ElIfThenExpr(InfixAppExpr("x", "=", "12"), ConstantExpr(ConstantUnit()))
}
|> produces
"""

if x = 12 then
()

elif x = 12 then
()
"""

[<Fact>]
Expand All @@ -71,7 +128,7 @@ if x = 12 then
ExprCompExprBodyNode([ ComputationExpressionStatement.OtherStatement(thenExpr) ], Range.Zero)
)

AnonymousModule() { ElIfThen(EscapeHatch(ifExp), EscapeHatch(thenExpr)) }
AnonymousModule() { ElIfThenExpr(EscapeHatch(ifExp), EscapeHatch(thenExpr)) }
|> produces
"""

Expand All @@ -82,7 +139,7 @@ elif x = 12 then
[<Fact>]
let ``Produces elif-then expression with expr widget``() =
AnonymousModule() {
ElIfThen(
ElIfThenExpr(
InfixAppExpr(ConstantExpr("x", false), "=", ConstantExpr("12", false)),
ConstantExpr(ConstantUnit())
)
Expand All @@ -97,7 +154,7 @@ elif x = 12 then
[<Fact>]
let ``Produces elseif-then expression with expr widget``() =
AnonymousModule() {
ElseIfThen(
ElseIfThenExpr(
InfixAppExpr(ConstantExpr(Constant("x", false)), "=", ConstantExpr(Constant("12", false))),
ConstantExpr(ConstantUnit())
)
Expand All @@ -109,17 +166,17 @@ else if x = 12 then
()
"""

module ConditionalExpr =
module IfThenElif =
[<Fact>]
let ``Produces If Then Elif Then expression with widgets``() =
AnonymousModule() {
ConditionalExpr() {
IfThen(
IfThenElifExpr() {
IfThenExpr(
InfixAppExpr(ConstantExpr("x", false), "=", ConstantExpr("12", false)),
ConstantExpr(ConstantUnit())
)

ElIfThen(
ElIfThenExpr(
InfixAppExpr(ConstantExpr(Constant("x", false)), "=", ConstantExpr("11", false)),
ConstantExpr(ConstantUnit())
)
Expand All @@ -136,13 +193,13 @@ elif x = 11 then
[<Fact>]
let ``Produces If Then Elif Then Else expression with widgets``() =
AnonymousModule() {
ConditionalExpr(ConstantExpr(ConstantUnit())) {
IfThen(
IfThenElifExpr(ConstantExpr(ConstantUnit())) {
IfThenExpr(
InfixAppExpr(ConstantExpr("x", false), "=", ConstantExpr("12", false)),
ConstantExpr(ConstantUnit())
)

ElIfThen(
ElIfThenExpr(
InfixAppExpr(ConstantExpr("x", false), "=", ConstantExpr("11", false)),
ConstantExpr(ConstantUnit())
)
Expand Down Expand Up @@ -195,7 +252,7 @@ else ()
)
)

AnonymousModule() { IfThenElse(EscapeHatch(ifExp), EscapeHatch(thenExpr), EscapeHatch(elseExpr)) }
AnonymousModule() { IfThenElseExpr(EscapeHatch(ifExp), EscapeHatch(thenExpr), EscapeHatch(elseExpr)) }
|> produces
"""

Expand All @@ -206,7 +263,7 @@ if x = 12 then () else ()
let ``Produces if-then-else expression with widgets``() =

AnonymousModule() {
IfThenElse(
IfThenElseExpr(
InfixAppExpr(ConstantExpr(Constant("x", false)), "=", ConstantExpr(Constant("12", false))),
ConstantExpr(ConstantUnit()),
ConstantExpr(ConstantUnit())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ module MethodMembers =
},
ConstantExpr("")
)

Method(
"__.DoSomething",
UnitPat(),
IfThenElseExpr(
InfixAppExpr(ConstantExpr(Constant("x", false)), "=", ConstantExpr(Constant("12", false))),
ConstantExpr(ConstantUnit()),
ConstantExpr(ConstantUnit())
)

)
}
}
|> produces
Expand All @@ -79,6 +90,7 @@ type Colors =
member this.I(p: string) = ""
member this.J(p: string, p2: string) = ""
member this.K (p: string) (p2: string) = ""
member __.DoSomething() = if x = 12 then () else ()

"""

Expand Down
7 changes: 7 additions & 0 deletions src/Fabulous.AST/Widgets/Expressions/Expr.fs
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,10 @@ type ExprYieldExtensions =
let node = Gen.mkOak x
let widget = Ast.EscapeHatch(node).Compile()
{ Widgets = MutStackArray1.One(widget) }

[<Extension>]
static member inline Yield(_: CollectionBuilder<'parent, ModuleDecl>, x: WidgetBuilder<Expr>) : CollectionContent =
let node = Gen.mkOak x
let moduleDecl = ModuleDecl.DeclExpr node
let widget = Ast.EscapeHatch(moduleDecl).Compile()
{ Widgets = MutStackArray1.One(widget) }
111 changes: 40 additions & 71 deletions src/Fabulous.AST/Widgets/Expressions/IfThen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,132 +7,101 @@ open Fabulous.AST.StackAllocatedCollections.StackList
open Fantomas.Core.SyntaxOak

module IfThen =
let IfNode = Attributes.defineScalar<IfKeywordNode> "IfNode"
let IfExpr = Attributes.defineWidget "IfExpr"
let ThenExpr = Attributes.defineWidget "ThenExpr"

let WidgetIfThenKey =
let WidgetKey =
Widgets.register "IfThen" (fun widget ->
let ifNode = Widgets.getScalarValue widget IfNode
let ifExpr = Widgets.getNodeFromWidget<Expr> widget IfExpr
let thenExpr = Widgets.getNodeFromWidget<Expr> widget ThenExpr

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

let WidgetElIfThenKey =
Widgets.register "ElIfThen" (fun widget ->
let ifExpr = Widgets.getNodeFromWidget<Expr> widget IfExpr
let thenExpr = Widgets.getNodeFromWidget<Expr> widget ThenExpr

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

let WidgetElseIfThenKey =
Widgets.register "ElIfThen" (fun widget ->
let elseIfExpr = Widgets.getNodeFromWidget<Expr> widget IfExpr
let thenExpr = Widgets.getNodeFromWidget<Expr> widget ThenExpr

ExprIfThenNode(
IfKeywordNode.ElseIf(ElseIfNode(Range.Zero, Range.Zero, Unchecked.defaultof<Node>, Range.Zero)),
elseIfExpr,
SingleTextNode.``then``,
thenExpr,
Range.Zero
))
Expr.IfThen(ExprIfThenNode(ifNode, ifExpr, SingleTextNode.``then``, thenExpr, Range.Zero)))

[<AutoOpen>]
module IfThenBuilders =
type Ast with

static member inline IfThen(ifExpr: WidgetBuilder<Expr>, thenExpr: WidgetBuilder<Expr>) =
WidgetBuilder<ExprIfThenNode>(
IfThen.WidgetIfThenKey,
static member inline IfThenExpr(ifExpr: WidgetBuilder<Expr>, thenExpr: WidgetBuilder<Expr>) =
WidgetBuilder<Expr>(
IfThen.WidgetKey,
AttributesBundle(
StackList.empty(),
StackList.one(IfThen.IfNode.WithValue(IfKeywordNode.SingleWord(SingleTextNode.``if``))),
ValueSome
[| IfThen.IfExpr.WithValue(ifExpr.Compile())
IfThen.ThenExpr.WithValue(thenExpr.Compile()) |],
ValueNone
)
)

static member inline IfThen(ifExpr: string, thenExpr: string) =
WidgetBuilder<ExprIfThenNode>(
IfThen.WidgetIfThenKey,
static member inline IfThenExpr(ifExpr: string, thenExpr: string) =
WidgetBuilder<Expr>(
IfThen.WidgetKey,
AttributesBundle(
StackList.empty(),
StackList.one(IfThen.IfNode.WithValue(IfKeywordNode.SingleWord(SingleTextNode.``if``))),
ValueSome
[| IfThen.IfExpr.WithValue(Ast.ConstantExpr(ifExpr, false).Compile())
IfThen.ThenExpr.WithValue(Ast.ConstantExpr(thenExpr, false).Compile()) |],
ValueNone
)
)

static member inline ElIfThen(elIfExpr: WidgetBuilder<Expr>, thenExpr: WidgetBuilder<Expr>) =
WidgetBuilder<ExprIfThenNode>(
IfThen.WidgetElIfThenKey,
static member inline ElIfThenExpr(elIfExpr: WidgetBuilder<Expr>, thenExpr: WidgetBuilder<Expr>) =
WidgetBuilder<Expr>(
IfThen.WidgetKey,
AttributesBundle(
StackList.empty(),
StackList.one(IfThen.IfNode.WithValue(IfKeywordNode.SingleWord(SingleTextNode.``elif``))),
ValueSome
[| IfThen.IfExpr.WithValue(elIfExpr.Compile())
IfThen.ThenExpr.WithValue(thenExpr.Compile()) |],
ValueNone
)
)

static member inline ElIfThen(elIfExpr: string, thenExpr: string) =
WidgetBuilder<ExprIfThenNode>(
IfThen.WidgetElIfThenKey,
static member inline ElIfThenExpr(elIfExpr: string, thenExpr: string) =
WidgetBuilder<Expr>(
IfThen.WidgetKey,
AttributesBundle(
StackList.empty(),
StackList.one(IfThen.IfNode.WithValue(IfKeywordNode.SingleWord(SingleTextNode.``elif``))),
ValueSome
[| IfThen.IfExpr.WithValue(Ast.ConstantExpr(elIfExpr, false).Compile())
IfThen.ThenExpr.WithValue(Ast.ConstantExpr(thenExpr, false).Compile()) |],
ValueNone
)
)

static member inline ElseIfThen(elseIfExpr: WidgetBuilder<Expr>, thenExpr: WidgetBuilder<Expr>) =
WidgetBuilder<ExprIfThenNode>(
IfThen.WidgetElseIfThenKey,
static member inline ElseIfThenExpr(elseIfExpr: WidgetBuilder<Expr>, thenExpr: WidgetBuilder<Expr>) =
WidgetBuilder<Expr>(
IfThen.WidgetKey,
AttributesBundle(
StackList.empty(),
StackList.one(
IfThen.IfNode.WithValue(
IfKeywordNode.ElseIf(
ElseIfNode(Range.Zero, Range.Zero, Unchecked.defaultof<Node>, Range.Zero)
)
)
),
ValueSome
[| IfThen.IfExpr.WithValue(elseIfExpr.Compile())
IfThen.ThenExpr.WithValue(thenExpr.Compile()) |],
ValueNone
)
)

static member inline ElseIfThen(elseIfExpr: string, thenExpr: string) =
WidgetBuilder<ExprIfThenNode>(
IfThen.WidgetElseIfThenKey,
static member inline ElseIfThenExpr(elseIfExpr: string, thenExpr: string) =
WidgetBuilder<Expr>(
IfThen.WidgetKey,
AttributesBundle(
StackList.empty(),
StackList.one(
IfThen.IfNode.WithValue(
IfKeywordNode.ElseIf(
ElseIfNode(Range.Zero, Range.Zero, Unchecked.defaultof<Node>, Range.Zero)
)
)
),
ValueSome
[| IfThen.IfExpr.WithValue(Ast.ConstantExpr(elseIfExpr, false).Compile())
IfThen.ThenExpr.WithValue(Ast.ConstantExpr(thenExpr, false).Compile()) |],
ValueNone
)
)

[<Extension>]
type IfThenYieldExtensions =
[<Extension>]
static member inline Yield
(_: CollectionBuilder<'parent, ModuleDecl>, x: WidgetBuilder<ExprIfThenNode>)
: CollectionContent =
let node = Gen.mkOak x
let expIfThen = Expr.IfThen(node)
let moduleDecl = ModuleDecl.DeclExpr expIfThen
let widget = Ast.EscapeHatch(moduleDecl).Compile()
{ Widgets = MutStackArray1.One(widget) }