Refactored stdlib to its own crate
This commit is contained in:
parent
7173c5dda1
commit
08c0cd9173
14 changed files with 83 additions and 43 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -74,7 +74,6 @@ dependencies = [
|
||||||
"num-complex",
|
"num-complex",
|
||||||
"num-rational",
|
"num-rational",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"paste",
|
|
||||||
"strum",
|
"strum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -84,10 +83,21 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"complexpr",
|
"complexpr",
|
||||||
|
"complexpr-stdlib",
|
||||||
"rustyline",
|
"rustyline",
|
||||||
"rustyline-derive",
|
"rustyline-derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "complexpr-stdlib"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"complexpr",
|
||||||
|
"lazy_static",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -186,6 +196,12 @@ version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06"
|
checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.132"
|
version = "0.2.132"
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [ "complexpr-bin", "complexpr" ]
|
members = [ "complexpr-bin", "complexpr", "complexpr-stdlib" ]
|
||||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
complexpr = { path = "../complexpr" }
|
complexpr = { path = "../complexpr" }
|
||||||
|
complexpr-stdlib = { path = "../complexpr-stdlib" }
|
||||||
backtrace = "0.3.66"
|
backtrace = "0.3.66"
|
||||||
rustyline = { version = "10.0.0", optional = true }
|
rustyline = { version = "10.0.0", optional = true }
|
||||||
rustyline-derive = { version = "0.7.0", optional = true }
|
rustyline-derive = { version = "0.7.0", optional = true }
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::{fs, panic::{self, PanicInfo}, process::ExitCode};
|
use std::{fs, panic::{self, PanicInfo}, process::ExitCode};
|
||||||
|
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
use complexpr::{interpreter::interpret};
|
use complexpr::{interpreter::interpret, env::Environment};
|
||||||
|
|
||||||
mod helper;
|
mod helper;
|
||||||
mod repl;
|
mod repl;
|
||||||
|
@ -22,10 +22,21 @@ fn panic_hook(info: &PanicInfo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_env() -> Environment {
|
||||||
|
let mut env = Environment::new();
|
||||||
|
|
||||||
|
complexpr_stdlib::prelude::load(&mut env);
|
||||||
|
complexpr_stdlib::io::load(&mut env);
|
||||||
|
complexpr_stdlib::iter::load(&mut env);
|
||||||
|
complexpr_stdlib::math::load(&mut env);
|
||||||
|
|
||||||
|
env
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
panic::set_hook(Box::new(panic_hook));
|
panic::set_hook(Box::new(panic_hook));
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
if args.len() == 2 {
|
if args.len() >= 2 {
|
||||||
let fname = &args[1];
|
let fname = &args[1];
|
||||||
let src = match fs::read_to_string(fname) {
|
let src = match fs::read_to_string(fname) {
|
||||||
Ok(src) => src,
|
Ok(src) => src,
|
||||||
|
@ -34,7 +45,10 @@ fn main() -> ExitCode {
|
||||||
return ExitCode::from(2);
|
return ExitCode::from(2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let res = interpret(&src, Some(fname.into()), None, false);
|
|
||||||
|
let env = create_env().wrap();
|
||||||
|
|
||||||
|
let res = interpret(&src, Some(fname.into()), Some(env), false);
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
eprintln!("Error: {}", e);
|
eprintln!("Error: {}", e);
|
||||||
return ExitCode::from(1);
|
return ExitCode::from(1);
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#![cfg(feature = "repl")]
|
#![cfg(feature = "repl")]
|
||||||
|
|
||||||
use rustyline::{self, error::ReadlineError, Config, CompletionType, EditMode, hint::HistoryHinter, validate::MatchingBracketValidator, Editor};
|
use rustyline::{self, error::ReadlineError, Config, CompletionType, EditMode, hint::HistoryHinter, validate::MatchingBracketValidator, Editor};
|
||||||
use complexpr::{env::Environment, interpreter::interpret, value::Value, stdlib};
|
use complexpr::{interpreter::interpret, value::Value};
|
||||||
|
|
||||||
use crate::helper::CxprHelper;
|
|
||||||
|
use crate::{helper::CxprHelper, create_env};
|
||||||
|
|
||||||
const C_RESET: &str = "\x1b[0m";
|
const C_RESET: &str = "\x1b[0m";
|
||||||
const C_BLUE: &str = "\x1b[94m";
|
const C_BLUE: &str = "\x1b[94m";
|
||||||
|
@ -17,7 +18,7 @@ pub fn repl() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.edit_mode(EditMode::Emacs)
|
.edit_mode(EditMode::Emacs)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let env = Environment::new().wrap();
|
let env = create_env().wrap();
|
||||||
|
|
||||||
let h = CxprHelper {
|
let h = CxprHelper {
|
||||||
hinter: HistoryHinter {},
|
hinter: HistoryHinter {},
|
||||||
|
@ -36,11 +37,6 @@ pub fn repl() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
println!("Press {}Ctrl+D{} to exit.", C_BLUE, C_RESET);
|
println!("Press {}Ctrl+D{} to exit.", C_BLUE, C_RESET);
|
||||||
|
|
||||||
stdlib::load(&mut env.borrow_mut());
|
|
||||||
stdlib::io::load(&mut env.borrow_mut());
|
|
||||||
stdlib::iter::load(&mut env.borrow_mut());
|
|
||||||
stdlib::math::load(&mut env.borrow_mut());
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let readline = rl.readline(">> ");
|
let readline = rl.readline(">> ");
|
||||||
match readline {
|
match readline {
|
||||||
|
|
12
complexpr-stdlib/Cargo.toml
Normal file
12
complexpr-stdlib/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "complexpr-stdlib"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
complexpr = { path = "../complexpr"}
|
||||||
|
num-traits = "0.2.15"
|
||||||
|
paste = "1.0.9"
|
||||||
|
lazy_static = "1.4.0"
|
|
@ -1,6 +1,8 @@
|
||||||
use std::{io::{Write, Read}, fs::{OpenOptions, File}, rc::Rc, cell::RefCell, fmt};
|
use std::{io::{Write, Read}, fs::{OpenOptions, File}, rc::Rc, cell::RefCell, fmt};
|
||||||
|
|
||||||
use crate::{env::Environment, declare_fn, value::{Value, Native, TypeData}, RuntimeError};
|
use complexpr::{env::Environment, value::{Value, Native, TypeData}, RuntimeError};
|
||||||
|
|
||||||
|
use crate::declare_fn;
|
||||||
|
|
||||||
pub fn load(env: &mut Environment) {
|
pub fn load(env: &mut Environment) {
|
||||||
declare_fn!(env, print, 1);
|
declare_fn!(env, print, 1);
|
||||||
|
@ -37,7 +39,7 @@ struct FileBox {
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref FILE_TYPE_ID: usize = crate::value::generate_type_id();
|
static ref FILE_TYPE_ID: usize = complexpr::value::generate_type_id();
|
||||||
}
|
}
|
||||||
thread_local!(static FILE_TYPE_NAME: Rc<str> = Rc::from("File"));
|
thread_local!(static FILE_TYPE_NAME: Rc<str> = Rc::from("File"));
|
||||||
|
|
||||||
|
@ -50,8 +52,8 @@ impl Native for FileBox {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_type(&self) -> crate::value::Type {
|
fn get_type(&self) -> complexpr::value::Type {
|
||||||
crate::value::Type { name: FILE_TYPE_NAME.with(Rc::clone), id: *FILE_TYPE_ID, typedata: TypeData::None }
|
complexpr::value::Type { name: FILE_TYPE_NAME.with(Rc::clone), id: *FILE_TYPE_ID, typedata: TypeData::None }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
use std::{rc::Rc, cell::RefCell};
|
use std::{rc::Rc, cell::RefCell};
|
||||||
|
|
||||||
use crate::{value::{Value, func::Func}, RuntimeError, env::Environment, declare_fn};
|
use complexpr::{value::{Value, func::Func}, RuntimeError, env::Environment};
|
||||||
|
|
||||||
|
use crate::declare_fn;
|
||||||
|
|
||||||
pub fn load(env: &mut Environment) {
|
pub fn load(env: &mut Environment) {
|
||||||
declare_fn!(env, take, 2);
|
declare_fn!(env, take, 2);
|
16
complexpr-stdlib/src/lib.rs
Normal file
16
complexpr-stdlib/src/lib.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
pub mod prelude;
|
||||||
|
pub mod io;
|
||||||
|
pub mod iter;
|
||||||
|
pub mod math;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! declare_fn {
|
||||||
|
($env:ident, $name:ident, $arg_count:literal) => {::paste::paste!{{
|
||||||
|
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from(stringify!($name));
|
||||||
|
$env.declare(s.clone(), ::complexpr::value::Value::Func(::complexpr::value::func::Func::Builtin { func: [<fn_ $name>], arg_count: $arg_count, name: s }));
|
||||||
|
}}};
|
||||||
|
($env:ident, $name:literal, $rust_name:ident, $arg_count:literal) => {{
|
||||||
|
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from($name);
|
||||||
|
$env.declare(s.clone(), ::complexpr::value::Value::Func(::complexpr::value::func::Func::Builtin { func: $rust_name, arg_count: $arg_count, name: s }));
|
||||||
|
}};
|
||||||
|
}
|
|
@ -2,7 +2,9 @@ use std::cmp::Ordering;
|
||||||
|
|
||||||
use num_traits::{ToPrimitive, Pow, Signed};
|
use num_traits::{ToPrimitive, Pow, Signed};
|
||||||
|
|
||||||
use crate::{value::{Value, Complex, Rational}, RuntimeError, env::Environment, declare_fn};
|
use complexpr::{value::{Value, Complex, Rational}, RuntimeError, env::Environment};
|
||||||
|
|
||||||
|
use crate::declare_fn;
|
||||||
|
|
||||||
enum Floaty {
|
enum Floaty {
|
||||||
Real(f64), Complex(Complex)
|
Real(f64), Complex(Complex)
|
|
@ -1,22 +1,8 @@
|
||||||
pub mod io;
|
|
||||||
pub mod iter;
|
|
||||||
pub mod math;
|
|
||||||
|
|
||||||
use std::{time::{SystemTime, UNIX_EPOCH}, rc::Rc, cell::RefCell};
|
use std::{time::{SystemTime, UNIX_EPOCH}, rc::Rc, cell::RefCell};
|
||||||
|
|
||||||
use crate::{value::{Value, func::Func}, RuntimeError, env::Environment};
|
use complexpr::{value::{Value, func::Func}, RuntimeError, env::Environment};
|
||||||
|
|
||||||
#[macro_export]
|
use crate::declare_fn;
|
||||||
macro_rules! declare_fn {
|
|
||||||
($env:ident, $name:ident, $arg_count:literal) => {::paste::paste!{{
|
|
||||||
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from(stringify!($name));
|
|
||||||
$env.declare(s.clone(), $crate::value::Value::Func($crate::value::func::Func::Builtin { func: [<fn_ $name>], arg_count: $arg_count, name: s }));
|
|
||||||
}}};
|
|
||||||
($env:ident, $name:literal, $rust_name:ident, $arg_count:literal) => {{
|
|
||||||
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from($name);
|
|
||||||
$env.declare(s.clone(), $crate::value::Value::Func($crate::value::func::Func::Builtin { func: $rust_name, arg_count: $arg_count, name: s }));
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load(env: &mut Environment) {
|
pub fn load(env: &mut Environment) {
|
||||||
declare_fn!(env, "type", fn_type, 1);
|
declare_fn!(env, "type", fn_type, 1);
|
|
@ -8,5 +8,3 @@ num-complex = "0.4.2"
|
||||||
num-rational = "0.4.1"
|
num-rational = "0.4.1"
|
||||||
num-traits = "0.2.15"
|
num-traits = "0.2.15"
|
||||||
strum = { version = "0.24.1", features = ["derive"] }
|
strum = { version = "0.24.1", features = ["derive"] }
|
||||||
paste = "1.0.9"
|
|
||||||
lazy_static = "1.4.0"
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{value::Value, lexer::Lexer, parser::Parser, eval::{eval_stmt, eval_expr}, expr::Stmt, stdlib, env::{EnvRef, Environment}};
|
use crate::{value::Value, lexer::Lexer, parser::Parser, eval::{eval_stmt, eval_expr}, expr::Stmt, env::{EnvRef, Environment}};
|
||||||
|
|
||||||
pub fn interpret(src: &str, fname: Option<String>, env: Option<EnvRef>, repl: bool) -> Result<Value, Box<dyn std::error::Error>> {
|
pub fn interpret(src: &str, fname: Option<String>, env: Option<EnvRef>, repl: bool) -> Result<Value, Box<dyn std::error::Error>> {
|
||||||
let ctx_name = if repl { "<interactive input>" } else { fname.as_ref().map(|s| s.as_ref()).unwrap_or("<unknown>") };
|
let ctx_name = if repl { "<interactive input>" } else { fname.as_ref().map(|s| s.as_ref()).unwrap_or("<unknown>") };
|
||||||
|
@ -13,10 +13,6 @@ pub fn interpret(src: &str, fname: Option<String>, env: Option<EnvRef>, repl: bo
|
||||||
environ = env;
|
environ = env;
|
||||||
} else {
|
} else {
|
||||||
environ = Rc::new(RefCell::new(Environment::new()));
|
environ = Rc::new(RefCell::new(Environment::new()));
|
||||||
stdlib::load(&mut environ.borrow_mut());
|
|
||||||
stdlib::io::load(&mut environ.borrow_mut());
|
|
||||||
stdlib::iter::load(&mut environ.borrow_mut());
|
|
||||||
stdlib::math::load(&mut environ.borrow_mut());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = Value::Nil;
|
let mut result = Value::Nil;
|
||||||
|
|
|
@ -8,7 +8,6 @@ pub mod value;
|
||||||
pub mod eval;
|
pub mod eval;
|
||||||
pub mod interpreter;
|
pub mod interpreter;
|
||||||
pub mod env;
|
pub mod env;
|
||||||
pub mod stdlib;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
|
|
Loading…
Reference in a new issue