1
//! Global / context accessors that don't take an entity index, plus
2
//! the two index-driven header readers `ENTITY-TYPE` and
3
//! `ENTITY-PARENT-IDX`, plus the legacy `GET-INPUT-ENTITIES` builder.
4
//!
5
//! Every eval handler here returns a `WasmRuntime(I32)` placeholder —
6
//! all real work happens at codegen time via the wasm import calls in
7
//! the compile_* counterparts.
8

            
9
use crate::ast::{Expr, PairElement, WasmType};
10
use crate::compiler::context::CompileContext;
11
use crate::compiler::emit::FunctionEmitter;
12
use crate::compiler::expr::{LOCAL_TEMP_I32, eval_value};
13
use crate::error::Result;
14
use crate::runtime::SymbolTable;
15

            
16
use super::{arity_check, compile_idx_to_stack, emit_entity_header_offset};
17

            
18
14912
pub(super) fn entity_count(_symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
19
14912
    arity_check("ENTITY-COUNT", args, 0)?;
20
14911
    Ok(Expr::WasmRuntime(WasmType::I32))
21
14912
}
22

            
23
1
pub(super) fn context_type(_symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
24
1
    arity_check("CONTEXT-TYPE", args, 0)?;
25
1
    Ok(Expr::WasmRuntime(WasmType::I32))
26
1
}
27

            
28
1918
pub(super) fn primary_entity_type(_symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
29
1918
    arity_check("PRIMARY-ENTITY-TYPE", args, 0)?;
30
1918
    Ok(Expr::WasmRuntime(WasmType::I32))
31
1918
}
32

            
33
3977
pub(super) fn primary_entity_idx(_symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
34
3977
    arity_check("PRIMARY-ENTITY-IDX", args, 0)?;
35
3977
    Ok(Expr::WasmRuntime(WasmType::I32))
36
3977
}
37

            
38
9373
pub(super) fn entity_type(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
39
9373
    arity_check("ENTITY-TYPE", args, 1)?;
40
9372
    eval_value(symbols, &args[0])?;
41
9372
    Ok(Expr::WasmRuntime(WasmType::I32))
42
9373
}
43

            
44
5254
pub(super) fn entity_parent_idx(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
45
5254
    arity_check("ENTITY-PARENT-IDX", args, 1)?;
46
5254
    eval_value(symbols, &args[0])?;
47
5254
    Ok(Expr::WasmRuntime(WasmType::I32))
48
5254
}
49

            
50
1065
pub(super) fn get_input_entities(_symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
51
1065
    arity_check("GET-INPUT-ENTITIES", args, 0)?;
52
1065
    Ok(Expr::WasmRuntime(WasmType::PairRef(PairElement::I32)))
53
1065
}
54

            
55
6532
pub(super) fn compile_entity_count_to_stack(
56
6532
    ctx: &mut CompileContext,
57
6532
    emit: &mut FunctionEmitter,
58
6532
    _symbols: &mut SymbolTable,
59
6532
    args: &[Expr],
60
6532
) -> Result<WasmType> {
61
6532
    arity_check("ENTITY-COUNT", args, 0)?;
62
6532
    emit.call(ctx.ids.get_input_entities_count()?);
63
6532
    Ok(WasmType::I32)
64
6532
}
65

            
66
71
pub(super) fn compile_context_type_to_stack(
67
71
    ctx: &mut CompileContext,
68
71
    emit: &mut FunctionEmitter,
69
71
    _symbols: &mut SymbolTable,
70
71
    args: &[Expr],
71
71
) -> Result<WasmType> {
72
71
    arity_check("CONTEXT-TYPE", args, 0)?;
73
71
    emit.call(ctx.ids.get_input_offset()?);
74
71
    emit.i32_load8_u(6);
75
71
    Ok(WasmType::I32)
76
71
}
77

            
78
710
pub(super) fn compile_primary_entity_type_to_stack(
79
710
    ctx: &mut CompileContext,
80
710
    emit: &mut FunctionEmitter,
81
710
    _symbols: &mut SymbolTable,
82
710
    args: &[Expr],
83
710
) -> Result<WasmType> {
84
710
    arity_check("PRIMARY-ENTITY-TYPE", args, 0)?;
85
710
    emit.call(ctx.ids.get_input_offset()?);
86
710
    emit.i32_load8_u(7);
87
710
    Ok(WasmType::I32)
88
710
}
89

            
90
1775
pub(super) fn compile_primary_entity_idx_to_stack(
91
1775
    ctx: &mut CompileContext,
92
1775
    emit: &mut FunctionEmitter,
93
1775
    _symbols: &mut SymbolTable,
94
1775
    args: &[Expr],
95
1775
) -> Result<WasmType> {
96
1775
    arity_check("PRIMARY-ENTITY-IDX", args, 0)?;
97
1775
    emit.call(ctx.ids.get_input_offset()?);
98
1775
    emit.i32_load(0x20);
99
1775
    Ok(WasmType::I32)
100
1775
}
101

            
102
2414
pub(super) fn compile_entity_type_to_stack(
103
2414
    ctx: &mut CompileContext,
104
2414
    emit: &mut FunctionEmitter,
105
2414
    symbols: &mut SymbolTable,
106
2414
    args: &[Expr],
107
2414
) -> Result<WasmType> {
108
2414
    arity_check("ENTITY-TYPE", args, 1)?;
109
2414
    compile_idx_to_stack(ctx, emit, symbols, &args[0])?;
110
2414
    emit_entity_header_offset(ctx, emit, LOCAL_TEMP_I32)?;
111
2414
    emit.i32_load8_u(0); // entity_type at offset 0 in header
112
2414
    Ok(WasmType::I32)
113
2414
}
114

            
115
1775
pub(super) fn compile_entity_parent_idx_to_stack(
116
1775
    ctx: &mut CompileContext,
117
1775
    emit: &mut FunctionEmitter,
118
1775
    symbols: &mut SymbolTable,
119
1775
    args: &[Expr],
120
1775
) -> Result<WasmType> {
121
1775
    arity_check("ENTITY-PARENT-IDX", args, 1)?;
122
1775
    compile_idx_to_stack(ctx, emit, symbols, &args[0])?;
123
1775
    emit_entity_header_offset(ctx, emit, LOCAL_TEMP_I32)?;
124
1775
    emit.i32_load(0x14); // parent_idx at offset 0x14 in header
125
1775
    Ok(WasmType::I32)
126
1775
}
127

            
128
568
pub(super) fn compile_get_input_entities_to_stack(
129
568
    ctx: &mut CompileContext,
130
568
    emit: &mut FunctionEmitter,
131
568
) -> Result<WasmType> {
132
    // Builds a `$pair<i32>` list: loop entity_count-1..=0, boxing each
133
    // index via `ref.i31` before pair_new so the values ride the anyref
134
    // car. Same loop as the legacy $cons builder; the difference is the
135
    // single `pair_new` call replacing the bespoke `struct.new cons`.
136
568
    let i_local = ctx.alloc_local(WasmType::I32)?;
137
568
    let result_local = ctx.alloc_local(WasmType::PairRef(PairElement::I32))?;
138
568
    let pair_type = ctx.ids.ty_pair;
139
568
    let pair_new = ctx.ids.pair_new;
140

            
141
    // result = nil
142
568
    emit.ref_null(pair_type);
143
568
    emit.local_set(result_local);
144

            
145
    // i = entity_count - 1
146
568
    emit.call(ctx.ids.get_input_offset()?);
147
568
    emit.i32_load(0x08); // entity_count at GlobalHeader offset 8
148
568
    emit.i32_const(1);
149
568
    emit.i32_sub();
150
568
    emit.local_set(i_local);
151

            
152
568
    emit.block_start();
153
568
    emit.loop_start();
154

            
155
    // if i < 0 → exit
156
568
    emit.local_get(i_local);
157
568
    emit.i32_const(0);
158
568
    emit.i32_lt_s();
159
568
    emit.br_if(1);
160

            
161
    // result = pair_new(ref.i31 i, result)
162
568
    emit.local_get(i_local);
163
568
    emit.ref_i31();
164
568
    emit.local_get(result_local);
165
568
    emit.call(pair_new);
166
568
    emit.local_set(result_local);
167

            
168
    // i = i - 1
169
568
    emit.local_get(i_local);
170
568
    emit.i32_const(1);
171
568
    emit.i32_sub();
172
568
    emit.local_set(i_local);
173

            
174
568
    emit.br(0);
175
568
    emit.block_end();
176
568
    emit.block_end();
177

            
178
568
    emit.local_get(result_local);
179
568
    Ok(WasmType::PairRef(PairElement::I32))
180
568
}