tricu

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

source_equation_cases.py (7884B)


      1 """Independent source/diagnostic expectations shared by compiler entrypoint tests."""
      2 import json
      3 
      4 def quoted(value):
      5     return json.dumps(value, ensure_ascii=False)
      6 
      7 
      8 def position(source, needle, occurrence=1, shift=0):
      9     offset = -1
     10     for _ in range(occurrence):
     11         offset = source.index(needle, offset + 1)
     12     offset += shift
     13     line = source[:offset].count("\n") + 1
     14     column = offset - source.rfind("\n", 0, offset)
     15     return f"(pair {line} (pair {column} {offset}))"
     16 
     17 
     18 cases = []
     19 
     20 
     21 def good(name, source, value, environment="[]"):
     22     cases.append((name, source, f"(ok {value} t)", environment, True))
     23 
     24 
     25 def bad(name, source, code, expected, found, needle=None, occurrence=1, shift=0):
     26     location = position(source, needle, occurrence, shift) if needle else "t"
     27     cases.append((name, source,
     28                   f"(err (parserDiagnostic {code} {expected} {found} {location} t) t)",
     29                   "[]", True))
     30 
     31 
     32 good("Leaf", "f t = 23\nf _ = 24\nmain = f t", "23")
     33 good("Stem", "f (t x) = x\nf _ = 24\nmain = f (t 23)", "23")
     34 good("Fork", "f (t x y) = [x y]\nf _ = []\nmain = f (t 23 24)", "[23 24]")
     35 good("Pair", "f (x, y) = [y x]\nf _ = []\nmain = f (t 23 24)", "[24 23]")
     36 good("Whole", "f all{x, y} = all\nf _ = t\nmain = f (t 23 24)", "(t 23 24)")
     37 good("WholeSpace", "f all {t x} = all\nf _ = t\nmain = f (t 23)", "(t 23)")
     38 good("NestedWhole", "f outer{t inner{t x} y} = [outer inner x y]\nf _ = []\nmain = f (t (t 23) 24)", "[(t (t 23) 24) (t 23) 23 24]")
     39 good("NestedSibling", "f ((t (t x)), (y, z)) = [x y z]\nf _ = []\nmain = f (t (t (t 23)) (t 24 25))", "[23 24 25]")
     40 good("Nil", "f [] = 23\nf _ = 24\nmain = f []", "23")
     41 good("Cons", "f [x | xs] = [x xs]\nf _ = []\nmain = f [23 24]", "[23 [24]]")
     42 good("ExactList", "f [x y] = [y x]\nf _ = []\nmain = f [23 24]", "[24 23]")
     43 good("ListMiss", "f [x y] = 23\nf _ = 24\nmain = f [23 24 25]", "24")
     44 good("WholeList", "f all{[x | xs]} = [all x xs]\nf _ = []\nmain = f [23 24]", "[[23 24] 23 [24]]")
     45 good("WholeWildcard", "f all{_} = all\nmain = f 23", "23")
     46 good("Number", "f 23 = 24\nf _ = 25\nmain = f 23", "24")
     47 good("String", 'f "a\\nb" = 24\nf _ = 25\nmain = f "a\\nb"', "24")
     48 good("False", "f t = 23\nf (t t) = 24\nf _ = 25\nmain = f t", "23")
     49 good("True", "f t = 23\nf (t t) = 24\nf _ = 25\nmain = f (t t)", "24")
     50 good("InvalidBoolStem", "f t = 23\nf (t t) = 24\nf _ = 25\nmain = f (t 23)", "25")
     51 good("InvalidBoolFork", "f t = 23\nf (t t) = 24\nf _ = 25\nmain = f (t t t)", "25")
     52 good("TwoArgs", "f t child = child\nf _ _ = 24\nmain = f t 23", "23")
     53 good("Partial", "f t x = x\nf _ _ = 24\npartial = f t\nmain = partial 23", "23")
     54 good("Closure", "f (t x) = y : [x y]\nf _ = y : [t y]\nmain = f (t 23) 24", "[23 24]")
     55 good("CaptureShadow", "x = 99\nf x = x\nmain = f 23", "23")
     56 good("FailedCapture", "f (x, t) = x\nf _ = 24\nmain = f (t 23 99)", "24")
     57 good("Ordered", "f x = 23\nf t = 24\nf _ = 25\nmain = f t", "23")
     58 good("BodyNoFallthrough", 'f t = err "body" t\nf _ = 24\nmain = f t', '(err "body" t)', '[(pair "err" err)]')
     59 good("PinForward", "f ^expected = 23\nf _ = 24\nexpected = 25\nmain = f 25", "23")
     60 good("PinMiss", "expected = 25\nf ^expected = 23\nf _ = 24\nmain = f 26", "24")
     61 good("QualifiedPin", "f ^Outer.value = 23\nf _ = 24\nmain = f 25", "23", '[(pair "Outer.value" 25)]')
     62 good("LocalLet", "main = let\n  f t = 23\n  f _ = 24\n  g x = f x\nin g t", "23")
     63 good("LocalWhere", "main = g t where\n  f t = 23\n  f _ = 24\n  g x = f x", "23")
     64 good("LocalPin", "main = let expected = 25 in let\n  f ^expected = 23\n  f _ = 24\nin f expected", "23")
     65 good("LocalClosure", "main = (outer : let\n  f (t x) = y : [outer x y]\n  f _ = y : [outer t y]\nin f (t 23) 24) 25", "[25 23 24]")
     66 good("InlineLet", "main = let f x = x in f 23", "23")
     67 good("InlineWhere", "main = f 23 where f x = x", "23")
     68 good("CommentGroup", "f t = 23\n-- same group\n\nf _ = 24\nmain = f t", "23")
     69 good("BlockComment", "f t = 23\n|-same group-|\nf _ = 24\nmain = f t", "23")
     70 good("DeeperBody", "f t = (x : x)\n  23\nf _ = 24\nmain = f t", "23")
     71 good("NestedLet", "main = let\n  f t = let\n    g t = 23\n    g _ = 24\n  in g t\n  f _ = 25\nin f t", "23")
     72 good("LocalOuterShadow", "f x = 23\nmain = let f x = f x in f t", "23")
     73 good("LocalEarlierPin", "main = let\n  expected = 25\n  f ^expected = 23\n  f _ = 24\nin f 25", "23")
     74 good("PatternBodyDependency", "f (t x) = helper x\nf _ = 24\nmain = f (t 23)\nhelper x = x", "23")
     75 
     76 good("ZeroIsLeaf", "f 0 = 23\nf _ = 24\nmain = f t", "23")
     77 good("MultilineTreePattern", "f (t\n  x\n  y) = [x y]\nf _ = []\nmain = f (t 23 24)", "[23 24]")
     78 good("MultilinePairPattern", "f (x\n ,\n y) = [x y]\nf _ = []\nmain = f (t 23 24)", "[23 24]")
     79 good("NestedPinScope", "f (t x) = let\n  g ^x = 23\n  g _ = 24\nin g x\nf _ = 25\nmain = f (t 26)", "23")
     80 
     81 worker = ("worker self t = 0\nworker self (t x) = 0\n"
     82           "worker self whole{x, y} = self whole\nworker _ _ = 0\n"
     83           "loop input = y worker input\n")
     84 good("LazyLater", worker + "f t = 23\nf x = loop x\nmain = f t", "23", '[(pair "y" y)]')
     85 good("LazyEarlier", worker + "f (t x y) = loop (t x y)\nf _ = 23\nmain = f t", "23", '[(pair "y" y)]')
     86 good("UnreachedPin", worker + "main = (outer : let expected = loop outer in let\n  f t ^expected = 24\n  f _ _ = 23\nin f (t 99) t) (t 23 24)", "23", '[(pair "y" y)]')
     87 
     88 bad("DuplicateCapture", "f x x = x\nmain = f t t", 48, '"unique capture"', '"x"', "x", 2)
     89 bad("WholeDuplicate", "f x{x} = x\nmain = f t", 48, '"unique capture"', '"x"', "x", 2)
     90 bad("PinCollision", "x = 25\nf x ^x = x\nf _ _ = t\nmain = f t t", 48, '"pin outside equation captures"', '"x"', "^x", shift=1)
     91 bad("PinLaterCapture", "x = 25\nf ^x x = x\nf _ _ = t\nmain = f t t", 48, '"pin outside equation captures"', '"x"', "^x", shift=1)
     92 bad("Catchall", "f t = 23\nmain = f t", 48, '"final irrefutable equation"', "t", "23")
     93 bad("Arity", "f t x = x\nf _ = 23\nmain = t", 48, '"consistent arity"', "1", "23")
     94 bad("Redefinition", "f t = 23\nf _ = 24\ng x = x\nf _ = 25\nmain = t", 30, '"f"', '"f"', "f _", 2)
     95 bad("ZeroArity", "f = 23\nf = 24\nmain = t", 30, '"f"', '"f"', "f =", 2)
     96 bad("LocalRedefinition", "main = let\n  f x = x\n  g x = x\n  f x = x\nin t", 30, '"f"', '"f"', "f x", 2)
     97 bad("LocalForward", "main = let\n  f x = g x\n  g x = x\nin f t", 20, '"g"', "t", "g x")
     98 bad("LocalSelf", "main = let\n  f x = f x\nin f t", 20, '"f"', "t", "f x", 2)
     99 bad("MissingPin", "f ^missing = 23\nf _ = 24\nmain = f t", 20, '"missing"', "t", "missing")
    100 bad("EmptyWhole", "f all{} = 23\nf _ = 24\nmain = t", 48, '"pattern"', "23", "}")
    101 bad("TooManyChildren", "f (t x y z) = 23\nf _ = 24\nmain = t", 48, '"at most two tree children"', "4", ")")
    102 bad("EmptyPrefix", "f [|tail] = 23\nf _ = 24\nmain = t", 48, '"nonempty list prefix"', "11", "=")
    103 bad("WildcardNoCapture", "f _ = _\nmain = f t", 20, '"_"', "t", "_", 2)
    104 bad("LetIndent", "main = let\nf x = x\nin f t", 40, '"indented local block"', "2", "f x")
    105 bad("WhereIndent", "main = f t where\nf x = x", 40, '"indented local block"', "2", "f x")
    106 bad("AnnotatedGroup", "f x@missing = x\nf y = y\nmain = t", 30, '"f"', '"f"', "f y")
    107 bad("DuplicateBeforeMissing", "f x x = missing\nmain = t", 48, '"unique capture"', '"x"', "x", 2)
    108 bad("ArityBeforeMissing", "f t x = missing\nf _ = t\nmain = t", 48, '"consistent arity"', "1", "f _ = t", shift=6)
    109 bad("CatchallBeforeMissing", "f t = missing\nmain = t", 48, '"final irrefutable equation"', "t", "missing")
    110 bad("LocalDuplicateBeforeMissing", "main = let\n  f x x = missing\nin t", 48, '"unique capture"', '"x"', "x", 2)
    111 # The source syntax really checks values and original locations, rather than
    112 # merely succeeding for everything. Both controls must return false.
    113 cases.append(("WrongValue", cases[0][1], "(ok 99 t)", "[]", False))
    114 missing = "f ^missing = 23\nf _ = 24\nmain = f t"
    115 cases.append(("WrongLocation", missing,
    116               '(err (parserDiagnostic 20 "missing" t (pair 1 (pair 5 4)) t) t)', "[]", False))