Skip to content

Add data persistence, serialization, services, contracts, and testing to language design - #2

Merged
benpayne merged 12 commits into
masterfrom
claude/add-claude-documentation-ueCaE
Feb 22, 2026
Merged

Add data persistence, serialization, services, contracts, and testing to language design#2
benpayne merged 12 commits into
masterfrom
claude/add-claude-documentation-ueCaE

Conversation

@benpayne

Copy link
Copy Markdown
Owner

Expand the language design spec with new sections informed by research into
LLM-optimized language design (MoonBit, Dana, MIT CSAIL, LMQL):

  • Data and Persistence: table structs, type-checked query expressions with
    pipeline syntax, automatic schema migrations (no manual migration files)
  • Serialization and Wire Protocols: @json/@grpc/@msgpack annotations with
    compiler code generation, gRPC as primary cross-language wire format
  • Network Services: HTTP and GraphQL as standard library (not language syntax),
    with rationale for the language-vs-stdlib boundary
  • Contracts: requires/ensures preconditions and postconditions
  • Built-in Testing: test blocks as a language keyword, inline with source
  • LLM Design Rules: no function overloading, mandatory public type signatures,
    flat module namespace (one level deep)
  • Phased implementation roadmap replacing flat next-steps list

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD

… to language design

Expand the language design spec with new sections informed by research into
LLM-optimized language design (MoonBit, Dana, MIT CSAIL, LMQL):

- Data and Persistence: table structs, type-checked query expressions with
  pipeline syntax, automatic schema migrations (no manual migration files)
- Serialization and Wire Protocols: @json/@grpc/@msgpack annotations with
  compiler code generation, gRPC as primary cross-language wire format
- Network Services: HTTP and GraphQL as standard library (not language syntax),
  with rationale for the language-vs-stdlib boundary
- Contracts: requires/ensures preconditions and postconditions
- Built-in Testing: test blocks as a language keyword, inline with source
- LLM Design Rules: no function overloading, mandatory public type signatures,
  flat module namespace (one level deep)
- Phased implementation roadmap replacing flat next-steps list

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
Phase 1 (76 tasks): Core language - fn syntax transition, structs, protocols,
generics, Result/Option, match, modules, CLI tooling
Phase 2 (57 tasks): Concurrency and safety - ownership model, spawn/chan,
async/await, contracts, built-in test blocks
Phase 3 (70 tasks): Data and services - pipeline operator, table structs,
query expressions, automatic migrations, serialization annotations,
gRPC, HTTP stdlib, GraphQL stdlib
Cross-cutting (14 tasks): Documentation, test infrastructure, CI

Each task categorized as impl/test/docs/infra with specific descriptions.
Includes current state assessment and recommended execution order.

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
- Add docs/implementation_plan.md with 217 tasks across 3 phases
  covering implementation, tests, and documentation for each feature
- Update language_design.md "Currently Working" to reflect merged PR:
  binary expressions, assignment operators, unary expressions, extern
  declarations, nested calls, and end-to-end LLVM codegen pipeline
- Remove completed items from Next Steps, link to implementation plan

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
…e xfail tests

Lexer (FileLexer.h/cpp):
- Add keywords: fn, bool, struct, impl, self, protocol, match, import, pub, break, continue
- Add BOOL token type for boolean type recognition

AST (Type.h, Expression.h):
- Add StructDefinition (fields + methods) and ProtocolDefinition (required method sigs)
- Add FieldAccessExpression (object.field), MatchExpression with MatchArm
- Add BreakStatement and ContinueStatement

Parser (QFunctionDefinition.cpp, QVariableDefinition.cpp):
- Support unnamed parameters in extern declarations (e.g. extern int printf(string, ...))
- Generate synthetic _arg0, _arg1 names for unnamed params

Tests:
- Move 4 passing xfail tests to pass/: arithmetic_stmt, assignment_stmt,
  binary_expr_return, comparison_expr
- Update test comments to reflect they now pass

