Fix VM memory allocation optimizations by reducing what we allocate on the heap
This commit is contained in:
@@ -13,9 +13,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
NULL = &object.Null{}
|
||||
TRUE = &object.Boolean{Value: true}
|
||||
FALSE = &object.Boolean{Value: false}
|
||||
NULL = object.Null{}
|
||||
TRUE = object.Boolean{Value: true}
|
||||
FALSE = object.Boolean{Value: false}
|
||||
)
|
||||
|
||||
func isError(obj object.Object) bool {
|
||||
@@ -52,7 +52,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
if isError(val) {
|
||||
return val
|
||||
}
|
||||
return &object.ReturnValue{Value: val}
|
||||
return object.ReturnValue{Value: val}
|
||||
|
||||
case *ast.BindExpression:
|
||||
value := Eval(node.Value, env)
|
||||
@@ -95,7 +95,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
if isError(index) {
|
||||
return index
|
||||
}
|
||||
if idx, ok := index.(*object.Integer); ok {
|
||||
if idx, ok := index.(object.Integer); ok {
|
||||
array.Elements[idx.Value] = value
|
||||
} else {
|
||||
return newError("cannot index array with %#v", index)
|
||||
@@ -130,7 +130,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
|
||||
// Expressions
|
||||
case *ast.IntegerLiteral:
|
||||
return &object.Integer{Value: node.Value}
|
||||
return object.Integer{Value: node.Value}
|
||||
|
||||
case *ast.Boolean:
|
||||
return nativeBoolToBooleanObject(node.Value)
|
||||
@@ -169,7 +169,7 @@ func Eval(node ast.Node, env *object.Environment) object.Object {
|
||||
return applyFunction(function, args)
|
||||
|
||||
case *ast.StringLiteral:
|
||||
return &object.String{Value: node.Value}
|
||||
return object.String{Value: node.Value}
|
||||
|
||||
case *ast.ArrayLiteral:
|
||||
elements := evalExpressions(node.Elements, env)
|
||||
@@ -203,12 +203,12 @@ func evalImportExpression(ie *ast.ImportExpression, env *object.Environment) obj
|
||||
return name
|
||||
}
|
||||
|
||||
if s, ok := name.(*object.String); ok {
|
||||
if s, ok := name.(object.String); ok {
|
||||
attrs := EvalModule(s.Value)
|
||||
if isError(attrs) {
|
||||
return attrs
|
||||
}
|
||||
return &object.Module{Name: s.Value, Attrs: attrs}
|
||||
return object.Module{Name: s.Value, Attrs: attrs}
|
||||
}
|
||||
return newError("ImportError: invalid import path '%s'", name)
|
||||
}
|
||||
@@ -243,9 +243,9 @@ func evalProgram(program *ast.Program, env *object.Environment) object.Object {
|
||||
result = Eval(statement, env)
|
||||
|
||||
switch result := result.(type) {
|
||||
case *object.ReturnValue:
|
||||
case object.ReturnValue:
|
||||
return result.Value
|
||||
case *object.Error:
|
||||
case object.Error:
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -271,7 +271,7 @@ func evalBlockStatements(block *ast.BlockStatement, env *object.Environment) obj
|
||||
return result
|
||||
}
|
||||
|
||||
func nativeBoolToBooleanObject(input bool) object.Object {
|
||||
func nativeBoolToBooleanObject(input bool) object.Boolean {
|
||||
if input {
|
||||
return TRUE
|
||||
}
|
||||
@@ -314,14 +314,14 @@ func evalIntegerPrefixOperatorExpression(operator string, right object.Object) o
|
||||
return newError("unknown operator: -%s", right.Type())
|
||||
}
|
||||
|
||||
value := right.(*object.Integer).Value
|
||||
value := right.(object.Integer).Value
|
||||
switch operator {
|
||||
case "!":
|
||||
return FALSE
|
||||
case "~":
|
||||
return &object.Integer{Value: ^value}
|
||||
return object.Integer{Value: ^value}
|
||||
case "-":
|
||||
return &object.Integer{Value: -value}
|
||||
return object.Integer{Value: -value}
|
||||
default:
|
||||
return newError("unknown operator: %s", operator)
|
||||
}
|
||||
@@ -354,7 +354,7 @@ func evalInfixExpression(operator string, left, right object.Object) object.Obje
|
||||
// [1] * 3
|
||||
case operator == "*" && left.Type() == object.ArrayType && right.Type() == object.IntegerType:
|
||||
leftVal := left.(*object.Array).Elements
|
||||
rightVal := int(right.(*object.Integer).Value)
|
||||
rightVal := int(right.(object.Integer).Value)
|
||||
elements := leftVal
|
||||
for i := rightVal; i > 1; i-- {
|
||||
elements = append(elements, leftVal...)
|
||||
@@ -363,7 +363,7 @@ func evalInfixExpression(operator string, left, right object.Object) object.Obje
|
||||
|
||||
// 3 * [1]
|
||||
case operator == "*" && left.Type() == object.IntegerType && right.Type() == object.ArrayType:
|
||||
leftVal := int(left.(*object.Integer).Value)
|
||||
leftVal := int(left.(object.Integer).Value)
|
||||
rightVal := right.(*object.Array).Elements
|
||||
elements := rightVal
|
||||
for i := leftVal; i > 1; i-- {
|
||||
@@ -373,15 +373,15 @@ func evalInfixExpression(operator string, left, right object.Object) object.Obje
|
||||
|
||||
// " " * 4
|
||||
case operator == "*" && left.Type() == object.StringType && right.Type() == object.IntegerType:
|
||||
leftVal := left.(*object.String).Value
|
||||
rightVal := right.(*object.Integer).Value
|
||||
return &object.String{Value: strings.Repeat(leftVal, int(rightVal))}
|
||||
leftVal := left.(object.String).Value
|
||||
rightVal := right.(object.Integer).Value
|
||||
return object.String{Value: strings.Repeat(leftVal, int(rightVal))}
|
||||
|
||||
// 4 * " "
|
||||
case operator == "*" && left.Type() == object.IntegerType && right.Type() == object.StringType:
|
||||
leftVal := left.(*object.Integer).Value
|
||||
rightVal := right.(*object.String).Value
|
||||
return &object.String{Value: strings.Repeat(rightVal, int(leftVal))}
|
||||
leftVal := left.(object.Integer).Value
|
||||
rightVal := right.(object.String).Value
|
||||
return object.String{Value: strings.Repeat(rightVal, int(leftVal))}
|
||||
|
||||
case operator == "==":
|
||||
return nativeBoolToBooleanObject(left.(object.Comparable).Compare(right) == 0)
|
||||
@@ -409,8 +409,8 @@ func evalInfixExpression(operator string, left, right object.Object) object.Obje
|
||||
}
|
||||
|
||||
func evalBooleanInfixExpression(operator string, left, right object.Object) object.Object {
|
||||
leftVal := left.(*object.Boolean).Value
|
||||
rightVal := right.(*object.Boolean).Value
|
||||
leftVal := left.(object.Boolean).Value
|
||||
rightVal := right.(object.Boolean).Value
|
||||
|
||||
switch operator {
|
||||
case "&&":
|
||||
@@ -423,42 +423,42 @@ func evalBooleanInfixExpression(operator string, left, right object.Object) obje
|
||||
}
|
||||
|
||||
func evalStringInfixExpression(operator string, left object.Object, right object.Object) object.Object {
|
||||
leftVal := left.(*object.String).Value
|
||||
rightVal := right.(*object.String).Value
|
||||
leftVal := left.(object.String).Value
|
||||
rightVal := right.(object.String).Value
|
||||
|
||||
switch operator {
|
||||
case "+":
|
||||
return &object.String{Value: leftVal + rightVal}
|
||||
return object.String{Value: leftVal + rightVal}
|
||||
default:
|
||||
return newError("unknown operator: %s %s %s", left.Type(), operator, right.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func evalIntegerInfixExpression(operator string, left, right object.Object) object.Object {
|
||||
leftVal := left.(*object.Integer).Value
|
||||
rightVal := right.(*object.Integer).Value
|
||||
leftVal := left.(object.Integer).Value
|
||||
rightVal := right.(object.Integer).Value
|
||||
|
||||
switch operator {
|
||||
case "+":
|
||||
return &object.Integer{Value: leftVal + rightVal}
|
||||
return object.Integer{Value: leftVal + rightVal}
|
||||
case "-":
|
||||
return &object.Integer{Value: leftVal - rightVal}
|
||||
return object.Integer{Value: leftVal - rightVal}
|
||||
case "*":
|
||||
return &object.Integer{Value: leftVal * rightVal}
|
||||
return object.Integer{Value: leftVal * rightVal}
|
||||
case "/":
|
||||
return &object.Integer{Value: leftVal / rightVal}
|
||||
return object.Integer{Value: leftVal / rightVal}
|
||||
case "%":
|
||||
return &object.Integer{Value: leftVal % rightVal}
|
||||
return object.Integer{Value: leftVal % rightVal}
|
||||
case "|":
|
||||
return &object.Integer{Value: leftVal | rightVal}
|
||||
return object.Integer{Value: leftVal | rightVal}
|
||||
case "^":
|
||||
return &object.Integer{Value: leftVal ^ rightVal}
|
||||
return object.Integer{Value: leftVal ^ rightVal}
|
||||
case "&":
|
||||
return &object.Integer{Value: leftVal & rightVal}
|
||||
return object.Integer{Value: leftVal & rightVal}
|
||||
case "<<":
|
||||
return &object.Integer{Value: leftVal << uint64(rightVal)}
|
||||
return object.Integer{Value: leftVal << uint64(rightVal)}
|
||||
case ">>":
|
||||
return &object.Integer{Value: leftVal >> uint64(rightVal)}
|
||||
return object.Integer{Value: leftVal >> uint64(rightVal)}
|
||||
case "<":
|
||||
return nativeBoolToBooleanObject(leftVal < rightVal)
|
||||
case "<=":
|
||||
@@ -504,11 +504,11 @@ func isTruthy(obj object.Object) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func newError(format string, a ...interface{}) *object.Error {
|
||||
return &object.Error{Message: fmt.Sprintf(format, a...)}
|
||||
func newError(format string, a ...interface{}) object.Error {
|
||||
return object.Error{Message: fmt.Sprintf(format, a...)}
|
||||
}
|
||||
|
||||
// EvalModule evaluates the named module and returns a *object.Module objec
|
||||
// EvalModule evaluates the named module and returns a object.Module objec
|
||||
func EvalModule(name string) object.Object {
|
||||
filename := utils.FindModule(name)
|
||||
|
||||
@@ -588,7 +588,7 @@ func extendFunctionEnv(fn *object.Function, args []object.Object) *object.Enviro
|
||||
}
|
||||
|
||||
func unwrapReturnValue(obj object.Object) object.Object {
|
||||
if returnValue, ok := obj.(*object.ReturnValue); ok {
|
||||
if returnValue, ok := obj.(object.ReturnValue); ok {
|
||||
return returnValue.Value
|
||||
}
|
||||
|
||||
@@ -611,20 +611,20 @@ func evalIndexExpression(left, index object.Object) object.Object {
|
||||
}
|
||||
|
||||
func EvalModuleIndexExpression(module, index object.Object) object.Object {
|
||||
moduleObject := module.(*object.Module)
|
||||
moduleObject := module.(object.Module)
|
||||
return evalHashIndexExpression(moduleObject.Attrs, index)
|
||||
}
|
||||
|
||||
func evalStringIndexExpression(str, index object.Object) object.Object {
|
||||
stringObject := str.(*object.String)
|
||||
idx := index.(*object.Integer).Value
|
||||
stringObject := str.(object.String)
|
||||
idx := index.(object.Integer).Value
|
||||
max := int64((len(stringObject.Value)) - 1)
|
||||
|
||||
if idx < 0 || idx > max {
|
||||
return &object.String{Value: ""}
|
||||
return object.String{Value: ""}
|
||||
}
|
||||
|
||||
return &object.String{Value: string(stringObject.Value[idx])}
|
||||
return object.String{Value: string(stringObject.Value[idx])}
|
||||
}
|
||||
|
||||
func evalHashIndexExpression(hash, index object.Object) object.Object {
|
||||
@@ -645,7 +645,7 @@ func evalHashIndexExpression(hash, index object.Object) object.Object {
|
||||
|
||||
func evalArrayIndexExpression(array, index object.Object) object.Object {
|
||||
arrayObject := array.(*object.Array)
|
||||
idx := index.(*object.Integer).Value
|
||||
idx := index.(object.Integer).Value
|
||||
maxInx := int64(len(arrayObject.Elements) - 1)
|
||||
|
||||
if idx < 0 || idx > maxInx {
|
||||
|
||||
Reference in New Issue
Block a user