1use std::fmt::{Debug, Display, Formatter};
2use std::iter::Zip;
3
4use sexprs_data_structures::{
5 AsSymbol, Symbol, Value, ValueIterator,
6};
7use sexprs_util::{try_result, with_caller, admonition, warn};
8use unique_pointer::UniquePointer;
9
10use crate::{runtime_error, BuiltinFunction, Context, Result, Sym};
11
12#[derive(Clone)]
13pub enum Function<'c> {
14 Builtin {
15 name: Symbol<'c>,
16 function: BuiltinFunction,
17 },
18 Defun {
19 name: Symbol<'c>,
20 args: Value<'c>,
21 body: Value<'c>,
22 },
23}
24impl<'c> Function<'c> {
25 pub fn is_builtin(&self) -> bool {
26 match self {
27 Function::Builtin {..} => true,
28 _ => false
29 }
30 }
31 pub fn is_defun(&self) -> bool {
32 match self {
33 Function::Defun {..} => true,
34 _ => false
35 }
36 }
37 pub fn validate_args(
38 &self,
39 name: &Symbol<'c>,
40 expected: &Value<'c>,
41 received: &Value<'c>,
42 ) -> Result<Zip<ValueIterator<'c>, ValueIterator<'c>>> {
43 let expected_length = expected.len();
44 let received_length = received.len();
45 if expected_length != received_length {
46 Err(with_caller!(runtime_error(
47 format!(
48 "{} expected {} args [{:#?}] but received {}: {:#?}",
49 name, expected_length, expected, received_length, received
50 ),
51 None
52 )))
53 } else {
54 Ok(expected
55 .clone()
56 .into_iter()
57 .zip(received))
58 }
59 }
60
61 pub fn bind_args_to_local_context(
62 &self,
63 mut vm: UniquePointer<Context<'c>>,
64 name: &Symbol<'c>,
65 expected: &Value<'c>,
66 received: &Value<'c>,
67 ) -> Result<Vec<(Symbol<'c>, Value<'c>)>> {
68 let mut args = Vec::<(Symbol<'c>, Value<'c>)>::new();
69 for (symbol, value) in try_result!(self.validate_args(name, expected, received))
70 {
71 args.push((symbol.as_symbol(), value.clone()));
72 try_result!(vm
73 .inner_mut()
74 .set_function_local(&symbol.as_symbol(), &Sym::Value(value.clone())));
75 }
76 Ok(args)
77 }
78
79 pub fn call(
80 &self,
81 mut vm: UniquePointer<Context<'c>>,
82 list: Value<'c>,
83 ) -> Result<Value<'c>> {
84 match self {
85 Function::Defun { name, args, body } => {
86 try_result!(self.bind_args_to_local_context(
89 vm.clone(),
90 name,
91 args,
92 &list
93 ));
94
95 let mut value = Value::nil();
96 for (_, val) in body.into_iter().enumerate() {
97 value = try_result!(vm.inner_mut().eval(val));
98 }
99 Ok(value)
100 },
101 Function::Builtin { name, function, .. } => {
102 Ok(try_result!(function(vm, list)))
106 },
107 }
108 }
109}
110
111impl<'c> Display for Function<'c> {
112 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
113 write!(
114 f,
115 "{}",
116 match self {
117 Function::Defun { name, args, body } =>
118 format!("(defun {} {} {})", name, args, body),
119 Function::Builtin { name, function } =>
120 format!("builtin-function {} {:#?}", name, function),
121 }
122 )
123 }
124}
125
126impl<'c> Debug for Function<'c> {
127 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
128 write!(
129 f,
130 "{}",
131 match self {
132 Function::Defun { name, args, body } =>
133 format!("(defun {} {} {})", name, args, body),
134 Function::Builtin { name, function } =>
135 format!("builtin-function {} {:#?}", name, function),
136 }
137 )
138 }
139}