-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathend_to_end_demo.exs
More file actions
163 lines (116 loc) · 6.45 KB
/
Copy pathend_to_end_demo.exs
File metadata and controls
163 lines (116 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# Firebird End-to-End Demo
# Run: mix run examples/end_to_end_demo.exs
#
# This demonstrates the complete WASM-from-Elixir workflow:
# 1. Load WASM modules from different sources (WAT, Rust, Go)
# 2. Call functions, inspect exports, validate calls
# 3. Memory operations
# 4. Cross-language comparison
# 5. Batch operations
# 6. Module wrapper pattern
IO.puts("""
╔══════════════════════════════════════════════════════════════╗
║ 🔥 Firebird End-to-End Demo ║
╚══════════════════════════════════════════════════════════════╝
""")
# ── 1. Load WASM modules ─────────────────────────────────────
IO.puts("📦 Loading WASM modules...\n")
{:ok, wat} = Firebird.load("fixtures/math.wasm")
IO.puts(" ✅ WAT math module loaded")
{:ok, rust} = Firebird.load("fixtures/rust_algorithms.wasm")
IO.puts(" ✅ Rust algorithms module loaded")
{:ok, go} = Firebird.load("fixtures/go_math.wasm", wasi: true)
IO.puts(" ✅ Go math module loaded (with WASI)")
# ── 2. Inspect exports ───────────────────────────────────────
IO.puts("\n📋 Module exports:\n")
for {name, inst} <- [{"WAT math", wat}, {"Rust algorithms", rust}, {"Go math", go}] do
exports = Firebird.exports(inst)
IO.puts(" #{name}: #{Enum.join(exports, ", ")}")
end
# ── 3. Call functions ─────────────────────────────────────────
IO.puts("\n🔢 Function calls:\n")
{:ok, [r]} = Firebird.call(wat, :add, [42, 58])
IO.puts(" WAT add(42, 58) = #{r}")
{:ok, [r]} = Firebird.call(wat, :fibonacci, [10])
IO.puts(" WAT fibonacci(10) = #{r}")
{:ok, [r]} = Firebird.call(rust, :is_palindrome, [12321])
IO.puts(" Rust is_palindrome(12321) = #{r} (1=true)")
{:ok, [r]} = Firebird.call(rust, :collatz_steps, [27])
IO.puts(" Rust collatz_steps(27) = #{r}")
{:ok, [r]} = Firebird.call(rust, :nth_prime, [100])
IO.puts(" Rust nth_prime(100) = #{r}")
{:ok, [r]} = Firebird.call(go, :multiply, [7, 8])
IO.puts(" Go multiply(7, 8) = #{r}")
# ── 4. Type signatures ───────────────────────────────────────
IO.puts("\n📐 Function signatures:\n")
{:ok, sig} = Firebird.function_type(wat, :add)
IO.puts(" add: #{inspect(sig)}")
{:ok, sig} = Firebird.function_type(wat, :fibonacci)
IO.puts(" fibonacci: #{inspect(sig)}")
# ── 5. Validate before calling ────────────────────────────────
IO.puts("\n✅ Call validation:\n")
:ok = Firebird.WasmRunner.validate_call(wat, :add, [1, 2])
IO.puts(" validate_call(:add, [1, 2]) = :ok")
{:error, reason} = Firebird.WasmRunner.validate_call(wat, :add, [1, 2, 3])
IO.puts(" validate_call(:add, [1, 2, 3]) = {:error, #{inspect(reason)}}")
{:error, reason} = Firebird.WasmRunner.validate_call(wat, :nonexistent, [1])
IO.puts(" validate_call(:nonexistent, [1]) = {:error, #{inspect(reason)}}")
# ── 6. Memory operations ─────────────────────────────────────
IO.puts("\n🧠 Memory operations:\n")
{:ok, size} = Firebird.memory_size(wat)
IO.puts(" Memory size: #{size} bytes (#{div(size, 65536)} pages)")
# Write and read data
:ok = Firebird.write_memory(wat, 0, "Hello WASM!")
{:ok, data} = Firebird.read_memory(wat, 0, 10)
IO.puts(" Wrote and read back: #{inspect(data)}")
# Write i32 array and sort with Rust module
{:ok, rust_mem_size} = Firebird.memory_size(rust)
IO.puts(" Rust module memory: #{rust_mem_size} bytes")
data = <<50::little-32, 10::little-32, 40::little-32, 20::little-32, 30::little-32>>
:ok = Firebird.write_memory(rust, 0, data)
{:ok, [5]} = Firebird.call(rust, :sort_i32, [0, 5])
{:ok, sorted} = Firebird.read_memory(rust, 0, 20)
sorted_list = for <<x::little-signed-32 <- sorted>>, do: x
IO.puts(" Sorted [50,10,40,20,30] → #{inspect(sorted_list)}")
# Binary search the sorted array
{:ok, [idx]} = Firebird.call(rust, :binary_search, [0, 5, 30])
IO.puts(" Binary search for 30 → index #{idx}")
# ── 7. Cross-language comparison ──────────────────────────────
IO.puts("\n🌍 Cross-language comparison (WAT vs Go):\n")
for {func, args} <- [
{:add, [100, 200]},
{:multiply, [7, 8]},
{:fibonacci, [15]},
{:factorial, [10]}
] do
{:ok, [wat_r]} = Firebird.call(wat, func, args)
{:ok, [go_r]} = Firebird.call(go, func, args)
match = if wat_r == go_r, do: "✅", else: "❌"
IO.puts(" #{match} #{func}(#{Enum.join(args, ", ")}): WAT=#{wat_r}, Go=#{go_r}")
end
# ── 8. Batch operations ──────────────────────────────────────
IO.puts("\n📦 Batch operations:\n")
{:ok, results} =
Firebird.WasmRunner.run_batch("fixtures/math.wasm", [
{:add, [1, 2]},
{:multiply, [3, 4]},
{:fibonacci, [10]},
{:factorial, [5]},
{:gcd, [48, 36]}
])
IO.puts(" Batch results: #{inspect(results)}")
# ── 9. WasmRunner auto-WASI ──────────────────────────────────
IO.puts("\n🔄 Auto-WASI detection:\n")
{:ok, auto} = Firebird.WasmRunner.start("fixtures/go_math.wasm")
{:ok, 8} = Firebird.WasmRunner.call_single(auto, :add, [5, 3])
IO.puts(" Auto-detected WASI for Go module: add(5, 3) = 8")
Firebird.WasmRunner.stop(auto)
# ── Cleanup ───────────────────────────────────────────────────
Firebird.stop(wat)
Firebird.stop(rust)
Firebird.stop(go)
IO.puts("""
╔══════════════════════════════════════════════════════════════╗
║ ✅ All demos completed successfully! ║
╚══════════════════════════════════════════════════════════════╝
""")