This commit is contained in:
agra
2026-02-15 12:02:36 +02:00
parent 476bf0d268
commit 2727b5509e
61 changed files with 263 additions and 102 deletions

View File

@@ -85,7 +85,6 @@ main :: () {
print("{}\n", size_of(Foo));
print("{}\n", size_of(Complex));
size:= size_of(Sx);
size := size_of(Sx);
print("{}\n", size);
}

View File

@@ -1,98 +0,0 @@
main :: {
// imagine a game loop
while(running) {
render_ui(build_menu);
}
}
build_menu :: (ctx: ViewContext) -> View {
// use ctx to allocate some state at the for Menu ViewContext
state : MenuState = ctx.state(MenuState);
// named args
HStack(ctx,
children = .[
Button(ctx,
label = "Up",
onTap = ctx.callback(goUp, state),
),
ScrollView(ctx,
LazyVStack(ctx,
builder = ctx.callback(build_menu_entry, state),
),
)
],
);
}
build_menu_entry :: (ctx: *ViewContext, index: s32, state: *MenuState) -> View {
entry := state.entries[index];
is_selected := index == state.selected_index;
icon := if entry.is_dir then "[D]" else " ";
Button(ctx,
label = concat(icon, " ", entry.name),
on_tap = ctx.callback(menu_go, state, index),
);
}
ViewContext :: struct {
//TBD
}
MenuState :: struct {
current_path: string;
entries: List(MenuEntry);
error_message: string;
}
MenuEntry :: struct {
name: string;
is_dir: bool;
}
menu_go_up :: (state: *MenuState) {
parent := fs.path.dirname(state.current_path) else return;
// this frees the current path & copies parent to be owned by MenuState
state.current_path = parent;
menu_refresh(state);
}
menu_go :: (state: *MenuState, s32 index) {
entry := state.entries[index] else return;
state.current_path := concat(state.current_path, "/", entry.name);
menu_refresh(state);
}
menu_refresh :: (state: *MenuState) {
// this could retain the capacity
state.entries.clear();
// this would basically create a copy of the empty string :(
state.error_message = "";
// ... multi return params vs Generic Result to deal with exceptions
// ... nullable
dir := io.Dir.open(state.current_path);
if !dir {
state.error_message = "failed to open";
return;
};
defer dir.close();
for iter.iterate() {
entries.append(.{it.name, it.kind == .Directory});
}
}
HStackState :: struct {
spacing: f32 = 8;
alignment: VerticalAlignment = .center;
padding: f32 = 0;
background: ?Color;
corner_radius: f32 = 0,
}
HStack :: (ctx: ViewContext, children: []View) -> View {
data := ctx.alloc(HStackState);
data.* = .{};
}

View File

