Skip to content

feat(stdlib): close 6 STEP-3 Deno-ESM gaps surfaced by TS→AS ports (Refs #239, #242)#504

Open
hyperpolymath wants to merge 1 commit into
mainfrom
claude/step3-stdlib-gap-closures-v2
Open

feat(stdlib): close 6 STEP-3 Deno-ESM gaps surfaced by TS→AS ports (Refs #239, #242)#504
hyperpolymath wants to merge 1 commit into
mainfrom
claude/step3-stdlib-gap-closures-v2

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Closes the smallest, safest tractable gaps that the four merged STEP-2 TS→AffineScript ports — phronesis#19, session-sentinel#25, tropical-resource-typing#15, nafa-app#23 — flagged for STEP 3 of the estate-wide campaign (hyperpolymath/standards#239, sub-issue #242).

What lands

stdlib/Deno.affine (+6 externs)

extern lowers to gap
statIsFile(path) -> Bool Deno.statSync(path).isFile 3
statIsDirectory(path) -> Bool Deno.statSync(path).isDirectory 3
bytesLength(b) -> Int (b).length 4
bytesByteAt(b, i) -> Int (b)[i] 4
bytesAsciiSlice(b, s, e) -> String String.fromCharCode(...(b).slice(s, e)) 4
importMetaUrl() -> String import.meta.url 5

The bytes* accessors give AffineScript first-class read access to the opaque Bytes returned by readFileBytes so callers can peek at file-magic / fixed-width binary headers without round-tripping through readTextFile (which throws on binary). importMetaUrl exposes the JS __dirname / __filename idiom for "find my own location"; only legal at module top level, which the Deno-ESM backend's output already is.

stdlib/string.affine (1 char)

fn ends_withpub fn ends_with. The function existed but was private, so the four STEP-2 ports each inlined a string_sub-backed helper instead of importing it. Gap 2.

lib/codegen_deno.ml — wildcard let _ fix (gap 7)

StmtLet { sl_pat = PatWildcard _; … } now lowers to a bare expression statement instead of const _ = X;. Three back-to-back let _ = side() discards in the same scope tripped JS SyntaxError: Identifier '_' has already been declared. The wildcard pattern doesn't bind, so dropping the binding entirely preserves AffineScript semantics (evaluate for side effects).

// before
function discard_chain() {
  const _ = side(1);
  const _ = side(2);   // ❌ SyntaxError
  const _ = side(3);
  return 42;
}

// after
function discard_chain() {
  side(1);
  side(2);
  side(3);
  return 42;
}

Tests

tests/codegen-deno/deno_scripting_part2.{affine,deno.js,harness.mjs} — 11 assertions across the new lowerings + the wildcard fix. The harness reaching its discard-chain assertion is itself the test for gap 7: a syntax-error generated module would have thrown at the dynamic import line before any assert ran.

Verification

step result
dune build bin/main.exe
dune runtest ✅ 353/353
./tools/run_codegen_deno_tests.sh ✅ all harnesses (incl. the new one)

What does not land here (deferred deliberately)

  • gap 1Deno.test extern lowering. The four merged STEP-2 ports use a panic-on-fail main() driver and it works; not unblocking STEP 4.
  • gap 6 — native TOML parser. Heavier work; STEP-2 ports used regex field-presence checks where TOML mattered.

Gaps 9 (AFFINESCRIPT_STDLIB env discovery ladder, shipped #433) and 10 (negative integer literals, verified working in all contexts — match arms, array literals, equality, ternaries) were audited as already-resolved.

Refs

  • Closes 6 of the 10 gaps blocking hyperpolymath/standards#242 (STEP 3 of #239).
  • Unblocks STEP 4 (#243, mid-tier 4-9 file ports) and STEP 5 (#244, idaptik DLC) for any consumer that needs stat predicates, byte accessors, module-URL inspection, the public ends_with, or multiple let _ discards in a single scope.

🤖 Generated with Claude Code

…efs #239, #242)

Closes the smallest, safest tractable gaps that the four merged STEP-2
ports (phronesis#19, session-sentinel#25, tropical-resource-typing#15,
nafa-app#23) flagged for STEP 3 (campaign #239):

Stdlib (`stdlib/Deno.affine`):
  + `statIsFile`        — `Deno.statSync(p).isFile`  (gap 3)
  + `statIsDirectory`   — `Deno.statSync(p).isDirectory`  (gap 3)
  + `bytesLength`       — `(b).length`               (gap 4)
  + `bytesByteAt`       — `(b)[i]`                   (gap 4)
  + `bytesAsciiSlice`   — `String.fromCharCode(...(b).slice(start, end))`  (gap 4)
  + `importMetaUrl`     — `import.meta.url`          (gap 5)

Stdlib (`stdlib/string.affine`):
  ! `ends_with` is now `pub` so consumers can `use string::{ends_with};`
    instead of inlining a `string_sub`-backed helper.   (gap 2)

Codegen (`lib/codegen_deno.ml`):
  ! `StmtLet { sl_pat = PatWildcard _; … }` lowers to a bare expression
    statement instead of `const _ = X;`. Three back-to-back `let _ = …`
    discards in the same scope used to trip JS
    `SyntaxError: Identifier '_' has already been declared`.  (gap 7)

Tests:
  + tests/codegen-deno/deno_scripting_part2.{affine,deno.js,harness.mjs}
    exercises every new lowering plus the wildcard fix (11 assertions).
  ✓ All 353 dune-runtest tests pass.
  ✓ All codegen-Deno-ESM harnesses pass (`tools/run_codegen_deno_tests.sh`).

Two further gaps from the STEP-2 set remain open, deliberately deferred:
  - gap 1 `Deno.test` extern lowering — panic-on-fail `main()` driver in
    the four merged STEP-2 ports works; not unblocking STEP 4.
  - gap 6 native TOML parser — heavier work; STEP-2 ports used regex
    field-presence checks where TOML was relevant.

Gaps 9 (`AFFINESCRIPT_STDLIB` env discovery ladder, shipped #433) and 10
(negative integer literals, working today) were audited and confirmed
already-resolved.

Refs: hyperpolymath/standards#239, hyperpolymath/standards#242

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 83 issues detected

Severity Count
🔴 Critical 2
🟠 High 13
🟡 Medium 68

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action perpolymath/standards/.github/workflows/governance-reusable.yml@main\n needs attention",
    "type": "unpinned_action",
    "file": "governance.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action ons/checkout@v6\n    needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action land/setup-deno@v2\n    needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in affine-vscode-publish.yml",
    "type": "missing_timeout_minutes",
    "file": "affine-vscode-publish.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "missing_timeout_minutes",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "missing_timeout_minutes",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant