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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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