Appearance
| 1 | namespace IR.Values is | |
| 2 | use Semantic.Types.Type | |
| 3 | ||
| 4 | // Spills the value sitting on top of the evaluation stack - the | |
| 5 | // unwrapped subject a COALESCE_LOAD present arm leaves there - | |
| 6 | // into a fresh local, then generates `built`, which was | |
| 7 | // constructed against a `Load.TEMP` referring to that local. | |
| 8 | // | |
| 9 | // A value consumed straight off the stack only works when the | |
| 10 | // consuming value's gen() reads it first, before pushing anything | |
| 11 | // of its own: true of a member access on the subject (it is the | |
| 12 | // call target, pushed before the arguments), false of invoking a | |
| 13 | // delegate with the subject as an argument - the delegate itself | |
| 14 | // is pushed first. Spilling to a local decouples the subject's | |
| 15 | // stack position from where the built value needs it. | |
| 16 | class SPILLED_SUBJECT(_temp_name: string, _receiver_type: Type, built: Value): Value is | |
| 17 | type: Type? => built.type | |
| 18 | is_lightweight_pure: bool => false | |
| 19 | ||
| 20 | gen(context: IR.CONTEXT) is | |
| 21 | let body = context.current_srm_body_emitter! | |
| 22 | body.declare_local(_temp_name, _receiver_type) | |
| 23 | body.stloc(_temp_name) | |
| 24 | ||
| 25 | gen(built, context) | |
| 26 | si | |
| 27 | ||
| 28 | to_string() -> string => | |
| 29 | "spilled-subject:[{type}]({built})" | |
| 30 | si | |
| 31 | si |