fix: correct append with variadic parameters and spread array (#124)

* fix: correct append with variadic parameters and spread array
* feat: add print builtin
This commit is contained in:
Marc Vertes
2019-03-19 12:25:04 +01:00
committed by Ludovic Fernandez
parent 70fab221de
commit 8717f1ef4b
6 changed files with 99 additions and 5 deletions

8
_test/print0.go Normal file
View File

@@ -0,0 +1,8 @@
package main
func main() {
print("hello")
}
// Output:
// hello

View File

@@ -94,6 +94,8 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
v.findex = vindex
}
}
n.findex = -1
n.val = nil
scope = scope.pushBloc()
case CaseClause:
@@ -532,6 +534,9 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
if n.typ = scope.getType(n.child[1].ident); n.typ == nil {
n.typ, err = nodeType(interp, scope, n.child[1])
}
if c2 := n.child[2]; len(n.child) == 3 && c2.typ.cat == ArrayT && c2.typ.val.id() == n.typ.val.id() {
n.gen = appendSlice
}
case "cap", "copy", "len":
n.typ = scope.getType("int")
case "make":
@@ -548,6 +553,9 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
}
if n.typ != nil {
n.findex = scope.add(n.typ)
} else {
n.findex = -1
n.val = nil
}
case n.child[0].isType(scope):
// Type conversion expression

View File

@@ -160,6 +160,7 @@ func initUniverse() *Scope {
"make": &Symbol{kind: Bltn, builtin: _make},
"new": &Symbol{kind: Bltn, builtin: _new},
"panic": &Symbol{kind: Bltn, builtin: _panic},
"print": &Symbol{kind: Bltn, builtin: _print},
"println": &Symbol{kind: Bltn, builtin: _println},
"recover": &Symbol{kind: Bltn, builtin: _recover},
// TODO: complex, copy, delete, imag, new, print, real

View File

@@ -55,6 +55,15 @@ func TestEvalAssign(t *testing.T) {
})
}
func TestEvalBuiltin(t *testing.T) {
i := interp.New(interp.Opt{})
runTests(t, i, []testCase{
{src: `a := []int{}; a = append(a, 1); a`, res: "[1]"},
{src: `a := []int{1}; a = append(a, 2, 3); a`, res: "[1 2 3]"},
{src: `a := []int{1}; b := []int{2, 3}; a = append(a, b...); a`, res: "[1 2 3]"},
})
}
func TestEvalDecl(t *testing.T) {
i := interp.New(interp.Opt{})
runTests(t, i, []testCase{

View File

@@ -4710,6 +4710,25 @@ func main() {
// true
}
func Example_print0() {
src := `
package main
func main() {
print("hello")
}
`
i := interp.New(interp.Opt{Entry: "main"})
i.Use(stdlib.Value)
_, err := i.Eval(src)
if err != nil {
panic(err)
}
// Output:
// hello
}
func Example_ptr0() {
src := `
package main

View File

@@ -320,6 +320,25 @@ func deref(n *Node) {
}
}
func _print(n *Node) {
child := n.child[1:]
next := getExec(n.tnext)
values := make([]func(*Frame) reflect.Value, len(child))
for i, c := range child {
values[i] = genValue(c)
}
n.exec = func(f *Frame) Builtin {
for i, value := range values {
if i > 0 {
fmt.Printf(" ")
}
fmt.Printf("%v", value(f))
}
return next
}
}
func _println(n *Node) {
child := n.child[1:]
next := getExec(n.tnext)
@@ -1276,19 +1295,49 @@ func _case(n *Node) {
}
}
// TODO: handle variable number of arguments to append
func _append(n *Node) {
func appendSlice(n *Node) {
i := n.findex
value0 := genValue(n.child[1])
value1 := genValue(n.child[2])
value := genValue(n.child[1])
next := getExec(n.tnext)
value0 := genValue(n.child[2])
n.exec = func(f *Frame) Builtin {
f.data[i] = reflect.Append(value0(f), value1(f))
f.data[i] = reflect.AppendSlice(value(f), value0(f))
return next
}
}
func _append(n *Node) {
i := n.findex
value := genValue(n.child[1])
next := getExec(n.tnext)
if len(n.child) > 3 {
args := n.child[2:]
l := len(args)
values := make([]func(*Frame) reflect.Value, l)
for i, arg := range args {
values[i] = genValue(arg)
}
n.exec = func(f *Frame) Builtin {
sl := make([]reflect.Value, l)
for i, v := range values {
sl[i] = v(f)
}
f.data[i] = reflect.Append(value(f), sl...)
return next
}
} else {
value0 := genValue(n.child[2])
n.exec = func(f *Frame) Builtin {
f.data[i] = reflect.Append(value(f), value0(f))
return next
}
}
}
func _cap(n *Node) {
i := n.findex
value := genValue(n.child[1])