Skip to content

Commit

Permalink
Update: Fixed Ext Library Standard.
Browse files Browse the repository at this point in the history
  • Loading branch information
PranavVerma-droid committed Dec 2, 2024
1 parent c484531 commit 0f407b0
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 58 deletions.
2 changes: 1 addition & 1 deletion scripts/run-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ for file in ../../Examples/Normal/*.td; do
fi

echo "Processing file: $basename"
../td "$file" -v
../td "$file"
done
130 changes: 74 additions & 56 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,19 +211,10 @@ impl Environment {

let mut parser = Parser::new(&contents);
let ast = parser.parse()?;
let mut lib = ExternalLibrary::new();

for node in ast {
match node {
ASTNode::FunctionDecl(name, params, body) => {
lib.add_function(name, params, body);
},
_ => return Err(Error::InterpreterError(
"External libraries can only contain function declarations".to_string()
))
}
}


let mut lib = ExternalLibrary::new(ast);
lib.initialize()?;

self.libraries.insert(name.to_string(), Box::new(lib));
Ok(())
}
Expand All @@ -233,47 +224,80 @@ impl Environment {

pub struct ExternalLibrary {
functions: HashMap<String, Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>>,
variables: HashMap<String, (Value, bool)>,
ast: Vec<ASTNode>,
is_initialized: bool,
}

impl ExternalLibrary {
pub fn new() -> Self {
pub fn new(ast: Vec<ASTNode>) -> Self {
ExternalLibrary {
functions: HashMap::new()
functions: HashMap::new(),
variables: HashMap::new(),
ast,
is_initialized: false,
}
}

pub fn add_function(&mut self, name: String, params: Vec<String>, body: Vec<ASTNode>) {
let func_name = name.clone();
let params = params.clone();
let body = body.clone();

let function = Box::new(move |args: Vec<Value>| -> Result<Value, Error> {
let mut env = Environment::new();
env.in_function = true;
fn initialize(&mut self) -> Result<(), Error> {
if self.is_initialized {
return Ok(());
}

if args.len() != params.len() {
return Err(Error::InvalidFunctionArguments(
func_name.to_string(),
params.len(),
args.len()
));
}
let mut env = Environment::new();
env.in_function = false;

for (param, arg) in params.iter().zip(args) {
env.insert_var(param.clone(), arg, true);
}
for node in &self.ast {
match node {
ASTNode::FunctionDecl(name, params, body) => {
let params = params.clone();
let body = body.clone();
let func_name = name.clone();

let function = Box::new(move |args: Vec<Value>| -> Result<Value, Error> {
let mut func_env = Environment::new();
func_env.in_function = true;

let mut result = Value::Null;
for node in &body {
match interpret_node(node, &mut env, false, false)? {
Value::ReturnValue(val) => return Ok(*val),
val => result = val,
if args.len() != params.len() {
return Err(Error::InvalidFunctionArguments(
func_name.clone(),
params.len(),
args.len()
));
}

for (param, arg) in params.iter().zip(args) {
func_env.insert_var(param.clone(), arg, true);
}

let mut result = Value::Null;
for node in &body {
match interpret_node(node, &mut func_env, false, false)? {
Value::ReturnValue(val) => return Ok(*val),
val => result = val,
}
}
Ok(result)
});

self.functions.insert(name.clone(), function);
}
ASTNode::Var(name, expr_opt, is_mutable) => {
if let Some(expr) = expr_opt {
if let Ok(value) = interpret_node(expr, &mut env, false, false) {
self.variables.insert(name.clone(), (value, *is_mutable));
}
} else {
self.variables.insert(name.clone(), (Value::Null, *is_mutable));
}
}
_ => {
}
}
Ok(result)
});
}

self.functions.insert(name, function);
self.is_initialized = true;
Ok(())
}
}

Expand All @@ -282,24 +306,18 @@ impl Library for ExternalLibrary {
self.functions.get(name)
}

fn get_constant(&self, _name: &str) -> Option<&Value> {
None
fn get_constant(&self, name: &str) -> Option<&Value> {
self.variables.get(name).map(|(val, _)| val)
}

fn is_mutable(&self, name: &str) -> Option<bool> {
self.variables.get(name).map(|(_, mutable)| *mutable)
}

fn box_clone(&self) -> Box<dyn Library> {
let mut new_lib = ExternalLibrary::new();
for (name, _) in self.functions.iter() {
let name_clone = name.clone();
new_lib.functions.insert(name.clone(),
Box::new(move |args| {
if let Some(func) = FUNCTION_CACHE.lock().unwrap().get(&name_clone) {
func(args)
} else {
Err(Error::InterpreterError("Function not found in cache".to_string()))
}
})
);
}
let mut new_lib = ExternalLibrary::new(self.ast.clone());
new_lib.variables = self.variables.clone();
new_lib.initialize().unwrap();
Box::new(new_lib)
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/libs/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::collections::HashMap;
pub struct MathLib {
functions: HashMap<String, Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>>,
constants: HashMap<String, Value>,
var_mutability: HashMap<String, bool>,
}

impl Library for MathLib {
Expand All @@ -22,13 +23,18 @@ impl Library for MathLib {
new_lib.constants = self.constants.clone();
Box::new(new_lib)
}

fn is_mutable(&self, name: &str) -> Option<bool> {
self.var_mutability.get(name).copied()
}
}

impl MathLib {
pub fn new() -> Self {
let mut lib = MathLib {
functions: HashMap::new(),
constants: HashMap::new(),
var_mutability: HashMap::new(),
};

lib.register_functions();
Expand Down
2 changes: 2 additions & 0 deletions src/libs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ pub mod os;
use crate::error::Error;
use crate::parser::Value;

#[allow(dead_code)]
pub trait Library {
fn get_function(&self, name: &str) -> Option<&Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>>;
fn get_constant(&self, name: &str) -> Option<&Value>;
fn is_mutable(&self, name: &str) -> Option<bool>;
fn box_clone(&self) -> Box<dyn Library>;
}
6 changes: 6 additions & 0 deletions src/libs/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::sync::{Arc, Mutex};
pub struct OSLib {
functions: HashMap<String, Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>>,
constants: HashMap<String, Value>,
var_mutability: HashMap<String, bool>,
}

impl Library for OSLib {
Expand All @@ -27,13 +28,18 @@ impl Library for OSLib {
new_lib.constants = self.constants.clone();
Box::new(new_lib)
}

fn is_mutable(&self, name: &str) -> Option<bool> {
self.var_mutability.get(name).copied()
}
}

impl OSLib {
pub fn new() -> Self {
let mut lib = OSLib {
functions: HashMap::new(),
constants: HashMap::new(),
var_mutability: HashMap::new(),
};
lib.register_functions();
lib.register_constants();
Expand Down
8 changes: 8 additions & 0 deletions src/libs/std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::collections::HashMap;
pub struct StdLib {
functions: HashMap<String, Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>>,
constants: HashMap<String, Value>,
// Add mutability tracking
var_mutability: HashMap<String, bool>,
}

impl Library for StdLib {
Expand All @@ -19,9 +21,14 @@ impl Library for StdLib {
self.constants.get(name)
}

fn is_mutable(&self, name: &str) -> Option<bool> {
self.var_mutability.get(name).copied()
}

fn box_clone(&self) -> Box<dyn Library> {
let mut new_lib = StdLib::new();
new_lib.constants = self.constants.clone();
new_lib.var_mutability = self.var_mutability.clone();
Box::new(new_lib)
}
}
Expand All @@ -31,6 +38,7 @@ impl StdLib {
let mut lib = StdLib {
functions: HashMap::new(),
constants: HashMap::new(),
var_mutability: HashMap::new(),
};

lib.register_functions();
Expand Down
7 changes: 6 additions & 1 deletion src/libs/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use sys_info;
pub struct SysLib {
functions: HashMap<String, Box<dyn Fn(Vec<Value>) -> Result<Value, Error>>>,
constants: HashMap<String, Value>,
var_mutability: HashMap<String, bool>,
}

impl Library for SysLib {
Expand All @@ -24,18 +25,22 @@ impl Library for SysLib {
}

fn box_clone(&self) -> Box<dyn Library> {
// Create a new instance which will recreate all functions
let mut new_lib = SysLib::new();
new_lib.constants = self.constants.clone();
Box::new(new_lib)
}

fn is_mutable(&self, name: &str) -> Option<bool> {
self.var_mutability.get(name).copied()
}
}

impl SysLib {
pub fn new() -> Self {
let mut lib = SysLib {
functions: HashMap::new(),
constants: HashMap::new(),
var_mutability: HashMap::new(),
};
lib.register_functions();
lib.register_constants();
Expand Down

0 comments on commit 0f407b0

Please sign in to comment.