Skip to content

Commit

Permalink
Merge f4fc95c into 4112e3e
Browse files Browse the repository at this point in the history
  • Loading branch information
odino committed Aug 17, 2019
2 parents 4112e3e + f4fc95c commit f0cc0fe
Show file tree
Hide file tree
Showing 20 changed files with 1,604 additions and 55 deletions.
11 changes: 5 additions & 6 deletions .travis.yml
Expand Up @@ -9,15 +9,14 @@ go:
- "1.12.x"

before_script:
- go get github.com/c-bata/go-prompt
- go get -v github.com/mattn/go-colorable
- go get -v github.com/mattn/go-tty
- go get -u
- go get github.com/mattn/goveralls
- go get -d -v `go list ./... | grep -v "/js"`

env:
- CONTEXT=abs
global:
- GO111MODULE=on
- CONTEXT=abs

script:
- go test `go list ./... | grep -v "/js"` -vet=off -v -covermode=count -coverprofile=coverage.out
- $GOPATH/bin/goveralls -service=travis-ci -coverprofile=coverage.out
- $GOPATH/bin/goveralls -service=travis-ci -coverprofile=coverage.out
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.6.x`. Bugs, instead,
create a new version branch, such as `1.7.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
1,330 changes: 1,330 additions & 0 deletions coverage.out

Large diffs are not rendered by default.

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.6.1
VERSION=1.7.0

echo "Trying to detect the details of your architecture."
echo ""
Expand Down
2 changes: 1 addition & 1 deletion docs/misc/technical-details.md
Expand Up @@ -216,7 +216,7 @@ ERROR: type mismatch: NULL + NUMBER

## Roadmap

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

## Next

Expand Down
14 changes: 11 additions & 3 deletions docs/types/builtin-function.md
Expand Up @@ -75,14 +75,22 @@ for input in stdin {
...
```
### exit(code)
### exit(code [, message])
Exists the script with status `code`:
Exits the script with status `code`:
``` bash
exit(99)
```
You can specify a message that's going to be outputted right
before exiting:
``` bash
⧐ exit(99, "Got problems...")
Got problems...%
```
### rand(max)
Returns a random integer number between 0 and `max`:
Expand Down Expand Up @@ -243,7 +251,7 @@ $ cat ~/.absrc
source("~/abs/lib/library.abs")
$ abs
Hello user, welcome to the ABS (1.6.1) programming language!
Hello user, welcome to the ABS (1.7.0) programming language!
Type 'quit' when you are done, 'help' if you get lost!
⧐ adder(1, 2)
3
Expand Down
12 changes: 10 additions & 2 deletions docs/types/string.md
Expand Up @@ -337,13 +337,21 @@ Creates a new string, repeating the original one `i` times:
"string".repeat(2) # "stringstring"
```

### replace(x, y, n)
### replace(x, y [, n])

Replaces occurrences of `x` with `y`, `n` times.
If `n` is negative it will replace all occurrencies:
If `n` is omitted, or negative, it will replace all occurrencies:

``` bash
"string".replace("i", "o", -1) # "strong"
"aaaa".replace("a", "x") # "xxxx"
"aaaa".replace("a", "x", 2) # "xxaa"
```

You can also replace an array of characters:

``` bash
"string".replace(["i", "g"], "o") # "strono"
```

### title()
Expand Down
18 changes: 18 additions & 0 deletions evaluator/evaluator_test.go
Expand Up @@ -47,6 +47,21 @@ func TestEvalFloatExpression(t *testing.T) {
}
}

