diff --git a/build.rs b/build.rs index 31abb1b..58f39f9 100644 --- a/build.rs +++ b/build.rs @@ -11,8 +11,7 @@ fn main() -> Result<(), Box> { let mut parser_builder = CTParserBuilder::new() .yacckind(YaccKind::Grmtools) .error_on_conflicts(false); - let lex_rule_ids_map = parser_builder - .process_file_in_src("syn/parser.y")?; + let lex_rule_ids_map = parser_builder.process_file_in_src("syn/parser.y")?; if let Some((grm, _, _, conflicts)) = parser_builder.conflicts() { eprintln!("{}", conflicts.pp(grm)); return Err("conflicts in parser".into()); diff --git a/src/bin/not.rs b/src/bin/not.rs index a538966..d3aa8da 100644 --- a/src/bin/not.rs +++ b/src/bin/not.rs @@ -1,4 +1,4 @@ -use not_python::{syn::ast, compile::Compile, vm::Vm}; +use not_python::{compile::Compile, syn::ast, vm::Vm}; use std::{fs, path::PathBuf}; use structopt::StructOpt; @@ -18,7 +18,6 @@ struct Options { #[structopt(short = "d", long)] disassemble: bool, */ - #[structopt(long, default_value = "run")] action: String, } @@ -28,8 +27,8 @@ fn main() -> Result<()> { let text = fs::read_to_string(&opt.input)?; let action = &opt.action.to_lowercase(); match action.as_str() { - "run" | "parse" | "dump" => {}, - _ => eprintln!("WARNING: unknown action {}", action) + "run" | "parse" | "dump" => {} + _ => eprintln!("WARNING: unknown action {}", action), } let ast = match ast::parse(text.as_str()) { @@ -40,7 +39,8 @@ fn main() -> Result<()> { } return Err("errors reported, exiting".into()); } - }.unwrap(); + } + .unwrap(); if action == "parse" { println!("{:#?}", ast); return Ok(()); diff --git a/src/compile/error.rs b/src/compile/error.rs index a8d8974..04fd678 100644 --- a/src/compile/error.rs +++ b/src/compile/error.rs @@ -10,4 +10,3 @@ pub enum Error { } pub type Result = std::result::Result; - diff --git a/src/compile/locals.rs b/src/compile/locals.rs index deb511f..4cf2da7 100644 --- a/src/compile/locals.rs +++ b/src/compile/locals.rs @@ -1,4 +1,8 @@ -use crate::{compile::Compile, obj::prelude::*, syn::{ast::*, visit::*}}; +use crate::{ + compile::Compile, + obj::prelude::*, + syn::{ast::*, visit::*}, +}; /// Collects local names from the given tree. /// @@ -30,10 +34,18 @@ impl<'c> CollectLocals<'c> { impl Visit for CollectLocals<'_> { type Out = (); - fn visit_body(&mut self, body: &Body) -> Self::Out { DefaultAccept::default_accept(body, self); } - fn visit_stmt(&mut self, stmt: &Stmt) -> Self::Out { DefaultAccept::default_accept(stmt, self); } - fn visit_assign_stmt(&mut self, assign: &AssignStmt) -> Self::Out { DefaultAccept::default_accept(assign, self); } - fn visit_return_stmt(&mut self, ret: &ReturnStmt) -> Self::Out { DefaultAccept::default_accept(ret, self); } + fn visit_body(&mut self, body: &Body) -> Self::Out { + DefaultAccept::default_accept(body, self); + } + fn visit_stmt(&mut self, stmt: &Stmt) -> Self::Out { + DefaultAccept::default_accept(stmt, self); + } + fn visit_assign_stmt(&mut self, assign: &AssignStmt) -> Self::Out { + DefaultAccept::default_accept(assign, self); + } + fn visit_return_stmt(&mut self, ret: &ReturnStmt) -> Self::Out { + DefaultAccept::default_accept(ret, self); + } fn visit_lhs_expr(&mut self, lhs_expr: &LhsExpr) -> Self::Out { match lhs_expr { LhsExpr::Name(name) => { @@ -43,14 +55,28 @@ impl Visit for CollectLocals<'_> { _ => { /* no op */ } } } - fn visit_expr(&mut self, expr: &Expr) -> Self::Out { DefaultAccept::default_accept(expr, self); } - fn visit_bin_expr(&mut self, expr: &BinExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); } - fn visit_un_expr(&mut self, expr: &UnExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); } - fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); } - fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); } - fn visit_access_expr(&mut self, expr: &AccessExpr) -> Self::Out { DefaultAccept::default_accept(expr, self); } + fn visit_expr(&mut self, expr: &Expr) -> Self::Out { + DefaultAccept::default_accept(expr, self); + } + fn visit_bin_expr(&mut self, expr: &BinExpr) -> Self::Out { + DefaultAccept::default_accept(expr, self); + } + fn visit_un_expr(&mut self, expr: &UnExpr) -> Self::Out { + DefaultAccept::default_accept(expr, self); + } + fn visit_call_expr(&mut self, expr: &CallExpr) -> Self::Out { + DefaultAccept::default_accept(expr, self); + } + fn visit_index_expr(&mut self, expr: &IndexExpr) -> Self::Out { + DefaultAccept::default_accept(expr, self); + } + fn visit_access_expr(&mut self, expr: &AccessExpr) -> Self::Out { + DefaultAccept::default_accept(expr, self); + } fn visit_fun_expr(&mut self, _expr: &FunExpr) -> Self::Out { // Do not collect names for function expressions, since they have their own scope. } - fn visit_atom(&mut self, atom: &Atom) -> Self::Out { DefaultAccept::default_accept(atom, self); } + fn visit_atom(&mut self, atom: &Atom) -> Self::Out { + DefaultAccept::default_accept(atom, self); + } } diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 8268410..ad89f39 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -4,7 +4,7 @@ mod locals; mod scope; pub mod thunk; -use crate::{syn::ast::Body, obj::prelude::*, vm::consts::*}; +use crate::{obj::prelude::*, syn::ast::Body, vm::consts::*}; use scope::*; use std::collections::HashMap; @@ -29,20 +29,28 @@ impl Compile { .to_vec(); // XXX TODO(compile) // remove this when we get returns implemented - main.push(crate::vm::inst::Inst::PushSym(crate::obj::reserved::NIL_NAME.sym)); + main.push(crate::vm::inst::Inst::PushSym( + crate::obj::reserved::NIL_NAME.sym, + )); main.push(crate::vm::inst::Inst::Return); - let globals_syms: std::collections::BTreeMap<_, _> = self.pop_scope_layer().unwrap() + let globals_syms: std::collections::BTreeMap<_, _> = self + .pop_scope_layer() + .unwrap() .into_iter() .map(|(sym, name)| (name, sym)) .collect(); - let globals = globals_syms.into_iter() + let globals = globals_syms + .into_iter() .enumerate() .map(|(index, (name, sym))| { assert_eq!(index, name.index()); sym }) .collect(); - Ok((self.const_data.const_pool, UserFun::new_obj(main, globals, 0))) + Ok(( + self.const_data.const_pool, + UserFun::new_obj(main, globals, 0), + )) } /// Gets the constant data that is interned in this compile session. diff --git a/src/compile/scope.rs b/src/compile/scope.rs index 2a348f1..d19b80c 100644 --- a/src/compile/scope.rs +++ b/src/compile/scope.rs @@ -11,9 +11,7 @@ pub struct Scope { impl Scope { pub fn lookup_local(&self, sym: Sym) -> Option { - self.locals() - .and_then(|locals| locals.get(&sym)) - .copied() + self.locals().and_then(|locals| locals.get(&sym)).copied() } pub fn lookup_global(&self, sym: Sym) -> Option { @@ -23,8 +21,7 @@ impl Scope { } pub fn create_local(&mut self, sym: Sym) -> Name { - let locals = self.locals_mut() - .expect("locals"); + let locals = self.locals_mut().expect("locals"); if let Some(local) = locals.get(&sym).copied() { local } else { @@ -35,8 +32,7 @@ impl Scope { } pub fn create_global(&mut self, sym: Sym) -> Name { - let globals = self.globals_mut() - .expect("globals"); + let globals = self.globals_mut().expect("globals"); if let Some(global) = globals.get(&sym).copied() { global } else { diff --git a/src/compile/thunk.rs b/src/compile/thunk.rs index f48e584..1430aec 100644 --- a/src/compile/thunk.rs +++ b/src/compile/thunk.rs @@ -106,8 +106,7 @@ impl Thunk { } pub fn flatten(self) -> BasicBlockList { - Flatten::default() - .flatten(self) + Flatten::default().flatten(self) } } @@ -158,10 +157,13 @@ impl Flatten { match thunk { Thunk::Body(thunk) => { let this_block = self.this_block(); - let prev = self.blocks.insert(this_block, BasicBlock::Block { - exit: next_block, - block: thunk, - }); + let prev = self.blocks.insert( + this_block, + BasicBlock::Block { + exit: next_block, + block: thunk, + }, + ); assert!(prev.is_none()); } Thunk::List(thunks) => { @@ -172,14 +174,20 @@ impl Flatten { } assert_eq!(next_block, self.this_block()); } - Thunk::Branch { thunk_true, thunk_false, } => { + Thunk::Branch { + thunk_true, + thunk_false, + } => { let branch_block = self.this_block(); let block_true = self.this_block() + 1; let block_false = block_true + thunk_true.basic_block_count(); - self.blocks.insert(branch_block, BasicBlock::Branch { - block_true, - block_false, - }); + self.blocks.insert( + branch_block, + BasicBlock::Branch { + block_true, + block_false, + }, + ); self.flatten_next(next_block, *thunk_true); self.flatten_next(next_block, *thunk_false); assert_eq!(self.this_block(), next_block); @@ -278,7 +286,10 @@ impl Visit for CompileBody<'_> { if let Some(local) = self.compile.lookup_local(sym) { thunk = Inst::PopLocal(Some(local)).into(); } else { - let global = self.compile.lookup_global(sym).expect("name expected to exist someplace(?)"); + let global = self + .compile + .lookup_global(sym) + .expect("name expected to exist someplace(?)"); thunk = Inst::PopGlobal(Some(global)).into(); } } @@ -368,7 +379,7 @@ impl Visit for CompileBody<'_> { // - push const // (functions are unique const values so a new function will be created for every literal // function defined in code) - + // This is pretty much the only place where a new scope layer gets pushed beyond the start // of the program self.compile.push_scope_layer(); @@ -378,9 +389,7 @@ impl Visit for CompileBody<'_> { } // Compile function body - let mut code = self.visit_body(&expr.body)? - .flatten() - .to_vec(); + let mut code = self.visit_body(&expr.body)?.flatten().to_vec(); // If the last instruction is not a return, or if there are no instructions, then return // :nil value. @@ -390,7 +399,9 @@ impl Visit for CompileBody<'_> { } // remap (Sym -> Name) to be (Name -> Sym) and make sure it's all in order. - let scope_locals: BTreeMap<_, _> = self.compile.pop_scope_layer() + let scope_locals: BTreeMap<_, _> = self + .compile + .pop_scope_layer() .unwrap() .into_iter() .map(|(sym, name)| (name, sym)) @@ -399,7 +410,8 @@ impl Visit for CompileBody<'_> { // this should be in numeric order since: // 1. locals are created exactly once or looked up // 2. scope_locals is a btreemap, keyed by names, which are in order from 0..N - let locals: FunLocals = scope_locals.into_iter() + let locals: FunLocals = scope_locals + .into_iter() .enumerate() .map(|(index, (name, sym))| { assert_eq!(index, name.index()); @@ -407,7 +419,9 @@ impl Visit for CompileBody<'_> { }) .collect(); - let (hdl, _fun) = self.compile.push_const(UserFun::new_obj(code, locals, expr.params.len())); + let (hdl, _fun) = + self.compile + .push_const(UserFun::new_obj(code, locals, expr.params.len())); // TODO(compile) : determine return value at the end of the body (preferably at parse-time) @@ -427,7 +441,10 @@ impl Visit for CompileBody<'_> { // This checks to make sure that it's both a local variable and that there's more // than one scope layer. let sym = global_sym(ident.to_string()); - if let (true, Some(local)) = (self.compile.scope().layers_len() > 1, self.compile.lookup_local(sym)) { + if let (true, Some(local)) = ( + self.compile.scope().layers_len() > 1, + self.compile.lookup_local(sym), + ) { // get local Inst::LoadLocal(local).into() } else { @@ -466,25 +483,20 @@ fn test_flatten_thunk() { let init_body = vec![ Inst::PushSym(Sym::new(0)), Inst::PushSym(Sym::new(1)), - Inst::Call(1) + Inst::Call(1), ]; let true_body = vec![Inst::PushSym(Sym::new(2))]; let false_body = vec![Inst::PushSym(Sym::new(3))]; - let end_body = vec![ - Inst::PushSym(Sym::new(1)), - Inst::Call(1) - ]; + let end_body = vec![Inst::PushSym(Sym::new(1)), Inst::Call(1)]; let thunk = Thunk::List(vec![ // do something before Thunk::Body(init_body.clone()), - // branch Thunk::Branch { thunk_true: Thunk::Body(true_body.clone()).into(), thunk_false: Thunk::Body(false_body.clone()).into(), }, - // do something after Thunk::Body(end_body.clone()), ]); @@ -495,10 +507,55 @@ fn test_flatten_thunk() { assert_eq!(blocks.len(), block_count); let mut iter = blocks.into_iter(); - assert_eq!(iter.next().unwrap(), (0, BasicBlock::Block { exit: 1, block: init_body, })); - assert_eq!(iter.next().unwrap(), (1, BasicBlock::Branch { block_true: 2, block_false: 3, })); - assert_eq!(iter.next().unwrap(), (2, BasicBlock::Block { exit: 4, block: true_body, })); - assert_eq!(iter.next().unwrap(), (3, BasicBlock::Block { exit: 4, block: false_body, })); - assert_eq!(iter.next().unwrap(), (4, BasicBlock::Block { exit: 5, block: end_body, })); + assert_eq!( + iter.next().unwrap(), + ( + 0, + BasicBlock::Block { + exit: 1, + block: init_body, + } + ) + ); + assert_eq!( + iter.next().unwrap(), + ( + 1, + BasicBlock::Branch { + block_true: 2, + block_false: 3, + } + ) + ); + assert_eq!( + iter.next().unwrap(), + ( + 2, + BasicBlock::Block { + exit: 4, + block: true_body, + } + ) + ); + assert_eq!( + iter.next().unwrap(), + ( + 3, + BasicBlock::Block { + exit: 4, + block: false_body, + } + ) + ); + assert_eq!( + iter.next().unwrap(), + ( + 4, + BasicBlock::Block { + exit: 5, + block: end_body, + } + ) + ); assert!(iter.next().is_none()); } diff --git a/src/lib.rs b/src/lib.rs index 6ef273b..a404eac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,6 @@ #[macro_use] pub mod obj; -pub mod syn; pub mod compile; +pub mod syn; pub mod vm; diff --git a/src/obj/attrs.rs b/src/obj/attrs.rs index c04051a..f912ed8 100644 --- a/src/obj/attrs.rs +++ b/src/obj/attrs.rs @@ -1,6 +1,9 @@ -use crate::obj::{ObjRef, sym::Sym}; +use crate::obj::{sym::Sym, ObjRef}; use shredder::{Gc, Scan}; -use std::{collections::BTreeMap, ops::{Deref, DerefMut}}; +use std::{ + collections::BTreeMap, + ops::{Deref, DerefMut}, +}; pub type Attrs = BTreeMap; pub type VtableAttrs = Gc; @@ -12,7 +15,9 @@ pub struct Vtable { impl Vtable { pub fn new(attrs: Attrs) -> Self { - Self { attrs: Gc::new(attrs), } + Self { + attrs: Gc::new(attrs), + } } } diff --git a/src/obj/builtin.rs b/src/obj/builtin.rs index 4b4e109..7e8e12c 100644 --- a/src/obj/builtin.rs +++ b/src/obj/builtin.rs @@ -1,49 +1,72 @@ -use crate::{obj::{prelude::*, reserved::*}, vm::{error::*, signal::*}}; +use crate::{ + obj::{prelude::*, reserved::*}, + vm::{error::*, signal::*}, +}; use maplit::btreemap; use once_cell::sync::Lazy; use std::collections::BTreeMap; -pub static PRINTLN_BUILTIN_FUN: Lazy = Lazy::new(|| NativeFun::new_obj(1, |_, vm, args| { - // TODO : use __get_attr__ when it gets added - let to_string = { - let obj_ref = &args[0]; - read_obj!(let obj = obj_ref); - obj.get_attr(STR_MEMBER_NAME.sym) - .ok_or(Error::MissingAttr { attr: STR_MEMBER_NAME.sym })? - }; - let return_value = vm.call(to_string, vec![])?; - { - read_obj!(let str_obj = return_value); - let str_obj: &Str = str_obj.as_any().downcast_ref() - .ok_or_else(|| Error::ValueError { error: "expected str value".to_string(), })?; - println!("{}", str_obj.value()); - } +pub static PRINTLN_BUILTIN_FUN: Lazy = Lazy::new(|| { + NativeFun::new_obj(1, |_, vm, args| { + // TODO : use __get_attr__ when it gets added + let to_string = { + let obj_ref = &args[0]; + read_obj!(let obj = obj_ref); + obj.get_attr(STR_MEMBER_NAME.sym) + .ok_or(Error::MissingAttr { + attr: STR_MEMBER_NAME.sym, + })? + }; + let return_value = vm.call(to_string, vec![])?; + { + read_obj!(let str_obj = return_value); + let str_obj: &Str = + str_obj + .as_any() + .downcast_ref() + .ok_or_else(|| Error::ValueError { + error: "expected str value".to_string(), + })?; + println!("{}", str_obj.value()); + } - vm.push(NIL_NAME.sym_ref()); - Ok(Signal::Return) -})); - -pub static PRINT_BUILTIN_FUN: Lazy = Lazy::new(|| NativeFun::new_obj(1, |_, vm, args| { - // TODO : use __get_attr__ when it gets added - let to_string = { - let obj_ref = &args[0]; - read_obj!(let obj = obj_ref); - obj.get_attr(STR_MEMBER_NAME.sym) - .ok_or(Error::MissingAttr { attr: STR_MEMBER_NAME.sym })? - }; - let return_value = vm.call(to_string, vec![])?; - { - read_obj!(let str_obj = return_value); - let str_obj: &Str = str_obj.as_any().downcast_ref() - .ok_or_else(|| Error::ValueError { error: "expected str value".to_string(), })?; - print!("{}", str_obj.value()); - } - - vm.push(NIL_NAME.sym_ref()); - Ok(Signal::Return) -})); - -pub static BUILTIN_OBJS: Lazy> = Lazy::new(|| btreemap! { - PRINTLN_BUILTIN_NAME.sym => PRINTLN_BUILTIN_FUN.clone() as _, - PRINT_BUILTIN_NAME.sym => PRINT_BUILTIN_FUN.clone() as _, + vm.push(NIL_NAME.sym_ref()); + Ok(Signal::Return) + }) +}); + +pub static PRINT_BUILTIN_FUN: Lazy = Lazy::new(|| { + NativeFun::new_obj(1, |_, vm, args| { + // TODO : use __get_attr__ when it gets added + let to_string = { + let obj_ref = &args[0]; + read_obj!(let obj = obj_ref); + obj.get_attr(STR_MEMBER_NAME.sym) + .ok_or(Error::MissingAttr { + attr: STR_MEMBER_NAME.sym, + })? + }; + let return_value = vm.call(to_string, vec![])?; + { + read_obj!(let str_obj = return_value); + let str_obj: &Str = + str_obj + .as_any() + .downcast_ref() + .ok_or_else(|| Error::ValueError { + error: "expected str value".to_string(), + })?; + print!("{}", str_obj.value()); + } + + vm.push(NIL_NAME.sym_ref()); + Ok(Signal::Return) + }) +}); + +pub static BUILTIN_OBJS: Lazy> = Lazy::new(|| { + btreemap! { + PRINTLN_BUILTIN_NAME.sym => PRINTLN_BUILTIN_FUN.clone() as _, + PRINT_BUILTIN_NAME.sym => PRINT_BUILTIN_FUN.clone() as _, + } }); diff --git a/src/obj/fun.rs b/src/obj/fun.rs index 7bd7bbf..064ef15 100644 --- a/src/obj/fun.rs +++ b/src/obj/fun.rs @@ -1,7 +1,14 @@ -use crate::{obj::{reserved::*, prelude::*}, vm::{consts::ConstPool, error::*, frame::*, inst::Inst, signal::*, Vm}}; +use crate::{ + obj::{prelude::*, reserved::*}, + vm::{consts::ConstPool, error::*, frame::*, inst::Inst, signal::*, Vm}, +}; use once_cell::sync::Lazy; use shredder::{GcSafeWrapper, Scan}; -use std::{fmt::{Debug, Formatter, self}, io::{self, Write}, sync::Arc}; +use std::{ + fmt::{self, Debug, Formatter}, + io::{self, Write}, + sync::Arc, +}; pub type FunLocals = Vec; @@ -49,9 +56,13 @@ impl Obj for Method { Some(&mut self.attrs) } - fn as_any(&self) -> &dyn std::any::Any { self } + fn as_any(&self) -> &dyn std::any::Any { + self + } - fn as_fun(&self) -> Option<&dyn Fun> { Some(self) } + fn as_fun(&self) -> Option<&dyn Fun> { + Some(self) + } } impl Fun for Method { @@ -110,7 +121,12 @@ impl UserFun { &self.locals } - pub fn dump(&self, writer: &mut dyn Write, const_pool: &ConstPool, globals: &FunLocals) -> io::Result<()> { + pub fn dump( + &self, + writer: &mut dyn Write, + const_pool: &ConstPool, + globals: &FunLocals, + ) -> io::Result<()> { fn num_digits(n: usize, radix: usize) -> usize { ((n as f64) + 1.0).log(radix as f64).ceil() as usize } @@ -126,21 +142,22 @@ impl UserFun { sym.index().to_string(), global_sym_lookup(*sym).unwrap().to_string(), ), - Inst::PushConst(hdl) => ( - hdl.index().to_string(), - { - let obj_ref = const_pool.get(*hdl); - read_obj!(let obj = obj_ref); - format!("{:?}", obj) - }, - ), + Inst::PushConst(hdl) => (hdl.index().to_string(), { + let obj_ref = const_pool.get(*hdl); + read_obj!(let obj = obj_ref); + format!("{:?}", obj) + }), Inst::LoadLocal(local) => ( local.index().to_string(), - global_sym_lookup(self.locals()[local.index()]).unwrap().to_string(), + global_sym_lookup(self.locals()[local.index()]) + .unwrap() + .to_string(), ), Inst::LoadGlobal(global) => ( global.index().to_string(), - global_sym_lookup(globals[global.index()]).unwrap().to_string(), + global_sym_lookup(globals[global.index()]) + .unwrap() + .to_string(), ), Inst::PopLocal(local) => { if let Some(local) = local { @@ -153,7 +170,7 @@ impl UserFun { } } Inst::PopGlobal(global) => { - if let Some(global) = global{ + if let Some(global) = global { let index = global.index(); let sym = globals[index]; let name = global_sym_lookup(sym).unwrap().to_string(); @@ -162,14 +179,8 @@ impl UserFun { ("(discarded)".to_string(), String::new()) } } - Inst::Jump(addr) | Inst::JumpTrue(addr) => ( - addr.to_string(), - String::new(), - ), - Inst::Call(argc) => ( - argc.to_string(), - String::new(), - ), + Inst::Jump(addr) | Inst::JumpTrue(addr) => (addr.to_string(), String::new()), + Inst::Call(argc) => (argc.to_string(), String::new()), _ => (String::new(), String::new()), }; @@ -224,12 +235,13 @@ impl Fun for UserFun { got: args.len(), }); } - let bindings: FrameBindings = args.into_iter() - .enumerate() - .collect(); - Ok(Frame::User( - UserFrame::new(callee, bindings, vm.pc(), Arc::clone(&self.code)) - )) + let bindings: FrameBindings = args.into_iter().enumerate().collect(); + Ok(Frame::User(UserFrame::new( + callee, + bindings, + vm.pc(), + Arc::clone(&self.code), + ))) } } @@ -294,7 +306,10 @@ impl NativeFun { impl Debug for NativeFun { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { fmt.debug_struct("NativeFun") - .field("fun", &format!("(function at {:x})", &self.fun as *const _ as usize)) + .field( + "fun", + &format!("(function at {:x})", &self.fun as *const _ as usize), + ) .field("attrs", &self.attrs) .finish() } @@ -330,9 +345,7 @@ impl Fun for NativeFun { got: args.len(), }); } - Ok(Frame::Native( - NativeFrame::new(callee, *self.fun, args) - )) + Ok(Frame::Native(NativeFrame::new(callee, *self.fun, args))) } } diff --git a/src/obj/int.rs b/src/obj/int.rs index 79670c8..a32ce5d 100644 --- a/src/obj/int.rs +++ b/src/obj/int.rs @@ -1,7 +1,10 @@ -use crate::{obj::{prelude::*, reserved::*}, vm::error::*}; +use crate::{ + obj::{prelude::*, reserved::*}, + vm::error::*, +}; use once_cell::sync::Lazy; use shredder::Scan; -use std::fmt::{Debug, Formatter, self}; +use std::fmt::{self, Debug, Formatter}; pub type IntRef = ObjRef; pub type IntValue = i128; @@ -43,9 +46,7 @@ impl_obj_readonly!(Int); impl Debug for Int { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - fmt.debug_struct("Int") - .field("value", &self.value) - .finish() + fmt.debug_struct("Int").field("value", &self.value).finish() } } diff --git a/src/obj/intern.rs b/src/obj/intern.rs index d8a873f..25e7893 100644 --- a/src/obj/intern.rs +++ b/src/obj/intern.rs @@ -9,14 +9,12 @@ pub struct Interner { impl Interner { pub fn new(forward: Vec>) -> Self { - let reverse = forward.iter() + let reverse = forward + .iter() .enumerate() .map(|(i, s)| (Arc::clone(s), Sym::new(i))) .collect(); - Self { - forward, - reverse, - } + Self { forward, reverse } } pub fn forward(&self) -> &Vec> { @@ -41,18 +39,19 @@ impl Interner { } pub fn lookup(&self, sym: Sym) -> Option> { - self.forward.get(sym.index()) - .map(Arc::clone) + self.forward.get(sym.index()).map(Arc::clone) } pub fn lookup_sym(&self, value: impl std::borrow::Borrow) -> Option { - self.reverse.get(value.borrow()) - .copied() + self.reverse.get(value.borrow()).copied() } } impl Default for Interner { fn default() -> Self { - Interner { forward: Default::default(), reverse: Default::default(), } + Interner { + forward: Default::default(), + reverse: Default::default(), + } } } diff --git a/src/obj/macros.rs b/src/obj/macros.rs index 86ea908..e3f6471 100644 --- a/src/obj/macros.rs +++ b/src/obj/macros.rs @@ -14,7 +14,7 @@ macro_rules! impl_obj { fn attrs_mut(&mut self) -> Option<&mut $crate::obj::attrs::Attrs> { Some(&mut self.$attrs) } - + fn as_any(&self) -> &dyn std::any::Any { self } @@ -23,7 +23,7 @@ macro_rules! impl_obj { ($ty:ty) => { impl_obj!($ty, vtable, attrs); - } + }; } #[macro_export] diff --git a/src/obj/mod.rs b/src/obj/mod.rs index 70f6307..5c82dfd 100644 --- a/src/obj/mod.rs +++ b/src/obj/mod.rs @@ -40,7 +40,7 @@ macro_rules! obj_attr { fn $name(&self) -> Option { self.get_attr($attr.sym) } - } + }; } pub trait Obj: Scan + Debug { @@ -58,7 +58,9 @@ pub trait Obj: Scan + Debug { fn as_any(&self) -> &dyn std::any::Any; /// Gets this object as a `dyn Fun` reference. - fn as_fun(&self) -> Option<&dyn Fun> { None } + fn as_fun(&self) -> Option<&dyn Fun> { + None + } obj_attr!(get_ty, TY_MEMBER_NAME); obj_attr!(get_call, CALL_MEMBER_NAME); @@ -140,7 +142,8 @@ where // impl Debug for ObjRef // impl Debug for ObjRef - where T: Obj + ?Sized + Send + Sync + 'static, +where + T: Obj + ?Sized + Send + Sync + 'static, { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { read_obj!(let obj: &T = self); diff --git a/src/obj/reserved.rs b/src/obj/reserved.rs index 4b8c471..31dc835 100644 --- a/src/obj/reserved.rs +++ b/src/obj/reserved.rs @@ -1,6 +1,6 @@ //! Reserved names for object members. -use crate::obj::sym::{Sym, SymRef, global_sym, global_sym_ref}; +use crate::obj::sym::{global_sym, global_sym_ref, Sym, SymRef}; use once_cell::sync::Lazy; macro_rules! name { @@ -8,9 +8,9 @@ macro_rules! name { pub static $name: Lazy = Lazy::new(|| { let name = $text; let sym = global_sym(name.to_string()); - NameInfo { name, sym, } + NameInfo { name, sym } }); - } + }; } pub struct NameInfo { @@ -79,4 +79,3 @@ name!(PLUS_OP_NAME, "__add__"); name!(MINUS_OP_NAME, "__sub__"); name!(TIMES_OP_NAME, "__mul__"); name!(DIV_OP_NAME, "__div__"); - diff --git a/src/obj/str.rs b/src/obj/str.rs index 27503be..bfd727b 100644 --- a/src/obj/str.rs +++ b/src/obj/str.rs @@ -1,7 +1,10 @@ -use crate::{obj::{prelude::*, reserved::*}, vm::error::*}; +use crate::{ + obj::{prelude::*, reserved::*}, + vm::error::*, +}; use once_cell::sync::Lazy; use shredder::Scan; -use std::fmt::{Debug, Formatter, self}; +use std::fmt::{self, Debug, Formatter}; pub type StrRef = ObjRef; @@ -37,9 +40,7 @@ impl_obj_readonly!(Str); impl Debug for Str { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { - fmt.debug_struct("Str") - .field("value", &self.value) - .finish() + fmt.debug_struct("Str").field("value", &self.value).finish() } } @@ -86,8 +87,9 @@ static STR_INT_FUN: Lazy = Lazy::new(|| { error: "expected Str value".to_string(), })?; - let int: IntValue = str_obj.value.parse() - .map_err(|_| Error::ValueError { error: "invalid Int value".to_string(), })?; + let int: IntValue = str_obj.value.parse().map_err(|_| Error::ValueError { + error: "invalid Int value".to_string(), + })?; vm.push(Int::new_obj(int)); Ok(crate::vm::signal::Signal::Return) diff --git a/src/obj/sym.rs b/src/obj/sym.rs index 0eed22d..b5f1855 100644 --- a/src/obj/sym.rs +++ b/src/obj/sym.rs @@ -1,6 +1,9 @@ -use crate::obj::{intern::Interner, reserved::*, prelude::*}; +use crate::obj::{intern::Interner, prelude::*, reserved::*}; use once_cell::sync::Lazy; -use std::{collections::BTreeMap, sync::{Arc, Mutex}}; +use std::{ + collections::BTreeMap, + sync::{Arc, Mutex}, +}; // // struct Sym diff --git a/src/obj/ty.rs b/src/obj/ty.rs index d9c5976..ef62076 100644 --- a/src/obj/ty.rs +++ b/src/obj/ty.rs @@ -1,4 +1,4 @@ -use crate::obj::{reserved::*, prelude::*}; +use crate::obj::{prelude::*, reserved::*}; use once_cell::sync::Lazy; use shredder::Scan; diff --git a/src/syn/ast.rs b/src/syn/ast.rs index b313614..4d5851c 100644 --- a/src/syn/ast.rs +++ b/src/syn/ast.rs @@ -13,10 +13,9 @@ impl Accept for Body { } } -impl> DefaultAccept for Body { +impl> DefaultAccept for Body { fn default_accept(&self, visitor: &mut V) -> V::Out { - self.iter() - .for_each(|stmt| visitor.visit_stmt(stmt)); + self.iter().for_each(|stmt| visitor.visit_stmt(stmt)); } } @@ -67,7 +66,7 @@ impl Accept for AssignStmt { // // impl DefaultAccept for AssignStmt // -impl> DefaultAccept for AssignStmt { +impl> DefaultAccept for AssignStmt { fn default_accept(&self, visitor: &mut V) -> V::Out { self.lhs.accept(visitor); self.rhs.accept(visitor); @@ -92,11 +91,11 @@ impl Accept for LhsExpr { // // impl DefaultAccept for LhsExpr // -impl> DefaultAccept for LhsExpr { +impl> DefaultAccept for LhsExpr { fn default_accept(&self, visitor: &mut V) -> V::Out { match self { LhsExpr::SetAttr(a) => a.accept(visitor), - LhsExpr::Name(_) => {}, + LhsExpr::Name(_) => {} } } } @@ -115,7 +114,7 @@ impl Accept for ReturnStmt { } } -impl> DefaultAccept for ReturnStmt { +impl> DefaultAccept for ReturnStmt { fn default_accept(&self, visitor: &mut V) -> V::Out { if let Some(expr) = self.expr.as_ref() { expr.accept(visitor) @@ -123,7 +122,6 @@ impl> DefaultAccept for ReturnStmt { } } - // // struct Expr // @@ -237,7 +235,7 @@ pub struct BinExpr { impl BinExpr { pub fn new_expr(lhs: Expr, op: BinOp, rhs: Expr) -> Expr { - Self { lhs, op, rhs, }.into() + Self { lhs, op, rhs }.into() } } @@ -253,7 +251,7 @@ impl Accept for BinExpr { // // impl DefaultAccept for BinExpr // -impl> DefaultAccept for BinExpr { +impl> DefaultAccept for BinExpr { fn default_accept(&self, visitor: &mut V) -> V::Out { visitor.visit_expr(&self.lhs); visitor.visit_expr(&self.rhs); @@ -326,11 +324,10 @@ impl Accept for CallExpr { // // impl DefaultAccept for CallExpr // -impl> DefaultAccept for CallExpr { +impl> DefaultAccept for CallExpr { fn default_accept(&self, visitor: &mut V) -> V::Out { visitor.visit_expr(&self.expr); - self.args.iter() - .for_each(|arg| visitor.visit_expr(arg)); + self.args.iter().for_each(|arg| visitor.visit_expr(arg)); } } @@ -345,7 +342,7 @@ pub struct IndexExpr { impl IndexExpr { pub fn new_expr(expr: Expr, index: Expr) -> Expr { - Self { expr, index, }.into() + Self { expr, index }.into() } } @@ -361,7 +358,7 @@ impl Accept for IndexExpr { // // impl DefaultAccept for IndexExpr // -impl> DefaultAccept for IndexExpr { +impl> DefaultAccept for IndexExpr { fn default_accept(&self, visitor: &mut V) -> V::Out { visitor.visit_expr(&self.expr); visitor.visit_expr(&self.index); @@ -379,7 +376,7 @@ pub struct AccessExpr { impl AccessExpr { pub fn new_expr(expr: Expr, access: String) -> Expr { - Self { expr, access, }.into() + Self { expr, access }.into() } } @@ -415,7 +412,7 @@ pub struct FunExpr { // impl FunExpr { pub fn new_expr(params: Vec, body: Body) -> Expr { - Self { params, body, }.into() + Self { params, body }.into() } } @@ -462,8 +459,8 @@ impl Accept for Atom { // impl DefaultAccept for Atom // -impl> DefaultAccept for Atom { - fn default_accept(&self, _visitor: &mut V) -> V::Out { } +impl> DefaultAccept for Atom { + fn default_accept(&self, _visitor: &mut V) -> V::Out {} } pub fn parse(text: &str) -> Result>, Vec> { @@ -473,9 +470,10 @@ pub fn parse(text: &str) -> Result>, Vec> { let (res, errors) = parser::parse(&lexer); if !errors.is_empty() { - return Err(errors.into_iter() + return Err(errors + .into_iter() .map(|e| e.pp(&lexer, &parser::token_epp)) - .collect()) + .collect()); } Ok(res.transpose().unwrap()) diff --git a/src/syn/mod.rs b/src/syn/mod.rs index 8116462..53649c1 100644 --- a/src/syn/mod.rs +++ b/src/syn/mod.rs @@ -1,18 +1,18 @@ -#![macro_use] mod macros; +#![macro_use] pub mod ast; +mod macros; pub mod visit; pub mod lexer { lrlex_mod!("syn/lexer.l"); - use lrlex::lrlex_mod; pub use self::lexer_l::*; - + use lrlex::lrlex_mod; } pub mod parser { lrpar_mod!("syn/parser.y"); - use lrpar::lrpar_mod; pub use self::parser_y::*; + use lrpar::lrpar_mod; } //pub use lexer_l as lexer; diff --git a/src/vm/consts.rs b/src/vm/consts.rs index 0fbf54d..1c9fdfe 100644 --- a/src/vm/consts.rs +++ b/src/vm/consts.rs @@ -8,7 +8,7 @@ pub struct ConstPool { } // Constant pools are constant, and live for the lifetime of the entire program. -impl shredder::EmptyScan for ConstPool { } +impl shredder::EmptyScan for ConstPool {} impl ConstPool { pub fn new() -> Self { diff --git a/src/vm/error.rs b/src/vm/error.rs index 6fd8a2a..79ccf93 100644 --- a/src/vm/error.rs +++ b/src/vm/error.rs @@ -4,20 +4,17 @@ use snafu::Snafu; #[derive(Debug, Snafu)] pub enum Error { #[snafu(display("missing attribute: {}", global_sym_lookup(*attr).unwrap()))] - MissingAttr { - attr: Sym, - }, + MissingAttr { attr: Sym }, #[snafu(display("{}", error))] - ValueError { - error: String, - }, + ValueError { error: String }, - #[snafu(display("incorrect function arity; expected {} but got {} instead", expected, got))] - ArityError { - expected: usize, - got: usize, - }, + #[snafu(display( + "incorrect function arity; expected {} but got {} instead", + expected, + got + ))] + ArityError { expected: usize, got: usize }, } pub type Result = std::result::Result; diff --git a/src/vm/frame.rs b/src/vm/frame.rs index 8d2b99e..4f55b4f 100644 --- a/src/vm/frame.rs +++ b/src/vm/frame.rs @@ -1,6 +1,6 @@ use crate::{obj::prelude::*, vm::inst::Inst}; +use std::fmt::{self, Debug, Formatter}; use std::{collections::BTreeMap, sync::Arc}; -use std::fmt::{self, Formatter, Debug}; pub type FrameBindings = BTreeMap; @@ -53,8 +53,18 @@ pub struct UserFrame { } impl UserFrame { - pub fn new(callee: ObjRef, bindings: FrameBindings, last_pc: usize, code: Arc>) -> Self { - Self { callee, bindings, last_pc, code, } + pub fn new( + callee: ObjRef, + bindings: FrameBindings, + last_pc: usize, + code: Arc>, + ) -> Self { + Self { + callee, + bindings, + last_pc, + code, + } } pub fn bindings(&self) -> &FrameBindings { @@ -86,7 +96,11 @@ pub struct NativeFrame { impl NativeFrame { pub fn new(callee: ObjRef, fun_ptr: NativeFunPtr, args: Vec) -> Self { - Self { callee, fun_ptr, args } + Self { + callee, + fun_ptr, + args, + } } pub fn fun_ptr(&self) -> &NativeFunPtr { @@ -105,7 +119,10 @@ impl NativeFrame { impl Debug for NativeFrame { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { fmt.debug_struct("NativeFrame") - .field("fun_ptr", &format!("{:#x}", &self.fun_ptr as *const _ as usize)) + .field( + "fun_ptr", + &format!("{:#x}", &self.fun_ptr as *const _ as usize), + ) .finish() } } diff --git a/src/vm/inst.rs b/src/vm/inst.rs index a8d534d..69e561c 100644 --- a/src/vm/inst.rs +++ b/src/vm/inst.rs @@ -154,4 +154,4 @@ impl Inst { } } -impl EmptyScan for Inst { } +impl EmptyScan for Inst {} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 0a83b3e..c4db78f 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -5,7 +5,7 @@ pub mod inst; pub mod signal; use crate::{ - obj::{builtin::BUILTIN_OBJS, reserved::*, prelude::*}, + obj::{builtin::BUILTIN_OBJS, prelude::*, reserved::*}, vm::{consts::ConstPool, error::*, frame::*, inst::*, signal::*}, }; @@ -19,7 +19,7 @@ pub struct Vm<'c> { } impl<'c> Vm<'c> { - pub fn new(const_pool: &'c ConstPool,) -> Self { + pub fn new(const_pool: &'c ConstPool) -> Self { Self { stack: Default::default(), frames: vec![], @@ -122,9 +122,7 @@ impl<'c> Vm<'c> { let args = fun.args().clone(); (*fun.fun_ptr())(callee, self, args)? } - Frame::User(_) => { - self.resume_user_fun() - } + Frame::User(_) => self.resume_user_fun(), }; self.handle_signal(signal)?; } @@ -148,8 +146,11 @@ impl<'c> Vm<'c> { match signal { Signal::Call(callee, args) => { read_obj!(let callee_obj = callee); - let frame = callee_obj.as_fun() - .ok_or_else(|| Error::ValueError { error: "cannot call this object".to_string() })? + let frame = callee_obj + .as_fun() + .ok_or_else(|| Error::ValueError { + error: "cannot call this object".to_string(), + })? .create_frame(callee.clone(), self, args)?; // Jump to the first address of the new function call if it's a user function if let Frame::User(_) = &frame { @@ -207,19 +208,20 @@ impl<'c> Vm<'c> { self.push(obj_ref); } Inst::LoadLocal(local) => { - let value = self.get_local(local) + let value = self + .get_local(local) .expect("TODO: throw error for missing local"); self.push(value); } Inst::LoadGlobal(global) => { - let value = self.get_global(global) + let value = self + .get_global(global) .or_else(|| self.get_builtin(global)) .expect("TODO: throw error for missing global"); self.push(value); } Inst::PopLocal(name) => { - let tos = self.pop() - .expect("stack underflow"); + let tos = self.pop().expect("stack underflow"); // pop into name if let Some(name) = name { self.set_local(name, tos); @@ -227,8 +229,7 @@ impl<'c> Vm<'c> { // else discard } Inst::PopGlobal(name) => { - let tos = self.pop() - .expect("stack underflow"); + let tos = self.pop().expect("stack underflow"); // pop into name if let Some(name) = name { self.set_global(name, tos); @@ -244,10 +245,8 @@ impl<'c> Vm<'c> { self.push(attr); } Inst::SetAttr(sym) => { - let target = self.pop() - .expect("no target available for SetAttr"); - let source = self.pop() - .expect("no source available for SetAttr"); + let target = self.pop().expect("no target available for SetAttr"); + let source = self.pop().expect("no source available for SetAttr"); write_obj!(let target = target); if let Some(attrs) = target.attrs_mut() { attrs.insert(sym, source); @@ -266,15 +265,17 @@ impl<'c> Vm<'c> { Inst::Call(argc) => { let stack_top = self.stack.len() - argc; let args = self.stack.split_off(stack_top); - let tos = self.pop() - .expect("stack underflow"); + let tos = self.pop().expect("stack underflow"); read_obj!(let tos = tos); - let callee = tos.get_call() + let callee = tos + .get_call() .expect("TODO: throw an error for missing __call__ attr"); signal = Some(Signal::Call(callee, args)); } Inst::Index => todo!(), - Inst::Return => { signal = Some(Signal::Return); } + Inst::Return => { + signal = Some(Signal::Return); + } Inst::UnNeg => todo!(), Inst::UnPos => todo!(), Inst::BinPlus => { @@ -282,7 +283,8 @@ impl<'c> Vm<'c> { let lhs = self.pop().unwrap(); let fun = { read_obj!(let lhs = lhs); - lhs.get_plus().expect("TODO: throw an error for missing __add__ attr") + lhs.get_plus() + .expect("TODO: throw an error for missing __add__ attr") }; signal = Some(Signal::Call(fun, vec![rhs])); } @@ -291,7 +293,8 @@ impl<'c> Vm<'c> { let lhs = self.pop().unwrap(); let fun = { read_obj!(let lhs = lhs); - lhs.get_minus().expect("TODO: throw an error for missing __sub__ attr") + lhs.get_minus() + .expect("TODO: throw an error for missing __sub__ attr") }; signal = Some(Signal::Call(fun, vec![rhs])); } @@ -300,7 +303,8 @@ impl<'c> Vm<'c> { let lhs = self.pop().unwrap(); let fun = { read_obj!(let lhs = lhs); - lhs.get_mul().expect("TODO: throw an error for missing __mul__ attr") + lhs.get_mul() + .expect("TODO: throw an error for missing __mul__ attr") }; signal = Some(Signal::Call(fun, vec![rhs])); } @@ -309,7 +313,8 @@ impl<'c> Vm<'c> { let lhs = self.pop().unwrap(); let fun = { read_obj!(let lhs = lhs); - lhs.get_div().expect("TODO: throw an error for missing __div__ attr") + lhs.get_div() + .expect("TODO: throw an error for missing __div__ attr") }; signal = Some(Signal::Call(fun, vec![rhs])); } @@ -318,7 +323,8 @@ impl<'c> Vm<'c> { let lhs = self.pop().unwrap(); let fun = { read_obj!(let lhs = lhs); - lhs.get_eq().expect("TODO: throw an error for missing __eq__ attr") + lhs.get_eq() + .expect("TODO: throw an error for missing __eq__ attr") }; signal = Some(Signal::Call(fun, vec![rhs])); } @@ -342,7 +348,7 @@ impl<'c> Vm<'c> { .get(&name.index()) .cloned() } - + fn set_local(&mut self, name: Name, value: ObjRef) { let frame = self .frame_mut() @@ -363,7 +369,8 @@ impl<'c> Vm<'c> { } fn set_global(&mut self, name: Name, value: ObjRef) { - let frame = self.frames_mut() + let frame = self + .frames_mut() .first_mut() .expect("global stack frame") .user_frame_mut() diff --git a/src/vm/signal.rs b/src/vm/signal.rs index 8475137..44f90b1 100644 --- a/src/vm/signal.rs +++ b/src/vm/signal.rs @@ -6,4 +6,3 @@ pub enum Signal { Call(ObjRef, Vec), Return, } -