Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions vendor/xslt-tests/filters
Original file line number Diff line number Diff line change
Expand Up @@ -1070,7 +1070,6 @@ bug-6201
bug-6301
bug-6401
= built-in-templates
built-in-templates-0101
built-in-templates-0201
built-in-templates-0202
built-in-templates-0301
Expand Down Expand Up @@ -1303,9 +1302,7 @@ copy-0103
copy-0104
copy-0105
copy-0501
copy-0602
copy-0603
copy-0604
copy-0606
copy-0609
copy-0610
Expand Down Expand Up @@ -10364,7 +10361,6 @@ string-120
string-121
string-125
string-131
string-133
string-134
string-135
string-136
Expand Down
3 changes: 3 additions & 0 deletions xee-interpreter/src/function/inline_function.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use xee_schema_type::Xs;
use xee_xpath_ast::Pattern;
use xee_xpath_type::ast::SequenceType;

use crate::sequence;
use crate::span::SourceSpan;
use crate::xml;

use super::signature::Signature;
use super::InlineFunctionId;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CastType {
Expand All @@ -32,6 +34,7 @@ pub struct InlineFunction {
pub cast_types: Vec<CastType>,
pub sequence_types: Vec<SequenceType>,
pub closure_names: Vec<Name>,
pub patterns: Vec<Pattern<InlineFunctionId>>,
// the compiled code, and the spans of each instruction
pub chunk: Vec<u8>,
pub spans: Vec<SourceSpan>,
Expand Down
25 changes: 16 additions & 9 deletions xee-interpreter/src/interpreter/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub enum Instruction {
Var(u16),
Set(u16),
ClosureVar(u16),
ClosureRecursiveSelf,
Comma,
CurlyArray,
SquareArray,
Expand Down Expand Up @@ -77,7 +78,7 @@ pub enum Instruction {
XmlAppend,
CopyShallow,
CopyDeep,
ApplyTemplates(u16),
MatchPattern(u16),
PrintTop,
PrintStack,
}
Expand All @@ -99,6 +100,7 @@ pub(crate) enum EncodedInstruction {
Var,
Set,
ClosureVar,
ClosureRecursiveSelf,
Comma,
CurlyArray,
SquareArray,
Expand Down Expand Up @@ -154,7 +156,7 @@ pub(crate) enum EncodedInstruction {
XmlComment,
XmlProcessingInstruction,
XmlAppend,
ApplyTemplates,
MatchPattern,
CopyShallow,
CopyDeep,
PrintTop,
Expand Down Expand Up @@ -198,6 +200,7 @@ pub(crate) fn decode_instruction(bytes: &[u8]) -> (Instruction, usize) {
let variable = u16::from_le_bytes([bytes[1], bytes[2]]);
(Instruction::ClosureVar(variable), 3)
}
EncodedInstruction::ClosureRecursiveSelf => (Instruction::ClosureRecursiveSelf, 1),
EncodedInstruction::Comma => (Instruction::Comma, 1),
EncodedInstruction::CurlyArray => (Instruction::CurlyArray, 1),
EncodedInstruction::SquareArray => (Instruction::SquareArray, 1),
Expand Down Expand Up @@ -285,9 +288,9 @@ pub(crate) fn decode_instruction(bytes: &[u8]) -> (Instruction, usize) {
EncodedInstruction::XmlAppend => (Instruction::XmlAppend, 1),
EncodedInstruction::CopyShallow => (Instruction::CopyShallow, 1),
EncodedInstruction::CopyDeep => (Instruction::CopyDeep, 1),
EncodedInstruction::ApplyTemplates => {
let mode_id = u16::from_le_bytes([bytes[1], bytes[2]]);
(Instruction::ApplyTemplates(mode_id), 3)
EncodedInstruction::MatchPattern => {
let pattern_id = u16::from_le_bytes([bytes[1], bytes[2]]);
(Instruction::MatchPattern(pattern_id), 3)
}
EncodedInstruction::PrintTop => (Instruction::PrintTop, 1),
EncodedInstruction::PrintStack => (Instruction::PrintStack, 1),
Expand Down Expand Up @@ -340,6 +343,9 @@ pub fn encode_instruction(instruction: Instruction, bytes: &mut Vec<u8>) {
bytes.push(EncodedInstruction::ClosureVar.to_u8().unwrap());
bytes.extend_from_slice(&variable.to_le_bytes());
}
Instruction::ClosureRecursiveSelf => {
bytes.push(EncodedInstruction::ClosureRecursiveSelf.to_u8().unwrap())
}
Instruction::Comma => bytes.push(EncodedInstruction::Comma.to_u8().unwrap()),
Instruction::CurlyArray => bytes.push(EncodedInstruction::CurlyArray.to_u8().unwrap()),
Instruction::SquareArray => bytes.push(EncodedInstruction::SquareArray.to_u8().unwrap()),
Expand Down Expand Up @@ -437,9 +443,9 @@ pub fn encode_instruction(instruction: Instruction, bytes: &mut Vec<u8>) {
Instruction::XmlAppend => bytes.push(EncodedInstruction::XmlAppend.to_u8().unwrap()),
Instruction::CopyShallow => bytes.push(EncodedInstruction::CopyShallow.to_u8().unwrap()),
Instruction::CopyDeep => bytes.push(EncodedInstruction::CopyDeep.to_u8().unwrap()),
Instruction::ApplyTemplates(mode_id) => {
bytes.push(EncodedInstruction::ApplyTemplates.to_u8().unwrap());
bytes.extend_from_slice(&mode_id.to_le_bytes());
Instruction::MatchPattern(pattern_id) => {
bytes.push(EncodedInstruction::MatchPattern.to_u8().unwrap());
bytes.extend_from_slice(&pattern_id.to_le_bytes());
}
Instruction::PrintTop => bytes.push(EncodedInstruction::PrintTop.to_u8().unwrap()),
Instruction::PrintStack => bytes.push(EncodedInstruction::PrintStack.to_u8().unwrap()),
Expand Down Expand Up @@ -468,6 +474,7 @@ pub fn instruction_size(instruction: &Instruction) -> usize {
| Instruction::CurlyArray
| Instruction::SquareArray
| Instruction::CurlyMap
| Instruction::ClosureRecursiveSelf
| Instruction::Eq
| Instruction::Ne
| Instruction::Lt
Expand Down Expand Up @@ -529,7 +536,7 @@ pub fn instruction_size(instruction: &Instruction) -> usize {
| Instruction::Treat(_)
| Instruction::ReturnConvert(_)
| Instruction::JumpIfFalse(_) => 3,
Instruction::ApplyTemplates(_) => 3,
Instruction::MatchPattern(_) => 3,
}
}

Expand Down
76 changes: 12 additions & 64 deletions xee-interpreter/src/interpreter/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ use crate::atomic::{
op_add, op_div, op_idiv, op_mod, op_multiply, op_subtract, OpEq, OpGe, OpGt, OpLe, OpLt, OpNe,
};
use crate::context::DynamicContext;
use crate::error;
use crate::function;
use crate::pattern::PredicateMatcher;
use crate::sequence;
use crate::span::SourceSpan;
use crate::stack;
use crate::xml;
use crate::{error, pattern};

use super::instruction::{read_i16, read_instruction, read_u16, read_u8, EncodedInstruction};
use super::runnable::Runnable;
Expand Down Expand Up @@ -176,6 +176,9 @@ impl<'a> Interpreter<'a> {
let index = self.read_u16();
self.state.push_closure_var(index as usize)?;
}
EncodedInstruction::ClosureRecursiveSelf => {
self.state.push_closure_recursive()?;
}
EncodedInstruction::Comma => {
let b = self.state.pop()?;
let a = self.state.pop()?;
Expand Down Expand Up @@ -630,12 +633,13 @@ impl<'a> Interpreter<'a> {
}
self.state.push(new_sequence);
}
EncodedInstruction::ApplyTemplates => {
let value = self.state.pop()?;
let mode_id = self.read_u16();
let mode = pattern::ModeId::new(mode_id as usize);
let value = self.apply_templates_sequence(mode, value)?;
self.state.push(value);
EncodedInstruction::MatchPattern => {
let pattern_id = self.read_u16();
let items = self.state.top()?;
let item = items.one()?;
let pattern = &(self.current_inline_function().patterns[pattern_id as usize]);
let result = self.matches(pattern, &item);
self.state.push(sequence::Item::Atomic(result.into()));
}
EncodedInstruction::PrintTop => {
let top = self.state.top()?;
Expand Down Expand Up @@ -694,7 +698,7 @@ impl<'a> Interpreter<'a> {
Ok(function::StaticFunctionData::new(static_function_id, closure_vars).into())
}

pub(crate) fn current_inline_function(&self) -> &function::InlineFunction {
pub(crate) fn current_inline_function(&self) -> &'a function::InlineFunction {
self.runnable
.program()
.inline_function(self.state.frame().function())
Expand Down Expand Up @@ -1183,62 +1187,6 @@ impl<'a> Interpreter<'a> {
}
}

fn apply_templates_sequence(
&mut self,
mode: pattern::ModeId,
sequence: sequence::Sequence,
) -> error::Result<sequence::Sequence> {
let mut r: Vec<sequence::Item> = Vec::new();
let size: IBig = sequence.len().into();

for (i, item) in sequence.iter().enumerate() {
let sequence = self.apply_templates_item(mode, item, i, size.clone())?;
if let Some(sequence) = sequence {
for item in sequence.iter() {
r.push(item.clone());
}
}
}
Ok(r.into())
}

fn apply_templates_item(
&mut self,
mode: pattern::ModeId,
item: sequence::Item,
position: usize,
size: IBig,
) -> error::Result<Option<sequence::Sequence>> {
let function_id = self.lookup_pattern(mode, &item);

if let Some(function_id) = function_id {
let position: IBig = (position + 1).into();
let arguments: Vec<sequence::Sequence> = vec![
item.into(),
atomic::Atomic::from(position).into(),
atomic::Atomic::from(size.clone()).into(),
];
let function = function::InlineFunctionData::new(function_id, Vec::new()).into();
self.call_function_with_arguments(&function, &arguments)
.map(Some)
} else {
Ok(None)
}
}

pub(crate) fn lookup_pattern(
&mut self,
mode: pattern::ModeId,
item: &sequence::Item,
) -> Option<function::InlineFunctionId> {
self.runnable
.program()
.declarations
.mode_lookup
.lookup(mode, |pattern| self.matches(pattern, item))
.copied()
}

// The interpreter can return an error for any byte code, in any level of
// nesting in the function. When this happens the interpreter stops with
// the error code. We here wrap it in a SpannedError using the current
Expand Down
3 changes: 0 additions & 3 deletions xee-interpreter/src/interpreter/program.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::context;
use crate::declaration::Declarations;
use crate::function;
use xee_name::Name;
use xee_xpath_ast::ast::Span;
Expand All @@ -10,7 +9,6 @@ use super::Runnable;
pub struct Program {
span: Span,
pub functions: Vec<function::InlineFunction>,
pub declarations: Declarations,
static_context: context::StaticContext,
map_signature: function::Signature,
array_signature: function::Signature,
Expand All @@ -21,7 +19,6 @@ impl Program {
Program {
span,
functions: Vec::new(),
declarations: Declarations::new(),
static_context,
map_signature: function::Signature::map_signature(),
array_signature: function::Signature::array_signature(),
Expand Down
7 changes: 7 additions & 0 deletions xee-interpreter/src/interpreter/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ impl<'a> State<'a> {
Ok(())
}

pub(crate) fn push_closure_recursive(&mut self) -> error::Result<()> {
let function = self.function()?;
let item: sequence::Item = function.into();
self.stack.push(stack::Value::Sequence(item.into()));
Ok(())
}

pub(crate) fn set_var(&mut self, index: usize) {
let base = self.frame().base;
self.stack[base + index] = self.stack.pop().unwrap();
Expand Down
21 changes: 17 additions & 4 deletions xee-ir/src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use xee_xpath_ast::ast;
use xee_interpreter::function::InlineFunctionId;
use xee_xpath_ast::{ast, Pattern};

use xee_interpreter::interpreter::instruction::{
encode_instruction, instruction_size, Instruction,
Expand Down Expand Up @@ -31,6 +32,7 @@ pub struct FunctionBuilder<'a> {
cast_types: Vec<function::CastType>,
sequence_types: Vec<ast::SequenceType>,
closure_names: Vec<ir::Name>,
patterns: Vec<Pattern<InlineFunctionId>>,
}

impl<'a> FunctionBuilder<'a> {
Expand All @@ -44,6 +46,7 @@ impl<'a> FunctionBuilder<'a> {
cast_types: Vec::new(),
sequence_types: Vec::new(),
closure_names: Vec::new(),
patterns: Vec::new(),
}
}

Expand Down Expand Up @@ -80,6 +83,15 @@ impl<'a> FunctionBuilder<'a> {
index
}

pub(crate) fn add_pattern(&mut self, pattern: Pattern<InlineFunctionId>) -> usize {
let index = self.patterns.len();
self.patterns.push(pattern.clone());
if index > (u16::MAX as usize) {
panic!("too many pattern names");
}
index
}

pub(crate) fn add_step(&mut self, step: xml::Step) -> usize {
let step_id = self.steps.len();
self.steps.push(step);
Expand Down Expand Up @@ -164,10 +176,10 @@ impl<'a> FunctionBuilder<'a> {
pub(crate) fn finish(
mut self,
name: String,
function_definition: &ir::FunctionDefinition,
signature: function::Signature,
span: span::SourceSpan,
) -> function::InlineFunction {
if let Some(return_type) = &function_definition.return_type {
if let Some(return_type) = signature.return_type() {
let sequence_type_id = self.add_sequence_type(return_type.clone());
if sequence_type_id > (u16::MAX as usize) {
panic!("too many sequence types");
Expand All @@ -177,14 +189,15 @@ impl<'a> FunctionBuilder<'a> {
self.emit(Instruction::Return, span);
function::InlineFunction {
name,
signature: function_definition.signature(),
signature,
chunk: self.compiled,
spans: self.spans,
closure_names: self.closure_names,
constants: self.constants,
steps: self.steps,
cast_types: self.cast_types,
sequence_types: self.sequence_types,
patterns: self.patterns,
}
}

Expand Down
Loading
Loading