Skip to content

Commit fc1a334

Browse files
Ph0enixKMMte90
andauthored
Feature: Len #441 (#545)
Co-authored-by: Daniele Scasciafratte <[email protected]>
1 parent af78b72 commit fc1a334

File tree

9 files changed

+111
-35
lines changed

9 files changed

+111
-35
lines changed

src/modules/builtin/len.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use crate::docs::module::DocumentationModule;
2+
use crate::modules::expression::expr::Expr;
3+
use crate::modules::expression::unop::UnOp;
4+
use crate::modules::types::{Type, Typed};
5+
use crate::translate::module::TranslateModule;
6+
use crate::utils::{ParserMetadata, TranslateMetadata};
7+
use heraclitus_compiler::prelude::*;
8+
9+
#[derive(Debug, Clone)]
10+
pub struct Len {
11+
value: Box<Expr>,
12+
}
13+
14+
impl Typed for Len {
15+
fn get_type(&self) -> Type {
16+
Type::Num
17+
}
18+
}
19+
20+
impl UnOp for Len {
21+
fn set_expr(&mut self, expr: Expr) {
22+
self.value = Box::new(expr);
23+
}
24+
25+
fn parse_operator(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
26+
token(meta, "len")?;
27+
Ok(())
28+
}
29+
}
30+
31+
impl SyntaxModule<ParserMetadata> for Len {
32+
syntax_name!("Length");
33+
34+
fn new() -> Self {
35+
Len {
36+
value: Box::new(Expr::new()),
37+
}
38+
}
39+
40+
fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
41+
if !matches!(self.value.get_type(), Type::Text | Type::Array(_)) {
42+
let msg = self
43+
.value
44+
.get_error_message(meta)
45+
.message("Length can only be applied to text or array types");
46+
return Err(Failure::Loud(msg));
47+
}
48+
Ok(())
49+
}
50+
}
51+
52+
impl TranslateModule for Len {
53+
fn translate(&self, meta: &mut TranslateMetadata) -> String {
54+
let value = self.value.translate(meta);
55+
if self.value.get_type() == Type::Text {
56+
meta.stmt_queue.push_back(format!("__AMBER_LEN={value}"));
57+
return String::from("\"${#__AMBER_LEN}\"")
58+
}
59+
// Case for Array passed as a reference
60+
if value.starts_with("\"${!") {
61+
meta.stmt_queue.push_back(format!("__AMBER_LEN=({value})"));
62+
String::from("\"${#__AMBER_LEN[@]}\"")
63+
} else {
64+
format!("\"${{#{}", value.trim_start_matches("\"${"))
65+
.trim_end()
66+
.to_string()
67+
}
68+
}
69+
}
70+
71+
impl DocumentationModule for Len {
72+
fn document(&self, _meta: &ParserMetadata) -> String {
73+
"".to_string()
74+
}
75+
}

src/modules/builtin/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ pub mod echo;
33
pub mod mv;
44
pub mod nameof;
55
pub mod exit;
6+
pub mod len;

src/modules/expression/expr.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use heraclitus_compiler::prelude::*;
22
use crate::docs::module::DocumentationModule;
3+
use crate::modules::builtin::len::Len;
34
use crate::modules::command::cmd::Command;
45
use crate::modules::expression::binop::BinOp;
56
use crate::modules::types::{Typed, Type};
@@ -79,6 +80,7 @@ pub enum ExprType {
7980
Cast(Cast),
8081
Status(Status),
8182
Nameof(Nameof),
83+
Len(Len),
8284
Is(Is),
8385
}
8486

@@ -143,11 +145,11 @@ impl SyntaxModule<ParserMetadata> for Expr {
143145
addition @ BinOp => [ Add, Sub ],
144146
multiplication @ BinOp => [ Mul, Div, Modulo ],
145147
types @ TypeOp => [ Is, Cast ],
146-
unops @ UnOp => [ Neg, Not ],
148+
unops @ UnOp => [ Neg, Not, Len ],
147149
literals @ Literal => [
148150
// Literals
149151
Parentheses, Bool, Number, Text,
150-
Array, Null, Nameof, Status,
152+
Array, Null, Status, Nameof,
151153
// Function invocation
152154
FunctionInvocation, Command,
153155
// Variable access
@@ -173,9 +175,10 @@ impl TranslateModule for Expr {
173175
// Binary operators
174176
Range, Cast, Is,
175177
// Unary operators
176-
Not, Neg, Nameof,
178+
Not, Neg, Nameof, Len,
177179
// Literals
178-
Parentheses, Bool, Number, Text, Array, Null, Status,
180+
Parentheses, Bool, Number, Text,
181+
Array, Null, Status,
179182
// Function invocation
180183
FunctionInvocation, Command,
181184
// Variable access
@@ -198,9 +201,10 @@ impl DocumentationModule for Expr {
198201
// Binary operators
199202
Range, Cast, Is,
200203
// Unary operators
201-
Not, Neg, Nameof,
204+
Not, Neg, Nameof, Len,
202205
// Literals
203-
Parentheses, Bool, Number, Text, Array, Null, Status,
206+
Parentheses, Bool, Number, Text,
207+
Array, Null, Status,
204208
// Function invocation
205209
FunctionInvocation, Command,
206210
// Variable access

src/modules/variable/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ pub fn variable_name_keywords() -> Vec<&'static str> {
3232
// Command Modifiers
3333
"silent", "trust",
3434
// Misc
35-
"echo", "status", "nameof", "mv", "cd", "exit",
35+
"echo", "status", "nameof", "mv", "cd",
36+
"exit", "len",
3637
]
3738
}
3839

src/std/fs.ab

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { join, len, replace_regex, split } from "std/text"
1+
import { join, replace_regex, split } from "std/text"
22

33
/// Checks if a directory exists.
44
pub fun dir_exist(path) {

src/std/text.ab

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,6 @@ pub fun chars(text: Text): [Text] {
9191
return chars
9292
}
9393

94-
/// Gets the length of provided text or array.
95-
#[allow_absurd_cast]
96-
pub fun len(value): Num {
97-
trust {
98-
if value is Text:
99-
return $ echo "\$\{#{nameof value}}" $ as Num
100-
else:
101-
return $ echo "\$\{#{nameof value}[@]}" $ as Num
102-
}
103-
}
104-
10594
/// Checks if some text contains a value/
10695
pub fun contains(text: Text, phrase: Text): Bool {
10796
let result = trust $ if [[ "{text}" == *"{phrase}"* ]]; then

src/tests/stdlib/len_list.ab

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/tests/stdlib/len_string.ab

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/tests/validity/len.ab

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Output
2+
// Text literal: 5
3+
// Array literal: 3
4+
// Text variable: 6
5+
// Array variable: 4
6+
// Text reference: 6
7+
// Array reference: 4
8+
9+
let name = "Andrew"
10+
let fruits = ["apple", "banana", "cherry", "date"]
11+
12+
fun foo(ref text, ref arr) {
13+
echo "Text reference: {len text}"
14+
echo "Array reference: {len arr}"
15+
}
16+
17+
echo "Text literal: {len "Hello"}"
18+
echo "Array literal: {len [1, 2, 3]}"
19+
echo "Text variable: {len name}"
20+
echo "Array variable: {len fruits}"
21+
22+
foo(name, fruits)

0 commit comments

Comments
 (0)