Add deep access

Signed-off-by: Marcel Müller <neikos@neikos.email>
This commit is contained in:
Marcel Müller 2026-03-15 14:31:46 +01:00
parent 4f770c1f24
commit ffd9baf90f
9 changed files with 669 additions and 5 deletions

View file

@ -108,6 +108,20 @@ pub enum Instruction {
args: Vec<VariableSlot>,
slot: VariableSlot,
},
LoadFromSlotToSlot {
from_slot: VariableSlot,
to_slot: VariableSlot,
},
JumpIfUndefined {
slot: VariableSlot,
jump: LabelSlot,
},
IndexSlotToSlot {
name: NomoInput,
from_slot: VariableSlot,
to_slot: VariableSlot,
fail_on_not_found: bool,
},
}
#[derive(Debug, Clone)]
@ -452,6 +466,63 @@ fn emit_expr_load(
fail_on_not_found: false,
});
}
TemplateAstExpr::AccessOperation { op, lhs, rhs } => {
assert_eq!(
op,
&TokenOperator::Dot,
"Only dot can be used to access variables, this is a bug"
);
fn inner_access_op(
eval: &mut Vec<Instruction>,
end_label: LabelSlot,
current_slot: VariableSlot,
next: &TemplateAstExpr<'_>,
) {
match next {
TemplateAstExpr::ConditionalAccess(template_token)
| TemplateAstExpr::VariableAccess(template_token) => {
eval.push(Instruction::IndexSlotToSlot {
name: template_token.source().clone(),
from_slot: current_slot,
to_slot: current_slot,
fail_on_not_found: matches!(
next,
TemplateAstExpr::VariableAccess { .. }
),
});
eval.push(Instruction::JumpIfUndefined {
slot: current_slot,
jump: end_label,
});
}
TemplateAstExpr::AccessOperation { op, lhs, rhs } => {
assert_eq!(
op,
&TokenOperator::Dot,
"Only dot can be used to access variables, this is a bug"
);
inner_access_op(eval, end_label, current_slot, lhs);
inner_access_op(eval, end_label, current_slot, rhs);
}
_ => unreachable!(),
}
}
let end_label = machine.reserve_label();
let start_slot = machine.reserve_slot();
emit_expr_load(machine, eval, start_slot, lhs);
eval.push(Instruction::JumpIfUndefined {
slot: start_slot,
jump: end_label,
});
inner_access_op(eval, end_label, start_slot, rhs);
machine.assign_label(end_label, eval.len());
eval.push(Instruction::LoadFromSlotToSlot {
from_slot: start_slot,
to_slot: emit_slot,
});
}
TemplateAstExpr::Literal { source, value } => {
eval.push(Instruction::LoadLiteralToSlot {
source: source.clone(),
@ -492,7 +563,6 @@ fn emit_expr_load(
}
TemplateAstExpr::ConditionalChain { .. } => todo!(),
TemplateAstExpr::ElseConditional { .. } => todo!(),
TemplateAstExpr::AccessOperation { .. } => todo!(),
TemplateAstExpr::EndBlock => todo!(),
TemplateAstExpr::Block { .. } => todo!(),
TemplateAstExpr::ForChain { .. } => todo!(),