Skip to content

Commit

Permalink
add #source_location method to methods and procs
Browse files Browse the repository at this point in the history
  • Loading branch information
timfel committed Feb 14, 2017
1 parent 08f1865 commit 50a8a2c
Show file tree
Hide file tree
Showing 12 changed files with 46 additions and 21 deletions.
1 change: 1 addition & 0 deletions lib-topaz/bootstrap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
load_bootstrap.call("thread.rb")
load_bootstrap.call("time.rb")
load_bootstrap.call("top_self.rb")
load_bootstrap.call("method.rb")

# ffi
load_bootstrap.call("ffitopaz/pointer.rb")
Expand Down
5 changes: 5 additions & 0 deletions lib-topaz/method.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Method
def to_proc
Proc.new { |*args, &blk| self.call(*args, &blk) }
end
end
6 changes: 0 additions & 6 deletions spec/tags/core/method/source_location_tags.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
fails:Method#source_location returns nil for built-in methods
fails:Method#source_location returns an Array
fails:Method#source_location sets the first value to the path of the file in which the method was defined
fails:Method#source_location sets the last value to a Fixnum representing the line on which the method was defined
fails:Method#source_location returns the last place the method was defined
fails:Method#source_location returns the location of the original method even if it was aliased
fails:Method#source_location works for methods defined with a block
fails:Method#source_location works for methods defined with a Method
fails:Method#source_location works for methods defined with an UnboundMethod
fails:Method#source_location works for methods whose visibility has been overridden in a subclass
fails:Method#source_location for a Method generated by respond_to_missing? it returns nil
fails:Method#source_location for a Method generated by respond_to_missing? returns nil
4 changes: 0 additions & 4 deletions spec/tags/core/proc/source_location_tags.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
fails:Proc#source_location returns an Array
fails:Proc#source_location sets the first value to the path of the file in which the proc was defined
fails:Proc#source_location sets the last value to a Fixnum representing the line on which the proc was defined
fails:Proc#source_location works even if the proc was created on the same line
fails:Proc#source_location returns the first line of a multi-line proc (i.e. the line containing 'proc do')
fails:Proc#source_location returns the location of the proc's body; not necessarily the proc itself
4 changes: 0 additions & 4 deletions spec/tags/core/unboundmethod/source_location_tags.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
fails:UnboundMethod#source_location sets the first value to the path of the file in which the method was defined
fails:UnboundMethod#source_location sets the last value to a Fixnum representing the line on which the method was defined
fails:UnboundMethod#source_location returns the last place the method was defined
fails:UnboundMethod#source_location returns the location of the original method even if it was aliased
fails:UnboundMethod#source_location works for define_method methods
fails:UnboundMethod#source_location works for define_singleton_method methods
7 changes: 5 additions & 2 deletions topaz/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ def compile_bytecode(self, ctx, code_ctx, args, splat_arg, post_args, kwargs, kw
body.compile(code_ctx)
code_ctx.emit(consts.RETURN)
return code_ctx.create_bytecode(
lineno=self.lineno,
args=arg_names,
defaults=arg_defaults,
first_default_arg=first_default_arg,
Expand All @@ -379,7 +380,8 @@ def compile_bytecode(self, ctx, code_ctx, args, splat_arg, post_args, kwargs, kw


class Function(AbstractCallable):
def __init__(self, parent, name, args, splat_arg, post_args, kwargs, kwrest_arg, block_arg, body):
def __init__(self, lineno, parent, name, args, splat_arg, post_args, kwargs, kwrest_arg, block_arg, body):
self.lineno = lineno
self.parent = parent
self.name = name
self.args = args
Expand Down Expand Up @@ -852,7 +854,8 @@ def __init__(self, receiver, lineno):


class SendBlock(AbstractCallable):
def __init__(self, block_args, splat_arg, post_args, kwargs, kwrest_arg, block_arg, block):
def __init__(self, lineno, block_args, splat_arg, post_args, kwargs, kwrest_arg, block_arg, block):
self.lineno = lineno
self.block_args = block_args
self.splat_arg = splat_arg
self.post_args = post_args
Expand Down
7 changes: 4 additions & 3 deletions topaz/astcompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ def __init__(self, space, code_name, symtable, filepath):
self.current_block = self.first_block = self.new_block()
self.frame_blocks = []

def create_bytecode(self, args=None, defaults=None, first_default_arg=None,
splat_arg=None, kwargs=None, kw_defaults=None,
kwrest_arg=None, block_arg=None):
def create_bytecode(self, lineno=-1, args=None, defaults=None,
first_default_arg=None, splat_arg=None, kwargs=None,
kw_defaults=None, kwrest_arg=None, block_arg=None):
if args is None:
args = []
if defaults is None:
Expand Down Expand Up @@ -143,6 +143,7 @@ def create_bytecode(self, args=None, defaults=None, first_default_arg=None,
return W_CodeObject(
self.code_name,
self.filepath,
lineno,
code,
depth,
self.consts[:],
Expand Down
7 changes: 5 additions & 2 deletions topaz/objects/codeobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ class W_CodeObject(W_BaseObject):
_immutable_fields_ = [
"code", "consts_w[*]", "max_stackdepth", "cellvars[*]", "freevars[*]",
"arg_pos[*]", "defaults[*]", "block_arg_pos", "splat_arg_pos",
"kwarg_names[*]", "kwrest_pos", "kw_defaults[*]", "default_arg_begin"
"kwarg_names[*]", "kwrest_pos", "kw_defaults[*]", "default_arg_begin",
"filepath", "lineno",
]

classdef = ClassDef("Code", W_BaseObject.classdef)

def __init__(self, name, filepath, code, max_stackdepth, consts, args,
def __init__(self, name, filepath, line, code, max_stackdepth, consts, args,
splat_arg, kwargs, kwrest_arg, block_arg,
defaults, first_default_arg, kw_defaults,
cellvars, freevars, lineno_table):

self.name = name
self.filepath = filepath
self.lineno = line
self.code = code
self.max_stackdepth = max_stackdepth
self.consts_w = consts
Expand Down Expand Up @@ -60,6 +62,7 @@ def __deepcopy__(self, memo):
obj = super(W_CodeObject, self).__deepcopy__(memo)
obj.name = self.name
obj.filepath = self.filepath
obj.lineno = self.lineno
obj.code = self.code
obj.max_stackdepth = self.max_stackdepth
obj.consts_w = copy.deepcopy(self.consts_w, memo)
Expand Down
9 changes: 9 additions & 0 deletions topaz/objects/functionobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ def update_visibility(self, visibility):
def arity(self, space):
return space.newint(0)

def source_location(self, space):
return space.w_nil


class W_UserFunction(W_FunctionObject):
_immutable_fields_ = ["bytecode", "lexical_scope"]
Expand Down Expand Up @@ -58,6 +61,12 @@ def call(self, space, w_receiver, args_w, block):
def arity(self, space):
return space.newint(self.bytecode.arity(negative_defaults=True))

def source_location(self, space):
return space.newarray([
space.newstr_fromstr(self.bytecode.filepath),
space.newint(self.bytecode.lineno)
])


class W_BuiltinFunction(W_FunctionObject):
_immutable_fields_ = ["func"]
Expand Down
8 changes: 8 additions & 0 deletions topaz/objects/methodobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ def method_to_s(self, space):
return method_to_s


def create_source_location(classdef):
@classdef.method("source_location")
def method_source_location(self, space):
return self.w_function.source_location(space)


class W_MethodObject(W_Object):
classdef = ClassDef("Method", W_Object.classdef)

Expand All @@ -30,6 +36,7 @@ def __init__(self, space, w_owner, w_function, w_receiver):
method_allocate = classdef.undefine_allocator()
method_owner = create_owner(classdef)
method_to_s = create_to_s(classdef)
method_source_location = create_source_location(classdef)

@classdef.method("[]")
@classdef.method("call")
Expand Down Expand Up @@ -74,6 +81,7 @@ def __init__(self, space, w_owner, w_function):
method_allocator = classdef.undefine_allocator()
method_owner = create_owner(classdef)
method_to_s = create_to_s(classdef)
method_source_location = create_source_location(classdef)

@classdef.method("bind")
def method_bind(self, space, w_receiver):
Expand Down
7 changes: 7 additions & 0 deletions topaz/objects/procobject.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,10 @@ def method_arity(self, space):
@classdef.method("binding")
def method_binding(self, space):
return space.newbinding_fromblock(self)

@classdef.method("source_location")
def method_source_location(self, space):
return space.newarray([
space.newstr_fromstr(self.bytecode.filepath),
space.newint(self.bytecode.lineno)
])
2 changes: 2 additions & 0 deletions topaz/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ def new_function(self, lineno, parent, fname, params, bodybox):
body = ast.Block(extra_stmts + [ast.Statement(body)])

return BoxAST(ast.Function(
lineno,
parent.getast() if parent is not None else None,
fname.getstr(),
args,
Expand All @@ -258,6 +259,7 @@ def new_send_block(self, lineno, params, body):
stmts = extra_stmts + stmts
block = ast.Block(stmts) if stmts else ast.Nil()
return BoxAST(ast.SendBlock(
lineno,
args,
splat,
postargs,
Expand Down

0 comments on commit 50a8a2c

Please sign in to comment.