let as last expr in block now returns rhs; clean up some comment cruft
This commit is contained in:
parent
61b1b7bf90
commit
2ce2e2c2d3
111
src/compiler.rs
111
src/compiler.rs
|
@ -315,14 +315,10 @@ pub struct Compiler<'a> {
|
||||||
loop_info: Vec<LoopInfo>,
|
loop_info: Vec<LoopInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_binding(expr: &Spanned<Ast>) -> bool {
|
fn is_let(expr: &Spanned<Ast>) -> bool {
|
||||||
let (ast, _) = expr;
|
let (ast, _) = expr;
|
||||||
use Ast::*;
|
use Ast::*;
|
||||||
match ast {
|
matches!(ast, Let(..))
|
||||||
Let(..) | LBox(..) => true,
|
|
||||||
// Fn(name, ..) => !name.is_empty(),
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Compiler<'a> {
|
impl<'a> Compiler<'a> {
|
||||||
|
@ -358,14 +354,6 @@ impl<'a> Compiler<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn kw_from(&self, kw: &str) -> Option<Value> {
|
|
||||||
// self.kw_index_from(kw).map(Value::Keyword)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn kw_index_from(&self, kw: &str) -> Option<usize> {
|
|
||||||
// self.chunk.keywords.iter().position(|s| *s == kw)
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn visit(&mut self, node: &'static Spanned<Ast>) {
|
pub fn visit(&mut self, node: &'static Spanned<Ast>) {
|
||||||
let root_node = self.ast;
|
let root_node = self.ast;
|
||||||
let root_span = self.span;
|
let root_span = self.span;
|
||||||
|
@ -377,18 +365,6 @@ impl<'a> Compiler<'a> {
|
||||||
self.span = root_span;
|
self.span = root_span;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn emit_keyword(&mut self, s: &'static str) {
|
|
||||||
// // let existing_kw = self.chunk.keywords.iter().position(|kw| *kw == s);
|
|
||||||
// // let kw_index = match existing_kw {
|
|
||||||
// // Some(index) => index,
|
|
||||||
// // None => self.chunk.keywords.len(),
|
|
||||||
// // };
|
|
||||||
// // if kw_index == self.chunk.keywords.len() {
|
|
||||||
// // self.chunk.keywords.push(s);
|
|
||||||
// // }
|
|
||||||
// self.emit_constant(Value::Keyword(s));
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn emit_constant(&mut self, val: Value) {
|
fn emit_constant(&mut self, val: Value) {
|
||||||
let const_idx = if let Some(idx) = self.chunk.constants.iter().position(|v| *v == val) {
|
let const_idx = if let Some(idx) = self.chunk.constants.iter().position(|v| *v == val) {
|
||||||
idx
|
idx
|
||||||
|
@ -404,11 +380,7 @@ impl<'a> Compiler<'a> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
self.emit_op(Op::Constant);
|
self.emit_op(Op::Constant);
|
||||||
// self.chunk.bytecode.push(Op::Constant as u8);
|
|
||||||
// self.spans.push(self.span);
|
|
||||||
self.emit_byte(const_idx);
|
self.emit_byte(const_idx);
|
||||||
// self.chunk.bytecode.push(constant_index as u8);
|
|
||||||
// self.spans.push(self.span);
|
|
||||||
self.stack_depth += 1;
|
self.stack_depth += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,12 +507,6 @@ impl<'a> Compiler<'a> {
|
||||||
self.stack_depth += 1;
|
self.stack_depth += 1;
|
||||||
}
|
}
|
||||||
String(s) => {
|
String(s) => {
|
||||||
// let existing_str = self.chunk.strings.iter().position(|e| e == s);
|
|
||||||
// let str_index = match existing_str {
|
|
||||||
// Some(idx) => idx,
|
|
||||||
// None => self.chunk.strings.len(),
|
|
||||||
// };
|
|
||||||
// self.chunk.strings.push(s);
|
|
||||||
self.emit_constant(Value::Interned(s));
|
self.emit_constant(Value::Interned(s));
|
||||||
}
|
}
|
||||||
Keyword(s) => self.emit_constant(Value::Keyword(s)),
|
Keyword(s) => self.emit_constant(Value::Keyword(s)),
|
||||||
|
@ -548,31 +514,37 @@ impl<'a> Compiler<'a> {
|
||||||
self.scope_depth += 1;
|
self.scope_depth += 1;
|
||||||
let stack_depth = self.stack_depth;
|
let stack_depth = self.stack_depth;
|
||||||
for expr in lines.iter().take(lines.len() - 1) {
|
for expr in lines.iter().take(lines.len() - 1) {
|
||||||
if is_binding(expr) {
|
if is_let(expr) {
|
||||||
self.visit(expr);
|
self.visit(expr);
|
||||||
} else {
|
} else {
|
||||||
self.visit(expr);
|
self.visit(expr);
|
||||||
self.pop();
|
self.pop();
|
||||||
// self.emit_op(Op::Pop);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let last_expr = lines.last().unwrap();
|
let last_expr = lines.last().unwrap();
|
||||||
// TODO: make sure this actually returns the RHS of the expression
|
match last_expr {
|
||||||
if is_binding(last_expr) {
|
(Let(patt, expr), _) => {
|
||||||
self.visit(last_expr);
|
self.match_depth = 0;
|
||||||
self.emit_op(Op::Duplicate);
|
self.emit_op(Op::ResetMatch);
|
||||||
self.stack_depth += 1;
|
self.visit(expr);
|
||||||
} else {
|
let expr_pos = self.stack_depth - 1;
|
||||||
self.visit(last_expr);
|
self.visit(patt);
|
||||||
|
self.emit_op(Op::PanicIfNoMatch);
|
||||||
|
self.emit_op(Op::PushBinding);
|
||||||
|
self.emit_byte(expr_pos);
|
||||||
self.stack_depth += 1;
|
self.stack_depth += 1;
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
|
self.visit(last_expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.stack_depth += 1;
|
||||||
self.emit_op(Op::Store);
|
self.emit_op(Op::Store);
|
||||||
self.scope_depth -= 1;
|
self.scope_depth -= 1;
|
||||||
// reset bindings
|
|
||||||
while let Some(binding) = self.bindings.last() {
|
while let Some(binding) = self.bindings.last() {
|
||||||
if binding.depth > self.scope_depth {
|
if binding.depth > self.scope_depth {
|
||||||
let binding = self.bindings.pop().unwrap();
|
self.bindings.pop();
|
||||||
println!("popping: {:?}", binding);
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -670,14 +642,6 @@ impl<'a> Compiler<'a> {
|
||||||
self.bind(word);
|
self.bind(word);
|
||||||
}
|
}
|
||||||
StringPattern(s) => {
|
StringPattern(s) => {
|
||||||
// let existing_str = self.chunk.strings.iter().position(|e| e == s);
|
|
||||||
// let str_index = match existing_str {
|
|
||||||
// Some(idx) => idx,
|
|
||||||
// None => self.chunk.strings.len(),
|
|
||||||
// };
|
|
||||||
// if str_index == self.chunk.strings.len() {
|
|
||||||
// self.chunk.strings.push(s)
|
|
||||||
// }
|
|
||||||
self.match_constant(Value::Interned(s));
|
self.match_constant(Value::Interned(s));
|
||||||
}
|
}
|
||||||
TuplePattern(members) => {
|
TuplePattern(members) => {
|
||||||
|
@ -706,11 +670,6 @@ impl<'a> Compiler<'a> {
|
||||||
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
|
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
|
||||||
}
|
}
|
||||||
for _ in 0..members.len() {
|
for _ in 0..members.len() {
|
||||||
// this only runs if there's no match
|
|
||||||
// so don't change the representation of the stack
|
|
||||||
// contingencies will be handled by the binding forms
|
|
||||||
// (i.e., `let` and `match`)
|
|
||||||
// thus: emit Op::Pop directly
|
|
||||||
self.emit_op(Op::Pop);
|
self.emit_op(Op::Pop);
|
||||||
}
|
}
|
||||||
self.chunk.bytecode[before_load_tup_idx] =
|
self.chunk.bytecode[before_load_tup_idx] =
|
||||||
|
@ -743,11 +702,6 @@ impl<'a> Compiler<'a> {
|
||||||
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
|
self.chunk.bytecode[idx] = self.len() as u8 - idx as u8 - 1;
|
||||||
}
|
}
|
||||||
for _ in 0..members.len() {
|
for _ in 0..members.len() {
|
||||||
// this only runs if there's no match
|
|
||||||
// so don't change the representation of the stack
|
|
||||||
// contingencies will be handled by the binding forms
|
|
||||||
// (i.e., `let` and `match`)
|
|
||||||
// thus: emit Op::Pop directly
|
|
||||||
self.emit_op(Op::Pop);
|
self.emit_op(Op::Pop);
|
||||||
}
|
}
|
||||||
self.chunk.bytecode[before_load_list_idx] =
|
self.chunk.bytecode[before_load_list_idx] =
|
||||||
|
@ -766,15 +720,10 @@ impl<'a> Compiler<'a> {
|
||||||
let (PairPattern(key, pattern), _) = pair else {
|
let (PairPattern(key, pattern), _) = pair else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
// algo:
|
|
||||||
// push the keyword onto the stack
|
|
||||||
self.emit_constant(Value::Keyword(key));
|
self.emit_constant(Value::Keyword(key));
|
||||||
// pull the value out of the dict
|
|
||||||
self.emit_op(Op::LoadDictValue);
|
self.emit_op(Op::LoadDictValue);
|
||||||
self.emit_byte(dict_stack_pos);
|
self.emit_byte(dict_stack_pos);
|
||||||
// visit the pattern
|
|
||||||
self.visit(pattern);
|
self.visit(pattern);
|
||||||
// jump if no match
|
|
||||||
self.emit_op(Op::JumpIfNoMatch);
|
self.emit_op(Op::JumpIfNoMatch);
|
||||||
jump_idxes.push(self.len());
|
jump_idxes.push(self.len());
|
||||||
self.emit_byte(0xff);
|
self.emit_byte(0xff);
|
||||||
|
@ -815,30 +764,14 @@ impl<'a> Compiler<'a> {
|
||||||
self.bind(name);
|
self.bind(name);
|
||||||
}
|
}
|
||||||
Dict(pairs) => {
|
Dict(pairs) => {
|
||||||
println!("Compiling dict of len {}", pairs.len());
|
|
||||||
println!("Stack len: {}", self.stack_depth);
|
|
||||||
for pair in pairs {
|
for pair in pairs {
|
||||||
self.visit(pair);
|
self.visit(pair);
|
||||||
println!("Visited pair {:?}", pair);
|
|
||||||
println!("Current stack len: {}", self.stack_depth);
|
|
||||||
}
|
}
|
||||||
self.emit_op(Op::PushDict);
|
self.emit_op(Op::PushDict);
|
||||||
self.emit_byte(pairs.len());
|
self.emit_byte(pairs.len());
|
||||||
self.stack_depth = self.stack_depth + 1 - (pairs.len() * 2);
|
self.stack_depth = self.stack_depth + 1 - (pairs.len() * 2);
|
||||||
println!(
|
|
||||||
"Finished compiling dict, stack len now: {}",
|
|
||||||
self.stack_depth
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Pair(key, value) => {
|
Pair(key, value) => {
|
||||||
// let existing_kw = self.chunk.keywords.iter().position(|kw| kw == key);
|
|
||||||
// let kw_index = match existing_kw {
|
|
||||||
// Some(index) => index,
|
|
||||||
// None => self.chunk.keywords.len(),
|
|
||||||
// };
|
|
||||||
// if kw_index == self.chunk.keywords.len() {
|
|
||||||
// self.chunk.keywords.push(key);
|
|
||||||
// }
|
|
||||||
self.emit_constant(Value::Keyword(key));
|
self.emit_constant(Value::Keyword(key));
|
||||||
self.visit(value);
|
self.visit(value);
|
||||||
}
|
}
|
||||||
|
@ -905,10 +838,6 @@ impl<'a> Compiler<'a> {
|
||||||
self.stack_depth -= args.len() - 1;
|
self.stack_depth -= args.len() - 1;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
//algo
|
|
||||||
// visit all the args
|
|
||||||
// then store them
|
|
||||||
// then call the function
|
|
||||||
let arity = args.len();
|
let arity = args.len();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.visit(arg);
|
self.visit(arg);
|
||||||
|
|
|
@ -76,12 +76,12 @@ pub fn run(src: &'static str) {
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
let src = "
|
let src = "
|
||||||
|
let bar = 42
|
||||||
let foo = {
|
let foo = {
|
||||||
let bar = :bar
|
let (1, 2, 3) = (1, 2, 3)
|
||||||
fn baz () -> bar
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foo ()
|
foo
|
||||||
";
|
";
|
||||||
run(src);
|
run(src);
|
||||||
}
|
}
|
||||||
|
|
20
src/value.rs
20
src/value.rs
|
@ -6,24 +6,6 @@ use imbl::{HashMap, Vector};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
// #[derive(Clone, Debug, PartialEq)]
|
|
||||||
// pub struct Defined {
|
|
||||||
// pub name: &'static str,
|
|
||||||
// pub doc: Option<&'static str>,
|
|
||||||
// // pub enclosing: Vec<(usize, Value)>,
|
|
||||||
// // pub has_run: bool,
|
|
||||||
// // pub input: &'static str,
|
|
||||||
// // pub src: &'static str,
|
|
||||||
// pub chunks: Vec<(u8, Chunk)>,
|
|
||||||
// pub closed: Vec<Value>,
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl Defined {
|
|
||||||
// pub fn close(&mut self, val: Value) {
|
|
||||||
// self.closed.push(val);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum LFn {
|
pub enum LFn {
|
||||||
Declared {
|
Declared {
|
||||||
|
@ -162,7 +144,7 @@ impl std::fmt::Display for Value {
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ")
|
.join(", ")
|
||||||
),
|
),
|
||||||
Box(value) => write!(f, "box {}", value.as_ref().borrow()),
|
Box(value) => write!(f, "box {{ {} }}", value.as_ref().borrow()),
|
||||||
Fn(lfn) => write!(f, "fn {}", lfn.name()),
|
Fn(lfn) => write!(f, "fn {}", lfn.name()),
|
||||||
BaseFn(_) => write!(f, "base fn"),
|
BaseFn(_) => write!(f, "base fn"),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user