Skip to content

Commit

Permalink
Merge branch '1.6.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
odino committed Aug 4, 2019
2 parents 2cefcfd + fa3bd94 commit ec94f32
Show file tree
Hide file tree
Showing 33 changed files with 503 additions and 127 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Expand Up @@ -8,7 +8,7 @@ repository.

Since we follow [semver](https://semver.org/),
when a new feature is released we don't backport it but simply
create a new version branch, such as `1.5.x`. Bugs, instead,
create a new version branch, such as `1.6.x`. Bugs, instead,
might be backported from `1.1.0` to, for example, `1.0.x` and we
will have a new [release](https://github.com/abs-lang/abs/releases),
say `1.0.1` for the `1.0.x` version branch.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Expand Up @@ -24,12 +24,12 @@

# The ABS programming language

ABS is a scripting language that works best when you're scripting on
ABS is a programming language that works best when you're scripting on
your terminal. It tries to combine the elegance of languages
such as Python, or Ruby, to the convenience of Bash.

``` bash
tz = $(cat /etc/timezone);
tz = `cat /etc/timezone`
continent, city = tz.split("/")

echo("Best city in the world?")
Expand Down Expand Up @@ -73,7 +73,7 @@ And here's how you could write the same code in ABS:
``` bash
# Simple program that fetches your IP and sums it up
res = $(curl -s 'https://api.ipify.org?format=json');
res = `curl -s 'https://api.ipify.org?format=json'`
if !res.ok {
echo("An error occurred: %s", res)
Expand Down
22 changes: 18 additions & 4 deletions ast/ast.go
Expand Up @@ -492,10 +492,18 @@ func (al *ArrayLiteral) String() string {
return out.String()
}

// IndexExpression allows accessing a single index, or a range,
// over a string or an array.
//
// array[1:10] -> left[index:end]
// array[1] -> left[index]
// string[1] -> left[index]
type IndexExpression struct {
Token token.Token // The [ token
Left Expression
Index Expression
Token token.Token // The [ token
Left Expression // the argument on which the index is access eg array of array[1]
Index Expression // the left-most index eg. 1 in array[1] or array[1:10]
IsRange bool // whether the expression is a range (1:10)
End Expression // the end of the range, if the expression is a range
}

func (ie *IndexExpression) expressionNode() {}
Expand All @@ -506,7 +514,13 @@ func (ie *IndexExpression) String() string {
out.WriteString("(")
out.WriteString(ie.Left.String())
out.WriteString("[")
out.WriteString(ie.Index.String())

if ie.IsRange {
out.WriteString(ie.Index.String() + ":" + ie.End.String())
} else {
out.WriteString(ie.Index.String())
}

out.WriteString("])")

return out.String()
Expand Down
10 changes: 5 additions & 5 deletions docs/README.md
Expand Up @@ -21,12 +21,12 @@
<img href="https://github.com/abs-lang/abs" alt="undefined" src="https://img.shields.io/github/stars/abs-lang/abs.svg?style=social">
</p>

ABS is a scripting language that works best when you're scripting on
ABS is a programming language that works best when you're scripting on
your terminal. It tries to combine the elegance of languages
such as Python, or Ruby, to the convenience of Bash.

``` bash
tz = $(cat /etc/timezone);
tz = `cat /etc/timezone`;
continent, city = tz.split("/")

echo("Best city in the world?")
Expand All @@ -48,14 +48,14 @@ in Bash:
``` bash
# Simple program that fetches your IP and sums it up
RES=$(curl -s 'https://api.ipify.org?format=json' || "ERR")
RES=`curl -s 'https://api.ipify.org?format=json' || "ERR"`

if [ "$RES" = "ERR" ]; then
echo "An error occurred"
exit 1
fi

IP=$(echo $RES | jq -r ".ip")
IP=`echo $RES | jq -r ".ip"`
IFS=. read first second third fourth <<EOF
${IP##*-}
EOF
Expand All @@ -70,7 +70,7 @@ And here's how you could write the same code in ABS:
``` bash
# Simple program that fetches your IP and sums it up
res = $(curl -s 'https://api.ipify.org?format=json');
res = `curl -s 'https://api.ipify.org?format=json'`
if !res.ok {
echo("An error occurred: %s", res)
Expand Down
2 changes: 1 addition & 1 deletion docs/installer.sh
Expand Up @@ -27,7 +27,7 @@ if [ "${MACHINE_TYPE}" = 'x86_64' ]; then
ARCH="amd64"
fi

VERSION=1.5.1
VERSION=1.6.0

echo "Trying to detect the details of your architecture."
echo ""
Expand Down
2 changes: 1 addition & 1 deletion docs/introduction/how-to-run-abs-code.md
Expand Up @@ -61,7 +61,7 @@ the fly:
$ abs
Hello there, welcome to the ABS programming language!
Type 'quit' when you're done, 'help' if you get lost!
⧐ ip = $(curl icanhazip.com)
⧐ ip = `curl icanhazip.com`
⧐ ip.ok
true
⧐ ip()
Expand Down
4 changes: 2 additions & 2 deletions docs/introduction/why-another-scripting-language.md
Expand Up @@ -44,7 +44,7 @@ call the API of nba.com in order to retrieve the stats for
one of last year's NBA games:

``` bash
r = $(curl "http://data.nba.net/prod/v1/20170201/0021600732_boxscore.json" -H 'DNT: 1' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://stats.nba.com/' -H 'Connection: keep-alive' --compressed);
r = `curl "http://data.nba.net/prod/v1/20170201/0021600732_boxscore.json" -H 'DNT: 1' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://stats.nba.com/' -H 'Connection: keep-alive' --compressed`;

if !r.ok {
echo("Could not fetch game data. Bummer!")
Expand Down Expand Up @@ -79,7 +79,7 @@ A sneak-peek at some of the things ABS can elegantly do:
``` bash
# Unix pipes work
ip = $(curl icanhazip.com | tr -d '\n')
ip = `curl icanhazip.com | tr -d '\n'`

# We now have a string -> "10.10.10.12"
echo(ip)
Expand Down
8 changes: 4 additions & 4 deletions docs/misc/error.md
Expand Up @@ -21,10 +21,10 @@ $ cat examples/error-parse.abs
m.a = 'abc'
# this is a command terminated with a semi
d/d = $(command);
d/d = `command`;
# this is a command terminated with a LF
c/c = $(command)
c/c = `command`
# this is a bad infix operator
b %% c
Expand All @@ -34,9 +34,9 @@ $ abs examples/error-parse.abs
no prefix parse function for '=' found
[4:5] m.a = 'abc'
no prefix parse function for '=' found
[7:5] d/d = $(command);
[7:5] d/d = `command`;
no prefix parse function for '=' found
[10:5] c/c = $(command)
[10:5] c/c = `command`
no prefix parse function for '%' found
[13:4] b %% c
Expand Down
6 changes: 3 additions & 3 deletions docs/misc/technical-details.md
Expand Up @@ -37,9 +37,9 @@ tests/test-parser.abs
no prefix parse function for '=' found
[4:5] m.a = 'abc'
no prefix parse function for '=' found
[7:5] d/d = $(command);
[7:5] d/d = `command`;
no prefix parse function for '=' found
[10:5] c/c = $(command)
[10:5] c/c = `command`
no prefix parse function for '%' found
[13:4] b %% c
no prefix parse function for '&&' found
Expand Down Expand Up @@ -205,7 +205,7 @@ ERROR: type mismatch: NULL + NUMBER

## Roadmap

We're currently working on [1.6](https://github.com/abs-lang/abs/milestone/13).
We're currently working on [1.7](https://github.com/abs-lang/abs/milestone/14).

## Next

Expand Down
8 changes: 8 additions & 0 deletions docs/syntax/return.md
Expand Up @@ -20,6 +20,14 @@ func = f(x) {
func(9) # 10
```

The default value of a `return` is `null`:

```
if x {
return # null
}
```

## Next

That's about it for this section!
Expand Down
122 changes: 63 additions & 59 deletions docs/syntax/system-commands.md
Expand Up @@ -4,11 +4,10 @@ Executing system commands is one of the most important features
of ABS, as it allows the mixing of conveniency of the shell with
the syntax of a modern programming language.

Commands are executed either with `$(command)` or `` `command` ``,
Commands are executed with the `` `command` `` syntax,
which resemble Bash's syntax to execute commands in a subshell:

``` bash
date = $(date) # "Sun Apr 1 04:30:59 +01 1995"
date = `date` # "Sun Apr 1 04:30:59 +01 1995"
```

Expand All @@ -18,7 +17,7 @@ encounter an error, the same string would hold the error
message:

``` bash
date = $(dat) # "bash: dat: command not found"
date = `dat` # "bash: dat: command not found"
```

It would be fairly painful to have to parse strings
Expand All @@ -27,60 +26,11 @@ in ABS, the returned string has a special property `ok` that
checks whether the command was successful:

``` bash
ls = $(ls -la)

if ls.ok {
echo("hello world")
}

# or

if `ls -la`.ok {
echo("hello world")
}
```
It is also possible to execute a shell command without capturing its
input or output using the `exec(command)` function. This allows long running
or interactive programs to be run using the terminal's Standard IO
(stdin, stdout, stderr). For example:
```bash
exec("sudo visudo")
```
would open the default text editor in super user mode on the /etc/sudoers file.
Unlike the normal backtick command execution syntax above,
the `exec(command)` function call does not return a result string unless it fails.
Therefore, the `exec(command)` may be the last command executed in a script
file leaving the executed command in charge of the terminal IO until it
terminates.
For example, an ABS script might be used to marshall the command line args
for an interactive program such as the nano editor:
``` bash
$ cat abs/tests/test-exec.abs
# marshall the args for the nano editor
# if the filename is not given in the args, prompt for it
# if the file is located outside the user's home dir, invoke sudo nano filename
cmd = 'nano'
filename = arg(2)
homedir = env("HOME")
while filename == '' {
echo("Please enter file name for %s: ", cmd)
filename = stdin()
}
if filename.prefix('~/') || filename.prefix(homedir) {
sudo = ''
} else {
sudo = 'sudo'
}
# execute the command with live stdIO
exec("$sudo $cmd $filename")
```
## Executing commands in background
Sometimes you might want to execute a command in
Expand Down Expand Up @@ -155,13 +105,21 @@ and if you need `$` literals in your command, you
simply need to escape them with a `\`:
``` bash
$(echo $PWD) # "" since the ABS variable PWD doesn't exist
$(echo \$PWD) # "/go/src/github.com/abs-lang/abs"
`echo $PWD` # "" since the ABS variable PWD doesn't exist
`echo \$PWD` # "/go/src/github.com/abs-lang/abs"
```
## Limitations
## Alternative $() syntax
Even though the use of backticks is the standard recommended
way to run system commands, for the ease of embedding ABS also
allows you to use the `$(command)` syntax:
```
$(basename $(dirname "/tmp/make/life/easy")) // "easy"
```
Currently, commands that use the `$()` syntax need to be
Commands that use the `$()` syntax need to be
on their own line, meaning that you will not
be able to have additional code on the same line.
This will throw an error:
Expand All @@ -170,10 +128,56 @@ This will throw an error:
$(sleep 10); echo("hello world")
```
Note that this is currently a limitation that will likely
be removed in the future (see [#41](https://github.com/abs-lang/abs/issues/41)).
## Executing commands without capturing I/O
It is also possible to execute a shell command without capturing its
input or output using the `exec(command)` function. This allows long running
or interactive programs to be run using the terminal's Standard IO
(stdin, stdout, stderr). For example:
```bash
exec("sudo visudo")
```
would open the default text editor in super user mode on the /etc/sudoers file.
Unlike the normal backtick command execution syntax above,
the `exec(command)` function call does not return a result string unless it fails.
Therefore, the `exec(command)` may be the last command executed in a script
file leaving the executed command in charge of the terminal IO until it
terminates.
For example, an ABS script might be used to marshall the command line args
for an interactive program such as the nano editor:
``` bash
$ cat abs/tests/test-exec.abs
# marshall the args for the nano editor
# if the filename is not given in the args, prompt for it
# if the file is located outside the user's home dir, invoke sudo nano filename
cmd = 'nano'
filename = arg(2)
homedir = env("HOME")
while filename == '' {
echo("Please enter file name for %s: ", cmd)
filename = stdin()
}
if filename.prefix('~/') || filename.prefix(homedir) {
sudo = ''
} else {
sudo = 'sudo'
}
# execute the command with live stdIO
exec("$sudo $cmd $filename")
```
## Limitations
Also note that, currently, the implementation of system commands
Note that the implementation of system commands
requires the `bash` executable to [be available on the system](https://github.com/abs-lang/abs/blob/5b5b0abf3115a5dd4dfe8485501f8765985ad0db/evaluator/evaluator.go#L696-L722).
On Windows, commands are executed through [cmd.exe](https://github.com/abs-lang/abs/blob/ee793641be09ad8572c3e913fef8468f69b0c0a2/evaluator/evaluator.go#L1101-L1103).
Future work will make it possible to select which shell to use,
Expand Down

0 comments on commit ec94f32

Please sign in to comment.