xee_interpreter/interpreter/
program.rs1use crate::context;
2use crate::declaration::Declarations;
3use crate::function;
4use xee_name::Name;
5use xee_xpath_ast::ast::Span;
6
7use super::Runnable;
8
9#[derive(Debug)]
10pub struct Program {
11 span: Span,
12 pub functions: Vec<function::InlineFunction>,
13 pub declarations: Declarations,
14 static_context: context::StaticContext,
15 map_signature: function::Signature,
16 array_signature: function::Signature,
17}
18
19impl Program {
20 pub fn new(static_context: context::StaticContext, span: Span) -> Self {
21 Program {
22 span,
23 functions: Vec::new(),
24 declarations: Declarations::new(),
25 static_context,
26 map_signature: function::Signature::map_signature(),
27 array_signature: function::Signature::array_signature(),
28 }
29 }
30
31 pub fn static_context(&self) -> &context::StaticContext {
32 &self.static_context
33 }
34
35 pub fn dynamic_context_builder(&self) -> context::DynamicContextBuilder {
36 context::DynamicContextBuilder::new(self)
37 }
38
39 pub fn span(&self) -> Span {
40 self.span
41 }
42
43 pub(crate) fn inline_function(
44 &self,
45 function_id: function::InlineFunctionId,
46 ) -> &function::InlineFunction {
47 &self.functions[function_id.0]
48 }
49
50 pub(crate) fn static_function(
51 &self,
52 function_id: function::StaticFunctionId,
53 ) -> &function::StaticFunction {
54 self.static_context.function_by_id(function_id)
55 }
56
57 pub fn function_info<'a, 'b>(
58 &'a self,
59 function: &'b function::Function,
60 ) -> FunctionInfo<'a, 'b> {
61 FunctionInfo::new(function, self)
62 }
63
64 pub fn runnable<'a>(&'a self, dynamic_context: &'a context::DynamicContext) -> Runnable<'a> {
66 Runnable::new(self, dynamic_context)
67 }
68
69 pub fn add_function(
70 &mut self,
71 function: function::InlineFunction,
72 ) -> function::InlineFunctionId {
73 let id = self.functions.len();
74 if id > u16::MAX as usize {
75 panic!("too many functions");
76 }
77 self.functions.push(function);
78
79 function::InlineFunctionId(id)
80 }
81
82 pub(crate) fn get_function(&self, index: usize) -> &function::InlineFunction {
83 &self.functions[index]
84 }
85
86 pub(crate) fn get_function_by_id(
87 &self,
88 id: function::InlineFunctionId,
89 ) -> &function::InlineFunction {
90 self.get_function(id.0)
91 }
92
93 pub(crate) fn main_id(&self) -> function::InlineFunctionId {
94 function::InlineFunctionId(self.functions.len() - 1)
95 }
96}
97
98pub struct FunctionInfo<'a, 'b> {
100 function: &'b function::Function,
101 program: &'a Program,
102}
103
104impl<'a, 'b> FunctionInfo<'a, 'b> {
105 pub(crate) fn new(
106 function: &'b function::Function,
107 program: &'a Program,
108 ) -> FunctionInfo<'a, 'b> {
109 FunctionInfo { function, program }
110 }
111
112 pub fn arity(&self) -> usize {
114 match self.function {
115 function::Function::Inline(data) => self.program.inline_function(data.id).arity(),
116 function::Function::Static(data) => self.program.static_function(data.id).arity(),
117 function::Function::Array(_) => 1,
118 function::Function::Map(_) => 1,
119 }
120 }
121
122 pub fn name(&self) -> Option<Name> {
126 match self.function {
127 function::Function::Static(data) => {
128 let static_function = self.program.static_function(data.id);
129 static_function.name().cloned()
130 }
131 _ => None,
132 }
133 }
134
135 pub fn signature(&self) -> &'a function::Signature {
137 match &self.function {
138 function::Function::Static(data) => {
139 let static_function = self.program.static_function(data.id);
140 static_function.signature()
141 }
142 function::Function::Inline(data) => {
143 let inline_function = self.program.inline_function(data.id);
144 inline_function.signature()
145 }
146 function::Function::Map(_map) => &self.program.map_signature,
147 function::Function::Array(_array) => &self.program.array_signature,
148 }
149 }
150}