Skip to content

Commit

Permalink
Merge pull request #70 from edgarfgp/fix-69
Browse files Browse the repository at this point in the history
Unable to return IfThenElse expression from a Method
  • Loading branch information
edgarfgp committed Mar 12, 2024
2 parents e178b2d + b50d095 commit a6c5e60
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 145 deletions.
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) }

0 comments on commit a6c5e60

Please sign in to comment.