diff --git a/blspc/src/compiler/compile.rs b/blspc/src/compiler/compile.rs index 373bb2c..6216b19 100644 --- a/blspc/src/compiler/compile.rs +++ b/blspc/src/compiler/compile.rs @@ -47,6 +47,11 @@ impl Compiler { result.append(&mut self.compile(c, depth + 1)?); } } + "list" => { + let mut joined = Vec::new(); + for c in cdr { joined.push(c); } + result.append(&mut self.compile_quoted(&joined)?); + } "if" => { // TODO: Remove .clone() let mut cond = self.compile(cdr[0].clone(), depth + 1)?; @@ -102,6 +107,17 @@ impl Compiler { } Ok(result) } + + fn compile_quoted(&mut self, atom: &Vec) -> Result, String> { + let mut result = Vec::new(); + + result.push(Instr::Push { + value: Type::String(format!("({})", atom.iter().map(|x| format!("{}", x)).collect::>().join(" "))), + label: self.next_label(), + }); + + Ok(result) + } fn compile_atom(&mut self, atom: &Sexpr, depth: usize) -> Result, String> { let mut result = Vec::new(); @@ -112,25 +128,25 @@ impl Compiler { value: Type::Int(*i), label: self.next_label(), }); - } + }, Float(f) => { result.push(Instr::Push { value: Type::Float(*f), label: self.next_label(), }); - } + }, Boolean(b) => { result.push(Instr::Push { value: Type::Boolean(*b), label: self.next_label(), }); - } + }, Str(s) => { result.push(Instr::Push { value: Type::String(s.clone()), label: self.next_label(), }); - } + }, _ => { result.append(&mut self.compile(atom.clone(), depth + 1)?); } diff --git a/blspc/src/compiler/parser.rs b/blspc/src/compiler/parser.rs index 95b70e7..82ea29b 100644 --- a/blspc/src/compiler/parser.rs +++ b/blspc/src/compiler/parser.rs @@ -58,7 +58,7 @@ impl Parser { match self.peek() { Some(s) => match s.as_str() { ")" => Err(format!("Unexpected ')' at position {}", self.position)), - "'" => { self.next(); Ok(Cons(Box::new(Str("quote".to_string())), vec![self.parse()?])) }, + "'" => { self.next(); self.parse_quote_sequence(")")}, "(" => self.parse_sequence(")"), _ => self.parse_atom(), } @@ -84,6 +84,24 @@ impl Parser { self.next(); Ok(Sexpr::Cons(Box::new(car), cdr)) } + + fn parse_quote_sequence(&mut self, end: &str) -> ParseResult { + let car = Symbol("list".to_string()); + + self.next(); + let mut cdr = Vec::new(); + loop { + let token = match self.peek() { + Some(token) => token, + None => return Err(format!("Unexpected end of input, expected '{}'", end)), + }; + if token == end { break; } + cdr.push(self.parse()?) + } + + self.next(); + Ok(Sexpr::Cons(Box::new(car), cdr)) + } fn parse_atom(&mut self) -> ParseResult { let token = self.next().unwrap(); diff --git a/blspc/src/main.rs b/blspc/src/main.rs index 9c78776..a7b4507 100644 --- a/blspc/src/main.rs +++ b/blspc/src/main.rs @@ -33,7 +33,7 @@ fn main() { // Compile (true, false) => { let src = read_to_string(&args.file).unwrap(); - compile_src(src, args.output, args.file, start); + compile_src(src, args.output, args.file, debug, start); }, // Run (false, true) => { @@ -43,7 +43,7 @@ fn main() { (false, false) => { if args.file.extension() == Some("blsp".as_ref()) { let src = read_to_string(&args.file).unwrap(); - compile_src(src, args.output, args.file, start); + compile_src(src, args.output, args.file, debug, start); } else if args.file.extension() == Some("bsm".as_ref()) { let src = read_to_string(&args.file).unwrap(); run_src(src, debug); @@ -55,7 +55,7 @@ fn main() { } -fn compile_src(src: String, path: Option, file: PathBuf, start: Instant) { +fn compile_src(src: String, path: Option, file: PathBuf, debug: bool, start: Instant) { let file_name = match path { Some(path) => path, None => Path::new(&file).to_path_buf(), @@ -64,7 +64,8 @@ fn compile_src(src: String, path: Option, file: PathBuf, start: Instant let tokens = tokenize(&cover_paren(src)); let mut parser = Parser::new(tokens.clone()); let result = parser.parse(); - + + if debug { println!("{:#?}", &result); } match result { Ok(ast) => { let mut compiler = Compiler::new(); diff --git a/blspc/src/vm/instr.rs b/blspc/src/vm/instr.rs index 19f1286..3b93c70 100644 --- a/blspc/src/vm/instr.rs +++ b/blspc/src/vm/instr.rs @@ -10,6 +10,7 @@ pub enum Type { Float(f64), Boolean(bool), String(String), + Array(Vec), } impl Type { @@ -20,6 +21,7 @@ impl Type { Type::Int(i) => *i != 0, Type::Float(f) => *f != 0.0, Type::String(s) => !s.is_empty(), + Type::Array(a) => !a.is_empty(), } } @@ -37,6 +39,7 @@ impl Type { Type::Float(f) => Type::Float(*f), Type::Boolean(b) => Type::Boolean(*b), Type::String(s) => Type::String(s[1..s.len() - 1].to_string()), + Type::Array(a) => Type::Array(a.iter().map(|t| t.trim()).collect()), } } @@ -50,6 +53,15 @@ impl Type { false => "false".to_string(), }, Type::String(s) => s.clone(), + Type::Array(a) => { + let mut s = "[".to_string(); + for t in a { + s.push_str(&t.fmt()); + s.push_str(", "); + } + s.push_str("]"); + s + } } } } @@ -119,6 +131,14 @@ impl Display for Type { Type::Float(fl) => write!(f, ":{}", fl), Type::Boolean(b) => write!(f, ":{}", b), Type::String(s) => write!(f, "$\"{}\"", s), + Type::Array(a) => { + write!(f, "[[")?; + for t in a { + write!(f, "{}", t)?; + write!(f, ", ")?; + } + write!(f, "]]") + } } } }