From 841e6a431d2d71217141a999e54247c81bf85047 Mon Sep 17 00:00:00 2001 From: b1ek Date: Sat, 25 May 2024 15:57:45 +1000 Subject: [PATCH 1/9] create RDC (runtime dependency checker) --- Cargo.lock | 45 ++++ Cargo.toml | 1 + setup/install.sh | 392 +++++++++++++++---------------- src/compiler.rs | 8 +- src/modules/command/statement.rs | 5 +- src/modules/mod.rs | 1 + src/modules/rdc.rs | 33 +++ src/modules/rdc.sh | 15 ++ src/utils/metadata/translate.rs | 7 +- 9 files changed, 307 insertions(+), 200 deletions(-) create mode 100644 src/modules/rdc.rs create mode 100644 src/modules/rdc.sh diff --git a/Cargo.lock b/Cargo.lock index 6c248fb9..9c9b8bf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "amber" version = "0.3.1-alpha" @@ -10,6 +19,7 @@ dependencies = [ "colored", "heraclitus-compiler", "itertools", + "regex", "similar-string", ] @@ -234,6 +244,12 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + [[package]] name = "pad" version = "0.1.6" @@ -261,6 +277,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + [[package]] name = "rustix" version = "0.38.10" diff --git a/Cargo.toml b/Cargo.toml index 55ed841d..e0585893 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ similar-string = "1.4.2" colored = "2.0.0" itertools = "0.11.0" clap = { version = "4.5.4", features = ["derive"] } +regex = "1.10.4" [profile.release] debug = true diff --git a/setup/install.sh b/setup/install.sh index 7ac24816..dfa2f5f6 100755 --- a/setup/install.sh +++ b/setup/install.sh @@ -1,254 +1,254 @@ -function has_failed__19_v0 { +#!/bin/bash +# Written in [Amber](https://amber-lang.com/) + +# This is the runtime dependency checker. Please do not remove these lines. +CD=('eval' 'exit' '[[' 'test' 'sudo' 'test' 'mkdir' 'curl' 'mv' 'chmod' 'ln' 'curl') +MD=() +for d in "${CD[@]}" +do + if ! command -v $d > /dev/null 2>&1; then + MD+=($d) + fi +done + +if (( ${#MD[@]} != 0 )); then + >&2 echo This program requires for these commands: \( $MD \) to be present in \$PATH. + exit 1 +fi +unset $CD +unset $MD +# Dependencies are ok at this point + +function has_failed__20_v0 { local command=$1 eval ${command} > /dev/null 2>&1 -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then -: -fi; - __AMBER_FUN_has_failed19_v0=$(echo $__AMBER_STATUS '!=' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//'); +__AS=$? + __AF_has_failed20_v0=$(echo $__AS '!=' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//'); return 0 -}; -function exit__20_v0 { +} +function exit__21_v0 { local code=$1 exit "${code}" -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then -: -fi -}; -function includes__21_v0 { +__AS=$? +} +function includes__22_v0 { local arr=("${!1}") local value=$2 [[ "${arr[@]}" =~ "${value}" ]] -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then -: -fi; - __AMBER_FUN_includes21_v0=$(echo $__AMBER_STATUS '==' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//'); +__AS=$? + __AF_includes22_v0=$(echo $__AS '==' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//'); return 0 } -function includes__21_v1 { +function includes__22_v1 { local arr=$1 local value=$2 [[ "${arr[@]}" =~ "${value}" ]] -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then -: -fi; - __AMBER_FUN_includes21_v1=$(echo $__AMBER_STATUS '==' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//'); +__AS=$? + __AF_includes22_v1=$(echo $__AS '==' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//'); return 0 } -function get_os__28_v0 { +function get_os__29_v0 { __AMBER_VAL_0=$(uname -s); - __AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to determine OS type."; - echo "Please try again or use another download method."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__8=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__8} > /dev/null 2>&1 -fi; - local os_type="${__AMBER_VAL_0}"; - local os=$(if [ $([ "_${os_type}" != "_Darwin" ]; echo $?) != 0 ]; then echo "macos"; else echo "linux"; fi); - __AMBER_FUN_get_os28_v0="${os}"; + __AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to determine OS type." + echo "Please try again or use another download method." + exit__21_v0 1; + __AF_exit21_v0__8=$__AF_exit21_v0; + echo $__AF_exit21_v0__8 > /dev/null 2>&1 +fi; + local os_type="${__AMBER_VAL_0}" + local os=$(if [ $([ "_${os_type}" != "_Darwin" ]; echo $?) != 0 ]; then echo "macos"; else echo "linux"; fi) + __AF_get_os29_v0="${os}"; return 0 -}; -function get_arch__29_v0 { +} +function get_arch__30_v0 { __AMBER_VAL_1=$(uname -m); - __AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to determine architecture."; - echo "Please try again or use another download method."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__22=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__22} > /dev/null 2>&1 -fi; - local arch_type="${__AMBER_VAL_1}"; + __AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to determine architecture." + echo "Please try again or use another download method." + exit__21_v0 1; + __AF_exit21_v0__22=$__AF_exit21_v0; + echo $__AF_exit21_v0__22 > /dev/null 2>&1 +fi; + local arch_type="${__AMBER_VAL_1}" __AMBER_ARRAY_0=("arm64" "aarch64"); - includes__21_v0 __AMBER_ARRAY_0[@] "${arch_type}"; - __AMBER_FUN_includes21_v0__25=${__AMBER_FUN_includes21_v0}; - local arch=$(if [ ${__AMBER_FUN_includes21_v0__25} != 0 ]; then echo "aarch64"; else echo "x86_64"; fi); - __AMBER_FUN_get_arch29_v0="${arch}"; + includes__22_v0 __AMBER_ARRAY_0[@] "${arch_type}"; + __AF_includes22_v0__25=$__AF_includes22_v0; + local arch=$(if [ $__AF_includes22_v0__25 != 0 ]; then echo "aarch64"; else echo "x86_64"; fi) + __AF_get_arch30_v0="${arch}"; return 0 -}; -function get_home__30_v0 { +} +function get_home__31_v0 { __AMBER_VAL_2=$(echo $HOME); - __AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "User installation requested, but unable to retrieve home directory from $HOME environment."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__35=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__35} > /dev/null 2>&1 -fi; - local home="${__AMBER_VAL_2}"; + __AS=$?; +if [ $__AS != 0 ]; then + echo "User installation requested, but unable to retrieve home directory from $HOME environment." + exit__21_v0 1; + __AF_exit21_v0__35=$__AF_exit21_v0; + echo $__AF_exit21_v0__35 > /dev/null 2>&1 +fi; + local home="${__AMBER_VAL_2}" if [ $([ "_${home}" != "_" ]; echo $?) != 0 ]; then - echo "User installation requested, but unable to find home directory."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__39=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__39} > /dev/null 2>&1 -fi; - __AMBER_FUN_get_home30_v0="${home}"; + echo "User installation requested, but unable to find home directory." + exit__21_v0 1; + __AF_exit21_v0__39=$__AF_exit21_v0; + echo $__AF_exit21_v0__39 > /dev/null 2>&1 +fi + __AF_get_home31_v0="${home}"; return 0 -}; -function get_bins_folder__31_v0 { +} +function get_bins_folder__32_v0 { local user_only=$1 if [ ${user_only} != 0 ]; then - get_home__30_v0 ; - __AMBER_FUN_get_home30_v0__46=${__AMBER_FUN_get_home30_v0}; - __AMBER_FUN_get_bins_folder31_v0="${__AMBER_FUN_get_home30_v0__46}/.local/bin"; + get_home__31_v0 ; + __AF_get_home31_v0__46="${__AF_get_home31_v0}"; + __AF_get_bins_folder32_v0="${__AF_get_home31_v0__46}/.local/bin"; return 0 else - local bins_folder="/usr/local/bin"; + local bins_folder="/usr/local/bin" test -d "${bins_folder}" -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then +__AS=$?; +if [ $__AS != 0 ]; then sudo mkdir -p "${bins_folder}" > /dev/null 2>&1 -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to create ${bins_folder} directory."; - exit__20_v0 1 > /dev/null 2>&1; - __AMBER_FUN_exit20_v0__53=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__53} > /dev/null 2>&1 +__AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to create ${bins_folder} directory." + exit__21_v0 1 > /dev/null 2>&1; + __AF_exit21_v0__53=$__AF_exit21_v0; + echo $__AF_exit21_v0__53 > /dev/null 2>&1 fi -fi; - __AMBER_FUN_get_bins_folder31_v0="${bins_folder}"; +fi + __AF_get_bins_folder32_v0="${bins_folder}"; return 0 fi -}; -function get_place__32_v0 { +} +function get_place__33_v0 { local user_only=$1 if [ ${user_only} != 0 ]; then - get_home__30_v0 ; - __AMBER_FUN_get_home30_v0__62=${__AMBER_FUN_get_home30_v0}; - get_arch__29_v0 ; - __AMBER_FUN_get_arch29_v0__62=${__AMBER_FUN_get_arch29_v0}; - __AMBER_FUN_get_place32_v0="${__AMBER_FUN_get_home30_v0__62}/.local/lib/${__AMBER_FUN_get_arch29_v0__62}/amber"; + get_home__31_v0 ; + __AF_get_home31_v0__62="${__AF_get_home31_v0}"; + get_arch__30_v0 ; + __AF_get_arch30_v0__62="${__AF_get_arch30_v0}"; + __AF_get_place33_v0="${__AF_get_home31_v0__62}/.local/lib/${__AF_get_arch30_v0__62}/amber"; return 0 else - __AMBER_FUN_get_place32_v0="/opt/amber"; + __AF_get_place33_v0="/opt/amber"; return 0 fi } -__0_name="AmberNative"; -__1_target="amber"; -__2_tag="0.3.1-alpha"; -has_failed__19_v0 "uname -a"; -__AMBER_FUN_has_failed19_v0__7=${__AMBER_FUN_has_failed19_v0}; +__0_name="AmberNative" +__1_target="amber" +__2_tag="0.3.1-alpha" +has_failed__20_v0 "uname -a"; +__AF_has_failed20_v0__7=$__AF_has_failed20_v0; __AMBER_VAL_3=$(uname -a); -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then -: -fi; -__3_agent=$(if [ ${__AMBER_FUN_has_failed19_v0__7} != 0 ]; then echo "unknown"; else echo "${__AMBER_VAL_3}"; fi); -echo ""; +__AS=$?; +__3_agent=$(if [ $__AF_has_failed20_v0__7 != 0 ]; then echo "unknown"; else echo "${__AMBER_VAL_3}"; fi) +echo "" args=$1 - get_os__28_v0 ; - __AMBER_FUN_get_os28_v0__14=${__AMBER_FUN_get_os28_v0}; - os=${__AMBER_FUN_get_os28_v0__14}; - get_arch__29_v0 ; - __AMBER_FUN_get_arch29_v0__15=${__AMBER_FUN_get_arch29_v0}; - arch=${__AMBER_FUN_get_arch29_v0__15}; - includes__21_v1 "${args}" "--user"; - __AMBER_FUN_includes21_v1__17=${__AMBER_FUN_includes21_v1}; - user_only_install=${__AMBER_FUN_includes21_v1__17}; - get_place__32_v0 ${user_only_install}; - __AMBER_FUN_get_place32_v0__18=${__AMBER_FUN_get_place32_v0}; - place=${__AMBER_FUN_get_place32_v0__18}; - get_bins_folder__31_v0 ${user_only_install}; - __AMBER_FUN_get_bins_folder31_v0__19=${__AMBER_FUN_get_bins_folder31_v0}; - bins_folder=${__AMBER_FUN_get_bins_folder31_v0__19}; + get_os__29_v0 ; + __AF_get_os29_v0__14="${__AF_get_os29_v0}"; + os="${__AF_get_os29_v0__14}" + get_arch__30_v0 ; + __AF_get_arch30_v0__15="${__AF_get_arch30_v0}"; + arch="${__AF_get_arch30_v0__15}" + includes__22_v1 "${args}" "--user"; + __AF_includes22_v1__17=$__AF_includes22_v1; + user_only_install=$__AF_includes22_v1__17 + get_place__33_v0 ${user_only_install}; + __AF_get_place33_v0__18="${__AF_get_place33_v0}"; + place="${__AF_get_place33_v0__18}" + get_bins_folder__32_v0 ${user_only_install}; + __AF_get_bins_folder32_v0__19="${__AF_get_bins_folder32_v0}"; + bins_folder="${__AF_get_bins_folder32_v0__19}" test -d "${place}" -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then -: -fi; - if [ $(echo $__AMBER_STATUS '==' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//') != 0 ]; then - echo "Amber already installed"; - echo "It seems that Amber is already installed on your system. (${place})"; - echo "If you want to reinstall Amber, uninstall it first."; - echo "(Find out more at https://docs.amber-lang.com/getting_started/installation#uninstallation)"; - exit__20_v0 2; - __AMBER_FUN_exit20_v0__29=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__29} > /dev/null 2>&1 -fi; - has_failed__19_v0 "curl -V"; - __AMBER_FUN_has_failed19_v0__33=${__AMBER_FUN_has_failed19_v0}; - if [ ${__AMBER_FUN_has_failed19_v0__33} != 0 ]; then - echo "Curl is not installed on your system."; - echo "Please install \`curl\` and try again."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__36=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__36} > /dev/null 2>&1 -fi; - echo "Installing Amber... 🚀"; - sudo=$(if [ ${user_only_install} != 0 ]; then echo ""; else echo "sudo"; fi); +__AS=$? + if [ $(echo $__AS '==' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//') != 0 ]; then + echo "Amber already installed" + echo "It seems that Amber is already installed on your system. (${place})" + echo "If you want to reinstall Amber, uninstall it first." + echo "(Find out more at https://docs.amber-lang.com/getting_started/installation#uninstallation)" + exit__21_v0 2; + __AF_exit21_v0__29=$__AF_exit21_v0; + echo $__AF_exit21_v0__29 > /dev/null 2>&1 +fi + has_failed__20_v0 "curl -V"; + __AF_has_failed20_v0__33=$__AF_has_failed20_v0; + if [ $__AF_has_failed20_v0__33 != 0 ]; then + echo "Curl is not installed on your system." + echo "Please install \`curl\` and try again." + exit__21_v0 1; + __AF_exit21_v0__36=$__AF_exit21_v0; + echo $__AF_exit21_v0__36 > /dev/null 2>&1 +fi + echo "Installing Amber... 🚀" + sudo=$(if [ ${user_only_install} != 0 ]; then echo ""; else echo "sudo"; fi) ${sudo} mkdir -p "${place}" > /dev/null 2>&1 -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to create directory for amber."; +__AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to create directory for amber." if [ ${user_only_install} != 0 ]; then echo "Please make sure that root user can access ${place} directory." else echo "Please make sure that your user can access ${place} directory." -fi; - exit__20_v0 1 > /dev/null 2>&1; - __AMBER_FUN_exit20_v0__52=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__52} > /dev/null 2>&1 -fi; +fi + exit__21_v0 1 > /dev/null 2>&1; + __AF_exit21_v0__52=$__AF_exit21_v0; + echo $__AF_exit21_v0__52 > /dev/null 2>&1 +fi if [ ${user_only_install} != 0 ]; then mkdir -p "${bins_folder}" > /dev/null 2>&1 -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to create directory for amber bin at ${bins_folder}."; - exit__20_v0 1 > /dev/null 2>&1; - __AMBER_FUN_exit20_v0__57=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__57} > /dev/null 2>&1 +__AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to create directory for amber bin at ${bins_folder}." + exit__21_v0 1 > /dev/null 2>&1; + __AF_exit21_v0__57=$__AF_exit21_v0; + echo $__AF_exit21_v0__57 > /dev/null 2>&1 fi -fi; - url="https://github.com/Ph0enixKM/${__0_name}/releases/download/${__2_tag}/amber_${os}_${arch}"; +fi + url="https://github.com/Ph0enixKM/${__0_name}/releases/download/${__2_tag}/amber_${os}_${arch}" curl -L -o "${__1_target}" "${url}" > /dev/null 2>&1 -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Curl failed to download amber."; - echo "Something went wrong. Please try again later."; - exit__20_v0 1 > /dev/null 2>&1; - __AMBER_FUN_exit20_v0__68=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__68} > /dev/null 2>&1 -fi; +__AS=$?; +if [ $__AS != 0 ]; then + echo "Curl failed to download amber." + echo "Something went wrong. Please try again later." + exit__21_v0 1 > /dev/null 2>&1; + __AF_exit21_v0__68=$__AF_exit21_v0; + echo $__AF_exit21_v0__68 > /dev/null 2>&1 +fi ${sudo} mv "${__1_target}" "${place}/${__1_target}" -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to move amber to the installation directory."; - echo "Please make sure that root user can access /opt directory."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__75=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__75} > /dev/null 2>&1 -fi; +__AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to move amber to the installation directory." + echo "Please make sure that root user can access /opt directory." + exit__21_v0 1; + __AF_exit21_v0__75=$__AF_exit21_v0; + echo $__AF_exit21_v0__75 > /dev/null 2>&1 +fi ${sudo} chmod +x "${place}/${__1_target}" -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to give permissions to execute amber."; - echo "Please make sure that root user can access /opt directory."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__81=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__81} > /dev/null 2>&1 -fi; +__AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to give permissions to execute amber." + echo "Please make sure that root user can access /opt directory." + exit__21_v0 1; + __AF_exit21_v0__81=$__AF_exit21_v0; + echo $__AF_exit21_v0__81 > /dev/null 2>&1 +fi ${sudo} ln -s "${place}/${__1_target}" "${bins_folder}/${__1_target}" -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then - echo "Failed to create amber symbol link."; - echo "Please make sure that root user can access /usr/local/bin directory."; - exit__20_v0 1; - __AMBER_FUN_exit20_v0__88=${__AMBER_FUN_exit20_v0}; - echo ${__AMBER_FUN_exit20_v0__88} > /dev/null 2>&1 -fi; +__AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to create amber symbol link." + echo "Please make sure that root user can access /usr/local/bin directory." + exit__21_v0 1; + __AF_exit21_v0__88=$__AF_exit21_v0; + echo $__AF_exit21_v0__88 > /dev/null 2>&1 +fi curl -G --data-urlencode "agent=${__3_agent}" --data-urlencode "name=download" "https://amber-lang.com/api/visit" > /dev/null 2>&1 -__AMBER_STATUS=$?; -if [ $__AMBER_STATUS != 0 ]; then -: -fi; - echo "Amber has been installed successfully. 🎉"; - echo "> Now you can use amber by typing \`amber\` in your terminal."; +__AS=$? + echo "Amber has been installed successfully. 🎉" + echo "> Now you can use amber by typing \`amber\` in your terminal." if [ ${user_only_install} != 0 ]; then echo "> Since you requested a user only install with \`--user\` ensure that ~/.local/bin is in your \$PATH." fi \ No newline at end of file diff --git a/src/compiler.rs b/src/compiler.rs index 0bb5afd6..22626590 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,5 +1,6 @@ use heraclitus_compiler::prelude::*; use crate::modules::block::Block; +use crate::modules::rdc; use crate::translate::check_all_blocks; use crate::utils::{ParserMetadata, TranslateMetadata}; use crate::translate::module::TranslateModule; @@ -108,7 +109,12 @@ impl AmberCompiler { println!("[{}]\tin\t{}ms\t{pathname}", "Translate".magenta(), time.elapsed().as_millis()); } result.push(block.translate(&mut meta)); - result.join("\n") + let res = result.join("\n"); + format!( + "{}\n{}", + rdc::generate(meta.externs), + res + ) } pub fn compile(&self) -> Result<(Vec, String), Message> { diff --git a/src/modules/command/statement.rs b/src/modules/command/statement.rs index 61cfc262..050e4fd0 100644 --- a/src/modules/command/statement.rs +++ b/src/modules/command/statement.rs @@ -1,5 +1,5 @@ use heraclitus_compiler::prelude::*; -use crate::{utils::{ParserMetadata, TranslateMetadata}, modules::{types::{Type, Typed}, condition::failed::Failed}}; +use crate::{modules::{condition::failed::Failed, rdc::scan_append_externs, types::{Type, Typed}}, utils::{ParserMetadata, TranslateMetadata}}; use crate::modules::expression::expr::Expr; use crate::translate::module::TranslateModule; @@ -49,6 +49,9 @@ impl TranslateModule for CommandStatement { let interps = self.interps.iter() .map(|item| item.translate(meta)) .collect::>(); + + scan_append_externs(self.strings.clone(), meta); + let failed = self.failed.translate(meta); let mut translation = translate_interpolated_region(self.strings.clone(), interps, false); let silent = meta.gen_silent(); diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 45667813..aef33eed 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -11,6 +11,7 @@ pub mod types; pub mod imports; pub mod main; pub mod builtin; +pub mod rdc; #[macro_export] macro_rules! handle_types { diff --git a/src/modules/rdc.rs b/src/modules/rdc.rs new file mode 100644 index 00000000..cbe3fae4 --- /dev/null +++ b/src/modules/rdc.rs @@ -0,0 +1,33 @@ +use itertools::Itertools; +use regex::Regex; + +use crate::utils::TranslateMetadata; + +/// RDC - Runtime dependency checker + +/// Generate the code +pub fn generate(externals: Vec) -> String { + let externals = externals.iter().dedup().map(|x| x.clone()).collect::>(); + let mut code = String::new(); + code += "# This is the runtime dependency checker. Please do not remove these lines.\n"; + code += format!("CD=(\'{}\')\n", externals.join("\' \'")).as_str(); + code += include_str!("rdc.sh"); + code +} + +pub fn scan_append_externs(strings: Vec, meta: &mut TranslateMetadata) -> () { + // source: https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html + let bash_deps = vec![ "alias", "bind", "builtin", "caller", "command", "declare", "echo", "enable", "help", "let", "local", "logout", "mapfile", "printf", "read", "readarray", "source", "type", "typeset", "ulimit", "unalias" ]; + + let remove_prefix_whitespace = Regex::new(r"^ +").unwrap(); + let remove_all_non_cmd = Regex::new(r" .*$").unwrap(); + + for x in strings.iter() { + let parsed = remove_prefix_whitespace.replace(x, "").to_string(); + let parsed = remove_all_non_cmd.replace(&parsed, "").to_string(); + if x.len() != 0 && bash_deps.iter().find(|y| x.to_string() == y.to_string()).is_none() { + meta.externs.push(parsed); + break; + } + } +} \ No newline at end of file diff --git a/src/modules/rdc.sh b/src/modules/rdc.sh new file mode 100644 index 00000000..ef1c8d45 --- /dev/null +++ b/src/modules/rdc.sh @@ -0,0 +1,15 @@ +MD=() +for d in "${CD[@]}" +do + if ! command -v $d > /dev/null 2>&1; then + MD+=($d) + fi +done + +if (( ${#MD[@]} != 0 )); then + >&2 echo This program requires for these commands: \( $MD \) to be present in \$PATH. + exit 1 +fi +unset $CD +unset $MD +# Dependencies are ok at this point diff --git a/src/utils/metadata/translate.rs b/src/utils/metadata/translate.rs index 2e414e9f..faf0c2ec 100644 --- a/src/utils/metadata/translate.rs +++ b/src/utils/metadata/translate.rs @@ -22,7 +22,9 @@ pub struct TranslateMetadata { /// Determines whether the current context should be silenced. pub silenced: bool, /// The current indentation level. - pub indent: i64 + pub indent: i64, + /// External commands used + pub externs: Vec } impl TranslateMetadata { @@ -36,7 +38,8 @@ impl TranslateMetadata { value_id: 0, eval_ctx: false, silenced: false, - indent: -1 + indent: -1, + externs: vec![] } } From 2ff902212321f912614663600e4ad8ae542e152c Mon Sep 17 00:00:00 2001 From: b1ek Date: Sat, 25 May 2024 15:58:50 +1000 Subject: [PATCH 2/9] add a header to be included in each file im feeling like RDC's first line might be treated as shebang like --- src/compiler.rs | 3 ++- src/header.sh | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 src/header.sh diff --git a/src/compiler.rs b/src/compiler.rs index 22626590..da271ac5 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -111,7 +111,8 @@ impl AmberCompiler { result.push(block.translate(&mut meta)); let res = result.join("\n"); format!( - "{}\n{}", + "{}\n{}\n{}", + include_str!("header.sh"), rdc::generate(meta.externs), res ) diff --git a/src/header.sh b/src/header.sh new file mode 100644 index 00000000..7d962fce --- /dev/null +++ b/src/header.sh @@ -0,0 +1,2 @@ +#!/bin/bash +# Written in [Amber](https://amber-lang.com/) From 005e44b5565b91911bc699c2b929d8c58072885c Mon Sep 17 00:00:00 2001 From: b1ek Date: Sat, 25 May 2024 16:36:12 +1000 Subject: [PATCH 3/9] make RDC disableable --- src/compiler.rs | 17 +++++++++++------ src/main.rs | 8 ++++++-- src/modules/imports/import.rs | 3 ++- src/tests/validity.rs | 3 ++- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index da271ac5..3705cb5f 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -16,14 +16,16 @@ const AMBER_DEBUG_TIME: &str = "AMBER_DEBUG_TIME"; pub struct AmberCompiler { pub cc: Compiler, - pub path: Option + pub path: Option, + pub rdc_disabled: bool } impl AmberCompiler { - pub fn new(code: String, path: Option) -> AmberCompiler { + pub fn new(code: String, path: Option, rdc_disabled: bool) -> AmberCompiler { AmberCompiler { cc: Compiler::new("Amber", rules::get_rules()), - path + path, + rdc_disabled }.load_code(code) } @@ -110,10 +112,13 @@ impl AmberCompiler { } result.push(block.translate(&mut meta)); let res = result.join("\n"); + let mut header = include_str!("header.sh").to_string(); + if ! self.rdc_disabled { + header += &rdc::generate(meta.externs); + } format!( - "{}\n{}\n{}", - include_str!("header.sh"), - rdc::generate(meta.externs), + "{}\n{}", + header, res ) } diff --git a/src/main.rs b/src/main.rs index 7207ccb0..a4ebd8dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,10 @@ struct Cli { /// Code to evaluate #[arg(short, long)] eval: Option, + + /// Disable Runtime Dependency Checker (not recommended) + #[arg(long)] + disable_rdc: bool } fn main() { @@ -32,7 +36,7 @@ fn main() { if let Some(code) = cli.eval { let code = format!("import * from \"std\"\n{code}"); - match AmberCompiler::new(code, None).compile() { + match AmberCompiler::new(code, None, cli.disable_rdc).compile() { Ok((messages, code)) => { messages.iter().for_each(|m| m.show()); (!messages.is_empty()).then(|| render_dash()); @@ -48,7 +52,7 @@ fn main() { match fs::read_to_string(&input) { Ok(code) => { - match AmberCompiler::new(code, Some(input)).compile() { + match AmberCompiler::new(code, Some(input), cli.disable_rdc).compile() { Ok((messages, code)) => { messages.iter().for_each(|m| m.show()); // Save to the output file diff --git a/src/modules/imports/import.rs b/src/modules/imports/import.rs index 22640a80..1a4d4651 100644 --- a/src/modules/imports/import.rs +++ b/src/modules/imports/import.rs @@ -87,7 +87,8 @@ impl Import { } fn handle_compile_code(&mut self, meta: &mut ParserMetadata, imported_code: String) -> SyntaxResult { - match AmberCompiler::new(imported_code.clone(), Some(self.path.value.clone())).tokenize() { + // FIXME: Disable RDC here, if it is disabled for user code + match AmberCompiler::new(imported_code.clone(), Some(self.path.value.clone()), false).tokenize() { Ok(tokens) => { let mut block = Block::new(); // Save snapshot of current file diff --git a/src/tests/validity.rs b/src/tests/validity.rs index ea663a7f..57e446e0 100644 --- a/src/tests/validity.rs +++ b/src/tests/validity.rs @@ -3,7 +3,8 @@ use crate::compiler::AmberCompiler; macro_rules! test_amber { ($code:expr, $result:expr) => { { - match AmberCompiler::new($code.to_string(), None).test_eval() { + // RDC is disabled in these tests because it will be tested later and could break things + match AmberCompiler::new($code.to_string(), None, false).test_eval() { Ok(result) => assert_eq!(result.trim(), $result), Err(err) => panic!("ERROR: {}", err.message.unwrap()) } From ebe83c7e69dab96ec309775c44aced32a0776848 Mon Sep 17 00:00:00 2001 From: b1ek Date: Sat, 25 May 2024 16:36:24 +1000 Subject: [PATCH 4/9] add tests for RDC --- src/tests/mod.rs | 3 ++- src/tests/rdc.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/tests/rdc.rs diff --git a/src/tests/mod.rs b/src/tests/mod.rs index a0363a6d..51b80c2d 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1 +1,2 @@ -pub mod validity; \ No newline at end of file +pub mod validity; +pub mod rdc; \ No newline at end of file diff --git a/src/tests/rdc.rs b/src/tests/rdc.rs new file mode 100644 index 00000000..974be120 --- /dev/null +++ b/src/tests/rdc.rs @@ -0,0 +1,35 @@ +use std::process::{Command, Stdio}; + +use crate::compiler::AmberCompiler; + +#[test] +fn nonexistant_command() { + let compiler = AmberCompiler::new("unsafe $rfdhyikjeldrhfnjdkfmgdfk$".to_string(), None, false); + let compiled = compiler.compile().map_or_else(Err, |(_, code)| { + let child = Command::new("/bin/bash") + .arg("-c") + .arg(code.to_string()) + .stderr(Stdio::piped()) + .spawn().unwrap().wait_with_output().unwrap(); + assert_eq!(child.status.code(), Some(1)); + assert_eq!(String::from_utf8(child.stderr).unwrap(), "This program requires for these commands: ( rfdhyikjeldrhfnjdkfmgdfk ) to be present in $PATH.\n"); + Ok(()) + }); + compiled.unwrap(); +} + +#[test] +fn existant_command() { + let compiler = AmberCompiler::new("unsafe $bash -c 'echo ok'$".to_string(), None, false); + let compiled = compiler.compile().map_or_else(Err, |(_, code)| { + let child = Command::new("/bin/bash") + .arg("-c") + .arg(code.to_string()) + .stdout(Stdio::piped()) + .spawn().unwrap().wait_with_output().unwrap(); + assert_eq!(child.status.code(), Some(0)); + assert_eq!(String::from_utf8(child.stdout).unwrap(), "ok\n"); + Ok(()) + }); + compiled.unwrap(); +} \ No newline at end of file From 6ac56d15e0d937c20d385f2924c474967610c0b6 Mon Sep 17 00:00:00 2001 From: b1ek Date: Sat, 25 May 2024 16:37:13 +1000 Subject: [PATCH 5/9] add RDC on install and uninstall scripts --- setup/install.sh | 1 - setup/uninstall.sh | 57 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/setup/install.sh b/setup/install.sh index dfa2f5f6..b71594b1 100755 --- a/setup/install.sh +++ b/setup/install.sh @@ -1,6 +1,5 @@ #!/bin/bash # Written in [Amber](https://amber-lang.com/) - # This is the runtime dependency checker. Please do not remove these lines. CD=('eval' 'exit' '[[' 'test' 'sudo' 'test' 'mkdir' 'curl' 'mv' 'chmod' 'ln' 'curl') MD=() diff --git a/setup/uninstall.sh b/setup/uninstall.sh index c50a7c76..9933a25f 100755 --- a/setup/uninstall.sh +++ b/setup/uninstall.sh @@ -1,3 +1,23 @@ +#!/bin/bash +# Written in [Amber](https://amber-lang.com/) +# This is the runtime dependency checker. Please do not remove these lines. +CD=('exit' '[[' 'test' 'sudo' 'test' 'rm') +MD=() +for d in "${CD[@]}" +do + if ! command -v $d > /dev/null 2>&1; then + MD+=($d) + fi +done + +if (( ${#MD[@]} != 0 )); then + >&2 echo This program requires for these commands: \( $MD \) to be present in \$PATH. + exit 1 +fi +unset $CD +unset $MD +# Dependencies are ok at this point + function exit__21_v0 { local code=$1 exit "${code}" @@ -60,11 +80,24 @@ function get_bins_folder__30_v0 { local user_only=$1 if [ ${user_only} != 0 ]; then get_home__29_v0 ; - __AF_get_home29_v0__46=$__AF_get_home29_v0; - __AF_get_bins_folder30_v0="$__AF_get_home29_v0__46/.local/bin"; + __AF_get_home29_v0__46="${__AF_get_home29_v0}"; + __AF_get_bins_folder30_v0="${__AF_get_home29_v0__46}/.local/bin"; return 0 else - __AF_get_bins_folder30_v0="/usr/local/bin"; + local bins_folder="/usr/local/bin" + test -d "${bins_folder}" +__AS=$?; +if [ $__AS != 0 ]; then + sudo mkdir -p "${bins_folder}" > /dev/null 2>&1 +__AS=$?; +if [ $__AS != 0 ]; then + echo "Failed to create ${bins_folder} directory." + exit__21_v0 1 > /dev/null 2>&1; + __AF_exit21_v0__53=$__AF_exit21_v0; + echo $__AF_exit21_v0__53 > /dev/null 2>&1 +fi +fi + __AF_get_bins_folder30_v0="${bins_folder}"; return 0 fi } @@ -72,10 +105,10 @@ function get_place__31_v0 { local user_only=$1 if [ ${user_only} != 0 ]; then get_home__29_v0 ; - __AF_get_home29_v0__54=$__AF_get_home29_v0; + __AF_get_home29_v0__62="${__AF_get_home29_v0}"; get_arch__28_v0 ; - __AF_get_arch28_v0__54=$__AF_get_arch28_v0; - __AF_get_place31_v0="$__AF_get_home29_v0__54/.local/lib/$__AF_get_arch28_v0__54/amber"; + __AF_get_arch28_v0__62="${__AF_get_arch28_v0}"; + __AF_get_place31_v0="${__AF_get_home29_v0__62}/.local/lib/${__AF_get_arch28_v0__62}/amber"; return 0 else __AF_get_place31_v0="/opt/amber"; @@ -85,17 +118,17 @@ fi echo "" args=$1 get_arch__28_v0 ; - __AF_get_arch28_v0__8=$__AF_get_arch28_v0; - arch=$__AF_get_arch28_v0__8 + __AF_get_arch28_v0__8="${__AF_get_arch28_v0}"; + arch="${__AF_get_arch28_v0__8}" includes__22_v1 "${args}" "--user"; __AF_includes22_v1__10=$__AF_includes22_v1; user_only_install=$__AF_includes22_v1__10 get_place__31_v0 ${user_only_install}; - __AF_get_place31_v0__11=$__AF_get_place31_v0; - place=$__AF_get_place31_v0__11 + __AF_get_place31_v0__11="${__AF_get_place31_v0}"; + place="${__AF_get_place31_v0__11}" get_bins_folder__30_v0 ${user_only_install}; - __AF_get_bins_folder30_v0__12=$__AF_get_bins_folder30_v0; - bins_folder=$__AF_get_bins_folder30_v0__12 + __AF_get_bins_folder30_v0__12="${__AF_get_bins_folder30_v0}"; + bins_folder="${__AF_get_bins_folder30_v0__12}" test -d "${place}" > /dev/null __AS=$? if [ $(echo $__AS '==' 0 | bc -l | sed '/\./ s/\.\{0,1\}0\{1,\}$//') != 0 ]; then From 00929b749a7c7887bf9f6aca8ceb164460b6f725 Mon Sep 17 00:00:00 2001 From: b1ek Date: Sat, 25 May 2024 16:52:40 +1000 Subject: [PATCH 6/9] prefix RDC's variables --- setup/install.sh | 16 ++++++++-------- setup/uninstall.sh | 16 ++++++++-------- src/modules/rdc.rs | 2 +- src/modules/rdc.sh | 14 +++++++------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/setup/install.sh b/setup/install.sh index b71594b1..8538df05 100755 --- a/setup/install.sh +++ b/setup/install.sh @@ -1,21 +1,21 @@ #!/bin/bash # Written in [Amber](https://amber-lang.com/) # This is the runtime dependency checker. Please do not remove these lines. -CD=('eval' 'exit' '[[' 'test' 'sudo' 'test' 'mkdir' 'curl' 'mv' 'chmod' 'ln' 'curl') -MD=() -for d in "${CD[@]}" +AMBER_RDC_CD=('eval' 'exit' '[[' 'test' 'sudo' 'test' 'mkdir' 'curl' 'mv' 'chmod' 'ln' 'curl') +AMBER_RDC_MD=() +for d in "${AMBER_RDC_CD[@]}" do if ! command -v $d > /dev/null 2>&1; then - MD+=($d) + AMBER_RDC_MD+=($d) fi done -if (( ${#MD[@]} != 0 )); then - >&2 echo This program requires for these commands: \( $MD \) to be present in \$PATH. +if (( ${#AMBER_RDC_MD[@]} != 0 )); then + >&2 echo This program requires for these commands: \( $AMBER_RDC_MD \) to be present in \$PATH. exit 1 fi -unset $CD -unset $MD +unset $AMBER_RDC_CD +unset $AMBER_RDC_MD # Dependencies are ok at this point function has_failed__20_v0 { diff --git a/setup/uninstall.sh b/setup/uninstall.sh index 9933a25f..c49eb165 100755 --- a/setup/uninstall.sh +++ b/setup/uninstall.sh @@ -1,21 +1,21 @@ #!/bin/bash # Written in [Amber](https://amber-lang.com/) # This is the runtime dependency checker. Please do not remove these lines. -CD=('exit' '[[' 'test' 'sudo' 'test' 'rm') -MD=() -for d in "${CD[@]}" +AMBER_RDC_CD=('exit' '[[' 'test' 'sudo' 'test' 'rm') +AMBER_RDC_MD=() +for d in "${AMBER_RDC_CD[@]}" do if ! command -v $d > /dev/null 2>&1; then - MD+=($d) + AMBER_RDC_MD+=($d) fi done -if (( ${#MD[@]} != 0 )); then - >&2 echo This program requires for these commands: \( $MD \) to be present in \$PATH. +if (( ${#AMBER_RDC_MD[@]} != 0 )); then + >&2 echo This program requires for these commands: \( $AMBER_RDC_MD \) to be present in \$PATH. exit 1 fi -unset $CD -unset $MD +unset $AMBER_RDC_CD +unset $AMBER_RDC_MD # Dependencies are ok at this point function exit__21_v0 { diff --git a/src/modules/rdc.rs b/src/modules/rdc.rs index cbe3fae4..51e704e0 100644 --- a/src/modules/rdc.rs +++ b/src/modules/rdc.rs @@ -10,7 +10,7 @@ pub fn generate(externals: Vec) -> String { let externals = externals.iter().dedup().map(|x| x.clone()).collect::>(); let mut code = String::new(); code += "# This is the runtime dependency checker. Please do not remove these lines.\n"; - code += format!("CD=(\'{}\')\n", externals.join("\' \'")).as_str(); + code += format!("AMBER_RDC_CD=(\'{}\')\n", externals.join("\' \'")).as_str(); code += include_str!("rdc.sh"); code } diff --git a/src/modules/rdc.sh b/src/modules/rdc.sh index ef1c8d45..810f04ff 100644 --- a/src/modules/rdc.sh +++ b/src/modules/rdc.sh @@ -1,15 +1,15 @@ -MD=() -for d in "${CD[@]}" +AMBER_RDC_MD=() +for d in "${AMBER_RDC_CD[@]}" do if ! command -v $d > /dev/null 2>&1; then - MD+=($d) + AMBER_RDC_MD+=($d) fi done -if (( ${#MD[@]} != 0 )); then - >&2 echo This program requires for these commands: \( $MD \) to be present in \$PATH. +if (( ${#AMBER_RDC_MD[@]} != 0 )); then + >&2 echo This program requires for these commands: \( $AMBER_RDC_MD \) to be present in \$PATH. exit 1 fi -unset $CD -unset $MD +unset $AMBER_RDC_CD +unset $AMBER_RDC_MD # Dependencies are ok at this point From da8c64f6a581c5c5257984a7a349dc1219cc34ff Mon Sep 17 00:00:00 2001 From: b1ek Date: Sun, 26 May 2024 10:50:11 +1000 Subject: [PATCH 7/9] strip variables in RDC --- src/modules/rdc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/rdc.rs b/src/modules/rdc.rs index 51e704e0..e05735cc 100644 --- a/src/modules/rdc.rs +++ b/src/modules/rdc.rs @@ -19,11 +19,11 @@ pub fn scan_append_externs(strings: Vec, meta: &mut TranslateMetadata) - // source: https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html let bash_deps = vec![ "alias", "bind", "builtin", "caller", "command", "declare", "echo", "enable", "help", "let", "local", "logout", "mapfile", "printf", "read", "readarray", "source", "type", "typeset", "ulimit", "unalias" ]; - let remove_prefix_whitespace = Regex::new(r"^ +").unwrap(); + let remove_prefix_var = Regex::new(r"^(\w+=\S+( \w+=\S+)*|) +").unwrap(); let remove_all_non_cmd = Regex::new(r" .*$").unwrap(); for x in strings.iter() { - let parsed = remove_prefix_whitespace.replace(x, "").to_string(); + let parsed = remove_prefix_var.replace(x, "").to_string(); let parsed = remove_all_non_cmd.replace(&parsed, "").to_string(); if x.len() != 0 && bash_deps.iter().find(|y| x.to_string() == y.to_string()).is_none() { meta.externs.push(parsed); From 2ffd63c242ae1c54be48c908fa0cbdc1c1014424 Mon Sep 17 00:00:00 2001 From: b1ek Date: Sun, 26 May 2024 11:13:22 +1000 Subject: [PATCH 8/9] don't attach RDC if there are no commands to check for --- src/modules/rdc.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/rdc.rs b/src/modules/rdc.rs index e05735cc..b6db9a69 100644 --- a/src/modules/rdc.rs +++ b/src/modules/rdc.rs @@ -7,6 +7,10 @@ use crate::utils::TranslateMetadata; /// Generate the code pub fn generate(externals: Vec) -> String { + if externals.len() == 0 { + return "".to_string(); + } + let externals = externals.iter().dedup().map(|x| x.clone()).collect::>(); let mut code = String::new(); code += "# This is the runtime dependency checker. Please do not remove these lines.\n"; From db674d2cf8cd632504ea18e7a81178415119732e Mon Sep 17 00:00:00 2001 From: b1ek Date: Sun, 26 May 2024 11:21:10 +1000 Subject: [PATCH 9/9] in case bc, sed or seq are used, add them to externs --- src/modules/expression/literal/range.rs | 1 + src/translate/compute.rs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/expression/literal/range.rs b/src/modules/expression/literal/range.rs index adc29e9d..77c532d3 100644 --- a/src/modules/expression/literal/range.rs +++ b/src/modules/expression/literal/range.rs @@ -46,6 +46,7 @@ impl TranslateModule for Range { fn translate(&self, meta: &mut TranslateMetadata) -> String { let from = self.from.translate(meta); let to = self.to.translate(meta); + meta.externs.push("seq".into()); if self.neq { let to_neq = translate_computation(meta, ArithOp::Sub, Some(to), Some("1".to_string())); meta.gen_subprocess(&format!("seq {} {}", from, to_neq)) diff --git a/src/translate/compute.rs b/src/translate/compute.rs index 4187cc26..aa17063b 100644 --- a/src/translate/compute.rs +++ b/src/translate/compute.rs @@ -21,7 +21,7 @@ pub enum ArithOp { Or } -pub fn translate_computation(meta: &TranslateMetadata, operation: ArithOp, left: Option, right: Option) -> String { +pub fn translate_computation(meta: &mut TranslateMetadata, operation: ArithOp, left: Option, right: Option) -> String { match meta.arith_module { ArithType::BcSed => { let (left, right) = (left.unwrap_or_default(), right.unwrap_or_default()); @@ -48,6 +48,8 @@ pub fn translate_computation(meta: &TranslateMetadata, operation: ArithOp, left: ArithOp::Or => "||" }; let math_lib_flag = if math_lib_flag { "-l" } else { "" }; + meta.externs.push("bc".into()); + meta.externs.push("sed".into()); meta.gen_subprocess(&format!("echo {left} '{op}' {right} | bc {math_lib_flag} | sed '{sed_regex}'")) } }