@@ -4223,8 +4223,16 @@ pub const CodeGen = struct {
fn genSizeOf(self: *CodeGen, call_node: ast.Call) !c.LLVMValueRef {
if (call_node.args.len != 1) return self.emitError("size_of expects exactly 1 argument");
const ty = self.resolveType(call_node.args[0]);
const arg = call_node.args[0];
const ty = self.resolveType(arg);
if (std.meta.eql(ty, Type.void_type)) {
// Uninstantiated generic type function → size of a function pointer
if (arg.data == .identifier or arg.data == .type_expr) {
const name = if (arg.data == .identifier) arg.data.identifier.name else arg.data.type_expr.name;
if (self.generic_templates.contains(name) or self.generic_struct_templates.contains(name)) {
return self.constInt64(self.getTypeSize(self.ptrType()));
}
}
return self.constInt64(0);
}
const llvm_ty = self.typeToLLVM(ty);

View File

@@ -97,10 +97,15 @@ pub fn main(init: std.process.Init) !void {
std.debug.print("error: failed to run program\n", .{});
return;
};
_ = child.wait(io) catch {
const term = child.wait(io) catch {
std.debug.print("error: program execution failed\n", .{});
return;
};
switch (term) {
.exited => |code| if (code != 0) std.process.exit(code),
.signal => std.process.exit(1),
.stopped, .unknown => std.process.exit(1),
}
} else {
printUsage();
}

View File

@@ -0,0 +1 @@
42

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
Hello

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,6 @@
v1: Vec4{x: 1.000000, y: 2.000000, z: 3.000000, w: 0.000000}
v2: Vec4{x: 4.000000, y: 1.000000, z: 1.000000, w: 3.000000}
v3: Vec4{x: 2.000000, y: 3.000000, z: 4.000000, w: 0.000000}
v4: Vec4{x: 9.000000, y: 0.000000, z: 5.000000, w: 6.000000}
Complex{foo: .S(Complex.foo.B{val: hello})}

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,4 @@
scope opened
scoped x: 6
scope closed
main x: 42

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,2 @@
hello 25
hello 25

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,3 @@
sum: 5
sum: 42
sum: 42.500000

View File

@@ -0,0 +1 @@
42

View File

@@ -0,0 +1 @@
still here

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,2 @@
hello thereafter hello
[1.000000, 2.000000, 3.000000]

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,16 @@
v1: Vec__3_f32{data: [1.000000, 3.000000, 2.000000]}
v2: [1.000000, 3.000000, 2.000000]
buff: [0.000000, 2.000000, 3.500000, 4.000000, 0.000000]
comp: Complex__u32{value: 42, count: 1}
add: [4.000000, 5.000000, 3.000000]
v2.x: 1.000000
v2[1]: 3.000000
scaled: [2.000000, 6.000000, 4.000000]
neg: [-1.000000, -3.000000, -2.000000]
sqrt(9): 3.000000
.counter(0.500000)
4
16
8
8
8

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,4 @@
dot: 0.000000
cross: [0.000000, 0.000000, 1.000000]
length: 5.000000
norm: [0.600000, 0.800000, 0.000000]

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,4 @@
f64
3.200000
Vec4
() -> s32

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
hello from the other side

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
[1.000000, 0.000000, -1.000000]

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,4 @@
count: 5
break at: 12
sum of odd 1-9: 25
sum 55

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,8 @@
circle: .circle(3.140000)
radius: 3.140000
none: .circle
rect: .circle(Shape.rect{w: 4.000000, h: 2.000000})
sh: .circle(2.710000)
rect val: Shape.rect{w: 2.000000, h: 4.000000}
matched rect
case : 2

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
-3

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
containedcontainedcontained

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,4 @@
60
1 2 3 4 5
60
10 20 30

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,3 @@
42 hello true 3.140000
point: (10,20) 99
3

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,7 @@
p: Point{x: 10, y: 20}
c: Color{r: 255, g: 128, b: 0}
n: 42
s: hello
b: true
&p: *Point@0xADDR
&p: *Point@0xADDR

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
5

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
[1, 2, 2, 2, 3, 3, 4, 5, 5, 6, 6, 333]

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@
List__s32{items: [*]s32@0xADDR, len: 5, cap: 8}

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,9 @@
arr.len = 5
arr[1..4] = [1, 4, 1]
sub.len = 3
arr[..3] = [3, 1, 4]
arr[2..] = [4, 1, 5]
sl[1..4] = [20, 30, 40]
mid[1..] = [30, 40]
msg[6..11] = world
msg[..5] = hello

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,5 @@
before: Vec2{x: 1.000000, y: 2.000000}
after: Vec2{x: 99.000000, y: 2.000000}
copy: Vec2{x: 99.000000, y: 2.000000}
mp[0] = 10
mp[2] = 30

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,4 @@
fp(3,4) = 7
fp(3,4) = 12
apply(add,5,6) = 11
apply(mul,5,6) = 30

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,6 @@
f=3.140000
i=1078523331
x=1.000000
y=2.000000
data[0]=1.000000
data[1]=2.000000

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,26 @@
perms: .read | .write
checking: .read | .write
- can read
- can write
all: .read | .write | .execute
checking: .read | .write | .execute
- can read
- can write
- can execute
read only: .read
checking: .read
- can read
match on flags:
execute
window: .vsync | .resizable
raw value: 68
color: .blue
raw: 2
0xFF & 0x0F = 15
1 | 2 | 4 = 7

92
tests/run_examples.sh Executable file
View File

@@ -0,0 +1,92 @@
#!/bin/bash
# Example regression test runner
# Usage: ./tests/run_examples.sh [--update]
# --update: regenerate expected output and exit code files
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
SX="$ROOT_DIR/zig-out/bin/sx"
EXPECTED_DIR="$SCRIPT_DIR/expected"
PASS=0
FAIL=0
SKIP=0
TIMEOUT_COUNT=0
UPDATE=0
TIMEOUT=10
if [[ "${1:-}" == "--update" ]]; then
UPDATE=1
fi
normalize() {
sed 's/0x[0-9a-f]\{4,\}/0xADDR/g'
}
for expected_file in "$EXPECTED_DIR"/*.txt; do
name=$(basename "$expected_file" .txt)
sx_file="$ROOT_DIR/examples/${name}.sx"
exit_file="$EXPECTED_DIR/${name}.exit"
if [[ ! -f "$sx_file" ]]; then
SKIP=$((SKIP + 1))
continue
fi
printf " %-30s" "$name"
actual=$(timeout "$TIMEOUT" "$SX" run "$sx_file" 2>&1 | normalize)
actual_exit=${PIPESTATUS[0]}
if [[ $actual_exit -eq 124 ]]; then
TIMEOUT_COUNT=$((TIMEOUT_COUNT + 1))
echo "TIMEOUT (>${TIMEOUT}s)"
continue
fi
if [[ $UPDATE -eq 1 ]]; then
echo "$actual" > "$expected_file"
echo "$actual_exit" > "$exit_file"
echo " updated $name (exit=$actual_exit)"
continue
fi
expected=$(cat "$expected_file" | normalize)
expected_exit=0
if [[ -f "$exit_file" ]]; then
expected_exit=$(cat "$exit_file")
fi
output_ok=true
exit_ok=true
if [[ "$actual" != "$expected" ]]; then
output_ok=false
fi
if [[ "$actual_exit" != "$expected_exit" ]]; then
exit_ok=false
fi
if $output_ok && $exit_ok; then
PASS=$((PASS + 1))
echo "ok"
else
FAIL=$((FAIL + 1))
echo "FAIL"
if ! $output_ok; then
diff <(echo "$expected") <(echo "$actual") || true
fi
if ! $exit_ok; then
echo " exit code: expected=$expected_exit actual=$actual_exit"
fi
fi
done
if [[ $UPDATE -eq 1 ]]; then
echo "Updated all expected output files."
exit 0
fi
echo "$PASS passed, $FAIL failed, $SKIP skipped, $TIMEOUT_COUNT timed out"
[[ $FAIL -eq 0 && $TIMEOUT_COUNT -eq 0 ]]