Tricu 2.0.0

Sorry for squashing all of this but 🤷
This commit is contained in:
2026-05-25 12:43:15 -05:00
parent 2e2db07bd6
commit fdebb6c13d
105 changed files with 10139 additions and 1938 deletions

View File

@@ -0,0 +1,137 @@
# View Contract Demos
These demos exercise the finalized View Contract stack in `lib/view.tri`:
portable View Trees/checkable typed-program nodes, structural View flow checks,
runtime guarded Views, checked-exec, source annotations, and module-boundary
View metadata.
## End-user guide
Start here. `demos/viewContracts.tri` is written with normal source annotation
sugar and reads as a short guide to View Contracts: motivating structural
mismatches, explaining plain Views, noting why this is not a full static type
system, and building a custom `NonEmptyList` guarded View.
```bash
tricu check demos/viewContracts.tri
```
Expected output:
```text
ok
```
## Complete explicit demo
`demos/viewContracts/complete.tri` shows the same layer from the portable
View Tree/checkable-program side. It uses explicit builders such as
`typedValue`, `typedRequire`, and `typedApply`, and demonstrates contextual guard
diagnostics, observation composition, reachability, and malformed guard output.
```bash
tricu eval demos/viewContracts/complete.tri -f decode
```
## Portable checker self-tests
Runs the checker self-test suite carried as ordinary `tricu` code.
```bash
tricu eval demos/viewContracts/selfTests.tri -f decode
```
Expected output is a list of `"ok"` strings.
## Diagnostic rendering
Shows a strict-mode structural View failure rendered for humans.
```bash
tricu eval demos/viewContracts/diagnostic.tri -f decode
```
Expected output:
```text
"symbol 162 expected List Bool but got List String"
```
## Stdlib-shaped contracts
Checks successful higher-order contracts shaped like common stdlib APIs.
```bash
tricu eval demos/viewContracts/stdlibContracts.tri -f decode
```
Expected output:
```text
["ok", "ok", "ok", "ok", "ok"]
```
These examples are structural View checks, not runtime guarded checks.
## Frontend emission layer
`frontendEmission/` documents the portable artifact shape a frontend can emit
after parsing/elaboration. The `*.source.txt` files are pseudo-source; the
matching `*.emitted.tri` files are explicit typed-program builder output.
This layer is still instructive because it shows the exact bridge between source
syntax and portable View Tree/checkable metadata.
## Source syntax sugar
The `sourceSyntax/` demos use ergonomic annotations and the `tricu check`
frontend. The frontend lowers annotations to the same typed-program nodes used by
the explicit demos above, then executes checked-exec so guarded annotations fail
through the portable runner.
Successful check:
```bash
tricu check demos/viewContracts/sourceSyntax/success.tri
```
Expected output:
```text
ok
```
Labeled diagnostic check:
```bash
tricu check demos/viewContracts/sourceSyntax/failure.tri
```
Expected first failing diagnostic:
```text
symbol 4 (x) expected Bool but got String
```
If the first definition is fixed or removed, the later application-result
failure demonstrates callee-aware labels:
```text
symbol 3 (g application result) expected String but got Bool
```
## Module boundary layer
`modules/` shows producer-checked module export Views flowing into a consumer
check as module-boundary evidence. During auto-build, annotated exports are
checked before the module manifest alias is published. Consumers then use the
manifest's View Contract metadata as assumptions, while compatibility is still
judged by `lib/view.tri`.
```bash
tricu check demos/viewContracts/modules/success.tri
# ok
tricu check demos/viewContracts/modules/failure.tri
# symbol 3 (Util.toString application result) expected Bool but got String
```

View File

