Run rustfmt

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-10-20 16:21:50 -07:00
parent ceda48988d
commit 692bb521ec
27 changed files with 402 additions and 251 deletions

View File

@@ -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(());

View File

@@ -10,4 +10,3 @@ pub enum Error {
}
pub type Result<T, E = Error> = std::result::Result<T, E>;

View File

@@ -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);
}
}

View File

@@ -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.

View File

@@ -11,9 +11,7 @@ pub struct Scope {
impl Scope {
pub fn lookup_local(&self, sym: Sym) -> Option<Name> {
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<Name> {
@@ -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 {

View File

@@ -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());
}

View File

@@ -3,6 +3,6 @@
#[macro_use]
pub mod obj;
pub mod syn;
pub mod compile;
pub mod syn;
pub mod vm;

View File

@@ -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<Sym, ObjRef>;
pub type VtableAttrs = Gc<Attrs>;
@@ -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),
}
}
}

View File

@@ -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<NativeFunRef> = 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<NativeFunRef> = 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<NativeFunRef> = 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<BTreeMap<Sym, ObjRef>> = 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<NativeFunRef> = 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<BTreeMap<Sym, ObjRef>> = Lazy::new(|| {
btreemap! {
PRINTLN_BUILTIN_NAME.sym => PRINTLN_BUILTIN_FUN.clone() as _,
PRINT_BUILTIN_NAME.sym => PRINT_BUILTIN_FUN.clone() as _,
}
});

View File

@@ -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<Sym>;
@@ -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)))
}
}

View File

@@ -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<Int>;
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()
}
}

View File

@@ -9,14 +9,12 @@ pub struct Interner<T: Hash + Eq> {
impl<T: Hash + Eq> Interner<T> {
pub fn new(forward: Vec<Arc<T>>) -> 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<Arc<T>> {
@@ -41,18 +39,19 @@ impl<T: Hash + Eq> Interner<T> {
}
pub fn lookup(&self, sym: Sym) -> Option<Arc<T>> {
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<T>) -> Option<Sym> {
self.reverse.get(value.borrow())
.copied()
self.reverse.get(value.borrow()).copied()
}
}
impl<T: Hash + Eq> Default for Interner<T> {
fn default() -> Self {
Interner { forward: Default::default(), reverse: Default::default(), }
Interner {
forward: Default::default(),
reverse: Default::default(),
}
}
}

View File

@@ -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]

View File

@@ -40,7 +40,7 @@ macro_rules! obj_attr {
fn $name(&self) -> Option<ObjRef> {
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<T> Debug for ObjRef<T>
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);

View File

@@ -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<NameInfo> = 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__");

View File

@@ -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<Str>;
@@ -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<NativeFunRef> = 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)

View File

@@ -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

View File

@@ -1,4 +1,4 @@
use crate::obj::{reserved::*, prelude::*};
use crate::obj::{prelude::*, reserved::*};
use once_cell::sync::Lazy;
use shredder::Scan;

View File

@@ -13,10 +13,9 @@ impl<V: Visit> Accept<V> for Body {
}
}
impl<V: Visit<Out=()>> DefaultAccept<V> for Body {
impl<V: Visit<Out = ()>> DefaultAccept<V> 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<V: Visit> Accept<V> for AssignStmt {
//
// impl DefaultAccept for AssignStmt
//
impl<V: Visit<Out=()>> DefaultAccept<V> for AssignStmt {
impl<V: Visit<Out = ()>> DefaultAccept<V> for AssignStmt {
fn default_accept(&self, visitor: &mut V) -> V::Out {
self.lhs.accept(visitor);
self.rhs.accept(visitor);
@@ -92,11 +91,11 @@ impl<V: Visit> Accept<V> for LhsExpr {
//
// impl DefaultAccept for LhsExpr
//
impl<V: Visit<Out=()>> DefaultAccept<V> for LhsExpr {
impl<V: Visit<Out = ()>> DefaultAccept<V> 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<V: Visit> Accept<V> for ReturnStmt {
}
}
impl<V: Visit<Out=()>> DefaultAccept<V> for ReturnStmt {
impl<V: Visit<Out = ()>> DefaultAccept<V> 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<V: Visit<Out=()>> DefaultAccept<V> 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<V: Visit> Accept<V> for BinExpr {
//
// impl DefaultAccept for BinExpr
//
impl<V: Visit<Out=()>> DefaultAccept<V> for BinExpr {
impl<V: Visit<Out = ()>> DefaultAccept<V> 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<V: Visit> Accept<V> for CallExpr {
//
// impl DefaultAccept for CallExpr
//
impl<V: Visit<Out=()>> DefaultAccept<V> for CallExpr {
impl<V: Visit<Out = ()>> DefaultAccept<V> 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<V: Visit> Accept<V> for IndexExpr {
//
// impl DefaultAccept for IndexExpr
//
impl<V: Visit<Out=()>> DefaultAccept<V> for IndexExpr {
impl<V: Visit<Out = ()>> DefaultAccept<V> 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<String>, body: Body) -> Expr {
Self { params, body, }.into()
Self { params, body }.into()
}
}
@@ -462,8 +459,8 @@ impl<V: Visit> Accept<V> for Atom {
// impl DefaultAccept for Atom
//
impl<V: Visit<Out=()>> DefaultAccept<V> for Atom {
fn default_accept(&self, _visitor: &mut V) -> V::Out { }
impl<V: Visit<Out = ()>> DefaultAccept<V> for Atom {
fn default_accept(&self, _visitor: &mut V) -> V::Out {}
}
pub fn parse(text: &str) -> Result<Option<Vec<Stmt>>, Vec<String>> {
@@ -473,9 +470,10 @@ pub fn parse(text: &str) -> Result<Option<Vec<Stmt>>, Vec<String>> {
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())

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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<T, E = Error> = std::result::Result<T, E>;

View File

@@ -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<usize, ObjRef>;
@@ -53,8 +53,18 @@ pub struct UserFrame {
}
impl UserFrame {
pub fn new(callee: ObjRef, bindings: FrameBindings, last_pc: usize, code: Arc<Vec<Inst>>) -> Self {
Self { callee, bindings, last_pc, code, }
pub fn new(
callee: ObjRef,
bindings: FrameBindings,
last_pc: usize,
code: Arc<Vec<Inst>>,
) -> 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<ObjRef>) -> 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()
}
}

View File

@@ -154,4 +154,4 @@ impl Inst {
}
}
impl EmptyScan for Inst { }
impl EmptyScan for Inst {}

View File

@@ -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()

View File

@@ -6,4 +6,3 @@ pub enum Signal {
Call(ObjRef, Vec<ObjRef>),
Return,
}