From 267db2cd91f840bc2ec43309108818e3ce8742d1 Mon Sep 17 00:00:00 2001
From: Joseph Ferano
Date: Sat, 26 Sep 2026 05:18:29 +0700
Subject: [PATCH 1/3] The typed read-only text type is spelled str, and string
is refused with that fix.
---
TODO.org | 6 +-
calc-me.flan | 2 +-
docs/BUILT.md | 38 ++---
docs/PORTING.md | 22 +--
emacs/MANUAL.md | 14 +-
emacs/flan-cnr.el | 2 +-
emacs/flan-fln-mode.el | 2 +-
emacs/flan-mode.el | 10 +-
emacs/test-flan-cider.el | 22 +--
emacs/test-flan-mode.el | 4 +-
examples/core-input-gestures-testbed.flan | 4 +-
examples/core-input-gestures.flan | 4 +-
examples/core-input-multitouch.flan | 2 +-
examples/core-input-virtual-controls.flan | 2 +-
examples/core-window-flags.flan | 2 +-
examples/digits.flan | 4 +-
examples/text-codepoints-loading.flan | 2 +-
examples/text-input-box.flan | 2 +-
examples/text-rectangle-bounds.flan | 2 +-
examples/text-writing-anim.flan | 2 +-
examples/textures-image-processing.flan | 2 +-
lib/ast.ml | 2 +-
lib/check.ml | 84 ++++++-----
lib/cimport.ml | 18 +--
lib/emit.ml | 4 +-
lib/js.ml | 8 +-
lib/parse.ml | 6 +-
lib/prelude.ml | 40 +++---
lib/render.ml | 2 +-
lib/shim.ml | 16 +--
lib/tast.ml | 2 +-
lib/types.ml | 8 +-
runtime/flan_dyn.c | 2 +-
spec-conditions.md | 2 +-
spec-memory.md | 2 +-
syntax-sketch.flan | 16 +--
test/programs/agent-queue.flan | 2 +-
test/programs/agent.flan | 2 +-
test/programs/algorithms.flan | 4 +-
test/programs/arena-region.flan | 2 +-
test/programs/arena-value.flan | 6 +-
test/programs/arith-condition.flan | 2 +-
test/programs/arith.flan | 2 +-
test/programs/bounds-condition.flan | 2 +-
test/programs/bounds.flan | 2 +-
test/programs/builtin-qualified.flan | 2 +-
test/programs/bytes-copy.flan | 6 +-
test/programs/bytes-view-write.flan | 2 +-
test/programs/bytes2.flan | 2 +-
test/programs/chain.flan | 4 +-
test/programs/condition-longmessage.flan | 2 +-
test/programs/condition-messages.flan | 2 +-
test/programs/condition-temp.flan | 2 +-
test/programs/const-slice.flan | 8 +-
test/programs/context-destroyed.flan | 2 +-
test/programs/cstr-return.flan | 4 +-
test/programs/datas.flan | 6 +-
test/programs/debug-permuted.flan | 2 +-
test/programs/debug.flan | 2 +-
test/programs/destroy-region.flan | 2 +-
test/programs/destructure.flan | 2 +-
test/programs/dev-globals.flan | 2 +-
test/programs/dev-locals.flan | 2 +-
test/programs/dev-macro.flan | 2 +-
test/programs/dev-parity.flan | 2 +-
test/programs/dev-temp-destroy.flan | 2 +-
test/programs/dev-temp-stop.flan | 2 +-
test/programs/dev-watch.flan | 8 +-
test/programs/dyn-class-slots.flan | 2 +-
test/programs/dyn-held-operand.flan | 2 +-
test/programs/dyn-index-site.flan | 2 +-
test/programs/dyn-slice.flan | 2 +-
test/programs/dyn-slot-trap.flan | 2 +-
test/programs/dyn-type-of.flan | 2 +-
test/programs/dyn-view.flan | 2 +-
test/programs/edn-provide.flan | 4 +-
test/programs/edn-read.flan | 4 +-
test/programs/edn.flan | 8 +-
test/programs/embed.flan | 6 +-
test/programs/enum-convert.flan | 2 +-
test/programs/fn-cfn-table.flan | 6 +-
test/programs/fn-escape.flan | 2 +-
test/programs/fn-in-map.flan | 2 +-
test/programs/format.flan | 4 +-
test/programs/frame-rollback.flan | 2 +-
test/programs/free-slice.flan | 4 +-
test/programs/int-float.flan | 4 +-
test/programs/json.flan | 18 +--
test/programs/limits.flan | 2 +-
test/programs/macro-loc-literal.flan | 2 +-
test/programs/macro-unless.flan | 2 +-
test/programs/map-array-key.flan | 10 +-
test/programs/map-exhausted.flan | 2 +-
test/programs/map-iter.flan | 2 +-
test/programs/map-keys.flan | 4 +-
test/programs/map-remove.flan | 2 +-
test/programs/maps.flan | 4 +-
test/programs/match-bool.flan | 4 +-
test/programs/match-enum.flan | 2 +-
test/programs/match-literal.flan | 6 +-
test/programs/pkg-data.flan | 2 +-
test/programs/pkgs/cret/cret.flan | 6 +-
test/programs/prelude-macros.flan | 2 +-
test/programs/printers.flan | 2 +-
test/programs/println.flan | 4 +-
test/programs/raylib-audio.flan | 6 +-
test/programs/raylib-codepoints.flan | 4 +-
test/programs/raylib-ffi.flan | 4 +-
test/programs/raylib-font.flan | 8 +-
test/programs/raylib-image-processing.flan | 10 +-
test/programs/raylib-image.flan | 8 +-
test/programs/restarts.flan | 6 +-
test/programs/shadow-builtin.flan | 2 +-
test/programs/shim-literal.flan | 8 +-
test/programs/shim-nul-end.flan | 8 +-
test/programs/shim-nul.flan | 4 +-
test/programs/slices.flan | 2 +-
test/programs/slurp.flan | 12 +-
test/programs/string-eq.flan | 4 +-
test/programs/string-of-bytes.flan | 26 ++--
test/programs/strings.flan | 8 +-
test/programs/temp-agent.flan | 4 +-
test/programs/temp-frame.flan | 6 +-
test/programs/trial-generic.flan | 2 +-
test/programs/two-numbers.flan | 22 +--
test/programs/vec-new-type.flan | 2 +-
test/programs/web-files.flan | 2 +-
test/programs/widening.flan | 2 +-
test/programs/x86-p11-reversed-slice.flan | 2 +-
test/programs/x86-p12-handler-value.flan | 4 +-
test/programs/x86-p7-slice-from.flan | 2 +-
test/syntax/algorithms.flan | 18 +--
test/syntax/algorithms.fln | 18 +--
test/syntax/handwritten/csv.fln | 14 +-
test/syntax/handwritten/inventory.fln | 6 +-
test/syntax/handwritten/rpn.fln | 8 +-
test/syntax/handwritten/stock/stock.fln | 4 +-
test/syntax/handwritten/traffic.fln | 2 +-
test/syntax/handwritten/words.fln | 12 +-
test/test_acceptance.ml | 34 ++---
test/test_dev.ml | 22 +--
test/test_flan.ml | 154 ++++++++++++---------
test/test_sanitize.ml | 2 +-
test/test_session.ml | 2 +-
vendor/agent/agent.flan | 4 +-
vendor/edn/edn.flan | 6 +-
vendor/edn/provide.flan | 54 ++++----
vendor/edn/read.flan | 8 +-
vendor/json/json.flan | 6 +-
vendor/json/provide.flan | 48 +++----
vendor/raylib/generated.flan | 126 ++++++++---------
vendor/raylib/raylib.flan | 54 ++++----
web/examples/control.flan | 2 +-
web/examples/enums.flan | 2 +-
web/examples/places.flan | 2 +-
web/examples/printing.flan | 2 +-
web/index.html | 24 ++--
157 files changed, 717 insertions(+), 679 deletions(-)
diff --git a/TODO.org b/TODO.org
index a192e5df..fd77cf02 100644
--- a/TODO.org
+++ b/TODO.org
@@ -12,8 +12,8 @@ rejected without a record is an idea that gets re-proposed.
* Language surface
** NEXT str and String
-Decided 2026-09-25: the typed read-only text is =str= (renamed from =string=); =String=
-is new, owned, growable, always valid UTF-8, through an allocator. The prelude's text
+Decided 2026-09-25: the typed read-only text is =str= (the rename from =string= is
+done; =string= is refused with the fix); =String= is new, owned, growable, always valid UTF-8, through an allocator. The prelude's text
builders return =String=; =(Vec u8)= stays for raw bytes. Text is UTF-8 everywhere and
a character is a code point; dyn gets a character tag, so \\I prints as \\I.
Dyn text stays immutable, with chars and text converting to and from a dyn
@@ -2086,7 +2086,7 @@ an unannotated two-name parameter vector compiles as two dyn parameters, and a
=defn= named after a builtin stopped being unreachable.
** WAIT Every diagnostic carries a stable kind at the end of its first line
-Decided 2026-09-25: wanted, in the shape =... found string [type-mismatch]=. Waits
+Decided 2026-09-25: wanted, in the shape =... found str [type-mismatch]=. Waits
for the documentation rewrite, which is what a kind would link to. The clause
order — understood, then the conflict, then the fix — is a rule in =CLAUDE.md=,
and reporting every error in a form is its own entry under the Editor heading.
diff --git a/calc-me.flan b/calc-me.flan
index 78d66745..11c51c5b 100644
--- a/calc-me.flan
+++ b/calc-me.flan
@@ -118,7 +118,7 @@
;; print and println are compiler-provided and structural: the walk over the
;; argument's concrete type happens at compile time, so there is nothing to
;; dispatch on at run time and no type to name at the call site.
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(if (< (length args) 2)
(do (println "usage: calc-me \"1 + 2 * 3\"") 1)
(match (evaluate (bytes-view (at args 1)))
diff --git a/docs/BUILT.md b/docs/BUILT.md
index 04774e78..c1cf78c2 100644
--- a/docs/BUILT.md
+++ b/docs/BUILT.md
@@ -676,8 +676,8 @@ exercised by running `sand.flan` and looking, which is the whole of what can be
### A string returned from C is copied into the context allocator
-A `declare-c` may return `string`. The C wrapper answers the pointer and its length, and the generated Flan wrapper is
-`(string (bytes (string (slice-from-ptr p n))))`: a view of C's bytes, copied by `bytes` into the context allocator. The
+A `declare-c` may return `str`. The C wrapper answers the pointer and its length, and the generated Flan wrapper is
+`(str (bytes (str (slice-from-ptr p n))))`: a view of C's bytes, copied by `bytes` into the context allocator. The
copy is Flan's rather than C's so that it goes through the same allocation guard (`StorageExhausted` with `retry`) and
the same registry note every other allocation does, and `with-allocator` picks where it lands. The string lives until
that allocator's `free-all` or destroy, which is the lifetime `(bytes s)` already has; a caller calling one every frame
@@ -689,7 +689,7 @@ in that case the wrapper first moves the text into one scratch buffer the shim o
there. Without a string argument the pointer is the library's own and nothing is moved twice. A null is the empty
string.
-The importer follows `const`. `const char *` returned is text the caller only reads, so it becomes `string`; `char *`
+The importer follows `const`. `const char *` returned is text the caller only reads, so it becomes `str`; `char *`
without `const` is text the caller owns and releases through the library (`LoadFileText` and `UnloadFileText`), and a
copy would leave the original with nothing to release it through, so that one stays refused and a hand-written
`declare-c` saying `(Ptr u8)` binds it. `TextFormat` stays unbound because it is variadic. Eighteen raylib functions came
@@ -711,7 +711,7 @@ over a mesh built in Flan and a model translated by its `transform`.
`FilePathList` is a `char **` raylib owns until the matching `Unload`. It crosses by the returned-string rule:
`dropped-files`, `directory-files` and `directory-files-ex` copy each path into the context allocator, release raylib's
-list before returning, and answer a `(Vec string)`. There is nothing of raylib's left for the caller to unload, which is
+list before returning, and answer a `(Vec str)`. There is nothing of raylib's left for the caller to unload, which is
why they are not named `load-`.
### rlgl is its own package
@@ -1167,7 +1167,7 @@ i8..i64 / u8..u64 i8..i64 signedness lives in the ops
f32 f64 float double
bool i1
an enum i32
-[T] and string { ptr, i64 } ptr+len, non-owning
+[T] and str { ptr, i64 } ptr+len, non-owning
[n T] [n x T] inline, a value
(Ptr T) ptr opaque pointers
(Option T) { i8, T } tag 0 None, 1 Some
@@ -2962,7 +2962,7 @@ as the shape of the whole feature: the answer is a Flan expression, and there is
program.
**Lookup stayed by name, and the signature is checked against what it found.** `flan_find_restart` matches the name
-hash and nothing else, so an inner `(use-value [s string] ...)` shadows an outer `(use-value [v i32] ...)` and an i32
+hash and nothing else, so an inner `(use-value [s str] ...)` shadows an outer `(use-value [v i32] ...)` and an i32
is refused there — the outer frame that would have taken it is never consulted. That is §4 read straight ("the first
frame offering the name") and it is the thing a reader will assume works the other way, so `restarts.flan` has a case
for it. Searching outward for a frame whose signature fits would make which restart runs depend on the arguments,
@@ -3002,7 +3002,7 @@ function values and the work doubles.
None of the four is anywhere near this. All four are about *surface syntax*, and a value the compiler builds that no
surface form names trips none of them:
-- `Allocator` is a `Types.t` case with no user-writable constructor, the way `string` is a builtin ptr+len. No Flan
+- `Allocator` is a `Types.t` case with no user-writable constructor, the way `str` is a builtin ptr+len. No Flan
type names its procedure.
- The procedure is a C symbol the emitter names.
- `vec-new`, `push`, `free`, `free-all` and the rest are ordinary named calls, which `check_call` already routes
@@ -3564,7 +3564,7 @@ the payload at offset 8, and 40/8 for a struct holding one.
[Empty
(Dot [x f64 y f64])
(Rect [w i32 h i32])
- (Tag [name string n u8])])
+ (Tag [name str n u8])])
(Shape.Rect {.w 3 .h 3}) ; a value: the type and the case, then the fields
(Shape.Rect {.w 3}) ; ZII, exactly as in a struct literal — .h is 0
@@ -3614,7 +3614,7 @@ is a layout change, the same way reordering a struct's fields is.
- **`(.x u)`.** A union's fields belong to a case, and which case is being held is what the tag says. `match` is how
one is opened, and its arms bind the fields of the case they matched.
- **A global initialised with a case.** `(defonce g U (U.B {.x 1}))` would mean serialising the fields into the payload
- blob at link time, which is a byte-level encoder this compiler does not have and which could not express a `string`
+ blob at link time, which is a byte-level encoder this compiler does not have and which could not express a `str`
field at all — that is a pointer the linker has to relocate and a byte array has nowhere to put a relocation. A
*zeroed* global is fine and needs none of it: it is the first declared case.
@@ -3771,7 +3771,7 @@ macro returns. That is the structural answer to "keep the source location of the
produces", and it is what the queued structured-error work reads.
Case order is tag order, so the list in the prelude is a layout contract and says so. The widest cases are
-`(Str [s string])` and `(List [xs [Form]])`; a string and a slice are both `%slice` = `{ptr, i64}`, 16 bytes at
+`(Str [s str])` and `(List [xs [Form]])`; a string and a slice are both `%slice` = `{ptr, i64}`, 16 bytes at
align 8. So the image is `{ i32 tag, [2 x i64] payload }`: **24 bytes, align 8, payload at offset 8**, and every case
holds its one member at the payload's start, so there is no third offset anywhere in the marshaller.
@@ -4310,8 +4310,8 @@ be wrong in a way worth being able to see: the prelude *was* reaching the expand
The list at the foot of `prelude.ml` used to be one sentence — every entry needed to produce bytes that did not exist
in its input, and there was no allocator. `join`, `concat`, `split`, `to-lower`, `to-upper`, `repeat` and `replace`
-have moved up into the code; `string-from-bytes` turned out to be the `string` builtin all along, and
-`(string (slice v))` is the round trip, free precisely because the layouts are identical.
+have moved up into the code; `string-from-bytes` turned out to be the `str` builtin all along, and
+`(str (slice v))` is the round trip, free precisely because the layouts are identical.
What remains is refused for four different reasons, and is now written that way: `pad`/`center` for *nothing at all*
except that no caller has asked; `format`/`sprintf` for variadics of mixed type; `map`/`filter`/`reduce`/`sort-by`
@@ -4879,7 +4879,7 @@ and the rule is easier to state and to trust with one construct in it.
## Assets are baked in, and the reason it is a compiler feature
-TODO.org, "Assets are embedded at compile time". `(embed "brush.png")` is a `[const u8]`, `(embed "brush.png" string)` is a `string`, and
+TODO.org, "Assets are embedded at compile time". `(embed "brush.png")` is a `[const u8]`, `(embed "brush.png" str)` is a `str`, and
`(embed-dir "assets")` is a `[n EmbedFile]` sorted by name. Odin's `#load` and `#load_directory` are the model
(`src/parser.cpp`, and `check_load_directive` / `check_load_directory_directive` in `src/check_builtin.cpp`); Odin's
`#` is not imported, because an s-expression language already has a head position for a name and these resolve as
@@ -4897,16 +4897,16 @@ into the same `private unnamed_addr constant` every string literal already becom
across the whole 0–255 range, so a PNG survives the round trip through the `.ll`. Bound with `defconst` at top level an
`embed-dir` is an LLVM constant outright, through emit.ml's `const`.
-**A `Str` node typed `[const u8]`, not a `Bytes` prim over a `string`.** This is the one non-obvious choice. `Bytes` is
+**A `Str` node typed `[const u8]`, not a `Bytes` prim over a `str`.** This is the one non-obvious choice. `Bytes` is
identity — emit.ml lowers `Types.String` and `Types.Slice _` to the same `%slice` — but wrapping the literal in a prim
makes the node non-constant, and `const` then refuses an `embed-dir` in a `defconst` with *a global's value must be a
compile-time constant*. Both of emit.ml's string emitters take the bytes and ignore the node's type, so it is the same
constant either way and this one is a constant a global can hold.
**Two spellings, not one form that changes type with its context.** Odin threads a `type_hint` everywhere and can
-afford `#load("p")` to mean a `string` here and a `[]u8` there. With structural equality and no conversion between one
+afford `#load("p")` to mean a `str` here and a `[]u8` there. With structural equality and no conversion between one
container and another — implicit widening is numbers only — the same text meaning two types would be a wart, so
-`string` is written down when it is wanted. The
+`str` is written down when it is wanted. The
site's expectation is a fallback only and nothing depends on it.
**The path is a literal and resolves relative to the file the form is written in.** Both are Odin's rules and for
@@ -5702,7 +5702,7 @@ Measured on a 200-million-iteration loop at `-O2`: 0.53s with the call, 0.00s wi
Four entry points a program can reach through `declare-c` write a scalar:
```flan
-(declare-c watch-i64 [name string x i64] i32 "flan_dev_watch_i64")
+(declare-c watch-i64 [name str x i64] i32 "flan_dev_watch_i64")
(watch-i64 "ticks" ticks)
```
@@ -7079,7 +7079,7 @@ expression the checker walks can live.
### The rules it derives, and the one the game file decided
A map with keyword keys is a struct, one field per key. An integer is `i64`, a float
-`f64`, a boolean `bool`, a string `string` — *copied*, which is `read.flan`'s contract and
+`f64`, a boolean `bool`, a string `str` — *copied*, which is `read.flan`'s contract and
not the tokenizer's: a `Token`'s text points into the buffer and a struct that outlives
the buffer cannot hold one. A vector of one repeated shape is `(Vec T)`. A nested map is a
struct named for the path that reaches it, `Tileset-selected-cells`, with a hyphen because
@@ -7403,7 +7403,7 @@ it: an assignment that *completed* before the signal stands, and rolling those b
restart is not a transaction"). What no longer happens is a single assignment left halfway.
**A `def` whose type changed** is refused before anything is stored, by `Session.compatible`, which already said the
-right sentence for this path: *`speed` changes type, from `i64` to `string`; the running program already laid that
+right sentence for this path: *`speed` changes type, from `i64` to `str`; the running program already laid that
storage out. Restart to change it.*
**`defonce` is untouched**, and that is its contract: `kind = Once` never reaches the store list, so re-evaluating one
diff --git a/docs/PORTING.md b/docs/PORTING.md
index bd5fff1b..ca8adfb7 100644
--- a/docs/PORTING.md
+++ b/docs/PORTING.md
@@ -255,7 +255,7 @@ host does:
1. Hold the state in a `let` in `main` and pass `(Ptr Game)` to update and draw. Costs
one parameter on three functions.
2. For the texture cache specifically, a `[8 CacheEntry]` fixed array with a count beats a
- `(Map string Texture2D)` outright — the game loads five textures, and a linear scan of
+ `(Map str Texture2D)` outright — the game loads five textures, and a linear scan of
five path comparisons at load time is not worth a hash table. This is a case where the
restriction pushes toward the right answer.
@@ -692,7 +692,7 @@ each finding in §A names the command that produced the failure.
> differences it accepted. `vendor/raylib/raylib.flan` carries
> `get-codepoint-previous-raw` — the exact declaration this section says it wanted — and
> a `get-codepoint-previous` wrapper over it that takes the bytes and an offset;
-> `generated.flan` no longer carries the `string`-faced version at all, because a binding
+> `generated.flan` no longer carries the `str`-faced version at all, because a binding
> that is wrong for the only direction it reads in is worse than no binding. The example's
> `step-back` is one call to it, the continuation-byte walk is gone, and the expression
> below now prints 12356 and 3. The section is kept as written; the reasoning is the part
@@ -700,7 +700,7 @@ each finding in §A names the command that produced the failure.
This is the real find of the round, and it is general: **a C function that reads
-*backwards* from the pointer it is handed cannot be given a Flan `string`.**
+*backwards* from the pointer it is handed cannot be given a Flan `str`.**
`lib/shim.ml` is explicit about why — `Pstr` is "ptr+len in, a NUL-terminated copy out",
and the wrapper builds that copy for the duration of the call. Forwards, that is invisible
@@ -714,7 +714,7 @@ It does not crash, which is the bad part. Run headless:
(let [text "いろはに"
b (bytes text)
sz 0]
- (println (rl/get-codepoint-previous (string (slice b 3 (length b))) (addr sz)))
+ (println (rl/get-codepoint-previous (str (slice b 3 (length b))) (addr sz)))
(println sz))
```
@@ -735,15 +735,15 @@ and means it, as `load-image-from-memory-raw` and `load-font-ex-raw` do:
```
with `(addr (at b i))` for the interior pointer. It does not work, and the reason is not
-the FFI. `lib/cimport.ml` maps `const char *` to `string`, and `agrees` — the function that
+the FFI. `lib/cimport.ml` maps `const char *` to `str`, and `agrees` — the function that
decides whether a hand-written declaration and the header say the same thing — accepts
-exactly one difference, an enum against a 32-bit integer. `(Ptr u8)` against `string` is not
+exactly one difference, an enum against a 32-bit integer. `(Ptr u8)` against `str` is not
it. Adding the line above and building *anything*, not only regenerating, gives:
```
vendor/raylib/generated.flan:233:12: the declare-c of get-codepoint-previous-raw
disagrees with vendor/raylib/raylib-5.5.h: parameter text is (Ptr u8) and the
- header says string (const char *)
+ header says str (const char *)
```
`headers` is read on every build, so the binding cannot be added without relaxing the
@@ -823,12 +823,12 @@ something with a length, and it was reached for three times across the two files
open question and the answer is clean. The reader takes the bytes, the object file carries
them, the shim hands them over, and `LoadCodepoints` decodes the 54 codepoints of the Iroha
into the 49 distinct ones the atlas is built from. Nothing in Flan claims to know what a
-character is — a `string` is bytes and `(bytes s)` / `(string b)` say so in both directions
+character is — a `str` is bytes and `(bytes s)` / `(str b)` say so in both directions
at no cost — and for this job that is exactly the right amount of opinion. There is a
`valid-utf8?` in the prelude and this example never needs it.
-**An interior pointer into a string has an idiom already.** `(string (slice b off (length b)))`
-is the C's `char *ptr` and compiles to nothing: a `string` and a `[u8]` are the same two
+**An interior pointer into a string has an idiom already.** `(str (slice b off (length b)))`
+is the C's `char *ptr` and compiles to nothing: a `str` and a `[u8]` are the same two
words. Every forward-reading `const char *` entry point is reachable that way.
**`load-font-ex` needed nothing.** It takes a `[i32]` of codepoints, takes the
@@ -852,7 +852,7 @@ example.
> test rather than a raylib example, and there is not one.
**Fixed arrays were the right shape for both.** A codepoint table with a count, a
-`[9 Rectangle]` of toggle buttons, a `[9 string]` of labels. The §3 finding from the
+`[9 Rectangle]` of toggle buttons, a `[9 str]` of labels. The §3 finding from the
siam-farmer report — a global cannot hold a `Vec`, and fixed arrays with counts are usually
the better answer anyway — held again, in two more programs, with no friction at all.
diff --git a/emacs/MANUAL.md b/emacs/MANUAL.md
index 36e24899..0814dafc 100644
--- a/emacs/MANUAL.md
+++ b/emacs/MANUAL.md
@@ -429,7 +429,7 @@ frames that have no file.
know which restart you want and do not need the buffer.
**The condition's fields are named and typed, and have no values.** Under the
-condition you get the struct it is — `:path string`, `:tried i32` — because the
+condition you get the struct it is — `:path str`, `:tried i32` — because the
daemon compiled the program and knows what that type looks like without asking
the program anything. What is beside each field is a note saying the value is
not available, not a blank: a value lives in the stopped frame, and nothing yet
@@ -551,7 +551,7 @@ answers a different question — it answers what the **next** run does.
now, and what you type is a Flan **expression**, evaluated in the program and
checked against the type of the place it is going into. `(+ 1 2)`, a string
literal, a whole struct literal all work; one that does not fit comes back with
-the checker's own sentence — *expected f32, found string* — and nothing is
+the checker's own sentence — *expected f32, found str* — and nothing is
stored. A literal arrives at the place's width, so `3` into an `f32` field is
three point oh and not a refusal you would have had to write `3.0` to avoid.
Point on no field line at all sets the whole value, which is how a data type's
@@ -772,8 +772,8 @@ last. These two are the other half. A slot keeps **count, min, max, last and
mean**, and the buffer renders them as one line:
```flan
-(declare-c watch-num-i64 [name string x i64] i32 "flan_dev_watch_num_i64")
-(declare-c watch-num-f64 [name string x f64] i32 "flan_dev_watch_num_f64")
+(declare-c watch-num-i64 [name str x i64] i32 "flan_dev_watch_num_i64")
+(declare-c watch-num-f64 [name str x f64] i32 "flan_dev_watch_num_f64")
(watch-num-i64 "cell" (at grid i))
```
@@ -795,9 +795,9 @@ table is also reachable as plain C functions, one per scalar type, which a
program declares like any other:
```flan
-(declare-c watch-i64 [name string x i64] i32 "flan_dev_watch_i64")
-(declare-c watch-f64 [name string x f64] i32 "flan_dev_watch_f64")
-(declare-c watch-str [name string s string] i32 "flan_dev_watch_str")
+(declare-c watch-i64 [name str x i64] i32 "flan_dev_watch_i64")
+(declare-c watch-f64 [name str x f64] i32 "flan_dev_watch_f64")
+(declare-c watch-str [name str s str] i32 "flan_dev_watch_str")
```
Each returns 1 if the value was written and 0 if nobody is watching or the
diff --git a/emacs/flan-cnr.el b/emacs/flan-cnr.el
index 45b8923a..7a944600 100644
--- a/emacs/flan-cnr.el
+++ b/emacs/flan-cnr.el
@@ -717,7 +717,7 @@ visits the source of the one it lands on."
(defun flan-cnr-param-types (params)
"The types in PARAMS, a restart's parameters as the program spells them.
-PARAMS is a parenthesised list such as \"(i64 (Option string))\"; the result
+PARAMS is a parenthesised list such as \"(i64 (Option str))\"; the result
is one string per type, or nil when it takes none or cannot be read."
(let ((form (and (stringp params)
(condition-case nil (car (read-from-string params))
diff --git a/emacs/flan-fln-mode.el b/emacs/flan-fln-mode.el
index 34b3cdad..7e538382 100644
--- a/emacs/flan-fln-mode.el
+++ b/emacs/flan-fln-mode.el
@@ -1584,7 +1584,7 @@ lambda or a `Fn(...)' type, and not after a match arm's."
(flan-fln--return-type-matcher 1 font-lock-type-face)
;; The package half of a qualified name, as `flan-mode' draws it.
("\\_<\\([a-zA-Z][a-zA-Z0-9!?*+=<>._-]*/\\)" 1 font-lock-type-face)
- ("\\_<\\(?:[iu]\\(?:8\\|16\\|32\\|64\\)\\|f\\(?:32\\|64\\)\\|bool\\|string\\|dyn\\|Never\\|Allocator\\|Ptr\\|Option\\|Vec\\|Map\\|C?Fn\\)\\_>"
+ ("\\_<\\(?:[iu]\\(?:8\\|16\\|32\\|64\\)\\|f\\(?:32\\|64\\)\\|bool\\|str\\|dyn\\|Never\\|Allocator\\|Ptr\\|Option\\|Vec\\|Map\\|C?Fn\\)\\_>"
. font-lock-type-face)
("\\_<\\$[^][ \t\n(){},;\":]*" . font-lock-type-face)
;; A character literal, `\c' or `\space'.
diff --git a/emacs/flan-mode.el b/emacs/flan-mode.el
index 9f45c30b..4e0d3b30 100644
--- a/emacs/flan-mode.el
+++ b/emacs/flan-mode.el
@@ -175,15 +175,15 @@ face says.")
;; containers and memory
"length" "at" "slice" "slice-from" "addr" "deref"
;; options, bytes, the host
- "Some" "bytes" "bytes-view" "string"
+ "Some" "bytes" "bytes-view" "str"
"bytes->f64" "bytes->i64" "f64->bytes" "i64->bytes"
"write-stdout" "print" "println" "exit" "argv")
"The functions the compiler provides, from `lib/check.ml''s `builtins' table.
Ordinary calls — nothing here is special to the parser — so they are drawn as
-builtins and not as keywords. `string' is in this list and in the type rule
-below and means a different thing in each: `(string b)' converts and a bare
-`string' names a type, which the rules tell apart by the paren.
+builtins and not as keywords. `str' is in this list and in the type rule
+below and means a different thing in each: `(str b)' converts and a bare
+`str' names a type, which the rules tell apart by the paren.
`destructure~nth' is in the table and not here: the compiler writes it into a
destructuring `let' and nobody types it.
@@ -253,7 +253,7 @@ reason and is the odd one — it is legal only as the last item of a `def' or a
;; word outright — unit is spelled `()'. Drawing it as a valid type would
;; advertise a spelling the parser rejects, which is the same reason
;; `find-restart' and `await' are left out of `flan--special'.
- ("\\_<\\(?:[iu]\\(?:8\\|16\\|32\\|64\\)\\|f\\(?:32\\|64\\)\\|bool\\|string\\|dyn\\|const\\|int\\|float\\|Never\\|Allocator\\|Ptr\\|Option\\|Vec\\|Map\\|C?Fn\\)\\_>"
+ ("\\_<\\(?:[iu]\\(?:8\\|16\\|32\\|64\\)\\|f\\(?:32\\|64\\)\\|bool\\|str\\|dyn\\|const\\|int\\|float\\|Never\\|Allocator\\|Ptr\\|Option\\|Vec\\|Map\\|C?Fn\\)\\_>"
. font-lock-type-face)
;; A type variable, `$t', which is what a generic `defn' names its
;; parameter types with and what `{:where (ordered? $t)}' constrains.
diff --git a/emacs/test-flan-cider.el b/emacs/test-flan-cider.el
index fcb43080..7c27f106 100644
--- a/emacs/test-flan-cider.el
+++ b/emacs/test-flan-cider.el
@@ -1093,7 +1093,7 @@ would be overwritten. Look again and re-do the edit")
:at "/src/files.flan:12:3" :arity 0 :params "()")
(:report "Try again with another path"
:at "/src/files.flan:12:3" :arity 1
- :params "(string)")
+ :params "(str)")
(:report "" :at nil :arity 0 :params "()")))))
(text (with-current-buffer buf (buffer-string))))
(test-flan--check "a restart's report is beside its name"
@@ -1101,7 +1101,7 @@ would be overwritten. Look again and re-do the edit")
(test-flan--check "and where its clause is written"
(string-match-p "again (/src/files.flan:12:3)" text))
(test-flan--check "a restart taking values shows their types"
- (string-match-p "\\[use-value\\] +(string) Try again with another path"
+ (string-match-p "\\[use-value\\] +(str) Try again with another path"
text))
(test-flan--check "one with no report and no source shows its name alone"
(string-match-p " 2: \\[plain\\] *\n" text))
@@ -1117,8 +1117,8 @@ would be overwritten. Look again and re-do the edit")
;; A restart that takes values asks for one per parameter and sends them.
(test-flan--check "a restart's parameter types are read from their spelling"
- (equal (flan-cnr-param-types "(i64 (Option string))")
- '("i64" "(Option string)")))
+ (equal (flan-cnr-param-types "(i64 (Option str))")
+ '("i64" "(Option str)")))
(let ((sent nil) (asked nil))
(let ((flan-cnr-request-function
(lambda (form) (setq sent form) (list :status "ok" :note "accepted"))))
@@ -1613,12 +1613,12 @@ would be overwritten. Look again and re-do the edit")
;; blame is even a field of this condition.
(let ((text (with-current-buffer
(test-flan--cnr (list :condition "Missing" :restarts '("retry")
- :fields '(("path" "string" nil)
+ :fields '(("path" "str" nil)
("tried" "i32" "3"))
:fields-why "the stop's value was not readable"))
(buffer-string))))
(test-flan--check "a field is named and typed even with no value"
- (string-match-p ":path *string *not read" text))
+ (string-match-p ":path *str *not read" text))
(test-flan--check "and the reason is one sentence, said once above the rows"
(and (string-match-p "not read — the stop's value" text)
(= 1 (seq-count
@@ -1696,7 +1696,7 @@ would be overwritten. Look again and re-do the edit")
(let ((text (with-current-buffer
(test-flan--cnr
(list :condition "Missing" :restarts '("retry" "a" "retry")
- :fields '(("path" "string" nil))
+ :fields '(("path" "str" nil))
:stack (list (list :fn "f" :fetched t :locals nil))))
(buffer-string))))
(test-flan--check "no bracketed implementation note leaks into the buffer"
@@ -1731,7 +1731,7 @@ would be overwritten. Look again and re-do the edit")
("break" '(:status "ok" :stopped t :condition "sim/Missing"
:restarts ("retry")))
("layout" '(:status "ok" :type "sim/Missing"
- :fields (("path" "string") ("tried" "i32"))))))))
+ :fields (("path" "str") ("tried" "i32"))))))))
(let ((text (with-current-buffer (save-window-excursion (flan-cnr-show))
(buffer-string))))
(test-flan--check "the condition's name is what `layout' is asked for"
@@ -1747,7 +1747,7 @@ would be overwritten. Look again and re-do the edit")
:type)
"sim/Missing"))
(test-flan--check "the fields are drawn, named and typed"
- (string-match-p ":path *string" text))
+ (string-match-p ":path *str\\_>" text))
;; Shape and contents are two different questions, and this stub's
;; daemon answers only the first — so the values fall back to the
;; layout, each row saying in one sentence why it is empty.
@@ -1783,7 +1783,7 @@ would be overwritten. Look again and re-do the edit")
;; that touches each one.
:globals '(("grid" "[4 i32]" "[7 5 0 0]" (0 1))
("pressure" "i64" "12" (0))
- ("label" "string" "\"running\"" (1)))))
+ ("label" "str" "\"running\"" (1)))))
(buf (test-flan--cnr state))
(text (with-current-buffer buf (buffer-string))))
(test-flan--check "a global is named, typed and valued"
@@ -1825,7 +1825,7 @@ would be overwritten. Look again and re-do the edit")
(test-flan--cnr
(list :condition "Boom" :restarts '("retry")
:stack (list (list :fn "f"))
- :globals '(("label" "string" "\"x\"" (1)))
+ :globals '(("label" "str" "\"x\"" (1)))
:globals-refused '(("weird" "no printer for (Map i64 i64)"))
:globals-skipped
'(("0: sim/inner" "this frame's body was redefined since it was entered"))))
diff --git a/emacs/test-flan-mode.el b/emacs/test-flan-mode.el
index 34ec904a..6593825a 100644
--- a/emacs/test-flan-mode.el
+++ b/emacs/test-flan-mode.el
@@ -111,13 +111,13 @@
;; there.
(test-flan-mode--check
"a defn with a return type indents its body by two"
- "(defn look [n i64 label string] i64
+ "(defn look [n i64 label str] i64
(print label)
n)")
(test-flan-mode--check
"and a defn without one indents it the same"
- "(defn show-trim [s string] ()
+ "(defn show-trim [s str] ()
(print s)
(println \"\"))")
diff --git a/examples/core-input-gestures-testbed.flan b/examples/core-input-gestures-testbed.flan
index 540bbf0d..83d1fbaf 100644
--- a/examples/core-input-gestures-testbed.flan
+++ b/examples/core-input-gestures-testbed.flan
@@ -67,7 +67,7 @@
(defconst gesture-log-size 20)
(defconst max-touch-count 32)
-(defonce gesture-log [gesture-log-size string])
+(defonce gesture-log [gesture-log-size str])
;; The C's inverted circular queue: the index counts DOWN and wraps at the top,
;; so the newest entry is always at gesture-log-index and the draw loop walks
;; forward from there. Starting at the size rather than at size-1 is the C's
@@ -103,7 +103,7 @@
;; belongs under a :gesture-none guard. The C's switch over single members
;; hides both; a range test cannot.
-(defn gesture-name [g rl/Gesture] string
+(defn gesture-name [g rl/Gesture] str
(cond
(= g :gesture-none) "None"
(= g :gesture-tap) "Tap"
diff --git a/examples/core-input-gestures.flan b/examples/core-input-gestures.flan
index 282c8c60..fc8b9111 100644
--- a/examples/core-input-gestures.flan
+++ b/examples/core-input-gestures.flan
@@ -30,7 +30,7 @@
(defconst max-gesture-strings 20)
-(defonce gesture-log [max-gesture-strings string])
+(defonce gesture-log [max-gesture-strings str])
(defonce gestures-count i32)
(defonce current-gesture rl/Gesture)
(defonce last-gesture rl/Gesture)
@@ -38,7 +38,7 @@
;; The C's switch, as a function. `:else` is its `default:` — an unnamed
;; gesture logs the empty string, which draws nothing, which is what falling
;; through the C's switch without a TextCopy leaves in the slot.
-(defn gesture-name [g rl/Gesture] string
+(defn gesture-name [g rl/Gesture] str
(cond
(= g :gesture-tap) "GESTURE TAP"
(= g :gesture-double-tap) "GESTURE DOUBLETAP"
diff --git a/examples/core-input-multitouch.flan b/examples/core-input-multitouch.flan
index c2d8a8b5..68ed7809 100644
--- a/examples/core-input-multitouch.flan
+++ b/examples/core-input-multitouch.flan
@@ -60,7 +60,7 @@
;; and a table of one-character strings; (string b) makes the
;; number a string with no instructions, so it is one draw-text and
;; this file imports nothing but raylib.
- (rl/draw-text (string (i64->bytes (i64 i)))
+ (rl/draw-text (str (i64->bytes (i64 i)))
(- (i32 (.x p)) 10) (- (i32 (.y p)) 70) 40
rl/black))))
diff --git a/examples/core-input-virtual-controls.flan b/examples/core-input-virtual-controls.flan
index 5d892e67..f5379d13 100644
--- a/examples/core-input-virtual-controls.flan
+++ b/examples/core-input-virtual-controls.flan
@@ -188,7 +188,7 @@
;; Not in the C: which button the search picked, as a number, so the
;; headless case and the window agree about the same thing.
(rl/draw-text "button: " 10 34 20 rl/lightgray)
- (rl/draw-text (string (i64->bytes (i64 pressed)))
+ (rl/draw-text (str (i64->bytes (i64 pressed)))
(+ 10 (rl/measure-text "button: " 20)) 34 20
rl/lightgray))
diff --git a/examples/core-window-flags.flan b/examples/core-window-flags.flan
index 7f2fc534..b0a24b76 100644
--- a/examples/core-window-flags.flan
+++ b/examples/core-window-flags.flan
@@ -47,7 +47,7 @@
;; One line of the state list: the label, then "on" or "off" in lime or
;; maroon, at the x the label ended. The C writes two whole DrawText calls per
;; flag with the text repeated; this says it once.
-(defn draw-flag [label string flag u32 y i32] ()
+(defn draw-flag [label str flag u32 y i32] ()
(rl/draw-text label 10 y 10 rl/gray)
(let [x (+ 10 (rl/measure-text label 10))]
(if (rl/window-state? flag)
diff --git a/examples/digits.flan b/examples/digits.flan
index 6fa674d6..16fe0b30 100644
--- a/examples/digits.flan
+++ b/examples/digits.flan
@@ -45,7 +45,7 @@
;;
;; Nothing may be formatted between the draw and the measure: `s` may be a view
;; of the shared buffer, and both calls have to see the same bytes.
-(defn draw-piece [s string x i32 y i32 size i32 color rl/Color] i32
+(defn draw-piece [s str x i32 y i32 size i32 color rl/Color] i32
(rl/draw-text s x y size color)
(rl/measure-text s size))
@@ -74,7 +74,7 @@
;; the old note about i32's most negative value — it is widened to i64 before
;; formatting, so there is no negation to wrap.
(defn draw-int [n i32 x i32 y i32 size i32 color rl/Color] i32
- (draw-piece (string (i64->bytes (i64 n))) x y size color))
+ (draw-piece (str (i64->bytes (i64 n))) x y size color))
;; The same with a fixed minimum number of digits — the C's "%03i". A number
;; wider than `width` is drawn in full rather than truncated, which is what
diff --git a/examples/text-codepoints-loading.flan b/examples/text-codepoints-loading.flan
index d96f2178..870f8c6d 100644
--- a/examples/text-codepoints-loading.flan
+++ b/examples/text-codepoints-loading.flan
@@ -135,7 +135,7 @@
(let [b (bytes-view text)]
(if (>= off (length b))
0
- (rl/get-codepoint-next (string (slice b off (length b))) size-out))))
+ (rl/get-codepoint-next (str (slice b off (length b))) size-out))))
;; One codepoint forward, clamped at the end.
;;
diff --git a/examples/text-input-box.flan b/examples/text-input-box.flan
index 6a1ac289..02aea30f 100644
--- a/examples/text-input-box.flan
+++ b/examples/text-input-box.flan
@@ -122,7 +122,7 @@
(i32 (.width text-box)) (i32 (.height text-box))
(if mouse-on-text rl/red rl/darkgray))
- (let [typed (string (slice name 0 letter-count))]
+ (let [typed (str (slice name 0 letter-count))]
(rl/draw-text typed (+ (i32 (.x text-box)) 5) (+ (i32 (.y text-box)) 8)
40 rl/maroon)
diff --git a/examples/text-rectangle-bounds.flan b/examples/text-rectangle-bounds.flan
index a3772a84..22257e45 100644
--- a/examples/text-rectangle-bounds.flan
+++ b/examples/text-rectangle-bounds.flan
@@ -82,7 +82,7 @@
i 0]
(while (< i length)
(let [size 0
- cp (rl/get-codepoint (string (slice text i length)) (addr size))]
+ cp (rl/get-codepoint (str (slice text i length)) (addr size))]
;; A byte that decodes to nothing answers '?' and raylib would normally
;; stop; this walks on one byte at a time so the bad bytes get drawn.
(when (= cp (i32 \?)) (set size 1))
diff --git a/examples/text-writing-anim.flan b/examples/text-writing-anim.flan
index b3815744..02b989b4 100644
--- a/examples/text-writing-anim.flan
+++ b/examples/text-writing-anim.flan
@@ -68,7 +68,7 @@
;; the C — see the header comment.
(let [b (bytes-view message)
n (min (i32 (length b)) (/ frames-counter 10))]
- (rl/draw-text (string (slice b 0 n)) 210 160 20 rl/maroon))
+ (rl/draw-text (str (slice b 0 n)) 210 160 20 rl/maroon))
(rl/draw-text "PRESS [ENTER] to RESTART!" 240 260 20 rl/lightgray)
(rl/draw-text "HOLD [SPACE] to SPEED UP!" 239 300 20 rl/lightgray))))
diff --git a/examples/textures-image-processing.flan b/examples/textures-image-processing.flan
index 45dc6ad3..b8f6cce9 100644
--- a/examples/textures-image-processing.flan
+++ b/examples/textures-image-processing.flan
@@ -80,7 +80,7 @@
(defconst proc-flip-vertical 7)
(defconst proc-flip-horizontal 8)
-(defonce process-names [num-processes string])
+(defonce process-names [num-processes str])
;; The nine toggle buttons down the left-hand side, laid out once at startup.
(defonce toggle-recs [num-processes rl/Rectangle])
diff --git a/lib/ast.ml b/lib/ast.ml
index 9658fd36..8850fd71 100644
--- a/lib/ast.ml
+++ b/lib/ast.ml
@@ -293,7 +293,7 @@ and decl_kind =
(* The same, but written in the C library's own terms — structs by value,
strings as strings. [Shim] generates the C that flattens it and rewrites
this into a [Declare] plus an ordinary [Defn], so nothing downstream sees
- one. Two forms and not one because [(declare f [p string] ...)] already
+ one. Two forms and not one because [(declare f [p str] ...)] already
means "the symbol takes ptr+len", which is the opposite of what this
means. *)
| DeclareC of fn * string
diff --git a/lib/check.ml b/lib/check.ml
index a23f2e83..e82242d1 100644
--- a/lib/check.ml
+++ b/lib/check.ml
@@ -570,7 +570,7 @@ let foreign_spelling = function
| "byte" -> Some "u8"
| "double" -> Some "f64"
| "boolean" -> Some "bool"
- | "str" -> Some "string"
+ | "string" -> Some "str"
| _ -> None
(* The builtin names, for the did-you-mean at a call — [prinltn] is a typo for
@@ -1953,7 +1953,7 @@ and resolve_name env ~seen loc n =
| None ->
match n with
| "bool" -> Types.Bool
- | "string" -> Types.String
+ | "str" -> Types.String
(* Lowercase and concrete, which the rule three screens down says is a
type variable. It is spelled this way because it is a primitive and
every other primitive is lowercase — [dyn] beside [i64] and [bool]
@@ -2086,7 +2086,7 @@ and array_len env loc = function
let is_type_name env n =
Types.ikind_of_name n <> None
|| Types.fkind_of_name n <> None
- || List.mem n [ "bool"; "string"; "dyn"; "Unit"; "Never"; "Allocator" ]
+ || List.mem n [ "bool"; "str"; "dyn"; "Unit"; "Never"; "Allocator" ]
|| Hashtbl.mem env.aliases n
|| Hashtbl.mem env.structs n
|| Hashtbl.mem env.gstructs n
@@ -2188,6 +2188,16 @@ let dyn_param_or_typo env n loc =
(* In a .fln file the type sits after [name:], so it cannot be read as a
second parameter and needs no word about parameter vectors. *)
let fln = Source.indented_at loc in
+ (* [string] is what most languages call the text type, so [[s string]] is
+ far likelier one parameter of a misspelled type than two dyn ones. The
+ other foreign spellings ([long], [byte], [double]) are ordinary parameter
+ names and keep the dyn reading. *)
+ if n = "string" then
+ Loc.failk "check/unknown-type" loc
+ "unknown type string — Flan spells it str%s"
+ (if fln then ""
+ else ". Otherwise string reads as a second parameter, because a \
+ parameter with no type is dyn, and wants another name");
match suggestion with
| Some m when fln ->
Loc.failk "check/unknown-type" loc "unknown type %s — did you mean %s?" n m
@@ -10397,6 +10407,9 @@ and type_named ctx n =
mistake, instead of this form reporting a missing element type. *)
|| n <> tyvar_bare n
|| List.mem n Types.primitive_names
+ (* Answered as a type so [resolve_name] says it is spelled [str], rather
+ than this form saying no element type was written. *)
+ || n = "string"
|| Hashtbl.mem ctx.env.structs n
|| Hashtbl.mem ctx.env.datas n
|| Hashtbl.mem ctx.env.unions n
@@ -10488,7 +10501,7 @@ and map_kv loc what (t : Types.t) =
(* The key and value for [map-new]: two leading bare symbols naming types, or
the expectation at the site. The same rule [vec-new] uses, with the same
escape for a symbol that is really a binding — an allocator, in practice —
- and the pair is written together or not at all, because (map-new string)
+ and the pair is written together or not at all, because (map-new str)
says half of a type and half is not a type. *)
and map_new_types ctx ~want loc args =
let is_type n =
@@ -10507,7 +10520,7 @@ and map_new_types ctx ~want loc args =
Option.get (as_type k), Option.get (as_type v), rest
| a :: _ when type_of_expr ~generic:(Hashtbl.mem ctx.env.gstructs) a <> None ->
fail loc
- "(map-new) names a key and no value — write both, as (map-new string \
+ "(map-new) names a key and no value — write both, as (map-new str \
i32)"
| { Ast.e = Ast.Var k; _ } :: rest when is_type k && rest = [] ->
fail loc
@@ -10519,7 +10532,7 @@ and map_new_types ctx ~want loc args =
| _ ->
fail loc
"nothing here says what (map-new) maps — write the key and value \
- types, as (map-new string i32)")
+ types, as (map-new str i32)")
(* The element type, or the reason this is not a Vec. *)
and vec_elem loc what (t : Types.t) =
@@ -12066,10 +12079,10 @@ and named_call ?(qualified = false) ctx ~want loc name args =
being told the file is missing and left to discover the other half
after fixing it. *)
(match args with
- | [ _; { Ast.e = Ast.Var "string"; _ } ] | [ _ ] -> ()
+ | [ _; { Ast.e = Ast.Var "str"; _ } ] | [ _ ] -> ()
| [ _; t ] ->
fail t.Ast.loc
- "embed's second argument is string, or nothing for a [const u8]"
+ "embed's second argument is str, or nothing for a [const u8]"
| _ -> ());
let data = read_embed_file (embed_path loc p) p.Ast.loc in
let as_string () = mk loc Types.String (Tast.Str data) in
@@ -12088,7 +12101,7 @@ and named_call ?(qualified = false) ctx ~want loc name args =
two types would be a wart. [want] is a fallback only, and nothing
depends on it. *)
(match args with
- | [ _; { Ast.e = Ast.Var "string"; _ } ] ->
+ | [ _; { Ast.e = Ast.Var "str"; _ } ] ->
expect ctx loc ~want (as_string ())
| _ ->
(match want with
@@ -12096,7 +12109,7 @@ and named_call ?(qualified = false) ctx ~want loc name args =
| _ -> expect ctx loc ~want (as_bytes ())))
| _ ->
fail loc
- "embed is (embed \"path\") for a [const u8], or (embed \"path\" string)")
+ "embed is (embed \"path\") for a [const u8], or (embed \"path\" str)")
(* ── What a macro says when it has to refuse ───────────────────
The one thing a macro could not do, written down in the prelude where
[unless] settles for it: "a macro has no error facility: it runs inside
@@ -12666,7 +12679,7 @@ and named_call ?(qualified = false) ctx ~want loc name args =
expect ctx loc ~want (dup_elems ctx loc (Types.Int Types.U8) s a)
| _ -> fail loc "bytes is (bytes s) or (bytes s allocator)")
- (* (string b): a [u8] seen as a string. The mirror of (bytes-view s),
+ (* (str b): a [u8] seen as a str. The mirror of (bytes-view s),
spelled the same way — a type name in head position, like (bytes s) and
unlike the numeric casts, which go through [is_cast] and really do
convert.
@@ -12680,7 +12693,7 @@ and named_call ?(qualified = false) ctx ~want loc name args =
Two decisions are baked in here.
- 1. It does NOT check UTF-8, because `string` does not claim UTF-8. The
+ 1. It does NOT check UTF-8, because `str` does not claim UTF-8. The
prelude settles this: valid-utf8? is an ordinary function you call when
you care, decode-rune/rune-at/rune-count all take [u8] rather than
string, and decode-rune answers {.ok false .width 1} on a malformed
@@ -12694,13 +12707,13 @@ and named_call ?(qualified = false) ctx ~want loc name args =
2. It takes a [const u8], so a [u8] and a (bytes-view s) are both
accepted. This direction only loses the ability to write — a string
- is read-only everywhere — so the result of (string b) can reach
+ is read-only everywhere — so the result of (str b) can reach
strictly fewer stores than b could.
The text i64->bytes and f64->bytes answer lives in the temp allocator
until the next (free-temp); calling it a string does not copy it, so text
kept past the frame is cloned first. *)
- | "string" ->
+ | "str" ->
arity ctx loc name 1 args;
prim Tast.StrOfBytes Types.String [ byte_slice ctx (List.hd args) ]
| "bytes->f64" ->
@@ -13362,6 +13375,13 @@ and ordinary_call ctx ~want loc name args =
not (List.mem m [ "true"; "false"; "nil"; "None";
"context/allocator"; "context/temp" ])
in
+ (* [(string b)], [(byte x)]: another language's name for a type, used
+ as the conversion, which Flan spells with its own type name. *)
+ (match foreign_spelling name with
+ | Some m ->
+ Loc.failk "check/unknown-function" loc
+ "unknown function %s — Flan spells it %s" name m
+ | None -> ());
match guess with
| Some m when not (callable m) ->
if args = [] then
@@ -14507,15 +14527,15 @@ let builtins : (string * string * string) list =
:keyword :map — or, for a value built by a defclass constructor, the \
class's name as class-of answers it. A typed value answers the kind it \
has as a dyn value: an i32 is :int.");
- ("keyword", "keyword [string|[const u8]] dyn",
+ ("keyword", "keyword [str|[const u8]] dyn",
"The interned dyn keyword named by the bytes, for a name that only \
exists at run time — a reader building :texture-path out of a token's \
text. A literal :foo is already one.");
(* assets, embedded at compile time *)
- ("embed", "embed [\"path\" string?] [const u8]",
+ ("embed", "embed [\"path\" str?] [const u8]",
"The file's bytes, read at compile time and baked in as a constant; \
- (embed \"p\" string) reads it as a string instead. The path is \
+ (embed \"p\" str) reads it as a str instead. The path is \
relative to the file the form is written in, and the slice points into \
read-only data.");
("embed-dir", "embed-dir [\"path\"] [n EmbedFile]",
@@ -14527,27 +14547,27 @@ let builtins : (string * string * string) list =
carries a name, and this carries a sentence.");
(* files *)
- ("slurp", "slurp [string Allocator?] (Vec u8)",
+ ("slurp", "slurp [str Allocator?] (Vec u8)",
"Reads a whole file. No Result and no out-parameter: a failure to read \
signals FileError under retry and use-value, and a failure to allocate \
signals StorageExhausted.");
- ("barf", "barf [string [const u8]] ()",
+ ("barf", "barf [str [const u8]] ()",
"Writes a whole file. On the web target it signals FileError every \
time, with the path — there is no conditional compilation, so the \
program decides rather than the build.");
- ("delete-file", "delete-file [string] ()",
+ ("delete-file", "delete-file [str] ()",
"Removes the file, or signals FileError with retry and use-value. It \
answers () and not a bool, because the failure is the condition.");
- ("make-directory", "make-directory [string] ()",
+ ("make-directory", "make-directory [str] ()",
"Creates the directory, or signals FileError. () for the reason \
delete-file answers one.");
- ("rename-file", "rename-file [string string] ()",
+ ("rename-file", "rename-file [str str] ()",
"Renames the first path to the second, or signals FileError. A \
use-value names a different source for the same destination, which is \
the direction a handler can act on.");
(* containers *)
- ("length", "length [[n T]|[T]|string|(Vec T)|(Map K V)] i32",
+ ("length", "length [[n T]|[T]|str|(Vec T)|(Map K V)] i32",
"How many elements. One question and one word across an array, a slice, \
a string, a Vec and a Map.");
("at", "at [collection i32 ...] T",
@@ -14555,7 +14575,7 @@ let builtins : (string * string * string) list =
allocator's epoch checked first. On a string it is the byte, a u8. It \
is also a place, so (set (at v i) x) goes through the same check; a \
string is the exception, being a view it does not own.");
- ("slice", "slice [[n T]|[T]|string|(Vec T) i32? i32?] [T]|string",
+ ("slice", "slice [[n T]|[T]|str|(Vec T) i32? i32?] [T]|str",
"The half-open range [lo hi) as a non-owning view. lo defaults to 0 and \
hi to the length, so (slice a) is the whole of it and (slice a n) is \
the tail from n. A bound may sit one past the end; a literal pair that \
@@ -14580,20 +14600,20 @@ let builtins : (string * string * string) list =
written as a name rather than as a call.");
(* the host primitives *)
- ("bytes", "bytes [string Allocator?] [u8]",
+ ("bytes", "bytes [str Allocator?] [u8]",
"A writable copy of the string's bytes, from the current allocator or \
one named. It allocates like vec-new does — a failure signals \
StorageExhausted with retry — and (free b) releases it, through the \
current allocator or (free b a) through the one it came from. For reading without a copy, \
bytes-view.");
- ("bytes-view", "bytes-view [string] [const u8]",
+ ("bytes-view", "bytes-view [str] [const u8]",
"The string's own storage seen as a read-only byte slice. It costs \
nothing — both are a ptr and a length at run time — and it decodes \
nothing. A store through it is a compile error; bytes is the writable \
copy.");
- ("string", "string [[const u8]] string",
- "A byte slice seen as a string, and free at run time. It does not check \
- UTF-8, because `string` does not claim UTF-8 — valid-utf8? is an \
+ ("str", "str [[const u8]] str",
+ "A byte slice seen as a str, and free at run time. It does not check \
+ UTF-8, because `str` does not claim UTF-8 — valid-utf8? is an \
ordinary function you call when you care.");
("bytes->f64", "bytes->f64 [[const u8]] f64", "Parses a float out of the bytes.");
("bytes->i64", "bytes->i64 [[const u8]] i64",
@@ -14615,7 +14635,7 @@ let builtins : (string * string * string) list =
is a read, so it does not consume the value.");
("println", "println [T ...] ()",
"print, with a newline after it — (println) alone is the newline.");
- ("watch", "watch [string T] ()",
+ ("watch", "watch [str T] ()",
"Writes the value, rendered as print renders it, into the dev session's \
watch table under the name, where M-x flan-watch shows it. Does nothing \
when no watch buffer is open. Outside a dev build it only evaluates \
@@ -14623,7 +14643,7 @@ let builtins : (string * string * string) list =
("exit", "exit [i32] never",
"Ends the process with this status. It has no value, so nothing written \
after it runs.");
- ("argv", "argv [] [string]", "The command line, as a slice of strings.");
+ ("argv", "argv [] [str]", "The command line, as a slice of strings.");
(* the names rather than calls — [var]'s arms. Their
signature is the [name type] shape [Dev.defs] gives a global, because
@@ -16507,7 +16527,7 @@ let check_main env decls =
in
if not ok_params then
fail at
- "main takes no parameters or one [string], not (%s)"
+ "main takes no parameters or one [str], not (%s)"
(String.concat (if Source.indented_at at then ", " else " ")
(List.map (tyname at) params));
if not (Types.equal ret Types.Unit || Types.equal ret (Types.Int Types.I32))
diff --git a/lib/cimport.ml b/lib/cimport.ml
index e1df2a27..69b60905 100644
--- a/lib/cimport.ml
+++ b/lib/cimport.ml
@@ -552,7 +552,7 @@ let param_ty env (s : string) : Ast.texpr =
let inner = String.trim (String.sub s 0 (String.length s - 1)) in
let is_const = strip_prefix "const " inner <> None in
match bare inner with
- | "char" when is_const -> tname "string"
+ | "char" when is_const -> tname "str"
| "char" ->
refuse
"char * is a parameter C may write through, and a Flan string crosses \
@@ -573,7 +573,7 @@ let param_ty env (s : string) : Ast.texpr =
[const char *] is text the caller only reads — a static buffer, a pointer
into an argument, a string literal — and [Shim] copies it into the context
- allocator, so it becomes a [string]. [char *] without the const is text the
+ allocator, so it becomes a [str]. [char *] without the const is text the
caller owns and must hand back through the library's own release function
([LoadFileText] and [UnloadFileText]); copying it would leak the original
with nothing left to release it through, so it is refused and a
@@ -585,7 +585,7 @@ let ret_ty env (s : string) : Ast.texpr option =
let inner = String.trim (String.sub s 0 (String.length s - 1)) in
let is_const = strip_prefix "const " inner <> None in
match bare inner with
- | "char" when is_const -> Some (tname "string")
+ | "char" when is_const -> Some (tname "str")
| "char" ->
refuse
"returns char *, which the caller owns and releases through the \
@@ -927,7 +927,7 @@ let agrees env (a : Ast.texpr) (b : Ast.texpr) =
The second tolerance, and the one [agrees] cannot express on its own. By the
time a C parameter has become a Flan type, what the header actually said
- about it is gone: [param_ty] renders [const char *] as [string] and
+ about it is gone: [param_ty] renders [const char *] as [str] and
[value_ty] renders [void *] as [(Ptr u8)], and both of those are the
importer's own choice rather than the header's word. A hand-written line
that says [(Ptr u8)] over a [const char *] is not disagreeing with the
@@ -966,7 +966,7 @@ let ptr_agrees_elem env ~inner (elem : Ast.texpr) =
reporting [value_ty]'s guess of [u8] back at the author as if the header
had said it. What is *not* given up is that it is a pointer at all: the
match above requires [(Ptr _)] on the Flan side, so an [i32] or a
- [string] declared against a [void *] is still a finding. That
+ [str] declared against a [void *] is still a finding. That
asymmetry is the point — raylib spells thirty-odd parameters [void *]
and none of them is a scalar. *)
let b = bare inner in
@@ -1580,7 +1580,7 @@ let decl_source (d : Ast.decl) =
- a [(Ptr T)] where the header says [T *] and the hand-written line chose
something more specific for a reason it recorded. That is [ptr_agrees],
and it needs the C spelling because the rendering has already thrown the
- answer away: [param_ty] turns [const char *] into [string] and [value_ty]
+ answer away: [param_ty] turns [const char *] into [str] and [value_ty]
turns [void *] into [(Ptr u8)], neither of which is what the header said.
[(Ptr u8)] over a [char *], and [(Ptr] anything[)] over a [void *], now
agree; [(Ptr A)] over a [B *] does not.
@@ -1642,15 +1642,15 @@ let diff_bound ~env ~(bound : (Ast.fn * string) list) (d : dump) =
| None ->
(match (try Ok (ret_ty env c.cret) with Refused w -> Error w) with
(* A return the importer refuses says nothing, as a parameter
- does — except a [string] over a [char *] without const. That
+ does — except a [str] over a [char *] without const. That
one is a real disagreement: the shim would copy the text and
leave the library's buffer with no owner. *)
| Error _ ->
(match fn.Ast.ret with
- | Some { Ast.t = Ast.Tname "string"; _ } ->
+ | Some { Ast.t = Ast.Tname "str"; _ } ->
say
(Printf.sprintf
- "returns string and the header says %s, which the \
+ "returns str and the header says %s, which the \
caller owns and releases through the library — \
declare it (Ptr u8)"
c.cret)
diff --git a/lib/emit.ml b/lib/emit.ml
index ed5eb35c..2f848442 100644
--- a/lib/emit.ml
+++ b/lib/emit.ml
@@ -1092,7 +1092,7 @@ let rec dty m d (t : Types.t) : int =
(* ptr+len, and shown as ptr+len. There is no hidden owner and no
capacity, so two members are the whole truth about a slice. *)
| Types.String ->
- composite "string"
+ composite "str"
[ ("ptr", Types.Ptr (Types.Mut, (Types.Int Types.U8))); ("len", Types.Int Types.I64) ]
| Types.Slice (_, e) ->
composite (Types.to_string t)
@@ -3989,7 +3989,7 @@ and prim f (e : Tast.expr) (p : Tast.prim) (args : Tast.expr list) =
no copy (plan.org, Milestone-2 primitives). *)
| Tast.Bytes, [ x ] -> value f x
(* (string b), and the same non-instruction for the same reason: String and
- Slice _ are both %slice. See check.ml's "string" case. *)
+ Slice _ are both %slice. See check.ml's "str" case. *)
| Tast.StrOfBytes, [ x ] -> value f x
| Tast.BytesToF64, [ x ] -> shim_in f "@flan_bytes_to_f64" "double" x
| Tast.BytesToI64, [ x ] -> shim_in f "@flan_bytes_to_i64" "i64" x
diff --git a/lib/js.ml b/lib/js.ml
index 800dc2f9..43d3af0c 100644
--- a/lib/js.ml
+++ b/lib/js.ml
@@ -36,7 +36,7 @@
- A struct — a plain object, [{x: 1, y: 2}], keyed by the field's own name.
Readable output is a goal, and this is most of it.
- [[n T]], a fixed array — a JS array, or a [Uint8Array] when [T] is [u8].
- - [[T]], a slice, and [string] — [{a, o, n}]: the backing store, an offset
+ - [[T]], a slice, and [str] — [{a, o, n}]: the backing store, an offset
into it and a length. A slice is a non-owning view in Flan and this is a
non-owning view here: writing through one writes the original, and a
copy of a slice shares its storage, both of which are what the other two
@@ -47,11 +47,11 @@
- [(Fn [..] R)] — a JS function. Function {e values} come along; they carry
no capture in Flan either.
- {b [string] and [[u8]] are the same representation, and that is not a
+ {b [str] and [[u8]] are the same representation, and that is not a
shortcut.} [Tast.Bytes] and [Tast.StrOfBytes] are documented there as
- non-instructions — in both existing backends a [string] {e is} a (ptr, len)
+ non-instructions — in both existing backends a [str] {e is} a (ptr, len)
pair over bytes, and the two prims reinterpret rather than convert. Making
- [string] a JS string would make [(length s)] count UTF-16 code units where
+ [str] a JS string would make [(length s)] count UTF-16 code units where
every other backend counts bytes, and the prelude is byte-oriented
throughout ([rune-count], [valid-utf8?], [decode-rune] all take [[u8]]).
So the JS string appears in exactly one place: the argument of
diff --git a/lib/parse.ml b/lib/parse.ml
index 73253793..42431173 100644
--- a/lib/parse.ml
+++ b/lib/parse.ml
@@ -1507,7 +1507,7 @@ let rec decl (f : Form.t) : Ast.decl =
(* An empty field vector is the same category as none. *)
| [ n; { v = Kw "parent"; _ }; p ] | [ n; { v = Kw "parent"; _ }; p; { v = Vec []; _ } ] ->
let str name =
- { Ast.fname = name; fty = { Ast.t = Ast.Tname "string"; tloc = f.loc };
+ { Ast.fname = name; fty = { Ast.t = Ast.Tname "str"; tloc = f.loc };
floc = f.loc }
in
mk (Ast.Defstruct (tname n, [ str "name"; str "message" ], Some (texpr p)))
@@ -1765,8 +1765,8 @@ let rec decl (f : Form.t) : Ast.decl =
[declare]'s signature IS the C signature, already flattened by whoever
wrote the C; [declare-c]'s is the *library's* — structs by value — and
[Shim] generates the flattening. The two cannot be one form, because
- (declare f [p string] ...) already means the symbol takes ptr+len and
- (declare-c f [p string] ...) means it takes a NUL-terminated char *. *)
+ (declare f [p str] ...) already means the symbol takes ptr+len and
+ (declare-c f [p str] ...) means it takes a NUL-terminated char *. *)
let mkd fn csym =
if String.equal which "declare-c" then Ast.DeclareC (fn, csym)
else Ast.Declare (fn, csym)
diff --git a/lib/prelude.ml b/lib/prelude.ml
index a23d2f38..16122e3a 100644
--- a/lib/prelude.ml
+++ b/lib/prelude.ml
@@ -60,7 +60,7 @@ let source = {flan|
;; condition has an empty sentence, since its fields say what it is.
;;
;; (pause) and warnings are not under Error: a breakpoint is not a failure.
-(defstruct Error [name string message string])
+(defstruct Error [name str message str])
;; The condition every allocating operation signals when the allocator cannot
;; satisfy a request — spec-memory.md, "Allocation failure". It is here rather
@@ -195,7 +195,7 @@ let source = {flan|
;; agreement flan_bounds_cond keeps with BoundsError. No restart is
;; established at the call, BoundsError's decision for BoundsError's reason:
;; nothing a handler supplies makes the old arguments fit the new body.
-(defstruct StaleCall :parent Error [callee string compiled string current string])
+(defstruct StaleCall :parent Error [callee str compiled str current str])
;; A call through a (CFn ...) that holds no function. A CFn may be a struct
;; field, a fixed array's element or a global, and each of those starts out
@@ -206,7 +206,7 @@ let source = {flan|
;; Signalled from the runtime — flan_null_call in runtime/flan_rt.c — so
;; **this field is a C struct that has to agree with this one**. No restart is
;; established at the call, BoundsError's decision for BoundsError's reason.
-(defstruct NullCall :parent Error [type string])
+(defstruct NullCall :parent Error [type str])
;; What a generic function signals when no method answers. `generic` is the
;; name written at the defgeneric or defmulti, and `value` is what the
@@ -228,7 +228,7 @@ let source = {flan|
;;
;; No restart is established at the miss, which is BoundsError's decision
;; taken for BoundsError's reason -- see the note above it.
-(defstruct NoMethod :parent Error [generic string value dyn])
+(defstruct NoMethod :parent Error [generic str value dyn])
;; A breakpoint. (pause) stops the program where it stands and hands it to the
;; break loop, with the whole stack under it readable — C-c C-b lists the
@@ -1282,9 +1282,9 @@ let source = {flan|
;; something. flan_getenv answers a length of -1 and a pointer at a valid empty
;; string, so the test below is arithmetic and the pointer is never dereferenced
;; on the absent path.
-(declare getenv-raw [name string out-len (Ptr i64)] (Ptr u8) "flan_getenv")
+(declare getenv-raw [name str out-len (Ptr i64)] (Ptr u8) "flan_getenv")
-(defn getenv [name string] (Option [u8])
+(defn getenv [name str] (Option [u8])
(let [n (i64 0)
p (getenv-raw name (addr n))]
(if (< n 0)
@@ -1992,7 +1992,7 @@ let source = {flan|
;; does, so an embed costs nothing at run time and nothing at startup. It is
;; also read-only, so `data` is a [const u8] and a store through it is refused
;; at compile time. To get a writable copy, copy the bytes into a Vec.
-(defstruct EmbedFile [name string data [const u8]])
+(defstruct EmbedFile [name str data [const u8]])
;; A linear scan, deliberately. A directory embed is tens of entries, the scan
;; is over names already in cache-warm .rodata, and the alternative — a
@@ -2003,7 +2003,7 @@ let source = {flan|
;; It takes a slice rather than the array (embed-dir) answers, because an array
;; length is part of its type and there are no generics: write
;; (embed-find (slice assets 0 (length assets)) "brush.png").
-(defn embed-find [files [EmbedFile] name string] (Option [const u8])
+(defn embed-find [files [EmbedFile] name str] (Option [const u8])
(dotimes [i (length files)]
(when (bytes=? (bytes-view (.name (at files i))) (bytes-view name))
(return (Some (.data (at files i))))))
@@ -2021,7 +2021,7 @@ let source = {flan|
;; parent link, not class inheritance", decides on is the
;; answer to that, and it is not built; when it is, these reasons can become
;; types without any call site changing.
-(defstruct FileError :parent Error [path string op i32 reason i32])
+(defstruct FileError :parent Error [path str op i32 reason i32])
(defconst file-op-read i32 0)
(defconst file-op-write i32 1)
@@ -2051,7 +2051,7 @@ let source = {flan|
;; each signals FileError with those two restarts. "Is it there" and "how big
;; is it" have no such answer: absence is the reply, not a fault, and a
;; condition would make the ordinary case cost a handler search.
-(declare file-stat-raw [path string out-size (Ptr i64)] i8 "flan_file_stat")
+(declare file-stat-raw [path str out-size (Ptr i64)] i8 "flan_file_stat")
;; True for anything the path resolves to — a file, a directory, a device —
;; because that is what the question asks and a caller wanting "and it is a
@@ -2063,7 +2063,7 @@ let source = {flan|
;; first. Reach for it when the answer is the point — choosing a config path,
;; deciding whether to write a default — and not as a guard in front of an
;; operation that already reports its own failure properly.
-(defn file-exists? [path string] bool
+(defn file-exists? [path str] bool
(let [n (i64 0)]
(= (file-stat-raw path (addr n)) 1)))
@@ -2071,7 +2071,7 @@ let source = {flan|
;; answer — that is the trade a caller makes by asking a question with no
;; restart on it. A caller that needs to tell "missing" from "denied" wants
;; `slurp`, whose FileError carries the reason.
-(defn file-size [path string] (Option i64)
+(defn file-size [path str] (Option i64)
(let [n (i64 0)]
(if (= (file-stat-raw path (addr n)) 1) (Some n) None)))
@@ -2100,10 +2100,10 @@ let source = {flan|
;; process rather than to any source file — nothing else knows better, and
;; every program links this runtime. It is not a file API and `slurp` is; this
;; exists so a macro can look at data at compile time.
-(declare macro-slurp-raw [path string out-len (Ptr i64)] (Ptr u8)
+(declare macro-slurp-raw [path str out-len (Ptr i64)] (Ptr u8)
"flan_macro_slurp")
-(defn macro-slurp [path string] (Option [u8])
+(defn macro-slurp [path str] (Option [u8])
(let [n (i64 0)
p (macro-slurp-raw path (addr n))]
(if (< n 0)
@@ -2131,11 +2131,11 @@ let source = {flan|
;; Case order is the tag order (docs/BUILT.md, data types), so this list is a layout
;; contract with lib/expand.ml's marshaller and may not be reordered.
(defdata Form
- [(Sym [s string])
- (Kw [s string])
+ [(Sym [s str])
+ (Kw [s str])
(Int [i i64])
(Float [x f64])
- (Str [s string])
+ (Str [s str])
(Byte [b i32])
(List [xs [Form]])
(Vec [xs [Form]])
@@ -2182,7 +2182,7 @@ let source = {flan|
;; (head x) for every x, which is what ~~@xs splices into an inner template:
;; one unquote per element, as SBCL's unquote* builds (src/code/backq.lisp).
-(defn form-wrap-each [head string xs [Form]] [Form]
+(defn form-wrap-each [head str xs [Form]] [Form]
(let [v (vec-new Form)]
(dotimes [i (length xs)]
(push v (Form.List {.xs (form-pair (Form.Sym {.s head}) (at xs i))})))
@@ -2219,7 +2219,7 @@ let source = {flan|
(let [d (i64->bytes (gensym-next))]
(dotimes [i (length d)]
(push v (at d i))))
- (Form.Sym {.s (string (slice v))})))
+ (Form.Sym {.s (str (slice v))})))
;; ── The first special form to stop being one ──────────────────────────
;;
@@ -2443,7 +2443,7 @@ let source = {flan|
(Form.List xs) xs
_ (form-nil)))
-(defn form-sym? [f Form name string] bool
+(defn form-sym? [f Form name str] bool
(match f
(Form.Sym s) (bytes=? (bytes-view s) (bytes-view name))
_ false))
diff --git a/lib/render.ml b/lib/render.ml
index 585372be..f9d5ecd9 100644
--- a/lib/render.ml
+++ b/lib/render.ml
@@ -307,7 +307,7 @@ let rec render ?(refuse = print_refusal) c depth (e : Tast.expr) : Tast.expr lis
Not squeamishness about indeterminate bytes — a printer that showed a
number nobody stored would be fine, and every member of a union is a
legal read by this language's own rule. It is that one of those members
- may be a [string] or a [Ptr], and rendering it would dereference
+ may be a [str] or a [Ptr], and rendering it would dereference
whatever bytes happen to be in the union's storage. A tagged data type
is safe to print because its tag says which case is live; there is no
such fact here, so the printer would be following a pointer it invented.
diff --git a/lib/shim.ml b/lib/shim.ml
index 395dedf7..9c817dc1 100644
--- a/lib/shim.ml
+++ b/lib/shim.ml
@@ -9,8 +9,8 @@
[declare-c] says the other thing: the signature is the *library's*, structs
by value and all, and the compiler is to produce whatever flattening makes
it crossable. The two cannot be one form —
- [(declare start-raw [path string] i32 "flan_agent_start")] and
- [(declare-c init-window [w i32 h i32 title string] "InitWindow")] are the
+ [(declare start-raw [path str] i32 "flan_agent_start")] and
+ [(declare-c init-window [w i32 h i32 title str] "InitWindow")] are the
same shape and mean opposite things about who NUL-terminates the string.
Why the crossing is still C, and not [emit.ml]: a small aggregate's calling
@@ -320,7 +320,7 @@ let rec cty env ~needed ~loc ~what (t : Ast.texpr) : string =
"%s is %s, a union, and the shim generator writes structs only. \
Pass (Ptr %s) and let the C side read it"
what n n
- else if String.equal n "string" then
+ else if String.equal n "str" then
fail loc
"%s is a string, and a string crosses only as a parameter or a \
return value — declare (Ptr u8) and read it in Flan"
@@ -379,7 +379,7 @@ type pkind =
let classify env ~needed ~loc ~what (t : Ast.texpr) =
let t' = unalias env t in
match t'.Ast.t with
- | Ast.Tname "string" -> (Pstr, "const char *")
+ | Ast.Tname "str" -> (Pstr, "const char *")
(* A copy crosses behind a pointer only: by value, the Flan half this
generator writes would have to spell the copy's type, and it builds its
wrapper from struct names. *)
@@ -891,7 +891,7 @@ let flan_wrapper ?track (fn : Ast.fn) (s : shim) raw : Ast.decl_kind =
out ],
Some (ty loc (Ast.Tname n)) )
| `Str ->
- (* (string (bytes (string (slice-from p n)))): a view of C's bytes,
+ (* (str (bytes (str (slice-from p n)))): a view of C's bytes,
copied by [bytes] into the context allocator, and seen as a string
again. The length is bound before the pointer is, so its address
exists to be written through. *)
@@ -903,9 +903,9 @@ let flan_wrapper ?track (fn : Ast.fn) (s : shim) raw : Ast.decl_kind =
bval = ex loc (Ast.Int 0L); bloc = loc };
{ Ast.bname = ptr_tmp; bty = None;
bval = call (args @ [ app "addr" [ v len_tmp ] ]); bloc = loc } ];
- ( [ app "string"
+ ( [ app "str"
[ app "bytes"
- [ app "string"
+ [ app "str"
[ app "slice-from" [ v ptr_tmp; v len_tmp ] ] ] ] ],
fn.Ast.ret )
| _ -> ([ call args ], fn.Ast.ret)
@@ -957,7 +957,7 @@ let one env ~taken ~tracks (fn : Ast.fn) csym loc =
let t' = unalias env t in
(match t'.Ast.t with
| Ast.Tname "Unit" -> `Void
- | Ast.Tname "string" -> `Str
+ | Ast.Tname "str" -> `Str
| Ast.Tname n when Hashtbl.mem env.structs n ->
ignore (cty env ~needed ~loc ~what t');
`Struct (n, ctype_name n)
diff --git a/lib/tast.ml b/lib/tast.ml
index cba851e2..be09a3a5 100644
--- a/lib/tast.ml
+++ b/lib/tast.ml
@@ -36,7 +36,7 @@ type prim =
calc-me's tokenizer and the prelude's printers each need. *)
| Bytes | BytesToF64 | BytesToI64 | F64ToBytes | I64ToBytes
(* (string b): the other direction of [Bytes], and the same non-instruction.
- See check.ml's "string" case for why it is unchecked. *)
+ See check.ml's "str" case for why it is unchecked. *)
| StrOfBytes
(* No surface name: the structural printer is the only thing that builds
these. U64ToBytes because u64 is not i64 with a flag, EscapeBytes for a
diff --git a/lib/types.ml b/lib/types.ml
index 7ba99ed4..d7942343 100644
--- a/lib/types.ml
+++ b/lib/types.ml
@@ -44,7 +44,7 @@ type t =
| Array of int64 * t (* [n T] inline, a value, copies *)
| Map of t * t (* (Map K V) *)
| Ptr of access * t (* (Ptr T) (Ptr const T) *)
- (* [Allocator]: a builtin opaque type, the way [string] is a builtin
+ (* [Allocator]: a builtin opaque type, the way [str] is a builtin
ptr+len. It is a [Types.t] case with no user-writable constructor, which
is what lets spec-memory.md's "procedure plus an opaque data pointer" be
expressed with none of milestone 5's function values — the procedure is a
@@ -145,7 +145,7 @@ let bits_f = function F32 -> 32 | F64 -> 64
that already accepts [i32] accepts [int] without learning the word.
Only these two. The rest of the foreign spellings — [long], [double],
- [uint], [str] — stay refusals that teach the Flan name; see
+ [uint], [string] — stay refusals that teach the Flan name; see
[Check.foreign_spelling] for why the line is drawn where it is.
The mapping is one-way on purpose: [ikind_name] and [fkind_name] below
@@ -175,7 +175,7 @@ let fkind_of_name = function
and the identity is a half one. *)
let primitive_names =
[ "i8"; "i16"; "i32"; "i64"; "u8"; "u16"; "u32"; "u64";
- "f32"; "f64"; "bool"; "string"; "dyn"; "Unit"; "Never"; "Allocator";
+ "f32"; "f64"; "bool"; "str"; "dyn"; "Unit"; "Never"; "Allocator";
"int"; "float" ]
let ikind_name k =
@@ -272,7 +272,7 @@ and to_string = function
| Int k -> ikind_name k
| Float k -> fkind_name k
| Bool -> "bool"
- | String -> "string"
+ | String -> "str"
| Unit -> "()"
| Never -> "Never"
| Named n -> (match Hashtbl.find_opt display n with Some d -> d | None -> n)
diff --git a/runtime/flan_dyn.c b/runtime/flan_dyn.c
index 2c9e048f..534f749c 100644
--- a/runtime/flan_dyn.c
+++ b/runtime/flan_dyn.c
@@ -1716,7 +1716,7 @@ static slot_type slot_type_of(const uint8_t *w, int64_t n) {
const char *w; uint8_t kind, fbits; int64_t lo, hi;
} known[] = {
{ "bool", ST_BOOL, 0, 0, 0 },
- { "string", ST_TEXT, 0, 0, 0 },
+ { "str", ST_TEXT, 0, 0, 0 },
{ "f32", ST_FLOAT, 24, 0, 0 },
{ "f64", ST_FLOAT, 53, 0, 0 },
{ "i8", ST_INT, 0, INT8_MIN, INT8_MAX },
diff --git a/spec-conditions.md b/spec-conditions.md
index 5dcba462..0a3d5043 100644
--- a/spec-conditions.md
+++ b/spec-conditions.md
@@ -24,7 +24,7 @@ The consequence is visible in the syntax. A `restart-case` in value position
must produce its type on the *fall-through* path too:
```
-(defn load-texture [path string] (Handle Texture)
+(defn load-texture [path str] (Handle Texture)
(if (file-exists? path)
(rl/load-texture path)
(restart-case
diff --git a/spec-memory.md b/spec-memory.md
index 1701ed4c..ab03cc91 100644
--- a/spec-memory.md
+++ b/spec-memory.md
@@ -53,7 +53,7 @@ it is usually written in — a `let` binding — has no type slot for it to take
them from:
```
-(let [enemies (map-new string Enemy)]
+(let [enemies (map-new str Enemy)]
...)
```
diff --git a/syntax-sketch.flan b/syntax-sketch.flan
index 07bfce3b..4964820f 100644
--- a/syntax-sketch.flan
+++ b/syntax-sketch.flan
@@ -134,7 +134,7 @@
;; `try` unwraps Ok, else early-returns Err, widening this function's error
;; set. Option→Result conversion is explicit — no implicit From, no anyhow.
-(defn load-config [path string] (Result Config)
+(defn load-config [path str] (Result Config)
(let [text (try (read-file path))
table (try (parse-toml text))
port (try (ok-or (get table "port")
@@ -143,7 +143,7 @@
;; errdefer runs only on the Result failure path — NOT on a restart transfer
;; (spec-conditions.md §5). Pairs with explicit allocation.
-(defn load-atlas [path string] (Result Atlas)
+(defn load-atlas [path str] (Result Atlas)
(let [buf (alloc-image context/allocator)]
(errdefer (free buf))
(try (decode-png path buf))
@@ -155,13 +155,13 @@
;; file is fixed on disk. So it offers a menu and the caller chooses.
;; A condition type is an ordinary struct — there is no defcondition, and no
;; class hierarchy to put one in. Matching is by type plus a predicate.
-(defstruct AssetMissing [path string])
+(defstruct AssetMissing [path str])
;; `signal` has type () and RETURNS if every handler returns normally, so the
;; fall-through path of a restart-case in value position must still produce the
;; type. `abort` has type Never, which unifies with (Handle Texture).
;; Every clause body and the restart-case body share one type.
-(defn load-texture [path string] (Handle Texture)
+(defn load-texture [path str] (Handle Texture)
(if (file-exists? path)
(rl/load-texture path)
(restart-case
@@ -176,7 +176,7 @@
;; then the body. It is not a type paired with an `fn`, and a handler closes
;; over nothing: it is lifted into its own function, so a value it wants to keep
;; goes on the condition or into a global.
-(defn load-level [path string] Level
+(defn load-level [path str] Level
(handler-bind [(AssetMissing [c]
(log "missing asset:" (.path c))
(invoke-restart 'use-placeholder))]
@@ -195,7 +195,7 @@
(skip-form [] (skip-to-next-delimiter p))))
forms))
-(defn collect-parse-errors [src string] (Result Ast)
+(defn collect-parse-errors [src str] (Result Ast)
(let [errors (make-vec ParseError)]
(handler-bind [(ParseError [c]
(push errors c) ; value struct: copies out of
@@ -218,7 +218,7 @@
;; ── defer for explicit resources ──────────────────────────────────────
;; defer DOES run when a restart transfer passes through this frame.
-(defn save-world [w (Ptr World) path string] ()
+(defn save-world [w (Ptr World) path str] ()
(let [f (open path :write)]
(defer (close f))
(write-bytes f (serialize w))))
@@ -235,7 +235,7 @@
;; An imperative loop, not (each (fn [p] (try ...))): `try` and `return` inside a
;; `fn` exit the FN, so a callback would swallow the Err instead of propagating
;; it out of preload.
-(defn ^:async preload [paths [string]] (Result ())
+(defn ^:async preload [paths [str]] (Result ())
(for [p paths]
(try (await (load-texture-async p))))
(Ok unit))
diff --git a/test/programs/agent-queue.flan b/test/programs/agent-queue.flan
index a2bf450d..ebebe84e 100644
--- a/test/programs/agent-queue.flan
+++ b/test/programs/agent-queue.flan
@@ -19,7 +19,7 @@
(set ticks (+ ticks 1))
ticks)
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(if (< (length args) 2)
(do (println "usage: agent-queue ") 2)
(do
diff --git a/test/programs/agent.flan b/test/programs/agent.flan
index 2cea4975..593198f4 100644
--- a/test/programs/agent.flan
+++ b/test/programs/agent.flan
@@ -19,7 +19,7 @@
(set ticks (+ ticks 1))
ticks)
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(if (< (length args) 2)
(do (println "usage: agent ") 2)
(do
diff --git a/test/programs/algorithms.flan b/test/programs/algorithms.flan
index 9f4aabea..7b5a56d3 100644
--- a/test/programs/algorithms.flan
+++ b/test/programs/algorithms.flan
@@ -15,7 +15,7 @@
(defn show-fields [s [[const u8]]] ()
(dotimes [i (length s)]
- (print (string (at s i)))
+ (print (str (at s i)))
(print " "))
(println ""))
@@ -114,7 +114,7 @@
(let [f (split (bytes-view "delta,alpha,charlie,bravo") \,)]
(sort-bytes (slice f))
(let [j (join (slice f) (bytes-view " < "))]
- (println (string (slice j))) ; alpha < bravo < charlie < delta
+ (println (str (slice j))) ; alpha < bravo < charlie < delta
(free j))
(free f))
0)
diff --git a/test/programs/arena-region.flan b/test/programs/arena-region.flan
index 69077139..aeb68d08 100644
--- a/test/programs/arena-region.flan
+++ b/test/programs/arena-region.flan
@@ -23,7 +23,7 @@
(defdata Value [Nil (Int [n i64]) (List [items (Vec Value)])])
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(set frame (arena-new 4096))
(let [which (if (> (length args) 1) (i32 (bytes->i64 (bytes-view (at args 1)))) 0)]
(cond
diff --git a/test/programs/arena-value.flan b/test/programs/arena-value.flan
index 8fd9a508..ff7b0802 100644
--- a/test/programs/arena-value.flan
+++ b/test/programs/arena-value.flan
@@ -19,9 +19,9 @@
(defdata Value
[(Nil [])
(Int [n i64])
- (Text [s string])
+ (Text [s str])
(List [items (Vec Value)])
- (Table [entries (Map string Value)])])
+ (Table [entries (Map str Value)])])
;; [0 1 .. n-1] as a dynamic list. No allocator is named: with-allocator in
;; main has rebound the context, and spec-memory.md puts the allocator in the
@@ -36,7 +36,7 @@
;; A table whose values are themselves lists, so the graph is three levels
;; deep before it reaches a leaf: Table -> Vec -> List -> Vec -> Int.
(defn a-table [] Value
- (let [entries (map-new string Value)]
+ (let [entries (map-new str Value)]
(put entries "xs" (number-list 3))
(put entries "ys" (number-list 5))
(put entries "name" (Value.Text {.s "edn"}))
diff --git a/test/programs/arith-condition.flan b/test/programs/arith-condition.flan
index db7881f6..264bcec2 100644
--- a/test/programs/arith-condition.flan
+++ b/test/programs/arith-condition.flan
@@ -61,7 +61,7 @@
(defonce small f64 -1e300)
(defonce uz u32)
-(defn show [name string n i64] ()
+(defn show [name str n i64] ()
(print name) (print " ") (print n) (println ""))
;;; Two frames deep with a defer on the way, so the transfer has something to
diff --git a/test/programs/arith.flan b/test/programs/arith.flan
index e8d200da..ed9c7ee4 100644
--- a/test/programs/arith.flan
+++ b/test/programs/arith.flan
@@ -30,7 +30,7 @@
(defonce m1-32 i32 -1)
(defonce wide f32 1e30)
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [n (i32 (bytes->i64 (bytes-view (at args 1))))
;; The most negative i64. No literal spells it — the reader parses the
;; digits and then negates, and the positive half does not fit — so it
diff --git a/test/programs/bounds-condition.flan b/test/programs/bounds-condition.flan
index 6f394c56..cac3dd9b 100644
--- a/test/programs/bounds-condition.flan
+++ b/test/programs/bounds-condition.flan
@@ -58,7 +58,7 @@
;;; Two frames deep, with a defer on the way, so the transfer has something to
;;; cross and something to run on its way out.
-(defn show [name string n i64] ()
+(defn show [name str n i64] ()
(print name) (print " ") (print n) (println ""))
(defn read-cell [i i32] i32
diff --git a/test/programs/bounds.flan b/test/programs/bounds.flan
index ff767eff..7daf8f7d 100644
--- a/test/programs/bounds.flan
+++ b/test/programs/bounds.flan
@@ -15,7 +15,7 @@
;;;; (that is a separate job) and lets LLVM fold the branch away here.
(defonce arr [3 i32])
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [n (i32 (bytes->i64 (bytes-view (at args 1))))
s (bytes-view "hello")] ; len 5
(cond
diff --git a/test/programs/builtin-qualified.flan b/test/programs/builtin-qualified.flan
index 27d6bf97..cf9a00e9 100644
--- a/test/programs/builtin-qualified.flan
+++ b/test/programs/builtin-qualified.flan
@@ -37,7 +37,7 @@
;;; one.
;;; Both additions are qualified too, since + is shadowed below and this
;;; function wants the arithmetic and not the 99.
-(defn length [s string] i32 (builtin/+ 1 (builtin/length s)))
+(defn length [s str] i32 (builtin/+ 1 (builtin/length s)))
(defn + [a i32 b i32] i32 99)
diff --git a/test/programs/bytes-copy.flan b/test/programs/bytes-copy.flan
index d198c27b..add2c27f 100644
--- a/test/programs/bytes-copy.flan
+++ b/test/programs/bytes-copy.flan
@@ -13,7 +13,7 @@
(let [s "INSERTIONSORT"
b (bytes s)]
(set (at b 0) \Z)
- (println (string b)) ; ZNSERTIONSORT
+ (println (str b)) ; ZNSERTIONSORT
(println s) ; INSERTIONSORT
;; The copy's block came from the context allocator, and free hands it
;; back there — which is what keeps this program leak-free.
@@ -23,7 +23,7 @@
;; at -O0 and silently do nothing at -O2.
(let [b (bytes "hi")]
(set (at b 0) \H)
- (println (string b)) ; Hi
+ (println (str b)) ; Hi
(free b))
;; 3. The view still costs nothing and reads the string's own storage.
@@ -36,7 +36,7 @@
(set frame (arena-new 4096))
(let [b (bytes "arena" frame)]
(set (at b 4) \A)
- (println (string b))) ; arenA
+ (println (str b))) ; arenA
(free-all frame)
(arena-destroy frame)
diff --git a/test/programs/bytes-view-write.flan b/test/programs/bytes-view-write.flan
index 68184fc6..c273f520 100644
--- a/test/programs/bytes-view-write.flan
+++ b/test/programs/bytes-view-write.flan
@@ -7,5 +7,5 @@
(defn main [] i32
(let [v (bytes-view "INSERTIONSORT")]
(set (at v 0) \Z)
- (print (string v))
+ (print (str v))
0))
diff --git a/test/programs/bytes2.flan b/test/programs/bytes2.flan
index 9a2a8135..5cc3575c 100644
--- a/test/programs/bytes2.flan
+++ b/test/programs/bytes2.flan
@@ -21,7 +21,7 @@
;; Brackets around the result so an empty trim is visible as [] rather than
;; as nothing at all — the all-whitespace case is otherwise indistinguishable
;; from a trim that printed the wrong slice of length zero.
-(defn show-trim [s string] ()
+(defn show-trim [s str] ()
(print "[")
(print (trim (bytes-view s)))
(print "]"))
diff --git a/test/programs/chain.flan b/test/programs/chain.flan
index 74fc61d2..36fad0ed 100644
--- a/test/programs/chain.flan
+++ b/test/programs/chain.flan
@@ -16,12 +16,12 @@
;; Prints its tag and answers its value. Every operand below is one of these,
;; so the tag line is a transcript of the evaluation.
-(defn mark [tag string v i32] i32
+(defn mark [tag str v i32] i32
(set calls (+ calls 1))
(print tag)
v)
-(defn markf [tag string v f64] f64
+(defn markf [tag str v f64] f64
(print tag)
v)
diff --git a/test/programs/condition-longmessage.flan b/test/programs/condition-longmessage.flan
index 3991b7ef..44222a87 100644
--- a/test/programs/condition-longmessage.flan
+++ b/test/programs/condition-longmessage.flan
@@ -5,7 +5,7 @@
;;;; before 1100 two-byte characters, so a cut at a fixed byte count would
;;;; land inside one.
-(defstruct Wide :parent Error [code i32 why string])
+(defstruct Wide :parent Error [code i32 why str])
(defstruct Longs :parent Error)
(defn main [] i32
diff --git a/test/programs/condition-messages.flan b/test/programs/condition-messages.flan
index fcb51192..2f3858f3 100644
--- a/test/programs/condition-messages.flan
+++ b/test/programs/condition-messages.flan
@@ -5,7 +5,7 @@
(defstruct IoError :parent Error)
(defstruct Empty :parent Error [])
-(defstruct MyErr :parent Error [code i32 why string])
+(defstruct MyErr :parent Error [code i32 why str])
(defonce zero i64)
diff --git a/test/programs/condition-temp.flan b/test/programs/condition-temp.flan
index ca69bb24..e1f91997 100644
--- a/test/programs/condition-temp.flan
+++ b/test/programs/condition-temp.flan
@@ -7,7 +7,7 @@
(defstruct MyErr :parent Error [code i32])
-(defn why [] string
+(defn why [] str
(handler-case (do (error (MyErr {.code 3})) "")
[(Error [e] (.message e))]))
diff --git a/test/programs/const-slice.flan b/test/programs/const-slice.flan
index 0790348e..2edd3d7f 100644
--- a/test/programs/const-slice.flan
+++ b/test/programs/const-slice.flan
@@ -39,7 +39,7 @@
(sort w)
(println (total w) (total (slice w 1)))
(println (first-of w) (first-of (bytes-view "z")))
- (println (string head) (string tail) (length head))
+ (println (str head) (str tail) (length head))
(println (bytes=? head (bytes-view "hello")) (starts-with? r head))
(push names head)
(push names tail)
@@ -51,15 +51,15 @@
both [a b]]
(println (widths (slice both)))
(set (at a 0) \A)
- (println (string a)))
+ (println (str a)))
(let [f (split (bytes-view "b,a,c") \,)]
(sort-bytes (slice f))
- (println (string (slice (join (slice f) (bytes-view "-"))))))
+ (println (str (slice (join (slice f) (bytes-view "-"))))))
(println (at r 0))
(println (call-rd rd) (call-bare rd) (call-mk mk))
(let [b (bytes "q")]
(println (peek (addr (at r 1))) (peek (addr (at "abc" 2)))
(peek (addr (at b 0)))
- (string (slice-from (addr (at r 7)) 5))))
+ (str (slice-from (addr (at r 7)) 5))))
(free names))
0)
diff --git a/test/programs/context-destroyed.flan b/test/programs/context-destroyed.flan
index 65de8c53..5cd02cc8 100644
--- a/test/programs/context-destroyed.flan
+++ b/test/programs/context-destroyed.flan
@@ -4,7 +4,7 @@
;;;; destroyed arena's record. Allocating from the context must then trap,
;;;; not quietly allocate from the new arena. Argument 1 reads context/allocator
;;;; as a value first and uses that instead, which traps the same way.
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [which (if (> (length args) 1) (bytes->i64 (bytes-view (at args 1))) 0)
a (arena-new 4096)]
(with-allocator a
diff --git a/test/programs/cstr-return.flan b/test/programs/cstr-return.flan
index f93e1452..94c06a80 100644
--- a/test/programs/cstr-return.flan
+++ b/test/programs/cstr-return.flan
@@ -19,8 +19,8 @@
(let [path (vec-new u8)]
(append (addr path) (bytes-view "dir/"))
(dotimes [i 300] (push path \x))
- (let [tail (cret/after-slash (string (slice path)))
- long-name (string (slice path 4))]
+ (let [tail (cret/after-slash (str (slice path)))
+ long-name (str (slice path 4))]
(println (length tail))
(println (= tail long-name))))
(println (length (cret/nothing)))
diff --git a/test/programs/datas.flan b/test/programs/datas.flan
index bb23d139..56b40d5a 100644
--- a/test/programs/datas.flan
+++ b/test/programs/datas.flan
@@ -13,7 +13,7 @@
[Empty
(Dot [x f64 y f64])
(Rect [w i32 h i32])
- (Tag [name string n u8])])
+ (Tag [name str n u8])])
;; A union crosses a call boundary in both directions, as a parameter and as a
;; return type -- a value that cannot do that is not a value.
@@ -29,7 +29,7 @@
;; alignment visible to something other than a slot.
(defstruct Cell [id i32 s Shape])
-(defn describe [s Shape] string
+(defn describe [s Shape] str
(match s
Empty "empty"
(Dot x y) (if (= x y) "dot on the diagonal" "dot")
@@ -100,7 +100,7 @@
;; and not unions, so (vec-new Shape) was refused for not saying what it
;; held -- by a program that had said.
(let [vs (vec-new Shape)
- ms (map-new string Shape)]
+ ms (map-new str Shape)]
(push vs (Shape.Rect {.w 2 .h 3}))
(push vs Shape.Empty)
(put ms "only" (Shape.Tag {.name "in a map" .n 1}))
diff --git a/test/programs/debug-permuted.flan b/test/programs/debug-permuted.flan
index 0b5c66b9..7b2d4abb 100644
--- a/test/programs/debug-permuted.flan
+++ b/test/programs/debug-permuted.flan
@@ -7,7 +7,7 @@
;;;; members here, which is what makes the pair a test rather than an
;;;; observation.
-(defstruct Cell [name string id i32 alive bool heat f64])
+(defstruct Cell [name str id i32 alive bool heat f64])
(defn tick [c (Ptr Cell) n i32] i32
(let [bump (+ n 1)]
diff --git a/test/programs/debug.flan b/test/programs/debug.flan
index 9e29a605..1461643b 100644
--- a/test/programs/debug.flan
+++ b/test/programs/debug.flan
@@ -12,7 +12,7 @@
;;;; wrong, because it is the only one whose own alignment exceeds its first
;;;; member's size.
-(defstruct Cell [alive bool heat f64 id i32 name string])
+(defstruct Cell [alive bool heat f64 id i32 name str])
(defn tick [c (Ptr Cell) n i32] i32
(let [bump (+ n 1)]
diff --git a/test/programs/destroy-region.flan b/test/programs/destroy-region.flan
index 7bc972de..e2e3581c 100644
--- a/test/programs/destroy-region.flan
+++ b/test/programs/destroy-region.flan
@@ -21,7 +21,7 @@
;;;; Argument 3 makes and destroys arenas in a loop, as many times as the
;;;; second argument says. A retired allocator is reused rather than kept, so
;;;; the loop's memory stays flat however long it runs.
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [which (if (> (length args) 1) (i32 (bytes->i64 (bytes-view (at args 1)))) 0)
a (arena-new 4096)]
(cond
diff --git a/test/programs/destructure.flan b/test/programs/destructure.flan
index 2fbfadf4..27cd0129 100644
--- a/test/programs/destructure.flan
+++ b/test/programs/destructure.flan
@@ -22,7 +22,7 @@
(set calls (+ calls 1))
(Point {.x 3 .y 4}))
-(defn show2 [label string a i32 b i32] ()
+(defn show2 [label str a i32 b i32] ()
(print label)
(print " ")
(print a)
diff --git a/test/programs/dev-globals.flan b/test/programs/dev-globals.flan
index 10da4d63..954776a9 100644
--- a/test/programs/dev-globals.flan
+++ b/test/programs/dev-globals.flan
@@ -16,7 +16,7 @@
(defstruct Boom [why i32])
-(defonce label string)
+(defonce label str)
(defonce grid [4 i32])
(defonce pressure i64)
(defonce untouched i64 99)
diff --git a/test/programs/dev-locals.flan b/test/programs/dev-locals.flan
index 8af737a2..1ca6415a 100644
--- a/test/programs/dev-locals.flan
+++ b/test/programs/dev-locals.flan
@@ -11,7 +11,7 @@
(defstruct Point [x f32 y f32])
(defstruct Boom [why i32])
-(defn look [n i64 label string] i64
+(defn look [n i64 label str] i64
(let [p (Point {.x 1.5 .y 2.5})
xs [10 20 30]
flag (> n 0)
diff --git a/test/programs/dev-macro.flan b/test/programs/dev-macro.flan
index a5f6ab70..62678def 100644
--- a/test/programs/dev-macro.flan
+++ b/test/programs/dev-macro.flan
@@ -18,7 +18,7 @@
(defonce ticks i64)
-(defn parity [n i64] string
+(defn parity [n i64] str
(let [out "even"]
(unless (= 0 (% n 2))
(set out "odd"))
diff --git a/test/programs/dev-parity.flan b/test/programs/dev-parity.flan
index f079ec36..11921d17 100644
--- a/test/programs/dev-parity.flan
+++ b/test/programs/dev-parity.flan
@@ -34,7 +34,7 @@
(defonce odd f64)
(defonce yes bool)
(defonce byte u8)
-(defonce text string)
+(defonce text str)
(defonce colour Colour)
(defonce stray Colour)
(defonce some (Option Point))
diff --git a/test/programs/dev-temp-destroy.flan b/test/programs/dev-temp-destroy.flan
index c6e30af7..f4231112 100644
--- a/test/programs/dev-temp-destroy.flan
+++ b/test/programs/dev-temp-destroy.flan
@@ -20,7 +20,7 @@
(defn hold [] i32
(set tv context/temp)
(let [r (fetch)]
- (println (string (i64->bytes 31)))
+ (println (str (i64->bytes 31)))
r))
(defn main [] i32
diff --git a/test/programs/dev-temp-stop.flan b/test/programs/dev-temp-stop.flan
index 666f3e09..3947379b 100644
--- a/test/programs/dev-temp-stop.flan
+++ b/test/programs/dev-temp-stop.flan
@@ -20,7 +20,7 @@
(defn hold [] i32
(set keep (vec-new u8 context/temp))
(push keep (u8 5))
- (let [s (string (i64->bytes 4242))
+ (let [s (str (i64->bytes 4242))
r (fetch)]
(println s)
(println (length keep))
diff --git a/test/programs/dev-watch.flan b/test/programs/dev-watch.flan
index 5c65e201..0c335550 100644
--- a/test/programs/dev-watch.flan
+++ b/test/programs/dev-watch.flan
@@ -10,13 +10,13 @@
;;;; at frame rate and the editor reads memory.
(import agent "vendor:agent")
-(declare-c watch-i64 [name string x i64] i32 "flan_dev_watch_i64")
-(declare-c watch-f64 [name string x f64] i32 "flan_dev_watch_f64")
-(declare-c watch-str [name string s string] i32 "flan_dev_watch_str")
+(declare-c watch-i64 [name str x i64] i32 "flan_dev_watch_i64")
+(declare-c watch-f64 [name str x f64] i32 "flan_dev_watch_f64")
+(declare-c watch-str [name str s str] i32 "flan_dev_watch_str")
;; The accumulator, for a value sampled from inside a hot loop. A scalar watch
;; there shows whichever iteration happened to run last, which is the case this
;; exists for; see flan_dev.c, "A number sampled thousands of times a frame".
-(declare-c watch-num-i64 [name string x i64] i32 "flan_dev_watch_num_i64")
+(declare-c watch-num-i64 [name str x i64] i32 "flan_dev_watch_num_i64")
(defonce ticks i64)
diff --git a/test/programs/dyn-class-slots.flan b/test/programs/dyn-class-slots.flan
index 8d3181f1..662d1ade 100644
--- a/test/programs/dyn-class-slots.flan
+++ b/test/programs/dyn-class-slots.flan
@@ -10,7 +10,7 @@
;;;; exists and (get s :pause) is a place, where a plain map's absent key is
;;;; not. dyn-slot-trap.flan has the refusals.
-(defclass state [pause bool step i32 speed f64 name string tag])
+(defclass state [pause bool step i32 speed f64 name str tag])
;; A class is a slot type, and (Option T) admits nil beside a T.
(defclass node [owner state next (Option node) weight (Option f32)])
diff --git a/test/programs/dyn-held-operand.flan b/test/programs/dyn-held-operand.flan
index dfefc044..ee278a86 100644
--- a/test/programs/dyn-held-operand.flan
+++ b/test/programs/dyn-held-operand.flan
@@ -45,7 +45,7 @@
(defn pick [x dyn n i64] dyn x)
(defn pick-t [t T n i64] dyn (.d t))
-(defn show [label string v dyn] ()
+(defn show [label str v dyn] ()
(churn)
(println label (at v 0) (at v 1)))
diff --git a/test/programs/dyn-index-site.flan b/test/programs/dyn-index-site.flan
index a89d54c5..2564fd16 100644
--- a/test/programs/dyn-index-site.flan
+++ b/test/programs/dyn-index-site.flan
@@ -10,7 +10,7 @@
(defonce tv (Vec i64))
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [which (if (> (length args) 1) (i32 (bytes->i64 (bytes-view (at args 1)))) 0)
v (vec-new dyn)
ar (arena-new 4096)]
diff --git a/test/programs/dyn-slice.flan b/test/programs/dyn-slice.flan
index b726b91c..bddb9c0b 100644
--- a/test/programs/dyn-slice.flan
+++ b/test/programs/dyn-slice.flan
@@ -3,7 +3,7 @@
;;
;; With an argument, the last slice runs past the end and traps.
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [d (the dyn "hello")]
(println (slice d))
(println (slice d 1))
diff --git a/test/programs/dyn-slot-trap.flan b/test/programs/dyn-slot-trap.flan
index 890489bc..4d2f4b7b 100644
--- a/test/programs/dyn-slot-trap.flan
+++ b/test/programs/dyn-slot-trap.flan
@@ -6,7 +6,7 @@
(defn as-dyn [d dyn] dyn d)
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [which (if (> (length args) 1) (i32 (bytes->i64 (bytes-view (at args 1)))) 0)
s (state false 3 nil)]
(println "before")
diff --git a/test/programs/dyn-type-of.flan b/test/programs/dyn-type-of.flan
index f5676b99..37bcf5ce 100644
--- a/test/programs/dyn-type-of.flan
+++ b/test/programs/dyn-type-of.flan
@@ -14,7 +14,7 @@
(let [n (the i32 7)
f (the f32 1.5)
b (the bool true)
- s (the string "typed")]
+ s (the str "typed")]
(println (type-of nil))
(println (type-of true))
(println (type-of 42))
diff --git a/test/programs/dyn-view.flan b/test/programs/dyn-view.flan
index bf7699c7..f3b57cbf 100644
--- a/test/programs/dyn-view.flan
+++ b/test/programs/dyn-view.flan
@@ -54,7 +54,7 @@
;; carries that pair, because a refusal cannot run.
(defonce rows [2 (Vec i64)])
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [n (i32 (bytes->i64 (bytes-view (at args 1))))]
(cond
(= n 0)
diff --git a/test/programs/edn-provide.flan b/test/programs/edn-provide.flan
index 2d36ccd7..12511e6f 100644
--- a/test/programs/edn-provide.flan
+++ b/test/programs/edn-provide.flan
@@ -66,7 +66,7 @@
;; The struct says :name :hp :speed :boss? :drops :hitbox. These bytes have no
;; :speed and have a :level the struct has never heard of, which is what a
;; tuning file looks like a month after the program was built.
-(defconst drifted string
+(defconst drifted str
"{:name \"imp\" :hp 3 :level 7 :boss? true :drops [1] :hitbox {:w 1 :h 1 :offset {:x 0 :y 0}}}")
(defn show-drift [a Allocator] ()
@@ -93,7 +93,7 @@
;; that — read-file answers an Option so that a malformed document is
;; distinguishable from one that is literally nil — and a derived reader has to
;; be at least as honest.
-(defconst broken string "{:name \"orc\" :hp }")
+(defconst broken str "{:name \"orc\" :hp }")
(defn show-broken [a Allocator] ()
(handler-bind
diff --git a/test/programs/edn-read.flan b/test/programs/edn-read.flan
index 9cf5c82f..4deb4908 100644
--- a/test/programs/edn-read.flan
+++ b/test/programs/edn-read.flan
@@ -54,12 +54,12 @@
;; The size of a set after the dedup, which is the whole of what the dedup can
;; be asked for.
-(defn set-size [src string] ()
+(defn set-size [src str] ()
(println (length (edn/read (bytes-view src)))))
;; Malformed input, told apart from the document `nil` by the cursor — the
;; return value alone cannot say it, and this is the spelling that can.
-(defn malformed? [src string] bool
+(defn malformed? [src str] bool
(let [c (edn/cursor (bytes-view src))
t (edn/next (addr c))
v (edn/read-value (addr c) t)] ; the value is not the question here
diff --git a/test/programs/edn.flan b/test/programs/edn.flan
index 10757311..0814a7c2 100644
--- a/test/programs/edn.flan
+++ b/test/programs/edn.flan
@@ -18,7 +18,7 @@
;; wrong — off by the quote, off by the colon — would pass on the letters
;; alone.
-(defn kind-letter [k i32] string
+(defn kind-letter [k i32] str
(cond
(= k edn/tok-eof) "."
(= k edn/tok-error) "!"
@@ -40,7 +40,7 @@
(= k edn/tok-set-open) "#"
:else "?"))
-(defn dump [src string] ()
+(defn dump [src str] ()
(let [b (bytes-view src)
c (edn/cursor b)
t (edn/next (addr c))]
@@ -58,7 +58,7 @@
;; The refusals. Asserted on the *reason*, not on the fact of failing: a
;; tokenizer that answered err-unexpected-byte for every one of these would
;; pass a test that only checked that it failed.
-(defn refusal [src string] ()
+(defn refusal [src str] ()
(let [b (bytes-view src)
c (edn/cursor b)]
(while (and (edn/ok? (addr c))
@@ -121,7 +121,7 @@
(return e)))))
e))
-(defn show-enemy [src string] ()
+(defn show-enemy [src str] ()
(let [b (bytes-view src)
c (edn/cursor b)
e (read-enemy (addr c))]
diff --git a/test/programs/embed.flan b/test/programs/embed.flan
index 051c017a..5a306859 100644
--- a/test/programs/embed.flan
+++ b/test/programs/embed.flan
@@ -20,13 +20,13 @@
;; The default answer is a [u8]: bytes, because that is what an asset is.
(let [a (embed "assets/a.txt")]
(println (length a)) ; 13
- (print (string a))) ; hello from a
+ (print (str a))) ; hello from a
;; `string` is the second spelling, not a different meaning for the same
;; text. With structural equality and nothing that converts one container
;; into another -- implicit widening is numbers only -- one form that changes
;; type with its context would be a wart.
- (println (embed "assets/b.bin" string)) ; BBB
+ (println (embed "assets/b.bin" str)) ; BBB
;; Byte-exact, including bytes no text encoding would survive: emit.ml's
;; escape hex-escapes everything outside printable ASCII, so a PNG makes the
@@ -50,7 +50,7 @@
;; there are no generics.
(let [all (slice assets 0 (length assets))]
(match (embed-find all "b.bin")
- (Some b) (println (string b)) ; BBB
+ (Some b) (println (str b)) ; BBB
None (println "missing"))
(match (embed-find all "nope.txt")
(Some _) (println "found")
diff --git a/test/programs/enum-convert.flan b/test/programs/enum-convert.flan
index a3617a4c..a1ccfaf5 100644
--- a/test/programs/enum-convert.flan
+++ b/test/programs/enum-convert.flan
@@ -18,7 +18,7 @@
;; An enum parameter driven by a loop variable, which is the shape this exists
;; for: the caller has an index, not a member.
-(defn name-at [i i32] string
+(defn name-at [i i32] str
(let [k (K i)]
(cond (= k :lo) "lo"
(= k :mid) "mid"
diff --git a/test/programs/fn-cfn-table.flan b/test/programs/fn-cfn-table.flan
index 3d796620..d14bf451 100644
--- a/test/programs/fn-cfn-table.flan
+++ b/test/programs/fn-cfn-table.flan
@@ -10,13 +10,13 @@
(defn double [x i32] i32 (* x 2))
(defn negate [x i32] i32 (- 0 x))
-(defstruct Ops [name string run (CFn [i32] i32)])
+(defstruct Ops [name str run (CFn [i32] i32)])
(defonce table [3 (CFn [i32] i32)])
(defonce hook (CFn [i32] i32))
(defonce evaluated i32 0)
(defonce caught i32 0)
-(defonce seen string "")
+(defonce seen str "")
(defn arg [x i32] i32
(set evaluated (+ evaluated 1))
@@ -27,7 +27,7 @@
(do (print (f (arg x))) (println ""))
(continue [] (println "empty"))))
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(set (at table 0) double)
(set (at table 2) negate)
(let [ops (Ops {.name "half-built"})]
diff --git a/test/programs/fn-escape.flan b/test/programs/fn-escape.flan
index b990128e..7f2a390e 100644
--- a/test/programs/fn-escape.flan
+++ b/test/programs/fn-escape.flan
@@ -51,7 +51,7 @@
(push msg who)
(fn [] (i64 (length msg)))))
-(defstruct Button [label string on-click (Option (Fn [] i64))])
+(defstruct Button [label str on-click (Option (Fn [] i64))])
(defonce handler (Option (Fn [i64] i64)))
diff --git a/test/programs/fn-in-map.flan b/test/programs/fn-in-map.flan
index 95c844ed..9a7d3688 100644
--- a/test/programs/fn-in-map.flan
+++ b/test/programs/fn-in-map.flan
@@ -17,7 +17,7 @@
(push junk true))))
(defn main [] i32
- (let [ops (map-new string (Fn [i32] i32))
+ (let [ops (map-new str (Fn [i32] i32))
many (map-new i32 (Fn [i32] i32))
rows (map-new i32 dyn)]
(put ops "one" (adder 1))
diff --git a/test/programs/format.flan b/test/programs/format.flan
index c042c9a2..e558b84b 100644
--- a/test/programs/format.flan
+++ b/test/programs/format.flan
@@ -11,7 +11,7 @@
(defn show [x f64 p i32] ()
(let [v (format-f64 x p)]
- (println (string (slice v)))
+ (println (str (slice v)))
(free v)))
(defn main [] i32
@@ -95,6 +95,6 @@
(let [f (format-f64 0.0166667 4)]
(append (addr b) (slice f))
(free f))
- (println (string (slice b))) ; fps 59.9 / frame 0.0167
+ (println (str (slice b))) ; fps 59.9 / frame 0.0167
(free b))
0)
diff --git a/test/programs/frame-rollback.flan b/test/programs/frame-rollback.flan
index 1fae5248..8778ac92 100644
--- a/test/programs/frame-rollback.flan
+++ b/test/programs/frame-rollback.flan
@@ -109,7 +109,7 @@
(when (!= (.brush world) (.brush world-backup)) (set d (+ d 1)))
d))
-(defn show [name string n i64] ()
+(defn show [name str n i64] ()
(print name) (print " ") (print n) (println ""))
(defn dump [] ()
diff --git a/test/programs/free-slice.flan b/test/programs/free-slice.flan
index 537c91f7..79a0c346 100644
--- a/test/programs/free-slice.flan
+++ b/test/programs/free-slice.flan
@@ -6,7 +6,7 @@
;;;; 3 frees a view of an array, which no allocator handed out; 4 frees a
;;;; Vec's storage through a let-bound view of it; 5 frees a formatted
;;;; number's text, which the temp allocator holds.
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [which (if (> (length args) 1) (bytes->i64 (bytes-view (at args 1))) 0)
a (arena-new 4096)]
(cond
@@ -26,7 +26,7 @@
(let [b (bytes "heap")
c (bytes "arena" a)
d (clone (slice [1.5 2.5]) (heap-allocator))]
- (println (string b) (string c) (at d 1))
+ (println (str b) (str c) (at d 1))
(free b)
(free c a)
(free d (heap-allocator))))
diff --git a/test/programs/int-float.flan b/test/programs/int-float.flan
index 20a90424..6a560237 100644
--- a/test/programs/int-float.flan
+++ b/test/programs/int-float.flan
@@ -6,7 +6,7 @@
;;;; position that takes i32 takes int, the cast head included, and nothing
;;;; downstream of the checker ever hears the word.
;;;;
-;;;; The rest of the foreign spellings -- long, double, integer, str -- are
+;;;; The rest of the foreign spellings -- long, double, integer, string -- are
;;;; still refusals that teach the Flan name, which a program cannot show
;;;; because it would not compile; that half is in test_flan.ml.
@@ -41,7 +41,7 @@
;; Generic type arguments: the element type of a Vec and both halves of a
;; Map, named with the alias.
(let [v (vec-new int)
- m (map-new string int)]
+ m (map-new str int)]
(push v 10)
(push v 20)
(put m "k" 30)
diff --git a/test/programs/json.flan b/test/programs/json.flan
index 73be92bc..64a22616 100644
--- a/test/programs/json.flan
+++ b/test/programs/json.flan
@@ -44,7 +44,7 @@
;; its backslash still on it; that is the divergence between the tokenizer and
;; string-of, and this is where it is visible.
-(defn kind-letter [k i32] string
+(defn kind-letter [k i32] str
(cond
(= k json/tok-eof) "."
(= k json/tok-error) "!"
@@ -61,7 +61,7 @@
(= k json/tok-comma) ","
:else "?"))
-(defn dump [src string] ()
+(defn dump [src str] ()
(let [b (bytes-view src)
c (json/cursor b)
t (json/next (addr c))]
@@ -79,7 +79,7 @@
;; The refusals. Asserted on the *reason* and not on the fact of failing: a
;; tokenizer answering one generic error for all of these would pass a test
;; that only checked that it stopped.
-(defn refusal [src string] ()
+(defn refusal [src str] ()
(let [b (bytes-view src)
c (json/cursor b)]
(while (and (json/ok? (addr c))
@@ -96,9 +96,9 @@
(Bool [b bool])
(Int [n i64])
(Float [x f64])
- (Text [s string])
+ (Text [s str])
(Array [items (Vec Value)])
- (Object [entries (Map string Value)])])
+ (Object [entries (Map str Value)])])
;; One token in hand, and the cursor for whatever the token opens. An array and
;; an object recurse; everything else is a leaf.
@@ -160,7 +160,7 @@
;; same string-of the values use, so the map owns its keys and the source
;; buffer is not in the picture.
(= (.kind t) json/tok-object-open)
- (let [entries (map-new string Value)
+ (let [entries (map-new str Value)
k (json/next c)
more (and (json/ok? c) (!= (.kind k) json/tok-object-close))]
(while more
@@ -234,14 +234,14 @@
(match (get entries "xs") (Some x) (sum-ints x) None (i64 0))
_ (i64 0)))
-(defn describe [v Value] string
+(defn describe [v Value] str
(match v
Null "null" (Bool _b) "bool" (Int _n) "int" (Float _x) "float"
(Text _s) "string" (Array _i) "array" (Object _e) "object"))
;; The text at a top-level key, or a marker. Used after the source buffer has
;; been scribbled over, which is the whole reason it exists.
-(defn text-at [v Value key string] string
+(defn text-at [v Value key str] str
(match v
(Object entries)
(match (get entries key)
@@ -257,7 +257,7 @@
;; A reader's own refusals, driven end to end: read the whole document and then
;; report what the cursor says. The position matters as much as the message —
;; a trailing comma reported at the opening brace would be useless.
-(defn reject [src string] ()
+(defn reject [src str] ()
(let [b (bytes-view src)
c (json/cursor b)
t (json/next (addr c))]
diff --git a/test/programs/limits.flan b/test/programs/limits.flan
index 954cc082..16010a12 100644
--- a/test/programs/limits.flan
+++ b/test/programs/limits.flan
@@ -55,7 +55,7 @@
(defn inf-f32? [x f32] bool
(and (= x (* x (f32 2.0))) (!= x (f32 0.0))))
-(defn say [name string ok bool] ()
+(defn say [name str ok bool] ()
(print name)
(print " ")
(println (if ok "ok" "WRONG")))
diff --git a/test/programs/macro-loc-literal.flan b/test/programs/macro-loc-literal.flan
index 003e0e75..923f5a90 100644
--- a/test/programs/macro-loc-literal.flan
+++ b/test/programs/macro-loc-literal.flan
@@ -10,7 +10,7 @@
(defmacro thru [& body]
`(do ~@body))
-(defn g [s string] i32 0)
+(defn g [s str] i32 0)
(defn main [] i32
(thru
diff --git a/test/programs/macro-unless.flan b/test/programs/macro-unless.flan
index ac3ca0ec..50a259a0 100644
--- a/test/programs/macro-unless.flan
+++ b/test/programs/macro-unless.flan
@@ -9,7 +9,7 @@
;;;; the move, which is the point: the test for the feature is the corpus that
;;;; was written against the special form.
-(defn classify [n i32] string
+(defn classify [n i32] str
(let [out "even"]
(unless (= 0 (% n 2))
(set out "odd"))
diff --git a/test/programs/map-array-key.flan b/test/programs/map-array-key.flan
index a06d2e67..af4d9358 100644
--- a/test/programs/map-array-key.flan
+++ b/test/programs/map-array-key.flan
@@ -2,13 +2,13 @@
;; Each element is hashed and compared by its own pair, so two keys built from
;; different storage with the same bytes are the same key.
-(defstruct Tag [name string n i32])
+(defstruct Tag [name str n i32])
(defn main [] i32
- (let [m (map-new [2 string] i32)
- a (the [2 string] ["ab" "cd"])
- b (the [2 string] [(slice "xab" 1) (slice "cdx" 0 2)])
- c (the [2 string] ["ab" "ce"])]
+ (let [m (map-new [2 str] i32)
+ a (the [2 str] ["ab" "cd"])
+ b (the [2 str] [(slice "xab" 1) (slice "cdx" 0 2)])
+ c (the [2 str] ["ab" "ce"])]
(put m a 1)
(put m c 3)
(println (or-else (get m b) -1))
diff --git a/test/programs/map-exhausted.flan b/test/programs/map-exhausted.flan
index 5811c7d1..e8b4c00c 100644
--- a/test/programs/map-exhausted.flan
+++ b/test/programs/map-exhausted.flan
@@ -64,7 +64,7 @@
(set failures (+ failures 1))
(set-alloc-budget tight (* 8 (alloc-budget tight)))
(invoke-restart 'retry))]
- (let [m (map-new string i32 tight)]
+ (let [m (map-new str i32 tight)]
(reserve m 200)
(println (length m)) ; 0
(put m "a" 1)
diff --git a/test/programs/map-iter.flan b/test/programs/map-iter.flan
index 9d8226ec..89e0c958 100644
--- a/test/programs/map-iter.flan
+++ b/test/programs/map-iter.flan
@@ -65,7 +65,7 @@
(defstruct Point [x i32 y i32])
(defn wider-entries [] ()
- (let [m (map-new string Point)]
+ (let [m (map-new str Point)]
(put m "a" (Point {.x 1 .y 2}))
(put m "bb" (Point {.x 3 .y 4}))
(put m "ccc" (Point {.x 5 .y 6}))
diff --git a/test/programs/map-keys.flan b/test/programs/map-keys.flan
index b6ff9362..8aca4b17 100644
--- a/test/programs/map-keys.flan
+++ b/test/programs/map-keys.flan
@@ -28,8 +28,8 @@
(free vs))
(free m))
;; A string key, and a map that never allocated.
- (let [names (map-new string i32)
- none (map-new string i32)]
+ (let [names (map-new str i32)
+ none (map-new str i32)]
(put names "b" 2)
(put names "a" 1)
(let [ks (map-keys names)
diff --git a/test/programs/map-remove.flan b/test/programs/map-remove.flan
index cecaee24..6f0fe420 100644
--- a/test/programs/map-remove.flan
+++ b/test/programs/map-remove.flan
@@ -88,7 +88,7 @@
(print (length g)) (println "") ; 399
(free g))
- (let [s (map-new string i32)]
+ (let [s (map-new str i32)]
(put s "alpha" 1)
(put s "beta" 2)
(match (map-remove s "alpha")
diff --git a/test/programs/maps.flan b/test/programs/maps.flan
index 1604c72e..5c57531e 100644
--- a/test/programs/maps.flan
+++ b/test/programs/maps.flan
@@ -5,7 +5,7 @@
;;;; version gets wrong, and the numbers differ per failure so a single wrong
;;;; answer names its own cause.
(defstruct Cell [x i32 y i32])
-(defstruct Named [tag string n i32])
+(defstruct Named [tag str n i32])
(defenum Suit [hearts 0 spades 1 clubs 2])
;;;; (8) A map crosses a function boundary in both directions. Returning one
@@ -103,7 +103,7 @@
;; (6) Upsert replaces and does not grow the length, and reserve means room
;; for n *entries* — n still under the load factor — not n slots.
- (let [u (map-new string i32)]
+ (let [u (map-new str i32)]
(reserve u 100)
(put u "k" 1)
(put u "k" 2)
diff --git a/test/programs/match-bool.flan b/test/programs/match-bool.flan
index 76e9ec11..e41c130d 100644
--- a/test/programs/match-bool.flan
+++ b/test/programs/match-bool.flan
@@ -7,7 +7,7 @@
(defn same? [a bool b bool] bool (= a b))
;; Exhaustive without a _ arm: true and false are every bool.
-(defn word [b bool] string
+(defn word [b bool] str
(match b
true "yes"
false "no"))
@@ -24,7 +24,7 @@
;; Over a dyn :north is the arm (= d :north), beside numbers, strings and
;; bools, which are dyn values too.
-(defn heading [d dyn] string
+(defn heading [d dyn] str
(match d
:north "up"
:south "down"
diff --git a/test/programs/match-enum.flan b/test/programs/match-enum.flan
index a7ba148a..988b092c 100644
--- a/test/programs/match-enum.flan
+++ b/test/programs/match-enum.flan
@@ -10,7 +10,7 @@
:south :west
:west :north))
-(defn name [d Dir] string
+(defn name [d Dir] str
(match d
:north "north"
:south "south"
diff --git a/test/programs/match-literal.flan b/test/programs/match-literal.flan
index 9253b7aa..2b95ed13 100644
--- a/test/programs/match-literal.flan
+++ b/test/programs/match-literal.flan
@@ -1,7 +1,7 @@
;;;; match over numbers, chars, strings and dyn values: each arm is (= t lit)
;;;; over one temporary, and a _ arm is the rest.
-(defn small [n i16] string
+(defn small [n i16] str
(match n
5 "five"
-3 "minus three"
@@ -19,7 +19,7 @@
98 2
_ 0))
-(defn command [s string] i32
+(defn command [s str] i32
(match s
"go" 1
"stop" 2
@@ -33,7 +33,7 @@
;; Over a dyn the test is dyn =, so 1 matches 1.0 and "go" matches only a
;; string.
-(defn kind [d dyn] string
+(defn kind [d dyn] str
(match d
1 "one"
2.5 "two and a half"
diff --git a/test/programs/pkg-data.flan b/test/programs/pkg-data.flan
index 98ae3ddb..50fb0ef5 100644
--- a/test/programs/pkg-data.flan
+++ b/test/programs/pkg-data.flan
@@ -14,7 +14,7 @@
(defonce frame Allocator)
;; The type in a signature, and a bare pattern over a value the package made.
-(defn describe [t tree/Node] string
+(defn describe [t tree/Node] str
(match t
(Leaf _n) "leaf"
(Branch _k) "branch"
diff --git a/test/programs/pkgs/cret/cret.flan b/test/programs/pkgs/cret/cret.flan
index 8f5de8e6..1bbbe922 100644
--- a/test/programs/pkgs/cret/cret.flan
+++ b/test/programs/pkgs/cret/cret.flan
@@ -1,5 +1,5 @@
;;;; Strings returned from C, bound through declare-c. See cret.c beside this.
-(declare-c count [n i32] string "cret_count")
-(declare-c after-slash [path string] string "cret_after_slash")
-(declare-c nothing [] string "cret_nothing")
+(declare-c count [n i32] str "cret_count")
+(declare-c after-slash [path str] str "cret_after_slash")
+(declare-c nothing [] str "cret_nothing")
diff --git a/test/programs/prelude-macros.flan b/test/programs/prelude-macros.flan
index aa5961b3..b7226d23 100644
--- a/test/programs/prelude-macros.flan
+++ b/test/programs/prelude-macros.flan
@@ -11,7 +11,7 @@
(defonce dyn-count dyn 5)
-(defn show [label string n i32] ()
+(defn show [label str n i32] ()
(print label)
(print " ")
(println n))
diff --git a/test/programs/printers.flan b/test/programs/printers.flan
index 5423c68e..391c3b0f 100644
--- a/test/programs/printers.flan
+++ b/test/programs/printers.flan
@@ -9,7 +9,7 @@
(import agent "vendor:agent")
(defstruct V [x f32 y f32])
-(defstruct Blob [id i32 name string pos V tags [3 i32]])
+(defstruct Blob [id i32 name str pos V tags [3 i32]])
(defenum Colour [red 0 green 1 blue 2])
(defonce ticks i64)
diff --git a/test/programs/println.flan b/test/programs/println.flan
index 9425cb23..997b61a4 100644
--- a/test/programs/println.flan
+++ b/test/programs/println.flan
@@ -11,7 +11,7 @@
;;;; would launder a slot mistake into working code.
(defstruct V [x f32 y f32])
-(defstruct Blob [id i32 name string pos V tags [3 i32]])
+(defstruct Blob [id i32 name str pos V tags [3 i32]])
(defenum Colour [red 0 green 1 blue 2])
;; Five deep, so the walk hits max_depth (4) and prints "..." rather than
@@ -31,7 +31,7 @@
(defonce wide [10 i32])
(defonce deep D1)
(defonce n i32)
-(defstruct Long [s string])
+(defstruct Long [s str])
(defonce long-one Long)
(defn nothing [] () )
diff --git a/test/programs/raylib-audio.flan b/test/programs/raylib-audio.flan
index 6be86581..e7df3a44 100644
--- a/test/programs/raylib-audio.flan
+++ b/test/programs/raylib-audio.flan
@@ -76,7 +76,7 @@
(defconst wav-path "/tmp/flan-raylib-audio.wav")
-(defn show-wave [name string w rl/Wave] ()
+(defn show-wave [name str w rl/Wave] ()
(print name)
(print " ") (print (.frame-count w))
(print " ") (print (.sample-rate w))
@@ -84,7 +84,7 @@
(print " ") (print (.channels w))
(println ""))
-(defn show-bool [name string b bool] ()
+(defn show-bool [name str b bool] ()
(print name) (print " ")
(println (if b "yes" "no")))
@@ -121,7 +121,7 @@
(rl/unload-wave one)
v)))
-(defn show-frame [name string w rl/Wave i i32 want f32] ()
+(defn show-frame [name str w rl/Wave i i32 want f32] ()
(show-bool name (near? (frame-at w i) want)))
(defn main [] i32
diff --git a/test/programs/raylib-codepoints.flan b/test/programs/raylib-codepoints.flan
index 926ed234..f76b44fb 100644
--- a/test/programs/raylib-codepoints.flan
+++ b/test/programs/raylib-codepoints.flan
@@ -46,9 +46,9 @@
(defonce backward [max-walk i32])
(defonce backward-n i32)
-(defn yes-no [b bool] string (if b "yes" "no"))
+(defn yes-no [b bool] str (if b "yes" "no"))
-(defn show [name string n i32] ()
+(defn show [name str n i32] ()
(print name) (print " ") (println n))
;; From the first codepoint to the last. step-forward clamps rather than
diff --git a/test/programs/raylib-ffi.flan b/test/programs/raylib-ffi.flan
index 1c0fa34b..18f5896f 100644
--- a/test/programs/raylib-ffi.flan
+++ b/test/programs/raylib-ffi.flan
@@ -46,7 +46,7 @@
;; ((140-100)/2)+8 = 28 and ((90-50)/2)+4 = 24. Swap offset and target in the
;; defstruct and this reads (143,-16); swap rotation and zoom and the zoom
;; becomes 0, the transform is singular, and both come back NaN.
-(defn show-bool [name string b bool] ()
+(defn show-bool [name str b bool] ()
(print name) (print " ")
(println (if b "yes" "no")))
@@ -71,7 +71,7 @@
(let [d (- a b)]
(< (if (< d 0.0) (- 0.0 d) d) 0.0001)))
-(defn show-near [name string v rl/Vector2 x f32 y f32] ()
+(defn show-near [name str v rl/Vector2 x f32 y f32] ()
(print name)
(println (if (and (near? (.x v) x) (near? (.y v) y)) " ok" " bad")))
diff --git a/test/programs/raylib-font.flan b/test/programs/raylib-font.flan
index 49b1ecd1..d6af87bd 100644
--- a/test/programs/raylib-font.flan
+++ b/test/programs/raylib-font.flan
@@ -80,20 +80,20 @@
(set (at glyphs 2) (rl/GlyphInfo {.value 67 .offset-x 3 .offset-y 0
.advance-x 0 .image (rl/Image {})})))
-(defn show-bool [name string b bool] ()
+(defn show-bool [name str b bool] ()
(print name) (print " ")
(println (if b "yes" "no")))
-(defn show-i [name string v i32] ()
+(defn show-i [name str v i32] ()
(print name) (print " ") (print v) (println ""))
-(defn show-v [name string v rl/Vector2] ()
+(defn show-v [name str v rl/Vector2] ()
(print name)
(print " ") (print (.x v))
(print " ") (print (.y v))
(println ""))
-(defn show-rect [name string r rl/Rectangle] ()
+(defn show-rect [name str r rl/Rectangle] ()
(print name)
(print " ") (print (.x r))
(print " ") (print (.y r))
diff --git a/test/programs/raylib-image-processing.flan b/test/programs/raylib-image-processing.flan
index c0b5513f..4e8de18f 100644
--- a/test/programs/raylib-image-processing.flan
+++ b/test/programs/raylib-image-processing.flan
@@ -51,7 +51,7 @@
(defconst probe-c-x 180) ; background gradient, right-hand side
(defconst probe-c-y 40)
-(defn show-color [name string which string c rl/Color] ()
+(defn show-color [name str which str c rl/Color] ()
(print name)
(print " ") (print which)
(print " ") (print (.r c))
@@ -63,14 +63,14 @@
;; Size and format on the same line as the name, because two of the nine
;; filters reallocate and a filter that quietly changed either would otherwise
;; only show up as three moved pixels.
-(defn show-shape [name string i rl/Image] ()
+(defn show-shape [name str i rl/Image] ()
(print name)
(print " ") (print (.width i))
(print " ") (print (.height i))
(print " ") (print (.format i))
(println ""))
-(defn probe [name string i rl/Image] ()
+(defn probe [name str i rl/Image] ()
(show-shape name i)
(show-color name "a" (rl/get-image-color i probe-a-x probe-a-y))
(show-color name "b" (rl/get-image-color i probe-b-x probe-b-y))
@@ -81,13 +81,13 @@
;; restores from the original before every filter for exactly this reason, and
;; a test that stacked them would be asserting the composition rather than the
;; parts.
-(defn run [name string src rl/Image which i32] ()
+(defn run [name str src rl/Image which i32] ()
(let [img (rl/image-copy src)]
(ip/apply-process (addr img) which)
(probe name img)
(rl/unload-image img)))
-(defn yes-no [b bool] string (if b "yes" "no"))
+(defn yes-no [b bool] str (if b "yes" "no"))
;; The blur, said in the only two ways a blur can be said without pinning
;; somebody else's kernel. The edge probe is one pixel outside the red
diff --git a/test/programs/raylib-image.flan b/test/programs/raylib-image.flan
index e09d880e..ec6e214a 100644
--- a/test/programs/raylib-image.flan
+++ b/test/programs/raylib-image.flan
@@ -34,7 +34,7 @@
;; write identical bytes, so sharing one path between runs is harmless.
(defconst png-path "/tmp/flan-raylib-image.png")
-(defn show-image [name string i rl/Image] ()
+(defn show-image [name str i rl/Image] ()
(print name)
(print " ") (print (.width i))
(print " ") (print (.height i))
@@ -42,7 +42,7 @@
(print " ") (print (.format i))
(println ""))
-(defn show-color [name string c rl/Color] ()
+(defn show-color [name str c rl/Color] ()
(print name)
(print " ") (print (.r c))
(print " ") (print (.g c))
@@ -50,13 +50,13 @@
(print " ") (print (.a c))
(println ""))
-(defn show-bool [name string b bool] ()
+(defn show-bool [name str b bool] ()
(print name) (print " ")
(println (if b "yes" "no")))
;; Every pixel read names its coordinates in the label, so a failure says
;; which one moved rather than only that something did.
-(defn show-pixel [name string i rl/Image x i32 y i32] ()
+(defn show-pixel [name str i rl/Image x i32 y i32] ()
(show-color name (rl/get-image-color i x y)))
(defn main [] i32
diff --git a/test/programs/restarts.flan b/test/programs/restarts.flan
index 18d88fe1..961c079f 100644
--- a/test/programs/restarts.flan
+++ b/test/programs/restarts.flan
@@ -69,7 +69,7 @@
;;; string is ptr+len and crosses the transfer as the two of them.
(defn labelled [n i32] i32
(restart-case (middle n)
- (use-labelled [label string v i32]
+ (use-labelled [label str v i32]
(do (print label) (println "") v))))
;;; The mismatch cases. Each is selected by the argument, because each stops
@@ -94,14 +94,14 @@
(defn shadowed [n i32] i32
(restart-case
(restart-case (middle n)
- (use-value [s string] (do (print s) 0)))
+ (use-value [s str] (do (print s) 0)))
(use-value [v i32] v)))
(defn mislaid [n i32] i32
(handler-bind [(AssetMissing [c] (invoke-restart 'use-value 21))]
(shadowed n)))
-(defn main [args [string]] i32
+(defn main [args [str]] i32
;; One argument selects a trap; none runs the table's case.
(if (> (length args) 1)
(let [k (i32 (bytes->i64 (bytes-view (at args 1))))]
diff --git a/test/programs/shadow-builtin.flan b/test/programs/shadow-builtin.flan
index 826b4f88..a13f7489 100644
--- a/test/programs/shadow-builtin.flan
+++ b/test/programs/shadow-builtin.flan
@@ -35,7 +35,7 @@
;;; is the one place there is no enclosing function to carry a package's
;;; qualified name. The package's (defonce size i32 (length "abcd")) is 4; this
;;; definition answers 999 and is reached only here.
-(defn length [s string] i32 999)
+(defn length [s str] i32 999)
(defn main [] ()
(println (get (P {.x 7})))
diff --git a/test/programs/shim-literal.flan b/test/programs/shim-literal.flan
index 8c9a3ac7..420b600b 100644
--- a/test/programs/shim-literal.flan
+++ b/test/programs/shim-literal.flan
@@ -16,9 +16,9 @@
;;;; basename, which answers the same pointer and ignores the extra argument.
(defstruct Ch [c i32])
-(declare-c c-where [s string] i64 "basename")
-(declare-c c-where2 [s string c Ch] i64 "__xpg_basename")
-(declare-c c-puts [s string] i32 "puts")
+(declare-c c-where [s str] i64 "basename")
+(declare-c c-where2 [s str c Ch] i64 "__xpg_basename")
+(declare-c c-puts [s str] i32 "puts")
(defn far? [a i64 b i64] bool
(let [d (- a b)]
@@ -30,5 +30,5 @@
(println (far? (c-where2 "hello" (Ch {.c 104})) (c-where2 s (Ch {.c 104}))))
(c-puts "hello")
(c-puts "")
- (c-puts (string (slice (bytes-view "hello world") 0 3))))
+ (c-puts (str (slice (bytes-view "hello world") 0 3))))
0)
diff --git a/test/programs/shim-nul-end.flan b/test/programs/shim-nul-end.flan
index 621e82d0..da23ea37 100644
--- a/test/programs/shim-nul-end.flan
+++ b/test/programs/shim-nul-end.flan
@@ -3,15 +3,15 @@
;;;; merely ends in a NUL is copied like any other, and the NUL inside it is
;;;; refused. Each argument is one way to spell such a string, and each is
;;;; refused naming the call.
-(declare-c c-puts [s string] i32 "puts")
+(declare-c c-puts [s str] i32 "puts")
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [which (if (> (length args) 1) (bytes->i64 (bytes-view (at args 1))) 0)]
(println "before")
(cond
(= which 1) (let [s "ab\0"] (c-puts s))
- (= which 2) (c-puts (string (slice (bytes-view "ab\0c") 0 3)))
- (= which 3) (c-puts (string (bytes "q\0")))
+ (= which 2) (c-puts (str (slice (bytes-view "ab\0c") 0 3)))
+ (= which 3) (c-puts (str (bytes "q\0")))
:else (c-puts "ab\0"))
(println "unreachable"))
0)
diff --git a/test/programs/shim-nul.flan b/test/programs/shim-nul.flan
index e2bd18e4..c7623757 100644
--- a/test/programs/shim-nul.flan
+++ b/test/programs/shim-nul.flan
@@ -12,7 +12,7 @@
;;;; the shim refuses it too, naming the declare-c that was called. It is a
;;;; trap rather than a condition because a foreign call has no allocation site
;;;; for the compiler to guard and no transfer channel of its own.
-(declare-c c-puts [s string] i32 "puts")
+(declare-c c-puts [s str] i32 "puts")
(defn main [] i32
(let [v (vec-new u8)]
@@ -22,7 +22,7 @@
(push v 104) ; h
(push v 105) ; i
(println "before")
- (c-puts (string (slice v)))
+ (c-puts (str (slice v)))
(println "unreachable")
(free v))
0)
diff --git a/test/programs/slices.flan b/test/programs/slices.flan
index c4250eb1..0c027bce 100644
--- a/test/programs/slices.flan
+++ b/test/programs/slices.flan
@@ -104,7 +104,7 @@
(show (slice a))) ; 1 2 4 4 5 6 9 9
(let [cs [\I \N \S \E \R \T \I \O \N \S \O \R \T]]
(sort (slice cs))
- (println (string (slice cs)))) ; EIINNOORRSSTT
+ (println (str (slice cs)))) ; EIINNOORRSSTT
;; ── Strings ────────────────────────────────────────────────────────
;; A string is ptr+len over bytes, so it indexes to a byte and slices to a
diff --git a/test/programs/slurp.flan b/test/programs/slurp.flan
index ee364558..c492fbf4 100644
--- a/test/programs/slurp.flan
+++ b/test/programs/slurp.flan
@@ -23,13 +23,13 @@
(defonce seen i64)
(defonce last-reason i32)
(defonce last-op i32)
-(defonce last-path string)
+(defonce last-path str)
(defn main [] i32
;; ── The happy path ────────────────────────────────────────────────
(let [v (slurp "programs/assets/a.txt")]
(println (length v)) ; 13
- (print (string (slice v))) ; hello from a
+ (print (str (slice v))) ; hello from a
(free v))
;; Byte-exact, the same as an embed: nothing here decodes anything.
@@ -52,7 +52,7 @@
(invoke-restart 'use-value "programs/assets/b.bin"))]
(let [v (slurp "programs/assets/does-not-exist")]
(println (length v)) ; 3
- (println (string (slice v))) ; BBB
+ (println (str (slice v))) ; BBB
(free v)))
(println seen) ; 1
(println (= last-reason file-missing)) ; true
@@ -65,7 +65,7 @@
(barf "slurp-out.txt" (bytes-view "round trip\n"))
(let [v (slurp "slurp-out.txt")]
(println (length v)) ; 11
- (print (string (slice v))) ; round trip
+ (print (str (slice v))) ; round trip
(free v))
;; barf's own failure signals the same condition with op = write. A directory
@@ -80,7 +80,7 @@
(println seen) ; 1
(println (= last-op file-op-write)) ; true
(let [v (slurp "slurp-out.txt")]
- (print (string (slice v))) ; second
+ (print (str (slice v))) ; second
(free v))
;; ── retry: the file was not there, so the handler makes it ────────
@@ -96,7 +96,7 @@
(barf "slurp-made.txt" (bytes-view "made by the handler\n"))
(invoke-restart 'retry))]
(let [v (slurp "slurp-made.txt")]
- (print (string (slice v))) ; made by the handler
+ (print (str (slice v))) ; made by the handler
(free v)))
(println seen) ; 1
(println (= last-reason file-missing)) ; true
diff --git a/test/programs/string-eq.flan b/test/programs/string-eq.flan
index 383c8e18..81bacf53 100644
--- a/test/programs/string-eq.flan
+++ b/test/programs/string-eq.flan
@@ -22,7 +22,7 @@
;; fire -- what answers here is the byte loop, or the length check first
;; ruling nothing out since both are three bytes.
(let [heap (to-lower (bytes-view "ABC"))]
- (let [h (string (slice heap))]
+ (let [h (str (slice heap))]
(println (= "abc" h)) ; true
(println (!= "abc" h)))
(free heap))
@@ -43,5 +43,5 @@
;; lengths -- the one pair the same-pointer fast path would answer wrong on
;; if it ran before the length check instead of after.
(let [s "abcd"]
- (println (= s (string (slice (bytes-view s) 0 2))))) ; false
+ (println (= s (str (slice (bytes-view s) 0 2))))) ; false
0)
diff --git a/test/programs/string-of-bytes.flan b/test/programs/string-of-bytes.flan
index 91bec2e0..d7003337 100644
--- a/test/programs/string-of-bytes.flan
+++ b/test/programs/string-of-bytes.flan
@@ -18,9 +18,9 @@
;; Its return is C's "some nonnegative value", not a number worth printing, so
;; it is only shown as a sign — and it is printed through Flan's own writer,
;; which shares stdout's buffer with puts, so the interleaving is stable.
-(declare-c c-puts [s string] i32 "puts")
+(declare-c c-puts [s str] i32 "puts")
-(defn shows [s string] ()
+(defn shows [s str] ()
(print "[")
(print s)
(print "] ")
@@ -30,34 +30,34 @@
(defn main [] i32
;; A number. The gap this closes: i64->bytes answers a [u8], every text
;; parameter wants a string, and until now nothing joined them.
- (shows (string (i64->bytes 42)))
- (shows (string (i64->bytes -7)))
- (shows (string (i64->bytes 0)))
+ (shows (str (i64->bytes 42)))
+ (shows (str (i64->bytes -7)))
+ (shows (str (i64->bytes 0)))
;; An empty slice. Length 0, and no read of the pointer.
- (shows (string (slice (bytes-view "abc") 1 1)))
+ (shows (str (slice (bytes-view "abc") 1 1)))
;; A sub-view, whose length is not the underlying storage's. The bytes after
;; index 5 are still there and must not appear.
(let [s (bytes-view "hello world")]
- (shows (string (slice s 0 5)))
- (shows (string (slice s 6 11)))
- (shows (string (slice s 11 11))))
+ (shows (str (slice s 0 5)))
+ (shows (str (slice s 6 11)))
+ (shows (str (slice s 11 11))))
;; Round trip: (bytes-view (string b)) is b, and both directions are the identity.
(let [b (i64->bytes 1234567)]
- (print (length (bytes-view (string b))))
+ (print (length (bytes-view (str b))))
(println ""))
;; Across the declare-c boundary. The first is a sub-view — five bytes out of
;; eleven, the sixth of which is a space and not a NUL — so a shim that did
;; not copy would print "hello world" here.
(let [s (bytes-view "hello world")]
- (print (if (>= (c-puts (string (slice s 0 5))) 0) "ok" "no"))
+ (print (if (>= (c-puts (str (slice s 0 5))) 0) "ok" "no"))
(println ""))
- (print (if (>= (c-puts (string (i64->bytes 12345))) 0) "ok" "no"))
+ (print (if (>= (c-puts (str (i64->bytes 12345))) 0) "ok" "no"))
(println "")
;; And an empty one: the shim's copy of a zero-length slice is "".
- (print (if (>= (c-puts (string (slice (bytes-view "abc") 1 1))) 0) "ok" "no"))
+ (print (if (>= (c-puts (str (slice (bytes-view "abc") 1 1))) 0) "ok" "no"))
(println "")
0)
diff --git a/test/programs/strings.flan b/test/programs/strings.flan
index 30209f35..f2120be5 100644
--- a/test/programs/strings.flan
+++ b/test/programs/strings.flan
@@ -12,7 +12,7 @@
;;; time. slice borrows -- it copies ptr+len and never the elements -- so v
;;; is still the owner afterwards and is still free-able.
(defn show [v (Ptr (Vec u8))] ()
- (println (string (slice (deref v)))))
+ (println (str (slice (deref v)))))
(defn main [] i32
;; The builder. Three appends and two numbers into one Vec.
@@ -101,8 +101,8 @@
;; disagree with each other.
(let [f (split (bytes-view "a,b,c") \,)]
(println (length f)) ; 3
- (println (string (at f 0))) ; a
- (println (string (at f 2))) ; c
+ (println (str (at f 0))) ; a
+ (println (str (at f 2))) ; c
(free f))
(let [f (split (bytes-view "a,b,") \,)]
(println (length f)) ; 3
@@ -115,7 +115,7 @@
;; No separator at all is one field, and the empty input is one empty field.
(let [f (split (bytes-view "abc") \,)]
(println (length f)) ; 1
- (println (string (at f 0))) ; abc
+ (println (str (at f 0))) ; abc
(free f))
(let [f (split (bytes-view "") \,)]
(println (length f)) ; 1
diff --git a/test/programs/temp-agent.flan b/test/programs/temp-agent.flan
index 1d58531f..cb84318e 100644
--- a/test/programs/temp-agent.flan
+++ b/test/programs/temp-agent.flan
@@ -6,12 +6,12 @@
(declare-c reg-overflowed [] i32 "flan_dev_reg_overflowed")
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [n (bytes->i64 (bytes-view (at args 1)))
total (i64 0)]
(dotimes [i (i32 n)]
(agent/poll)
- (let [s (string (i64->bytes (i64 i)))]
+ (let [s (str (i64->bytes (i64 i)))]
(set total (+ total (i64 (length (bytes-view s)))))))
(println total)
(println (reg-overflowed)))
diff --git a/test/programs/temp-frame.flan b/test/programs/temp-frame.flan
index 46e7b6d8..2b287e1f 100644
--- a/test/programs/temp-frame.flan
+++ b/test/programs/temp-frame.flan
@@ -11,13 +11,13 @@
;;;; build's registry fills. The last line is whether the registry overflowed.
(declare-c reg-overflowed [] i32 "flan_dev_reg_overflowed")
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [arg (bytes->i64 (bytes-view (at args 1)))
n (if (< arg 0) (- 0 arg) arg)
total (i64 0)
kept (bytes-view "")]
(dotimes [i (i32 n)]
- (let [s (string (i64->bytes (i64 i)))
+ (let [s (str (i64->bytes (i64 i)))
f (f64->bytes (+ (f64 i) 0.5))]
(set total (+ total (i64 (+ (length (bytes-view s)) (length f)))))
(when (= i 7)
@@ -25,6 +25,6 @@
(when (> arg 0)
(free-temp)))
(println total)
- (println (string kept))
+ (println (str kept))
(println (reg-overflowed)))
0)
diff --git a/test/programs/trial-generic.flan b/test/programs/trial-generic.flan
index 9ae05f20..0ef7a2f0 100644
--- a/test/programs/trial-generic.flan
+++ b/test/programs/trial-generic.flan
@@ -3,7 +3,7 @@
;;;; lambda, a condition's message printer — has to be kept with it, or the
;;;; program links against a function nobody emitted.
-(defstruct MyErr :parent Error [code i32 why string])
+(defstruct MyErr :parent Error [code i32 why str])
(defn ap [x i32 f (Fn [i32] i32)] i32 (f x))
diff --git a/test/programs/two-numbers.flan b/test/programs/two-numbers.flan
index ba24e10a..e37c2c79 100644
--- a/test/programs/two-numbers.flan
+++ b/test/programs/two-numbers.flan
@@ -11,31 +11,31 @@
;;;; The conversion's bytes are now copied into the temp allocator, so a
;;;; result outlives the frame that made it: the last two cases return one from
;;;; a function and push them into a Vec that outlives the loop that made them.
-(defn numstr [n i64] string
- (string (i64->bytes n)))
+(defn numstr [n i64] str
+ (str (i64->bytes n)))
(defn main [] i32
;; Two i64 conversions alive at the same time.
- (let [a (string (i64->bytes 11))
- b (string (i64->bytes 22))]
+ (let [a (str (i64->bytes 11))
+ b (str (i64->bytes 22))]
(print a) (print " ") (println b)) ; 11 22
;; Three, and read in the order they were made rather than in reverse, so a
;; version that rotated among two buffers would still be caught.
- (let [a (string (i64->bytes 1))
- b (string (i64->bytes 2))
- c (string (i64->bytes 3))]
+ (let [a (str (i64->bytes 1))
+ b (str (i64->bytes 2))
+ c (str (i64->bytes 3))]
(print a) (print b) (println c)) ; 123
;; Across the two shims: the f64's text is made first and read last.
- (let [x (string (f64->bytes 2.5))
- n (string (i64->bytes 7))]
+ (let [x (str (f64->bytes 2.5))
+ n (str (i64->bytes 7))]
(print x) (print " ") (println n)) ; 2.5 7
;; Inside a loop, one conversion per turn. Printed on one line so the
;; loop's shape is visible in the output.
(dotimes [i 4]
- (let [s (string (i64->bytes (i64 (* i 11))))]
+ (let [s (str (i64->bytes (i64 (* i 11))))]
(print s) (print " ")))
(println "") ; 0 11 22 33
@@ -50,6 +50,6 @@
(dotimes [i 3]
(push v (f64->bytes (+ (f64 i) 0.5))))
(dotimes [i 3]
- (print (string (at v i))) (print " "))
+ (print (str (at v i))) (print " "))
(println "")) ; 0.5 1.5 2.5
0)
diff --git a/test/programs/vec-new-type.flan b/test/programs/vec-new-type.flan
index a809bd26..020bf0c6 100644
--- a/test/programs/vec-new-type.flan
+++ b/test/programs/vec-new-type.flan
@@ -9,7 +9,7 @@
pairs (vec-new [2 i32])
ptrs (vec-new (Ptr i32))
opts (vec-new (Option i64) a)
- m (map-new string [const u8])
+ m (map-new str [const u8])
x (i32 7)]
(push words (bytes-view "ab"))
(push words (bytes-view "cde"))
diff --git a/test/programs/web-files.flan b/test/programs/web-files.flan
index 33cf3959..2c5c2d8b 100644
--- a/test/programs/web-files.flan
+++ b/test/programs/web-files.flan
@@ -16,7 +16,7 @@
(defn main [] i32
;; Embedding needs no filesystem and no host ABI, so this line is identical
;; on both targets and is why decision 1 came first.
- (print (embed "assets/a.txt" string))
+ (print (embed "assets/a.txt" str))
(handler-bind
[(FileError [c]
diff --git a/test/programs/widening.flan b/test/programs/widening.flan
index 693679b8..85d372a8 100644
--- a/test/programs/widening.flan
+++ b/test/programs/widening.flan
@@ -52,7 +52,7 @@
(defn w-add-wide-first [] i64 (+ w-i64big w-i32one))
(defn w-add-narrow-first [] i64 (+ w-i32one w-i64big))
-(defn main [args [string]] i32
+(defn main [args [str]] i32
;; ── integer to integer ──────────────────────────────────────────
(println (w-take-i64 w-i8neg)) ;; -5
(println (w-take-i64 w-i8pos)) ;; 127
diff --git a/test/programs/x86-p11-reversed-slice.flan b/test/programs/x86-p11-reversed-slice.flan
index 26d762dc..0ac0bc25 100644
--- a/test/programs/x86-p11-reversed-slice.flan
+++ b/test/programs/x86-p11-reversed-slice.flan
@@ -17,7 +17,7 @@
;;;; The two ends come from (length args), which is 1 for a program run with no
;;;; arguments and is not a number either optimiser can see, so the branch
;;;; cannot be folded away and the checker has no literal to object to.
-(defn main [args [string]] i32
+(defn main [args [str]] i32
(let [s (bytes-view "hello")
hi (i32 (length args))
lo (+ hi 1)]
diff --git a/test/programs/x86-p12-handler-value.flan b/test/programs/x86-p12-handler-value.flan
index 690cae0c..faa843a2 100644
--- a/test/programs/x86-p12-handler-value.flan
+++ b/test/programs/x86-p12-handler-value.flan
@@ -72,9 +72,9 @@
(restart-case (do (signal (Oops {.id 5})) 1.5)
(use-value [v f64] (* v 2.0))))
-(defn spelled [] string
+(defn spelled [] str
(restart-case (do (signal (Oops {.id 6})) "fell-through")
- (use-value [v string] v)))
+ (use-value [v str] v)))
(defn main [] i32
(handler-bind [(Oops [c] (invoke-restart 'use-zero))]
diff --git a/test/programs/x86-p7-slice-from.flan b/test/programs/x86-p7-slice-from.flan
index faa4346c..dc7bb50b 100644
--- a/test/programs/x86-p7-slice-from.flan
+++ b/test/programs/x86-p7-slice-from.flan
@@ -23,7 +23,7 @@
(length s))
(give-up [] -1)))
-(defn show [name string n i64] ()
+(defn show [name str n i64] ()
(print name)
(print " ")
(println n))
diff --git a/test/syntax/algorithms.flan b/test/syntax/algorithms.flan
index c99ccb33..a5e86892 100644
--- a/test/syntax/algorithms.flan
+++ b/test/syntax/algorithms.flan
@@ -1,10 +1,10 @@
(import agent "vendor:agent")
-(defn find-match [str string pattern string] i32
- (dotimes [i (length str)]
+(defn find-match [text str pattern str] i32
+ (dotimes [i (length text)]
(let [matched true]
(dotimes [j (length pattern)]
- (when (!= (at str (+ i j)) (at pattern j))
+ (when (!= (at text (+ i j)) (at pattern j))
(set matched false)))
(when matched
(return i))))
@@ -41,11 +41,11 @@
(comment
(insertion-sort [\I \N \S \E \R \T \I \O \N \S \O \R \T])
(insertion-sort (slice [6 2 4 9 1 9 4 5] 0 8))
- (let [str (bytes "INSERTIONSORT")]
- (insertion-sort str)
- (println str))
- (let [str (bytes "SELECTIONSORT")]
- (selection-sort str)
- (println str))
+ (let [text (bytes "INSERTIONSORT")]
+ (insertion-sort text)
+ (println text))
+ (let [text (bytes "SELECTIONSORT")]
+ (selection-sort text)
+ (println text))
(find-match "aababba" "abba")
:-)
diff --git a/test/syntax/algorithms.fln b/test/syntax/algorithms.fln
index 151f6193..037f14fa 100644
--- a/test/syntax/algorithms.fln
+++ b/test/syntax/algorithms.fln
@@ -3,11 +3,11 @@
import agent "vendor:agent"
-fn find-match(str: string, pattern: string) -> i32
- for i in range(length(str))
+fn find-match(text: str, pattern: str) -> i32
+ for i in range(length(text))
let matched = true
for j in range(length(pattern))
- if str[i + j] != pattern[j]
+ if text[i + j] != pattern[j]
matched = false
if matched
return i
@@ -42,11 +42,11 @@ fn main() -> i32 = 0
comment():
insertion-sort([\I \N \S \E \R \T \I \O \N \S \O \R \T])
insertion-sort(slice([6 2 4 9 1 9 4 5], 0, 8))
- let str = bytes("INSERTIONSORT")
- insertion-sort(str)
- println(str)
- let str = bytes("SELECTIONSORT")
- selection-sort(str)
- println(str)
+ let text = bytes("INSERTIONSORT")
+ insertion-sort(text)
+ println(text)
+ let text = bytes("SELECTIONSORT")
+ selection-sort(text)
+ println(text)
find-match("aababba", "abba")
:-
diff --git a/test/syntax/handwritten/csv.fln b/test/syntax/handwritten/csv.fln
index bb1a54cb..7aa9f652 100644
--- a/test/syntax/handwritten/csv.fln
+++ b/test/syntax/handwritten/csv.fln
@@ -18,13 +18,13 @@ defmacro(with-section, [title & body]):
~@body
println("-----")
-fn flush(field: Ptr(Vec(u8)), row: Ptr(Vec(string))) -> ()
- push(deref(row), string(slice(deref(field))))
+fn flush(field: Ptr(Vec(u8)), row: Ptr(Vec(str))) -> ()
+ push(deref(row), str(slice(deref(field))))
fields-seen += 1
deref(field) = vec-new(u8)
-fn parse-line(line: [const u8]) -> Vec(string)
- let row = vec-new(string)
+fn parse-line(line: [const u8]) -> Vec(str)
+ let row = vec-new(str)
let field = vec-new(u8)
let state = State.start
for i in range(length(line))
@@ -57,14 +57,14 @@ fn parse-line(line: [const u8]) -> Vec(string)
rows-seen += 1
row
-fn widest(rows: [Vec(string)]) -> i32
+fn widest(rows: [Vec(str)]) -> i32
let best = 0
for r in range(length(rows))
for f in range(length(rows[r]))
best = max(best, i32(length(rows[r][f])))
best
-fn pad(s: string, width: i32) -> ()
+fn pad(s: str, width: i32) -> ()
print(s)
let n = width - i32(length(s))
until n <= 0
@@ -77,7 +77,7 @@ fn main() -> i32
defer arena-destroy(frame)
with-allocator(frame):
let lines = split(bytes-view(text), \newline)
- let rows = vec-new(Vec(string))
+ let rows = vec-new(Vec(str))
for i in range(length(lines))
push(rows, parse-line(lines[i]))
let w = widest(slice(rows)) + 1
diff --git a/test/syntax/handwritten/inventory.fln b/test/syntax/handwritten/inventory.fln
index 6f23270d..94bcd51c 100644
--- a/test/syntax/handwritten/inventory.fln
+++ b/test/syntax/handwritten/inventory.fln
@@ -5,7 +5,7 @@
import stock "stock"
struct Rule
- label: string
+ label: str
applies: CFn(stock/Item) -> bool
def report-width: i32 = 28
@@ -36,7 +36,7 @@ fn line(it: stock/Item) -> ()
print(it.name)
for i in range(max(dots, 1))
print(".")
- println(string(slice(price)))
+ println(str(slice(price)))
fn low?(it: stock/Item) -> bool = it.count < reorder-below
@@ -60,7 +60,7 @@ fn main() -> i32
for i in range(length(items))
line(items[i])
for r in range(length(rules))
- let names = vec-new(string)
+ let names = vec-new(str)
for i in range(length(items))
if rules[r].applies(items[i])
push(names, items[i].name)
diff --git a/test/syntax/handwritten/rpn.fln b/test/syntax/handwritten/rpn.fln
index e98f2239..18b1767f 100644
--- a/test/syntax/handwritten/rpn.fln
+++ b/test/syntax/handwritten/rpn.fln
@@ -58,7 +58,7 @@ fn apply(op: u8, a: i64, b: i64) -> i64
\/ -> if b == 0 then 0 else a / b
_ -> a % b
-fn run(src: string) -> i64
+fn run(src: str) -> i64
let m: Machine = zeroed()
let text = bytes-view(src)
let pos = 0
@@ -82,7 +82,7 @@ fn run(src: string) -> i64
error(Unknown{.word w})
pop!(addr(m), \=)
-fn show(src: string) -> ()
+fn show(src: str) -> ()
let r =
handler-case
run(src)
@@ -90,11 +90,11 @@ fn show(src: string) -> ()
println(src, "=> stack empty at", string-of-byte(u.op))
return
on Unknown(u)
- println(src, "=> unknown word", string(u.word))
+ println(src, "=> unknown word", str(u.word))
return
println(src, "=>", r)
-fn string-of-byte(b: u8) -> string
+fn string-of-byte(b: u8) -> str
match b
\+ -> "+"
\- -> "-"
diff --git a/test/syntax/handwritten/stock/stock.fln b/test/syntax/handwritten/stock/stock.fln
index 868ff437..9ccfcb2b 100644
--- a/test/syntax/handwritten/stock/stock.fln
+++ b/test/syntax/handwritten/stock/stock.fln
@@ -1,7 +1,7 @@
; Stock items and prices kept in cents, imported by ../inventory.fln.
struct Item
- name: string
+ name: str
cents: i64
count: i32
@@ -16,7 +16,7 @@ fn- whole(cents: i64) -> i64 = cents / cents-per-unit
fn- part(cents: i64) -> i64 = cents % cents-per-unit
-fn item(name: string, cents: i64, count: i32) -> Item
+fn item(name: str, cents: i64, count: i32) -> Item
Item{.name name, .cents cents, .count count}
fn value(it: Item) -> i64 = it.cents * i64(it.count)
diff --git a/test/syntax/handwritten/traffic.fln b/test/syntax/handwritten/traffic.fln
index efcf64fa..ccf3d613 100644
--- a/test/syntax/handwritten/traffic.fln
+++ b/test/syntax/handwritten/traffic.fln
@@ -29,7 +29,7 @@ fn next(l: Light, pressed: bool) -> Light
if left > 1 then Light.Red{.left left - 1, .walk walk} else Light.Green{.left green-time}
Flashing -> Light.Flashing{}
-fn show(l: Light) -> string
+fn show(l: Light) -> str
match l
Green(_) -> "G"
Yellow(_, _) -> "Y"
diff --git a/test/syntax/handwritten/words.fln b/test/syntax/handwritten/words.fln
index e090d550..fc4cb2f4 100644
--- a/test/syntax/handwritten/words.fln
+++ b/test/syntax/handwritten/words.fln
@@ -33,14 +33,14 @@ fn words(text: [const u8]) -> Vec([const u8])
out
fn tally(ws: [[const u8]]) -> Vec(Count)
- let seen = map-new(string, i32)
+ let seen = map-new(str, i32)
defer free(seen)
let counts = vec-new(Count)
for i in range(length(ws))
- match get(seen, string(ws[i]))
+ match get(seen, str(ws[i]))
Some(k) -> counts[k].n += 1
None ->
- put(seen, string(ws[i]), i32(length(counts)))
+ put(seen, str(ws[i]), i32(length(counts)))
push(counts, Count{.word ws[i], .n 1})
counts
@@ -48,7 +48,7 @@ fn grade(distinct: i32, total: i32) -> Grade
let ratio = distinct * 10 / max(total, 1)
if ratio >= 7 then :rich else if ratio >= 4 then :fair else :poor
-fn describe(g: Grade) -> string
+fn describe(g: Grade) -> str
match i32(g)
1 -> "repetitive"
2 -> "ordinary"
@@ -65,7 +65,7 @@ fn main() -> i32
sort-by(slice(counts), by-count)
for i in range(3)
let {.word .n} = counts[i]
- println(string(word), n)
+ println(str(word), n)
let top: [3 i32] = [counts[0].n counts[1].n counts[2].n]
let [most & others] = top
println("most frequent seen", most, "times, then", others)
@@ -75,7 +75,7 @@ fn main() -> i32
println(distinct, "of", total, "distinct:", describe(g))
let longest = reduce(slice(ws), slice(ws[0], 0, 0), fn(a, b) =
if length(b) > length(a) then b else a)
- println("longest", string(longest))
+ println("longest", str(longest))
let short = 0 < length(longest) < 5
match short
true -> println("short words only")
diff --git a/test/test_acceptance.ml b/test/test_acceptance.ml
index f12aca6d..6d83f46c 100644
--- a/test/test_acceptance.ml
+++ b/test/test_acceptance.ml
@@ -1383,7 +1383,7 @@ let () =
refuses "a restart invoked with too few arguments" "1"
"restart use-value takes (i32), given ()";
refuses "a restart invoked with the wrong type" "2"
- "restart use-value takes (i32), given (string)";
+ "restart use-value takes (i32), given (str)";
refuses "arguments given to a restart that takes none" "3"
"restart retry takes (), given (i32)";
(* §4 meets §3. The name finds the innermost frame offering it and the
@@ -1391,7 +1391,7 @@ let () =
frame the arguments would have fitted, and an outer clause that would
have taken them is not consulted. *)
refuses "a shadowing clause of the same name and a different signature" "4"
- "restart use-value takes (string), given (i32)";
+ "restart use-value takes (str), given (i32)";
(try Sys.remove exe with Sys_error _ -> ())
in
restart_mismatch ();
@@ -1541,7 +1541,7 @@ let () =
spellings, not one form that changes type with its context. *)
refuses_src "embed asked for a type it cannot read a file as"
"(defn main [] i32 (length (embed \"no-such-asset.bin\" i32)))"
- "embed's second argument is string";
+ "embed's second argument is str";
(* Allocators, spec-memory.md. The tier on its own, with no container
above it, so that a failure here is not read as a Vec bug. What is
@@ -1751,7 +1751,7 @@ let () =
let json_refusal = refusal ~pkg:"json" ~mac:"defjson" ~ext:"json" in
(* The element positions are named, both of them, because "heterogeneous"
on its own sends someone to read the whole file. *)
- provider_refusal "mixed-vector" "{:xs [1 2 \"three\"]}" "element 2 is string";
+ provider_refusal "mixed-vector" "{:xs [1 2 \"three\"]}" "element 2 is str";
(* A map whose keys are not all keywords is not a struct: a field is named,
and "name" in quotes is a value. *)
provider_refusal "mixed-keys" "{:a 1 \"b\" 2}" "that is not a keyword";
@@ -1805,7 +1805,7 @@ let () =
field" when the name has no escape in it. Refusing is what keeps those
two facts from quietly disagreeing. *)
json_refusal "json-mixed-array" "{\"xs\": [1, 2, \"three\"]}"
- "element 2 is string";
+ "element 2 is str";
json_refusal "json-null" "{\"a\": null}" "has no type to derive";
json_refusal "json-empty-array" "{\"xs\": []}"
"has no element to derive an element type from";
@@ -3722,7 +3722,7 @@ let () =
and cannot change. *)
refuses "a package generic's bound, refused at the call"
"programs/pkg-generic-reject.flan"
- "string is not ordered?";
+ "str is not ordered?";
refuses "and the refusal quotes the clause the package wrote"
"programs/pkg-generic-reject.flan" "{:where (ordered? $t)}";
@@ -4444,13 +4444,13 @@ level "1"
computed. The Flan name travels with the copy so that the refusal a NUL
in the bytes raises can name the call — see programs/shim-nul.flan. *)
shim_case "declare-c: a string is copied, NUL-terminated and freed"
- "(declare-c open-it [path string] bool \"OpenIt\")"
+ "(declare-c open-it [path str] bool \"OpenIt\")"
[ "char a0_b[256];";
"flan_shim_cstr(a0_p, a0_n, a0_b, sizeof a0_b, \"open-it\")";
"bool r = OpenIt(a0);"; "flan_shim_cstr_free(a0, a0_b, a0_p);";
" return r;\n" ];
shim_case "declare-c: two strings get two buffers"
- "(declare-c both [a string b string] \"Both\")"
+ "(declare-c both [a str b str] \"Both\")"
[ "char a0_b[256];"; "char a1_b[256];";
"flan_shim_cstr_free(a0, a0_b, a0_p);"; "flan_shim_cstr_free(a1, a1_b, a1_p);" ];
@@ -4458,7 +4458,7 @@ level "1"
signature, which is what vendor/agent's flan_agent_start and the
prelude's sqrtf depend on. A program with no declare-c generates no C
at all. *)
- if shim_of "(declare start [path string] i32 \"flan_agent_start\")" <> ""
+ if shim_of "(declare start [path str] i32 \"flan_agent_start\")" <> ""
then begin
incr failures;
print_endline "FAIL declare (not declare-c) generated a shim"
@@ -4478,19 +4478,19 @@ level "1"
"(declare-c takes [xs [4 f32]] \"Takes\")"
"which C passes as a pointer and Flan as a value";
shim_refuses "declare-c: a map"
- "(declare-c takes [m (Map string i32)] \"Takes\")"
+ "(declare-c takes [m (Map str i32)] \"Takes\")"
"which has no C representation";
(* A returned string comes back as the pointer and its length. With no
string argument the pointer is the library's own; with one, it may point
into the argument's copy, so it is moved to the scratch buffer before
that copy is freed. programs/cstr-return.flan runs both. *)
shim_case "declare-c: a returned string answers its length"
- "(declare-c name [] string \"Name\")"
+ "(declare-c name [] str \"Name\")"
[ "extern const char * Name(void);";
"const char *r = flan_shim_ret_len(Name(), out_n);";
"int32_t *out_n" ];
shim_case "declare-c: a returned string outlives the argument copies"
- "(declare-c base [p string] string \"Base\")"
+ "(declare-c base [p str] str \"Base\")"
[ "const char *r = flan_shim_ret_keep(Base(a0), out_n);\n\
\ flan_shim_cstr_free(a0, a0_b, a0_p);\n return r;\n" ];
shim_refuses "declare-c: a callback"
@@ -5080,7 +5080,7 @@ level "1"
(* A number has no pointer to be recognised by, so it takes the location of
the call around it — a form the author wrote, which does have one. *)
reports "a literal a macro passed through" "programs/macro-loc-literal.flan"
- [ "macro-loc-literal.flan:17:5: expected string, found the integer \
+ [ "macro-loc-literal.flan:17:5: expected str, found the integer \
literal 5";
"macro-loc-literal.flan:16:3: note: expanded from the macro thru" ];
(* The list is the macro's and is reported at the call; the name inside it
@@ -6594,8 +6594,8 @@ level "1"
| _ -> ()));
()
in
- let cell = "(defstruct Cell [alive bool heat f64 id i32 name string])\n" in
- let cell' = "(defstruct Cell [name string id i32 alive bool heat f64])\n" in
+ let cell = "(defstruct Cell [alive bool heat f64 id i32 name str])\n" in
+ let cell' = "(defstruct Cell [name str id i32 alive bool heat f64])\n" in
let body = "(defn main [] i32 (let [c (Cell {.id 1})] (i32 (.id c))))\n" in
layout_case "DWARF offsets agree with LLVM: a mixed struct" (cell ^ body)
"Cell" [ "alive"; "heat"; "id"; "name" ];
@@ -6894,7 +6894,7 @@ level "1"
("!DIBasicType(name: \"bool\", size: 8, encoding: DW_ATE_boolean)", "bool");
(* ptr+len, and shown as ptr+len — there is no owner and no capacity
to hide, so two members are the whole truth about a string. *)
- ("name: \"string\", size: 128", "string");
+ ("name: \"str\", size: 128", "str");
(* A let-bound local carries the name the source gave it. [Tast.fn]
records one per slot and [Check] fills it in at the binding, so
[(let [c ...)] is [c] in the debug info and not [s0] -- which is
@@ -7002,7 +7002,7 @@ level "1"
(defn fetch [n i32] i32\n\
\ (restart-case\n\
\ (do (error (Missing {.id n})) 0)\n\
- \ (use-value [v i32 s string] (do (print s) v))\n\
+ \ (use-value [v i32 s str] (do (print s) v))\n\
\ (use-placeholder [] -1)))\n\
(defn run [] i32\n\
\ (defer (set seen (+ seen 1)))\n\
diff --git a/test/test_dev.ml b/test/test_dev.ml
index e7dd4f1b..a2287ce7 100644
--- a/test/test_dev.ml
+++ b/test/test_dev.ml
@@ -2546,7 +2546,7 @@ let () =
in
let want =
[ ("n", "i64", "3");
- ("label", "string", "\"hello\"");
+ ("label", "str", "\"hello\"");
(* The *renderer's* output, not source — and it is a dot now.
[render.ml] and [emacs/flan-inspect.el] are the two ends of
one wire format, and they moved together, which is what the
@@ -2571,7 +2571,7 @@ let () =
outer [label] is on the same list: strip the suffix from one
and the frame shows two rows called [label] with nothing to
tell them apart. *)
- ("label~2", "string", "\"inner\"") ]
+ ("label~2", "str", "\"inner\"") ]
in
if got <> want then
fail "locals of the stopped frame: %s"
@@ -2619,7 +2619,7 @@ let () =
one slot more than the body this session now holds. *)
let r =
ask
- "(:op \"eval\" :code \"(defn look [n i64 label string] i64 (let [p (Point {.x 1.5 .y 2.5}) xs [10 20 30]] (restart-case (do (error (Boom {.why 7})) (let [after (i64 99)] after)) (carry-on [] 5))))\" :file \"/tmp/buf.flan\")"
+ "(:op \"eval\" :code \"(defn look [n i64 label str] i64 (let [p (Point {.x 1.5 .y 2.5}) xs [10 20 30]] (restart-case (do (error (Boom {.why 7})) (let [after (i64 99)] after)) (carry-on [] 5))))\" :file \"/tmp/buf.flan\")"
in
if status r <> "ok" then
fail "installing a body with fewer slots while stopped: %s"
@@ -2643,7 +2643,7 @@ let () =
or the *count* would catch this and the fingerprint would go
untested. Every name differs and every type matches, which is
exactly what a count cannot see. *)
- "(:op \"eval\" :code \"(defn look [n i64 label string] i64 (let [q (Point {.x 9.0 .y 9.0}) ys [1 2 3] mark (< n 0) ch (u8 98) sp (u8 33) cc (u8 8)] (dotimes [pip 0] (print \\\"\\\")) (let [tag \\\"x\\\"] (restart-case (do (error (Boom {.why 7})) (let [later (i64 99)] later)) (carry-on [] 5)))))\" :file \"/tmp/buf.flan\")"
+ "(:op \"eval\" :code \"(defn look [n i64 label str] i64 (let [q (Point {.x 9.0 .y 9.0}) ys [1 2 3] mark (< n 0) ch (u8 98) sp (u8 33) cc (u8 8)] (dotimes [pip 0] (print \\\"\\\")) (let [tag \\\"x\\\"] (restart-case (do (error (Boom {.why 7})) (let [later (i64 99)] later)) (carry-on [] 5)))))\" :file \"/tmp/buf.flan\")"
in
if status r <> "ok" then
fail "installing a renamed body while stopped: %s"
@@ -3606,7 +3606,7 @@ let () =
out of the program's own storage, so both are in it. *)
[ ("grid", "[4 i32]", "[7 5 0 0]", [ 0; 1 ]);
("pressure", "i64", "12", [ 0 ]);
- ("label", "string", "\"running\"", [ 1 ]) ]
+ ("label", "str", "\"running\"", [ 1 ]) ]
in
let got = rows r in
if got <> want then
@@ -6695,7 +6695,7 @@ let () =
else begin
let want =
[ ("n", "i64", "3");
- ("label", "string", "\"hello\"");
+ ("label", "str", "\"hello\"");
("p", "Point", "(Point {.x 1.5 .y 2.5})");
("xs", "[3 i32]", "[10 20 30]");
("flag", "bool", "true");
@@ -6709,7 +6709,7 @@ let () =
the loop's hidden bound hidden, the shadowing rebind kept
raw because the outer [label] is on the same list. *)
("hop", "i32", "0");
- ("label~2", "string", "\"inner\"") ]
+ ("label~2", "str", "\"inner\"") ]
in
let got = triples r "locals" in
if got <> want then
@@ -7456,7 +7456,7 @@ let () =
in
let r =
request c
- "(:op \"eval\" :code \"(defonce msg string)\" \
+ "(:op \"eval\" :code \"(defonce msg str)\" \
:file \"programs/dev-dyn-global.flan\")"
in
if status r <> "ok" then fail "--%s: defonce msg: %s" backend (said r)
@@ -7855,7 +7855,7 @@ let () =
(* A retype is refused before anything is stored, by the pass
that can name both types. *)
let r = request c ("(:op \"eval\" :code "
- ^ Wire.quote "(def speed string \"x\")" ^ file) in
+ ^ Wire.quote "(def speed str \"x\")" ^ file) in
if status r <> "error" then
fail "a def that changes type was accepted (%s)" tag
else if not (contains_sub (said r) "changes type") then
@@ -9607,7 +9607,7 @@ let () =
"(defmethod update-instance-for-redefined-class point \
[p added discarded] nil)"
&& defined "a slot's type changed to one its value does not fit"
- "(defclass point [x string radius z n i32 note string])"
+ "(defclass point [x str radius z n i32 note str])"
then begin
holds "a value that no longer fits is kept"
"(if (= (get (at instances 0) :x) 3) 1 0)";
@@ -9620,7 +9620,7 @@ let () =
let warned () =
contains_sub (output ())
"warning: point was redefined, and its slot :x is now \
- declared string"
+ declared str"
in
if not (await warned) then
fail "%sno warning for a kept value that does not fit: %S" what
diff --git a/test/test_flan.ml b/test/test_flan.ml
index c186c9dd..cadce45c 100644
--- a/test/test_flan.ml
+++ b/test/test_flan.ml
@@ -494,7 +494,7 @@ let () =
| Tapp ("Ptr", [ _ ]) -> () | _ -> check "(Ptr T)" false);
(* A map type is an application like (Ptr T) and (Vec T) now that the brace
spelling is gone: [Ast.Tmap] survives only as what [Cimport] builds. *)
- (match ty "(Map string i32)" with
+ (match ty "(Map str i32)" with
| Tapp ("Map", [ _; _ ]) -> () | _ -> check "(Map K V) is a map type" false);
(match ty "(Fn [a a] bool)" with
| Tfn (_, [ _; _ ], _) -> () | _ -> check "(Fn [T] R)" false);
@@ -1073,7 +1073,7 @@ let () =
infers "int defaults to i32" "42" "i32";
infers "float defaults to f64" "0.5" "f64";
infers "byte is u8" "\\space" "u8";
- infers "string" "\"hi\"" "string";
+ infers "string" "\"hi\"" "str";
infers "bool" "true" "bool";
infers "arithmetic keeps kind" "(+ 1 2)" "i32";
infers "comparison is bool" "(< 1 2)" "bool";
@@ -1107,8 +1107,8 @@ let () =
(* A string slices to a string and indexes to a byte. Not to a [u8]: the
result views bytes the program does not own, and a byte slice is
writable-looking. *)
- infers "slice of a string" "(slice \"hi\" 0 1)" "string";
- infers "whole of a string" "(slice \"hi\")" "string";
+ infers "slice of a string" "(slice \"hi\" 0 1)" "str";
+ infers "whole of a string" "(slice \"hi\")" "str";
infers "string index is a u8" "(at \"hi\" 0)" "u8";
infers "parse text to f64" "(bytes->f64 (bytes \"1.5\"))" "f64";
@@ -1362,7 +1362,7 @@ let () =
infers "a negated literal" "(- 1)" "i32";
infers "a negated literal takes its type from the site" "(i64 (- 1))" "i64";
rejects_check "unary minus over a string names the operand"
- "(defn f [s string] () (println (- s)))" ~needle:"- takes numbers";
+ "(defn f [s str] () (println (- s)))" ~needle:"- takes numbers";
rejects_check "unary minus at an unsigned literal is out of range"
"(defn f [] u8 (- 1))" ~needle:"does not fit in u8";
rejects_check "there is no reciprocal"
@@ -1443,8 +1443,8 @@ let () =
you to plan.org instead of to the character you mistyped. *)
rejects_check "a mistyped primitive" "(defn f [x f65] ())"
~needle:"did you mean f64?";
- rejects_check "a transposed primitive" "(defn f [x stirng] ())"
- ~needle:"did you mean string?";
+ rejects_check "a transposed primitive" "(defn f [x i23] ())"
+ ~needle:"did you mean i32?";
rejects_check "a mistyped struct"
"(defstruct Cursor [x i32]) (defn f [c Curser] ())"
~needle:"did you mean Cursor?";
@@ -1519,7 +1519,7 @@ let () =
would need a dyn string's own boxing, whose payload is a pointer into
the collector's heap, planted where nothing will ever trace it. *)
rejects_check "a Vec of strings does not view into dyn yet"
- "(defonce v (Vec string) (vec-new string))\n\
+ "(defonce v (Vec str) (vec-new str))\n\
(defn take [d dyn] i32 1)\n\
(defn main [] i32 (take v))"
~needle:"only when its elements are i64, f64 or bool";
@@ -1543,7 +1543,7 @@ let () =
rejects_check "a local Vec of strings gets the element refusal, not the \
lifetime one"
"(defn take [d dyn] i32 1)\n\
- (defn main [] i32 (let [v (vec-new string)] (take v)))"
+ (defn main [] i32 (let [v (vec-new str)] (take v)))"
~needle:"only when its elements are i64, f64 or bool";
(* ── The lifetime guard, added on review ─────────────────────────
A local, a parameter and a temporary all answer false to
@@ -2039,7 +2039,7 @@ let () =
\ (if (has-key? m :b) (length m) 0)))";
accepts "has-key? still serves the typed map"
"(defn main [] i32\n\
- \ (let [m (map-new string i32 (heap-allocator))]\n\
+ \ (let [m (map-new str i32 (heap-allocator))]\n\
\ (if (has-key? m \"a\") 1 0)))";
(* The x86 backend used to refuse dyn by name, and what was pinned here was
@@ -2230,35 +2230,35 @@ let () =
(* A string indexes and slices, and neither is a place: it is a view of
bytes the program does not own — a literal's are in constant storage —
so there is no store through one to allow. *)
- accepts "a string slices" "(defn f [s string] string (slice s 1))";
- accepts "a string indexes" "(defn f [s string] u8 (at s 1))";
+ accepts "a string slices" "(defn f [s str] str (slice s 1))";
+ accepts "a string indexes" "(defn f [s str] u8 (at s 1))";
(* Both routes to a Pindex, because there are two and they do not share a
line of code: one index goes through the [set] arm that checks its own
target, two through [check_place]. The one-index spelling is the one a
person writes, and it is the one that would silently store into
constant data. *)
rejects_check "set through a string"
- "(defn f [s string] () (set (at s 0) 65))" ~needle:"not a place";
+ "(defn f [s str] () (set (at s 0) 65))" ~needle:"not a place";
rejects_check "set through a string, two indices"
- "(defn f [s [2 string]] () (set (at s 0 0) 65))" ~needle:"not a place";
+ "(defn f [s [2 str]] () (set (at s 0 0) 65))" ~needle:"not a place";
(* The mirror, and the one the walk could break by moving the question a
level up: the refusal is about the type being *indexed*, not about the
element that comes out. An array of strings has a string element and
indexes nothing but the array, so assigning a whole one stays legal. *)
accepts "set an array's string element"
- "(defn f [s [2 string]] () (set (at s 0) \"world\"))";
+ "(defn f [s [2 str]] () (set (at s 0) \"world\"))";
rejects_check "set through a string's slice"
- "(defn f [s string] () (set (at (slice s 1) 0) 65))"
+ "(defn f [s str] () (set (at (slice s 1) 0) 65))"
~needle:"not a place";
(* The address of one is a (Ptr const u8), so it is not a (Ptr u8). *)
rejects_check "the address of a string's byte is read-only"
- "(defn f [s string] (Ptr u8) (addr (at s 0)))"
+ "(defn f [s str] (Ptr u8) (addr (at s 0)))"
~needle:"expected (Ptr u8), found (Ptr const u8)";
(* And a string is still not a [u8]: slicing one does not smuggle a byte
slice out of it. *)
rejects_check "a string slice is not a byte slice"
- "(defn g [b [u8]] i32 (length b)) (defn f [s string] i32 (g (slice s)))"
- ~needle:"expected [u8], found string";
+ "(defn g [b [u8]] i32 (length b)) (defn f [s str] i32 (g (slice s)))"
+ ~needle:"expected [u8], found str";
(* [const T]: a view that can only be read. Every route to a store through
one is refused, and none of the reads is. *)
@@ -2266,8 +2266,8 @@ let () =
"(slice (bytes-view \"hello\") 1 3)" "[const u8]";
infers "vec-new reads [const u8] as a type" "(vec-new [const u8])"
"(Vec [const u8])";
- infers "map-new reads [const u8] as a type" "(map-new string [const u8])"
- "(Map string [const u8])";
+ infers "map-new reads [const u8] as a type" "(map-new str [const u8])"
+ "(Map str [const u8])";
rejects_check "set through a const slice"
"(defn f [s [const u8]] () (set (at s 0) 65))"
~needle:"this writes through a [const u8]";
@@ -2316,11 +2316,11 @@ let () =
"(defn f [s [const (Vec i32)]] () (push (at s 0) 5))"
~needle:"reached through a [const (Vec i32)]";
rejects_check "put through a const slice of maps"
- "(defn f [s [const (Map string i32)]] () (put (at s 0) \"a\" 5))"
- ~needle:"reached through a [const (Map string i32)]";
+ "(defn f [s [const (Map str i32)]] () (put (at s 0) \"a\" 5))"
+ ~needle:"reached through a [const (Map str i32)]";
rejects_check "map-remove through a const slice of maps"
- "(defn f [s [const (Map string i32)]] bool (map-remove (at s 0) \"a\"))"
- ~needle:"reached through a [const (Map string i32)]";
+ "(defn f [s [const (Map str i32)]] bool (map-remove (at s 0) \"a\"))"
+ ~needle:"reached through a [const (Map str i32)]";
rejects_check "reserve through a const slice of Vecs"
"(defn f [s [const (Vec i32)]] () (reserve (at s 0) 10))"
~needle:"reached through a [const (Vec i32)]";
@@ -2357,7 +2357,7 @@ let () =
"(defn f [v [const u8]] () (set (deref (addr (at v 0))) 1))"
~needle:"this writes through a (Ptr const u8)";
rejects_check "a store through the address of a string's byte"
- "(defn f [s string] () (set (deref (addr (at s 0))) 1))"
+ "(defn f [s str] () (set (deref (addr (at s 0))) 1))"
~needle:"this writes through a (Ptr const u8)";
rejects_check "a field store through a const pointer"
"(defstruct P [x i32]) (defn f [p (Ptr const P)] () (set (.x p) 1))"
@@ -2494,7 +2494,7 @@ let () =
accepts "a writable slice is a const one"
"(defn g [b [const u8]] u8 (at b 0)) (defn f [s [u8]] u8 (g s))";
accepts "and so is a string's bytes, at a prelude reader"
- "(defn f [s string] bool (bytes=? (bytes-view s) (bytes-view \"x\")))";
+ "(defn f [s str] bool (bytes=? (bytes-view s) (bytes-view \"x\")))";
accepts "under a const slice the element converts too"
"(defn g [p [const [const u8]]] i32 0) (defn f [p [[u8]]] i32 (g p))";
accepts "the address of a const element, for C"
@@ -2666,7 +2666,7 @@ let () =
rejects_check "positional argument of the wrong type"
"(defstruct Cell [row i32 col f32]) \
(defn f [] Cell (Cell 1 \"x\"))"
- ~needle:"expected f32, found string";
+ ~needle:"expected f32, found str";
(* A struct type and a function cannot share a name — [collect]'s
[claimed] table spans every declaration kind — so the head of a call
resolves to exactly one of them and this refusal is what proves it. *)
@@ -2785,13 +2785,13 @@ let () =
application; the refusal names the missing return type rather than the
form's head. *)
rejects_check "a body form in the return slot is a missing return type"
- "(defn f [s string] (dotimes [i (length s)] (println i)))"
+ "(defn f [s str] (dotimes [i (length s)] (println i)))"
~needle:"f has no return type: (dotimes ...) stands where the return type goes";
rejects_check "and says how a function returning nothing is written"
"(defn f [a i32 b i32] (+ a b))"
~needle:"a function that returns nothing writes () there";
accepts "the fix compiles"
- "(defn f [s string] () (dotimes [i (length s)] (println i)))";
+ "(defn f [s str] () (dotimes [i (length s)] (println i)))";
accepts "a type application in the slot is still a type"
"(defn f [] (Option i32) None)";
rejects_check "a misspelled constructor is a near miss"
@@ -2969,7 +2969,7 @@ let () =
accepts "the i32 a rand-i32-range caller wanted"
"(defn f [] i32 (i32 (rand-int-range 0 10)))";
accepts "main with no parameters and no return" "(defn main [] ())";
- accepts "main with argv and a status" "(defn main [args [string]] i32 0)";
+ accepts "main with argv and a status" "(defn main [args [str]] i32 0)";
rejects_check "main with a wrong parameter" "(defn main [n i32] ())"
~needle:"main takes no parameters";
rejects_check "main returning the wrong type" "(defn main [] bool true)"
@@ -3213,7 +3213,7 @@ let () =
accepts "a data type case holding a Vec of itself"
"(defdata Value [Nil (List [items (Vec Value)])])";
accepts "a data type case holding a Map of itself"
- "(defdata Value [Nil (Table [entries (Map string Value)])])";
+ "(defdata Value [Nil (Table [entries (Map str Value)])])";
(* Since the second repeal the plain case is admitted too: a struct or a
case holding a heap-backed Vec copies as bytes, the copies alias one
buffer, and a free through two copies is the program's bug — Odin's
@@ -3917,7 +3917,7 @@ let () =
"(defstruct Oops :parent Error [n i32]) (defn f [] () (error (Oops {.n 1})))";
accepts "a category with no field vector gets Error's fields"
"(defstruct Io :parent Error) (defstruct Full :parent Io [n i32]) \
- (defn f [e Io] string (.message e))";
+ (defn f [e Io] str (.message e))";
accepts "the suggested category spelling compiles"
"(defstruct Category :parent Error)";
rejects_check "a parent with fields of its own is refused, fixed at the parent"
@@ -3930,7 +3930,7 @@ let () =
(defstruct E :parent Error)";
accepts "an empty field vector under a parent is a category"
"(defstruct Io :parent Error []) (defstruct Full :parent Io [n i32]) \
- (defn f [e Io] string (.message e))";
+ (defn f [e Io] str (.message e))";
rejects_check "a parent that is not a struct is refused"
"(defstruct Oops :parent i32 [n i32])"
~needle:"a parent is a condition struct";
@@ -4196,6 +4196,24 @@ let () =
"(defn f [] double 1.0)" ~needle:"unknown type double — Flan spells it f64";
rejects_check "long still teaches"
"(defn f [] long 1)" ~needle:"unknown type long — Flan spells it i64";
+ rejects_check "string teaches str"
+ "(defn f [s string] i32 1)" ~needle:"unknown type string — Flan spells it str";
+ rejects_check "a string field teaches str"
+ "(defstruct P [name string]) (defn f [] i32 1)"
+ ~needle:"unknown type string — Flan spells it str";
+ rejects_check "a string return teaches str"
+ "(defn f [] string \"a\")" ~needle:"unknown type string — Flan spells it str";
+ rejects_check "a string element type teaches str"
+ "(defn f [] i32 (let [v (vec-new string)] 0))"
+ ~needle:"unknown type string — Flan spells it str";
+ rejects_check "a string key type teaches str"
+ "(defn f [] i32 (let [m (map-new string i32)] 0))"
+ ~needle:"unknown type string — Flan spells it str";
+ rejects_check "the string conversion teaches str"
+ "(defn f [b [u8]] str (string b))"
+ ~needle:"unknown function string — Flan spells it str";
+ accepts "a program may name its own function string"
+ "(defn string [b [u8]] str (str b)) (defn f [b [u8]] str (string b))";
(* A shift by the operand's own width or more is poison in LLVM, and at -O2
a poison return is a function that returns nothing at all. A literal count
is rejected; a computed one is masked in [emit]. *)
@@ -4373,10 +4391,10 @@ let () =
none, as in a let binding, the first one that produces a value sets it. *)
rejects_check "a clause that disagrees with the body"
"(defn f [] i32 (restart-case 1 (skip [] \"no\")))"
- ~needle:"expected i32, found string";
+ ~needle:"expected i32, found str";
rejects_check "two clauses that disagree, with nothing expected"
"(defn f [] i32 (let [x (restart-case (exit 1) (a [] 1) (b [] \"no\"))] 0))"
- ~needle:"expected i32, found string";
+ ~needle:"expected i32, found str";
(* §4 finds the first frame offering a name. Two of one name in one frame
would make that a choice nothing in the source shows. *)
rejects_check "one restart-case offering a name twice"
@@ -4454,11 +4472,11 @@ let () =
found. *)
rejects_check "a handler-case clause that disagrees with the body"
(boom ^ "(defn f [] i32 (handler-case 1 [(Boom [c] \"no\")]))")
- ~needle:"expected i32, found string";
+ ~needle:"expected i32, found str";
rejects_check "two handler-case clauses that disagree"
(boom ^ "(defn f [] () (println (handler-case 1 [(Boom [c] 2) \
(Dud [c] \"no\")])))")
- ~needle:"expected i32, found string";
+ ~needle:"expected i32, found str";
(* Two clauses for one condition type: the first would take every one of
them and the second could never run. *)
rejects_check "one condition type twice"
@@ -4733,7 +4751,7 @@ let () =
~needle:"whose arms are (Some x) and None";
rejects_check "arms of different types"
(k ^ "(defn f [k K] i32 (match k :lo 1 _ \"x\"))")
- ~needle:"expected i32, found string";
+ ~needle:"expected i32, found str";
rejects_check "match over something that is none of them"
"(defn f [n [u8]] i32 (match n _ 2))"
~needle:"match works on an Option, a data type, an enum, a bool, a \
@@ -4746,7 +4764,7 @@ let () =
arm that never matches. *)
accepts "match over an i16, a literal arm built at i16"
"(defn f [n i16] i32 (match n 5 1 -3 2 _ 0))";
- accepts "match over a string" "(defn f [s string] i32 (match s \"go\" 1 _ 0))";
+ accepts "match over a string" "(defn f [s str] i32 (match s \"go\" 1 _ 0))";
accepts "match over a dyn, arms of several kinds"
"(defn f [d dyn] i32 (match d 1 1 2.5 2 \"go\" 3 \\a 4 _ 0))";
accepts "match over a number, :else for the rest"
@@ -4762,8 +4780,8 @@ let () =
"(defn f [n i32] i32 (match n \"a\" 1 _ 0))"
~needle:"and \"a\" is a string";
rejects_check "a number arm over a string"
- "(defn f [s string] i32 (match s 5 1 _ 0))"
- ~needle:"so each arm has to be a string, and 5 is a number";
+ "(defn f [s str] i32 (match s 5 1 _ 0))"
+ ~needle:"so each arm has to be a str, and 5 is a number";
rejects_check "a literal match with no _ arm"
"(defn f [n i32] i32 (match n 5 1 6 2))"
~needle:"this match is not exhaustive — its arms are literals, and no list \
@@ -5067,7 +5085,7 @@ let () =
(* const char * is a string going in — the one C spelling that means
something different in a parameter than it does anywhere else. *)
emits "const char * as a string parameter"
- "(declare-c name-length [text string] i32 \"name_length\")";
+ "(declare-c name-length [text str] i32 \"name_length\")";
(* const int * is a pointer C promises not to write through. *)
emits "a const pointer parameter"
"(declare-c count-at [values (Ptr const i32) n i32] i32 \"count_at\")";
@@ -5083,7 +5101,7 @@ let () =
emits "a function of no arguments" "(declare-c take-nothing [] \"take_nothing\")";
(* And returned: text the caller only reads, which the shim copies. *)
emits "const char * as a string return"
- "(declare-c name-of [which i32] string \"name_of\")";
+ "(declare-c name-of [which i32] str \"name_of\")";
(* And the refusals, each by its reason rather than by a count. *)
let refused name needle =
@@ -5703,7 +5721,7 @@ let () =
"(declare-c name-length [text (Ptr u8)] i32 \"name_length\")";
(* And the string face goes on being right, because this is an addition. *)
agreed "a string where the header says const char *"
- "(declare-c name-length [text string] i32 \"name_length\")";
+ "(declare-c name-length [text str] i32 \"name_length\")";
agreed "a pointer that matches the header exactly"
"(declare-c count-at [values (Ptr i32) n i32] i32 \"count_at\")";
agreed "a const pointer that matches the header exactly"
@@ -5750,9 +5768,9 @@ let () =
Over a char * without const the copy would leave the library's buffer
with no owner; over a const char * it is the importer's own face. *)
agreed "a string returned where the header says const char *"
- "(declare-c name-of [which i32] string \"name_of\")";
+ "(declare-c name-of [which i32] str \"name_of\")";
differs "a string returned where the header says char *"
- "(declare-c owned-text [] string \"owned_text\")"
+ "(declare-c owned-text [] str \"owned_text\")"
"which the caller owns";
agreed "a (Ptr u8) returned where the header says char *"
"(declare-c owned-text [] (Ptr u8) \"owned_text\")";
@@ -6053,7 +6071,7 @@ let () =
(d.Loc.dloc.Loc.col = 27);
check "and text is told where concatenation lives"
(contains d.Loc.dmsg
- "+ takes numbers, and this is string — there is no + on text. The \
+ "+ takes numbers, and this is str — there is no + on text. The \
prelude concatenates with concat and join")
| None -> check "a non-numeric operand is refused" false);
@@ -6278,7 +6296,7 @@ let () =
resolution, which is a check that cannot fail — found in review. *)
(match
Check.program
- (program "(defn length [a string b string] i32 999)"
+ (program "(defn length [a str b str] i32 999)"
@ Parse.program
(read ~file:"" "(defn g [] i32 (length \"a\" \"b\"))"))
with
@@ -6302,10 +6320,10 @@ let () =
at two arguments checks, and the qualified one at two arguments is
measured against the builtin's arity. *)
accepts "the bare name reaches the shadowing defn"
- "(defn length [a string b string] i32 999)\n\
+ "(defn length [a str b str] i32 999)\n\
(defn f [] i32 (length \"a\" \"b\"))";
rejects_check "and builtin/ beside it reaches the builtin"
- "(defn length [a string b string] i32 999)\n\
+ "(defn length [a str b str] i32 999)\n\
(defn f [] i32 (builtin/length \"a\" \"b\"))"
~needle:"length takes 1 argument, given 2";
(* The program the earlier lane could not write: a shadowing defn that
@@ -6314,7 +6332,7 @@ let () =
time; what is pinned here is that the body holds no call to [length] at
all, which is the difference between a wrapper and a loop. *)
(match
- checked "(defn length [s string] i32 (builtin/+ 1 (builtin/length s)))"
+ checked "(defn length [s str] i32 (builtin/+ 1 (builtin/length s)))"
with
| p ->
let recurs = ref false in
@@ -6357,7 +6375,7 @@ let () =
than falling through to the function table, which holds the very
definition the qualifier was written to get away from. *)
rejects_check "a call-only builtin is refused as a value, not resolved"
- "(defn length [s string] i32 1)\n(defn f [] () (println builtin/length))"
+ "(defn length [s str] i32 1)\n(defn f [] () (println builtin/length))"
~needle:
"builtin/length is the builtin length, which is a call and not a value";
(* The qualifier reaching nothing. Named as not a builtin, and the
@@ -6388,7 +6406,7 @@ let () =
'/' is an ordinary symbol character — and would land in the function
table under a name nothing can ever call, because the prefix is stripped
before any table is consulted. *)
- (match diag_of "(defn builtin/length [s string] i32 1)" with
+ (match diag_of "(defn builtin/length [s str] i32 1)" with
| Some d ->
check "a declaration cannot take the reserved qualifier"
(contains d.Loc.dmsg
@@ -6606,13 +6624,13 @@ let () =
position entirely, so the slot after the return type can be nothing but
the constraint map, and braces in a type say where the spelling went. *)
accepts "a map return type, written the one way there is"
- "(defn f [] (Map string i32) (map-new string i32))";
+ "(defn f [] (Map str i32) (map-new str i32))";
accepts "a map return type followed by a constraint map"
- "(defn f [x $t] (Map string i32) {:where (equal? $t)} \
- (do x (map-new string i32)))";
+ "(defn f [x $t] (Map str i32) {:where (equal? $t)} \
+ (do x (map-new str i32)))";
rejects_check "braces in type position say where the spelling went"
~needle:"written (Map K V)"
- "(defn f [] {string i32} (map-new string i32))";
+ "(defn f [] {str i32} (map-new str i32))";
(* The predicates, and each one gating the operator it is for. *)
accepts "ordered? admits <"
@@ -7551,7 +7569,7 @@ let () =
(defn arith [a b] () (take (+ a b)))\n\
(defn main [] ()\n\
\ (let [a (arena-new 4096)\n\
- \ tm (map-new string i32 a)\n\
+ \ tm (map-new str i32 a)\n\
\ tv (vec-new i32 a)\n\
\ txt (slurp \"x\" a)]\n\
\ (take gv)\n\
@@ -7684,8 +7702,8 @@ let () =
accepts "max-value at a type variable the bound admits"
"(defn f [x $t] $t {:where (integer? $t)} (max-value t))";
rejects_check "max-value at a type that is not a number names the bound"
- "(defn f [] string (max-value string))"
- ~needle:"max-value takes a numeric? type, and string is not one";
+ "(defn f [] str (max-value str))"
+ ~needle:"max-value takes a numeric? type, and str is not one";
rejects_check "max-value of a value says it takes a type"
"(defn f [x i32] i32 (max-value x))" ~needle:"max-value takes a type";
accepts "max-of of a slice is the prelude's reduction"
@@ -7702,8 +7720,8 @@ let () =
"(defn f [x dyn] i32 (the i32 x))" ~needle:"write (i32 x) to convert it";
accepts "the cast that refusal names compiles" "(defn f [x dyn] i32 (i32 x))";
rejects_check "the refuses a dyn at a type a dyn does not become"
- "(defn f [x dyn] string (the string x))"
- ~needle:"dyn — string does not cross into a written type yet";
+ "(defn f [x dyn] str (the str x))"
+ ~needle:"dyn — str does not cross into a written type yet";
rejects_check "the refuses a dyn at bool, which a dyn becomes where passed"
"(defn f [x dyn] bool (the bool x))"
~needle:"a dyn becomes a bool where a bool is passed";
@@ -7881,7 +7899,7 @@ let () =
(defn od [n i32] _ (if (= n 0) false (ev (- n 1))))\n\
(defn main [] ())";
rejects_check "a body error behind an inferred return is its own"
- ~needle:"expected i32, found string"
+ ~needle:"expected i32, found str"
"(defn f [x i32] _ (+ x \"a\"))\n(defn g [x i32] _ (f x))\n(defn main [] ())";
rejects_check "no value on one path and a value on another"
~needle:"f gives no value here and i32 on another path"
@@ -7938,7 +7956,7 @@ let () =
~needle:"300 does not fit in u8"
"(defn f [c bool] _ (when c (return 300)) (u8 2))\n(defn main [] ())";
rejects_check "a string exit and a number exit"
- ~needle:"expected string, found the integer literal 1"
+ ~needle:"expected str, found the integer literal 1"
"(defn f [c bool] _ (when c (return \"s\")) 1)\n(defn main [] ())";
rejects_check "a constant computed by a _ function, as by a written one"
~needle:"a constant's value must be a compile-time constant — the constant K is computed"
@@ -7982,7 +8000,7 @@ let () =
| _ -> check "a match arm of another type is refused" false
| exception Loc.Error { Loc.dloc; dmsg; _ } ->
check "a match arm of another type is refused at its value"
- (dloc.Loc.col = 87 && contains dmsg "expected i8, found string"));
+ (dloc.Loc.col = 87 && contains dmsg "expected i8, found str"));
(* Nested arms that meet at a wider type are checked once each, not once
per level above them — when the else arm fits the then arm's type, and
when it is wider, so that every level's first attempt is refused. *)
@@ -8090,8 +8108,8 @@ let () =
~needle:"(Option i64) does not cross into dyn yet"
"(defn eqo [b (Option i64) d dyn] bool (= b d))\n(defn main [] ())";
rejects_check "nil beside a string, as before"
- ~needle:"string"
- "(defn f [c bool s string] string (let [v (if c s nil)] v))\n(defn main [] ())";
+ ~needle:"str"
+ "(defn f [c bool s str] str (let [v (if c s nil)] v))\n(defn main [] ())";
rejects_check "an else arm's own error is the one reported"
~needle:"unknown function nope2"
"(defn g [c bool a i32 b i64] i64 (let [v (if c a (+ b (nope2 1)))] v))\n\
diff --git a/test/test_sanitize.ml b/test/test_sanitize.ml
index 5e5b61bf..8f32618c 100644
--- a/test/test_sanitize.ml
+++ b/test/test_sanitize.ml
@@ -685,7 +685,7 @@ let () =
control ~expect_report:false ~args:[ "2" ] "flan-san-ctl-negslice"
~why:"flan_bytes_to_i64 or flan_bytes_to_f64 is reading off the end of \
a negative-length slice again — see clamp_len in flan_rt.c."
- "(defn main [args [string]] i32\n\
+ "(defn main [args [str]] i32\n\
\ (let [s (bytes-view \"42\")\n\
\ n (i32 (bytes->i64 (bytes-view (at args 1))))]\n\
\ (print (bytes->i64 (slice s n 1)))\n\
diff --git a/test/test_session.ml b/test/test_session.ml
index d0f5b417..328158fd 100644
--- a/test/test_session.ml
+++ b/test/test_session.ml
@@ -1396,7 +1396,7 @@ let () =
if not (has got want) then
fail "expanding a defedn: %S is not in\n%s" want got)
[ (* The struct, with a type per field derived from the value. *)
- "(defstruct Tuning [name string hp i64 speed f64 boss? bool";
+ "(defstruct Tuning [name str hp i64 speed f64 boss? bool";
(* The vector, and the constructor that states its type so that
(vec-new) has something to take it from. *)
"drops (Vec i64)";
diff --git a/vendor/agent/agent.flan b/vendor/agent/agent.flan
index cbae3cee..0173fb3b 100644
--- a/vendor/agent/agent.flan
+++ b/vendor/agent/agent.flan
@@ -21,7 +21,7 @@
;;;;
;;;; No aggregate crosses this boundary, so there is no shim: a Flan string is
;;;; already ptr+len and flan_agent_start takes it that way.
-(declare start-at-raw [path string] i32 "flan_agent_start")
+(declare start-at-raw [path str] i32 "flan_agent_start")
(declare start-auto-raw [] i32 "flan_agent_start_auto")
(declare poll-raw [] i32 "flan_agent_poll")
(declare wait-raw [ms i32] i32 "flan_agent_wait")
@@ -30,7 +30,7 @@
;;; an error and not a second listener: the C side answers 0 and leaves the
;;; first socket alone, so a program that gets a listener from somewhere else
;;; and also calls start is a program with one listener.
-(defn start-at [path string] i32 (start-at-raw path))
+(defn start-at [path str] i32 (start-at-raw path))
(defn start-auto [] i32 (start-auto-raw))
;;; The optional argument, which Flan has no other spelling for: a function
diff --git a/vendor/edn/edn.flan b/vendor/edn/edn.flan
index a9f14590..63286e73 100644
--- a/vendor/edn/edn.flan
+++ b/vendor/edn/edn.flan
@@ -194,7 +194,7 @@
;; Each refusal names itself and says why, so a file that uses one fails with
;; the sentence explaining what to do about it rather than with a code.
-(defn error-message [code i32] string
+(defn error-message [code i32] str
(cond
(= code err-none) "no error"
(= code err-unexpected-byte) "unexpected byte: not the start of any EDN value"
@@ -536,12 +536,12 @@
(Some (bytes=? (.text t) (bytes-view "true")))
None))
-(defn- text=? [t Token s string] bool
+(defn- text=? [t Token s str] bool
(bytes=? (.text t) (bytes-view s)))
;; A keyword whose name is s. The leading colon is not part of `text`, so this
;; is written (keyword=? t "hp") and not (keyword=? t ":hp").
-(defn keyword=? [t Token s string] bool
+(defn keyword=? [t Token s str] bool
(and (= (.kind t) tok-keyword) (bytes=? (.text t) (bytes-view s))))
;; ── Reading past a value ────────────────────────────────────────────
diff --git a/vendor/edn/provide.flan b/vendor/edn/provide.flan
index ab7b5c80..b558a3d4 100644
--- a/vendor/edn/provide.flan
+++ b/vendor/edn/provide.flan
@@ -57,13 +57,13 @@
;; ── Small string work, for the refusals and the names ───────────────
-(defn- joined [a string b string] string
+(defn- joined [a str b str] str
(let [v (vec-new u8)]
(append (addr v) (bytes-view a))
(append (addr v) (bytes-view b))
- (string (slice v))))
+ (str (slice v))))
-(defn- joined3 [a string b string c string] string
+(defn- joined3 [a str b str c str] str
(joined a (joined b c)))
;; Copied out, and not `(string (i64->bytes n))`. The prelude's note over
@@ -71,16 +71,16 @@
;; in the runtime, so two of its results cannot be held at once — and `where`
;; below holds a line and a column at the same time, which read as the same
;; number until this copied.
-(defn- i64->string [n i64] string
+(defn- i64->string [n i64] str
(let [v (vec-new u8)]
(append-i64 (addr v) n)
- (string (slice v))))
+ (str (slice v))))
;; The tokenizer answers byte offsets, because that is what a slice into the
;; buffer costs nothing to produce. A person reading a refusal wants a line and
;; a column, so the newlines before the offset are counted here — once per
;; refusal, which is as often as this is ever called.
-(defn- where [src [const u8] pos i32] string
+(defn- where [src [const u8] pos i32] str
(let [line (i64 1)
col (i64 1)
i (i32 0)]
@@ -108,9 +108,9 @@
[ty Form
decls [Form]
reader Form
- bad string])
+ bad str])
-(defn- derived-bad [msg string] Derived
+(defn- derived-bad [msg str] Derived
(Derived {.ty `i64 .decls (form-nil) .reader `0 .bad msg}))
(defn- ok-derived [ty Form decls [Form] reader Form] Derived
@@ -146,11 +146,11 @@
;; a struct and a Token's text. The lifetime contract at the top of edn.flan is
;; the reason: `text` is a slice of the buffer, and a struct read out of a
;; buffer that is later freed would hold a dangling one.
-(defn need-string [c (Ptr Cursor) a Allocator] string
+(defn need-string [c (Ptr Cursor) a Allocator] str
(let [t (expect c tok-string)
b (vec-new u8 a)]
(append (addr b) (.text t))
- (string (slice b))))
+ (str (slice b))))
;; Whether the next thing, past trivia, is this byte. Enough of a peek for
;; every loop below — "is the collection over" is the only lookahead a reader
@@ -178,8 +178,8 @@
;; an unknown one, and of the token that ended the map for a missing one, which
;; is where a person would look to add it.
(defstruct SchemaDrift
- [field string
- struct string
+ [field str
+ struct str
extra? bool
pos i32])
@@ -203,7 +203,7 @@
;; something to stop on. `code` is an err-* constant, which `error-message`
;; turns into a sentence.
(defstruct ReadFailed
- [struct string
+ [struct str
code i32
pos i32])
@@ -212,7 +212,7 @@
;; One value, from the cursor's current position, consumed. `name` is what a
;; struct here would be called; `src` is the whole buffer, for the positions a
;; refusal names.
-(defn- derive [c (Ptr Cursor) name string src [const u8]] Derived
+(defn- derive [c (Ptr Cursor) name str src [const u8]] Derived
(let [t (next c)]
(when (not (ok? c))
(return (derived-bad
@@ -222,7 +222,7 @@
(= (.kind t) tok-int) (ok-derived `i64 (form-nil) `(need-int c))
(= (.kind t) tok-float) (ok-derived `f64 (form-nil) `(need-float c))
(= (.kind t) tok-bool) (ok-derived `bool (form-nil) `(need-bool c))
- (= (.kind t) tok-string) (ok-derived `string (form-nil) `(need-string c a))
+ (= (.kind t) tok-string) (ok-derived `str (form-nil) `(need-string c a))
(= (.kind t) tok-map-open) (derive-map c name (.pos t) src)
(= (.kind t) tok-vec-open) (derive-vec c name (.pos t) src)
@@ -242,7 +242,7 @@
;; decides; every one after it is compared against that decision and both
;; positions are named when they disagree, because "heterogeneous" without
;; saying where sends someone to read the whole file.
-(defn- derive-vec [c (Ptr Cursor) name string at-pos i32 src [const u8]] Derived
+(defn- derive-vec [c (Ptr Cursor) name str at-pos i32 src [const u8]] Derived
(when (at-byte? c \])
(return (derived-bad
(joined3 "the empty vector at " (where src at-pos)
@@ -291,7 +291,7 @@
;; A set becomes `(Map T bool)`, so its elements are map keys. `derive-key` is
;; where that constraint is enforced and said.
-(defn- derive-set [c (Ptr Cursor) name string at-pos i32 src [const u8]] Derived
+(defn- derive-set [c (Ptr Cursor) name str at-pos i32 src [const u8]] Derived
(when (at-byte? c \})
(return (derived-bad
(joined3 "the empty set at " (where src at-pos)
@@ -326,7 +326,7 @@
;; fixed array, which is one where a Vec is not; anything else is refused here
;; rather than at the `(Map ...)` the caller would build out of it, because a
;; map-key refusal names a type nobody wrote.
-(defn- derive-key [c (Ptr Cursor) name string src [const u8]] Derived
+(defn- derive-key [c (Ptr Cursor) name str src [const u8]] Derived
(when (at-byte? c \[)
(return (derive-array c name src)))
(let [d (derive c name src)]
@@ -342,7 +342,7 @@
;; of the set has to be the same length as well as the same shape — which falls
;; out of the type comparison the caller already makes, since the length is in
;; the type it compares.
-(defn- derive-array [c (Ptr Cursor) name string src [const u8]] Derived
+(defn- derive-array [c (Ptr Cursor) name str src [const u8]] Derived
(let [open (next c)]
(when (at-byte? c \])
(return (derived-bad
@@ -379,8 +379,8 @@
(expect c tok-vec-close)
arr)))))))
-(defn- disagreement [what string src [const u8] at-pos i32 n i64
- first Form second Form] string
+(defn- disagreement [what str src [const u8] at-pos i32 n i64
+ first Form second Form] str
(joined3 (joined3 "the " what " at ")
(where src at-pos)
(joined3 (joined3 " holds more than one shape: its first element is "
@@ -400,7 +400,7 @@
;; differently is the two arms a hand-written reader had no reason to have — a
;; key that is not a field of the struct, and a field the file did not have.
;; Both signal SchemaDrift. See the note over that type.
-(defn- derive-map [c (Ptr Cursor) name string at-pos i32 src [const u8]] Derived
+(defn- derive-map [c (Ptr Cursor) name str at-pos i32 src [const u8]] Derived
(when (at-byte? c \})
(return (derived-bad
(joined3 "the empty map at " (where src at-pos)
@@ -491,7 +491,7 @@
;; A type form as text, for the refusals. Only the shapes this file builds — a
;; name, a number, `(Vec T)`, `(Map K V)` and `[n T]` — because nothing else
;; ever reaches it.
-(defn render [f Form] string
+(defn render [f Form] str
(match f
(Form.Sym s) s
(Form.Int i) (i64->string i)
@@ -499,7 +499,7 @@
(Form.Vec xs) (joined3 "[" (render-items xs) "]")
_ "?"))
-(defn- render-items [xs [Form]] string
+(defn- render-items [xs [Form]] str
(let [out ""]
(dotimes [i (length xs)]
(set out (if (= i 0)
@@ -543,7 +543,7 @@
_ (refuse "defedn's first argument is the name of the struct to declare, written as a name"))
_ (refuse "defedn's second argument is the path to the data file, written as a string literal — the file is read while this is being compiled, so there is nothing here to compute a path from"))))
-(defn- provide [name string path string src [const u8]] Form
+(defn- provide [name str path str src [const u8]] Form
(let [cur (cursor src)
d (derive (addr cur) name src)]
(if (bad? d)
@@ -570,7 +570,7 @@
.code (.err c)
.pos (.err-pos c)})))
out))
- (defn ~fname [p string a Allocator] ~sname
+ (defn ~fname [p str a Allocator] ~sname
(let [b (slurp p a)]
(~bname (slice b) a)))))))))
@@ -580,5 +580,5 @@
;; already put the report on the `defedn` the author wrote. The name is a
;; gensym, so two refusals in one file are two reports rather than a name
;; defined twice.
-(defn- refuse [msg string] Form
+(defn- refuse [msg str] Form
`(defn ~(gensym) [] () (compile-error ~(Form.Str {.s msg}))))
diff --git a/vendor/edn/read.flan b/vendor/edn/read.flan
index e09fb45d..78dc573b 100644
--- a/vendor/edn/read.flan
+++ b/vendor/edn/read.flan
@@ -65,10 +65,10 @@
;; dropped here on purpose. Nothing individually owns a block in a region —
;; free-all owns all of them — so keeping the header around to free through
;; would be keeping a handle for an operation that never happens.
-(defn copy-text [s [const u8]] string
+(defn copy-text [s [const u8]] str
(let [b (vec-new u8)]
(append (addr b) s)
- (string (slice b))))
+ (str (slice b))))
;; ── Reading ─────────────────────────────────────────────────────────
@@ -85,7 +85,7 @@
;; document owns its strings" rule this file has always had: a view into
;; the source buffer would be garbage with nothing to say so the moment
;; the caller reads the next file into it.
- (= (.kind t) tok-string) (string (.text t))
+ (= (.kind t) tok-string) (str (.text t))
(= (.kind t) tok-keyword) (keyword (.text t))
;; A symbol becomes a keyword. Nothing that reads a document this way
;; tells the two apart, and a case nobody can act on differently is a
@@ -155,7 +155,7 @@
;; to write a default is the caller's policy in every program. Nothing here
;; establishes a handler, so slurp's condition reaches the caller's with both
;; restarts still armed.
-(defn read-file [path string] dyn
+(defn read-file [path str] dyn
(let [src (slurp path (heap-allocator))]
(defer (free src))
(read (slice src))))
diff --git a/vendor/json/json.flan b/vendor/json/json.flan
index 647648f5..c9dc5e43 100644
--- a/vendor/json/json.flan
+++ b/vendor/json/json.flan
@@ -239,7 +239,7 @@
;; with the sentence explaining what to do about it rather than with a code.
;; Most of these say "JSON5" somewhere, because most of them are a thing that
;; is legal in the dialect the file was probably written for.
-(defn error-message [code i32] string
+(defn error-message [code i32] str
(cond
(= code err-none) "no error"
(= code err-unexpected-byte) "unexpected byte: not the start of any JSON value"
@@ -671,7 +671,7 @@
;; None only for a token that is not a string. Every way the bytes themselves
;; could be wrong was already refused by read-string, which is why this cannot
;; fail halfway through and leave a half-built answer behind.
-(defn string-of [t Token] (Option string)
+(defn string-of [t Token] (Option str)
(when (!= (.kind t) tok-string)
(return None))
(let [s (.text t)
@@ -718,7 +718,7 @@
;; because a dropped character is not worth a crash and the
;; tokenizer is the place that already said no.
None (do)))))))))
- (Some (string (slice b)))))
+ (Some (str (slice b)))))
;; ── Reading past a value ────────────────────────────────────────────
diff --git a/vendor/json/provide.flan b/vendor/json/provide.flan
index c8e99c3b..9df3186f 100644
--- a/vendor/json/provide.flan
+++ b/vendor/json/provide.flan
@@ -42,28 +42,28 @@
;; ── Small string work ───────────────────────────────────────────────
-(defn- joined [a string b string] string
+(defn- joined [a str b str] str
(let [v (vec-new u8)]
(append (addr v) (bytes-view a))
(append (addr v) (bytes-view b))
- (string (slice v))))
+ (str (slice v))))
-(defn- joined3 [a string b string c string] string
+(defn- joined3 [a str b str c str] str
(joined a (joined b c)))
;; Copied out, and not `(string (i64->bytes n))`: the prelude's note over
;; append-i64 is the reason — i64->bytes renders into one shared static buffer
;; in the runtime, so two of its results cannot be held at once, and `where`
;; holds a line and a column at the same time.
-(defn- i64->string [n i64] string
+(defn- i64->string [n i64] str
(let [v (vec-new u8)]
(append-i64 (addr v) n)
- (string (slice v))))
+ (str (slice v))))
;; The tokenizer answers byte offsets. A person reading a refusal wants a line
;; and a column, so the newlines before the offset are counted here — once per
;; refusal, which is as often as this is ever called.
-(defn- where [src [const u8] pos i32] string
+(defn- where [src [const u8] pos i32] str
(let [line (i64 1)
col (i64 1)
i (i32 0)]
@@ -85,9 +85,9 @@
[ty Form
decls [Form]
reader Form
- bad string])
+ bad str])
-(defn- derived-bad [msg string] Derived
+(defn- derived-bad [msg str] Derived
(Derived {.ty `i64 .decls (form-nil) .reader `0 .bad msg}))
(defn- ok-derived [ty Form decls [Form] reader Form] Derived
@@ -123,7 +123,7 @@
;; `string-of` and not `.text`. The header says why: `.text` is the raw
;; interior and an escape in it has not been decoded, so a field read off it
;; would hold a backslash and an n where the file meant a newline.
-(defn need-string [c (Ptr Cursor)] string
+(defn need-string [c (Ptr Cursor)] str
(match (string-of (expect c tok-string)) (Some s) s None ""))
;; Whether the next thing, past whitespace, is this byte. Enough of a peek for
@@ -154,8 +154,8 @@
;; other. A program reading both files binds two clauses, which is the honest
;; shape: the two conditions carry different provenance.
(defstruct SchemaDrift
- [field string
- struct string
+ [field str
+ struct str
extra? bool
pos i32])
@@ -167,13 +167,13 @@
;; louder failure would have had the quieter answer. `code` is an err-*
;; constant, which `error-message` turns into a sentence.
(defstruct ReadFailed
- [struct string
+ [struct str
code i32
pos i32])
;; ── Deriving ────────────────────────────────────────────────────────
-(defn- derive [c (Ptr Cursor) name string src [const u8]] Derived
+(defn- derive [c (Ptr Cursor) name str src [const u8]] Derived
(let [t (next c)]
(when (not (ok? c))
(return (derived-bad
@@ -183,7 +183,7 @@
(= (.kind t) tok-int) (ok-derived `i64 (form-nil) `(need-int c))
(= (.kind t) tok-float) (ok-derived `f64 (form-nil) `(need-float c))
(= (.kind t) tok-bool) (ok-derived `bool (form-nil) `(need-bool c))
- (= (.kind t) tok-string) (ok-derived `string (form-nil) `(need-string c))
+ (= (.kind t) tok-string) (ok-derived `str (form-nil) `(need-string c))
(= (.kind t) tok-object-open) (derive-object c name (.pos t) src)
(= (.kind t) tok-array-open) (derive-array c name (.pos t) src)
@@ -202,7 +202,7 @@
;; every one after it is compared against that, and both positions are named
;; when they disagree — "heterogeneous" on its own sends someone to read the
;; whole file.
-(defn- derive-array [c (Ptr Cursor) name string at-pos i32 src [const u8]] Derived
+(defn- derive-array [c (Ptr Cursor) name str at-pos i32 src [const u8]] Derived
(when (at-byte? c \])
(return (derived-bad
(joined3 "the empty array at " (where src at-pos)
@@ -248,7 +248,7 @@
;; ── An object, which is a struct ────────────────────────────────────
-(defn- derive-object [c (Ptr Cursor) name string at-pos i32 src [const u8]] Derived
+(defn- derive-object [c (Ptr Cursor) name str at-pos i32 src [const u8]] Derived
(when (at-byte? c \})
(return (derived-bad
(joined3 "the empty object at " (where src at-pos)
@@ -346,7 +346,7 @@
;; The generated reader's key test. Against the raw interior, which is the
;; whole of why a name with an escape in it is refused above.
-(defn key=? [t Token s string] bool
+(defn key=? [t Token s str] bool
(bytes=? (.text t) (bytes-view s)))
(defn- has-escape? [s [const u8]] bool
@@ -372,10 +372,10 @@
;; A copy of a token's raw text as a string. The Vec header is dropped here on
;; purpose: this runs inside the compiler, where an expansion is bounded by the
;; size of the program being compiled.
-(defn- copy-of [s [const u8]] string
+(defn- copy-of [s [const u8]] str
(let [b (vec-new u8)]
(append (addr b) s)
- (string (slice b))))
+ (str (slice b))))
;; ── Comparing and rendering a type form ─────────────────────────────
@@ -384,7 +384,7 @@
;; A type form as text, for the refusals. Only the shapes this file builds — a
;; name and `(Vec T)` — because nothing else ever reaches it.
-(defn render [f Form] string
+(defn render [f Form] str
(match f
(Form.Sym s) s
(Form.Int i) (i64->string i)
@@ -392,7 +392,7 @@
(Form.Vec xs) (joined3 "[" (render-items xs) "]")
_ "?"))
-(defn- render-items [xs [Form]] string
+(defn- render-items [xs [Form]] str
(let [out ""]
(dotimes [i (length xs)]
(set out (if (= i 0)
@@ -424,7 +424,7 @@
_ (refuse "defjson's first argument is the name of the struct to declare, written as a name"))
_ (refuse "defjson's second argument is the path to the data file, written as a string literal — the file is read while this is being compiled, so there is nothing here to compute a path from"))))
-(defn- provide [name string path string src [const u8]] Form
+(defn- provide [name str path str src [const u8]] Form
(let [cur (cursor src)
d (derive (addr cur) name src)]
(if (bad? d)
@@ -451,7 +451,7 @@
.code (.err c)
.pos (.err-pos c)})))
out))
- (defn ~fname [p string a Allocator] ~sname
+ (defn ~fname [p str a Allocator] ~sname
(let [b (slurp p a)]
(~bname (slice b) a)))))))))
@@ -460,5 +460,5 @@
;; calls: the checker walks it, the arm fires, and `Loc.from_macro` has already
;; put the report on the `defjson` the author wrote. The name is a gensym, so
;; two refusals in one file are two reports rather than a name defined twice.
-(defn- refuse [msg string] Form
+(defn- refuse [msg str] Form
`(defn ~(gensym) [] () (compile-error ~(Form.Str {.s msg}))))
diff --git a/vendor/raylib/generated.flan b/vendor/raylib/generated.flan
index 2ce0d70f..9205d3d1 100644
--- a/vendor/raylib/generated.flan
+++ b/vendor/raylib/generated.flan
@@ -28,7 +28,7 @@
(declare-c restore-window [] "RestoreWindow")
(declare-c set-window-icon [image Image] "SetWindowIcon")
(declare-c set-window-icons [images (Ptr Image) count i32] "SetWindowIcons")
-(declare-c set-window-title [title string] "SetWindowTitle")
+(declare-c set-window-title [title str] "SetWindowTitle")
(declare-c set-window-position [x i32 y i32] "SetWindowPosition")
(declare-c set-window-monitor [monitor i32] "SetWindowMonitor")
(declare-c set-window-min-size [width i32 height i32] "SetWindowMinSize")
@@ -49,9 +49,9 @@
(declare-c get-monitor-refresh-rate [monitor i32] i32 "GetMonitorRefreshRate")
(declare-c get-window-position [] Vector2 "GetWindowPosition")
(declare-c get-window-scale-dpi [] Vector2 "GetWindowScaleDPI")
-(declare-c get-monitor-name [monitor i32] string "GetMonitorName")
-(declare-c set-clipboard-text [text string] "SetClipboardText")
-(declare-c get-clipboard-text [] string "GetClipboardText")
+(declare-c get-monitor-name [monitor i32] str "GetMonitorName")
+(declare-c set-clipboard-text [text str] "SetClipboardText")
+(declare-c get-clipboard-text [] str "GetClipboardText")
(declare-c get-clipboard-image [] Image "GetClipboardImage")
(declare-c enable-event-waiting [] "EnableEventWaiting")
(declare-c disable-event-waiting [] "DisableEventWaiting")
@@ -73,27 +73,27 @@
(declare-c get-random-value [min i32 max i32] i32 "GetRandomValue")
(declare-c load-random-sequence [count u32 min i32 max i32] (Ptr i32) "LoadRandomSequence")
(declare-c unload-random-sequence [sequence (Ptr i32)] "UnloadRandomSequence")
-(declare-c take-screenshot [file-name string] "TakeScreenshot")
-(declare-c open-url [url string] "OpenURL")
-(declare-c load-file-data [file-name string data-size (Ptr i32)] (Ptr u8) "LoadFileData")
+(declare-c take-screenshot [file-name str] "TakeScreenshot")
+(declare-c open-url [url str] "OpenURL")
+(declare-c load-file-data [file-name str data-size (Ptr i32)] (Ptr u8) "LoadFileData")
(declare-c unload-file-data [data (Ptr u8)] "UnloadFileData")
-(declare-c save-file-data [file-name string data (Ptr u8) data-size i32] bool "SaveFileData")
-(declare-c export-data-as-code [data (Ptr const u8) data-size i32 file-name string] bool "ExportDataAsCode")
-(declare-c file-exists [file-name string] bool "FileExists")
-(declare-c directory-exists [dir-path string] bool "DirectoryExists")
-(declare-c file-extension? [file-name string ext string] bool "IsFileExtension")
-(declare-c get-file-length [file-name string] i32 "GetFileLength")
-(declare-c get-file-extension [file-name string] string "GetFileExtension")
-(declare-c get-file-name [file-path string] string "GetFileName")
-(declare-c get-file-name-without-ext [file-path string] string "GetFileNameWithoutExt")
-(declare-c get-directory-path [file-path string] string "GetDirectoryPath")
-(declare-c get-prev-directory-path [dir-path string] string "GetPrevDirectoryPath")
-(declare-c get-working-directory [] string "GetWorkingDirectory")
-(declare-c get-application-directory [] string "GetApplicationDirectory")
-(declare-c make-directory [dir-path string] i32 "MakeDirectory")
-(declare-c change-directory [dir string] bool "ChangeDirectory")
-(declare-c path-file? [path string] bool "IsPathFile")
-(declare-c file-name-valid? [file-name string] bool "IsFileNameValid")
+(declare-c save-file-data [file-name str data (Ptr u8) data-size i32] bool "SaveFileData")
+(declare-c export-data-as-code [data (Ptr const u8) data-size i32 file-name str] bool "ExportDataAsCode")
+(declare-c file-exists [file-name str] bool "FileExists")
+(declare-c directory-exists [dir-path str] bool "DirectoryExists")
+(declare-c file-extension? [file-name str ext str] bool "IsFileExtension")
+(declare-c get-file-length [file-name str] i32 "GetFileLength")
+(declare-c get-file-extension [file-name str] str "GetFileExtension")
+(declare-c get-file-name [file-path str] str "GetFileName")
+(declare-c get-file-name-without-ext [file-path str] str "GetFileNameWithoutExt")
+(declare-c get-directory-path [file-path str] str "GetDirectoryPath")
+(declare-c get-prev-directory-path [dir-path str] str "GetPrevDirectoryPath")
+(declare-c get-working-directory [] str "GetWorkingDirectory")
+(declare-c get-application-directory [] str "GetApplicationDirectory")
+(declare-c make-directory [dir-path str] i32 "MakeDirectory")
+(declare-c change-directory [dir str] bool "ChangeDirectory")
+(declare-c path-file? [path str] bool "IsPathFile")
+(declare-c file-name-valid? [file-name str] bool "IsFileNameValid")
(declare-c file-dropped? [] bool "IsFileDropped")
(declare-c compress-data [data (Ptr const u8) data-size i32 comp-data-size (Ptr i32)] (Ptr u8) "CompressData")
(declare-c decompress-data [comp-data (Ptr const u8) comp-data-size i32 data-size (Ptr i32)] (Ptr u8) "DecompressData")
@@ -106,8 +106,8 @@
(declare-c stop-automation-event-recording [] "StopAutomationEventRecording")
(declare-c get-key-pressed-raw [] i32 "GetKeyPressed")
(declare-c get-char-pressed-raw [] i32 "GetCharPressed")
-(declare-c get-gamepad-name [gamepad i32] string "GetGamepadName")
-(declare-c set-gamepad-mappings [mappings string] i32 "SetGamepadMappings")
+(declare-c get-gamepad-name [gamepad i32] str "GetGamepadName")
+(declare-c set-gamepad-mappings [mappings str] i32 "SetGamepadMappings")
(declare-c set-gamepad-vibration [gamepad i32 left-motor f32 right-motor f32 duration f32] "SetGamepadVibration")
(declare-c get-mouse-x [] i32 "GetMouseX")
(declare-c get-mouse-y [] i32 "GetMouseY")
@@ -146,13 +146,13 @@
(declare-c get-spline-point-catmull-rom [p-1 Vector2 p-2 Vector2 p-3 Vector2 p-4 Vector2 t f32] Vector2 "GetSplinePointCatmullRom")
(declare-c get-spline-point-bezier-quad [p-1 Vector2 c-2 Vector2 p-3 Vector2 t f32] Vector2 "GetSplinePointBezierQuad")
(declare-c get-spline-point-bezier-cubic [p-1 Vector2 c-2 Vector2 c-3 Vector2 p-4 Vector2 t f32] Vector2 "GetSplinePointBezierCubic")
-(declare-c load-image-raw [file-name string width i32 height i32 format i32 header-size i32] Image "LoadImageRaw")
-(declare-c load-image-anim [file-name string frames (Ptr i32)] Image "LoadImageAnim")
-(declare-c load-image-anim-from-memory [file-type string file-data (Ptr const u8) data-size i32 frames (Ptr i32)] Image "LoadImageAnimFromMemory")
+(declare-c load-image-raw [file-name str width i32 height i32 format i32 header-size i32] Image "LoadImageRaw")
+(declare-c load-image-anim [file-name str frames (Ptr i32)] Image "LoadImageAnim")
+(declare-c load-image-anim-from-memory [file-type str file-data (Ptr const u8) data-size i32 frames (Ptr i32)] Image "LoadImageAnimFromMemory")
(declare-c load-image-from-texture [texture Texture2D] Image "LoadImageFromTexture")
(declare-c load-image-from-screen [] Image "LoadImageFromScreen")
-(declare-c export-image-to-memory [image Image file-type string file-size (Ptr i32)] (Ptr u8) "ExportImageToMemory")
-(declare-c export-image-as-code [image Image file-name string] bool "ExportImageAsCode")
+(declare-c export-image-to-memory [image Image file-type str file-size (Ptr i32)] (Ptr u8) "ExportImageToMemory")
+(declare-c export-image-as-code [image Image file-name str] bool "ExportImageAsCode")
(declare-c gen-image-gradient-linear [width i32 height i32 direction i32 start Color end Color] Image "GenImageGradientLinear")
(declare-c gen-image-gradient-radial [width i32 height i32 density f32 inner Color outer Color] Image "GenImageGradientRadial")
(declare-c gen-image-gradient-square [width i32 height i32 density f32 inner Color outer Color] Image "GenImageGradientSquare")
@@ -160,11 +160,11 @@
(declare-c gen-image-white-noise [width i32 height i32 factor f32] Image "GenImageWhiteNoise")
(declare-c gen-image-perlin-noise [width i32 height i32 offset-x i32 offset-y i32 scale f32] Image "GenImagePerlinNoise")
(declare-c gen-image-cellular [width i32 height i32 tile-size i32] Image "GenImageCellular")
-(declare-c gen-image-text [width i32 height i32 text string] Image "GenImageText")
+(declare-c gen-image-text [width i32 height i32 text str] Image "GenImageText")
(declare-c image-copy [image Image] Image "ImageCopy")
(declare-c image-from-channel [image Image selected-channel i32] Image "ImageFromChannel")
-(declare-c image-text [text string font-size i32 color Color] Image "ImageText")
-(declare-c image-text-ex [font Font text string font-size f32 spacing f32 tint Color] Image "ImageTextEx")
+(declare-c image-text [text str font-size i32 color Color] Image "ImageText")
+(declare-c image-text-ex [font Font text str font-size f32 spacing f32 tint Color] Image "ImageTextEx")
(declare-c image-to-pot [image (Ptr Image) fill Color] "ImageToPOT")
(declare-c image-alpha-crop [image (Ptr Image) threshold f32] "ImageAlphaCrop")
(declare-c image-alpha-clear [image (Ptr Image) color Color threshold f32] "ImageAlphaClear")
@@ -208,8 +208,8 @@
(declare-c image-draw-triangle-fan-raw [dst (Ptr Image) points (Ptr Vector2) point-count i32 color Color] "ImageDrawTriangleFan")
(declare-c image-draw-triangle-strip-raw [dst (Ptr Image) points (Ptr Vector2) point-count i32 color Color] "ImageDrawTriangleStrip")
(declare-c image-draw [dst (Ptr Image) src Image src-rec Rectangle dst-rec Rectangle tint Color] "ImageDraw")
-(declare-c image-draw-text [dst (Ptr Image) text string pos-x i32 pos-y i32 font-size i32 color Color] "ImageDrawText")
-(declare-c image-draw-text-ex [dst (Ptr Image) font Font text string position Vector2 font-size f32 spacing f32 tint Color] "ImageDrawTextEx")
+(declare-c image-draw-text [dst (Ptr Image) text str pos-x i32 pos-y i32 font-size i32 color Color] "ImageDrawText")
+(declare-c image-draw-text-ex [dst (Ptr Image) font Font text str position Vector2 font-size f32 spacing f32 tint Color] "ImageDrawTextEx")
(declare-c load-texture-cubemap [image Image layout i32] Texture2D "LoadTextureCubemap")
(declare-c update-texture [texture Texture2D pixels (Ptr const u8)] "UpdateTexture")
(declare-c update-texture-rec [texture Texture2D rec Rectangle pixels (Ptr const u8)] "UpdateTextureRec")
@@ -229,33 +229,33 @@
(declare-c set-pixel-color [dst-ptr (Ptr u8) color Color format i32] "SetPixelColor")
(declare-c get-pixel-data-size [width i32 height i32 format i32] i32 "GetPixelDataSize")
(declare-c load-font-from-image [image Image key Color first-char i32] Font "LoadFontFromImage")
-(declare-c load-font-from-memory [file-type string file-data (Ptr const u8) data-size i32 font-size i32 codepoints (Ptr i32) codepoint-count i32] Font "LoadFontFromMemory")
+(declare-c load-font-from-memory [file-type str file-data (Ptr const u8) data-size i32 font-size i32 codepoints (Ptr i32) codepoint-count i32] Font "LoadFontFromMemory")
(declare-c load-font-data [file-data (Ptr const u8) data-size i32 font-size i32 codepoints (Ptr i32) codepoint-count i32 type i32] (Ptr GlyphInfo) "LoadFontData")
(declare-c gen-image-font-atlas [glyphs (Ptr const GlyphInfo) glyph-recs (Ptr (Ptr Rectangle)) glyph-count i32 font-size i32 padding i32 pack-method i32] Image "GenImageFontAtlas")
(declare-c unload-font-data [glyphs (Ptr GlyphInfo) glyph-count i32] "UnloadFontData")
-(declare-c export-font-as-code [font Font file-name string] bool "ExportFontAsCode")
-(declare-c draw-text-pro [font Font text string position Vector2 origin Vector2 rotation f32 font-size f32 spacing f32 tint Color] "DrawTextPro")
+(declare-c export-font-as-code [font Font file-name str] bool "ExportFontAsCode")
+(declare-c draw-text-pro [font Font text str position Vector2 origin Vector2 rotation f32 font-size f32 spacing f32 tint Color] "DrawTextPro")
(declare-c draw-text-codepoints [font Font codepoints (Ptr const i32) codepoint-count i32 position Vector2 font-size f32 spacing f32 tint Color] "DrawTextCodepoints")
(declare-c set-text-line-spacing [spacing i32] "SetTextLineSpacing")
-(declare-c load-codepoints [text string count (Ptr i32)] (Ptr i32) "LoadCodepoints")
+(declare-c load-codepoints [text str count (Ptr i32)] (Ptr i32) "LoadCodepoints")
(declare-c unload-codepoints [codepoints (Ptr i32)] "UnloadCodepoints")
-(declare-c get-codepoint-count [text string] i32 "GetCodepointCount")
-(declare-c get-codepoint [text string codepoint-size (Ptr i32)] i32 "GetCodepoint")
-(declare-c get-codepoint-next [text string codepoint-size (Ptr i32)] i32 "GetCodepointNext")
-(declare-c codepoint-to-utf8 [codepoint i32 utf-8size (Ptr i32)] string "CodepointToUTF8")
-(declare-c text-is-equal [text-1 string text-2 string] bool "TextIsEqual")
-(declare-c text-length [text string] u32 "TextLength")
-(declare-c text-subtext [text string position i32 length i32] string "TextSubtext")
-(declare-c text-join [text-list (Ptr const (Ptr i8)) count i32 delimiter string] string "TextJoin")
-(declare-c text-split [text string delimiter i8 count (Ptr i32)] (Ptr (Ptr i8)) "TextSplit")
-(declare-c text-find-index [text string find string] i32 "TextFindIndex")
-(declare-c text-to-upper [text string] string "TextToUpper")
-(declare-c text-to-lower [text string] string "TextToLower")
-(declare-c text-to-pascal [text string] string "TextToPascal")
-(declare-c text-to-snake [text string] string "TextToSnake")
-(declare-c text-to-camel [text string] string "TextToCamel")
-(declare-c text-to-integer [text string] i32 "TextToInteger")
-(declare-c text-to-float [text string] f32 "TextToFloat")
+(declare-c get-codepoint-count [text str] i32 "GetCodepointCount")
+(declare-c get-codepoint [text str codepoint-size (Ptr i32)] i32 "GetCodepoint")
+(declare-c get-codepoint-next [text str codepoint-size (Ptr i32)] i32 "GetCodepointNext")
+(declare-c codepoint-to-utf8 [codepoint i32 utf-8size (Ptr i32)] str "CodepointToUTF8")
+(declare-c text-is-equal [text-1 str text-2 str] bool "TextIsEqual")
+(declare-c text-length [text str] u32 "TextLength")
+(declare-c text-subtext [text str position i32 length i32] str "TextSubtext")
+(declare-c text-join [text-list (Ptr const (Ptr i8)) count i32 delimiter str] str "TextJoin")
+(declare-c text-split [text str delimiter i8 count (Ptr i32)] (Ptr (Ptr i8)) "TextSplit")
+(declare-c text-find-index [text str find str] i32 "TextFindIndex")
+(declare-c text-to-upper [text str] str "TextToUpper")
+(declare-c text-to-lower [text str] str "TextToLower")
+(declare-c text-to-pascal [text str] str "TextToPascal")
+(declare-c text-to-snake [text str] str "TextToSnake")
+(declare-c text-to-camel [text str] str "TextToCamel")
+(declare-c text-to-integer [text str] i32 "TextToInteger")
+(declare-c text-to-float [text str] f32 "TextToFloat")
(declare-c draw-line-3d [start-pos Vector3 end-pos Vector3 color Color] "DrawLine3D")
(declare-c draw-point-3d [position Vector3 color Color] "DrawPoint3D")
(declare-c draw-circle-3d [center Vector3 radius f32 rotation-axis Vector3 rotation-angle f32 color Color] "DrawCircle3D")
@@ -270,7 +270,7 @@
(declare-c draw-capsule [start-pos Vector3 end-pos Vector3 radius f32 slices i32 rings i32 color Color] "DrawCapsule")
(declare-c draw-capsule-wires [start-pos Vector3 end-pos Vector3 radius f32 slices i32 rings i32 color Color] "DrawCapsuleWires")
(declare-c draw-plane [center-pos Vector3 size Vector2 color Color] "DrawPlane")
-(declare-c load-model [file-name string] Model "LoadModel")
+(declare-c load-model [file-name str] Model "LoadModel")
(declare-c load-model-from-mesh [mesh Mesh] Model "LoadModelFromMesh")
(declare-c model-valid? [model Model] bool "IsModelValid")
(declare-c unload-model [model Model] "UnloadModel")
@@ -290,8 +290,8 @@
(declare-c unload-mesh [mesh Mesh] "UnloadMesh")
(declare-c get-mesh-bounding-box [mesh Mesh] BoundingBox "GetMeshBoundingBox")
(declare-c gen-mesh-tangents [mesh (Ptr Mesh)] "GenMeshTangents")
-(declare-c export-mesh [mesh Mesh file-name string] bool "ExportMesh")
-(declare-c export-mesh-as-code [mesh Mesh file-name string] bool "ExportMeshAsCode")
+(declare-c export-mesh [mesh Mesh file-name str] bool "ExportMesh")
+(declare-c export-mesh-as-code [mesh Mesh file-name str] bool "ExportMeshAsCode")
(declare-c gen-mesh-poly [sides i32 radius f32] Mesh "GenMeshPoly")
(declare-c gen-mesh-plane [width f32 length f32 res-x i32 res-z i32] Mesh "GenMeshPlane")
(declare-c gen-mesh-cube [width f32 height f32 length f32] Mesh "GenMeshCube")
@@ -312,10 +312,10 @@
(declare-c get-ray-collision-mesh [ray Ray mesh Mesh transform Matrix] RayCollision "GetRayCollisionMesh")
(declare-c get-ray-collision-triangle [ray Ray p-1 Vector3 p-2 Vector3 p-3 Vector3] RayCollision "GetRayCollisionTriangle")
(declare-c get-ray-collision-quad [ray Ray p-1 Vector3 p-2 Vector3 p-3 Vector3 p-4 Vector3] RayCollision "GetRayCollisionQuad")
-(declare-c load-wave-from-memory [file-type string file-data (Ptr const u8) data-size i32] Wave "LoadWaveFromMemory")
+(declare-c load-wave-from-memory [file-type str file-data (Ptr const u8) data-size i32] Wave "LoadWaveFromMemory")
(declare-c update-sound [sound Sound data (Ptr const u8) sample-count i32] "UpdateSound")
-(declare-c export-wave-as-code [wave Wave file-name string] bool "ExportWaveAsCode")
-(declare-c load-music-stream-from-memory [file-type string data (Ptr const u8) data-size i32] Music "LoadMusicStreamFromMemory")
+(declare-c export-wave-as-code [wave Wave file-name str] bool "ExportWaveAsCode")
+(declare-c load-music-stream-from-memory [file-type str data (Ptr const u8) data-size i32] Music "LoadMusicStreamFromMemory")
(declare-c load-audio-stream [sample-rate u32 sample-size u32 channels u32] AudioStream "LoadAudioStream")
(declare-c audio-stream-valid? [stream AudioStream] bool "IsAudioStreamValid")
(declare-c unload-audio-stream [stream AudioStream] "UnloadAudioStream")
diff --git a/vendor/raylib/raylib.flan b/vendor/raylib/raylib.flan
index 5a085a9f..8b6cd16b 100644
--- a/vendor/raylib/raylib.flan
+++ b/vendor/raylib/raylib.flan
@@ -113,7 +113,7 @@
;; ── Window ──────────────────────────────────────────────────────────
-(declare-c init-window [width i32 height i32 title string] "InitWindow")
+(declare-c init-window [width i32 height i32 title str] "InitWindow")
(declare-c close-window [] "CloseWindow")
(declare-c window-should-close? [] bool "WindowShouldClose")
@@ -613,7 +613,7 @@
;; only in the log; raylib 5.5 spells it IsTextureValid, and IsTextureReady,
;; which older code calls, does not exist in this version.
-(declare-c load-texture [path string] Texture2D "LoadTexture")
+(declare-c load-texture [path str] Texture2D "LoadTexture")
(declare-c texture-valid? [texture Texture2D] bool "IsTextureValid")
@@ -748,7 +748,7 @@
[image (Ptr Image) new-format PixelFormat]
"ImageFormat")
-(declare-c load-image [path string] Image "LoadImage")
+(declare-c load-image [path str] Image "LoadImage")
;; raylib 5.5 spells this IsImageValid. IsImageReady, which older code calls,
;; does not exist here — the same rename that took IsTextureReady.
@@ -770,7 +770,7 @@
;; which integer type a C count parameter is. The Flan wrapper below takes the
;; slice apart, which is where that idiom lives everywhere else in this file.
(declare-c load-image-from-memory-raw
- [file-type string file-data (Ptr const u8) data-size i32] Image
+ [file-type str file-data (Ptr const u8) data-size i32] Image
"LoadImageFromMemory")
;; Empty is answered here rather than passed on, exactly as in
@@ -780,7 +780,7 @@
;; false for it either way, so a caller that checks sees the same thing.
(defonce no-image Image)
-(defn load-image-from-memory [file-type string data [const u8]] Image
+(defn load-image-from-memory [file-type str data [const u8]] Image
(if (= (length data) 0)
no-image
(load-image-from-memory-raw file-type (addr (at data 0)) (length data))))
@@ -792,7 +792,7 @@
;; The format is taken from the path's extension, so ".png" writes a PNG.
;; False means it could not be written.
-(declare-c export-image [image Image path string] bool "ExportImage")
+(declare-c export-image [image Image path str] bool "ExportImage")
(declare-c gen-image-color
[width i32 height i32 color Color] Image
@@ -1054,10 +1054,10 @@
;; headless test turned out to exist after all.
(declare-c draw-text
- [text string x i32 y i32 font-size i32 color Color]
+ [text str x i32 y i32 font-size i32 color Color]
"DrawText")
-(declare-c measure-text [text string font-size i32] i32 "MeasureText")
+(declare-c measure-text [text str font-size i32] i32 "MeasureText")
;; ── Timing and window state ─────────────────────────────────────────
;;
@@ -1292,7 +1292,7 @@
(defstruct Wave [frame-count u32 sample-rate u32 sample-size u32
channels u32 data (Ptr u8)])
-(declare-c load-wave [path string] Wave "LoadWave")
+(declare-c load-wave [path str] Wave "LoadWave")
;; raylib 5.5 spells this IsWaveValid; IsWaveReady is gone, as everywhere else.
(declare-c wave-valid? [wave Wave] bool "IsWaveValid")
@@ -1304,7 +1304,7 @@
;; sample-rate, sample-size and channels, and the payload length carries
;; frame-count, so a permuted defstruct writes a file that reads back
;; differently — the same argument the PNG round trip makes for Image.
-(declare-c export-wave [wave Wave path string] bool "ExportWave")
+(declare-c export-wave [wave Wave path str] bool "ExportWave")
;; Allocates a copy of the buffer; the copy is unloaded on its own.
(declare-c wave-copy [wave Wave] Wave "WaveCopy")
@@ -1341,7 +1341,7 @@
(defstruct Sound [stream AudioStream frame-count u32])
-(declare-c load-sound [path string] Sound "LoadSound")
+(declare-c load-sound [path str] Sound "LoadSound")
;; Note what this does to the frame count: the mixer resamples to the device's
;; own rate, so a sound made from an 8 kHz wave on a 48 kHz device reports six
@@ -1378,7 +1378,7 @@
(defstruct Music [stream AudioStream frame-count u32 looping bool
ctx-type i32 ctx-data (Ptr u8)])
-(declare-c load-music-stream [path string] Music "LoadMusicStream")
+(declare-c load-music-stream [path str] Music "LoadMusicStream")
(declare-c music-valid? [music Music] bool "IsMusicValid")
(declare-c unload-music-stream [music Music] "UnloadMusicStream")
@@ -1458,7 +1458,7 @@
;; measure-text answer 0 headless.
(declare-c get-font-default [] Font "GetFontDefault")
-(declare-c load-font [path string] Font "LoadFont")
+(declare-c load-font [path str] Font "LoadFont")
;; The codepoint set is a C array plus an int count, so — like
;; collision-point-poly? — the declaration says (Ptr i32) and the Flan wrapper
@@ -1474,10 +1474,10 @@
(defonce default-codepoints (Ptr i32))
(declare-c load-font-ex-raw
- [path string font-size i32 codepoints (Ptr i32) count i32] Font
+ [path str font-size i32 codepoints (Ptr i32) count i32] Font
"LoadFontEx")
-(defn load-font-ex [path string font-size i32 codepoints [i32]] Font
+(defn load-font-ex [path str font-size i32 codepoints [i32]] Font
(if (= (length codepoints) 0)
(load-font-ex-raw path font-size default-codepoints 0)
(load-font-ex-raw path font-size (addr (at codepoints 0)) (length codepoints))))
@@ -1492,14 +1492,14 @@
;; `spacing` is extra pixels between glyphs, added per gap and not per glyph,
;; so a one-character string is unaffected by it. raylib's own DrawTextEx adds
;; it the same way measure-text-ex counts it, which is why the two agree.
-(declare-c draw-text-ex [font Font text string position Vector2
+(declare-c draw-text-ex [font Font text str position Vector2
font-size f32 spacing f32 tint Color] "DrawTextEx")
;; Pure arithmetic over the font — no GL, no window — and therefore the one
;; thing in this section the acceptance table can assert. See the note above:
;; it refuses to measure anything at all when the font's texture id is 0.
(declare-c measure-text-ex
- [font Font text string font-size f32 spacing f32] Vector2
+ [font Font text str font-size f32 spacing f32] Vector2
"MeasureTextEx")
;; `recs` and `glyphs` are the two places in this whole package where a C
@@ -1628,10 +1628,10 @@
(declare-c load-dropped-files-raw [] FilePathList "LoadDroppedFiles")
(declare-c unload-dropped-files-raw [files FilePathList] "UnloadDroppedFiles")
-(declare-c load-directory-files-raw [dir-path string] FilePathList
+(declare-c load-directory-files-raw [dir-path str] FilePathList
"LoadDirectoryFiles")
(declare-c load-directory-files-ex-raw
- [base-path string filter string scan-subdirs bool] FilePathList
+ [base-path str filter str scan-subdirs bool] FilePathList
"LoadDirectoryFilesEx")
(declare-c unload-directory-files-raw [files FilePathList]
"UnloadDirectoryFiles")
@@ -1640,17 +1640,17 @@
;; The NUL is the only thing that says where a C string ends, so the walk
;; stops there and nothing past it is read. `char` is i8 in the header, and
;; each byte is converted as it is copied.
-(defn- c-string-copy [p (Ptr i8)] string
+(defn- c-string-copy [p (Ptr i8)] str
(let [s (slice-from p 2147483647)
out (vec-new u8)
i 0]
(while (!= (at s i) 0)
(push out (u8 (at s i)))
(set i (+ i 1)))
- (string (slice out))))
+ (str (slice out))))
-(defn- file-path-list-copy [files FilePathList] (Vec string)
- (let [out (vec-new string)
+(defn- file-path-list-copy [files FilePathList] (Vec str)
+ (let [out (vec-new str)
n (i32 (.count files))
paths (slice-from (.paths files) n)]
(dotimes [i n]
@@ -1659,14 +1659,14 @@
;; The paths dropped on the window since the last call; empty when
;; file-dropped? is false.
-(defn dropped-files [] (Vec string)
+(defn dropped-files [] (Vec str)
(let [files (load-dropped-files-raw)
out (file-path-list-copy files)]
(unload-dropped-files-raw files)
out))
;; The entries of one directory, files and subdirectories both.
-(defn directory-files [dir-path string] (Vec string)
+(defn directory-files [dir-path str] (Vec str)
(let [files (load-directory-files-raw dir-path)
out (file-path-list-copy files)]
(unload-directory-files-raw files)
@@ -1674,8 +1674,8 @@
;; `filter` is raylib's: extensions such as ".png;.jpg", or "DIR" for
;; directories only. `scan-subdirs` walks the tree.
-(defn directory-files-ex [base-path string filter string scan-subdirs bool]
- (Vec string)
+(defn directory-files-ex [base-path str filter str scan-subdirs bool]
+ (Vec str)
(let [files (load-directory-files-ex-raw base-path filter scan-subdirs)
out (file-path-list-copy files)]
(unload-directory-files-raw files)
diff --git a/web/examples/control.flan b/web/examples/control.flan
index 5f151c44..6b2205b8 100644
--- a/web/examples/control.flan
+++ b/web/examples/control.flan
@@ -1,6 +1,6 @@
(defconst nums [5 i32] [1 3 8 9 10])
-(defn classify [n i32] string
+(defn classify [n i32] str
(cond
(< n 0) "negative"
(= n 0) "zero"
diff --git a/web/examples/enums.flan b/web/examples/enums.flan
index 67432515..68df8084 100644
--- a/web/examples/enums.flan
+++ b/web/examples/enums.flan
@@ -1,7 +1,7 @@
(defenum Key
[space 32 escape 256 left 263 right 262])
-(defn key-name [k Key] string
+(defn key-name [k Key] str
(cond
(= k :space) "space"
(= k :escape) "escape"
diff --git a/web/examples/places.flan b/web/examples/places.flan
index 69efa3d8..fd728bd8 100644
--- a/web/examples/places.flan
+++ b/web/examples/places.flan
@@ -1,4 +1,4 @@
-(defstruct Enemy [hp i32 name string])
+(defstruct Enemy [hp i32 name str])
(defonce spawned i32)
(defconst room-size 4)
diff --git a/web/examples/printing.flan b/web/examples/printing.flan
index 6a8542b6..4c9a39e0 100644
--- a/web/examples/printing.flan
+++ b/web/examples/printing.flan
@@ -1,5 +1,5 @@
(defenum Key [space 32 left 263])
-(defstruct Enemy [hp i32 name string key Key])
+(defstruct Enemy [hp i32 name str key Key])
(defn look-up [k Key] (Option i32)
(if (= k :space) (Some 32) None))
diff --git a/web/index.html b/web/index.html
index 817f687b..e5395bb2 100644
--- a/web/index.html
+++ b/web/index.html
@@ -361,7 +361,7 @@ the editor.
(defn main [] ()
(println "hello from flan"))
-The entry point is (defn main [args [string]] i32). The parameter is
+
The entry point is (defn main [args [str]] i32). The parameter is
optional — omitting args means the program ignores argv — and the return
type is not: () is unit, and a main that returns it exits 0.
@@ -398,7 +398,7 @@ heap is involved.
Places — the forms set accepts — are a fixed list, not an extensible
setf:
-(defstruct Enemy [hp i32 name string])
+(defstruct Enemy [hp i32 name str])
(defonce spawned i32)
(defconst room-size 4)
@@ -517,7 +517,7 @@ notation reads as exactly one data item.
i8 … i64, u8 … u64 | machine integers, wrapping arithmetic | the obvious one |
f32, f64 | floats | float, double |
bool | | i1 |
-string | a byte slice with no NUL | ptr + len |
+str | a byte slice with no NUL | ptr + len |
[T] | slice, non-owning | ptr + len |
[const T] | read-only slice: a [T] converts to one, never the reverse | ptr + len |
[n T] | fixed array, a value | n inline items |
@@ -717,7 +717,7 @@ slots, and a slot may be followed by a type, the way a parameter is:
[x y] is two slots that hold any value, and [pause bool]
is one that holds only a bool. The type is checked whenever a value is stored,
and a slot may be bool, an integer type, f32,
-f64, string, a class, or (Option T) of one of
+f64, str, a class, or (Option T) of one of
those, which also admits nil. The constructor is the class's own name
and is positional, and class-of answers the tag, or nil
for anything that is not an instance. type-of answers any value's
@@ -858,7 +858,7 @@ typo is an error there rather than a wrong number later.
(defenum Key
[space 32 escape 256 left 263 right 262])
-(defn key-name [k Key] string
+(defn key-name [k Key] str
(cond
(= k :space) "space"
(= k :escape) "escape"
@@ -1010,7 +1010,7 @@ C caller knows nothing about one.
(defconst nums [5 i32] [1 3 8 9 10])
-(defn classify [n i32] string
+(defn classify [n i32] str
(cond
(< n 0) "negative"
(= n 0) "zero"
@@ -1351,7 +1351,7 @@ argument whose printing is decided at run time, because it is the one v
that carries a tag to decide it with.
(defenum Key [space 32 left 263])
-(defstruct Enemy [hp i32 name string key Key])
+(defstruct Enemy [hp i32 name str key Key])
(defn look-up [k Key] (Option i32)
(if (= k :space) (Some 32) None))
@@ -1372,7 +1372,7 @@ none
no newline: true
The walk covers every integer and float type, bool, (),
-string, [u8], dyn, enums, Ptr,
+str, [u8], dyn, enums, Ptr,
Option, structs, unions, fixed arrays and slices. An owning container has no printer for its
contents and comes back as a marker instead — <vec>,
<pool>, <allocator> — while a Handle
@@ -1722,7 +1722,7 @@ that version silently rolls back the frames that succeeded.
A restart's parameters are checked at run time, count then
spelling, because a restart is found by name on a dynamic stack and neither end can see
the other. Lookup is by the name alone and the signature is checked after it, so an
- inner (use-value [s string] …) shadows an outer
+ inner (use-value [s str] …) shadows an outer
(use-value [v i32] …) and (invoke-restart 'use-value 21)
stops the program even though the outer clause would have taken it. The clause's
parameters are slots of the function that wrote it, and the invoker fills a buffer that
@@ -2006,11 +2006,11 @@ listener thread, a single-producer ring, and three calls. This is the whole of
agent.flan — no aggregate crosses the boundary, so a plain
declare does it and there is no shim.
-(declare start-raw [path string] i32 "flan_agent_start")
+(declare start-raw [path str] i32 "flan_agent_start")
(declare poll-raw [] i32 "flan_agent_poll")
(declare wait-raw [ms i32] i32 "flan_agent_wait")
-(defn start [path string] i32 (start-raw path))
+(defn start [path str] i32 (start-raw path))
(defn poll [] i32 (poll-raw))
(defn wait [ms i32] i32 (wait-raw ms))
@@ -2532,7 +2532,7 @@ disagree with the first.
"restart-case invoke-restart fn quote defmacro gensym " +
"defclass defgeneric defmulti defmethod").split(" "));
// Capitalised names are types; these are the ones that are not capitalised.
- var TYPES = new Set(("i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 bool string dyn").split(" "));
+ var TYPES = new Set(("i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 bool str dyn").split(" "));
var TOKEN = /(;[^\n]*)|("(?:\\.|[^"\\])*")|(\\[A-Za-z0-9]+)|(:[A-Za-z][\w?!*<>=+-]*)|(\b0[xX][0-9a-fA-F]+\b|\b\d[\d.]*\b)|([A-Za-z][\w*?!<>=./+-]*)/g;
function esc(s) {
return s.replace(/&/g, "&").replace(//g, ">");
From b92e91bcaac45b96f41219e92a97a1bf6b8e3b7b Mon Sep 17 00:00:00 2001
From: Joseph Ferano
Date: Sat, 26 Sep 2026 05:27:23 +0700
Subject: [PATCH 2/3] A parameter, local or field may be named str or any other
type name when a type follows it, and a type-named parameter with no type
after it is refused with both fixes.
---
lib/check.ml | 41 ++++++++++++++++++++++++++++---------
test/syntax/algorithms.flan | 18 ++++++++--------
test/syntax/algorithms.fln | 18 ++++++++--------
test/test_flan.ml | 18 ++++++++++++----
4 files changed, 63 insertions(+), 32 deletions(-)
diff --git a/lib/check.ml b/lib/check.ml
index e82242d1..db1fd732 100644
--- a/lib/check.ml
+++ b/lib/check.ml
@@ -2077,12 +2077,10 @@ and array_len env loc = function
another name that is not a type, or by nothing, takes one and is [dyn]. That
is the whole rule, and it reads the way the vector reads.
- A name that *is* a type name is refused rather than paired. [(defn f [i64 x]
- ...)] has no good reading: taken as written it is a parameter called [i64],
- which shadows nothing but confuses everything, and the likelier intent is a
- pair written backwards. Refusing here costs a rename in the one program that
- meant it and closes the one place where this rule could still hand somebody
- a signature they did not write. *)
+ A name that *is* a type name pairs only when a type follows it: [[str str]]
+ has one reading. [(defn f [i64 x] ...)] has two — a dyn parameter called
+ [i64], or a pair written backwards — so it is refused rather than handed
+ back as a signature nobody wrote. *)
let is_type_name env n =
Types.ikind_of_name n <> None
|| Types.fkind_of_name n <> None
@@ -2255,11 +2253,20 @@ let pair_params ?(also = fun _ -> false) ?(declared = fun _ -> None)
Loc.failk "check/parameter-name-expected" t.Ast.tloc
"a parameter's name was expected here, and this is a type. Parameters \
are [name Type ...]"
- | Ast.Pname (n, loc) :: rest when is_type_name env n ->
- ignore rest;
+ (* A parameter may share a type's name — [str] is a common name for text —
+ when a type follows it: [[str str]] and [str: str] can only be a name
+ then a type. Without a type after it, [[i64 x]] is a pair written
+ backwards as likely as a dyn parameter called [i64], so that one is
+ refused with both fixes. *)
+ | Ast.Pname (n, loc) :: Ast.Ptype t :: rest when is_type_name env n ->
+ { Ast.fname = n; fty = t; floc = loc } :: go rest
+ | Ast.Pname (n, loc) :: Ast.Pname (t, tloc) :: rest
+ when is_type_name env n && is_type_name env t ->
+ { Ast.fname = n; fty = { Ast.t = Ast.Tname t; tloc }; floc = loc } :: go rest
+ | Ast.Pname (n, loc) :: _ when is_type_name env n ->
Loc.failk "check/parameter-named-type" loc
- "%s names a type, so it cannot also be this parameter's name. Write \
- [name %s], or rename the parameter" n n
+ "%s names a type, and no type follows this parameter called %s. Give \
+ it one, as [%s %s], or if the pair is backwards write [name %s]" n n n n n
(* [_] reads a type off a body, and a parameter has none to read. *)
| Ast.Pname (n, _) :: Ast.Pname ("_", tloc) :: _ ->
Loc.failk "check/infer-misplaced" tloc
@@ -10416,6 +10423,18 @@ and type_named ctx n =
|| Hashtbl.mem ctx.env.enums n
|| Hashtbl.mem ctx.env.aliases n
+(* A local or global that shares a type's name — [str] is a common name for
+ text — is the binding in (vec-new str), and then nothing names the type.
+ Said here so the refusal names the binding rather than a missing type. *)
+and shadowed_type_arg ctx loc what args =
+ match args with
+ | { Ast.e = Ast.Var n; _ } :: _
+ when type_named ctx n && (lookup ctx n <> None || global_value ctx n) ->
+ fail loc
+ "%s here is the value named %s and not the type, so nothing says what \
+ (%s) makes — rename that binding to write the type" n n what
+ | _ -> ()
+
(* The element type for [vec-new]: a leading bare symbol naming a type, a
leading type expression — [(vec-new [u8])], [(vec-new (Ptr Cell))], which
Parse has already read as one — or the expectation at the site. A bare
@@ -10440,6 +10459,7 @@ and vec_new_elem ctx ~want loc args =
(match want with
| Some (Types.Vec t) -> t, args
| _ ->
+ shadowed_type_arg ctx loc "vec-new" args;
fail loc
"nothing here says what (vec-new) is a Vec of — write the element \
type, as (vec-new i32)")
@@ -10530,6 +10550,7 @@ and map_new_types ctx ~want loc args =
(match want with
| Some (Types.Map (k, v)) -> k, v, args
| _ ->
+ shadowed_type_arg ctx loc "map-new" args;
fail loc
"nothing here says what (map-new) maps — write the key and value \
types, as (map-new str i32)")
diff --git a/test/syntax/algorithms.flan b/test/syntax/algorithms.flan
index a5e86892..a511f265 100644
--- a/test/syntax/algorithms.flan
+++ b/test/syntax/algorithms.flan
@@ -1,10 +1,10 @@
(import agent "vendor:agent")
-(defn find-match [text str pattern str] i32
- (dotimes [i (length text)]
+(defn find-match [str str pattern str] i32
+ (dotimes [i (length str)]
(let [matched true]
(dotimes [j (length pattern)]
- (when (!= (at text (+ i j)) (at pattern j))
+ (when (!= (at str (+ i j)) (at pattern j))
(set matched false)))
(when matched
(return i))))
@@ -41,11 +41,11 @@
(comment
(insertion-sort [\I \N \S \E \R \T \I \O \N \S \O \R \T])
(insertion-sort (slice [6 2 4 9 1 9 4 5] 0 8))
- (let [text (bytes "INSERTIONSORT")]
- (insertion-sort text)
- (println text))
- (let [text (bytes "SELECTIONSORT")]
- (selection-sort text)
- (println text))
+ (let [str (bytes "INSERTIONSORT")]
+ (insertion-sort str)
+ (println str))
+ (let [str (bytes "SELECTIONSORT")]
+ (selection-sort str)
+ (println str))
(find-match "aababba" "abba")
:-)
diff --git a/test/syntax/algorithms.fln b/test/syntax/algorithms.fln
index 037f14fa..ac29948e 100644
--- a/test/syntax/algorithms.fln
+++ b/test/syntax/algorithms.fln
@@ -3,11 +3,11 @@
import agent "vendor:agent"
-fn find-match(text: str, pattern: str) -> i32
- for i in range(length(text))
+fn find-match(str: str, pattern: str) -> i32
+ for i in range(length(str))
let matched = true
for j in range(length(pattern))
- if text[i + j] != pattern[j]
+ if str[i + j] != pattern[j]
matched = false
if matched
return i
@@ -42,11 +42,11 @@ fn main() -> i32 = 0
comment():
insertion-sort([\I \N \S \E \R \T \I \O \N \S \O \R \T])
insertion-sort(slice([6 2 4 9 1 9 4 5], 0, 8))
- let text = bytes("INSERTIONSORT")
- insertion-sort(text)
- println(text)
- let text = bytes("SELECTIONSORT")
- selection-sort(text)
- println(text)
+ let str = bytes("INSERTIONSORT")
+ insertion-sort(str)
+ println(str)
+ let str = bytes("SELECTIONSORT")
+ selection-sort(str)
+ println(str)
find-match("aababba", "abba")
:-
diff --git a/test/test_flan.ml b/test/test_flan.ml
index cadce45c..1f3d72cb 100644
--- a/test/test_flan.ml
+++ b/test/test_flan.ml
@@ -1479,11 +1479,21 @@ let () =
(* ── dyn, and what it does not do yet ──────────────────────────── *)
- (* The pairing rule's own refusal. A name that is also a type's has no good
- reading — taken as written it is a parameter called [i64] — and the
- likelier intent is a pair the wrong way round, which the message names. *)
+ (* The pairing rule's own refusal. A type-named parameter with no type after
+ it is a dyn parameter or a pair the wrong way round; the message names
+ both fixes. With a type after it there is one reading. *)
rejects_check "a parameter named after a type" "(defn f [i64 x] ())"
- ~needle:"cannot also be this parameter's name";
+ ~needle:"no type follows this parameter called i64";
+ rejects_check "a last parameter named after a type" "(defn f [a i32 str] ())"
+ ~needle:"Give it one, as [str str]";
+ accepts "a parameter named str with a type" "(defn f [str str] i32 (length str))";
+ accepts "a parameter named str of another type"
+ "(defn f [str [u8]] i32 (length str))";
+ accepts "a local named str" "(defn f [b [u8]] str (let [str (str b)] str))";
+ accepts "a field named str" "(defstruct P [str str]) (defn f [p P] str (.str p))";
+ rejects_check "a local named str is not the type at vec-new"
+ "(defn f [] i32 (let [str 1 v (vec-new str)] 0))"
+ ~needle:"str here is the value named str and not the type";
(* M2 item 3 lifted the container-into-dyn refusal: a [(Vec T)], a slice or
a fixed array with an i64/f64/bool element now crosses as a VIEW rather
From 49e6ac6512aecc3c78bcdffd0ae65737a3602bdd Mon Sep 17 00:00:00 2001
From: Joseph Ferano
Date: Sat, 26 Sep 2026 05:39:56 +0700
Subject: [PATCH 3/3] Comments and the README example spell the text type str.
---
README.md | 2 +-
lib/prelude.ml | 2 +-
runtime/flan_dev.c | 4 ++--
runtime/flan_dyn.c | 2 +-
runtime/flan_rt.c | 10 +++++-----
vendor/edn/provide.flan | 2 +-
vendor/edn/read.flan | 2 +-
vendor/json/json.flan | 4 ++--
vendor/json/provide.flan | 2 +-
vendor/raylib/raylib.flan | 2 +-
10 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/README.md b/README.md
index 873ef788..1131110d 100644
--- a/README.md
+++ b/README.md
@@ -182,7 +182,7 @@ problems:
$ flan import-c test/headers/sample.h
(declare-c set-seed [seed u32] "set_seed")
(declare-c add-ints [a i32 b i32] i32 "add_ints")
-(declare-c name-length [text string] i32 "name_length")
+(declare-c name-length [text str] i32 "name_length")
...
;; 9 imported, 12 refused, of 22 functions in test/headers/sample.h
;; refused owned-text: owned_text returns char *, which the caller owns and
diff --git a/lib/prelude.ml b/lib/prelude.ml
index 16122e3a..b4d97d75 100644
--- a/lib/prelude.ml
+++ b/lib/prelude.ml
@@ -1951,7 +1951,7 @@ let source = {flan|
;; stopped being true when `Vec` landed, and most of the list has moved up into
;; the building section above: join, concat, split, to-lower, to-upper, repeat
;; and replace are all written now, and `string-from-bytes` turned out to be
-;; the `string` builtin all along — (string (slice v)) is the round trip,
+;; the `str` builtin all along — (str (slice v)) is the round trip,
;; and the layouts being identical is exactly why it is free.
;;
;; What is left is refused for four *different* reasons, which is why they are
diff --git a/runtime/flan_dev.c b/runtime/flan_dev.c
index 45512a4e..3825e777 100644
--- a/runtime/flan_dev.c
+++ b/runtime/flan_dev.c
@@ -778,7 +778,7 @@ void flan_dev_watch_end(void) {
/* These are the whole feature for a scalar, and they are what a program can
* use today:
*
- * (declare-c watch-i64 [name string x i64] i32 "flan_dev_watch_i64")
+ * (declare-c watch-i64 [name str x i64] i32 "flan_dev_watch_i64")
* ...
* (watch-i64 "ticks" ticks)
*
@@ -901,7 +901,7 @@ void flan_dev_watch_reset(void) {
/* Reachable from a program by [declare-c], the same as the four scalars and
* for the same reason — no arm in the checker, nothing the compiler learns:
*
- * (declare-c watch-num-i64 [name string x i64] i32 "flan_dev_watch_num_i64")
+ * (declare-c watch-num-i64 [name str x i64] i32 "flan_dev_watch_num_i64")
* ...
* (watch-num-i64 "cell" (at grid i))
*
diff --git a/runtime/flan_dyn.c b/runtime/flan_dyn.c
index 534f749c..ace75dbc 100644
--- a/runtime/flan_dyn.c
+++ b/runtime/flan_dyn.c
@@ -2682,7 +2682,7 @@ flan_dyn flan_dyn_rem(flan_dyn a, flan_dyn b, const uint8_t *loc,
*
* Numbers against numbers, text against text, and nothing else. Text orders
* bytewise, which is [memcmp] with the shorter one first on a tie — the same
- * order a sort of a [(Vec string)] would want and the only order that needs no
+ * order a sort of a [(Vec str)] would want and the only order that needs no
* locale, no collation table and no argument.
*
* A number against a text traps rather than answering. The temptation is to
diff --git a/runtime/flan_rt.c b/runtime/flan_rt.c
index 1036c878..b841fec7 100644
--- a/runtime/flan_rt.c
+++ b/runtime/flan_rt.c
@@ -71,7 +71,7 @@ void flan_handler_pop(flan_handler *h) {
*
* A handler that matched through a parent link is not handed the condition,
* whose layout is its own type's, but a view laid out as the prelude's
- * (defstruct Error [name string message string]) — the parent's type is
+ * (defstruct Error [name str message str]) — the parent's type is
* Error-shaped, which the checker requires. The view's message is the
* condition with its values: [message] for the runtime's own conditions,
* which format their sentence before signalling; what [render] prints for a
@@ -388,7 +388,7 @@ typedef struct { const uint8_t *ptr; int64_t len; } flan_slice;
static int rt_argc;
static char **rt_argv;
-static flan_slice *rt_args; /* argv as [string], built once, never freed */
+static flan_slice *rt_args; /* argv as [str], built once, never freed */
void flan_rt_init(int32_t argc, char **argv) {
rt_argc = (int)argc;
@@ -1487,7 +1487,7 @@ void flan_arith_error(const uint8_t *loc, int64_t loclen, int32_t op,
* is the price of never pinning a module for it.
*
* The condition must agree field for field with the prelude's
- * (defstruct StaleCall [callee string compiled string current string]),
+ * (defstruct StaleCall [callee str compiled str current str]),
* the same hand-kept agreement flan_bounds_cond has with BoundsError. */
typedef struct { flan_slice callee, compiled, current; } flan_stale_cond;
@@ -1551,7 +1551,7 @@ void flan_stale_call(const char *site, const char *callee, const char *want,
* `type` is copied and never freed, for flan_stale_call's reason: the text
* lives in the image of the module that compiled the call, which may be a
* thunk that is unloaded once it returns. Must agree with the prelude's
- * (defstruct NullCall :parent Error [type string]). */
+ * (defstruct NullCall :parent Error [type str]). */
typedef struct { flan_slice type; } flan_nullcall_cond;
@@ -3529,7 +3529,7 @@ int8_t flan_map_init(flan_map *m, flan_allocator *a, int64_t ksize,
m->alloc = a;
m->epoch = (int64_t)a->epoch;
/* No block until something is put in it: an empty map that is never written
- * costs nothing, which is what makes a (defonce m (Map string i32)) free. */
+ * costs nothing, which is what makes a (defonce m (Map str i32)) free. */
return 1;
}
diff --git a/vendor/edn/provide.flan b/vendor/edn/provide.flan
index b558a3d4..7b99110e 100644
--- a/vendor/edn/provide.flan
+++ b/vendor/edn/provide.flan
@@ -66,7 +66,7 @@
(defn- joined3 [a str b str c str] str
(joined a (joined b c)))
-;; Copied out, and not `(string (i64->bytes n))`. The prelude's note over
+;; Copied out, and not `(str (i64->bytes n))`. The prelude's note over
;; append-i64 is the reason: i64->bytes renders into one shared static buffer
;; in the runtime, so two of its results cannot be held at once — and `where`
;; below holds a line and a column at the same time, which read as the same
diff --git a/vendor/edn/read.flan b/vendor/edn/read.flan
index 78dc573b..547d3ad1 100644
--- a/vendor/edn/read.flan
+++ b/vendor/edn/read.flan
@@ -118,7 +118,7 @@
;; A map's key is a whole value, read by the same recursion as anything
;; else — :a and "a" are two keys, [0 0] can key a map, and the old
- ;; (Map string Value) narrowing that collapsed them is gone with the type
+ ;; (Map str Value) narrowing that collapsed them is gone with the type
;; that forced it.
(= (.kind t) tok-map-open)
(let [m {}
diff --git a/vendor/json/json.flan b/vendor/json/json.flan
index c9dc5e43..efc5b5fb 100644
--- a/vendor/json/json.flan
+++ b/vendor/json/json.flan
@@ -140,7 +140,7 @@
;;;; the only place that still knows the offset of the offending backslash;
;;;; string-of works over a literal the cursor has already accepted and cannot
;;;; fail on its contents. That is also Odin's split — its scan_escape runs in
-;;;; get_token — and it is why string-of is an (Option string) on the token's
+;;;; get_token — and it is why string-of is an (Option str) on the token's
;;;; kind alone and not on its bytes.
;; ── Token kinds ─────────────────────────────────────────────────────
@@ -661,7 +661,7 @@
;; free-all and under the heap it is a block nobody has freed. There is no
;; third owner.
;;
-;; The builder is a (Vec u8) and the answer is (string (slice b)) taken ONCE
+;; The builder is a (Vec u8) and the answer is (str (slice b)) taken ONCE
;; at the end. That ordering is load-bearing rather than stylistic: a push
;; after the slice has been taken can grow the Vec into a new block, and in an
;; arena the old block is still mapped, so the already-taken string would go on
diff --git a/vendor/json/provide.flan b/vendor/json/provide.flan
index 9df3186f..1e48a5bb 100644
--- a/vendor/json/provide.flan
+++ b/vendor/json/provide.flan
@@ -51,7 +51,7 @@
(defn- joined3 [a str b str c str] str
(joined a (joined b c)))
-;; Copied out, and not `(string (i64->bytes n))`: the prelude's note over
+;; Copied out, and not `(str (i64->bytes n))`: the prelude's note over
;; append-i64 is the reason — i64->bytes renders into one shared static buffer
;; in the runtime, so two of its results cannot be held at once, and `where`
;; holds a line and a column at the same time.
diff --git a/vendor/raylib/raylib.flan b/vendor/raylib/raylib.flan
index 8b6cd16b..b1638d2b 100644
--- a/vendor/raylib/raylib.flan
+++ b/vendor/raylib/raylib.flan
@@ -1621,7 +1621,7 @@
;; FilePathList is an array of C strings raylib owns until the matching
;; Unload call. It crosses the way a returned string does: each path is copied
;; into the context allocator, raylib's list is released before the function
-;; returns, and the caller gets a (Vec string) with nothing of raylib's left
+;; returns, and the caller gets a (Vec str) with nothing of raylib's left
;; to unload. `free` on the Vec releases the Vec; the paths live until their
;; allocator's free-all, as (bytes s) does.
(defstruct FilePathList [capacity u32 count u32 paths (Ptr (Ptr i8))])