Skip to content

Commit 17140fd

Browse files
committed
VM wall of fire, GC pointers
1 parent bcd34c4 commit 17140fd

File tree

11 files changed

+1129
-338
lines changed

11 files changed

+1129
-338
lines changed

.gitignore

-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
target
2-
Cargo.lock
32
*.sublime-workspace

Cargo.lock

+14
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
name = "r5rs"
33
version = "0.1.0"
44
authors = ["Jose Roberto Vidal <vidal.roberto.j@gmail.com>"]
5+
6+
[dependencies]
7+
gc = "*"

src/bin/compiler.rs

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
extern crate r5rs;
2+
3+
use std::io::{stdin, stdout, Write};
4+
5+
// use r5rs::values::*;
6+
use r5rs::parser::*;
7+
use r5rs::reader::*;
8+
use r5rs::lexer::*;
9+
use r5rs::compiler::*;
10+
11+
fn main() {
12+
let mut buffer = String::new();
13+
let mut chars;
14+
// let mut environment = Environment::new(None);
15+
// let mut heap = Heap::new();
16+
17+
loop {
18+
buffer.clear();
19+
20+
21+
let prompt = stdout().write("> ".as_bytes()).and(stdout().flush());
22+
23+
if let Err(_) = prompt {
24+
panic!("IO error");
25+
}
26+
27+
match stdin().read_line(&mut buffer) {
28+
Ok(_) => {}
29+
_ => panic!(""),
30+
}
31+
32+
chars = buffer.clone().chars().collect();
33+
34+
let tokens = match token_stream(chars) {
35+
Ok(tokens) => tokens,
36+
Err(e) => {
37+
println!("Invalid input: {:?}", e);
38+
continue;
39+
}
40+
};
41+
42+
let mut tokens = tokens.into_iter().collect();
43+
44+
let datum = match parse_datum(&mut tokens) {
45+
Ok(Some(datum)) => datum,
46+
Err(e) => {
47+
println!("Invalid datum: {:?}", e);
48+
continue;
49+
}
50+
Ok(None) => {
51+
continue;
52+
}
53+
};
54+
55+
// println!("datum: {:?}", datum);
56+
let expression = match parse_expression(datum) {
57+
Ok(exp) => exp,
58+
Err(_) => {
59+
println!("Invalid expression");
60+
continue;
61+
}
62+
};
63+
64+
println!("{:?}", compile(expression));
65+
66+
}
67+
}

src/bin/interpreter.rs

+34-12
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
extern crate r5rs;
2+
extern crate gc;
23

4+
use gc::Trace;
35
use std::io::{stdin, stdout, Write};
46

5-
use r5rs::interpret::*;
6-
use r5rs::values::*;
7+
// use r5rs::values::*;
78
use r5rs::parser::*;
89
use r5rs::reader::*;
910
use r5rs::lexer::*;
11+
use r5rs::interpret::*;
12+
use r5rs::compiler::*;
1013

1114
fn main() {
1215
let mut buffer = String::new();
1316
let mut chars;
14-
let mut environment = Environment::new(None);
15-
let mut heap = Heap::new();
17+
let mut environment = null_env();
18+
// let mut heap = Heap::new();
19+
// let env_gc = heap.insert_env(environment);
1620

1721
loop {
1822
buffer.clear();
@@ -61,16 +65,34 @@ fn main() {
6165
}
6266
};
6367

64-
// println!("{:?}", expression);
6568

66-
let object = match eval(&expression, &mut environment, &mut heap) {
67-
Ok(obj) => obj,
68-
Err(e) => {
69-
println!("{:?}", e);
70-
continue;
71-
}
69+
let (bytecode, entry) = compile(expression);
70+
71+
println!("Code:\n{:?}", bytecode);
72+
let result = exec(bytecode, environment.clone(), entry);
73+
74+
match result {
75+
Ok(Value::Scalar(ref s)) => println!("{:?}", s),
76+
x @ _ => println!("{:?}", x),
77+
// Ok(Value::Reference(ref r)) => if let Ok(ref v) = r.borrow() {
78+
// let ref_value : &Reference = &*v;
79+
// println!("{:?}", ref_value);
80+
// } else {
81+
// println!("heap error");
82+
// },
83+
Err(_) => println!("execution error"),
7284
};
7385

74-
println!("{}", object.to_repl());
86+
// println!("{:?}", expression);
87+
88+
// let object = match eval(&expression, &mut environment, &mut heap) {
89+
// Ok(obj) => obj,
90+
// Err(e) => {
91+
// println!("{:?}", e);
92+
// continue;
93+
// }
94+
// };
95+
96+
// println!("{}", object.to_repl());
7597
}
7698
}

src/compiler/mod.rs

+220
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
2+
use std::collections::HashMap;
3+
use std::iter::once;
4+
5+
use parser::{Body, Expression, LambdaFormals};
6+
use helpers::{CowString, ImmutableString};
7+
8+
#[derive(Debug, Clone)]
9+
pub enum Instruction {
10+
Integer(isize),
11+
String(CowString),
12+
Character(char),
13+
Boolean(bool),
14+
Ret,
15+
Nil,
16+
Call(usize),
17+
Branch(usize),
18+
BranchUnless(usize),
19+
Lambda(usize),
20+
Pair,
21+
LoadVar(ImmutableString),
22+
SetVar(ImmutableString),
23+
}
24+
25+
struct ByProduct {
26+
instructions: Vec<Instruction>,
27+
lambdas: Option<HashMap<usize, Vec<Instruction>>>,
28+
}
29+
30+
pub fn compile(expression: Expression) -> (Vec<Instruction>, usize) {
31+
let mut counter = 0;
32+
let objects = compile_inner(expression, &mut counter);
33+
assemble(objects)
34+
}
35+
36+
fn assemble(objects: ByProduct) -> (Vec<Instruction>, usize) {
37+
let mut lambda_indices = HashMap::new();
38+
let ByProduct {
39+
lambdas,
40+
instructions,
41+
} = objects;
42+
43+
let mut final_instructions = vec![];
44+
45+
if let Some(l) = lambdas {
46+
for (lambda_idx, code) in l.into_iter() {
47+
let offset = final_instructions.len();
48+
final_instructions.extend(code);
49+
lambda_indices.insert(lambda_idx, offset);
50+
}
51+
}
52+
53+
let entry = final_instructions.len();
54+
final_instructions.extend(instructions);
55+
56+
for ins in final_instructions.iter_mut() {
57+
if let Instruction::Lambda(ref mut lambda_idx) = *ins {
58+
*lambda_idx = *lambda_indices.get(lambda_idx).expect("unexpected lambda");
59+
}
60+
}
61+
62+
(final_instructions, entry)
63+
}
64+
65+
impl ByProduct {
66+
fn from_instructions(instructions: Vec<Instruction>) -> ByProduct {
67+
ByProduct {
68+
instructions,
69+
lambdas: None,
70+
}
71+
}
72+
}
73+
74+
fn compile_inner(expression: Expression, mut counter: &mut usize) -> ByProduct {
75+
let from_instructions = ByProduct::from_instructions;
76+
77+
match expression {
78+
Expression::String(s) => from_instructions(vec![Instruction::String(CowString::from(s))]),
79+
Expression::Character(c) => from_instructions(vec![Instruction::Character(c)]),
80+
81+
Expression::Variable(s) => {
82+
from_instructions(vec![Instruction::LoadVar(ImmutableString::from(s))])
83+
}
84+
85+
Expression::Assignment {
86+
variable,
87+
expression,
88+
} => {
89+
let mut byproduct = compile_inner(*expression, counter);
90+
byproduct
91+
.instructions
92+
.push(Instruction::SetVar(ImmutableString::from(variable)));
93+
byproduct
94+
}
95+
96+
Expression::Boolean(b) => from_instructions(vec![Instruction::Boolean(b)]),
97+
98+
Expression::Call {
99+
operator,
100+
mut operands,
101+
} => {
102+
let mut ins = vec![];
103+
let operands_n = operands.len();
104+
operands.reverse();
105+
operands.push(*operator);
106+
107+
let mut lambdas = HashMap::new();
108+
109+
for op in operands.into_iter() {
110+
let compiled = compile_inner(op, counter);
111+
ins.extend(compiled.instructions);
112+
merge_lambdas(&mut lambdas, compiled.lambdas);
113+
}
114+
ins.push(Instruction::Call(operands_n));
115+
116+
ByProduct {
117+
instructions: ins,
118+
lambdas: if lambdas.len() > 0 {
119+
Some(lambdas)
120+
} else {
121+
None
122+
},
123+
}
124+
}
125+
Expression::Lambda { formals, body } => {
126+
let mut ins = vec![];
127+
let mut lambdas = HashMap::new();
128+
129+
match formals {
130+
LambdaFormals::List(vars) => for var in vars {
131+
ins.push(Instruction::SetVar(ImmutableString::from(var)));
132+
},
133+
_ => panic!("unsupported formals"),
134+
}
135+
136+
let Body {
137+
definitions,
138+
commands,
139+
expression: body_expression,
140+
} = body;
141+
142+
// TODO: handle definitions
143+
for (c, is_command) in commands
144+
.into_iter()
145+
.map(|c| (c, true))
146+
.chain(once((*body_expression, false)))
147+
{
148+
149+
let ByProduct {
150+
lambdas: c_lambdas,
151+
instructions,
152+
} = compile_inner(c, counter);
153+
merge_lambdas(&mut lambdas, c_lambdas);
154+
ins.extend(instructions);
155+
ins.push(Instruction::Ret);
156+
if is_command {
157+
// ins.push(Instruction::Pop);
158+
}
159+
}
160+
161+
let lambda_id = *counter;
162+
*counter += 1;
163+
lambdas.insert(lambda_id, ins);
164+
165+
ByProduct {
166+
instructions: vec![Instruction::Lambda(lambda_id)],
167+
lambdas: Some(lambdas),
168+
}
169+
}
170+
171+
Expression::Conditional {
172+
test,
173+
consequent,
174+
alternate,
175+
} => {
176+
let mut ins = vec![];
177+
let mut lambdas = HashMap::new();
178+
179+
let byproduct = compile_inner(*test, counter);
180+
merge_lambdas(&mut lambdas, byproduct.lambdas);
181+
ins.extend(byproduct.instructions);
182+
183+
let byproduct = compile_inner(*consequent, counter);
184+
merge_lambdas(&mut lambdas, byproduct.lambdas);
185+
ins.push(Instruction::BranchUnless(byproduct.instructions.len() + 2));
186+
ins.extend(byproduct.instructions);
187+
188+
if let Some(alternate) = alternate {
189+
let byproduct = compile_inner(*alternate, counter);
190+
ins.push(Instruction::Branch(byproduct.instructions.len() + 1));
191+
ins.extend(byproduct.instructions);
192+
merge_lambdas(&mut lambdas, byproduct.lambdas);
193+
} else {
194+
ins.push(Instruction::Nil);
195+
}
196+
197+
ByProduct {
198+
instructions: ins,
199+
lambdas: if lambdas.len() > 0 {
200+
Some(lambdas)
201+
} else {
202+
None
203+
},
204+
}
205+
206+
}
207+
208+
_ => panic!("unsupported expression"),
209+
}
210+
}
211+
212+
213+
fn merge_lambdas(
214+
lambdas: &mut HashMap<usize, Vec<Instruction>>,
215+
other: Option<HashMap<usize, Vec<Instruction>>>,
216+
) {
217+
if let Some(other_l) = other {
218+
lambdas.extend(other_l)
219+
}
220+
}

0 commit comments

Comments
 (0)