Merge pull request #43 from d5/printf
add 'printf' and 'sprintf' builtin functions
This commit is contained in:
commit
a1bd73f238
5 changed files with 92 additions and 2 deletions
|
@ -697,7 +697,7 @@ func TestCompiler_Compile(t *testing.T) {
|
|||
expect(t, `len([]);`,
|
||||
bytecode(
|
||||
concat(
|
||||
compiler.MakeInstruction(compiler.OpGetBuiltin, 1),
|
||||
compiler.MakeInstruction(compiler.OpGetBuiltin, 3),
|
||||
compiler.MakeInstruction(compiler.OpArray, 0),
|
||||
compiler.MakeInstruction(compiler.OpCall, 1),
|
||||
compiler.MakeInstruction(compiler.OpPop)),
|
||||
|
@ -710,7 +710,7 @@ func TestCompiler_Compile(t *testing.T) {
|
|||
compiler.MakeInstruction(compiler.OpPop)),
|
||||
objectsArray(
|
||||
compiledFunction(0, 0,
|
||||
compiler.MakeInstruction(compiler.OpGetBuiltin, 1),
|
||||
compiler.MakeInstruction(compiler.OpGetBuiltin, 3),
|
||||
compiler.MakeInstruction(compiler.OpArray, 0),
|
||||
compiler.MakeInstruction(compiler.OpCall, 1),
|
||||
compiler.MakeInstruction(compiler.OpReturnValue, 1)))))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -12,6 +12,14 @@ var Builtins = []NamedBuiltinFunc{
|
|||
Name: "print",
|
||||
Func: builtinPrint,
|
||||
},
|
||||
{
|
||||
Name: "printf",
|
||||
Func: builtinPrintf,
|
||||
},
|
||||
{
|
||||
Name: "sprintf",
|
||||
Func: builtinSprintf,
|
||||
},
|
||||
{
|
||||
Name: "len",
|
||||
Func: builtinLen,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue