1#![macro_use]
2
3use crate::{
4 ast::Ast,
5 ast_walk::{walk, LazyWalkReses, WalkRule},
6 form::Form,
7 name::*,
8 util::assoc::Assoc,
9 walk_mode::{NegativeWalkMode, WalkMode},
10};
11use num::bigint::BigInt;
12use std::{self, rc::Rc};
13
14#[derive(Debug, Clone, PartialEq)]
17pub enum Value {
18 Int(BigInt),
19 Sequence(Vec<Rc<Value>>), Function(Rc<Closure>), BuiltInFunction(BIF),
22 AbstractSyntax(Ast),
23 Struct(Assoc<Name, Value>),
24 Enum(Name, Vec<Value>),
25 Text(String),
30 Cell(Rc<std::cell::RefCell<Value>>),
31 ParseContext(Box<crate::earley::ParseContext>),
34}
35
36pub use self::Value::*;
37
38#[derive(Debug, Clone, PartialEq)]
39pub struct Closure {
40 pub body: Ast,
41 pub params: Vec<Name>,
42 pub env: Assoc<Name, Value>,
43}
44
45impl Value {
46 pub fn prefab(self) -> Ast {
49 raw_ast!(Node(
50 typed_form!(
51 "prefab_internal",
52 (impossible), cust_rc_box!(move |_| Ok(ast!(
54 {"Type" "forall_type" :
56 "param" => ["T"],
57 "body" => (import [* [forall "param"]] (vr "T"))}))),
58 cust_rc_box!(move |_| Ok(self.clone()))
59 ),
60 crate::util::mbe::EnvMBE::new(),
61 crate::beta::ExportBeta::Nothing
62 ))
63 }
64}
65
66impl Closure {
69 pub fn prefab(&self) -> Ast {
70 ast!({"Expr" "lambda" :
71 "param" => (@"p" ,seq self.params.iter().map(|n| ast!(*n))),
72 "p_t" => (@"p" ,seq self.params.iter().map(|_| ast!((trivial)))),
73 "body" => (import [* ["param" : "p_t"]] (,
74 crate::alpha::substitute(&self.body,
75 &self.env.map(|v| v.clone().prefab())
76 )
77 ))
78 })
79 }
80}
81
82pub struct BIF(pub Rc<(dyn Fn(Vec<Value>) -> Value)>);
84
85pub fn apply__function_value(f: &Value, args: Vec<Value>) -> Value {
86 match *f {
87 BuiltInFunction(BIF(ref f)) => f(args.into_iter().collect()),
88 Function(ref cl) => {
89 let mut clo_env = cl.env.clone();
90 if cl.params.len() != args.len() {
91 panic!(
92 "[type error] Attempted to apply {} arguments to function requiring {} \
93 parameters",
94 args.len(),
95 cl.params.len()
96 );
97 }
98 for (p, a) in cl.params.iter().zip(args.into_iter()) {
99 clo_env = clo_env.set(*p, a)
100 }
101 eval(&cl.body, clo_env).unwrap()
102 }
103 _ => panic!("[type error] {:#?} is not a function", f),
104 }
105}
106
107impl PartialEq for BIF {
108 fn eq(&self, other: &BIF) -> bool { self as *const BIF == other as *const BIF }
109}
110
111impl Clone for BIF {
112 fn clone(&self) -> BIF { BIF(self.0.clone()) }
113}
114
115impl std::fmt::Display for Value {
116 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
117 match *self {
118 Int(ref bi) => write!(f, "{}", bi),
119 Sequence(ref seq) => {
120 for elt in seq {
121 write!(f, "{}", &*elt)?;
122 }
123 Ok(())
124 }
125 Function(_) => write!(f, "[closure]"),
126 BuiltInFunction(_) => write!(f, "[built-in function]"),
127 AbstractSyntax(ref ast) => write!(f, "'[{}]'", ast),
128 Struct(ref parts) => {
129 write!(f, "*[")?;
130 for (k, v) in parts.iter_pairs() {
131 write!(f, "{}: {} ", k, v)?;
132 }
133 write!(f, "]*")
134 }
135 Enum(n, ref parts) => {
136 write!(f, "+[{}", n)?;
137 for p in parts.iter() {
138 write!(f, " {}", p)?;
139 }
140 write!(f, "]+")
141 }
142 Text(ref st) => write!(f, "{}", st),
143 Cell(ref cell) => write!(f, "{}", cell.borrow()),
144 ParseContext(_) => write!(f, "[a language]"),
145 }
146 }
147}
148
149impl std::fmt::Debug for BIF {
150 fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
151 formatter.write_str("[built-in function]")
152 }
153}
154
155impl crate::walk_mode::WalkElt for Value {
156 fn from_ast(a: &Ast) -> Value { AbstractSyntax(a.clone()) }
157 fn to_ast(&self) -> Ast {
158 match *self {
159 AbstractSyntax(ref a) => a.clone(),
160 _ => icp!("[type error] {} is not syntax", self),
161 }
162 }
163}
164
165custom_derive! {
166 #[derive(Copy, Clone, Debug, Reifiable)]
167 pub struct Eval {}
168}
169custom_derive! {
170 #[derive(Copy, Clone, Debug, Reifiable)]
171 pub struct Destructure {}
172}
173
174impl WalkMode for Eval {
175 fn name() -> &'static str { "Evalu" }
176
177 type Elt = Value;
178 type Negated = Destructure;
179 type AsPositive = Eval;
180 type AsNegative = Destructure;
181 type Err = ();
182 type D = crate::walk_mode::Positive<Eval>;
183 type ExtraInfo = ();
184
185 fn get_walk_rule(f: &Form) -> WalkRule<Eval> {
186 if f.name == n("macro_invocation") {
188 icp!("unexpanded macro!")
189 }
190 f.eval.pos().clone()
191 }
192 fn automatically_extend_env() -> bool { true }
193
194 fn walk_var(n: Name, cnc: &LazyWalkReses<Eval>) -> Result<Value, ()> {
195 match cnc.env.find(&n) {
196 Some(v) => Ok(v.clone()),
197 None => panic!("Undefined var `{}` in {}", n, cnc.env),
198 }
199 }
200
201 fn underspecified(_: Name) -> Value { val!(enum "why is this here?", ) }
203}
204
205impl WalkMode for Destructure {
206 fn name() -> &'static str { "Destr" }
207
208 type Elt = Value;
209 type Negated = Eval;
210 type AsPositive = Eval;
211 type AsNegative = Destructure;
212 type Err = ();
213 type D = crate::walk_mode::Negative<Destructure>;
214 type ExtraInfo = ();
215
216 fn get_walk_rule(f: &Form) -> WalkRule<Destructure> { f.eval.neg().clone() }
220 fn automatically_extend_env() -> bool { true } }
222
223impl NegativeWalkMode for Destructure {
224 fn needs_pre_match() -> bool { false } }
226
227impl crate::walk_mode::WalkElt for Ast {
228 fn from_ast(a: &Ast) -> Ast { a.clone() }
229 fn to_ast(&self) -> Ast { self.clone() }
230}
231
232pub fn eval_top(expr: &Ast) -> Result<Value, ()> { eval(expr, Assoc::new()) }
233
234pub fn eval(expr: &Ast, env: Assoc<Name, Value>) -> Result<Value, ()> {
235 walk::<Eval>(expr, &LazyWalkReses::new_wrapper(env))
236}
237
238pub fn neg_eval(pat: &Ast, env: Assoc<Name, Value>) -> Result<Assoc<Name, Value>, ()> {
239 walk::<Destructure>(pat, &LazyWalkReses::new_wrapper(env))
240}
241
242custom_derive! {
243 #[derive(Copy, Clone, Debug, Reifiable)]
244 pub struct QQuote {}
245}
246custom_derive! {
247 #[derive(Copy, Clone, Debug, Reifiable)]
248 pub struct QQuoteDestr {}
249}
250
251impl WalkMode for QQuote {
252 fn name() -> &'static str { "QQuote" }
253
254 type Elt = Value;
256 type Negated = QQuoteDestr;
257 type AsPositive = QQuote;
258 type AsNegative = QQuoteDestr;
259 type Err = ();
260 type D = crate::walk_mode::Positive<QQuote>;
261 type ExtraInfo = ();
262
263 fn walk_var(n: Name, _: &LazyWalkReses<Self>) -> Result<Value, ()> { Ok(val!(ast (vr n))) }
264 fn walk_atom(n: Name, _: &LazyWalkReses<Self>) -> Result<Value, ()> { Ok(val!(ast (at n))) }
265 fn get_walk_rule(f: &Form) -> WalkRule<QQuote> { f.quasiquote.pos().clone() }
267 fn automatically_extend_env() -> bool { false }
268}
269
270impl WalkMode for QQuoteDestr {
271 fn name() -> &'static str { "QQDes" }
272
273 type Elt = Value;
274 type Negated = QQuote;
275 type AsPositive = QQuote;
276 type AsNegative = QQuoteDestr;
277 type Err = ();
278 type D = crate::walk_mode::Negative<QQuoteDestr>;
279 type ExtraInfo = ();
280
281 fn walk_var(n: Name, cnc: &LazyWalkReses<Self>) -> Result<Assoc<Name, Value>, ()> {
282 let val = val!(ast (vr n));
283 if cnc.context_elt() == &val {
284 Ok(Assoc::<Name, Value>::new())
285 } else {
286 Err(Self::qlit_mismatch_error(val, cnc.context_elt().clone()))
287 }
288 }
289 fn walk_atom(n: Name, cnc: &LazyWalkReses<Self>) -> Result<Assoc<Name, Value>, ()> {
290 let val = val!(ast (at n));
291 if cnc.context_elt() == &val {
292 Ok(Assoc::<Name, Value>::new())
293 } else {
294 Err(Self::qlit_mismatch_error(val, cnc.context_elt().clone()))
295 }
296 }
297 fn get_walk_rule(f: &Form) -> WalkRule<QQuoteDestr> { f.quasiquote.neg().clone() }
299 fn automatically_extend_env() -> bool { false }
300}
301
302impl NegativeWalkMode for QQuoteDestr {
303 fn needs_pre_match() -> bool { true } }
305
306