From 61e39855920dfe7bbddbe68dfdd374911c532dc0 Mon Sep 17 00:00:00 2001 From: Aidan Date: Sun, 7 Feb 2021 23:16:25 -0800 Subject: [PATCH] Add vars table - added vars table - refactored function and func table to use impl - added add and delete methods for func table --- src/func.rs | 169 +++++++++++++++++++++++++++++----------------------- src/vars.rs | 47 +++++++++++++++ 2 files changed, 140 insertions(+), 76 deletions(-) create mode 100644 src/vars.rs diff --git a/src/func.rs b/src/func.rs index 803c02c..416da33 100644 --- a/src/func.rs +++ b/src/func.rs @@ -49,89 +49,106 @@ pub struct Function { pub eval_lazy: bool } -/* call_function - * routine is called by eval when a function call is detected - * full list of cells considered to be a function call is passed in - * (that means that args contains the function symbol in 0 index) - */ -pub fn call_function( - args: Box, - func: Function, - vars: Box, - funcs: Box -) -> Result, String> { - let mut n_args = args; - if !func.eval_lazy { - match eval(args, vars, funcs, func.loose_syms) { - Ok(box_cell) => n_args = box_cell, - Err(s) => return Err( - format!( - "error evaluating args to {}: {}", - func.name, - s - ) - ) - } - } - - let mut passes = false; - match func.args { - Args::Lazy(num) => { - if num < 0 { - passes = true - } - - if !(num == (args.len() - 1)) { - return Err(format!("expected {} args in call to {}", num, func.name)) - } - }, - - Args::Strict(arg_types) => { - let idx: usize = 0; - passes = args.circuit(|c: Ctr| { - if idx >= arg_types.len() { - return false; - } - - if let c = Ctr::None { - return false; - } - - let ret = arg_types[idx] == c.to_type(); - if ret { - idx += 1; - } - return ret; - }); - - if passes && idx < (arg_types.len() - 1) { - Err(format!( - "{} too little arguments in call to {}", - arg_types.len() - (idx + 1), - func.name - )); - } - - if !passes { - if idx < (arg_types.len() - 1) { - Err(format!( - "argument {} in call to {} is of wrong type (expected {})", - idx + 1, +impl Function { + /* call + * routine is called by eval when a function call is detected + */ + pub fn call_function ( + &mut self, + args: Box, + vars: Box, + funcs: Box + ) -> Result, String> { + let mut n_args = args; + if !self.eval_lazy { + match eval(args, vars, funcs, self.loose_syms) { + Ok(box_cell) => n_args = box_cell, + Err(s) => return Err( + format!( + "error evaluating args to {}: {}", func.name, - arg_types[idx].to_str() + s + ) + ) + } + } + + let mut passes = false; + match self.args { + Args::Lazy(num) => { + if num < 0 { + passes = true + } + + if !(num == (args.len() - 1)) { + return Err(format!("expected {} args in call to {}", num, self.name)) + } + }, + + Args::Strict(arg_types) => { + let idx: usize = 0; + passes = args.circuit(|c: Ctr| { + if idx >= arg_types.len() { + return false; + } + + if let c = Ctr::None { + return false; + } + + let ret = arg_types[idx] == c.to_type(); + if ret { + idx += 1; + } + return ret; + }); + + if passes && idx < (arg_types.len() - 1) { + Err(format!( + "{} too little arguments in call to {}", + arg_types.len() - (idx + 1), + self.name )); } - if idx == (arg_types.len() - 1) { - Err(format!( - "too many arguments in call to {}", - func.name - )); + if !passes { + if idx < (arg_types.len() - 1) { + Err(format!( + "argument {} in call to {} is of wrong type (expected {})", + idx + 1, + self.name, + arg_types[idx].to_str() + )); + } + + if idx == (arg_types.len() - 1) { + Err(format!( + "too many arguments in call to {}", + self.name + )); + } } } } + + self.times_called += 1; + return Ok((self.function)(args, vars, funcs)); + } +} + +impl FTable { + pub fn declare( + &mut self, + f: Function + ) { + // memory leak here? where does Function go? maybe it should be boxed.... + self.insert(f.name, f); } - func.times_called += 1; - return Ok((func.function)(args, vars, funcs)); + pub fn get( + &mut self, + identifier: String + ) -> Result, String> { + self.get(identifier) + } } diff --git a/src/vars.rs b/src/vars.rs new file mode 100644 index 0000000..e7c5f37 --- /dev/null +++ b/src/vars.rs @@ -0,0 +1,47 @@ +/* relish: versatile lisp shell + * Copyright (C) 2021 Aidan Hahn + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use std::boxed::Box; +use std::collections::HashMap; +use crate::cell::{Ctr, Cell}; + +/* Mapping between a string token and a tree of Cells + * The string token can be found in any Ctr::Symbol value + * + * Considerations: should I use a structure of cells for this? + * Current thoughts: if this was a language without proper data types, yes. + */ +pub type VTable = HashMap; + +impl VTable { + pub fn define( + &mut self, + identifier: String, + var_tree: Box + ) { + if let Some(boxed_cell) = self.insert(identifier, var_tree) { + drop(boxed_cell); + } + } + + pub fn get( + &self, + identifier: String + ) -> Option> { + self.get(identifier) + } +}