gloss 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gloss.yml +1 -0
- data/Gemfile.lock +3 -3
- data/exe/gloss +10 -13
- data/ext/gloss/src/cr_ast.cr +61 -71
- data/ext/gloss/src/rb_ast.cr +37 -36
- data/lib/gloss.rb +14 -7
- data/lib/gloss/cli.rb +61 -40
- data/lib/gloss/config.rb +3 -1
- data/lib/gloss/errors.rb +1 -1
- data/lib/gloss/logger.rb +1 -6
- data/lib/gloss/prog_loader.rb +141 -0
- data/lib/gloss/scope.rb +1 -1
- data/lib/gloss/source.rb +1 -1
- data/lib/gloss/type_checker.rb +46 -28
- data/lib/gloss/utils.rb +44 -0
- data/lib/gloss/version.rb +1 -1
- data/lib/gloss/{builder.rb → visitor.rb} +80 -53
- data/lib/gloss/watcher.rb +2 -2
- data/lib/gloss/writer.rb +21 -10
- data/sig/core.rbs +2 -0
- data/sig/fast_blank.rbs +4 -0
- data/sig/{gloss.rbs → gls.rbs} +0 -0
- data/sig/optparse.rbs +6 -0
- data/sig/rubygems.rbs +9 -0
- data/sig/yaml.rbs +3 -0
- data/src/exe/gloss +19 -0
- data/src/lib/gloss.gl +26 -0
- data/src/lib/gloss/cli.gl +41 -26
- data/src/lib/gloss/config.gl +2 -2
- data/src/lib/gloss/logger.gl +1 -6
- data/src/lib/gloss/prog_loader.gl +133 -0
- data/src/lib/gloss/scope.gl +0 -2
- data/src/lib/gloss/type_checker.gl +42 -24
- data/src/lib/gloss/utils.gl +38 -0
- data/src/lib/gloss/version.gl +1 -1
- data/src/lib/gloss/{builder.gl → visitor.gl} +73 -44
- data/src/lib/gloss/watcher.gl +3 -4
- data/src/lib/gloss/writer.gl +15 -13
- metadata +16 -5
@@ -0,0 +1,38 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
module Gloss
|
4
|
+
module Utils
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def absolute_path(path)
|
8
|
+
pn = Pathname.new(path)
|
9
|
+
if pn.absolute?
|
10
|
+
pn.to_s
|
11
|
+
else
|
12
|
+
ap = File.absolute_path path
|
13
|
+
if File.exist? ap
|
14
|
+
ap
|
15
|
+
else
|
16
|
+
throw :error, "File path #{path} does not exist (also looked for #{ap})"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def gem_path_for(gem_name)
|
22
|
+
Gem.ui.instance_variable_set :"@outs", StringIO.new
|
23
|
+
Gem::GemRunner.new.run(["which", gem_name])
|
24
|
+
Gem.ui.outs.string
|
25
|
+
rescue SystemExit => e
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_file_header(str)
|
30
|
+
"#{Visitor::FILE_HEADER}\n\n#{str}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def src_path_to_output_path(src_path : String) : String
|
34
|
+
src_path.sub("#{Config.src_dir}/", "")
|
35
|
+
.sub(/\.gl$/, ".rb")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/src/lib/gloss/version.gl
CHANGED
@@ -1,35 +1,26 @@
|
|
1
1
|
module Gloss
|
2
|
-
|
3
|
-
module_function
|
4
|
-
|
5
|
-
def with_file_header(str)
|
6
|
-
"#{Builder::FILE_HEADER}\n\n#{str}"
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
class Builder
|
2
|
+
class Visitor
|
11
3
|
FILE_HEADER = <<~RUBY
|
12
4
|
#{"# frozen_string_literal: true\n" if Config.frozen_string_literals}
|
13
5
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
14
6
|
##### See #{Config.src_dir}/ to make changes
|
15
7
|
RUBY
|
16
8
|
|
17
|
-
include Utils
|
18
|
-
|
19
9
|
attr_reader :tree
|
20
10
|
|
21
|
-
def initialize(tree_hash, type_checker = nil)
|
11
|
+
def initialize(tree_hash, type_checker = nil, @on_new_file_referenced = nil)
|
22
12
|
@indent_level = 0
|
23
13
|
@inside_macro = false
|
24
14
|
@eval_vars = false
|
25
15
|
@current_scope = nil
|
26
16
|
@tree = tree_hash
|
27
17
|
@type_checker = type_checker
|
18
|
+
@after_module_function = false
|
28
19
|
end
|
29
20
|
|
30
21
|
def run
|
31
22
|
rb_output = visit_node(@tree)
|
32
|
-
with_file_header(rb_output)
|
23
|
+
Utils.with_file_header(rb_output)
|
33
24
|
end
|
34
25
|
|
35
26
|
# type node = Hash[Symbol, String | Array[String | node] | Hash[Symbol, node]] | true | false
|
@@ -41,18 +32,31 @@ module Gloss
|
|
41
32
|
class_name = visit_node(node[:name])
|
42
33
|
current_namespace = @current_scope ? @current_scope.name.to_namespace : RBS::Namespace.root
|
43
34
|
superclass_type = nil
|
44
|
-
superclass_output =
|
35
|
+
superclass_output = ""
|
45
36
|
if node[:superclass]
|
46
37
|
@eval_vars = true
|
47
38
|
superclass_output = visit_node(node[:superclass])
|
48
39
|
@eval_vars = false
|
49
|
-
|
40
|
+
args = Array.new
|
50
41
|
if node.dig(:superclass, :type) == "Generic"
|
51
|
-
superclass_output = superclass_output[/^[^\[]+/]
|
42
|
+
superclass_output = superclass_output[/^[^\[]+/] || superclass_output
|
43
|
+
args = node.dig(:superclass, :args).map { |n| RBS::Parser.parse_type(visit_node(n)) }
|
52
44
|
end
|
45
|
+
|
46
|
+
class_name_index = superclass_output.index(/[^(?:::)]+\z/) || 0
|
47
|
+
namespace = superclass_output[0, class_name_index]
|
48
|
+
superclass_name = superclass_output[/[^(?:::)]+\z/] || superclass_output
|
49
|
+
superclass_type = RBS::AST::Declarations::Class::Super.new(
|
50
|
+
name: RBS::TypeName.new(
|
51
|
+
namespace: method(:Namespace).call(namespace),
|
52
|
+
name: superclass_name.to_sym,
|
53
|
+
),
|
54
|
+
args: args,
|
55
|
+
location: build_location(node),
|
56
|
+
)
|
53
57
|
end
|
54
58
|
|
55
|
-
src.write_ln "class #{class_name}#{" < #{superclass_output}"
|
59
|
+
src.write_ln "class #{class_name}#{" < #{superclass_output}" unless superclass_output.blank?}"
|
56
60
|
|
57
61
|
class_type = RBS::AST::Declarations::Class.new(
|
58
62
|
name: RBS::TypeName.new(
|
@@ -63,7 +67,7 @@ module Gloss
|
|
63
67
|
super_class: superclass_type,
|
64
68
|
members: Array.new, # TODO
|
65
69
|
annotations: Array.new, # TODO
|
66
|
-
location: node
|
70
|
+
location: build_location(node),
|
67
71
|
comment: node[:comment]
|
68
72
|
)
|
69
73
|
old_parent_scope = @current_scope
|
@@ -77,10 +81,12 @@ module Gloss
|
|
77
81
|
|
78
82
|
@current_scope.members << class_type if @current_scope
|
79
83
|
|
80
|
-
if @type_checker
|
81
|
-
@type_checker.top_level_decls
|
84
|
+
if @type_checker && !@current_scope
|
85
|
+
@type_checker.top_level_decls.add(class_type)
|
82
86
|
end
|
83
87
|
when "ModuleNode"
|
88
|
+
existing_module_function_state = @after_module_function.dup
|
89
|
+
@after_module_function = false
|
84
90
|
module_name = visit_node node[:name]
|
85
91
|
src.write_ln "module #{module_name}"
|
86
92
|
|
@@ -95,7 +101,7 @@ module Gloss
|
|
95
101
|
self_types: Array.new, # TODO
|
96
102
|
members: Array.new, # TODO
|
97
103
|
annotations: Array.new, # TODO
|
98
|
-
location: node
|
104
|
+
location: build_location(node),
|
99
105
|
comment: node[:comment]
|
100
106
|
)
|
101
107
|
old_parent_scope = @current_scope
|
@@ -107,10 +113,11 @@ module Gloss
|
|
107
113
|
|
108
114
|
@current_scope.members << module_type if @current_scope
|
109
115
|
|
110
|
-
if @type_checker
|
111
|
-
@type_checker.top_level_decls
|
116
|
+
if @type_checker && !@current_scope
|
117
|
+
@type_checker.top_level_decls.add(module_type)
|
112
118
|
end
|
113
119
|
src.write_ln "end"
|
120
|
+
@after_module_function = existing_module_function_state
|
114
121
|
when "DefNode"
|
115
122
|
args = render_args(node)
|
116
123
|
receiver = node[:receiver] ? visit_node(node[:receiver]) : nil
|
@@ -123,11 +130,11 @@ module Gloss
|
|
123
130
|
namespace: RBS::Namespace.root
|
124
131
|
),
|
125
132
|
args: EMPTY_ARRAY, # TODO
|
126
|
-
location: node
|
133
|
+
location: build_location(node)
|
127
134
|
)
|
128
135
|
else
|
129
136
|
RBS::Types::Bases::Any.new(
|
130
|
-
location: node
|
137
|
+
location: build_location(node)
|
131
138
|
)
|
132
139
|
end
|
133
140
|
|
@@ -154,19 +161,19 @@ module Gloss
|
|
154
161
|
required_keywords: Hash.new,
|
155
162
|
optional_keywords: Hash.new,
|
156
163
|
rest_keywords: nil,
|
157
|
-
return_type: RBS::Types::Bases::Any.new(location: node
|
164
|
+
return_type: RBS::Types::Bases::Any.new(location: build_location(node))
|
158
165
|
),
|
159
166
|
required: !!(node[:block_arg] || node[:yield_arg_count])
|
160
167
|
) : nil,
|
161
|
-
location: node
|
168
|
+
location: build_location(node)
|
162
169
|
)
|
163
170
|
]
|
164
171
|
method_definition = RBS::AST::Members::MethodDefinition.new(
|
165
172
|
name: node[:name].to_sym,
|
166
|
-
kind: receiver ? :
|
173
|
+
kind: @after_module_function ? :singleton_instance : receiver ? :singleton : :instance,
|
167
174
|
types: method_types,
|
168
175
|
annotations: EMPTY_ARRAY, # TODO
|
169
|
-
location: node
|
176
|
+
location: build_location(node),
|
170
177
|
comment: node[:comment],
|
171
178
|
overload: false
|
172
179
|
)
|
@@ -202,7 +209,14 @@ module Gloss
|
|
202
209
|
else
|
203
210
|
nil
|
204
211
|
end
|
205
|
-
|
212
|
+
name = node[:name]
|
213
|
+
call = "#{obj}#{name}#{opening_delimiter}#{args}#{")" if has_parens}#{block}"
|
214
|
+
case name
|
215
|
+
when "require_relative"
|
216
|
+
@on_new_file_referenced.call(name, true) if @on_new_file_referenced
|
217
|
+
when "module_function"
|
218
|
+
@after_module_function = true
|
219
|
+
end
|
206
220
|
src.write_ln(call)
|
207
221
|
|
208
222
|
when "Block"
|
@@ -247,9 +261,10 @@ module Gloss
|
|
247
261
|
src.write node[:value]
|
248
262
|
|
249
263
|
when "Require"
|
264
|
+
path = node[:value]
|
265
|
+
src.write_ln %(require "#{path}")
|
250
266
|
|
251
|
-
|
252
|
-
|
267
|
+
@on_new_file_referenced.call(path, false) if @on_new_file_referenced
|
253
268
|
when "Assign", "OpAssign"
|
254
269
|
|
255
270
|
src.write_ln "#{visit_node(node[:target])} #{node[:op]}= #{visit_node(node[:value]).strip}"
|
@@ -388,7 +403,8 @@ module Gloss
|
|
388
403
|
src.write "return#{val}"
|
389
404
|
when "TypeDeclaration"
|
390
405
|
src.write_ln "# @type var #{visit_node(node[:var])}: #{visit_node(node[:declared_type])}"
|
391
|
-
|
406
|
+
value = node[:value] ? " = #{visit_node node[:value]}" : nil
|
407
|
+
src.write_ln "#{visit_node(node[:var])}#{value}"
|
392
408
|
when "ExceptionHandler"
|
393
409
|
src.write_ln "begin"
|
394
410
|
indented src do
|
@@ -422,7 +438,7 @@ module Gloss
|
|
422
438
|
name: method(:TypeName).call(name),
|
423
439
|
args: Array.new,
|
424
440
|
annotations: Array.new,
|
425
|
-
location: node
|
441
|
+
location: build_location(node),
|
426
442
|
comment: node[:comment]
|
427
443
|
)
|
428
444
|
if @current_scope
|
@@ -438,7 +454,7 @@ module Gloss
|
|
438
454
|
name: method(:TypeName).call(name),
|
439
455
|
args: Array.new,
|
440
456
|
annotations: Array.new,
|
441
|
-
location: node
|
457
|
+
location: build_location(node),
|
442
458
|
comment: node[:comment]
|
443
459
|
)
|
444
460
|
if @current_scope
|
@@ -510,37 +526,50 @@ module Gloss
|
|
510
526
|
rest_kw ? "**#{visit_node(rest_kw)}" : ""
|
511
527
|
].reject(&:empty?).flatten.join(", ")
|
512
528
|
representation = "(#{contents})"
|
513
|
-
rp.map
|
529
|
+
rp_args = rp.map do |a|
|
514
530
|
RBS::Types::Function::Param.new(
|
515
531
|
name: visit_node(a).to_sym,
|
516
532
|
type: RBS::Types::Bases::Any.new(
|
517
|
-
location: a
|
533
|
+
location: build_location(a)
|
518
534
|
)
|
519
535
|
)
|
520
536
|
end
|
521
|
-
op.map
|
537
|
+
op_args = op.map do |a|
|
522
538
|
RBS::Types::Function::Param.new(
|
523
539
|
name: visit_node(a).to_sym,
|
524
|
-
type: RBS::Types::Bases::Any.new(location: a
|
540
|
+
type: RBS::Types::Bases::Any.new(location: build_location(a))
|
525
541
|
)
|
526
542
|
end
|
527
|
-
|
543
|
+
rpa = rest_p ? RBS::Types::Function::Param.new(
|
544
|
+
name: rest_p.to_sym,
|
545
|
+
type: RBS::Types::Bases::Any.new(location: build_location(node))
|
546
|
+
) : nil
|
528
547
|
{
|
529
548
|
representation: representation,
|
530
549
|
types: {
|
531
|
-
required_positionals:
|
532
|
-
optional_positionals:
|
533
|
-
rest_positionals:
|
550
|
+
required_positionals: rp_args,
|
551
|
+
optional_positionals: op_args,
|
552
|
+
rest_positionals: rpa,
|
534
553
|
trailing_positionals: EMPTY_ARRAY, # TODO
|
535
554
|
required_keywords: node[:req_kw_args] || EMPTY_HASH,
|
536
555
|
optional_keywords: node[:opt_kw_args] || EMPTY_HASH,
|
537
556
|
rest_keywords: node[:rest_kw_args] ?
|
538
557
|
RBS::Types::Function::Param.new(
|
539
558
|
name: visit_node(node[:rest_kw_args]).to_sym,
|
540
|
-
type: RBS::Types::Bases::Any.new(location: node
|
559
|
+
type: RBS::Types::Bases::Any.new(location: build_location(node))
|
541
560
|
) : nil
|
542
561
|
}
|
543
562
|
}
|
544
563
|
end
|
564
|
+
|
565
|
+
def build_location(node)
|
566
|
+
return nil unless node[:location]
|
567
|
+
|
568
|
+
# RBS::Location.new(
|
569
|
+
# buffer: RBS::Buffer.new(@file_path, @file_content),
|
570
|
+
# start_pos: node[:location][:start],
|
571
|
+
# end_pos: node[:location][:end]
|
572
|
+
# )
|
573
|
+
end
|
545
574
|
end
|
546
575
|
end
|
data/src/lib/gloss/watcher.gl
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require "listen"
|
4
2
|
|
5
3
|
module Gloss
|
@@ -7,7 +5,8 @@ module Gloss
|
|
7
5
|
def initialize(@paths : Array[String])
|
8
6
|
if @paths.empty?
|
9
7
|
@paths = [File.join(Dir.pwd, Config.src_dir)]
|
10
|
-
|
8
|
+
# either any filepath with .gl extension, or executable with extension
|
9
|
+
@only = /(?:(\.gl|(?:(?<=\/)[^\.\/]+))\z|\A[^\.\/]+\z)/
|
11
10
|
else
|
12
11
|
file_names = Array.new
|
13
12
|
paths = Array.new
|
@@ -33,7 +32,7 @@ module Gloss
|
|
33
32
|
content = File.read(f)
|
34
33
|
err = catch :error do
|
35
34
|
Writer.new(
|
36
|
-
|
35
|
+
Visitor.new(
|
37
36
|
Parser.new(
|
38
37
|
content
|
39
38
|
).run
|
data/src/lib/gloss/writer.gl
CHANGED
@@ -4,30 +4,32 @@ require "pathname"
|
|
4
4
|
require "fileutils"
|
5
5
|
|
6
6
|
module Gloss
|
7
|
-
module Utils
|
8
|
-
module_function
|
9
|
-
|
10
|
-
def src_path_to_output_path(src_path : String) : String
|
11
|
-
src_path.sub("#{Config.src_dir}/", "")
|
12
|
-
.sub(/\.gl$/, ".rb")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
7
|
class Writer
|
17
|
-
include Utils
|
18
|
-
|
19
8
|
def initialize(
|
20
9
|
@content,
|
21
|
-
src_path : String,
|
22
|
-
@output_path : Pathname? = Pathname.new(
|
10
|
+
@src_path : String,
|
11
|
+
@output_path : Pathname? = Pathname.new(
|
12
|
+
Utils.src_path_to_output_path(src_path)
|
13
|
+
)
|
23
14
|
)
|
24
15
|
end
|
25
16
|
|
26
17
|
def run
|
27
18
|
FileUtils.mkdir_p(@output_path.parent) unless @output_path.parent.exist?
|
28
19
|
File.open(@output_path, "wb") do |file|
|
20
|
+
sb = shebang
|
21
|
+
file.puts sb if sb
|
29
22
|
file.puts @content
|
30
23
|
end
|
31
24
|
end
|
25
|
+
|
26
|
+
private def shebang
|
27
|
+
if @output_path.executable?
|
28
|
+
first_line = File.open(@src_path) { |f| f.readline }
|
29
|
+
first_line.start_with?("#!") ? first_line : nil
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gloss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- johansenja
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-02-
|
11
|
+
date: 2021-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fast_blank
|
@@ -159,32 +159,43 @@ files:
|
|
159
159
|
- ext/gloss/src/rb_ast.cr
|
160
160
|
- gloss.gemspec
|
161
161
|
- lib/gloss.rb
|
162
|
-
- lib/gloss/builder.rb
|
163
162
|
- lib/gloss/cli.rb
|
164
163
|
- lib/gloss/config.rb
|
165
164
|
- lib/gloss/errors.rb
|
166
165
|
- lib/gloss/initializer.rb
|
167
166
|
- lib/gloss/logger.rb
|
168
167
|
- lib/gloss/parser.rb
|
168
|
+
- lib/gloss/prog_loader.rb
|
169
169
|
- lib/gloss/scope.rb
|
170
170
|
- lib/gloss/source.rb
|
171
171
|
- lib/gloss/type_checker.rb
|
172
|
+
- lib/gloss/utils.rb
|
172
173
|
- lib/gloss/version.rb
|
174
|
+
- lib/gloss/visitor.rb
|
173
175
|
- lib/gloss/watcher.rb
|
174
176
|
- lib/gloss/writer.rb
|
175
|
-
- sig/
|
177
|
+
- sig/core.rbs
|
178
|
+
- sig/fast_blank.rbs
|
179
|
+
- sig/gls.rbs
|
176
180
|
- sig/listen.rbs
|
177
|
-
-
|
181
|
+
- sig/optparse.rbs
|
182
|
+
- sig/rubygems.rbs
|
183
|
+
- sig/yaml.rbs
|
184
|
+
- src/exe/gloss
|
185
|
+
- src/lib/gloss.gl
|
178
186
|
- src/lib/gloss/cli.gl
|
179
187
|
- src/lib/gloss/config.gl
|
180
188
|
- src/lib/gloss/errors.gl
|
181
189
|
- src/lib/gloss/initializer.gl
|
182
190
|
- src/lib/gloss/logger.gl
|
183
191
|
- src/lib/gloss/parser.gl
|
192
|
+
- src/lib/gloss/prog_loader.gl
|
184
193
|
- src/lib/gloss/scope.gl
|
185
194
|
- src/lib/gloss/source.gl
|
186
195
|
- src/lib/gloss/type_checker.gl
|
196
|
+
- src/lib/gloss/utils.gl
|
187
197
|
- src/lib/gloss/version.gl
|
198
|
+
- src/lib/gloss/visitor.gl
|
188
199
|
- src/lib/gloss/watcher.gl
|
189
200
|
- src/lib/gloss/writer.gl
|
190
201
|
homepage:
|