std: restructure — std/ modules, namespace tail, std/xml.sx

allocators/fs/process/socket/log/trace/test move under modules/std/
(allocators.sx becomes std/mem.sx; the Allocator protocol moves into
the std.sx prelude, impls stay in mem.sx). New std/xml.sx holds
xml_escape as xml.escape. std.sx gains the carried namespace tail —
flat-importing std.sx now also provides mem./xml./log. — with the
remaining modules (fs/process/socket/json/cli/hash/test) deferred from
the tail until the global last-wins maps are fully own-wins (pulling
them into every closure collides bare names corpus-wide; they stay
direct imports: modules/std/fs.sx etc.). log.sx's internal emit
renamed log_emit (it clobbered consumer fns named emit program-wide).
bundle.sx uses xml.escape via the carried alias. Consumer import paths
swept mechanically; .ir snapshots recaptured for the larger std
closure. m3te + game build unchanged.
This commit is contained in:
agra
2026-06-11 06:10:59 +03:00
parent ee00db849c
commit 59f0aa7716
112 changed files with 18612 additions and 15988 deletions

View File

@@ -21,7 +21,7 @@
// the Metal backend takes — caller branches on OS).
#import "modules/std.sx";
#import "modules/allocators.sx";
#import "modules/std/mem.sx";
#import "modules/compiler.sx";
#import "modules/opengl.sx";
#import "modules/gpu/types.sx";

View File

@@ -7,7 +7,7 @@
// non-iOS targets don't reach the Metal-touching code paths.
#import "modules/std.sx";
#import "modules/allocators.sx";
#import "modules/std/mem.sx";
#import "modules/std/objc.sx";
#import "modules/compiler.sx";
#import "modules/gpu/types.sx";

View File

