mirror of
https://github.com/MorizzG/rlox.git
synced 2025-12-06 04:12:42 +00:00
rustfmt with nightly options
also some other minor formatting changes
This commit is contained in:
parent
671f7d5306
commit
f8b59e6034
17 changed files with 91 additions and 291 deletions
|
|
@ -16,7 +16,8 @@ pub struct LoxClass {
|
|||
methods: FxHashMap<String, Value>,
|
||||
}
|
||||
|
||||
/// Representation of a class in Lox. Always behind an Rc to ensure uniqueness. Should never be handled raw.
|
||||
/// Representation of a class in Lox. Always behind an Rc to ensure uniqueness. Should never be
|
||||
/// handled raw.
|
||||
impl LoxClass {
|
||||
pub fn new(
|
||||
name: impl Into<SmolStr>,
|
||||
|
|
@ -81,19 +82,10 @@ impl LoxClass {
|
|||
return method.arity();
|
||||
}
|
||||
|
||||
/* if let Some(superclass) = self.superclass {
|
||||
return superclass.arity();
|
||||
} */
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
pub fn get_method(&self, name: &str, this: LoxReference) -> Option<Value> {
|
||||
/* self.methods
|
||||
.get(name)
|
||||
.cloned()
|
||||
.or_else(|| self.superclass.as_ref().and_then(|cls| cls.get_method(name))) */
|
||||
|
||||
if let Some(method) = self.methods.get(name) {
|
||||
match method {
|
||||
Value::Function(method) => {
|
||||
|
|
@ -111,19 +103,6 @@ impl LoxClass {
|
|||
|
||||
None
|
||||
}
|
||||
|
||||
/* pub fn init(&self, args: Vec<Value>, env: &mut Environment) -> EvalResult<()> {
|
||||
if let Some(ref superclass) = self.superclass {
|
||||
let args = args.clone();
|
||||
superclass.init(args, env)?;
|
||||
}
|
||||
|
||||
if let Some(Value::Function(method)) = self.get_method("init") {
|
||||
method.call(args, env)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} */
|
||||
}
|
||||
|
||||
impl Display for LoxClass {
|
||||
|
|
@ -138,7 +117,8 @@ impl Display for LoxClass {
|
|||
}
|
||||
|
||||
// slightly hacky: two classes are equal if they are stored at the same location
|
||||
// since a LoxClass is always (supposed to be) behind an Rc anyways, we might as well compare their pointers
|
||||
// since a LoxClass is always (supposed to be) behind an Rc anyways, we might as well compare their
|
||||
// pointers
|
||||
impl PartialEq for LoxClass {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let self_ptr = self as *const LoxClass;
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ use std::rc::Rc;
|
|||
use rustc_hash::FxHashMap;
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
|
||||
use super::{Runtime, Value};
|
||||
use crate::error::RuntimeError;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HeapedValue {
|
||||
|
|
@ -145,9 +144,9 @@ impl<'a> Environment<'a> {
|
|||
!self.scope_stack.is_empty()
|
||||
}
|
||||
|
||||
/* fn current_scope(&self) -> &Scope {
|
||||
self.scope_stack.last().unwrap()
|
||||
} */
|
||||
// fn current_scope(&self) -> &Scope {
|
||||
// self.scope_stack.last().unwrap()
|
||||
// }
|
||||
|
||||
fn current_scope_mut(&mut self) -> &mut Scope {
|
||||
self.scope_stack.last_mut().unwrap()
|
||||
|
|
@ -193,11 +192,7 @@ impl<'a> Environment<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
panic!("Name not defined not caught by resolver");
|
||||
|
||||
/* Err(RuntimeError::NameNotDefined {
|
||||
name: name.to_owned(),
|
||||
}) */
|
||||
panic!("{self}\n\nvar {name} not at level {level} where expected");
|
||||
}
|
||||
|
||||
pub fn get_local_heaped(
|
||||
|
|
@ -213,11 +208,7 @@ impl<'a> Environment<'a> {
|
|||
return Ok(scoped_value.heapified());
|
||||
}
|
||||
|
||||
panic!("Name not defined not caught by resolver");
|
||||
|
||||
/* Err(RuntimeError::NameNotDefined {
|
||||
name: name.to_owned(),
|
||||
}) */
|
||||
panic!("{self}\n\nheaped var {name} not at level {level} where expected");
|
||||
}
|
||||
|
||||
pub fn define(&mut self, name: impl Into<SmolStr>, value: Value) {
|
||||
|
|
@ -314,59 +305,3 @@ impl Write for Environment<'_> {
|
|||
self.runtime.flush()
|
||||
}
|
||||
}
|
||||
|
||||
/*====================================================================================================================*/
|
||||
|
||||
/* struct Frame {
|
||||
scopes: Vec<Scope>,
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
fn new(base_scope: Scope) -> Self {
|
||||
Frame {
|
||||
scopes: vec![base_scope],
|
||||
}
|
||||
}
|
||||
|
||||
fn new_global() -> Self {
|
||||
Frame { scopes: Vec::new() }
|
||||
}
|
||||
|
||||
fn enter_scope(&mut self) {
|
||||
self.scopes.push(Scope::new());
|
||||
}
|
||||
|
||||
fn exit_scope(&mut self) {
|
||||
self.scopes.pop().expect("Tried to exit scope, but no scope to exit");
|
||||
}
|
||||
|
||||
fn get(&self, name: &str) -> Option<Value> {
|
||||
for scope in self.scopes.iter().rev() {
|
||||
if let Some(heap_value) = scope.get(name) {
|
||||
return Some(heap_value.get_clone());
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn try_define(&mut self, name: impl Into<String> + Borrow<str>, value: Value) -> Result<(), Value> {
|
||||
if let Some(scope) = self.scopes.last_mut() {
|
||||
scope.insert(name.into(), HeapValue::new(value));
|
||||
Ok(())
|
||||
} else {
|
||||
Err(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_assign(&mut self, name: &str, value: Value) -> Result<(), Value> {
|
||||
for scope in self.scopes.iter_mut().rev() {
|
||||
if let Some(heap_value) = scope.get_mut(name) {
|
||||
heap_value.replace(value);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(value)
|
||||
}
|
||||
} */
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ use rlox2_frontend::parser::{BinaryOp, ParserError, UnaryOp};
|
|||
use smol_str::SmolStr;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::Value;
|
||||
use crate::{LoxClass, ResolverError};
|
||||
use crate::{LoxClass, ResolverError, Value};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum RuntimeError {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ impl Display for LoxFunction {
|
|||
}
|
||||
|
||||
// slightly hacky: two functions are equal if they are stored at the same location
|
||||
// since a LoxFunction is always (supposed to be) behind an Rc anyways, we might as well compare their pointers
|
||||
// since a LoxFunction is always (supposed to be) behind an Rc anyways, we might as well compare
|
||||
// their pointers
|
||||
impl PartialEq for LoxFunction {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let self_ptr = self as *const LoxFunction;
|
||||
|
|
@ -78,7 +79,7 @@ impl PartialEq for LoxFunction {
|
|||
}
|
||||
}
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
pub type ExternFunClosure = fn(Vec<Value>, &mut Environment) -> EvalResult<Value>;
|
||||
|
||||
|
|
@ -135,7 +136,8 @@ impl Debug for LoxExternFunction {
|
|||
}
|
||||
|
||||
// slightly hacky: two extern functions are equal if they are stored at the same location
|
||||
// since a LoxExternFunction is always (supposed to be) behind an Rc anyways, we might as well compare their pointers
|
||||
// since a LoxExternFunction is always (supposed to be) behind an Rc anyways, we might as well
|
||||
// compare their pointers
|
||||
impl PartialEq for LoxExternFunction {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let self_ptr = self as *const LoxExternFunction;
|
||||
|
|
|
|||
|
|
@ -3,16 +3,15 @@ use std::rc::Rc;
|
|||
use rlox2_frontend::parser::{BinaryOp, Expr, Literal, LogicalOp, Stmt, UnaryOp};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use super::environment::Environment;
|
||||
use super::{LoxFunction, Runtime, Value};
|
||||
use crate::error::RuntimeError;
|
||||
use crate::function::LoxExternFunction;
|
||||
use crate::{LoxClass, LoxReference};
|
||||
|
||||
use super::environment::Environment;
|
||||
use super::{LoxFunction, Runtime, Value};
|
||||
|
||||
pub type EvalResult<T> = Result<T, RuntimeError>;
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
pub fn execute(statement: Stmt, runtime: &mut Runtime) -> Result<(), RuntimeError> {
|
||||
let mut env = Environment::new(runtime);
|
||||
|
|
@ -22,7 +21,7 @@ pub fn execute(statement: Stmt, runtime: &mut Runtime) -> Result<(), RuntimeErro
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
trait Eval {
|
||||
fn eval(&self, env: &mut Environment) -> EvalResult<Value>;
|
||||
|
|
@ -214,6 +213,7 @@ impl Eval for Expr {
|
|||
|
||||
for method_expr in method_exprs.iter() {
|
||||
let method = method_expr.eval(env)?;
|
||||
|
||||
if let Value::Function(ref fun) = method {
|
||||
let name = fun.name().to_owned();
|
||||
methods.insert(name, method);
|
||||
|
|
@ -307,7 +307,7 @@ impl Eval for Stmt {
|
|||
}
|
||||
}
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
pub fn call_fun(fun: Rc<LoxFunction>, env: &mut Environment) -> EvalResult<Value> {
|
||||
let args = env.collect_args();
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
use smol_str::SmolStr;
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
|
||||
use super::function::{ExternFunClosure, LoxExternFunction};
|
||||
use super::{Runtime, Value};
|
||||
use crate::error::RuntimeError;
|
||||
|
||||
pub fn init_std(env: &mut Runtime) {
|
||||
clock().register(env);
|
||||
|
|
@ -13,6 +12,38 @@ pub fn init_std(env: &mut Runtime) {
|
|||
print_globals().register(env);
|
||||
}
|
||||
|
||||
fn clock() -> LoxExternFunction {
|
||||
let closure: ExternFunClosure = |args, _env| {
|
||||
assert_eq!(args.len(), 0);
|
||||
let time = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs_f64();
|
||||
|
||||
Ok(Value::Number(time))
|
||||
};
|
||||
|
||||
LoxExternFunction::new("clock", 0, closure)
|
||||
}
|
||||
|
||||
fn exit() -> LoxExternFunction {
|
||||
let closure: ExternFunClosure = |args, _env| {
|
||||
assert_eq!(args.len(), 1);
|
||||
if let Value::Number(exit_code) = args[0] {
|
||||
if exit_code.fract() == 0.0 {
|
||||
let exit_code = exit_code as i32;
|
||||
return Err(RuntimeError::Exit { exit_code });
|
||||
}
|
||||
}
|
||||
Err(RuntimeError::ExtFunCallFailed {
|
||||
name: "exit".to_owned(),
|
||||
msg: "Arguments to exit() must an integer".to_owned(),
|
||||
})
|
||||
};
|
||||
|
||||
LoxExternFunction::new("exit", 1, closure)
|
||||
}
|
||||
|
||||
fn input() -> LoxExternFunction {
|
||||
let closure: ExternFunClosure = |args, _env| {
|
||||
assert_eq!(args.len(), 0);
|
||||
|
|
@ -32,18 +63,14 @@ fn input() -> LoxExternFunction {
|
|||
LoxExternFunction::new("input", 0, closure)
|
||||
}
|
||||
|
||||
fn clock() -> LoxExternFunction {
|
||||
let closure: ExternFunClosure = |args, _env| {
|
||||
fn print_env() -> LoxExternFunction {
|
||||
let closure: ExternFunClosure = |args, env| {
|
||||
assert_eq!(args.len(), 0);
|
||||
let time = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_secs_f64();
|
||||
|
||||
Ok(Value::Number(time))
|
||||
println!("{env}");
|
||||
Ok(Value::Nil)
|
||||
};
|
||||
|
||||
LoxExternFunction::new("clock", 0, closure)
|
||||
LoxExternFunction::new("print_env", 0, closure)
|
||||
}
|
||||
|
||||
fn print_globals() -> LoxExternFunction {
|
||||
|
|
@ -62,31 +89,3 @@ fn print_globals() -> LoxExternFunction {
|
|||
|
||||
LoxExternFunction::new("print_globals", 0, closure)
|
||||
}
|
||||
|
||||
fn print_env() -> LoxExternFunction {
|
||||
let closure: ExternFunClosure = |args, env| {
|
||||
assert_eq!(args.len(), 0);
|
||||
println!("{env}");
|
||||
Ok(Value::Nil)
|
||||
};
|
||||
|
||||
LoxExternFunction::new("print_env", 0, closure)
|
||||
}
|
||||
|
||||
fn exit() -> LoxExternFunction {
|
||||
let closure: ExternFunClosure = |args, _env| {
|
||||
assert_eq!(args.len(), 1);
|
||||
if let Value::Number(exit_code) = args[0] {
|
||||
if exit_code.fract() == 0.0 {
|
||||
let exit_code = exit_code as i32;
|
||||
return Err(RuntimeError::Exit { exit_code });
|
||||
}
|
||||
}
|
||||
Err(RuntimeError::ExtFunCallFailed {
|
||||
name: "exit".to_owned(),
|
||||
msg: "Arguments to exit() must an integer".to_owned(),
|
||||
})
|
||||
};
|
||||
|
||||
LoxExternFunction::new("exit", 1, closure)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,11 @@ impl LoxObject {
|
|||
}
|
||||
}
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
/// Pointer-like to LoxObject. Has interior mutability, which means it can't give out references to its interior.
|
||||
/// Also includes the possibility of weird, self-referential constructions that lead to unsafe beheaviour,
|
||||
/// so make sure not to do any (too) weird shit here.
|
||||
/// Pointer-like to LoxObject. Has interior mutability, which means it can't give out references to
|
||||
/// its interior. Also includes the possibility of weird, self-referential constructions that lead
|
||||
/// to unsafe beheaviour, so make sure not to do any (too) weird shit here.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LoxReference {
|
||||
inner: Rc<UnsafeCell<LoxObject>>,
|
||||
|
|
@ -83,10 +83,6 @@ impl LoxReference {
|
|||
object.set(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
/* pub fn init(&self, args: Vec<Value>, env: &mut Environment) -> EvalResult<()> {
|
||||
self.class().init(self.clone(), args, env)
|
||||
} */
|
||||
}
|
||||
|
||||
impl PartialEq for LoxReference {
|
||||
|
|
|
|||
|
|
@ -2,17 +2,16 @@ use rlox2_frontend::parser::{Expr, Stmt};
|
|||
use rustc_hash::FxHashMap;
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use crate::Runtime;
|
||||
use crate::{LoxError, ResolverError};
|
||||
use crate::{LoxError, ResolverError, Runtime};
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
type ResolverScope = FxHashMap<SmolStr, ResolveStatus>;
|
||||
// type ResolverFrame = Vec<ResolverScope>;
|
||||
|
||||
type ResolverResult<T> = Result<T, ResolverError>;
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum ResolveStatus {
|
||||
|
|
@ -36,7 +35,7 @@ impl ResolverFrame {
|
|||
}
|
||||
}
|
||||
|
||||
/*====================================================================================================================*/
|
||||
// =================================================================================================
|
||||
|
||||
pub fn resolve(statement: &mut Stmt, runtime: &mut Runtime) -> Result<(), LoxError> {
|
||||
let global_names = runtime.globals().keys().cloned();
|
||||
|
|
@ -88,9 +87,9 @@ impl Resolver {
|
|||
&mut self.frame_mut().scopes
|
||||
}
|
||||
|
||||
/* fn closure_vars(&self) -> &FxHashMap<SmolStr, usize> {
|
||||
&self.frame().closure_vars
|
||||
} */
|
||||
// fn closure_vars(&self) -> &FxHashMap<SmolStr, usize> {
|
||||
// &self.frame().closure_vars
|
||||
// }
|
||||
|
||||
fn closure_vars_mut(&mut self) -> &mut FxHashMap<SmolStr, usize> {
|
||||
&mut self.frame_mut().closure_vars
|
||||
|
|
@ -186,7 +185,7 @@ impl Resolver {
|
|||
|
||||
// if we have more than one frame: look for closure variable
|
||||
if self.frames.len() > 1 {
|
||||
//try to resolve closure variable up from one frame down
|
||||
// try to resolve closure variable up from one frame down
|
||||
if let Some(level) = self.resolve_closure(name.clone(), self.frames.len() - 2) {
|
||||
self.closure_vars_mut().insert(name.clone(), level);
|
||||
|
||||
|
|
@ -340,8 +339,6 @@ impl Resolver {
|
|||
closure_vars,
|
||||
body,
|
||||
} => {
|
||||
// let old_closure_names = std::mem::take(&mut self.closure_vars);
|
||||
|
||||
self.push_frame();
|
||||
|
||||
self.declare(name.clone())?;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
use rlox2_frontend::lexer::{scan_tokens, Token};
|
||||
use rlox2_frontend::parser::parse_tokens;
|
||||
|
||||
use super::Runtime;
|
||||
use crate::error::LoxError;
|
||||
use crate::interpreter::execute;
|
||||
use crate::resolver::resolve;
|
||||
|
||||
use super::Runtime;
|
||||
|
||||
pub fn run(source: &str, runtime: &mut Runtime) -> Result<(), LoxError> {
|
||||
let tokens: Vec<Token> = scan_tokens(source)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@ use std::rc::Rc;
|
|||
use rustc_hash::FxHashMap;
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use crate::error::RuntimeError;
|
||||
|
||||
use super::lox_std::init_std;
|
||||
use super::Value;
|
||||
use crate::error::RuntimeError;
|
||||
|
||||
pub struct Runtime {
|
||||
globals: FxHashMap<SmolStr, Value>,
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@ use std::rc::Rc;
|
|||
|
||||
use smol_str::SmolStr;
|
||||
|
||||
use crate::{LoxClass, LoxReference};
|
||||
|
||||
use super::function::LoxExternFunction;
|
||||
use super::LoxFunction;
|
||||
use crate::{LoxClass, LoxReference};
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq)]
|
||||
pub enum Value {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue