Skip to content

Commit

Permalink
Handle "self" uniformly in cpath
Browse files Browse the repository at this point in the history
Also, integrate SingletonClassNode to ModuleBaseNode
  • Loading branch information
mame committed Jul 22, 2024
1 parent 8bc8b76 commit 9777b6e
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 90 deletions.
9 changes: 6 additions & 3 deletions lib/typeprof/core/ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ def self.create_node(raw_node, lenv, use_result = true)
when :statements_node then StatementsNode.new(raw_node, lenv, use_result)
when :module_node then ModuleNode.new(raw_node, lenv, use_result)
when :class_node then ClassNode.new(raw_node, lenv, use_result)
when :singleton_class_node then SingletonClassNode.new(raw_node, lenv, use_result)
when :def_node then DefNode.new(raw_node, lenv, use_result)
when :alias_method_node then AliasNode.new(raw_node, lenv)
when :singleton_class_node then SingletonClassNode.new(raw_node, lenv)

# control
when :and_node then AndNode.new(raw_node, lenv)
Expand Down Expand Up @@ -258,7 +258,7 @@ def self.create_target_node(raw_node, lenv)
end
end

def self.parse_cpath(raw_node, base_cpath)
def self.parse_cpath(raw_node, cref)
names = []
while raw_node
case raw_node.type
Expand All @@ -273,11 +273,14 @@ def self.parse_cpath(raw_node, base_cpath)
else
return names.reverse
end
when :self_node
break if cref.scope_level == :class
return nil
else
return nil
end
end
return base_cpath + names.reverse
return cref.cpath + names.reverse
end

def self.parse_rbs(path, src)
Expand Down
4 changes: 2 additions & 2 deletions lib/typeprof/core/ast/const.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ def initialize(raw_node, rhs, lenv)
when :constant_path_write_node, :constant_path_operator_write_node, :constant_path_or_write_node, :constant_path_and_write_node
# expr::C = expr
@cpath = AST.create_node(raw_node.target, lenv)
@static_cpath = AST.parse_cpath(raw_node.target, lenv.cref.cpath)
@static_cpath = AST.parse_cpath(raw_node.target, lenv.cref)
@cname_code_range = TypeProf::CodeRange.from_node(raw_node.target)
when :constant_path_target_node
# expr::C, * = ary
@cpath = ConstantReadNode.new(raw_node, lenv)
@static_cpath = AST.parse_cpath(raw_node, lenv.cref.cpath)
@static_cpath = AST.parse_cpath(raw_node, lenv.cref)
@cname_code_range = TypeProf::CodeRange.from_node(raw_node)
else
raise
Expand Down
94 changes: 9 additions & 85 deletions lib/typeprof/core/ast/module.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
module TypeProf::Core
class AST
class ModuleBaseNode < Node
def initialize(raw_node, lenv, raw_cpath, raw_scope, use_result)
def initialize(raw_node, lenv, raw_cpath, meta, raw_scope, use_result)
super(raw_node, lenv)

@cpath = AST.create_node(raw_cpath, lenv)
@static_cpath = AST.parse_cpath(raw_cpath, lenv.cref.cpath)
@static_cpath = AST.parse_cpath(raw_cpath, lenv.cref)
@tbl = raw_node.locals

# TODO: class Foo < Struct.new(:foo, :bar)

if @static_cpath
ncref = CRef.new(@static_cpath, :class, nil, lenv.cref)
ncref = CRef.new(@static_cpath, meta ? :metaclass : :class, nil, lenv.cref)
nlenv = LocalEnv.new(@lenv.path, ncref, {}, [])
@body = raw_scope ? AST.create_node(raw_scope, nlenv, use_result) : DummyNilNode.new(code_range, lenv)
else
@body = nil
end

@cname_code_range = TypeProf::CodeRange.from_node(raw_node.constant_path)
@cname_code_range = meta ? nil : TypeProf::CodeRange.from_node(raw_node.constant_path)
end

attr_reader :tbl, :cpath, :static_cpath, :cname_code_range, :body
Expand Down Expand Up @@ -78,13 +78,13 @@ def modified_vars(tbl, vars)

class ModuleNode < ModuleBaseNode
def initialize(raw_node, lenv, use_result)
super(raw_node, lenv, raw_node.constant_path, raw_node.body, use_result)
super(raw_node, lenv, raw_node.constant_path, false, raw_node.body, use_result)
end
end

class ClassNode < ModuleBaseNode
def initialize(raw_node, lenv, use_result)
super(raw_node, lenv, raw_node.constant_path, raw_node.body, use_result)
super(raw_node, lenv, raw_node.constant_path, false, raw_node.body, use_result)
raw_superclass = raw_node.superclass
@superclass_cpath = raw_superclass ? AST.create_node(raw_superclass, lenv) : nil
end
Expand Down Expand Up @@ -114,85 +114,9 @@ def install0(genv)
end
end

class SingletonClassNode < Node
def initialize(raw_node, lenv)
super(raw_node, lenv)

@expression = AST.create_node(raw_node.expression, lenv)
@tbl = raw_node.locals

@static_cpath = case @expression
when ConstantReadNode
AST.parse_cpath(@raw_node.expression, lenv.cref.cpath)
when SelfNode
lenv.cref.cpath
else
raise "unsupported expression: #{@expression}"
end

if @static_cpath.nil? || @static_cpath.empty?
@body = nil
else
ncref = CRef.new(static_cpath, :metaclass, nil, lenv.cref)
nlenv = LocalEnv.new(lenv.path, ncref, {}, [])
@body = @raw_node.body ? AST.create_node(@raw_node.body, nlenv) : DummyNilNode.new(code_range, lenv)
end
end

attr_reader :expression, :tbl, :static_cpath, :body

def subnodes = { expression:, body: }
def attrs = { tbl:, static_cpath: }

def define0(genv)
@expression.define(genv)

if @body
@body.define(genv)
@mod = genv.resolve_cpath(@static_cpath)
@mod_cdef = @mod.add_module_def(genv, self)
else
@changes.add_diagnostic(:code_range, "TypeProf cannot analyze a non-static class") # warning
nil
end
end

def define_copy(genv)
if @body
@mod_cdef.add_def(self)
@mod_cdef.remove_def(@prev_node)
end
super(genv)
end

def undefine0(genv)
if @body
@mod.remove_module_def(genv, self)
@body.undefine(genv)
end

@expression.undefine(genv)
end

def install0(genv)
@expression.install(genv)

if @body
@tbl.each {|var| @body.lenv.locals[var] = Source.new(genv.nil_type) }
@body.lenv.locals[:"*self"] = @body.lenv.cref.get_self(genv)

@mod_val = Source.new(Type::Singleton.new(genv, genv.resolve_cpath(@static_cpath)))
@changes.add_edge(genv, @mod_val, @mod_cdef.vtx)
ret = Vertex.new(self)
@changes.add_edge(genv, @body.install(genv), ret)
ret
else
Source.new
end
end

def modified_vars(tbl, vars)
# skip
class SingletonClassNode < ModuleBaseNode
def initialize(raw_node, lenv, use_result)
super(raw_node, lenv, raw_node.expression, true, raw_node.body, use_result)
end
end
end
Expand Down

0 comments on commit 9777b6e

Please sign in to comment.