All 25 tests pass. Build compiles cleanly.

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
Verifies that extern functions can omit parameter names:
  extern int printf(string, ...);
  extern void exit(int);

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
…ions

Parser - fn declarations (QFunctionDefinition.cpp):
- Parse `fn name(params) -> type { body }` syntax
- Omitted `->` defaults to void return type
- C-style declarations still supported as fallback

Parser - break/continue (QBreakContinue.cpp, QStatement.cpp):
- New QBreakContinue.cpp with Parse methods for both statements
- Statement dispatcher routes KEYWORD_BREAK/KEYWORD_CONTINUE tokens

Parser - struct definitions (QStructDefinition.cpp, qcc.cpp):
- Parse `struct Name { type field; ... }` at module level
- Module::Parse dispatches to StructDefinition::Parse on struct keyword
- Fields parsed as type+name pairs

Build (CMakeLists.txt):
- Add QBreakContinue.cpp and QStructDefinition.cpp to qcc target

Tests (6 new, all passing):
- fn_simple.c, fn_void.c — fn-style function declarations
- break_continue.c — break/continue in while loop
- struct_basic.c — simple struct definition

All 30 tests pass (29 pass + 1 xfail).

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
Parser (QExpression.cpp):
- Parse postfix field access: expr.field chains as left-associative
- a.b.c parses as FieldAccessExpression(FieldAccessExpression(a, "b"), "c")

AST (Expression.h):
- Add public constructor to FieldAccessExpression(Expression*, string)

Documentation (CLAUDE.md):
- Document new keywords (fn, bool, struct, impl, self, protocol, etc.)
- Document fn declarations, break/continue, struct definitions
- Update class hierarchy with new AST nodes
- Update repository structure with new files
- Update test count to 30

All 30 tests pass.

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
Parser - struct literals (QExpression.cpp, Expression.h):
- Parse `StructName { field: value, ... }` as StructLiteralExpression
- New StructLiteralExpression AST node with field names and values
- Detects struct names in scope to disambiguate from blocks

Parser - protocol definitions (QProtocolDefinition.cpp, qcc.cpp):
- Parse `protocol Name { fn method(params) -> type; ... }`
- Method signatures parsed without bodies (semicolon-terminated)
- Module::Parse dispatches on KEYWORD_PROTOCOL token

Parser - bool type (QType.cpp):
- BOOL token now recognized as a valid type in declarations
- Works in variable decls, function params, and return types

AST (Type.h):
- Add ProtocolDefinition as friend of FunctionDefinition for
  method signature construction

Build (CMakeLists.txt):
- Add QProtocolDefinition.cpp to qcc target

Tests (4 new, all passing):
- struct_literal.c, protocol_basic.c, bool_type.c

All 34 tests pass (33 pass + 1 xfail).

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
QProtocolDefinition.cpp now delegates method signature parsing to
FunctionDefinition::Parse instead of manually constructing
FunctionDefinition objects. This removes the need for the
ProtocolDefinition friend declaration on FunctionDefinition.

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
- QFieldAccessExpression.cpp: stub Parse method for FieldAccessExpression
- field_access.c: test with struct definition and basic usage
- Minor adjustments from background agent verification

All 34 tests pass.

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
Parser - impl blocks (QImplBlock.cpp, qcc.cpp):
- Parse `impl StructName { fn methods... }`
- Parse `impl Protocol for StructName { fn methods... }`
- Methods added to struct's method list via addMethod()
- Module::Parse dispatches on KEYWORD_IMPL

Parser - match expressions (QMatchExpression.cpp, QStatement.cpp):
- Parse `match expr { pattern { body } ... }`
- Patterns: integer, string, char constants, identifiers
- Statement dispatcher routes KEYWORD_MATCH to MatchExpression::Parse

Parser - const/var (QVariableDefinition.cpp, Type.h):
- `const` variables require initializers, flag stored on VariableDefinition
- `var` keyword for type inference (placeholder type "var")
- `var` requires initializer for inference