@@ -0,0 +1,119 @@
!import "prelude" !Local
!import "view" !Local
-- Complete explicit View Contract demo.
-- Run with: tricu eval demos/viewContracts/complete.tri -f decode
--
-- This file uses the low-level portable typed-program builders directly. It is
-- useful for understanding what source annotations lower to. For the end-user
-- guide, see demos/viewContracts.tri.
requireNonEmpty = (xs :
lazyBool
(_ : guardFail)
(_ : guardOk xs)
(emptyList? xs))
NonEmptyList = (elemView :
viewGuarded (viewList elemView) requireNonEmpty)
checkedResult = (result :
matchResult
(diag env : renderDiagnostic diag)
(exec env :
matchResult
(runtimeDiag runtimeEnv : renderDiagnostic runtimeDiag)
(value runtimeEnv : value)
(runChecked exec))
result)
checkedContract = (program :
checkedResult (checkTypedProgramWith policyStrict program))
plainViewFailure =
matchResult
(diag env : renderDiagnostic diag)
(exec env : "unexpected-ok")
(checkTypedProgramWith
policyStrict
(typedProgram
0
[(typedValue 0 (viewList viewString) [("Ada")])
(typedRequire 0 (viewList viewBool) t)]))
nonEmptyRootSuccess =
matchBool
"ok"
"unexpected-value"
(equal?
(checkedContract
(typedProgram
0
[(typedValue 0 (NonEmptyList viewString) [("Ada") ("Grace")])]))
[("Ada") ("Grace")])
nonEmptyRootFailure =
checkedContract
(typedProgram
0
[(typedValue 0 (viewList viewString) [])
(typedRequire 0 (NonEmptyList viewString) [])])
firstNameSuccess =
checkedContract
(typedProgram
2
[(typedValue 0 (viewFn [(NonEmptyList viewString)] viewString) (xs : head xs))
(typedValue 1 (viewList viewString) [("Ada") ("Grace")])
(typedApply 2 0 1 "Ada")
(typedRequire 2 viewString "Ada")])
firstNameFailure =
checkedContract
(typedProgram
2
[(typedValue 0 (viewFn [(NonEmptyList viewString)] viewString) (xs : head xs))
(typedValue 1 (viewList viewString) [])
(typedApply 2 0 1 t)
(typedRequire 2 viewString t)])
resultGuardFailure =
checkedContract
(typedProgram
2
[(typedValue 0 (viewFn [(viewString)] (NonEmptyList viewString)) (name : []))
(typedValue 1 viewString "Ada")
(typedApply 2 0 1 [])])
observationComposition =
checkedContract
(typedProgram
0
[(typedValue 0 viewString "Ada")
(typedRequire 0 (viewGuarded viewString (x : guardOk (append x " Lovelace"))) "Ada")
(typedRequire 0 (viewGuarded viewString (x : guardOk (append x "!"))) "Ada")])
unreachableGuard =
checkedContract
(typedProgram
0
[(typedValue 0 viewString "only the root is checked")
(typedValue 1 (viewList viewString) [])
(typedRequire 1 (NonEmptyList viewString) [])])
malformedGuard =
checkedContract
(typedProgram
0
[(typedValue 0 (viewGuarded viewString (x : record 99 t)) "bad guard")])
main = [
(append "plain View structural failure: " plainViewFailure)
(append "NonEmptyList root success: " nonEmptyRootSuccess)
(append "NonEmptyList root failure: " nonEmptyRootFailure)
(append "NonEmptyList function argument success: " firstNameSuccess)
(append "NonEmptyList function argument failure: " firstNameFailure)
(append "NonEmptyList function result failure: " resultGuardFailure)
(append "guard observations compose: " observationComposition)
(append "unreachable guard does not run: " unreachableGuard)
(append "malformed guard result: " malformedGuard)]

View File

@@ -0,0 +1,9 @@
!import "prelude" !Local
!import "view" !Local
!import "views.catalog" !Local
main =
matchResult
(diag env : renderDiagnostic diag)
(env rest : "ok")
(checkTypedProgramWith policyStrict listMapWrongListArgContract)

View File

