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): ...@@ -413,10 +413,11 @@ class ExprVisitor(ast.NodeVisitor):
# The function object gets written to a temporary writer because we need # The function object gets written to a temporary writer because we need
# it as an expression that we subsequently bind to some variable. # it as an expression that we subsequently bind to some variable.
self.writer.write_tmpl( self.writer.write_tmpl(
'$result = πg.NewFunction(' '$result = πg.NewFunction(πg.NewCode($name, $filename, $args, '
'$name, πg.NewCode($name, $args, $flags, func(' '$flags, func(πF *πg.Frame, πArgs []*πg.Object) '
'πF *πg.Frame, πArgs []*πg.Object) (*πg.Object, *πg.BaseException) {', '(*πg.Object, *πg.BaseException) {',
result=result.name, name=util.go_str(node.name), args=func_args.expr, 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) flags=' | '.join(flags) if flags else 0)
with self.writer.indent_block(): with self.writer.indent_block():
# Declare the local variables used in this function. # Declare the local variables used in this function.
......
...@@ -17,7 +17,8 @@ const ( ...@@ -17,7 +17,8 @@ const (
type Code struct { type Code struct {
Object Object
name string name string
filename string
// argc is the number of positional arguments. // argc is the number of positional arguments.
argc int `attr:"co_argcount"` argc int `attr:"co_argcount"`
// minArgc is the number of positional non-keyword arguments (i.e. the // minArgc is the number of positional non-keyword arguments (i.e. the
...@@ -28,7 +29,7 @@ type Code struct { ...@@ -28,7 +29,7 @@ type Code struct {
fn func(*Frame, []*Object) (*Object, *BaseException) 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) argc := len(args)
minArgc := 0 minArgc := 0
for ; minArgc < argc; minArgc++ { for ; minArgc < argc; minArgc++ {
...@@ -42,7 +43,7 @@ func NewCode(name string, args []FunctionArg, flags CodeFlag, fn func(*Frame, [] ...@@ -42,7 +43,7 @@ func NewCode(name string, args []FunctionArg, flags CodeFlag, fn func(*Frame, []
logFatal(fmt.Sprintf(format, name, arg.Name)) 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 { func toCodeUnsafe(o *Object) *Code {
......
...@@ -14,7 +14,7 @@ func TestNewCodeKeywordsCheck(t *testing.T) { ...@@ -14,7 +14,7 @@ func TestNewCodeKeywordsCheck(t *testing.T) {
logFatal = func(msg string) { logFatal = func(msg string) {
got = msg 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 { if want := "foo() non-keyword arg baz after keyword arg"; got != want {
t.Errorf("NewCode logged %q, want %q", got, want) t.Errorf("NewCode logged %q, want %q", got, want)
} }
...@@ -31,24 +31,24 @@ func TestNewCode(t *testing.T) { ...@@ -31,24 +31,24 @@ func TestNewCode(t *testing.T) {
return NewTuple(Args(args).makeCopy()...).ToObject(), nil return NewTuple(Args(args).makeCopy()...).ToObject(), nil
} }
cases := []invokeTestCase{ cases := []invokeTestCase{
invokeTestCase{args: wrapArgs(NewCode("f1", nil, 0, fn)), want: NewTuple().ToObject()}, invokeTestCase{args: wrapArgs(NewCode("f1", "foo.py", 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", "foo.py", []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", "foo.py", []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", "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", []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)), 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("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", []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, 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", "foo.py", []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", "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", []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("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", []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), 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", "foo.py", []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("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", []FunctionArg{{"a", nil}}, CodeFlagVarArg, fn), 1), want: newTestTuple(1, NewTuple()).ToObject()}, invokeTestCase{args: wrapArgs(NewCode("f5", "foo.py", []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("f5", "foo.py", []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", "foo.py", []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", "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", []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("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 { for _, cas := range cases {
if err := runInvokeTestCase(testFunc.ToObject(), &cas); err != "" { if err := runInvokeTestCase(testFunc.ToObject(), &cas); err != "" {
......
...@@ -93,8 +93,8 @@ type FunctionArg struct { ...@@ -93,8 +93,8 @@ type FunctionArg struct {
// validated before calling fn. This includes checking that an appropriate // validated before calling fn. This includes checking that an appropriate
// number of arguments are provided, populating *args and **kwargs if // number of arguments are provided, populating *args and **kwargs if
// necessary, etc. // necessary, etc.
func NewFunction(name string, c *Code) *Function { func NewFunction(c *Code) *Function {
return &Function{Object{typ: FunctionType, dict: NewDict()}, nil, name, c} return &Function{Object{typ: FunctionType, dict: NewDict()}, nil, c.name, c}
} }
// newBuiltinFunction returns a function object with the given name that // newBuiltinFunction returns a function object with the given name that
......
...@@ -23,7 +23,7 @@ func TestFunctionCall(t *testing.T) { ...@@ -23,7 +23,7 @@ func TestFunctionCall(t *testing.T) {
foo := newBuiltinFunction("foo", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) { foo := newBuiltinFunction("foo", func(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
return newTestTuple(NewTuple(args.makeCopy()...), kwargs.makeDict()).ToObject(), nil return newTestTuple(NewTuple(args.makeCopy()...), kwargs.makeDict()).ToObject(), nil
}).ToObject() }).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 return args[0], nil
})) }))
cases := []invokeTestCase{ 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