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 +4 -4
- data/Gemfile.lock +4 -4
- data/README.md +19 -20
- data/lib/gloss.rb +3 -3
- data/lib/gloss/cli.rb +3 -3
- data/lib/gloss/config.rb +3 -5
- data/lib/gloss/errors.rb +2 -3
- data/lib/gloss/initializer.rb +2 -3
- data/lib/gloss/logger.rb +2 -3
- data/lib/gloss/parser.rb +2 -3
- data/lib/gloss/prog_loader.rb +27 -15
- data/lib/gloss/runtime.rb +25 -0
- data/lib/gloss/scope.rb +2 -3
- data/lib/gloss/source.rb +2 -3
- data/lib/gloss/type_checker.rb +2 -3
- data/lib/gloss/utils.rb +7 -3
- data/lib/gloss/version.rb +3 -4
- data/lib/gloss/visitor.rb +11 -5
- data/lib/gloss/watcher.rb +2 -3
- data/lib/gloss/writer.rb +38 -25
- data/src/lib/gloss.gl +1 -0
- data/src/lib/gloss/cli.gl +1 -0
- data/src/lib/gloss/config.gl +1 -3
- data/src/lib/gloss/prog_loader.gl +18 -14
- data/src/lib/gloss/runtime.gl +20 -0
- data/src/lib/gloss/utils.gl +5 -0
- data/src/lib/gloss/version.gl +1 -1
- data/src/lib/gloss/visitor.gl +6 -3
- data/src/lib/gloss/writer.gl +28 -15
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9239f0e7898094d7957a2e1eae3b980ff57f94be27eea836f00561262eb8f8d4
|
4
|
+
data.tar.gz: 0ffa974e3146f699a9280878a412f589005cc4723f262c377a215aacd5cae146
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
31
|
-
listen (3.
|
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_label=)](https://rubygems.org/gems/gloss)
|
5
5
|
[&metric=true)](https://rubygems.org/gems/gloss)
|
6
6
|
|
7
|
-
[Gloss](https://en.wikipedia.org/wiki/Gloss_(annotation)) is a
|
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
|
-
##
|
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
|
-
|
2
|
-
|
1
|
+
|
3
2
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See
|
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
|
-
|
2
|
-
|
1
|
+
|
3
2
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See
|
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
|
-
|
2
|
-
|
1
|
+
|
3
2
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See
|
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 => "
|
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
data/lib/gloss/initializer.rb
CHANGED
data/lib/gloss/logger.rb
CHANGED
data/lib/gloss/parser.rb
CHANGED
data/lib/gloss/prog_loader.rb
CHANGED
@@ -1,33 +1,42 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
|
3
2
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See
|
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
|
-
|
13
|
-
(if
|
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
|
-
|
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() { |
|
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.
|
126
|
-
|
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
data/lib/gloss/source.rb
CHANGED
data/lib/gloss/type_checker.rb
CHANGED
data/lib/gloss/utils.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
|
3
2
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See
|
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
data/lib/gloss/visitor.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
|
3
2
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See
|
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
|
-
|
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
data/lib/gloss/writer.rb
CHANGED
@@ -1,46 +1,59 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
|
3
2
|
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
-
##### See
|
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,
|
9
|
+
def initialize(content, src_path, output = nil)
|
11
10
|
@content = content
|
12
11
|
@src_path = src_path
|
13
|
-
@
|
12
|
+
@output = output
|
14
13
|
end
|
15
14
|
def run()
|
16
|
-
|
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
|
-
|
18
|
+
otpt.puts(sb)
|
24
19
|
end)
|
25
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
data/src/lib/gloss/cli.gl
CHANGED
data/src/lib/gloss/config.gl
CHANGED
@@ -9,7 +9,7 @@ module Gloss
|
|
9
9
|
src_dir: "src",
|
10
10
|
entrypoint: nil,
|
11
11
|
strict_require: false,
|
12
|
-
type_checking_strictness: "
|
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
|
-
|
11
|
-
if
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|
-
|
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
|
data/src/lib/gloss/utils.gl
CHANGED
data/src/lib/gloss/version.gl
CHANGED
data/src/lib/gloss/visitor.gl
CHANGED
@@ -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
|
-
|
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,
|
data/src/lib/gloss/writer.gl
CHANGED
@@ -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
|
-
@
|
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
|
-
|
19
|
-
File.open(@output_path, "wb") do |file|
|
14
|
+
write_to_output do |otpt|
|
20
15
|
sb = shebang
|
21
|
-
|
22
|
-
|
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
|
-
|
31
|
-
|
32
|
-
|
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.
|
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-
|
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
|
236
|
+
rubygems_version: 3.1.2
|
235
237
|
signing_key:
|
236
238
|
specification_version: 4
|
237
239
|
summary: A superset of ruby
|