tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

1d43992c04f9881c1ebd0e0ef7f6bdc735780f646a52f95b5a7fb46e14fd4f83.tri (14902B)


      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 -- Sequential fallback for arbitrary ordered patterns. A final irrefutable row
    154 -- cannot miss, so it needs neither a failure binder nor a delayed empty suffix.
    155 spSequentialEquations equations ctx = (lazyList (_ : spLit t)
    156   (equation rest : lazyBool
    157     (_ : spMatchArguments (fst equation) ctx (snd equation) (spLit t))
    158     (_ : spApp
    159       (spLam (spMatchArguments (fst equation)
    160         (spShiftContext ctx) (snd equation) (spApp (spVar 0) (spLit t))))
    161       (spLam (spShift (spSequentialEquations rest ctx))))
    162     (emptyList? rest)) equations)
    163 
    164 -- Only factor a constructor test that the FIRST row must reach. All preceding
    165 -- columns must be plain captures/wildcards in EVERY row. Pins, literals and
    166 -- whole patterns at the split column conservatively retain sequential lowering.
    167 -- This is not permission to reorder tests of different arguments or children.
    168 spPlainIrrefutable pattern = (let tag = sourcePatternTag pattern in
    169   or? (equal? tag 0) (equal? tag 4))
    170 spRootPattern pattern = (let tag = sourcePatternTag pattern in
    171   or? (spPlainIrrefutable pattern)
    172     (or? (equal? tag 1) (or? (equal? tag 2) (equal? tag 3))))
    173 spFindSplit equations patterns column = (lazyList (_ : nothing)
    174   (pattern rest : lazyBool
    175     (_ : lazyBool
    176       (_ : spFindSplit equations rest (succ column))
    177       (_ : nothing)
    178       (all? (equation : spPlainIrrefutable (nth column (fst equation))) equations))
    179     (_ : lazyBool
    180       (_ : just column)
    181       (_ : nothing)
    182       (and? (spRootPattern pattern)
    183         (all? (equation : spRootPattern (nth column (fst equation))) equations)))
    184     (spPlainIrrefutable pattern)) patterns)
    185 spRootAccepts kind pattern =
    186   or? (spPlainIrrefutable pattern) (equal? kind (sourcePatternTag pattern))
    187 
    188 -- The selected constructor and its child expressions are already available.
    189 -- Child coordinates travel explicitly because a failure binder shifts them.
    190 -- Nested patterns still use ordinary left-to-right matching and saved siblings.
    191 spKnownPattern pattern children value ctx hit miss = (case sourcePatternTag pattern of
    192   1 = hit ctx miss
    193   2 = spPattern (sourcePatternPayload pattern) (fst children) ctx hit miss
    194   3 = (spPattern (fst (sourcePatternPayload pattern)) (fst children)
    195     (spSave ctx (fst (snd children)))
    196     (next nextMiss : spPattern (snd (sourcePatternPayload pattern))
    197       (fst (spPending next)) (spPop next) hit nextMiss) miss)
    198   _ = spPattern pattern value ctx hit miss)
    199 spKnownArguments patterns column children ctx body miss = (lazyList
    200   (_ : spBody body ctx)
    201   (pattern rest : lazyBool
    202     (_ : spKnownPattern pattern children (fst (spPending ctx)) (spPop ctx)
    203       (next nextMiss : spMatchArguments rest next body nextMiss) miss)
    204     (_ : spPattern pattern (fst (spPending ctx)) (spPop ctx)
    205       (next nextMiss : spKnownArguments rest (pred_ column) children next body nextMiss) miss)
    206     (isZero_? column)) patterns)
    207 spKnownIrrefutable pattern = (case sourcePatternTag pattern of
    208   1 = true
    209   2 = spIrrefutable (sourcePatternPayload pattern)
    210   3 = and? (spIrrefutable (fst (sourcePatternPayload pattern)))
    211            (spIrrefutable (snd (sourcePatternPayload pattern)))
    212   _ = spIrrefutable pattern)
    213 spKnownRowIrrefutable patterns column = (lazyList (_ : true)
    214   (pattern rest : lazyBool
    215     (_ : and? (spKnownIrrefutable pattern) (spAllIrrefutable rest))
    216     (_ : and? (spIrrefutable pattern) (spKnownRowIrrefutable rest (pred_ column)))
    217     (isZero_? column)) patterns)
    218 spKnownEquations equations column children ctx = (lazyList (_ : spLit t)
    219   (equation rest : lazyBool
    220     (_ : spKnownArguments (fst equation) column children ctx (snd equation) (spLit t))
    221     (_ : spApp
    222       (spLam (spKnownArguments (fst equation) column (map spShift children)
    223         (spShiftContext ctx) (snd equation) (spApp (spVar 0) (spLit t))))
    224       (spLam (spShift (spKnownEquations rest column children ctx))))
    225     (spKnownRowIrrefutable (fst equation) column)) equations)
    226 spSplitEquations equations column ctx = (let
    227   rows kind = filter (equation : spRootAccepts kind (nth column (fst equation))) equations
    228   stemCtx = spShiftContext ctx
    229   forkCtx = spShiftContext stemCtx
    230   in spCase
    231     (spKnownEquations (rows 1) column [] ctx)
    232     (spKnownEquations (rows 2) column [(spVar 0)] stemCtx)
    233     (spKnownEquations (rows 3) column [(spVar 1) (spVar 0)] forkCtx)
    234     (nth column (spPending ctx)))
    235 spEquations equations ctx = (lazyMaybe
    236   (_ : spSequentialEquations equations ctx)
    237   (column : spSplitEquations equations column ctx)
    238   (spFindSplit equations (fst (fst equations)) 0))
    239 spWrap patterns body = (lazyList (_ : body)
    240   (_ rest : spLam (spWrap rest body)) patterns)
    241 
    242 spDiagnostic expected found location = parserDiagnostic 48 expected found location t
    243 spError expected pattern = (err
    244   (spDiagnostic expected (sourcePatternTag pattern) (sourcePatternLocation pattern)) t)
    245 spHasName names name = (lazyList (_ : false)
    246   (head rest : lazyBool (_ : true) (_ : spHasName rest name) (equal? head name)) names)
    247 spIntroduce names name pattern = (lazyBool
    248   (_ : err (spDiagnostic "unique capture" name (sourcePatternLocation pattern)) t)
    249   (_ : ok (pair name names) t) (spHasName names name))
    250 spValidatePattern pattern names = (let payload = sourcePatternPayload pattern in
    251   case sourcePatternTag pattern of
    252     0 = ok names t
    253     1 = ok names t
    254     2 = spValidatePattern payload names
    255     3 = (bindResult (spValidatePattern (fst payload) names)
    256       (next _ : spValidatePattern (snd payload) next))
    257     4 = spIntroduce names payload pattern
    258     5 = ok names t
    259     6 = (bindResult (spIntroduce names (fst payload) pattern)
    260       (next _ : spValidatePattern (snd payload) next))
    261     7 = ok names t
    262     _ = spError "pattern tag" pattern)
    263 spValidateArguments patterns = (let rec
    264   validate remaining names = (lazyList (_ : ok names t)
    265     (pattern rest : bindResult (spValidatePattern pattern names)
    266       (next _ : validate rest next)) remaining)
    267   in validate patterns t)
    268 spIrrefutable pattern = case sourcePatternTag pattern of
    269   0 = true
    270   4 = true
    271   6 = spIrrefutable (snd (sourcePatternPayload pattern))
    272   _ = false
    273 spAllIrrefutable patterns = (lazyList (_ : true)
    274   (pattern rest : lazyBool (_ : spAllIrrefutable rest) (_ : false) (spIrrefutable pattern)) patterns)
    275 spValidateEquations equations arity = (lazyList
    276   (_ : err (spDiagnostic "nonempty equations" t t) t)
    277   (equation rest : lazyBool
    278     (_ : lazyResult (problem tail : err problem tail)
    279       (names tail : lazyList
    280         (_ : lazyBool (_ : ok t t)
    281           (_ : err (spDiagnostic "final irrefutable equation" t
    282             (sourceCoreStart (snd equation))) t)
    283           (spAllIrrefutable (fst equation)))
    284         (_ tail : spValidateEquations rest arity) rest)
    285       (spValidateArguments (fst equation)))
    286     (_ : err (spDiagnostic "consistent arity" (length (fst equation))
    287       (sourceCoreStart (snd equation))) t)
    288     (equal? (length (fst equation)) arity)) equations)
    289 
    290 sourceLowerEquations equations = (lazyList
    291   (_ : err (spDiagnostic "nonempty equations" t t) t)
    292   (first rest : let patterns = fst first in
    293     let arity = length patterns in
    294     lazyBool
    295       (_ : err (spDiagnostic "positive equation arity" 0
    296         (sourceCoreStart (snd first))) t)
    297       (_ : lazyResult (problem tail : err problem tail)
    298         (_ tail : ok (spWrap patterns
    299           (spEquations equations (spContext patterns t (spArguments patterns)))) t)
    300         (spValidateEquations equations arity))
    301       (isZero_? arity)) equations)
    302