spec: vector primitives — bounds-checked ref/set!, vector-copy start/end slice
vector-ref and vector-set! now raise Eval_error on out-of-bounds index instead of an OCaml array exception. vector-copy accepts optional start and end parameters for slicing (R7RS §6.8). spec/primitives.sx doc updated to reflect slice params. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1227,11 +1227,19 @@ let () =
|
|||||||
| _ -> raise (Eval_error "vector-length: expected vector"));
|
| _ -> raise (Eval_error "vector-length: expected vector"));
|
||||||
register "vector-ref" (fun args ->
|
register "vector-ref" (fun args ->
|
||||||
match args with
|
match args with
|
||||||
| [Vector arr; Number n] -> arr.(int_of_float n)
|
| [Vector arr; Number n] ->
|
||||||
|
let i = int_of_float n in
|
||||||
|
if i < 0 || i >= Array.length arr then
|
||||||
|
raise (Eval_error (Printf.sprintf "vector-ref: index %d out of bounds (length %d)" i (Array.length arr)));
|
||||||
|
arr.(i)
|
||||||
| _ -> raise (Eval_error "vector-ref: expected (vector index)"));
|
| _ -> raise (Eval_error "vector-ref: expected (vector index)"));
|
||||||
register "vector-set!" (fun args ->
|
register "vector-set!" (fun args ->
|
||||||
match args with
|
match args with
|
||||||
| [Vector arr; Number n; v] -> arr.(int_of_float n) <- v; Nil
|
| [Vector arr; Number n; v] ->
|
||||||
|
let i = int_of_float n in
|
||||||
|
if i < 0 || i >= Array.length arr then
|
||||||
|
raise (Eval_error (Printf.sprintf "vector-set!: index %d out of bounds (length %d)" i (Array.length arr)));
|
||||||
|
arr.(i) <- v; Nil
|
||||||
| _ -> raise (Eval_error "vector-set!: expected (vector index value)"));
|
| _ -> raise (Eval_error "vector-set!: expected (vector index value)"));
|
||||||
register "vector->list" (fun args ->
|
register "vector->list" (fun args ->
|
||||||
match args with [Vector arr] -> List (Array.to_list arr)
|
match args with [Vector arr] -> List (Array.to_list arr)
|
||||||
@@ -1246,8 +1254,18 @@ let () =
|
|||||||
| [Vector arr; v] -> Array.fill arr 0 (Array.length arr) v; Nil
|
| [Vector arr; v] -> Array.fill arr 0 (Array.length arr) v; Nil
|
||||||
| _ -> raise (Eval_error "vector-fill!: expected (vector value)"));
|
| _ -> raise (Eval_error "vector-fill!: expected (vector value)"));
|
||||||
register "vector-copy" (fun args ->
|
register "vector-copy" (fun args ->
|
||||||
match args with [Vector arr] -> Vector (Array.copy arr)
|
match args with
|
||||||
| _ -> raise (Eval_error "vector-copy: expected vector"));
|
| [Vector arr] -> Vector (Array.copy arr)
|
||||||
|
| [Vector arr; Number s] ->
|
||||||
|
let start = int_of_float s in
|
||||||
|
let len = Array.length arr - start in
|
||||||
|
if len <= 0 then Vector [||] else Vector (Array.sub arr start len)
|
||||||
|
| [Vector arr; Number s; Number e] ->
|
||||||
|
let start = int_of_float s in
|
||||||
|
let stop = min (int_of_float e) (Array.length arr) in
|
||||||
|
let len = stop - start in
|
||||||
|
if len <= 0 then Vector [||] else Vector (Array.sub arr start len)
|
||||||
|
| _ -> raise (Eval_error "vector-copy: expected (vector) or (vector start) or (vector start end)"));
|
||||||
|
|
||||||
(* Capability-based sandboxing — gate IO operations *)
|
(* Capability-based sandboxing — gate IO operations *)
|
||||||
let cap_stack : string list ref = ref [] in
|
let cap_stack : string list ref = ref [] in
|
||||||
|
|||||||
@@ -50,8 +50,10 @@ Primitives to add:
|
|||||||
- `vector-copy` `v` `[start]` `[end]` → fresh copy of slice
|
- `vector-copy` `v` `[start]` `[end]` → fresh copy of slice
|
||||||
|
|
||||||
Steps:
|
Steps:
|
||||||
- [ ] OCaml: add `SxVector of value array` to `hosts/ocaml/sx_types.ml`; implement all
|
- [x] OCaml: add `SxVector of value array` to `hosts/ocaml/sx_types.ml`; implement all
|
||||||
primitives in `hosts/ocaml/sx_primitives.ml` (or equivalent); wire into evaluator.
|
primitives in `hosts/ocaml/sx_primitives.ml` (or equivalent); wire into evaluator.
|
||||||
|
Note: Vector type + most prims were already present; added bounds-checked vector-ref/set!
|
||||||
|
and optional start/end to vector-copy. 10/10 vector tests pass (r7rs suite).
|
||||||
- [ ] Spec: add vector entries to `spec/primitives.sx` with type signatures and descriptions.
|
- [ ] Spec: add vector entries to `spec/primitives.sx` with type signatures and descriptions.
|
||||||
- [ ] JS bootstrapper: implement vectors in `hosts/javascript/platform.js` (or equivalent);
|
- [ ] JS bootstrapper: implement vectors in `hosts/javascript/platform.js` (or equivalent);
|
||||||
ensure `sx-browser.js` rebuild picks them up.
|
ensure `sx-browser.js` rebuild picks them up.
|
||||||
@@ -194,4 +196,5 @@ Brief each language's loop agent (or do inline) after rebasing their branch onto
|
|||||||
|
|
||||||
_Newest first._
|
_Newest first._
|
||||||
|
|
||||||
|
- 2026-04-25: Phase 1 OCaml step done — bounds-checked vector-ref/set!, vector-copy now accepts optional start/end, spec/primitives.sx doc updated. 10/10 r7rs vector tests pass, 4747 total (394 pre-existing hs-upstream fails unchanged).
|
||||||
- 2026-04-25: Phase 0 complete — stopped CL/APL/Ruby/Tcl loops (all 4 idle at shell); confirmed E38 (tokenizer :end/:line) and E39 (WebWorker stub) both have implementation commits.
|
- 2026-04-25: Phase 0 complete — stopped CL/APL/Ruby/Tcl loops (all 4 idle at shell); confirmed E38 (tokenizer :end/:line) and E39 (WebWorker stub) both have implementation commits.
|
||||||
|
|||||||
@@ -227,9 +227,11 @@
|
|||||||
|
|
||||||
(define-primitive
|
(define-primitive
|
||||||
"vector-copy"
|
"vector-copy"
|
||||||
:params ((v :as vector))
|
:params ((v :as vector)
|
||||||
|
(start :as number :optional true)
|
||||||
|
(end :as number :optional true))
|
||||||
:returns "vector"
|
:returns "vector"
|
||||||
:doc "Independent shallow copy.")
|
:doc "Shallow copy of vector, optionally sliced from start (inclusive) to end (exclusive).")
|
||||||
|
|
||||||
(define-primitive
|
(define-primitive
|
||||||
"min"
|
"min"
|
||||||
|
|||||||
Reference in New Issue
Block a user