gloss 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 622926d0bd44e5bd9b93cfa75ea54dc67d976a63c91a5a60f17c859987ee2fce
4
- data.tar.gz: 789917be6b264be0108cb03371b797c4ebc865e01fcb7218589808ccd68bdf83
3
+ metadata.gz: 9239f0e7898094d7957a2e1eae3b980ff57f94be27eea836f00561262eb8f8d4
4
+ data.tar.gz: 0ffa974e3146f699a9280878a412f589005cc4723f262c377a215aacd5cae146
5
5
  SHA512:
6
- metadata.gz: c5fe3cf7f37aa5eec834b806c1f80083dde5be4b15000f18ae4807cb0d2ee5e3f378eaa271ffe3cb4d61b58feb98c3ac0586ab65da5ef2bb3df5dad1e4a02b2e
7
- data.tar.gz: b2f55defed2e6ba5d3dec55dd7b6795a3f3ff54fa1e94532bc0bda6d91f099200d5ec40926c6c3b001a27809477016bdd8a59d24a6472419b0958647df6b5c00
6
+ metadata.gz: 97ef28c0abd86a51f35224661765950f9aab162cb119f7a0d2b05e3d985464f25c58546b0c191cd69fc537a1b921c22ebd8d7c2d4bd446257d17e9b6a454c346
7
+ data.tar.gz: a9c9b94fbe5ec96b3be1a5c67d5149219d0e138ef7081190c133676c784865fb90d3c1b86b250b0eb207d890c67120a86f27763c5de105baadf550bc158a464f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gloss (0.1.5)
4
+ gloss (0.1.6)
5
5
  fast_blank
6
6
  listen
7
7
  rbs (= 1.0.4)
@@ -10,7 +10,7 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activesupport (6.1.3)
13
+ activesupport (6.1.3.1)
14
14
  concurrent-ruby (~> 1.0, >= 1.0.2)
15
15
  i18n (>= 1.6, < 2)
16
16
  minitest (>= 5.1)
@@ -27,8 +27,8 @@ GEM
27
27
  ffi (1.15.0)
28
28
  i18n (1.8.9)
29
29
  concurrent-ruby (~> 1.0)
30
- language_server-protocol (3.15.0.1)
31
- listen (3.4.1)
30
+ language_server-protocol (3.15.0.2)
31
+ listen (3.5.0)
32
32
  rb-fsevent (~> 0.10, >= 0.10.3)
33
33
  rb-inotify (~> 0.9, >= 0.9.10)
34
34
  method_source (1.0.0)
