Amber icon indicating copy to clipboard operation
Amber copied to clipboard

[BUG] Cannot shadow variables which are already declared readonly

Open karpfediem opened this issue 11 months ago • 6 comments

Describe the bug The generated printf function tries create a local variable by the name "args". If this variable name was previously declared as readonly, bash exits with the error:

$ amber run name-collision.ab 
environment: line 9: args: readonly variable
environment: line 9: local: args: readonly variable
environment: line 10: args: readonly variable

amber 0.4.0-alpha rev: d3ceda317fc053ae9645e9f3c8f166657eba24e9

To Reproduce File: name-collision.ab

import { echo_info } from "std/env"

main(args) {
echo_info("hi")
}
$ amber run name-collision.ab 
environment: line 9: args: readonly variable
environment: line 9: local: args: readonly variable
environment: line 10: args: readonly variable

Expected behavior The scripts should not crash and be able to assign local variables. We might need to use a prefix or generate variable names a user likely won't use in their own code. (Which would unfortunately make code more unreadable).

Additional context Some discussions can be found here https://lists.gnu.org/archive/html/bug-bash/2011-02/msg00105.html and here https://lists.gnu.org/archive/html/bug-bash/2019-03/msg00150.html

In the name-collision.ab example given in this issue, the variable args is already assigned as global read-only variable:

#!/usr/bin/env bash
# Written in [Amber](https://amber-lang.com/)
# version: 0.4.0-alpha
# date: 2025-01-15 17:04:11


printf__99_v0() {
    local format=$1
    local args=("${!2}")
     args=("${format}" "${args[@]}") ;
    __AS=$?
     printf "${args[@]}" ;
    __AS=$?
}
echo_info__106_v0() {
    local message=$1
    __AMBER_ARRAY_0=("${message}");
    printf__99_v0 "\x1b[1;3;97;44m%s\x1b[0m
" __AMBER_ARRAY_0[@];
    __AF_printf99_v0__147_5="$__AF_printf99_v0";
    echo "$__AF_printf99_v0__147_5" > /dev/null 2>&1
}
declare -r args=("$0" "$@")
    echo_info__106_v0 "hi";
    __AF_echo_info106_v0__4_1="$__AF_echo_info106_v0";
    echo "$__AF_echo_info106_v0__4_1" > /dev/null 2>&1

Relevant Parts:

declare -r args=("$0" "$@")

and later a reassignment even if shadowed is rejected:

    local args=("${!2}")

karpfediem avatar Jan 15 '25 16:01 karpfediem

So we need to improve this function code https://github.com/amber-lang/amber/blob/main/src/std/env.ab#L110

Maybe we can use a variable name less common like __args?

Mte90 avatar Jan 15 '25 16:01 Mte90

So we need to improve this function code https://github.com/amber-lang/amber/blob/main/src/std/env.ab#L110

Maybe we can use a variable name less common like __args?

That would only fix the problem in this instance. I think a better solution would be to name-mangle local as well as global variables, by using local __0_args instead of local args.

hdwalters avatar Jan 15 '25 17:01 hdwalters

Specifically, we would need to change https://github.com/amber-lang/amber/blob/main/src/modules/variable/init.rs#L72, and other lines like it. This is one reason I've been wanting to centralise all Bash variable name generation, so we don't have to go searching for all instances... but that may be a larger task than is called for at this point.

hdwalters avatar Jan 15 '25 17:01 hdwalters

Even better would be to just always assign a global ID. I'm trying a fix.

hdwalters avatar Jan 15 '25 19:01 hdwalters

However, since this affects the translation layer, it would be sensible to wait until @Ph0enixKM has merged his forthcoming PR.

hdwalters avatar Jan 16 '25 19:01 hdwalters

maybe the argument to main doesn't need to be read-only?

Thesola10 avatar Mar 06 '25 19:03 Thesola10