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
|
|
@ -3,7 +3,7 @@ use smol_str::SmolStr;
|
||||||
|
|
||||||
use super::{CodePos, LexerError, Token, TokenType};
|
use super::{CodePos, LexerError, Token, TokenType};
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
static KEYWORDS: phf::Map<&'static str, TokenType> = phf_map! {
|
static KEYWORDS: phf::Map<&'static str, TokenType> = phf_map! {
|
||||||
"and" => TokenType::And,
|
"and" => TokenType::And,
|
||||||
|
|
@ -25,7 +25,7 @@ static KEYWORDS: phf::Map<&'static str, TokenType> = phf_map! {
|
||||||
"while" => TokenType::While
|
"while" => TokenType::While
|
||||||
};
|
};
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
pub fn scan_tokens(source_code: &str) -> Result<Vec<Token>, Vec<LexerError>> {
|
pub fn scan_tokens(source_code: &str) -> Result<Vec<Token>, Vec<LexerError>> {
|
||||||
let lexer = Lexer::new(source_code);
|
let lexer = Lexer::new(source_code);
|
||||||
|
|
@ -33,7 +33,7 @@ pub fn scan_tokens(source_code: &str) -> Result<Vec<Token>, Vec<LexerError>> {
|
||||||
lexer.scan_tokens()
|
lexer.scan_tokens()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Lexer {
|
struct Lexer {
|
||||||
|
|
@ -242,18 +242,6 @@ impl Lexer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_parse_string(&mut self) {
|
fn try_parse_string(&mut self) {
|
||||||
// first '"' already consumed
|
|
||||||
|
|
||||||
// advance until second "
|
|
||||||
/* while self.advance() != '"' {
|
|
||||||
if self.source_is_empty() {
|
|
||||||
self.errors.push(LexerError::UnterminatedStringLiteral {
|
|
||||||
code_pos: self.code_pos,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
|
|
||||||
let starting_pos = self.code_pos;
|
let starting_pos = self.code_pos;
|
||||||
|
|
@ -356,11 +344,6 @@ impl Lexer {
|
||||||
|
|
||||||
let lexeme: String = self.source[self.start..self.current].iter().collect();
|
let lexeme: String = self.source[self.start..self.current].iter().collect();
|
||||||
|
|
||||||
/* let token_type = KEYWORDS
|
|
||||||
.get(&lexeme)
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(TokenType::Identifier(Box::new(lexeme))); */
|
|
||||||
|
|
||||||
if let Some(token_type) = KEYWORDS.get(&lexeme) {
|
if let Some(token_type) = KEYWORDS.get(&lexeme) {
|
||||||
// Token::new(token_type, self.code_pos)
|
// Token::new(token_type, self.code_pos)
|
||||||
self.push_token(token_type.clone());
|
self.push_token(token_type.clone());
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
use crate::lexer::{Token, TokenType};
|
|
||||||
use crate::parser::expr::BinaryOp;
|
|
||||||
|
|
||||||
use super::expr::{Expr, UnaryOp};
|
use super::expr::{Expr, UnaryOp};
|
||||||
use super::{LogicalOp, ParserError, Stmt};
|
use super::{LogicalOp, ParserError, Stmt};
|
||||||
|
use crate::lexer::{Token, TokenType};
|
||||||
|
use crate::parser::expr::BinaryOp;
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
type ParserResult<T> = Result<T, ParserError>;
|
type ParserResult<T> = Result<T, ParserError>;
|
||||||
|
|
||||||
|
|
@ -14,7 +13,7 @@ pub fn parse_tokens(tokens: Vec<Token>) -> Result<Vec<Stmt>, Vec<ParserError>> {
|
||||||
Parser::new(tokens).parse()
|
Parser::new(tokens).parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
// takes care of token iteration
|
// takes care of token iteration
|
||||||
struct TokenIter {
|
struct TokenIter {
|
||||||
|
|
@ -71,7 +70,7 @@ impl Iterator for TokenIter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
struct Parser {
|
struct Parser {
|
||||||
token_iter: TokenIter,
|
token_iter: TokenIter,
|
||||||
|
|
@ -413,6 +412,7 @@ impl Parser {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let is_in_init = self.is_in_init;
|
let is_in_init = self.is_in_init;
|
||||||
|
|
||||||
if &*method_name == "init" {
|
if &*method_name == "init" {
|
||||||
self.is_in_init = true;
|
self.is_in_init = true;
|
||||||
}
|
}
|
||||||
|
|
@ -841,21 +841,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_token(&mut self) -> Token {
|
fn next_token(&mut self) -> Token {
|
||||||
/* let token = self.token_iter.next().unwrap();
|
self.token_iter.next().unwrap()
|
||||||
|
|
||||||
// println!("Next token: {next:?}");
|
|
||||||
|
|
||||||
if token.token_type == TokenType::EOF {
|
|
||||||
panic!("Someone ate a EOF token");
|
|
||||||
}
|
|
||||||
|
|
||||||
// if token.token_type == TokenType::Print {
|
|
||||||
// panic!("Found the print");
|
|
||||||
// }
|
|
||||||
|
|
||||||
token */
|
|
||||||
|
|
||||||
self.token_iter.next().unwrap() // .ok_or(ParserError::TokenStreamEnded)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek_token(&mut self) -> &Token {
|
fn peek_token(&mut self) -> &Token {
|
||||||
|
|
@ -866,14 +852,6 @@ impl Parser {
|
||||||
where
|
where
|
||||||
F: Fn(&Token) -> ParserError,
|
F: Fn(&Token) -> ParserError,
|
||||||
{
|
{
|
||||||
/* let token = self.next_token();
|
|
||||||
|
|
||||||
if token.token_type == token_type {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(err_fn(token))
|
|
||||||
} */
|
|
||||||
|
|
||||||
match &self.peek_token().token_type {
|
match &self.peek_token().token_type {
|
||||||
tt if tt == &token_type => {
|
tt if tt == &token_type => {
|
||||||
let _ = self.next_token();
|
let _ = self.next_token();
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::lexer::{CodePos, Token};
|
|
||||||
|
|
||||||
use super::Expr;
|
use super::Expr;
|
||||||
|
use crate::lexer::{CodePos, Token};
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ParserError {
|
pub enum ParserError {
|
||||||
|
|
|
||||||
|
|
@ -155,10 +155,9 @@ impl Expr {
|
||||||
|
|
||||||
pub fn function(name: impl Into<SmolStr>, param_names: Vec<SmolStr>, body: Stmt) -> Self {
|
pub fn function(name: impl Into<SmolStr>, param_names: Vec<SmolStr>, body: Stmt) -> Self {
|
||||||
let name = name.into();
|
let name = name.into();
|
||||||
#[allow(clippy::box_default)]
|
|
||||||
// let closure_vars = Box::new(Vec::new());
|
|
||||||
let closure_vars = Vec::new();
|
let closure_vars = Vec::new();
|
||||||
let body = Box::new(body);
|
let body = Box::new(body);
|
||||||
|
|
||||||
Self::Function {
|
Self::Function {
|
||||||
name,
|
name,
|
||||||
param_names,
|
param_names,
|
||||||
|
|
@ -264,7 +263,7 @@ impl Display for Expr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
|
|
@ -285,7 +284,7 @@ impl Display for Literal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum UnaryOp {
|
pub enum UnaryOp {
|
||||||
|
|
@ -302,7 +301,7 @@ impl Display for UnaryOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ pub struct LoxClass {
|
||||||
methods: FxHashMap<String, Value>,
|
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 {
|
impl LoxClass {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
name: impl Into<SmolStr>,
|
name: impl Into<SmolStr>,
|
||||||
|
|
@ -81,19 +82,10 @@ impl LoxClass {
|
||||||
return method.arity();
|
return method.arity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if let Some(superclass) = self.superclass {
|
|
||||||
return superclass.arity();
|
|
||||||
} */
|
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_method(&self, name: &str, this: LoxReference) -> Option<Value> {
|
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) {
|
if let Some(method) = self.methods.get(name) {
|
||||||
match method {
|
match method {
|
||||||
Value::Function(method) => {
|
Value::Function(method) => {
|
||||||
|
|
@ -111,19 +103,6 @@ impl LoxClass {
|
||||||
|
|
||||||
None
|
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 {
|
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
|
// 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 {
|
impl PartialEq for LoxClass {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
let self_ptr = self as *const LoxClass;
|
let self_ptr = self as *const LoxClass;
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,8 @@ use std::rc::Rc;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
use crate::error::RuntimeError;
|
|
||||||
|
|
||||||
use super::{Runtime, Value};
|
use super::{Runtime, Value};
|
||||||
|
use crate::error::RuntimeError;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct HeapedValue {
|
pub struct HeapedValue {
|
||||||
|
|
@ -145,9 +144,9 @@ impl<'a> Environment<'a> {
|
||||||
!self.scope_stack.is_empty()
|
!self.scope_stack.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fn current_scope(&self) -> &Scope {
|
// fn current_scope(&self) -> &Scope {
|
||||||
self.scope_stack.last().unwrap()
|
// self.scope_stack.last().unwrap()
|
||||||
} */
|
// }
|
||||||
|
|
||||||
fn current_scope_mut(&mut self) -> &mut Scope {
|
fn current_scope_mut(&mut self) -> &mut Scope {
|
||||||
self.scope_stack.last_mut().unwrap()
|
self.scope_stack.last_mut().unwrap()
|
||||||
|
|
@ -193,11 +192,7 @@ impl<'a> Environment<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("Name not defined not caught by resolver");
|
panic!("{self}\n\nvar {name} not at level {level} where expected");
|
||||||
|
|
||||||
/* Err(RuntimeError::NameNotDefined {
|
|
||||||
name: name.to_owned(),
|
|
||||||
}) */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_local_heaped(
|
pub fn get_local_heaped(
|
||||||
|
|
@ -213,11 +208,7 @@ impl<'a> Environment<'a> {
|
||||||
return Ok(scoped_value.heapified());
|
return Ok(scoped_value.heapified());
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("Name not defined not caught by resolver");
|
panic!("{self}\n\nheaped var {name} not at level {level} where expected");
|
||||||
|
|
||||||
/* Err(RuntimeError::NameNotDefined {
|
|
||||||
name: name.to_owned(),
|
|
||||||
}) */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn define(&mut self, name: impl Into<SmolStr>, value: Value) {
|
pub fn define(&mut self, name: impl Into<SmolStr>, value: Value) {
|
||||||
|
|
@ -314,59 +305,3 @@ impl Write for Environment<'_> {
|
||||||
self.runtime.flush()
|
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 smol_str::SmolStr;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::Value;
|
use crate::{LoxClass, ResolverError, Value};
|
||||||
use crate::{LoxClass, ResolverError};
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum RuntimeError {
|
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
|
// 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 {
|
impl PartialEq for LoxFunction {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
let self_ptr = self as *const LoxFunction;
|
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>;
|
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
|
// 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 {
|
impl PartialEq for LoxExternFunction {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
let self_ptr = self as *const LoxExternFunction;
|
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 rlox2_frontend::parser::{BinaryOp, Expr, Literal, LogicalOp, Stmt, UnaryOp};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use super::environment::Environment;
|
||||||
|
use super::{LoxFunction, Runtime, Value};
|
||||||
use crate::error::RuntimeError;
|
use crate::error::RuntimeError;
|
||||||
use crate::function::LoxExternFunction;
|
use crate::function::LoxExternFunction;
|
||||||
use crate::{LoxClass, LoxReference};
|
use crate::{LoxClass, LoxReference};
|
||||||
|
|
||||||
use super::environment::Environment;
|
|
||||||
use super::{LoxFunction, Runtime, Value};
|
|
||||||
|
|
||||||
pub type EvalResult<T> = Result<T, RuntimeError>;
|
pub type EvalResult<T> = Result<T, RuntimeError>;
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
pub fn execute(statement: Stmt, runtime: &mut Runtime) -> Result<(), RuntimeError> {
|
pub fn execute(statement: Stmt, runtime: &mut Runtime) -> Result<(), RuntimeError> {
|
||||||
let mut env = Environment::new(runtime);
|
let mut env = Environment::new(runtime);
|
||||||
|
|
@ -22,7 +21,7 @@ pub fn execute(statement: Stmt, runtime: &mut Runtime) -> Result<(), RuntimeErro
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
trait Eval {
|
trait Eval {
|
||||||
fn eval(&self, env: &mut Environment) -> EvalResult<Value>;
|
fn eval(&self, env: &mut Environment) -> EvalResult<Value>;
|
||||||
|
|
@ -214,6 +213,7 @@ impl Eval for Expr {
|
||||||
|
|
||||||
for method_expr in method_exprs.iter() {
|
for method_expr in method_exprs.iter() {
|
||||||
let method = method_expr.eval(env)?;
|
let method = method_expr.eval(env)?;
|
||||||
|
|
||||||
if let Value::Function(ref fun) = method {
|
if let Value::Function(ref fun) = method {
|
||||||
let name = fun.name().to_owned();
|
let name = fun.name().to_owned();
|
||||||
methods.insert(name, method);
|
methods.insert(name, method);
|
||||||
|
|
@ -307,7 +307,7 @@ impl Eval for Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
pub fn call_fun(fun: Rc<LoxFunction>, env: &mut Environment) -> EvalResult<Value> {
|
pub fn call_fun(fun: Rc<LoxFunction>, env: &mut Environment) -> EvalResult<Value> {
|
||||||
let args = env.collect_args();
|
let args = env.collect_args();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
use crate::error::RuntimeError;
|
|
||||||
|
|
||||||
use super::function::{ExternFunClosure, LoxExternFunction};
|
use super::function::{ExternFunClosure, LoxExternFunction};
|
||||||
use super::{Runtime, Value};
|
use super::{Runtime, Value};
|
||||||
|
use crate::error::RuntimeError;
|
||||||
|
|
||||||
pub fn init_std(env: &mut Runtime) {
|
pub fn init_std(env: &mut Runtime) {
|
||||||
clock().register(env);
|
clock().register(env);
|
||||||
|
|
@ -13,6 +12,38 @@ pub fn init_std(env: &mut Runtime) {
|
||||||
print_globals().register(env);
|
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 {
|
fn input() -> LoxExternFunction {
|
||||||
let closure: ExternFunClosure = |args, _env| {
|
let closure: ExternFunClosure = |args, _env| {
|
||||||
assert_eq!(args.len(), 0);
|
assert_eq!(args.len(), 0);
|
||||||
|
|
@ -32,18 +63,14 @@ fn input() -> LoxExternFunction {
|
||||||
LoxExternFunction::new("input", 0, closure)
|
LoxExternFunction::new("input", 0, closure)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clock() -> LoxExternFunction {
|
fn print_env() -> LoxExternFunction {
|
||||||
let closure: ExternFunClosure = |args, _env| {
|
let closure: ExternFunClosure = |args, env| {
|
||||||
assert_eq!(args.len(), 0);
|
assert_eq!(args.len(), 0);
|
||||||
let time = std::time::SystemTime::now()
|
println!("{env}");
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
Ok(Value::Nil)
|
||||||
.unwrap()
|
|
||||||
.as_secs_f64();
|
|
||||||
|
|
||||||
Ok(Value::Number(time))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
LoxExternFunction::new("clock", 0, closure)
|
LoxExternFunction::new("print_env", 0, closure)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_globals() -> LoxExternFunction {
|
fn print_globals() -> LoxExternFunction {
|
||||||
|
|
@ -62,31 +89,3 @@ fn print_globals() -> LoxExternFunction {
|
||||||
|
|
||||||
LoxExternFunction::new("print_globals", 0, closure)
|
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.
|
/// Pointer-like to LoxObject. Has interior mutability, which means it can't give out references to
|
||||||
/// Also includes the possibility of weird, self-referential constructions that lead to unsafe beheaviour,
|
/// its interior. Also includes the possibility of weird, self-referential constructions that lead
|
||||||
/// so make sure not to do any (too) weird shit here.
|
/// to unsafe beheaviour, so make sure not to do any (too) weird shit here.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LoxReference {
|
pub struct LoxReference {
|
||||||
inner: Rc<UnsafeCell<LoxObject>>,
|
inner: Rc<UnsafeCell<LoxObject>>,
|
||||||
|
|
@ -83,10 +83,6 @@ impl LoxReference {
|
||||||
object.set(name, value)
|
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 {
|
impl PartialEq for LoxReference {
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,16 @@ use rlox2_frontend::parser::{Expr, Stmt};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
use crate::Runtime;
|
use crate::{LoxError, ResolverError, Runtime};
|
||||||
use crate::{LoxError, ResolverError};
|
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
type ResolverScope = FxHashMap<SmolStr, ResolveStatus>;
|
type ResolverScope = FxHashMap<SmolStr, ResolveStatus>;
|
||||||
// type ResolverFrame = Vec<ResolverScope>;
|
// type ResolverFrame = Vec<ResolverScope>;
|
||||||
|
|
||||||
type ResolverResult<T> = Result<T, ResolverError>;
|
type ResolverResult<T> = Result<T, ResolverError>;
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum ResolveStatus {
|
enum ResolveStatus {
|
||||||
|
|
@ -36,7 +35,7 @@ impl ResolverFrame {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*====================================================================================================================*/
|
// =================================================================================================
|
||||||
|
|
||||||
pub fn resolve(statement: &mut Stmt, runtime: &mut Runtime) -> Result<(), LoxError> {
|
pub fn resolve(statement: &mut Stmt, runtime: &mut Runtime) -> Result<(), LoxError> {
|
||||||
let global_names = runtime.globals().keys().cloned();
|
let global_names = runtime.globals().keys().cloned();
|
||||||
|
|
@ -88,9 +87,9 @@ impl Resolver {
|
||||||
&mut self.frame_mut().scopes
|
&mut self.frame_mut().scopes
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fn closure_vars(&self) -> &FxHashMap<SmolStr, usize> {
|
// fn closure_vars(&self) -> &FxHashMap<SmolStr, usize> {
|
||||||
&self.frame().closure_vars
|
// &self.frame().closure_vars
|
||||||
} */
|
// }
|
||||||
|
|
||||||
fn closure_vars_mut(&mut self) -> &mut FxHashMap<SmolStr, usize> {
|
fn closure_vars_mut(&mut self) -> &mut FxHashMap<SmolStr, usize> {
|
||||||
&mut self.frame_mut().closure_vars
|
&mut self.frame_mut().closure_vars
|
||||||
|
|
@ -340,8 +339,6 @@ impl Resolver {
|
||||||
closure_vars,
|
closure_vars,
|
||||||
body,
|
body,
|
||||||
} => {
|
} => {
|
||||||
// let old_closure_names = std::mem::take(&mut self.closure_vars);
|
|
||||||
|
|
||||||
self.push_frame();
|
self.push_frame();
|
||||||
|
|
||||||
self.declare(name.clone())?;
|
self.declare(name.clone())?;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
use rlox2_frontend::lexer::{scan_tokens, Token};
|
use rlox2_frontend::lexer::{scan_tokens, Token};
|
||||||
use rlox2_frontend::parser::parse_tokens;
|
use rlox2_frontend::parser::parse_tokens;
|
||||||
|
|
||||||
|
use super::Runtime;
|
||||||
use crate::error::LoxError;
|
use crate::error::LoxError;
|
||||||
use crate::interpreter::execute;
|
use crate::interpreter::execute;
|
||||||
use crate::resolver::resolve;
|
use crate::resolver::resolve;
|
||||||
|
|
||||||
use super::Runtime;
|
|
||||||
|
|
||||||
pub fn run(source: &str, runtime: &mut Runtime) -> Result<(), LoxError> {
|
pub fn run(source: &str, runtime: &mut Runtime) -> Result<(), LoxError> {
|
||||||
let tokens: Vec<Token> = scan_tokens(source)?;
|
let tokens: Vec<Token> = scan_tokens(source)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@ use std::rc::Rc;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
use crate::error::RuntimeError;
|
|
||||||
|
|
||||||
use super::lox_std::init_std;
|
use super::lox_std::init_std;
|
||||||
use super::Value;
|
use super::Value;
|
||||||
|
use crate::error::RuntimeError;
|
||||||
|
|
||||||
pub struct Runtime {
|
pub struct Runtime {
|
||||||
globals: FxHashMap<SmolStr, Value>,
|
globals: FxHashMap<SmolStr, Value>,
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,9 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use smol_str::SmolStr;
|
use smol_str::SmolStr;
|
||||||
|
|
||||||
use crate::{LoxClass, LoxReference};
|
|
||||||
|
|
||||||
use super::function::LoxExternFunction;
|
use super::function::LoxExternFunction;
|
||||||
use super::LoxFunction;
|
use super::LoxFunction;
|
||||||
|
use crate::{LoxClass, LoxReference};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq)]
|
#[derive(Debug, Default, Clone, PartialEq)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
|
|
|
||||||
33
src/main.rs
33
src/main.rs
|
|
@ -19,44 +19,11 @@ struct CliArgs {
|
||||||
debug: bool,
|
debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
let source_code = std::fs::read_to_string(script_path).unwrap_or_else(|err| {
|
|
||||||
eprintln!("Reading script file {script_path} failed: {err}");
|
|
||||||
std::process::exit(66);
|
|
||||||
}); */
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let cli_args = CliArgs::parse();
|
let cli_args = CliArgs::parse();
|
||||||
|
|
||||||
if cli_args.vm {
|
if cli_args.vm {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
/* use rlox2_vm::LoxError;
|
|
||||||
|
|
||||||
let mut vm = rlox2_vm::VM::default();
|
|
||||||
|
|
||||||
if let Some(file_name) = cli_args.file_name {
|
|
||||||
let source = std::fs::read_to_string(&file_name).unwrap_or_else(|err| {
|
|
||||||
eprintln!("Reading script file {file_name} failed: {err}");
|
|
||||||
std::process::exit(66);
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Err(err) = rlox2_vm::run(&source, &mut vm) {
|
|
||||||
eprintln!("{err}");
|
|
||||||
match err {
|
|
||||||
LoxError::LexerError { .. } | LoxError::CompileError { .. } => {
|
|
||||||
std::process::exit(65)
|
|
||||||
}
|
|
||||||
LoxError::RuntimeError { .. } => std::process::exit(70),
|
|
||||||
LoxError::Exit { exit_code } => std::process::exit(exit_code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !cli_args.interactive {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rlox2_vm::run_repl(&mut vm); */
|
|
||||||
} else {
|
} else {
|
||||||
use rlox2_interpreter::LoxError;
|
use rlox2_interpreter::LoxError;
|
||||||
|
|
||||||
|
|
|
||||||
33
src/repl.rs
33
src/repl.rs
|
|
@ -151,36 +151,7 @@ pub fn run_repl<F: FnMut(&str) -> LoxResult<E>, E: Error>(mut run: F) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 'inner: loop {
|
readline.save_history("/tmp/rlox_history.txt").unwrap();
|
||||||
let num_open_braces =
|
|
||||||
(input_buf.matches('{').count() as i64) - (input_buf.matches('}').count() as i64);
|
|
||||||
let num_open_parens =
|
|
||||||
(input_buf.matches('(').count() as i64) - (input_buf.matches(')').count() as i64);
|
|
||||||
let num_open_brackets =
|
|
||||||
(input_buf.matches('[').count() as i64) - (input_buf.matches(']').count() as i64);
|
|
||||||
|
|
||||||
// all braces/parens/brackets closed => break
|
|
||||||
if num_open_braces == 0 && num_open_parens == 0 && num_open_brackets == 0 {
|
|
||||||
break 'inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
// any braces/parens/brackets more closing than opening => break (will be parse error)
|
|
||||||
if num_open_braces < 0 || num_open_parens < 0 || num_open_brackets < 0 {
|
|
||||||
break 'inner;
|
|
||||||
}
|
|
||||||
|
|
||||||
match readline.readline("< ") {
|
|
||||||
Ok(line) => {
|
|
||||||
input_buf += &line;
|
|
||||||
}
|
|
||||||
Err(ReadlineError::Interrupted) => continue 'outer,
|
|
||||||
Err(ReadlineError::Eof) => break 'outer,
|
|
||||||
Err(err) => {
|
|
||||||
println!("Error: {:?}", err);
|
|
||||||
continue 'outer;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} */
|
|
||||||
|
|
||||||
if input_buf.is_empty() || input_buf == "exit\n" || input_buf == "quit\n" {
|
if input_buf.is_empty() || input_buf == "exit\n" || input_buf == "quit\n" {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
|
|
@ -194,6 +165,4 @@ pub fn run_repl<F: FnMut(&str) -> LoxResult<E>, E: Error>(mut run: F) {
|
||||||
LoxResult::Exit(exit_code) => std::process::exit(exit_code),
|
LoxResult::Exit(exit_code) => std::process::exit(exit_code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readline.save_history("/tmp/rlox_history.txt").unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue