jazz/
function.rs

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    /// Get Object Id's(Used for GC) W.I.P
26    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    /// Call object
60    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}