Skip to content

Commit

Permalink
Merge pull request #73 from d5/charop
Browse files Browse the repository at this point in the history
Operators on Char type
  • Loading branch information
d5 authored Feb 2, 2019
2 parents 0d99cca + 9e73f40 commit 4f222b1
Show file tree
Hide file tree
Showing 9 changed files with 306 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ _* See [here](https://github.com/d5/tengobench) for commands/codes used_

- [Language Syntax](https://github.com/d5/tengo/blob/master/docs/tutorial.md)
- [Object Types](https://github.com/d5/tengo/blob/master/docs/objects.md)
- [Runtime Types](https://github.com/d5/tengo/blob/master/docs/runtime-types.md)
- [Runtime Types](https://github.com/d5/tengo/blob/master/docs/runtime-types.md) and [Operators](https://github.com/d5/tengo/blob/master/docs/operators.md)
- [Builtin Functions](https://github.com/d5/tengo/blob/master/docs/builtins.md)
- [Interoperability](https://github.com/d5/tengo/blob/master/docs/interoperability.md)
- [Tengo CLI](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md)
Expand Down
2 changes: 1 addition & 1 deletion docs/builtins.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ five := from_json(`"five"`)

## string

Tries to convert an object to string object. See [this](https://github.com/d5/tengo/wiki/Variable-Types) for more details on type conversion.
Tries to convert an object to string object. See [Runtime Types](https://github.com/d5/tengo/blob/master/docs/runtime-types.md) for more details on type conversion.

```golang
x := string(123) // v == "123"
Expand Down
2 changes: 1 addition & 1 deletion docs/objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Alternatively the method can return an `Error` value as its result `res` (the fi
IsFalsy() bool
```

IsFalsy method should return true if the underlying value is considered to be [falsy](https://github.com/d5/tengo/wiki/Variable-Types#objectisfalsy).
IsFalsy method should return true if the underlying value is considered to be [falsy](https://github.com/d5/tengo/blob/master/docs/runtime-types.md#objectisfalsy).

```golang
Equals(o Object) bool
Expand Down
185 changes: 185 additions & 0 deletions docs/operators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Operators

## Int

### Equality

- `(int) == (int) = (bool)`: equality
- `(int) != (int) = (bool)`: inequality

### Arithmetic Operators

- `(int) + (int) = (int)`: sum
- `(int) - (int) = (int)`: difference
- `(int) * (int) = (int)`: product
- `(int) / (int) = (int)`: quotient
- `(int) % (int) = (int)`: remainder
- `(int) + (float) = (float)`: sum
- `(int) - (float) = (float)`: difference
- `(int) * (float) = (float)`: product
- `(int) / (float) = (float)`: quotient
- `(int) + (char) = (char)`: sum
- `(int) - (char) = (char)`: difference

### Bitwise Operators

- `(int) & (int) = (int)`: bitwise AND
- `(int) | (int) = (int)`: bitwise OR
- `(int) ^ (int) = (int)`: bitwise XOR
- `(int) &^ (int) = (int)`: bitclear (AND NOT)
- `(int) << (int) = (int)`: left shift
- `(int) >> (int) = (int)`: right shift

### Comparison Operators

- `(int) < (int) = (bool)`: less than
- `(int) > (int) = (bool)`: greater than
- `(int) <= (int) = (bool)`: less than or equal to
- `(int) >= (int) = (bool)`: greater than or equal to
- `(int) < (float) = (bool)`: less than
- `(int) > (float) = (bool)`: greater than
- `(int) <= (float) = (bool)`: less than or equal to
- `(int) >= (float) = (bool)`: greater than or equal to
- `(int) < (char) = (bool)`: less than
- `(int) > (char) = (bool)`: greater than
- `(int) <= (char) = (bool)`: less than or equal to
- `(int) >= (char) = (bool)`: greater than or equal to

## Float

### Equality

- `(float) == (float) = (bool)`: equality
- `(float) != (float) = (bool)`: inequality

### Arithmetic Operators

- `(float) + (float) = (float)`: sum
- `(float) - (float) = (float)`: difference
- `(float) * (float) = (float)`: product
- `(float) / (float) = (float)`: quotient
- `(float) + (int) = (int)`: sum
- `(float) - (int) = (int)`: difference
- `(float) * (int) = (int)`: product
- `(float) / (int) = (int)`: quotient

### Comparison Operators

- `(float) < (float) = (bool)`: less than
- `(float) > (float) = (bool)`: greater than
- `(float) <= (float) = (bool)`: less than or equal to
- `(float) >= (float) = (bool)`: greater than or equal to
- `(float) < (int) = (bool)`: less than
- `(float) > (int) = (bool)`: greater than
- `(float) <= (int) = (bool)`: less than or equal to
- `(float) >= (int) = (bool)`: greater than or equal to

## String

### Equality

- `(string) == (string) = (bool)`: equality
- `(string) != (string) = (bool)`: inequality

### Concatenation

- `(string) + (string) = (string)`: concatenation
- `(string) + (other types) = (string)`: concatenation (after string-converted)

## Char

### Equality

- `(char) == (char) = (bool)`: equality
- `(char) != (char) = (bool)`: inequality

### Arithmetic Operators

- `(char) + (char) = (char)`: sum
- `(char) - (char) = (char)`: difference
- `(char) + (int) = (char)`: sum
- `(char) - (int) = (char)`: difference

### Comparison Operators

- `(char) < (char) = (bool)`: less than
- `(char) > (char) = (bool)`: greater than
- `(char) <= (char) = (bool)`: less than or equal to
- `(char) >= (char) = (bool)`: greater than or equal to
- `(char) < (int) = (bool)`: less than
- `(char) > (int) = (bool)`: greater than
- `(char) <= (int) = (bool)`: less than or equal to
- `(char) >= (int) = (bool)`: greater than or equal to

## Bool

### Equality

- `(bool) == (bool) = (bool)`: equality
- `(bool) != (bool) = (bool)`: inequality

## Bytes

### Equality

Test whether two byte array contain the same data. Uses [bytes.Compare](https://golang.org/pkg/bytes/#Compare) internally.

- `(bytes) == (bytes) = (bool)`: equality
- `(bytes) != (bytes) = (bool)`: inequality

## Time

### Equality

Tests whether two times represent the same time instance. Uses [Time.Equal](https://golang.org/pkg/time/#Time.Equal) internally.

- `(time) == (time) = (bool)`: equality
- `(time) != (time) = (bool)`: inequality

### Arithmetic Operators

- `(time) - (time) = (int)`: difference in nanoseconds (duration)
- `(time) + (int) = (time)`: time + duration (nanoseconds)
- `(time) - (int) = (time)`: time - duration (nanoseconds)

### Comparison Operators

- `(time) < (time) = (bool)`: less than
- `(time) > (time) = (bool)`: greater than
- `(time) <= (time) = (bool)`: less than or equal to
- `(time) >= (time) = (bool)`: greater than or equal to

## Array and ImmutableArray

### Equality

Tests whether two _(immutable)_ arrays contain the same objects.

- `(array) == (array) = (bool)`: equality
- `(array) != (array) = (bool)`: inequality
- `(array) == (immutable-array) = (bool)`: equality
- `(array) != (immutable-array) = (bool)`: inequality
- `(immutable-array) == (immutable-array) = (bool)`: equality
- `(immutable-array) != (immutable-array) = (bool)`: inequality
- `(immutable-array) == (array) = (bool)`: equality
- `(immutable-array) != (array) = (bool)`: inequality

### Concatenation

- `(array) + (array)`: return a concatenated array

## Map and ImmutableMap

### Equality

Tests whether two _(immutable)_ maps contain the same key-objects.

- `(map) == (map) = (bool)`: equality
- `(map) != (map) = (bool)`: inequality
- `(map) == (immutable-map) = (bool)`: equality
- `(map) != (immutable-map) = (bool)`: inequality
- `(immutable-map) == (immutable-map) = (bool)`: equality
- `(immutable-map) != (immutable-map) = (bool)`: inequality
- `(immutable-map) == (map) = (bool)`: equality
- `(immutable-map) != (map) = (bool)`: inequality

2 changes: 1 addition & 1 deletion docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ c5 := char("X") // 'X'
```
> [Run in Playground](https://tengolang.com/?s=8d57905b82959eb244e9bbd2111e12ee04a33045)
_See [Variable Types](https://github.com/d5/tengo/wiki/Variable-Types) for more details on the variable types._
_See [Runtime Types](https://github.com/d5/tengo/blob/master/docs/runtime-types.md) and [Operators](https://github.com/d5/tengo/blob/master/docs/operators.md) for more details on the value types._

## Indexing

Expand Down
73 changes: 73 additions & 0 deletions objects/char.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,79 @@ func (o *Char) TypeName() string {
// BinaryOp returns another object that is the result of
// a given binary operator and a right-hand side object.
func (o *Char) BinaryOp(op token.Token, rhs Object) (Object, error) {
switch rhs := rhs.(type) {
case *Char:
switch op {
case token.Add:
r := o.Value + rhs.Value
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Sub:
r := o.Value - rhs.Value
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Less:
if o.Value < rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value > rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value <= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value >= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
}
case *Int:
switch op {
case token.Add:
r := o.Value + rune(rhs.Value)
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Sub:
r := o.Value - rune(rhs.Value)
if r == o.Value {
return o, nil
}
return &Char{Value: r}, nil
case token.Less:
if int64(o.Value) < rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if int64(o.Value) > rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if int64(o.Value) <= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if int64(o.Value) >= rhs.Value {
return TrueValue, nil
}
return FalseValue, nil
}
}

return nil, ErrInvalidOperator
}

Expand Down
27 changes: 27 additions & 0 deletions objects/int.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,33 @@ func (o *Int) BinaryOp(op token.Token, rhs Object) (Object, error) {
}
return FalseValue, nil
}
case *Char:
switch op {
case token.Add:
return &Char{rune(o.Value) + rhs.Value}, nil
case token.Sub:
return &Char{rune(o.Value) - rhs.Value}, nil
case token.Less:
if o.Value < int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.Greater:
if o.Value > int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.LessEq:
if o.Value <= int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
case token.GreaterEq:
if o.Value >= int64(rhs.Value) {
return TrueValue, nil
}
return FalseValue, nil
}
}

return nil, ErrInvalidOperator
Expand Down
14 changes: 14 additions & 0 deletions runtime/vm_char_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,18 @@ func TestChar(t *testing.T) {
expect(t, `out = 'a'`, 'a')
expect(t, `out = '九'`, rune(20061))
expect(t, `out = 'Æ'`, rune(198))

expect(t, `out = '0' + '9'`, rune(105))
expect(t, `out = '0' + 9`, '9')
expect(t, `out = '9' - 4`, '5')
expect(t, `out = '0' == '0'`, true)
expect(t, `out = '0' != '0'`, false)
expect(t, `out = '2' < '4'`, true)
expect(t, `out = '2' > '4'`, false)
expect(t, `out = '2' <= '4'`, true)
expect(t, `out = '2' >= '4'`, false)
expect(t, `out = '4' < '4'`, false)
expect(t, `out = '4' > '4'`, false)
expect(t, `out = '4' <= '4'`, true)
expect(t, `out = '4' >= '4'`, true)
}
3 changes: 3 additions & 0 deletions runtime/vm_integer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ func TestInteger(t *testing.T) {
expect(t, `out = 5 % 3 + 4`, 6)
expect(t, `out = +5`, 5)
expect(t, `out = +5 + -5`, 0)

expect(t, `out = 9 + '0'`, '9')
expect(t, `out = '9' - 5`, '4')
}

0 comments on commit 4f222b1

Please sign in to comment.