Skip to content

Commit 46e4138

Browse files
Merge branch 'main' into claude/step4-b-random-perf
Signed-off-by: Jonathan D.A. Jewell <6759885+hyperpolymath@users.noreply.github.com>
2 parents c0169be + a4dd22a commit 46e4138

5 files changed

Lines changed: 476 additions & 22 deletions

File tree

lib/codegen_deno.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,14 @@ let () =
513513
b "ensureDir" (fun a -> Printf.sprintf "__as_ensureDir(%s)" (arg 0 a));
514514
b "readDirNames" (fun a -> Printf.sprintf "__as_readDirNames(%s)" (arg 0 a));
515515
b "statSize" (fun a -> Printf.sprintf "Deno.statSync(%s).size" (arg 0 a));
516+
b "statIsFile" (fun a -> Printf.sprintf "Deno.statSync(%s).isFile" (arg 0 a));
517+
b "statIsDirectory" (fun a -> Printf.sprintf "Deno.statSync(%s).isDirectory" (arg 0 a));
518+
b "bytesLength" (fun a -> Printf.sprintf "(%s).length" (arg 0 a));
519+
b "bytesByteAt" (fun a -> Printf.sprintf "(%s)[%s]" (arg 0 a) (arg 1 a));
520+
b "bytesAsciiSlice" (fun a -> Printf.sprintf "String.fromCharCode(...(%s).slice(%s, %s))" (arg 0 a) (arg 1 a) (arg 2 a));
521+
(* `import.meta.url` — only legal at module top level, which the
522+
Deno-ESM backend's output already is. *)
523+
b "importMetaUrl" (fun _ -> "import.meta.url");
516524
b "pathJoin" (fun a -> Printf.sprintf "__as_pathJoin(%s, %s)" (arg 0 a) (arg 1 a));
517525
b "isNotFound" (fun a -> Printf.sprintf "__as_isNotFound(%s)" (arg 0 a));
518526
(* ---- JSON ---- *)
@@ -1258,6 +1266,13 @@ and gen_try_stmt ctx body catch finally =
12581266

12591267
and gen_stmt ctx (stmt : stmt) : string =
12601268
match stmt with
1269+
| StmtLet { sl_pat = PatWildcard _; sl_value; _ } ->
1270+
(* `let _ = X` evaluates X for side effects and drops the value.
1271+
Emitting `const _ = X;` produces a JS SyntaxError on the second
1272+
occurrence in the same scope ("Identifier '_' has already been
1273+
declared"). Drop the binding entirely; the bare expression
1274+
statement keeps the semantics. *)
1275+
gen_expr ctx sl_value ^ ";"
12611276
| StmtLet { sl_pat; sl_value; sl_mut; sl_quantity = _; sl_ty = _ } ->
12621277
let kw = if sl_mut then "let" else "const" in
12631278
let js = kw ^ " " ^ gen_pattern ctx sl_pat ^ " = "

stdlib/Deno.affine

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ pub extern fn readDirNames(path: String) -> [String];
6868
/// `Deno.statSync(path).size` in bytes.
6969
pub extern fn statSize(path: String) -> Int;
7070

71+
/// `Deno.statSync(path).isFile` — true if `path` is a regular file.
72+
/// Throws on a missing path (pair with `isNotFound` for the absent case).
73+
pub extern fn statIsFile(path: String) -> Bool;
74+
75+
/// `Deno.statSync(path).isDirectory` — true if `path` is a directory.
76+
/// Throws on a missing path (pair with `isNotFound` for the absent case).
77+
pub extern fn statIsDirectory(path: String) -> Bool;
78+
7179
/// Recursive walk under `root` — every file path beneath it, depth-first.
7280
/// Mirrors `std/fs/walk` for the common case (no glob filter; callers
7381
/// filter by extension). Throws on a missing root via `Deno.readDirSync`.
@@ -164,29 +172,14 @@ pub extern fn dateNow() -> Int;
164172
/// returns epoch millis as `Int`.
165173
pub extern fn dateNowIso() -> String;
166174

167-
/// `performance.now()` — high-resolution sub-millisecond timer in
168-
/// milliseconds since process start. Use for fine-grained timings (the
169-
/// existing `dateNow()` returns coarse epoch-millis as Int). Standard
170-
/// JS performance API, present in Deno, Node ≥ 16, and modern browsers.
171-
pub extern fn performance_now() -> Float;
172-
173-
// ── Randomness (PRNG, non-crypto) ──────────────────────────────────
174-
//
175-
// Bound on `Math.random()` — the JS PRNG, **not cryptographically
176-
// secure**. Sufficient for property-test input generation, sampling,
177-
// and simulations. For cryptographic random bytes, a separate
178-
// `crypto_random_bytes` binding routing to `crypto.getRandomValues()`
179-
// belongs in a different sub-issue (different host call, different
180-
// threat model).
181-
182-
/// `Math.random()` — uniform pseudo-random Float in `[0, 1)`.
183-
pub extern fn math_random() -> Float;
184-
185-
/// Uniform u32 in `[0, 2^32)`, derived from `math_random()`.
186-
pub extern fn random_u32() -> Int;
175+
// ── Module identity ────────────────────────────────────────────────
187176

188-
/// Uniform Int in `[lo, hi)`. Undefined behaviour if `hi <= lo`.
189-
pub extern fn random_in_range(lo: Int, hi: Int) -> Int;
177+
/// `import.meta.url` — the absolute URL of the importing module. The JS
178+
/// idiom for "find my own location" (cf. `__dirname` / `__filename`). At
179+
/// Deno-ESM top level, lowers to the bare `import.meta.url` expression;
180+
/// callers parse it (`new URL(...)`/`fileURLToPath`/string split) for
181+
/// directory-relative behaviour.
182+
pub extern fn importMetaUrl() -> String;
190183

191184
// ── CLI ────────────────────────────────────────────────────────────
192185

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// campaign #239 STEP 3 — second batch of Deno-scripting stdlib gaps
3+
// surfaced during STEP 2 ports (panic-attack#82, session-sentinel#25,
4+
// tropical-resource-typing#15, nafa-app#23).
5+
//
6+
// New externs / fixes exercised:
7+
// - statIsFile / statIsDirectory (gap 3)
8+
// - bytesLength / bytesByteAt /
9+
// bytesAsciiSlice (gap 4)
10+
// - importMetaUrl (gap 5)
11+
// - let _ = X wildcard binding emits
12+
// a bare expression statement (gap 7)
13+
//
14+
// Signatures stay in primitives so the harness can stub the host.
15+
16+
use Deno::{ statIsFile, statIsDirectory, bytesLength, bytesByteAt, bytesAsciiSlice, importMetaUrl, readFileBytes };
17+
18+
pub fn classify_path(p: String) -> Int {
19+
if statIsFile(p) {
20+
1
21+
} else {
22+
if statIsDirectory(p) {
23+
2
24+
} else {
25+
0
26+
}
27+
}
28+
}
29+
30+
pub fn first_byte(p: String) -> Int {
31+
let b = readFileBytes(p);
32+
if bytesLength(b) == 0 {
33+
0
34+
} else {
35+
bytesByteAt(b, 0)
36+
}
37+
}
38+
39+
pub fn header_string(p: String, n: Int) -> String {
40+
let b = readFileBytes(p);
41+
let lim = bytesLength(b);
42+
let end = if n > lim { lim } else { n };
43+
bytesAsciiSlice(b, 0, end)
44+
}
45+
46+
pub fn module_url_has_scheme() -> Bool {
47+
let u = importMetaUrl();
48+
// Any well-formed module URL starts with `file:` or `http`.
49+
len(u) > 4
50+
}
51+
52+
fn side(n: Int) -> Int { n + 1 }
53+
54+
pub fn discard_chain() -> Int {
55+
// Three back-to-back `let _ = side(N)` discards. Before the fix this
56+
// tripped JS `SyntaxError: Identifier '_' has already been declared`
57+
// because the AS pattern lowered to `const _ = ...` thrice. Now they
58+
// lower to bare expression statements.
59+
let _ = side(1);
60+
let _ = side(2);
61+
let _ = side(3);
62+
42
63+
}

0 commit comments

Comments
 (0)