Bitshift
This commit is contained in:
@@ -33,6 +33,8 @@ const (
|
||||
OpBitwiseXOR
|
||||
OpBitwiseAND
|
||||
OpBitwiseNOT
|
||||
OpLeftShift
|
||||
OpRightShift
|
||||
OpTrue
|
||||
OpFalse
|
||||
OpEqual
|
||||
@@ -84,6 +86,8 @@ var definitions = map[Opcode]*Definition{
|
||||
OpBitwiseXOR: {"OpBitwiseXOR", []int{}},
|
||||
OpBitwiseAND: {"OpBitwiseAND", []int{}},
|
||||
OpBitwiseNOT: {"OpBitwiseNOT", []int{}},
|
||||
OpLeftShift: {"OpLeftShift", []int{}},
|
||||
OpRightShift: {"OpRightShift", []int{}},
|
||||
OpTrue: {"OpTrue", []int{}},
|
||||
OpFalse: {"OpFalse", []int{}},
|
||||
OpEqual: {"OpEqual", []int{}},
|
||||
|
||||
@@ -148,6 +148,10 @@ func (c *Compiler) Compile(node ast.Node) error {
|
||||
c.emit(code.OpBitwiseXOR)
|
||||
case "&":
|
||||
c.emit(code.OpBitwiseAND)
|
||||
case "<<":
|
||||
c.emit(code.OpLeftShift)
|
||||
case ">>":
|
||||
c.emit(code.OpRightShift)
|
||||
case "||":
|
||||
c.emit(code.OpOr)
|
||||
case "&&":
|
||||
|
||||
@@ -87,6 +87,26 @@ func TestIntegerArithmetic(t *testing.T) {
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "1 << 2",
|
||||
expectedConstants: []interface{}{1, 2},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpLeftShift),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "4 >> 2",
|
||||
expectedConstants: []interface{}{4, 2},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpRightShift),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "-1",
|
||||
expectedConstants: []interface{}{1},
|
||||
|
||||
@@ -434,6 +434,10 @@ func evalIntegerInfixExpression(operator string, left, right object.Object) obje
|
||||
return &object.Integer{Value: leftVal ^ rightVal}
|
||||
case "&":
|
||||
return &object.Integer{Value: leftVal & rightVal}
|
||||
case "<<":
|
||||
return &object.Integer{Value: leftVal << uint64(rightVal)}
|
||||
case ">>":
|
||||
return &object.Integer{Value: leftVal >> uint64(rightVal)}
|
||||
case "<":
|
||||
return nativeBoolToBooleanObject(leftVal < rightVal)
|
||||
case "<=":
|
||||
|
||||
@@ -38,6 +38,8 @@ func TestEvalExpressions(t *testing.T) {
|
||||
{"3 & 6", 2},
|
||||
{`" " * 4`, " "},
|
||||
{`4 * " "`, " "},
|
||||
{"1 << 2", 4},
|
||||
{"4 >> 2", 1},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -116,6 +116,11 @@ func (l *Lexer) NextToken() token.Token {
|
||||
l.readChar()
|
||||
tok = newToken(token.LTE, l.ch)
|
||||
tok.Literal = "<="
|
||||
} else if l.peekChar() == '<' {
|
||||
ch := l.ch
|
||||
l.readChar()
|
||||
literal := string(ch) + string(l.ch)
|
||||
tok = token.Token{Type: token.LEFT_SHIFT, Literal: literal}
|
||||
} else {
|
||||
tok = newToken(token.LT, l.ch)
|
||||
}
|
||||
@@ -124,6 +129,11 @@ func (l *Lexer) NextToken() token.Token {
|
||||
l.readChar()
|
||||
tok = newToken(token.GTE, l.ch)
|
||||
tok.Literal = ">="
|
||||
} else if l.peekChar() == '>' {
|
||||
ch := l.ch
|
||||
l.readChar()
|
||||
literal := string(ch) + string(l.ch)
|
||||
tok = token.Token{Type: token.RIGHT_SHIFT, Literal: literal}
|
||||
} else {
|
||||
tok = newToken(token.GT, l.ch)
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ func TestNextToken(t *testing.T) {
|
||||
d.foo
|
||||
&|^~
|
||||
!&&||
|
||||
<<>>
|
||||
`
|
||||
|
||||
tests := []struct {
|
||||
@@ -146,6 +147,8 @@ func TestNextToken(t *testing.T) {
|
||||
{token.NOT, "!"},
|
||||
{token.AND, "&&"},
|
||||
{token.OR, "||"},
|
||||
{token.LEFT_SHIFT, "<<"},
|
||||
{token.RIGHT_SHIFT, ">>"},
|
||||
{token.EOF, ""},
|
||||
}
|
||||
|
||||
|
||||
@@ -14,17 +14,18 @@ const (
|
||||
OR
|
||||
AND
|
||||
NOT
|
||||
ASSIGN // := or =
|
||||
EQUALS // ==
|
||||
LESSGREATER // > or <
|
||||
BITWISE_OR // |
|
||||
BITWISE_XOR // ^
|
||||
BITWISE_AND // &
|
||||
SUM // + or -
|
||||
PRODUCT // * or / or %
|
||||
PREFIX // -X or !X
|
||||
CALL // myFunction(X)
|
||||
INDEX // array[index]
|
||||
ASSIGN // := or =
|
||||
EQUALS // ==
|
||||
LESSGREATER // > or <
|
||||
BITWISE_OR // |
|
||||
BITWISE_XOR // ^
|
||||
BITWISE_AND // &
|
||||
BITWISE_SHIFT // << or >>
|
||||
SUM // + or -
|
||||
PRODUCT // * or / or %
|
||||
PREFIX // -X or !X
|
||||
CALL // myFunction(X)
|
||||
INDEX // array[index]
|
||||
)
|
||||
|
||||
var precedences = map[token.TokenType]int{
|
||||
@@ -42,6 +43,8 @@ var precedences = map[token.TokenType]int{
|
||||
token.BITWISE_OR: BITWISE_OR,
|
||||
token.BITWISE_XOR: BITWISE_XOR,
|
||||
token.BITWISE_AND: BITWISE_AND,
|
||||
token.LEFT_SHIFT: BITWISE_SHIFT,
|
||||
token.RIGHT_SHIFT: BITWISE_SHIFT,
|
||||
token.PLUS: SUM,
|
||||
token.MINUS: SUM,
|
||||
token.DIVIDE: PRODUCT,
|
||||
@@ -112,6 +115,9 @@ func New(l *lexer.Lexer) *Parser {
|
||||
p.registerInfix(token.BITWISE_XOR, p.parseInfixExpression)
|
||||
p.registerInfix(token.BITWISE_AND, p.parseInfixExpression)
|
||||
|
||||
p.registerInfix(token.LEFT_SHIFT, p.parseInfixExpression)
|
||||
p.registerInfix(token.RIGHT_SHIFT, p.parseInfixExpression)
|
||||
|
||||
p.registerPrefix(token.NOT, p.parsePrefixExpression)
|
||||
p.registerInfix(token.OR, p.parseInfixExpression)
|
||||
p.registerInfix(token.AND, p.parseInfixExpression)
|
||||
|
||||
@@ -38,6 +38,10 @@ const (
|
||||
BITWISE_XOR = "^"
|
||||
// BITWISE_NOT NOT
|
||||
BITWISE_NOT = "~"
|
||||
// LeftShift
|
||||
LEFT_SHIFT = "<<"
|
||||
// RightShift
|
||||
RIGHT_SHIFT = ">>"
|
||||
|
||||
//
|
||||
// Comparision operators
|
||||
|
||||
7
vm/vm.go
7
vm/vm.go
@@ -114,7 +114,8 @@ func (vm *VM) Run() error {
|
||||
}
|
||||
|
||||
case code.OpAdd, code.OpSub, code.OpMul, code.OpDiv, code.OpMod, code.OpOr,
|
||||
code.OpAnd, code.OpBitwiseOR, code.OpBitwiseXOR, code.OpBitwiseAND:
|
||||
code.OpAnd, code.OpBitwiseOR, code.OpBitwiseXOR, code.OpBitwiseAND,
|
||||
code.OpLeftShift, code.OpRightShift:
|
||||
err := vm.executeBinaryOperation(op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -631,6 +632,10 @@ func (vm *VM) executeBinaryIntegerOperation(op code.Opcode, left, right object.O
|
||||
result = leftValue ^ rightValue
|
||||
case code.OpBitwiseAND:
|
||||
result = leftValue & rightValue
|
||||
case code.OpLeftShift:
|
||||
result = leftValue << uint64(rightValue)
|
||||
case code.OpRightShift:
|
||||
result = leftValue >> uint64(rightValue)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown integer operator: %d", op)
|
||||
|
||||
@@ -230,6 +230,8 @@ func TestIntegerArithmetic(t *testing.T) {
|
||||
{"1 | 2", 3},
|
||||
{"2 ^ 4", 6},
|
||||
{"3 & 6", 2},
|
||||
{"1 << 2", 4},
|
||||
{"4 >> 2", 1},
|
||||
}
|
||||
|
||||
runVmTests(t, tests)
|
||||
|
||||
Reference in New Issue
Block a user