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.
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Gloss
2
- VERSION = "0.0.6"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -1,35 +1,26 @@
1
1
  module Gloss
2
- module Utils
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 = nil
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
- superclass_type = RBS::Parser.parse_type superclass_output
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}" if 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[:location],
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[class_type.name.name] = class_type unless @current_scope
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[:location],
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[module_type.name.name] = module_type unless @current_scope
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[:location]
133
+ location: build_location(node)
127
134
  )
128
135
  else
129
136
  RBS::Types::Bases::Any.new(
130
- location: node[:location]
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[:location])
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[:location]
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 ? :class : :instance,
173
+ kind: @after_module_function ? :singleton_instance : receiver ? :singleton : :instance,
167
174
  types: method_types,
168
175
  annotations: EMPTY_ARRAY, # TODO
169
- location: node[:location],
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
- call = "#{obj}#{node[:name]}#{opening_delimiter}#{args}#{")" if has_parens}#{block}"
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
- src.write_ln %(require "#{node[:value]}")
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
- src.write_ln "#{visit_node(node[:var])} = #{visit_node(node[:value])}"
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[:location],
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[:location],
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! do |a|
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[:location]
533
+ location: build_location(a)
518
534
  )
519
535
  )
520
536
  end
521
- op.map! do |a|
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[:location])
540
+ type: RBS::Types::Bases::Any.new(location: build_location(a))
525
541
  )
526
542
  end
527
- rest_p = (rpa = node[:rest_p_args]) ? RBS::Types::Function::Param.new(name: visit_node(rpa).to_sym, type: RBS::Types::Bases::Any.new(location: node[:location])) : nil
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: rp,
532
- optional_positionals: op,
533
- rest_positionals: rest_p,
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[:location])
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
@@ -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
- @only = /\.gl$/
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
- Builder.new(
35
+ Visitor.new(
37
36
  Parser.new(
38
37
  content
39
38
  ).run
@@ -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(src_path_to_output_path(src_path))
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.6
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-07 00:00:00.000000000 Z
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/gloss.rbs
177
+ - sig/core.rbs
178
+ - sig/fast_blank.rbs
179
+ - sig/gls.rbs
176
180
  - sig/listen.rbs
177
- - src/lib/gloss/builder.gl
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: