diff --git a/muscript/src/main/java/io/gitlab/jfronny/muscript/compiler/Parser.java b/muscript/src/main/java/io/gitlab/jfronny/muscript/compiler/Parser.java index a045c33..0e29654 100644 --- a/muscript/src/main/java/io/gitlab/jfronny/muscript/compiler/Parser.java +++ b/muscript/src/main/java/io/gitlab/jfronny/muscript/compiler/Parser.java @@ -242,8 +242,14 @@ public class Parser { yield new Get(start, end, asDynamic(expr), Expr.literal(name.start, name.current - 1, name.lexeme)); } case DoubleColon -> { - TokenData name = consume(Token.Identifier, "Expected variable name after '::'."); - yield new Bind(start, end, new Variable(name.start, name.current - 1, name.lexeme), expr.asDynamicExpr()); + DynamicExpr callable; + if (match(Token.Identifier)) { + callable = new Variable(previous.start, previous.current - 1, previous.lexeme); + } else if (match(Token.LeftParen)) { + callable = expression().asDynamicExpr(); + consume(Token.RightParen, "Expected ')' after expression."); + } else throw error("Bind operator requires right side to be a literal identifier or to be wrapped in parentheses."); + yield new Bind(start, end, callable, expr.asDynamicExpr()); } case LeftBracket -> { expr = new Get(start, end, asDynamic(expr), expression()); diff --git a/muscript/src/test/java/io/gitlab/jfronny/muscript/test/BindTest.java b/muscript/src/test/java/io/gitlab/jfronny/muscript/test/BindTest.java index 0700a67..90ca5aa 100644 --- a/muscript/src/test/java/io/gitlab/jfronny/muscript/test/BindTest.java +++ b/muscript/src/test/java/io/gitlab/jfronny/muscript/test/BindTest.java @@ -21,4 +21,18 @@ class BindTest { numbers::map({n->n::function(2)})::filter({n->n%2!=0}) """).asExpr().asStringExpr().get(makeArgs())); } + + @Test + void complexBind() { + // fn = {b -> 2 * b} + assertEquals(6, Parser.parseScript(""" + fn = 2::({a, b -> a * b}) + fn(3) + """).asExpr().asNumberExpr().get(makeArgs())); + // {a, b, c -> a(b(c))}(fn, {a -> a + 5}, 3) + assertEquals(16, Parser.parseScript(""" + fn = 2::({a, b -> a * b}) + fn::({a, b, c -> a(b(c))})({a -> a + 5}, 3) + """).asExpr().asNumberExpr().get(makeArgs())); + } }