Skip to content

Wire codegen dispatch for perry/i18n format wrappers (Currency, Percent, FormatNumber, ShortDate, LongDate, FormatTime, Raw) #188

Description

@proggeramlug

Context

Surfaced during the v0.5.299 docs audit. The perry/i18n module exports 8 functions per types/perry/i18n/index.d.ts:

t, Currency, Percent, ShortDate, LongDate, FormatNumber, FormatTime, Raw

All 7 format wrappers have runtime implementations in crates/perry-runtime/src/i18n.rs:633-823:

  • perry_i18n_format_number
  • perry_i18n_format_currency
  • perry_i18n_format_percent
  • perry_i18n_format_date (used by ShortDate and LongDate)
  • perry_i18n_format_time

But crates/perry-codegen/src/lower_call.rs only wires the t() lookup. Calls to Currency(99.99), Percent(0.5), etc. compile + link cleanly (because the runtime symbols exist) but reach the receiver-less native-call early-out at lower_call.rs:2849-2854 and return NaN-boxed undefined at runtime.

Repro:

import { Currency } from "perry/i18n"
console.log(Currency(99.99))   // prints `undefined`, expected "$99.99" (or locale equivalent)

What to do

Add UiSig rows in crates/perry-codegen/src/lower_call.rs (the same table that already wires perry/ui and perry/system) that map each TS-callable name to its runtime symbol:

UiSig { method: "Currency",     runtime: "perry_i18n_format_currency", args: &[UiArgKind::F64], ret: UiReturnKind::Str },
UiSig { method: "Percent",      runtime: "perry_i18n_format_percent",  args: &[UiArgKind::F64], ret: UiReturnKind::Str },
UiSig { method: "FormatNumber", runtime: "perry_i18n_format_number",   args: &[UiArgKind::F64], ret: UiReturnKind::Str },
UiSig { method: "ShortDate",    runtime: "perry_i18n_format_date_short", args: &[UiArgKind::F64], ret: UiReturnKind::Str },
UiSig { method: "LongDate",     runtime: "perry_i18n_format_date_long",  args: &[UiArgKind::F64], ret: UiReturnKind::Str },
UiSig { method: "FormatTime",   runtime: "perry_i18n_format_time",    args: &[UiArgKind::F64], ret: UiReturnKind::Str },
UiSig { method: "Raw",          runtime: "perry_i18n_format_raw",     args: &[UiArgKind::F64], ret: UiReturnKind::Str },

ShortDate and LongDate may need either two distinct runtime exports or a single perry_i18n_format_date(value, style_flag) shape — check what the runtime currently exposes and pick whichever is least invasive.

Acceptance criteria

  • Each function callable from TS produces the locale-formatted string the runtime computes.
  • docs/examples/i18n/snippets.ts can drop its // run: false banner — the harness should run it to a clean exit.
  • docs/src/i18n/formatting.md and overview.md no longer need their "format wrappers reach the receiver-less early-out" status notes.
  • Snippet test: a runtime example that calls each wrapper and prints the result, with _expected/.../*.stdout byte-diffed.

Pointers

  • Wrapper definitions: types/perry/i18n/index.d.ts
  • Runtime implementations: crates/perry-runtime/src/i18n.rs:633-823
  • Existing dispatcher pattern: crates/perry-codegen/src/lower_call.rs — search for UiSig { method: "isDarkMode" or UiSig { method: "audioStart" for the most-similar shape (perry/system uses the exact same dispatch table for cross-module functions).
  • Failing call site: lower_call.rs:2849-2854 (receiver-less early-out that swallows args).

Estimated size

Small — ~15 lines of dispatcher code plus one runtime exit-style runtime export if format_date doesn't currently distinguish short/long.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew capability or improvement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions