@@ -538,15 +538,21 @@ const Expr *parse_var_ref(ParseState &ps) {
538
538
return var_ref;
539
539
} else {
540
540
/* we know that this was declared as a "var", so let's just automatically
541
- * load it for the user. if they want to treat is as a ref, then they need
542
- * to preface it with & */
543
- return new Application ( new Var (Identifier{tld::mktld (" std" , " load_value" ), id.location }),
544
- {var_ref});
541
+ * load it for the user. */
542
+ return new Application (
543
+ new Var (Identifier{tld::mktld (" std" , " load_value" ), id.location }),
544
+ {var_ref});
545
545
}
546
546
}
547
547
548
548
const Expr *parse_base_expr (ParseState &ps) {
549
- if (ps.token .tk == tk_lparen) {
549
+ if (ps.token .tk == tk_dot) {
550
+ auto iid = gensym (ps.token .location );
551
+ return new Lambda (
552
+ {iid}, {type_variable (ps.token .location )},
553
+ type_variable (ps.token .location ),
554
+ new ReturnStatement (parse_postfix_chain (ps, new Var (iid))));
555
+ } else if (ps.token .tk == tk_lparen) {
550
556
return parse_tuple_expr (ps);
551
557
} else if (ps.token .is_ident (K (new ))) {
552
558
return parse_new_expr (ps);
@@ -1099,51 +1105,57 @@ const Expr *parse_literal(ParseState &ps) {
1099
1105
}
1100
1106
}
1101
1107
1102
- const Expr *parse_postfix_expr (ParseState &ps) {
1103
- const Expr *expr = parse_base_expr (ps);
1108
+ const Expr *parse_application (ParseState &ps,
1109
+ const Expr *expr,
1110
+ std::vector<const Expr *> args) {
1111
+ /* function call or implicit partial application (implicit lambda) */
1112
+ auto location = ps.token .location ;
1113
+ ps.advance ();
1114
+ if (ps.token .tk == tk_rparen) {
1115
+ ps.advance ();
1116
+ if (args.size () == 0 ) {
1117
+ args.push_back (unit_expr (ps.token .location ));
1118
+ }
1119
+ return new Application (expr, args);
1120
+ } else {
1121
+ while (ps.token .tk != tk_rparen) {
1122
+ args.push_back (parse_expr (ps, true /* allow_for_comprehensions*/ ));
1123
+ if (ps.token .tk == tk_comma) {
1124
+ ps.advance ();
1125
+ } else {
1126
+ expect_token (tk_rparen);
1127
+ }
1128
+ }
1129
+ expr = new Application (expr, args);
1104
1130
1105
- while (!ps.line_broke () &&
1106
- (ps.token .tk == tk_lsquare || ps.token .tk == tk_lparen ||
1107
- ps.token .tk == tk_dot || ps.token .tk == tk_bang)) {
1131
+ chomp_token (tk_rparen);
1132
+ }
1133
+ return expr;
1134
+ }
1135
+
1136
+ const Expr *parse_postfix_chain (ParseState &ps, const Expr *expr) {
1137
+ while (ps.token .tk == tk_dot ||
1138
+ (!ps.line_broke () &&
1139
+ (ps.token .tk == tk_lsquare || ps.token .tk == tk_lparen ||
1140
+ ps.token .tk == tk_bang))) {
1108
1141
switch (ps.token .tk ) {
1109
1142
case tk_bang:
1110
1143
expr = new As (expr, type_unit (ps.token_and_advance ().location ),
1111
1144
true /* force_cast*/ );
1112
1145
break ;
1113
1146
case tk_lparen: {
1114
- /* function call or implicit partial application (implicit lambda) */
1115
- auto location = ps.token .location ;
1116
- ps.advance ();
1117
- if (ps.token .tk == tk_rparen) {
1118
- ps.advance ();
1119
- expr = new Application (expr, {unit_expr (ps.token .location )});
1120
- } else {
1121
- std::vector<const Expr *> callsite_refs;
1122
- for (int index = 0 ; ps.token .tk != tk_rparen; ++index ) {
1123
- callsite_refs.push_back (
1124
- parse_expr (ps, true /* allow_for_comprehensions*/ ));
1125
- if (ps.token .tk == tk_comma) {
1126
- ps.advance ();
1127
- } else {
1128
- expect_token (tk_rparen);
1129
- }
1130
- }
1131
- expr = new Application (expr, {callsite_refs});
1132
-
1133
- chomp_token (tk_rparen);
1134
- }
1147
+ expr = parse_application (ps, expr, {});
1135
1148
break ;
1136
1149
}
1137
1150
case tk_dot: {
1138
1151
ps.advance ();
1139
1152
expect_token (tk_identifier);
1140
- if (!islower (ps.token .text [0 ])) {
1141
- throw user_error (
1142
- ps.token .location ,
1143
- " property accessors must start with lowercase letters" );
1153
+ auto iid = tld::tld (ps.identifier_and_advance ());
1154
+ if (!ps.line_broke () && ps.token .tk == tk_lparen) {
1155
+ expr = parse_application (ps, new Var (iid), {expr});
1156
+ } else {
1157
+ expr = new Application (new Var (iid), {expr});
1144
1158
}
1145
- auto iid = ps.identifier_and_advance ();
1146
- expr = new Application (new Var (iid), {expr});
1147
1159
break ;
1148
1160
}
1149
1161
case tk_lsquare: {
@@ -1169,13 +1181,15 @@ const Expr *parse_postfix_expr(ParseState &ps) {
1169
1181
auto location = ps.token_and_advance ().location ;
1170
1182
auto rhs = parse_expr (ps, false /* allow_for_comprehensions*/ );
1171
1183
expr = new Application (
1172
- new Var (Identifier{tld::mktld (" std" , " set_indexed_item" ), location}),
1184
+ new Var (
1185
+ Identifier{tld::mktld (" std" , " set_indexed_item" ), location}),
1173
1186
{expr, start, rhs});
1174
1187
} else {
1175
1188
expr = new Application (
1176
- new Var (Identifier{tld::mktld (" std" , is_slice ? " get_slice_from"
1177
- : " get_indexed_item" ),
1178
- ps.token .location }),
1189
+ new Var (
1190
+ Identifier{tld::mktld (" std" , is_slice ? " get_slice_from"
1191
+ : " get_indexed_item" ),
1192
+ ps.token .location }),
1179
1193
{expr, start});
1180
1194
}
1181
1195
} else {
@@ -1184,8 +1198,8 @@ const Expr *parse_postfix_expr(ParseState &ps) {
1184
1198
1185
1199
assert (is_slice);
1186
1200
expr = new Application (
1187
- new Var (ps.id_mapped (
1188
- Identifier{ tld::mktld (" std" , " get_slice_from_to" ), ps.token .location })),
1201
+ new Var (ps.id_mapped (Identifier{
1202
+ tld::mktld (" std" , " get_slice_from_to" ), ps.token .location })),
1189
1203
{expr, start, stop});
1190
1204
}
1191
1205
break ;
@@ -1198,6 +1212,12 @@ const Expr *parse_postfix_expr(ParseState &ps) {
1198
1212
return expr;
1199
1213
}
1200
1214
1215
+ const Expr *parse_postfix_expr (ParseState &ps) {
1216
+ const Expr *expr = parse_base_expr (ps);
1217
+
1218
+ return parse_postfix_chain (ps, expr);
1219
+ }
1220
+
1201
1221
const Expr *parse_cast_expr (ParseState &ps) {
1202
1222
const Expr *expr = parse_postfix_expr (ps);
1203
1223
while (!ps.line_broke () && ps.token .is_ident (K (as))) {
0 commit comments