gloss 0.1.5 → 0.1.6

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 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