@@ -0,0 +1,116 @@
# Frontend Emission Demos
These examples show the layer between source-level View annotations and the
portable View Contract checker.
Each `*.source.txt` file is pseudo-source: it is not parsed by `tricu`. It shows
the information a frontend has after parsing/elaboration.
Each matching `*.emitted.tri` file shows the lowered typed-program metadata that
a frontend can emit today. A successful check returns checked-exec; these demos
focus on structural Views, so they report `"ok"` as soon as metadata checking
succeeds. Guarded programs should run the returned checked-exec with
`runChecked`, as shown in `demos/viewContracts.tri` and by `tricu check`.
## Successful map use
Pseudo-source:
```text
map : Fn [Fn [Bool] String, List Bool] (List String)
f : Fn [Bool] String
xs : List Bool
partial = map f
out = partial xs
require out : List String
```
Run the emitted artifact:
```bash
tricu eval demos/viewContracts/frontendEmission/map-success.emitted.tri -f decode
```
Expected output:
```text
"ok"
```
## Wrong list argument
Pseudo-source:
```text
map : Fn [Fn [Bool] String, List Bool] (List String)
f : Fn [Bool] String
xs : List String
partial = map f
out = partial xs
```
Run:
```bash
tricu eval demos/viewContracts/frontendEmission/map-wrong-list.emitted.tri -f decode
```
Expected output:
```text
"symbol 162 expected List Bool but got List String"
```
## Wrong filter predicate
Pseudo-source:
```text
filter : Fn [Fn [Bool] Bool, List Bool] (List Bool)
pred : Fn [Bool] String
xs : List Bool
partial = filter pred
out = partial xs
```
Run:
```bash
tricu eval demos/viewContracts/frontendEmission/filter-wrong-predicate.emitted.tri -f decode
```
Expected output:
```text
"symbol 181 expected Fn [Bool] Bool but got Fn [Bool] String"
```
## Lowering shape
A frontend does not need to expose `tricu` syntax internally. It only needs to
emit portable typed-program nodes:
```text
typedValue symbol view term
typedApply out callee arg term
typedRequire symbol view term
```
The source-level flow:
```text
out = map f xs
```
lowers to curried Tree Calculus application nodes:
```text
typedApply partial map f partialTerm
typedApply out partial xs outTerm
```
Function Views drive argument checking and result inference.

View File

@@ -0,0 +1,17 @@
!import "prelude" !Local
!import "view" !Local
!import "views.catalog" !Local
-- Lowering of filter-wrong-predicate.source.txt to portable typed-program metadata.
-- Symbols:
-- 180 filter
-- 181 pred
-- 182 partial
program = listFilterWrongPredicateContract
main =
matchResult
(diag env : renderDiagnostic diag)
(env rest : "unexpected-ok")
(checkTypedProgramWith policyStrict program)

View File

@@ -0,0 +1,20 @@
!import "prelude" !Local
!import "view" !Local
!import "views.catalog" !Local
-- Lowering of map-success.source.txt to portable typed-program metadata.
-- Symbols:
-- 100 map
-- 101 f
-- 102 xs
-- 103 partial
-- 104 out
program =
listMapUseContract viewBool viewString 100 101 102 103 104
main =
matchResult
(diag env : renderDiagnostic diag)
(env rest : "ok")
(checkTypedProgramWith policyStrict program)

View File

@@ -0,0 +1,19 @@
!import "prelude" !Local
!import "view" !Local
!import "views.catalog" !Local
-- Lowering of map-wrong-list.source.txt to portable typed-program metadata.
-- Symbols:
-- 160 map
-- 161 f
-- 162 xs
-- 163 partial
-- 164 out
program = listMapWrongListArgContract
main =
matchResult
(diag env : renderDiagnostic diag)
(env rest : "unexpected-ok")
(checkTypedProgramWith policyStrict program)

View File

@@ -0,0 +1,30 @@
!import "prelude" !Local
!import "io" !Local
!import "view" !Local
-- View Contracts inside IO continuations
-- Run with:
--
-- tricu eval demos/viewContracts/io-continuation.tri --io -f decode
--
-- Checked IO evaluation instruments continuation bodies once from source
-- annotations. The IO runtime still executes ordinary interaction-tree actions;
-- the returned continuations already contain the checked-exec guard boundaries.
requireNonEmpty = (xs :
lazyBool
(_ : guardFail)
(_ : guardOk xs)
(emptyList? xs))
NonEmptyList elem = viewGuarded (viewList elem) requireNonEmpty
acceptNames xs@(NonEmptyList String) =@String "accepted"
useHandler handler@(Fn [(NonEmptyList String)] String) xs@(List String) =@String
handler xs
-- The IO action yields an empty list. The higher-order boundary requires a
-- handler that accepts NonEmptyList String, so the continuation-internal pure
-- call fails before returning the next IO value.
main = io (bind (pure []) (xs : pure (useHandler acceptNames xs)))

View File

@@ -0,0 +1,51 @@
!import "prelude" !Local
!import "io" !Local
!import "view" !Local
-- View Contracts + IO interaction trees
-- Run with:
--
-- tricu eval demos/viewContracts/io.tri --io -f decode
--
-- The IO runtime expects the top-level value to be an interaction tree wrapped
-- by the `io` sentinel:
--
-- pair "tricuIO" (pair version action)
--
-- View Contracts can validate that boundary before the IO driver starts. The IO
-- value is still just an interaction tree; this demo only checks how it was
-- exposed.
ioSentinel? = (value :
and?
(equal? (fst value) "tricuIO")
(equal? (fst (snd value)) 1))
requireIO = (value :
lazyBool
(_ : guardOk value)
(_ : guardFail)
(ioSentinel? value))
-- A first useful IO View is intentionally shallow:
--
-- viewAny -- accept any payload structurally
-- requireIO sentinel -- require the top-level IO wrapper at runtime
--
-- This does not prove every future continuation step is well-formed. It proves
-- the checked program exposes an IO interaction tree to the host driver.
viewIO = viewGuarded viewAny requireIO
checkedIO = (action :
matchResult
(diag env : io (pure (renderDiagnostic diag)))
(exec env :
matchResult
(runtimeDiag runtimeEnv : io (pure (renderDiagnostic runtimeDiag)))
(value runtimeEnv : value)
(runChecked exec))
(checkTypedProgramWith
policyStrict
(typedProgram 0 [(typedValue 0 viewIO action)])))
main = checkedIO (io (pure "checked interaction tree"))

View File

@@ -0,0 +1,17 @@
# Module View Contract demo
This demo shows producer-checked module export Views flowing into a consumer
check as trusted View Contract evidence.
```sh
tricu check demos/viewContracts/modules/success.tri
# ok
tricu check demos/viewContracts/modules/failure.tri
# symbol 3 (Util.toString application result) expected Bool but got String
```
`util.tri` is a local workspace module. During auto-build, its annotated exports
are checked before the module manifest alias is published. The consumer then
uses the manifest's View Contract metadata and View Tree export artifacts as
module-boundary assumptions; compatibility is still judged by `lib/view.tri`.

View File

@@ -0,0 +1,3 @@
!import "vc.demo.util" Util
foo x@Bool =@Bool Util.toString x

View File

@@ -0,0 +1,3 @@
!import "vc.demo.util" Util
foo x@Bool =@Bool Util.id x

View File

@@ -0,0 +1 @@
module vc.demo.util = util.tri

View File

@@ -0,0 +1,2 @@
id x@Bool =@Bool x
toString x@Bool =@String "ok"

View File

@@ -0,0 +1,3 @@
!import "views.catalog" !Local
main = viewCatalogSelfTests

View File

@@ -0,0 +1,9 @@
-- Source-level View Contract diagnostic demo.
-- Run with: tricu check demos/viewContracts/sourceSyntax/failure.tri
makeBool x@String =@Bool x
xs =@(List String) [(g "hi")]
g y@String =@Bool y
main = "if you're seeing this instead of an error, you ran the file unchecked"

View File

@@ -0,0 +1,10 @@
-- Source-level View Contract syntax sugar demo.
-- Run with: tricu check demos/viewContracts/sourceSyntax/success.tri
message =@String "hello"
boxedMessages =@(Maybe (List String)) just [(message) ("world")]
chooseFirst x@String y@Byte =@String x
fromLambda =@(Fn [String] String) (x : x)

View File

@@ -0,0 +1,10 @@
!import "prelude" !Local
!import "view" !Local
!import "views.catalog" !Local
main = [
(typedContractCheck listMapBoolStringContract)
(typedContractCheck headMaybeBoolContract)
(typedContractCheck listFilterBoolContract)
(typedContractCheck listFoldStringBoolContract)
(typedContractCheck listMapMaybeBoolStringContract)]