gloss 0.0.4 → 0.1.2

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +3 -0
  3. data/.github/workflows/{crystal.yml → crystal_specs.yml} +1 -1
  4. data/.github/workflows/{ruby.yml → ruby_specs.yml} +2 -2
  5. data/.gloss.yml +1 -0
  6. data/.rspec +1 -0
  7. data/Gemfile.lock +9 -11
  8. data/README.md +35 -5
  9. data/Rakefile +1 -1
  10. data/exe/gloss +13 -2
  11. data/ext/gloss/Makefile +8 -19
  12. data/ext/gloss/spec/parser_spec.cr +83 -83
  13. data/ext/gloss/src/cr_ast.cr +63 -77
  14. data/ext/gloss/src/gloss.cr +1 -2
  15. data/ext/gloss/src/rb_ast.cr +40 -38
  16. data/lib/gloss.rb +15 -7
  17. data/lib/gloss/cli.rb +75 -32
  18. data/lib/gloss/config.rb +10 -3
  19. data/lib/gloss/errors.rb +1 -1
  20. data/lib/gloss/initializer.rb +6 -5
  21. data/lib/gloss/logger.rb +29 -0
  22. data/lib/gloss/parser.rb +17 -2
  23. data/lib/gloss/prog_loader.rb +141 -0
  24. data/lib/gloss/scope.rb +1 -1
  25. data/lib/gloss/source.rb +1 -1
  26. data/lib/gloss/type_checker.rb +80 -32
  27. data/lib/gloss/utils.rb +44 -0
  28. data/lib/gloss/version.rb +5 -5
  29. data/lib/gloss/{builder.rb → visitor.rb} +125 -74
  30. data/lib/gloss/watcher.rb +47 -11
  31. data/lib/gloss/writer.rb +22 -11
  32. data/sig/core.rbs +2 -0
  33. data/sig/fast_blank.rbs +4 -0
  34. data/sig/{gloss.rbs → gls.rbs} +0 -0
  35. data/sig/optparse.rbs +6 -0
  36. data/sig/rubygems.rbs +9 -0
  37. data/sig/yaml.rbs +3 -0
  38. data/src/exe/gloss +19 -0
  39. data/src/lib/gloss.gl +26 -0
  40. data/src/lib/gloss/cli.gl +53 -24
  41. data/src/lib/gloss/config.gl +9 -3
  42. data/src/lib/gloss/initializer.gl +4 -6
  43. data/src/lib/gloss/logger.gl +21 -0
  44. data/src/lib/gloss/parser.gl +17 -5
  45. data/src/lib/gloss/prog_loader.gl +133 -0
  46. data/src/lib/gloss/scope.gl +0 -2
  47. data/src/lib/gloss/type_checker.gl +85 -39
  48. data/src/lib/gloss/utils.gl +38 -0
  49. data/src/lib/gloss/version.gl +1 -1
  50. data/src/lib/gloss/{builder.gl → visitor.gl} +123 -68
  51. data/src/lib/gloss/watcher.gl +44 -10
  52. data/src/lib/gloss/writer.gl +16 -14
  53. metadata +23 -8
@@ -4,14 +4,13 @@ require "./cr_ast"
4
4
  require "./rb_ast"
5
5
  require "./parser"
6
6
 
7
- def parse_string(self : CrRuby::VALUE, str : CrRuby::VALUE)
7
+ def parse_string(_self : CrRuby::VALUE, str : CrRuby::VALUE)
8
8
  st = CrRuby.rb_str_to_str(str)
9
9
  string = String.new(CrRuby.rb_string_value_cstr(pointerof(st)))
10
10
 
11
11
  output = begin
12
12
  Gloss.parse_string(string)
13
13
  rescue e : Crystal::SyntaxException
14
- pp e.backtrace
15
14
  e.to_s
16
15
  end
17
16
 
@@ -19,7 +19,7 @@ module Rb
19
19
  abstract class NodeWithChildren < Node
20
20
  @info : NamedTuple(type: String, children: Array(Node))
21
21
 
22
- def initialize(@children : Array(Node))
22
+ def initialize(@children : Array(Node), location : Crystal::Location?)
23
23
  @info = {
24
24
  type: self.class.name.split("::").last,
25
25
  children: @children,
@@ -32,7 +32,7 @@ module Rb
32
32
  abstract class NodeWithValue < Node
33
33
  @info : NamedTuple(type: String, value: String)
34
34
 
35
- def initialize(@value : String)
35
+ def initialize(@value : String, location : Crystal::Location?)
36
36
  @info = {
37
37
  type: self.class.name.split("::").last,
38
38
  value: @value,
@@ -43,13 +43,14 @@ module Rb
43
43
  end
44
44
 
45
45
  class Block < Node
46
- @info : NamedTuple(type: String, args: Array(Var), body: Node)
46
+ @info : NamedTuple(type: String, positional_args: Array(Var), body: Node, rest_p_args: Node?)
47
47
 
48
- def initialize(args, body)
48
+ def initialize(args, splat, body, location : Crystal::Location?)
49
49
  @info = {
50
50
  type: self.class.name.split("::").last,
51
51
  body: body,
52
- args: args,
52
+ positional_args: args,
53
+ rest_p_args: splat
53
54
  }
54
55
  end
55
56
 
@@ -62,7 +63,7 @@ module Rb
62
63
  class ClassNode < Node
63
64
  @info : NamedTuple(type: String, name: Path, body: Node, superclass: Node?, type_vars: Array(String)?, abstract: Bool)
64
65
 
65
- def initialize(name : Path, body : Node, superclass : Node?, type_vars : Array(String)?, abstr : Bool)
66
+ def initialize(name : Path, body : Node, superclass : Node?, type_vars : Array(String)?, abstr : Bool, location : Crystal::Location?)
66
67
  @info = {
67
68
  type: self.class.name.split("::").last,
68
69
  name: name,
@@ -80,7 +81,7 @@ module Rb
80
81
  class ModuleNode < Node
81
82
  @info : NamedTuple(type: String, name: Path, body: Node, type_vars: Array(String)?)
82
83
 
83
- def initialize(name : Path, body : Node, type_vars : Array(String)?)
84
+ def initialize(name : Path, body : Node, type_vars : Array(String)?, location : Crystal::Location?)
84
85
  @info = {
85
86
  type: self.class.name.split("::").last,
86
87
  name: name,
@@ -106,7 +107,8 @@ module Rb
106
107
  body : Node,
107
108
  return_type : Node?,
108
109
  yields : Int32?,
109
- block_arg : Node?
110
+ block_arg : Node?,
111
+ location : Crystal::Location?
110
112
  )
111
113
  @info = {
112
114
  type: self.class.name.split("::").last,
@@ -129,7 +131,8 @@ module Rb
129
131
  @info : NamedTuple(type: String, name: String, external_name: String, value: Node?,
130
132
  restriction: Node?, keyword_arg: Bool)
131
133
 
132
- def initialize(name : String, external_name : String, restriction : Node?, value : Node?, keyword_arg)
134
+ def initialize(name : String, external_name : String, restriction : Node?, value : Node?,
135
+ keyword_arg, location : Crystal::Location?)
133
136
  @info = {
134
137
  type: self.class.name.split("::").last,
135
138
  name: name,
@@ -146,7 +149,7 @@ module Rb
146
149
  class LiteralNode < Node
147
150
  @info : NamedTuple(type: String, value: String | Int32 | Bool | Nil, rb_type: String)
148
151
 
149
- def initialize(value, rb_type : RbLiteral)
152
+ def initialize(value, rb_type : RbLiteral, location : Crystal::Location?)
150
153
  val = case rb_type
151
154
  when Rb::AST::RbLiteral::TrueClass
152
155
  true
@@ -172,7 +175,7 @@ module Rb
172
175
  class ArrayLiteral < Node
173
176
  @info : NamedTuple(type: String, elements: Array(Node), frozen: Bool)
174
177
 
175
- def initialize(elems, frozen = false)
178
+ def initialize(elems, location : Crystal::Location?, frozen = false)
176
179
  @info = {
177
180
  type: self.class.name.split("::").last,
178
181
  elements: elems,
@@ -186,7 +189,7 @@ module Rb
186
189
  class HashLiteral < Node
187
190
  @info : NamedTuple(type: String, elements: Array(Tuple(Node, Node)) | Array(Tuple(String, Node)), frozen: Bool)
188
191
 
189
- def initialize(elems, frozen = false)
192
+ def initialize(elems, location : Crystal::Location?, frozen = false)
190
193
  @info = {
191
194
  type: self.class.name.split("::").last,
192
195
  elements: elems,
@@ -200,7 +203,7 @@ module Rb
200
203
  class RangeLiteral < Node
201
204
  @info : NamedTuple(type: String, from: Node, to: Node, exclusive: Bool)
202
205
 
203
- def initialize(from, to, exclusive)
206
+ def initialize(from, to, exclusive, location : Crystal::Location?)
204
207
  @info = {
205
208
  type: self.class.name.split("::").last,
206
209
  from: from,
@@ -215,7 +218,7 @@ module Rb
215
218
  class RegexLiteral < Node
216
219
  @info : NamedTuple(type: String, value: Node)
217
220
 
218
- def initialize(value)
221
+ def initialize(value, location : Crystal::Location?)
219
222
  @info = {
220
223
  type: self.class.name.split("::").last,
221
224
  value: value,
@@ -236,7 +239,7 @@ module Rb
236
239
  end
237
240
 
238
241
  class EmptyNode < Nop
239
- def initialize(class_name : String)
242
+ def initialize(class_name : String, location : Crystal::Location?)
240
243
  STDERR.puts "Encountered a ruby EmptyNode class name: #{class_name}"
241
244
  @info = {
242
245
  type: self.class.name.split("::").last,
@@ -247,7 +250,7 @@ module Rb
247
250
  class Var < Node
248
251
  @info : NamedTuple(type: String, name: String)
249
252
 
250
- def initialize(@name : String)
253
+ def initialize(@name : String, location : Crystal::Location?)
251
254
  @info = {
252
255
  type: self.class.name.split("::").last,
253
256
  name: @name,
@@ -266,7 +269,7 @@ module Rb
266
269
  abstract class Conditional < Node
267
270
  @info : NamedTuple(type: String, condition: Node, then: Node, else: Node)
268
271
 
269
- def initialize(@condition : Node, @thn : Node, @els : Node)
272
+ def initialize(@condition : Node, @thn : Node, @els : Node, location : Crystal::Location?)
270
273
  @info = {
271
274
  type: self.class.name.split("::").last,
272
275
  condition: @condition,
@@ -287,7 +290,7 @@ module Rb
287
290
  class Case < Node
288
291
  @info : NamedTuple(type: String, condition: Node?, whens: Array(When), else: Node?, exhaustive: Bool)
289
292
 
290
- def initialize(cond : Node?, whens : Array(When), els : Node?, exhaustive : Bool)
293
+ def initialize(cond : Node?, whens : Array(When), els : Node?, exhaustive : Bool, location : Crystal::Location?)
291
294
  @info = {
292
295
  type: self.class.name.split("::").last,
293
296
  condition: cond,
@@ -303,7 +306,7 @@ module Rb
303
306
  class When < Node
304
307
  @info : NamedTuple(type: String, conditions: Array(Node), body: Node, exhaustive: Bool)
305
308
 
306
- def initialize(conds : Array(Node), body : Node, exhaustive : Bool)
309
+ def initialize(conds : Array(Node), body : Node, exhaustive : Bool, location : Crystal::Location?)
307
310
  @info = {
308
311
  type: self.class.name.split("::").last,
309
312
  conditions: conds,
@@ -318,7 +321,7 @@ module Rb
318
321
  class Enum < Node
319
322
  @info : NamedTuple(type: String, name: Crystal::Path, members: Array(Node))
320
323
 
321
- def initialize(@name : Crystal::Path, @members : Array(Node))
324
+ def initialize(@name : Crystal::Path, @members : Array(Node), location : Crystal::Location?)
322
325
  @info = {
323
326
  type: self.class.name.split("::").last,
324
327
  name: @name,
@@ -332,8 +335,7 @@ module Rb
332
335
  class Call < Node
333
336
  @info : NamedTuple(type: String, name: String, args: Array(Node), object: Node?, block: Block?, block_arg: Node?, named_args: Array(Arg)?, has_parentheses: Bool)
334
337
 
335
- def initialize(object : Node?, name : String, args : Array(Node), named_args, block,
336
- block_arg, has_parentheses)
338
+ def initialize(object : Node?, name : String, args : Array(Node), named_args, block, block_arg, has_parentheses, location : Crystal::Location?)
337
339
  @info = {
338
340
  type: self.class.name.split("::").last,
339
341
  name: name,
@@ -358,7 +360,7 @@ module Rb
358
360
  class StringInterpolation < Node
359
361
  @info : NamedTuple(type: String, contents: Array(Node))
360
362
 
361
- def initialize(contents)
363
+ def initialize(contents, location : Crystal::Location?)
362
364
  @info = {
363
365
  type: self.class.name.split("::").last,
364
366
  contents: contents,
@@ -371,7 +373,7 @@ module Rb
371
373
  class UnaryExpr < Node
372
374
  @info : NamedTuple(type: String, op: String, value: Node, with_parens: Bool)
373
375
 
374
- def initialize(val, op, parens)
376
+ def initialize(val, op, parens, location : Crystal::Location?)
375
377
  @info = {
376
378
  type: self.class.name.split("::").last,
377
379
  value: val,
@@ -386,7 +388,7 @@ module Rb
386
388
  class BinaryOp < Node
387
389
  @info : NamedTuple(type: String, op: String, left: Node, right: Node)
388
390
 
389
- def initialize(op, left, right)
391
+ def initialize(op, left, right, location : Crystal::Location?)
390
392
  @info = {
391
393
  type: self.class.name.split("::").last,
392
394
  left: left,
@@ -401,7 +403,7 @@ module Rb
401
403
  class Assign < Node
402
404
  @info : NamedTuple(type: String, op: String?, target: Node, value: Node)
403
405
 
404
- def initialize(target, value, op = nil)
406
+ def initialize(target, value, op, location : Crystal::Location?)
405
407
  @info = {
406
408
  type: self.class.name.split("::").last,
407
409
  target: target,
@@ -416,7 +418,7 @@ module Rb
416
418
  class MultiAssign < Node
417
419
  @info : NamedTuple(type: String, targets: Array(Node), values: Array(Node))
418
420
 
419
- def initialize(targets, values)
421
+ def initialize(targets, values, location : Crystal::Location?)
420
422
  @info = {
421
423
  type: self.class.name.split("::").last,
422
424
  targets: targets,
@@ -430,7 +432,7 @@ module Rb
430
432
  class TypeDeclaration < Node
431
433
  @info : NamedTuple(type: String, var: Node, declared_type: Node, value: Node?, var_type: String)
432
434
 
433
- def initialize(@var : Node, @declared_type : Node, @value : Node?)
435
+ def initialize(@var : Node, @declared_type : Node, @value : Node?, location : Crystal::Location?)
434
436
  @info = {
435
437
  type: self.class.name.split("::").last,
436
438
  var: @var,
@@ -446,7 +448,7 @@ module Rb
446
448
  class MacroFor < Node
447
449
  @info : NamedTuple(type: String, vars: Array(Var), expr: Node, body: Node)
448
450
 
449
- def initialize(vars, expr, body)
451
+ def initialize(vars, expr, body, location : Crystal::Location?)
450
452
  @info = {
451
453
  type: self.class.name.split("::").last,
452
454
  vars: vars,
@@ -467,7 +469,7 @@ module Rb
467
469
  class MacroExpression < Node
468
470
  @info : NamedTuple(type: String, expr: Node, output: Bool)
469
471
 
470
- def initialize(expr, output)
472
+ def initialize(expr, output, location : Crystal::Location?)
471
473
  @info = {
472
474
  type: self.class.name.split("::").last,
473
475
  expr: expr,
@@ -481,7 +483,7 @@ module Rb
481
483
  class ControlExpression < Node
482
484
  @info : NamedTuple(type: String, value: Node?)
483
485
 
484
- def initialize(value)
486
+ def initialize(value, location : Crystal::Location?)
485
487
  @info = {
486
488
  type: self.class.name.split("::").last,
487
489
  value: value,
@@ -504,7 +506,7 @@ module Rb
504
506
  @info : NamedTuple(type: String, body: Node, rescues: Array(Rescue)?, else: Node?,
505
507
  ensure: Node?)
506
508
 
507
- def initialize(body, rescues, else_node, ensure_node)
509
+ def initialize(body, rescues, else_node, ensure_node, location : Crystal::Location?)
508
510
  @info = {
509
511
  type: self.class.name.split("::").last,
510
512
  body: body,
@@ -520,7 +522,7 @@ module Rb
520
522
  class Rescue < Node
521
523
  @info : NamedTuple(type: String, body: Node, types: Array(Node)?, name: String?)
522
524
 
523
- def initialize(body, types, name)
525
+ def initialize(body, types, name, location : Crystal::Location?)
524
526
  @info = {
525
527
  type: self.class.name.split("::").last,
526
528
  body: body,
@@ -535,7 +537,7 @@ module Rb
535
537
  class Union < Node
536
538
  @info : NamedTuple(type: String, types: Array(Node))
537
539
 
538
- def initialize(types)
540
+ def initialize(types, location : Crystal::Location?)
539
541
  @info = {
540
542
  type: self.class.name.split("::").last,
541
543
  types: types,
@@ -548,7 +550,7 @@ module Rb
548
550
  class Generic < Node
549
551
  @info : NamedTuple(type: String, name: Node, args: Array(Node))
550
552
 
551
- def initialize(name, args)
553
+ def initialize(name, args, location : Crystal::Location?)
552
554
  @info = {
553
555
  type: self.class.name.split("::").last,
554
556
  name: name,
@@ -562,7 +564,7 @@ module Rb
562
564
  class Proc < Node
563
565
  @info : NamedTuple(type: String, function: DefNode)
564
566
 
565
- def initialize(function)
567
+ def initialize(function, location : Crystal::Location?)
566
568
  @info = {
567
569
  type: self.class.name.split("::").last,
568
570
  function: function,
@@ -575,7 +577,7 @@ module Rb
575
577
  class NodeWithNameNode < Node
576
578
  @info : NamedTuple(type: String, name: Node)
577
579
 
578
- def initialize(name)
580
+ def initialize(name, location : Crystal::Location?)
579
581
  @info = {
580
582
  type: self.class.name.split("::").last,
581
583
  name: name,
@@ -594,7 +596,7 @@ module Rb
594
596
  class VisibilityModifier < Node
595
597
  @info : NamedTuple(type: String, visibility: String, exp: Node)
596
598
 
597
- def initialize(visibility : Crystal::Visibility, exp : Node)
599
+ def initialize(visibility : Crystal::Visibility, exp : Node, location : Crystal::Location?)
598
600
  vis = case visibility
599
601
  when Crystal::Visibility::Public
600
602
  "public"
data/lib/gloss.rb CHANGED
@@ -1,10 +1,12 @@
1
- # frozen_string_literal: true
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
2
5
 
3
6
  require "rbs"
4
7
  require "json"
5
8
  require "steep"
6
9
  require "fast_blank"
7
-
8
10
  require "gloss/version"
9
11
  require "gloss/cli"
10
12
  require "gloss/watcher"
@@ -15,10 +17,16 @@ require "gloss/config"
15
17
  require "gloss/writer"
16
18
  require "gloss/source"
17
19
  require "gloss/scope"
18
- require "gloss/builder"
20
+ require "gloss/visitor"
19
21
  require "gloss/errors"
20
-
21
- require "gls" unless ENV["CI"] # a bit of a hack for now
22
-
23
- EMPTY_ARRAY = [].freeze
22
+ require "gloss/logger"
23
+ require "gloss/prog_loader"
24
+ require "gloss/utils"
25
+ is_ci = ENV.fetch("CI") { ||
26
+ false}
27
+ unless is_ci
28
+ require "gls"
29
+ end
30
+ EMPTY_ARRAY = Array.new
31
+ .freeze
24
32
  EMPTY_HASH = {}.freeze
data/lib/gloss/cli.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  ##### This file was generated by Gloss; any changes made here will be overwritten.
4
4
  ##### See src/ to make changes
5
5
 
6
- require "optparse"
6
+ require "optparse"
7
7
  module Gloss
8
8
  class CLI
9
9
  def initialize(argv)
@@ -11,43 +11,86 @@ module Gloss
11
11
  end
12
12
  def run()
13
13
  command = @argv.first
14
- files = @argv.[]((1..-1))
14
+ files = @argv.[](((1)..(-1)))
15
+ err_msg = catch(:"error") { ||
15
16
  case command
16
- when "watch"
17
- Watcher.new
17
+ when "init"
18
+ force = false
19
+ OptionParser.new() { |opt|
20
+ opt.on("--force", "-f") { ||
21
+ force = true
22
+ }
23
+ }
24
+ .parse(@argv)
25
+ Initializer.new(force)
26
+ .run
27
+ when "version", "--version", "-v"
28
+ puts(Gloss::VERSION)
29
+ when "watch", "build"
30
+ type_checker = ProgLoader.new
31
+ .run
32
+ (if command.==("watch")
33
+ files = files.map() { |f|
34
+ path = (if Pathname.new(f)
35
+ .absolute?
36
+ f
37
+ else
38
+ File.join(Dir.pwd, f)
39
+ end)
40
+ (if Pathname.new(path)
41
+ .exist?
42
+ path
43
+ else
44
+ throw(:"error", "Pathname #{f} does not exist")
45
+ end)
46
+ }
47
+ Watcher.new(files)
18
48
  .watch
19
- when "build"
20
- (if files.empty?
21
- Dir.glob("#{Config.src_dir}/**/*.gl")
22
- else
23
- files
24
- end)
25
- .each() { |fp|
26
- puts("=====> Building #{fp}")
27
- content = File.read(fp)
28
- tree_hash = Parser.new(content)
49
+ else
50
+ (if command.==("build")
51
+ entry_tree = Parser.new(File.read(Config.entrypoint))
29
52
  .run
30
- type_checker = TypeChecker.new
31
- rb_output = Builder.new(tree_hash, type_checker)
53
+ Visitor.new(entry_tree, type_checker)
32
54
  .run
33
- type_checker.run(rb_output)
34
- puts("=====> Writing #{fp}")
35
- Writer.new(rb_output, fp)
55
+ (if files.empty?
56
+ files = Dir.glob("#{Config.src_dir}/**/*.gl")
57
+ end)
58
+ files.each() { |fp|
59
+ fp = File.absolute_path(fp)
60
+ preloaded_output = OUTPUT_BY_PATH.fetch(fp) { ||
61
+ nil }
62
+ (if preloaded_output
63
+ rb_output = preloaded_output
64
+ else
65
+ Gloss.logger
66
+ .info("Building #{fp}")
67
+ content = File.read(fp)
68
+ tree_hash = Parser.new(content)
36
69
  .run
37
- }
38
- when "init"
39
- force = false
40
- OptionParser.new() { |opt|
41
- opt.on("--force", "-f") { ||
42
- force = true
43
- }
44
- }
45
- .parse(@argv)
46
- Initializer.new(force)
70
+ rb_output = Visitor.new(tree_hash, type_checker)
47
71
  .run
48
- else
49
- abort("Gloss doesn't know how to #{command}")
50
- end
72
+ end)
73
+ Gloss.logger
74
+ .info("Type checking #{fp}")
75
+ type_checker.run(fp, rb_output)
76
+ }
77
+ files.each() { |fp|
78
+ fp = File.absolute_path(fp)
79
+ rb_output = OUTPUT_BY_PATH.fetch(fp)
80
+ Gloss.logger
81
+ .info("Writing #{fp}")
82
+ Writer.new(rb_output, fp)
83
+ .run
84
+ }
85
+ end)
86
+ end)
87
+ else
88
+ throw(:"error", "Gloss doesn't know how to #{command}")
89
+ end
90
+ nil }
91
+ (if err_msg
92
+ abort(err_msg)
93
+ end)
51
94
  end
52
95
  end
53
96
  end