WIP lambda

* typesystem extended
* docstrings and callback
* tests defined, not implemented
This commit is contained in:
Ava Apples Affine 2023-03-12 20:29:39 -07:00
parent 7befdc869b
commit b0bd369c1d
Signed by: affine
GPG key ID: 3A4645B8CF806069
4 changed files with 88 additions and 24 deletions

View file

@ -14,6 +14,7 @@
* 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 crate::sym::UserFn;
use std::fmt;
use std::marker::PhantomData;
use std::ops::{Add, Div, Index, Mul, Sub};
@ -27,6 +28,7 @@ pub enum Ctr {
Float(f64),
Bool(bool),
Seg(Seg),
Lambda(UserFn),
#[default]
None,
}
@ -40,6 +42,7 @@ pub enum Type {
Float,
Bool,
Seg,
Lambda,
None,
}
@ -80,6 +83,7 @@ impl Ctr {
Ctr::Float(_s) => Type::Float,
Ctr::Bool(_s) => Type::Bool,
Ctr::Seg(_s) => Type::Seg,
Ctr::Lambda(_s) => Type::Lambda,
Ctr::None => Type::None,
}
}
@ -240,6 +244,7 @@ impl Clone for Ctr {
Ctr::Float(s) => Ctr::Float(*s),
Ctr::Bool(s) => Ctr::Bool(*s),
Ctr::Seg(s) => Ctr::Seg(s.clone()),
Ctr::Lambda(s) => Ctr::Seg(s.clone()),
Ctr::None => Ctr::None,
}
}
@ -260,6 +265,7 @@ impl fmt::Display for Ctr {
}
}
Ctr::Seg(s) => write!(f, "{}", s),
Ctr::Lambda(l) => write!(f, "{}", l),
Ctr::None => Ok(()),
}
}
@ -398,6 +404,7 @@ impl fmt::Display for Type {
Type::Float => "float",
Type::Bool => "bool",
Type::Seg => "segment",
Type::Lambda => "lambda",
Type::None => "none",
};
@ -414,6 +421,7 @@ impl std::convert::From<String> for Type {
"float" => Type::Float,
"bool" => Type::Bool,
"segment" => Type::Seg,
"lambda" => Type::Lambda,
_ => Type::None,
}
}

View file

@ -244,3 +244,44 @@ pub fn env_callback(_ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
}
Ok(Ctr::None)
}
pub const LAMBDA_DOCSTRING: &str = "Takes two arguments of any type.
No args are evaluated when lambda is called.
Lambda makes sure the first argument is a list of symbols (or 'arguments') to the lambda function.
The next arg is stored in a tree to evaluate on demand.
Example: (lambda (x y) (add x y))
This can then be evaluated like so:
((lambda (x y) (add x y)) 1 2)
which is functionally equivalent to:
(add 1 2)";
pub fn lambda_callback(
ast: &Seg,
_syms: &mut SymTable
) -> Result<Ctr, String> {
let mut args = vec![];
if let Ctr::Seg(ref arg_head) = *ast.car {
if !arg_head.circuit(&mut |arg: &Ctr| -> bool {
if let Ctr::Symbol(ref s) = *arg {
args.push(s.clone());
true
} else {
false
}
}) {
Err("all elements of first argumnets must be symbols".to_string())
} else {
if let Ctr::Seg(ref eval_head) = *ast.cdr {
Ok(Ctr::Lambda(UserFn{
ast: Box::new(eval_head.clone()),
arg_syms: args,
}))
} else {
Err("not enough args".to_string())
}
}
} else {
Err("first argument should be a list of symbols".to_string())
}
}

View file

@ -227,6 +227,18 @@ impl fmt::Display for Args {
}
}
impl fmt::Display for UserFn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "(lambda: (");
for i in self.arg_syms {
write!(f, "{} ", i);
}
write!(f, ") {})", self.ast);
Ok(())
}
}
impl fmt::Display for ValueType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {