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