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:
committed by
Ludovic Fernandez
parent
70fab221de
commit
8717f1ef4b
8
_test/print0.go
Normal file
8
_test/print0.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
print("hello")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// hello
|
||||||
@@ -94,6 +94,8 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
|
|||||||
v.findex = vindex
|
v.findex = vindex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
n.findex = -1
|
||||||
|
n.val = nil
|
||||||
scope = scope.pushBloc()
|
scope = scope.pushBloc()
|
||||||
|
|
||||||
case CaseClause:
|
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 {
|
if n.typ = scope.getType(n.child[1].ident); n.typ == nil {
|
||||||
n.typ, err = nodeType(interp, scope, n.child[1])
|
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":
|
case "cap", "copy", "len":
|
||||||
n.typ = scope.getType("int")
|
n.typ = scope.getType("int")
|
||||||
case "make":
|
case "make":
|
||||||
@@ -548,6 +553,9 @@ func (interp *Interpreter) Cfg(root *Node) ([]*Node, error) {
|
|||||||
}
|
}
|
||||||
if n.typ != nil {
|
if n.typ != nil {
|
||||||
n.findex = scope.add(n.typ)
|
n.findex = scope.add(n.typ)
|
||||||
|
} else {
|
||||||
|
n.findex = -1
|
||||||
|
n.val = nil
|
||||||
}
|
}
|
||||||
case n.child[0].isType(scope):
|
case n.child[0].isType(scope):
|
||||||
// Type conversion expression
|
// Type conversion expression
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ func initUniverse() *Scope {
|
|||||||
"make": &Symbol{kind: Bltn, builtin: _make},
|
"make": &Symbol{kind: Bltn, builtin: _make},
|
||||||
"new": &Symbol{kind: Bltn, builtin: _new},
|
"new": &Symbol{kind: Bltn, builtin: _new},
|
||||||
"panic": &Symbol{kind: Bltn, builtin: _panic},
|
"panic": &Symbol{kind: Bltn, builtin: _panic},
|
||||||
|
"print": &Symbol{kind: Bltn, builtin: _print},
|
||||||
"println": &Symbol{kind: Bltn, builtin: _println},
|
"println": &Symbol{kind: Bltn, builtin: _println},
|
||||||
"recover": &Symbol{kind: Bltn, builtin: _recover},
|
"recover": &Symbol{kind: Bltn, builtin: _recover},
|
||||||
// TODO: complex, copy, delete, imag, new, print, real
|
// TODO: complex, copy, delete, imag, new, print, real
|
||||||
|
|||||||
@@ -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) {
|
func TestEvalDecl(t *testing.T) {
|
||||||
i := interp.New(interp.Opt{})
|
i := interp.New(interp.Opt{})
|
||||||
runTests(t, i, []testCase{
|
runTests(t, i, []testCase{
|
||||||
|
|||||||
@@ -4710,6 +4710,25 @@ func main() {
|
|||||||
// true
|
// 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() {
|
func Example_ptr0() {
|
||||||
src := `
|
src := `
|
||||||
package main
|
package main
|
||||||
|
|||||||
@@ -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) {
|
func _println(n *Node) {
|
||||||
child := n.child[1:]
|
child := n.child[1:]
|
||||||
next := getExec(n.tnext)
|
next := getExec(n.tnext)
|
||||||
@@ -1276,19 +1295,49 @@ func _case(n *Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle variable number of arguments to append
|
func appendSlice(n *Node) {
|
||||||
func _append(n *Node) {
|
|
||||||
i := n.findex
|
i := n.findex
|
||||||
value0 := genValue(n.child[1])
|
value := genValue(n.child[1])
|
||||||
value1 := genValue(n.child[2])
|
|
||||||
next := getExec(n.tnext)
|
next := getExec(n.tnext)
|
||||||
|
value0 := genValue(n.child[2])
|
||||||
|
|
||||||
n.exec = func(f *Frame) Builtin {
|
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
|
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) {
|
func _cap(n *Node) {
|
||||||
i := n.findex
|
i := n.findex
|
||||||
value := genValue(n.child[1])
|
value := genValue(n.child[1])
|
||||||
|
|||||||
Reference in New Issue
Block a user