Skip to content

Commit

Permalink
Add type printer
Browse files Browse the repository at this point in the history
  • Loading branch information
soutaro committed Apr 15, 2019
1 parent 4c8ead0 commit 6d681de
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 24 deletions.
17 changes: 17 additions & 0 deletions lib/ruby/signature/method_type.rb
Expand Up @@ -76,6 +76,23 @@ def map_type(&block)
location: location
)
end

def to_s
s = case
when block && block.required
"(#{type.param_to_s}) { (#{block.type.param_to_s} -> #{block.type.return_to_s} } -> #{type.return_to_s}"
when block
"(#{type.param_to_s}) ?{ (#{block.type.param_to_s} -> #{block.type.return_to_s} } -> #{type.return_to_s}"
else
"(#{type.param_to_s}) -> #{type.return_to_s}"
end

if type_params.empty?
s
else
"[#{type_params.join(", ")}] #{s}"
end
end
end
end
end
144 changes: 121 additions & 23 deletions lib/ruby/signature/types.rb
Expand Up @@ -35,31 +35,34 @@ def hash
include NoSubst

def to_json(*a)
klass = case self
when Types::Bases::Bool
:bool
when Types::Bases::Void
:void
when Types::Bases::Any
:any
when Types::Bases::Nil
:nil
when Types::Bases::Top
:top
when Types::Bases::Bottom
:bot
when Types::Bases::Self
:self
when Types::Bases::Instance
:instance
when Types::Bases::Class
:class
else
raise "Unexpected base type: #{type.inspect}"
end

klass = to_s.to_sym
{ class: klass, location: location }.to_json(*a)
end

def to_s(level = 0)
case self
when Types::Bases::Bool
'bool'
when Types::Bases::Void
'void'
when Types::Bases::Any
'any'
when Types::Bases::Nil
'nil'
when Types::Bases::Top
'top'
when Types::Bases::Bottom
'bot'
when Types::Bases::Self
'self'
when Types::Bases::Instance
'instance'
when Types::Bases::Class
'class'
else
raise "Unexpected base type: #{type.inspect}"
end
end
end

class Bool < Base; end
Expand Down Expand Up @@ -120,6 +123,10 @@ def self.fresh(v = :T)
@@count = @@count + 1
new(name: :"#{v}@#{@@count}", location: nil)
end

def to_s(level = 0)
name.to_s
end
end

class ClassSingleton
Expand Down Expand Up @@ -147,6 +154,10 @@ def hash
def to_json(*a)
{ class: :class_singleton, name: name, location: location }.to_json(*a)
end

def to_s(level = 0)
"singleton(#{name})"
end
end

module Application
Expand All @@ -170,6 +181,14 @@ def free_variables(set = Set.new)
end
end
end

def to_s(level = 0)
if args.empty?
name.to_s
else
"#{name}[#{args.join(", ")}]"
end
end
end

class Interface
Expand Down Expand Up @@ -241,6 +260,10 @@ def hash
def to_json(*a)
{ class: :alias, name: name, location: location }.to_json(*a)
end

def to_s(level = 0)
name.to_s
end
end

class Tuple
Expand Down Expand Up @@ -278,6 +301,10 @@ def sub(s)
self.class.new(types: types.map {|ty| ty.sub(s) },
location: location)
end

def to_s(level = 0)
"[ #{types.join(", ")} ]"
end
end

class Record
Expand Down Expand Up @@ -315,6 +342,13 @@ def sub(s)
self.class.new(fields: fields.transform_values {|ty| ty.sub(s) },
location: location)
end

def to_s(level = 0)
fields = self.fields.map do |key, type|
"#{key}: #{type}"
end
"{ #{fields.join(", ")} }"
end
end

class Optional
Expand Down Expand Up @@ -347,6 +381,10 @@ def to_json(*a)
def sub(s)
self.class.new(type: type.sub(s), location: location)
end

def to_s(level = 0)
"#{type.to_s(1)}?"
end
end

