Commit 58a93660 authored by Dylan Trotter's avatar Dylan Trotter

Remove name param from NewFunction and use code's name. Add filename field to code object.

parent 0f4a1a11
......@@ -413,10 +413,11 @@ class ExprVisitor(ast.NodeVisitor):
# The function object gets written to a temporary writer because we need
# it as an expression that we subsequently bind to some variable.
self.writer.write_tmpl(
'$result = πg.NewFunction('
'$name, πg.NewCode($name, $args, $flags, func('
'πF *πg.Frame, πArgs []*πg.Object) (*πg.Object, *πg.BaseException) {',
result=result.name, name=util.go_str(node.name), args=func_args.expr,
'$result = πg.NewFunction(πg.NewCode($name, $filename, $args, '
'$flags, func(πF *πg.Frame, πArgs []*πg.Object) '
'(*πg.Object, *πg.BaseException) {',
result=result.name, name=util.go_str(node.name),
filename=util.go_str(self.block.filename), args=func_args.expr,
flags=' | '.join(flags) if flags else 0)
with self.writer.indent_block():
# Declare the local variables used in this function.
......
......@@ -18,6 +18,7 @@ const (
type Code struct {
Object
name string
filename string
// argc is the number of positional arguments.
argc int `attr:"co_argcount"`
// minArgc is the number of positional non-keyword arguments (i.e. the
......@@ -28,7 +29,7 @@ type Code struct {
fn func(*Frame, []*Object) (*Object, *BaseException)
}
func NewCode(name string, args []FunctionArg, flags CodeFlag, fn func(*Frame, []*Object) (*Object, *BaseException)) *Code {
func NewCode(name, filename string, args []FunctionArg, flags CodeFlag, fn func(*Frame, []*Object) (*Object, *BaseException)) *Code {
argc := len(args)
minArgc := 0
for ; minArgc < argc; minArgc++ {
......@@ -42,7 +43,7 @@ func NewCode(name string, args []FunctionArg, flags CodeFlag, fn func(*Frame, []
logFatal(fmt.Sprintf(format, name, arg.Name))
}
}
return &Code{Object{typ: CodeType}, name, argc, minArgc, flags, args, fn}
return &Code{Object{typ: CodeType}, name, filename, argc, minArgc, flags, args, fn}
}
func toCodeUnsafe(o *Object) *Code {
......
......@@ -14,7 +14,7 @@ func TestNewCodeKeywordsCheck(t *testing.T) {
logFatal = func(msg string) {
got = msg
}
NewCode("foo", []FunctionArg{{"bar", None}, {"baz", nil}}, 0, nil)
NewCode("foo", "foo.py", []FunctionArg{{"bar", None}, {"baz", nil}}, 0, nil)
if want := "foo() non-keyword arg baz after keyword arg"; got != want {
t.Errorf("NewCode logged %q, want %q", got, want)
}
......@@ -31,24 +31,24 @@ func TestNewCode(t *testing.T) {
return NewTuple(Args(args).makeCopy()...).ToObject(), nil
}
cases := []invokeTestCase{
invokeTestCase{args: wrapArgs(NewCode("f1", nil, 0, fn)), want: NewTuple().ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f2", []FunctionArg{{"a", nil}}, 0, fn), 123), want: newTestTuple(123).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f2", []FunctionArg{{"a", nil}}, 0, fn)), kwargs: wrapKWArgs("a", "apple"), want: newTestTuple("apple").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f2", []FunctionArg{{"a", nil}}, 0, fn)), kwargs: wrapKWArgs("b", "bear"), wantExc: mustCreateException(TypeErrorType, "f2() got an unexpected keyword argument 'b'")},
invokeTestCase{args: wrapArgs(NewCode("f2", []FunctionArg{{"a", nil}}, 0, fn)), wantExc: mustCreateException(TypeErrorType, "f2() takes at least 1 arguments (0 given)")},
invokeTestCase{args: wrapArgs(NewCode("f2", []FunctionArg{{"a", nil}}, 0, fn), 1, 2, 3), wantExc: mustCreateException(TypeErrorType, "f2() takes 1 arguments (3 given)")},
invokeTestCase{args: wrapArgs(NewCode("f3", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn), 1, 2), want: newTestTuple(1, 2).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f3", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn), 1), kwargs: wrapKWArgs("b", "bear"), want: newTestTuple(1, "bear").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f3", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn)), kwargs: wrapKWArgs("b", "bear", "a", "apple"), want: newTestTuple("apple", "bear").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f3", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn), 1), kwargs: wrapKWArgs("a", "alpha"), wantExc: mustCreateException(TypeErrorType, "f3() got multiple values for keyword argument 'a'")},
invokeTestCase{args: wrapArgs(NewCode("f4", []FunctionArg{{"a", nil}, {"b", None}}, 0, fn), 123), want: newTestTuple(123, None).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f4", []FunctionArg{{"a", nil}, {"b", None}}, 0, fn), 123, "bar"), want: newTestTuple(123, "bar").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f4", []FunctionArg{{"a", nil}, {"b", None}}, 0, fn)), kwargs: wrapKWArgs("a", 123, "b", "bar"), want: newTestTuple(123, "bar").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f5", []FunctionArg{{"a", nil}}, CodeFlagVarArg, fn), 1), want: newTestTuple(1, NewTuple()).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f5", []FunctionArg{{"a", nil}}, CodeFlagVarArg, fn), 1, 2, 3), want: newTestTuple(1, newTestTuple(2, 3)).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f6", []FunctionArg{{"a", nil}}, CodeFlagKWArg, fn), "bar"), want: newTestTuple("bar", NewDict()).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f6", []FunctionArg{{"a", nil}}, CodeFlagKWArg, fn)), kwargs: wrapKWArgs("a", "apple", "b", "bear"), want: newTestTuple("apple", newTestDict("b", "bear")).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f6", []FunctionArg{{"a", nil}}, CodeFlagKWArg, fn), "bar"), kwargs: wrapKWArgs("b", "baz", "c", "qux"), want: newTestTuple("bar", newTestDict("b", "baz", "c", "qux")).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f1", "foo.py", nil, 0, fn)), want: NewTuple().ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f2", "foo.py", []FunctionArg{{"a", nil}}, 0, fn), 123), want: newTestTuple(123).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f2", "foo.py", []FunctionArg{{"a", nil}}, 0, fn)), kwargs: wrapKWArgs("a", "apple"), want: newTestTuple("apple").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f2", "foo.py", []FunctionArg{{"a", nil}}, 0, fn)), kwargs: wrapKWArgs("b", "bear"), wantExc: mustCreateException(TypeErrorType, "f2() got an unexpected keyword argument 'b'")},
invokeTestCase{args: wrapArgs(NewCode("f2", "foo.py", []FunctionArg{{"a", nil}}, 0, fn)), wantExc: mustCreateException(TypeErrorType, "f2() takes at least 1 arguments (0 given)")},
invokeTestCase{args: wrapArgs(NewCode("f2", "foo.py", []FunctionArg{{"a", nil}}, 0, fn), 1, 2, 3), wantExc: mustCreateException(TypeErrorType, "f2() takes 1 arguments (3 given)")},
invokeTestCase{args: wrapArgs(NewCode("f3", "foo.py", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn), 1, 2), want: newTestTuple(1, 2).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f3", "foo.py", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn), 1), kwargs: wrapKWArgs("b", "bear"), want: newTestTuple(1, "bear").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f3", "foo.py", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn)), kwargs: wrapKWArgs("b", "bear", "a", "apple"), want: newTestTuple("apple", "bear").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f3", "foo.py", []FunctionArg{{"a", nil}, {"b", nil}}, 0, fn), 1), kwargs: wrapKWArgs("a", "alpha"), wantExc: mustCreateException(TypeErrorType, "f3() got multiple values for keyword argument 'a'")},
invokeTestCase{args: wrapArgs(NewCode("f4", "foo.py", []FunctionArg{{"a", nil}, {"b", None}}, 0, fn), 123), want: newTestTuple(123, None).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f4", "foo.py", []FunctionArg{{"a", nil}, {"b", None}}, 0, fn), 123, "bar"), want: newTestTuple(123, "bar").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f4", "foo.py", []FunctionArg{{"a", nil}, {"b", None}}, 0, fn)), kwargs: wrapKWArgs("a", 123, "b", "bar"), want: newTestTuple(123, "bar").ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f5", "foo.py", []FunctionArg{{"a", nil}}, CodeFlagVarArg, fn), 1), want: newTestTuple(1, NewTuple()).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f5", "foo.py", []FunctionArg{{"a", nil}}, CodeFlagVarArg, fn), 1, 2, 3), want: newTestTuple(1, newTestTuple(2, 3)).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f6", "foo.py", []FunctionArg{{"a", nil}}, CodeFlagKWArg, fn), "bar"), want: newTestTuple("bar", NewDict()).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f6", "foo.py", []FunctionArg{{"a", nil}}, CodeFlagKWArg, fn)), kwargs: wrapKWArgs("a", "apple", "b", "bear"), want: newTestTuple("apple", newTestDict("b", "bear")).ToObject()},
invokeTestCase{args: wrapArgs(NewCode("f6", "foo.py", []FunctionArg{{"a", nil}}, CodeFlagKWArg, fn), "bar"), kwargs: wrapKWArgs("b", "baz", "c", "qux"), want: newTestTuple("bar", newTestDict("b", "baz", "c", "qux")).ToObject()},
}
for _, cas := range cases {
if err := runInvokeTestCase(testFunc.ToObject(), &cas); err != "" {
......
......@@ -93,8 +93,8 @@ type FunctionArg struct {
// validated before calling fn. This includes checking that an appropriate
// number of arguments are provided, populating *args and **kwargs if
// necessary, etc.
func NewFunction(name string, c *Code) *Function {
return &Function{Object{typ: FunctionType, dict: NewDict()}, nil, name, c}
func NewFunction(c *Code) *Function {
return &Function{Object{typ: FunctionType, dict: NewDict()}, nil, c.name, c}
}
// newBuiltinFunction returns a function object with the given name that
......
......@@ -23,7 +23,7 @@ func TestFunctionCall(t *testing.T) {
foo := newBuiltinFunction("foo", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
return newTestTuple(NewTuple(args.makeCopy()...), kwargs.makeDict()).ToObject(), nil
}).ToObject()
bar := NewFunction("bar", NewCode("bar", nil, CodeFlagVarArg, func(f *Frame, args []*Object) (*Object, *BaseException) {
bar := NewFunction(NewCode("bar", "bar.py", nil, CodeFlagVarArg, func(f *Frame, args []*Object) (*Object, *BaseException) {
return args[0], nil
}))
cases := []invokeTestCase{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment