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