AST (Type.h):
- Add mIsConst flag + setConst/isConst to VariableDefinition
- Add addMethod() to StructDefinition

Tests (12 new, all passing):
- Pass: impl_basic, impl_protocol, match_basic, const_decl, var_infer
- Fail: const_no_init, var_no_init, struct_missing_brace,
  struct_bad_field, protocol_no_fn, fn_missing_arrow_type, duplicate_func

All 46 tests pass (45 + 1 xfail).

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
… method calls

Implement core Phase 1 features for the BLang parser:

- Enum/sum types with variants and associated types (enum Option<T> { some(T), none })
- Generic parameters on functions, structs, and protocols (<T: Constraint>)
- Generic type arguments in type expressions (Array<int>, Map<string, int>)
- For-in loops with range iteration (for i in 0..10 {}), collection iteration, and infinite loops (for {})
- Array literal expressions ([1, 2, 3]) and index expressions (arr[0])
- Method call expressions (obj.method(args))
- Range expressions (start..end)
- Float/double literal lexing (3.14, 0.001)
- Arrow token (->) as first-class lexer token
- Wildcard token (_) for pattern matching
- Match expression improvements: wildcard patterns, destructuring with bindings (ok(value) => {})
- Self parameter support in method definitions

New files: QEnumDefinition.cpp, QForInStatement.cpp
New AST nodes: ForInStatement, ArrayLiteralExpression, IndexExpression, MethodCallExpression,
  RangeExpression, StringInterpolation, EnumDefinition
18 new pass tests, 2 new fail tests (66 total, all passing)

https://claude.ai/code/session_01RGhzmTBfPssMgJbPvsJTzD
@benpayne
benpayne merged commit 559a80e into master Feb 22, 2026
1 check passed
benpayne pushed a commit that referenced this pull request Jul 1, 2026
…Result

Example #2: an arithmetic expression interpreter (examples/calculator). It
tokenizes an expression and evaluates it with a classic recursive-descent
parser over Result<int, string>, exercising enums with payloads, arrays of
enums, `?` error propagation, pattern matching, a mutable Parser struct threaded
by reference, forward references / mutual recursion, and string/char scanning.
The `test` blocks are colocated in main.b and run via `bcc test`;
test_calculator.sh automates build + demo + test suite.

Writing it surfaced two real codegen bugs, both fixed here:

- `&&` / `||` did not short-circuit. genOperationsExpression evaluated BOTH
  operands up front, so the right side always ran — a guard like
  `i < n && s[i] == c` would index out of bounds. Now emitted with proper
  branching: the right operand is generated in its own block and evaluated only
  when the left does not already decide the result, joined with a PHI.

- Refcounted heap payloads carried through Result/Option were freed too early.
  genEnumConstruct transferred ownership for string payloads (untrack) but did
  nothing for Array/Buffer/struct — yet emitEnumPayloadRelease releases all of
  them at scope exit. So a local array returned via Result.ok(a) was released by
  its origin scope while the enum still referenced it (use-after-free / garbage
  length on unwrap). The enum now retains Array/Buffer/struct payloads so it owns
  its own reference (verified leak-free with ASan).

Regression tests: test_files/codegen_short_circuit.b (short-circuit prevents an
OOB index) and test_files/codegen_array_in_result.b (Array survives a Result
round-trip). Full suite green: 168 parse/fail + 80 codegen E2E.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wh5TjYg4CbEY3FaARMpVDo
benpayne added a commit that referenced this pull request Jul 22, 2026
+16 genuine behavioral codegen_*.b tests (118 -> 134, >=132 target met) across
all four areas (math/time/random/env/collections/sort/cli/opt/debug), named to
satisfy the evaluation.md module-test globs; all pass at -O0/-O2/-g, leak-clean,
deterministic goldens. CI legs added that EXECUTE the new gates: opt-suite
(-O2 codegen + leak + --release + aarch64 cross-compile), debug-suite (-g codegen
+ DWARF/gdb smoke + -g-O2 verify), epic-acceptance (multi-error + JSON schema +
-Werror + stdlib globs + count + architect-reviewed specs).

EPIC 001-toolchain-and-stdlib COMPLETE — all six done-conditions verified on a
clean build (evaluation.md acceptance): #1 correctness (LLVM 198 + parse-only 193
+ codegen 134 at -O0/-O2/-g + ctest 77 + leak 0); #2 diagnostics (>=3 located +
JSON schema + -Werror); #3 optimization (-O2 suite + opt-delta + --release +
aarch64); #4 debug info (DWARF subprogram + line table + gdb + -g-O2 verifies);
#5 stdlib breadth (math/time/random/env/sort/hashed-Map/Set/flags each tested);
#6 count 134 + four architect-reviewed area specs + CI legs.

Reviewed-by: architect (Vera, PASS-WITH-FINDINGS, 0 blocking)
Reviewed-by: code-reviewer (Rex, APPROVE, 0 blocking; GO for complete)
benpayne pushed a commit that referenced this pull request Jul 27, 2026
…fer generic call type args

The root cause behind four filed known-issues (#1-remainder, #3, #4, #6):
every ARC decision keyed on declared type NAMES, and inside a monomorphized
generic those names are the erased parameters (T/K/V), so refcounted values
were invisible to tracking, retains, and releases. sort<string> crashed,
Map<string,string> leaked, struct-valued Map corrupted under churn, and
Map<string, Array<int>> double-freed in its destructor.

One shared resolution layer (CGTypes.cpp), applied to every site together:
- resolvedTypeName(Type*): declared name through the active monomorphization
  substitution ("T" -> string inside sort<string>).
- callReturnTypeName(CallExpression*): a generic call's declared return mapped
  through its (explicit or inferred) type arguments.
- methodReturnTypeName(MethodCallExpression*): a generic-struct method's
  declared return (Map<K,V>.get's "V") mapped through the object instance's
  type arguments — resolvable at the CALLER, where no substitution is active.

Sites moved onto it: var-decl scope tracking (string/Array), borrowed-source
bind-retains, untrack-on-store, genMethodCall/generic-call temp tracking, and
the isStringType/isArrayType predicates (isArrayType gains the index-element
and method-return cases isStringType already had). genReturnStatement's array
retain now includes IndexExpression sources — an element read is a borrow, so
`return self.values[idx]` must hand the caller its own reference.

Generic calls without an explicit <...> list now INFER their type arguments by
structurally unifying declared parameter types against the arguments' static
types (Array<T> vs Array<string> binds T=string). Previously such a call fell
through to "undefined function" WITHOUT setting mHasError — the compile
exited 0 with the call silently dropped and the consumer reading uninitialized
memory. Both that path and failed instantiation are now loud errors, and a
generic call that can neither infer nor was given explicit args fails with a
located suggestion (cgfail/generic_infer_fail.b).

Matrix locked in with goldens, all ASan/LSan-clean:
- codegen_generic_arc_sort.b   sort<T> over strings (inferred) + ints
- codegen_generic_arc_return.b generic returns, inferred + explicit
- codegen_generic_arc_map.b    Map string values, struct values under 80-set
                               churn with interpolated keys, Array values

known-issues.md #1/#3/#4/#6 marked fixed (#2 aggregate-return and #5
namespaced-module remain open). Suites: 203/203 parse, 145/145 codegen E2E,
0 leaks, ctest green, all four examples green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wh5TjYg4CbEY3FaARMpVDo
benpayne pushed a commit that referenced this pull request Jul 27, 2026
…s) verified fixed

The two remaining known-issues' repros now pass ASan/LSan-clean — the string
bind-retain and temp-string/return ownership work resolved both as a side
effect. Locked in permanently:

