Summary
X ends with "…" and X starts with "…" do not work reliably in a check if
condition at statement level. The parser's multi-word–identifier rule absorbs the
operator keyword, lexing path ends with ".css" as the identifier path ends
followed by with ".css". The program then fails semantic analysis with
Variable 'path ends' is not defined (and analogously for starts).
There is no dedicated lexer token for these operators — the lexer only defines
KeywordContains (src/lexer/token.rs), not ends/starts — so they are not
parsed as operators at all in this position.
Reproduction (release build)
store path as "/style.css"
check if path ends with ".css":
display "css"
otherwise:
display "no"
end check
error[ANALYZE-SEMANTIC]: Variable 'path ends' is not defined
Same failure for check if path starts with "/style": → Variable 'path starts' is not defined.
contains works correctly as contains of X and Y, and the 3-argument
substring of X and 1 and length of X works; only the starts with / ends with
infix forms are affected.
Why this is easy to miss
Several existing programs contain these forms — e.g.
TestPrograms/comprehensive_web_server_demo.wfl uses both
request_path starts with "/static/" and file_path ends with ".css". They pass
--parse and survive --analyze (which is lenient here), so they look supported,
but they fault under the full pipeline. The forms also appear in user-facing docs.
Impact
- Prefix/suffix string matching — a very common need, especially for web-server
request routing — silently breaks or misleads users.
- Docs and demo programs imply these operators work when they do not end-to-end.
Suggested fix
Give starts with / ends with real operator support — either dedicated
KeywordStartsWith / KeywordEndsWith tokens, or a proper infix parse that binds
before multi-word identifier accumulation — mirroring how contains is handled.
Add TestPrograms covering both operators under the full pipeline so regressions are
caught (the current demo usages only exercise --analyze).
Notes
Found while drafting the route construct design (PR #565), where prefix/suffix
when heads depend on these operators. Context and validated interim workarounds
are documented in Docs/development/route-construct-design.md.
Summary
X ends with "…"andX starts with "…"do not work reliably in acheck ifcondition at statement level. The parser's multi-word–identifier rule absorbs the
operator keyword, lexing
path ends with ".css"as the identifierpath endsfollowed by
with ".css". The program then fails semantic analysis withVariable 'path ends' is not defined(and analogously forstarts).There is no dedicated lexer token for these operators — the lexer only defines
KeywordContains(src/lexer/token.rs), notends/starts— so they are notparsed as operators at all in this position.
Reproduction (release build)
Same failure for
check if path starts with "/style":→Variable 'path starts' is not defined.containsworks correctly ascontains of X and Y, and the 3-argumentsubstring of X and 1 and length of Xworks; only thestarts with/ends withinfix forms are affected.
Why this is easy to miss
Several existing programs contain these forms — e.g.
TestPrograms/comprehensive_web_server_demo.wfluses bothrequest_path starts with "/static/"andfile_path ends with ".css". They pass--parseand survive--analyze(which is lenient here), so they look supported,but they fault under the full pipeline. The forms also appear in user-facing docs.
Impact
request routing — silently breaks or misleads users.
Suggested fix
Give
starts with/ends withreal operator support — either dedicatedKeywordStartsWith/KeywordEndsWithtokens, or a proper infix parse that bindsbefore multi-word identifier accumulation — mirroring how
containsis handled.Add TestPrograms covering both operators under the full pipeline so regressions are
caught (the current demo usages only exercise
--analyze).Notes
Found while drafting the
routeconstruct design (PR #565), where prefix/suffixwhenheads depend on these operators. Context and validated interim workaroundsare documented in
Docs/development/route-construct-design.md.