int() bool() and str()
This commit is contained in:
@@ -992,11 +992,11 @@ func TestBuiltins(t *testing.T) {
|
||||
`,
|
||||
expectedConstants: []interface{}{1},
|
||||
expectedInstructions: []code.Instructions{
|
||||
code.Make(code.OpGetBuiltin, 5),
|
||||
code.Make(code.OpGetBuiltin, 7),
|
||||
code.Make(code.OpArray, 0),
|
||||
code.Make(code.OpCall, 1),
|
||||
code.Make(code.OpPop),
|
||||
code.Make(code.OpGetBuiltin, 8),
|
||||
code.Make(code.OpGetBuiltin, 10),
|
||||
code.Make(code.OpArray, 0),
|
||||
code.Make(code.OpConstant, 0),
|
||||
code.Make(code.OpCall, 2),
|
||||
@@ -1007,7 +1007,7 @@ func TestBuiltins(t *testing.T) {
|
||||
input: `fn() { return len([]) }`,
|
||||
expectedConstants: []interface{}{
|
||||
[]code.Instructions{
|
||||
code.Make(code.OpGetBuiltin, 5),
|
||||
code.Make(code.OpGetBuiltin, 7),
|
||||
code.Make(code.OpArray, 0),
|
||||
code.Make(code.OpCall, 1),
|
||||
code.Make(code.OpReturn),
|
||||
|
||||
@@ -411,12 +411,36 @@ func TestBuiltinFunctions(t *testing.T) {
|
||||
{`input()`, ""},
|
||||
{`pop([])`, errors.New("cannot pop from an empty array")},
|
||||
{`pop([1])`, 1},
|
||||
{`bool(1)`, true},
|
||||
{`bool(0)`, false},
|
||||
{`bool(true)`, true},
|
||||
{`bool(false)`, false},
|
||||
{`bool(null)`, false},
|
||||
{`bool("")`, false},
|
||||
{`bool("foo")`, true},
|
||||
{`bool([])`, false},
|
||||
{`bool([1, 2, 3])`, true},
|
||||
{`bool({})`, false},
|
||||
{`bool({"a": 1})`, true},
|
||||
{`int(true)`, 1},
|
||||
{`int(false)`, 0},
|
||||
{`int(1)`, 1},
|
||||
{`int("10")`, 10},
|
||||
{`str(null)`, "null"},
|
||||
{`str(true)`, "true"},
|
||||
{`str(false)`, "false"},
|
||||
{`str(10)`, "10"},
|
||||
{`str("foo")`, "foo"},
|
||||
{`str([1, 2, 3])`, "[1, 2, 3]"},
|
||||
{`str({"a": 1})`, "{\"a\": 1}"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
evaluated := testEval(tt.input)
|
||||
|
||||
switch expected := tt.expected.(type) {
|
||||
case bool:
|
||||
testBooleanObject(t, evaluated, expected)
|
||||
case int:
|
||||
testIntegerObject(t, evaluated, int64(expected))
|
||||
case string:
|
||||
|
||||
38
object/builtin_bool.go
Normal file
38
object/builtin_bool.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package object
|
||||
|
||||
// Bool ...
|
||||
func Bool(args ...Object) Object {
|
||||
if len(args) != 1 {
|
||||
return newError("wrong number of arguments. got=%d, want=1", len(args))
|
||||
}
|
||||
|
||||
switch arg := args[0].(type) {
|
||||
case *Null:
|
||||
return &Boolean{Value: false}
|
||||
case *Boolean:
|
||||
return arg
|
||||
case *Integer:
|
||||
if arg.Value == 0 {
|
||||
return &Boolean{Value: false}
|
||||
}
|
||||
return &Boolean{Value: true}
|
||||
case *String:
|
||||
if len(arg.Value) > 0 {
|
||||
return &Boolean{Value: true}
|
||||
}
|
||||
return &Boolean{Value: false}
|
||||
case *Array:
|
||||
if len(arg.Elements) > 0 {
|
||||
return &Boolean{Value: true}
|
||||
}
|
||||
return &Boolean{Value: false}
|
||||
case *Hash:
|
||||
if len(arg.Pairs) > 0 {
|
||||
return &Boolean{Value: true}
|
||||
}
|
||||
return &Boolean{Value: false}
|
||||
|
||||
default:
|
||||
return newError("argument to `bool` not supported, got=%s", args[0].Type())
|
||||
}
|
||||
}
|
||||
29
object/builtin_int.go
Normal file
29
object/builtin_int.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package object
|
||||
|
||||
import "strconv"
|
||||
|
||||
// Int ...
|
||||
func Int(args ...Object) Object {
|
||||
if len(args) != 1 {
|
||||
return newError("wrong number of arguments. got=%d, want=1", len(args))
|
||||
}
|
||||
|
||||
switch arg := args[0].(type) {
|
||||
case *Boolean:
|
||||
if arg.Value {
|
||||
return &Integer{Value: 1}
|
||||
}
|
||||
return &Integer{Value: 0}
|
||||
case *Integer:
|
||||
return arg
|
||||
case *String:
|
||||
n, err := strconv.ParseInt(arg.Value, 10, 64)
|
||||
if err != nil {
|
||||
return newError("could not parse string to int: %s", err)
|
||||
}
|
||||
|
||||
return &Integer{Value: n}
|
||||
default:
|
||||
return newError("argument to `int` not supported, got=%s", args[0].Type())
|
||||
}
|
||||
}
|
||||
19
object/builtin_str.go
Normal file
19
object/builtin_str.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package object
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Str ...
|
||||
func Str(args ...Object) Object {
|
||||
if len(args) != 1 {
|
||||
return newError("wrong number of arguments. got=%d, want=1", len(args))
|
||||
}
|
||||
|
||||
arg, ok := args[0].(fmt.Stringer)
|
||||
if !ok {
|
||||
return newError("argument to `str` not supported, got %s", args[0].Type())
|
||||
}
|
||||
|
||||
return &String{Value: arg.String()}
|
||||
}
|
||||
@@ -17,6 +17,9 @@ var Builtins = map[string]*Builtin{
|
||||
"pop": {Name: "pop", Fn: Pop},
|
||||
"exit": {Name: "exit", Fn: Exit},
|
||||
"assert": {Name: "assert", Fn: Assert},
|
||||
"bool": {Name: "bool", Fn: Bool},
|
||||
"int": {Name: "int", Fn: Int},
|
||||
"str": {Name: "str", Fn: Str},
|
||||
}
|
||||
|
||||
// BuiltinsIndex ...
|
||||
|
||||
@@ -656,6 +656,28 @@ func TestBuiltinFunctions(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{`pop([1])`, 1},
|
||||
{`bool(1)`, true},
|
||||
{`bool(0)`, false},
|
||||
{`bool(true)`, true},
|
||||
{`bool(false)`, false},
|
||||
{`bool(null)`, false},
|
||||
{`bool("")`, false},
|
||||
{`bool("foo")`, true},
|
||||
{`bool([])`, false},
|
||||
{`bool([1, 2, 3])`, true},
|
||||
{`bool({})`, false},
|
||||
{`bool({"a": 1})`, true},
|
||||
{`int(true)`, 1},
|
||||
{`int(false)`, 0},
|
||||
{`int(1)`, 1},
|
||||
{`int("10")`, 10},
|
||||
{`str(null)`, "null"},
|
||||
{`str(true)`, "true"},
|
||||
{`str(false)`, "false"},
|
||||
{`str(10)`, "10"},
|
||||
{`str("foo")`, "foo"},
|
||||
{`str([1, 2, 3])`, "[1, 2, 3]"},
|
||||
{`str({"a": 1})`, "{\"a\": 1}"},
|
||||
}
|
||||
|
||||
runVmTests(t, tests)
|
||||
|
||||
Reference in New Issue
Block a user