Appearance
| 1 | namespace Syntax.Process is | |
| 2 | use IR | |
| 3 | use IR.Values | |
| 4 | ||
| 5 | // An argument pack thunk has no literal behind it, so its body is | |
| 6 | // generated from the description on its closure rather than walked: | |
| 7 | // read the thunk's own parameters, turn the pack from the shape the | |
| 8 | // thunk takes into the shape the wrapped function takes, call that | |
| 9 | // function and return what it returns. | |
| 10 | partial GENERATE_IL is | |
| 11 | _gen_pack_thunk(closure: Semantic.Symbols.Closure) is | |
| 12 | let thunk = closure.pack_thunk | |
| 13 | ||
| 14 | if !thunk? then | |
| 15 | return | |
| 16 | fi | |
| 17 | ||
| 18 | closure.map_type_arguments() | |
| 19 | ||
| 20 | let assembly_emitter = _context.srm_assembly_emitter | |
| 21 | let enclosing = _context.current_srm_body_emitter | |
| 22 | let enclosing_member = assembly_emitter.current_emission_member | |
| 23 | let body_emitter = IR.Emitter.SRM_METHOD_BODY_EMITTER() | |
| 24 | ||
| 25 | _context.current_srm_body_emitter = body_emitter | |
| 26 | assembly_emitter.current_emission_member = closure | |
| 27 | ||
| 28 | enter_block() | |
| 29 | ||
| 30 | let arguments = Collections.LIST[Value]() | |
| 31 | ||
| 32 | for i in 0..thunk.fixed_count do | |
| 33 | arguments.add(_pack_thunk_parameter(closure, i)) | |
| 34 | od | |
| 35 | ||
| 36 | if thunk.is_unpack then | |
| 37 | let tuple = IR.TEMP(current_block, "pack_thunk_tuple", _pack_thunk_parameter(closure, thunk.fixed_count)) | |
| 38 | ||
| 39 | let strategy = DESTRUCTURE_RESOLVER.resolve_strategy(tuple.type, thunk.element_types.count) | |
| 40 | ||
| 41 | for i in 0..thunk.element_types.count do | |
| 42 | arguments.add(strategy.members[i]!.load(closure.location, tuple.load(), _symbol_loader)) | |
| 43 | od | |
| 44 | else | |
| 45 | let elements = Collections.LIST[Value]() | |
| 46 | ||
| 47 | for i in 0..thunk.element_types.count do | |
| 48 | elements.add(_pack_thunk_parameter(closure, thunk.fixed_count + i)) | |
| 49 | od | |
| 50 | ||
| 51 | arguments.add( | |
| 52 | Values.TUPLE( | |
| 53 | _innate_symbol_lookup.get_tuple_type(thunk.element_types, null), | |
| 54 | elements | |
| 55 | ) | |
| 56 | ) | |
| 57 | fi | |
| 58 | ||
| 59 | let return_type = closure.return_type! | |
| 60 | ||
| 61 | if let target = thunk.target then | |
| 62 | add(target.call(closure.location, null, arguments, null, _function_caller)) | |
| 63 | elif let callee = thunk.callee then | |
| 64 | add( | |
| 65 | Values.Call.CLOSURE( | |
| 66 | callee, | |
| 67 | return_type, | |
| 68 | return_type.compare(_innate_symbol_lookup.get_void_type()) == Semantic.Types.MATCH.SAME, | |
| 69 | thunk.callee_type, | |
| 70 | arguments | |
| 71 | ) | |
| 72 | ) | |
| 73 | fi | |
| 74 | ||
| 75 | add(Values.RET()) | |
| 76 | ||
| 77 | current_block.gen(_context) | |
| 78 | ||
| 79 | leave_block() | |
| 80 | ||
| 81 | assembly_emitter.handles.set_body_offset(closure, body_emitter.flush(assembly_emitter)) | |
| 82 | assembly_emitter.handles.set_il_outputs(closure, body_emitter.il_outputs) | |
| 83 | ||
| 84 | _context.current_srm_body_emitter = enclosing | |
| 85 | assembly_emitter.current_emission_member = enclosing_member | |
| 86 | ||
| 87 | closure.unmap_type_arguments() | |
| 88 | si | |
| 89 | ||
| 90 | _pack_thunk_parameter(closure: Semantic.Symbols.Closure, index: int) -> Value => | |
| 91 | closure.find_direct("$pack_{index}")!.load(closure.location, null, _symbol_loader) | |
| 92 | si | |
| 93 | si |