e241dbc6ad44737d47e20cbd6ca22604a105e98f9201bf31f5ef91e304762330.tri (10782B)
1 !import prelude * 2 !import parser * 3 !import source_core * 4 !export * 5 6 -- Equation lowering prototype, independent of the surface parser and SCP ABI. 7 -- Pattern = (tag, (payload, location)); literal payloads are opaque trees. 8 -- Equation = (argument patterns, core body). Body indices address captures in 9 -- reverse introduction order, then surrounding lexical binders. Pin core is 10 -- resolved in that surrounding scope, never against this equation's captures. 11 -- Inputs are compiler-built patterns and well-formed source.core syntax. 12 13 sourcePatternNode tag payload location = pair tag (pair payload location) 14 sourcePatternTag pattern = fst pattern 15 sourcePatternPayload pattern = fst (snd pattern) 16 sourcePatternLocation pattern = snd (snd pattern) 17 sourcePatternAny location = sourcePatternNode 0 t location 18 sourcePatternLeaf location = sourcePatternNode 1 t location 19 sourcePatternStem child location = sourcePatternNode 2 child location 20 sourcePatternFork left right location = sourcePatternNode 3 (pair left right) location 21 sourcePatternCapture name location = sourcePatternNode 4 name location 22 sourcePatternLiteral tree location = sourcePatternNode 5 tree location 23 sourcePatternWhole name child location = sourcePatternNode 6 (pair name child) location 24 sourcePatternPin core location = sourcePatternNode 7 core location 25 sourceEquation patterns body = pair patterns body 26 27 spLit tree = sourceCoreExternal tree t t 28 spVar index = sourceCoreBound index t t 29 spApp function argument = sourceCoreApply function argument t t 30 spLam body = sourceCoreLambda body t t 31 spApp2 f a b = spApp (spApp f a) b 32 spApp3 f a b c = spApp (spApp2 f a b) c 33 spApp4 f a b c d = spApp (spApp3 f a b c) d 34 35 -- All three branches are continuations, including Leaf. Work is performed 36 -- only after structural selection, not passed as an ordinary triage result. 37 spSelect leafK stemK forkK value = ((chosen : chosen t) 38 (triage leafK (child : _ : stemK child) 39 (left right : _ : forkK left right) value)) 40 41 -- Syntax-driven shifting; never inspect an External's arbitrary tree payload. 42 -- This hot visitor deliberately retains cheap tag dispatch. Patterned case 43 -- dispatch measured ~29% more allocation on nested binder/application syntax. 44 spShift node = (let rec 45 shift node cutoff = (let kind = sourceCoreKind node in 46 lazyBool 47 (_ : lazyBool 48 (_ : sourceCoreBound (succ (sourceCorePayload node)) 49 (sourceCoreStart node) (sourceCoreEnd node)) 50 (_ : node) (lte_? cutoff (sourceCorePayload node))) 51 (_ : lazyBool 52 (_ : sourceCoreApply 53 (shift (fst (sourceCorePayload node)) cutoff) 54 (shift (snd (sourceCorePayload node)) cutoff) 55 (sourceCoreStart node) (sourceCoreEnd node)) 56 (_ : lazyBool 57 (_ : sourceCoreLambda (shift (sourceCorePayload node) (succ cutoff)) 58 (sourceCoreStart node) (sourceCoreEnd node)) 59 (_ : lazyBool 60 (_ : sourceCoreList (map (child : shift child cutoff) 61 (sourceCorePayload node)) (sourceCoreStart node) (sourceCoreEnd node)) 62 (_ : node) (equal? kind sourceCoreListKind)) 63 (equal? kind sourceCoreLambdaKind)) 64 (equal? kind sourceCoreApplyKind)) 65 (equal? kind sourceCoreBoundKind)) 66 in shift node 0) 67 spShift2 node = spShift (spShift node) 68 -- Consume a syntax-derived binder list, not a numeric depth difference. 69 spRaise node fuel = (lazyList (_ : node) 70 (_ rest : spRaise (spShift node) rest) fuel) 71 72 -- Context = (binder fuel, (reverse captures, pending argument/sibling syntax)). 73 -- Capture aliases and pending expressions are shifted together under every 74 -- generated binder. No counter-driven sibling raising or runtime table exists. 75 spContext fuel captures pending = pair fuel (pair captures pending) 76 spFuel ctx = fst ctx 77 spDepth ctx = length (spFuel ctx) 78 spCaptures ctx = fst (snd ctx) 79 spPending ctx = snd (snd ctx) 80 spShiftContext ctx = (spContext (pair t (spFuel ctx)) 81 (map (entry : pair (fst entry) (spShift (snd entry))) (spCaptures ctx)) 82 (map spShift (spPending ctx))) 83 spBind ctx name value = (spContext (spFuel ctx) 84 (pair (pair name value) (spCaptures ctx)) (spPending ctx)) 85 spSave ctx value = spContext (spFuel ctx) (spCaptures ctx) (pair value (spPending ctx)) 86 spPop ctx = spContext (spFuel ctx) (spCaptures ctx) (snd (spPending ctx)) 87 88 spCaptureAt captures index = (lazyList (_ : nothing) 89 (entry rest : lazyBool (_ : just (snd entry)) 90 (_ : spCaptureAt rest (pred_ index)) (isZero_? index)) captures) 91 92 -- Substitute resolved capture indices, preserving lambdas in the body and 93 -- shifting outer lexical references past generated matcher binders. 94 spBodyBound node ctx fuel = (let index = sourceCorePayload node in 95 let cutoff = length fuel in 96 lazyBool (_ : node) 97 (_ : lazyMaybe 98 (_ : sourceCoreBound 99 (add cutoff (add (spDepth ctx) 100 (sub (sub index cutoff) (length (spCaptures ctx))))) 101 (sourceCoreStart node) (sourceCoreEnd node)) 102 (value : sourceCoreWithSpan (spRaise value fuel) 103 (sourceCoreStart node) (sourceCoreEnd node)) 104 (spCaptureAt (spCaptures ctx) (sub index cutoff))) 105 (lt_? index cutoff)) 106 spBody node ctx = (let rec 107 substitute node fuel = (let payload = sourceCorePayload node in 108 let start = sourceCoreStart node in 109 let end = sourceCoreEnd node in 110 case sourceCoreKind node of 111 ^sourceCoreBoundKind = spBodyBound node ctx fuel 112 ^sourceCoreApplyKind = (sourceCoreApply 113 (substitute (fst payload) fuel) (substitute (snd payload) fuel) start end) 114 ^sourceCoreLambdaKind = sourceCoreLambda (substitute payload (pair t fuel)) start end 115 ^sourceCoreListKind = sourceCoreList (map (child : substitute child fuel) payload) start end 116 _ = node) 117 in substitute node t) 118 119 spCase leaf stem fork value = (spApp4 (spLit spSelect) 120 (spLam (spShift leaf)) (spLam stem) (spLam (spLam fork)) value) 121 spIf yes no condition = (spApp3 (spLit lazyBool) 122 (spLam (spShift yes)) (spLam (spShift no)) condition) 123 124 -- hit receives the updated context and shifted miss expression. A left 125 -- child's handlers may add binders before its saved right sibling is visited. 126 spPattern pattern value ctx hit miss = (let payload = sourcePatternPayload pattern in 127 case sourcePatternTag pattern of 128 0 = hit ctx miss 129 1 = spCase (hit ctx miss) (spShift miss) (spShift2 miss) value 130 2 = (spCase miss 131 (spPattern payload (spVar 0) (spShiftContext ctx) hit (spShift miss)) 132 (spShift2 miss) value) 133 3 = (spCase miss (spShift miss) 134 (spPattern (fst payload) (spVar 1) 135 (spSave (spShiftContext (spShiftContext ctx)) (spVar 0)) 136 (next nextMiss : spPattern (snd payload) (fst (spPending next)) 137 (spPop next) hit nextMiss) 138 (spShift2 miss)) value) 139 4 = hit (spBind ctx payload value) miss 140 5 = spIf (hit ctx miss) miss (spApp2 (spLit equal?) value (spLit payload)) 141 6 = spPattern (snd payload) value (spBind ctx (fst payload) value) hit miss 142 -- Validation admits only tags 0..7; the remaining tag is a resolved pin. 143 _ = (spIf (hit ctx miss) miss 144 (spApp2 (spLit equal?) value (spRaise payload (spFuel ctx))))) 145 146 spArguments patterns = (lazyList (_ : t) 147 (_ rest : pair (spVar (length rest)) (spArguments rest)) patterns) 148 spMatchArguments patterns ctx body miss = (lazyList 149 (_ : spBody body ctx) 150 (pattern rest : spPattern pattern (fst (spPending ctx)) (spPop ctx) 151 (next nextMiss : spMatchArguments rest next body nextMiss) miss) patterns) 152 153 -- The final equation is irrefutable, so the empty suffix is unreachable. 154 -- One native lazy continuation shares all misses to the remaining equations. 155 spEquations equations ctx = (lazyList (_ : spLit t) 156 (equation rest : spApp 157 (spLam (spMatchArguments (fst equation) 158 (spShiftContext ctx) (snd equation) (spApp (spVar 0) (spLit t)))) 159 (spLam (spShift (spEquations rest ctx)))) equations) 160 spWrap patterns body = (lazyList (_ : body) 161 (_ rest : spLam (spWrap rest body)) patterns) 162 163 spDiagnostic expected found location = parserDiagnostic 48 expected found location t 164 spError expected pattern = (err 165 (spDiagnostic expected (sourcePatternTag pattern) (sourcePatternLocation pattern)) t) 166 spHasName names name = (lazyList (_ : false) 167 (head rest : lazyBool (_ : true) (_ : spHasName rest name) (equal? head name)) names) 168 spIntroduce names name pattern = (lazyBool 169 (_ : err (spDiagnostic "unique capture" name (sourcePatternLocation pattern)) t) 170 (_ : ok (pair name names) t) (spHasName names name)) 171 spValidatePattern pattern names = (let payload = sourcePatternPayload pattern in 172 case sourcePatternTag pattern of 173 0 = ok names t 174 1 = ok names t 175 2 = spValidatePattern payload names 176 3 = (bindResult (spValidatePattern (fst payload) names) 177 (next _ : spValidatePattern (snd payload) next)) 178 4 = spIntroduce names payload pattern 179 5 = ok names t 180 6 = (bindResult (spIntroduce names (fst payload) pattern) 181 (next _ : spValidatePattern (snd payload) next)) 182 7 = ok names t 183 _ = spError "pattern tag" pattern) 184 spValidateArguments patterns = (let rec 185 validate remaining names = (lazyList (_ : ok names t) 186 (pattern rest : bindResult (spValidatePattern pattern names) 187 (next _ : validate rest next)) remaining) 188 in validate patterns t) 189 spIrrefutable pattern = case sourcePatternTag pattern of 190 0 = true 191 4 = true 192 6 = spIrrefutable (snd (sourcePatternPayload pattern)) 193 _ = false 194 spAllIrrefutable patterns = (lazyList (_ : true) 195 (pattern rest : lazyBool (_ : spAllIrrefutable rest) (_ : false) (spIrrefutable pattern)) patterns) 196 spValidateEquations equations arity = (lazyList 197 (_ : err (spDiagnostic "nonempty equations" t t) t) 198 (equation rest : lazyBool 199 (_ : lazyResult (problem tail : err problem tail) 200 (names tail : lazyList 201 (_ : lazyBool (_ : ok t t) 202 (_ : err (spDiagnostic "final irrefutable equation" t 203 (sourceCoreStart (snd equation))) t) 204 (spAllIrrefutable (fst equation))) 205 (_ tail : spValidateEquations rest arity) rest) 206 (spValidateArguments (fst equation))) 207 (_ : err (spDiagnostic "consistent arity" (length (fst equation)) 208 (sourceCoreStart (snd equation))) t) 209 (equal? (length (fst equation)) arity)) equations) 210 211 sourceLowerEquations equations = (lazyList 212 (_ : err (spDiagnostic "nonempty equations" t t) t) 213 (first rest : let patterns = fst first in 214 let arity = length patterns in 215 lazyBool 216 (_ : err (spDiagnostic "positive equation arity" 0 217 (sourceCoreStart (snd first))) t) 218 (_ : lazyResult (problem tail : err problem tail) 219 (_ tail : ok (spWrap patterns 220 (spEquations equations (spContext patterns t (spArguments patterns)))) t) 221 (spValidateEquations equations arity)) 222 (isZero_? arity)) equations) 223