class Union
Expand Down Expand Up @@ -384,6 +422,14 @@ def sub(s)
self.class.new(types: types.map {|ty| ty.sub(s) },
location: location)
end

def to_s(level = 0)
if level > 0
"(#{types.join(" | ")})"
else
types.join(" | ")
end
end
end

class Intersection
Expand Down Expand Up @@ -421,6 +467,15 @@ def sub(s)
self.class.new(types: types.map {|ty| ty.sub(s) },
location: location)
end

def to_s(level = 0)
strs = types.map {|ty| ty.to_s(2) }
if level > 0
"(#{strs.join(" & ")})"
else
strs.join(" & ")
end
end
end

class Function
Expand Down Expand Up @@ -454,6 +509,14 @@ def map_type
def to_json(*a)
{ type: type, name: name }.to_json(*a)
end

def to_s
if name
"#{type} #{name}"
else
"#{type}"
end
end
end

attr_reader :required_positionals
Expand Down Expand Up @@ -576,6 +639,33 @@ def with_return_type(type)
return_type: type
)
end

def empty?
required_positionals.empty? &&
optional_positionals.empty? &&
!rest_positionals &&
trailing_positionals.empty? &&
required_keywords.empty? &&
optional_keywords.empty? &&
!rest_keywords
end

def param_to_s
params = []
params.push(*required_positionals.map(&:to_s))
params.push(*optional_positionals.map {|p| "?#{p}"})
params.push("*#{rest_positionals}") if rest_positionals
params.push(*trailing_positionals.map(&:to_s))
params.push(*required_keywords.map {|name, param| "#{name}: #{param}" })
params.push(*optional_keywords.map {|name, param| "?#{name}: #{param}" })
params.push("**#{rest_keywords}") if rest_keywords

params.join(", ")
end

def return_to_s
return_type.to_s(1)
end
end

class Proc
Expand Down Expand Up @@ -608,6 +698,10 @@ def to_json(*a)
def sub(s)
self.class.new(type: type.sub(s), location: location)
end

def to_s(level = 0)
"^(#{type.param_to_s}) -> #{type.return_to_s}".lstrip
end
end

class Literal
Expand Down Expand Up @@ -635,6 +729,10 @@ def hash
def to_json(*a)
{ class: :literal, literal: literal.inspect, location: location }.to_json(*a)
end

def to_s(level = 0)
literal.to_s
end
end
end
end
Expand Down
17 changes: 16 additions & 1 deletion test/ruby/signature/types_test.rb
Expand Up @@ -3,6 +3,21 @@
class Ruby::Signature::TypesTest < Minitest::Test
Types = Ruby::Signature::Types

def test_union_build
include TestHelper

def test_to_s
assert_equal "Array[Integer]", parse_type("Array[Integer]").to_s
assert_equal "Array[Integer]?", parse_type("Array[Integer]?").to_s
assert_equal "[ Integer, bool? ]", parse_type("[Integer, bool?]").to_s
assert_equal "String | bool?", parse_type("String | bool?").to_s
assert_equal "(String | bool)?", parse_type("(String | bool)?").to_s
assert_equal "String & bool?", parse_type("String & bool?").to_s
assert_equal "(String & bool)?", parse_type("(String & bool)?").to_s
assert_equal "Integer | String & bool", parse_type("Integer | String & bool").to_s
assert_equal "(Integer | String) & bool", parse_type("(Integer | String) & bool").to_s
assert_equal "(Integer | String & bool)?", parse_type("(Integer | String & bool)?").to_s
assert_equal "((Integer | String) & bool)?", parse_type("((Integer | String) & bool)?").to_s
assert_equal "^() -> void", parse_type("^() -> void").to_s
assert_equal "^(bool flag, ?any, *Symbol, name: String, ?email: nil, **Symbol) -> void", parse_type("^(bool flag, ?any, *Symbol, name: String, ?email: nil, **Symbol) -> void").to_s
end
end

0 comments on commit 6d681de

Please sign in to comment.