1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::{any::Any, cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};

use crate::{
	data::Data,
	scope::{
		function::{CallScope, Function},
		Scope, ScopeRef,
	},
};

pub mod collections;
pub mod runtime;

pub struct Module {
	functions: HashMap<String, Rc<dyn Fn(Vec<Data>, Option<Function>, ScopeRef) -> Data>>,
	submodules: HashMap<String, Rc<RefCell<Module>>>,
}

impl Module {
	pub fn new(constructor: fn(&mut Module)) -> Self {
		let mut module = Module {
			functions: HashMap::new(),
			submodules: HashMap::new(),
		};
		constructor(&mut module);
		module
	}

	pub fn function<F>(&mut self, name: &str, function: F) -> &mut Self
	where
		F: Fn(Vec<Data>, Option<Function>, ScopeRef) -> Data + 'static,
	{
		self.functions.insert(String::from(name), Rc::new(function));
		self
	}

	pub fn submodule<F>(&mut self, name: &str, constructor: F) -> &mut Self
	where
		F: FnOnce(&mut Module),
	{
		let mut module = Module {
			functions: HashMap::new(),
			submodules: HashMap::new(),
		};
		constructor(&mut module);
		self.submodules
			.insert(String::from(name), Rc::new(RefCell::new(module)));
		self
	}
}

impl Scope for Module {
	fn has_function(&self, name: &str) -> bool {
		self.functions.contains_key(name) || self.submodules.contains_key(name)
	}

	fn get_function(&self, name: &str) -> Option<Function> {
		self.functions
			.get(name)
			.map(|x| Function::BuiltIn {
				callback: Rc::clone(x),
			})
			.or_else(|| {
				self.submodules.get(name).map(|x: &Rc<RefCell<Module>>| {
					Function::Variable {
						value: Data::Scope(Rc::clone(x) as ScopeRef),
						constant: true,
						name: String::new(),
					}
				})
			})
	}

	fn set_function(&mut self, _name: &str, _function: Function) {}
	fn delete_function(&mut self, _name: &str) {}
	fn set_return_value(&mut self, _value: Data) {
		panic!("Cannot return from module.")
	}

	fn get_call_scope(&self) -> Option<Rc<RefCell<CallScope>>> {
		None
	}

	fn get_function_list(&self) -> HashMap<String, Function> {
		let mut map = HashMap::new();
		for (k, fun) in &self.functions {
			map.insert(
				k.clone(),
				Function::BuiltIn {
					callback: Rc::clone(fun),
				},
			);
		}
		map
	}

	fn as_any(&self) -> &dyn Any {
		self
	}
	fn as_mut(&mut self) -> &mut dyn Any {
		self
	}
}

impl Debug for Module {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		f.debug_struct("Module")
			.field("functions", &self.functions.keys())
			.field("submodules", &self.submodules)
			.finish()
	}
}