gloss 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: