Move built-in functions to a separate module

This commit is contained in:
Jeff 2024-08-07 19:44:01 -04:00
parent 9840c3c193
commit e4ea402dfa
5 changed files with 103 additions and 96 deletions

View File

@ -5,7 +5,7 @@ use std::{
use serde::{Deserialize, Serialize};
use crate::{Identifier, Span, Type, Value};
use crate::{BuiltInFunction, Identifier, Span, Type, Value};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct AbstractSyntaxTree {
@ -169,94 +169,3 @@ impl Display for Statement {
}
}
}
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInFunction {
IsEven,
IsOdd,
Length,
}
impl BuiltInFunction {
pub fn name(&self) -> &'static str {
match self {
BuiltInFunction::IsEven => "is_even",
BuiltInFunction::IsOdd => "is_odd",
BuiltInFunction::Length => "length",
}
}
pub fn call(
&self,
_type_arguments: Option<Vec<Type>>,
value_arguments: Option<Vec<Value>>,
) -> Result<Value, BuiltInFunctionError> {
match self {
BuiltInFunction::IsEven => {
if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 {
if let Some(integer) = value_arguments[0].as_integer() {
Ok(Value::boolean(integer % 2 == 0))
} else {
Err(BuiltInFunctionError::ExpectedInteger)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
}
BuiltInFunction::IsOdd => {
if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 {
if let Some(integer) = value_arguments[0].as_integer() {
Ok(Value::boolean(integer % 2 != 0))
} else {
Err(BuiltInFunctionError::ExpectedInteger)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
}
BuiltInFunction::Length => {
if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 {
if let Some(list) = value_arguments[0].as_list() {
Ok(Value::integer(list.len() as i64))
} else {
Err(BuiltInFunctionError::ExpectedInteger)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
}
}
}
pub fn expected_type(&self) -> Option<Type> {
match self {
BuiltInFunction::IsEven => Some(Type::Boolean),
BuiltInFunction::IsOdd => Some(Type::Boolean),
BuiltInFunction::Length => Some(Type::Integer),
}
}
}
impl Display for BuiltInFunction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum BuiltInFunctionError {
ExpectedInteger,
WrongNumberOfValueArguments,
}

View File

@ -0,0 +1,96 @@
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
use crate::{Type, Value};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum BuiltInFunction {
IsEven,
IsOdd,
Length,
}
impl BuiltInFunction {
pub fn name(&self) -> &'static str {
match self {
BuiltInFunction::IsEven => "is_even",
BuiltInFunction::IsOdd => "is_odd",
BuiltInFunction::Length => "length",
}
}
pub fn call(
&self,
_type_arguments: Option<Vec<Type>>,
value_arguments: Option<Vec<Value>>,
) -> Result<Value, BuiltInFunctionError> {
match self {
BuiltInFunction::IsEven => {
if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 {
if let Some(integer) = value_arguments[0].as_integer() {
Ok(Value::boolean(integer % 2 == 0))
} else {
Err(BuiltInFunctionError::ExpectedInteger)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
}
BuiltInFunction::IsOdd => {
if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 {
if let Some(integer) = value_arguments[0].as_integer() {
Ok(Value::boolean(integer % 2 != 0))
} else {
Err(BuiltInFunctionError::ExpectedInteger)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
}
BuiltInFunction::Length => {
if let Some(value_arguments) = value_arguments {
if value_arguments.len() == 1 {
if let Some(list) = value_arguments[0].as_list() {
Ok(Value::integer(list.len() as i64))
} else {
Err(BuiltInFunctionError::ExpectedInteger)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
} else {
Err(BuiltInFunctionError::WrongNumberOfValueArguments)
}
}
}
}
pub fn expected_type(&self) -> Option<Type> {
match self {
BuiltInFunction::IsEven => Some(Type::Boolean),
BuiltInFunction::IsOdd => Some(Type::Boolean),
BuiltInFunction::Length => Some(Type::Integer),
}
}
}
impl Display for BuiltInFunction {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "{}", self.name())
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum BuiltInFunctionError {
ExpectedInteger,
WrongNumberOfValueArguments,
}

View File

@ -7,6 +7,7 @@
//! `Interpreter` and runs the given source code.
pub mod abstract_tree;
pub mod analyzer;
pub mod built_in_function;
pub mod identifier;
pub mod lex;
pub mod parse;
@ -15,8 +16,9 @@ pub mod r#type;
pub mod value;
pub mod vm;
pub use abstract_tree::{AbstractSyntaxTree, BuiltInFunction, Node, Statement};
pub use abstract_tree::{AbstractSyntaxTree, Node, Statement};
pub use analyzer::{analyze, Analyzer, AnalyzerError};
pub use built_in_function::{BuiltInFunction, BuiltInFunctionError};
pub use identifier::Identifier;
pub use lex::{lex, LexError, Lexer};
pub use parse::{parse, ParseError, Parser};

View File

@ -6,7 +6,7 @@
use std::collections::VecDeque;
use crate::{
abstract_tree::BuiltInFunction, AbstractSyntaxTree, LexError, Lexer, Node, Span, Statement,
built_in_function::BuiltInFunction, AbstractSyntaxTree, LexError, Lexer, Node, Span, Statement,
Token, Value,
};

View File

@ -1,8 +1,8 @@
use std::collections::HashMap;
use crate::{
abstract_tree::BuiltInFunctionError, parse, AbstractSyntaxTree, Analyzer, AnalyzerError,
Identifier, Node, ParseError, Span, Statement, Value, ValueError,
parse, AbstractSyntaxTree, Analyzer, AnalyzerError, BuiltInFunctionError, Identifier, Node,
ParseError, Span, Statement, Value, ValueError,
};
pub fn run(