Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
4d99bfe
feat: initial commit
Ph0enixKM Feb 13, 2025
2285055
fix: validity tests
Ph0enixKM Mar 1, 2025
39bf6d6
fix: some of the stdlib errors
Ph0enixKM Mar 2, 2025
fa0b88f
fix: some tests
Ph0enixKM Mar 2, 2025
54e15ee
fix: stdlib tests
Ph0enixKM Mar 2, 2025
95d9a95
fix: additional error
Ph0enixKM Mar 3, 2025
c4dbcbc
fix: cargo clippy
Ph0enixKM Mar 4, 2025
17b449d
fix: wrong quoting
Ph0enixKM Mar 7, 2025
9941789
fix: wrong init value
Ph0enixKM Mar 7, 2025
977a81e
fix: block rendering
Ph0enixKM Mar 7, 2025
d5cad6c
feat: improve block formatting
Ph0enixKM Mar 7, 2025
a01789d
fix: shellcheck issues
Ph0enixKM Mar 9, 2025
090951e
feat: add more tests
Ph0enixKM Mar 9, 2025
b82f26d
fix: shellcheck issues
Ph0enixKM Mar 10, 2025
b3a8fa9
fix: clippy error
Ph0enixKM Mar 10, 2025
1159c07
feat: add ternary tests
Ph0enixKM Mar 10, 2025
a529ba0
fix: escaping of slices
Ph0enixKM Mar 13, 2025
c25e40d
impl From<String> for CommentFragment
b1ek Apr 1, 2025
be7db0f
simplify path for use
b1ek Apr 1, 2025
dd20c9b
refactor match for readability
b1ek Apr 1, 2025
b56ae08
refactor &*self.index -> self.index.as_ref()
b1ek Apr 1, 2025
fb277f7
add trailing comma to match block
b1ek Apr 1, 2025
46dbc40
rigidly match all requirements to be 1 1 0
b1ek Apr 1, 2025
6757da9
remove a redundant blank line
b1ek Apr 1, 2025
83fc719
simplify echoing the array
b1ek Apr 1, 2025
d018575
reword unreachable code
b1ek Apr 1, 2025
f5c5946
refactor constructor to give every function its own line
b1ek Apr 1, 2025
439991a
refactor: render -> to_string
Ph0enixKM Apr 1, 2025
53f432a
fix: trailing commas
Ph0enixKM Apr 1, 2025
219a6bc
refactor: rename fragment structures
Ph0enixKM Apr 1, 2025
fbecb63
refactor: symbols and block fn name
Ph0enixKM Apr 1, 2025
272207b
refactor: add context to text escaped regular character test
Ph0enixKM Apr 1, 2025
27b618b
refactor: remove padding in doc comments
Ph0enixKM Apr 1, 2025
ba6f320
fix: comment and compound
Ph0enixKM Apr 3, 2025
68190b5
refactor: remove unnecessary files
Ph0enixKM Apr 3, 2025
7d9cee5
refactor: compount -> list
Ph0enixKM Apr 3, 2025
a7a4d8b
refactor: set_quoted -> with_quotes
Ph0enixKM Apr 3, 2025
1a7eb91
refactor: iter loop
Ph0enixKM Apr 3, 2025
2445192
refactor: fragments(raw:) -> raw_fragment()
Ph0enixKM Apr 3, 2025
52d07a8
refactor: formatting
Ph0enixKM Apr 3, 2025
a7d2d0e
refactor: improve readability
Ph0enixKM Apr 3, 2025
53042d6
refactor: variable
Ph0enixKM Apr 3, 2025
8f86380
refactor: finalize addressing concerns
Ph0enixKM Apr 3, 2025
284452a
fix: clippy errors
Ph0enixKM Apr 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
extern crate chrono;
use crate::docs::module::DocumentationModule;
use crate::modules::block::Block;
use crate::modules::prelude::{BlockFragment, FragmentRenderable};
use crate::translate::check_all_blocks;
use crate::translate::module::TranslateModule;
use crate::utils::{ParserMetadata, TranslateMetadata};
Expand Down Expand Up @@ -165,9 +166,9 @@ impl AmberCompiler {
let ast_forest = self.get_sorted_ast_forest(block, &meta);
let mut meta_translate = TranslateMetadata::new(meta, &self.options);
let time = Instant::now();
let mut result = vec![];
let mut result = BlockFragment::new(Vec::new(), false);
for (_path, block) in ast_forest {
result.push(block.translate(&mut meta_translate));
result.append(block.translate(&mut meta_translate));
}
if Self::env_flag_set(AMBER_DEBUG_TIME) {
let pathname = self.path.clone().unwrap_or(String::from("unknown"));
Expand All @@ -178,7 +179,7 @@ impl AmberCompiler {
);
}

let mut result = result.join("\n") + "\n";
let mut result = result.to_string(&mut meta_translate);

let filters = self.options.no_proc.iter()
.map(|x| WildMatchPattern::new(x))
Expand Down
43 changes: 28 additions & 15 deletions src/modules/block.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
use std::collections::VecDeque;
use std::ops::Index;

use crate::modules::prelude::*;
use heraclitus_compiler::prelude::*;
use itertools::Itertools;
use crate::docs::module::DocumentationModule;
use crate::utils::{metadata::ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::statement::stmt::Statement;

#[derive(Debug, Clone)]
pub struct Block {
pub statements: Vec<Statement>
pub statements: Vec<Statement>,
pub should_indent: bool,
pub needs_noop: bool,
}

impl Block {
Expand All @@ -23,14 +23,26 @@ impl Block {
pub fn push_statement(&mut self, statement: Statement) {
self.statements.push(statement);
}

pub fn with_needs_noop(mut self) -> Self {
self.needs_noop = true;
self
}

pub fn with_no_indent(mut self) -> Self {
self.should_indent = false;
self
}
}

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

fn new() -> Self {
Block {
statements: vec![]
statements: vec![],
should_indent: true,
needs_noop: false,
}
}

Expand Down Expand Up @@ -61,20 +73,21 @@ impl SyntaxModule<ParserMetadata> for Block {
}

impl TranslateModule for Block {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind {
// Save the current statement queue and create a new one
let mut new_queue = VecDeque::new();
std::mem::swap(&mut meta.stmt_queue, &mut new_queue);
meta.increase_indent();
let result = if self.is_empty() {
":".to_string()
} else {
self.statements.iter()
.map(|statement| statement.translate(meta))
.filter(|translation| !translation.trim().is_empty())
.collect::<Vec<_>>().join("\n")
let result = {
let mut statements = vec![];
for statement in &self.statements {
let statement = statement.translate(meta);
statements.extend(meta.stmt_queue.drain(..));
statements.push(statement);
}
BlockFragment::new(statements, self.should_indent)
.with_needs_noop(self.needs_noop)
.to_frag()
};
meta.decrease_indent();
// Restore the old statement queue
std::mem::swap(&mut meta.stmt_queue, &mut new_queue);
result
Expand Down
18 changes: 7 additions & 11 deletions src/modules/builtin/cd.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
use heraclitus_compiler::prelude::*;
use crate::fragments;
use crate::modules::expression::expr::Expr;
use crate::docs::module::DocumentationModule;
use heraclitus_compiler::prelude::*;
use crate::modules::prelude::*;
use crate::modules::types::{Type, Typed};
use crate::translate::module::TranslateModule;
use crate::utils::{ParserMetadata, TranslateMetadata};

#[derive(Debug, Clone)]
pub struct Cd {
value: Expr
value: Expr,
}

impl SyntaxModule<ParserMetadata> for Cd {
syntax_name!("ChangeDirectory");

fn new() -> Self {
Cd {
value: Expr::new()
}
Cd { value: Expr::new() }
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
Expand All @@ -35,9 +32,8 @@ impl SyntaxModule<ParserMetadata> for Cd {
}

impl TranslateModule for Cd {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let value = self.value.translate(meta);
format!("cd {} || exit", value)
fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind {
fragments!("cd ", self.value.translate(meta), " || exit")
}
}

Expand Down
16 changes: 7 additions & 9 deletions src/modules/builtin/echo.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::fragments;
use crate::modules::expression::expr::Expr;
use crate::translate::module::TranslateModule;
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::modules::prelude::*;
use heraclitus_compiler::prelude::*;

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

impl SyntaxModule<ParserMetadata> for Echo {
syntax_name!("Log");

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

Expand All @@ -26,9 +25,8 @@ impl SyntaxModule<ParserMetadata> for Echo {
}

impl TranslateModule for Echo {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let value = self.value.translate(meta);
format!("echo {}", value)
fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind {
fragments!("echo ", self.value.translate(meta))
}
}

Expand Down
21 changes: 9 additions & 12 deletions src/modules/builtin/exit.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
use heraclitus_compiler::prelude::*;
use crate::fragments;
use crate::modules::expression::expr::Expr;
use crate::docs::module::DocumentationModule;
use crate::modules::prelude::*;
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 Exit {
code: Option<Expr>
code: Option<Expr>,
}

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

fn new() -> Self {
Exit {
code: None
}
Exit { code: None }
}

fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
Expand All @@ -43,11 +40,11 @@ impl SyntaxModule<ParserMetadata> for Exit {
}

impl TranslateModule for Exit {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let code = self.code.as_ref()
fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind {
let exit_code = self.code.as_ref()
.map(|expr| expr.translate(meta))
.unwrap_or_else(|| "0".to_string());
format!("exit {}", code)
.unwrap_or(fragments!("0"));
fragments!("exit ", exit_code)
}
}

Expand Down
21 changes: 6 additions & 15 deletions src/modules/builtin/len.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::docs::module::DocumentationModule;
use crate::modules::expression::expr::Expr;
use crate::modules::expression::unop::UnOp;
use crate::modules::prelude::*;
use crate::modules::types::{Type, Typed};
use crate::translate::module::TranslateModule;
use crate::utils::{ParserMetadata, TranslateMetadata};
Expand Down Expand Up @@ -50,21 +50,12 @@ impl SyntaxModule<ParserMetadata> for Len {
}

impl TranslateModule for Len {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind {
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()
}
let id = meta.gen_value_id();
meta.push_intermediate_variable_lazy("__length", Some(id), Type::Num, value)
.with_length_getter(true)
.to_frag()
}
}

Expand Down
53 changes: 27 additions & 26 deletions src/modules/builtin/lines.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use heraclitus_compiler::prelude::*;
use crate::docs::module::DocumentationModule;
use crate::fragments;
use crate::raw_fragment;
use crate::modules::expression::expr::Expr;
use crate::modules::types::{Type, Typed};
use crate::translate::module::TranslateModule;
use crate::utils::metadata::{ParserMetadata, TranslateMetadata};
use crate::modules::prelude::*;
use heraclitus_compiler::prelude::*;

#[derive(Debug, Clone)]
pub struct LinesInvocation {
Expand All @@ -12,7 +14,7 @@ pub struct LinesInvocation {

impl Typed for LinesInvocation {
fn get_type(&self) -> Type {
Type::Array(Box::new(Type::Text))
Type::array_of(Type::Text)
}
}

Expand All @@ -21,7 +23,7 @@ impl SyntaxModule<ParserMetadata> for LinesInvocation {

fn new() -> Self {
LinesInvocation {
path: Box::new(None)
path: Box::new(None),
}
}

Expand All @@ -33,7 +35,10 @@ impl SyntaxModule<ParserMetadata> for LinesInvocation {
syntax(meta, &mut path)?;
token(meta, ")")?;
if path.get_type() != Type::Text {
let msg = format!("Expected value of type 'Text' but got '{}'", path.get_type());
let msg = format!(
"Expected value of type 'Text' but got '{}'",
path.get_type()
);
return error!(meta, tok, msg);
}
self.path = Box::new(Some(path));
Expand All @@ -42,34 +47,30 @@ impl SyntaxModule<ParserMetadata> for LinesInvocation {
}

impl TranslateModule for LinesInvocation {
fn translate(&self, meta: &mut TranslateMetadata) -> String {
let name = format!("__AMBER_ARRAY_{}", meta.gen_value_id());
fn translate(&self, meta: &mut TranslateMetadata) -> FragmentKind {
let temp = format!("__AMBER_LINE_{}", meta.gen_value_id());
let path = (*self.path).as_ref()
.map(|p| p.translate_eval(meta, false))
.unwrap_or_default();
let quote = meta.gen_quote();
let dollar = meta.gen_dollar();
let path = (*self.path)
.as_ref()
.map(|p| p.translate(meta))
.expect("Cannot read lines without provided path");
let indent = TranslateMetadata::single_indent();
let block = [
format!("{name}=()"),
format!("while IFS= read -r {temp}; do"),
format!("{indent}{name}+=(\"${temp}\")"),
format!("done <{path}"),
].join("\n");
meta.stmt_queue.push_back(block);
format!("{quote}{dollar}{{{name}[@]}}{quote}")
let id = meta.gen_value_id();
let value = meta.push_intermediate_variable_lazy("__array", Some(id), Type::array_of(Type::Text), FragmentKind::Empty);
meta.stmt_queue.extend([
raw_fragment!("while IFS= read -r {temp}; do"),
raw_fragment!("{indent}{}+=(\"${}\")", value.get_name(), temp),
fragments!("done <", path),
]);
value.to_frag()
}
}

impl LinesInvocation {
pub fn surround_iter(&self, meta: &mut TranslateMetadata, name: &str) -> (String, String) {
let path = (*self.path).as_ref()
pub fn translate_path(&self, meta: &mut TranslateMetadata) -> FragmentKind {
(*self.path)
.as_ref()
.map(|p| p.translate(meta))
.unwrap_or_default();
let prefix = format!("while IFS= read -r {name}; do");
let suffix = format!("done <{path}");
(prefix, suffix)
.expect("Cannot read lines without provided path in iterator loop")
}
}

Expand Down
Loading