Skip to content

Commit

Permalink
Feature: Len #441 (#545)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniele Scasciafratte <[email protected]>
  • Loading branch information
Ph0enixKM and Mte90 authored Oct 28, 2024
1 parent af78b72 commit fc1a334
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 35 deletions.
75 changes: 75 additions & 0 deletions src/modules/builtin/len.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use crate::docs::module::DocumentationModule;
use crate::modules::expression::expr::Expr;
use crate::modules::expression::unop::UnOp;
use crate::modules::types::{Type, Typed};
use crate::translate::module::TranslateModule;
use crate::utils::{ParserMetadata, TranslateMetadata};
use heraclitus_compiler::prelude::*;

#[derive(Debug, Clone)]
pub struct Len {
value: Box<Expr>,
}

impl Typed for Len {
fn get_type(&self) -> Type {
Type::Num
}
}

impl UnOp for Len {
fn set_expr(&mut self, expr: Expr) {
self.value = Box::new(expr);
}

fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
token(meta, "len")?;
Ok(())
}
}

impl SyntaxModule<ParserMetadata> for Len {
syntax_name!("Length");

fn new() -> Self {
Len {
value: Box::new(Expr::new()),
}
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
if !matches!(self.value.get_type(), Type::Text | Type::Array(_)) {
let msg = self
.value
.get_error_message(meta)
.message("Length can only be applied to text or array types");
return Err(Failure::Loud(msg));
}
Ok(())
}
}

impl TranslateModule for Len {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let value = self.value.translate(meta);
if self.value.get_type() == Type::Text {
meta.stmt_queue.push_back(format!("__AMBER_LEN={value}"));
return String::from("\"${#__AMBER_LEN}\"")
}
// Case for Array passed as a reference
if value.starts_with("\"${!") {
meta.stmt_queue.push_back(format!("__AMBER_LEN=({value})"));
String::from("\"${#__AMBER_LEN[@]}\"")
} else {
format!("\"${{#{}", value.trim_start_matches("\"${"))
.trim_end()
.to_string()
}
}
}

impl DocumentationModule for Len {
fn document(&self, _meta: &ParserMetadata) -> String {
"".to_string()
}
}
1 change: 1 addition & 0 deletions src/modules/builtin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pub mod echo;
pub mod mv;
pub mod nameof;
pub mod exit;
pub mod len;
16 changes: 10 additions & 6 deletions src/modules/expression/expr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::modules::builtin::len::Len;
use crate::modules::command::cmd::Command;
use crate::modules::expression::binop::BinOp;
use crate::modules::types::{Typed, Type};
Expand Down Expand Up @@ -79,6 +80,7 @@ pub enum ExprType {
Cast(Cast),
Status(Status),
Nameof(Nameof),
Len(Len),
Is(Is),
}

Expand Down Expand Up @@ -143,11 +145,11 @@ impl SyntaxModule<ParserMetadata> for Expr {
addition @ BinOp => [ Add, Sub ],
multiplication @ BinOp => [ Mul, Div, Modulo ],
types @ TypeOp => [ Is, Cast ],
unops @ UnOp => [ Neg, Not ],
unops @ UnOp => [ Neg, Not, Len ],
literals @ Literal => [
// Literals
Parentheses, Bool, Number, Text,
Array, Null, Nameof, Status,
Array, Null, Status, Nameof,
// Function invocation
FunctionInvocation, Command,
// Variable access
Expand All @@ -173,9 +175,10 @@ impl TranslateModule for Expr {
// Binary operators
Range, Cast, Is,
// Unary operators
Not, Neg, Nameof,
Not, Neg, Nameof, Len,
// Literals
Parentheses, Bool, Number, Text, Array, Null, Status,
Parentheses, Bool, Number, Text,
Array, Null, Status,
// Function invocation
FunctionInvocation, Command,
// Variable access
Expand All @@ -198,9 +201,10 @@ impl DocumentationModule for Expr {
// Binary operators
Range, Cast, Is,
// Unary operators
Not, Neg, Nameof,
Not, Neg, Nameof, Len,
// Literals
Parentheses, Bool, Number, Text, Array, Null, Status,
Parentheses, Bool, Number, Text,
Array, Null, Status,
// Function invocation
FunctionInvocation, Command,
// Variable access
Expand Down
3 changes: 2 additions & 1 deletion src/modules/variable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ pub fn variable_name_keywords() -> Vec<&'static str> {
// Command Modifiers
"silent", "trust",
// Misc
"echo", "status", "nameof", "mv", "cd", "exit",
"echo", "status", "nameof", "mv", "cd",
"exit", "len",
]
}

Expand Down
2 changes: 1 addition & 1 deletion src/std/fs.ab
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { join, len, replace_regex, split } from "std/text"
import { join, replace_regex, split } from "std/text"

/// Checks if a directory exists.
pub fun dir_exist(path) {
Expand Down
11 changes: 0 additions & 11 deletions src/std/text.ab
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,6 @@ pub fun chars(text: Text): [Text] {
return chars
}

/// Gets the length of provided text or array.
#[allow_absurd_cast]
pub fun len(value): Num {
trust {
if value is Text:
return $ echo "\$\{#{nameof value}}" $ as Num
else:
return $ echo "\$\{#{nameof value}[@]}" $ as Num
}
}

/// Checks if some text contains a value/
pub fun contains(text: Text, phrase: Text): Bool {
let result = trust $ if [[ "{text}" == *"{phrase}"* ]]; then
Expand Down
8 changes: 0 additions & 8 deletions src/tests/stdlib/len_list.ab

This file was deleted.

8 changes: 0 additions & 8 deletions src/tests/stdlib/len_string.ab

This file was deleted.

22 changes: 22 additions & 0 deletions src/tests/validity/len.ab
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Output
// Text literal: 5
// Array literal: 3
// Text variable: 6
// Array variable: 4
// Text reference: 6
// Array reference: 4

let name = "Andrew"
let fruits = ["apple", "banana", "cherry", "date"]

fun foo(ref text, ref arr) {
echo "Text reference: {len text}"
echo "Array reference: {len arr}"
}

echo "Text literal: {len "Hello"}"
echo "Array literal: {len [1, 2, 3]}"
echo "Text variable: {len name}"
echo "Array variable: {len fruits}"

foo(name, fruits)

0 comments on commit fc1a334

Please sign in to comment.