While auditing every ```wfl code block in Docs/ (new harness scripts/test_docs_code_blocks.py, see TestPrograms/docs_examples/DOC_CODE_AUDIT.md), several constructs turned up that read like perfectly natural WFL and appear throughout the docs, but do not work on the release interpreter (26.7.9). Most doc failures were plain syntax drift and are being fixed in the docs; the items below are language-side rough edges worth a maintainer decision (implement the feature, or make the docs stop teaching it). All repros verified against target/release/wfl.
High severity
1. Arithmetic binds looser than comparison inside conditions
The most natural conditional a beginner writes fails to type-check:
store y as 3
check if y plus 1 is equal to 4:
display "yes"
end check
→ error: Condition must be a boolean expression - Expected Boolean but found Number
It parses as y plus (1 is equal to 4). Affects plus, minus, times, divided by, and %. Workaround: parenthesize the arithmetic, (y plus 1) is equal to 4.
2. of-call binds tighter than arithmetic → breaks recursion
display fibonacci of n minus 1
parses as (fibonacci of n) minus 1, so a recursive argument never decreases (non-termination / type error). Workaround: fibonacci of (n minus 1). Combined with #1, the precedence of of-calls vs. arithmetic vs. comparison needs a coherent, documented ladder.
3. / division operator fails to lex
→ Lexing error at position N: unexpected input /``. +, `-`, `*`, `%` all work as symbols; only `/` does not (presumably because `//` starts a comment). `divided by` works. The operator reference lists `/` as valid.
4. finally is not implemented
The docs described a full try/catch/finally, but there is no finally token/parser branch — finally: is read as an undefined variable. Only cleanup placed after end try works. (Note otherwise: is not a finally: it is a fallback for error types no when clause matched, and never runs on success.)
Medium severity
5. between is unusable outside pattern quantifiers
between is a reserved keyword but only wired into pattern quantifiers. Both of these — used in the docs — fail with Unexpected token in expression: KeywordBetween:
check if x is between 1 and 10: -- range check
store d as random int between 1 and 6 -- random in range
Real forms today: two comparisons and-ed together; random_int of 1 and 6.
6. repeat N times is not supported
repeat 3 times:
display "hi"
end repeat
→ Expected 'while', 'until', 'forever', or ':' after 'repeat' (collides with the times multiply operator). Workaround: count from 1 to 3:.
7. is above / is below are lexed but not parsed
above/below are keywords (lexer comment: // e.g., "is above 100") but the expression parser rejects temperature is above 30 with Unexpected token in expression: KeywordAbove. Only is greater than / is less than work.
8. No word form for modulo, and no text→number conversion
12 modulo 4 → Variable 'modulo' is not defined (only %). Separately, convert text to number doesn't parse and no to_number/parse builtin exists — yet the type checker's own hint says "Try converting the text to a number using 'convert to number'." Both fight the natural-language / minimize-special-characters principles.
9. Caught-error binding: only implicit error_message works
when error: binds an implicit error_message (single identifier) which works. But the natural binding form when error as e: is a parse error (Expected ':' after error type), and the two-word error message fails (Variable 'message' is not defined).
Lower severity / inference gaps
- Action/function return-type inference often yields
Nothing. define action called double with parameters n: return n times 2 end action then double of 5 minus 1 → Cannot perform Minus operation on Nothing and Number. Untyped params defeat inference.
- Type-safety gap: docs promise
Number plus Text is a compile error, but display age plus name (25, "Alice") silently prints 25Alice.
- Action parameters are immutable:
change x to x plus 10 on a param → Cannot modify constant 'x'.
- Zero-arg action reference in a boolean condition is evaluated eagerly (no short-circuit) and type-errors as
Function() -> ….
list files … as <var> inline binding doesn't parse though store <var> as list files in "." does.
- Web-server example: the release binary leaves an orphaned server process holding the port after its parent is killed on timeout (
Address already in use for later runs).
Filed from a documentation code-examples audit; the docs themselves are being corrected to the working forms in branch claude/docs-code-examples-audit-c9xzl9. Deciding these at the language level (vs. documenting the workarounds) affects WFL's "no-unlearning" natural-language promise, since each of the above is the form a beginner reaches for first.
While auditing every
```wflcode block inDocs/(new harnessscripts/test_docs_code_blocks.py, seeTestPrograms/docs_examples/DOC_CODE_AUDIT.md), several constructs turned up that read like perfectly natural WFL and appear throughout the docs, but do not work on the release interpreter (26.7.9). Most doc failures were plain syntax drift and are being fixed in the docs; the items below are language-side rough edges worth a maintainer decision (implement the feature, or make the docs stop teaching it). All repros verified againsttarget/release/wfl.High severity
1. Arithmetic binds looser than comparison inside conditions
The most natural conditional a beginner writes fails to type-check:
→
error: Condition must be a boolean expression - Expected Boolean but found NumberIt parses as
y plus (1 is equal to 4). Affectsplus,minus,times,divided by, and%. Workaround: parenthesize the arithmetic,(y plus 1) is equal to 4.2.
of-call binds tighter than arithmetic → breaks recursionparses as
(fibonacci of n) minus 1, so a recursive argument never decreases (non-termination / type error). Workaround:fibonacci of (n minus 1). Combined with #1, the precedence ofof-calls vs. arithmetic vs. comparison needs a coherent, documented ladder.3.
/division operator fails to lex→
Lexing error at position N: unexpected input/``.+, `-`, `*`, `%` all work as symbols; only `/` does not (presumably because `//` starts a comment). `divided by` works. The operator reference lists `/` as valid.4.
finallyis not implementedThe docs described a full try/catch/finally, but there is no
finallytoken/parser branch —finally:is read as an undefined variable. Only cleanup placed afterend tryworks. (Noteotherwise:is not a finally: it is a fallback for error types nowhenclause matched, and never runs on success.)Medium severity
5.
betweenis unusable outside pattern quantifiersbetweenis a reserved keyword but only wired into pattern quantifiers. Both of these — used in the docs — fail withUnexpected token in expression: KeywordBetween:Real forms today: two comparisons
and-ed together;random_int of 1 and 6.6.
repeat N timesis not supported→
Expected 'while', 'until', 'forever', or ':' after 'repeat'(collides with thetimesmultiply operator). Workaround:count from 1 to 3:.7.
is above/is beloware lexed but not parsedabove/beloware keywords (lexer comment:// e.g., "is above 100") but the expression parser rejectstemperature is above 30withUnexpected token in expression: KeywordAbove. Onlyis greater than/is less thanwork.8. No word form for modulo, and no text→number conversion
12 modulo 4→Variable 'modulo' is not defined(only%). Separately,convert text to numberdoesn't parse and noto_number/parse builtin exists — yet the type checker's own hint says "Try converting the text to a number using 'convert to number'." Both fight the natural-language / minimize-special-characters principles.9. Caught-error binding: only implicit
error_messageworkswhen error:binds an impliciterror_message(single identifier) which works. But the natural binding formwhen error as e:is a parse error (Expected ':' after error type), and the two-worderror messagefails (Variable 'message' is not defined).Lower severity / inference gaps
Nothing.define action called double with parameters n: return n times 2 end actionthendouble of 5 minus 1→Cannot perform Minus operation on Nothing and Number. Untyped params defeat inference.Number plus Textis a compile error, butdisplay age plus name(25, "Alice") silently prints25Alice.change x to x plus 10on a param →Cannot modify constant 'x'.Function() -> ….list files … as <var>inline binding doesn't parse thoughstore <var> as list files in "."does.Address already in usefor later runs).Filed from a documentation code-examples audit; the docs themselves are being corrected to the working forms in branch
claude/docs-code-examples-audit-c9xzl9. Deciding these at the language level (vs. documenting the workarounds) affects WFL's "no-unlearning" natural-language promise, since each of the above is the form a beginner reaches for first.