Skip to content

Commit 3b4fed5

Browse files
committed
Do not use Gc, and instead focus on improving get performance
1 parent 25e60a6 commit 3b4fed5

File tree

6 files changed

+175
-159
lines changed

6 files changed

+175
-159
lines changed

Cargo.lock

Lines changed: 55 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ ariadne = "0.1.5"
1010
chumsky = "0.8.0"
1111
clap = { version = "3.2.12", features = ["derive"] }
1212
color-eyre = "0.6.1"
13-
gc = { version = "0.4.1", features = ["derive"] }
13+
im-rc = "15.1.0"
1414
rustyline = "9.1.2"
1515
tracing = "0.1.35"
1616
tracing-subscriber = "0.3.15"

src/atom.rs

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
use std::rc::Rc;
2+
13
use color_eyre::eyre::eyre;
24
use color_eyre::Result;
35

4-
use gc::{Finalize, Gc, Trace};
5-
66
use crate::env::Env;
77

88
/// Evalutation happens here.
99
pub mod eval;
1010

1111
/// A single value in lwhlisp.
12-
#[derive(Clone, Trace, Finalize)]
12+
#[derive(Clone)]
1313
pub enum Atom {
1414
/// Number
1515
Number(f64),
@@ -21,15 +21,15 @@ pub enum Atom {
2121
///
2222
/// This is also used to construct lists, using nested pairs.
2323
/// For example (pseudocode), `Pair(1, Pair(2, Pair(3, nil)))` would be interpreted as `(1 2 3)`.
24-
Pair(Gc<Atom>, Gc<Atom>),
24+
Pair(Rc<Atom>, Rc<Atom>),
2525
/// Native Rust function.
2626
///
2727
/// This is used to implement some base function that require direct access to the underlying data.
28-
NativeFunc(fn(Gc<Atom>) -> Result<Gc<Atom>>),
28+
NativeFunc(fn(Rc<Atom>) -> Result<Rc<Atom>>),
2929
/// Closure
30-
Closure(Env, Gc<Atom>, Gc<Atom>),
30+
Closure(Env, Rc<Atom>, Rc<Atom>),
3131
/// Macro
32-
Macro(Env, Gc<Atom>, Gc<Atom>),
32+
Macro(Env, Rc<Atom>, Rc<Atom>),
3333
}
3434

3535
impl PartialEq for Atom {
@@ -172,8 +172,8 @@ impl Atom {
172172
Atom::Macro(_env, args, expr) => {
173173
let mut s = String::new();
174174
let atom = Atom::Pair(
175-
Gc::new(Atom::symbol("defmacro")),
176-
Gc::new(Atom::Pair(args.clone(), expr.clone())),
175+
Rc::new(Atom::symbol("defmacro")),
176+
Rc::new(Atom::Pair(args.clone(), expr.clone())),
177177
);
178178
write!(s, "{}", atom.pretty_print(indent_level)).unwrap();
179179
s
@@ -187,18 +187,18 @@ impl Atom {
187187

188188
impl Atom {
189189
/// Get the car of the atom if it is a pair, else return the atom itself.
190-
pub fn car(&self) -> Gc<Atom> {
190+
pub fn car(&self) -> Rc<Atom> {
191191
match self {
192192
Atom::Pair(car, _) => car.clone(),
193-
a => Gc::new(a.clone()),
193+
a => Rc::new(a.clone()),
194194
}
195195
}
196196

197197
/// Get the cdr of the atom if it is a pair, else return the atom itself.
198-
pub fn cdr(&self) -> Gc<Atom> {
198+
pub fn cdr(&self) -> Rc<Atom> {
199199
match self {
200200
Atom::Pair(_, cdr) => cdr.clone(),
201-
a => Gc::new(a.clone()),
201+
a => Rc::new(a.clone()),
202202
}
203203
}
204204

@@ -208,9 +208,9 @@ impl Atom {
208208
///
209209
/// # Errors
210210
/// If the atom is not a pair or nil, return an error.
211-
pub fn strict_cdr(&self) -> Result<Gc<Atom>> {
211+
pub fn strict_cdr(&self) -> Result<Rc<Atom>> {
212212
if self.is_nil() {
213-
Ok(Gc::new(self.clone()))
213+
Ok(Rc::new(self.clone()))
214214
} else {
215215
match self {
216216
Atom::Pair(_, cdr) => Ok(cdr.clone()),
@@ -230,7 +230,7 @@ impl Atom {
230230
/// Return true if the atom is a proper list.
231231
///
232232
/// A proper list is a cons list where the last element is nil.
233-
pub fn is_proper_list(expr: Gc<Self>) -> bool {
233+
pub fn is_proper_list(expr: Rc<Self>) -> bool {
234234
let mut expr = expr;
235235
while !expr.is_nil() {
236236
match expr.as_ref() {
@@ -243,7 +243,7 @@ impl Atom {
243243
}
244244

245245
/// Return true if the atom is a pair.
246-
pub fn is_list(expr: &Gc<Self>) -> bool {
246+
pub fn is_list(expr: &Rc<Self>) -> bool {
247247
matches!(expr.as_ref(), Atom::Pair(_, _))
248248
}
249249

@@ -262,7 +262,7 @@ impl Atom {
262262
/// Constructs a pair from two atoms
263263
#[must_use]
264264
pub fn cons(car: Atom, cdr: Atom) -> Atom {
265-
Atom::Pair(Gc::new(car), Gc::new(cdr))
265+
Atom::Pair(Rc::new(car), Rc::new(cdr))
266266
}
267267

268268
/// Constructs a symbol from a string
@@ -310,9 +310,9 @@ impl Atom {
310310

311311
fn validate_closure_form(
312312
env: Env,
313-
args: Gc<Atom>,
314-
body: Gc<Atom>,
315-
) -> Result<(Env, Gc<Atom>, Gc<Atom>)> {
313+
args: Rc<Atom>,
314+
body: Rc<Atom>,
315+
) -> Result<(Env, Rc<Atom>, Rc<Atom>)> {
316316
if Atom::is_proper_list(body.clone()) {
317317
// check argument names are all symbol
318318
let mut p = args.clone();
@@ -339,25 +339,25 @@ impl Atom {
339339
///
340340
/// # Errors
341341
/// Return an error if an invalid closure form is given
342-
pub fn closure(env: Env, args: Gc<Atom>, body: Gc<Atom>) -> Result<Gc<Atom>> {
342+
pub fn closure(env: Env, args: Rc<Atom>, body: Rc<Atom>) -> Result<Rc<Atom>> {
343343
let (env, args, body) = Atom::validate_closure_form(env, args, body)?;
344-
Ok(Gc::new(Atom::Closure(env, args, body)))
344+
Ok(Rc::new(Atom::Closure(env, args, body)))
345345
}
346346

347347
/// Set a binding in a closure's environment if the atom is a closure.
348348
///
349349
/// # Errors
350350
/// Returns an error if the given atom is not a closure.
351351
pub fn closure_add_env_binding(
352-
atom: &Gc<Atom>,
352+
atom: &Rc<Atom>,
353353
name: String,
354-
value: Gc<Atom>,
355-
) -> Result<Gc<Atom>> {
354+
value: Rc<Atom>,
355+
) -> Result<Rc<Atom>> {
356356
match atom.as_ref() {
357357
Atom::Closure(env, a, b) => {
358358
let mut env = env.clone();
359359
env.set(name, value);
360-
Ok(Gc::new(Atom::Closure(env, a.clone(), b.clone())))
360+
Ok(Rc::new(Atom::Closure(env, a.clone(), b.clone())))
361361
}
362362
a => {
363363
Err(eyre!(format!("Tried to change the environment of a closure, but the provided atom was not a closure. Found {}", a)))
@@ -384,7 +384,7 @@ impl Atom {
384384
///
385385
/// # Errors
386386
/// Returns an error if the given atom is not a list, or if the list is not long enough
387-
pub fn get_list_item_by_index(list: Gc<Self>, index: usize) -> Result<Gc<Self>> {
387+
pub fn get_list_item_by_index(list: Rc<Self>, index: usize) -> Result<Rc<Self>> {
388388
let mut list = list;
389389
let mut index = index;
390390
while index > 0 {
@@ -396,7 +396,7 @@ impl Atom {
396396

397397
/// WARNING: This is probably broken, and should only be used when it doesn't matter much.
398398
/// Currently it is used in the pretty printer, where it is used to count the lenght of a list.
399-
pub fn into_vec(atom: Gc<Self>) -> Vec<Gc<Self>> {
399+
pub fn into_vec(atom: Rc<Self>) -> Vec<Rc<Self>> {
400400
match atom.as_ref() {
401401
Atom::Pair(car, cdr) => {
402402
let mut v = vec![car.clone()];

0 commit comments

Comments
 (0)