- codegen_arc_aggregate_return.b (#2): a multi-field struct whose Array fields
  are populated inside the function and returned — two live aggregates,
  reads through both, mutation through the returned aggregate, and passing
  one to a function. This was the reason stdlib `cli` returns scalars instead
  of a Flags struct.
- codegen_arc_namespaced_strings.b (#5): a namespaced stdlib module's internal
  string-returning call chain (net.build_http_response -> net.http_status_text
  under net__ module-prefix codegen), looped 20x. This was the reason
  `cli`/`collections` were parsed into the global scope.

test_codegen.sh now combines net.b when a test contains `import net;`
(content-gated, mirroring bcc's real stdlib resolution) in addition to the
historical filename patterns.

known-issues.md: ledger closed — zero open ARC issues. The global-scope
placement of cli/collections is now an API choice, not a correctness
workaround.

Suites: 203/203 parse, 148/148 codegen E2E, 0 leaks, ctest green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wh5TjYg4CbEY3FaARMpVDo
benpayne added a commit that referenced this pull request Aug 5, 2026
N1 (BLOCKER) — a conformance record naming a user-defined protocol made the
.bmod unparseable. BmodEmitter::emit ran the struct loop before the protocol
loop, so every `impl P for S { }` record was a FORWARD REFERENCE:

    t.bmod:11:23: error: Unknown protocol 'Sizeable' in impl block

i.e. a library whose interface no consumer can read -- the same defect class as
the `table pub struct` break fixed earlier in this PR, and a regression against
master introduced by U2's own headline feature.

It hid because every fixture in the corpus conformed only to `Printable`, the one
builtin protocol pre-registered in every scope, so its record resolved wherever
it appeared. All 48 checks passed on a compiler that broke every user-defined
protocol conformance.

Fixed by emitting protocols FIRST. The "a record must follow its struct's
interface block" constraint concerns the struct (conformance checking reads the
struct's accumulated methods), not the protocol, so both orderings satisfy it.
Additionally, a record naming a NON-exported protocol is now skipped: a non-`pub`
protocol is not emitted into the interface, so such a record would dangle and
take the file down with it. (Rejecting that combination at the library build is
P9 enforcement, U3's; U2's job is only not to emit an unreadable file.)

New fixture pair test_build/sizelib + sizeapp, using a user-defined `pub
protocol`, asserting the ordering, the non-exported-protocol skip, that the .bmod
re-parses standalone, and that the consumer builds and runs. Without it the whole
class stays untested.

N2 (MAJOR) — investigated and split, because the two halves have different
answers. Generic conformance records themselves WORK: a generic struct with a
multi-line conformance impl emits `impl Summable for Pair { }` and round-trips
cleanly. So suppressing generic record emission would have removed working
behaviour to dodge an unrelated bug. Instead mathlib now carries a real
`pub protocol Summable` conformed to by `Pair<T>`, so the golden check named
"generic bodies + conformances" finally guards a file containing one, plus two
explicit assertions. The check name is corrected to say what it guards.

The slicing defect the critic pointed at is real but ORTHOGONAL and pre-existing:
it fires on a SINGLE-LINE impl block (the method's location is the impl line, so
the slice takes the whole block and the emitter nests it inside another). Filed
as KI-11 with a minimal repro, and confirmed untouched by U2 --
sliceDefinitionSource is BmodEmitter.cpp:33-103 and U2's earliest change to that
file is line 222.

n-3 — deleted the dead structVarDef; the B1 fix went through
getExpressionAddress.

Format version deliberately NOT bumped (manager ruling): the reorder changes no
emitted shape for any case that previously worked -- files that parsed before
parse byte-identically, and the only files whose bytes moved are ones no consumer
could read. Judgement recorded in BmodFormat.h so U3 does not re-litigate it.

Filed without fixing: KI-12 (a `sync` receiver is not locked around a method
call, so `sync` gives no mutual exclusion for method bodies at all -- print
dispatch is now consistent with genMethodCall, but the shared behaviour is weaker
than `sync` implies); KI-13 (`bcc build` swallows qcc's located diagnostic, so
every located cross-module diagnostic this epic adds is invisible through the
command users actually run); KI-14 (local structs are Printable by method name,
imported ones by conformance record -- deliberate and commented, recorded as a U5
convergence item).

KI-8 and KI-10 assigned to U4 per the manager's ruling, recorded in
known-issues.md and workplan.md with both indirect done-condition exposures (DC8
pushes authors toward the silently-broken spellings; CLAUDE.md claims coverage no
test has) and the hard constraint that they land BEFORE U5's corpus migration.

Gates (local; CI is the authority): run_tests 222/0 LLVM, 215/0 parse-only;
test_codegen 157/0; --leak-check Leaks: 0; test_lsp 54/0; run_build_tests 56
checks all pass; ctest 79/79.
benpayne added a commit that referenced this pull request Aug 9, 2026
U4 remainder functionally complete at the PR gate (accessor surface, examples
migration, KI-20/21 fixed, gates green + leak-clean); U5 not started. Record
KI-22 (pre-existing for-in/generic-method codegen bug, routed around in-scope)
as Open Question #2 needing a product-owner ruling; log Q-U4-1 deferral to
U5/PR #3.
benpayne added a commit that referenced this pull request Aug 9, 2026
… CHANGES-REQUIRED, test-only)

The two resolver ctests leaked under ASan/LSan and failed the runtime-units CI job
(ctest under build-asan). Test-only fix; production Resolver untouched.

- ResolverTest.cpp: hold newModuleScope() results in SmartPtr<Scope> locals (were
  raw Scope*), so they release before ~Resolver; a leaked module scope's retained
  mParent otherwise pinned the builtin global scope alive (the reviewer's exact
  diagnosis).
- ResolverReuseTest.cpp: restructured so no scope outlives its Resolver (capture
  resolution RESULTS inside each block, not a returned scope), and switched to a
  STRUCT-ONLY fixture. A struct registers as BOTH a type and a symbol, so the DC5
  test still proves type AND symbol resolution identical across the qcc and real
  lsp::compileDocument paths (plus negative resolution). Parsing a function BODY /
  extern-fn param list leaks the parser's internal AST/scope allocations under ASan
  -- a PRE-EXISTING compiler-process leak these ctests are the first to surface
  (filed KG-7); the struct-only fixture avoids it without weakening the proof.
- Reviewer's optional owning-handle suggestion SKIPPED per its guidance (would
  change both production call sites that already own their scopes); noted in KG-7.

Verified LSan-clean: full Test project /opt/wip/blang/build-asan
      Start  1: resolver_component
 1/81 Test  #1: resolver_component ...............   Passed    0.02 sec
      Start  2: resolver_reuse
 2/81 Test  #2: resolver_reuse ...................   Passed    0.02 sec
      Start  3: array_create_empty
 3/81 Test  #3: array_create_empty ...............   Passed    0.01 sec
      Start  4: array_push_length
 4/81 Test  #4: array_push_length ................   Passed    0.01 sec
      Start  5: array_get
 5/81 Test  #5: array_get ........................   Passed    0.01 sec
      Start  6: array_set
 6/81 Test  #6: array_set ........................   Passed    0.02 sec
      Start  7: array_pop
 7/81 Test  #7: array_pop ........................   Passed    0.02 sec
      Start  8: array_pop_empty
 8/81 Test  #8: array_pop_empty ..................   Passed    0.01 sec
      Start  9: array_insert_remove
 9/81 Test  #9: array_insert_remove ..............   Passed    0.01 sec
      Start 10: array_concat
10/81 Test #10: array_concat .....................   Passed    0.01 sec
      Start 11: array_clear
11/81 Test #11: array_clear ......................   Passed    0.01 sec
      Start 12: array_grow
12/81 Test #12: array_grow .......................   Passed    0.02 sec
      Start 13: array_get_oob
13/81 Test #13: array_get_oob ....................   Passed    0.02 sec
      Start 14: array_set_oob
14/81 Test #14: array_set_oob ....................   Passed    0.02 sec
      Start 15: array_get_null
15/81 Test #15: array_get_null ...................   Passed    0.02 sec
      Start 16: string_create_len
16/81 Test #16: string_create_len ................   Passed    0.01 sec
      Start 17: string_empty
17/81 Test #17: string_empty .....................   Passed    0.01 sec
      Start 18: string_equals
18/81 Test #18: string_equals ....................   Passed    0.01 sec
      Start 19: string_concat
19/81 Test #19: string_concat ....................   Passed    0.01 sec
      Start 20: string_substring
20/81 Test #20: string_substring .................   Passed    0.01 sec
      Start 21: string_to_upper
21/81 Test #21: string_to_upper ..................   Passed    0.01 sec
      Start 22: string_to_lower
22/81 Test #22: string_to_lower ..................   Passed    0.01 sec
      Start 23: string_trim
23/81 Test #23: string_trim ......................   Passed    0.01 sec
      Start 24: string_contains
24/81 Test #24: string_contains ..................   Passed    0.01 sec
      Start 25: string_starts_ends
25/81 Test #25: string_starts_ends ...............   Passed    0.01 sec
      Start 26: string_index_of
26/81 Test #26: string_index_of ..................   Passed    0.01 sec
      Start 27: string_compare
27/81 Test #27: string_compare ...................   Passed    0.01 sec
      Start 28: string_to_int
28/81 Test #28: string_to_int ....................   Passed    0.01 sec
      Start 29: string_replace
29/81 Test #29: string_replace ...................   Passed    0.01 sec
      Start 30: string_char_at_oob
30/81 Test #30: string_char_at_oob ...............   Passed    0.02 sec
      Start 31: buffer_create
31/81 Test #31: buffer_create ....................   Passed    0.01 sec
      Start 32: buffer_append_byte
32/81 Test #32: buffer_append_byte ...............   Passed    0.01 sec
      Start 33: buffer_from_string
33/81 Test #33: buffer_from_string ...............   Passed    0.01 sec
      Start 34: buffer_append_string
34/81 Test #34: buffer_append_string .............   Passed    0.01 sec
      Start 35: buffer_get_set
35/81 Test #35: buffer_get_set ...................   Passed    0.01 sec
      Start 36: buffer_to_string
36/81 Test #36: buffer_to_string .................   Passed    0.01 sec
      Start 37: buffer_slice
37/81 Test #37: buffer_slice .....................   Passed    0.01 sec
      Start 38: buffer_index_of
38/81 Test #38: buffer_index_of ..................   Passed    0.01 sec
      Start 39: buffer_clear
39/81 Test #39: buffer_clear .....................   Passed    0.01 sec
      Start 40: buffer_get_oob
40/81 Test #40: buffer_get_oob ...................   Passed    0.02 sec
      Start 41: json_decode_int
41/81 Test #41: json_decode_int ..................   Passed    0.01 sec
      Start 42: json_decode_string
42/81 Test #42: json_decode_string ...............   Passed    0.01 sec
      Start 43: json_decode_bool
43/81 Test #43: json_decode_bool .................   Passed    0.01 sec
      Start 44: json_decode_error
44/81 Test #44: json_decode_error ................   Passed    0.01 sec
      Start 45: json_object_roundtrip
45/81 Test #45: json_object_roundtrip ............   Passed    0.02 sec
      Start 46: json_array_build
46/81 Test #46: json_array_build .................   Passed    0.01 sec
      Start 47: json_object_get_missing
47/81 Test #47: json_object_get_missing ..........   Passed    0.01 sec
      Start 48: fs_write_read
48/81 Test #48: fs_write_read ....................   Passed    0.02 sec
      Start 49: fs_seek
49/81 Test #49: fs_seek ..........................   Passed    0.02 sec
      Start 50: fs_size
50/81 Test #50: fs_size ..........................   Passed    0.02 sec
      Start 51: fs_remove
51/81 Test #51: fs_remove ........................   Passed    0.02 sec
      Start 52: fs_mkdir_list
52/81 Test #52: fs_mkdir_list ....................   Passed    0.02 sec
      Start 53: net_connect_refused
53/81 Test #53: net_connect_refused ..............   Passed    0.02 sec
      Start 54: net_connect_bad_host
54/81 Test #54: net_connect_bad_host .............   Passed    0.02 sec
      Start 55: net_selector_lifecycle
55/81 Test #55: net_selector_lifecycle ...........   Passed    0.02 sec
      Start 56: net_close_invalid
56/81 Test #56: net_close_invalid ................   Passed    0.02 sec
      Start 57: math_sqrt
57/81 Test #57: math_sqrt ........................   Passed    0.02 sec
      Start 58: math_pow
58/81 Test #58: math_pow .........................   Passed    0.02 sec
      Start 59: math_trig
59/81 Test #59: math_trig ........................   Passed    0.01 sec
      Start 60: math_log_exp
60/81 Test #60: math_log_exp .....................   Passed    0.01 sec
      Start 61: math_floor_ceil
61/81 Test #61: math_floor_ceil ..................   Passed    0.01 sec
      Start 62: math_fabs
62/81 Test #62: math_fabs ........................   Passed    0.01 sec
      Start 63: math_abs_int
63/81 Test #63: math_abs_int .....................   Passed    0.01 sec
      Start 64: time_now_positive
64/81 Test #64: time_now_positive ................   Passed    0.01 sec
      Start 65: time_millis_ge_seconds
65/81 Test #65: time_millis_ge_seconds ...........   Passed    0.01 sec
      Start 66: time_monotonic_nondecreasing
66/81 Test #66: time_monotonic_nondecreasing .....   Passed    0.01 sec
      Start 67: random_seeded_sequence
67/81 Test #67: random_seeded_sequence ...........   Passed    0.02 sec
      Start 68: random_seed_reproducible
68/81 Test #68: random_seed_reproducible .........   Passed    0.01 sec
      Start 69: random_int_range_bounds
69/81 Test #69: random_int_range_bounds ..........   Passed    0.01 sec
      Start 70: random_int_range_empty
70/81 Test #70: random_int_range_empty ...........   Passed    0.01 sec
      Start 71: random_float01_bounds
71/81 Test #71: random_float01_bounds ............   Passed    0.01 sec
      Start 72: env_get_hit
72/81 Test #72: env_get_hit ......................   Passed    0.01 sec
      Start 73: env_get_miss
73/81 Test #73: env_get_miss .....................   Passed    0.01 sec
      Start 74: env_has_true
74/81 Test #74: env_has_true .....................   Passed    0.01 sec
      Start 75: env_has_false
75/81 Test #75: env_has_false ....................   Passed    0.01 sec
      Start 76: hash_deterministic
76/81 Test #76: hash_deterministic ...............   Passed    0.01 sec
      Start 77: hash_distinct
77/81 Test #77: hash_distinct ....................   Passed    0.01 sec
      Start 78: hash_nonnegative
78/81 Test #78: hash_nonnegative .................   Passed    0.01 sec
      Start 79: hash_empty_string
79/81 Test #79: hash_empty_string ................   Passed    0.01 sec
      Start 80: lsp_json
80/81 Test #80: lsp_json .........................   Passed    0.01 sec
      Start 81: build_cache_key
81/81 Test #81: build_cache_key ..................   Passed    0.02 sec

100% tests passed, 0 tests failed out of 81

Total Test time (real) =   1.16 sec 81/81 pass (incl.
resolver_component + resolver_reuse); build/ ctest resolver 2/2. Production code
unchanged, so the behavior-neutral gates (run_tests 240/0 + 233/0, test_codegen
168/0, --leak-check 168/0, test_lsp 63/0, test_build) are unaffected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants