gloss 0.0.2 → 0.0.3
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 +17 -17
- data/ext/gloss/spec/parser_spec.cr +33 -0
- data/ext/gloss/src/cr_ast.cr +70 -15
- data/ext/gloss/src/parser.cr +4 -4
- data/ext/gloss/src/rb_ast.cr +50 -6
- data/lib/gloss/builder.rb +87 -33
- data/lib/gloss/cli.rb +3 -2
- data/lib/gloss/config.rb +10 -8
- data/lib/gloss/errors.rb +14 -7
- data/lib/gloss/initializer.rb +5 -0
- data/lib/gloss/parser.rb +7 -4
- data/lib/gloss/type_checker.rb +44 -58
- data/lib/gloss/version.rb +7 -1
- data/lib/gloss/watcher.rb +26 -17
- data/lib/gloss/writer.rb +19 -11
- data/sig/gloss.rbs +3 -0
- data/src/lib/gloss/config.gl +15 -0
- data/src/lib/gloss/errors.gl +11 -0
- data/src/lib/{hrb → gloss}/initializer.gl +0 -0
- data/src/lib/gloss/parser.gl +19 -0
- data/src/lib/gloss/type_checker.gl +70 -0
- data/src/lib/gloss/version.gl +3 -0
- data/src/lib/{hrb → gloss}/watcher.gl +0 -0
- data/src/lib/gloss/writer.gl +33 -0
- metadata +12 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3a1461d26e97ea9693ee00d63016e0fa1e34ea719de672ae0d4c303e4efb5144
|
4
|
+
data.tar.gz: 2370827768056a2575c1987d661a140d7247b68629e049aa58b0bc9d1de0bc31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17d5c598e8199b375599112a4365cb14691e651783a86880844dd35ff312dc2ca2ed0bb632e0a51897dcd3ba774231ae9c547710f19ed134318a39e098224a37
|
7
|
+
data.tar.gz: 6626ff60cab24dacfc6e6780368a719e04c45c80c1f4e8b89db76bfdc0848f725e33d907058b6c9991fc80c1b97b518503eb42a47435c733f43a4e0d0d49eb0e
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gloss (0.0.
|
4
|
+
gloss (0.0.3)
|
5
5
|
fast_blank
|
6
6
|
listen
|
7
7
|
rbs
|
@@ -10,7 +10,7 @@ PATH
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
12
12
|
specs:
|
13
|
-
activesupport (6.1.
|
13
|
+
activesupport (6.1.1)
|
14
14
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
15
|
i18n (>= 1.6, < 2)
|
16
16
|
minitest (>= 5.1)
|
@@ -26,14 +26,14 @@ GEM
|
|
26
26
|
diff-lcs (1.4.4)
|
27
27
|
fast_blank (1.0.0)
|
28
28
|
ffi (1.14.2)
|
29
|
-
i18n (1.8.
|
29
|
+
i18n (1.8.7)
|
30
30
|
concurrent-ruby (~> 1.0)
|
31
31
|
language_server-protocol (3.15.0.1)
|
32
|
-
listen (3.4.
|
32
|
+
listen (3.4.1)
|
33
33
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
34
34
|
rb-inotify (~> 0.9, >= 0.9.10)
|
35
35
|
method_source (1.0.0)
|
36
|
-
minitest (5.14.
|
36
|
+
minitest (5.14.3)
|
37
37
|
parallel (1.20.1)
|
38
38
|
parser (2.7.2.0)
|
39
39
|
ast (~> 2.4.1)
|
@@ -44,40 +44,40 @@ GEM
|
|
44
44
|
byebug (~> 11.0)
|
45
45
|
pry (~> 0.13.0)
|
46
46
|
rainbow (3.0.0)
|
47
|
-
rake (13.0.
|
47
|
+
rake (13.0.3)
|
48
48
|
rake-compiler (1.1.1)
|
49
49
|
rake
|
50
50
|
rb-fsevent (0.10.4)
|
51
51
|
rb-inotify (0.10.1)
|
52
52
|
ffi (~> 1.0)
|
53
53
|
rbs (1.0.0)
|
54
|
-
regexp_parser (2.0.
|
54
|
+
regexp_parser (2.0.3)
|
55
55
|
rexml (3.2.4)
|
56
56
|
rspec (3.10.0)
|
57
57
|
rspec-core (~> 3.10.0)
|
58
58
|
rspec-expectations (~> 3.10.0)
|
59
59
|
rspec-mocks (~> 3.10.0)
|
60
|
-
rspec-core (3.10.
|
60
|
+
rspec-core (3.10.1)
|
61
61
|
rspec-support (~> 3.10.0)
|
62
|
-
rspec-expectations (3.10.
|
62
|
+
rspec-expectations (3.10.1)
|
63
63
|
diff-lcs (>= 1.2.0, < 2.0)
|
64
64
|
rspec-support (~> 3.10.0)
|
65
|
-
rspec-mocks (3.10.
|
65
|
+
rspec-mocks (3.10.1)
|
66
66
|
diff-lcs (>= 1.2.0, < 2.0)
|
67
67
|
rspec-support (~> 3.10.0)
|
68
|
-
rspec-support (3.10.
|
69
|
-
rubocop (1.
|
68
|
+
rspec-support (3.10.1)
|
69
|
+
rubocop (1.7.0)
|
70
70
|
parallel (~> 1.10)
|
71
71
|
parser (>= 2.7.1.5)
|
72
72
|
rainbow (>= 2.2.2, < 4.0)
|
73
|
-
regexp_parser (>=
|
73
|
+
regexp_parser (>= 1.8, < 3.0)
|
74
74
|
rexml
|
75
|
-
rubocop-ast (>= 1.2.0)
|
75
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
76
76
|
ruby-progressbar (~> 1.7)
|
77
77
|
unicode-display_width (>= 1.4.0, < 2.0)
|
78
|
-
rubocop-ast (1.
|
78
|
+
rubocop-ast (1.4.0)
|
79
79
|
parser (>= 2.7.1.5)
|
80
|
-
ruby-progressbar (1.
|
80
|
+
ruby-progressbar (1.11.0)
|
81
81
|
steep (0.39.0)
|
82
82
|
activesupport (>= 5.1)
|
83
83
|
ast_utils (~> 0.3.0)
|
@@ -103,4 +103,4 @@ DEPENDENCIES
|
|
103
103
|
rubocop
|
104
104
|
|
105
105
|
BUNDLED WITH
|
106
|
-
2.
|
106
|
+
2.2.3
|
@@ -88,4 +88,37 @@ module Gloss
|
|
88
88
|
hsh : Hash[String, String] = { "hello" => "world" }
|
89
89
|
GLS
|
90
90
|
end
|
91
|
+
|
92
|
+
it "parses method calls in case statements" do
|
93
|
+
expected =
|
94
|
+
%q|{"type":"Case","condition":{"type":"LiteralNode","value":"\"abc\"","rb_type":"String"},"whens":[{"type":"When","conditions":[{"type":"Proc","function":{"type":"DefNode","name":"->","body":{"type":"Call","name":"start_with?","args":[{"type":"LiteralNode","value":"\"a\"","rb_type":"String"}],"object":{"type":"Var","name":"x"},"block":null,"block_arg":null},"rp_args":[{"type":"Arg","name":"x","external_name":"x","default_value":null,"restriction":null,"keyword_arg":false}],"receiver":null,"return_type":null,"rest_kw_args":null}}],"body":{"type":"LiteralNode","value":"1","rb_type":"Integer"},"exhaustive":false}],"else":{"type":"LiteralNode","value":"0","rb_type":"Integer"},"exhaustive":false}|
|
95
|
+
Gloss.parse_string(<<-GLS).should eq expected
|
96
|
+
case "abc"
|
97
|
+
when .start_with? 'a'
|
98
|
+
1
|
99
|
+
else
|
100
|
+
0
|
101
|
+
end
|
102
|
+
GLS
|
103
|
+
end
|
104
|
+
|
105
|
+
it "allows constant methods" do
|
106
|
+
Gloss.parse_string(<<-GLS).should be_truthy
|
107
|
+
def Hello(arg = nil)
|
108
|
+
end
|
109
|
+
|
110
|
+
Hello()
|
111
|
+
|
112
|
+
Hello("a")
|
113
|
+
GLS
|
114
|
+
end
|
115
|
+
|
116
|
+
it "requires constant methods to be called with ()" do
|
117
|
+
Gloss.parse_string(<<-GLS).should be_falsey
|
118
|
+
def Hello(arg = nil)
|
119
|
+
end
|
120
|
+
|
121
|
+
Hello
|
122
|
+
GLS
|
123
|
+
end
|
91
124
|
end
|
data/ext/gloss/src/cr_ast.cr
CHANGED
@@ -62,7 +62,7 @@ module Crystal
|
|
62
62
|
|
63
63
|
class SymbolLiteral < ASTNode
|
64
64
|
def to_rb
|
65
|
-
Rb::AST::LiteralNode.new("
|
65
|
+
Rb::AST::LiteralNode.new(%{:"#{@value.to_s}"}, Rb::AST::RbLiteral::Symbol)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -74,13 +74,13 @@ module Crystal
|
|
74
74
|
|
75
75
|
class HashLiteral < ASTNode
|
76
76
|
def to_rb
|
77
|
-
Rb::AST::HashLiteral.new(@entries.map { |e| {
|
77
|
+
Rb::AST::HashLiteral.new(@entries.map { |e| {e.key.to_rb, e.value.to_rb} })
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
81
|
class NamedTupleLiteral < ASTNode
|
82
82
|
def to_rb
|
83
|
-
Rb::AST::HashLiteral.new(@entries.map { |e| {
|
83
|
+
Rb::AST::HashLiteral.new(@entries.map { |e| {e.key, e.value.to_rb} }, frozen: true)
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -92,7 +92,7 @@ module Crystal
|
|
92
92
|
|
93
93
|
class RegexLiteral < ASTNode
|
94
94
|
def to_rb
|
95
|
-
Rb::AST::RegexLiteral.new(
|
95
|
+
Rb::AST::RegexLiteral.new(@value.to_rb)
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
@@ -105,7 +105,7 @@ module Crystal
|
|
105
105
|
class Def < ASTNode
|
106
106
|
def to_rb
|
107
107
|
Rb::AST::DefNode.new(@name, @args.map(&.to_rb), @body.to_rb, receiver.try(&.to_rb),
|
108
|
-
|
108
|
+
return_type.try(&.to_rb), @double_splat.try(&.to_rb))
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -135,8 +135,14 @@ module Crystal
|
|
135
135
|
|
136
136
|
class Call < ASTNode
|
137
137
|
def to_rb
|
138
|
-
Rb::AST::Call.new(
|
139
|
-
|
138
|
+
Rb::AST::Call.new(
|
139
|
+
@obj.try(&.to_rb),
|
140
|
+
@name,
|
141
|
+
@args.map(&.to_rb),
|
142
|
+
@named_args.try(&.map(&.to_rb.as(Rb::AST::Arg))),
|
143
|
+
@block.try(&.to_rb),
|
144
|
+
@block_arg.try(&.to_rb)
|
145
|
+
)
|
140
146
|
end
|
141
147
|
end
|
142
148
|
|
@@ -145,13 +151,13 @@ module Crystal
|
|
145
151
|
|
146
152
|
def to_rb
|
147
153
|
Rb::AST::Arg.new(@name, @external_name, @restriction.try(&.to_rb),
|
148
|
-
|
154
|
+
@default_value.try(&.to_rb), @keyword_arg)
|
149
155
|
end
|
150
156
|
end
|
151
157
|
|
152
158
|
class NamedArgument < ASTNode
|
153
159
|
def to_rb
|
154
|
-
Rb::AST::
|
160
|
+
Rb::AST::Arg.new(@name, @name, nil, @value.to_rb, true)
|
155
161
|
end
|
156
162
|
end
|
157
163
|
|
@@ -161,6 +167,12 @@ module Crystal
|
|
161
167
|
end
|
162
168
|
end
|
163
169
|
|
170
|
+
class Unless < ASTNode
|
171
|
+
def to_rb
|
172
|
+
Rb::AST::Unless.new(@cond.to_rb, @then.to_rb, @else.to_rb)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
164
176
|
class Assign < ASTNode
|
165
177
|
def to_rb
|
166
178
|
Rb::AST::Assign.new(@target.to_rb, @value.to_rb)
|
@@ -295,7 +307,20 @@ module Crystal
|
|
295
307
|
class When < ASTNode
|
296
308
|
def to_rb
|
297
309
|
Rb::AST::When.new(
|
298
|
-
@conds.map
|
310
|
+
@conds.map do |c|
|
311
|
+
if c.is_a? Call
|
312
|
+
arg_name = "x"
|
313
|
+
ProcLiteral.new(
|
314
|
+
Def.new(
|
315
|
+
"->",
|
316
|
+
[Arg.new(arg_name)],
|
317
|
+
c.tap { |call| call.obj = Var.new(arg_name) }
|
318
|
+
)
|
319
|
+
).to_rb
|
320
|
+
else
|
321
|
+
c.to_rb
|
322
|
+
end
|
323
|
+
end,
|
299
324
|
@body.to_rb,
|
300
325
|
@exhaustive
|
301
326
|
)
|
@@ -351,7 +376,7 @@ module Crystal
|
|
351
376
|
class ExceptionHandler < ASTNode
|
352
377
|
def to_rb
|
353
378
|
Rb::AST::ExceptionHandler.new(@body.to_rb, @rescues.try(&.map(&.to_rb)), @else.try(&.to_rb),
|
354
|
-
|
379
|
+
@ensure.try(&.to_rb))
|
355
380
|
end
|
356
381
|
end
|
357
382
|
|
@@ -373,11 +398,41 @@ module Crystal
|
|
373
398
|
end
|
374
399
|
end
|
375
400
|
|
376
|
-
|
401
|
+
class ProcLiteral < ASTNode
|
402
|
+
def to_rb
|
403
|
+
Rb::AST::Proc.new(@def.to_rb)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
class Include < ASTNode
|
408
|
+
def to_rb
|
409
|
+
Rb::AST::Include.new(@name.to_rb)
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
class Extend < ASTNode
|
414
|
+
def to_rb
|
415
|
+
Rb::AST::Extend.new(@name.to_rb)
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
class IsA < ASTNode
|
420
|
+
def to_rb
|
421
|
+
Rb::AST::Call.new(
|
422
|
+
@obj.to_rb,
|
423
|
+
"is_a?",
|
424
|
+
[@const.to_rb],
|
425
|
+
nil,
|
426
|
+
nil,
|
427
|
+
nil
|
428
|
+
)
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
{% for class_name in %w[ProcNotation Macro OffsetOf VisibilityModifier RespondsTo
|
377
433
|
Select ImplicitObj AnnotationDef While Until UninitializedVar
|
378
|
-
|
379
|
-
|
380
|
-
Metaclass Cast NilableCast TypeOf Annotation
|
434
|
+
ProcPointer Self Yield LibDef FunDef TypeDef CStructOrUnionDef
|
435
|
+
ExternalVar Alias Metaclass Cast NilableCast TypeOf Annotation
|
381
436
|
Underscore MagicConstant Asm AsmOperand] %}
|
382
437
|
class {{class_name.id}} < ASTNode
|
383
438
|
def to_rb
|
data/ext/gloss/src/parser.cr
CHANGED
@@ -17,10 +17,10 @@ module Gloss
|
|
17
17
|
line = @line_number
|
18
18
|
column = @token.column_number
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
Crystal::ArrayLiteral.new([] of Crystal::ASTNode)
|
20
|
+
next_token_skip_space
|
21
|
+
next_token_skip_space_or_newline
|
22
|
+
of = nil
|
23
|
+
Crystal::ArrayLiteral.new([] of Crystal::ASTNode).at_end(of)
|
24
24
|
end
|
25
25
|
|
26
26
|
def new_hash_literal(entries, line, column, end_location, allow_of = true)
|
data/ext/gloss/src/rb_ast.cr
CHANGED
@@ -113,16 +113,16 @@ module Rb
|
|
113
113
|
end
|
114
114
|
|
115
115
|
class Arg < Node
|
116
|
-
@info : NamedTuple(type: String, name: String, external_name: String,
|
116
|
+
@info : NamedTuple(type: String, name: String, external_name: String, value: Node?,
|
117
117
|
restriction: Node?, keyword_arg: Bool)
|
118
118
|
|
119
|
-
def initialize(name : String, external_name : String, restriction : Node?,
|
119
|
+
def initialize(name : String, external_name : String, restriction : Node?, value :
|
120
120
|
Node?, keyword_arg)
|
121
121
|
@info = {
|
122
122
|
type: self.class.name.split("::").last,
|
123
123
|
name: name,
|
124
124
|
restriction: restriction,
|
125
|
-
|
125
|
+
value: value,
|
126
126
|
external_name: external_name,
|
127
127
|
keyword_arg: keyword_arg
|
128
128
|
}
|
@@ -200,7 +200,17 @@ module Rb
|
|
200
200
|
delegate :to_json, to: @info
|
201
201
|
end
|
202
202
|
|
203
|
-
class RegexLiteral <
|
203
|
+
class RegexLiteral < Node
|
204
|
+
@info : NamedTuple(type: String, value: Node)
|
205
|
+
|
206
|
+
def initialize(value)
|
207
|
+
@info = {
|
208
|
+
type: self.class.name.split("::").last,
|
209
|
+
value: value,
|
210
|
+
}
|
211
|
+
end
|
212
|
+
|
213
|
+
delegate :to_json, to: @info
|
204
214
|
end
|
205
215
|
|
206
216
|
class Nop < Node
|
@@ -308,9 +318,10 @@ module Rb
|
|
308
318
|
end
|
309
319
|
|
310
320
|
class Call < Node
|
311
|
-
@info : NamedTuple(type: String, name: String, args: Array(Node), object: Node?, block:
|
321
|
+
@info : NamedTuple(type: String, name: String, args: Array(Node), object: Node?, block:
|
322
|
+
Block?, block_arg: Node?, named_args: Array(Arg)?)
|
312
323
|
|
313
|
-
def initialize(object : Node?, name : String, args : Array(Node), block, block_arg)
|
324
|
+
def initialize(object : Node?, name : String, args : Array(Node), named_args, block, block_arg)
|
314
325
|
@info = {
|
315
326
|
type: self.class.name.split("::").last,
|
316
327
|
name: name,
|
@@ -318,6 +329,7 @@ module Rb
|
|
318
329
|
object: object,
|
319
330
|
block: block,
|
320
331
|
block_arg: block_arg,
|
332
|
+
named_args: named_args,
|
321
333
|
}
|
322
334
|
end
|
323
335
|
|
@@ -519,5 +531,37 @@ module Rb
|
|
519
531
|
|
520
532
|
delegate :to_json, to: @info
|
521
533
|
end
|
534
|
+
|
535
|
+
class Proc < Node
|
536
|
+
@info : NamedTuple(type: String, function: DefNode)
|
537
|
+
|
538
|
+
def initialize(function)
|
539
|
+
@info = {
|
540
|
+
type: self.class.name.split("::").last,
|
541
|
+
function: function
|
542
|
+
}
|
543
|
+
end
|
544
|
+
|
545
|
+
delegate :to_json, to: @info
|
546
|
+
end
|
547
|
+
|
548
|
+
class NodeWithNameNode < Node
|
549
|
+
@info : NamedTuple(type: String, name: Node)
|
550
|
+
|
551
|
+
def initialize(name)
|
552
|
+
@info = {
|
553
|
+
type: self.class.name.split("::").last,
|
554
|
+
name: name
|
555
|
+
}
|
556
|
+
end
|
557
|
+
|
558
|
+
delegate :to_json, to: @info
|
559
|
+
end
|
560
|
+
|
561
|
+
class Extend < NodeWithNameNode
|
562
|
+
end
|
563
|
+
|
564
|
+
class Include < NodeWithNameNode
|
565
|
+
end
|
522
566
|
end
|
523
567
|
end
|
data/lib/gloss/builder.rb
CHANGED
@@ -15,8 +15,13 @@ module Gloss
|
|
15
15
|
|
16
16
|
def run
|
17
17
|
rb_output = visit_node(@tree)
|
18
|
-
|
19
|
-
|
18
|
+
<<~RUBY
|
19
|
+
#{"# frozen_string_literal: true\n" if Config.frozen_string_literals}
|
20
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
21
|
+
##### See #{Config.src_dir}/ to make changes
|
22
|
+
|
23
|
+
#{rb_output}
|
24
|
+
RUBY
|
20
25
|
end
|
21
26
|
|
22
27
|
def visit_node(node, scope = Scope.new)
|
@@ -24,24 +29,39 @@ module Gloss
|
|
24
29
|
case node[:type]
|
25
30
|
when "ClassNode"
|
26
31
|
class_name = visit_node(node[:name])
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
current_namespace = @current_scope ? @current_scope.name.to_namespace : RBS::Namespace.root
|
33
|
+
superclass_type = nil
|
34
|
+
superclass_output = nil
|
35
|
+
if node[:superclass]
|
36
|
+
@eval_vars = true
|
37
|
+
superclass_output = visit_node(node[:superclass])
|
38
|
+
@eval_vars = false
|
39
|
+
ns = if superclass_output.start_with? '::'
|
40
|
+
RBS::Namespace.root
|
41
|
+
elsif superclass_output.include? '::'
|
42
|
+
current_namespace
|
43
|
+
else
|
44
|
+
RBS::Namespace.empty
|
45
|
+
end
|
46
|
+
superclass_type = RBS::AST::Declarations::Class::Super.new(
|
47
|
+
name: RBS::TypeName.new(
|
48
|
+
name: superclass_output.to_sym,
|
49
|
+
namespace: ns
|
50
|
+
),
|
51
|
+
args: [],
|
52
|
+
location: nil
|
53
|
+
)
|
54
|
+
end
|
34
55
|
|
35
|
-
src.write_ln "class #{class_name}#{" < #{
|
56
|
+
src.write_ln "class #{class_name}#{" < #{superclass_output}" if superclass_output}"
|
36
57
|
|
37
|
-
current_namespace = @current_scope ? @current_scope.name.to_namespace : RBS::Namespace.root
|
38
58
|
class_type = RBS::AST::Declarations::Class.new(
|
39
59
|
name: RBS::TypeName.new(
|
40
60
|
namespace: current_namespace,
|
41
61
|
name: class_name.to_sym
|
42
62
|
),
|
43
63
|
type_params: RBS::AST::Declarations::ModuleTypeParams.new, # responds to #add to add params
|
44
|
-
super_class:
|
64
|
+
super_class: superclass_type,
|
45
65
|
members: [],
|
46
66
|
annotations: [],
|
47
67
|
location: node[:location],
|
@@ -55,6 +75,9 @@ module Gloss
|
|
55
75
|
src.write_ln "end"
|
56
76
|
|
57
77
|
@current_scope = old_parent_scope
|
78
|
+
|
79
|
+
@current_scope.members << class_type if @current_scope
|
80
|
+
|
58
81
|
if @type_checker
|
59
82
|
@type_checker.top_level_decls[class_type.name.name] = class_type unless @current_scope
|
60
83
|
end
|
@@ -62,7 +85,7 @@ module Gloss
|
|
62
85
|
module_name = visit_node node[:name]
|
63
86
|
src.write_ln "module #{module_name}"
|
64
87
|
|
65
|
-
current_namespace =
|
88
|
+
current_namespace = @current_scope ? @current_scope.name.to_namespace : RBS::Namespace.root
|
66
89
|
|
67
90
|
module_type = RBS::AST::Declarations::Module.new(
|
68
91
|
name: RBS::TypeName.new(
|
@@ -82,6 +105,9 @@ module Gloss
|
|
82
105
|
indented(src) { src.write_ln visit_node(node[:body]) if node[:body] }
|
83
106
|
|
84
107
|
@current_scope = old_parent_scope
|
108
|
+
|
109
|
+
@current_scope.members << module_type if @current_scope
|
110
|
+
|
85
111
|
if @type_checker
|
86
112
|
@type_checker.top_level_decls[module_type.name.name] = module_type unless @current_scope
|
87
113
|
end
|
@@ -107,12 +133,17 @@ module Gloss
|
|
107
133
|
RBS::MethodType.new(
|
108
134
|
type_params: [],
|
109
135
|
type: RBS::Types::Function.new(
|
110
|
-
required_positionals: []
|
111
|
-
|
112
|
-
|
136
|
+
required_positionals: node[:rp_args]&.map do |a|
|
137
|
+
RBS::Types::Function::Param.new(
|
138
|
+
name: visit_node(a).to_sym,
|
139
|
+
type: RBS::Types::Bases::Any.new(location: nil)
|
140
|
+
)
|
141
|
+
end || EMPTY_ARRAY,
|
142
|
+
optional_positionals: node[:op_args] || EMPTY_ARRAY,
|
143
|
+
rest_positionals: node[:rest_p_args],
|
113
144
|
trailing_positionals: [],
|
114
|
-
required_keywords:
|
115
|
-
optional_keywords:
|
145
|
+
required_keywords: node[:req_kw_args] || EMPTY_HASH,
|
146
|
+
optional_keywords: node[:opt_kw_args] || EMPTY_HASH,
|
116
147
|
rest_keywords: node[:rest_kw_args] ?
|
117
148
|
RBS::Types::Function::Param.new(
|
118
149
|
name: visit_node(node[:rest_kw_args]).to_sym,
|
@@ -148,6 +179,7 @@ module Gloss
|
|
148
179
|
when "Call"
|
149
180
|
obj = node[:object] ? "#{visit_node(node[:object], scope)}." : ""
|
150
181
|
args = node[:args] || EMPTY_ARRAY
|
182
|
+
args += node[:named_args] if node[:named_args]
|
151
183
|
args = if !args.empty? || node[:block_arg]
|
152
184
|
"(#{args.map { |a| visit_node(a, scope).strip }.reject(&:blank?).join(", ")}#{"&#{visit_node(node[:block_arg]).strip}" if node[:block_arg]})"
|
153
185
|
else
|
@@ -224,9 +256,9 @@ module Gloss
|
|
224
256
|
val = node[:external_name]
|
225
257
|
if node[:keyword_arg]
|
226
258
|
val += ":"
|
227
|
-
val += " #{visit_node(node[:
|
228
|
-
elsif node[:
|
229
|
-
val += " = #{visit_node(node[:
|
259
|
+
val += " #{visit_node(node[:value])}" if node[:value]
|
260
|
+
elsif node[:value]
|
261
|
+
val += " = #{visit_node(node[:value])}"
|
230
262
|
end
|
231
263
|
|
232
264
|
src.write val
|
@@ -272,6 +304,16 @@ module Gloss
|
|
272
304
|
end
|
273
305
|
|
274
306
|
src.write_ln "end)"
|
307
|
+
when "Unless"
|
308
|
+
src.write_ln "unless #{visit_node node[:condition]}"
|
309
|
+
indented(src) { src.write_ln visit_node(node[:then]) }
|
310
|
+
|
311
|
+
if node[:else]
|
312
|
+
src.write_ln "else"
|
313
|
+
indented(src) { src.write_ln visit_node(node[:else]) }
|
314
|
+
end
|
315
|
+
|
316
|
+
src.write_ln "end"
|
275
317
|
when "Case"
|
276
318
|
src.write "case"
|
277
319
|
src.write " #{visit_node(node[:condition]).strip}\n" if node[:condition]
|
@@ -321,22 +363,34 @@ module Gloss
|
|
321
363
|
src.write_ln "#{visit_node(node[:var])} = #{visit_node(node[:value])}"
|
322
364
|
when "ExceptionHandler"
|
323
365
|
src.write_ln "begin"
|
324
|
-
src
|
325
|
-
|
326
|
-
src.write_ln "rescue #{r[:types].map { |n| visit_node n }.join(", ") if r[:types]}#{" => #{r[:name]}" if r[:name]}"
|
327
|
-
src.write_ln visit_node(r[:body]) if r[:body]
|
328
|
-
end
|
329
|
-
if node[:else]
|
330
|
-
src.write_ln "else"
|
331
|
-
src.write_ln visit_node(node[:else])
|
332
|
-
end
|
333
|
-
if node[:ensure]
|
334
|
-
src.write_ln "ensure"
|
335
|
-
src.write_ln visit_node(node[:ensure])
|
366
|
+
indented src do
|
367
|
+
src.write_ln visit_node(node[:body])
|
336
368
|
end
|
369
|
+
node[:rescues]&.each do |r|
|
370
|
+
src.write_ln "rescue #{r[:types].map { |n| visit_node n }.join(", ") if r[:types]}#{" => #{r[:name]}" if r[:name]}"
|
371
|
+
indented(src) { src.write_ln visit_node(r[:body]) } if r[:body]
|
372
|
+
end
|
373
|
+
if node[:else]
|
374
|
+
src.write_ln "else"
|
375
|
+
indented(src) { src.write_ln visit_node(node[:else]) }
|
376
|
+
end
|
377
|
+
if node[:ensure]
|
378
|
+
src.write_ln "ensure"
|
379
|
+
intended(src) { src.write_ln visit_node(node[:ensure]) }
|
380
|
+
end
|
337
381
|
src.write_ln "end"
|
338
382
|
when "Generic"
|
339
383
|
src.write "#{node[:name]}[#{node[:args].map { |a| visit_node a }.join(", ")}]"
|
384
|
+
when "Proc"
|
385
|
+
fn = node[:function]
|
386
|
+
src.write "->#{render_args(fn)} { #{visit_node fn[:body]} }"
|
387
|
+
when "Include"
|
388
|
+
src.write_ln "include #{visit_node node[:name]}"
|
389
|
+
when "Extend"
|
390
|
+
src.write_ln "extend #{visit_node node[:name]}"
|
391
|
+
when "RegexLiteral"
|
392
|
+
contents = visit_node node[:value]
|
393
|
+
src.write Regexp.new(contents.undump).inspect
|
340
394
|
when "EmptyNode"
|
341
395
|
# pass
|
342
396
|
else
|
data/lib/gloss/cli.rb
CHANGED
@@ -14,12 +14,13 @@ module Gloss
|
|
14
14
|
when "watch"
|
15
15
|
Watcher.new.watch
|
16
16
|
when "build"
|
17
|
-
(files.empty? ? Dir.glob("#{Config.src_dir}/**/*.
|
17
|
+
(files.empty? ? Dir.glob("#{Config.src_dir}/**/*.gl") : files).each do |fp|
|
18
18
|
puts "=====> Building #{fp}"
|
19
19
|
content = File.read(fp)
|
20
20
|
tree_hash = Parser.new(content).run
|
21
21
|
type_checker = TypeChecker.new
|
22
|
-
rb_output = Builder.new(tree_hash, type_checker)
|
22
|
+
rb_output = Builder.new(tree_hash, type_checker).run
|
23
|
+
type_checker.run(rb_output)
|
23
24
|
|
24
25
|
puts "=====> Writing #{fp}"
|
25
26
|
Writer.new(rb_output, fp).run
|
data/lib/gloss/config.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
5
|
+
|
3
6
|
require "ostruct"
|
4
7
|
require "yaml"
|
5
|
-
|
6
8
|
module Gloss
|
7
9
|
user_config = YAML.safe_load(File.read(".gloss.yml"))
|
8
|
-
Config = OpenStruct.new(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
}.
|
13
|
-
|
14
|
-
Config.default_config.each { |k, v| Config.send(:"#{k}=", user_config[k.to_s] || v) }
|
10
|
+
Config = OpenStruct.new(default_config: {:frozen_string_literals => true,
|
11
|
+
:src_dir => "src"}.freeze)
|
12
|
+
Config.default_config
|
13
|
+
.each { |k, v|
|
14
|
+
Config.send(:"#{k}=", user_config.[](k.to_s) || v)
|
15
|
+
}
|
15
16
|
end
|
17
|
+
|
data/lib/gloss/errors.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
|
-
|
2
|
-
module Errors
|
3
|
-
class BaseGlossError < StandardError; end
|
4
|
-
|
5
|
-
class TypeValidationError < BaseGlossError; end
|
1
|
+
# frozen_string_literal: true
|
6
2
|
|
7
|
-
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
8
5
|
|
9
|
-
|
6
|
+
module Gloss
|
7
|
+
module Errors
|
8
|
+
class BaseGlossError < StandardError
|
9
|
+
end
|
10
|
+
class TypeValidationError < BaseGlossError
|
11
|
+
end
|
12
|
+
class TypeError < BaseGlossError
|
13
|
+
end
|
14
|
+
class ParserError < BaseGlossError
|
15
|
+
end
|
10
16
|
end
|
11
17
|
end
|
18
|
+
|
data/lib/gloss/initializer.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
5
|
+
|
2
6
|
require "yaml"
|
3
7
|
module Gloss
|
4
8
|
class Initializer
|
@@ -18,3 +22,4 @@ module Gloss
|
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
25
|
+
|
data/lib/gloss/parser.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
5
|
+
|
3
6
|
module Gloss
|
4
7
|
class Parser
|
5
8
|
def initialize(str)
|
6
9
|
@str = str
|
7
10
|
end
|
8
|
-
|
9
|
-
def run
|
11
|
+
def run()
|
10
12
|
tree_json = Gloss.parse_buffer(@str)
|
11
13
|
begin
|
12
|
-
JSON.parse
|
14
|
+
JSON.parse(tree_json, symbolize_names: true)
|
13
15
|
rescue JSON::ParserError
|
14
|
-
raise
|
16
|
+
raise(Errors::ParserError, tree_json)
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
21
|
+
|
data/lib/gloss/type_checker.rb
CHANGED
@@ -1,75 +1,61 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
5
|
+
|
3
6
|
module Gloss
|
4
7
|
class TypeChecker
|
5
|
-
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@steep_target = Steep::Project::Target.new(
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
ignore_patterns: [],
|
13
|
-
signature_patterns: []
|
14
|
-
)
|
8
|
+
Project = Struct.new(:targets)
|
9
|
+
attr_reader(:steep_target, :top_level_decls)
|
10
|
+
def initialize()
|
11
|
+
@steep_target = Steep::Project::Target.new(name: "gloss", options: Steep::Project::Options.new
|
12
|
+
.tap { |o|
|
13
|
+
o.allow_unknown_constant_assignment=(true)
|
14
|
+
}, source_patterns: ["gloss.rb"], ignore_patterns: Array.new, signature_patterns: ["sig"])
|
15
15
|
@top_level_decls = {}
|
16
|
-
Dir.glob("sig/**/*.rbs").each do |fp|
|
17
|
-
next if !@steep_target.possible_signature_file?(fp) || @steep_target.signature_file?(fp)
|
18
|
-
|
19
|
-
Steep.logger.info { "Adding signature file: #{fp}" }
|
20
|
-
@steep_target.add_signature path, (Pathname(".") + fp).cleanpath.read
|
21
|
-
end
|
22
16
|
end
|
23
|
-
|
24
17
|
def run(rb_str)
|
25
|
-
unless
|
26
|
-
raise
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
18
|
+
unless check_types(rb_str)
|
19
|
+
raise(Errors::TypeError, @steep_target.errors
|
20
|
+
.map { |e|
|
21
|
+
case e
|
22
|
+
when Steep::Errors::NoMethod
|
23
|
+
"Unknown method :#{e.method}, location: #{e.type
|
24
|
+
.location
|
25
|
+
.inspect}"
|
26
|
+
when Steep::Errors::MethodBodyTypeMismatch
|
27
|
+
"Invalid method body type - expected: #{e.expected}, actual: #{e.actual}"
|
28
|
+
when Steep::Errors::IncompatibleArguments
|
29
|
+
"Invalid argmuents - method type: #{e.method_type}, receiver type: #{e.receiver_type}"
|
30
|
+
when Steep::Errors::ReturnTypeMismatch
|
31
|
+
"Invalid return type - expected: #{e.expected}, actual: #{e.actual}"
|
32
|
+
when Steep::Errors::IncompatibleAssignment
|
33
|
+
"Invalid assignment - cannot assign #{e.rhs_type} to type #{e.lhs_type}"
|
34
|
+
end
|
35
|
+
}
|
36
|
+
.join("\n"))
|
43
37
|
end
|
44
|
-
|
45
|
-
true
|
38
|
+
true
|
46
39
|
end
|
47
|
-
|
48
40
|
def check_types(rb_str)
|
49
41
|
env_loader = RBS::EnvironmentLoader.new
|
50
42
|
env = RBS::Environment.from_loader(env_loader)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
43
|
+
project = Steep::Project.new(steepfile_path: Pathname.new(Config.src_dir)
|
44
|
+
.realpath)
|
45
|
+
project.targets
|
46
|
+
.<<(@steep_target)
|
47
|
+
loader = Steep::Project::FileLoader.new(project: project)
|
48
|
+
loader.load_signatures
|
49
|
+
@steep_target.add_source("gloss.rb", rb_str)
|
50
|
+
@top_level_decls.each { |_, decl|
|
51
|
+
env.<<(decl)
|
52
|
+
}
|
55
53
|
env = env.resolve_type_names
|
56
|
-
|
57
54
|
@steep_target.instance_variable_set("@environment", env)
|
58
|
-
@steep_target.
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
check = Steep::Subtyping::Check.new(factory: factory)
|
63
|
-
validator = Steep::Signature::Validator.new(checker: check)
|
64
|
-
validator.validate
|
65
|
-
|
66
|
-
raise Errors::TypeValidationError, validator.each_error.to_a.join("\n") unless validator.no_error?
|
67
|
-
|
68
|
-
@steep_target.run_type_check(env, check, Time.now)
|
69
|
-
|
70
|
-
@steep_target.status.is_a?(Steep::Project::Target::TypeCheckStatus) &&
|
71
|
-
@steep_target.no_error? &&
|
72
|
-
@steep_target.errors.empty?
|
55
|
+
@steep_target.type_check
|
56
|
+
@steep_target.status
|
57
|
+
.is_a?(Steep::Project::Target::TypeCheckStatus) && @steep_target.no_error? && @steep_target.errors
|
58
|
+
.empty?
|
73
59
|
end
|
74
60
|
end
|
75
61
|
end
|
data/lib/gloss/version.rb
CHANGED
data/lib/gloss/watcher.rb
CHANGED
@@ -1,32 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
4
5
|
|
6
|
+
require "listen"
|
5
7
|
module Gloss
|
6
8
|
class Watcher
|
7
|
-
def initialize
|
8
|
-
@paths =
|
9
|
+
def initialize()
|
10
|
+
@paths = ["src/"]
|
9
11
|
end
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def watch()
|
13
|
+
puts("=====> Now listening for changes in #{@paths.join(", ")}")
|
14
|
+
listener = Listen.to(*@paths, latency: 2) { |modified, added, removed|
|
15
|
+
modified.+(added)
|
16
|
+
.each { |f|
|
15
17
|
content = File.read(f)
|
16
|
-
Writer.new(Builder.new(content)
|
17
|
-
|
18
|
-
|
18
|
+
Writer.new(Builder.new(content)
|
19
|
+
.run, f)
|
20
|
+
.run
|
21
|
+
}
|
22
|
+
removed.each { |f|
|
19
23
|
out_path = Utils.src_path_to_output_path(f)
|
20
|
-
|
21
|
-
|
22
|
-
|
24
|
+
(if File.exist?(out_path)
|
25
|
+
File.delete(out_path)
|
26
|
+
end)
|
27
|
+
}
|
28
|
+
}
|
23
29
|
listener.start
|
24
30
|
begin
|
25
|
-
loop {
|
31
|
+
loop { ||
|
32
|
+
sleep(10)
|
33
|
+
}
|
26
34
|
rescue Interrupt
|
27
|
-
puts
|
28
|
-
exit
|
35
|
+
puts("=====> Interrupt signal received, shutting down")
|
36
|
+
exit(0)
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
32
40
|
end
|
41
|
+
|
data/lib/gloss/writer.rb
CHANGED
@@ -1,26 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
##### This file was generated by Gloss; any changes made here will be overwritten.
|
4
|
+
##### See src/ to make changes
|
5
|
+
|
6
|
+
require "pathname"
|
7
|
+
require "fileutils"
|
3
8
|
module Gloss
|
4
9
|
module Utils
|
5
10
|
module_function
|
6
|
-
|
7
11
|
def src_path_to_output_path(src_path)
|
8
|
-
src_path.sub(
|
12
|
+
src_path.sub(/\A(?:\.\/)?#{Config.src_dir}\/?/, "")
|
13
|
+
.sub(/\.gl$/, ".rb")
|
9
14
|
end
|
10
15
|
end
|
11
|
-
|
12
16
|
class Writer
|
13
17
|
include Utils
|
14
|
-
|
15
|
-
|
16
|
-
@content
|
17
|
-
@output_path = output_path
|
18
|
+
def initialize(content, src_path, output_path = Pathname.new(src_path_to_output_path(src_path))
|
19
|
+
)
|
20
|
+
@content = content
|
21
|
+
@output_path = output_path
|
18
22
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
+
def run()
|
24
|
+
unless @output_path.parent
|
25
|
+
.exist?
|
26
|
+
FileUtils.mkdir_p(@output_path.parent)
|
23
27
|
end
|
28
|
+
File.open(@output_path, "wb") { |file|
|
29
|
+
file.<<(@content)
|
30
|
+
}
|
24
31
|
end
|
25
32
|
end
|
26
33
|
end
|
34
|
+
|
data/sig/gloss.rbs
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ostruct"
|
4
|
+
require "yaml"
|
5
|
+
|
6
|
+
module Gloss
|
7
|
+
user_config = YAML.safe_load(File.read(".gloss.yml"))
|
8
|
+
Config = OpenStruct.new(
|
9
|
+
default_config: {
|
10
|
+
frozen_string_literals: true,
|
11
|
+
src_dir: "src",
|
12
|
+
}
|
13
|
+
)
|
14
|
+
Config.default_config.each { |k, v| Config.send(:"#{k}=", user_config[k.to_s] || v) }
|
15
|
+
end
|
File without changes
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gloss
|
4
|
+
class Parser
|
5
|
+
def initialize(@str : String)
|
6
|
+
end
|
7
|
+
|
8
|
+
def run : String
|
9
|
+
tree_json = Gloss.parse_buffer(@str)
|
10
|
+
begin
|
11
|
+
JSON.parse tree_json, symbolize_names: true
|
12
|
+
rescue JSON::ParserError
|
13
|
+
# if parsing fails then tree is invalid and most likely an error message from the parser in
|
14
|
+
# crystal
|
15
|
+
raise Errors::ParserError, tree_json
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gloss
|
4
|
+
class TypeChecker
|
5
|
+
Project = Struct.new :targets
|
6
|
+
|
7
|
+
attr_reader :steep_target, :top_level_decls
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@steep_target = Steep::Project::Target.new(
|
11
|
+
name: "gloss",
|
12
|
+
options: Steep::Project::Options.new.tap do |o|
|
13
|
+
o.allow_unknown_constant_assignment = true
|
14
|
+
end,
|
15
|
+
source_patterns: ["gloss.rb"],
|
16
|
+
ignore_patterns: Array.new,
|
17
|
+
signature_patterns: ["sig"]
|
18
|
+
)
|
19
|
+
@top_level_decls = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(rb_str)
|
23
|
+
unless check_types(rb_str)
|
24
|
+
raise Errors::TypeError,
|
25
|
+
@steep_target.errors.map { |e|
|
26
|
+
case e
|
27
|
+
when Steep::Errors::NoMethod
|
28
|
+
"Unknown method :#{e.method}, location: #{e.type.location.inspect}"
|
29
|
+
when Steep::Errors::MethodBodyTypeMismatch
|
30
|
+
"Invalid method body type - expected: #{e.expected}, actual: #{e.actual}"
|
31
|
+
when Steep::Errors::IncompatibleArguments
|
32
|
+
"Invalid argmuents - method type: #{e.method_type}, receiver type: #{e.receiver_type}"
|
33
|
+
when Steep::Errors::ReturnTypeMismatch
|
34
|
+
"Invalid return type - expected: #{e.expected}, actual: #{e.actual}"
|
35
|
+
when Steep::Errors::IncompatibleAssignment
|
36
|
+
"Invalid assignment - cannot assign #{e.rhs_type} to type #{e.lhs_type}"
|
37
|
+
else
|
38
|
+
e.inspect
|
39
|
+
end
|
40
|
+
}.join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def check_types(rb_str)
|
47
|
+
env_loader = RBS::EnvironmentLoader.new
|
48
|
+
env = RBS::Environment.from_loader(env_loader)
|
49
|
+
project = Steep::Project.new(steepfile_path: Pathname.new(Config.src_dir).realpath)
|
50
|
+
project.targets << @steep_target
|
51
|
+
loader = Steep::Project::FileLoader.new(project: project)
|
52
|
+
loader.load_signatures
|
53
|
+
|
54
|
+
@steep_target.add_source("gloss.rb", rb_str)
|
55
|
+
|
56
|
+
@top_level_decls.each do |_, decl|
|
57
|
+
env << decl
|
58
|
+
end
|
59
|
+
env = env.resolve_type_names
|
60
|
+
|
61
|
+
@steep_target.instance_variable_set("@environment", env)
|
62
|
+
|
63
|
+
@steep_target.type_check
|
64
|
+
|
65
|
+
@steep_target.status.is_a?(Steep::Project::Target::TypeCheckStatus) &&
|
66
|
+
@steep_target.no_error? &&
|
67
|
+
@steep_target.errors.empty?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pathname"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
module Gloss
|
7
|
+
module Utils
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def src_path_to_output_path(src_path)
|
11
|
+
src_path.sub(%r{\A(?:\./)?#{Config.src_dir}/?}, "")
|
12
|
+
.sub(/\.gl$/, ".rb")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Writer
|
17
|
+
include Utils
|
18
|
+
|
19
|
+
def initialize(
|
20
|
+
@content,
|
21
|
+
src_path : String?,
|
22
|
+
@output_path : Pathname = Pathname.new(src_path_to_output_path(src_path))
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
FileUtils.mkdir_p(@output_path.parent) unless @output_path.parent.exist?
|
28
|
+
File.open(@output_path, "wb") do |file|
|
29
|
+
file << @content
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gloss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- johansenja
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-01-
|
11
|
+
date: 2021-01-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fast_blank
|
@@ -168,9 +168,16 @@ files:
|
|
168
168
|
- lib/gloss/version.rb
|
169
169
|
- lib/gloss/watcher.rb
|
170
170
|
- lib/gloss/writer.rb
|
171
|
+
- sig/gloss.rbs
|
171
172
|
- sig/listen.rbs
|
172
|
-
- src/lib/
|
173
|
-
- src/lib/
|
173
|
+
- src/lib/gloss/config.gl
|
174
|
+
- src/lib/gloss/errors.gl
|
175
|
+
- src/lib/gloss/initializer.gl
|
176
|
+
- src/lib/gloss/parser.gl
|
177
|
+
- src/lib/gloss/type_checker.gl
|
178
|
+
- src/lib/gloss/version.gl
|
179
|
+
- src/lib/gloss/watcher.gl
|
180
|
+
- src/lib/gloss/writer.gl
|
174
181
|
homepage:
|
175
182
|
licenses:
|
176
183
|
- MIT
|
@@ -190,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
197
|
- !ruby/object:Gem::Version
|
191
198
|
version: '0'
|
192
199
|
requirements: []
|
193
|
-
rubygems_version: 3.
|
200
|
+
rubygems_version: 3.2.3
|
194
201
|
signing_key:
|
195
202
|
specification_version: 4
|
196
203
|
summary: A superset of ruby
|