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
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
Reference in New Issue
Block a user