Summary
replace <pattern> with <text> in <text> silently returns the input unchanged — it parses, type-checks, runs, exits 0, and produces a wrong answer with no diagnostic.
Reproduction
create pattern w:
"world"
end pattern
store s as "hello world world"
display "[" with (replace w with "there" in s) with "]"
Command:
wfl d1_pattern_replace_noop.wfl
Expected
[hello there there].
replace is documented as the pattern-replacement keyword in
Docs/reference/keyword-reference.md:155 (| replace | Pattern replacement | ✗ |),
and the expression form is a first-class production in the parser
(src/parser/expr/primary.rs:1218-1238 and src/parser/expr/binary.rs:648-665),
the analyzer, the type checker, and the interpreter
(src/interpreter/mod.rs:14628).
Actual
Exit code: 0. No warning, no error, no diagnostic on stderr.
Root cause: native_pattern_replace validates all three arguments and then discards them.
// src/stdlib/pattern.rs:214-262
pub fn native_pattern_replace(args: Vec<Value>, line: usize, column: usize) -> Result<Value, RuntimeError> {
...
let _pattern = ...; // validated, then unused
let _replacement = ...; // validated, then unused
// TODO: Update to use new pattern system for replacement
Ok(Value::Text(Arc::from(text)))
}
Passing a Text where the Pattern is expected does fail loudly
(Second argument must be a pattern), so the failure is specific to the
supported, documented form.
Compounding problem — the literal string replace is unreachable from WFL source.
A working 3-argument literal replace exists and is unit-tested
(native_replace, src/stdlib/text.rs:435, tests at :456-472), but replace
lexes as Token::KeywordReplace and the parser only accepts the
<pattern> with <x> in <y> shape:
display replace of s and "world" and "there"
=> error[ERROR]: Unexpected token in expression: KeywordOf (exit 2)
The repository already documents this dead end in a test comment:
// TestPrograms/stdlib_comprehensive.wfl:95-96
// Note: string replace() is a native function but 'replace' keyword is reserved
// for pattern replacement. String replace is tested in Rust unit tests.
So today WFL has no reachable string-replacement operation at all: the pattern
form silently no-ops, and the literal form cannot be called. The documented
workaround shape is join of (split <text> by <needle>) and <replacement>.
Environment
- wfl --version:
WebFirst Language (WFL) version 26.8.4
- binary: system install
C:\Program Files\wfl\bin\wfl.exe
- commit: c277d8f
- OS: Windows 11 Pro 10.0.26200
- build: release
Also reproduces identically on the repo build G:\repos\wfl\target\release\wfl.exe
(version 26.8.2), so this is not a regression — it is long-standing.
No .wflcfg in scope for the repro.
Context
Found while porting G:/repos/JShrink/src/JShrink/Minifier.php (a 738-line PHP
JavaScript minifier) to WFL. JShrink's unlock() step is a literal str_replace
and its lock() step is a preg_replace with backreferences.
This one was encountered, not blocking: the port uses
join of (split src by needle) and replacement for the literal replace and a
pattern_find_all + rebuild loop for the backreference case, so no stub was left.
It is filed because of how it fails, not because it blocked us — a program that
reaches for the documented keyword gets a silently wrong result and a zero exit
status, which is the worst failure mode in the set. Separately, replacement with
capture-group backreferences ($1/$2) has no form at all; that is a distinct
enhancement, not part of this bug.
Summary
replace <pattern> with <text> in <text>silently returns the input unchanged — it parses, type-checks, runs, exits 0, and produces a wrong answer with no diagnostic.Reproduction
Command:
Expected
[hello there there].replaceis documented as the pattern-replacement keyword inDocs/reference/keyword-reference.md:155(|replace| Pattern replacement | ✗ |),and the expression form is a first-class production in the parser
(
src/parser/expr/primary.rs:1218-1238andsrc/parser/expr/binary.rs:648-665),the analyzer, the type checker, and the interpreter
(
src/interpreter/mod.rs:14628).Actual
Exit code: 0. No warning, no error, no diagnostic on stderr.
Root cause:
native_pattern_replacevalidates all three arguments and then discards them.Passing a Text where the Pattern is expected does fail loudly
(
Second argument must be a pattern), so the failure is specific to thesupported, documented form.
Compounding problem — the literal string
replaceis unreachable from WFL source.A working 3-argument literal replace exists and is unit-tested
(
native_replace,src/stdlib/text.rs:435, tests at:456-472), butreplacelexes as
Token::KeywordReplaceand the parser only accepts the<pattern> with <x> in <y>shape:The repository already documents this dead end in a test comment:
So today WFL has no reachable string-replacement operation at all: the pattern
form silently no-ops, and the literal form cannot be called. The documented
workaround shape is
join of (split <text> by <needle>) and <replacement>.Environment
WebFirst Language (WFL) version 26.8.4C:\Program Files\wfl\bin\wfl.exeAlso reproduces identically on the repo build
G:\repos\wfl\target\release\wfl.exe(version 26.8.2), so this is not a regression — it is long-standing.
No
.wflcfgin scope for the repro.Context
Found while porting
G:/repos/JShrink/src/JShrink/Minifier.php(a 738-line PHPJavaScript minifier) to WFL. JShrink's
unlock()step is a literalstr_replaceand its
lock()step is apreg_replacewith backreferences.This one was encountered, not blocking: the port uses
join of (split src by needle) and replacementfor the literal replace and apattern_find_all+ rebuild loop for the backreference case, so no stub was left.It is filed because of how it fails, not because it blocked us — a program that
reaches for the documented keyword gets a silently wrong result and a zero exit
status, which is the worst failure mode in the set. Separately, replacement with
capture-group backreferences (
$1/$2) has no form at all; that is a distinctenhancement, not part of this bug.