Add vars table

- added vars table
- refactored function and func table to use impl
- added add and delete methods for func table
This commit is contained in:
Aidan 2021-02-07 23:16:25 -08:00
parent af28692175
commit 61e3985592
No known key found for this signature in database
GPG key ID: 327711E983899316
2 changed files with 140 additions and 76 deletions

View file

@ -49,20 +49,19 @@ pub struct Function {
pub eval_lazy: bool pub eval_lazy: bool
} }
/* call_function impl Function {
/* call
* routine is called by eval when a function call is detected * 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 ( pub fn call_function (
args: Box<Cell>, &mut self,
func: Function, args: Box<cell>,
vars: Box<VTable>, vars: Box<VTable>,
funcs: Box<FTable> funcs: Box<FTable>
) -> Result<Box<Cell>, String> { ) -> Result<Box<Cell>, String> {
let mut n_args = args; let mut n_args = args;
if !func.eval_lazy { if !self.eval_lazy {
match eval(args, vars, funcs, func.loose_syms) { match eval(args, vars, funcs, self.loose_syms) {
Ok(box_cell) => n_args = box_cell, Ok(box_cell) => n_args = box_cell,
Err(s) => return Err( Err(s) => return Err(
format!( format!(
@ -75,14 +74,14 @@ pub fn call_function(
} }
let mut passes = false; let mut passes = false;
match func.args { match self.args {
Args::Lazy(num) => { Args::Lazy(num) => {
if num < 0 { if num < 0 {
passes = true passes = true
} }
if !(num == (args.len() - 1)) { if !(num == (args.len() - 1)) {
return Err(format!("expected {} args in call to {}", num, func.name)) return Err(format!("expected {} args in call to {}", num, self.name))
} }
}, },
@ -108,7 +107,7 @@ pub fn call_function(
Err(format!( Err(format!(
"{} too little arguments in call to {}", "{} too little arguments in call to {}",
arg_types.len() - (idx + 1), arg_types.len() - (idx + 1),
func.name self.name
)); ));
} }
@ -117,7 +116,7 @@ pub fn call_function(
Err(format!( Err(format!(
"argument {} in call to {} is of wrong type (expected {})", "argument {} in call to {} is of wrong type (expected {})",
idx + 1, idx + 1,
func.name, self.name,
arg_types[idx].to_str() arg_types[idx].to_str()
)); ));
} }
@ -125,13 +124,31 @@ pub fn call_function(
if idx == (arg_types.len() - 1) { if idx == (arg_types.len() - 1) {
Err(format!( Err(format!(
"too many arguments in call to {}", "too many arguments in call to {}",
func.name self.name
)); ));
} }
} }
} }
} }
func.times_called += 1; self.times_called += 1;
return Ok((func.function)(args, vars, funcs)); 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);
}
pub fn get(
&mut self,
identifier: String
) -> Result<Box<Cell>, String> {
self.get(identifier)
}
} }

47
src/vars.rs Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<String, Cell>;
impl VTable {
pub fn define(
&mut self,
identifier: String,
var_tree: Box<Cell>
) {
if let Some(boxed_cell) = self.insert(identifier, var_tree) {
drop(boxed_cell);
}
}
pub fn get(
&self,
identifier: String
) -> Option<Box<Cell>> {
self.get(identifier)
}
}