Skip to content

Commit

Permalink
Merge branch '1.11.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
odino committed Feb 16, 2020
2 parents 5cd75ac + 170019d commit 6af68af
Show file tree
Hide file tree
Showing 21 changed files with 705 additions and 57 deletions.
38 changes: 38 additions & 0 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ func (ce *CommandExpression) String() string {

type FunctionLiteral struct {
Token token.Token // The 'fn' token
Name string // identifier for this function
Parameters []*Identifier
Body *BlockStatement
}
Expand All @@ -433,6 +434,43 @@ func (fl *FunctionLiteral) String() string {
return out.String()
}

type Decorator struct {
Token token.Token // @
Name string
Arguments []Expression
Decorated *FunctionLiteral
}

func (dc *Decorator) expressionNode() {}
func (dc *Decorator) TokenLiteral() string { return dc.Token.Literal }
func (dc *Decorator) String() string {
var out bytes.Buffer

args := []string{}
for _, a := range dc.Arguments {
args = append(args, a.String())
}

out.WriteString(dc.TokenLiteral())
out.WriteString(dc.Name)
out.WriteString("(")
out.WriteString(strings.Join(args, ", "))
out.WriteString(") ")
out.WriteString(dc.Decorated.String())

return out.String()
}

type CurrentArgsLiteral struct {
Token token.Token // ...
}

func (cal *CurrentArgsLiteral) expressionNode() {}
func (cal *CurrentArgsLiteral) TokenLiteral() string { return cal.Token.Literal }
func (cal *CurrentArgsLiteral) String() string {
return "..."
}

type CallExpression struct {
Token token.Token // The '(' token
Function Expression // Identifier or FunctionLiteral
Expand Down
1 change: 1 addition & 0 deletions docs/_includes/toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
* [Hash](/types/hash)
* [Functions](/types/function)
* [Builtin functions](/types/builtin-function)
* [Decorators](/types/decorator)

## Miscellaneous

Expand Down
Binary file modified docs/abs.wasm
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ if [ "${MACHINE_TYPE}" = 'x86_64' ]; then
ARCH="amd64"
fi

VERSION=1.10.1
VERSION=1.11.0

echo "Trying to detect the details of your architecture."
echo ""
Expand Down
2 changes: 1 addition & 1 deletion docs/misc/3pl.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ another file is specified:

```
$ ~/projects/abs/builds/abs
Hello alex, welcome to the ABS (1.10.1) programming language!
Hello alex, welcome to the ABS (1.11.0) programming language!
Type 'quit' when you're done, 'help' if you get lost!
⧐ require("abs-sample-module")
Expand Down
4 changes: 2 additions & 2 deletions docs/types/builtin-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ $ cat ~/.absrc
source("~/abs/lib/library.abs")
$ abs
Hello user, welcome to the ABS (1.10.1) programming language!
Hello user, welcome to the ABS (1.11.0) programming language!
Type 'quit' when you are done, 'help' if you get lost!
⧐ adder(1, 2)
3
Expand Down Expand Up @@ -353,4 +353,4 @@ statements until changed.
That's about it for this section!
You can now head over to read a little bit about [how to install 3rd party libraries](/misc/3pl).
You can now head over to read a little bit about [decorators](/types/decorator).
73 changes: 73 additions & 0 deletions docs/types/decorator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Decorator

Decorators are a feature built on top of
ABS' functions -- they're not a type *per se*.

A decorator is a function that "wraps" another
function, allowing you to enhance the original
function's functionality with the decorator's
one.

An example could be a decorator that logs how
long a function takes to execute, or delays
execution altogether.

## Declaring decorators

A decorator is a plain-old function that
accepts `1 + N` arguments, where `1` is the
function being wrapped, and returns a new
function that wraps the original one:

```py
f log_if_slow(original_fn, treshold_ms) {
return f() {
start = `date +%s%3N`.int()
res = original_fn(...)
end = `date +%s%3N`.int()

if end - start > treshold_ms {
echo("mmm, we were pretty slow...")
}

return res
}
}
```

That's as simple as that: a named function
that returns a new function that executes the
decorated one (`original_fn`) and returns its
result, while logging if it takes longer than
a few milliseconds.

## Using decorators

Now that we've declared our decorator, it's time
to use it, through the `@` notation:

```py
@log_if_slow(500)
f return_random_number_after_sleeping(seconds) {
`sleep $seconds`
return rand(1000)
}
```

and we can test our decorator has takn the stage:

```console
⧐ return_random_number_after_sleeping(0)
493
⧐ return_random_number_after_sleeping(1)
mmm, we were pretty slow...
371
```

Decorators are heavily inspired by [Python](https://www.python.org/dev/peps/pep-0318/).

## Next

That's about it for this section!

You can now head over to read a little bit about [how to install 3rd party libraries](/misc/3pl).
97 changes: 96 additions & 1 deletion docs/types/function.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ Functions must be called with the right number of arguments:

``` bash
fn = f(x) { x }
fn() # ERROR: Wrong number of arguments passed to f(x) {
fn()
# ERROR: Wrong number of arguments passed to f(x) {
# x
# }. Want [x], got []
```
Expand Down Expand Up @@ -80,6 +81,91 @@ func = f(x) {
}
```
## Named functions
You can create named functions by specifying an identifier
after the `f` keyword:
``` bash
f greeter(name) {
echo("Hello $name!")
}

greeter(`whoami`) # "Hello root!"
```
As an alternative, you can manually assign
a function declaration to a variable, though
this is not the recommended approach:
``` bash
greeter = f (name) {
echo("Hello $name!")
}

greeter(`whoami`) # "Hello root!"
```
Named functions are the basis of [decorators](/types/decorators).
## Accessing function arguments
Functions can receive a dynamic number of arguments,
and arguments can be "packed" through the special
`...` variable:
```py
f sum_numbers() {
s = 0
for x in ... {
s += x
}

return s
}

sum_numbers(1) # 1
sum_numbers(1, 2, 3) # 6
```
`...` is a special variable that acts
like an array, so you can loop and slice
it however you want:
```py
f first_arg() {
if ....len() > 0 {
return ...[0]
}

return "No first arg"
}

first_arg() # "No first arg"
first_arg(1) # 1
```
When you pass `...` directly to a function,
it will be unpacked:
```py
f echo_wrapper() {
echo(...)
}

echo_wrapper("hello %s", "root") # "hello root"
```
and you can add additional arguments as well:
```py
f echo_wrapper() {
echo(..., "root")
}

echo_wrapper("hello %s %s", "sir") # "hello sir root"
```
## Supported functions
### str()
Expand All @@ -93,6 +179,15 @@ f(x){}.str()
# }
```
### call(args)
Calls a function with the given arguments:
``` bash
doubler = f(x) { x * 2 }
doubler.call([10]) # 20
```
## Next
That's about it for this section!
Expand Down
Loading

0 comments on commit 6af68af

Please sign in to comment.