Skip to content

Commit 4e8fa0b

Browse files
committed
add quote syntax and binary executable
1 parent 2cfe2e5 commit 4e8fa0b

File tree

5 files changed

+64
-23
lines changed

5 files changed

+64
-23
lines changed

examples/collection.cl

+10-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
;; (println num)
44
;; (setq num (- num 1))) ; num = num - 1
55

6-
(define nil (< 1 0))
7-
86
(defun reverse (lis)
97
(define res)
108
(while lis
@@ -21,4 +19,13 @@
2119
(setq x (if lis (car lis) nil)))
2220
(reverse res))
2321

24-
(println (map (quote (1 2 3 4 5 6 7)) (lambda (x) (+ x 5))))
22+
(defun seq (cnt)
23+
(define ret)
24+
(while (< 0 cnt)
25+
(setq ret (cons cnt ret))
26+
(setq cnt (- cnt 1)))
27+
ret)
28+
29+
(println
30+
(map (seq 15)
31+
(lambda (x) (+ x 5))))

src/context.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -224,24 +224,24 @@ impl<'a> RootRef<'a> {
224224
}
225225

226226
pub fn make_list(self, l: impl IntoIterator<Item = impl ToLisp>) {
227-
root!(next, cdr);
227+
root!(next, car, ret, t1);
228228
let mut it = l.into_iter();
229229
if let Some(first) = it.next() {
230-
first.to_lisp(cdr);
231-
let first_cell = unsafe { Obj::new_pair(Pair { cdr: cdr.get(), car: Obj::nil() }) };
230+
first.to_lisp(car);
231+
let first_cell = unsafe { Obj::new_pair(Pair { car: car.get(), cdr: Obj::nil() }) };
232232
next.set(first_cell);
233-
self.set(first_cell);
233+
ret.set(first_cell);
234234
for num in it {
235-
num.to_lisp(cdr);
236-
let next_cell = unsafe { Obj::new_pair(Pair { cdr: cdr.get(), car: Obj::nil() }) };
237-
root!(t1);
235+
num.to_lisp(car);
236+
let next_cell = unsafe { Obj::new_pair(Pair { car: car.get(), cdr: Obj::nil() }) };
238237
t1.set(next_cell);
239-
next.set_car(t1);
238+
next.set_cdr(t1);
240239
t1.copy_to(next);
241240
}
242241
} else {
243-
self.set(Obj::nil())
242+
ret.set(Obj::nil())
244243
}
244+
ret.copy_to(self)
245245
}
246246

247247
pub fn make_string(self, s: impl AsRef<str>) {
@@ -397,3 +397,15 @@ impl std::fmt::Debug for RootRef<'_> {
397397
Ok(())
398398
}
399399
}
400+
401+
#[cfg(test)]
402+
mod tests {
403+
use super::*;
404+
405+
#[test]
406+
fn make_lists() {
407+
root!(val);
408+
(1, 2, 3).to_lisp(val);
409+
assert_eq!(format!("{val:?}"), "(1 2 3)")
410+
}
411+
}

src/context/eval.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub(crate) fn progn(env: RootRef, list: RootRef) -> Obj {
4949
root!(it, ret);
5050
list.copy_to(it);
5151
for val in it.to_list_iter(ret) {
52-
eprintln!("progn stmt: {val:?}");
52+
// eprintln!("progn stmt: {val:?}");
5353
ret.set(eval(env, val));
5454
}
5555
return ret.get();

src/main.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1-
fn main() {
2-
println!("Hello, world!");
1+
use std::error::Error;
2+
3+
fn usage() -> String {
4+
let exe = std::env::args().next().unwrap_or_else(|| "grel".into());
5+
format!("usage: {exe} <file>")
6+
}
7+
8+
fn main() -> Result<(), Box<dyn Error>> {
9+
let program = std::env::args_os().nth(1).ok_or_else(usage)?;
10+
let content = std::fs::read_to_string(program)?;
11+
grel::exec_expr(&content);
12+
13+
Ok(())
314
}

src/parse.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
use std::iter::Peekable;
1+
use std::{borrow::Cow, iter::Peekable};
22

3-
use crate::{intern::intern, root, Obj};
3+
use crate::{intern::intern, root, Obj, ToLisp};
44

55
enum Tok<'a> {
6-
Str(&'a str),
6+
#[expect(dead_code)]
7+
Str(Cow<'a, str>),
78
Sym(&'a str),
89
Num(i64),
910
Quote,
@@ -54,10 +55,6 @@ impl<'a> Iterator for Lex<'a> {
5455
';' => {
5556
self.take_until(|c| c == '\n');
5657
},
57-
c if c.is_whitespace() => {
58-
self.take_char();
59-
continue
60-
},
6158
'-' => {
6259
let s = self.take_until(term_end);
6360
if s.chars().skip(1).next().map_or(false, |c| c.is_ascii_digit()) {
@@ -90,6 +87,10 @@ impl<'a> Iterator for Lex<'a> {
9087
self.take_char();
9188
return Some(Tok::Dot);
9289
}
90+
c if c.is_whitespace() => {
91+
self.take_char();
92+
continue
93+
},
9394
_ => {
9495
let sym = self.take_until(term_end);
9596
assert!(valid_sym(sym), "{sym} is invalid symbol");
@@ -155,9 +156,19 @@ fn parse_expr(lex: &mut PLex) -> ExprRes {
155156
};
156157
match tok {
157158
Tok::Str(_) => todo!(),
159+
Tok::Sym("nil") => ExprRes::Obj(Obj::nil()),
158160
Tok::Sym(s) => ExprRes::Obj(intern(s)),
159161
Tok::Num(i) => ExprRes::Obj(Obj::from_num(i)),
160-
Tok::Quote => todo!(),
162+
Tok::Quote => {
163+
root!(quote, expr, res);
164+
let ExprRes::Obj(val) = parse_expr(lex) else {
165+
panic!("unfinished quote");
166+
};
167+
expr.set(val);
168+
quote.set(intern("quote"));
169+
(quote, expr).to_lisp(res);
170+
ExprRes::Obj(res.get())
171+
},
161172
Tok::OpenParen => ExprRes::Obj(parse_list(lex)),
162173
Tok::CloseParen => ExprRes::Close,
163174
Tok::Dot => ExprRes::Dot,

0 commit comments

Comments
 (0)