gloss 0.0.4 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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