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