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
17515
pub(super) fn entity_count(_symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
19
17515
    arity_check("ENTITY-COUNT", args, 0)?;
20
17514
    Ok(Expr::WasmRuntime(WasmType::I32))
21
17515
}
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
2242
pub(super) fn primary_entity_type(_symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
29
2242
    arity_check("PRIMARY-ENTITY-TYPE", args, 0)?;
30
2242
    Ok(Expr::WasmRuntime(WasmType::I32))
31
2242
}
32

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

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

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

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

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

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

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

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

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

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

            
128
664
pub(super) fn compile_get_input_entities_to_stack(
129
664
    ctx: &mut CompileContext,
130
664
    emit: &mut FunctionEmitter,
131
664
) -> 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
664
    let i_local = ctx.alloc_local(WasmType::I32)?;
137
664
    let result_local = ctx.alloc_local(WasmType::PairRef(PairElement::I32))?;
138
664
    let pair_type = ctx.ids.ty_pair;
139
664
    let pair_new = ctx.ids.pair_new;
140

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

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

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

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

            
161
    // result = pair_new(box_index i, result)
162
664
    emit.local_get(i_local);
163
664
    emit.call(ctx.ids.box_index);
164
664
    emit.local_get(result_local);
165
664
    emit.call(pair_new);
166
664
    emit.local_set(result_local);
167

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

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

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