func TestEvalNumberAbbreviations(t *testing.T) {
tests := []struct {
input string
expected float64
}{
{"5k", 5000},
{"1m / 1M", 1},
}

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

func TestEvalNumberExpression(t *testing.T) {
tests := []struct {
input string
Expand Down Expand Up @@ -880,6 +895,9 @@ c")`, []string{"a", "b", "c"}},
{`[1,2,3].slice(-1, 3)`, []int{3}},
{`[1,2,3].slice(-1, 1)`, []int{3}},
{`"a".replace("a", "b", -1)`, "b"},
{`"a".replace("a", "b")`, "b"},
{`"ac".replace(["a", "c"], "b", -1)`, "bb"},
{`"ac".replace(["a", "c"], "b")`, "bb"},
{`"a".str()`, "a"},
{`1.str()`, "1"},
{`[1].str()`, "[1]"},
Expand Down
51 changes: 46 additions & 5 deletions evaluator/functions.go
Expand Up @@ -396,12 +396,26 @@ func randFn(tok token.Token, args ...object.Object) object.Object {
}

// exit(code:0)
// exit(code:0, message:"Adios!")
func exitFn(tok token.Token, args ...object.Object) object.Object {
err := validateArgs(tok, "exit", args, 1, [][]string{{object.NUMBER_OBJ}})
var err object.Object
var message string

if len(args) == 2 {
err = validateArgs(tok, "exit", args, 2, [][]string{{object.NUMBER_OBJ}, {object.STRING_OBJ}})
message = args[1].(*object.String).Value
} else {
err = validateArgs(tok, "exit", args, 1, [][]string{{object.NUMBER_OBJ}})
}

if err != nil {
return err
}

if message != "" {
fmt.Fprintf(globalEnv.Writer, message)
}

arg := args[0].(*object.Number)
os.Exit(int(arg.Value))
return arg
Expand Down Expand Up @@ -715,7 +729,7 @@ func typeFn(tok token.Token, args ...object.Object) object.Object {
return &object.String{Token: tok, Value: string(args[0].Type())}
}

// split(string:"hello")
// split(string:"hello world!", sep:" ")
func splitFn(tok token.Token, args ...object.Object) object.Object {
err := validateArgs(tok, "split", args, 2, [][]string{{object.STRING_OBJ}, {object.STRING_OBJ}})
if err != nil {
Expand Down Expand Up @@ -1151,14 +1165,41 @@ func repeatFn(tok token.Token, args ...object.Object) object.Object {
return &object.String{Token: tok, Value: strings.Repeat(args[0].(*object.String).Value, int(args[1].(*object.Number).Value))}
}

// replace("abc", "b", "f", -1)
// replace("abd", "d", "c") --> short form
// replace("abd", "d", "c", -1)
// replace("abc", ["a", "b"], "c", -1)
func replaceFn(tok token.Token, args ...object.Object) object.Object {
err := validateArgs(tok, "replace", args, 4, [][]string{{object.STRING_OBJ}, {object.STRING_OBJ}, {object.STRING_OBJ}, {object.NUMBER_OBJ}})
var err object.Object

// Support short form
if len(args) == 3 {
err = validateArgs(tok, "replace", args, 3, [][]string{{object.STRING_OBJ}, {object.STRING_OBJ, object.ARRAY_OBJ}, {object.STRING_OBJ}})
} else {
err = validateArgs(tok, "replace", args, 4, [][]string{{object.STRING_OBJ}, {object.STRING_OBJ, object.ARRAY_OBJ}, {object.STRING_OBJ}, {object.NUMBER_OBJ}})
}

if err != nil {
return err
}

return &object.String{Token: tok, Value: strings.Replace(args[0].(*object.String).Value, args[1].(*object.String).Value, args[2].(*object.String).Value, int(args[3].(*object.Number).Value))}
original := args[0].(*object.String).Value
replacement := args[2].(*object.String).Value

n := -1

if len(args) == 4 {
n = int(args[3].(*object.Number).Value)
}

if characters, ok := args[1].(*object.Array); ok {
for _, c := range characters.Elements {
original = strings.Replace(original, c.Inspect(), replacement, n)
}

return &object.String{Token: tok, Value: original}
}

return &object.String{Token: tok, Value: strings.Replace(original, args[1].(*object.String).Value, replacement, n)}
}

// title("some thing")
Expand Down
10 changes: 6 additions & 4 deletions go.mod
Expand Up @@ -3,11 +3,13 @@ module github.com/abs-lang/abs
go 1.12

require (
github.com/c-bata/go-prompt v0.2.3
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/c-bata/go-prompt v0.2.4-0
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.9 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859 // indirect
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 // indirect
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
)

replace github.com/c-bata/go-prompt => github.com/odino/go-prompt v0.2.4-0.20190816001457-ea717205ca73412c085f2b2296f11c674f359f5c
32 changes: 19 additions & 13 deletions go.sum
@@ -1,22 +1,28 @@
github.com/c-bata/go-prompt v0.2.3 h1:jjCS+QhG/sULBhAaBdjb2PlMRVaKXQgn+4yzaauvs2s=
github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859 h1:smQbSzmT3EHl4EUwtFwFGmGIpiYgIiiPeVv1uguIQEE=
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/mattn/go-tty v0.0.0-20190424173100-523744f04859/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 h1:A7GG7zcGjl3jqAqGPmcNjd/D9hzL95SuoOQAaFNdLU0=
github.com/odino/go-prompt v0.2.4-0.20190816001457-9305aa75823e h1:mTySyY/vV0hlz9FlqLIrBthNof8fjMqVZPDhn6v2jJs=
github.com/odino/go-prompt v0.2.4-0.20190816001457-9305aa75823e/go.mod h1:r3+2ndvD23nUkN89DAba+DuXLHnaDwNrpvmSl/eYGUU=
github.com/odino/go-prompt v0.2.4-0.20190816001457-ea717205ca73412c085f2b2296f11c674f359f5c h1:VifSDBOIAnbm1vrgm0/hkiXNEd9UgBjW++10L7PDoVM=
github.com/odino/go-prompt v0.2.4-0.20190816001457-ea717205ca73412c085f2b2296f11c674f359f5c/go.mod h1:r3+2ndvD23nUkN89DAba+DuXLHnaDwNrpvmSl/eYGUU=
github.com/pkg/term v0.0.0-20180423043932-cda20d4ac917/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20180620133508-ad87a3a340fa/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862 h1:rM0ROo5vb9AdYJi1110yjWGMej9ITfKddS89P3Fkhug=
golang.org/x/sys v0.0.0-20190509141414-a5b02f93d862/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
29 changes: 25 additions & 4 deletions lexer/lexer.go
Expand Up @@ -347,19 +347,32 @@ func (l *Lexer) readIdentifier() string {
return string(l.input[position:l.position])
}

// List of character that can appear in a "number"
//
// * digits
// * dot for floats
// * scientific notation characters (12e-1)
// * separators (1_000_000)
// * abbreviations (12M)
func isCharAllowedInNumber(c rune) bool {
lowchar := unicode.ToLower(c)
_, isAbbr := token.NumberAbbreviations[string(lowchar)]

return isDigit(lowchar) || lowchar == '.' || lowchar == '+' || lowchar == '-' || c == 'e' || lowchar == token.NumberSeparator || isAbbr
}

// 12
// 12.2
// 12e-1
// 12e+1
// 12e1
func (l *Lexer) readNumber() (number string, kind token.TokenType) {
position := l.position
hasDot := false
kind = token.NUMBER
hasExponent := false
var hasDot bool
var hasExponent bool

// List of character that can appear in a "number"
for isDigit(l.ch) || l.ch == '.' || l.ch == '+' || l.ch == '-' || l.ch == 'e' || l.ch == '_' {
for isCharAllowedInNumber(l.ch) {
// If we have a plus / minus but there was no exponent
// in this number, it means we're at the end of the
// number and we're at an addition / subtraction.
Expand All @@ -373,6 +386,14 @@ func (l *Lexer) readNumber() (number string, kind token.TokenType) {
hasExponent = true
}

// If this character is a number abbreviation
// (eg. the K in 12K), let's read it and complete
// the number
if _, isAbbr := token.NumberAbbreviations[string(l.ch)]; isAbbr {
l.readChar()
return string(l.input[position:l.position]), kind
}

// If we have a dot, let's check whether this is a range
// or maybe a method call (122.string())
if l.ch == '.' && (l.peekChar() == '.' || !isDigit(l.peekChar())) {
Expand Down
16 changes: 16 additions & 0 deletions lexer/lexer_test.go
Expand Up @@ -85,6 +85,14 @@ $111
10_000
10_00.00
1_2e1
12k
12K
12m
12M
12t
12T
12b
12B
小明
hello_w0rld
Expand Down Expand Up @@ -316,6 +324,14 @@ a[1:3]
{token.NUMBER, "10000"},
{token.NUMBER, "1000.00"},
{token.NUMBER, "12e1"},
{token.NUMBER, "12k"},
{token.NUMBER, "12K"},
{token.NUMBER, "12m"},
{token.NUMBER, "12M"},
{token.NUMBER, "12t"},
{token.NUMBER, "12T"},
{token.NUMBER, "12b"},
{token.NUMBER, "12B"},
{token.IDENT, "小明"},
{token.ILLEGAL, "❤"},
{token.IDENT, "hello_w0rld"},
Expand Down
2 changes: 1 addition & 1 deletion main.go
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/abs-lang/abs/repl"
)

var Version = "1.6.1"
var Version = "1.7.0"

// The ABS interpreter
func main() {
Expand Down
3 changes: 3 additions & 0 deletions object/environment.go
Expand Up @@ -2,6 +2,7 @@ package object

import (
"io"
"sort"
)

// NewEnclosedEnvironment creates an environment
Expand Down Expand Up @@ -49,6 +50,8 @@ func (e *Environment) GetKeys() []string {
keys = append(keys, k)
}

sort.Strings(keys)

return keys
}

Expand Down

0 comments on commit f0cc0fe

Please sign in to comment.