moulo
This commit is contained in:
@@ -25,6 +25,7 @@ const (
|
||||
OpSub
|
||||
OpMul
|
||||
OpDiv
|
||||
OpMod
|
||||
OpTrue
|
||||
OpFalse
|
||||
OpEqual
|
||||
@@ -69,6 +70,7 @@ var definitions = map[Opcode]*Definition{
|
||||
OpSub: {"OpSub", []int{}},
|
||||
OpMul: {"OpMul", []int{}},
|
||||
OpDiv: {"OpDiv", []int{}},
|
||||
OpMod: {"OpMod", []int{}},
|
||||
OpTrue: {"OpTrue", []int{}},
|
||||
OpFalse: {"OpFalse", []int{}},
|
||||
OpEqual: {"OpEqual", []int{}},
|
||||
|
||||
@@ -139,6 +139,8 @@ func (c *Compiler) Compile(node ast.Node) error {
|
||||
c.emit(code.OpMul)
|
||||
case "/":
|
||||
c.emit(code.OpDiv)
|
||||
case "%":
|
||||
c.emit(code.OpMod)
|
||||
case ">":
|
||||
c.emit(code.OpGreaterThan)
|
||||
case ">=":
|
||||
|
||||
@@ -77,6 +77,16 @@ func TestIntegerArithmetic(t *testing.T) {
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "5 % 2",
|
||||
expectedConstants: []interface{}{5, 2},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpConstant, 1),
|
||||
code.Make(code.OpMod),
|
||||
code.Make(code.OpPop),
|
||||
},
|
||||
},
|
||||
{
|
||||
input: "-1",
|
||||
expectedConstants: []interface{}{1},
|
||||
|
||||
@@ -336,6 +336,8 @@ 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 % rightVal}
|
||||
case "<":
|
||||
return nativeBoolToBooleanObject(leftVal < rightVal)
|
||||
case "<=":
|
||||
|
||||
@@ -30,6 +30,7 @@ func TestEvalIntegerExpression(t *testing.T) {
|
||||
{"3 * 3 * 3 + 10", 37},
|
||||
{"3 * (3 * 3) + 10", 37},
|
||||
{"(5 + 10 * 2 + 15 / 3) * 2 + -10", 50},
|
||||
{"5 % 2", 1},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
@@ -87,6 +87,8 @@ func (l *Lexer) NextToken() token.Token {
|
||||
}
|
||||
case '*':
|
||||
tok = newToken(token.ASTERISK, l.ch)
|
||||
case '%':
|
||||
tok = newToken(token.PERCENT, l.ch)
|
||||
case '<':
|
||||
if l.peekChar() == '=' {
|
||||
l.readChar()
|
||||
|
||||
@@ -14,8 +14,8 @@ const (
|
||||
ASSIGN // := or =
|
||||
EQUALS // ==
|
||||
LESSGREATER // > or <
|
||||
SUM // +
|
||||
PRODUCT // *
|
||||
SUM // + or -
|
||||
PRODUCT // * or / or %
|
||||
PREFIX // -X or !X
|
||||
CALL // myFunction(X)
|
||||
INDEX // array[index]
|
||||
@@ -34,6 +34,7 @@ var precedences = map[token.TokenType]int{
|
||||
token.MINUS: SUM,
|
||||
token.SLASH: PRODUCT,
|
||||
token.ASTERISK: PRODUCT,
|
||||
token.PERCENT: PRODUCT,
|
||||
token.LPAREN: CALL,
|
||||
token.LBRACKET: INDEX,
|
||||
token.DOT: INDEX,
|
||||
@@ -82,6 +83,7 @@ func New(l *lexer.Lexer) *Parser {
|
||||
p.registerInfix(token.MINUS, p.parseInfixExpression)
|
||||
p.registerInfix(token.SLASH, p.parseInfixExpression)
|
||||
p.registerInfix(token.ASTERISK, p.parseInfixExpression)
|
||||
p.registerInfix(token.PERCENT, p.parseInfixExpression)
|
||||
p.registerInfix(token.EQ, p.parseInfixExpression)
|
||||
p.registerInfix(token.NOT_EQ, p.parseInfixExpression)
|
||||
p.registerInfix(token.LT, p.parseInfixExpression)
|
||||
|
||||
@@ -27,6 +27,7 @@ const (
|
||||
BANG = "!"
|
||||
ASTERISK = "*"
|
||||
SLASH = "/"
|
||||
PERCENT = "%"
|
||||
|
||||
LT = "<"
|
||||
LTE = "<="
|
||||
|
||||
5
vm/vm.go
5
vm/vm.go
@@ -112,7 +112,7 @@ func (vm *VM) Run() error {
|
||||
return err
|
||||
}
|
||||
|
||||
case code.OpAdd, code.OpSub, code.OpMul, code.OpDiv:
|
||||
case code.OpAdd, code.OpSub, code.OpMul, code.OpDiv, code.OpMod:
|
||||
err := vm.executeBinaryOperation(op)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -543,6 +543,9 @@ func (vm *VM) executeBinaryIntegerOperation(op code.Opcode, left, right object.O
|
||||
result = leftValue * rightValue
|
||||
case code.OpDiv:
|
||||
result = leftValue / rightValue
|
||||
case code.OpMod:
|
||||
result = leftValue % rightValue
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unknown integer operator: %d", op)
|
||||
}
|
||||
|
||||
@@ -224,6 +224,7 @@ func TestIntegerArithmetic(t *testing.T) {
|
||||
{"-10", -10},
|
||||
{"-50 + 100 + -50", 0},
|
||||
{"(5 + 10 * 2 + 15 / 3) * 2 + -10", 50},
|
||||
{"5 % 2", 1},
|
||||
}
|
||||
|
||||
runVmTests(t, tests)
|
||||
|
||||
Reference in New Issue
Block a user