@@ -88,6 +88,7 @@ state type fn_ctxt = rec(ValueRef llfn,
88
88
ValueRef llenv,
89
89
ValueRef llretptr,
90
90
mutable option. t[ ValueRef ] llself ,
91
+ mutable option. t[ ValueRef ] lliterbody ,
91
92
hashmap[ ast. def_id, ValueRef ] llargs ,
92
93
hashmap[ ast. def_id, ValueRef ] llobjfields ,
93
94
hashmap[ ast. def_id, ValueRef ] lllocals ,
@@ -399,6 +400,8 @@ fn type_of_explicit_args(@crate_ctxt cx,
399
400
// - trans_args
400
401
401
402
fn type_of_fn_full ( @crate_ctxt cx ,
403
+ // FIXME: change bool flag to tag
404
+ bool is_iter ,
402
405
option. t[ TypeRef ] obj_self ,
403
406
vec[ ty. arg] inputs ,
404
407
@ty. t output ) -> TypeRef {
@@ -436,14 +439,26 @@ fn type_of_fn_full(@crate_ctxt cx,
436
439
}
437
440
}
438
441
442
+ if ( is_iter) {
443
+ // If it's an iter, the 'output' type of the iter is actually the
444
+ // *input* type of the function we're given as our iter-block
445
+ // argument.
446
+ atys += T_fn_pair ( type_of_fn_full ( cx, false , none[ TypeRef ] ,
447
+ vec ( rec ( mode=ast. val , ty=output) ) ,
448
+ plain_ty ( ty. ty_nil ) ) ) ;
449
+ }
450
+
439
451
// ... then explicit args.
440
452
atys += type_of_explicit_args ( cx, inputs) ;
441
453
442
454
ret T_fn ( atys, llvm. LLVMVoidType ( ) ) ;
443
455
}
444
456
445
- fn type_of_fn ( @crate_ctxt cx , vec[ ty. arg] inputs , @ty. t output ) -> TypeRef {
446
- ret type_of_fn_full ( cx, none[ TypeRef ] , inputs, output) ;
457
+ fn type_of_fn ( @crate_ctxt cx ,
458
+ // FIXME: change bool flag to tag
459
+ bool is_iter ,
460
+ vec[ ty. arg] inputs , @ty. t output ) -> TypeRef {
461
+ ret type_of_fn_full ( cx, is_iter, none[ TypeRef ] , inputs, output) ;
447
462
}
448
463
449
464
fn type_of_native_fn ( @crate_ctxt cx , vec[ ty. arg] inputs ,
@@ -499,7 +514,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef {
499
514
ret T_struct ( tys) ;
500
515
}
501
516
case ( ty. ty_fn ( ?args, ?out) ) {
502
- ret T_fn_pair ( type_of_fn ( cx, args, out) ) ;
517
+ // FIXME: put iter in ty_fn.
518
+ ret T_fn_pair ( type_of_fn ( cx, false , args, out) ) ;
503
519
}
504
520
case ( ty. ty_native_fn ( ?args, ?out) ) {
505
521
ret T_fn_pair ( type_of_native_fn ( cx, args, out) ) ;
@@ -512,6 +528,8 @@ fn type_of_inner(@crate_ctxt cx, @ty.t t) -> TypeRef {
512
528
for ( ty. method m in meths) {
513
529
let TypeRef mty =
514
530
type_of_fn_full ( cx,
531
+ // FIXME: support method iters
532
+ false ,
515
533
some[ TypeRef ] ( self_ty) ,
516
534
m. inputs , m. output ) ;
517
535
mtys += T_ptr ( mty) ;
@@ -2141,7 +2159,83 @@ fn trans_for_each(@block_ctxt cx,
2141
2159
@ast. decl decl,
2142
2160
@ast. expr seq,
2143
2161
& ast. block body) -> result {
2144
- cx. fcx. ccx. sess. unimpl( "for each loop" ) ;
2162
+
2163
+ /*
2164
+ * The translation is a little .. complex here. Code like:
2165
+ *
2166
+ * let ty1 p = ...;
2167
+ *
2168
+ * let ty1 q = ...;
2169
+ *
2170
+ * foreach (ty v in foo(a,b)) { body(p,q,v) }
2171
+ *
2172
+ *
2173
+ * Turns into a something like so (C/Rust mishmash):
2174
+ *
2175
+ * type env = { *ty1 p, *ty2 q, ... };
2176
+ *
2177
+ * let env e = { &p, &q, ... };
2178
+ *
2179
+ * fn foreach123_body(env* e, ty v) { body(*(e->p),*(e->q),v) }
2180
+ *
2181
+ * foo([foreach123_body, env*], a, b);
2182
+ *
2183
+ */
2184
+
2185
+ // Step 1: walk body and figure out which references it makes
2186
+ // escape. This could be determined upstream, and probably ought
2187
+ // to be so, eventualy. For first cut, skip this. Null env.
2188
+
2189
+ auto env_ty = T_struct ( vec( T_ptr ( T_i8 ( ) ) ) ) ;
2190
+
2191
+
2192
+ // Step 2: Declare foreach body function.
2193
+
2194
+ // FIXME: possibly support alias-mode here?
2195
+ auto decl_ty = plain_ty( ty. ty_nil) ;
2196
+ alt ( decl. node) {
2197
+ case ( ast. decl_local( ?local) ) {
2198
+ decl_ty = node_ann_type( cx. fcx. ccx, local. ann) ;
2199
+ }
2200
+ }
2201
+
2202
+ let str s =
2203
+ cx. fcx. ccx. names. next( "_rust_foreach")
2204
+ + sep( ) + cx. fcx. ccx. path;
2205
+
2206
+ // The 'env' arg entering the body function is a fake env member (as in
2207
+ // the env-part of the normal rust calling convention) that actually
2208
+ // points to a stack allocated env in this frame. We bundle that env
2209
+ // pointer along with the foreach-body-fn pointer into a 'normal' fn pair
2210
+ // and pass it in as a first class fn-arg to the iterator.
2211
+
2212
+ auto foreach_llty = type_of_fn_full( cx. fcx. ccx, false, none[ TypeRef ] ,
2213
+ vec( rec( mode=ast. val, ty=decl_ty) ) ,
2214
+ plain_ty( ty. ty_nil) ) ;
2215
+
2216
+ let ValueRef llforeach = decl_fastcall_fn( cx. fcx. ccx. llmod,
2217
+ s, foreach_llty) ;
2218
+
2219
+ // FIXME: handle ty params properly.
2220
+ let vec[ ast. ty_param] ty_params = vec( ) ;
2221
+
2222
+ auto fcx = new_fn_ctxt( cx. fcx. ccx, s, llforeach) ;
2223
+ auto bcx = new_top_block_ctxt( fcx) ;
2224
+
2225
+ // FIXME: populate lllocals from llenv here.
2226
+ auto res = trans_block( bcx, body) ;
2227
+ res. bcx. build. RetVoid ( ) ;
2228
+
2229
+
2230
+ // Step 3: Call iter passing [llforeach, llenv], plus other args.
2231
+
2232
+ alt ( seq. node) {
2233
+ case ( ast. expr_call( ?f, ?args, ?ann) ) {
2234
+ // FIXME_ finish here by transferring to trans_call,
2235
+ // suitably refactored.
2236
+ cx. fcx. ccx. sess. unimpl( "for each loop in trans") ;
2237
+ }
2238
+ }
2145
2239
fail;
2146
2240
}
2147
2241
@@ -3538,6 +3632,7 @@ fn new_fn_ctxt(@crate_ctxt cx,
3538
3632
llenv=llenv,
3539
3633
llretptr=llretptr,
3540
3634
mutable llself=none[ ValueRef ] ,
3635
+ mutable lliterbody=none[ ValueRef ] ,
3541
3636
llargs=llargs,
3542
3637
llobjfields=llobjfields,
3543
3638
lllocals=lllocals,
@@ -3553,6 +3648,8 @@ fn new_fn_ctxt(@crate_ctxt cx,
3553
3648
// - trans_args
3554
3649
3555
3650
fn create_llargs_for_fn_args ( & @fn_ctxt cx ,
3651
+ // FIXME: change bool flag to tag
3652
+ bool is_iter ,
3556
3653
option. t[ TypeRef ] ty_self ,
3557
3654
@ty. t ret_ty ,
3558
3655
& vec[ ast. arg] args ,
@@ -3577,6 +3674,12 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx,
3577
3674
}
3578
3675
}
3579
3676
3677
+ if ( is_iter) {
3678
+ auto llarg = llvm. LLVMGetParam ( cx. llfn, arg_n) ;
3679
+ check ( llarg as int != 0 ) ;
3680
+ cx. lliterbody = some[ ValueRef ] ( llarg) ;
3681
+ arg_n += 1 u;
3682
+ }
3580
3683
3581
3684
for ( ast. arg arg in args) {
3582
3685
auto llarg = llvm. LLVMGetParam ( cx. llfn, arg_n) ;
@@ -3713,7 +3816,8 @@ fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
3713
3816
cx. item_names. insert( cx. path, llfndecl) ;
3714
3817
3715
3818
auto fcx = new_fn_ctxt( cx, cx. path, llfndecl) ;
3716
- create_llargs_for_fn_args ( fcx, ty_self, ret_ty_of_fn ( ann) ,
3819
+ create_llargs_for_fn_args( fcx, f. is_iter,
3820
+ ty_self, ret_ty_of_fn( ann) ,
3717
3821
f. decl. inputs, ty_params) ;
3718
3822
auto bcx = new_top_block_ctxt( fcx) ;
3719
3823
@@ -3754,6 +3858,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
3754
3858
alt ( node_ann_type( cx, m. node. ann) . struct ) {
3755
3859
case ( ty. ty_fn( ?inputs, ?output) ) {
3756
3860
llfnty = type_of_fn_full( cx,
3861
+ // FIXME: support method iters.
3862
+ false ,
3757
3863
some[ TypeRef ] ( self_ty) ,
3758
3864
inputs, output) ;
3759
3865
}
@@ -3797,7 +3903,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
3797
3903
}
3798
3904
3799
3905
auto fcx = new_fn_ctxt( cx, cx. path, llctor_decl) ;
3800
- create_llargs_for_fn_args( fcx, none[ TypeRef ] , ret_ty_of_fn( ann) ,
3906
+ create_llargs_for_fn_args( fcx, false ,
3907
+ none[ TypeRef ] , ret_ty_of_fn( ann) ,
3801
3908
fn_args, ty_params) ;
3802
3909
3803
3910
auto bcx = new_top_block_ctxt( fcx) ;
@@ -3925,7 +4032,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
3925
4032
let ValueRef llfndecl = cx. item_ids. get( variant. id) ;
3926
4033
3927
4034
auto fcx = new_fn_ctxt( cx, cx. path, llfndecl) ;
3928
- create_llargs_for_fn_args( fcx, none[ TypeRef ] , ret_ty_of_fn( variant. ann) ,
4035
+ create_llargs_for_fn_args( fcx, false ,
4036
+ none[ TypeRef ] , ret_ty_of_fn( variant. ann) ,
3929
4037
fn_args, ty_params) ;
3930
4038
3931
4039
auto bcx = new_top_block_ctxt( fcx) ;
@@ -4331,6 +4439,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) {
4331
4439
llenv=C_null ( T_opaque_closure_ptr ( ) ) ,
4332
4440
llretptr=C_null ( T_ptr ( T_nil ( ) ) ) ,
4333
4441
mutable llself=none[ ValueRef ] ,
4442
+ mutable lliterbody=none[ ValueRef ] ,
4334
4443
llargs=new_def_hash[ ValueRef ] ( ) ,
4335
4444
llobjfields=new_def_hash[ ValueRef ] ( ) ,
4336
4445
lllocals=new_def_hash[ ValueRef ] ( ) ,
0 commit comments