summaryrefslogtreecommitdiff
path: root/src/runtime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime.rs')
-rw-r--r--src/runtime.rs61
1 files changed, 42 insertions, 19 deletions
diff --git a/src/runtime.rs b/src/runtime.rs
index 97de85a..56b565e 100644
--- a/src/runtime.rs
+++ b/src/runtime.rs
@@ -37,6 +37,11 @@ pub enum OpCode {
/// stack:
Return = 0x08,
+ /// Invoke a function
+ /// operands:
+ /// stack: [arguments..., function id] -> [return value?]
+ InvokeDynamic = 0x09,
+
/// Push a typed Ion value onto the stack.
/// operands: T and L
/// length
@@ -352,6 +357,29 @@ fn execute_frame(mut frame: StackFrame) {
});
}
+#[inline]
+async fn invoke_function(frame: &mut StackFrame, function_id: usize) {
+ let function = frame.runtime.0.functions.get(&function_id)
+ .expect("Undefined function");
+ let mut args = Vec::with_capacity(function.arguments as usize);
+ for _ in 0..function.arguments {
+ args.push(frame.stack.pop_value());
+ }
+ let mut rx = frame.runtime.invoke(function_id, args);
+ let mut previous_ret = None;
+ while let Some(ret) = rx.recv().await {
+ if let Some(previous_ret) = previous_ret.take() {
+ let mut branch = frame.clone();
+ branch.stack.push_value(&previous_ret);
+ execute_frame(branch);
+ }
+ previous_ret = Some(ret);
+ }
+ if let Some(ret) = previous_ret.take() {
+ frame.stack.push_value(&ret);
+ }
+}
+
async fn execute(frame: &mut StackFrame) -> ExecutionState {
if frame.eof() {
return ExecutionState::Halt;
@@ -393,25 +421,11 @@ async fn execute(frame: &mut StackFrame) -> ExecutionState {
},
0x05 => { // OpType::Invoke
let function_id = frame.next_varuint();
- let function = frame.runtime.0.functions.get(&function_id)
- .expect("Undefined function");
- let mut args = Vec::with_capacity(function.arguments as usize);
- for _ in 0..function.arguments {
- args.push(frame.stack.pop_value());
- }
- let mut rx = frame.runtime.invoke(function_id, args);
- let mut previous_ret = None;
- while let Some(ret) = rx.recv().await {
- if let Some(previous_ret) = previous_ret.take() {
- let mut branch = frame.clone();
- branch.stack.push_value(&previous_ret);
- execute_frame(branch);
- }
- previous_ret = Some(ret);
- }
- if let Some(ret) = previous_ret.take() {
- frame.stack.push_value(&ret);
- }
+ invoke_function(frame, function_id).await;
+ },
+ 0x09 => { // OpType::InvokeDynamic
+ let function_id = frame.stack.pop_symbol();
+ invoke_function(frame, function_id).await;
},
0x06 => { // OpType::InvokeGenerator
let function_id = frame.next_varuint();
@@ -785,6 +799,15 @@ impl Stack {
value
}
+ pub fn pop_symbol(&mut self) -> usize {
+ let mut it = IonReader::new(self.0.iter().copied().rev(), 0);
+ let value = it.next_symbol_id();
+ let offset = it.offset();
+ self.0.truncate(self.0.len() - offset);
+ value
+ }
+
+
#[inline]
pub fn push_byte(&mut self, value: u8) {
self.0.push(value);