1
0

Implement string functions

This commit is contained in:
Jeff 2024-01-01 09:39:59 -05:00
parent c2d919957e
commit ab4c8922b1
3 changed files with 109 additions and 63 deletions

View File

@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
use crate::{ use crate::{
built_in_functions::{string_functions, StringFunction}, built_in_functions::string_functions, AbstractTree, BuiltInFunction, Function, List, Map,
AbstractTree, BuiltInFunction, Function, List, Map, Result, Type, Value, Result, Type, Value,
}; };
static ARGS: OnceLock<Value> = OnceLock::new(); static ARGS: OnceLock<Value> = OnceLock::new();
@ -29,7 +29,7 @@ pub enum BuiltInValue {
impl BuiltInValue { impl BuiltInValue {
fn r#type(&self) -> Type { fn r#type(&self) -> Type {
match self { match self {
BuiltInValue::Args => Type::list_of(Type::String), BuiltInValue::Args => Type::list(Type::String),
BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(), BuiltInValue::AssertEqual => BuiltInFunction::AssertEqual.r#type(),
BuiltInValue::Fs => Type::Map, BuiltInValue::Fs => Type::Map,
BuiltInValue::Json => Type::Map, BuiltInValue::Json => Type::Map,
@ -106,7 +106,7 @@ impl BuiltInValue {
{ {
let mut variables = string_context.variables_mut().unwrap(); let mut variables = string_context.variables_mut().unwrap();
for string_function in [StringFunction::AsBytes] { for string_function in string_functions() {
let key = string_function.name().to_string(); let key = string_function.name().to_string();
let value = Value::Function(Function::BuiltIn(BuiltInFunction::String( let value = Value::Function(Function::BuiltIn(BuiltInFunction::String(
string_function, string_function,

View File

@ -69,7 +69,7 @@ pub enum Type {
} }
impl Type { impl Type {
pub fn list_of(item_type: Type) -> Self { pub fn list(item_type: Type) -> Self {
Type::List(Box::new(item_type)) Type::List(Box::new(item_type))
} }
@ -80,6 +80,10 @@ impl Type {
} }
} }
pub fn option(optional_type: Type) -> Self {
Type::Option(Box::new(optional_type))
}
pub fn check(&self, other: &Type) -> Result<()> { pub fn check(&self, other: &Type) -> Result<()> {
match (self, other) { match (self, other) {
(Type::Any, _) (Type::Any, _)
@ -257,10 +261,10 @@ impl Display for Type {
} => { } => {
write!(f, "(")?; write!(f, "(")?;
for parameter_type in parameter_types { for (index, parameter_type) in parameter_types.iter().enumerate() {
write!(f, "{parameter_type}")?; write!(f, "{parameter_type}")?;
if parameter_type != parameter_types.last().unwrap() { if index != parameter_types.len() - 1 {
write!(f, " ")?; write!(f, " ")?;
} }
} }

View File

@ -43,68 +43,104 @@ impl StringFunction {
pub fn name(&self) -> &'static str { pub fn name(&self) -> &'static str {
match self { match self {
StringFunction::AsBytes => "as_bytes", StringFunction::AsBytes => "as_bytes",
StringFunction::EndsWith => todo!(), StringFunction::EndsWith => "ends_with",
StringFunction::Find => todo!(), StringFunction::Find => "find",
StringFunction::IsAscii => todo!(), StringFunction::IsAscii => "is_ascii",
StringFunction::IsEmpty => todo!(), StringFunction::IsEmpty => "is_empty",
StringFunction::Lines => todo!(), StringFunction::Lines => "lines",
StringFunction::Matches => todo!(), StringFunction::Matches => "matches",
StringFunction::Split => todo!(), StringFunction::Split => "split",
StringFunction::SplitAt => todo!(), StringFunction::SplitAt => "split_at",
StringFunction::SplitInclusive => todo!(), StringFunction::SplitInclusive => "split_inclusive",
StringFunction::SplitN => todo!(), StringFunction::SplitN => "split_n",
StringFunction::SplitOnce => todo!(), StringFunction::SplitOnce => "split_once",
StringFunction::SplitTerminator => todo!(), StringFunction::SplitTerminator => "split_terminator",
StringFunction::SplitWhitespace => todo!(), StringFunction::SplitWhitespace => "split_whitespace",
StringFunction::StartsWith => todo!(), StringFunction::StartsWith => "starts_with",
StringFunction::StripPrefix => todo!(), StringFunction::StripPrefix => "strip_prefix",
StringFunction::ToLowercase => todo!(), StringFunction::ToLowercase => "to_lowercase",
StringFunction::ToUppercase => todo!(), StringFunction::ToUppercase => "to_uppercase",
StringFunction::Trim => todo!(), StringFunction::Trim => "trim",
StringFunction::TrimEnd => todo!(), StringFunction::TrimEnd => "trim_end",
StringFunction::TrimEndMatches => todo!(), StringFunction::TrimEndMatches => "trim_end_matches",
StringFunction::TrimLeft => todo!(), StringFunction::TrimLeft => "trim_left",
StringFunction::TrimLeftMatches => todo!(), StringFunction::TrimLeftMatches => "trim_left_matches",
StringFunction::TrimMatches => todo!(), StringFunction::TrimMatches => "trim_matches",
StringFunction::TrimRight => todo!(), StringFunction::TrimRight => "trim_right",
StringFunction::TrimRightMatches => todo!(), StringFunction::TrimRightMatches => "trim_right_matches",
StringFunction::TrimStart => todo!(), StringFunction::TrimStart => "trim_start",
StringFunction::TrimStartMatches => todo!(), StringFunction::TrimStartMatches => "trim_start_matches",
} }
} }
pub fn r#type(&self) -> Type { pub fn r#type(&self) -> Type {
match self { match self {
StringFunction::AsBytes => { StringFunction::AsBytes => {
Type::function(vec![Type::String], Type::list_of(Type::Integer)) Type::function(vec![Type::String], Type::list(Type::Integer))
}
StringFunction::EndsWith => {
Type::function(vec![Type::String, Type::String], Type::Boolean)
}
StringFunction::Find => Type::function(
vec![Type::String, Type::String],
Type::option(Type::Integer),
),
StringFunction::IsAscii => Type::function(vec![Type::String], Type::Boolean),
StringFunction::IsEmpty => Type::function(vec![Type::String], Type::Boolean),
StringFunction::Lines => Type::function(vec![Type::String], Type::list(Type::String)),
StringFunction::Matches => {
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
}
StringFunction::Split => {
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
}
StringFunction::SplitAt => {
Type::function(vec![Type::String, Type::Integer], Type::list(Type::String))
}
StringFunction::SplitInclusive => {
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
}
StringFunction::SplitN => Type::function(
vec![Type::String, Type::Integer, Type::String],
Type::list(Type::String),
),
StringFunction::SplitOnce => {
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
}
StringFunction::SplitTerminator => {
Type::function(vec![Type::String, Type::String], Type::list(Type::String))
}
StringFunction::SplitWhitespace => {
Type::function(vec![Type::String], Type::list(Type::String))
}
StringFunction::StartsWith => {
Type::function(vec![Type::String, Type::String], Type::Boolean)
}
StringFunction::StripPrefix => {
Type::function(vec![Type::String, Type::String], Type::option(Type::String))
}
StringFunction::ToLowercase => Type::function(vec![Type::String], Type::String),
StringFunction::ToUppercase => Type::function(vec![Type::String], Type::String),
StringFunction::Trim => Type::function(vec![Type::String], Type::String),
StringFunction::TrimEnd => Type::function(vec![Type::String], Type::String),
StringFunction::TrimEndMatches => {
Type::function(vec![Type::String, Type::String], Type::String)
}
StringFunction::TrimLeft => Type::function(vec![Type::String], Type::String),
StringFunction::TrimLeftMatches => {
Type::function(vec![Type::String, Type::String], Type::String)
}
StringFunction::TrimMatches => {
Type::function(vec![Type::String, Type::String], Type::String)
}
StringFunction::TrimRight => Type::function(vec![Type::String], Type::String),
StringFunction::TrimRightMatches => {
Type::function(vec![Type::String, Type::String], Type::String)
}
StringFunction::TrimStart => Type::function(vec![Type::String], Type::String),
StringFunction::TrimStartMatches => {
Type::function(vec![Type::String, Type::String], Type::String)
} }
StringFunction::EndsWith => todo!(),
StringFunction::Find => todo!(),
StringFunction::IsAscii => todo!(),
StringFunction::IsEmpty => todo!(),
StringFunction::Lines => todo!(),
StringFunction::Matches => todo!(),
StringFunction::Split => todo!(),
StringFunction::SplitAt => todo!(),
StringFunction::SplitInclusive => todo!(),
StringFunction::SplitN => todo!(),
StringFunction::SplitOnce => todo!(),
StringFunction::SplitTerminator => todo!(),
StringFunction::SplitWhitespace => todo!(),
StringFunction::StartsWith => todo!(),
StringFunction::StripPrefix => todo!(),
StringFunction::ToLowercase => todo!(),
StringFunction::ToUppercase => todo!(),
StringFunction::Trim => todo!(),
StringFunction::TrimEnd => todo!(),
StringFunction::TrimEndMatches => todo!(),
StringFunction::TrimLeft => todo!(),
StringFunction::TrimLeftMatches => todo!(),
StringFunction::TrimMatches => todo!(),
StringFunction::TrimRight => todo!(),
StringFunction::TrimRightMatches => todo!(),
StringFunction::TrimStart => todo!(),
StringFunction::TrimStartMatches => todo!(),
} }
} }
@ -138,7 +174,13 @@ impl StringFunction {
StringFunction::StripPrefix => todo!(), StringFunction::StripPrefix => todo!(),
StringFunction::ToLowercase => todo!(), StringFunction::ToLowercase => todo!(),
StringFunction::ToUppercase => todo!(), StringFunction::ToUppercase => todo!(),
StringFunction::Trim => todo!(), StringFunction::Trim => {
Error::expect_argument_amount(self.name(), 1, arguments.len())?;
let trimmed = arguments.first().unwrap().as_string()?.trim().to_string();
Ok(Value::String(trimmed))
}
StringFunction::TrimEnd => todo!(), StringFunction::TrimEnd => todo!(),
StringFunction::TrimEndMatches => todo!(), StringFunction::TrimEndMatches => todo!(),
StringFunction::TrimLeft => todo!(), StringFunction::TrimLeft => todo!(),