data/README.md CHANGED
@@ -4,8 +4,7 @@
4
4
  [![Total Downloads](http://ruby-gem-downloads-badge.herokuapp.com/gloss?type=total&color=green&label=downloads%20(total)&total_label=)](https://rubygems.org/gems/gloss)
5
5
  [![Current Version](http://ruby-gem-downloads-badge.herokuapp.com/gloss?color=green&label=downloads%20(current%20version)&metric=true)](https://rubygems.org/gems/gloss)
6
6
 
7
- [Gloss](https://en.wikipedia.org/wiki/Gloss_(annotation)) is a high-level programming language based on [Ruby](https://github.com/ruby/ruby) and [Crystal](https://github.com/crystal-lang/crystal), which compiles to ruby; its aims are on transparency,
8
- efficiency, and to enhance ruby's goal of developer happiness and productivity.
7
+ [Gloss](https://en.wikipedia.org/wiki/Gloss_(annotation)) is a language project inspired by [Crystal](https://github.com/crystal-lang/crystal), Ruby's [RBS](https://github.com/ruby/rbs), [Steep](https://github.com/soutaro/steep) and [TypeScript](https://github.com/microsoft/TypeScript). It compiles to pure Ruby.
9
8
 
10
9
  ### Current features
11
10
 
@@ -20,23 +19,6 @@ efficiency, and to enhance ruby's goal of developer happiness and productivity.
20
19
 
21
20
  This project is at a stage where the core non-crystal parts are written in Gloss and compile to ruby (essentially self-hosting), albeit with the type checking being fairly loose. However the project is still in the very early stages; with (as of yet) no Linux support nor error handling (see roadmap below). Use at your own discretion!
22
21
 
23
- ### Approx. roadmap:
24
-
25
- - Improve error handling and logging (currently almost non-existant)
26
- - Address Linux compatibility (currently more or less non-existant)
27
- - Implement different strictnesses of type checking
28
- - Metaprogramming helpers/safety:*
29
- - Abstract classes and methods
30
- - Method lookup/existence checking at compile time
31
- - Method overloading
32
-
33
- #### Related items:
34
-
35
- - Rails helpers; probably some time away*
36
- - Editor plugins/syntax highlighting/langserver; probably some time away*
37
-
38
- *__Dependent on popularity__
39
-
40
22
  ## Examples:
41
23
 
42
24
  #### Type checking:
@@ -225,7 +207,14 @@ BaseClass.new(123) # Error - can't instantiate abstract class
225
207
  Child.new(123).what_is_var # Ok - "var is 123"
226
208
  ```
227
209
 
228
- ## Usage:
210
+ ## Getting started:
211
+
212
+ **Note: This gem currently requires Crystal to be installed. If you don't wish to install it, or run into other installation problems, consider using the Docker image:**
213
+
214
+ ```dockerfile
215
+ FROM johansenja/gloss:latest
216
+ # ...
217
+ ```
229
218
 
230
219
  ```ruby
231
220
  # Gemfile
@@ -248,8 +237,18 @@ then
248
237
 
249
238
  then
250
239
 
240
+ `vi .gloss.yml # set entrypoint to src/hello_world.gl`
241
+
242
+ then
243
+
251
244
  `gloss build`
252
245
 
253
246
  then
254
247
 
255
248
  `ruby ./hello_world.rb`
249
+
250
+ ## Example Projects:
251
+
252
+ - This one! Gloss is mostly self-hosting, so check out the `./src` and `./.gloss.yml`, or the generated output in `./lib`
253
+ - [onefiveone](https://github.com/johansenja/onefiveone) - A Roman Numeral CLI. Read the accompanying article [here](https://johansenja.medium.com/ruby-crystal-pt-ii-a-simple-app-using-gloss-368ff849db67)
254
+ - More to come (including web apps)! Also check out `Used by` section in the sidebar
data/lib/gloss.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "rbs"
7
6
  require "json"
@@ -22,6 +21,7 @@ require "gloss/errors"
22
21
  require "gloss/logger"
23
22
  require "gloss/prog_loader"
24
23
  require "gloss/utils"
24
+ require "gloss/runtime"
25
25
  require "gls"
26
26
  EMPTY_ARRAY = Array.new
27
27
  .freeze
data/lib/gloss/cli.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "optparse"
7
6
  module Gloss
@@ -27,6 +26,7 @@ case command
27
26
  when "version", "--version", "-v"
28
27
  puts(Gloss::VERSION)
29
28
  when "watch", "build"
29
+ Gloss.load_config
30
30
  type_checker = ProgLoader.new
31
31
  .run
32
32
  (if command.==("watch")
data/lib/gloss/config.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "ostruct"
7
6
  require "yaml"
@@ -11,7 +10,7 @@ module Gloss
11
10
  :src_dir => "src",
12
11
  :entrypoint => nil,
13
12
  :strict_require => false,
14
- :type_checking_strictness => "strict",
13
+ :type_checking_strictness => "lenient",
15
14
  :prettify_output_executable_path => nil}.freeze)
16
15
  def self.load_config()
17
16
  user_config = (if File.exist?(File.absolute_path(File.join(Dir.pwd, CONFIG_PATH)))
@@ -24,5 +23,4 @@ module Gloss
24
23
  Config.send(:"#{k}=", user_config.[](k.to_s) || v)
25
24
  }
26
25
  end
27
- load_config
28
26
  end
data/lib/gloss/errors.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  module Errors
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "yaml"
7
6
  module Gloss
data/lib/gloss/logger.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  def self.logger()
data/lib/gloss/parser.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Parser
@@ -1,33 +1,42 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "rubygems/gem_runner"
7
6
  module Gloss
8
7
  OUTPUT_BY_PATH = Hash.new
9
8
  class ProgLoader
10
9
  attr_reader(:"type_checker")
11
- def initialize()
12
- entrypoint = Config.entrypoint
13
- (if entrypoint.==(nil) || entrypoint.==("")
10
+ def initialize(entrypoint_path = nil, entrypoint_contents = nil)
11
+ entrypoint_path ||= Config.entrypoint
12
+ (if entrypoint_path.==(nil) || entrypoint_path.==("")
14
13
  throw(:"error", "Entrypoint is not yet set in .gloss.yml")
15
14
  end)
16
- @files_to_process = [Utils.absolute_path(Config.entrypoint), Utils.absolute_path(File.join(__dir__ || "", "..", "..", "sig", "core.rbs"))]
15
+ entrypoint = (if entrypoint_path && entrypoint_contents
16
+ ep = (if entrypoint_path.==(Runtime::NON_EXISTENT_FILEPATH)
17
+ entrypoint_path
18
+ else
19
+ Utils.absolute_path(entrypoint_path)
20
+ end)
21
+ [ep, entrypoint_contents]
22
+ else
23
+ Utils.abs_path_with_contents(entrypoint_path)
24
+ end)
25
+ core_types = Utils.abs_path_with_contents(File.join(__dir__ || "", "..", "..", "sig", "core.rbs"))
26
+ @files_to_process = [entrypoint, core_types]
17
27
  @processed_files = Set.new
18
28
  @type_checker = TypeChecker.new
19
29
  end
20
30
  def run()
21
- @files_to_process.each() { |path_string|
31
+ @files_to_process.each() { |__arg0|
32
+ path_string = __arg0.[](0)
33
+ file_contents = __arg0.[](1)
22
34
  (if path_string.end_with?(".rbs")
23
35
  @type_checker.load_sig_path(path_string)
24
36
  else
25
37
  (if !@processed_files.member?(path_string) || !OUTPUT_BY_PATH.[](path_string)
26
38
  Gloss.logger
27
39
  .debug("Loading #{path_string}")
28
- path = Utils.absolute_path(path_string)
29
- file_contents = File.open(path)
30
- .read
31
40
  contents_tree = Parser.new(file_contents)
32
41
  .run
33
42
  on_new_file_referenced = proc() { |ps, relative|
@@ -55,14 +64,14 @@ module Gloss
55
64
  base = File.join(Dir.pwd, path)
56
65
  fp = base.+(".gl")
57
66
  (if File.exist?(fp)
58
- @files_to_process.<<(fp)
67
+ @files_to_process.<<(Utils.abs_path_with_contents(fp))
59
68
  end)
60
69
  return
61
70
  end)
62
71
  full = File.absolute_path("#{File.join(Config.src_dir, "lib", path)}.gl")
63
72
  pathn = Pathname.new(full)
64
73
  (if pathn.file?
65
- @files_to_process.<<(pathn.to_s)
74
+ @files_to_process.<<(Utils.abs_path_with_contents(pathn.to_s))
66
75
  else
67
76
  pathn = Pathname.new("#{File.join(Dir.pwd, "sig", path)}.rbs")
68
77
  gem_path = Utils.gem_path_for(path)
@@ -122,8 +131,11 @@ nil }
122
131
  end)
123
132
  }
124
133
  (if pn
125
- unless @files_to_process.include?(pn)
126
- @files_to_process.<<(pn)
134
+ unless @files_to_process.any?() { |__arg1|
135
+ fp = __arg1.[](0)
136
+ fp.==(pn)
137
+ }
138
+ @files_to_process.<<(Utils.abs_path_with_contents(pn))
127
139
  end
128
140
  else
129
141
  (if Config.strict_require
@@ -0,0 +1,25 @@
1
+
2
+ ##### This file was generated by Gloss; any changes made here will be overwritten.
3
+ ##### See / to make changes
4
+
5
+ require "stringio"
6
+ module Gloss
7
+ class Runtime
8
+ NON_EXISTENT_FILEPATH = "__string__"
9
+ def self.process_string(str, options = Config.default_config)
10
+ out_io = StringIO.new
11
+ error_msg = catch(:"error") { ||
12
+ tree = Parser.new(str)
13
+ .run
14
+ tc = ProgLoader.new(NON_EXISTENT_FILEPATH, str)
15
+ .run
16
+ rb_output = Visitor.new(tree, tc)
17
+ .run
18
+ tc.run(NON_EXISTENT_FILEPATH, rb_output)
19
+ Writer.new(rb_output, NON_EXISTENT_FILEPATH, out_io)
20
+ .run
21
+ nil }
22
+ return [out_io.string, error_msg].freeze
23
+ end
24
+ end
25
+ end
data/lib/gloss/scope.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Scope < Hash
data/lib/gloss/source.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Source < String
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "set"
7
6
  module Gloss
data/lib/gloss/utils.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "rubygems"
7
6
  module Gloss
@@ -34,5 +33,10 @@ module Gloss
34
33
  src_path.sub("#{Config.src_dir}/", "")
35
34
  .sub(/\.gl$/, ".rb")
36
35
  end
36
+ def abs_path_with_contents(path)
37
+ abs_path = absolute_path(path)
38
+ return [abs_path, File.open(abs_path)
39
+ .read].freeze
40
+ end
37
41
  end
38
42
  end
data/lib/gloss/version.rb CHANGED
@@ -1,8 +1,7 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
- VERSION = "0.1.5"
6
+ VERSION = "0.1.6"
8
7
  end
data/lib/gloss/visitor.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  module Gloss
7
6
  class Visitor
@@ -123,7 +122,7 @@ case node.[](:"type")
123
122
  else
124
123
  RBS::Types::Bases::Any.new(location: build_location(node))
125
124
  end)
126
- method_types = [RBS::MethodType.new(type_params: EMPTY_ARRAY, type: RBS::Types::Function.new(required_positionals: args.dig(:"types", :"required_positionals"), optional_positionals: args.dig(:"types", :"optional_positionals"), rest_positionals: args.dig(:"types", :"rest_positionals"), trailing_positionals: args.dig(:"types", :"trailing_positionals"), required_keywords: args.dig(:"types", :"required_keywords"), optional_keywords: args.dig(:"types", :"optional_keywords"), rest_keywords: args.dig(:"types", :"rest_keywords"), return_type: return_type), block: (if node.[](:"yield_arg_count")
125
+ method_types = [RBS::MethodType.new(type_params: EMPTY_ARRAY, type: RBS::Types::Function.new(required_positionals: args.dig(:"types", :"required_positionals"), optional_positionals: args.dig(:"types", :"optional_positionals"), rest_positionals: args.dig(:"types", :"rest_positionals"), trailing_positionals: args.dig(:"types", :"trailing_positionals"), required_keywords: args.dig(:"types", :"required_keywords"), optional_keywords: args.dig(:"types", :"optional_keywords"), rest_keywords: args.dig(:"types", :"rest_keywords"), return_type: return_type), block: (if node.[](:"yield_arg_count") || args.dig(:"types", :"block_arg")
127
126
  RBS::Types::Block.new(type: RBS::Types::Function.new(required_positionals: Array.new, optional_positionals: Array.new, rest_positionals: nil, trailing_positionals: Array.new, required_keywords: Hash.new, optional_keywords: Hash.new, rest_keywords: nil, return_type: RBS::Types::Bases::Any.new(location: build_location(node))), required: !!node.[](:"block_arg") || node.[](:"yield_arg_count"))
128
127
  else
129
128
  nil
@@ -616,7 +615,9 @@ EMPTY_HASH }
616
615
  end)
617
616
  # @type var rest_kw: Hash[Symbol, Any]?
618
617
  rest_kw = node.[](:"rest_kw_args")
619
- (if [rp, op, rkw, okw, rest_p, rest_kw].all?() { |a|
618
+ # @type var block_arg: Hash[Symbol, Any]?
619
+ block_arg = node.[](:"block_arg")
620
+ (if [rp, op, rkw, okw, rest_p, rest_kw, block_arg].all?() { |a|
620
621
  a && a.empty? }
621
622
  return nil
622
623
  end)
@@ -634,6 +635,10 @@ a && a.empty? }
634
635
  "**#{visit_node(rest_kw)}"
635
636
  else
636
637
  ""
638
+ end), (if block_arg
639
+ "&#{visit_node(block_arg)}"
640
+ else
641
+ ""
637
642
  end)].reject(&:"empty?")
638
643
  .flatten
639
644
  .join(", ")
@@ -658,6 +663,7 @@ a && a.empty? }
658
663
  :trailing_positionals => EMPTY_ARRAY,
659
664
  :required_keywords => node.[](:"req_kw_args") || EMPTY_HASH,
660
665
  :optional_keywords => node.[](:"opt_kw_args") || EMPTY_HASH,
666
+ :block_arg => true,
661
667
  :rest_keywords => (if node.[](:"rest_kw_args")
662
668
  RBS::Types::Function::Param.new(name: visit_node(node.[](:"rest_kw_args"))
663
669
  .to_sym, type: RBS::Types::Bases::Any.new(location: build_location(node)))
data/lib/gloss/watcher.rb CHANGED
@@ -1,7 +1,6 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "listen"
7
6
  module Gloss
data/lib/gloss/writer.rb CHANGED
@@ -1,46 +1,59 @@
1
- # frozen_string_literal: true
2
-
1
+
3
2
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
- ##### See src/ to make changes
3
+ ##### See / to make changes
5
4
 
6
5
  require "pathname"
7
6
  require "fileutils"
8
7
  module Gloss
9
8
  class Writer
10
- def initialize(content, src_path, output_path = Pathname.new(Utils.src_path_to_output_path(src_path)))
9
+ def initialize(content, src_path, output = nil)
11
10
  @content = content
12
11
  @src_path = src_path
13
- @output_path = output_path
12
+ @output = output
14
13
  end
15
14
  def run()
16
- unless @output_path.parent
17
- .exist?
18
- FileUtils.mkdir_p(@output_path.parent)
19
- end
20
- File.open(@output_path, "wb") { |file|
15
+ write_to_output() { |otpt|
21
16
  sb = shebang
22
17
  (if sb
23
- file.puts(sb)
18
+ otpt.puts(sb)
24
19
  end)
25
- file.puts(@content)
20
+ otpt.puts(@content)
26
21
  }
27
- (if Config.prettify_output_executable_path
28
- system(Config.prettify_output_executable_path, @output_path.to_s)
29
- end)
30
22
  end
31
23
  private def shebang()
32
- (if @output_path.executable?
33
- first_line = File.open(@src_path) { |f|
34
- f.readline
35
- }
36
- (if first_line.start_with?("#!")
37
- first_line
24
+ case @output
25
+ when Pathname
26
+ (if @output.executable?
27
+ first_line = File.open(@src_path) { |f|
28
+ f.readline
29
+ }
30
+ (if first_line.start_with?("#!")
31
+ first_line
32
+ else
33
+ nil
34
+ end)
35
+ end)
38
36
  else
39
37
  nil
40
- end)
41
- else
42
- nil
43
- end)
38
+ end
39
+ end
40
+ private def write_to_output(&blk)
41
+ case @output
42
+ when IO, StringIO
43
+ yield(@output)
44
+ else
45
+ output = @output || Pathname.new(Utils.src_path_to_output_path(@src_path))
46
+ unless output.parent
47
+ .exist?
48
+ FileUtils.mkdir_p(output.parent)
49
+ end
50
+ File.open(output, "wb") { |file|
51
+ yield(file)
52
+ }
53
+ (if Config.prettify_output_executable_path
54
+ system(Config.prettify_output_executable_path, @output.to_s)
55
+ end)
56
+ end
44
57
  end
45
58
  end
46
59
  end
data/src/lib/gloss.gl CHANGED
@@ -18,6 +18,7 @@ require "gloss/errors"
18
18
  require "gloss/logger"
19
19
  require "gloss/prog_loader"
20
20
  require "gloss/utils"
21
+ require "gloss/runtime"
21
22
 
22
23
  require "gls"
23
24
 
data/src/lib/gloss/cli.gl CHANGED
@@ -21,6 +21,7 @@ module Gloss
21
21
  when "version", "--version", "-v"
22
22
  puts Gloss::VERSION
23
23
  when "watch", "build"
24
+ Gloss.load_config
24
25
  type_checker = ProgLoader.new.run
25
26
  if command == "watch"
26
27
  files = files.map do |f|
@@ -9,7 +9,7 @@ module Gloss
9
9
  src_dir: "src",
10
10
  entrypoint: nil,
11
11
  strict_require: false,
12
- type_checking_strictness: "strict",
12
+ type_checking_strictness: "lenient",
13
13
  prettify_output_executable_path: nil
14
14
  }
15
15
  )
@@ -22,6 +22,4 @@ module Gloss
22
22
  end
23
23
  Config.default_config.each { |k, v| Config.send(:"#{k}=", user_config[k.to_s] || v) }
24
24
  end
25
-
26
- load_config
27
25
  end
@@ -6,29 +6,31 @@ module Gloss
6
6
  class ProgLoader
7
7
  attr_reader :type_checker
8
8
 
9
- def initialize
10
- entrypoint = Config.entrypoint
11
- if entrypoint == nil || entrypoint == ""
9
+ def initialize(entrypoint_path = nil, entrypoint_contents = nil)
10
+ entrypoint_path ||= Config.entrypoint
11
+ if entrypoint_path == nil || entrypoint_path == ""
12
12
  throw :error, "Entrypoint is not yet set in .gloss.yml"
13
13
  end
14
- @files_to_process = [
15
- Utils.absolute_path(Config.entrypoint),
16
- # __dir__ is typed as String? - but it shouldn't be nil here
17
- Utils.absolute_path(File.join((__dir__||""), "..", "..", "sig", "core.rbs"))
18
- ]
14
+ entrypoint = if entrypoint_path && entrypoint_contents
15
+ ep = entrypoint_path == Runtime::NON_EXISTENT_FILEPATH ? entrypoint_path : Utils.absolute_path(entrypoint_path)
16
+ [ep, entrypoint_contents]
17
+ else
18
+ Utils.abs_path_with_contents(entrypoint_path)
19
+ end
20
+ # __dir__ is typed as String? - but it shouldn't be nil here
21
+ core_types = Utils.abs_path_with_contents(File.join((__dir__||""), "..", "..", "sig", "core.rbs"))
22
+ @files_to_process = [entrypoint, core_types]
19
23
  @processed_files = Set.new
20
24
  @type_checker = TypeChecker.new
21
25
  end
22
26
 
23
27
  def run
24
- @files_to_process.each do |path_string|
28
+ @files_to_process.each do |(path_string, file_contents)|
25
29
  # currently steep would give an `unexpected jump` if next was used
26
30
  if path_string.end_with? ".rbs"
27
31
  @type_checker.load_sig_path path_string
28
32
  elsif !@processed_files.member?(path_string) || !OUTPUT_BY_PATH.[](path_string)
29
33
  Gloss.logger.debug "Loading #{path_string}"
30
- path = Utils.absolute_path(path_string)
31
- file_contents = File.open(path).read
32
34
  contents_tree = Parser.new(file_contents).run
33
35
  on_new_file_referenced = proc do |ps, relative|
34
36
  ps.each do |pa|
@@ -58,7 +60,7 @@ module Gloss
58
60
  base = File.join(Dir.pwd, path)
59
61
  fp = base + ".gl"
60
62
  if File.exist? fp
61
- @files_to_process << fp
63
+ @files_to_process << Utils.abs_path_with_contents(fp)
62
64
  end
63
65
  return
64
66
  end
@@ -67,7 +69,7 @@ module Gloss
67
69
  full = File.absolute_path("#{File.join(Config.src_dir, "lib", path)}.gl")
68
70
  pathn = Pathname.new full
69
71
  if pathn.file?
70
- @files_to_process << pathn.to_s
72
+ @files_to_process << Utils.abs_path_with_contents(pathn.to_s)
71
73
  else
72
74
  # no .gl file available - .rbs file available?
73
75
  # TODO: verify file is still actually requireable
@@ -118,7 +120,9 @@ module Gloss
118
120
  end
119
121
 
120
122
  if pn
121
- @files_to_process << pn unless @files_to_process.include? pn
123
+ unless @files_to_process.any? { |(fp, _)| fp == pn }
124
+ @files_to_process << Utils.abs_path_with_contents(pn)
125
+ end
122
126
  elsif Config.strict_require
123
127
  throw :error, "Cannot resolve relative path for #{path}"
124
128
  else
@@ -0,0 +1,20 @@
1
+ require "stringio"
2
+
3
+ module Gloss
4
+ class Runtime
5
+ NON_EXISTENT_FILEPATH = "__string__"
6
+
7
+ def self.process_string(str : String, options = Config.default_config)
8
+ out_io = StringIO.new
9
+ error_msg = catch :error do
10
+ tree = Parser.new(str).run
11
+ tc = ProgLoader.new(NON_EXISTENT_FILEPATH, str).run
12
+ rb_output = Visitor.new(tree, tc).run
13
+ tc.run(NON_EXISTENT_FILEPATH, rb_output)
14
+ Writer.new(rb_output, NON_EXISTENT_FILEPATH, out_io).run
15
+ nil
16
+ end
17
+ return out_io.string, error_msg
18
+ end
19
+ end
20
+ end
@@ -31,5 +31,10 @@ module Gloss
31
31
  src_path.sub("#{Config.src_dir}/", "")
32
32
  .sub(/\.gl$/, ".rb")
33
33
  end
34
+
35
+ def abs_path_with_contents(path)
36
+ abs_path = absolute_path(path)
37
+ return abs_path, File.open(abs_path).read
38
+ end
34
39
  end
35
40
  end
@@ -1,3 +1,3 @@
1
1
  module Gloss
2
- VERSION = "0.1.5"
2
+ VERSION = "0.1.6"
3
3
  end
@@ -151,7 +151,7 @@ module Gloss
151
151
  rest_keywords: args.dig(:types, :rest_keywords),
152
152
  return_type: return_type
153
153
  ),
154
- block: node[:yield_arg_count] ?
154
+ block: node[:yield_arg_count] || args.dig(:types, :block_arg) ?
155
155
  RBS::Types::Block.new(
156
156
  type: RBS::Types::Function.new(
157
157
  required_positionals: Array.new,
@@ -523,7 +523,8 @@ module Gloss
523
523
  okw : Hash[Symbol, Any] = node.fetch(:opt_kw_args) { EMPTY_HASH }
524
524
  rest_p : String? = node[:rest_p_args] ? visit_node(node[:rest_p_args]) : nil
525
525
  rest_kw : Hash[Symbol, Any]? = node[:rest_kw_args]
526
- return nil if [rp, op, rkw, okw, rest_p, rest_kw].all? { |a| a && a.empty? }
526
+ block_arg : Hash[Symbol, Any]? = node[:block_arg]
527
+ return nil if [rp, op, rkw, okw, rest_p, rest_kw, block_arg].all? { |a| a && a.empty? }
527
528
 
528
529
  contents = [
529
530
  rp.map { |a| visit_node(a) },
@@ -531,7 +532,8 @@ module Gloss
531
532
  rkw.map { |name, _| "#{name}:" },
532
533
  okw.map { |name, value| "#{name}: #{value}" },
533
534
  rest_p ? "*#{rest_p}" : "",
534
- rest_kw ? "**#{visit_node(rest_kw)}" : ""
535
+ rest_kw ? "**#{visit_node(rest_kw)}" : "",
536
+ block_arg ? "&#{visit_node(block_arg)}" : ""
535
537
  ].reject(&:empty?).flatten.join(", ")
536
538
  representation = "(#{contents})"
537
539
  rp_args = rp.map do |a|
@@ -561,6 +563,7 @@ module Gloss
561
563
  trailing_positionals: EMPTY_ARRAY, # TODO
562
564
  required_keywords: node[:req_kw_args] || EMPTY_HASH,
563
565
  optional_keywords: node[:opt_kw_args] || EMPTY_HASH,
566
+ block_arg: true,
564
567
  rest_keywords: node[:rest_kw_args] ?
565
568
  RBS::Types::Function::Param.new(
566
569
  name: visit_node(node[:rest_kw_args]).to_sym,
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  require "pathname"
4
2
  require "fileutils"
5
3
 
@@ -8,31 +6,46 @@ module Gloss
8
6
  def initialize(
9
7
  @content,
10
8
  @src_path : String,
11
- @output_path : Pathname? = Pathname.new(
12
- Utils.src_path_to_output_path(src_path)
13
- )
9
+ @output : Pathname | IO | NilClass = nil
14
10
  )
15
11
  end
16
12
 
17
13
  def run
18
- FileUtils.mkdir_p(@output_path.parent) unless @output_path.parent.exist?
19
- File.open(@output_path, "wb") do |file|
14
+ write_to_output do |otpt|
20
15
  sb = shebang
21
- file.puts sb if sb
22
- file.puts @content
23
- end
24
- if Config.prettify_output_executable_path
25
- system Config.prettify_output_executable_path, @output_path.to_s
16
+ otpt.puts sb if sb
17
+ otpt.puts @content
26
18
  end
27
19
  end
28
20
 
29
21
  private def shebang
30
- if @output_path.executable?
31
- first_line = File.open(@src_path) { |f| f.readline }
32
- first_line.start_with?("#!") ? first_line : nil
22
+ case @output
23
+ when Pathname
24
+ if @output.executable?
25
+ first_line = File.open(@src_path) { |f| f.readline }
26
+ first_line.start_with?("#!") ? first_line : nil
27
+ end
33
28
  else
34
29
  nil
35
30
  end
36
31
  end
32
+
33
+ private def write_to_output(&blk)
34
+ case @output
35
+ when IO, StringIO
36
+ # blk.call(@output)
37
+ yield @output
38
+ else
39
+ output = @output || Pathname.new(Utils.src_path_to_output_path(@src_path))
40
+ FileUtils.mkdir_p(output.parent) unless output.parent.exist?
41
+ File.open(output, "wb") do |file|
42
+ # blk.call(file)
43
+ yield file
44
+ end
45
+ if Config.prettify_output_executable_path
46
+ system Config.prettify_output_executable_path, @output.to_s
47
+ end
48
+ end
49
+ end
37
50
  end
38
51
  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.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - johansenja
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-13 00:00:00.000000000 Z
11
+ date: 2021-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fast_blank
@@ -179,6 +179,7 @@ files:
179
179
  - lib/gloss/logger.rb
180
180
  - lib/gloss/parser.rb
181
181
  - lib/gloss/prog_loader.rb
182
+ - lib/gloss/runtime.rb
182
183
  - lib/gloss/scope.rb
183
184
  - lib/gloss/source.rb
184
185
  - lib/gloss/type_checker.rb
@@ -204,6 +205,7 @@ files:
204
205
  - src/lib/gloss/logger.gl
205
206
  - src/lib/gloss/parser.gl
206
207
  - src/lib/gloss/prog_loader.gl
208
+ - src/lib/gloss/runtime.gl
207
209
  - src/lib/gloss/scope.gl
208
210
  - src/lib/gloss/source.gl
209
211
  - src/lib/gloss/type_checker.gl
@@ -231,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
233
  - !ruby/object:Gem::Version
232
234
  version: '0'
233
235
  requirements: []
234
- rubygems_version: 3.2.3
236
+ rubygems_version: 3.1.2
235
237
  signing_key:
236
238
  specification_version: 4
237
239
  summary: A superset of ruby