Skip to content

Commit

Permalink
Change unsafe keywords to trust (#498)
Browse files Browse the repository at this point in the history
* feat(unsafe): change unsafe keywords to trust

* Update make_executable.ab

keep consistency

* fix: add command flags

---------

Co-authored-by: Daniele Scasciafratte <[email protected]>
  • Loading branch information
Ph0enixKM and Mte90 authored Oct 4, 2024
1 parent 2ab9894 commit cd0338a
Show file tree
Hide file tree
Showing 50 changed files with 167 additions and 161 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ use crate::modules::expression::expr::Expr;
// Translate module is not included in Heraclitus prelude as it's leaving the backend up to developer
use crate::translate::module::TranslateModule;
// Metadata is the object that is carried when iterating over syntax tree.
// - `ParserMetadata` - it carries the necessary information about the current parsing context such as variables and functions that were declared up to this point, warning messages aggregated up to this point, information whether this syntax is declared in a loop, function, main block, unsafe scope etc.
// - `ParserMetadata` - it carries the necessary information about the current parsing context such as variables and functions that were declared up to this point, warning messages aggregated up to this point, information whether this syntax is declared in a loop, function, main block, trust scope etc.
// `TranslateMetadata` - it carries the necessary information for translation such as wether we are in a silent scope, in an eval context or what indentation should be used.
use crate::utils::{ParserMetadata, TranslateMetadata};
// Documentation module tells compiler what markdown content should it generate for this syntax module. This is irrelevent to our simple module so we will just return empty string.
Expand Down
4 changes: 2 additions & 2 deletions build.ab
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Check if such directory exists
$test -f "Cargo.toml" > /dev/null$ failed {
echo "Please run this command in the project root directory"
unsafe $exit 1$
trust $exit 1$
}

unsafe {
trust {
if status == 0 {
// Recompile installer scripts
$cargo run -- setup/install.ab setup/install.sh$
Expand Down
8 changes: 4 additions & 4 deletions grammar.ebnf
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ TYPE = 'Text' | 'Num' | 'Bool' | 'Null';
UNARY_OP = '-' | 'not' ;
BINARY_OP = '+' | '-' | '*' | '/' | '%' | 'and' | 'or' | '==' | '!=' | '<' | '<=' | '>' | '>=' ;
SILENT_MOD = 'silent' ;
UNSAFE_MOD = 'unsafe' ;
TRUST_MOD = 'trust' ;
VISIBILITY = 'pub' ;
(* Identifier *)
Expand Down Expand Up @@ -59,11 +59,11 @@ list = empty_list | full_list ;
(* Command expression *)
(* The ordering of command modifiers doesn't matter *)
command_modifier = SILENT_MOD, [ UNSAFE_MOD ] ;
command_modifier = SILENT_MOD, [ TRUST_MOD ] ;
command_modifier_block = command_modifier, multiline_block ;
command_base = '$', { ANY_CHAR | interpolation }, '$' ;
command = [ SILENT_MOD ], command_base, [ failure_handler ] ;
command_unsafe = [ SILENT_MOD ], UNSAFE_MOD, command_base ;
command_trust = [ SILENT_MOD ], TRUST_MOD, command_base ;
(* Operations *)
binary_operation = expression , BINARY_OP , expression ;
Expand All @@ -86,7 +86,7 @@ variable_set = identifier, variable_index?, '=', expression ;
(* Function *)
function_call = identifier, '(', [ expression, { ',', expression } ], ')' ;
function_call_failed = [ SILENT_MOD ], function_call, failure_handler ;
function_call_unsafe = [ SILENT_MOD ], UNSAFE_MOD, function_call ;
function_call_trust = [ SILENT_MOD ], TRUST_MOD, function_call ;
function_def = [ VISIBILITY ], 'fun', identifier, '(', [ identifier, { ',', identifier } ], ')', block ;
function_def_typed = [ VISIBILITY ], 'fun', identifier, '(',
[ identifier, ':', TYPE, { ',', identifier, ':', TYPE } ], ')', ':', TYPE, block ;
Expand Down
6 changes: 3 additions & 3 deletions setup/install.ab
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ let target = "amber"
let archive = "amber.tar.xz"
let agent = has_failed("uname -a")
then "unknown"
else unsafe $uname -a$
else trust $uname -a$

echo ""

Expand All @@ -33,7 +33,7 @@ main(args) {
let bins_folder = get_bins_folder(user_only_install)

// Check if such directory exists
unsafe $test -d "{place}"$
trust $test -d "{place}"$

if status == 0 {
echo "Amber already installed"
Expand Down Expand Up @@ -134,7 +134,7 @@ main(args) {
let nickname = input("Would you like to help improve Amber by sharing your OS info with our developer database? Enter your GitHub nickname (or any nickname) or type `no`:")
if (nickname != "no") {
// Send feedback to the server
unsafe silent $curl -G --data-urlencode "agent={agent}" --data-urlencode "nickname={nickname}" --data-urlencode "name=download" "https://amber-lang.com/api/visit"$
trust silent $curl -G --data-urlencode "agent={agent}" --data-urlencode "nickname={nickname}" --data-urlencode "name=download" "https://amber-lang.com/api/visit"$
}

// Send success message
Expand Down
2 changes: 1 addition & 1 deletion setup/uninstall.ab
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ main(args) {
let place = get_place(user_only_install)
let bins_folder = get_bins_folder(user_only_install)

unsafe $test -d "{place}" > /dev/null$
trust $test -d "{place}" > /dev/null$

if status == 0 {
let sudo = user_only_install then "" else "sudo"
Expand Down
28 changes: 17 additions & 11 deletions src/modules/command/modifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::utils::metadata::{ParserMetadata, TranslateMetadata};
pub struct CommandModifier {
pub block: Box<Block>,
pub is_block: bool,
pub is_unsafe: bool,
pub is_trust: bool,
pub is_silent: bool
}

Expand All @@ -23,14 +23,14 @@ impl CommandModifier {
pub fn use_modifiers<F>(
&mut self, meta: &mut ParserMetadata, context: F
) -> SyntaxResult where F: FnOnce(&mut Self, &mut ParserMetadata) -> SyntaxResult {
let mut is_unsafe_holder = self.is_unsafe;
if self.is_unsafe {
swap(&mut is_unsafe_holder, &mut meta.context.is_unsafe_ctx);
let mut is_trust_holder = self.is_trust;
if self.is_trust {
swap(&mut is_trust_holder, &mut meta.context.is_trust_ctx);
}
let result = context(self, meta);
// Swap back the value
if self.is_unsafe {
swap(&mut is_unsafe_holder, &mut meta.context.is_unsafe_ctx);
if self.is_trust {
swap(&mut is_trust_holder, &mut meta.context.is_trust_ctx);
}
result
}
Expand All @@ -40,11 +40,17 @@ impl CommandModifier {
match meta.get_current_token() {
Some(tok) => {
match tok.word.as_str() {
"unsafe" => {
if self.is_unsafe {
return error!(meta, Some(tok.clone()), "You already declared `unsafe` modifier before");
trust @ ("trust" | "unsafe") => {
if trust == "unsafe" {
let message = Message::new_warn_at_token(meta, Some(tok.clone()))
.message("The keyword `unsafe` has been deprecated in favor of `trust`.")
.comment("Learn more about this change: https://docs.amber-lang.com/basic_syntax/commands#command-modifiers");
meta.add_message(message);
}
self.is_unsafe = true;
if self.is_trust {
return error!(meta, Some(tok.clone()), "You already declared `trust` modifier before");
}
self.is_trust = true;
meta.increment_index();
},
"silent" => {
Expand All @@ -71,7 +77,7 @@ impl SyntaxModule<ParserMetadata> for CommandModifier {
CommandModifier {
block: Box::new(Block::new()),
is_block: true,
is_unsafe: false,
is_trust: false,
is_silent: false
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/modules/condition/failed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl SyntaxModule<ParserMetadata> for Failed {
fn parse(&mut self, meta: &mut ParserMetadata) -> SyntaxResult {
let tok = meta.get_current_token();
if token(meta, "?").is_ok() {
if !meta.context.is_fun_ctx && !meta.context.is_main_ctx && !meta.context.is_unsafe_ctx {
if !meta.context.is_fun_ctx && !meta.context.is_main_ctx && !meta.context.is_trust_ctx {
return error!(meta, tok, "The '?' operator can only be used in the main block or function body")
}
self.is_question_mark = true;
Expand All @@ -40,7 +40,7 @@ impl SyntaxModule<ParserMetadata> for Failed {
if self.block.is_empty() {
let message = Message::new_warn_at_token(meta, tok)
.message("Empty failed block")
.comment("You should use 'unsafe' modifier to run commands without handling errors");
.comment("You should use 'trust' modifier to run commands without handling errors");
meta.add_message(message);
}
token(meta, "}")?;
Expand All @@ -56,7 +56,7 @@ impl SyntaxModule<ParserMetadata> for Failed {
}
}
},
Err(_) => if meta.context.is_unsafe_ctx {
Err(_) => if meta.context.is_trust_ctx {
self.is_main = meta.context.is_main_ctx;
self.is_parsed = true;
return Ok(());
Expand Down
2 changes: 1 addition & 1 deletion src/modules/variable/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn variable_name_keywords() -> Vec<&'static str> {
// Types
"Text", "Number", "Bool", "Null",
// Command Modifiers
"silent", "unsafe",
"silent", "trust",
// Misc
"echo", "status", "nameof", "mv", "cd", "exit",
]
Expand Down
8 changes: 4 additions & 4 deletions src/std/date.ab
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
/// ```
pub fun date_posix(format: Text = "", date: Text = "", utc: Bool = false): Text? {
if format == "": format = "%FT%T%Z"
if date == "": date = unsafe $date +"%FT%T%Z"$
if date == "": date = trust $date +"%FT%T%Z"$
if (utc) {
return $date --utc -d "{date}" +"{format}"$?
} else {
Expand All @@ -81,7 +81,7 @@ pub fun date_posix(format: Text = "", date: Text = "", utc: Bool = false): Text?
/// Returns the current timestamp (seconds since the Epoch (1970-01-01 00:00 UTC)).
#[allow_absurd_cast]
pub fun now(): Num {
return unsafe $date +%s$ as Num
return trust $date +%s$ as Num
}

/// ### EXPERIMENTAL
Expand All @@ -101,7 +101,7 @@ pub fun now(): Num {
/// - minutes
/// - seconds
pub fun date_add(add:Text, date:Text = "", utc: Bool = false): Text? {
if date == "": date = unsafe $date +"%FT%T%Z"$
if date == "": date = trust $date +"%FT%T%Z"$
return date_posix("", "{date_posix("%F", date, utc)?} {add} {date_posix("%T", date, utc)?}", utc)?
}

Expand All @@ -117,7 +117,7 @@ pub fun date_add(add:Text, date:Text = "", utc: Bool = false): Text? {
/// If date_b is not provided, current date will be used.
#[allow_absurd_cast]
pub fun date_compare(date_a: Text, date_b: Text = "", utc: Bool = false): Num? {
if date_b == "": date_b = unsafe date_posix("", "", utc)
if date_b == "": date_b = trust date_posix("", "", utc)
let timestamp_a = date_posix("%s", date_a, utc)? as Num
let timestamp_b = date_posix("%s", date_b, utc)? as Num
if timestamp_a > timestamp_b: return 1
Expand Down
26 changes: 13 additions & 13 deletions src/std/env.ab
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ import * from "std/text"

/// Retrieves the value of an environment variable, optionally sourcing it from a file if not already set.
pub fun get_env_var(var: Text, file: Text = ".env"): Text {
let _var = unsafe $echo "\$\{!var}"$
let _var = trust $echo "\$\{!var}"$
if _var != "" {
return _var
}

if file_exist(file) {
unsafe $source "{file}"$
return unsafe $echo "\$\{!var}"$
trust $source "{file}"$
return trust $echo "\$\{!var}"$
}

return ""
}

/// Loads the env file in the environment, using `xargs`.
pub fun load_env_file(file: Text = ".env"): Null {
unsafe $export "\$(xargs < {file})" > /dev/null$
trust $export "\$(xargs < {file})" > /dev/null$
}

/// Checks if a variable inside the shell session exists.
Expand Down Expand Up @@ -64,13 +64,13 @@ pub fun is_command(command: Text): Bool {

/// Creates a prompt and returns the value.
pub fun input(prompt: Text): Text {
unsafe $read -p "\${nameof prompt}"$
trust $read -p "\${nameof prompt}"$
return "\$REPLY"
}

/// Creates a prompt, hides any user input and returns the value.
pub fun input_hidden(prompt: Text): Text {
unsafe {
trust {
$read -s -p "\${nameof prompt}"$
$echo "" >&2$
}
Expand All @@ -82,24 +82,24 @@ pub fun input_hidden(prompt: Text): Text {
/// "No" is the default choice, set default_yes to true for "Yes" as default choice.
pub fun confirm(prompt: Text, default_yes: Bool = false): Bool {
let choice_default = default_yes then " [\x1b[1mY/\x1b[0mn]" else " [y/\x1b[1mN\x1b[0m]"
unsafe {
trust {
$printf "\x1b[1m{prompt}\x1b[0m{choice_default}"$
$read -s -n 1$
$printf "\n"$
}
let result = lower(unsafe $echo \$REPLY$)
let result = lower(trust $echo \$REPLY$)
return result == "y" or (result == "" and default_yes)
}

/// Checks if the command has failed.
pub fun has_failed(command: Text): Bool {
unsafe silent $eval {command}$
trust silent $eval {command}$
return status != 0
}

/// Checks if the script is running with a user with root permission.
pub fun is_root(): Bool {
if unsafe $id -u$ == "0" {
if trust $id -u$ == "0" {
return true
}

Expand All @@ -108,13 +108,13 @@ pub fun is_root(): Bool {

/// `printf` the text following the arguments.
pub fun printf(format: Text, args: [Text] = [""]): Null {
unsafe ${nameof args}=("{format}" "\$\{{nameof args}[@]}")$
unsafe $printf "\$\{{nameof args}[@]}"$
trust ${nameof args}=("{format}" "\$\{{nameof args}[@]}")$
trust $printf "\$\{{nameof args}[@]}"$
}

/// Escapes the text to be used with `printf`.
pub fun printf_escape(text: Text): Text {
return unsafe $echo \${nameof text} | sed -e 's/\\\\/\\\\\\\\/g' -e "s/%/%%/g"$
return trust $echo \${nameof text} | sed -e 's/\\\\/\\\\\\\\/g' -e "s/%/%%/g"$
}

/// Prepares a text with formatting options for `printf`.
Expand Down
8 changes: 4 additions & 4 deletions src/std/fs.ab
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fun file_append(path, content) {
/// If the file doesn't exist, it returns a boolean and prints a message.
pub fun create_symbolic_link(origin: Text, destination: Text): Bool {
if file_exist(origin) {
unsafe $ln -s "{origin}" "{destination}"$
trust $ln -s "{origin}" "{destination}"$
return true
}

Expand All @@ -48,7 +48,7 @@ pub fun create_symbolic_link(origin: Text, destination: Text): Bool {
/// Creates a directory with all parent directories as required.
pub fun create_dir(path: Text): Null {
if not dir_exist(path) {
unsafe $mkdir -p "{path}"$
trust $mkdir -p "{path}"$
}
}

Expand All @@ -57,7 +57,7 @@ pub fun create_dir(path: Text): Null {
/// If the file doesn't exist, it returns a boolean and prints a message.
pub fun make_executable(path: Text): Bool {
if file_exist(path) {
unsafe $chmod +x "{path}"$
trust $chmod +x "{path}"$
return true
}

Expand All @@ -70,7 +70,7 @@ pub fun make_executable(path: Text): Bool {
/// If the file doesn't exist, it returns `false`
pub fun change_owner(user: Text, path: Text): Bool {
if file_exist(path) or dir_exist(path) {
unsafe $chown -R "{user}" "{path}"$
trust $chown -R "{user}" "{path}"$
return true
}

Expand Down
6 changes: 3 additions & 3 deletions src/std/http.ab
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import * from "std/env"
pub fun download(url: Text, path: Text): Bool {
if {
is_command("curl") {
unsafe $curl -L -o "{path}" "{url}"$
trust $curl -L -o "{path}" "{url}"$
}
is_command("wget") {
unsafe $wget "{url}" -P "{path}"$
trust $wget "{url}" -P "{path}"$
}
is_command("aria2c") {
unsafe $aria2c "{url}" -d "{path}"$
trust $aria2c "{url}" -d "{path}"$
}
else {
return false
Expand Down
8 changes: 4 additions & 4 deletions src/std/math.ab
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
/// Sums an array's contents
#[allow_absurd_cast]
pub fun sum(list: [Num]): Num {
return unsafe $echo "{list}" | awk '\{s=0; for (i=1; i<=NF; i++) s+=\$i; print s}'$ as Num
return trust $echo "{list}" | awk '\{s=0; for (i=1; i<=NF; i++) s+=\$i; print s}'$ as Num
}

/// Returns a number, rounded to the nearest integer
#[allow_absurd_cast]
pub fun round(number: Num): Num {
if number > 0 {
return unsafe $echo "({number}+0.5)/1" | bc$ as Num
return trust $echo "({number}+0.5)/1" | bc$ as Num
}

return unsafe $echo "({number}-0.5)/1" | bc$ as Num
return trust $echo "({number}-0.5)/1" | bc$ as Num
}

/// Returns the largest integer less than or equal to a number
#[allow_absurd_cast]
pub fun floor(number: Num): Num {
return unsafe $echo "{number}" | awk '\{printf "%d", (\$1 < 0 ? int(\$1) - 1 : int(\$1))}'$ as Num
return trust $echo "{number}" | awk '\{printf "%d", (\$1 < 0 ? int(\$1) - 1 : int(\$1))}'$ as Num
}

/// Returns the smallest integer greater than or equal to a number
Expand Down
Loading

0 comments on commit cd0338a

Please sign in to comment.