tenda_runtime/
function.rs1use std::sync::atomic::{AtomicUsize, Ordering};
2use tenda_common::span::SourceSpan;
3use tenda_parser::ast;
4
5use crate::environment::Environment;
6use crate::runtime::Runtime;
7
8use super::runtime_error::Result;
9use super::value::Value;
10
11static FUNCTION_ID_COUNTER: AtomicUsize = AtomicUsize::new(1);
12
13#[derive(Debug, Clone)]
14pub struct Function {
15 pub id: usize,
16 pub object: FunctionObject,
17 pub metadata: Option<FunctionRuntimeMetadata>,
18}
19
20impl Function {
21 pub fn new(
22 params: Vec<FunctionParam>,
23 captured_env: Environment,
24 body: Box<ast::Stmt>,
25 ) -> Self {
26 let unique_id = FUNCTION_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
27
28 Function {
29 id: unique_id,
30 object: FunctionObject::new(params, Box::new(captured_env), body),
31 metadata: None,
32 }
33 }
34
35 pub fn new_builtin(params: Vec<FunctionParam>, func_ptr: BuiltinFunctionPointer) -> Self {
36 let unique_id = FUNCTION_ID_COUNTER.fetch_add(1, Ordering::SeqCst);
37
38 Function {
39 id: unique_id,
40 object: FunctionObject::new_builtin(params, Box::default(), func_ptr),
41 metadata: None,
42 }
43 }
44
45 pub fn get_params(&self) -> Vec<FunctionParam> {
46 match &self.object {
47 FunctionObject::UserDefined { params, .. } => params.clone(),
48 FunctionObject::Builtin { params, .. } => params.clone(),
49 }
50 }
51
52 pub fn get_env(&self) -> &Environment {
53 match &self.object {
54 FunctionObject::UserDefined { env, .. } => env,
55 FunctionObject::Builtin { env, .. } => env,
56 }
57 }
58
59 pub fn get_env_mut(&mut self) -> &mut Box<Environment> {
60 match &mut self.object {
61 FunctionObject::UserDefined { env, .. } => env,
62 FunctionObject::Builtin { env, .. } => env,
63 }
64 }
65
66 pub fn set_metadata(&mut self, metadata: FunctionRuntimeMetadata) {
67 self.metadata = Some(metadata);
68 }
69}
70
71impl PartialEq for Function {
72 fn eq(&self, other: &Self) -> bool {
73 self.id == other.id
74 }
75}
76
77#[derive(Debug, Clone)]
78pub struct FunctionParam {
79 pub name: String,
80 pub is_captured: bool,
81}
82
83impl From<ast::FunctionParam> for FunctionParam {
84 fn from(param: ast::FunctionParam) -> Self {
85 FunctionParam {
86 name: param.name,
87 is_captured: param.captured,
88 }
89 }
90}
91
92type BuiltinFunctionPointer = fn(
93 params: Vec<(FunctionParam, Value)>,
94 runtime: &mut Runtime,
95 context: Box<Environment>,
96) -> Result<Value>;
97
98#[derive(Debug, Clone)]
99pub enum FunctionObject {
100 UserDefined {
101 params: Vec<FunctionParam>,
102 env: Box<Environment>,
103 body: Box<ast::Stmt>,
104 },
105 Builtin {
106 params: Vec<FunctionParam>,
107 env: Box<Environment>,
108 func_ptr: BuiltinFunctionPointer,
109 },
110}
111
112impl FunctionObject {
113 pub fn new(
114 params: Vec<FunctionParam>,
115 context: Box<Environment>,
116 body: Box<ast::Stmt>,
117 ) -> Self {
118 FunctionObject::UserDefined {
119 params,
120 body,
121 env: context,
122 }
123 }
124
125 pub fn new_builtin(
126 params: Vec<FunctionParam>,
127 env: Box<Environment>,
128 func_ptr: BuiltinFunctionPointer,
129 ) -> Self {
130 FunctionObject::Builtin {
131 params,
132 env,
133 func_ptr,
134 }
135 }
136}
137
138#[derive(Debug, Clone)]
139pub struct FunctionRuntimeMetadata {
140 span: Option<Box<SourceSpan>>,
141 name: Option<String>,
142}
143
144impl FunctionRuntimeMetadata {
145 pub fn new(span: Option<SourceSpan>, name: Option<String>) -> Self {
146 FunctionRuntimeMetadata {
147 span: span.map(Box::new),
148 name,
149 }
150 }
151}
152
153impl FunctionRuntimeMetadata {
154 pub fn get_span(&self) -> Option<Box<SourceSpan>> {
155 self.span.clone()
156 }
157
158 pub fn get_name(&self) -> Option<String> {
159 self.name.clone()
160 }
161}
162
163#[macro_export]
164macro_rules! params {
165 ($($kind:expr),*) => {
166 {
167 use $crate::FunctionParam;
168 vec![$($kind.to_string()),*].into_iter().map(|name| FunctionParam {
169 name,
170 is_captured: false,
171 }).collect()
172 }
173 };
174}