1use crate::{machine::Machine, object::Object, opcodes::*, value::Value};
2use std::any::Any;
3
4#[derive(Debug)]
5pub enum Function
6{
7 Virtual(VirtualFunction),
8 Native(NativeFunction),
9}
10
11impl crate::object::ObjectAddon for Function {}
12
13impl Object for Function
14{
15 fn as_any(&self) -> &dyn Any
16 {
17 self as &dyn Any
18 }
19
20 fn as_any_mut(&mut self) -> &mut dyn Any
21 {
22 self as &mut dyn Any
23 }
24
25 fn get_children(&self) -> Vec<usize>
27 {
28 vec![]
29 }
30
31 fn load_at(&self, m: &mut Machine, _args: Vec<Value>, dest: usize)
32 {
33 let _this = _args[0];
34 let val = if let Value::Object(id) = &_args[1] {
35 m.pool.get(*id)
36 } else {
37 panic!("Exptected object")
38 };
39
40 let fname: &str = &val.to_string(m);
41
42 match fname {
43 "disassemble" => {
44 let code = if let Function::Virtual(vf) = self {
45 vf.code.toString()
46 } else {
47 "<native function>".to_string()
48 };
49 let obj = m.pool.allocate(Box::new(code));
50 let code = vec![Instruction::LoadObject(1, obj), Instruction::Ret(1)];
51 let func = Function::from(code);
52 let obj = m.pool.allocate(Box::new(func));
53 m.set(dest, Value::Object(obj));
54 }
55 f => panic!("Unknown field `{}`", f),
56 }
57 }
58
59 fn call(&self, m: &mut Machine, args: Vec<Value>, c_index: u8) -> Value
61 {
62 if c_index == 0 {
63 let ret = match self {
64 Function::Virtual(ref vf) => {
65 let func = vf.clone();
66
67 for i in 0..args.len() {
68 m.last_frame_mut().stack[i] = args[i];
69 }
70
71 m.run_code(func.code)
72 }
73
74 Function::Native(nv) => nv.invoke(m, args),
75 };
76 return ret;
77 } else {
78 panic!("Function expect CALL idnex,found `{}`", c_index);
79 }
80 }
81}
82
83#[derive(Clone, Debug)]
84pub struct VirtualFunction
85{
86 pub code: Vec<Instruction>,
87 pub argc: usize,
88}
89
90impl Function
91{
92 pub fn from_instructions(code: Vec<Instruction>, args: usize) -> Function
93 {
94 Function::Virtual(VirtualFunction {
95 code: code,
96 argc: args,
97 })
98 }
99
100 pub fn from_native(f: NativeFunction) -> Function
101 {
102 Function::Native(f)
103 }
104}
105
106impl From<Vec<Instruction>> for Function
107{
108 fn from(f: Vec<Instruction>) -> Function
109 {
110 Function::Virtual(VirtualFunction { code: f, argc: 0 })
111 }
112}
113
114pub struct NativeFunction(Box<dyn Fn(&mut Machine, Vec<Value>) -> Value + Send>);
115
116impl NativeFunction
117{
118 pub fn invoke(&self, m: &mut Machine, args: Vec<Value>) -> Value
119 {
120 self.0(m, args)
121 }
122}
123
124use std::fmt;
125
126impl fmt::Debug for NativeFunction
127{
128 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
129 {
130 write!(f, "<native function>")
131 }
132}