From 9777b6e04b9f834e5714d962b63c6f2395b0df5f Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Mon, 22 Jul 2024 18:23:19 +0900 Subject: [PATCH] Handle "self" uniformly in cpath Also, integrate SingletonClassNode to ModuleBaseNode --- lib/typeprof/core/ast.rb | 9 ++-- lib/typeprof/core/ast/const.rb | 4 +- lib/typeprof/core/ast/module.rb | 94 ++++----------------------------- 3 files changed, 17 insertions(+), 90 deletions(-) diff --git a/lib/typeprof/core/ast.rb b/lib/typeprof/core/ast.rb index 204bb11bc..730acafcd 100644 --- a/lib/typeprof/core/ast.rb +++ b/lib/typeprof/core/ast.rb @@ -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) @@ -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 @@ -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) diff --git a/lib/typeprof/core/ast/const.rb b/lib/typeprof/core/ast/const.rb index a67c89c61..cb430a21d 100644 --- a/lib/typeprof/core/ast/const.rb +++ b/lib/typeprof/core/ast/const.rb @@ -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 diff --git a/lib/typeprof/core/ast/module.rb b/lib/typeprof/core/ast/module.rb index 80353579e..021dfabe2 100644 --- a/lib/typeprof/core/ast/module.rb +++ b/lib/typeprof/core/ast/module.rb @@ -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 @@ -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 @@ -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