add 'printf' and 'sprintf' builtin functions

This commit is contained in:
Daniel Kang 2019-01-24 16:38:04 -08:00
parent 1315489a4a
commit 37016f4e17
4 changed files with 90 additions and 0 deletions

View file

@ -7,6 +7,29 @@ Prints a string representation of the given variable to the standard output.
```golang
v := [1, 2, 3]
print(v) // "[1, 2, 3]"
print(1, 2, 3)
// "1"
// "2"
// "3"
```
## printf
Prints a formatted string to the standard output. It does not append the newline character at the end. The first argument must a String object. It's same as Go's `fmt.Printf`.
```golang
a := [1, 2, 3]
printf("foo %v", a) // "foo [1, 2, 3]"
```
## sprintf
Returns a formatted string. The first argument must be a String object. It's the same as Go's `fmt.Sprintf`.
```golang
a := [1, 2, 3]
b := sprintp("foo %v", a) // b == "foo [1, 2, 3]"
```
## len

View file

@ -4,6 +4,7 @@ import (
"fmt"
)
// print(args...)
func builtinPrint(args ...Object) (Object, error) {
for _, arg := range args {
if str, ok := arg.(*String); ok {
@ -15,3 +16,52 @@ func builtinPrint(args ...Object) (Object, error) {
return nil, nil
}
// printf("format", args...)
func builtinPrintf(args ...Object) (Object, error) {
numArgs := len(args)
if numArgs == 0 {
return nil, ErrWrongNumArguments
}
format, ok := args[0].(*String)
if !ok {
return nil, ErrInvalidTypeConversion
}
if numArgs == 1 {
fmt.Print(format)
return nil, nil
}
formatArgs := make([]interface{}, numArgs-1, numArgs-1)
for idx, arg := range args[1:] {
formatArgs[idx] = objectToInterface(arg)
}
fmt.Printf(format.Value, formatArgs...)
return nil, nil
}
// sprintf("format", args...)
func builtinSprintf(args ...Object) (Object, error) {
numArgs := len(args)
if numArgs == 0 {
return nil, ErrWrongNumArguments
}
format, ok := args[0].(*String)
if !ok {
return nil, ErrInvalidTypeConversion
}
if numArgs == 1 {
return format, nil // okay to return 'format' directly as String is immutable
}
formatArgs := make([]interface{}, numArgs-1, numArgs-1)
for idx, arg := range args[1:] {
formatArgs[idx] = objectToInterface(arg)
}
return &String{Value: fmt.Sprintf(format.Value, formatArgs...)}, nil
}

View file

@ -12,6 +12,14 @@ var Builtins = []NamedBuiltinFunc{
Name: "print",
Func: builtinPrint,
},
{
Name: "printf",
Func: builtinPrintf,
},
{
Name: "sprintf",
Func: builtinSprintf,
},
{
Name: "len",
Func: builtinLen,

View file

@ -140,4 +140,13 @@ func TestBuiltinFunction(t *testing.T) {
expect(t, `out = from_json("5")`, 5.0)
expect(t, `out = from_json("[\"bar\",1,1.8,56,true]")`, ARR{"bar", 1.0, 1.8, 56.0, true})
// sprintf
expect(t, `out = sprintf("")`, "")
expect(t, `out = sprintf("foo")`, "foo")
expect(t, `out = sprintf("foo %d %v %s", 1, 2, "bar")`, "foo 1 2 bar")
expect(t, `out = sprintf("foo %v", [1, "bar", true])`, "foo [1 bar true]")
expect(t, `out = sprintf("foo %v %d", [1, "bar", true], 19)`, "foo [1 bar true] 19")
expectError(t, `sprintf(1)`) // format has to be String
expectError(t, `sprintf('c')`) // format has to be String
}