Skip to content

Commit

Permalink
[doc] Introduce concepts "h-value" and "r-value" of the expansion ${x}
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Dec 31, 2024
1 parent 13491ca commit a17ddcf
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 18 deletions.
5 changes: 3 additions & 2 deletions core/runtime.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,9 @@ module runtime

coerced = Int | Float | Neither

# evaluation state for BracedVarSub
VarSubState = (bool join_array, value holder_val, Token array_ref)
# evaluation state for BracedVarSub. See "doc/ref/chap-word-lang.md" for
# the description of h-value of a variable substitution.
VarSubState = (bool join_array, value h_value, Token array_ref)

# A Cell is a wrapper for a value.
# TODO: add location for declaration for 'assigning const' error
Expand Down
31 changes: 19 additions & 12 deletions doc/ref/chap-word-lang.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,27 +300,34 @@ string:

---

`${x@a}` returns the set of characters that represent the attributes of the
variable in which each resulting string is stored.
`${x@a}` returns the set of characters that represent the attributes of
*h-value* of the expansion `$x`.

Here, *h-value* is the variable (or the object that the variable directly
points) from which the result of `$x` would originally come. This is different
from the *r-value* of the expansion `$x`, namely the result of the expansion
`$x`.

The characters representing attributes are listed below:

- `a`: The value of `$x` would be obtained from an indexed array element.
- `A`: The value of `$x` would be obtained from an associative array element.
- `r`: The value of `$x` would be obtained from a readonly container.
- `x`: The value of `$x` would be obtained from a container with the export attribute.
- `n`: `x` is a name reference (OSH extension)

It should be noted that `${x@a}` does not return the attributes of the obtained
value. For example, `${a[0]@a}` returns `a` because the string `${a[0]}` would
be obtained from an array although the resulting value of `${a[0]}` is a scalar
string.
It should be noted that `${x@a}` does not return the attributes of the
*r-value* of the expansion `$x`. For example, although the *r-value* of
`${arr[0]}` is arr scalar string, `${arr[0]@a}` returns `a` because the
*h-value* is array `arr`, which stores the element `arr[0]`.

$ echo ${a[0]@a}
$ echo ${arr[0]@a}
a

When `$x` would result in a word list (such as `${a[@]}` and `${!ref}` with
`ref="a[@]"`), `${x@a}` returns a word list containing the attributes for each
word.
When `$x` would result in a word list (such as `${arr[@]}` and `${!ref}` with
`ref="arr[@]"`), `${x@a}` returns a word list containing the attributes of the
*h-value* of each word.

$ a=(1 2 3)
$ echo "${a[@]@a}"
$ arr=(1 2 3)
$ echo "${arr[@]@a}"
a a a
8 changes: 4 additions & 4 deletions osh/word_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -1104,7 +1104,7 @@ def _Nullary(self, val, op, var_name, vsub_token, vsub_state):
# We're ONLY simluating -a and -A, not -r -x -n for now. See
# spec/ble-idioms.test.sh.
chars = [] # type: List[str]
with tagswitch(vsub_state.holder_val) as case:
with tagswitch(vsub_state.h_value) as case:
if case(value_e.BashArray):
chars.append('a')
elif case(value_e.BashAssoc):
Expand Down Expand Up @@ -1353,8 +1353,8 @@ def _VarRefValue(self, part, quoted, vsub_state, vtest_place):
# $* decays
val = self._EvalSpecialVar(part.name_tok.id, quoted, vsub_state)

# update the holder of the current value
vsub_state.holder_val = val
# update h-value (i.e., the holder of the current value)
vsub_state.h_value = val

# We don't need var_index because it's only for L-Values of test ops?
if self.exec_opts.eval_unsafe_arith():
Expand Down Expand Up @@ -1448,7 +1448,7 @@ def _EvalBracedVarSub(self, part, part_vals, quoted):
suffix_op_ = part.suffix_op
if suffix_op_:
UP_op = suffix_op_
vsub_state.holder_val = val
vsub_state.h_value = val

# 2. Bracket Op
val = self._EvalBracketOp(val, part, quoted, vsub_state, vtest_place)
Expand Down

0 comments on commit a17ddcf

Please sign in to comment.