#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(unreachable_patterns)]
#![allow(ambiguous_glob_reexports)]
#![allow(unused_doc_comments)]
#![allow(deprecated)]
#![allow(unused_mut)]
#![allow(unused_assignments)]
#![allow(unused_must_use)]
#![allow(non_snake_case)]
#![warn(missing_docs, rust_2018_idioms)]
#![allow(clippy::module_inception)]
pub mod ast;
pub mod lexer;
pub mod parser;
pub mod macro_system;
pub mod types;
pub mod effects;
pub mod module_system;
#[cfg(feature = "async-runtime")]
pub mod concurrency;
pub mod eval;
pub mod runtime;
pub mod stdlib;
pub mod bytecode;
pub mod jit;
pub mod regex;
pub mod numeric;
pub mod containers;
pub mod metaprogramming;
pub mod ffi;
pub mod diagnostics;
pub mod utils;
#[cfg(any(feature = "minimal-repl", feature = "repl", feature = "enhanced-repl"))]
pub mod repl;
pub mod cli;
pub mod benchmarks;
pub use ast::{Expr, Literal, Program};
pub use diagnostics::{Error, Result, Span};
pub use eval::{Evaluator, Value};
pub use lexer::{Lexer, Token};
pub use parser::Parser;
pub use runtime::{Runtime, LambdustRuntime, ParallelResult, EvaluatorHandle};
pub use stdlib::system;
pub use metaprogramming::{
MetaprogrammingSystem, ReflectionSystem, CodeGenerator, DynamicEvaluator,
ProceduralMacro, StaticAnalyzer, EnvironmentManipulator, SecurityManager
};
#[derive(Debug)]
pub struct Lambdust {
runtime: Runtime,
}
impl Lambdust {
pub fn new() -> Self {
Self {
runtime: Runtime::new(),
}
}
pub fn with_runtime(runtime: Runtime) -> Self {
Self { runtime }
}
pub fn eval(&mut self, source: &str, filename: Option<&str>) -> Result<Value> {
let tokens = self.tokenize(source, filename)?;
let ast = self.parse(tokens)?;
let expanded = self.expand_macros(ast)?;
let typed = self.type_check(expanded)?;
self.runtime.eval(typed)
}
pub fn tokenize(&self, source: &str, filename: Option<&str>) -> Result<Vec<Token>> {
let mut lexer = Lexer::new(source, filename);
lexer.tokenize()
}
pub fn parse(&self, tokens: Vec<Token>) -> Result<Program> {
let mut parser = Parser::new(tokens);
parser.parse()
}
pub fn expand_macros(&mut self, program: Program) -> Result<Program> {
self.runtime.expand_macros(program)
}
pub fn type_check(&self, program: Program) -> Result<Program> {
self.runtime.type_check(program)
}
pub fn runtime(&self) -> &Runtime {
&self.runtime
}
pub fn runtime_mut(&mut self) -> &mut Runtime {
&mut self.runtime
}
}
impl Default for Lambdust {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug)]
pub struct MultithreadedLambdust {
runtime: LambdustRuntime,
}
impl MultithreadedLambdust {
pub fn new(num_threads: Option<usize>) -> Result<Self> {
let runtime = match num_threads {
Some(count) => LambdustRuntime::with_threads(count)?,
None => LambdustRuntime::new()?,
};
Ok(Self {
runtime,
})
}
pub fn with_runtime(runtime: LambdustRuntime) -> Self {
Self { runtime }
}
pub async fn eval(&self, source: &str, filename: Option<&str>) -> Result<Value> {
let tokens = self.tokenize(source, filename)?;
let ast = self.parse(tokens)?;
let expanded = self.expand_macros(ast)?;
let typed = self.type_check(expanded)?;
self.runtime.eval_program(&typed).await
}
pub async fn eval_parallel(&self, sources: Vec<(&str, Option<&str>)>) -> Result<ParallelResult> {
let mut expressions = Vec::new();
for (source, filename) in sources {
let tokens = self.tokenize(source, filename)?;
let ast = self.parse(tokens)?;
let expanded = self.expand_macros(ast)?;
let typed = self.type_check(expanded)?;
for expr in typed.expressions {
expressions.push((expr.inner, Some(expr.span)));
}
}
Ok(self.runtime.eval_parallel(expressions).await)
}
pub fn spawn_evaluator(&self) -> Result<EvaluatorHandle> {
self.runtime.spawn_evaluator()
}
pub fn tokenize(&self, source: &str, filename: Option<&str>) -> Result<Vec<Token>> {
let mut lexer = Lexer::new(source, filename);
lexer.tokenize()
}
pub fn parse(&self, tokens: Vec<Token>) -> Result<Program> {
let mut parser = Parser::new(tokens);
parser.parse()
}
pub fn expand_macros(&self, program: Program) -> Result<Program> {
Ok(program)
}
pub fn type_check(&self, program: Program) -> Result<Program> {
Ok(program)
}
pub fn runtime(&self) -> &LambdustRuntime {
&self.runtime
}
pub fn thread_count(&self) -> usize {
self.runtime.thread_count()
}
pub async fn shutdown(self) -> Result<()> {
self.runtime.shutdown().await
}
}
impl Default for MultithreadedLambdust {
fn default() -> Self {
Self::new(None).expect("Failed to create default multithreaded Lambdust")
}
}
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const LANGUAGE_VERSION: &str = "0.1.0";
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_evaluation() {
let mut lambdust = Lambdust::new();
let _result = lambdust.eval("(+ 1 2)", Some("test"));
}
#[test]
fn test_version_constants() {
assert_eq!(LANGUAGE_VERSION, "0.1.0");
}
}