more builtins
This commit is contained in:
20
builtins/abs.go
Normal file
20
builtins/abs.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import "monkey/object"
|
||||||
|
|
||||||
|
// Abs ...
|
||||||
|
func Abs(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := args[0].(*object.Integer); ok {
|
||||||
|
value := i.Value
|
||||||
|
if value < 0 {
|
||||||
|
value = value * -1
|
||||||
|
}
|
||||||
|
return &object.Integer{Value: value}
|
||||||
|
}
|
||||||
|
return newError("argument to `abs` not supported, got %s", args[0].Type())
|
||||||
|
}
|
||||||
20
builtins/bin.go
Normal file
20
builtins/bin.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"monkey/object"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Bin ...
|
||||||
|
func Bin(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := args[0].(*object.Integer); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("0b%s", strconv.FormatInt(i.Value, 2))}
|
||||||
|
}
|
||||||
|
return newError("argument to `bin` not supported, got %s", args[0].Type())
|
||||||
|
}
|
||||||
@@ -31,6 +31,16 @@ var Builtins = map[string]*object.Builtin{
|
|||||||
"read": {Name: "read", Fn: Read},
|
"read": {Name: "read", Fn: Read},
|
||||||
"write": {Name: "write", Fn: Write},
|
"write": {Name: "write", Fn: Write},
|
||||||
"ffi": {Name: "ffi", Fn: FFI},
|
"ffi": {Name: "ffi", Fn: FFI},
|
||||||
|
"abs": {Name: "abs", Fn: Abs},
|
||||||
|
"bin": {Name: "bin", Fn: Bin},
|
||||||
|
"hex": {Name: "hex", Fn: Hex},
|
||||||
|
"ord": {Name: "ord", Fn: Ord},
|
||||||
|
"chr": {Name: "chr", Fn: Chr},
|
||||||
|
"divmod": {Name: "divmod", Fn: Divmod},
|
||||||
|
"hash": {Name: "hash", Fn: HashOf},
|
||||||
|
"id": {Name: "id", Fn: IdOf},
|
||||||
|
"oct": {Name: "oct", Fn: Oct},
|
||||||
|
"pow": {Name: "pow", Fn: Pow},
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuiltinsIndex ...
|
// BuiltinsIndex ...
|
||||||
|
|||||||
19
builtins/chr.go
Normal file
19
builtins/chr.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"monkey/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Chr ...
|
||||||
|
func Chr(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := args[0].(*object.Integer); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%c", rune(i.Value))}
|
||||||
|
}
|
||||||
|
return newError("argument to `chr` not supported, got %s", args[0].Type())
|
||||||
|
}
|
||||||
24
builtins/divmod.go
Normal file
24
builtins/divmod.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import "monkey/object"
|
||||||
|
|
||||||
|
// Divmod ...
|
||||||
|
func Divmod(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 2 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=2",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if a, ok := args[0].(*object.Integer); ok {
|
||||||
|
if b, ok := args[1].(*object.Integer); ok {
|
||||||
|
elements := make([]object.Object, 2)
|
||||||
|
elements[0] = &object.Integer{Value: a.Value / b.Value}
|
||||||
|
elements[1] = &object.Integer{Value: a.Value % b.Value}
|
||||||
|
return &object.Array{Elements: elements}
|
||||||
|
} else {
|
||||||
|
return newError("expected argument #2 to `divmod` to be `int` got=%s", args[1].Type())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return newError("expected argument #1 to `divmod` to be `int` got=%s", args[0].Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
16
builtins/hash.go
Normal file
16
builtins/hash.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import "monkey/object"
|
||||||
|
|
||||||
|
// HashOf ...
|
||||||
|
func HashOf(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if hash, ok := args[0].(object.Hashable); ok {
|
||||||
|
return &object.Integer{Value: int64(hash.HashKey().Value)}
|
||||||
|
}
|
||||||
|
return newError("argument #1 to `hash()` is not hashable: %s", args[0].Inspect())
|
||||||
|
}
|
||||||
20
builtins/hex.go
Normal file
20
builtins/hex.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"monkey/object"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Hex ...
|
||||||
|
func Hex(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := args[0].(*object.Integer); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("0x%s", strconv.FormatInt(i.Value, 16))}
|
||||||
|
}
|
||||||
|
return newError("argument to `hex` not supported, got %s", args[0].Type())
|
||||||
|
}
|
||||||
38
builtins/id.go
Normal file
38
builtins/id.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"monkey/object"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IdOf ...
|
||||||
|
func IdOf(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
arg := args[0]
|
||||||
|
|
||||||
|
if n, ok := arg.(*object.Null); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", n)}
|
||||||
|
} else if b, ok := arg.(*object.Boolean); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", b)}
|
||||||
|
} else if i, ok := arg.(*object.Integer); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", i)}
|
||||||
|
} else if s, ok := arg.(*object.String); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", s)}
|
||||||
|
} else if a, ok := arg.(*object.Array); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", a)}
|
||||||
|
} else if h, ok := arg.(*object.Hash); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", h)}
|
||||||
|
} else if f, ok := arg.(*object.Function); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", f)}
|
||||||
|
} else if c, ok := arg.(*object.Closure); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", c)}
|
||||||
|
} else if b, ok := arg.(*object.Builtin); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("%p", b)}
|
||||||
|
} else {
|
||||||
|
return newError("argument 31 to `id()` unsupported got=%T", arg.Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
20
builtins/oct.go
Normal file
20
builtins/oct.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"monkey/object"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Oct ...
|
||||||
|
func Oct(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if i, ok := args[0].(*object.Integer); ok {
|
||||||
|
return &object.String{Value: fmt.Sprintf("0%s", strconv.FormatInt(i.Value, 8))}
|
||||||
|
}
|
||||||
|
return newError("argument to `oct` not supported, got %s", args[0].Type())
|
||||||
|
}
|
||||||
19
builtins/ord.go
Normal file
19
builtins/ord.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import "monkey/object"
|
||||||
|
|
||||||
|
// Ord ...
|
||||||
|
func Ord(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 1 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=1",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if s, ok := args[0].(*object.String); ok {
|
||||||
|
if len(s.Value) == 1 {
|
||||||
|
return &object.Integer{Value: int64(s.Value[0])}
|
||||||
|
}
|
||||||
|
return newError("`ord()` expected a character but got string of length %d", len(s.Value))
|
||||||
|
}
|
||||||
|
return newError("argument to `ord` not supported, got %s", args[0].Type())
|
||||||
|
}
|
||||||
34
builtins/pow.go
Normal file
34
builtins/pow.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package builtins
|
||||||
|
|
||||||
|
import "monkey/object"
|
||||||
|
|
||||||
|
func pow(x, y int64) int64 {
|
||||||
|
p := int64(1)
|
||||||
|
for y > 0 {
|
||||||
|
if y&1 != 0 {
|
||||||
|
p *= x
|
||||||
|
}
|
||||||
|
y >>= 1
|
||||||
|
x *= x
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pow ...
|
||||||
|
func Pow(args ...object.Object) object.Object {
|
||||||
|
if len(args) != 2 {
|
||||||
|
return newError("wrong number of arguments. got=%d, want=2",
|
||||||
|
len(args))
|
||||||
|
}
|
||||||
|
|
||||||
|
if x, ok := args[0].(*object.Integer); ok {
|
||||||
|
if y, ok := args[1].(*object.Integer); ok {
|
||||||
|
value := pow(x.Value, y.Value)
|
||||||
|
return &object.Integer{Value: value}
|
||||||
|
} else {
|
||||||
|
return newError("expected argument #2 to `pow` to be `int` got=%s", args[1].Type())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return newError("expected argument #1 to `pow` to be `int` got=%s", args[0].Type())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -879,11 +879,11 @@ func TestBuiltins(t *testing.T) {
|
|||||||
`,
|
`,
|
||||||
expectedConstants: []interface{}{1},
|
expectedConstants: []interface{}{1},
|
||||||
expectedInstructions: []code.Instructions{
|
expectedInstructions: []code.Instructions{
|
||||||
code.Make(code.OpGetBuiltin, 11),
|
code.Make(code.OpGetBuiltin, 18),
|
||||||
code.Make(code.OpArray, 0),
|
code.Make(code.OpArray, 0),
|
||||||
code.Make(code.OpCall, 1),
|
code.Make(code.OpCall, 1),
|
||||||
code.Make(code.OpPop),
|
code.Make(code.OpPop),
|
||||||
code.Make(code.OpGetBuiltin, 15),
|
code.Make(code.OpGetBuiltin, 25),
|
||||||
code.Make(code.OpArray, 0),
|
code.Make(code.OpArray, 0),
|
||||||
code.Make(code.OpConstant, 0),
|
code.Make(code.OpConstant, 0),
|
||||||
code.Make(code.OpCall, 2),
|
code.Make(code.OpCall, 2),
|
||||||
@@ -894,7 +894,7 @@ func TestBuiltins(t *testing.T) {
|
|||||||
input: `fn() { return len([]) }`,
|
input: `fn() { return len([]) }`,
|
||||||
expectedConstants: []interface{}{
|
expectedConstants: []interface{}{
|
||||||
[]code.Instructions{
|
[]code.Instructions{
|
||||||
code.Make(code.OpGetBuiltin, 11),
|
code.Make(code.OpGetBuiltin, 18),
|
||||||
code.Make(code.OpArray, 0),
|
code.Make(code.OpArray, 0),
|
||||||
code.Make(code.OpCall, 1),
|
code.Make(code.OpCall, 1),
|
||||||
code.Make(code.OpReturn),
|
code.Make(code.OpReturn),
|
||||||
|
|||||||
Reference in New Issue
Block a user