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
use crate::eval::Env;
use crate::objects::{Eval, Object, Source, Vtable};
use crate::parse::Parser;
use crate::unwind::{Error, Unwind};
pub fn class_vtable() -> Vtable {
let vt = Vtable::new("class Compiler");
vt.add_primitive_method_or_panic("new", class_compiler_new);
vt
}
pub fn instance_vtable() -> Vtable {
let vt = Vtable::new("Compiler");
vt.add_primitive_method_or_panic("define:as:", compiler_define_as);
vt.add_primitive_method_or_panic("evaluate", compiler_evaluate);
vt.add_primitive_method_or_panic("parse:", compiler_parse);
vt.add_primitive_method_or_panic("parse:onEof:", compiler_parse_on_eof);
vt
}
fn class_compiler_new(_receiver: &Object, _args: &[Object], env: &Env) -> Eval {
Ok(env.foo.make_compiler())
}
fn compiler_evaluate(receiver: &Object, _args: &[Object], _env: &Env) -> Eval {
let compiler = receiver.compiler();
let expr = compiler.expr.borrow();
let source = compiler.source.borrow();
compiler.env.eval(&expr).context(&source)
}
fn compiler_define_as(receiver: &Object, args: &[Object], _env: &Env) -> Eval {
let name = args[0].string_as_str();
let value = args[1].clone();
receiver.compiler().env.define(name, value);
Ok(receiver.clone())
}
fn parse_aux(receiver: &Object, source: &Object, handler: Option<&Object>, env: &Env) -> Eval {
let source = source.string_as_str();
let mut parser = Parser::new(source, env.foo.root());
let compiler = receiver.compiler();
let expr = match parser.parse() {
Ok(expr) => expr,
Err(Unwind::Exception(Error::EofError(ref e), ..)) if handler.is_some() => {
return handler.unwrap().send("value:", &[env.foo.into_string(e.what())], env)
}
Err(unwind) => return Err(unwind).context(source),
};
compiler.source.replace(source.to_string());
compiler.expr.replace(expr);
Ok(receiver.clone())
}
fn compiler_parse(receiver: &Object, args: &[Object], env: &Env) -> Eval {
parse_aux(receiver, &args[0], None, env)
}
fn compiler_parse_on_eof(receiver: &Object, args: &[Object], env: &Env) -> Eval {
parse_aux(receiver, &args[0], Some(&args[1]), env)
}