@@ -1,7 +1,7 @@
#import "../std.sx";
#import "../compiler.sx";
#import "../fs.sx";
#import "../process.sx";
#import "../std/fs.sx";
#import "../std/process.sx";
// =====================================================================
// platform.bundle — sx-side Apple `.app` bundler.
@@ -269,7 +269,7 @@ build_info_plist :: (opts: BuildOptions, exe_name: string, bundle_id: string) ->
<string>{}</string>
</dict>
</plist>
PLIST, xml_escape(bundle_id), xml_escape(exe_name), xml_escape(exe_name), IOS_MIN_OS, platform_key);
PLIST, xml.escape(bundle_id), xml.escape(exe_name), xml.escape(exe_name), IOS_MIN_OS, platform_key);
}
// macOS (and any non-iOS Apple target) — the minimal plist both
@@ -293,7 +293,7 @@ PLIST, xml_escape(bundle_id), xml_escape(exe_name), xml_escape(exe_name), IOS_MI
<string>0.1</string>
</dict>
</plist>
PLIST, xml_escape(bundle_id), xml_escape(exe_name), xml_escape(exe_name))
PLIST, xml.escape(bundle_id), xml.escape(exe_name), xml.escape(exe_name))
}
// Read a `.mobileprovision` and write it to
@@ -868,15 +868,15 @@ lib_name_from_so_basename :: (basename: string) -> string {
// Otherwise it falls back to the legacy NativeActivity shape with an
// `android.app.lib_name` meta-data entry pointing at the .so.
build_android_manifest :: (opts: BuildOptions, package: string, lib_name: string) -> string {
pkg_esc := xml_escape(package);
lib_esc := xml_escape(lib_name);
pkg_esc := xml.escape(package);
lib_esc := xml.escape(lib_name);
if opts.jni_main_count() > 0 {
// First `#jni_main` decl drives the Activity. The foreign_path
// uses `/` separators; Java fully-qualified class names use
// `.` so we rewrite.
foreign := opts.jni_main_foreign_path_at(0);
cls := slash_to_dot(foreign);
cls_esc := xml_escape(cls);
cls_esc := xml.escape(cls);
return format(#string MANIFEST
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx";
#import "modules/allocators.sx";
#import "modules/std/mem.sx";
#import "modules/compiler.sx";
#import "modules/opengl.sx";
#import "modules/sdl3.sx";

View File

@@ -36,7 +36,14 @@ Source_Location :: struct {
}
string :: []u8 #builtin;
#import "allocators.sx";
#import "std/mem.sx";
// --- Allocator protocol (impls live in std/mem.sx) ---
Allocator :: protocol #inline {
alloc :: (size: s64) -> *void;
dealloc :: (ptr: *void);
}
// --- Context ---
@@ -215,37 +222,6 @@ substr :: (s: string, start: s64, len: s64) -> string {
buf
}
// Replace XML special characters with their entity references. Used
// when emitting Info.plist / AndroidManifest content from sx values
// that may contain user-supplied text (bundle id, app name, etc).
xml_escape :: (s: string) -> string {
result := "";
i := 0;
seg_start := 0;
while i < s.len {
c := s[i];
// 38='&', 60='<', 62='>', 34='"', 39='\''
ent := "";
if c == 38 { ent = "&amp;"; }
if c == 60 { ent = "&lt;"; }
if c == 62 { ent = "&gt;"; }
if c == 34 { ent = "&quot;"; }
if c == 39 { ent = "&apos;"; }
if ent.len > 0 {
if i > seg_start {
result = concat(result, substr(s, seg_start, i - seg_start));
}
result = concat(result, ent);
seg_start = i + 1;
}
i += 1;
}
if seg_start < s.len {
result = concat(result, substr(s, seg_start, s.len - seg_start));
}
result
}
// Join path components with the POSIX separator ('/'). Skips empty
// components and collapses duplicate separators at component
// boundaries. Used for bundle paths where Apple .app and Android APK
@@ -513,4 +489,13 @@ List :: struct ($T: Type) {
list.len = 0;
list.cap = 0;
}
}
}
// --- The stdlib namespace tail: flat-importing std.sx carries these ---
mem :: #import "std/mem.sx";
xml :: #import "std/xml.sx";
log :: #import "std/log.sx";
// fs/process/socket/json/cli/hash/test join the tail once the global
// last-wins maps are fully own-wins (their decls collide across programs
// when pulled into every closure) — import them directly meanwhile:
// #import "modules/std/fs.sx"; etc.

View File

@@ -31,7 +31,7 @@
#import "modules/std.sx";
#import "modules/compiler.sx";
proc :: #import "modules/process.sx";
proc :: #import "modules/std/process.sx";
libc :: #library "c";
@@ -54,7 +54,7 @@ ns_get_argc :: () -> *s32 #foreign libc "_NSGetArgc";
// value), `EX_UNAVAILABLE` when the platform is unsupported.
// 2. TERMINATORS. `exit_ok()` / `exit_usage()` end the process with the
// matching code. They route through the canonical
// `process.exit(code: u8)` (modules/process.sx) — there is NO second
// `process.exit(code: u8)` (modules/std/process.sx) — there is NO second
// hand-rolled `_exit` binding in this module; the unsupported-platform
// path below goes through `proc.exit(EX_UNAVAILABLE)` too.
//
@@ -62,7 +62,7 @@ ns_get_argc :: () -> *s32 #foreign libc "_NSGetArgc";
// `parsed.json` (true iff `--json` appears in the argv — see `Parsed.json`).
// The convention a front-end follows: in json mode stdout carries ONLY the
// machine result, and human diagnostics go to stderr (e.g. via
// `modules/log.sx`'s `log.err`). Detect json mode by reading `parsed.json`.
// `modules/std/log.sx`'s `log.err`). Detect json mode by reading `parsed.json`.
// =====================================================================
EX_OK :u8: 0; // success

View File

@@ -1,4 +1,4 @@
#import "std.sx";
#import "modules/std.sx";
// =====================================================================
// fs.sx — file system stdlib (POSIX backend, macOS values).

View File

@@ -31,7 +31,7 @@
// =====================================================================
#import "modules/std.sx";
#import "modules/fs.sx";
#import "modules/std/fs.sx";
// Low 32 bits. SHA-256 is defined over 32-bit words; every add/rotate
// result is masked back through this so the carry never escapes bit 31.

View File

@@ -60,8 +60,8 @@
#import "modules/std.sx";
// `Array`/`Object` methods take an explicit `alloc: Allocator`; bare-import
// visibility is non-transitive, so the module that names the type imports it.
#import "modules/allocators.sx";
#import "modules/fs.sx";
#import "modules/std/mem.sx";
#import "modules/std/fs.sx";
// The writer's failure contract: a too-small caller buffer (Overflow) or
// a short/failed file write (Io). Surfaced on the error channel — never a

View File

@@ -1,4 +1,4 @@
#import "std.sx";
#import "modules/std.sx";
// =====================================================================
// log.sx — plain leveled logging (ERR step E4.1), orthogonal to the
@@ -18,12 +18,12 @@ libc :: #library "c";
write :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
// Prefix the level, append a newline, write the whole line to stderr.
emit :: (level: string, msg: string) {
log_emit :: (level: string, msg: string) {
line := concat(concat(level, msg), "\n");
write(2, line.ptr, xx line.len);
}
warn :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"WARN: \", result);"; }
info :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"INFO: \", result);"; }
debug :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"DEBUG: \", result);"; }
err :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "emit(\"ERROR: \", result);"; }
warn :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "log_emit(\"WARN: \", result);"; }
info :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "log_emit(\"INFO: \", result);"; }
debug :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "log_emit(\"DEBUG: \", result);"; }
err :: ($fmt: string, ..$args) { #insert build_format(fmt); #insert "log_emit(\"ERROR: \", result);"; }

View File

@@ -1,11 +1,4 @@
#import "std.sx";
// --- Allocator protocol (inline: ctx + fn-ptrs, no vtable indirection) ---
Allocator :: protocol #inline {
alloc :: (size: s64) -> *void;
dealloc :: (ptr: *void);
}
#import "modules/std.sx";
// --- CAllocator: stateless allocator that delegates directly to libc ---
//

View File

@@ -1,5 +1,5 @@
#import "std.sx";
trace :: #import "trace.sx";
#import "modules/std.sx";
trace :: #import "modules/std/trace.sx";
// =====================================================================
// process.sx — subprocess + environment stdlib (POSIX backend).

View File

@@ -1,4 +1,4 @@
#import "std.sx";
#import "modules/std.sx";
assert :: (condition: bool) {
if !condition {

View File

@@ -1,4 +1,4 @@
#import "std.sx";
#import "modules/std.sx";
// =====================================================================
// trace.sx — error return-trace formatting (ERR step E3.3).

View File

@@ -0,0 +1,32 @@
// XML helpers. `escape` replaces XML special characters with entity
// references — used when emitting Info.plist / AndroidManifest content
// from sx values that may contain user-supplied text.
#import "modules/std.sx";
escape :: (s: string) -> string {
result := "";
i := 0;
seg_start := 0;
while i < s.len {
c := s[i];
// 38='&', 60='<', 62='>', 34='"', 39='\''
ent := "";
if c == 38 { ent = "&amp;"; }
if c == 60 { ent = "&lt;"; }
if c == 62 { ent = "&gt;"; }
if c == 34 { ent = "&quot;"; }
if c == 39 { ent = "&apos;"; }
if ent.len > 0 {
if i > seg_start {
result = concat(result, substr(s, seg_start, i - seg_start));
}
result = concat(result, ent);
seg_start = i + 1;
}
i += 1;
}
if seg_start < s.len {
result = concat(result, substr(s, seg_start, s.len - seg_start));
}
result
}

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx";
#import "modules/allocators.sx";
#import "modules/std/mem.sx";
#import "modules/math";
#import "modules/ui/types.sx";
#import "modules/ui/render.sx";

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx";
#import "modules/allocators.sx";
#import "modules/std/mem.sx";
#import "modules/opengl.sx";
#import "modules/gpu/types.sx";
#import "modules/gpu/api.sx";

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx";
#import "modules/allocators.sx";
#import "modules/std/mem.sx";
#import "modules/ui/glyph_cache.sx"; // `font: GlyphCache` — name it, import it (non-transitive).
#import "modules/opengl.sx";
#import "modules/gpu/api.sx";

View File

@@ -1,5 +1,5 @@
#import "modules/std.sx";
#import "modules/allocators.sx";
#import "modules/std/mem.sx";
// --- State(T) — a handle to persistent storage ---