@@ -1244,6 +1244,87 @@ fn check_pat(&@fn_ctxt fcx, @ast.pat pat) -> @ast.pat {
1244
1244
}
1245
1245
1246
1246
fn check_expr( & @fn_ctxt fcx , @ast . expr expr) -> @ast . expr {
1247
+ // A generic function to factor out common logic from call and bind
1248
+ // expressions.
1249
+ fn check_call_or_bind( & @fn_ctxt fcx , & @ast. expr f ,
1250
+ & vec[ option. t[ @ast. expr] ] args )
1251
+ -> tup ( @ast . expr, vec[ option. t[ @ast. expr] ] ) {
1252
+
1253
+ // Check the function.
1254
+ auto f_0 = check_expr ( fcx, f) ;
1255
+
1256
+ // Check the arguments and generate the argument signature.
1257
+ let vec[ option. t [ @ast. expr ] ] args_0 = vec ( ) ;
1258
+ let vec[ arg] arg_tys_0 = vec ( ) ;
1259
+ for ( option. t[ @ast. expr] a_opt in args) {
1260
+ alt ( a_opt) {
1261
+ case ( some[ @ast. expr] ( ?a) ) {
1262
+ auto a_0 = check_expr( fcx, a) ;
1263
+ args_0 += vec( some[ @ast. expr] ( a_0) ) ;
1264
+
1265
+ // FIXME: this breaks aliases. We need a ty_fn_arg.
1266
+ auto arg_ty = rec( mode=ast. val, ty=expr_ty( a_0) ) ;
1267
+ append[ arg] ( arg_tys_0, arg_ty) ;
1268
+ }
1269
+ case ( none[ @ast. expr] ) {
1270
+ args_0 += vec( none[ @ast. expr] ) ;
1271
+
1272
+ // FIXME: breaks aliases too?
1273
+ auto typ = next_ty_var( fcx. ccx) ;
1274
+ append[ arg] ( arg_tys_0, rec( mode=ast. val, ty=typ) ) ;
1275
+ }
1276
+ }
1277
+ }
1278
+
1279
+ auto proto_0 = ast. proto_fn; // FIXME: typestate botch
1280
+ alt ( expr_ty( f_0) . struct ) {
1281
+ case ( ty. ty_fn( ?proto, _, _) ) { proto_0 = proto; }
1282
+ case ( _) {
1283
+ log "check_call_or_bind(): fn expr doesn't have fn type" ;
1284
+ fail;
1285
+ }
1286
+ }
1287
+
1288
+ auto rt_0 = next_ty_var( fcx. ccx) ;
1289
+ auto t_0 = plain_ty( ty. ty_fn( proto_0, arg_tys_0, rt_0) ) ;
1290
+
1291
+ // Unify and write back to the function.
1292
+ auto f_1 = demand_expr( fcx, t_0, f_0) ;
1293
+
1294
+ // Take the argument types out of the resulting function type.
1295
+ auto t_1 = expr_ty( f_1) ;
1296
+
1297
+ if ( !ty. is_fn_ty( t_1) ) {
1298
+ fcx. ccx. sess. span_err( f_1. span,
1299
+ "mismatched types: callee has " +
1300
+ "non-function type: " +
1301
+ ty_to_str( t_1) ) ;
1302
+ }
1303
+
1304
+ let vec[ arg] arg_tys_1 = ty. ty_fn_args( t_1) ;
1305
+ let @ty. t rt_1 = ty. ty_fn_ret( t_1) ;
1306
+
1307
+ // Unify and write back to the arguments.
1308
+ auto i = 0 u;
1309
+ let vec[ option. t[ @ast. expr] ] args_1 = vec( ) ;
1310
+ while ( i < _vec. len[ option . t[ @ast. expr] ] ( args_0 ) ) {
1311
+ alt ( args_0. ( i) ) {
1312
+ case ( some[ @ast. expr ] ( ?e_0) ) {
1313
+ auto arg_ty_1 = arg_tys_1. ( i) ;
1314
+ auto e_1 = demand_expr ( fcx, arg_ty_1. ty , e_0) ;
1315
+ append[ option. t [ @ast. expr ] ] ( args_1, some[ @ast. expr ] ( e_1) ) ;
1316
+ }
1317
+ case ( none[ @ast. expr ] ) {
1318
+ append[ option. t [ @ast. expr ] ] ( args_1, none[ @ast. expr ] ) ;
1319
+ }
1320
+ }
1321
+
1322
+ i += 1 u;
1323
+ }
1324
+
1325
+ ret tup ( f_1, args_1) ;
1326
+ }
1327
+
1247
1328
alt ( expr. node ) {
1248
1329
case ( ast. expr_lit ( ?lit, _) ) {
1249
1330
auto ty = check_lit ( lit) ;
@@ -1658,62 +1739,40 @@ fn check_expr(&@fn_ctxt fcx, @ast.expr expr) -> @ast.expr {
1658
1739
i += 1 u;
1659
1740
}
1660
1741
1661
- let @ty. t t_1 = plain_ty( ty. ty_fn( proto,
1662
- residual_args , rt_0 ) ) ;
1742
+ let @ty. t t_1 = plain_ty( ty. ty_fn( proto, residual_args , rt_0 ) ) ;
1743
+
1663
1744
ret @fold. respan[ ast. expr_] ( expr. span,
1664
1745
ast. expr_bind( f_0, args_1,
1665
1746
ast. ann_type( t_1) ) ) ;
1666
-
1667
1747
}
1668
1748
1669
1749
case ( ast. expr_call ( ?f , ?args , _) ) {
1670
-
1671
- // Check the function.
1672
- auto f_0 = check_expr( fcx, f) ;
1673
-
1674
- // Check the arguments and generate the argument signature.
1675
- let vec[ @ast. expr] args_0 = vec( ) ;
1676
- let vec[ arg] arg_tys_0 = vec( ) ;
1677
- for ( @ast. expr a in args) {
1678
- auto a_0 = check_expr( fcx, a) ;
1679
- append[ @ast. expr] ( args_0, a_0) ;
1680
-
1681
- // FIXME: this breaks aliases. We need a ty_fn_arg.
1682
- append[ arg] ( arg_tys_0, rec( mode=ast. val, ty=expr_ty( a_0) ) ) ;
1750
+ let vec[ option. t[ @ast. expr] ] args_opt_0 = vec( ) ;
1751
+ for ( @ast. expr arg in args) {
1752
+ args_opt_0 += vec( some[ @ast. expr] ( arg) ) ;
1683
1753
}
1684
- auto rt_0 = next_ty_var( fcx. ccx) ;
1685
- auto t_0 = plain_ty( ty. ty_fn( ty. ty_fn_proto( expr_ty( f_0) ) ,
1686
- arg_tys_0, rt_0) ) ;
1687
-
1688
- // Unify and write back to the function.
1689
- auto f_1 = demand_expr( fcx, t_0, f_0) ;
1690
1754
1691
- // Take the argument types out of the resulting function type .
1692
- auto t_1 = expr_ty ( f_1 ) ;
1755
+ // Call the generic checker .
1756
+ auto result = check_call_or_bind ( fcx , f , args_opt_0 ) ;
1693
1757
1694
- if ( !ty. is_fn_ty( t_1) ) {
1695
- fcx. ccx. sess. span_err( f_1. span,
1696
- "mismatched types: callee has " +
1697
- "non-function type: " +
1698
- ty_to_str( t_1) ) ;
1699
- }
1700
-
1701
- let vec[ arg] arg_tys_1 = ty. ty_fn_args( t_1) ;
1702
- let @ty. t rt_1 = ty. ty_fn_ret( t_1) ;
1703
-
1704
- // Unify and write back to the arguments.
1705
- auto i = 0 u;
1758
+ // Pull out the arguments.
1706
1759
let vec[ @ast. expr] args_1 = vec( ) ;
1707
- while ( i < _vec . len[ @ast. expr] ( args_0 ) ) {
1708
- auto arg_ty_1 = arg_tys_1. ( i) ;
1709
- auto e = demand_expr ( fcx, arg_ty_1. ty , args_0. ( i) ) ;
1710
- append[ @ast. expr ] ( args_1, e) ;
1760
+ for ( option. t[ @ast. expr] arg in result. _1) {
1761
+ args_1 += vec( option. get[ @ast. expr] ( arg) ) ;
1762
+ }
1711
1763
1712
- i += 1 u;
1764
+ // Pull the return type out of the type of the function.
1765
+ auto rt_1 = plain_ty( ty. ty_nil) ; // FIXME: typestate botch
1766
+ alt ( expr_ty( result. _0) . struct ) {
1767
+ case ( ty. ty_fn( _, _, ?rt) ) { rt_1 = rt; }
1768
+ case ( _) {
1769
+ log "LHS of call expr didn' t have a function type ?!";
1770
+ fail;
1771
+ }
1713
1772
}
1714
1773
1715
1774
ret @fold. respan[ ast. expr_] ( expr. span,
1716
- ast. expr_call ( f_1 , args_1,
1775
+ ast. expr_call( result . _0 , args_1,
1717
1776
ast. ann_type( rt_1) ) ) ;
1718
1777
}
1719
1778
0 commit comments