import option::*; import pat_util::*; import syntax::ast::*; import syntax::ast_util::*; import syntax::visit; import syntax::codemap::span; import syntax::ast_util::respan; import driver::session::session; import aux::*; import std::map::hashmap; type ctxt = {cs: @mut [sp_constr], tcx: ty::ctxt}; fn collect_pred(e: @expr, cx: ctxt, v: visit::vt) { alt e.node { expr_check(_, ch) { *cx.cs += [expr_to_constr(cx.tcx, ch)]; } expr_if_check(ex, _, _) { *cx.cs += [expr_to_constr(cx.tcx, ex)]; } // If it's a call, generate appropriate instances of the // call's constraints. expr_call(operator, operands, _) { for constraints_expr(cx.tcx, operator).each {|c| let ct: sp_constr = respan(c.span, aux::substitute_constr_args(cx.tcx, operands, c)); *cx.cs += [ct]; } } _ { } } // visit subexpressions visit::visit_expr(e, cx, v); } fn find_locals(tcx: ty::ctxt, fk: visit::fn_kind, f_decl: fn_decl, f_body: blk, sp: span, id: node_id) -> ctxt { let cx: ctxt = {cs: @mut [], tcx: tcx}; let visitor = visit::default_visitor::(); let visitor = @{visit_expr: collect_pred, visit_fn: bind do_nothing(_, _, _, _, _, _, _) with *visitor}; visit::visit_fn(fk, f_decl, f_body, sp, id, cx, visit::mk_vt(visitor)); ret cx; } fn add_constraint(tcx: ty::ctxt, c: sp_constr, next: uint, tbl: constr_map) -> uint { log(debug, constraint_to_str(tcx, c) + " |-> " + uint::str(next)); let {path: p, def_id: d_id, args: args} = c.node; alt tbl.find(d_id) { some(ct) { let {path: _, descs: pds} = ct; *pds += [respan(c.span, {args: args, bit_num: next})]; } none { let rslt: @mut [pred_args] = @mut [respan(c.span, {args: args, bit_num: next})]; tbl.insert(d_id, {path:p, descs:rslt}); } } ret next + 1u; } /* builds a table mapping each local var defined in f to a bit number in the precondition/postcondition vectors */ fn mk_fn_info(ccx: crate_ctxt, fk: visit::fn_kind, f_decl: fn_decl, f_body: blk, f_sp: span, id: node_id) { let name = visit::name_of_fn(fk); let res_map = new_def_hash::(); let mut next: uint = 0u; let cx: ctxt = find_locals(ccx.tcx, fk, f_decl, f_body, f_sp, id); /* now we have to add bit nums for both the constraints and the variables... */ let mut i = 0u, l = vec::len(*cx.cs); while i < l { next = add_constraint(cx.tcx, copy cx.cs[i], next, res_map); i += 1u; } /* if this function has any constraints, instantiate them to the argument names and add them */ for f_decl.constraints.each {|c| let sc = ast_constr_to_sp_constr(cx.tcx, f_decl.inputs, c); next = add_constraint(cx.tcx, sc, next, res_map); } let v: @mut [node_id] = @mut []; let rslt = {constrs: res_map, num_constraints: next, cf: f_decl.cf, used_vars: v}; ccx.fm.insert(id, rslt); #debug("%s has %u constraints", name, num_constraints(rslt)); } /* initializes the global fn_info_map (mapping each function ID, including nested locally defined functions, onto a mapping from local variable name to bit number) */ fn mk_f_to_fn_info(ccx: crate_ctxt, c: @crate) { let visitor = visit::mk_simple_visitor(@{visit_fn: bind mk_fn_info(ccx, _, _, _, _, _) with *visit::default_simple_visitor()}); visit::visit_crate(*c, (), visitor); } // // Local Variables: // mode: rust // fill-column: 78; // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix // End: //