Skip to content

Commit

Permalink
Bas-style interpolation in strings, closes #169
Browse files Browse the repository at this point in the history
Now you can embed variables inside strings by prefixing them with
`$`. Literal `$` simply need a `\`. This aligns the string interpolation
syntax with commands, and makes it easier to switch between running
a command (`` `$some $command` ``) and echoing it (`echo("$some $command")`).
  • Loading branch information
odino committed Sep 8, 2019
1 parent 3fbfaef commit 430e40a
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 6 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ if !res.ok {
ip = res.json().ip
total = ip.split(".").map(int).sum()
if total > 100 {
echo("The sum of [%s] is a large number, %s.", ip, total)
echo("The sum of [$ip] is a large number, $total.")
}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ if !res.ok {
ip = res.json().ip
total = ip.split(".").map(int).sum()
if total > 100 {
echo("The sum of [%s] is a large number, %s.", ip, total)
echo("The sum of [$ip] is a large number, $total.")
}
```
Expand Down
19 changes: 19 additions & 0 deletions docs/types/string.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@ To test for the existence of substrings within strings use the `in` operator:
"xyz" in "string" # false
```

## Interpolation

You can also replace parts of the string with variables
declared within your program using the `$` symbol:

``` bash
file = "/etc/hosts"
x = "File name is: $file"
echo(x) # "File name is: /etc/hosts"
```

If you need `$` literals in your command, you
simply need to escape them with a `\`:

``` bash
"$non_existing_var" # "" since the ABS variable 'non_existing_var' doesn't exist
"\$non_existing_var" # "$non_existing_var"
```

## Special characters embedded in strings

Double and single quoted strings behave differently if the string contains
Expand Down
2 changes: 1 addition & 1 deletion evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
return NULL

case *ast.StringLiteral:
return &object.String{Token: node.Token, Value: node.Value}
return &object.String{Token: node.Token, Value: util.InterpolateStringVars(node.Value, env)}

case *ast.Boolean:
return nativeBoolToBooleanObject(node.Value)
Expand Down
16 changes: 16 additions & 0 deletions evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,22 @@ func TestStringWriters(t *testing.T) {
}
}

func TestStringInterpolation(t *testing.T) {
tests := []struct {
input string
expected string
}{
{`a = "123"; "abc$a"`, "abc123"},
{`a = "123"; "abc\$a"`, "abc$a"},
{`a = "123"; "$$a$$a$$a"`, "$123$123$123"},
}

for _, tt := range tests {
evaluated := testEval(tt.input)
testStringObject(t, evaluated, tt.expected)
}
}

func TestForInExpressions(t *testing.T) {
tests := []struct {
input string
Expand Down
2 changes: 1 addition & 1 deletion examples/ip-sum.abs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ if !res.ok {
ip = res.json().ip
total = ip.split(".").map(int).sum()
if total > 100 {
echo("The sum of [%s] is a large number, %s.", ip, total)
echo("The sum of [$ip] is a large number, $total.")
}
4 changes: 2 additions & 2 deletions scripts/release.abs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ if !rm.ok {

version = `cat ./main.go | grep "var Version"`
version = version.slice(15, len(version) - 1)
echo("Running builds for version %s, confirm by typing \"y\"".fmt(version))
echo("Running builds for version $version, confirm by typing \"y\"")
selection = stdin()

if selection != "y" {
Expand All @@ -63,7 +63,7 @@ if selection != "y" {

for platform in platforms {
goos, goarch = platform.split("/")
output_name = "builds/abs-%s-%s-%s".fmt(version, goos, goarch)
output_name = "builds/abs-$version-$goos-$goarch"
entry_point = "main.go"

if goos == "windows" {
Expand Down

0 comments on commit 430e40a

Please sign in to comment.