Skip to content

Commit 6e188ff

Browse files
committed
feat(compiler)!: Partial function application
1 parent dac76f2 commit 6e188ff

File tree

14 files changed

+869
-178
lines changed

14 files changed

+869
-178
lines changed

compiler/src/formatting/fmt.re

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ type formatter = {
289289
print_attribute: (formatter, attribute) => Doc.t,
290290
print_application_argument:
291291
(formatter, ~infix_wrap: t => t=?, application_argument) => Doc.t,
292+
print_partial_application_argument:
293+
(formatter, ~infix_wrap: t => t=?, partial_application_argument) => Doc.t,
292294
print_if:
293295
(
294296
formatter,
@@ -1157,6 +1159,32 @@ let print_application_argument = (fmt, ~infix_wrap=?, arg) => {
11571159
++ fmt.print_expression(fmt, ~infix_wrap?, arg.paa_expr);
11581160
};
11591161

1162+
let print_partial_application_argument = (fmt, ~infix_wrap=?, arg) => {
1163+
(
1164+
switch (arg.ppaa_label) {
1165+
| Unlabeled => empty
1166+
| Labeled({txt: label, loc: label_loc})
1167+
| Default({txt: label, loc: label_loc}) =>
1168+
string(label)
1169+
++ string("=")
1170+
++ fmt.print_comment_range(
1171+
fmt,
1172+
label_loc,
1173+
switch (arg.ppaa_expr) {
1174+
| ArgumentGiven(expr) => expr.pexp_loc
1175+
| ArgumentHole(loc) => loc
1176+
},
1177+
)
1178+
}
1179+
)
1180+
++ (
1181+
switch (arg.ppaa_expr) {
1182+
| ArgumentGiven(expr) => fmt.print_expression(fmt, ~infix_wrap?, expr)
1183+
| ArgumentHole(_) => string("_")
1184+
}
1185+
);
1186+
};
1187+
11601188
let print_if =
11611189
(fmt, ~force_blocks=false, ~loc, condition, true_branch, false_branch) =>
11621190
if (force_blocks) {
@@ -1743,6 +1771,69 @@ let print_expression = (fmt, ~infix_wrap=d => group(indent(d)), expr) => {
17431771
++ break,
17441772
),
17451773
)
1774+
| PExpPartial(fn, args) =>
1775+
string("partial")
1776+
++ fmt.print_comment_range(
1777+
fmt,
1778+
~allow_breaks=false,
1779+
~none=space,
1780+
~lead=space,
1781+
~trail=space,
1782+
enclosing_start_location(expr.pexp_loc),
1783+
fn.pexp_loc,
1784+
)
1785+
++ group(
1786+
fmt.print_grouped_access_expression(fmt, fn)
1787+
++ parens(
1788+
indent(
1789+
concat_map(
1790+
~lead=
1791+
next =>
1792+
fmt.print_comment_range(
1793+
fmt,
1794+
~none=break,
1795+
~lead=if_broken(space, empty),
1796+
~trail=breakable_space,
1797+
fn.pexp_loc,
1798+
next.ppaa_loc,
1799+
),
1800+
~sep=
1801+
(prev, next) =>
1802+
fmt.print_comment_range(
1803+
fmt,
1804+
~none=breakable_space,
1805+
~lead=space,
1806+
~trail=breakable_space,
1807+
prev.ppaa_loc,
1808+
next.ppaa_loc,
1809+
),
1810+
~trail=
1811+
prev =>
1812+
fmt.print_comment_range(
1813+
fmt,
1814+
~block_end=true,
1815+
~lead=space,
1816+
prev.ppaa_loc,
1817+
enclosing_end_location(expr.pexp_loc),
1818+
),
1819+
~f=
1820+
(~final, a) =>
1821+
if (final) {
1822+
group(
1823+
fmt.print_partial_application_argument(fmt, a),
1824+
);
1825+
} else {
1826+
group(
1827+
fmt.print_partial_application_argument(fmt, a)
1828+
++ comma,
1829+
);
1830+
},
1831+
args,
1832+
),
1833+
)
1834+
++ break,
1835+
),
1836+
)
17461837
| PExpLambda(
17471838
[
17481839
{
@@ -4119,6 +4210,7 @@ let default_formatter: formatter = {
41194210
print_match_branch,
41204211
print_attribute,
41214212
print_application_argument,
4213+
print_partial_application_argument,
41224214
print_if,
41234215
print_assignment,
41244216
print_expression,

compiler/src/parsing/ast_helper.re

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,31 @@ module Expression = {
319319
mk(~loc, ~core_loc, ~attributes?, PExpLambda(a, b));
320320
let apply = (~loc, ~core_loc, ~attributes=?, a, b) =>
321321
mk(~loc, ~core_loc, ~attributes?, PExpApp(a, b));
322+
let partial_apply = (~loc, ~core_loc, ~attributes=?, a, b) =>
323+
mk(~loc, ~core_loc, ~attributes?, PExpPartial(a, b));
324+
let total_apply_args = (~loc, ~core_loc, ~attributes=?, a, b) => {
325+
let args =
326+
List.map(
327+
arg =>
328+
{
329+
paa_loc: arg.ppaa_loc,
330+
paa_expr:
331+
switch (arg.ppaa_expr) {
332+
| ArgumentGiven(expr) => expr
333+
| ArgumentHole(_) =>
334+
raise(
335+
SyntaxError(
336+
loc,
337+
"To use partial application, prefix the function call with `partial`.",
338+
),
339+
)
340+
},
341+
paa_label: arg.ppaa_label,
342+
},
343+
b,
344+
);
345+
mk(~loc, ~core_loc, ~attributes?, PExpApp(a, args));
346+
};
322347
let construct = (~loc, ~core_loc, ~attributes=?, a, b) =>
323348
mk(~loc, ~core_loc, ~attributes?, PExpConstruct(a, b));
324349
let singleton_construct = (~loc, ~core_loc, ~attributes=?, a) =>

compiler/src/parsing/ast_helper.rei

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,24 @@ module Expression: {
374374
list(application_argument)
375375
) =>
376376
expression;
377+
let partial_apply:
378+
(
379+
~loc: loc,
380+
~core_loc: loc,
381+
~attributes: attributes=?,
382+
expression,
383+
list(partial_application_argument)
384+
) =>
385+
expression;
386+
let total_apply_args:
387+
(
388+
~loc: loc,
389+
~core_loc: loc,
390+
~attributes: attributes=?,
391+
expression,
392+
list(partial_application_argument)
393+
) =>
394+
expression;
377395
let construct:
378396
(
379397
~loc: loc,

compiler/src/parsing/ast_mapper.re

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,26 @@ module E = {
252252
el,
253253
),
254254
)
255+
| PExpPartial(e, el) =>
256+
partial_apply(
257+
~loc,
258+
~core_loc,
259+
~attributes,
260+
sub.expr(sub, e),
261+
List.map(
262+
arg =>
263+
{
264+
ppaa_label: arg.ppaa_label,
265+
ppaa_expr:
266+
switch (arg.ppaa_expr) {
267+
| ArgumentGiven(expr) => ArgumentGiven(sub.expr(sub, expr))
268+
| ArgumentHole(loc) => ArgumentHole(sub.location(sub, loc))
269+
},
270+
ppaa_loc: sub.location(sub, arg.ppaa_loc),
271+
},
272+
el,
273+
),
274+
)
255275
| PExpConstruct(id, e) =>
256276
construct(
257277
~loc,

compiler/src/parsing/lexer.re

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ let rec token = lexbuf => {
291291
| "catch" => positioned(CATCH)
292292
| "macro" => positioned(MACRO)
293293
| "yield" => positioned(YIELD)
294+
| "partial" => positioned(PARTIAL)
294295
| "..." => positioned(ELLIPSIS)
295296
| "." => positioned(DOT)
296297
| "::" => positioned(COLONCOLON)

compiler/src/parsing/parser.messages

Lines changed: 133 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,26 @@ program: MODULE UIDENT EOL EOL WASMI64 THICKARROW
11331133
## In state 826, spurious reduction of production toplevel_stmt -> expr
11341134
## In state 819, spurious reduction of production lseparated_nonempty_list_inner(eos,toplevel_stmt) -> toplevel_stmt
11351135
##
1136+
program: MODULE UIDENT EOL PARTIAL LIDENT LPAREN RPAREN YIELD
1137+
##
1138+
## Ends in an error in state: 743.
1139+
##
1140+
## app_expr -> left_accessor_expr lparen option(comma) rparen . [ LPAREN LBRACK DOT ]
1141+
## partial_app_expr -> PARTIAL left_accessor_expr lparen option(comma) rparen . [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
1142+
##
1143+
## The known suffix of the stack is as follows:
1144+
## PARTIAL left_accessor_expr lparen option(comma) rparen
1145+
##
1146+
program: MODULE UIDENT EOL PARTIAL LIDENT LPAREN UIDENT RPAREN YIELD
1147+
##
1148+
## Ends in an error in state: 746.
1149+
##
1150+
## app_expr -> left_accessor_expr lparen lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen . [ LPAREN LBRACK DOT ]
1151+
## partial_app_expr -> PARTIAL left_accessor_expr lparen lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen . [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
1152+
##
1153+
## The known suffix of the stack is as follows:
1154+
## PARTIAL left_accessor_expr lparen lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen
1155+
##
11361156

11371157
Expected a newline character to terminate the statement.
11381158

@@ -1840,6 +1860,16 @@ program: MODULE UIDENT EOL WHILE LPAREN UIDENT RPAREN EOL YIELD
18401860
## In state 1, spurious reduction of production nonempty_list(eol) -> EOL
18411861
## In state 5, spurious reduction of production eols -> nonempty_list(eol)
18421862
##
1863+
program: MODULE UIDENT EOL PARTIAL YIELD
1864+
##
1865+
## Ends in an error in state: 124.
1866+
##
1867+
## partial_app_expr -> PARTIAL . left_accessor_expr lparen option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
1868+
## partial_app_expr -> PARTIAL . left_accessor_expr lparen lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
1869+
##
1870+
## The known suffix of the stack is as follows:
1871+
## PARTIAL
1872+
##
18431873

18441874
Expected an expression.
18451875

@@ -3504,6 +3534,102 @@ program: MODULE UIDENT EOL IF WHILE
35043534

35053535
Expected `(` followed by a condition expression.
35063536

3537+
program: MODULE UIDENT EOL PARTIAL UIDENT YIELD
3538+
##
3539+
## Ends in an error in state: 740.
3540+
##
3541+
## app_expr -> left_accessor_expr . lparen option(comma) rparen [ LPAREN LBRACK DOT ]
3542+
## app_expr -> left_accessor_expr . lparen lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen [ LPAREN LBRACK DOT ]
3543+
## array_get -> left_accessor_expr . lbrack expr rbrack [ LPAREN LBRACK DOT ]
3544+
## partial_app_expr -> PARTIAL left_accessor_expr . lparen option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
3545+
## partial_app_expr -> PARTIAL left_accessor_expr . lparen lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
3546+
## record_get -> left_accessor_expr . DOT lid [ LPAREN LBRACK DOT ]
3547+
## record_get -> left_accessor_expr . DOT eols lid [ LPAREN LBRACK DOT ]
3548+
##
3549+
## The known suffix of the stack is as follows:
3550+
## PARTIAL left_accessor_expr
3551+
##
3552+
## WARNING: This example involves spurious reductions.
3553+
## This implies that, although the LR(1) items shown above provide an
3554+
## accurate view of the past (what has been recognized so far), they
3555+
## may provide an INCOMPLETE view of the future (what was expected next).
3556+
## In state 265, spurious reduction of production qualified_uid -> lseparated_nonempty_list_inner(dot,type_id_str)
3557+
## In state 162, spurious reduction of production construct_expr -> qualified_uid
3558+
## In state 312, spurious reduction of production left_accessor_expr -> construct_expr
3559+
##
3560+
3561+
Expected `(` followed by partial application arguments.
3562+
3563+
program: MODULE UIDENT EOL PARTIAL LIDENT LPAREN YIELD
3564+
##
3565+
## Ends in an error in state: 741.
3566+
##
3567+
## app_expr -> left_accessor_expr lparen . option(comma) rparen [ LPAREN LBRACK DOT ]
3568+
## app_expr -> left_accessor_expr lparen . lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen [ LPAREN LBRACK DOT ]
3569+
## partial_app_expr -> PARTIAL left_accessor_expr lparen . option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
3570+
## partial_app_expr -> PARTIAL left_accessor_expr lparen . lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
3571+
##
3572+
## The known suffix of the stack is as follows:
3573+
## PARTIAL left_accessor_expr lparen
3574+
##
3575+
## WARNING: This example involves spurious reductions.
3576+
## This implies that, although the LR(1) items shown above provide an
3577+
## accurate view of the past (what has been recognized so far), they
3578+
## may provide an INCOMPLETE view of the future (what was expected next).
3579+
## In state 4, spurious reduction of production lparen -> LPAREN
3580+
##
3581+
3582+
Expected an expression or `_`.
3583+
3584+
program: MODULE UIDENT EOL PARTIAL LIDENT LPAREN COMMA YIELD
3585+
##
3586+
## Ends in an error in state: 742.
3587+
##
3588+
## app_expr -> left_accessor_expr lparen option(comma) . rparen [ LPAREN LBRACK DOT ]
3589+
## partial_app_expr -> PARTIAL left_accessor_expr lparen option(comma) . rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
3590+
##
3591+
## The known suffix of the stack is as follows:
3592+
## PARTIAL left_accessor_expr lparen option(comma)
3593+
##
3594+
## WARNING: This example involves spurious reductions.
3595+
## This implies that, although the LR(1) items shown above provide an
3596+
## accurate view of the past (what has been recognized so far), they
3597+
## may provide an INCOMPLETE view of the future (what was expected next).
3598+
## In state 39, spurious reduction of production comma -> COMMA
3599+
## In state 516, spurious reduction of production option(comma) -> comma
3600+
##
3601+
3602+
Expected a comma-separated list of partial application arguments or `)` to complete the partial application.
3603+
3604+
program: MODULE UIDENT EOL PARTIAL LIDENT LPAREN UIDENT YIELD
3605+
##
3606+
## Ends in an error in state: 744.
3607+
##
3608+
## app_expr -> left_accessor_expr lparen lseparated_nonempty_list_inner(comma,app_arg) . option(comma) rparen [ LPAREN LBRACK DOT ]
3609+
## lseparated_nonempty_list_inner(comma,app_arg) -> lseparated_nonempty_list_inner(comma,app_arg) . comma app_arg [ RPAREN EOL COMMA ]
3610+
## partial_app_expr -> PARTIAL left_accessor_expr lparen lseparated_nonempty_list_inner(comma,app_arg) . option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LCARET INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 EOL EOF ELSE DASH COMMA COLON AND ]
3611+
##
3612+
## The known suffix of the stack is as follows:
3613+
## PARTIAL left_accessor_expr lparen lseparated_nonempty_list_inner(comma,app_arg)
3614+
##
3615+
## WARNING: This example involves spurious reductions.
3616+
## This implies that, although the LR(1) items shown above provide an
3617+
## accurate view of the past (what has been recognized so far), they
3618+
## may provide an INCOMPLETE view of the future (what was expected next).
3619+
## In state 265, spurious reduction of production qualified_uid -> lseparated_nonempty_list_inner(dot,type_id_str)
3620+
## In state 162, spurious reduction of production construct_expr -> qualified_uid
3621+
## In state 312, spurious reduction of production left_accessor_expr -> construct_expr
3622+
## In state 287, spurious reduction of production non_assign_expr -> left_accessor_expr
3623+
## In state 263, spurious reduction of production non_binop_expr -> non_assign_expr
3624+
## In state 194, spurious reduction of production annotated_expr -> non_binop_expr
3625+
## In state 321, spurious reduction of production non_stmt_expr -> annotated_expr
3626+
## In state 187, spurious reduction of production expr -> non_stmt_expr
3627+
## In state 514, spurious reduction of production app_arg -> expr
3628+
## In state 517, spurious reduction of production lseparated_nonempty_list_inner(comma,app_arg) -> app_arg
3629+
##
3630+
3631+
Expected a comma or `)` to complete the partial application.
3632+
35073633
program: MODULE UIDENT EOL FOREIGN WASM LIDENT COLON UIDENT FROM YIELD
35083634
##
35093635
## Ends in an error in state: 753.
@@ -6617,21 +6743,22 @@ program: MODULE UIDENT EOL WASMI64 COLON UIDENT LCARET UIDENT RPAREN
66176743

66186744
Expected `>` to complete the type.
66196745

6620-
program: MODULE UIDENT EOL WASMI64 DOT LIDENT LPAREN UNDERSCORE
6746+
program: MODULE UIDENT EOL BIGINT LPAREN YIELD
66216747
##
6622-
## Ends in an error in state: 468.
6748+
## Ends in an error in state: 279.
66236749
##
6624-
## app_expr -> record_get lparen . option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LPAREN LCARET LBRACK INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 GETS EOL EOF ELSE DOT DASH COMMA COLON ]
6625-
## app_expr -> record_get lparen . lseparated_nonempty_list_inner(comma,expr) option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LPAREN LCARET LBRACK INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 GETS EOL EOF ELSE DOT DASH COMMA COLON ]
6750+
## app_expr -> left_accessor_expr lparen . option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LPAREN LCARET LBRACK INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 GETS EOL EOF ELSE DOT DASH COMMA COLON AND ]
6751+
## app_expr -> left_accessor_expr lparen . lseparated_nonempty_list_inner(comma,app_arg) option(comma) rparen [ THICKARROW STAR SLASH SEMI RPAREN RCARET RBRACK RBRACE PIPE LPAREN LCARET LBRACK INFIX_90 INFIX_80 INFIX_70 INFIX_60 INFIX_50 INFIX_40 INFIX_30 INFIX_120 INFIX_110 INFIX_100 GETS EOL EOF ELSE DOT DASH COMMA COLON AND ]
66266752
##
66276753
## The known suffix of the stack is as follows:
6628-
## record_get lparen
6754+
## left_accessor_expr lparen
66296755
##
66306756
## WARNING: This example involves spurious reductions.
66316757
## This implies that, although the LR(1) items shown above provide an
66326758
## accurate view of the past (what has been recognized so far), they
66336759
## may provide an INCOMPLETE view of the future (what was expected next).
6634-
## In state 2, spurious reduction of production lparen -> LPAREN
6760+
## In state 1, spurious reduction of production nonempty_list(eol) -> EOL
6761+
## In state 5, spurious reduction of production eols -> nonempty_list(eol)
66356762
##
66366763
program: MODULE UIDENT EOL LBRACKRCARET RBRACK LPAREN COMMA WHILE
66376764
##

0 commit comments

Comments
 (0)