summaryrefslogtreecommitdiff
path: root/src/builtins.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/builtins.zig')
-rw-r--r--src/builtins.zig101
1 files changed, 96 insertions, 5 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 5a6b6ea9..0c9993a7 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -28,15 +28,21 @@ const output_pane = @import("output_pane.zig");
const image_pane = @import("image_pane.zig");
const config = @import("config.zig");
const runtime_config = @import("runtime_config.zig");
+const board_memory = @import("board_memory.zig");
/// The platform's runtime-setting facilities, stated once as plain data.
/// Registry generation, leader paths, Config, and EffectCode all consume this
/// exact value rather than rebuilding equivalent-looking boolean expressions.
pub const capabilities: runtime_config.Capabilities = .{
.font_picker = pardes.font_picker,
- .panel_transitions = pardes.platform != .web,
+ // A transition is composited by the shell, and EffectCode has to be able
+ // to show WHICH compositor: only the three hosted shells are in this
+ // package, so the hostless platforms have no honest source to print.
+ .panel_transitions = pardes.hosted,
.scene_shaders = pardes.platform == .gui or pardes.platform == .macos,
- .tagline_font_size = pardes.platform != .tty,
+ // The tty's font belongs to its emulator, and the P4 firmware's belongs to
+ // whatever terminal is on the other end of the serial line.
+ .tagline_font_size = pardes.platform != .tty and pardes.platform != .p4,
};
/// What a builtin gets to act on. One bundle rather than five parameters
@@ -150,7 +156,12 @@ pub const OutputTraits = struct {
/// on the builtin enum being constructed.
pub const registry = struct {
pub fn Builtin() type {
- @setEvalBranchQuota(20_000);
+ // The duplicate-name check below is O(n^2) string comparisons over every manual builtin AND
+ // every generated setting, so this quota grows quadratically with the builtin count. 20,000
+ // was enough until three more (Peek/Poke/Hexdump) tipped `-Dplatform=gui` over with
+ // "evaluation exceeded 20000 backwards branches". Raised with room rather than to the next
+ // value that happens to pass, so the next builtin does not have to rediscover this.
+ @setEvalBranchQuota(200_000);
const manual = manualBuiltinList();
const generated = settingList();
const count = manual.len + generated.len;
@@ -198,6 +209,18 @@ test "capabilities exactly gate setting and effect-source builtins" {
try std.testing.expectEqual(EffectCode.enabled, effect_code_registered);
}
+// The three memory words, checked the same way but at COMPTIME rather than in
+// a test, because the property is about builds this test binary is not: the
+// tty suite can only ever observe its own platform, and what matters is that
+// `-Dplatform=web -Dtarget=wasm32-freestanding` does not quietly hand a
+// browser tab a Poke. Every build of every platform now proves its own half.
+comptime {
+ for ([_][]const u8{ "Peek", "Poke", "Hexdump" }) |name|
+ if (@hasField(registry.Builtin(), name) != board_memory.enabled) @compileError(
+ "bare-metal memory word gating leaked: " ++ name,
+ );
+}
+
// ---- the two acme verbs ----
// Look and Execute are the verbs the whole environment is built on, and they
@@ -336,7 +359,7 @@ pub const ThemeSel = struct {
/// core owns parsing and keeps the last valid value across a bad live edit.
pub const ThemeFile = struct {
pub const takes_arg = true;
- pub const enabled = pardes.platform != .web;
+ pub const enabled = pardes.hosted;
pub fn run(c: Ctx) void {
if (comptime enabled)
c.p.requestThemeFile(c.id, c.arg orelse return)
@@ -349,7 +372,7 @@ pub const ThemeFile = struct {
/// `<config>/themes/builtin`. Filesystem work remains a host effect, just like
/// Dump and Save; the build-time ring itself is the sole source of the data.
pub const DumpThemes = struct {
- pub const enabled = pardes.platform != .web;
+ pub const enabled = pardes.hosted;
pub fn run(c: Ctx) void {
if (comptime enabled) {
if (c.p.opts.config_dir == null) {
@@ -894,3 +917,71 @@ pub const Lspwhy = struct {
c.p.lspRequest(c.id, .explain, "");
}
};
+
+// ---- the machine's address space (bare metal only) ----
+//
+// Three words gated by `board_memory.enabled`, which is a fact about the
+// TARGET (freestanding, and not wasm) rather than about `pardes.platform` —
+// see the reasoning there. Today that is exactly `-Dplatform=p4`; what makes
+// it the right predicate is that a second bare-metal port gets them without
+// anyone remembering to add an enum arm, and the browser never does.
+// Elsewhere they are absent from the command enum, the help index, the leader
+// table and the dispatcher, which is the gate ThemeFile and DumpThemes
+// already use.
+//
+// They are not a debugger and not a privilege: with no OS there is no MMU, no
+// supervisor and no process, so pardes IS the system software and all 2^32
+// addresses are already its own. RAM, the peripheral registers behind the
+// console it is talking to you over, and its own .text are one flat space, and
+// a word that could reach only part of it would be pretending to be an
+// application. What you actually reach for these for is the case a hosted
+// editor never has: the display did not come up, and the question is whether
+// the register you thought you wrote holds what you thought you wrote.
+//
+// Implementation, parsing, the volatile accesses and the clamp are all in
+// board_memory.zig, the way the PDF words live in pdf_pane.zig — these three
+// structs are the words, their argument contract, and where the answer goes.
+
+/// `Peek <addr> [count]` — count 32-bit words (default 1) as `addr: value`
+/// rows, hex or decimal address, refused rather than trapped when unaligned.
+pub const Peek = struct {
+ pub const takes_arg = true;
+ pub const enabled = board_memory.enabled;
+ pub const output: OutputTraits = .{ .name = config.peek_buffer };
+ pub fn run(c: Ctx) void {
+ if (comptime enabled) apply(c) else unreachable;
+ }
+ fn apply(c: Ctx) void {
+ board_memory.peek(c.p, c.id, c.arg orelse "") catch |err|
+ c.p.reportError(c.id, "peek", err);
+ }
+};
+
+/// `Poke <addr> <value>` — one 32-bit store, answered on the message row with
+/// the value written AND the value that reads back, which on MMIO is the
+/// interesting half (see board_memory.poke).
+pub const Poke = struct {
+ pub const takes_arg = true;
+ pub const enabled = board_memory.enabled;
+ pub fn run(c: Ctx) void {
+ if (comptime enabled) apply(c) else unreachable;
+ }
+ fn apply(c: Ctx) void {
+ board_memory.poke(c.p, c.id, c.arg orelse "") catch |err|
+ c.p.reportError(c.id, "poke", err);
+ }
+};
+
+/// `Hexdump <addr> [len]` — len bytes (default 256) in `hexdump -C`'s layout.
+pub const Hexdump = struct {
+ pub const takes_arg = true;
+ pub const enabled = board_memory.enabled;
+ pub const output: OutputTraits = .{ .name = config.hexdump_buffer };
+ pub fn run(c: Ctx) void {
+ if (comptime enabled) apply(c) else unreachable;
+ }
+ fn apply(c: Ctx) void {
+ board_memory.hexdump(c.p, c.id, c.arg orelse "") catch |err|
+ c.p.reportError(c.id, "hexdump", err);
+ }
+};