tricu

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

consumer_semantic_boundary.tri (5198B)


      1 -- Failures during a selected output never become a rule or arm miss.
      2 -- Negative validation checks are separate from reference/lexical agreement.
      3 !import "consumers.structural" S
      4 !import "consumers.lexical-worker" L
      5 !import "consumers.validate" V
      6 !import "consumers.base-source" B
      7 !import "prelude" !Local
      8 rule input state output = S.makeRule input state output
      9 one output = S.makeConsumer t [(rule S.patAny S.patAny output)
     10   (rule S.patAny S.patAny (S.outLiteral 999))]
     11 compare reference executable input = (equal? (S.runConsumer reference input)
     12   (L.lRunChecked executable input))
     13 
     14 -- Left-to-right pattern binding, then state matching, with fallthrough.
     15 order = S.makeConsumer t [
     16   (rule (S.patFork (S.patCapture 0) (S.patLiteral 5))
     17     S.patAny (S.outCapture 0))
     18   (rule S.patLeaf (S.patLiteral true) (S.outLiteral 10))
     19   (rule S.patLeaf S.patAny (S.outLiteral 20))
     20   (rule S.patAny S.patAny (S.outLiteral 30))]
     21 orderWorker = resultOr t (L.lCompile order)
     22 noArm = (S.outMatch (S.outLiteral true)
     23   [(pair S.patLeaf (S.outLiteral 5))])
     24 noRule = S.makeConsumer t []
     25 noRuleWorker = resultOr t (L.lCompile noRule)
     26 callTarget target = (S.outCall (S.outLiteral target)
     27   (S.outLiteral t) 0 (S.outCapture 0))
     28 -- Both children fail differently; the left failure must win.
     29 leftFirst target = one (S.outFork (callTarget target) noArm)
     30 rightFirst target = one (S.outFork noArm (callTarget target))
     31 refLeft = leftFirst noRule
     32 lexLeft = resultOr t (L.lCompile (leftFirst noRuleWorker))
     33 refRight = rightFirst noRule
     34 lexRight = resultOr t (L.lCompile (rightFirst noRuleWorker))
     35 -- The unchosen arm is valid, but would fail if evaluated.
     36 lazyArm target = one (S.outMatch (S.outLiteral t) [
     37   (pair S.patLeaf (S.outLiteral 7))
     38   (pair S.patAny (callTarget target))])
     39 refLazy = lazyArm noRule
     40 lexLazy = resultOr t (L.lCompile (lazyArm noRuleWorker))
     41 -- Both sibling arms may use slot 1; it cannot leak into a later sibling.
     42 siblings = S.makeConsumer t [(rule (S.patCapture 0) S.patAny
     43   (S.outMatch (S.outCapture 0) [
     44     (pair (S.patStem (S.patCapture 1)) (S.outCapture 1))
     45     (pair (S.patCapture 1) (S.outCapture 1))]))]
     46 siblingsWorker = resultOr t (L.lCompile siblings)
     47 leak = one (S.outMatch (S.outLiteral t) [
     48   (pair (S.patStem (S.patCapture 0)) (S.outCapture 0))
     49   (pair S.patLeaf (S.outCapture 0))])
     50 duplicate = S.makeConsumer t [(rule (S.patCapture 0) S.patAny
     51   (S.outMatch (S.outCapture 0) [
     52     (pair (S.patCapture 0) (S.outCapture 0))]))]
     53 malformedArms = one (S.outMatch (S.outLiteral t) (t t))
     54 malformedTail = one (S.outMatch (S.outLiteral t)
     55   (pair (pair S.patLeaf (S.outLiteral t)) (t t)))
     56 malformedArm = one (S.outMatch (S.outLiteral t) [t])
     57 -- Source spelling must agree with the authored IR contract as well.
     58 source = (B.compileBaseSource
     59   "consumer boundary\n  [] @ leaf => match leaf of (leaf => 1 | _ => 2)\n  [] @ _ => 3\n  x @ _ => match x of (stem value => value | leaf => leaf)")
     60 sourceIR = snd (resultOr t source)
     61 sourceWorker = resultOr t (L.lCompile sourceIR)
     62 -- State-pattern and output numerals share ordinary compact tricu semantics.
     63 numericIR = snd (resultOr t (B.compileBaseSource
     64   "consumer numeric\n  x @ 2 => 4\n  x @ _ => 0"))
     65 numeric = S.makeConsumer 2 (snd numericIR)
     66 numericWorker = resultOr t (L.lCompile numeric)
     67 checks = foldl and? true [
     68   (compare numeric numericWorker 8)
     69   (equal? (S.runConsumer numeric 8) (ok 4 t))
     70   (resultIsOk (V.vValidate order))
     71   (compare order orderWorker (pair 7 8))
     72   (equal? (S.runConsumer order (pair 7 8)) (ok 30 t))
     73   (compare order orderWorker t)
     74   (equal? (S.runConsumer order t) (ok 20 t))
     75   (compare order orderWorker (pair 7 5))
     76   (equal? (S.runConsumer order (pair 7 5)) (ok 7 t))
     77   (compare refLeft lexLeft t)
     78   (equal? (S.runConsumer refLeft t) (err "no matching consumer rule" t))
     79   (compare refRight lexRight t)
     80   (equal? (S.runConsumer refRight t) (err "no matching output arm" t))
     81   (compare refLazy lexLazy t)
     82   (equal? (S.runConsumer refLazy t) (ok 7 t))
     83   (resultIsOk (V.vValidate siblings))
     84   (compare siblings siblingsWorker t)
     85   (compare siblings siblingsWorker (t 7))
     86   (equal? (S.runConsumer siblings t) (ok t t))
     87   (equal? (S.runConsumer siblings (t 7)) (ok 7 t))
     88   (equal? (V.vValidate leak)
     89     (err (V.vDiagnostic "malformed" 0 ["arm" "output"] "unknown capture") t))
     90   (equal? (L.lCompile leak) (V.vValidate leak))
     91   (equal? (V.vValidate duplicate)
     92     (err (V.vDiagnostic "malformed" 0 ["pattern" "output"] "duplicate binding") t))
     93   (equal? (V.vValidate malformedArms)
     94     (err (V.vDiagnostic "malformed" 0 ["output"] "match arm list") t))
     95   (equal? (L.lCompile malformedArms) (V.vValidate malformedArms))
     96   (equal? (V.vValidate malformedTail)
     97     (err (V.vDiagnostic "malformed" 0 ["output"] "match arm list") t))
     98   (equal? (L.lCompile malformedTail) (V.vValidate malformedTail))
     99   (equal? (V.vValidate malformedArm)
    100     (err (V.vDiagnostic "malformed" 0 ["output"] "match arm") t))
    101   (resultIsOk source)
    102   (resultIsOk (L.lCompile sourceIR))
    103   (compare sourceIR sourceWorker t)
    104   (equal? (S.runConsumer sourceIR t) (ok 1 t))
    105   (compare sourceIR sourceWorker (t 7))
    106   (equal? (S.runConsumer sourceIR (t 7)) (ok 7 t))]
    107 main = matchBool "consumer-boundary-ok" "consumer-boundary-DIFFER" checks
    108 main