lib/strings+test: Hare port (dup/concat/trim/index/contains/has{pre,suf}fix/compare/utf8)
Hare-faithful index/predicate family per ref/hare/strings/{dup,
concat,trim,index,suffix,contains,compare,utf8}.ha. Non-variadic
subset (concat 2-arg, trim single-rune, contains single-needle)
pending task #16 — cstage variadic-pack drops .len on multi-field
element types; ship the Hare-faithful single-arg shape now, file
the variadic upgrade as follow-up. `sub` follow-up filed as #29
(commit 2 with iterator + utf8.chars relocation).
Surface: dup, concat, trim/trimprefix/trimsuffix (single rune),
hasprefix, hassuffix (both with (str|rune) sum needle),
byteindex, rbyteindex (both with (str|rune) sum needle),
contains (single str needle), compare, toutf8, fromutf8_unsafe,
runebytes helper. (str|rune) match arms route the rune via
utf8.encoderune into a [4]u8 scratch then bytes.index/rindex —
drew-devault's directive for clean Hare-fidelity over invented
ASCII-only rune-byte arms.
byteindex / rbyteindex rune-arm semantic correction —
corpus-coverage-blind unmask. Pre-existing impl scanned for
`r: u8` (broken for all rune values >0x7F since strings.ww first
landed; no caller exercised it). Replaced with utf8.encoderune-
based scan via runebytes helper. Severity-marker: silent
wrong-result for any non-ASCII rune needle, masked by zero
in-tree callers until lib/strings + utf8 chain pulled the shape
in.
Build-system propagation: lib/strings depends transitively on
lib/encoding/utf8 (via byteindex's rune arm). cmd/ww driver's
locate_import_in (cmd/ww/main.c:85) walks `<dir>/<name>.ww` and
`<dir>/<name>/<name>.ww` only — `use utf8;` doesn't find
lib/encoding/utf8/utf8.ww without explicit `-I lib/encoding/utf8`.
Propagated through 5 wwstage-tool Makefile targets + 7 test
wrappers + test/wcc/995_self_rebuild.c sprintf lines. Task #17
filed for the principled resolver fix (subdir walk vs Hare's
qualified `use encoding::utf8;` notation).
This commit chain (#15 strings) surfaced 7 cgen bugs during
landing: #16 cstage variadic-pack, #17 resolver nested-paths,
#27 aliaslookup leaf-collision, #22 zero-init !void/void-alias
let-decl, #15-cstage retscr SSoT name, #24 composite CALL return
as composite arg, #28 N_DOT calleeparams. All blocking ones
fixed (#16/#17 deferred-with-stopgap, others fixed in their
respective commits). Pre-flight + stop-and-surface discipline
held throughout — no workarounds shipped in stdlib.
Tests:
- 966_strings_run drives lib/strings/stringstest.ww via ww run.
15 @test fns: dup (alloc, multibyte), concat (empty, lopsided,
multibyte), trim/ltrim/rtrim incl. 4-byte rune U+1D68A,
hasprefix/hassuffix with (str|rune) incl. multibyte,
byteindex/rbyteindex both arms 1/2/3/4-byte rune coverage,
compare. Cited from ref/hare/strings/+test.ha where vectors
apply.
100/100 ok. 995_self_rebuild stays green (ww2==ww3==ww4 byte-id).
This commit is contained in:
@@ -1748,8 +1748,14 @@ main(void)
|
||||
char tmpdir[64];
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/wwe2e_%d_d_%d", getpid(), i);
|
||||
mkdir(tmpdir, 0755);
|
||||
snprintf(cmd, sizeof cmd, "cd %s && %s/ww build %s",
|
||||
tmpdir, bin, src);
|
||||
/* -I lib/encoding/utf8 for any fixture that pulls in fmt /
|
||||
* strconv / strings via `use` (transitive utf8.encoderune;
|
||||
* task #17). Unused -I is benign for fixtures that don't. */
|
||||
char cwd700[1024];
|
||||
if (getcwd(cwd700, sizeof cwd700) == NULL) { fail++; continue; }
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"cd %s && %s/ww build -I %s/lib/encoding/utf8 %s",
|
||||
tmpdir, bin, cwd700, src);
|
||||
if (runwait(cmd) != 0) { fail++; continue; }
|
||||
|
||||
char outbin[128];
|
||||
|
||||
55
test/wcc/966_strings_run.c
Normal file
55
test/wcc/966_strings_run.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 966_strings_run — execute the lib/strings @test fixture under the
|
||||
* C-side `ww run` driver and assert exit 0.
|
||||
*
|
||||
* Same thin-wrapper shape as 967_bytes_run / 968_utf8_run / 979_hex_run:
|
||||
* stringstest.ww carries its own `export fn main()` that drives the
|
||||
* @test fns and signals which case failed via the exit code.
|
||||
*
|
||||
* -I lib/encoding/utf8 is required because lib/strings.byteindex
|
||||
* encodes the rune-needle arm via utf8.encoderune; the import resolver
|
||||
* doesn't yet walk encoding/ subdirs (task #17).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static int
|
||||
runwait(const char *cmd)
|
||||
{
|
||||
int rc = system(cmd);
|
||||
if (rc == -1) return -1;
|
||||
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const char *bin = getenv("BIN");
|
||||
if (!bin) bin = "out/bin";
|
||||
char absbin[1024];
|
||||
if (bin[0] != '/') {
|
||||
char cwd[1024];
|
||||
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
|
||||
snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin);
|
||||
bin = absbin;
|
||||
}
|
||||
char cwd[1024];
|
||||
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
|
||||
|
||||
const char *src = "lib/strings/stringstest.ww";
|
||||
char path[1024], cmd[2048];
|
||||
snprintf(path, sizeof path, "%s/%s", cwd, src);
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/ww run -I %s/lib/encoding/utf8 %s",
|
||||
bin, cwd, path);
|
||||
int rc = runwait(cmd);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "strings_run FAIL: %s exited %d\n", src, rc);
|
||||
return 1;
|
||||
}
|
||||
printf("strings_run: %s ok\n", src);
|
||||
return 0;
|
||||
}
|
||||
@@ -41,7 +41,9 @@ main(void)
|
||||
const char *src = "lib/fmt/fmttest.ww";
|
||||
char path[1024], cmd[2048];
|
||||
snprintf(path, sizeof path, "%s/%s", cwd, src);
|
||||
snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, path);
|
||||
/* -I lib/encoding/utf8 — task #17 */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/ww run -I %s/lib/encoding/utf8 %s", bin, cwd, path);
|
||||
int rc = runwait(cmd);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "fmt_run FAIL: %s exited %d\n", src, rc);
|
||||
|
||||
@@ -41,7 +41,9 @@ main(void)
|
||||
const char *src = "lib/log/logtest.ww";
|
||||
char path[1024], cmd[2048];
|
||||
snprintf(path, sizeof path, "%s/%s", cwd, src);
|
||||
snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, path);
|
||||
/* -I lib/encoding/utf8 — task #17 */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/ww run -I %s/lib/encoding/utf8 %s", bin, cwd, path);
|
||||
int rc = runwait(cmd);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "log_run FAIL: %s exited %d\n", src, rc);
|
||||
|
||||
@@ -41,7 +41,9 @@ main(void)
|
||||
const char *src = "lib/fnmatch/fnmatchtest.ww";
|
||||
char path[1024], cmd[2048];
|
||||
snprintf(path, sizeof path, "%s/%s", cwd, src);
|
||||
snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, path);
|
||||
/* -I lib/encoding/utf8 — task #17 */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/ww run -I %s/lib/encoding/utf8 %s", bin, cwd, path);
|
||||
int rc = runwait(cmd);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "fnmatch_run FAIL: %s exited %d\n", src, rc);
|
||||
|
||||
@@ -40,7 +40,10 @@ main(void)
|
||||
const char *src = "lib/getopt/getopttest.ww";
|
||||
char path[1024], cmd[2048];
|
||||
snprintf(path, sizeof path, "%s/%s", cwd, src);
|
||||
snprintf(cmd, sizeof cmd, "%s/ww run %s", bin, path);
|
||||
/* -I lib/encoding/utf8: getopt -> strings -> utf8.encoderune
|
||||
* (task #17 — resolver doesn't yet walk encoding/ subdirs). */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/ww run -I %s/lib/encoding/utf8 %s", bin, cwd, path);
|
||||
int rc = runwait(cmd);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "getopt_run FAIL: %s exited %d\n", src, rc);
|
||||
|
||||
@@ -99,9 +99,11 @@ probe_smoke(const char *bin)
|
||||
snprintf(tmpdir, sizeof tmpdir, "/tmp/wwsh_%d", getpid());
|
||||
mkdir(tmpdir, 0755);
|
||||
char cmd[2048];
|
||||
/* -I lib/encoding/utf8: smoke.ww uses strconv -> strings ->
|
||||
* utf8.encoderune (task #17 — resolver doesn't walk encoding/). */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"cd %s && %s/ww build %s/selfhost/test/smoke.ww >/dev/null 2>&1",
|
||||
tmpdir, bin, cwd);
|
||||
"cd %s && %s/ww build -I %s/lib/encoding/utf8 %s/selfhost/test/smoke.ww >/dev/null 2>&1",
|
||||
tmpdir, bin, cwd, cwd);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "smoke FAIL: ww build did not succeed\n");
|
||||
return -1;
|
||||
@@ -743,8 +745,8 @@ probe_ww_links(const char *bin)
|
||||
runwait(cmd);
|
||||
/* ww build to get the .combined.ww as a side effect. */
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"cd %s && %s/ww build -I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse -I %s/selfhost/cmd/wcc %s >/dev/null 2>&1",
|
||||
tmpdir, bin, cwd, cwd, cwd, cwd, tmpsrc);
|
||||
"cd %s && %s/ww build -I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse -I %s/lib/encoding/utf8 -I %s/selfhost/cmd/wcc %s >/dev/null 2>&1",
|
||||
tmpdir, bin, cwd, cwd, cwd, cwd, cwd, tmpsrc);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "ww-links FAIL: ww build %s\n", fix);
|
||||
fail++;
|
||||
|
||||
@@ -150,8 +150,8 @@ main(void)
|
||||
static char wwdump_src[2048], wwdump_incs[4096];
|
||||
snprintf(wwdump_src, sizeof wwdump_src, "%s/selfhost/cmd/wwdump/main.ww", cwd);
|
||||
snprintf(wwdump_incs, sizeof wwdump_incs,
|
||||
"%s/lib/ww:%s/lib/ww/lex:%s/lib/ww/parse:%s/selfhost/cmd/wcc",
|
||||
cwd, cwd, cwd, cwd);
|
||||
"%s/lib/ww:%s/lib/ww/lex:%s/lib/ww/parse:%s/lib/encoding/utf8:%s/selfhost/cmd/wcc",
|
||||
cwd, cwd, cwd, cwd, cwd);
|
||||
cases[1].src = wwdump_src;
|
||||
cases[1].incs = wwdump_incs;
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ slurp_eq(const char *a, const char *b)
|
||||
/* Each tool builds via `ww_ww build -I <local> -I lib/ww -I selfhost/cmd/wcc src`.
|
||||
* lib/ww holds the language introspection (lex/tok/ast/parse/typ/sym);
|
||||
* selfhost/cmd/wcc holds the compiler internals (mem/check/cgen*).
|
||||
* lib/encoding/utf8 carries the rune codec strings.byteindex needs;
|
||||
* the import resolver doesn't yet walk encoding/ subdirs (task #17),
|
||||
* so the dep travels as an explicit -I until it does.
|
||||
* Some tools have a local module dir (w6a, w6l with sibling .ww files).
|
||||
* inc_local is "" for tools without one (w6c, ww, wwdump).
|
||||
*/
|
||||
@@ -77,14 +80,14 @@ rebuild_one(const char *bin, const char *cwd, const char *tool,
|
||||
|
||||
if (inc_local && inc_local[0]) {
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"cd %s && %s/ww_ww build -I %s/%s -I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse -I %s/selfhost/cmd/wcc "
|
||||
"cd %s && %s/ww_ww build -I %s/%s -I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse -I %s/lib/encoding/utf8 -I %s/selfhost/cmd/wcc "
|
||||
"%s/%s >/dev/null 2>&1",
|
||||
workdir, bin, cwd, inc_local, cwd, cwd, cwd, cwd, cwd, src_rel);
|
||||
workdir, bin, cwd, inc_local, cwd, cwd, cwd, cwd, cwd, cwd, src_rel);
|
||||
} else {
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"cd %s && %s/ww_ww build -I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse -I %s/selfhost/cmd/wcc "
|
||||
"cd %s && %s/ww_ww build -I %s/lib/ww -I %s/lib/ww/lex -I %s/lib/ww/parse -I %s/lib/encoding/utf8 -I %s/selfhost/cmd/wcc "
|
||||
"%s/%s >/dev/null 2>&1",
|
||||
workdir, bin, cwd, cwd, cwd, cwd, cwd, src_rel);
|
||||
workdir, bin, cwd, cwd, cwd, cwd, cwd, cwd, src_rel);
|
||||
}
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "self-rebuild FAIL: ww_ww build errored on %s\n", tool);
|
||||
|
||||
Reference in New Issue
Block a user