Skip to content

Commit

Permalink
floats are a thing now, closes #44, closes #29
Browse files Browse the repository at this point in the history
  • Loading branch information
odino committed Dec 26, 2018
1 parent afe2af9 commit d46530b
Show file tree
Hide file tree
Showing 18 changed files with 348 additions and 250 deletions.
10 changes: 5 additions & 5 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,14 @@ func (b *Boolean) expressionNode() {}
func (b *Boolean) TokenLiteral() string { return b.Token.Literal }
func (b *Boolean) String() string { return b.Token.Literal }

type IntegerLiteral struct {
type NumberLiteral struct {
Token token.Token
Value int64
Value float64
}

func (il *IntegerLiteral) expressionNode() {}
func (il *IntegerLiteral) TokenLiteral() string { return il.Token.Literal }
func (il *IntegerLiteral) String() string { return il.Token.Literal }
func (nl *NumberLiteral) expressionNode() {}
func (nl *NumberLiteral) TokenLiteral() string { return nl.Token.Literal }
func (nl *NumberLiteral) String() string { return nl.Token.Literal }

type PrefixExpression struct {
Token token.Token // The prefix token, e.g. !
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ sh <(curl https://www.abs-lang.org/installer.sh)
## Types and functions
* [String](/types/string)
* [Integer](/types/int)
* [Number](/types/number)
* [Array](/types/array)
* [Hash](/types/hash)
* [Functions](/types/function)
Expand Down
12 changes: 6 additions & 6 deletions docs/introduction/why-another-scripting-language.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,21 @@ call the API of nba.com in order to retrieve the stats for
one of last year's NBA games:

``` bash
res = $(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 !res.ok {
if !r.ok {
echo("Could not fetch game data. Bummer!")
exit(1)
}

doc = res.json()
doc = r.json()

arena = doc["basicGameData"]["arena"]["name"]
city = doc["basicGameData"]["arena"]["city"]
highlight = doc["basicGameData"]["nugget"]["text"]
arena = doc.basicGameData.arena.name
city = doc.basicGameData.arena.city

echo("The game was played at the %s in %s", arena, city)

highlight = doc.basicGameData.nugget.text
if highlight.len() {
echo("The press said: \"%s\"", highlight)
}
Expand Down
3 changes: 1 addition & 2 deletions docs/misc/error.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ $ cat examples/error.abs
echo("should not reach here")
$ abs examples/error.abs
go build -o builds/abs main.go
ERROR: type mismatch: INTEGER + STRING
ERROR: type mismatch: NUMBER + STRING
$ echo $?
99
Expand Down
14 changes: 7 additions & 7 deletions docs/types/array.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ Returns the length of the array:
### sum()
Sums the elements of the array. Only supported on arrays of integers:
Sums the elements of the array. Only supported on arrays of numbers:
``` bash
[1, 1, 1].sum() # 3
```
### sort()
Sorts the array. Only supported on arrays of only integers
Sorts the array. Only supported on arrays of only numbers
or only strings:
``` bash
Expand Down Expand Up @@ -88,7 +88,7 @@ Returns true when all elements in the array
return `true` when applied to the function `f`:
``` bash
[0, 1, 2].every(f(x){type(x) == "INTEGER"}) # true
[0, 1, 2].every(f(x){type(x) == "NUMBER"}) # true
[0, 1, 2].every(f(x){x == 0}) # false
```
Expand All @@ -97,7 +97,7 @@ return `true` when applied to the function `f`:
Returns the first element that returns `true` when applied to the function `f`:
``` bash
["hello", 0, 1, 2].find(f(x){type(x) == "INTEGER"}) # 0
["hello", 0, 1, 2].find(f(x){type(x) == "NUMBER"}) # 0
```
### find(f)
Expand All @@ -106,7 +106,7 @@ Returns a new array with only the elements that returned
`true` when applied to the function `f`:
``` bash
["hello", 0, 1, 2].filter(f(x){type(x) == "INTEGER"}) # [0, 1, 2]
["hello", 0, 1, 2].filter(f(x){type(x) == "NUMBER"}) # [0, 1, 2]
```
### json()
Expand All @@ -125,8 +125,8 @@ as well as being able to parse all valid JSON expressions (see [#54](https://git
### contains(e)
Checks whether `e` is present in the array. `e` can only be
a string or integer and the array needs to be a heterogeneous array
of strings or integers:
a string or number and the array needs to be a heterogeneous array
of strings or number:
``` bash
[1, 2, 3].contains(3) # true
Expand Down
6 changes: 3 additions & 3 deletions docs/types/builtin-function.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ There are many builtin functions in ABS.
Take `type`, for example:

``` bash
type(1) # INTEGER
type(1) # NUMBER
type([]) # ARRAY
```

We'll reveal you a secret now: all string, array, integer, hash functions
We'll reveal you a secret now: all string, array, number & hash functions
are actually "generic", but the syntax you see makes you think those are
specific to the string, integer, etc object.
specific to the string, number, etc object.

The trick is very simple; whenever the ABS' interpreter seem a method call
such as `object.func(arg)` it will actually translate it to `func(object, arg)`.
Expand Down
25 changes: 17 additions & 8 deletions docs/types/int.md → docs/types/number.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@
</a>
</p>

# Integer
# Number

Integers are very straightforward data structures:
Numbers are very straightforward data structures:

``` bash
123456789
123
1.23
```

Most mathematical operators are designed to work
with them

``` bash
2 ** 5 / 1 / 3 + 19 % 5
(2 ** 5.5 / 1 / 3 + 19) % 5 # 4.08494466531301
```

Note that integers have what we call a "zero value":
Note that numbers have what we call a "zero value":
a value that evaluates to `false` when casted to boolean:

``` bash
Expand All @@ -28,17 +29,25 @@ a value that evaluates to `false` when casted to boolean:

## Supported functions

### int()
### number()

Identity:

``` bash
99.int() # 99
99.5.number() # 99.5
```

### int()

Rounds down the number to the closest integer:

``` bash
10.3.int() # 10
```

### str()

Returns a string containing the integer:
Returns a string containing the number:

``` bash
99.str() # "99"
Expand Down
14 changes: 12 additions & 2 deletions docs/types/string.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,22 @@ Formats a string ([sprintf convention](https://linux.die.net/man/3/sprintf)):
"hello %s".fmt("world") # "hello world"
```

### number()

Converts a string to a number, if possible:

``` bash
"99.5".number() # 99.5
"a".number() # ERROR: int(...) can only be called on strings which represent numbers, 'a' given
```

### int()

Converts a string to integer, if possible:

``` bash
"99".int() # 99
"99.5".int() # 99
"a".int() # ERROR: int(...) can only be called on strings which represent numbers, 'a' given
```

### split(separator)
Expand Down Expand Up @@ -237,4 +247,4 @@ back as many characters as the value of `start`:

That's about it for this section!

You can now head over to read about [integers](/types/int).
You can now head over to read about [numbers](/types/number).
54 changes: 27 additions & 27 deletions evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
}

// Expressions
case *ast.IntegerLiteral:
return &object.Integer{Value: node.Value}
case *ast.NumberLiteral:
return &object.Number{Value: node.Value}

case *ast.StringLiteral:
return &object.String{Value: node.Value}
Expand Down Expand Up @@ -292,8 +292,8 @@ func evalInfixExpression(
case operator == "+=":
fmt.Printf("%s %s %s", operator, left, right)
return nil
case left.Type() == object.INTEGER_OBJ && right.Type() == object.INTEGER_OBJ:
return evalIntegerInfixExpression(operator, left, right)
case left.Type() == object.NUMBER_OBJ && right.Type() == object.NUMBER_OBJ:
return evalNumberInfixExpression(operator, left, right)
case left.Type() == object.STRING_OBJ && right.Type() == object.STRING_OBJ:
return evalStringInfixExpression(operator, left, right)
case left.Type() == object.ARRAY_OBJ && right.Type() == object.ARRAY_OBJ:
Expand Down Expand Up @@ -325,7 +325,7 @@ func evalBangOperatorExpression(right object.Object) object.Object {
}

return FALSE
case *object.Integer:
case *object.Number:
if o.Value == o.ZeroValue() {
return TRUE
}
Expand All @@ -338,35 +338,35 @@ func evalBangOperatorExpression(right object.Object) object.Object {
}

func evalMinusPrefixOperatorExpression(right object.Object) object.Object {
if right.Type() != object.INTEGER_OBJ {
if right.Type() != object.NUMBER_OBJ {
return newError("unknown operator: -%s", right.Type())
}

value := right.(*object.Integer).Value
return &object.Integer{Value: -value}
value := right.(*object.Number).Value
return &object.Number{Value: -value}
}

func evalIntegerInfixExpression(
func evalNumberInfixExpression(
operator string,
left, right object.Object,
) object.Object {
leftVal := left.(*object.Integer).Value
rightVal := right.(*object.Integer).Value
leftVal := left.(*object.Number).Value
rightVal := right.(*object.Number).Value

switch operator {
case "+":
return &object.Integer{Value: leftVal + rightVal}
return &object.Number{Value: leftVal + rightVal}
case "-":
return &object.Integer{Value: leftVal - rightVal}
return &object.Number{Value: leftVal - rightVal}
case "*":
return &object.Integer{Value: leftVal * rightVal}
return &object.Number{Value: leftVal * rightVal}
case "/":
return &object.Integer{Value: leftVal / rightVal}
return &object.Number{Value: leftVal / rightVal}
case "**":
// TODO this does not support floats
return &object.Integer{Value: int64(math.Pow(float64(leftVal), float64(rightVal)))}
return &object.Number{Value: math.Pow(leftVal, rightVal)}
case "%":
return &object.Integer{Value: leftVal % rightVal}
return &object.Number{Value: math.Mod(leftVal, rightVal)}
case "<":
return nativeBoolToBooleanObject(leftVal < rightVal)
case ">":
Expand All @@ -376,7 +376,7 @@ func evalIntegerInfixExpression(
case ">=":
return nativeBoolToBooleanObject(leftVal >= rightVal)
case "<=>":
i := &object.Integer{}
i := &object.Number{}

if leftVal == rightVal {
i.Value = 0
Expand All @@ -396,7 +396,7 @@ func evalIntegerInfixExpression(
a := make([]object.Object, 0)

for i := leftVal; i <= rightVal; i++ {
a = append(a, &object.Integer{Value: int64(i)})
a = append(a, &object.Number{Value: float64(i)})
}
return &object.Array{Elements: a}
default:
Expand Down Expand Up @@ -564,7 +564,7 @@ func evalForInExpression(
for k, v := range i.Elements {
// set the special k v variables in the
// environment
env.Set(fie.Key, &object.Integer{Value: int64(k)})
env.Set(fie.Key, &object.Number{Value: float64(k)})
env.Set(fie.Value, v)
err := Eval(fie.Block, env)

Expand Down Expand Up @@ -607,7 +607,7 @@ func isTruthy(obj object.Object) bool {
return v.Value
// An integer is truthy
// unless it's 0
case *object.Integer:
case *object.Number:
return v.Value != v.ZeroValue()
// A string is truthy
// unless is empty
Expand Down Expand Up @@ -736,11 +736,11 @@ func unwrapReturnValue(obj object.Object) object.Object {

func evalIndexExpression(left, index object.Object) object.Object {
switch {
case left.Type() == object.ARRAY_OBJ && index.Type() == object.INTEGER_OBJ:
case left.Type() == object.ARRAY_OBJ && index.Type() == object.NUMBER_OBJ:
return evalArrayIndexExpression(left, index)
case left.Type() == object.HASH_OBJ && index.Type() == object.STRING_OBJ:
return evalHashIndexExpression(left, index)
case left.Type() == object.STRING_OBJ && index.Type() == object.INTEGER_OBJ:
case left.Type() == object.STRING_OBJ && index.Type() == object.NUMBER_OBJ:
return evalStringIndexExpression(left, index)
default:
return newError("index operator not supported: %s on %s", index.Inspect(), left.Type())
Expand All @@ -749,8 +749,8 @@ func evalIndexExpression(left, index object.Object) object.Object {

func evalStringIndexExpression(array, index object.Object) object.Object {
stringObject := array.(*object.String)
idx := index.(*object.Integer).Value
max := int64(len(stringObject.Value) - 1)
idx := index.(*object.Number).Int()
max := len(stringObject.Value) - 1

if idx < 0 || idx > max {
return NULL
Expand All @@ -761,8 +761,8 @@ func evalStringIndexExpression(array, index object.Object) object.Object {

func evalArrayIndexExpression(array, index object.Object) object.Object {
arrayObject := array.(*object.Array)
idx := index.(*object.Integer).Value
max := int64(len(arrayObject.Elements) - 1)
idx := index.(*object.Number).Int()
max := len(arrayObject.Elements) - 1

if idx < 0 || idx > max {
return NULL
Expand Down
Loading

0 comments on commit d46530b

Please sign in to comment.