diff options
| author | Graydon Hoare <[email protected]> | 2011-02-17 12:20:55 -0800 |
|---|---|---|
| committer | Graydon Hoare <[email protected]> | 2011-02-17 12:20:55 -0800 |
| commit | 79d3ceaac0b4a6ca83f0ff7b8b533649fc5165a1 (patch) | |
| tree | cb102047edb55b39921373dae7bbce2c2e8ea72e /src/comp | |
| parent | Un-XFAIL mutable-vec-drop.rs. (diff) | |
| download | rust-79d3ceaac0b4a6ca83f0ff7b8b533649fc5165a1.tar.xz rust-79d3ceaac0b4a6ca83f0ff7b8b533649fc5165a1.zip | |
Steps toward implementing iterators.
Diffstat (limited to 'src/comp')
| -rw-r--r-- | src/comp/middle/trans.rs | 123 |
1 files changed, 116 insertions, 7 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index e3e68d4b..62b5a415 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -88,6 +88,7 @@ state type fn_ctxt = rec(ValueRef llfn, ValueRef llenv, ValueRef llretptr, mutable option.t[ValueRef] llself, + mutable option.t[ValueRef] lliterbody, hashmap[ast.def_id, ValueRef] llargs, hashmap[ast.def_id, ValueRef] llobjfields, hashmap[ast.def_id, ValueRef] lllocals, @@ -399,6 +400,8 @@ fn type_of_explicit_args(@crate_ctxt cx, // - trans_args fn type_of_fn_full(@crate_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, option.t[TypeRef] obj_self, vec[ty.arg] inputs, @ty.t output) -> TypeRef { @@ -436,14 +439,26 @@ fn type_of_fn_full(@crate_ctxt cx, } } + if (is_iter) { + // If it's an iter, the 'output' type of the iter is actually the + // *input* type of the function we're given as our iter-block + // argument. + atys += T_fn_pair(type_of_fn_full(cx, false, none[TypeRef], + vec(rec(mode=ast.val, ty=output)), + plain_ty(ty.ty_nil))); + } + // ... then explicit args. atys += type_of_explicit_args(cx, inputs); ret T_fn(atys, llvm.LLVMVoidType()); } -fn type_of_fn(@crate_ctxt cx, vec[ty.arg] inputs, @ty.t output) -> TypeRef { - ret type_of_fn_full(cx, none[TypeRef], inputs, output); +fn type_of_fn(@crate_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, + vec[ty.arg] inputs, @ty.t output) -> TypeRef { + ret type_of_fn_full(cx, is_iter, none[TypeRef], inputs, output); } 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 { ret T_struct(tys); } case (ty.ty_fn(?args, ?out)) { - ret T_fn_pair(type_of_fn(cx, args, out)); + // FIXME: put iter in ty_fn. + ret T_fn_pair(type_of_fn(cx, false, args, out)); } case (ty.ty_native_fn(?args, ?out)) { 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 { for (ty.method m in meths) { let TypeRef mty = type_of_fn_full(cx, + // FIXME: support method iters + false, some[TypeRef](self_ty), m.inputs, m.output); mtys += T_ptr(mty); @@ -2141,7 +2159,83 @@ fn trans_for_each(@block_ctxt cx, @ast.decl decl, @ast.expr seq, &ast.block body) -> result { - cx.fcx.ccx.sess.unimpl("for each loop"); + + /* + * The translation is a little .. complex here. Code like: + * + * let ty1 p = ...; + * + * let ty1 q = ...; + * + * foreach (ty v in foo(a,b)) { body(p,q,v) } + * + * + * Turns into a something like so (C/Rust mishmash): + * + * type env = { *ty1 p, *ty2 q, ... }; + * + * let env e = { &p, &q, ... }; + * + * fn foreach123_body(env* e, ty v) { body(*(e->p),*(e->q),v) } + * + * foo([foreach123_body, env*], a, b); + * + */ + + // Step 1: walk body and figure out which references it makes + // escape. This could be determined upstream, and probably ought + // to be so, eventualy. For first cut, skip this. Null env. + + auto env_ty = T_struct(vec(T_ptr(T_i8()))); + + + // Step 2: Declare foreach body function. + + // FIXME: possibly support alias-mode here? + auto decl_ty = plain_ty(ty.ty_nil); + alt (decl.node) { + case (ast.decl_local(?local)) { + decl_ty = node_ann_type(cx.fcx.ccx, local.ann); + } + } + + let str s = + cx.fcx.ccx.names.next("_rust_foreach") + + sep() + cx.fcx.ccx.path; + + // The 'env' arg entering the body function is a fake env member (as in + // the env-part of the normal rust calling convention) that actually + // points to a stack allocated env in this frame. We bundle that env + // pointer along with the foreach-body-fn pointer into a 'normal' fn pair + // and pass it in as a first class fn-arg to the iterator. + + auto foreach_llty = type_of_fn_full(cx.fcx.ccx, false, none[TypeRef], + vec(rec(mode=ast.val, ty=decl_ty)), + plain_ty(ty.ty_nil)); + + let ValueRef llforeach = decl_fastcall_fn(cx.fcx.ccx.llmod, + s, foreach_llty); + + // FIXME: handle ty params properly. + let vec[ast.ty_param] ty_params = vec(); + + auto fcx = new_fn_ctxt(cx.fcx.ccx, s, llforeach); + auto bcx = new_top_block_ctxt(fcx); + + // FIXME: populate lllocals from llenv here. + auto res = trans_block(bcx, body); + res.bcx.build.RetVoid(); + + + // Step 3: Call iter passing [llforeach, llenv], plus other args. + + alt (seq.node) { + case (ast.expr_call(?f, ?args, ?ann)) { + // FIXME_ finish here by transferring to trans_call, + // suitably refactored. + cx.fcx.ccx.sess.unimpl("for each loop in trans"); + } + } fail; } @@ -3538,6 +3632,7 @@ fn new_fn_ctxt(@crate_ctxt cx, llenv=llenv, llretptr=llretptr, mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], llargs=llargs, llobjfields=llobjfields, lllocals=lllocals, @@ -3553,6 +3648,8 @@ fn new_fn_ctxt(@crate_ctxt cx, // - trans_args fn create_llargs_for_fn_args(&@fn_ctxt cx, + // FIXME: change bool flag to tag + bool is_iter, option.t[TypeRef] ty_self, @ty.t ret_ty, &vec[ast.arg] args, @@ -3577,6 +3674,12 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, } } + if (is_iter) { + auto llarg = llvm.LLVMGetParam(cx.llfn, arg_n); + check (llarg as int != 0); + cx.lliterbody = some[ValueRef](llarg); + arg_n += 1u; + } for (ast.arg arg in args) { 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, cx.item_names.insert(cx.path, llfndecl); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, ty_self, ret_ty_of_fn(ann), + create_llargs_for_fn_args(fcx, f.is_iter, + ty_self, ret_ty_of_fn(ann), f.decl.inputs, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3754,6 +3858,8 @@ fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty, alt (node_ann_type(cx, m.node.ann).struct) { case (ty.ty_fn(?inputs, ?output)) { llfnty = type_of_fn_full(cx, + // FIXME: support method iters. + false, some[TypeRef](self_ty), inputs, output); } @@ -3797,7 +3903,8 @@ fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid, } auto fcx = new_fn_ctxt(cx, cx.path, llctor_decl); - create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(ann), + create_llargs_for_fn_args(fcx, false, + none[TypeRef], ret_ty_of_fn(ann), fn_args, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -3925,7 +4032,8 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id, let ValueRef llfndecl = cx.item_ids.get(variant.id); auto fcx = new_fn_ctxt(cx, cx.path, llfndecl); - create_llargs_for_fn_args(fcx, none[TypeRef], ret_ty_of_fn(variant.ann), + create_llargs_for_fn_args(fcx, false, + none[TypeRef], ret_ty_of_fn(variant.ann), fn_args, ty_params); auto bcx = new_top_block_ctxt(fcx); @@ -4331,6 +4439,7 @@ fn trans_exit_task_glue(@crate_ctxt cx) { llenv=C_null(T_opaque_closure_ptr()), llretptr=C_null(T_ptr(T_nil())), mutable llself=none[ValueRef], + mutable lliterbody=none[ValueRef], llargs=new_def_hash[ValueRef](), llobjfields=new_def_hash[ValueRef](), lllocals=new_def_hash[ValueRef](), |