fix type parsing bugs
This commit is contained in:
@@ -317,6 +317,8 @@ where
|
|||||||
},
|
},
|
||||||
ParseTree::FunctionCall(ident, args) => {
|
ParseTree::FunctionCall(ident, args) => {
|
||||||
let obj = self.get_object_mut(&ident)?;
|
let obj = self.get_object_mut(&ident)?;
|
||||||
|
let globals = Self::obj_globals(obj);
|
||||||
|
let locals = Self::obj_locals(obj);
|
||||||
let v = Self::eval(obj)?;
|
let v = Self::eval(obj)?;
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
@@ -325,7 +327,7 @@ where
|
|||||||
.map(|x| Object::variable(x, self.globals.clone(), self.locals.clone()))
|
.map(|x| Object::variable(x, self.globals.clone(), self.locals.clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
f.call(Self::obj_globals(obj), Self::obj_locals(obj), args)
|
f.call(globals, locals, args)
|
||||||
},
|
},
|
||||||
_ => Err(RuntimeError::FunctionUndefined(ident.clone()))
|
_ => Err(RuntimeError::FunctionUndefined(ident.clone()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ impl Display for FunctionType {
|
|||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Function {
|
pub struct Function {
|
||||||
name: Option<String>,
|
pub(crate) name: Option<String>,
|
||||||
t: FunctionType,
|
t: FunctionType,
|
||||||
arg_names: Vec<String>,
|
arg_names: Vec<String>,
|
||||||
body: Box<ParseTree>,
|
body: Box<ParseTree>,
|
||||||
|
|||||||
@@ -112,13 +112,16 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn add_global(self, k: String, v: Type) -> Self {
|
pub fn add_global(self, k: String, v: Type) -> Self {
|
||||||
self.globals.insert(k, v);
|
self.globals.insert(k, v);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_globals<Items: Iterator<Item = (String, Type)>>(self, items: Items) -> Self {
|
pub fn add_globals<Items: Iterator<Item = (String, Type)>>(self, items: Items) -> Self {
|
||||||
items.for_each(|(name, t)| _ = self.globals.insert(name, t));
|
items.for_each(|(name, t)| {
|
||||||
|
self.globals.insert(name, t);
|
||||||
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +136,9 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_locals<Items: Iterator<Item = (String, Type)>>(mut self, items: Items) -> Self {
|
pub fn add_locals<Items: Iterator<Item = (String, Type)>>(mut self, items: Items) -> Self {
|
||||||
items.for_each(|(name, t)| _ = self.locals.insert(name, t));
|
items.for_each(|(name, t)| {
|
||||||
|
self.locals.insert(name, t);
|
||||||
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,22 +374,27 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
|
|||||||
.locals(locals).parse()?)))
|
.locals(locals).parse()?)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_function_declaration(tokens: &mut Peekable<I>, arg_count: usize) -> Result<(FunctionType, Vec<String>), ParseError> {
|
fn parse_function_declaration(
|
||||||
|
tokens: &mut Peekable<I>,
|
||||||
|
arg_count: usize) -> Result<(FunctionType, Vec<String>), ParseError>
|
||||||
|
{
|
||||||
let args: Vec<(Type, String)> = (0..arg_count)
|
let args: Vec<(Type, String)> = (0..arg_count)
|
||||||
.map(|_| Self::parse_function_declaration_parameter(tokens))
|
.map(|_| Self::parse_function_declaration_parameter(tokens))
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
let (types, names): (Vec<_>, Vec<_>) = args.into_iter().unzip();
|
let (types, names): (Vec<_>, Vec<_>) = args.into_iter().unzip();
|
||||||
let mut ret = Type::Any;
|
let ret = if tokens.next_if(|x| matches!(x, Ok(Token::Operator(Op::Arrow)))).is_some() {
|
||||||
|
Self::parse_type(tokens)?
|
||||||
if tokens.next_if(|x| matches!(x, Ok(Token::Operator(Op::Arrow)))).is_some() {
|
} else {
|
||||||
ret = Self::parse_type(tokens)?;
|
Type::Any
|
||||||
}
|
};
|
||||||
|
|
||||||
Ok((FunctionType(Box::new(ret), types), names))
|
Ok((FunctionType(Box::new(ret), types), names))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_function_declaration_parameter(mut tokens: &mut Peekable<I>) -> Result<(Type, String), ParseError> {
|
fn parse_function_declaration_parameter(
|
||||||
|
mut tokens: &mut Peekable<I>) -> Result<(Type, String), ParseError>
|
||||||
|
{
|
||||||
match tokens.next() {
|
match tokens.next() {
|
||||||
// untyped variable
|
// untyped variable
|
||||||
Some(Ok(Token::Identifier(x))) => Ok((Type::Any, x)),
|
Some(Ok(Token::Identifier(x))) => Ok((Type::Any, x)),
|
||||||
@@ -412,7 +422,7 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
|
|||||||
let mut ret = Type::Any;
|
let mut ret = Type::Any;
|
||||||
|
|
||||||
// this is annoying
|
// this is annoying
|
||||||
// inside of the next_if closure, we already can know that its an error
|
// inside the next_if closure, we already can know that its an error
|
||||||
// and return it, but we cannot return out of a closure
|
// and return it, but we cannot return out of a closure
|
||||||
if let Some(t) = tokens.next_if(|x| matches!(x, Ok(Token::Operator(Op::Arrow))))
|
if let Some(t) = tokens.next_if(|x| matches!(x, Ok(Token::Operator(Op::Arrow))))
|
||||||
{
|
{
|
||||||
@@ -433,20 +443,16 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type(tokens: &mut Peekable<I>) -> Result<Type, ParseError> {
|
// for some dumbass reason,
|
||||||
|
// this is the only code that breaks if it doesn't take an impl Iterator instead of simply I ...
|
||||||
|
fn parse_type(tokens: &mut Peekable<impl Iterator<Item = Result<Token, TokenizeError>>>) -> Result<Type, ParseError> {
|
||||||
match tokens.next() {
|
match tokens.next() {
|
||||||
Some(Ok(Token::Type(t))) => Ok(t),
|
Some(Ok(Token::Type(t))) => Ok(t),
|
||||||
Some(Ok(Token::Operator(Op::FunctionDefine(n)))) => {
|
|
||||||
let args: Vec<Type> = (0..n)
|
|
||||||
.map(|_| Self::parse_type(tokens))
|
|
||||||
.collect::<Result<_, ParseError>>()?;
|
|
||||||
|
|
||||||
let rett = Self::parse_type(tokens)?;
|
|
||||||
|
|
||||||
Ok(Type::Function(FunctionType(Box::new(rett), args.clone())))
|
|
||||||
},
|
|
||||||
Some(Ok(Token::Operator(Op::OpenArray))) => {
|
Some(Ok(Token::Operator(Op::OpenArray))) => {
|
||||||
let mut depth = 1;
|
let mut depth = 1;
|
||||||
|
|
||||||
|
// take tokens until we reach the end of this array
|
||||||
|
// if we don't collect them here it causes rust to overflow computing the types
|
||||||
let array_tokens = tokens.by_ref().take_while(|t| match t {
|
let array_tokens = tokens.by_ref().take_while(|t| match t {
|
||||||
Ok(Token::Operator(Op::OpenArray)) => {
|
Ok(Token::Operator(Op::OpenArray)) => {
|
||||||
depth += 1;
|
depth += 1;
|
||||||
@@ -459,18 +465,25 @@ impl<'a, I: Iterator<Item = Result<Token, TokenizeError>>> Parser<'a, I> {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}).collect::<Result<Vec<_>, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?;
|
}).collect::<Result<Vec<_>, TokenizeError>>().map_err(|e| ParseError::TokenizeError(e))?;
|
||||||
|
|
||||||
if array_tokens.len() == 0 {
|
// ... thanks to this conversion here. The compiler complains that the types don't
|
||||||
return Ok(Type::Array(Box::new(Type::Any)));
|
// match. there is code elsewhere in this codebase that looks exactly like this and
|
||||||
}
|
// still simply uses &mut Peekable<I> as the type. I don't understand why this code
|
||||||
|
// is special, but we have to do horribleness for it to work.
|
||||||
|
let mut array_tokens = array_tokens
|
||||||
|
.into_iter()
|
||||||
|
.map(|t| Ok(t))
|
||||||
|
.collect::<Vec<Result<Token, TokenizeError>>>()
|
||||||
|
.into_iter()
|
||||||
|
.peekable();
|
||||||
|
|
||||||
let t = Self::parse_type(tokens)?;
|
let t = match Self::parse_type(&mut array_tokens) {
|
||||||
let _ = match tokens.next() {
|
Ok(t) => t,
|
||||||
Some(Ok(Token::Operator(Op::CloseArray))) => (),
|
Err(ParseError::UnexpectedEndInput) => Type::Any,
|
||||||
_ => return Err(ParseError::UnmatchedArrayClose),
|
Err(e) => return Err(e),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Type::Array(Box::new(t)))
|
Ok(Type::Array(Box::new(t)))
|
||||||
}
|
},
|
||||||
Some(Ok(t)) => Err(ParseError::UnwantedToken(t.clone())),
|
Some(Ok(t)) => Err(ParseError::UnwantedToken(t.clone())),
|
||||||
Some(Err(e)) => Err(ParseError::TokenizeError(e)),
|
Some(Err(e)) => Err(ParseError::TokenizeError(e)),
|
||||||
None => Err(ParseError::UnexpectedEndInput),
|
None => Err(ParseError::UnexpectedEndInput),
|
||||||
|
|||||||
@@ -419,15 +419,28 @@ impl<R: BufRead> std::iter::Iterator for Tokenizer<R> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use crate::parser::Parser;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn a() {
|
fn tokenizer() {
|
||||||
let program = ":. map : f .? x [Any] -> [Any]";
|
let program = ": length ?. x [] -> Int ?? x + 1 length tail x 0 length [ 1 2 3 ]";
|
||||||
|
|
||||||
let tokens: Vec<Token> = Tokenizer::from_str(program).unwrap().collect::<Result<_, _>>().unwrap();
|
let tokens: Vec<Token> = Tokenizer::from_str(program).unwrap().collect::<Result<_, _>>().unwrap();
|
||||||
|
|
||||||
println!("{tokens:?}");
|
println!("{tokens:#?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn a() {
|
||||||
|
let program = ": length ?. x [] -> Int ?? x + 1 length tail x 0 length [ 1 2 3 ]";
|
||||||
|
|
||||||
|
let mut tokenizer = Tokenizer::from_str(program).unwrap().peekable();
|
||||||
|
|
||||||
|
let mut globals = HashMap::new();
|
||||||
|
let mut parser = Parser::new(&mut tokenizer, &mut globals);
|
||||||
|
|
||||||
|
let tree = parser.next();
|
||||||
|
println!("{tree:#?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user