Compare commits
No commits in common. "main" and "1.0.0-beta.18" have entirely different histories.
main
...
1.0.0-beta
@ -1,87 +0,0 @@
|
||||
# 1.0.0-beta.19 Test Discovery And User-Project Conformance Foundation
|
||||
|
||||
## Scope
|
||||
|
||||
`1.0.0-beta.19` is a compiler/tooling and conformance slice. It does
|
||||
not change the Slovo source language or standard library surface.
|
||||
|
||||
Add deterministic list-only test discovery for:
|
||||
|
||||
- `glagol test --list <file|project|workspace>`
|
||||
- `glagol --run-tests --list <file>` for the legacy single-file path
|
||||
|
||||
## Contract
|
||||
|
||||
List mode must reuse the same checked front-end path as normal test execution:
|
||||
parse, lower, type-check, resolve project/workspace inputs, discover tests, and
|
||||
apply `--filter <substring>`.
|
||||
|
||||
The command then lists discovered/selected tests without evaluating test bodies.
|
||||
It must not execute runtime calls from test bodies, mutate files through test
|
||||
logic, open sockets through test logic, or otherwise trigger user test
|
||||
side-effects.
|
||||
|
||||
Ordering must remain deterministic and match current test execution discovery:
|
||||
|
||||
- single-file tests keep source order
|
||||
- project tests keep existing module/package discovery order
|
||||
- workspace tests keep existing workspace/package discovery order
|
||||
|
||||
Normal `glagol test` behavior and output remain unchanged unless `--list` is
|
||||
present. Invalid files, projects, and workspaces still fail through the
|
||||
existing diagnostic path.
|
||||
|
||||
## Output Shape
|
||||
|
||||
The initial output format is beta tooling. It should be stable enough for local
|
||||
release-gate tests, but it is not a frozen public schema.
|
||||
|
||||
The output should make selected, skipped, total discovered, and filter state
|
||||
visible. A concise text shape is enough; a stable JSON/event stream is out of
|
||||
scope for this slice.
|
||||
|
||||
## Non-Scope
|
||||
|
||||
This scope does not add:
|
||||
|
||||
- source-language syntax
|
||||
- runtime helper names
|
||||
- JSON expansion
|
||||
- parallel test execution
|
||||
- retries
|
||||
- tags or groups
|
||||
- coverage reports
|
||||
- event streams
|
||||
- stable artifact-manifest schema freeze
|
||||
- stable Markdown schema freeze
|
||||
- LSP or watch behavior
|
||||
- SARIF or daemon protocols
|
||||
- package registries
|
||||
- semver solving
|
||||
- performance claims
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `glagol test --list <file.slo>` lists checked/discovered tests without
|
||||
executing bodies.
|
||||
- `glagol test --list <project>` and workspace inputs preserve current
|
||||
project/workspace ordering.
|
||||
- `glagol --run-tests --list <file.slo>` works for the legacy single-file path.
|
||||
- `--filter <substring>` marks/selects the same tests as normal filtered
|
||||
execution while avoiding body evaluation.
|
||||
- Normal `glagol test` output stays byte-stable for existing covered cases.
|
||||
- Invalid inputs still emit existing diagnostics.
|
||||
- Docs describe beta19 as a released tooling/conformance slice.
|
||||
- Release-gate coverage includes the focused beta19 test-discovery suite.
|
||||
|
||||
## Suggested Gates
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
cargo test --test test_discovery_beta19
|
||||
cargo test --test project_mode
|
||||
cargo test --test cli_v1_1
|
||||
cargo test --test diagnostics_schema_beta13
|
||||
cargo test
|
||||
./scripts/release-gate.sh
|
||||
```
|
||||
@ -1,89 +0,0 @@
|
||||
# 1.0.0-beta.20 String Search And ASCII Trim Foundation
|
||||
|
||||
## Scope
|
||||
|
||||
`1.0.0-beta.20` is a standard-library and compiler-gate slice. It does not
|
||||
change source-language syntax, runtime C, compiler-known runtime names, or
|
||||
ABI/layout policy.
|
||||
|
||||
The release adds source-authored `std.string` helpers:
|
||||
|
||||
- `contains ((value string) (needle string)) -> bool`
|
||||
- `index_of_option ((value string) (needle string)) -> (option i32)`
|
||||
- `last_index_of_option ((value string) (needle string)) -> (option i32)`
|
||||
- `trim_ascii_start ((value string)) -> string`
|
||||
- `trim_ascii_end ((value string)) -> string`
|
||||
- `trim_ascii ((value string)) -> string`
|
||||
|
||||
## Contract
|
||||
|
||||
Search is byte-oriented over the current runtime string representation.
|
||||
`index_of_option` returns the first zero-based byte offset for a matching
|
||||
needle, `last_index_of_option` returns the last zero-based byte offset, and
|
||||
`contains` is true when `index_of_option` returns `some`.
|
||||
|
||||
Empty needles are valid:
|
||||
|
||||
- `index_of_option value ""` returns `some 0`
|
||||
- `last_index_of_option value ""` returns `some (len value)`
|
||||
- `contains value ""` returns `true`
|
||||
|
||||
Missing needles return `none`.
|
||||
|
||||
ASCII trim removes only these byte values from the requested edges:
|
||||
|
||||
- `9` horizontal tab
|
||||
- `10` line feed
|
||||
- `11` vertical tab
|
||||
- `12` form feed
|
||||
- `13` carriage return
|
||||
- `32` space
|
||||
|
||||
The helpers compose over already-promoted string primitives:
|
||||
|
||||
- `std.string.len`
|
||||
- `std.string.byte_at_result`
|
||||
- `std.string.slice_result`
|
||||
- `std.string.starts_with`
|
||||
- `std.string.ends_with`
|
||||
|
||||
## Non-Scope
|
||||
|
||||
This scope does not add:
|
||||
|
||||
- compiler-known `std.string.*` runtime names for the new helpers
|
||||
- runtime C helper implementations
|
||||
- source-language syntax
|
||||
- Unicode scalar, grapheme, display-width, or normalization semantics
|
||||
- case folding or locale-sensitive search
|
||||
- regular expressions
|
||||
- tokenizer/parser APIs
|
||||
- mutable strings
|
||||
- language slice/view syntax
|
||||
- stable string ABI/layout
|
||||
- stable allocation ownership rules
|
||||
- stable standard-library compatibility
|
||||
- performance claims
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `lib/std/string.slo` exports all six helpers.
|
||||
- Explicit `std.string` import examples exercise contains, first/last search,
|
||||
missing needles, empty needles, leading trim, trailing trim, full trim,
|
||||
all-whitespace trim, and no-trim cases.
|
||||
- Local `std-layout-local-string` examples mirror the public helper surface.
|
||||
- Focused compiler coverage verifies the helpers are source-authored and that
|
||||
direct compiler-known runtime calls for the new names remain unsupported.
|
||||
- `scripts/release-gate.sh` runs the focused beta20 test.
|
||||
- Generated standard-library API documentation includes the new signatures.
|
||||
|
||||
## Gates
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
cargo test --test standard_string_search_trim_beta20
|
||||
cargo test --test standard_string_source_fallback_helpers_alpha
|
||||
cargo test --test standard_string_scanning_beta16
|
||||
cargo test
|
||||
./scripts/release-gate.sh
|
||||
```
|
||||
@ -1,72 +0,0 @@
|
||||
# 1.0.0-beta.21 JSON Document Scalar Parsing Foundation
|
||||
|
||||
## Scope
|
||||
|
||||
`1.0.0-beta.21` is a standard-library and compiler-gate slice. It adds
|
||||
source-authored `std.json` helpers for scalar JSON documents while keeping
|
||||
source-language syntax, runtime C, compiler-known runtime names, and ABI/layout
|
||||
policy unchanged.
|
||||
|
||||
The release adds:
|
||||
|
||||
- `parse_string_document_result ((document string)) -> (result string i32)`
|
||||
- `parse_bool_document_result ((document string)) -> (result bool i32)`
|
||||
- `parse_i32_document_result ((document string)) -> (result i32 i32)`
|
||||
- `parse_u32_document_result ((document string)) -> (result u32 i32)`
|
||||
- `parse_i64_document_result ((document string)) -> (result i64 i32)`
|
||||
- `parse_u64_document_result ((document string)) -> (result u64 i32)`
|
||||
- `parse_f64_document_result ((document string)) -> (result f64 i32)`
|
||||
- `parse_null_document_result ((document string)) -> (result bool i32)`
|
||||
|
||||
## Contract
|
||||
|
||||
Each helper trims ASCII whitespace around the whole input document with
|
||||
`std.string.trim_ascii`, then delegates to the already released exact
|
||||
value-token parser for that scalar family.
|
||||
|
||||
Leading and trailing ASCII whitespace around one scalar document is accepted.
|
||||
Trailing non-whitespace remains an ordinary parse failure and returns `err 1`
|
||||
through the underlying exact parser.
|
||||
|
||||
## Non-Scope
|
||||
|
||||
This scope does not add:
|
||||
|
||||
- compiler-known `std.json.*_document_result` runtime names
|
||||
- private `__glagol_json_*document*` runtime symbols
|
||||
- runtime C helper implementations
|
||||
- source-language syntax
|
||||
- object or array parsing
|
||||
- recursive `JsonValue`
|
||||
- tokenizer/parser objects
|
||||
- maps, sets, executable generics, or generic collections
|
||||
- streaming parsers or encoders
|
||||
- Unicode escape decoding beyond the existing string-token helper
|
||||
- embedded NUL policy
|
||||
- stable JSON APIs
|
||||
- stable ABI/layout
|
||||
- stable standard-library compatibility
|
||||
- performance claims
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `lib/std/json.slo` exports all eight document scalar helpers.
|
||||
- Explicit `std.json` import examples exercise trimmed whitespace success,
|
||||
no-whitespace success, and trailing non-whitespace failure.
|
||||
- Local `std-layout-local-json` examples mirror the public helper surface with
|
||||
an explicit local `string` dependency for `trim_ascii`.
|
||||
- Focused compiler coverage verifies the helpers are source-authored and that
|
||||
direct compiler-known runtime calls for the new names remain unsupported.
|
||||
- `scripts/release-gate.sh` runs the focused beta21 test.
|
||||
- Generated standard-library API documentation includes the new signatures.
|
||||
|
||||
## Gates
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
cargo test --test standard_json_document_scalar_parsing_beta21
|
||||
cargo test --test standard_json_source_facade_alpha
|
||||
cargo test --test promotion_gate
|
||||
cargo test
|
||||
./scripts/release-gate.sh
|
||||
```
|
||||
@ -1,71 +0,0 @@
|
||||
# 1.0.0-beta.22 Run Manifest And Execution Report Hardening
|
||||
|
||||
## Scope
|
||||
|
||||
`1.0.0-beta.22` is a compiler/tooling evidence-hardening slice for
|
||||
`glagol run --manifest`. It keeps the Slovo source language, typed core,
|
||||
runtime capabilities, standard-library surface, compiler-known runtime names,
|
||||
ABI/layout policy, and package behavior unchanged.
|
||||
|
||||
The release adds an additive run-report block to run-mode artifact manifests
|
||||
so manifest evidence can record:
|
||||
|
||||
- process exit status for the invoked program
|
||||
- captured stdout from the run
|
||||
- captured stderr from the run
|
||||
- forwarded program arguments passed through `glagol run`
|
||||
|
||||
## Contract
|
||||
|
||||
When `glagol run --manifest <path>` completes far enough to write an artifact
|
||||
manifest, the manifest should include run execution evidence in addition to the
|
||||
existing schema marker, command, mode, success, diagnostics metadata, primary
|
||||
output, and artifacts fields.
|
||||
|
||||
The run-report data describes the native executable invocation performed by
|
||||
`glagol run`, not a new source-language or runtime feature. Captured stdout
|
||||
and stderr are evidence fields for tooling and release-gate review; they do
|
||||
not redefine ordinary terminal behavior. Forwarded args are recorded so
|
||||
fixtures can distinguish compiler arguments from user-program arguments.
|
||||
|
||||
The block is additive beta tooling metadata. It is not a stable public schema
|
||||
freeze and does not bump `slovo.artifact-manifest` version `1`.
|
||||
|
||||
## Non-Scope
|
||||
|
||||
This scope does not add:
|
||||
|
||||
- source-language syntax
|
||||
- standard-library helpers
|
||||
- compiler-known `std.*` runtime names
|
||||
- runtime C capabilities
|
||||
- package, workspace, import, or registry behavior
|
||||
- stable artifact-manifest schema freeze
|
||||
- stable Markdown schema freeze
|
||||
- LSP, watch, SARIF, or daemon protocols
|
||||
- performance claims
|
||||
- stable ABI/layout
|
||||
- beta maturity beyond the existing `1.0.0-beta` line
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `glagol run --manifest <path>` writes an artifact manifest with an additive
|
||||
run-report block after executing a supported program.
|
||||
- The run report records exit status, captured stdout, captured stderr, and
|
||||
forwarded args.
|
||||
- Existing manifest fields and schema/version markers remain compatible with
|
||||
the beta artifact-manifest contract.
|
||||
- Non-run modes do not need run-report metadata.
|
||||
- Documentation describes beta22 as tooling/CLI evidence hardening only.
|
||||
- Release notes and roadmaps state that beta22 does not add language or
|
||||
stdlib features and does not freeze the manifest schema.
|
||||
|
||||
## Suggested Gates
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
cargo test --test run_manifest_beta22
|
||||
cargo test --test cli_v1_1
|
||||
./scripts/release-gate.sh
|
||||
git diff --check
|
||||
```
|
||||
@ -1,73 +0,0 @@
|
||||
# 1.0.0-beta.23 Standard Library Stability Tier Ledger And Catalog Alignment
|
||||
|
||||
## Scope
|
||||
|
||||
`1.0.0-beta.23` is a documentation/catalog clarity slice for the standard
|
||||
library. It adds a public stability-tier ledger and aligns the surrounding
|
||||
README, roadmap, release-note, and specification text with the generated API
|
||||
catalog boundary.
|
||||
|
||||
This release does not change the source language, typed core, runtime
|
||||
capabilities, standard-library helper surface, compiler-known runtime names,
|
||||
ABI/layout policy, or package behavior. It does change generated catalog
|
||||
output and release-gate checks so tier metadata is visible and enforced.
|
||||
|
||||
## Contract
|
||||
|
||||
The public standard-library docs use exactly these tier labels:
|
||||
|
||||
- `beta-supported`
|
||||
- `experimental`
|
||||
- `internal`
|
||||
|
||||
The generated `docs/language/STDLIB_API.md` catalog remains the exact exported
|
||||
signature inventory generated from `lib/std/*.slo`. The new
|
||||
`docs/language/STDLIB_TIERS.md` ledger records maturity and stability
|
||||
expectations for those helpers and surrounding standard-library domains.
|
||||
|
||||
Experimental domains in the beta23 ledger include JSON, loopback networking,
|
||||
random/time, and filesystem resource-handle helpers. Concrete vector modules
|
||||
remain beta-supported concrete lanes; they are not a generic collections
|
||||
freeze and do not imply executable generics, maps, sets, iterators, mutable
|
||||
vectors, slice/view APIs, runtime collection changes, or stable ABI/layout.
|
||||
|
||||
## Non-Scope
|
||||
|
||||
This scope does not add:
|
||||
|
||||
- source-language syntax
|
||||
- standard-library helpers
|
||||
- compiler-known `std.*` runtime names
|
||||
- runtime C capabilities
|
||||
- package, workspace, import, or registry behavior
|
||||
- stable standard-library/API compatibility freeze
|
||||
- stable manifest schema freeze
|
||||
- stable Markdown schema freeze
|
||||
- stable ABI/layout
|
||||
- performance claims
|
||||
- beta maturity beyond the existing `1.0.0-beta` line
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `docs/language/STDLIB_TIERS.md` defines the public tier labels and their
|
||||
current meaning.
|
||||
- The tier ledger marks JSON, loopback networking, random/time, and filesystem
|
||||
resource-handle helpers as experimental domains.
|
||||
- The tier ledger records concrete vector modules as beta-supported concrete
|
||||
lanes without claiming generic collection stability.
|
||||
- README, `lib/std/README.md`, language release notes, language roadmap,
|
||||
post-beta roadmap, and the v1 spec link or describe the tier ledger.
|
||||
- Documentation states beta23 is docs/catalog tooling clarity only and does
|
||||
not add language, stdlib, runtime, stable schema, or stable API behavior.
|
||||
- The generated API catalog emits tier metadata, and the release gate checks
|
||||
that experimental tiers remain represented.
|
||||
|
||||
## Suggested Gates
|
||||
|
||||
```bash
|
||||
node --check scripts/render-stdlib-api-doc.js
|
||||
node --check scripts/check-stdlib-api-tiers.js
|
||||
./scripts/render-stdlib-api-doc.sh
|
||||
./scripts/check-stdlib-api-tiers.js
|
||||
git diff --check
|
||||
```
|
||||
@ -1,79 +0,0 @@
|
||||
# 1.0.0-beta.24 Package Manifest Identity And Dependency Discipline
|
||||
|
||||
## Scope
|
||||
|
||||
`1.0.0-beta.24` is a package/workspace discipline hardening slice for local
|
||||
manifest diagnostics. It tightens how package manifest identity and local
|
||||
dependency tables are reported when users write ambiguous or invalid manifest
|
||||
keys.
|
||||
|
||||
This release changes diagnostics only. It does not change the Slovo source
|
||||
language, typed core, runtime behavior, standard-library helper surface,
|
||||
compiler-known runtime names, package graph semantics, ABI/layout policy, or
|
||||
artifact/Markdown schema stability guarantees.
|
||||
|
||||
## Contract
|
||||
|
||||
The beta package model remains a closed local workspace model:
|
||||
|
||||
- package manifests declare `[package]` identity metadata and optional
|
||||
`[dependencies]` local path records
|
||||
- dependency keys name local packages and must match the target package name
|
||||
- dependency paths remain local path records under the existing workspace and
|
||||
package boundary checks
|
||||
|
||||
The beta24 diagnostic hardening makes these manifest errors explicit:
|
||||
|
||||
- duplicate keys in package manifests report `PackageManifestInvalid`
|
||||
- invalid dependency keys report `InvalidPackageDependencyName`
|
||||
- duplicate dependency keys report `DuplicatePackageDependencyName`
|
||||
|
||||
These diagnostics are part of the beta package/workspace discipline surface.
|
||||
They do not promote a package manager, resolver, lockfile, registry, publish
|
||||
flow, or stable package ABI/layout.
|
||||
|
||||
## Non-Scope
|
||||
|
||||
This scope does not add:
|
||||
|
||||
- remote registry behavior
|
||||
- lockfiles
|
||||
- semantic-version solving
|
||||
- package publishing
|
||||
- optional, dev, target, or feature-gated dependencies
|
||||
- build scripts or package archives
|
||||
- stable package ABI/layout
|
||||
- stable package manager behavior
|
||||
- source-language syntax or semantics
|
||||
- runtime behavior or runtime C capabilities
|
||||
- standard-library helpers or stdlib behavior
|
||||
- compiler-known `std.*` runtime names
|
||||
- stable artifact-manifest or Markdown schema guarantees
|
||||
- performance claims
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- `docs/language/PACKAGES.md` documents duplicate package-manifest keys,
|
||||
invalid dependency keys, and duplicate dependency keys as explicit beta
|
||||
diagnostics.
|
||||
- Language and compiler release notes describe beta24 as package manifest
|
||||
identity/dependency diagnostic hardening only.
|
||||
- Language and compiler roadmaps record beta24 as a local package/workspace
|
||||
diagnostics slice with all registry, lockfile, semver, publishing,
|
||||
optional/dev/target dependency, ABI/layout, language, runtime, and stdlib
|
||||
work deferred.
|
||||
- README and the post-beta roadmap identify `1.0.0-beta.24` as the current
|
||||
package/workspace discipline hardening slice.
|
||||
- Glagol is versioned as `1.0.0-beta.24`.
|
||||
- `compiler/tests/package_workspace_discipline_beta24.rs` covers the focused
|
||||
package manifest/dependency diagnostics and a positive local dependency
|
||||
workspace.
|
||||
- `scripts/release-gate.sh` runs the focused beta24 test.
|
||||
|
||||
## Suggested Gates
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
cargo fmt --check
|
||||
cargo test --test package_workspace_discipline_beta24
|
||||
```
|
||||
@ -1,55 +0,0 @@
|
||||
# 1.0.0-beta.19 Release Review
|
||||
|
||||
Scope: Test Discovery And User-Project Conformance Foundation
|
||||
|
||||
## Findings
|
||||
|
||||
No blocking findings.
|
||||
|
||||
The implementation matches the beta19 contract at the release-blocking level:
|
||||
`glagol test --list <file|project|workspace>` and legacy
|
||||
`glagol --run-tests --list <file>` route through checked discovery, avoid test
|
||||
body evaluation, preserve the existing discovery ordering, honor
|
||||
`--filter <substring>`, keep ordinary test output unchanged, and are wired into
|
||||
the release gate through `cargo test --test test_discovery_beta19`.
|
||||
|
||||
## Non-Blocking Notes
|
||||
|
||||
- Resolved during controller integration: unfiltered list output now prints the
|
||||
same summary suffix as filtered list output, including `total_discovered`,
|
||||
`selected`, `passed`, `failed`, `skipped`, and `filter none`.
|
||||
- Resolved during controller integration: the grammar typo in
|
||||
`docs/POST_BETA_ROADMAP.md` was corrected.
|
||||
|
||||
## Verification Notes
|
||||
|
||||
Inspected:
|
||||
|
||||
- Working tree status and beta19 diff across CLI parsing/dispatch, project test
|
||||
mode, test-runner listing, focused tests, docs, version files, and
|
||||
`scripts/release-gate.sh`.
|
||||
- Contract drift against
|
||||
`.llm/BETA_19_TEST_DISCOVERY_AND_CONFORMANCE.md`,
|
||||
`docs/language/SPEC-v1.md`, release notes, roadmaps, and README beta scope.
|
||||
- Cached diff status; no cached beta19 changes were present.
|
||||
|
||||
Read-only checks run:
|
||||
|
||||
- `git diff --check` - passed.
|
||||
- `git diff --cached --check` - passed.
|
||||
- Stale-version scan for beta18/beta19 references - no blocking stale current
|
||||
release references found.
|
||||
- Conflict-marker and trailing-whitespace scans for the untracked beta19
|
||||
contract/test files - passed.
|
||||
|
||||
Not run:
|
||||
|
||||
- `cargo fmt --check`, focused cargo tests, full `cargo test`, and
|
||||
`./scripts/release-gate.sh`; those commands write build artifacts, and this
|
||||
review was constrained to read-only commands except for the review file.
|
||||
|
||||
## Verdict
|
||||
|
||||
Release-ready from this review. No blocking beta19 issues remain in the current
|
||||
working tree diff. The controller should still run the focused beta19 test suite
|
||||
and full release gate before tagging.
|
||||
@ -1,95 +0,0 @@
|
||||
# 1.0.0-beta.20 Release Review
|
||||
|
||||
Scope: String Search And ASCII Trim Foundation
|
||||
|
||||
## Findings
|
||||
|
||||
No blocking findings.
|
||||
|
||||
The beta20 diff matches the documented release contract at the
|
||||
release-blocking level. `lib/std/string.slo:1` exports all six new helpers, and
|
||||
the implementations remain ordinary source helpers over the existing string
|
||||
facade primitives: first search at `lib/std/string.slo:30`, last search at
|
||||
`lib/std/string.slo:47`, `contains` at `lib/std/string.slo:64`, and ASCII trim
|
||||
at `lib/std/string.slo:71`. The local mirror in
|
||||
`examples/projects/std-layout-local-string/src/string.slo:1` exposes the same
|
||||
surface without changing the public contract shape.
|
||||
|
||||
The example coverage is explicit and scoped correctly. The standard import
|
||||
example covers present, missing, empty-needle, first/last index, leading trim,
|
||||
trailing trim, full trim, all-whitespace trim, and no-trim cases at
|
||||
`examples/projects/std-import-string/src/main.slo:204`; the documentation copy
|
||||
matches at `docs/language/examples/projects/std-import-string/src/main.slo:204`;
|
||||
the local fixture mirrors the same behavior at
|
||||
`examples/projects/std-layout-local-string/src/main.slo:204`.
|
||||
|
||||
The compiler gate coverage is aligned with the non-scope. The focused beta20
|
||||
test builds an explicit `std.string` import fixture at
|
||||
`compiler/tests/standard_string_search_trim_beta20.rs:47`, asserts the helpers
|
||||
are source-authored at `compiler/tests/standard_string_search_trim_beta20.rs:178`,
|
||||
and rejects direct compiler-known runtime calls for the new names. The existing
|
||||
local-string fallback test now expects and inventories the new helpers at
|
||||
`compiler/tests/standard_string_source_fallback_helpers_alpha.rs:8` and
|
||||
`compiler/tests/standard_string_source_fallback_helpers_alpha.rs:24`.
|
||||
The repo-root standard-source import gate and promotion gate are also aligned at
|
||||
`compiler/tests/standard_core_facade_source_search_alpha.rs:8`,
|
||||
`compiler/tests/standard_core_facade_source_search_alpha.rs:33`,
|
||||
`compiler/tests/promotion_gate.rs:1318`, and
|
||||
`compiler/tests/promotion_gate.rs:7368`.
|
||||
|
||||
## Contract Drift
|
||||
|
||||
No blocking contract drift found.
|
||||
|
||||
The README, language release notes, language roadmap, v1 spec, compiler release
|
||||
notes, compiler roadmap, post-beta roadmap, stdlib README, and beta20 `.llm`
|
||||
contract all describe the same narrow surface: byte-oriented search, empty
|
||||
needle behavior, ASCII-only trimming over bytes `9`, `10`, `11`, `12`, `13`,
|
||||
and `32`, no new compiler-known runtime names, no runtime C work, no new source
|
||||
syntax, and no Unicode, regex, tokenizer, mutable-string, stable ABI/layout, or
|
||||
stable stdlib/API claims. Representative anchors: `README.md:144`,
|
||||
`docs/language/RELEASE_NOTES.md:39`, `docs/language/ROADMAP.md:80`,
|
||||
`docs/language/SPEC-v1.md:232`, `docs/compiler/RELEASE_NOTES.md:15`,
|
||||
`docs/compiler/ROADMAP.md:100`, `docs/POST_BETA_ROADMAP.md:111`,
|
||||
`lib/std/README.md:233`, and
|
||||
`.llm/BETA_20_STRING_SEARCH_AND_ASCII_TRIM_FOUNDATION.md:1`.
|
||||
|
||||
The version and generated catalog updates are coherent: `compiler/Cargo.toml:3`
|
||||
and `compiler/Cargo.lock` are bumped to `1.0.0-beta.20`,
|
||||
`docs/language/STDLIB_API.md:18` reports 596 exported signatures, and
|
||||
`docs/language/STDLIB_API.md:486` lists 36 `std.string` signatures including
|
||||
the six beta20 helpers. `scripts/release-gate.sh:73` wires the focused beta20
|
||||
test into the release gate.
|
||||
|
||||
## Verification Notes
|
||||
|
||||
Inspected:
|
||||
|
||||
- Working tree diff and untracked beta20 contract/test files for std source,
|
||||
explicit std/local examples, docs, compiler tests, generated catalog, version
|
||||
bump, and release-gate integration.
|
||||
- Contract drift against README, language roadmap/spec/release notes, compiler
|
||||
roadmap/release notes, post-beta roadmap, stdlib README, and the beta20 `.llm`
|
||||
contract.
|
||||
- Sibling `glagol` repository status; no sibling worktree changes were present.
|
||||
|
||||
Read-only checks run:
|
||||
|
||||
- `git diff --check` - passed.
|
||||
- `git diff --cached --check` - passed.
|
||||
- `bash -n scripts/release-gate.sh` - passed.
|
||||
- `cargo fmt --check --manifest-path compiler/Cargo.toml` - passed.
|
||||
- Local/private publication text scan over source/docs/tests/.llm with build
|
||||
artifacts excluded - passed.
|
||||
|
||||
Not run:
|
||||
|
||||
- Focused cargo tests, full `cargo test`, and `./scripts/release-gate.sh`.
|
||||
Those commands write build/generated artifacts, and this review was
|
||||
constrained to read-only commands except for the review file.
|
||||
|
||||
## Verdict
|
||||
|
||||
Release-ready from this review. No blocking beta20 issues remain in the current
|
||||
working tree diff. The controller should still run the focused beta20 test stack
|
||||
and full release gate before tagging.
|
||||
@ -1,25 +0,0 @@
|
||||
# 1.0.0-beta.21 Glagol Implementation Notes
|
||||
|
||||
Scope: JSON Document Scalar Parsing Foundation.
|
||||
|
||||
This Glagol-side slice prepares compiler/test/release-gate coverage for the
|
||||
source-authored `std.json` document scalar helpers:
|
||||
|
||||
- `parse_string_document_result`
|
||||
- `parse_bool_document_result`
|
||||
- `parse_i32_document_result`
|
||||
- `parse_u32_document_result`
|
||||
- `parse_i64_document_result`
|
||||
- `parse_u64_document_result`
|
||||
- `parse_f64_document_result`
|
||||
- `parse_null_document_result`
|
||||
|
||||
The focused beta21 test uses an explicit `std.json` import, checks/formats/tests
|
||||
the imported helpers, requires the helpers to exist in `lib/std/json.slo`, and
|
||||
asserts that no `std.json.parse_*_document_result` compiler-known calls or
|
||||
private `__glagol_json_*document*` runtime symbols are introduced.
|
||||
|
||||
The JSON source-facade and promotion-gate inventories are updated to match the
|
||||
Slovo-side source/export/example work, which adds three JSON document scalar
|
||||
fixture tests and raises local and explicit `std.json` fixture output from 9 to
|
||||
12 tests.
|
||||
@ -1,52 +0,0 @@
|
||||
# 1.0.0-beta.21 Release Review
|
||||
|
||||
Scope: JSON Document Scalar Parsing Foundation.
|
||||
|
||||
## Findings
|
||||
|
||||
No blocking findings.
|
||||
|
||||
The uncommitted beta21 candidate matches the release contract:
|
||||
|
||||
- `lib/std/json.slo` exports all eight source-authored
|
||||
`parse_*_document_result` helpers.
|
||||
- Each document helper trims the whole input with `trim_ascii`, then delegates
|
||||
to the existing exact scalar value-token parser for the matching family.
|
||||
- Direct compiler-known `std.json.parse_*_document_result` calls are not
|
||||
introduced, and no private `__glagol_json_*document*` runtime symbol is
|
||||
introduced.
|
||||
- The explicit `std.json` example imports repo-root `std.json` and covers
|
||||
trimmed success, plain success, trailing non-whitespace failure, scalar
|
||||
token parsing, fields, arrays, objects, and 12 tests.
|
||||
- The local JSON example imports local `json`, the local `json` fixture imports
|
||||
local `string (trim_ascii)`, and it mirrors the same 12-test coverage.
|
||||
- Compiler coverage includes the focused beta21 test, JSON facade inventory,
|
||||
promotion-gate alignment, release-gate wiring, package version bump, and the
|
||||
generated standard-library API catalog signatures.
|
||||
- Release docs describe `1.0.0-beta.21` as released, and the source/docs scan
|
||||
did not find local/private publication text.
|
||||
|
||||
## Verification
|
||||
|
||||
Commands run:
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
git diff --cached --check
|
||||
bash -n scripts/release-gate.sh
|
||||
cargo fmt --check --manifest-path compiler/Cargo.toml
|
||||
cargo test --test standard_json_document_scalar_parsing_beta21
|
||||
cargo test --test standard_json_source_facade_alpha
|
||||
cargo test --test promotion_gate -- promotion_gate_artifacts_are_aligned
|
||||
```
|
||||
|
||||
Results:
|
||||
|
||||
- `standard_json_document_scalar_parsing_beta21`: 2 passed.
|
||||
- `standard_json_source_facade_alpha`: 2 passed.
|
||||
- `promotion_gate_artifacts_are_aligned`: 1 passed.
|
||||
- Formatting, shell syntax, and diff whitespace checks passed.
|
||||
- Targeted stale-release/private-text scans over source/docs paths passed.
|
||||
|
||||
Not run by design for this review: full `cargo test`, ignored smoke tests, and
|
||||
the full release gate.
|
||||
@ -1,45 +0,0 @@
|
||||
# Beta22 Release Review
|
||||
|
||||
Verdict: PASS with notes.
|
||||
|
||||
## Findings
|
||||
|
||||
No blocking or non-blocking findings in the reviewed scope.
|
||||
|
||||
## Scope Reviewed
|
||||
|
||||
- `compiler/src/main.rs` run manifest rendering and exit behavior.
|
||||
- `compiler/tests/run_manifest_beta22.rs` focused coverage.
|
||||
- `.llm/BETA_22_RUN_MANIFEST_AND_EXECUTION_REPORT_HARDENING.md` beta22 contract and suggested gates.
|
||||
- `README.md`, `docs/compiler/RELEASE_NOTES.md`, `docs/compiler/ROADMAP.md`, `docs/language/RELEASE_NOTES.md`, `docs/language/ROADMAP.md`, and `docs/language/SPEC-v1.md` release claims.
|
||||
- `scripts/release-gate.sh` inclusion.
|
||||
|
||||
## Acceptance Checklist
|
||||
|
||||
- PASS: `glagol run --manifest <path>` writes additive run execution evidence after a supported program executes. The run path captures child stdout/stderr/status before manifest rendering and exits with the child status in `compiler/src/main.rs:892` through `compiler/src/main.rs:918`; rendering emits `(run-report ...)` in `compiler/src/main.rs:2162` through `compiler/src/main.rs:2188`.
|
||||
- PASS: Run-report records exit status, captured stdout, captured stderr, and forwarded args. Tests cover success stdout and args in `compiler/tests/run_manifest_beta22.rs:10` through `compiler/tests/run_manifest_beta22.rs:60`, and nonzero exit plus stderr preservation in `compiler/tests/run_manifest_beta22.rs:62` through `compiler/tests/run_manifest_beta22.rs:128`.
|
||||
- PASS: Existing manifest fields and schema/version markers remain compatible. The new path passes `Some(run_report)` only through the run-specific wrapper in `compiler/src/main.rs:2019` through `compiler/src/main.rs:2043`; the renderer still emits `slovo.artifact-manifest` version `1` in `compiler/src/main.rs:2067` through `compiler/src/main.rs:2069`.
|
||||
- PASS: Source failures do not receive fake run evidence. The focused test asserts no run-report for a type failure in `compiler/tests/run_manifest_beta22.rs:130` through `compiler/tests/run_manifest_beta22.rs:161`.
|
||||
- PASS: Non-run modes are outside the run-report requirement. Existing foreign-import/project manifest wrappers pass `None` for the run-report slot in `compiler/src/main.rs:1992` through `compiler/src/main.rs:2017`; beta22 docs state this explicitly in `.llm/BETA_22_RUN_MANIFEST_AND_EXECUTION_REPORT_HARDENING.md:58` and `docs/compiler/RELEASE_NOTES.md:35`.
|
||||
- PASS: Documentation does not overclaim language, stdlib, runtime, package, ABI, or stable manifest-schema changes. Representative deferrals are present in `README.md:172` through `README.md:178`, `docs/compiler/ROADMAP.md:118` through `docs/compiler/ROADMAP.md:124`, `docs/language/RELEASE_NOTES.md:52` through `docs/language/RELEASE_NOTES.md:62`, `docs/language/ROADMAP.md:99` through `docs/language/ROADMAP.md:106`, and `docs/language/SPEC-v1.md:260` through `docs/language/SPEC-v1.md:267`.
|
||||
- PASS: The beta22 contract suggested gate names match the implemented focused test and release gate. `.llm/BETA_22_RUN_MANIFEST_AND_EXECUTION_REPORT_HARDENING.md:63` through `.llm/BETA_22_RUN_MANIFEST_AND_EXECUTION_REPORT_HARDENING.md:71` lists `cargo test --test run_manifest_beta22`; `scripts/release-gate.sh:75` includes the same focused test.
|
||||
|
||||
## Verification
|
||||
|
||||
Ran:
|
||||
|
||||
```bash
|
||||
cargo test --test run_manifest_beta22
|
||||
```
|
||||
|
||||
Result: passed, 3 tests passed.
|
||||
|
||||
Recommended before release tag:
|
||||
|
||||
```bash
|
||||
cargo fmt --check
|
||||
./scripts/release-gate.sh
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Note: the focused hosted-run tests depend on Clang discovery, matching existing project patterns. In this local run they executed and passed rather than skipping.
|
||||
@ -1,54 +0,0 @@
|
||||
# Beta23 Release Review
|
||||
|
||||
Verdict: PASS with notes.
|
||||
|
||||
## Findings
|
||||
|
||||
No blocking or non-blocking findings in the reviewed scope.
|
||||
|
||||
## Scope Reviewed
|
||||
|
||||
- `scripts/render-stdlib-api-doc.js` tier rendering.
|
||||
- `scripts/check-stdlib-api-tiers.js` tier gate.
|
||||
- `scripts/release-gate.sh` integration.
|
||||
- Generated `docs/language/STDLIB_API.md`.
|
||||
- `docs/language/STDLIB_TIERS.md`, README, release notes, roadmaps, and spec updates.
|
||||
- Compiler package version bump and compiler release documentation.
|
||||
|
||||
## Acceptance Checklist
|
||||
|
||||
- PASS: `docs/language/STDLIB_TIERS.md` defines the public tier labels and explains the current beta meaning. See `docs/language/STDLIB_TIERS.md:21` through `docs/language/STDLIB_TIERS.md:25`.
|
||||
- PASS: The tier ledger marks JSON, loopback networking, random/time, and filesystem resource-handle helpers as experimental domains. See `docs/language/STDLIB_TIERS.md:46` through `docs/language/STDLIB_TIERS.md:49`.
|
||||
- PASS: The tier ledger records concrete vector modules as beta-supported concrete lanes without claiming generic collection stability. See `docs/language/STDLIB_TIERS.md:44`.
|
||||
- PASS: The generated API catalog emits tier metadata and summary counts. See `docs/language/STDLIB_API.md:6` through `docs/language/STDLIB_API.md:24`.
|
||||
- PASS: Generated catalog classification matches the beta23 contract: filesystem handle helpers are experimental in `docs/language/STDLIB_API.md:115` through `docs/language/STDLIB_API.md:119`; `std.json`, `std.net`, `std.random`, and `std.time` are experimental in `docs/language/STDLIB_API.md:195` through `docs/language/STDLIB_API.md:240`, `docs/language/STDLIB_API.md:294` through `docs/language/STDLIB_API.md:308`, `docs/language/STDLIB_API.md:425` through `docs/language/STDLIB_API.md:432`, and `docs/language/STDLIB_API.md:540` through `docs/language/STDLIB_API.md:547`.
|
||||
- PASS: Concrete vector modules retain explicit no-generic-collection-freeze notes in generated output. Representative coverage is `docs/language/STDLIB_API.md:549` through `docs/language/STDLIB_API.md:554`, with the same note repeated for the other concrete `std.vec_*` modules.
|
||||
- PASS: The renderer implements the tier map and emits per-module/per-helper tiers. See `scripts/render-stdlib-api-doc.js:12` through `scripts/render-stdlib-api-doc.js:46`, `scripts/render-stdlib-api-doc.js:245` through `scripts/render-stdlib-api-doc.js:263`, and `scripts/render-stdlib-api-doc.js:297` through `scripts/render-stdlib-api-doc.js:330`.
|
||||
- PASS: The tier gate checks stale wording, summary tier definitions, experimental module/helper coverage, and vector boundary notes. See `scripts/check-stdlib-api-tiers.js:47` through `scripts/check-stdlib-api-tiers.js:80`.
|
||||
- PASS: `scripts/release-gate.sh` runs syntax checks for both tier scripts and executes the tier checker after catalog rendering. See `scripts/release-gate.sh:12` through `scripts/release-gate.sh:16`.
|
||||
- PASS: README, `lib/std/README.md`, language release notes, language roadmap, post-beta roadmap, and v1 spec link or describe the tier ledger and non-scope. Representative references: `README.md:69` through `README.md:79`, `lib/std/README.md:174` through `lib/std/README.md:184`, `docs/language/RELEASE_NOTES.md:53` through `docs/language/RELEASE_NOTES.md:69`, `docs/language/ROADMAP.md:109` through `docs/language/ROADMAP.md:119`, `docs/POST_BETA_ROADMAP.md:121` through `docs/POST_BETA_ROADMAP.md:132`, and `docs/language/SPEC-v1.md:268` through `docs/language/SPEC-v1.md:279`.
|
||||
- PASS: Documentation states beta23 is documentation/catalog tooling clarity only and does not add language, stdlib, runtime, stable schema, ABI/layout, or stable API behavior. See `docs/language/STDLIB_TIERS.md:10` through `docs/language/STDLIB_TIERS.md:15` and `docs/language/STDLIB_TIERS.md:52` through `docs/language/STDLIB_TIERS.md:68`.
|
||||
- PASS: Compiler package version and compiler release docs are aligned to `1.0.0-beta.23`. See `compiler/Cargo.toml:3`, `compiler/Cargo.lock:7`, `docs/compiler/RELEASE_NOTES.md:15` through `docs/compiler/RELEASE_NOTES.md:43`, and `docs/compiler/ROADMAP.md:126` through `docs/compiler/ROADMAP.md:132`.
|
||||
|
||||
## Verification
|
||||
|
||||
Ran:
|
||||
|
||||
```bash
|
||||
node --check scripts/render-stdlib-api-doc.js
|
||||
node --check scripts/check-stdlib-api-tiers.js
|
||||
./scripts/check-stdlib-api-tiers.js
|
||||
git diff --check
|
||||
rg -n '^- `experimental`' docs/language/STDLIB_API.md
|
||||
```
|
||||
|
||||
Result: all focused checks passed. The `rg` inspection confirmed 58 experimental helper signatures across the expected filesystem-handle, JSON, loopback networking, random, and time surfaces.
|
||||
|
||||
Recommended before release tag:
|
||||
|
||||
```bash
|
||||
./scripts/render-stdlib-api-doc.sh
|
||||
./scripts/release-gate.sh
|
||||
```
|
||||
|
||||
Note: run the full release gate after the generated catalog changes are staged or committed; the gate intentionally fails if `docs/language/STDLIB_API.md` has unstaged generated-doc drift.
|
||||
@ -1,66 +0,0 @@
|
||||
# Beta24 Release Review
|
||||
|
||||
Verdict: PASS.
|
||||
|
||||
## Findings
|
||||
|
||||
No blocking or non-blocking findings in the reviewed scope.
|
||||
|
||||
## Scope Reviewed
|
||||
|
||||
- `compiler/src/project.rs` package manifest diagnostics.
|
||||
- `compiler/tests/package_workspace_discipline_beta24.rs`.
|
||||
- `scripts/release-gate.sh` beta24 focused gate entry.
|
||||
- `compiler/Cargo.toml` and `compiler/Cargo.lock` version bump.
|
||||
- `.llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md`.
|
||||
- README, language package/diagnostic/release/roadmap docs, compiler release/roadmap docs, and post-beta roadmap updates.
|
||||
|
||||
## Acceptance Checklist
|
||||
|
||||
- PASS: Duplicate package manifest keys now use package-scoped diagnostics through `set_manifest_key(..., "PackageManifestInvalid", "package")` for package identity keys. See `compiler/src/project.rs:1505` through `compiler/src/project.rs:1545` and `compiler/src/project.rs:1752` through `compiler/src/project.rs:1771`.
|
||||
- PASS: Invalid dependency keys are rejected before graph validation with `InvalidPackageDependencyName`. See `compiler/src/project.rs:1556` through `compiler/src/project.rs:1572`.
|
||||
- PASS: Duplicate dependency keys are rejected before graph validation with `DuplicatePackageDependencyName`, and invalid/duplicate dependency records are not added to the dependency graph. See `compiler/src/project.rs:1573` through `compiler/src/project.rs:1593`.
|
||||
- PASS: Existing local-path-only dependency parsing and later dependency key/name matching remain in place. See `compiler/src/project.rs:1594` through `compiler/src/project.rs:1601`, `compiler/src/project.rs:1743` through `compiler/src/project.rs:1749`, and `compiler/src/project.rs:2970` through `compiler/src/project.rs:3005`.
|
||||
- PASS: Focused tests cover duplicate package keys, invalid dependency keys, duplicate dependency keys, and a clean local dependency workspace. See `compiler/tests/package_workspace_discipline_beta24.rs:11` through `compiler/tests/package_workspace_discipline_beta24.rs:109`.
|
||||
- PASS: `scripts/release-gate.sh` runs the beta24 focused test before full `cargo test`. See `scripts/release-gate.sh:68` through `scripts/release-gate.sh:82`.
|
||||
- PASS: The compiler package version is aligned to `1.0.0-beta.24` in both Cargo files. See `compiler/Cargo.toml:3` and `compiler/Cargo.lock:7`.
|
||||
- PASS: The beta24 contract defines diagnostics-only scope, explicit non-scope, acceptance criteria, and focused gates. See `.llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md:5` through `.llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md:79`.
|
||||
- PASS: README identifies `1.0.0-beta.24` as current and describes the package manifest/dependency diagnostic hardening scope without claiming package-manager, runtime, language, or stdlib changes. See `README.md:9` and `README.md:27` through `README.md:50`.
|
||||
- PASS: `docs/language/PACKAGES.md` documents duplicate package manifest keys, invalid dependency keys, and duplicate dependency keys as beta package/workspace diagnostics. See `docs/language/PACKAGES.md:59` through `docs/language/PACKAGES.md:73` and `docs/language/PACKAGES.md:111` through `docs/language/PACKAGES.md:130`.
|
||||
- PASS: `docs/language/DIAGNOSTICS.md` includes the new package/workspace diagnostic codes in the project/workspace catalog. See `docs/language/DIAGNOSTICS.md:240` through `docs/language/DIAGNOSTICS.md:279`.
|
||||
- PASS: Language and compiler release notes describe beta24 as package manifest identity/dependency diagnostic hardening only. See `docs/language/RELEASE_NOTES.md:44` through `docs/language/RELEASE_NOTES.md:68` and `docs/compiler/RELEASE_NOTES.md:15` through `docs/compiler/RELEASE_NOTES.md:42`.
|
||||
- PASS: Language/compiler roadmaps and post-beta roadmap mark beta24 as the current local package/workspace diagnostics slice with registry, lockfile, semver, publishing, optional/dev/target dependencies, ABI/layout, language, runtime, and stdlib work deferred. See `docs/language/ROADMAP.md:11` through `docs/language/ROADMAP.md:33`, `docs/compiler/ROADMAP.md:24` through `docs/compiler/ROADMAP.md:38`, `docs/compiler/ROADMAP.md:722` through `docs/compiler/ROADMAP.md:728`, and `docs/POST_BETA_ROADMAP.md:185` through `docs/POST_BETA_ROADMAP.md:191`.
|
||||
|
||||
## Verification Commands
|
||||
|
||||
Ran:
|
||||
|
||||
```bash
|
||||
git diff --check
|
||||
cargo fmt --check
|
||||
cargo test --test package_workspace_discipline_beta24
|
||||
cargo test --test project_mode workspace_package_boundaries_are_diagnostics
|
||||
cargo test --test project_mode
|
||||
rg -n "beta\\.23|beta23|beta\\.24|beta24|1\\.0\\.0-beta\\.2[0-9]|current|Release state|Last updated" README.md docs/language/PACKAGES.md docs/language/DIAGNOSTICS.md docs/language/RELEASE_NOTES.md docs/language/ROADMAP.md docs/compiler/RELEASE_NOTES.md docs/compiler/ROADMAP.md docs/POST_BETA_ROADMAP.md .llm/BETA_24_PACKAGE_MANIFEST_IDENTITY_AND_DEPENDENCY_DISCIPLINE.md compiler/Cargo.toml compiler/Cargo.lock scripts/release-gate.sh
|
||||
```
|
||||
|
||||
Result: all executed checks passed. The focused beta24 test reported 4 passed tests. The full `project_mode` suite reported 36 passed tests.
|
||||
|
||||
## Final Gate Disposition
|
||||
|
||||
After this review, the controller ran the full release gate:
|
||||
|
||||
```bash
|
||||
./scripts/release-gate.sh
|
||||
```
|
||||
|
||||
Result: PASS. The gate completed docs/catalog checks, focused beta13-beta24
|
||||
tests, full `cargo test`, ignored promotion smoke, ignored binary smoke, and
|
||||
ignored LLVM smoke.
|
||||
|
||||
## Residual Risks
|
||||
|
||||
- No release-blocking residual risks remain. The release gate regenerated and
|
||||
checked the standard-library API catalog; publication PDFs were not
|
||||
regenerated because this slice does not touch paper sources, and the gate
|
||||
verified that the required PDF artifacts are present.
|
||||
172
README.md
172
README.md
@ -6,7 +6,7 @@ This repository is the canonical public monorepo for the language design,
|
||||
standard library source, compiler, runtime, examples, benchmarks, and technical
|
||||
documents.
|
||||
|
||||
Current release: `1.0.0-beta.24`.
|
||||
Current release: `1.0.0-beta.18`.
|
||||
|
||||
## Repository Layout
|
||||
|
||||
@ -24,7 +24,7 @@ scripts/ local release and document tooling
|
||||
|
||||
## Beta Scope
|
||||
|
||||
`1.0.0-beta.24` keeps the `1.0.0-beta` language baseline, includes the
|
||||
`1.0.0-beta.18` keeps the `1.0.0-beta` language baseline, includes the
|
||||
`1.0.0-beta.1` tooling/install hardening slice, the `1.0.0-beta.2`
|
||||
runtime/resource foundation bundle, the `1.0.0-beta.3` standard-library
|
||||
stabilization bundle, the `1.0.0-beta.4` language-usability diagnostics
|
||||
@ -39,16 +39,8 @@ slice, the `1.0.0-beta.13` diagnostic catalog and schema policy slice, the
|
||||
`1.0.0-beta.14` benchmark suite catalog and metadata gate, and the
|
||||
`1.0.0-beta.15` reserved generic collection boundary hardening and collection
|
||||
ledger, the `1.0.0-beta.16` string scanning and token boundary foundation,
|
||||
the `1.0.0-beta.17` JSON primitive scalar parsing foundation, the
|
||||
`1.0.0-beta.18` JSON string token parsing foundation, the
|
||||
`1.0.0-beta.19` test discovery and user-project conformance foundation, the
|
||||
`1.0.0-beta.20` string search and ASCII trim foundation, and the
|
||||
`1.0.0-beta.21` JSON document scalar parsing foundation, plus the
|
||||
`1.0.0-beta.22` run manifest and execution report hardening slice, and the
|
||||
`1.0.0-beta.23` standard-library stability tier ledger and catalog alignment
|
||||
slice, and the `1.0.0-beta.24` package manifest identity and local dependency
|
||||
diagnostic hardening slice.
|
||||
|
||||
the `1.0.0-beta.17` JSON primitive scalar parsing foundation, and the
|
||||
`1.0.0-beta.18` JSON string token parsing foundation.
|
||||
The language baseline supports practical local command-line, file, and
|
||||
loopback-network programs with:
|
||||
|
||||
@ -63,22 +55,13 @@ loopback-network programs with:
|
||||
`SLOVO_STD_PATH`
|
||||
- beta-scoped loopback TCP handles through `std.net`
|
||||
- JSON string quoting, compact JSON text construction, primitive scalar token
|
||||
parsing, ASCII JSON string-token parsing, and scalar JSON document parsing
|
||||
through `std.json`
|
||||
- byte-oriented string search and ASCII edge trimming through `std.string`
|
||||
parsing, and ASCII JSON string-token parsing through `std.json`
|
||||
- hosted native builds through LLVM IR, Clang, and `runtime/runtime.c`
|
||||
|
||||
The generated standard-library API catalog is a beta discovery aid: it lists
|
||||
exported helper signatures from `lib/std/*.slo`, normalizes module-local
|
||||
concrete aliases such as `VecI32` and `ResultU64` to their concrete public
|
||||
types, and omits non-exported helpers and `(type ...)` aliases.
|
||||
The companion
|
||||
[`docs/language/STDLIB_TIERS.md`](docs/language/STDLIB_TIERS.md) ledger
|
||||
defines the public tier labels `beta-supported`, `experimental`, and
|
||||
`internal`, marks JSON, loopback networking, random/time, and filesystem
|
||||
resource-handle helpers as experimental domains, and keeps concrete vector
|
||||
modules as beta-supported concrete lanes rather than a generic collections
|
||||
freeze.
|
||||
`glagol symbols <file.slo|project|workspace>` emits deterministic
|
||||
editor-facing S-expression metadata for modules, imports, exports, aliases,
|
||||
structs, enums, functions, tests, source spans, and workspace package names.
|
||||
@ -86,11 +69,6 @@ structs, enums, functions, tests, source spans, and workspace package names.
|
||||
API sections for local package and module documentation: exact exported
|
||||
function signatures, exported struct fields, exported enum variants and payload
|
||||
types, non-export filtering, and module-local alias normalization.
|
||||
The `1.0.0-beta.22` tooling slice adds an additive run-report block to
|
||||
`glagol run --manifest` artifact manifests so local evidence can record the
|
||||
program exit status, captured stdout, captured stderr, and forwarded program
|
||||
arguments. This is beta CLI evidence hardening only: it does not add language
|
||||
or stdlib features and does not freeze the artifact-manifest schema.
|
||||
The `1.0.0-beta.12` vector parity slice adds source-authored helper coverage
|
||||
only: `std.vec_i64` gains `count_of`, `starts_with`, `without_prefix`,
|
||||
`ends_with`, and `without_suffix`, while `std.vec_f64` gains `count_of`.
|
||||
@ -140,87 +118,38 @@ concrete numeric primitives, and exact `null` only. Numeric and boolean parse
|
||||
helpers consume one isolated JSON primitive token: no leading/trailing
|
||||
whitespace, no leading `+`, no leading-zero integer form except `0`, and no
|
||||
non-finite f64 values. This is not full JSON parsing: object/array parsing,
|
||||
tokenizers, recursive `JsonValue`, document parsing beyond the beta21 scalar
|
||||
document helpers, schema validation, streaming, Unicode escape handling,
|
||||
stable ABI/layout, and a stable stdlib/API freeze remain deferred.
|
||||
tokenizers, recursive `JsonValue`, whitespace-tolerant document parsing,
|
||||
schema validation, streaming, Unicode escape handling, stable ABI/layout, and
|
||||
a stable stdlib/API freeze remain deferred.
|
||||
|
||||
The `1.0.0-beta.18` JSON string token parsing foundation adds
|
||||
`std.json.parse_string_value_result` as a thin source facade over the matching
|
||||
promoted runtime name. It consumes one already-isolated ASCII JSON string token
|
||||
with exact quotes and no leading/trailing whitespace, decodes the simple JSON
|
||||
escapes `\"`, `\\`, `\/`, `\b`, `\f`, `\n`, `\r`, and `\t`, and returns
|
||||
`err 1` for ordinary parse failure. Complete JSON document parsing beyond the
|
||||
beta21 scalar document helpers, object/array parsing, tokenizer APIs, Unicode
|
||||
escape decoding/normalization, embedded NUL policy, stable ABI/layout, and a
|
||||
stable stdlib/API freeze remain deferred.
|
||||
|
||||
The `1.0.0-beta.19` test discovery and user-project conformance foundation
|
||||
adds `glagol test --list <file|project|workspace>` plus legacy
|
||||
`glagol --run-tests --list <file>` support for listing checked and discovered
|
||||
tests without executing test bodies. The list mode preserves existing file,
|
||||
project, and workspace test ordering, honors `--filter <substring>`, and
|
||||
remains beta tooling rather than a stable output schema.
|
||||
|
||||
The `1.0.0-beta.20` string search and ASCII trim foundation adds
|
||||
`std.string.contains`, `std.string.index_of_option`,
|
||||
`std.string.last_index_of_option`, `std.string.trim_ascii_start`,
|
||||
`std.string.trim_ascii_end`, and `std.string.trim_ascii` as ordinary source
|
||||
helpers over the existing byte string primitives. Search is byte-oriented,
|
||||
empty needles match at the first index and at `(len value)` for last search,
|
||||
and ASCII trimming removes only bytes `9`, `10`, `11`, `12`, `13`, and `32`.
|
||||
|
||||
The `1.0.0-beta.21` JSON document scalar parsing foundation adds
|
||||
source-authored `std.json.parse_*_document_result` helpers for string, bool,
|
||||
`i32`, `u32`, `i64`, `u64`, `f64`, and exact `null` scalar JSON documents.
|
||||
Each helper trims ASCII whitespace around the whole document with
|
||||
`std.string.trim_ascii`, then delegates to the already released exact JSON
|
||||
value-token parser for that scalar family. This scope does not add new
|
||||
compiler-known runtime names, object/array parsing, recursive `JsonValue`,
|
||||
tokenizer objects, maps/sets, streaming, Unicode escape decoding beyond the
|
||||
existing string-token behavior, embedded NUL policy, stable ABI/layout, or a
|
||||
stable stdlib/API freeze.
|
||||
|
||||
The `1.0.0-beta.22` run manifest and execution report hardening slice extends
|
||||
`glagol run --manifest` artifact manifests with additive run-report evidence:
|
||||
the executed program's exit status, captured stdout, captured stderr, and
|
||||
forwarded user-program arguments. This release does not add source-language
|
||||
syntax, standard-library helpers, compiler-known runtime names, runtime
|
||||
capabilities, package behavior, stable artifact-manifest schema guarantees,
|
||||
stable ABI/layout, or a stable stdlib/API freeze.
|
||||
|
||||
The `1.0.0-beta.23` standard-library stability tier ledger and catalog
|
||||
alignment slice adds the public
|
||||
[`STDLIB_TIERS.md`](docs/language/STDLIB_TIERS.md) maturity ledger beside the
|
||||
generated [`STDLIB_API.md`](docs/language/STDLIB_API.md) signature catalog.
|
||||
It is documentation/catalog tooling clarity only: no source-language syntax,
|
||||
stdlib helpers, compiler-known runtime names, runtime behavior, stable manifest
|
||||
schema, stable Markdown schema, stable ABI/layout, or stable stdlib/API freeze
|
||||
changes. The generated catalog and release gate now expose and check tier
|
||||
metadata.
|
||||
|
||||
The `1.0.0-beta.24` package manifest identity and local dependency discipline
|
||||
slice tightens local manifest diagnostics only: duplicate package manifest
|
||||
keys, invalid dependency keys, and duplicate dependency keys are explicit beta
|
||||
package/workspace diagnostics. It does not add remote registries, lockfiles,
|
||||
semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, stable package ABI/layout, source-language changes, runtime
|
||||
changes, or standard-library changes.
|
||||
`err 1` for ordinary parse failure. Full JSON document parsing, object/array
|
||||
parsing, tokenizer APIs, Unicode escape decoding/normalization, embedded NUL
|
||||
policy, stable ABI/layout, and a stable stdlib/API freeze remain deferred.
|
||||
|
||||
Still deferred before stable: executable generics, generic aliases, maps/sets,
|
||||
broad package registry semantics, stable artifact-manifest schema, stable
|
||||
Markdown schema, stable stdlib/API compatibility freeze, DNS/TLS/async
|
||||
networking, LSP/watch guarantees, SARIF and daemon protocols, stable `1.0.0`
|
||||
diagnostics freeze,
|
||||
broad package registry semantics, stable Markdown schema, stable stdlib/API
|
||||
compatibility freeze, DNS/TLS/async networking, LSP/watch guarantees, SARIF
|
||||
and daemon protocols, stable `1.0.0` diagnostics freeze,
|
||||
re-exports/globs/hierarchical modules, mutable vectors, slice/view APIs,
|
||||
iterators, additional compiler-known runtime names, stable ABI and layout,
|
||||
performance claims, stable benchmark JSON metadata schema, and runtime changes
|
||||
for generic collections.
|
||||
|
||||
The beta19 tooling scope is deliberately tooling-only. It does not add parallel
|
||||
test execution, retries, tags/groups, coverage reports, event streams, stable
|
||||
manifest or Markdown schema guarantees, LSP/watch behavior, SARIF/daemon
|
||||
protocols, JSON expansion, runtime helper names, source-language syntax,
|
||||
remote package registries, semver solving, or performance claims.
|
||||
The next likely language slice after `1.0.0-beta.18` should continue from the
|
||||
developer-experience, package, benchmark metadata, collection, or string
|
||||
processing lanes without claiming executable generics, maps, sets, traits,
|
||||
inference, monomorphization, iterators, ABI stability, broad runtime changes,
|
||||
LSP/watch protocols, SARIF/daemon protocols, registry semantics, stable
|
||||
Markdown schema, stable benchmark JSON schema, a stable `1.0.0` diagnostics
|
||||
freeze, standard-library/API compatibility freeze, mutable vectors, language
|
||||
slice/view APIs, additional runtime names, Unicode/grapheme semantics, broader
|
||||
JSON object/array/full-value parsing, or performance claims until the contract
|
||||
and gates are explicit.
|
||||
|
||||
## Build And Test
|
||||
|
||||
@ -340,18 +269,6 @@ package/dependency summary, new workspace templates declare
|
||||
local-package rules. Remote registries, lockfiles, semantic-version solving,
|
||||
package publishing, and stable package ABI/layout remain deferred.
|
||||
|
||||
## 1.0.0-beta.24 Package Manifest Identity And Dependency Discipline
|
||||
|
||||
The `1.0.0-beta.24` release keeps the local package model closed and local. It
|
||||
hardens diagnostics for manifest identity/dependency mistakes only: duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
are reported explicitly.
|
||||
|
||||
This scope does not add a remote registry, lockfile, semantic-version solver,
|
||||
package publishing flow, optional/dev/target dependencies, stable package
|
||||
ABI/layout, source-language behavior, runtime behavior, or standard-library
|
||||
behavior.
|
||||
|
||||
## 1.0.0-beta.6 Networking Foundation
|
||||
|
||||
The `1.0.0-beta.6` release adds a narrow blocking loopback TCP foundation:
|
||||
@ -494,47 +411,6 @@ semantics; full JSON parsing; object/array parsing; tokenizer APIs; a language
|
||||
slice/view feature; mutable strings; stable ABI/layout; or a stable stdlib/API
|
||||
freeze.
|
||||
|
||||
## 1.0.0-beta.20 String Search And ASCII Trim Foundation
|
||||
|
||||
The `1.0.0-beta.20` scope extends the source-authored `std.string` facade
|
||||
with byte-oriented search and ASCII trim helpers:
|
||||
`contains`, `index_of_option`, `last_index_of_option`, `trim_ascii_start`,
|
||||
`trim_ascii_end`, and `trim_ascii`.
|
||||
|
||||
This scope adds no compiler-known runtime names. It does not claim Unicode
|
||||
scalar, grapheme, case-folding, locale, regex, tokenizer, mutable string,
|
||||
language slice/view, stable ABI/layout, or stable stdlib/API semantics.
|
||||
|
||||
## 1.0.0-beta.21 JSON Document Scalar Parsing Foundation
|
||||
|
||||
The `1.0.0-beta.21` scope extends `std.json` with source-authored
|
||||
whole-document scalar helpers:
|
||||
`parse_string_document_result`, `parse_bool_document_result`,
|
||||
`parse_i32_document_result`, `parse_u32_document_result`,
|
||||
`parse_i64_document_result`, `parse_u64_document_result`,
|
||||
`parse_f64_document_result`, and `parse_null_document_result`.
|
||||
|
||||
The helpers accept leading and trailing ASCII whitespace around a single
|
||||
scalar document by composing with `std.string.trim_ascii`; trailing
|
||||
non-whitespace still fails through the existing exact value-token parsers.
|
||||
|
||||
This scope does not add object/array parsing, recursive JSON values, parser
|
||||
objects, maps/sets, streaming, Unicode escape decoding beyond the existing
|
||||
string-token behavior, embedded NUL policy, new compiler-known runtime names,
|
||||
stable ABI/layout, or stable stdlib/API semantics.
|
||||
|
||||
## 1.0.0-beta.22 Run Manifest And Execution Report Hardening
|
||||
|
||||
The `1.0.0-beta.22` scope hardens `glagol run --manifest` evidence by adding
|
||||
an additive run-report block to run-mode artifact manifests. The block records
|
||||
the executed program's exit status, captured stdout, captured stderr, and
|
||||
forwarded program arguments.
|
||||
|
||||
This is tooling/CLI evidence work only. It does not add language syntax,
|
||||
stdlib helpers, compiler-known runtime names, runtime C capabilities, package
|
||||
or import behavior, stable artifact-manifest schema guarantees, stable
|
||||
ABI/layout, or stable stdlib/API semantics.
|
||||
|
||||
## 1.0.0-beta.15 Reserved Generic Collection Boundary Hardening And Collection Ledger
|
||||
|
||||
The `1.0.0-beta.15` release documents the current concrete collection and
|
||||
|
||||
2
compiler/Cargo.lock
generated
2
compiler/Cargo.lock
generated
@ -4,4 +4,4 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "glagol"
|
||||
version = "1.0.0-beta.24"
|
||||
version = "1.0.0-beta.18"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "glagol"
|
||||
version = "1.0.0-beta.24"
|
||||
version = "1.0.0-beta.18"
|
||||
edition = "2021"
|
||||
description = "Glagol, the first compiler for the Slovo language"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
@ -52,16 +52,6 @@ pub fn run_tests(
|
||||
test_runner::run(file, &checked, filter)
|
||||
}
|
||||
|
||||
pub fn list_tests(
|
||||
file: &str,
|
||||
source: &str,
|
||||
filter: Option<&str>,
|
||||
) -> Result<test_runner::TestRunSuccess, test_runner::TestRunFailure> {
|
||||
let checked =
|
||||
checked_program(file, source).map_err(test_runner::TestRunFailure::before_execution)?;
|
||||
Ok(test_runner::list(&checked, filter))
|
||||
}
|
||||
|
||||
fn checked_program(file: &str, source: &str) -> Result<check::CheckedProgram, Vec<Diagnostic>> {
|
||||
let tokens = lexer::lex(file, source)?;
|
||||
let forms = sexpr::parse(file, &tokens)?;
|
||||
|
||||
@ -184,13 +184,7 @@ fn run_project_check(invocation: Invocation) -> ! {
|
||||
}
|
||||
|
||||
fn run_project_test(invocation: Invocation) -> ! {
|
||||
let result = if invocation.test_list {
|
||||
project::list_tests(&invocation.path, invocation.test_filter.as_deref())
|
||||
} else {
|
||||
project::run_tests(&invocation.path, invocation.test_filter.as_deref())
|
||||
};
|
||||
|
||||
match result {
|
||||
match project::run_tests(&invocation.path, invocation.test_filter.as_deref()) {
|
||||
Ok(success) => {
|
||||
let output = success.output;
|
||||
let primary_output = if let Some(output_path) = invocation.output_path.as_deref() {
|
||||
@ -685,13 +679,7 @@ fn finish_formatted_source(
|
||||
|
||||
fn run_test_mode(invocation: Invocation, source: &str) -> ! {
|
||||
let foreign_imports = c_imports_for_manifest(&invocation.path, source);
|
||||
let result = if invocation.test_list {
|
||||
driver::list_tests(&invocation.path, source, invocation.test_filter.as_deref())
|
||||
} else {
|
||||
driver::run_tests(&invocation.path, source, invocation.test_filter.as_deref())
|
||||
};
|
||||
|
||||
match result {
|
||||
match driver::run_tests(&invocation.path, source, invocation.test_filter.as_deref()) {
|
||||
Ok(result) => {
|
||||
let output = result.output;
|
||||
let primary_output = if let Some(output_path) = invocation.output_path.as_deref() {
|
||||
@ -892,15 +880,14 @@ fn run_native_from_llvm(
|
||||
let _ = io::stdout().write_all(&run_output.stdout);
|
||||
let _ = io::stderr().write_all(&run_output.stderr);
|
||||
let stdout = String::from_utf8_lossy(&run_output.stdout).to_string();
|
||||
let stderr = String::from_utf8_lossy(&run_output.stderr).to_string();
|
||||
let exit_status = run_output.status.code();
|
||||
write_manifest_if_requested_with_run_report(
|
||||
write_manifest_if_requested_with_foreign_imports(
|
||||
&invocation,
|
||||
run_output.status.success(),
|
||||
PrimaryOutput::Stdout {
|
||||
kind: Mode::Run.output_kind(),
|
||||
text: &stdout,
|
||||
},
|
||||
None,
|
||||
Some(BuildInfo {
|
||||
clang: &native.clang,
|
||||
runtime: &native.runtime,
|
||||
@ -908,14 +895,8 @@ fn run_native_from_llvm(
|
||||
}),
|
||||
&foreign_imports,
|
||||
project_artifact.as_ref(),
|
||||
RunReport {
|
||||
exit_status,
|
||||
stdout: &stdout,
|
||||
stderr: &stderr,
|
||||
args: &invocation.run_args,
|
||||
},
|
||||
);
|
||||
process::exit(exit_status.unwrap_or(1));
|
||||
process::exit(run_output.status.code().unwrap_or(1));
|
||||
}
|
||||
|
||||
struct NativeBuild {
|
||||
@ -1120,7 +1101,6 @@ struct Invocation {
|
||||
project_template: scaffold::ProjectTemplate,
|
||||
link_c_paths: Vec<String>,
|
||||
test_filter: Option<String>,
|
||||
test_list: bool,
|
||||
run_args: Vec<String>,
|
||||
}
|
||||
|
||||
@ -1157,7 +1137,6 @@ fn parse_args(raw_args: &[String]) -> Result<Args, ParseError> {
|
||||
let mut project_template = scaffold::ProjectTemplate::Binary;
|
||||
let mut link_c_paths = Vec::new();
|
||||
let mut test_filter = None;
|
||||
let mut test_list = false;
|
||||
let mut run_args = Vec::new();
|
||||
let mut no_color = false;
|
||||
let command_line = raw_args.join(" ");
|
||||
@ -1366,17 +1345,6 @@ fn parse_args(raw_args: &[String]) -> Result<Args, ParseError> {
|
||||
command_line: command_line.clone(),
|
||||
})?);
|
||||
}
|
||||
"--list" => {
|
||||
if test_list {
|
||||
return parse_error(
|
||||
"`--list` was provided more than once",
|
||||
manifest_path,
|
||||
diagnostics,
|
||||
command_line,
|
||||
);
|
||||
}
|
||||
test_list = true;
|
||||
}
|
||||
"check" | "fmt" | "test" | "build" | "run" | "clean" | "new" | "doc" | "symbols"
|
||||
if path.is_none() =>
|
||||
{
|
||||
@ -1496,15 +1464,6 @@ fn parse_args(raw_args: &[String]) -> Result<Args, ParseError> {
|
||||
);
|
||||
}
|
||||
|
||||
if test_list && mode != Mode::RunTests {
|
||||
return parse_error(
|
||||
"`--list` is only supported with `test` and `--run-tests`",
|
||||
manifest_path,
|
||||
diagnostics,
|
||||
command_line,
|
||||
);
|
||||
}
|
||||
|
||||
if !run_args.is_empty() && mode != Mode::Run {
|
||||
return parse_error(
|
||||
"`--` program arguments are only supported with `run`",
|
||||
@ -1556,7 +1515,6 @@ fn parse_args(raw_args: &[String]) -> Result<Args, ParseError> {
|
||||
project_template,
|
||||
link_c_paths,
|
||||
test_filter,
|
||||
test_list,
|
||||
run_args,
|
||||
}))
|
||||
}
|
||||
@ -1630,7 +1588,6 @@ fn exit_parse_error(err: ParseError, command_line: &str) -> ! {
|
||||
project_template: scaffold::ProjectTemplate::Binary,
|
||||
link_c_paths: Vec::new(),
|
||||
test_filter: None,
|
||||
test_list: false,
|
||||
run_args: Vec::new(),
|
||||
};
|
||||
write_manifest_or_exit(
|
||||
@ -1643,7 +1600,6 @@ fn exit_parse_error(err: ParseError, command_line: &str) -> ! {
|
||||
PrimaryOutput::Diagnostics { text: &stderr },
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
&[],
|
||||
None,
|
||||
err.diagnostics,
|
||||
@ -1897,13 +1853,6 @@ struct TestSummary {
|
||||
filter: Option<String>,
|
||||
}
|
||||
|
||||
struct RunReport<'a> {
|
||||
exit_status: Option<i32>,
|
||||
stdout: &'a str,
|
||||
stderr: &'a str,
|
||||
args: &'a [String],
|
||||
}
|
||||
|
||||
fn test_summary_from_report(report: test_runner::TestReport) -> TestSummary {
|
||||
TestSummary {
|
||||
total_discovered: report.total_discovered,
|
||||
@ -2006,34 +1955,6 @@ fn write_manifest_if_requested_with_foreign_imports(
|
||||
success,
|
||||
primary_output,
|
||||
test_summary,
|
||||
None,
|
||||
build_info,
|
||||
foreign_imports,
|
||||
project_info,
|
||||
invocation.diagnostics,
|
||||
);
|
||||
write_manifest_or_exit(manifest_path, &manifest);
|
||||
}
|
||||
}
|
||||
|
||||
fn write_manifest_if_requested_with_run_report(
|
||||
invocation: &Invocation,
|
||||
success: bool,
|
||||
primary_output: PrimaryOutput<'_>,
|
||||
build_info: Option<BuildInfo<'_>>,
|
||||
foreign_imports: &[project::ProjectArtifactCImport],
|
||||
project_info: Option<&project::ProjectArtifact>,
|
||||
run_report: RunReport<'_>,
|
||||
) {
|
||||
if let Some(manifest_path) = invocation.manifest_path.as_deref() {
|
||||
let manifest = render_manifest(
|
||||
Some(&invocation.path),
|
||||
&invocation.command_line,
|
||||
Some(invocation.manifest_mode_name.as_str()),
|
||||
success,
|
||||
primary_output,
|
||||
None,
|
||||
Some(run_report),
|
||||
build_info,
|
||||
foreign_imports,
|
||||
project_info,
|
||||
@ -2057,7 +1978,6 @@ fn render_manifest(
|
||||
success: bool,
|
||||
primary_output: PrimaryOutput<'_>,
|
||||
test_summary: Option<TestSummary>,
|
||||
run_report: Option<RunReport<'_>>,
|
||||
build_info: Option<BuildInfo<'_>>,
|
||||
foreign_imports: &[project::ProjectArtifactCImport],
|
||||
project_info: Option<&project::ProjectArtifact>,
|
||||
@ -2159,34 +2079,6 @@ fn render_manifest(
|
||||
out.push_str(" )");
|
||||
}
|
||||
|
||||
if let Some(report) = run_report {
|
||||
out.push('\n');
|
||||
out.push_str(" (run-report\n");
|
||||
match report.exit_status {
|
||||
Some(status) => out.push_str(&format!(" (exit-status {})\n", status)),
|
||||
None => out.push_str(" (exit-status null)\n"),
|
||||
}
|
||||
out.push_str(&format!(
|
||||
" (stdout {})\n",
|
||||
diag::render_string(report.stdout)
|
||||
));
|
||||
out.push_str(&format!(
|
||||
" (stderr {})\n",
|
||||
diag::render_string(report.stderr)
|
||||
));
|
||||
out.push_str(" (args");
|
||||
if report.args.is_empty() {
|
||||
out.push_str(")\n");
|
||||
} else {
|
||||
out.push('\n');
|
||||
for arg in report.args {
|
||||
out.push_str(&format!(" (arg {})\n", diag::render_string(arg)));
|
||||
}
|
||||
out.push_str(" )\n");
|
||||
}
|
||||
out.push_str(" )");
|
||||
}
|
||||
|
||||
if let Some(build) = build_info {
|
||||
out.push('\n');
|
||||
out.push_str(" (hosted-build\n");
|
||||
@ -2675,6 +2567,6 @@ fn normalized_output_path(path: &str) -> Option<PathBuf> {
|
||||
|
||||
fn print_usage() {
|
||||
eprintln!(
|
||||
"usage: glagol [check|fmt|test|build|run|clean|symbols] [--json-diagnostics] [--no-color] [--manifest <path>] [--link-c <path>] [-o <path>] [--filter <substring>] [--list] <file.slo|project> [-- <program-args>...]\n glagol fmt [--check|--write] <file.slo|project>\n glagol new <project-dir> [--name <name>] [--template binary|library|workspace]\n glagol doc <file.slo|project> -o <dir>\n glagol symbols <file.slo|project|workspace>\n glagol [--emit=llvm|--format|--print-tree|--inspect-lowering=surface|--inspect-lowering=checked|--check-tests|--run-tests] [--json-diagnostics] [--no-color] [-o <path>] [--manifest <path>] [--filter <substring>] [--list] <file.slo>\n glagol --version"
|
||||
"usage: glagol [check|fmt|test|build|run|clean|symbols] [--json-diagnostics] [--no-color] [--manifest <path>] [--link-c <path>] [-o <path>] [--filter <substring>] <file.slo|project> [-- <program-args>...]\n glagol fmt [--check|--write] <file.slo|project>\n glagol new <project-dir> [--name <name>] [--template binary|library|workspace]\n glagol doc <file.slo|project> -o <dir>\n glagol symbols <file.slo|project|workspace>\n glagol [--emit=llvm|--format|--print-tree|--inspect-lowering=surface|--inspect-lowering=checked|--check-tests|--run-tests] [--json-diagnostics] [--no-color] [-o <path>] [--manifest <path>] [--filter <substring>] <file.slo>\n glagol --version"
|
||||
);
|
||||
}
|
||||
|
||||
@ -452,26 +452,6 @@ pub fn run_tests(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list_tests(
|
||||
input: &str,
|
||||
filter: Option<&str>,
|
||||
) -> Result<ProjectTestSuccess, ProjectTestFailure> {
|
||||
let checked = load_checked_project(input, false).map_err(|failure| ProjectTestFailure {
|
||||
diagnostics: failure.diagnostics,
|
||||
report: None,
|
||||
sources: failure.sources,
|
||||
artifact: failure.artifact,
|
||||
})?;
|
||||
|
||||
let success = test_runner::list(&checked.program, filter);
|
||||
Ok(ProjectTestSuccess {
|
||||
output: success.output,
|
||||
report: success.report,
|
||||
sources: checked.sources,
|
||||
artifact: checked.artifact,
|
||||
})
|
||||
}
|
||||
|
||||
struct CheckedProject {
|
||||
program: CheckedProgram,
|
||||
sources: Vec<SourceFile>,
|
||||
@ -1124,16 +1104,7 @@ fn parse_manifest(path: PathBuf, source: String) -> Result<Manifest, Vec<Diagnos
|
||||
};
|
||||
|
||||
match key {
|
||||
"name" => set_manifest_key(
|
||||
&file,
|
||||
&mut errors,
|
||||
&mut name,
|
||||
parsed,
|
||||
line.span,
|
||||
"name",
|
||||
"ProjectManifestInvalid",
|
||||
"project",
|
||||
),
|
||||
"name" => set_manifest_key(&file, &mut errors, &mut name, parsed, line.span, "name"),
|
||||
"source_root" => set_manifest_key(
|
||||
&file,
|
||||
&mut errors,
|
||||
@ -1141,19 +1112,8 @@ fn parse_manifest(path: PathBuf, source: String) -> Result<Manifest, Vec<Diagnos
|
||||
parsed,
|
||||
line.span,
|
||||
"source_root",
|
||||
"ProjectManifestInvalid",
|
||||
"project",
|
||||
),
|
||||
"entry" => set_manifest_key(
|
||||
&file,
|
||||
&mut errors,
|
||||
&mut entry,
|
||||
parsed,
|
||||
line.span,
|
||||
"entry",
|
||||
"ProjectManifestInvalid",
|
||||
"project",
|
||||
),
|
||||
"entry" => set_manifest_key(&file, &mut errors, &mut entry, parsed, line.span, "entry"),
|
||||
_ => errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
@ -1432,7 +1392,6 @@ fn parse_package_manifest(
|
||||
let mut source_root = None::<String>;
|
||||
let mut entry = None::<String>;
|
||||
let mut dependencies = Vec::new();
|
||||
let mut dependency_keys = BTreeSet::<String>::new();
|
||||
|
||||
for line in manifest_lines(&source) {
|
||||
let trimmed = line.text.trim();
|
||||
@ -1510,8 +1469,6 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"name",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
"version" => set_manifest_key(
|
||||
&file,
|
||||
@ -1520,8 +1477,6 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"version",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
"source_root" => set_manifest_key(
|
||||
&file,
|
||||
@ -1530,8 +1485,6 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"source_root",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
"entry" => set_manifest_key(
|
||||
&file,
|
||||
@ -1540,8 +1493,6 @@ fn parse_package_manifest(
|
||||
parsed,
|
||||
line.span,
|
||||
"entry",
|
||||
"PackageManifestInvalid",
|
||||
"package",
|
||||
),
|
||||
other => errors.push(
|
||||
Diagnostic::new(
|
||||
@ -1553,44 +1504,12 @@ fn parse_package_manifest(
|
||||
),
|
||||
}
|
||||
}
|
||||
"dependencies" => {
|
||||
let valid_key = if is_project_name(key) {
|
||||
true
|
||||
} else {
|
||||
errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
"InvalidPackageDependencyName",
|
||||
format!(
|
||||
"package dependency name `{}` must start with `a-z` and contain only `a-z`, `0-9`, and `-`",
|
||||
key
|
||||
),
|
||||
)
|
||||
.with_span(line.span),
|
||||
);
|
||||
false
|
||||
};
|
||||
let unique_key = if dependency_keys.insert(key.to_string()) {
|
||||
true
|
||||
} else {
|
||||
errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
"DuplicatePackageDependencyName",
|
||||
format!("duplicate package dependency name `{}`", key),
|
||||
)
|
||||
.with_span(line.span),
|
||||
);
|
||||
false
|
||||
};
|
||||
|
||||
match parse_dependency_path(value) {
|
||||
Some(path) if valid_key && unique_key => dependencies.push(PackageDependency {
|
||||
"dependencies" => match parse_dependency_path(value) {
|
||||
Some(path) => dependencies.push(PackageDependency {
|
||||
key: key.to_string(),
|
||||
path,
|
||||
span: line.span,
|
||||
}),
|
||||
Some(_) => {}
|
||||
None => errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
@ -1599,8 +1518,7 @@ fn parse_package_manifest(
|
||||
)
|
||||
.with_span(line.span),
|
||||
),
|
||||
}
|
||||
}
|
||||
},
|
||||
"" | "project" => errors.push(
|
||||
Diagnostic::new(
|
||||
&file,
|
||||
@ -1756,15 +1674,13 @@ fn set_manifest_key(
|
||||
value: String,
|
||||
span: Span,
|
||||
key: &str,
|
||||
code: &'static str,
|
||||
manifest_kind: &str,
|
||||
) {
|
||||
if slot.replace(value).is_some() {
|
||||
errors.push(
|
||||
Diagnostic::new(
|
||||
file,
|
||||
code,
|
||||
format!("duplicate {} manifest key `{}`", manifest_kind, key),
|
||||
"ProjectManifestInvalid",
|
||||
format!("duplicate project manifest key `{}`", key),
|
||||
)
|
||||
.with_span(span),
|
||||
);
|
||||
|
||||
@ -173,39 +173,6 @@ pub fn run(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn list(program: &CheckedProgram, filter: Option<&str>) -> TestRunSuccess {
|
||||
let mut output = String::new();
|
||||
let mut report = TestReport {
|
||||
total_discovered: program.tests.len(),
|
||||
selected: 0,
|
||||
passed: 0,
|
||||
failed: 0,
|
||||
skipped: 0,
|
||||
filter: filter.map(str::to_string),
|
||||
};
|
||||
|
||||
for test in &program.tests {
|
||||
output.push_str("test ");
|
||||
write_test_name(&test.name, &mut output);
|
||||
if let Some(filter) = filter {
|
||||
if !test.name.contains(filter) {
|
||||
report.skipped += 1;
|
||||
output.push_str(" ... skipped\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
report.selected += 1;
|
||||
output.push_str(" ... selected\n");
|
||||
}
|
||||
|
||||
output.push_str(&format!("{} test(s) selected", report.selected));
|
||||
write_report_suffix(&report, &mut output);
|
||||
output.push('\n');
|
||||
|
||||
TestRunSuccess { output, report }
|
||||
}
|
||||
|
||||
fn write_report_suffix(report: &TestReport, output: &mut String) {
|
||||
output.push_str(&format!(
|
||||
" (total_discovered {}, selected {}, passed {}, failed {}, skipped {}",
|
||||
@ -214,8 +181,6 @@ fn write_report_suffix(report: &TestReport, output: &mut String) {
|
||||
if let Some(filter) = report.filter.as_deref() {
|
||||
output.push_str(", filter ");
|
||||
write_test_name(filter, output);
|
||||
} else {
|
||||
output.push_str(", filter none");
|
||||
}
|
||||
output.push(')');
|
||||
}
|
||||
|
||||
@ -1,229 +0,0 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::PathBuf,
|
||||
process::{Command, Output},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
static NEXT_WORKSPACE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[test]
|
||||
fn duplicate_package_keys_report_package_manifest_invalid() {
|
||||
let workspace = write_workspace(
|
||||
"duplicate-package-key",
|
||||
"[workspace]\nmembers = [\"packages/app\"]\n",
|
||||
&[WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nname = \"other\"\nversion = \"0.1.0\"\n",
|
||||
modules: &[("main", "(module main)\n\n(fn main () -> i32\n 0)\n")],
|
||||
}],
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"--json-diagnostics".as_ref(),
|
||||
"check".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
]);
|
||||
assert_exit_code("duplicate package key", &output, 1);
|
||||
assert_json_diagnostic_code("duplicate package key", &output, "PackageManifestInvalid");
|
||||
assert_json_diagnostic_code_absent("duplicate package key", &output, "ProjectManifestInvalid");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_dependency_key_reports_invalid_package_dependency_name() {
|
||||
let workspace = write_workspace(
|
||||
"invalid-dependency-key",
|
||||
"[workspace]\nmembers = [\"packages/app\"]\n",
|
||||
&[WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nversion = \"0.1.0\"\n\n[dependencies]\nBad_Name = { path = \"../util\" }\n",
|
||||
modules: &[("main", "(module main)\n\n(fn main () -> i32\n 0)\n")],
|
||||
}],
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"--json-diagnostics".as_ref(),
|
||||
"check".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
]);
|
||||
assert_exit_code("invalid dependency key", &output, 1);
|
||||
assert_json_diagnostic_code(
|
||||
"invalid dependency key",
|
||||
&output,
|
||||
"InvalidPackageDependencyName",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn duplicate_dependency_keys_report_duplicate_package_dependency_name() {
|
||||
let workspace = write_workspace(
|
||||
"duplicate-dependency-key",
|
||||
"[workspace]\nmembers = [\"packages/app\"]\n",
|
||||
&[WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nversion = \"0.1.0\"\n\n[dependencies]\nutil = { path = \"../util\" }\nutil = { path = \"../util-again\" }\n",
|
||||
modules: &[("main", "(module main)\n\n(fn main () -> i32\n 0)\n")],
|
||||
}],
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"--json-diagnostics".as_ref(),
|
||||
"check".as_ref(),
|
||||
workspace.as_os_str(),
|
||||
]);
|
||||
assert_exit_code("duplicate dependency key", &output, 1);
|
||||
assert_json_diagnostic_code(
|
||||
"duplicate dependency key",
|
||||
&output,
|
||||
"DuplicatePackageDependencyName",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn valid_dependency_identity_checks_cleanly() {
|
||||
let workspace = write_workspace(
|
||||
"valid-dependency-identity",
|
||||
"[workspace]\nmembers = [\"packages/app\", \"packages/util\"]\n",
|
||||
&[
|
||||
WorkspacePackageSpec {
|
||||
member: "packages/util",
|
||||
manifest: "[package]\nname = \"util\"\nversion = \"0.1.0\"\n",
|
||||
modules: &[(
|
||||
"util",
|
||||
"(module util (export answer))\n\n(fn answer () -> i32\n 42)\n",
|
||||
)],
|
||||
},
|
||||
WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nversion = \"0.1.0\"\n\n[dependencies]\nutil = { path = \"../util\" }\n",
|
||||
modules: &[(
|
||||
"main",
|
||||
"(module main)\n\n(import util.util (answer))\n\n(fn main () -> i32\n (answer))\n",
|
||||
)],
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
let output = run_glagol(["check".as_ref(), workspace.as_os_str()]);
|
||||
assert_success_stdout("valid dependency identity", output, "");
|
||||
}
|
||||
|
||||
struct WorkspacePackageSpec<'a> {
|
||||
member: &'a str,
|
||||
manifest: &'a str,
|
||||
modules: &'a [(&'a str, &'a str)],
|
||||
}
|
||||
|
||||
fn write_workspace(
|
||||
name: &str,
|
||||
workspace_manifest: &str,
|
||||
packages: &[WorkspacePackageSpec<'_>],
|
||||
) -> PathBuf {
|
||||
let root = unique_path(name);
|
||||
fs::create_dir_all(&root).expect("create workspace root");
|
||||
fs::write(root.join("slovo.toml"), workspace_manifest).expect("write workspace manifest");
|
||||
|
||||
for package in packages {
|
||||
let package_root = root.join(package.member);
|
||||
let src = package_root.join("src");
|
||||
fs::create_dir_all(&src).expect("create workspace package src");
|
||||
fs::write(package_root.join("slovo.toml"), package.manifest)
|
||||
.expect("write workspace package manifest");
|
||||
for (module, source) in package.modules {
|
||||
fs::write(src.join(format!("{}.slo", module)), source)
|
||||
.expect("write workspace package module");
|
||||
}
|
||||
}
|
||||
|
||||
root
|
||||
}
|
||||
|
||||
fn unique_path(name: &str) -> PathBuf {
|
||||
let id = NEXT_WORKSPACE_ID.fetch_add(1, Ordering::SeqCst);
|
||||
let nanos = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|duration| duration.as_nanos())
|
||||
.unwrap_or(0);
|
||||
std::env::temp_dir().join(format!(
|
||||
"glagol-package-workspace-discipline-beta24-{}-{}-{}-{}",
|
||||
std::process::id(),
|
||||
nanos,
|
||||
id,
|
||||
name
|
||||
))
|
||||
}
|
||||
|
||||
fn run_glagol<I, S>(args: I) -> Output
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<std::ffi::OsStr>,
|
||||
{
|
||||
Command::new(env!("CARGO_BIN_EXE_glagol"))
|
||||
.args(args)
|
||||
.output()
|
||||
.expect("run glagol")
|
||||
}
|
||||
|
||||
fn assert_success_stdout(context: &str, output: Output, expected: &str) {
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{} failed\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
expected,
|
||||
"{} stdout mismatch",
|
||||
context
|
||||
);
|
||||
assert!(
|
||||
output.stderr.is_empty(),
|
||||
"{} wrote stderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_exit_code(context: &str, output: &Output, expected: i32) {
|
||||
assert_eq!(
|
||||
output.status.code(),
|
||||
Some(expected),
|
||||
"{} exit code mismatch\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_json_diagnostic_code(context: &str, output: &Output, expected: &str) {
|
||||
let diagnostics = diagnostic_text(output);
|
||||
assert!(
|
||||
diagnostics.contains(&format!(r#""code":"{}""#, expected)),
|
||||
"{} did not report `{}`:\n{}",
|
||||
context,
|
||||
expected,
|
||||
diagnostics
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_json_diagnostic_code_absent(context: &str, output: &Output, unexpected: &str) {
|
||||
let diagnostics = diagnostic_text(output);
|
||||
assert!(
|
||||
!diagnostics.contains(&format!(r#""code":"{}""#, unexpected)),
|
||||
"{} unexpectedly reported `{}`:\n{}",
|
||||
context,
|
||||
unexpected,
|
||||
diagnostics
|
||||
);
|
||||
}
|
||||
|
||||
fn diagnostic_text(output: &Output) -> String {
|
||||
format!(
|
||||
"{}{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)
|
||||
}
|
||||
@ -1229,14 +1229,6 @@ const STANDARD_JSON_SOURCE_FACADE_ALPHA: &[&str] = &[
|
||||
"parse_u64_value_result",
|
||||
"parse_f64_value_result",
|
||||
"parse_null_value_result",
|
||||
"parse_string_document_result",
|
||||
"parse_bool_document_result",
|
||||
"parse_i32_document_result",
|
||||
"parse_u32_document_result",
|
||||
"parse_i64_document_result",
|
||||
"parse_u64_document_result",
|
||||
"parse_f64_document_result",
|
||||
"parse_null_document_result",
|
||||
"field_string",
|
||||
"field_bool",
|
||||
"field_i32",
|
||||
@ -1273,7 +1265,6 @@ const STANDARD_JSON_RUNTIME_NAMES: &[&str] = &[
|
||||
];
|
||||
|
||||
const STANDARD_JSON_ALLOWED_STD_NAMES: &[&str] = &[
|
||||
"(import std.string (trim_ascii))",
|
||||
"std.json.quote_string",
|
||||
"std.string.concat",
|
||||
"std.num.i32_to_string",
|
||||
@ -1290,17 +1281,6 @@ const STANDARD_JSON_ALLOWED_STD_NAMES: &[&str] = &[
|
||||
"std.json.parse_f64_value_result",
|
||||
];
|
||||
|
||||
const STANDARD_JSON_DOCUMENT_SCALAR_BETA21: &[&str] = &[
|
||||
"parse_string_document_result",
|
||||
"parse_bool_document_result",
|
||||
"parse_i32_document_result",
|
||||
"parse_u32_document_result",
|
||||
"parse_i64_document_result",
|
||||
"parse_u64_document_result",
|
||||
"parse_f64_document_result",
|
||||
"parse_null_document_result",
|
||||
];
|
||||
|
||||
const STANDARD_PROCESS_SOURCE_FACADE_ALPHA: &[&str] = &[
|
||||
"argc",
|
||||
"arg",
|
||||
@ -1342,12 +1322,6 @@ const STANDARD_STRING_SOURCE_FACADE_ALPHA: &[&str] = &[
|
||||
"slice_result",
|
||||
"starts_with",
|
||||
"ends_with",
|
||||
"contains",
|
||||
"index_of_option",
|
||||
"last_index_of_option",
|
||||
"trim_ascii_start",
|
||||
"trim_ascii_end",
|
||||
"trim_ascii",
|
||||
"parse_i32_result",
|
||||
"parse_i32_option",
|
||||
"parse_u32_result",
|
||||
@ -4478,7 +4452,6 @@ fn assert_slovo_std_source_layout_alpha(repo: &Path, std_dir: &Path) {
|
||||
);
|
||||
for source in [&slovo_json, &glagol_json] {
|
||||
assert_deferred_json_surface_absent(source, "standard json facade");
|
||||
assert_json_document_scalar_helpers_are_source_authored(source, "standard json facade");
|
||||
}
|
||||
for helper in STANDARD_JSON_SOURCE_FACADE_ALPHA {
|
||||
assert!(
|
||||
@ -7337,13 +7310,10 @@ fn assert_project_std_import_json_tooling_matches_fixture(project: &Path) {
|
||||
"test \"explicit std json primitive scalar parse failure facade\" ... ok\n",
|
||||
"test \"explicit std json string token parse success facade\" ... ok\n",
|
||||
"test \"explicit std json string token parse failure facade\" ... ok\n",
|
||||
"test \"explicit std json document parse trimmed success facade\" ... ok\n",
|
||||
"test \"explicit std json document parse plain success facade\" ... ok\n",
|
||||
"test \"explicit std json document parse trailing failure facade\" ... ok\n",
|
||||
"test \"explicit std json fields facade\" ... ok\n",
|
||||
"test \"explicit std json arrays objects facade\" ... ok\n",
|
||||
"test \"explicit std json facade all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"9 test(s) passed\n",
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -7404,10 +7374,8 @@ fn assert_project_std_import_string_tooling_matches_fixture(project: &Path) {
|
||||
"test \"explicit std string parse integer fallbacks\" ... ok\n",
|
||||
"test \"explicit std string parse float bool fallbacks\" ... ok\n",
|
||||
"test \"explicit std string parse custom fallbacks\" ... ok\n",
|
||||
"test \"explicit std string search helpers\" ... ok\n",
|
||||
"test \"explicit std string ascii trim helpers\" ... ok\n",
|
||||
"test \"explicit std string helpers all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"10 test(s) passed\n",
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -8886,10 +8854,8 @@ fn assert_project_std_layout_local_string_tooling_matches_fixture(project: &Path
|
||||
"test \"explicit local string parse integer fallbacks\" ... ok\n",
|
||||
"test \"explicit local string parse float bool fallbacks\" ... ok\n",
|
||||
"test \"explicit local string parse custom fallbacks\" ... ok\n",
|
||||
"test \"explicit local string search helpers\" ... ok\n",
|
||||
"test \"explicit local string ascii trim helpers\" ... ok\n",
|
||||
"test \"explicit local string helpers all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"10 test(s) passed\n",
|
||||
),
|
||||
"std layout local string project test",
|
||||
);
|
||||
@ -8930,11 +8896,11 @@ fn assert_standard_string_source_fallback_helpers_alpha(project: &Path) {
|
||||
"standard string source helper fixture must use only existing std.string runtime names",
|
||||
);
|
||||
assert!(
|
||||
!string.contains("locale")
|
||||
!string.contains("trim")
|
||||
&& !string.contains("locale")
|
||||
&& !string.contains("unicode")
|
||||
&& !string.contains("bytes")
|
||||
&& !string.contains("case_insensitive")
|
||||
&& !string.contains("regex")
|
||||
&& !string.contains("host_error"),
|
||||
"standard string source helper fixture must not claim deferred parsing or richer error APIs"
|
||||
);
|
||||
@ -9551,13 +9517,10 @@ fn assert_project_std_layout_local_json_tooling_matches_fixture(project: &Path)
|
||||
"test \"explicit local json primitive scalar parse failure facade\" ... ok\n",
|
||||
"test \"explicit local json string token parse success facade\" ... ok\n",
|
||||
"test \"explicit local json string token parse failure facade\" ... ok\n",
|
||||
"test \"explicit local json document parse trimmed success facade\" ... ok\n",
|
||||
"test \"explicit local json document parse plain success facade\" ... ok\n",
|
||||
"test \"explicit local json document parse trailing failure facade\" ... ok\n",
|
||||
"test \"explicit local json fields facade\" ... ok\n",
|
||||
"test \"explicit local json arrays objects facade\" ... ok\n",
|
||||
"test \"explicit local json facade all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"9 test(s) passed\n",
|
||||
),
|
||||
"std layout local json project test",
|
||||
);
|
||||
@ -10751,34 +10714,6 @@ fn assert_deferred_json_surface_absent(source: &str, context: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_json_document_scalar_helpers_are_source_authored(source: &str, context: &str) {
|
||||
for helper in STANDARD_JSON_DOCUMENT_SCALAR_BETA21 {
|
||||
assert!(
|
||||
!source.contains(&format!("std.json.{}", helper)),
|
||||
"{} must keep `{}` source-authored, not compiler-known",
|
||||
context,
|
||||
helper
|
||||
);
|
||||
}
|
||||
for private_prefix in [
|
||||
"__glagol_json_parse_string_document",
|
||||
"__glagol_json_parse_bool_document",
|
||||
"__glagol_json_parse_i32_document",
|
||||
"__glagol_json_parse_u32_document",
|
||||
"__glagol_json_parse_i64_document",
|
||||
"__glagol_json_parse_u64_document",
|
||||
"__glagol_json_parse_f64_document",
|
||||
"__glagol_json_parse_null_document",
|
||||
] {
|
||||
assert!(
|
||||
!source.contains(private_prefix),
|
||||
"{} must not introduce private JSON document runtime symbol `{}`",
|
||||
context,
|
||||
private_prefix
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn repo_root() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.parent()
|
||||
|
||||
@ -1,267 +0,0 @@
|
||||
use std::{
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Output},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
static NEXT_FIXTURE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[test]
|
||||
fn run_manifest_records_success_report_stdout_and_program_args() {
|
||||
let Some(clang) = find_clang() else {
|
||||
eprintln!("skipping run manifest success report: set GLAGOL_CLANG or install clang");
|
||||
return;
|
||||
};
|
||||
|
||||
let source = write_fixture(
|
||||
"success",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
(print_string "beta22-out")
|
||||
0)
|
||||
"#,
|
||||
"slo",
|
||||
);
|
||||
let manifest_path = temp_path("success-manifest", "manifest.slo");
|
||||
|
||||
let mut command = Command::new(compiler_path());
|
||||
command
|
||||
.arg("run")
|
||||
.arg(&source)
|
||||
.arg("--manifest")
|
||||
.arg(&manifest_path)
|
||||
.arg("--")
|
||||
.arg("alpha")
|
||||
.arg("two words")
|
||||
.arg("--literal")
|
||||
.env("GLAGOL_CLANG", &clang);
|
||||
configure_clang_runtime_env(&mut command, &clang);
|
||||
|
||||
let output = command.output().expect("run glagol success manifest");
|
||||
assert_success_stdout("run manifest success", &output, "beta22-out\n");
|
||||
|
||||
let manifest = read_manifest(&manifest_path);
|
||||
assert!(
|
||||
manifest.contains(" (mode run)\n")
|
||||
&& manifest.contains(" (success true)\n")
|
||||
&& manifest.contains(" (run-report\n")
|
||||
&& manifest.contains(" (exit-status 0)\n")
|
||||
&& manifest.contains(" (stdout \"beta22-out\\n\")\n")
|
||||
&& manifest.contains(" (stderr \"\")\n")
|
||||
&& manifest.contains(" (arg \"alpha\")\n")
|
||||
&& manifest.contains(" (arg \"two words\")\n")
|
||||
&& manifest.contains(" (arg \"--literal\")\n"),
|
||||
"successful run manifest mismatch:\n{}",
|
||||
manifest
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_manifest_records_nonzero_report_and_preserves_program_stderr() {
|
||||
let Some(clang) = find_clang() else {
|
||||
eprintln!("skipping run manifest nonzero report: set GLAGOL_CLANG or install clang");
|
||||
return;
|
||||
};
|
||||
|
||||
let source = write_fixture(
|
||||
"nonzero",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(import_c beta22_stderr () -> i32)
|
||||
|
||||
(fn emit_stderr () -> i32
|
||||
(unsafe
|
||||
(beta22_stderr)))
|
||||
|
||||
(fn main () -> i32
|
||||
(emit_stderr)
|
||||
7)
|
||||
"#,
|
||||
"slo",
|
||||
);
|
||||
let c_source = write_fixture(
|
||||
"nonzero-stderr",
|
||||
r#"
|
||||
#include <stdio.h>
|
||||
|
||||
int beta22_stderr(void) {
|
||||
fputs("beta22-err\n", stderr);
|
||||
return 0;
|
||||
}
|
||||
"#,
|
||||
"c",
|
||||
);
|
||||
let manifest_path = temp_path("nonzero-manifest", "manifest.slo");
|
||||
|
||||
let mut command = Command::new(compiler_path());
|
||||
command
|
||||
.arg("run")
|
||||
.arg(&source)
|
||||
.arg("--link-c")
|
||||
.arg(&c_source)
|
||||
.arg("--manifest")
|
||||
.arg(&manifest_path)
|
||||
.env("GLAGOL_CLANG", &clang);
|
||||
configure_clang_runtime_env(&mut command, &clang);
|
||||
|
||||
let output = command.output().expect("run glagol nonzero manifest");
|
||||
assert_exit_code("run manifest nonzero", &output, 7);
|
||||
assert_eq!(output.stdout, b"", "nonzero run stdout drifted");
|
||||
assert_eq!(output.stderr, b"beta22-err\n", "nonzero run stderr drifted");
|
||||
|
||||
let manifest = read_manifest(&manifest_path);
|
||||
assert!(
|
||||
manifest.contains(" (mode run)\n")
|
||||
&& manifest.contains(" (success false)\n")
|
||||
&& manifest.contains(" (run-report\n")
|
||||
&& manifest.contains(" (exit-status 7)\n")
|
||||
&& manifest.contains(" (stdout \"\")\n")
|
||||
&& manifest.contains(" (stderr \"beta22-err\\n\")\n")
|
||||
&& manifest.contains(" (args)\n"),
|
||||
"nonzero run manifest mismatch:\n{}",
|
||||
manifest
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run_manifest_source_failure_does_not_record_fake_run_report() {
|
||||
let source = write_fixture(
|
||||
"source-failure",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
true)
|
||||
"#,
|
||||
"slo",
|
||||
);
|
||||
let manifest_path = temp_path("source-failure-manifest", "manifest.slo");
|
||||
|
||||
let output = run_glagol([
|
||||
"run".as_ref(),
|
||||
source.as_os_str(),
|
||||
"--manifest".as_ref(),
|
||||
manifest_path.as_os_str(),
|
||||
]);
|
||||
assert_exit_code("run manifest source failure", &output, 1);
|
||||
|
||||
let manifest = read_manifest(&manifest_path);
|
||||
assert!(
|
||||
manifest.contains(" (mode run)\n")
|
||||
&& manifest.contains(" (success false)\n")
|
||||
&& manifest.contains(" (kind diagnostics)\n")
|
||||
&& manifest.contains("TypeMismatch")
|
||||
&& !manifest.contains(" (run-report\n"),
|
||||
"source failure manifest included fake run report:\n{}",
|
||||
manifest
|
||||
);
|
||||
}
|
||||
|
||||
fn run_glagol<const N: usize>(args: [&std::ffi::OsStr; N]) -> Output {
|
||||
Command::new(compiler_path())
|
||||
.args(args)
|
||||
.output()
|
||||
.expect("run glagol")
|
||||
}
|
||||
|
||||
fn compiler_path() -> &'static str {
|
||||
env!("CARGO_BIN_EXE_glagol")
|
||||
}
|
||||
|
||||
fn write_fixture(name: &str, source: &str, extension: &str) -> PathBuf {
|
||||
let path = temp_path(name, extension);
|
||||
fs::write(&path, source).unwrap_or_else(|err| panic!("write `{}`: {}", path.display(), err));
|
||||
path
|
||||
}
|
||||
|
||||
fn temp_path(name: &str, extension: &str) -> PathBuf {
|
||||
let id = NEXT_FIXTURE_ID.fetch_add(1, Ordering::Relaxed);
|
||||
let mut path = env::temp_dir();
|
||||
path.push(format!(
|
||||
"glagol-run-manifest-beta22-{}-{}-{}.{}",
|
||||
std::process::id(),
|
||||
id,
|
||||
name,
|
||||
extension
|
||||
));
|
||||
path
|
||||
}
|
||||
|
||||
fn read_manifest(path: &Path) -> String {
|
||||
fs::read_to_string(path).unwrap_or_else(|err| panic!("read `{}`: {}", path.display(), err))
|
||||
}
|
||||
|
||||
fn assert_success_stdout(context: &str, output: &Output, expected: &str) {
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{} failed\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
expected,
|
||||
"{} stdout mismatch",
|
||||
context
|
||||
);
|
||||
assert!(
|
||||
output.stderr.is_empty(),
|
||||
"{} wrote stderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_exit_code(context: &str, output: &Output, expected: i32) {
|
||||
assert_eq!(
|
||||
output.status.code(),
|
||||
Some(expected),
|
||||
"{} exit code mismatch\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn find_clang() -> Option<PathBuf> {
|
||||
if let Some(path) = env::var_os("GLAGOL_CLANG").filter(|value| !value.is_empty()) {
|
||||
let path = PathBuf::from(path);
|
||||
if path.is_file() {
|
||||
return Some(path);
|
||||
}
|
||||
}
|
||||
|
||||
let hermetic_clang = PathBuf::from("/tmp/glagol-clang-root/usr/bin/clang");
|
||||
if hermetic_clang.is_file() {
|
||||
return Some(hermetic_clang);
|
||||
}
|
||||
|
||||
find_on_path("clang")
|
||||
}
|
||||
|
||||
fn find_on_path(name: &str) -> Option<PathBuf> {
|
||||
let path = env::var_os("PATH")?;
|
||||
env::split_paths(&path)
|
||||
.map(|dir| dir.join(name))
|
||||
.find(|candidate| candidate.is_file())
|
||||
}
|
||||
|
||||
fn configure_clang_runtime_env(command: &mut Command, clang: &Path) {
|
||||
if !clang.starts_with("/tmp/glagol-clang-root") {
|
||||
return;
|
||||
}
|
||||
|
||||
let root = Path::new("/tmp/glagol-clang-root");
|
||||
let lib64 = root.join("usr/lib64");
|
||||
let lib = root.join("usr/lib");
|
||||
let existing = env::var_os("LD_LIBRARY_PATH").unwrap_or_default();
|
||||
let mut paths = vec![lib64, lib];
|
||||
paths.extend(env::split_paths(&existing));
|
||||
let joined = env::join_paths(paths).expect("join LD_LIBRARY_PATH");
|
||||
command.env("LD_LIBRARY_PATH", joined);
|
||||
}
|
||||
@ -15,10 +15,8 @@ const EXPECTED_STD_STRING_OUTPUT: &str = concat!(
|
||||
"test \"explicit std string parse integer fallbacks\" ... ok\n",
|
||||
"test \"explicit std string parse float bool fallbacks\" ... ok\n",
|
||||
"test \"explicit std string parse custom fallbacks\" ... ok\n",
|
||||
"test \"explicit std string search helpers\" ... ok\n",
|
||||
"test \"explicit std string ascii trim helpers\" ... ok\n",
|
||||
"test \"explicit std string helpers all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"10 test(s) passed\n",
|
||||
);
|
||||
|
||||
const EXPECTED_STD_NUM_OUTPUT: &str = concat!(
|
||||
@ -41,12 +39,6 @@ fn explicit_std_string_import_loads_repo_root_standard_source() {
|
||||
"slice_result",
|
||||
"starts_with",
|
||||
"ends_with",
|
||||
"contains",
|
||||
"index_of_option",
|
||||
"last_index_of_option",
|
||||
"trim_ascii_start",
|
||||
"trim_ascii_end",
|
||||
"trim_ascii",
|
||||
"parse_i32_result",
|
||||
"parse_i32_option",
|
||||
"parse_u32_result",
|
||||
|
||||
@ -1,313 +0,0 @@
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Output},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
static NEXT_TEMP_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
const EXPECTED_TEST_OUTPUT: &str = concat!(
|
||||
"test \"explicit std json document scalar string\" ... ok\n",
|
||||
"test \"explicit std json document scalar bool\" ... ok\n",
|
||||
"test \"explicit std json document scalar integer\" ... ok\n",
|
||||
"test \"explicit std json document scalar float null\" ... ok\n",
|
||||
"test \"explicit std json document scalar failures\" ... ok\n",
|
||||
"test \"explicit std json document scalar all\" ... ok\n",
|
||||
"6 test(s) passed\n",
|
||||
);
|
||||
|
||||
const STANDARD_JSON_DOCUMENT_SCALAR_BETA21: &[&str] = &[
|
||||
"parse_string_document_result",
|
||||
"parse_bool_document_result",
|
||||
"parse_i32_document_result",
|
||||
"parse_u32_document_result",
|
||||
"parse_i64_document_result",
|
||||
"parse_u64_document_result",
|
||||
"parse_f64_document_result",
|
||||
"parse_null_document_result",
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn explicit_std_json_document_scalar_helpers_check_and_test() {
|
||||
let project = write_project(
|
||||
"std-json-document-scalar-beta21",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(import std.json (parse_string_document_result parse_bool_document_result parse_i32_document_result parse_u32_document_result parse_i64_document_result parse_u64_document_result parse_f64_document_result parse_null_document_result))
|
||||
|
||||
(fn imported_json_document_string_ok () -> bool
|
||||
(if (= (std.result.unwrap_ok (parse_string_document_result " \"slovo\" ")) "slovo")
|
||||
(= (std.result.unwrap_ok (parse_string_document_result "\n\t\"slo\\\"vo\"\t")) "slo\"vo")
|
||||
false))
|
||||
|
||||
(fn imported_json_document_bool_ok () -> bool
|
||||
(if (std.result.unwrap_ok (parse_bool_document_result " true "))
|
||||
(= (std.result.unwrap_ok (parse_bool_document_result "\nfalse\t")) false)
|
||||
false))
|
||||
|
||||
(fn imported_json_document_integer_ok () -> bool
|
||||
(if (= (std.result.unwrap_ok (parse_i32_document_result " -7 ")) -7)
|
||||
(if (= (std.result.unwrap_ok (parse_u32_document_result "\n7\t")) 7u32)
|
||||
(if (= (std.result.unwrap_ok (parse_i64_document_result " -8 ")) -8i64)
|
||||
(= (std.result.unwrap_ok (parse_u64_document_result "9 ")) 9u64)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_document_float_null_ok () -> bool
|
||||
(if (= (std.result.unwrap_ok (parse_f64_document_result " 1e2 ")) 100.0)
|
||||
(std.result.unwrap_ok (parse_null_document_result "\nnull\t"))
|
||||
false))
|
||||
|
||||
(fn imported_json_document_failures_ok () -> bool
|
||||
(if (= (std.result.unwrap_err (parse_string_document_result "\"slovo\" x")) 1)
|
||||
(if (= (std.result.unwrap_err (parse_bool_document_result " TRUE ")) 1)
|
||||
(if (= (std.result.unwrap_err (parse_i32_document_result " 01 ")) 1)
|
||||
(if (= (std.result.unwrap_err (parse_u32_document_result " -1 ")) 1)
|
||||
(if (= (std.result.unwrap_err (parse_i64_document_result " 8i64 ")) 1)
|
||||
(if (= (std.result.unwrap_err (parse_u64_document_result " ")) 1)
|
||||
(if (= (std.result.unwrap_err (parse_f64_document_result " 01.0 ")) 1)
|
||||
(= (std.result.unwrap_err (parse_null_document_result " NULL ")) 1)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_document_scalar_all_ok () -> bool
|
||||
(if (imported_json_document_string_ok)
|
||||
(if (imported_json_document_bool_ok)
|
||||
(if (imported_json_document_integer_ok)
|
||||
(if (imported_json_document_float_null_ok)
|
||||
(imported_json_document_failures_ok)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn main () -> i32
|
||||
(if (imported_json_document_scalar_all_ok)
|
||||
42
|
||||
1))
|
||||
|
||||
(test "explicit std json document scalar string"
|
||||
(imported_json_document_string_ok))
|
||||
|
||||
(test "explicit std json document scalar bool"
|
||||
(imported_json_document_bool_ok))
|
||||
|
||||
(test "explicit std json document scalar integer"
|
||||
(imported_json_document_integer_ok))
|
||||
|
||||
(test "explicit std json document scalar float null"
|
||||
(imported_json_document_float_null_ok))
|
||||
|
||||
(test "explicit std json document scalar failures"
|
||||
(imported_json_document_failures_ok))
|
||||
|
||||
(test "explicit std json document scalar all"
|
||||
(= (main) 42))
|
||||
"#,
|
||||
);
|
||||
|
||||
let source = read(&project.join("src/main.slo"));
|
||||
let std_json = read(&std_json_path());
|
||||
|
||||
assert!(
|
||||
!project.join("src/json.slo").exists(),
|
||||
"beta21 fixture must exercise repo-root std.json, not a local module copy"
|
||||
);
|
||||
assert!(
|
||||
source.starts_with("(module main)\n\n(import std.json ("),
|
||||
"beta21 fixture must use an explicit std.json import"
|
||||
);
|
||||
assert_json_document_scalar_helpers_are_source_authored(&std_json);
|
||||
|
||||
let fmt = run_glagol([
|
||||
OsStr::new("fmt"),
|
||||
OsStr::new("--check"),
|
||||
project.as_os_str(),
|
||||
]);
|
||||
assert_success("std json document scalar fmt --check", &fmt);
|
||||
|
||||
let check = run_glagol([OsStr::new("check"), project.as_os_str()]);
|
||||
assert_success_stdout(check, "", "std json document scalar check");
|
||||
|
||||
let test = run_glagol([OsStr::new("test"), project.as_os_str()]);
|
||||
assert_success_stdout(test, EXPECTED_TEST_OUTPUT, "std json document scalar test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn json_document_scalar_helpers_are_not_compiler_known_runtime_calls() {
|
||||
let std_json = read(&std_json_path());
|
||||
assert_json_document_scalar_helpers_are_source_authored(&std_json);
|
||||
|
||||
for helper in STANDARD_JSON_DOCUMENT_SCALAR_BETA21 {
|
||||
let fixture = write_fixture(
|
||||
helper,
|
||||
&format!(
|
||||
"(module main)\n\n(fn main () -> i32\n (std.result.unwrap_err (std.json.{} \"invalid\")))\n",
|
||||
helper
|
||||
),
|
||||
);
|
||||
let output = run_glagol([fixture.as_os_str()]);
|
||||
assert_failure_stderr_contains(
|
||||
&format!("direct std.json.{} runtime call", helper),
|
||||
&output,
|
||||
&format!(
|
||||
"standard library call `std.json.{}` is not supported",
|
||||
helper
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_json_document_scalar_helpers_are_source_authored(std_json: &str) {
|
||||
assert!(
|
||||
std_json.starts_with("(module json (export "),
|
||||
"lib/std/json.slo must stay a source-authored module export"
|
||||
);
|
||||
|
||||
for helper in STANDARD_JSON_DOCUMENT_SCALAR_BETA21 {
|
||||
assert!(
|
||||
std_json.contains(&format!("(fn {} ", helper)),
|
||||
"lib/std/json.slo is missing source facade `{}`",
|
||||
helper
|
||||
);
|
||||
assert!(
|
||||
!std_json.contains(&format!("std.json.{}", helper)),
|
||||
"std.json.{} must remain source-authored, not a compiler-known runtime call",
|
||||
helper
|
||||
);
|
||||
}
|
||||
|
||||
for private_prefix in [
|
||||
"__glagol_json_parse_string_document",
|
||||
"__glagol_json_parse_bool_document",
|
||||
"__glagol_json_parse_i32_document",
|
||||
"__glagol_json_parse_u32_document",
|
||||
"__glagol_json_parse_i64_document",
|
||||
"__glagol_json_parse_u64_document",
|
||||
"__glagol_json_parse_f64_document",
|
||||
"__glagol_json_parse_null_document",
|
||||
] {
|
||||
assert!(
|
||||
!std_json.contains(private_prefix),
|
||||
"lib/std/json.slo must not introduce private JSON document runtime symbol `{}`",
|
||||
private_prefix
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_glagol<I, S>(args: I) -> Output
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
Command::new(env!("CARGO_BIN_EXE_glagol"))
|
||||
.args(args)
|
||||
.current_dir(Path::new(env!("CARGO_MANIFEST_DIR")))
|
||||
.output()
|
||||
.expect("run glagol")
|
||||
}
|
||||
|
||||
fn write_project(name: &str, source: &str) -> PathBuf {
|
||||
let root = temp_root(name);
|
||||
let src = root.join("src");
|
||||
fs::create_dir_all(&src).unwrap_or_else(|err| panic!("create `{}`: {}", src.display(), err));
|
||||
fs::write(
|
||||
root.join("slovo.toml"),
|
||||
format!(
|
||||
"[project]\nname = \"{}\"\nsource_root = \"src\"\nentry = \"main\"\n",
|
||||
name
|
||||
),
|
||||
)
|
||||
.unwrap_or_else(|err| panic!("write project manifest: {}", err));
|
||||
fs::write(src.join("main.slo"), source.trim_start())
|
||||
.unwrap_or_else(|err| panic!("write project main.slo: {}", err));
|
||||
root
|
||||
}
|
||||
|
||||
fn write_fixture(name: &str, source: &str) -> PathBuf {
|
||||
let mut path = env::temp_dir();
|
||||
path.push(format!(
|
||||
"glagol-standard-json-document-scalar-beta21-{}-{}-{}.slo",
|
||||
name,
|
||||
std::process::id(),
|
||||
NEXT_TEMP_ID.fetch_add(1, Ordering::Relaxed)
|
||||
));
|
||||
fs::write(&path, source.trim_start())
|
||||
.unwrap_or_else(|err| panic!("write `{}`: {}", path.display(), err));
|
||||
path
|
||||
}
|
||||
|
||||
fn temp_root(name: &str) -> PathBuf {
|
||||
let root = env::temp_dir().join(format!(
|
||||
"glagol-standard-json-document-scalar-beta21-{}-{}-{}",
|
||||
name,
|
||||
std::process::id(),
|
||||
NEXT_TEMP_ID.fetch_add(1, Ordering::Relaxed)
|
||||
));
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
fs::create_dir_all(&root).unwrap_or_else(|err| panic!("create `{}`: {}", root.display(), err));
|
||||
root
|
||||
}
|
||||
|
||||
fn std_json_path() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("../lib/std/json.slo")
|
||||
}
|
||||
|
||||
fn read(path: &Path) -> String {
|
||||
fs::read_to_string(path).unwrap_or_else(|err| panic!("read `{}`: {}", path.display(), err))
|
||||
}
|
||||
|
||||
fn assert_success(context: &str, output: &Output) {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{} failed\nstatus: {:?}\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
output.status.code(),
|
||||
stdout,
|
||||
stderr
|
||||
);
|
||||
assert!(stderr.is_empty(), "{} wrote stderr:\n{}", context, stderr);
|
||||
}
|
||||
|
||||
fn assert_success_stdout(output: Output, expected: &str, context: &str) {
|
||||
assert_success(context, &output);
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
assert_eq!(stdout, expected, "{}", context);
|
||||
}
|
||||
|
||||
fn assert_failure_stderr_contains(context: &str, output: &Output, needle: &str) {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
!output.status.success(),
|
||||
"{} unexpectedly passed\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
stdout,
|
||||
stderr
|
||||
);
|
||||
assert!(
|
||||
stdout.is_empty(),
|
||||
"{} rejected compile wrote stdout:\n{}",
|
||||
context,
|
||||
stdout
|
||||
);
|
||||
assert!(
|
||||
stderr.contains(needle),
|
||||
"{} stderr did not contain `{}`:\n{}",
|
||||
context,
|
||||
needle,
|
||||
stderr
|
||||
);
|
||||
}
|
||||
@ -12,13 +12,10 @@ const EXPECTED_LOCAL_TEST_OUTPUT: &str = concat!(
|
||||
"test \"explicit local json primitive scalar parse failure facade\" ... ok\n",
|
||||
"test \"explicit local json string token parse success facade\" ... ok\n",
|
||||
"test \"explicit local json string token parse failure facade\" ... ok\n",
|
||||
"test \"explicit local json document parse trimmed success facade\" ... ok\n",
|
||||
"test \"explicit local json document parse plain success facade\" ... ok\n",
|
||||
"test \"explicit local json document parse trailing failure facade\" ... ok\n",
|
||||
"test \"explicit local json fields facade\" ... ok\n",
|
||||
"test \"explicit local json arrays objects facade\" ... ok\n",
|
||||
"test \"explicit local json facade all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"9 test(s) passed\n",
|
||||
);
|
||||
|
||||
const EXPECTED_STD_IMPORT_TEST_OUTPUT: &str = concat!(
|
||||
@ -28,13 +25,10 @@ const EXPECTED_STD_IMPORT_TEST_OUTPUT: &str = concat!(
|
||||
"test \"explicit std json primitive scalar parse failure facade\" ... ok\n",
|
||||
"test \"explicit std json string token parse success facade\" ... ok\n",
|
||||
"test \"explicit std json string token parse failure facade\" ... ok\n",
|
||||
"test \"explicit std json document parse trimmed success facade\" ... ok\n",
|
||||
"test \"explicit std json document parse plain success facade\" ... ok\n",
|
||||
"test \"explicit std json document parse trailing failure facade\" ... ok\n",
|
||||
"test \"explicit std json fields facade\" ... ok\n",
|
||||
"test \"explicit std json arrays objects facade\" ... ok\n",
|
||||
"test \"explicit std json facade all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"9 test(s) passed\n",
|
||||
);
|
||||
|
||||
const STANDARD_JSON_SOURCE_FACADE_ALPHA: &[&str] = &[
|
||||
@ -54,14 +48,6 @@ const STANDARD_JSON_SOURCE_FACADE_ALPHA: &[&str] = &[
|
||||
"parse_u64_value_result",
|
||||
"parse_f64_value_result",
|
||||
"parse_null_value_result",
|
||||
"parse_string_document_result",
|
||||
"parse_bool_document_result",
|
||||
"parse_i32_document_result",
|
||||
"parse_u32_document_result",
|
||||
"parse_i64_document_result",
|
||||
"parse_u64_document_result",
|
||||
"parse_f64_document_result",
|
||||
"parse_null_document_result",
|
||||
"field_string",
|
||||
"field_bool",
|
||||
"field_i32",
|
||||
@ -98,7 +84,6 @@ const STANDARD_JSON_RUNTIME_NAMES: &[&str] = &[
|
||||
];
|
||||
|
||||
const STANDARD_JSON_ALLOWED_STD_NAMES: &[&str] = &[
|
||||
"(import std.string (trim_ascii))",
|
||||
"std.json.quote_string",
|
||||
"std.string.concat",
|
||||
"std.num.i32_to_string",
|
||||
@ -115,17 +100,6 @@ const STANDARD_JSON_ALLOWED_STD_NAMES: &[&str] = &[
|
||||
"std.json.parse_f64_value_result",
|
||||
];
|
||||
|
||||
const STANDARD_JSON_DOCUMENT_SCALAR_BETA21: &[&str] = &[
|
||||
"parse_string_document_result",
|
||||
"parse_bool_document_result",
|
||||
"parse_i32_document_result",
|
||||
"parse_u32_document_result",
|
||||
"parse_i64_document_result",
|
||||
"parse_u64_document_result",
|
||||
"parse_f64_document_result",
|
||||
"parse_null_document_result",
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn standard_json_source_facade_project_checks_formats_and_tests() {
|
||||
let project =
|
||||
@ -225,7 +199,6 @@ fn assert_json_source_shape(json: &str, main: &str, context: &str) {
|
||||
}
|
||||
assert_std_only_contains(json, STANDARD_JSON_ALLOWED_STD_NAMES, context);
|
||||
assert_deferred_json_surface_absent(json, main, context);
|
||||
assert_json_document_scalar_helpers_are_source_authored(json, context);
|
||||
|
||||
for helper in STANDARD_JSON_SOURCE_FACADE_ALPHA {
|
||||
assert!(
|
||||
@ -243,34 +216,6 @@ fn assert_json_source_shape(json: &str, main: &str, context: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_json_document_scalar_helpers_are_source_authored(json: &str, context: &str) {
|
||||
for helper in STANDARD_JSON_DOCUMENT_SCALAR_BETA21 {
|
||||
assert!(
|
||||
!json.contains(&format!("std.json.{}", helper)),
|
||||
"{} must keep `{}` source-authored, not compiler-known",
|
||||
context,
|
||||
helper
|
||||
);
|
||||
}
|
||||
for private_prefix in [
|
||||
"__glagol_json_parse_string_document",
|
||||
"__glagol_json_parse_bool_document",
|
||||
"__glagol_json_parse_i32_document",
|
||||
"__glagol_json_parse_u32_document",
|
||||
"__glagol_json_parse_i64_document",
|
||||
"__glagol_json_parse_u64_document",
|
||||
"__glagol_json_parse_f64_document",
|
||||
"__glagol_json_parse_null_document",
|
||||
] {
|
||||
assert!(
|
||||
!json.contains(private_prefix),
|
||||
"{} must not introduce private JSON document runtime symbol `{}`",
|
||||
context,
|
||||
private_prefix
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_deferred_json_surface_absent(json: &str, main: &str, context: &str) {
|
||||
for deferred in [
|
||||
"parse_object",
|
||||
|
||||
@ -1,478 +0,0 @@
|
||||
use std::{
|
||||
env,
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Output},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
static NEXT_TEMP_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
const EXPECTED_TEST_OUTPUT: &str = concat!(
|
||||
"test \"explicit std string contains\" ... ok\n",
|
||||
"test \"explicit std string index_of_option\" ... ok\n",
|
||||
"test \"explicit std string last_index_of_option\" ... ok\n",
|
||||
"test \"explicit std string ascii trim\" ... ok\n",
|
||||
"test \"explicit std string search trim composition\" ... ok\n",
|
||||
"test \"explicit std string search trim all\" ... ok\n",
|
||||
"6 test(s) passed\n",
|
||||
);
|
||||
|
||||
const STANDARD_STRING_SEARCH_TRIM_BETA20: &[&str] = &[
|
||||
"contains",
|
||||
"index_of_option",
|
||||
"last_index_of_option",
|
||||
"trim_ascii_start",
|
||||
"trim_ascii_end",
|
||||
"trim_ascii",
|
||||
];
|
||||
|
||||
const ALLOWED_STD_REFERENCES: &[&str] = &[
|
||||
"std.result",
|
||||
"std.string.parse_bool_result",
|
||||
"std.string.parse_f64_result",
|
||||
"std.string.parse_i64_result",
|
||||
"std.string.parse_u64_result",
|
||||
"std.string.parse_i32_result",
|
||||
"std.string.parse_u32_result",
|
||||
"std.string.byte_at_result",
|
||||
"std.string.slice_result",
|
||||
"std.string.starts_with",
|
||||
"std.string.ends_with",
|
||||
"std.string.concat",
|
||||
"std.string.len",
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn explicit_std_string_search_and_ascii_trim_helpers_check_and_test() {
|
||||
let project = write_project(
|
||||
"std-string-search-trim-beta20",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(import std.string (contains index_of_option last_index_of_option trim_ascii_start trim_ascii_end trim_ascii))
|
||||
|
||||
(fn option_i32_eq ((maybe (option i32)) (expected i32)) -> bool
|
||||
(match maybe
|
||||
((some value)
|
||||
(= value expected))
|
||||
((none)
|
||||
false)))
|
||||
|
||||
(fn option_i32_none ((maybe (option i32))) -> bool
|
||||
(match maybe
|
||||
((some value)
|
||||
false)
|
||||
((none)
|
||||
true)))
|
||||
|
||||
(fn imported_string_contains_ok () -> bool
|
||||
(if (contains "slovo compiler" "slo")
|
||||
(if (contains "slovo compiler" "compiler")
|
||||
(= (contains "slovo compiler" "missing") false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_index_of_ok () -> bool
|
||||
(if (option_i32_eq (index_of_option "bananana" "ana") 1)
|
||||
(if (option_i32_eq (index_of_option "slovo" "s") 0)
|
||||
(if (option_i32_eq (index_of_option "slovo" "vo") 3)
|
||||
(option_i32_none (index_of_option "slovo" "compiler"))
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_last_index_of_ok () -> bool
|
||||
(if (option_i32_eq (last_index_of_option "bananana" "ana") 5)
|
||||
(if (option_i32_eq (last_index_of_option "slovo" "o") 4)
|
||||
(if (option_i32_eq (last_index_of_option "slovo" "s") 0)
|
||||
(option_i32_none (last_index_of_option "slovo" "compiler"))
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_ascii_trim_ok () -> bool
|
||||
(if (= (trim_ascii_start "\n\t slovo \t") "slovo \t")
|
||||
(if (= (trim_ascii_end "\n\t slovo \t") "\n\t slovo")
|
||||
(if (= (trim_ascii "\n\t slovo \t") "slovo")
|
||||
(if (= (trim_ascii "slovo") "slovo")
|
||||
(= (trim_ascii " ") "")
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_search_trim_composes_ok () -> bool
|
||||
(if (= (trim_ascii " slovo compiler ") "slovo compiler")
|
||||
(if (contains (trim_ascii " slovo compiler ") "compiler")
|
||||
(if (option_i32_eq (index_of_option (trim_ascii_start "\t\tprefix-core") "core") 7)
|
||||
(option_i32_eq (last_index_of_option (trim_ascii_end "core-core\n") "core") 5)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_search_trim_all_ok () -> bool
|
||||
(if (imported_string_contains_ok)
|
||||
(if (imported_string_index_of_ok)
|
||||
(if (imported_string_last_index_of_ok)
|
||||
(if (imported_string_ascii_trim_ok)
|
||||
(imported_string_search_trim_composes_ok)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn main () -> i32
|
||||
(if (imported_string_search_trim_all_ok)
|
||||
42
|
||||
1))
|
||||
|
||||
(test "explicit std string contains"
|
||||
(imported_string_contains_ok))
|
||||
|
||||
(test "explicit std string index_of_option"
|
||||
(imported_string_index_of_ok))
|
||||
|
||||
(test "explicit std string last_index_of_option"
|
||||
(imported_string_last_index_of_ok))
|
||||
|
||||
(test "explicit std string ascii trim"
|
||||
(imported_string_ascii_trim_ok))
|
||||
|
||||
(test "explicit std string search trim composition"
|
||||
(imported_string_search_trim_composes_ok))
|
||||
|
||||
(test "explicit std string search trim all"
|
||||
(= (main) 42))
|
||||
"#,
|
||||
);
|
||||
|
||||
let source = read(&project.join("src/main.slo"));
|
||||
let std_string = read(&std_string_path());
|
||||
|
||||
assert!(
|
||||
!project.join("src/string.slo").exists(),
|
||||
"beta20 fixture must exercise repo-root std.string, not a local module copy"
|
||||
);
|
||||
assert!(
|
||||
source.starts_with("(module main)\n\n(import std.string ("),
|
||||
"beta20 fixture must use an explicit std.string import"
|
||||
);
|
||||
assert_std_string_search_trim_facades(&std_string);
|
||||
|
||||
let fmt = run_glagol([
|
||||
OsStr::new("fmt"),
|
||||
OsStr::new("--check"),
|
||||
project.as_os_str(),
|
||||
]);
|
||||
assert_success("std string search trim fmt --check", &fmt);
|
||||
|
||||
let check = run_glagol([OsStr::new("check"), project.as_os_str()]);
|
||||
assert_success_stdout(check, "", "std string search trim check");
|
||||
|
||||
let test = run_glagol([OsStr::new("test"), project.as_os_str()]);
|
||||
assert_success_stdout(test, EXPECTED_TEST_OUTPUT, "std string search trim test");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_search_and_ascii_trim_helpers_are_not_compiler_known_runtime_calls() {
|
||||
let std_string = read(&std_string_path());
|
||||
assert_std_string_search_trim_facades(&std_string);
|
||||
|
||||
for helper in STANDARD_STRING_SEARCH_TRIM_BETA20 {
|
||||
assert!(
|
||||
!std_string.contains(&format!("std.string.{}", helper)),
|
||||
"std.string.{} must remain source-authored, not a compiler-known runtime call",
|
||||
helper
|
||||
);
|
||||
assert!(
|
||||
!std_string.contains(&format!("__glagol_string_{}", helper)),
|
||||
"std.string.{} must not introduce a private runtime symbol",
|
||||
helper
|
||||
);
|
||||
}
|
||||
|
||||
let cases = [
|
||||
UnsupportedRuntimeCase {
|
||||
name: "contains",
|
||||
symbol: "std.string.contains",
|
||||
source: r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
(if (std.string.contains "slovo" "ovo")
|
||||
0
|
||||
1))
|
||||
"#,
|
||||
},
|
||||
UnsupportedRuntimeCase {
|
||||
name: "index-of-option",
|
||||
symbol: "std.string.index_of_option",
|
||||
source: r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
(match (std.string.index_of_option "slovo" "o")
|
||||
((some value)
|
||||
value)
|
||||
((none)
|
||||
0)))
|
||||
"#,
|
||||
},
|
||||
UnsupportedRuntimeCase {
|
||||
name: "last-index-of-option",
|
||||
symbol: "std.string.last_index_of_option",
|
||||
source: r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
(match (std.string.last_index_of_option "slovo" "o")
|
||||
((some value)
|
||||
value)
|
||||
((none)
|
||||
0)))
|
||||
"#,
|
||||
},
|
||||
UnsupportedRuntimeCase {
|
||||
name: "trim-ascii-start",
|
||||
symbol: "std.string.trim_ascii_start",
|
||||
source: r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
(std.string.len (std.string.trim_ascii_start " slovo")))
|
||||
"#,
|
||||
},
|
||||
UnsupportedRuntimeCase {
|
||||
name: "trim-ascii-end",
|
||||
symbol: "std.string.trim_ascii_end",
|
||||
source: r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
(std.string.len (std.string.trim_ascii_end "slovo ")))
|
||||
"#,
|
||||
},
|
||||
UnsupportedRuntimeCase {
|
||||
name: "trim-ascii",
|
||||
symbol: "std.string.trim_ascii",
|
||||
source: r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
(std.string.len (std.string.trim_ascii " slovo ")))
|
||||
"#,
|
||||
},
|
||||
];
|
||||
|
||||
for case in cases {
|
||||
let fixture = write_fixture(case.name, case.source);
|
||||
let output = run_glagol([fixture.as_os_str()]);
|
||||
assert_failure_stderr_contains(
|
||||
&format!("direct {} runtime call", case.symbol),
|
||||
&output,
|
||||
&format!("standard library call `{}` is not supported", case.symbol),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_std_string_search_trim_facades(std_string: &str) {
|
||||
assert!(
|
||||
std_string.starts_with("(module string (export "),
|
||||
"lib/std/string.slo must stay a source-authored module export"
|
||||
);
|
||||
|
||||
let mut non_allowed_std = std_string.to_owned();
|
||||
for allowed in ALLOWED_STD_REFERENCES {
|
||||
non_allowed_std = non_allowed_std.replace(allowed, "");
|
||||
}
|
||||
assert!(
|
||||
!non_allowed_std.contains("std."),
|
||||
"std.string beta20 helpers must use only existing std.result bridges and promoted beta16-or-earlier std.string primitives"
|
||||
);
|
||||
|
||||
for helper in STANDARD_STRING_SEARCH_TRIM_BETA20 {
|
||||
assert!(
|
||||
std_string.contains(&format!("(fn {} ", helper)),
|
||||
"lib/std/string.slo is missing source facade `{}`",
|
||||
helper
|
||||
);
|
||||
}
|
||||
|
||||
let search_trim_source = search_trim_source_region(std_string);
|
||||
for primitive in [
|
||||
("len", ["std.string.len", "(len "]),
|
||||
(
|
||||
"byte_at_result",
|
||||
["std.string.byte_at_result", "(byte_at_result "],
|
||||
),
|
||||
(
|
||||
"slice_result",
|
||||
["std.string.slice_result", "(slice_result "],
|
||||
),
|
||||
("starts_with", ["std.string.starts_with", "(starts_with "]),
|
||||
] {
|
||||
assert!(
|
||||
primitive
|
||||
.1
|
||||
.iter()
|
||||
.any(|needle| search_trim_source.contains(needle)),
|
||||
"beta20 search/trim facades must compose over existing beta16 string primitive `{}`",
|
||||
primitive.0
|
||||
);
|
||||
}
|
||||
|
||||
assert!(
|
||||
!std_string.contains("unicode")
|
||||
&& !std_string.contains("grapheme")
|
||||
&& !std_string.contains("locale")
|
||||
&& !std_string.contains("case_insensitive")
|
||||
&& !std_string.contains("regex"),
|
||||
"beta20 string helpers must not claim deferred Unicode, locale, case-folding, or regex APIs"
|
||||
);
|
||||
}
|
||||
|
||||
fn search_trim_source_region(source: &str) -> &str {
|
||||
let ends_with_end = function_range(source, "ends_with").1;
|
||||
let parse_start = function_range(source, "parse_i32_result").0;
|
||||
&source[ends_with_end..parse_start]
|
||||
}
|
||||
|
||||
fn function_range(source: &str, name: &str) -> (usize, usize) {
|
||||
let needle = format!("(fn {} ", name);
|
||||
let start = source
|
||||
.find(&needle)
|
||||
.unwrap_or_else(|| panic!("missing function `{}`", name));
|
||||
let mut depth = 0usize;
|
||||
|
||||
for (offset, byte) in source.as_bytes()[start..].iter().enumerate() {
|
||||
match byte {
|
||||
b'(' => depth += 1,
|
||||
b')' => {
|
||||
depth = depth
|
||||
.checked_sub(1)
|
||||
.unwrap_or_else(|| panic!("unbalanced function `{}`", name));
|
||||
if depth == 0 {
|
||||
return (start, start + offset + 1);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
panic!("unterminated function `{}`", name);
|
||||
}
|
||||
|
||||
fn run_glagol<I, S>(args: I) -> Output
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
Command::new(env!("CARGO_BIN_EXE_glagol"))
|
||||
.args(args)
|
||||
.current_dir(Path::new(env!("CARGO_MANIFEST_DIR")))
|
||||
.output()
|
||||
.expect("run glagol")
|
||||
}
|
||||
|
||||
fn write_project(name: &str, source: &str) -> PathBuf {
|
||||
let root = temp_root(name);
|
||||
let src = root.join("src");
|
||||
fs::create_dir_all(&src).unwrap_or_else(|err| panic!("create `{}`: {}", src.display(), err));
|
||||
fs::write(
|
||||
root.join("slovo.toml"),
|
||||
format!(
|
||||
"[project]\nname = \"{}\"\nsource_root = \"src\"\nentry = \"main\"\n",
|
||||
name
|
||||
),
|
||||
)
|
||||
.unwrap_or_else(|err| panic!("write project manifest: {}", err));
|
||||
fs::write(src.join("main.slo"), source.trim_start())
|
||||
.unwrap_or_else(|err| panic!("write project main.slo: {}", err));
|
||||
root
|
||||
}
|
||||
|
||||
fn write_fixture(name: &str, source: &str) -> PathBuf {
|
||||
let mut path = env::temp_dir();
|
||||
path.push(format!(
|
||||
"glagol-standard-string-search-trim-beta20-{}-{}-{}.slo",
|
||||
name,
|
||||
std::process::id(),
|
||||
NEXT_TEMP_ID.fetch_add(1, Ordering::Relaxed)
|
||||
));
|
||||
fs::write(&path, source.trim_start())
|
||||
.unwrap_or_else(|err| panic!("write `{}`: {}", path.display(), err));
|
||||
path
|
||||
}
|
||||
|
||||
fn temp_root(name: &str) -> PathBuf {
|
||||
let root = env::temp_dir().join(format!(
|
||||
"glagol-standard-string-search-trim-beta20-{}-{}-{}",
|
||||
name,
|
||||
std::process::id(),
|
||||
NEXT_TEMP_ID.fetch_add(1, Ordering::Relaxed)
|
||||
));
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
fs::create_dir_all(&root).unwrap_or_else(|err| panic!("create `{}`: {}", root.display(), err));
|
||||
root
|
||||
}
|
||||
|
||||
fn std_string_path() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("../lib/std/string.slo")
|
||||
}
|
||||
|
||||
fn read(path: &Path) -> String {
|
||||
fs::read_to_string(path).unwrap_or_else(|err| panic!("read `{}`: {}", path.display(), err))
|
||||
}
|
||||
|
||||
fn assert_success(context: &str, output: &Output) {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{} failed\nstatus: {:?}\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
output.status.code(),
|
||||
stdout,
|
||||
stderr
|
||||
);
|
||||
assert!(stderr.is_empty(), "{} wrote stderr:\n{}", context, stderr);
|
||||
}
|
||||
|
||||
fn assert_success_stdout(output: Output, expected: &str, context: &str) {
|
||||
assert_success(context, &output);
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
assert_eq!(stdout, expected, "{}", context);
|
||||
}
|
||||
|
||||
fn assert_failure_stderr_contains(context: &str, output: &Output, needle: &str) {
|
||||
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
assert!(
|
||||
!output.status.success(),
|
||||
"{} unexpectedly passed\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
stdout,
|
||||
stderr
|
||||
);
|
||||
assert!(
|
||||
stdout.is_empty(),
|
||||
"{} rejected compile wrote stdout:\n{}",
|
||||
context,
|
||||
stdout
|
||||
);
|
||||
assert!(
|
||||
stderr.contains(needle),
|
||||
"{} stderr did not contain `{}`:\n{}",
|
||||
context,
|
||||
needle,
|
||||
stderr
|
||||
);
|
||||
}
|
||||
|
||||
struct UnsupportedRuntimeCase {
|
||||
name: &'static str,
|
||||
symbol: &'static str,
|
||||
source: &'static str,
|
||||
}
|
||||
@ -15,10 +15,8 @@ const EXPECTED_TEST_OUTPUT: &str = concat!(
|
||||
"test \"explicit local string parse integer fallbacks\" ... ok\n",
|
||||
"test \"explicit local string parse float bool fallbacks\" ... ok\n",
|
||||
"test \"explicit local string parse custom fallbacks\" ... ok\n",
|
||||
"test \"explicit local string search helpers\" ... ok\n",
|
||||
"test \"explicit local string ascii trim helpers\" ... ok\n",
|
||||
"test \"explicit local string helpers all\" ... ok\n",
|
||||
"12 test(s) passed\n",
|
||||
"10 test(s) passed\n",
|
||||
);
|
||||
|
||||
const STANDARD_STRING_SOURCE_FALLBACK_HELPERS_ALPHA: &[&str] = &[
|
||||
@ -28,12 +26,6 @@ const STANDARD_STRING_SOURCE_FALLBACK_HELPERS_ALPHA: &[&str] = &[
|
||||
"slice_result",
|
||||
"starts_with",
|
||||
"ends_with",
|
||||
"contains",
|
||||
"index_of_option",
|
||||
"last_index_of_option",
|
||||
"trim_ascii_start",
|
||||
"trim_ascii_end",
|
||||
"trim_ascii",
|
||||
"parse_i32_result",
|
||||
"parse_i32_option",
|
||||
"parse_u32_result",
|
||||
@ -129,11 +121,11 @@ fn assert_local_string_fixture_is_source_authored(project: &Path) {
|
||||
"string fixture must use only the existing promoted std.string runtime names"
|
||||
);
|
||||
assert!(
|
||||
!string.contains("locale")
|
||||
!string.contains("trim")
|
||||
&& !string.contains("locale")
|
||||
&& !string.contains("unicode")
|
||||
&& !string.contains("bytes")
|
||||
&& !string.contains("case_insensitive")
|
||||
&& !string.contains("regex")
|
||||
&& !string.contains("host_error"),
|
||||
"string fixture must not claim deferred parsing or richer error APIs"
|
||||
);
|
||||
|
||||
@ -1,384 +0,0 @@
|
||||
use std::{
|
||||
fs,
|
||||
path::PathBuf,
|
||||
process::{Command, Output},
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
static NEXT_FIXTURE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[test]
|
||||
fn file_list_preserves_order_and_does_not_execute_bodies() {
|
||||
let fixture = write_fixture(
|
||||
"file-list",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(test "alpha first"
|
||||
true)
|
||||
|
||||
(test "beta would fail"
|
||||
false)
|
||||
"#,
|
||||
);
|
||||
|
||||
let output = run_glagol(["test".as_ref(), "--list".as_ref(), fixture.as_os_str()]);
|
||||
|
||||
assert_success_stdout(
|
||||
"file test list",
|
||||
output,
|
||||
"test \"alpha first\" ... selected\n\
|
||||
test \"beta would fail\" ... selected\n\
|
||||
2 test(s) selected (total_discovered 2, selected 2, passed 0, failed 0, skipped 0, filter none)\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn file_list_filter_marks_selected_and_skipped_in_order() {
|
||||
let fixture = write_fixture(
|
||||
"file-list-filter",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(test "alpha first"
|
||||
false)
|
||||
|
||||
(test "beta second"
|
||||
false)
|
||||
"#,
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"test".as_ref(),
|
||||
"--list".as_ref(),
|
||||
fixture.as_os_str(),
|
||||
"--filter".as_ref(),
|
||||
"beta".as_ref(),
|
||||
]);
|
||||
|
||||
assert_success_stdout(
|
||||
"file filtered test list",
|
||||
output,
|
||||
"test \"alpha first\" ... skipped\n\
|
||||
test \"beta second\" ... selected\n\
|
||||
1 test(s) selected (total_discovered 2, selected 1, passed 0, failed 0, skipped 1, filter \"beta\")\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn legacy_run_tests_list_matches_test_subcommand_list() {
|
||||
let fixture = write_fixture(
|
||||
"legacy-list",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(test "legacy first"
|
||||
false)
|
||||
|
||||
(test "legacy second"
|
||||
false)
|
||||
"#,
|
||||
);
|
||||
|
||||
let subcommand = run_glagol(["test".as_ref(), "--list".as_ref(), fixture.as_os_str()]);
|
||||
let legacy = run_glagol([
|
||||
"--run-tests".as_ref(),
|
||||
"--list".as_ref(),
|
||||
fixture.as_os_str(),
|
||||
]);
|
||||
|
||||
assert_success("test --list", &subcommand);
|
||||
assert_success("legacy --run-tests --list", &legacy);
|
||||
assert_eq!(
|
||||
legacy.stdout, subcommand.stdout,
|
||||
"legacy list output differed from test subcommand"
|
||||
);
|
||||
assert!(legacy.stderr.is_empty(), "legacy list wrote stderr");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn project_list_preserves_topological_order_and_filter_counts() {
|
||||
let project = write_project(
|
||||
"project-list",
|
||||
&[(
|
||||
"provider",
|
||||
"(module provider (export value))\n\n\
|
||||
(fn value () -> i32\n 1)\n\n\
|
||||
(test \"provider first\"\n false)\n",
|
||||
)],
|
||||
"(module main)\n\n\
|
||||
(import provider (value))\n\n\
|
||||
(fn main () -> i32\n (value))\n\n\
|
||||
(test \"consumer second\"\n false)\n",
|
||||
);
|
||||
|
||||
let output = run_glagol([
|
||||
"test".as_ref(),
|
||||
"--list".as_ref(),
|
||||
project.as_os_str(),
|
||||
"--filter".as_ref(),
|
||||
"consumer".as_ref(),
|
||||
]);
|
||||
|
||||
assert_success_stdout(
|
||||
"project filtered list",
|
||||
output,
|
||||
"test \"provider first\" ... skipped\n\
|
||||
test \"consumer second\" ... selected\n\
|
||||
1 test(s) selected (total_discovered 2, selected 1, passed 0, failed 0, skipped 1, filter \"consumer\")\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn workspace_list_preserves_package_order_without_running_tests() {
|
||||
let workspace = write_workspace(
|
||||
"workspace-list",
|
||||
"[workspace]\nmembers = [\"packages/app\", \"packages/util\"]\n",
|
||||
&[
|
||||
WorkspacePackageSpec {
|
||||
member: "packages/util",
|
||||
manifest: "[package]\nname = \"util\"\nversion = \"0.1.0\"\n",
|
||||
modules: &[(
|
||||
"util",
|
||||
"(module util (export answer))\n\n\
|
||||
(fn answer () -> i32\n 41)\n\n\
|
||||
(test \"util provider first\"\n false)\n",
|
||||
)],
|
||||
},
|
||||
WorkspacePackageSpec {
|
||||
member: "packages/app",
|
||||
manifest: "[package]\nname = \"app\"\nversion = \"0.1.0\"\n\n[dependencies]\nutil = { path = \"../util\" }\n",
|
||||
modules: &[(
|
||||
"main",
|
||||
"(module main)\n\n\
|
||||
(import util.util (answer))\n\n\
|
||||
(fn main () -> i32\n (answer))\n\n\
|
||||
(test \"app consumer second\"\n false)\n",
|
||||
)],
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
let output = run_glagol(["test".as_ref(), "--list".as_ref(), workspace.as_os_str()]);
|
||||
|
||||
assert_success_stdout(
|
||||
"workspace list",
|
||||
output,
|
||||
"test \"util provider first\" ... selected\n\
|
||||
test \"app consumer second\" ... selected\n\
|
||||
2 test(s) selected (total_discovered 2, selected 2, passed 0, failed 0, skipped 0, filter none)\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ordinary_test_output_stays_byte_stable() {
|
||||
let fixture = write_fixture(
|
||||
"ordinary-test",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(test "alpha first"
|
||||
true)
|
||||
|
||||
(test "beta second"
|
||||
true)
|
||||
"#,
|
||||
);
|
||||
|
||||
let subcommand = run_glagol(["test".as_ref(), fixture.as_os_str()]);
|
||||
assert_success_stdout(
|
||||
"ordinary test",
|
||||
subcommand,
|
||||
"test \"alpha first\" ... ok\n\
|
||||
test \"beta second\" ... ok\n\
|
||||
2 test(s) passed\n",
|
||||
);
|
||||
|
||||
let legacy = run_glagol(["--run-tests".as_ref(), fixture.as_os_str()]);
|
||||
assert_success_stdout(
|
||||
"ordinary legacy run-tests",
|
||||
legacy,
|
||||
"test \"alpha first\" ... ok\n\
|
||||
test \"beta second\" ... ok\n\
|
||||
2 test(s) passed\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_mode_reuses_checked_diagnostics_for_invalid_tests() {
|
||||
let fixture = write_fixture(
|
||||
"invalid-list",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(test "not bool"
|
||||
1)
|
||||
"#,
|
||||
);
|
||||
|
||||
let output = run_glagol(["test".as_ref(), "--list".as_ref(), fixture.as_os_str()]);
|
||||
|
||||
assert_failure_stderr_contains(
|
||||
"invalid list",
|
||||
&output,
|
||||
&[
|
||||
"TestExpressionNotBool",
|
||||
"Expected:",
|
||||
"bool",
|
||||
"Found:",
|
||||
"i32",
|
||||
],
|
||||
);
|
||||
assert!(
|
||||
output.stdout.is_empty(),
|
||||
"invalid list wrote stdout:\n{}",
|
||||
String::from_utf8_lossy(&output.stdout)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_flag_is_rejected_outside_test_mode() {
|
||||
let fixture = write_fixture(
|
||||
"list-outside-test",
|
||||
r#"
|
||||
(module main)
|
||||
|
||||
(fn main () -> i32
|
||||
0)
|
||||
"#,
|
||||
);
|
||||
|
||||
let output = run_glagol(["check".as_ref(), "--list".as_ref(), fixture.as_os_str()]);
|
||||
|
||||
assert_failure_stderr_contains(
|
||||
"check --list",
|
||||
&output,
|
||||
&["`--list` is only supported with `test` and `--run-tests`"],
|
||||
);
|
||||
}
|
||||
|
||||
fn write_fixture(name: &str, source: &str) -> PathBuf {
|
||||
let path = unique_path(name).with_extension("slo");
|
||||
fs::write(&path, source).expect("write fixture");
|
||||
path
|
||||
}
|
||||
|
||||
fn write_project(name: &str, modules: &[(&str, &str)], main: &str) -> PathBuf {
|
||||
let root = unique_path(name);
|
||||
let src = root.join("src");
|
||||
fs::create_dir_all(&src).expect("create project src");
|
||||
fs::write(
|
||||
root.join("slovo.toml"),
|
||||
format!(
|
||||
"[project]\nname = \"{}\"\nsource_root = \"src\"\nentry = \"main\"\n",
|
||||
name
|
||||
),
|
||||
)
|
||||
.expect("write project manifest");
|
||||
fs::write(src.join("main.slo"), main).expect("write project main");
|
||||
for (module, source) in modules {
|
||||
fs::write(src.join(format!("{}.slo", module)), source).expect("write project module");
|
||||
}
|
||||
root
|
||||
}
|
||||
|
||||
struct WorkspacePackageSpec<'a> {
|
||||
member: &'a str,
|
||||
manifest: &'a str,
|
||||
modules: &'a [(&'a str, &'a str)],
|
||||
}
|
||||
|
||||
fn write_workspace(
|
||||
name: &str,
|
||||
workspace_manifest: &str,
|
||||
packages: &[WorkspacePackageSpec<'_>],
|
||||
) -> PathBuf {
|
||||
let root = unique_path(name);
|
||||
fs::create_dir_all(&root).expect("create workspace root");
|
||||
fs::write(root.join("slovo.toml"), workspace_manifest).expect("write workspace manifest");
|
||||
for package in packages {
|
||||
let package_root = root.join(package.member);
|
||||
let src = package_root.join("src");
|
||||
fs::create_dir_all(&src).expect("create workspace package src");
|
||||
fs::write(package_root.join("slovo.toml"), package.manifest)
|
||||
.expect("write workspace package manifest");
|
||||
for (module, source) in package.modules {
|
||||
fs::write(src.join(format!("{}.slo", module)), source)
|
||||
.expect("write workspace package module");
|
||||
}
|
||||
}
|
||||
root
|
||||
}
|
||||
|
||||
fn unique_path(name: &str) -> PathBuf {
|
||||
let id = NEXT_FIXTURE_ID.fetch_add(1, Ordering::SeqCst);
|
||||
let nanos = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map(|duration| duration.as_nanos())
|
||||
.unwrap_or(0);
|
||||
std::env::temp_dir().join(format!(
|
||||
"glagol-test-discovery-beta19-{}-{}-{}-{}",
|
||||
std::process::id(),
|
||||
nanos,
|
||||
id,
|
||||
name
|
||||
))
|
||||
}
|
||||
|
||||
fn run_glagol<I, S>(args: I) -> Output
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<std::ffi::OsStr>,
|
||||
{
|
||||
Command::new(env!("CARGO_BIN_EXE_glagol"))
|
||||
.args(args)
|
||||
.output()
|
||||
.expect("run glagol")
|
||||
}
|
||||
|
||||
fn assert_success(context: &str, output: &Output) {
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"{} failed\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_success_stdout(context: &str, output: Output, expected: &str) {
|
||||
assert_success(context, &output);
|
||||
assert_eq!(
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
expected,
|
||||
"{} stdout mismatch",
|
||||
context
|
||||
);
|
||||
assert!(
|
||||
output.stderr.is_empty(),
|
||||
"{} wrote stderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_failure_stderr_contains(context: &str, output: &Output, expected: &[&str]) {
|
||||
assert!(
|
||||
!output.status.success(),
|
||||
"{} unexpectedly succeeded\nstdout:\n{}\nstderr:\n{}",
|
||||
context,
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
for needle in expected {
|
||||
assert!(
|
||||
stderr.contains(needle),
|
||||
"{} stderr missing `{}`:\n{}",
|
||||
context,
|
||||
needle,
|
||||
stderr
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -41,21 +41,6 @@ Released in `1.0.0-beta.1`: `glagol run`, `glagol clean`,
|
||||
installed std/runtime discovery, README coverage, focused DX tests, and a
|
||||
concise release-gate success line.
|
||||
|
||||
Released in `1.0.0-beta.19`: test discovery and user-project conformance
|
||||
tooling. The scope adds the
|
||||
`glagol test --list <file|project|workspace>` command and legacy
|
||||
`glagol --run-tests --list <file>` so users and tooling can list
|
||||
checked/discovered tests without executing test bodies. It preserves existing
|
||||
single-file, project, and workspace ordering, honors
|
||||
`--filter <substring>`, and keeps the output beta-scoped rather than a stable
|
||||
public schema.
|
||||
|
||||
Beta19 non-scope: no parallel test execution, retries, tags/groups, coverage
|
||||
reports, event streams, stable artifact-manifest or Markdown schema freeze,
|
||||
LSP/watch behavior, SARIF/daemon protocols, JSON expansion, runtime helper
|
||||
names, source-language syntax, package registries, semver solving, or
|
||||
performance claims.
|
||||
|
||||
Why first: it reduces friction for every later feature and gives users a better
|
||||
way to exercise the beta.
|
||||
|
||||
@ -108,29 +93,6 @@ generated from `lib/std/*.slo` and guarded by `scripts/release-gate.sh`.
|
||||
that composes `std.fs`, `std.string`, `std.math`, and `std.io` through explicit
|
||||
standard imports, with focused check/test/doc/run coverage.
|
||||
|
||||
Released in `1.0.0-beta.20`: source-authored `std.string` search and ASCII
|
||||
trim helpers. The scope adds `contains`, `index_of_option`,
|
||||
`last_index_of_option`, `trim_ascii_start`, `trim_ascii_end`, and
|
||||
`trim_ascii` over existing byte-oriented string primitives, with explicit
|
||||
`std.string` import examples and focused compiler gates. Empty needles match
|
||||
at first index `0` and last index `(len value)`; ASCII trimming removes only
|
||||
bytes `9`, `10`, `11`, `12`, `13`, and `32`. Unicode/grapheme semantics,
|
||||
case folding, regexes, tokenizers, mutable strings, slice/view syntax, new
|
||||
runtime names, and stable stdlib/API promises remain deferred.
|
||||
|
||||
Released in `1.0.0-beta.23`: the public
|
||||
[`docs/language/STDLIB_TIERS.md`](language/STDLIB_TIERS.md) ledger defines the
|
||||
current standard-library tier labels `beta-supported`, `experimental`, and
|
||||
`internal`, and aligns the docs around the generated
|
||||
[`docs/language/STDLIB_API.md`](language/STDLIB_API.md) signature catalog.
|
||||
JSON, loopback networking, random/time, and filesystem resource-handle helpers
|
||||
are documented as experimental domains. Concrete vector modules remain
|
||||
beta-supported concrete lanes, not a generic collections freeze. The slice is
|
||||
documentation/catalog tooling clarity only: no syntax, helper, runtime,
|
||||
manifest-schema, Markdown-schema, ABI/layout, or stable stdlib/API behavior
|
||||
changes. It updates generated catalog output and the release gate so tier
|
||||
metadata is visible and checked.
|
||||
|
||||
Why third: stdlib growth is already broad enough that naming and stability tiers
|
||||
matter more than adding another isolated helper group.
|
||||
|
||||
@ -182,14 +144,6 @@ local-package rules. Lockfiles, remote registries, semver solving, publishing,
|
||||
optional/dev/target dependencies, and stable package ABI/layout remain out of
|
||||
scope.
|
||||
|
||||
Released in `1.0.0-beta.24`: package manifest identity and dependency
|
||||
diagnostics are tightened without changing the package model. Duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
are explicit diagnostics. The slice adds no remote registry, lockfile,
|
||||
semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, stable package ABI/layout, source-language change, runtime
|
||||
change, or standard-library change.
|
||||
|
||||
Why fifth: stable package rules are a prerequisite for a usable public language,
|
||||
but remote publishing can wait.
|
||||
|
||||
@ -252,15 +206,6 @@ object/array parsing, tokenizer objects, Unicode escape decoding or
|
||||
normalization, embedded NUL policy, streaming, schema validation, and stable
|
||||
ABI/API guarantees remain deferred.
|
||||
|
||||
Released in `1.0.0-beta.21`: `lib/std/json.slo` adds source-authored scalar
|
||||
document parse facades for string, bool, `i32`, `u32`, `i64`, `u64`, `f64`,
|
||||
and exact `null`. Each helper trims ASCII whitespace around the whole document
|
||||
with `std.string.trim_ascii`, then delegates to the already released exact
|
||||
value-token parser. This intentionally remains scalar document parsing only:
|
||||
object/array parsing, recursive JSON values, parser/tokenizer objects,
|
||||
maps/sets, streaming, new compiler-known runtime names, broader Unicode escape
|
||||
policy, embedded NUL policy, and stable ABI/API guarantees remain deferred.
|
||||
|
||||
Why seventh: networking and CLI tools need data interchange, but a complete JSON
|
||||
library depends on collection work.
|
||||
|
||||
@ -562,11 +507,8 @@ foundation before richer string or data-interchange APIs are credible.
|
||||
Slovo should not become stable until all of these are true:
|
||||
|
||||
- migration and deprecation policy is documented
|
||||
- `lib/std` has explicit beta-supported, experimental, and internal tiers plus
|
||||
a later stable-tier/deprecation policy before `1.0.0`
|
||||
- `lib/std` has explicit stable and experimental tiers
|
||||
- package/workspace behavior is deterministic
|
||||
- package manifest identity and dependency-key failures have explicit
|
||||
diagnostics
|
||||
- conformance tests cover user-shaped projects
|
||||
- release gates are reproducible on a clean checkout
|
||||
- diagnostics and formatter output are stable for promoted features
|
||||
|
||||
@ -10,201 +10,10 @@ integration/readiness release, not the first real beta.
|
||||
|
||||
## Unreleased
|
||||
|
||||
No active unreleased compiler scope is documented here yet.
|
||||
Next scoped Glagol work is expected to continue after the `1.0.0-beta.18`
|
||||
JSON string token parsing foundation.
|
||||
|
||||
## 1.0.0-beta.24
|
||||
|
||||
Release label: `1.0.0-beta.24`
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Release state: package manifest identity and local dependency diagnostic
|
||||
hardening
|
||||
|
||||
### Summary
|
||||
|
||||
The beta.24 compiler/tooling slice tightens local package manifest diagnostics
|
||||
without changing the language, runtime, stdlib, or package graph model:
|
||||
|
||||
- Bump the `glagol` compiler package version to `1.0.0-beta.24`.
|
||||
- Diagnose duplicate package manifest keys explicitly.
|
||||
- Diagnose invalid dependency keys explicitly.
|
||||
- Diagnose duplicate dependency keys explicitly.
|
||||
- Keep dependency records local-path-only and require dependency keys to match
|
||||
target package names.
|
||||
|
||||
### Explicit Deferrals
|
||||
|
||||
This release does not implement remote registries, lockfiles,
|
||||
semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, feature flags, build scripts, package archives, stable package
|
||||
ABI/layout, source-language syntax, runtime C capabilities, standard-library
|
||||
helpers, compiler-known `std.*` runtime names, stable artifact-manifest schema
|
||||
guarantees, stable Markdown schemas, LSP/watch/SARIF/daemon protocols, or
|
||||
performance claims.
|
||||
|
||||
## 1.0.0-beta.23
|
||||
|
||||
Release label: `1.0.0-beta.23`
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Release state: standard-library stability tier ledger and catalog alignment
|
||||
|
||||
### Summary
|
||||
|
||||
The beta.23 compiler/tooling slice aligns generated standard-library API
|
||||
catalog output with the public tier ledger:
|
||||
|
||||
- Bump the `glagol` compiler package version to `1.0.0-beta.23`.
|
||||
- Render per-module and per-helper `beta-supported` or `experimental` tier
|
||||
metadata in `docs/language/STDLIB_API.md`.
|
||||
- Add `scripts/check-stdlib-api-tiers.js` and wire it into the release gate.
|
||||
- Mark JSON, loopback networking, random/time, and filesystem resource-handle
|
||||
helpers as experimental in generated catalog output.
|
||||
- Keep concrete vector modules beta-supported concrete lanes with an explicit
|
||||
no-generic-collection-freeze note.
|
||||
|
||||
### Explicit Deferrals
|
||||
|
||||
This release does not implement source-language syntax, standard-library
|
||||
helpers, compiler-known `std.*` runtime names, runtime C capabilities, package
|
||||
or workspace behavior, stable artifact-manifest schema guarantees, stable
|
||||
Markdown schemas, LSP/watch/SARIF/daemon protocols, performance claims,
|
||||
stable ABI/layout, or a stable standard-library compatibility contract.
|
||||
|
||||
## 1.0.0-beta.22
|
||||
|
||||
Release label: `1.0.0-beta.22`
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Release state: run manifest and execution report hardening
|
||||
|
||||
### Summary
|
||||
|
||||
The beta.22 compiler/tooling slice hardens `glagol run --manifest` evidence
|
||||
without changing the Slovo language or standard-library surface:
|
||||
|
||||
- Bump the `glagol` compiler package version to `1.0.0-beta.22`.
|
||||
- Add an additive run-report block to run-mode artifact manifests.
|
||||
- Record executed-program exit status, captured stdout, captured stderr, and
|
||||
forwarded program arguments.
|
||||
- Keep the run report as beta tooling metadata under the existing
|
||||
`slovo.artifact-manifest` version `1` contract rather than a stable schema
|
||||
freeze.
|
||||
- Keep non-run modes outside this run-report requirement.
|
||||
|
||||
### Explicit Deferrals
|
||||
|
||||
This release does not implement source-language syntax, standard-library
|
||||
helpers, compiler-known `std.*` runtime names, runtime C capabilities, package
|
||||
or workspace behavior, stable artifact-manifest schema guarantees, stable
|
||||
Markdown schemas, LSP/watch/SARIF/daemon protocols, performance claims,
|
||||
stable ABI/layout, or a stable standard-library compatibility contract.
|
||||
|
||||
## 1.0.0-beta.21
|
||||
|
||||
Release label: `1.0.0-beta.21`
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Release state: JSON document scalar parsing foundation
|
||||
|
||||
### Summary
|
||||
|
||||
The beta.21 compiler/tooling slice adds focused coverage for source-authored
|
||||
`std.json` document-scalar helpers without adding compiler-known runtime names:
|
||||
|
||||
- Bump the `glagol` compiler package version to `1.0.0-beta.21`.
|
||||
- Add focused `standard_json_document_scalar_parsing_beta21` coverage for
|
||||
explicit `std.json` imports of `parse_string_document_result`,
|
||||
`parse_bool_document_result`, `parse_i32_document_result`,
|
||||
`parse_u32_document_result`, `parse_i64_document_result`,
|
||||
`parse_u64_document_result`, `parse_f64_document_result`, and
|
||||
`parse_null_document_result`.
|
||||
- Gate the helpers as source-authored public facades over existing JSON token
|
||||
parsers and source-level document trimming/composition.
|
||||
- Require direct `std.json.parse_*_document_result` runtime calls and private
|
||||
`__glagol_json_*document*` runtime symbols to remain unsupported.
|
||||
- Add the focused beta21 test to `scripts/release-gate.sh`.
|
||||
|
||||
### Explicit Deferrals
|
||||
|
||||
This release does not implement object parsing, array parsing, recursive JSON
|
||||
values, tokenizers, Unicode escape decoding, streaming, schema validation,
|
||||
stable parser APIs, new compiler-known `std.*` runtime names, runtime C
|
||||
changes, source-language syntax, stable ABI/layout, or a stable
|
||||
standard-library compatibility contract.
|
||||
|
||||
## 1.0.0-beta.20
|
||||
|
||||
Release label: `1.0.0-beta.20`
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Release state: string search and ASCII trim foundation
|
||||
|
||||
### Summary
|
||||
|
||||
The beta.20 compiler/tooling slice adds focused coverage for source-authored
|
||||
`std.string` search and ASCII trim helpers without adding compiler-known
|
||||
runtime names:
|
||||
|
||||
- Bump the `glagol` compiler package version to `1.0.0-beta.20`.
|
||||
- Add focused `standard_string_search_trim_beta20` coverage for explicit
|
||||
`std.string` imports of `contains`, `index_of_option`,
|
||||
`last_index_of_option`, `trim_ascii_start`, `trim_ascii_end`, and
|
||||
`trim_ascii`.
|
||||
- Require the new public helpers to remain source facades over beta16-or-earlier
|
||||
string primitives and existing result/option shapes.
|
||||
- Gate direct `std.string.contains`, `std.string.index_of_option`,
|
||||
`std.string.last_index_of_option`, `std.string.trim_ascii_start`,
|
||||
`std.string.trim_ascii_end`, and `std.string.trim_ascii` runtime calls as
|
||||
unsupported compiler-known names.
|
||||
- Add the focused beta20 test to `scripts/release-gate.sh`.
|
||||
|
||||
### Explicit Deferrals
|
||||
|
||||
This release does not implement new compiler-known `std.*` runtime names,
|
||||
runtime C changes, source-language syntax, Unicode or grapheme semantics,
|
||||
locale/case-folded search, regex, tokenizer/parser APIs, stable string
|
||||
ABI/layout, stable allocation ownership rules, or a stable standard-library
|
||||
compatibility contract.
|
||||
|
||||
## 1.0.0-beta.19
|
||||
|
||||
Release label: `1.0.0-beta.19`
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Release state: test discovery and user-project conformance foundation
|
||||
|
||||
### Summary
|
||||
|
||||
The beta.19 compiler/tooling contract adds deterministic list-only test
|
||||
discovery without changing normal test execution output:
|
||||
|
||||
- `glagol test --list <file|project|workspace>`
|
||||
- `glagol --run-tests --list <file>` for legacy single-file test execution
|
||||
|
||||
- Bump the `glagol` compiler package version to `1.0.0-beta.19`.
|
||||
- Reuse the same checked discovery path as normal `glagol test` for file,
|
||||
project, and workspace inputs.
|
||||
- Preserve current file/project/workspace test ordering.
|
||||
- Honor `--filter <substring>` by marking selected and skipped discovered
|
||||
tests without executing test bodies or triggering runtime/test side effects.
|
||||
- Keep normal `glagol test` and legacy `glagol --run-tests` output unchanged
|
||||
when `--list` is absent.
|
||||
- Add focused beta19 release-gate coverage for test discovery.
|
||||
|
||||
### Explicit Deferrals
|
||||
|
||||
This release does not implement parallel test execution, retries, tags/groups, coverage,
|
||||
event streams, stable artifact-manifest or Markdown schema freezes,
|
||||
LSP/watch/SARIF/daemon protocols, JSON expansion, runtime helper names,
|
||||
source-language syntax, package registries, semver solving, and performance
|
||||
claims.
|
||||
No unreleased compiler scope is committed here yet.
|
||||
|
||||
## 1.0.0-beta.18
|
||||
|
||||
|
||||
@ -9,9 +9,10 @@ Compiler rule: make the tree visible. The pipeline should remain:
|
||||
.slo source -> tokens -> S-expression tree -> AST -> typed AST -> LLVM IR text -> hosted Clang/runtime executable step
|
||||
```
|
||||
|
||||
Long-horizon compiler planning lives in `.llm/ROADMAP_TO_STABLE.md`. It
|
||||
mirrors Slovo's release train beyond the first real general-purpose beta
|
||||
toolchain.
|
||||
Long-horizon compiler planning lives in
|
||||
`.llm/GENERAL_PURPOSE_LANGUAGE_ROADMAP.md`. It mirrors Slovo's experimental
|
||||
release train from the historical `v2.0.0-beta.1` tag toward and beyond the
|
||||
first real general-purpose beta toolchain.
|
||||
|
||||
Release maturity policy lives in `.llm/RELEASE_MATURITY_POLICY.md`. Historical
|
||||
`exp-*` releases remain experimental maturity. `1.0.0-beta` is the first real
|
||||
@ -21,8 +22,8 @@ general-purpose beta release.
|
||||
|
||||
A Glagol feature is done only when it has parser/lowerer support, checker behavior, diagnostics for invalid forms, backend behavior or explicit unsupported diagnostics, and tests.
|
||||
|
||||
Current stage: `1.0.0-beta.24`, released on 2026-05-23 as package manifest
|
||||
identity and local dependency diagnostic hardening. It keeps the
|
||||
Current stage: `1.0.0-beta.18`, released on 2026-05-23 as a JSON string
|
||||
token parsing runtime foundation. It keeps the
|
||||
`1.0.0-beta` language/compiler support baseline and includes the
|
||||
`1.0.0-beta.1` tooling hardening release, the `1.0.0-beta.2` runtime/resource
|
||||
foundation release, the `1.0.0-beta.3` standard-library stabilization release,
|
||||
@ -88,67 +89,16 @@ diagnostics. It keeps object parsing, array parsing, recursive values,
|
||||
tokenizers, Unicode escape decoding, Unicode normalization, streaming, schema
|
||||
validation, embedded NUL support in the current null-terminated string ABI, and
|
||||
stable JSON APIs deferred.
|
||||
The beta.19 compiler/tooling slice adds
|
||||
`glagol test --list <file|project|workspace>` and legacy
|
||||
`glagol --run-tests --list <file>` support. The list action reuses the same
|
||||
checked discovery path as normal test execution, preserves existing
|
||||
single-file, project, and workspace ordering, honors `--filter <substring>`,
|
||||
and avoids executing test bodies. It keeps normal test execution output
|
||||
unchanged when `--list` is absent.
|
||||
|
||||
The beta.20 compiler/tooling slice bumps the package version and gates
|
||||
source-authored `std.string` facades for `contains`, `index_of_option`,
|
||||
`last_index_of_option`, `trim_ascii_start`, `trim_ascii_end`, and `trim_ascii`
|
||||
through explicit `std.string` imports. It keeps those helpers composed over
|
||||
beta16-or-earlier string primitives and existing option/result shapes, and
|
||||
verifies that direct compiler-known runtime calls for the new helper names
|
||||
remain unsupported.
|
||||
|
||||
The beta.21 compiler/tooling slice bumps the package version and gates
|
||||
source-authored `std.json` document scalar facades for
|
||||
`parse_string_document_result`, `parse_bool_document_result`,
|
||||
`parse_i32_document_result`, `parse_u32_document_result`,
|
||||
`parse_i64_document_result`, `parse_u64_document_result`,
|
||||
`parse_f64_document_result`, and `parse_null_document_result` through explicit
|
||||
`std.json` imports. It keeps those helpers source-authored over the existing
|
||||
JSON token parser family and existing source-level composition, and verifies
|
||||
that direct compiler-known runtime calls and private `__glagol_json_*document*`
|
||||
symbols for the new helper names remain unsupported.
|
||||
|
||||
The beta.22 compiler/tooling slice bumps the package version and hardens
|
||||
`glagol run --manifest` evidence with an additive run-report block in
|
||||
run-mode artifact manifests. The block records executed-program exit status,
|
||||
captured stdout, captured stderr, and forwarded program arguments. It is beta
|
||||
CLI evidence metadata under the existing `slovo.artifact-manifest` version
|
||||
`1` contract, not a stable schema freeze, and it adds no source-language,
|
||||
runtime, package, or standard-library surface.
|
||||
|
||||
The beta.23 compiler/tooling slice bumps the package version and updates
|
||||
generated `docs/language/STDLIB_API.md` output with per-module and per-helper
|
||||
tier metadata. It adds a release-gate checker for the tier catalog, marks JSON,
|
||||
loopback networking, random/time, and filesystem resource-handle helpers as
|
||||
experimental, and keeps concrete vector modules beta-supported concrete lanes
|
||||
without claiming generic collection stability. It adds no source-language,
|
||||
runtime, package, or standard-library helper surface.
|
||||
|
||||
The beta.24 compiler/tooling slice bumps the package version and tightens
|
||||
local package manifest diagnostics. Duplicate package manifest keys, invalid
|
||||
dependency keys, and duplicate dependency keys are explicit diagnostics. It
|
||||
keeps the existing closed local workspace model and adds no remote registry,
|
||||
lockfile, semantic-version solving, package publishing, optional/dev/target
|
||||
dependencies, stable package ABI/layout, source-language behavior, runtime
|
||||
behavior, or standard-library behavior.
|
||||
|
||||
Generic vectors, generic collections, maps, sets, generic stdlib dispatch,
|
||||
runtime collection changes, collection unification, stable human diagnostic
|
||||
text, stable artifact-manifest or Markdown schema freezes, LSP/watch
|
||||
protocols, SARIF/daemon protocols, re-exports/globs/hierarchical modules,
|
||||
registry semantics, semver solving, mutable vectors, stable slice/view APIs,
|
||||
tokenizers, broader JSON parsing, runtime helper names, source-language
|
||||
syntax, parallel test execution, retries, tags/groups, coverage/event streams,
|
||||
performance claims, ABI/layout stability, and a stable stdlib/API
|
||||
compatibility freeze remain unimplemented until a later scoped contract
|
||||
promotes them explicitly.
|
||||
Next stage target: post-`1.0.0-beta.18` developer-experience, package, and
|
||||
collection/generic planning. Generic vectors, generic collections, maps, sets,
|
||||
generic stdlib dispatch, runtime collection changes, collection unification,
|
||||
stable human diagnostic text, stable Markdown schema, LSP/watch protocols,
|
||||
SARIF/daemon protocols, re-exports/globs/hierarchical modules, registry
|
||||
semantics, mutable vectors, stable slice/view APIs, tokenizers, broader JSON
|
||||
parsing, iterators, performance claims, ABI/layout stability, and a stable
|
||||
stdlib/API compatibility freeze remain unimplemented until a later scoped
|
||||
contract promotes them explicitly.
|
||||
|
||||
The final experimental precursor scope is `exp-125`. Its unsigned direct-value
|
||||
flow, parse/format runtime lanes, and matching staged stdlib helper breadth
|
||||
@ -722,8 +672,6 @@ Alpha is the latest compiler semantic/runtime-operation support slice.
|
||||
- [x] Diagnose missing packages, duplicate package names, dependency cycles,
|
||||
path escapes, invalid package names, invalid package versions, private
|
||||
visibility, and dependency key mismatches.
|
||||
- [x] Diagnose duplicate package manifest keys, invalid dependency keys, and
|
||||
duplicate dependency keys explicitly.
|
||||
- [x] Keep registries, lockfiles, semver solving, aliases/globs/re-exports,
|
||||
generated code, build scripts, publishing, optional/dev/target
|
||||
dependencies, stable package ABI, and remote dependencies deferred.
|
||||
|
||||
@ -237,47 +237,6 @@ Future releases may add codes or split broad codes when the release scope
|
||||
requires more precise tooling behavior. Such changes must be documented using
|
||||
the compatibility classes above.
|
||||
|
||||
## Project And Workspace Codes
|
||||
|
||||
Project, package, and workspace diagnostics are covered by integration tests
|
||||
because they often require multiple files, manifests, or generated temporary
|
||||
directories rather than a single `.slo` golden fixture. These codes still use
|
||||
the same `slovo.diagnostic` version `1` schema and PascalCase code policy.
|
||||
|
||||
Current package/workspace loader and graph diagnostics include:
|
||||
|
||||
- `DependencyNameMismatch`
|
||||
- `DependencyPathEscape`
|
||||
- `DuplicatePackageDependencyName`
|
||||
- `DuplicatePackageName`
|
||||
- `DuplicateWorkspaceMember`
|
||||
- `InvalidPackageDependencyName`
|
||||
- `InvalidPackageName`
|
||||
- `InvalidPackageVersion`
|
||||
- `MissingPackageDependency`
|
||||
- `MissingPackageModule`
|
||||
- `PackageDependencyCycle`
|
||||
- `PackageImportNotDependency`
|
||||
- `PackageManifestInvalid`
|
||||
- `PackageSourceReadFailed`
|
||||
- `PackageSourceRootEscape`
|
||||
- `PackageSourceRootMissing`
|
||||
- `ProjectEntryMainInvalidSignature`
|
||||
- `ProjectEntryMainMissing`
|
||||
- `ProjectManifestInvalid`
|
||||
- `ProjectManifestReadFailed`
|
||||
- `ProjectSourceReadFailed`
|
||||
- `ProjectSourceRootMissing`
|
||||
- `UnsupportedDependency`
|
||||
- `WorkspaceBuildAmbiguousEntryPackage`
|
||||
- `WorkspaceDefaultPackageEntryMissing`
|
||||
- `WorkspaceDefaultPackageMissing`
|
||||
- `WorkspaceEntryMainInvalidSignature`
|
||||
- `WorkspaceEntryMainMissing`
|
||||
- `WorkspaceManifestInvalid`
|
||||
- `WorkspaceMemberManifestMissing`
|
||||
- `WorkspaceMemberPathEscape`
|
||||
|
||||
## Explicit Deferrals
|
||||
|
||||
`1.0.0-beta.13` does not define:
|
||||
|
||||
@ -56,10 +56,6 @@ used for solving dependency constraints.
|
||||
dependency paths must stay inside the workspace/package boundary after
|
||||
normalization and canonical path checks.
|
||||
|
||||
Duplicate keys in package manifests are `PackageManifestInvalid` diagnostics.
|
||||
The manifest loader does not silently choose one spelling for repeated package
|
||||
identity or dependency entries.
|
||||
|
||||
Dependencies are local path records only. The dependency key must match the
|
||||
target package name:
|
||||
|
||||
@ -67,11 +63,6 @@ target package name:
|
||||
mathlib = { path = "../mathlib" }
|
||||
```
|
||||
|
||||
Dependency keys use the same package-name shape as package identities. Invalid
|
||||
dependency keys are `InvalidPackageDependencyName` diagnostics, and duplicate
|
||||
dependency keys are `DuplicatePackageDependencyName` diagnostics before the
|
||||
local dependency graph is accepted.
|
||||
|
||||
## Imports
|
||||
|
||||
Within a workspace, a package imports a dependency module through the package
|
||||
@ -115,12 +106,9 @@ The package/workspace gate covers these user-facing error families:
|
||||
- missing member manifests
|
||||
- duplicate normalized workspace members
|
||||
- invalid member or dependency paths
|
||||
- duplicate package manifest keys
|
||||
- invalid package names and versions
|
||||
- duplicate package names
|
||||
- missing local path dependencies
|
||||
- invalid dependency keys
|
||||
- duplicate dependency keys
|
||||
- dependency key/name mismatches
|
||||
- package dependency cycles
|
||||
- private cross-package imports
|
||||
|
||||
@ -8,7 +8,7 @@ Historical `exp-*` releases listed here are experimental maturity milestones.
|
||||
The pushed tag `v2.0.0-beta.1` is historical. It is now documented as an
|
||||
experimental integration/readiness release, not as a beta maturity claim.
|
||||
|
||||
The current release is `1.0.0-beta.24`, published on 2026-05-23. It keeps the
|
||||
The current release is `1.0.0-beta.18`, published on 2026-05-23. It keeps the
|
||||
`1.0.0-beta` language surface, includes the first post-beta tooling/install
|
||||
hardening bundle from `1.0.0-beta.1`, and adds the first runtime/resource
|
||||
foundation bundle from `1.0.0-beta.2` plus the first standard-library
|
||||
@ -28,189 +28,11 @@ collection alias unification and generic reservation slice from
|
||||
collection ledger from `1.0.0-beta.15`, plus the string scanning and token
|
||||
boundary foundation from `1.0.0-beta.16`, and the JSON primitive scalar
|
||||
parsing foundation from `1.0.0-beta.17`, plus the JSON string token parsing
|
||||
foundation from `1.0.0-beta.18`, the test discovery and user-project
|
||||
conformance foundation from `1.0.0-beta.19`, and the string search and ASCII
|
||||
trim foundation from `1.0.0-beta.20`, plus the JSON document scalar parsing
|
||||
foundation from `1.0.0-beta.21`, and the run manifest execution-report
|
||||
hardening slice from `1.0.0-beta.22`, plus the standard-library stability tier
|
||||
ledger and catalog alignment slice from `1.0.0-beta.23`, and the package
|
||||
manifest identity and local dependency diagnostic hardening slice from
|
||||
`1.0.0-beta.24`.
|
||||
foundation from `1.0.0-beta.18`.
|
||||
|
||||
## Unreleased
|
||||
|
||||
No active unreleased language scope is documented here yet.
|
||||
|
||||
## 1.0.0-beta.24
|
||||
|
||||
Release label: `1.0.0-beta.24`
|
||||
|
||||
Release name: Package Manifest Identity And Dependency Discipline
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Status: released beta package/workspace diagnostic hardening on the
|
||||
`1.0.0-beta` language baseline.
|
||||
|
||||
This release tightens diagnostics for local package manifests only. Duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
are explicit beta package/workspace diagnostics.
|
||||
|
||||
The package model remains the existing closed local workspace model:
|
||||
dependencies are local path records, dependency keys must match target package
|
||||
names, and package-qualified imports still resolve through the local workspace
|
||||
graph.
|
||||
|
||||
This release adds no remote registry, lockfile, semantic-version solving,
|
||||
package publishing, optional/dev/target dependencies, stable package
|
||||
ABI/layout, source-language syntax or semantics, runtime behavior,
|
||||
standard-library helpers, compiler-known runtime names, stable manifest schema,
|
||||
stable Markdown schema, or performance claim.
|
||||
|
||||
## 1.0.0-beta.23
|
||||
|
||||
Release label: `1.0.0-beta.23`
|
||||
|
||||
Release name: Standard Library Stability Tier Ledger And Catalog Alignment
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Status: released beta documentation/catalog clarity on the `1.0.0-beta`
|
||||
language baseline.
|
||||
|
||||
This release adds [`STDLIB_TIERS.md`](STDLIB_TIERS.md) as the public maturity
|
||||
ledger for the generated [`STDLIB_API.md`](STDLIB_API.md) standard-library API
|
||||
catalog. The ledger defines the tier labels `beta-supported`, `experimental`,
|
||||
and `internal`.
|
||||
|
||||
The beta23 ledger classifies JSON, loopback networking, random/time, and
|
||||
filesystem resource-handle helpers as experimental domains. Concrete vector
|
||||
modules remain beta-supported concrete lanes; this is not a generic
|
||||
collections freeze and does not imply executable generics, maps, sets,
|
||||
iterators, mutable vectors, slice/view APIs, runtime collection changes, or
|
||||
stable ABI/layout.
|
||||
|
||||
This release adds no source-language syntax, standard-library helpers,
|
||||
compiler-known runtime names, runtime behavior, package behavior, stable
|
||||
artifact-manifest schema, stable Markdown schema, stable ABI/layout, or stable
|
||||
stdlib/API compatibility freeze. It does update generated catalog output and
|
||||
the release gate so tier metadata is visible and checked.
|
||||
|
||||
## 1.0.0-beta.22
|
||||
|
||||
Release label: `1.0.0-beta.22`
|
||||
|
||||
Release name: Run Manifest And Execution Report Hardening
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Status: released beta tooling/CLI evidence hardening on the `1.0.0-beta`
|
||||
language baseline.
|
||||
|
||||
This release does not change the Slovo language or standard-library surface.
|
||||
It documents the matching Glagol tooling update: `glagol run --manifest`
|
||||
artifact manifests now include an additive run-report block for the executed
|
||||
program's exit status, captured stdout, captured stderr, and forwarded program
|
||||
arguments.
|
||||
|
||||
The run-report block is beta tooling metadata under the existing
|
||||
`slovo.artifact-manifest` version `1` contract. It is not a stable manifest
|
||||
schema freeze and does not add source-language syntax, stdlib helpers,
|
||||
compiler-known runtime names, runtime C capabilities, package/import behavior,
|
||||
stable ABI/layout guarantees, or stable stdlib/API compatibility.
|
||||
|
||||
## 1.0.0-beta.21
|
||||
|
||||
Release label: `1.0.0-beta.21`
|
||||
|
||||
Release name: JSON Document Scalar Parsing Foundation
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Status: released beta standard-library JSON document scalar parsing foundation
|
||||
on the `1.0.0-beta` language baseline.
|
||||
|
||||
The source facade adds these source-authored `std.json` helpers:
|
||||
|
||||
- `parse_string_document_result ((document string)) -> (result string i32)`
|
||||
- `parse_bool_document_result ((document string)) -> (result bool i32)`
|
||||
- `parse_i32_document_result ((document string)) -> (result i32 i32)`
|
||||
- `parse_u32_document_result ((document string)) -> (result u32 i32)`
|
||||
- `parse_i64_document_result ((document string)) -> (result i64 i32)`
|
||||
- `parse_u64_document_result ((document string)) -> (result u64 i32)`
|
||||
- `parse_f64_document_result ((document string)) -> (result f64 i32)`
|
||||
- `parse_null_document_result ((document string)) -> (result bool i32)`
|
||||
|
||||
Each helper trims ASCII whitespace around the whole document with
|
||||
`std.string.trim_ascii`, then delegates to the already released exact
|
||||
value-token parser for that scalar family. Leading and trailing ASCII
|
||||
whitespace around one scalar document is accepted; trailing non-whitespace
|
||||
still returns `err 1` through the underlying exact parser.
|
||||
|
||||
This release adds no compiler-known runtime names, parser objects, object/array
|
||||
parsing, recursive `JsonValue`, maps/sets, streaming, Unicode escape decoding
|
||||
beyond the existing string-token behavior, embedded NUL policy, stable
|
||||
ABI/layout guarantees, or stable stdlib/API freeze.
|
||||
|
||||
## 1.0.0-beta.20
|
||||
|
||||
Release label: `1.0.0-beta.20`
|
||||
|
||||
Release name: String Search And ASCII Trim Foundation
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Status: released beta standard-library string helper foundation on the
|
||||
`1.0.0-beta` language baseline.
|
||||
|
||||
The source facade adds these source-authored `std.string` helpers:
|
||||
|
||||
- `contains ((value string) (needle string)) -> bool`
|
||||
- `index_of_option ((value string) (needle string)) -> (option i32)`
|
||||
- `last_index_of_option ((value string) (needle string)) -> (option i32)`
|
||||
- `trim_ascii_start ((value string)) -> string`
|
||||
- `trim_ascii_end ((value string)) -> string`
|
||||
- `trim_ascii ((value string)) -> string`
|
||||
|
||||
Search remains byte-oriented over current runtime strings. Empty needles match:
|
||||
`index_of_option` returns `some 0`, `last_index_of_option` returns
|
||||
`some (len value)`, and `contains` returns `true`. Missing needles return
|
||||
`none`.
|
||||
|
||||
The ASCII trim helpers remove only bytes `9`, `10`, `11`, `12`, `13`, and
|
||||
`32` from the requested edges. This release adds no compiler-known runtime
|
||||
names, Unicode/grapheme semantics, case folding, locale-sensitive matching,
|
||||
regular expressions, tokenizer APIs, language slice/view syntax, mutable
|
||||
strings, stable ABI/layout guarantees, or stable stdlib/API freeze.
|
||||
|
||||
## 1.0.0-beta.19
|
||||
|
||||
Release label: `1.0.0-beta.19`
|
||||
|
||||
Release name: Test Discovery And User-Project Conformance Foundation
|
||||
|
||||
Release date: 2026-05-23
|
||||
|
||||
Status: released beta tooling/conformance foundation on the `1.0.0-beta`
|
||||
language baseline.
|
||||
|
||||
The beta19 contract is tooling/conformance only. It adds deterministic test
|
||||
discovery listing for:
|
||||
|
||||
- `glagol test --list <file|project|workspace>`
|
||||
- `glagol --run-tests --list <file>` for the legacy single-file test path
|
||||
|
||||
List mode parses, lowers, type-checks, and discovers tests through the same
|
||||
front-end path as normal test execution, then prints the discovered/selected
|
||||
tests without evaluating their bodies. It preserves current single-file,
|
||||
project, and workspace test ordering, honors `--filter <substring>`, and
|
||||
leaves normal `glagol test` execution output unchanged.
|
||||
|
||||
This release does not add source-language syntax, runtime helper names, JSON
|
||||
expansion, parallel test execution, retries, tags/groups, coverage reports,
|
||||
event streams, stable manifest schemas, stable Markdown schemas, LSP/watch
|
||||
behavior, SARIF/daemon protocols, package registries, semver solving, or
|
||||
performance claims.
|
||||
No unreleased language scope is committed here yet.
|
||||
|
||||
## 1.0.0-beta.18
|
||||
|
||||
|
||||
@ -5,13 +5,14 @@ compiler implementation inside the same monorepo.
|
||||
|
||||
Guiding rule: the manifest wins. A feature is not accepted until it has surface syntax, typed-core meaning, lowering behavior, formatter behavior, diagnostics, and tests.
|
||||
|
||||
Long-horizon planning lives in `.llm/ROADMAP_TO_STABLE.md`. It defines the
|
||||
release train beyond the first real general-purpose beta Slovo contract.
|
||||
Long-horizon planning lives in
|
||||
`.llm/GENERAL_PURPOSE_LANGUAGE_ROADMAP.md`. It defines the experimental
|
||||
release train from the historical `v2.0.0-beta.1` tag toward and beyond the
|
||||
first real general-purpose beta Slovo contract.
|
||||
|
||||
Current stage: `1.0.0-beta.24`, released on 2026-05-23 as post-beta
|
||||
package manifest identity and local dependency diagnostic hardening. It keeps
|
||||
the `1.0.0-beta` language contract and includes the `1.0.0-beta.1` tooling
|
||||
hardening release, the
|
||||
Current stage: `1.0.0-beta.18`, released on 2026-05-23 as a post-beta JSON
|
||||
string token parsing foundation. It keeps the `1.0.0-beta` language
|
||||
contract and includes the `1.0.0-beta.1` tooling hardening release, the
|
||||
`1.0.0-beta.2` runtime/resource foundation release, the `1.0.0-beta.3`
|
||||
standard-library stabilization release, the `1.0.0-beta.4`
|
||||
language-usability diagnostics release, the `1.0.0-beta.5` package/workspace
|
||||
@ -24,13 +25,7 @@ documentation, `1.0.0-beta.12` concrete vector helper parity,
|
||||
benchmark suite catalog and metadata gate, `1.0.0-beta.15` reserved generic
|
||||
collection boundary hardening and collection ledger, and `1.0.0-beta.16`
|
||||
string scanning and token boundary helpers, `1.0.0-beta.17` JSON primitive
|
||||
scalar token parsing, `1.0.0-beta.18` JSON string token parsing,
|
||||
`1.0.0-beta.19` test discovery and user-project conformance tooling, and
|
||||
`1.0.0-beta.20` string search and ASCII trim helpers, plus
|
||||
`1.0.0-beta.21` JSON document scalar parsing helpers, and
|
||||
`1.0.0-beta.22` run manifest execution-report hardening, plus
|
||||
`1.0.0-beta.23` standard-library stability tier documentation, and
|
||||
`1.0.0-beta.24` package manifest/dependency diagnostic hardening.
|
||||
scalar token parsing, and `1.0.0-beta.18` JSON string token parsing.
|
||||
|
||||
`1.0.0-beta.16` adds `std.string` source facades and examples for
|
||||
`byte_at_result`, `slice_result`, `starts_with`, and `ends_with`. These helpers
|
||||
@ -42,12 +37,11 @@ semantics; full JSON parsing; object/array parsing; tokenizer objects;
|
||||
language slice/view syntax; mutable strings; stable ABI/layout; performance
|
||||
claims; or a stable stdlib/API freeze.
|
||||
|
||||
The current released JSON stage adds primitive scalar JSON token parse facades
|
||||
for booleans, concrete numeric primitives, exact `null`, one narrow ASCII JSON
|
||||
string-token helper, and scalar JSON document helpers that accept leading and
|
||||
trailing ASCII whitespace. Object/array parsing, recursive JSON values,
|
||||
tokenizers, schema validation, streaming, Unicode escape
|
||||
decoding/normalization beyond the existing string-token helper, embedded NUL
|
||||
The current released stage adds primitive scalar JSON token parse facades for
|
||||
booleans, concrete numeric primitives, exact `null`, and one narrow ASCII JSON
|
||||
string-token helper. Full JSON document parsing, object/array parsing,
|
||||
recursive JSON values, tokenizers, whitespace-tolerant document parsing, schema
|
||||
validation, streaming, Unicode escape decoding/normalization, embedded NUL
|
||||
policy, stable ABI/layout, and stable stdlib/API freeze remain deferred.
|
||||
|
||||
Full JSON parsing, object/array parsing, recursive JSON values,
|
||||
@ -62,70 +56,16 @@ APIs, additional runtime names, Unicode/grapheme string semantics, timing
|
||||
publication, performance claims, stable benchmark JSON schema, and package
|
||||
registry semantics remain deferred.
|
||||
|
||||
`1.0.0-beta.19` is a tooling/conformance slice, not a new source-language
|
||||
feature. It adds the `glagol test --list <file|project|workspace>` command
|
||||
plus legacy `glagol --run-tests --list <file>`: parse, lower, type-check, and
|
||||
discover tests through the same front-end path as normal test execution, then
|
||||
list the discovered/selected tests without evaluating test bodies. The mode
|
||||
preserves current single-file, project, and workspace ordering, honors
|
||||
`--filter <substring>`, and leaves normal `glagol test` execution behavior
|
||||
unchanged.
|
||||
|
||||
The beta19 tooling scope does not claim executable generics, maps/sets,
|
||||
iterators, runtime helper names, source-language syntax, JSON expansion,
|
||||
parallel test execution, retries, tags/groups, coverage/event streams,
|
||||
LSP/watch protocols, SARIF/daemon protocols, stable artifact-manifest or
|
||||
Markdown schemas, stable benchmark JSON schema, stable `1.0.0` diagnostics
|
||||
freeze, stable standard-library/API compatibility freeze, registry semantics,
|
||||
semver solving, performance claims, mutable vectors, language slice/view APIs,
|
||||
additional runtime names, or Unicode/grapheme semantics.
|
||||
|
||||
`1.0.0-beta.20` adds source-authored `std.string` helpers for byte-oriented
|
||||
`contains`, first/last index option search, and ASCII edge trimming over bytes
|
||||
`9`, `10`, `11`, `12`, `13`, and `32`. Empty needles match at first index `0`
|
||||
and last index `(len value)`. The scope adds no compiler-known runtime names,
|
||||
Unicode/grapheme semantics, case folding, regexes, tokenizer APIs, language
|
||||
slice/view syntax, mutable strings, stable ABI/layout guarantees, or stable
|
||||
stdlib/API freeze.
|
||||
|
||||
`1.0.0-beta.21` adds source-authored
|
||||
`std.json.parse_*_document_result` helpers for string, bool, `i32`, `u32`,
|
||||
`i64`, `u64`, `f64`, and exact `null` documents by trimming ASCII whitespace
|
||||
around the whole document with `std.string.trim_ascii`, then delegating to the
|
||||
existing exact value-token parser for each scalar family. The scope keeps
|
||||
object/array parsing, recursive JSON values, tokenizer objects, maps/sets,
|
||||
streaming, new compiler-known runtime names, Unicode escape decoding beyond
|
||||
the existing string-token helper, embedded NUL policy, stable ABI/layout, and
|
||||
stable stdlib/API freeze deferred.
|
||||
|
||||
`1.0.0-beta.22` is tooling/CLI evidence hardening, not a language feature. It
|
||||
documents the matching Glagol `run --manifest` update: run-mode artifact
|
||||
manifests gain an additive run-report block for executed-program exit status,
|
||||
captured stdout, captured stderr, and forwarded program arguments. The block is
|
||||
beta tooling metadata under the existing `slovo.artifact-manifest` version `1`
|
||||
contract. It is not a stable schema freeze and adds no language syntax,
|
||||
standard-library helpers, runtime capabilities, package/import behavior,
|
||||
stable ABI/layout, or stable stdlib/API guarantees.
|
||||
|
||||
`1.0.0-beta.23` is documentation/catalog clarity, not a language or stdlib
|
||||
behavior feature. It adds [`STDLIB_TIERS.md`](STDLIB_TIERS.md) as the public
|
||||
stability-tier ledger beside the generated [`STDLIB_API.md`](STDLIB_API.md)
|
||||
signature catalog. The ledger defines `beta-supported`, `experimental`, and
|
||||
`internal`; marks JSON, loopback networking, random/time, and filesystem
|
||||
resource-handle helpers as experimental domains; and keeps concrete vector
|
||||
modules as beta-supported concrete lanes rather than a generic collections
|
||||
freeze. It adds no source-language syntax, helpers, runtime names, runtime
|
||||
behavior, stable manifest schema, stable Markdown schema, stable ABI/layout,
|
||||
or stable stdlib/API freeze. It does update generated catalog output and the
|
||||
release gate so tier metadata is visible and checked.
|
||||
|
||||
`1.0.0-beta.24` is package/workspace diagnostic hardening, not a language,
|
||||
runtime, package-manager, or stdlib behavior feature. It makes duplicate
|
||||
package manifest keys, invalid dependency keys, and duplicate dependency keys
|
||||
explicit diagnostics while keeping the existing closed local workspace model.
|
||||
It adds no remote registry, lockfile, semantic-version solving, package
|
||||
publishing, optional/dev/target dependencies, stable package ABI/layout,
|
||||
source-language change, runtime change, or stdlib change.
|
||||
Next stage target: post-`1.0.0-beta.18` continuation from
|
||||
developer-experience,
|
||||
package, benchmark metadata, collection, or string-processing planning without
|
||||
claiming executable generics, an LSP/watch protocol, SARIF/daemon protocol,
|
||||
stable Markdown schema, registry semantics, stable benchmark JSON schema,
|
||||
stable `1.0.0` diagnostics freeze, stable standard-library/API compatibility
|
||||
freeze, mutable vectors, language slice/view APIs, additional runtime names,
|
||||
Unicode/grapheme semantics, full JSON parsing, maps/sets, iterators, or
|
||||
performance claims until the exact scope is frozen from the manifest and
|
||||
roadmap.
|
||||
|
||||
The final experimental precursor scope is `exp-125`, defined in
|
||||
`.llm/EXP_125_UNSIGNED_U32_U64_NUMERIC_AND_STDLIB_BREADTH_ALPHA.md`. Its
|
||||
|
||||
@ -9,14 +9,10 @@ diagnostic catalog and schema policy update, and `1.0.0-beta.14` benchmark
|
||||
suite catalog and metadata gate, `1.0.0-beta.15` reserved generic collection
|
||||
boundary hardening and collection ledger, `1.0.0-beta.16` string scanning
|
||||
and token boundary foundation, `1.0.0-beta.17` JSON primitive scalar parsing
|
||||
foundation, `1.0.0-beta.18` JSON string token parsing foundation,
|
||||
`1.0.0-beta.19` test discovery and user-project conformance tooling, and
|
||||
`1.0.0-beta.20` string search and ASCII trim foundation, and
|
||||
`1.0.0-beta.21` JSON document scalar parsing foundation, and
|
||||
`1.0.0-beta.22` run manifest and execution-report hardening, and
|
||||
`1.0.0-beta.23` standard-library stability tier ledger and catalog alignment.
|
||||
The language contract integrates promoted language slices through `exp-125`
|
||||
and the historical publication
|
||||
foundation, and `1.0.0-beta.18` JSON string token
|
||||
parsing foundation. The language contract
|
||||
integrates
|
||||
promoted language slices through `exp-125` and the historical publication
|
||||
baseline through `exp-123`. `1.0.0-beta` is the first real general-purpose
|
||||
beta release. `exp-125` completed the unsigned numeric and stdlib breadth
|
||||
precursor scope, `exp-124` is the last tagged experimental alpha language
|
||||
@ -207,76 +203,20 @@ Current v1 release surface and explicit experimental targets:
|
||||
`std.json.parse_i64_value_result`, `std.json.parse_u64_value_result`,
|
||||
`std.json.parse_f64_value_result`, and `std.json.parse_null_value_result`
|
||||
consume one already-isolated primitive scalar token and return concrete
|
||||
`(result ... i32)` values; JSON document parsing beyond the beta21 scalar
|
||||
helpers, string/object/array parsing, tokenizers, recursive `JsonValue`,
|
||||
Unicode escape handling, stable ABI/layout, performance claims, and stable
|
||||
stdlib/API freeze remain out of scope
|
||||
`(result ... i32)` values; full JSON document parsing, string/object/array
|
||||
parsing, tokenizers, recursive `JsonValue`, Unicode escape handling, stable
|
||||
ABI/layout, performance claims, and stable stdlib/API freeze remain out of
|
||||
scope
|
||||
- `1.0.0-beta.18` JSON string token parsing target:
|
||||
`std.json.parse_string_value_result : (string) -> (result string i32)`
|
||||
consumes one already-isolated ASCII JSON string token with exact quotes and
|
||||
no leading/trailing whitespace, decodes simple JSON escapes, returns
|
||||
`err 1` for ordinary parse failure, and rejects raw control bytes, bad
|
||||
escapes, unterminated/trailing bytes, raw non-ASCII, and all `\uXXXX` escapes
|
||||
for this slice; JSON document parsing beyond the beta21 scalar helpers,
|
||||
object/array parsing, tokenizer APIs, recursive `JsonValue`, Unicode escape
|
||||
decoding/normalization, embedded NUL policy, stable ABI/layout, performance
|
||||
claims, and stable stdlib/API freeze remain out of scope
|
||||
- `1.0.0-beta.19` test discovery and user-project conformance target:
|
||||
`glagol test --list <file|project|workspace>` and legacy
|
||||
`glagol --run-tests --list <file>` list checked/discovered tests without
|
||||
executing test bodies; list mode preserves current test ordering, honors
|
||||
`--filter <substring>`, and remains beta tooling rather than a stable
|
||||
schema. This target does not add source-language syntax, runtime helper
|
||||
names, JSON expansion, parallel test execution, retries, tags/groups,
|
||||
coverage/event streams, stable artifact-manifest or Markdown schemas,
|
||||
LSP/watch behavior, SARIF/daemon protocols, package registries, semver
|
||||
solving, or performance claims
|
||||
- `1.0.0-beta.20` string search and ASCII trim target:
|
||||
source-authored `std.string.contains`, `std.string.index_of_option`,
|
||||
`std.string.last_index_of_option`, `std.string.trim_ascii_start`,
|
||||
`std.string.trim_ascii_end`, and `std.string.trim_ascii` compose over the
|
||||
existing byte-oriented string primitives; search is byte-oriented, missing
|
||||
needles return `none`, empty needles match at first index `0` and last index
|
||||
`(len value)`, and trim removes only bytes `9`, `10`, `11`, `12`, `13`, and
|
||||
`32` from the requested edges. This target does not add compiler-known
|
||||
runtime names, Unicode/grapheme semantics, case folding, locale-sensitive
|
||||
matching, regex, tokenizer APIs, language slice/view syntax, mutable
|
||||
strings, stable ABI/layout, performance claims, or stable stdlib/API freeze
|
||||
- `1.0.0-beta.21` JSON document scalar parsing:
|
||||
source-authored `std.json.parse_string_document_result`,
|
||||
`std.json.parse_bool_document_result`,
|
||||
`std.json.parse_i32_document_result`,
|
||||
`std.json.parse_u32_document_result`,
|
||||
`std.json.parse_i64_document_result`,
|
||||
`std.json.parse_u64_document_result`,
|
||||
`std.json.parse_f64_document_result`, and
|
||||
`std.json.parse_null_document_result` trim ASCII whitespace around the whole
|
||||
document with `std.string.trim_ascii`, then delegate to the existing exact
|
||||
value-token parsers for one scalar JSON document. This target does not add
|
||||
compiler-known runtime names, object/array parsing, recursive `JsonValue`,
|
||||
parser/tokenizer objects, maps/sets, streaming, Unicode escape decoding
|
||||
beyond the existing string-token behavior, embedded NUL policy,
|
||||
ABI/layout guarantees, performance claims, or stable stdlib/API freeze
|
||||
- `1.0.0-beta.22` run manifest and execution-report hardening:
|
||||
`glagol run --manifest` artifact manifests include an additive run-report
|
||||
block after a supported program executes. The block records the executed
|
||||
program exit status, captured stdout, captured stderr, and forwarded
|
||||
program arguments. This target is beta tooling evidence only; it does not
|
||||
add source-language syntax, stdlib helpers, compiler-known runtime names,
|
||||
runtime C capabilities, package/import behavior, stable artifact-manifest
|
||||
schema guarantees, stable ABI/layout, or stable stdlib/API freeze
|
||||
- `1.0.0-beta.23` standard-library stability tier ledger and catalog
|
||||
alignment:
|
||||
[`STDLIB_TIERS.md`](STDLIB_TIERS.md) defines the public tier labels
|
||||
`beta-supported`, `experimental`, and `internal` beside the generated
|
||||
[`STDLIB_API.md`](STDLIB_API.md) signature catalog. JSON, loopback
|
||||
networking, random/time, and filesystem resource-handle helpers are
|
||||
experimental domains. Concrete vector modules remain beta-supported concrete
|
||||
lanes, not a generic collections freeze. This target does not add
|
||||
source-language syntax, stdlib helpers, compiler-known runtime names,
|
||||
runtime behavior, stable artifact-manifest schema, stable Markdown schema,
|
||||
stable ABI/layout, or stable stdlib/API freeze. It does update generated
|
||||
catalog output and the release gate so tier metadata is visible and checked
|
||||
for this slice; full JSON document parsing, object/array parsing, tokenizer
|
||||
APIs, recursive `JsonValue`, Unicode escape decoding/normalization, embedded
|
||||
NUL policy, stable ABI/layout, performance claims, and stable stdlib/API
|
||||
freeze remain out of scope
|
||||
- `exp-1` owned runtime strings: compiler-known `std.string.concat` accepts two
|
||||
`string` values and returns an immutable runtime-owned `string`; existing
|
||||
string equality, length, printing, locals, parameters, returns, and calls work
|
||||
@ -1303,10 +1243,6 @@ std.json.parse_string_value_result: (string) -> (result string i32)
|
||||
std.json.parse_bool_value_result: (string) -> (result bool i32)
|
||||
std.json.parse_i32_value_result/parse_u32_value_result/parse_i64_value_result/parse_u64_value_result/parse_f64_value_result
|
||||
std.json.parse_null_value_result: (string) -> (result bool i32)
|
||||
std.json.parse_string_document_result: (string) -> (result string i32)
|
||||
std.json.parse_bool_document_result: (string) -> (result bool i32)
|
||||
std.json.parse_i32_document_result/parse_u32_document_result/parse_i64_document_result/parse_u64_document_result/parse_f64_document_result
|
||||
std.json.parse_null_document_result: (string) -> (result bool i32)
|
||||
std.json.field_string/field_bool/field_i32/field_u32/field_i64/field_u64/field_f64/field_null
|
||||
std.json.array0/array1/array2/array3
|
||||
std.json.object0/object1/object2/object3
|
||||
@ -1334,20 +1270,13 @@ whitespace. It decodes the simple JSON escapes `\"`, `\\`, `\/`, `\b`, `\f`,
|
||||
unterminated or trailing bytes, raw non-ASCII, and all `\uXXXX` escapes for
|
||||
this slice.
|
||||
|
||||
The `1.0.0-beta.21` JSON foundation adds source-authored
|
||||
`parse_*_document_result` helpers for string, bool, concrete numeric
|
||||
primitives, and exact `null`. Each helper accepts leading and trailing ASCII
|
||||
whitespace around one scalar JSON document by composing with
|
||||
`std.string.trim_ascii`, then delegates to the matching exact value-token
|
||||
parser. Trailing non-whitespace still fails through the exact parser.
|
||||
|
||||
This is not a complete JSON or serialization contract. JSON parsing beyond the
|
||||
scalar document helpers, object/array parsing, recursive JSON values, maps/sets,
|
||||
generic collections, tokenizer objects, streaming decoders or encoders, schema
|
||||
validation, Unicode escape decoding or normalization beyond the existing
|
||||
string-token behavior, embedded NUL policy, stable text encoding policy beyond
|
||||
the current null-terminated runtime string ABI, stable runtime helper symbols,
|
||||
and stable standard-library API guarantees remain deferred.
|
||||
single ASCII string-token helper, object/array parsing, recursive JSON values,
|
||||
maps/sets, generic collections, tokenizer objects, streaming decoders or
|
||||
encoders, schema validation, Unicode escape decoding or
|
||||
normalization, embedded NUL policy, stable text encoding policy beyond the
|
||||
current null-terminated runtime string ABI, stable runtime helper symbols, and
|
||||
stable standard-library API guarantees remain deferred.
|
||||
|
||||
### 4.4.6 Post-Beta Concrete Type Alias Foundation
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,68 +0,0 @@
|
||||
# Slovo Standard Library Stability Tiers
|
||||
|
||||
Status: beta public ledger for `1.0.0-beta.23`.
|
||||
|
||||
This document records the current maturity labels for the source-authored
|
||||
standard-library facade surface. Exact exported helper signatures remain in
|
||||
[`STDLIB_API.md`](STDLIB_API.md), which is generated from `lib/std/*.slo`.
|
||||
This ledger explains how to read that catalog during the beta line.
|
||||
|
||||
`1.0.0-beta.23` is documentation and catalog-tooling alignment only. It adds no
|
||||
source syntax, standard-library helpers, compiler-known runtime names, runtime
|
||||
behavior, package behavior, manifest schema guarantee, Markdown schema
|
||||
guarantee, ABI/layout guarantee, or stable standard-library/API compatibility
|
||||
freeze. It does make the generated API catalog emit tier metadata and makes the
|
||||
release gate check that experimental tier metadata is present.
|
||||
|
||||
## Tier Labels
|
||||
|
||||
Slovo uses these public standard-library tier labels:
|
||||
|
||||
| Tier | Meaning |
|
||||
| --- | --- |
|
||||
| `beta-supported` | Exported from `lib/std`, covered by current beta source-search, promotion, facade, or composition gates, and suitable for beta programs. Names and behavior are still beta contracts, not a stable `1.0.0` freeze. |
|
||||
| `experimental` | Exported or documented in the beta line, but intentionally fluid because the domain still depends on deferred language, runtime, resource, platform, or schema policy. Use for feedback and narrow programs, not compatibility promises. |
|
||||
| `internal` | Not public standard-library API. This includes non-exported helper names, module-local concrete aliases, implementation details, generated-document internals, and private runtime symbols. Internal names may be omitted from public catalogs or changed without migration promises. |
|
||||
|
||||
## Catalog Boundary
|
||||
|
||||
[`STDLIB_API.md`](STDLIB_API.md) is the generated signature inventory: it lists
|
||||
exported `(fn ...)` helpers from `lib/std/*.slo`, normalizes module-local
|
||||
concrete aliases to public concrete types, and omits non-exported helpers and
|
||||
`(type ...)` aliases.
|
||||
|
||||
This ledger is the public maturity companion to that generated catalog. If the
|
||||
catalog lists a signature, read the tier marker beside that signature as the
|
||||
generated summary of this ledger. The generated catalog is a beta discovery
|
||||
aid, not a stable Markdown schema or stable API freeze.
|
||||
|
||||
## Current Tier Ledger
|
||||
|
||||
| Surface | Current tier | Notes |
|
||||
| --- | --- | --- |
|
||||
| `std.cli`, `std.env`, `std.io`, `std.math`, `std.num`, `std.option`, `std.process`, `std.result`, and byte-oriented `std.string` helpers | `beta-supported` | Current source facade helpers over promoted concrete runtime/value families. The beta label still allows additive changes and scoped migrations before `1.0.0`. |
|
||||
| Concrete vector modules: `std.vec_i32`, `std.vec_i64`, `std.vec_f64`, `std.vec_bool`, and `std.vec_string` | `beta-supported` | These are concrete immutable vector lanes over existing concrete runtime families. This is not a generic collections freeze and does not imply executable generics, generic aliases, maps, sets, iterators, mutable vectors, slice/view APIs, runtime collection changes, or stable ABI/layout. |
|
||||
| Basic filesystem text/status helpers such as `read_text`, `write_text_result`, `exists`, `is_file`, `is_dir`, `remove_file_result`, and `create_dir_result` | `beta-supported` | Current concrete file helpers remain beta contracts over host filesystem behavior. Platform-specific errors and richer host-error ADTs remain deferred. |
|
||||
| Filesystem resource-handle helpers such as `open_text_read_result`, `read_open_text_result`, `close_result`, `read_text_via_handle_result`, and `close_ok` | `experimental` | Handles are beta-scoped opaque `i32` values. Writable handles, directory handles/enumeration, stable handle ABI/layout, and richer platform error policy remain deferred. |
|
||||
| `std.json` | `experimental` | Includes compact JSON text construction, exact primitive scalar token parsing, ASCII string-token parsing, and scalar document parsing. Object/array parsing, recursive `JsonValue`, parser/tokenizer objects, maps/sets, streaming, broad Unicode escape policy, embedded NUL policy, stable text encoding policy, and stable JSON API compatibility remain deferred. |
|
||||
| `std.net` | `experimental` | Current blocking loopback TCP facade only. DNS, TLS, UDP, async IO, non-loopback binding, HTTP frameworks, stable socket ABI/layout, and rich host-error ADTs remain deferred. |
|
||||
| `std.random` and `std.time` | `experimental` | Available as narrow beta host facades, but deterministic testing policy, seeding/time-source contracts, monotonic/wall-clock distinctions, reproducibility guarantees, and stable platform behavior remain deferred. |
|
||||
| Non-exported helper names, module-local aliases, private runtime symbols, generated catalog internals, and release-tool implementation details | `internal` | Not part of the public standard-library compatibility surface. |
|
||||
|
||||
## Explicit Non-Changes
|
||||
|
||||
This ledger does not promote:
|
||||
|
||||
- source-language syntax
|
||||
- standard-library helper additions, removals, or renames
|
||||
- compiler-known runtime names
|
||||
- runtime behavior changes
|
||||
- executable generics or generic aliases
|
||||
- generic stdlib dispatch
|
||||
- maps, sets, iterators, mutable vectors, or slice/view APIs
|
||||
- object/array JSON parsing or stable JSON schemas
|
||||
- DNS, TLS, UDP, async networking, or non-loopback binding
|
||||
- stable resource-handle ABI/layout
|
||||
- stable artifact-manifest schema
|
||||
- stable generated Markdown schema
|
||||
- stable `1.0.0` standard-library/API compatibility freeze
|
||||
@ -1,6 +1,6 @@
|
||||
(module main)
|
||||
|
||||
(import std.string (len concat byte_at_result slice_result starts_with ends_with contains index_of_option last_index_of_option trim_ascii_start trim_ascii_end trim_ascii parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
(import std.string (len concat byte_at_result slice_result starts_with ends_with parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
|
||||
(fn imported_string_concat () -> string
|
||||
(concat "slo" "vo"))
|
||||
@ -187,50 +187,6 @@
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_option_i32_is_some_value ((actual (option i32)) (expected i32)) -> bool
|
||||
(match actual
|
||||
((some payload)
|
||||
(= payload expected))
|
||||
((none)
|
||||
false)))
|
||||
|
||||
(fn imported_option_i32_is_none ((actual (option i32))) -> bool
|
||||
(match actual
|
||||
((some payload)
|
||||
false)
|
||||
((none)
|
||||
true)))
|
||||
|
||||
(fn imported_string_search_ok () -> bool
|
||||
(if (contains "alpha beta alpha" "beta")
|
||||
(if (contains "alpha" "z")
|
||||
false
|
||||
(if (contains "alpha" "")
|
||||
(if (imported_option_i32_is_some_value (index_of_option "alpha beta alpha" "alpha") 0)
|
||||
(if (imported_option_i32_is_none (index_of_option "alpha" "z"))
|
||||
(if (imported_option_i32_is_some_value (index_of_option "alpha" "") 0)
|
||||
(if (imported_option_i32_is_some_value (last_index_of_option "alpha beta alpha" "alpha") 11)
|
||||
(if (imported_option_i32_is_some_value (last_index_of_option "alpha" "") 5)
|
||||
(imported_option_i32_is_none (last_index_of_option "alpha" "z"))
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
false))
|
||||
|
||||
(fn imported_string_ascii_trim_ok () -> bool
|
||||
(if (= (trim_ascii_start " \t\nslovo") "slovo")
|
||||
(if (= (trim_ascii_end "slovo \t\n") "slovo")
|
||||
(if (= (trim_ascii " \t\nslovo \t\n") "slovo")
|
||||
(if (= (trim_ascii " \t\n") "")
|
||||
(= (trim_ascii "slovo") "slovo")
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_helpers_ok () -> bool
|
||||
(if (= (imported_string_len_concat_score) 42)
|
||||
(if (imported_string_byte_at_ok)
|
||||
@ -240,11 +196,7 @@
|
||||
(if (imported_string_parse_options_ok)
|
||||
(if (imported_string_parse_integer_fallbacks_ok)
|
||||
(if (imported_string_parse_float_bool_fallbacks_ok)
|
||||
(if (imported_string_parse_custom_fallbacks_ok)
|
||||
(if (imported_string_search_ok)
|
||||
(imported_string_ascii_trim_ok)
|
||||
false)
|
||||
false)
|
||||
(imported_string_parse_custom_fallbacks_ok)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
@ -286,11 +238,5 @@
|
||||
(test "explicit std string parse custom fallbacks"
|
||||
(imported_string_parse_custom_fallbacks_ok))
|
||||
|
||||
(test "explicit std string search helpers"
|
||||
(imported_string_search_ok))
|
||||
|
||||
(test "explicit std string ascii trim helpers"
|
||||
(imported_string_ascii_trim_ok))
|
||||
|
||||
(test "explicit std string helpers all"
|
||||
(= (main) 42))
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
(module main)
|
||||
|
||||
(import std.json (quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result parse_string_document_result parse_bool_document_result parse_i32_document_result parse_u32_document_result parse_i64_document_result parse_u64_document_result parse_f64_document_result parse_null_document_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
(import std.json (quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
|
||||
(type JsonText string)
|
||||
|
||||
@ -92,57 +92,6 @@
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_parse_document_trimmed_success () -> bool
|
||||
(if (= (unwrap_ok (parse_string_document_result " \t\n\"slovo\" \n\t")) "slovo")
|
||||
(if (unwrap_ok (parse_bool_document_result "\n true \t"))
|
||||
(if (= (unwrap_ok (parse_i32_document_result " -7 ")) -7)
|
||||
(if (= (unwrap_ok (parse_u32_document_result " 7 ")) 7u32)
|
||||
(if (= (unwrap_ok (parse_i64_document_result " 8 ")) 8i64)
|
||||
(if (= (unwrap_ok (parse_u64_document_result " 9 ")) 9u64)
|
||||
(if (= (unwrap_ok (parse_f64_document_result " 1e2 ")) 100.0)
|
||||
(unwrap_ok (parse_null_document_result " null "))
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_parse_document_plain_success () -> bool
|
||||
(if (= (unwrap_ok (parse_string_document_result "\"plain\"")) "plain")
|
||||
(if (= (unwrap_ok (parse_bool_document_result "false")) false)
|
||||
(if (= (unwrap_ok (parse_i32_document_result "-8")) -8)
|
||||
(if (= (unwrap_ok (parse_u32_document_result "8")) 8u32)
|
||||
(if (= (unwrap_ok (parse_i64_document_result "9")) 9i64)
|
||||
(if (= (unwrap_ok (parse_u64_document_result "10")) 10u64)
|
||||
(if (= (unwrap_ok (parse_f64_document_result "1.5")) 1.5)
|
||||
(unwrap_ok (parse_null_document_result "null"))
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_parse_document_trailing_failure () -> bool
|
||||
(if (= (unwrap_err (parse_string_document_result " \t\"slovo\"x \n")) 1)
|
||||
(if (= (unwrap_err (parse_bool_document_result " truex ")) 1)
|
||||
(if (= (unwrap_err (parse_i32_document_result " -7x ")) 1)
|
||||
(if (= (unwrap_err (parse_u32_document_result " 7x ")) 1)
|
||||
(if (= (unwrap_err (parse_i64_document_result " 8x ")) 1)
|
||||
(if (= (unwrap_err (parse_u64_document_result " 9x ")) 1)
|
||||
(if (= (unwrap_err (parse_f64_document_result " 1.5x ")) 1)
|
||||
(= (unwrap_err (parse_null_document_result " nullx ")) 1)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_fields () -> bool
|
||||
(if (= (field_string "name" "slo\"vo") "\"name\":\"slo\\\"vo\"")
|
||||
(if (= (field_bool "ok" true) "\"ok\":true")
|
||||
@ -190,9 +139,6 @@
|
||||
(if (imported_json_parse_scalar_failure)
|
||||
(if (imported_json_parse_string_success)
|
||||
(if (imported_json_parse_string_failure)
|
||||
(if (imported_json_parse_document_trimmed_success)
|
||||
(if (imported_json_parse_document_plain_success)
|
||||
(if (imported_json_parse_document_trailing_failure)
|
||||
(if (imported_json_fields)
|
||||
(imported_json_arrays_objects)
|
||||
false)
|
||||
@ -201,9 +147,6 @@
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn main () -> i32
|
||||
@ -229,15 +172,6 @@
|
||||
(test "explicit std json string token parse failure facade"
|
||||
(imported_json_parse_string_failure))
|
||||
|
||||
(test "explicit std json document parse trimmed success facade"
|
||||
(imported_json_parse_document_trimmed_success))
|
||||
|
||||
(test "explicit std json document parse plain success facade"
|
||||
(imported_json_parse_document_plain_success))
|
||||
|
||||
(test "explicit std json document parse trailing failure facade"
|
||||
(imported_json_parse_document_trailing_failure))
|
||||
|
||||
(test "explicit std json fields facade"
|
||||
(imported_json_fields))
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
(module main)
|
||||
|
||||
(import std.string (len concat byte_at_result slice_result starts_with ends_with contains index_of_option last_index_of_option trim_ascii_start trim_ascii_end trim_ascii parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
(import std.string (len concat byte_at_result slice_result starts_with ends_with parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
|
||||
(fn imported_string_concat () -> string
|
||||
(concat "slo" "vo"))
|
||||
@ -187,50 +187,6 @@
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_option_i32_is_some_value ((actual (option i32)) (expected i32)) -> bool
|
||||
(match actual
|
||||
((some payload)
|
||||
(= payload expected))
|
||||
((none)
|
||||
false)))
|
||||
|
||||
(fn imported_option_i32_is_none ((actual (option i32))) -> bool
|
||||
(match actual
|
||||
((some payload)
|
||||
false)
|
||||
((none)
|
||||
true)))
|
||||
|
||||
(fn imported_string_search_ok () -> bool
|
||||
(if (contains "alpha beta alpha" "beta")
|
||||
(if (contains "alpha" "z")
|
||||
false
|
||||
(if (contains "alpha" "")
|
||||
(if (imported_option_i32_is_some_value (index_of_option "alpha beta alpha" "alpha") 0)
|
||||
(if (imported_option_i32_is_none (index_of_option "alpha" "z"))
|
||||
(if (imported_option_i32_is_some_value (index_of_option "alpha" "") 0)
|
||||
(if (imported_option_i32_is_some_value (last_index_of_option "alpha beta alpha" "alpha") 11)
|
||||
(if (imported_option_i32_is_some_value (last_index_of_option "alpha" "") 5)
|
||||
(imported_option_i32_is_none (last_index_of_option "alpha" "z"))
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
false))
|
||||
|
||||
(fn imported_string_ascii_trim_ok () -> bool
|
||||
(if (= (trim_ascii_start " \t\nslovo") "slovo")
|
||||
(if (= (trim_ascii_end "slovo \t\n") "slovo")
|
||||
(if (= (trim_ascii " \t\nslovo \t\n") "slovo")
|
||||
(if (= (trim_ascii " \t\n") "")
|
||||
(= (trim_ascii "slovo") "slovo")
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_helpers_ok () -> bool
|
||||
(if (= (imported_string_len_concat_score) 42)
|
||||
(if (imported_string_byte_at_ok)
|
||||
@ -240,11 +196,7 @@
|
||||
(if (imported_string_parse_options_ok)
|
||||
(if (imported_string_parse_integer_fallbacks_ok)
|
||||
(if (imported_string_parse_float_bool_fallbacks_ok)
|
||||
(if (imported_string_parse_custom_fallbacks_ok)
|
||||
(if (imported_string_search_ok)
|
||||
(imported_string_ascii_trim_ok)
|
||||
false)
|
||||
false)
|
||||
(imported_string_parse_custom_fallbacks_ok)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
@ -286,11 +238,5 @@
|
||||
(test "explicit std string parse custom fallbacks"
|
||||
(imported_string_parse_custom_fallbacks_ok))
|
||||
|
||||
(test "explicit std string search helpers"
|
||||
(imported_string_search_ok))
|
||||
|
||||
(test "explicit std string ascii trim helpers"
|
||||
(imported_string_ascii_trim_ok))
|
||||
|
||||
(test "explicit std string helpers all"
|
||||
(= (main) 42))
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
(module json (export quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result parse_string_document_result parse_bool_document_result parse_i32_document_result parse_u32_document_result parse_i64_document_result parse_u64_document_result parse_f64_document_result parse_null_document_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
|
||||
(import string (trim_ascii))
|
||||
(module json (export quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
|
||||
(type JsonText string)
|
||||
|
||||
@ -58,30 +56,6 @@
|
||||
(ok bool i32 true)
|
||||
(err bool i32 1)))
|
||||
|
||||
(fn parse_string_document_result ((document string)) -> (result string i32)
|
||||
(parse_string_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_bool_document_result ((document string)) -> (result bool i32)
|
||||
(parse_bool_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_i32_document_result ((document string)) -> (result i32 i32)
|
||||
(parse_i32_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_u32_document_result ((document string)) -> (result u32 i32)
|
||||
(parse_u32_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_i64_document_result ((document string)) -> (result i64 i32)
|
||||
(parse_i64_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_u64_document_result ((document string)) -> (result u64 i32)
|
||||
(parse_u64_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_f64_document_result ((document string)) -> (result f64 i32)
|
||||
(parse_f64_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_null_document_result ((document string)) -> (result bool i32)
|
||||
(parse_null_value_result (trim_ascii document)))
|
||||
|
||||
(fn field_fragment ((name string) (encoded_value JsonText)) -> JsonField
|
||||
(std.string.concat (std.string.concat (quote_string name) ":") encoded_value))
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
(module main)
|
||||
|
||||
(import json (quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result parse_string_document_result parse_bool_document_result parse_i32_document_result parse_u32_document_result parse_i64_document_result parse_u64_document_result parse_f64_document_result parse_null_document_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
(import json (quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
|
||||
(type JsonText string)
|
||||
|
||||
@ -92,57 +92,6 @@
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_parse_document_trimmed_success () -> bool
|
||||
(if (= (unwrap_ok (parse_string_document_result " \t\n\"slovo\" \n\t")) "slovo")
|
||||
(if (unwrap_ok (parse_bool_document_result "\n true \t"))
|
||||
(if (= (unwrap_ok (parse_i32_document_result " -7 ")) -7)
|
||||
(if (= (unwrap_ok (parse_u32_document_result " 7 ")) 7u32)
|
||||
(if (= (unwrap_ok (parse_i64_document_result " 8 ")) 8i64)
|
||||
(if (= (unwrap_ok (parse_u64_document_result " 9 ")) 9u64)
|
||||
(if (= (unwrap_ok (parse_f64_document_result " 1e2 ")) 100.0)
|
||||
(unwrap_ok (parse_null_document_result " null "))
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_parse_document_plain_success () -> bool
|
||||
(if (= (unwrap_ok (parse_string_document_result "\"plain\"")) "plain")
|
||||
(if (= (unwrap_ok (parse_bool_document_result "false")) false)
|
||||
(if (= (unwrap_ok (parse_i32_document_result "-8")) -8)
|
||||
(if (= (unwrap_ok (parse_u32_document_result "8")) 8u32)
|
||||
(if (= (unwrap_ok (parse_i64_document_result "9")) 9i64)
|
||||
(if (= (unwrap_ok (parse_u64_document_result "10")) 10u64)
|
||||
(if (= (unwrap_ok (parse_f64_document_result "1.5")) 1.5)
|
||||
(unwrap_ok (parse_null_document_result "null"))
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_parse_document_trailing_failure () -> bool
|
||||
(if (= (unwrap_err (parse_string_document_result " \t\"slovo\"x \n")) 1)
|
||||
(if (= (unwrap_err (parse_bool_document_result " truex ")) 1)
|
||||
(if (= (unwrap_err (parse_i32_document_result " -7x ")) 1)
|
||||
(if (= (unwrap_err (parse_u32_document_result " 7x ")) 1)
|
||||
(if (= (unwrap_err (parse_i64_document_result " 8x ")) 1)
|
||||
(if (= (unwrap_err (parse_u64_document_result " 9x ")) 1)
|
||||
(if (= (unwrap_err (parse_f64_document_result " 1.5x ")) 1)
|
||||
(= (unwrap_err (parse_null_document_result " nullx ")) 1)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_json_fields () -> bool
|
||||
(if (= (field_string "name" "slo\"vo") "\"name\":\"slo\\\"vo\"")
|
||||
(if (= (field_bool "ok" true) "\"ok\":true")
|
||||
@ -190,9 +139,6 @@
|
||||
(if (imported_json_parse_scalar_failure)
|
||||
(if (imported_json_parse_string_success)
|
||||
(if (imported_json_parse_string_failure)
|
||||
(if (imported_json_parse_document_trimmed_success)
|
||||
(if (imported_json_parse_document_plain_success)
|
||||
(if (imported_json_parse_document_trailing_failure)
|
||||
(if (imported_json_fields)
|
||||
(imported_json_arrays_objects)
|
||||
false)
|
||||
@ -201,9 +147,6 @@
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn main () -> i32
|
||||
@ -229,15 +172,6 @@
|
||||
(test "explicit local json string token parse failure facade"
|
||||
(imported_json_parse_string_failure))
|
||||
|
||||
(test "explicit local json document parse trimmed success facade"
|
||||
(imported_json_parse_document_trimmed_success))
|
||||
|
||||
(test "explicit local json document parse plain success facade"
|
||||
(imported_json_parse_document_plain_success))
|
||||
|
||||
(test "explicit local json document parse trailing failure facade"
|
||||
(imported_json_parse_document_trailing_failure))
|
||||
|
||||
(test "explicit local json fields facade"
|
||||
(imported_json_fields))
|
||||
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
(module string (export trim_ascii))
|
||||
|
||||
(fn len ((value string)) -> i32
|
||||
(std.string.len value))
|
||||
|
||||
(fn byte_at_result ((value string) (index i32)) -> (result i32 i32)
|
||||
(std.string.byte_at_result value index))
|
||||
|
||||
(fn slice_result ((value string) (start i32) (count i32)) -> (result string i32)
|
||||
(std.string.slice_result value start count))
|
||||
|
||||
(fn is_ascii_trim_byte ((value i32)) -> bool
|
||||
(if (= value 9)
|
||||
true
|
||||
(if (= value 10)
|
||||
true
|
||||
(if (= value 11)
|
||||
true
|
||||
(if (= value 12)
|
||||
true
|
||||
(if (= value 13)
|
||||
true
|
||||
(= value 32)))))))
|
||||
|
||||
(fn byte_is_ascii_trim ((value string) (position i32)) -> bool
|
||||
(match (byte_at_result value position)
|
||||
((ok byte)
|
||||
(is_ascii_trim_byte byte))
|
||||
((err code)
|
||||
false)))
|
||||
|
||||
(fn trim_ascii_start ((value string)) -> string
|
||||
(let value_len i32 (len value))
|
||||
(var start i32 0)
|
||||
(while (and (< start value_len) (byte_is_ascii_trim value start))
|
||||
(set start (+ start 1)))
|
||||
(match (slice_result value start (- value_len start))
|
||||
((ok text)
|
||||
text)
|
||||
((err code)
|
||||
value)))
|
||||
|
||||
(fn trim_ascii_end ((value string)) -> string
|
||||
(let value_len i32 (len value))
|
||||
(var end i32 value_len)
|
||||
(while (and (> end 0) (byte_is_ascii_trim value (- end 1)))
|
||||
(set end (- end 1)))
|
||||
(match (slice_result value 0 end)
|
||||
((ok text)
|
||||
text)
|
||||
((err code)
|
||||
value)))
|
||||
|
||||
(fn trim_ascii ((value string)) -> string
|
||||
(trim_ascii_end (trim_ascii_start value)))
|
||||
@ -1,6 +1,6 @@
|
||||
(module main)
|
||||
|
||||
(import string (len concat byte_at_result slice_result starts_with ends_with contains index_of_option last_index_of_option trim_ascii_start trim_ascii_end trim_ascii parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
(import string (len concat byte_at_result slice_result starts_with ends_with parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
|
||||
(fn imported_string_concat () -> string
|
||||
(concat "slo" "vo"))
|
||||
@ -187,50 +187,6 @@
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_option_i32_is_some_value ((actual (option i32)) (expected i32)) -> bool
|
||||
(match actual
|
||||
((some payload)
|
||||
(= payload expected))
|
||||
((none)
|
||||
false)))
|
||||
|
||||
(fn imported_option_i32_is_none ((actual (option i32))) -> bool
|
||||
(match actual
|
||||
((some payload)
|
||||
false)
|
||||
((none)
|
||||
true)))
|
||||
|
||||
(fn imported_string_search_ok () -> bool
|
||||
(if (contains "alpha beta alpha" "beta")
|
||||
(if (contains "alpha" "z")
|
||||
false
|
||||
(if (contains "alpha" "")
|
||||
(if (imported_option_i32_is_some_value (index_of_option "alpha beta alpha" "alpha") 0)
|
||||
(if (imported_option_i32_is_none (index_of_option "alpha" "z"))
|
||||
(if (imported_option_i32_is_some_value (index_of_option "alpha" "") 0)
|
||||
(if (imported_option_i32_is_some_value (last_index_of_option "alpha beta alpha" "alpha") 11)
|
||||
(if (imported_option_i32_is_some_value (last_index_of_option "alpha" "") 5)
|
||||
(imported_option_i32_is_none (last_index_of_option "alpha" "z"))
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
false))
|
||||
|
||||
(fn imported_string_ascii_trim_ok () -> bool
|
||||
(if (= (trim_ascii_start " \t\nslovo") "slovo")
|
||||
(if (= (trim_ascii_end "slovo \t\n") "slovo")
|
||||
(if (= (trim_ascii " \t\nslovo \t\n") "slovo")
|
||||
(if (= (trim_ascii " \t\n") "")
|
||||
(= (trim_ascii "slovo") "slovo")
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
false))
|
||||
|
||||
(fn imported_string_helpers_ok () -> bool
|
||||
(if (= (imported_string_len_concat_score) 42)
|
||||
(if (imported_string_byte_at_ok)
|
||||
@ -240,11 +196,7 @@
|
||||
(if (imported_string_parse_options_ok)
|
||||
(if (imported_string_parse_integer_fallbacks_ok)
|
||||
(if (imported_string_parse_float_bool_fallbacks_ok)
|
||||
(if (imported_string_parse_custom_fallbacks_ok)
|
||||
(if (imported_string_search_ok)
|
||||
(imported_string_ascii_trim_ok)
|
||||
false)
|
||||
false)
|
||||
(imported_string_parse_custom_fallbacks_ok)
|
||||
false)
|
||||
false)
|
||||
false)
|
||||
@ -286,11 +238,5 @@
|
||||
(test "explicit local string parse custom fallbacks"
|
||||
(imported_string_parse_custom_fallbacks_ok))
|
||||
|
||||
(test "explicit local string search helpers"
|
||||
(imported_string_search_ok))
|
||||
|
||||
(test "explicit local string ascii trim helpers"
|
||||
(imported_string_ascii_trim_ok))
|
||||
|
||||
(test "explicit local string helpers all"
|
||||
(= (main) 42))
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
(module string (export len concat byte_at_result slice_result starts_with ends_with contains index_of_option last_index_of_option trim_ascii_start trim_ascii_end trim_ascii parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
(module string (export len concat byte_at_result slice_result starts_with ends_with parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
|
||||
(import result (ok_or_none_i32 ok_or_none_u32 ok_or_none_i64 ok_or_none_u64 ok_or_none_f64 ok_or_none_bool))
|
||||
|
||||
@ -20,99 +20,6 @@
|
||||
(fn ends_with ((value string) (suffix string)) -> bool
|
||||
(std.string.ends_with value suffix))
|
||||
|
||||
(fn suffix_starts_with ((value string) (needle string) (position i32) (value_len i32)) -> bool
|
||||
(match (slice_result value position (- value_len position))
|
||||
((ok text)
|
||||
(starts_with text needle))
|
||||
((err code)
|
||||
false)))
|
||||
|
||||
(fn index_of_option ((value string) (needle string)) -> (option i32)
|
||||
(let value_len i32 (len value))
|
||||
(let needle_len i32 (len needle))
|
||||
(let max_start i32 (- value_len needle_len))
|
||||
(var position i32 0)
|
||||
(var found_position i32 -1)
|
||||
(while (and (> needle_len 0) (and (< found_position 0) (<= position max_start)))
|
||||
(set found_position (if (suffix_starts_with value needle position value_len)
|
||||
position
|
||||
found_position))
|
||||
(set position (+ position 1)))
|
||||
(if (= needle_len 0)
|
||||
(some i32 0)
|
||||
(if (< found_position 0)
|
||||
(none i32)
|
||||
(some i32 found_position))))
|
||||
|
||||
(fn last_index_of_option ((value string) (needle string)) -> (option i32)
|
||||
(let value_len i32 (len value))
|
||||
(let needle_len i32 (len needle))
|
||||
(let max_start i32 (- value_len needle_len))
|
||||
(var position i32 0)
|
||||
(var found_position i32 -1)
|
||||
(while (and (> needle_len 0) (<= position max_start))
|
||||
(set found_position (if (suffix_starts_with value needle position value_len)
|
||||
position
|
||||
found_position))
|
||||
(set position (+ position 1)))
|
||||
(if (= needle_len 0)
|
||||
(some i32 value_len)
|
||||
(if (< found_position 0)
|
||||
(none i32)
|
||||
(some i32 found_position))))
|
||||
|
||||
(fn contains ((value string) (needle string)) -> bool
|
||||
(match (index_of_option value needle)
|
||||
((some position)
|
||||
true)
|
||||
((none)
|
||||
false)))
|
||||
|
||||
(fn is_ascii_trim_byte ((value i32)) -> bool
|
||||
(if (= value 9)
|
||||
true
|
||||
(if (= value 10)
|
||||
true
|
||||
(if (= value 11)
|
||||
true
|
||||
(if (= value 12)
|
||||
true
|
||||
(if (= value 13)
|
||||
true
|
||||
(= value 32)))))))
|
||||
|
||||
(fn byte_is_ascii_trim ((value string) (position i32)) -> bool
|
||||
(match (byte_at_result value position)
|
||||
((ok byte)
|
||||
(is_ascii_trim_byte byte))
|
||||
((err code)
|
||||
false)))
|
||||
|
||||
(fn trim_ascii_start ((value string)) -> string
|
||||
(let value_len i32 (len value))
|
||||
(var start i32 0)
|
||||
(while (and (< start value_len) (byte_is_ascii_trim value start))
|
||||
(set start (+ start 1)))
|
||||
(match (slice_result value start (- value_len start))
|
||||
((ok text)
|
||||
text)
|
||||
((err code)
|
||||
value)))
|
||||
|
||||
(fn trim_ascii_end ((value string)) -> string
|
||||
(let value_len i32 (len value))
|
||||
(var end i32 value_len)
|
||||
(while (and (> end 0) (byte_is_ascii_trim value (- end 1)))
|
||||
(set end (- end 1)))
|
||||
(match (slice_result value 0 end)
|
||||
((ok text)
|
||||
text)
|
||||
((err code)
|
||||
value)))
|
||||
|
||||
(fn trim_ascii ((value string)) -> string
|
||||
(trim_ascii_end (trim_ascii_start value)))
|
||||
|
||||
(fn parse_i32_result ((value string)) -> (result i32 i32)
|
||||
(std.string.parse_i32_result value))
|
||||
|
||||
|
||||
@ -22,8 +22,7 @@ helpers updated through `exp-54`, `exp-55`, and `exp-72`; CLI option helpers
|
||||
updated through `exp-110`; CLI local-source gate
|
||||
aligned in `exp-78`; string fallback helpers updated through `exp-60` and
|
||||
`exp-68`; string option helpers updated through `exp-110`; string
|
||||
byte-scanning and token-boundary helpers updated in `1.0.0-beta.16`; string
|
||||
search and ASCII trim helpers updated in `1.0.0-beta.20`; process fallback
|
||||
byte-scanning and token-boundary helpers updated in `1.0.0-beta.16`; process fallback
|
||||
helpers updated through `exp-61`; process typed helpers updated through
|
||||
`exp-67` and `exp-71`; process option helpers updated through `exp-110`; env
|
||||
fallback helpers updated through `exp-62` and `exp-69`; env typed helpers
|
||||
@ -42,13 +41,10 @@ compiler-known runtime calls; `1.0.0-beta.7` serialization work releases
|
||||
`1.0.0-beta.17` JSON foundation adds primitive scalar token parse facades for
|
||||
booleans, concrete numeric primitives, and exact `null`; the Slovo-facing
|
||||
`1.0.0-beta.18` JSON foundation adds one ASCII string-token parse
|
||||
facade; the `1.0.0-beta.21` JSON foundation adds source-authored
|
||||
whole-document scalar parse facades over `std.string.trim_ascii` and the
|
||||
existing exact value-token parsers; the
|
||||
facade; the
|
||||
`1.0.0-beta.8` concrete type alias target keeps that same helper surface while
|
||||
using local `JsonText` and `JsonField` aliases as transparent names for
|
||||
`string` JSON fragments; `1.0.0-beta.23` adds the public
|
||||
standard-library stability tier ledger without changing this helper surface.
|
||||
`string` JSON fragments.
|
||||
|
||||
This directory is the source home for staged standard library modules and
|
||||
examples. exp-44 lets project-mode source explicitly import `std/math.slo` as
|
||||
@ -114,15 +110,10 @@ and the current `std.num.*_to_string` helpers. The Slovo-facing
|
||||
facades over promoted `std.json` bool/numeric runtime helpers and an exact
|
||||
source-only `null` token helper. The `1.0.0-beta.18` JSON foundation
|
||||
adds `parse_string_value_result` for one already-isolated ASCII JSON string
|
||||
token over the matching promoted runtime helper. The
|
||||
`1.0.0-beta.21` JSON foundation adds source-authored
|
||||
`parse_*_document_result` helpers for string, bool, concrete numeric
|
||||
primitives, and exact `null` by trimming ASCII whitespace around the whole
|
||||
document and delegating to those exact value-token parsers. Object/array
|
||||
parsing, recursive JSON values, maps/sets, streaming decoders or encoders,
|
||||
schema validation, Unicode escape decoding/normalization beyond the existing
|
||||
string-token behavior, embedded NUL policy, and stable text encoding policy
|
||||
remain deferred;
|
||||
token over the matching promoted runtime helper. Full JSON document parsing,
|
||||
object/array parsing, recursive JSON values, maps/sets, streaming decoders or
|
||||
encoders, schema validation, Unicode escape decoding/normalization, embedded
|
||||
NUL policy, and stable text encoding policy remain deferred;
|
||||
`1.0.0-beta.8` targets top-level concrete type aliases in source facades and
|
||||
uses `JsonText` / `JsonField` only as local transparent aliases inside
|
||||
`std/json.slo` and matching local JSON fixtures. These aliases are not exported
|
||||
@ -171,18 +162,6 @@ make the standard library fully self-hosted, does not add automatic
|
||||
standard-library imports, and does not replace the compiler-known `std.*`
|
||||
standard-runtime calls cataloged in `../STANDARD_RUNTIME.md`.
|
||||
|
||||
`docs/language/STDLIB_API.md` remains the generated exact signature catalog
|
||||
for exported helpers in this directory. `docs/language/STDLIB_TIERS.md` is the
|
||||
beta23 public maturity ledger for that catalog. It defines the tier labels
|
||||
`beta-supported`, `experimental`, and `internal`; classifies JSON, loopback
|
||||
networking, random/time, and filesystem resource-handle helpers as
|
||||
experimental domains; and records the concrete vector modules as
|
||||
beta-supported concrete lanes, not a generic collections freeze. The tier
|
||||
ledger is documentation/catalog tooling clarity only and does not add helpers,
|
||||
syntax, runtime behavior, stable Markdown schema, or a stable stdlib/API
|
||||
freeze. The generated catalog and release gate now expose and check tier
|
||||
metadata.
|
||||
|
||||
The current `.slo` files use flat module declarations such as `(module math)`.
|
||||
For exp-44, exp-45, exp-47, exp-48, exp-49, exp-52, exp-53, exp-76, exp-94,
|
||||
exp-96, exp-97, exp-98, exp-99, exp-103, exp-104, exp-105, exp-107, exp-108,
|
||||
@ -250,12 +229,6 @@ exp-125 target adds matching `parse_u32_result`, `parse_u32_option`,
|
||||
`1.0.0-beta.16` adds `byte_at_result`, `slice_result`, `starts_with`, and
|
||||
`ends_with` as byte-oriented helpers over current runtime strings. Invalid
|
||||
byte indexes and ranges return `err 1`; empty prefixes and suffixes match.
|
||||
`1.0.0-beta.20` adds `contains`,
|
||||
`index_of_option`, `last_index_of_option`, `trim_ascii_start`,
|
||||
`trim_ascii_end`, and `trim_ascii` as ordinary source helpers over those same
|
||||
byte primitives. Empty needles match at first index `0` and last index
|
||||
`(len value)`. ASCII trim removes only bytes `9`, `10`, `11`, `12`, `13`, and
|
||||
`32` from the requested edges.
|
||||
This string scanning foundation does not add Unicode scalar or grapheme
|
||||
semantics, full JSON parsing, tokenizer objects, language-level slice/view
|
||||
syntax, mutable strings, stable ABI/layout promises, or a stable stdlib/API
|
||||
@ -350,18 +323,11 @@ array, and small object text from existing string and number helpers.
|
||||
`1.0.0-beta.17` adds primitive scalar token parse facades for `bool`, `i32`,
|
||||
`u32`, `i64`, `u64`, `f64`, and exact `null` only. The
|
||||
`1.0.0-beta.18` source facade adds `parse_string_value_result` for one exact
|
||||
ASCII JSON string token with simple escape decoding. The
|
||||
`1.0.0-beta.21` source facade adds `parse_string_document_result`,
|
||||
`parse_bool_document_result`, `parse_i32_document_result`,
|
||||
`parse_u32_document_result`, `parse_i64_document_result`,
|
||||
`parse_u64_document_result`, `parse_f64_document_result`, and
|
||||
`parse_null_document_result`; each trims ASCII whitespace around the whole
|
||||
document with `std.string.trim_ascii`, then delegates to the matching exact
|
||||
value-token parser. It is not a full JSON parser and does not define
|
||||
object/array parsing, recursive JSON values, maps/sets, streaming decoders or
|
||||
encoders, schema validation, Unicode escape decoding/normalization beyond the
|
||||
existing string-token behavior, embedded NUL policy, or stable text encoding
|
||||
policy beyond the current runtime string ABI.
|
||||
ASCII JSON string token with simple escape decoding. It is not a full JSON
|
||||
parser and does not define object/array parsing, recursive JSON values,
|
||||
maps/sets, streaming decoders or encoders, schema validation, Unicode escape
|
||||
decoding/normalization, embedded NUL policy, or stable text encoding policy
|
||||
beyond the current runtime string ABI.
|
||||
`std/process.slo` includes the exp-52 narrow source wrappers over already
|
||||
released process argument runtime calls and a source-authored `has_arg`
|
||||
predicate. exp-61 adds `arg_or` and `arg_or_empty` as ordinary source
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
(module json (export quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result parse_string_document_result parse_bool_document_result parse_i32_document_result parse_u32_document_result parse_i64_document_result parse_u64_document_result parse_f64_document_result parse_null_document_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
|
||||
(import std.string (trim_ascii))
|
||||
(module json (export quote_string null_value bool_value i32_value u32_value i64_value u64_value f64_value parse_string_value_result parse_bool_value_result parse_i32_value_result parse_u32_value_result parse_i64_value_result parse_u64_value_result parse_f64_value_result parse_null_value_result field_string field_bool field_i32 field_u32 field_i64 field_u64 field_f64 field_null array0 array1 array2 array3 object0 object1 object2 object3))
|
||||
|
||||
(type JsonText string)
|
||||
|
||||
@ -58,30 +56,6 @@
|
||||
(ok bool i32 true)
|
||||
(err bool i32 1)))
|
||||
|
||||
(fn parse_string_document_result ((document string)) -> (result string i32)
|
||||
(parse_string_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_bool_document_result ((document string)) -> (result bool i32)
|
||||
(parse_bool_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_i32_document_result ((document string)) -> (result i32 i32)
|
||||
(parse_i32_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_u32_document_result ((document string)) -> (result u32 i32)
|
||||
(parse_u32_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_i64_document_result ((document string)) -> (result i64 i32)
|
||||
(parse_i64_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_u64_document_result ((document string)) -> (result u64 i32)
|
||||
(parse_u64_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_f64_document_result ((document string)) -> (result f64 i32)
|
||||
(parse_f64_value_result (trim_ascii document)))
|
||||
|
||||
(fn parse_null_document_result ((document string)) -> (result bool i32)
|
||||
(parse_null_value_result (trim_ascii document)))
|
||||
|
||||
(fn field_fragment ((name string) (encoded_value JsonText)) -> JsonField
|
||||
(std.string.concat (std.string.concat (quote_string name) ":") encoded_value))
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
(module string (export len concat byte_at_result slice_result starts_with ends_with contains index_of_option last_index_of_option trim_ascii_start trim_ascii_end trim_ascii parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
(module string (export len concat byte_at_result slice_result starts_with ends_with parse_i32_result parse_i32_option parse_u32_result parse_u32_option parse_i64_result parse_i64_option parse_u64_result parse_u64_option parse_f64_result parse_f64_option parse_bool_result parse_bool_option parse_i32_or_zero parse_u32_or_zero parse_i64_or_zero parse_u64_or_zero parse_f64_or_zero parse_bool_or_false parse_i32_or parse_u32_or parse_i64_or parse_u64_or parse_f64_or parse_bool_or))
|
||||
|
||||
(import std.result (ok_or_none_i32 ok_or_none_u32 ok_or_none_i64 ok_or_none_u64 ok_or_none_f64 ok_or_none_bool))
|
||||
|
||||
@ -20,99 +20,6 @@
|
||||
(fn ends_with ((value string) (suffix string)) -> bool
|
||||
(std.string.ends_with value suffix))
|
||||
|
||||
(fn suffix_starts_with ((value string) (needle string) (position i32) (value_len i32)) -> bool
|
||||
(match (slice_result value position (- value_len position))
|
||||
((ok text)
|
||||
(starts_with text needle))
|
||||
((err code)
|
||||
false)))
|
||||
|
||||
(fn index_of_option ((value string) (needle string)) -> (option i32)
|
||||
(let value_len i32 (len value))
|
||||
(let needle_len i32 (len needle))
|
||||
(let max_start i32 (- value_len needle_len))
|
||||
(var position i32 0)
|
||||
(var found_position i32 -1)
|
||||
(while (and (> needle_len 0) (and (< found_position 0) (<= position max_start)))
|
||||
(set found_position (if (suffix_starts_with value needle position value_len)
|
||||
position
|
||||
found_position))
|
||||
(set position (+ position 1)))
|
||||
(if (= needle_len 0)
|
||||
(some i32 0)
|
||||
(if (< found_position 0)
|
||||
(none i32)
|
||||
(some i32 found_position))))
|
||||
|
||||
(fn last_index_of_option ((value string) (needle string)) -> (option i32)
|
||||
(let value_len i32 (len value))
|
||||
(let needle_len i32 (len needle))
|
||||
(let max_start i32 (- value_len needle_len))
|
||||
(var position i32 0)
|
||||
(var found_position i32 -1)
|
||||
(while (and (> needle_len 0) (<= position max_start))
|
||||
(set found_position (if (suffix_starts_with value needle position value_len)
|
||||
position
|
||||
found_position))
|
||||
(set position (+ position 1)))
|
||||
(if (= needle_len 0)
|
||||
(some i32 value_len)
|
||||
(if (< found_position 0)
|
||||
(none i32)
|
||||
(some i32 found_position))))
|
||||
|
||||
(fn contains ((value string) (needle string)) -> bool
|
||||
(match (index_of_option value needle)
|
||||
((some position)
|
||||
true)
|
||||
((none)
|
||||
false)))
|
||||
|
||||
(fn is_ascii_trim_byte ((value i32)) -> bool
|
||||
(if (= value 9)
|
||||
true
|
||||
(if (= value 10)
|
||||
true
|
||||
(if (= value 11)
|
||||
true
|
||||
(if (= value 12)
|
||||
true
|
||||
(if (= value 13)
|
||||
true
|
||||
(= value 32)))))))
|
||||
|
||||
(fn byte_is_ascii_trim ((value string) (position i32)) -> bool
|
||||
(match (byte_at_result value position)
|
||||
((ok byte)
|
||||
(is_ascii_trim_byte byte))
|
||||
((err code)
|
||||
false)))
|
||||
|
||||
(fn trim_ascii_start ((value string)) -> string
|
||||
(let value_len i32 (len value))
|
||||
(var start i32 0)
|
||||
(while (and (< start value_len) (byte_is_ascii_trim value start))
|
||||
(set start (+ start 1)))
|
||||
(match (slice_result value start (- value_len start))
|
||||
((ok text)
|
||||
text)
|
||||
((err code)
|
||||
value)))
|
||||
|
||||
(fn trim_ascii_end ((value string)) -> string
|
||||
(let value_len i32 (len value))
|
||||
(var end i32 value_len)
|
||||
(while (and (> end 0) (byte_is_ascii_trim value (- end 1)))
|
||||
(set end (- end 1)))
|
||||
(match (slice_result value 0 end)
|
||||
((ok text)
|
||||
text)
|
||||
((err code)
|
||||
value)))
|
||||
|
||||
(fn trim_ascii ((value string)) -> string
|
||||
(trim_ascii_end (trim_ascii_start value)))
|
||||
|
||||
(fn parse_i32_result ((value string)) -> (result i32 i32)
|
||||
(std.string.parse_i32_result value))
|
||||
|
||||
|
||||
@ -1,80 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const repoRoot = path.resolve(__dirname, "..");
|
||||
const catalogPath = path.join(repoRoot, "docs", "language", "STDLIB_API.md");
|
||||
const catalog = fs.readFileSync(catalogPath, "utf8");
|
||||
|
||||
function fail(message) {
|
||||
console.error(`stdlib API tier check failed: ${message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function requireText(text, message) {
|
||||
if (!catalog.includes(text)) {
|
||||
fail(message);
|
||||
}
|
||||
}
|
||||
|
||||
function moduleSection(moduleName) {
|
||||
const marker = `### std.${moduleName}\n`;
|
||||
const start = catalog.indexOf(marker);
|
||||
if (start < 0) {
|
||||
fail(`missing std.${moduleName} module section`);
|
||||
}
|
||||
const next = catalog.indexOf("\n### std.", start + marker.length);
|
||||
return next < 0 ? catalog.slice(start) : catalog.slice(start, next);
|
||||
}
|
||||
|
||||
function requireModuleTier(moduleName, expectedTier) {
|
||||
const section = moduleSection(moduleName);
|
||||
if (!section.includes(`- Tiers: \`${expectedTier}\``)) {
|
||||
fail(`std.${moduleName} is not marked as ${expectedTier}`);
|
||||
}
|
||||
}
|
||||
|
||||
function requireHelperTier(moduleName, helperName, expectedTier) {
|
||||
const section = moduleSection(moduleName);
|
||||
const helperPattern = new RegExp(`^- \`${expectedTier}\` \`${helperName} `, "m");
|
||||
if (!helperPattern.test(section)) {
|
||||
fail(`std.${moduleName}.${helperName} is not marked as ${expectedTier}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (/experimental`: not used|experimental not used/i.test(catalog)) {
|
||||
fail("catalog still contains stale wording that says experimental is unused");
|
||||
}
|
||||
|
||||
requireText("- `beta-supported`:", "missing beta-supported tier definition");
|
||||
requireText("- `experimental`:", "missing experimental tier definition");
|
||||
requireText("- `internal`:", "missing internal tier definition");
|
||||
requireText("- `experimental` helper signatures:", "missing experimental summary count");
|
||||
requireText("Concrete `std.vec_*` modules are beta-supported as concrete helper families only; this does not freeze a generic collection API.", "missing concrete vector boundary");
|
||||
|
||||
if (!/^- `experimental` `[^`]+`/m.test(catalog)) {
|
||||
fail("catalog does not list any experimental helper signatures");
|
||||
}
|
||||
|
||||
for (const moduleName of ["json", "net", "random", "time"]) {
|
||||
requireModuleTier(moduleName, "experimental");
|
||||
}
|
||||
|
||||
for (const helperName of [
|
||||
"open_text_read_result",
|
||||
"read_open_text_result",
|
||||
"close_result",
|
||||
"read_text_via_handle_result",
|
||||
"close_ok",
|
||||
]) {
|
||||
requireHelperTier("fs", helperName, "experimental");
|
||||
}
|
||||
|
||||
for (const moduleName of ["vec_bool", "vec_f64", "vec_i32", "vec_i64", "vec_string"]) {
|
||||
const section = moduleSection(moduleName);
|
||||
if (!section.includes("- Note: concrete-only vector helper family; no generic collection freeze.")) {
|
||||
fail(`std.${moduleName} is missing the concrete vector boundary note`);
|
||||
}
|
||||
}
|
||||
@ -9,11 +9,8 @@ cd "${repo_root}"
|
||||
git diff --check
|
||||
bash -n scripts/install.sh
|
||||
bash -n scripts/render-stdlib-api-doc.sh
|
||||
node --check scripts/render-stdlib-api-doc.js
|
||||
node --check scripts/check-stdlib-api-tiers.js
|
||||
|
||||
"${repo_root}/scripts/render-stdlib-api-doc.sh"
|
||||
"${repo_root}/scripts/check-stdlib-api-tiers.js"
|
||||
git diff --check
|
||||
if ! git diff --quiet -- docs/language/STDLIB_API.md; then
|
||||
echo "standard library API catalog changed; review and commit generated docs before release" >&2
|
||||
@ -72,11 +69,6 @@ cargo test --test reserved_generic_collection_beta15
|
||||
cargo test --test standard_string_scanning_beta16
|
||||
cargo test --test standard_json_scalar_parsing_beta17
|
||||
cargo test --test standard_json_string_parsing_beta18
|
||||
cargo test --test test_discovery_beta19
|
||||
cargo test --test standard_string_search_trim_beta20
|
||||
cargo test --test standard_json_document_scalar_parsing_beta21
|
||||
cargo test --test run_manifest_beta22
|
||||
cargo test --test package_workspace_discipline_beta24
|
||||
# Full cargo test includes unignored integration gates such as dx_v1_7,
|
||||
# beta_v2_0_0_beta_1, and beta_1_0_0.
|
||||
cargo test
|
||||
|
||||
@ -9,46 +9,6 @@ const stdDir = path.join(repoRoot, "lib", "std");
|
||||
const outputPath = path.join(repoRoot, "docs", "language", "STDLIB_API.md");
|
||||
const readmePath = path.join(repoRoot, "README.md");
|
||||
|
||||
const TIERS = Object.freeze({
|
||||
BETA_SUPPORTED: "beta-supported",
|
||||
EXPERIMENTAL: "experimental",
|
||||
INTERNAL: "internal",
|
||||
});
|
||||
|
||||
const EXPERIMENTAL_MODULES = new Set(["json", "net", "random", "time"]);
|
||||
|
||||
const EXPERIMENTAL_HELPERS = new Map([
|
||||
[
|
||||
"fs",
|
||||
new Set([
|
||||
"open_text_read_result",
|
||||
"read_open_text_result",
|
||||
"close_result",
|
||||
"read_text_via_handle_result",
|
||||
"close_ok",
|
||||
]),
|
||||
],
|
||||
]);
|
||||
|
||||
const CONCRETE_VEC_MODULES = new Set(["vec_bool", "vec_f64", "vec_i32", "vec_i64", "vec_string"]);
|
||||
|
||||
function helperTier(moduleName, exportName) {
|
||||
if (EXPERIMENTAL_MODULES.has(moduleName)) {
|
||||
return TIERS.EXPERIMENTAL;
|
||||
}
|
||||
|
||||
const experimentalHelpers = EXPERIMENTAL_HELPERS.get(moduleName);
|
||||
if (experimentalHelpers && experimentalHelpers.has(exportName)) {
|
||||
return TIERS.EXPERIMENTAL;
|
||||
}
|
||||
|
||||
return TIERS.BETA_SUPPORTED;
|
||||
}
|
||||
|
||||
function uniqueSorted(values) {
|
||||
return Array.from(new Set(values)).sort();
|
||||
}
|
||||
|
||||
function tokenize(source) {
|
||||
const tokens = [];
|
||||
let index = 0;
|
||||
@ -244,11 +204,7 @@ function stdModules() {
|
||||
|
||||
for (const exported of module.exports) {
|
||||
if (functions.has(exported)) {
|
||||
signatures.push({
|
||||
name: exported,
|
||||
signature: functionSignature(functions.get(exported), aliases, relativePath),
|
||||
tier: helperTier(module.name, exported),
|
||||
});
|
||||
signatures.push(functionSignature(functions.get(exported), aliases, relativePath));
|
||||
} else if (aliases.has(exported)) {
|
||||
omittedAliasExports.push(exported);
|
||||
} else {
|
||||
@ -260,7 +216,6 @@ function stdModules() {
|
||||
fileName,
|
||||
relativePath,
|
||||
name: module.name,
|
||||
tiers: uniqueSorted(signatures.map((signature) => signature.tier)),
|
||||
signatures,
|
||||
omittedAliasExports,
|
||||
};
|
||||
@ -279,15 +234,6 @@ function releaseVersion() {
|
||||
function render(modules, version) {
|
||||
const totalExports = modules.reduce((count, module) => count + module.signatures.length, 0);
|
||||
const totalOmittedAliases = modules.reduce((count, module) => count + module.omittedAliasExports.length, 0);
|
||||
const tierCounts = new Map([
|
||||
[TIERS.BETA_SUPPORTED, 0],
|
||||
[TIERS.EXPERIMENTAL, 0],
|
||||
]);
|
||||
for (const module of modules) {
|
||||
for (const signature of module.signatures) {
|
||||
tierCounts.set(signature.tier, (tierCounts.get(signature.tier) || 0) + 1);
|
||||
}
|
||||
}
|
||||
const out = [];
|
||||
out.push("# Slovo Standard Library API Catalog");
|
||||
out.push("");
|
||||
@ -297,13 +243,12 @@ function render(modules, version) {
|
||||
out.push("## Stability Tiers");
|
||||
out.push("");
|
||||
out.push("- `beta-supported`: exported from `lib/std` and covered by source-search, promotion, or facade gates in the current beta line.");
|
||||
out.push(`- \`experimental\`: exported from \`lib/std\` in \`${version}\`, but still has beta caveats around host behavior, resource handles, or API shape.`);
|
||||
out.push(`- \`experimental\`: not used for exported \`lib/std\` helpers in \`${version}\`; future releases may mark new helpers this way before they graduate.`);
|
||||
out.push("- `internal`: helper names that are not exported from their module; they are intentionally omitted from this catalog.");
|
||||
out.push("");
|
||||
out.push("The catalog is a beta API discovery aid, not a stable `1.0.0` standard-library freeze.");
|
||||
out.push("Module-local concrete aliases are normalized in signatures so names such as `VecI32` and `ResultU64` do not leak into the public catalog.");
|
||||
out.push("Only exported `(fn ...)` helpers are listed; `(type ...)` aliases and non-exported helpers are omitted.");
|
||||
out.push("Concrete `std.vec_*` modules are beta-supported as concrete helper families only; this does not freeze a generic collection API.");
|
||||
out.push("");
|
||||
out.push("## Summary");
|
||||
out.push("");
|
||||
@ -311,8 +256,6 @@ function render(modules, version) {
|
||||
out.push(`- Exported helper signatures: ${totalExports}`);
|
||||
out.push(`- Exported type aliases omitted: ${totalOmittedAliases}`);
|
||||
out.push("- Default tier: `beta-supported`");
|
||||
out.push(`- \`${TIERS.BETA_SUPPORTED}\` helper signatures: ${tierCounts.get(TIERS.BETA_SUPPORTED) || 0}`);
|
||||
out.push(`- \`${TIERS.EXPERIMENTAL}\` helper signatures: ${tierCounts.get(TIERS.EXPERIMENTAL) || 0}`);
|
||||
out.push("");
|
||||
out.push("## Modules");
|
||||
out.push("");
|
||||
@ -320,14 +263,11 @@ function render(modules, version) {
|
||||
out.push(`### std.${module.name}`);
|
||||
out.push("");
|
||||
out.push(`- Path: \`${module.relativePath}\``);
|
||||
out.push(`- Tiers: ${module.tiers.map((tier) => `\`${tier}\``).join(", ")}`);
|
||||
out.push("- Tier: `beta-supported`");
|
||||
out.push(`- Exported helper signatures: ${module.signatures.length}`);
|
||||
if (CONCRETE_VEC_MODULES.has(module.name)) {
|
||||
out.push("- Note: concrete-only vector helper family; no generic collection freeze.");
|
||||
}
|
||||
out.push("");
|
||||
for (const { signature, tier } of module.signatures) {
|
||||
out.push(`- \`${tier}\` \`${signature}\``);
|
||||
for (const signature of module.signatures) {
|
||||
out.push(`- \`${signature}\``);
|
||||
}
|
||||
out.push("");
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user