rune/runtime/
protocol_caller.rs
1use crate::runtime::vm::{CallResult, CallResultOnly, Isolated};
2use crate::runtime::{
3 DynArgs, Protocol, Stack, UnitFn, Value, Vm, VmError, VmErrorKind, VmExecution, VmResult,
4};
5use crate::Hash;
6
7pub(crate) trait ProtocolCaller: 'static {
9 fn call_protocol_fn(
11 &mut self,
12 protocol: &'static Protocol,
13 target: Value,
14 args: &mut dyn DynArgs,
15 ) -> VmResult<Value> {
16 match vm_try!(self.try_call_protocol_fn(protocol, target, args)) {
17 CallResultOnly::Ok(value) => VmResult::Ok(value),
18 CallResultOnly::Unsupported(value) => {
19 VmResult::err(VmErrorKind::MissingProtocolFunction {
20 protocol,
21 instance: value.type_info(),
22 })
23 }
24 }
25 }
26
27 fn try_call_protocol_fn(
29 &mut self,
30 protocol: &'static Protocol,
31 target: Value,
32 args: &mut dyn DynArgs,
33 ) -> VmResult<CallResultOnly<Value>>;
34}
35
36pub(crate) struct EnvProtocolCaller;
40
41impl ProtocolCaller for EnvProtocolCaller {
42 fn try_call_protocol_fn(
43 &mut self,
44 protocol: &Protocol,
45 target: Value,
46 args: &mut dyn DynArgs,
47 ) -> VmResult<CallResultOnly<Value>> {
48 fn check_args(args: usize, expected: usize) -> Result<(), VmError> {
50 if args != expected {
51 return Err(VmError::from(VmErrorKind::BadArgumentCount {
52 actual: args,
53 expected,
54 }));
55 }
56
57 Ok(())
58 }
59
60 crate::runtime::env::shared(|context, unit| {
61 let count = args.count() + 1;
62 let hash = Hash::associated_function(target.type_hash(), protocol.hash);
63
64 if let Some(UnitFn::Offset {
65 offset,
66 args: expected,
67 call,
68 ..
69 }) = unit.function(&hash)
70 {
71 vm_try!(check_args(count, *expected));
72
73 let mut stack = vm_try!(Stack::with_capacity(count));
74 vm_try!(stack.push(target));
75 vm_try!(args.push_to_stack(&mut stack));
76 let mut vm = Vm::with_stack(context.clone(), unit.clone(), stack);
77 vm.set_ip(*offset);
78 return VmResult::Ok(CallResultOnly::Ok(vm_try!(call.call_with_vm(vm))));
79 }
80
81 if let Some(handler) = context.function(&hash) {
82 let mut stack = vm_try!(Stack::with_capacity(count));
83 let addr = stack.addr();
84 vm_try!(stack.push(target));
85 vm_try!(args.push_to_stack(&mut stack));
86 vm_try!(handler(&mut stack, addr, count, addr.output()));
87 let value = stack.at(addr).clone();
88 return VmResult::Ok(CallResultOnly::Ok(value));
89 }
90
91 VmResult::Ok(CallResultOnly::Unsupported(target))
92 })
93 }
94}
95
96impl ProtocolCaller for Vm {
97 fn try_call_protocol_fn(
98 &mut self,
99 protocol: &'static Protocol,
100 target: Value,
101 args: &mut dyn DynArgs,
102 ) -> VmResult<CallResultOnly<Value>> {
103 let addr = self.stack().addr();
104 vm_try!(self.stack_mut().push(()));
105
106 match vm_try!(self.call_instance_fn(
107 Isolated::Isolated,
108 target,
109 protocol,
110 args,
111 addr.output()
112 )) {
113 CallResult::Unsupported(value) => VmResult::Ok(CallResultOnly::Unsupported(value)),
114 CallResult::Ok(()) => {
115 let value = self.stack().at(addr).clone();
116 self.stack_mut().truncate(addr);
117 VmResult::Ok(CallResultOnly::Ok(value))
118 }
119 CallResult::Frame => {
120 let mut execution = VmExecution::new(self);
121 let value = vm_try!(execution.complete());
122 execution.vm_mut().stack_mut().truncate(addr);
123 VmResult::Ok(CallResultOnly::Ok(value))
124 }
125 }
126 }
127}