gloss 0.0.2 → 0.1.0

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 (61) 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} +1 -1
  5. data/.gloss.yml +1 -0
  6. data/.rspec +1 -0
  7. data/Gemfile.lock +25 -27
  8. data/README.md +36 -5
  9. data/exe/gloss +13 -2
  10. data/ext/gloss/{src/lib → lib}/cr_ruby.cr +0 -0
  11. data/ext/gloss/lib/rbs_types.cr +3 -0
  12. data/ext/gloss/spec/parser_spec.cr +83 -50
  13. data/ext/gloss/src/cr_ast.cr +146 -72
  14. data/ext/gloss/src/gloss.cr +2 -2
  15. data/ext/gloss/src/lexer.cr +59 -1
  16. data/ext/gloss/src/parser.cr +4 -4
  17. data/ext/gloss/src/rb_ast.cr +152 -57
  18. data/lib/gloss.rb +15 -7
  19. data/lib/gloss/cli.rb +85 -27
  20. data/lib/gloss/config.rb +18 -10
  21. data/lib/gloss/errors.rb +13 -7
  22. data/lib/gloss/initializer.rb +11 -6
  23. data/lib/gloss/logger.rb +29 -0
  24. data/lib/gloss/parser.rb +22 -5
  25. data/lib/gloss/prog_loader.rb +141 -0
  26. data/lib/gloss/scope.rb +7 -2
  27. data/lib/gloss/source.rb +17 -14
  28. data/lib/gloss/type_checker.rb +105 -66
  29. data/lib/gloss/utils.rb +44 -0
  30. data/lib/gloss/version.rb +6 -1
  31. data/lib/gloss/visitor.rb +667 -0
  32. data/lib/gloss/watcher.rb +63 -19
  33. data/lib/gloss/writer.rb +35 -18
  34. data/sig/core.rbs +2 -0
  35. data/sig/fast_blank.rbs +4 -0
  36. data/sig/gls.rbs +3 -0
  37. data/sig/listen.rbs +1 -0
  38. data/sig/optparse.rbs +6 -0
  39. data/sig/rubygems.rbs +9 -0
  40. data/sig/yaml.rbs +3 -0
  41. data/src/exe/gloss +19 -0
  42. data/src/lib/gloss.gl +26 -0
  43. data/src/lib/gloss/cli.gl +70 -0
  44. data/src/lib/gloss/config.gl +21 -0
  45. data/src/lib/gloss/errors.gl +11 -0
  46. data/src/lib/gloss/initializer.gl +20 -0
  47. data/src/lib/gloss/logger.gl +21 -0
  48. data/src/lib/gloss/parser.gl +31 -0
  49. data/src/lib/gloss/prog_loader.gl +133 -0
  50. data/src/lib/gloss/scope.gl +7 -0
  51. data/src/lib/gloss/source.gl +32 -0
  52. data/src/lib/gloss/type_checker.gl +119 -0
  53. data/src/lib/gloss/utils.gl +38 -0
  54. data/src/lib/gloss/version.gl +3 -0
  55. data/src/lib/gloss/visitor.gl +575 -0
  56. data/src/lib/gloss/watcher.gl +66 -0
  57. data/src/lib/gloss/writer.gl +35 -0
  58. metadata +35 -8
  59. data/lib/gloss/builder.rb +0 -393
  60. data/src/lib/hrb/initializer.gl +0 -22
  61. data/src/lib/hrb/watcher.gl +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0bcae87434234732f58cc6d0bb9a1408a72fae1f51b9fe0c1dcf86249784fe2
4
- data.tar.gz: d3db73f4c6e907a0b11eaba71f4428680372b56df1e3e6d8df973e80c8346e26
3
+ metadata.gz: 2f2a161efc722fa324547e073280e488143cd33141d9267609419d72894bcffc
4
+ data.tar.gz: 163032e06b8c91cdd1286b423846ff6a41a278a3fef7ed19bac5dcd21fb85e87
5
5
  SHA512:
6
- metadata.gz: d58d4583ec2c703c023741bc6fd211fd146d81e3e90b3c882b5c4e37aa4cb12de2ad8cf46f6c26a7bf392cfd6accc1372cbaa01be8eb763468918d0a60d05eba
7
- data.tar.gz: ab6244066db5797def1d7225598c87e5bd9cde3385b303854e176332a96c16f8fbbe6f4a531dadb6fe6e22e9d860152daab4b5d4282af79646f7421ce4cde0e3
6
+ metadata.gz: 636bafe05b90c4b46f27a91b3d29d653a37cd3fcf083b6e80326be5b665fa48ba5648ae65a3b7eb7b7eba79c610ed3fee44f1ef586d4fcace105a9955ddc1299
7
+ data.tar.gz: 73fba2b35872586cfe17253f9a295c7c277fd4c298e796300f882386b555ea13e367bc2a2de2a153f12a053df9608ae89999803c893163ba8ebf7c73f0dee7aa
data/.gitattributes ADDED
@@ -0,0 +1,3 @@
1
+ lib/gloss/**/*.rb linguist-generated
2
+ # this will basically cover 99% of the syntax anyway
3
+ **/*.gl linguist-language=Crystal
@@ -1,4 +1,4 @@
1
- name: Crystal CI
1
+ name: Crystal Specs
2
2
 
3
3
  on:
4
4
  push:
@@ -5,7 +5,7 @@
5
5
  # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
6
  # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
7
 
8
- name: Ruby
8
+ name: Ruby Specs
9
9
 
10
10
  on:
11
11
  push:
data/.gloss.yml CHANGED
@@ -1,3 +1,4 @@
1
1
  ---
2
2
  frozen_string_literals: true
3
3
  src_dir: src
4
+ entrypoint: src/exe/gloss
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gloss (0.0.2)
4
+ gloss (0.1.0)
5
5
  fast_blank
6
6
  listen
7
7
  rbs
@@ -10,30 +10,29 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- activesupport (6.1.0)
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)
17
17
  tzinfo (~> 2.0)
18
18
  zeitwerk (~> 2.3)
19
19
  ast (2.4.1)
20
- ast_utils (0.3.0)
21
- parser (~> 2.4)
22
- thor (>= 0.19)
20
+ ast_utils (0.4.0)
21
+ parser (>= 2.7.0)
23
22
  byebug (11.1.3)
24
23
  coderay (1.1.3)
25
- concurrent-ruby (1.1.7)
24
+ concurrent-ruby (1.1.8)
26
25
  diff-lcs (1.4.4)
27
26
  fast_blank (1.0.0)
28
27
  ffi (1.14.2)
29
- i18n (1.8.6)
28
+ i18n (1.8.8)
30
29
  concurrent-ruby (~> 1.0)
31
30
  language_server-protocol (3.15.0.1)
32
- listen (3.4.0)
31
+ listen (3.4.1)
33
32
  rb-fsevent (~> 0.10, >= 0.10.3)
34
33
  rb-inotify (~> 0.9, >= 0.9.10)
35
34
  method_source (1.0.0)
36
- minitest (5.14.2)
35
+ minitest (5.14.3)
37
36
  parallel (1.20.1)
38
37
  parser (2.7.2.0)
39
38
  ast (~> 2.4.1)
@@ -44,49 +43,48 @@ GEM
44
43
  byebug (~> 11.0)
45
44
  pry (~> 0.13.0)
46
45
  rainbow (3.0.0)
47
- rake (13.0.1)
46
+ rake (13.0.3)
48
47
  rake-compiler (1.1.1)
49
48
  rake
50
49
  rb-fsevent (0.10.4)
51
50
  rb-inotify (0.10.1)
52
51
  ffi (~> 1.0)
53
- rbs (1.0.0)
54
- regexp_parser (2.0.0)
52
+ rbs (1.0.4)
53
+ regexp_parser (2.0.3)
55
54
  rexml (3.2.4)
56
55
  rspec (3.10.0)
57
56
  rspec-core (~> 3.10.0)
58
57
  rspec-expectations (~> 3.10.0)
59
58
  rspec-mocks (~> 3.10.0)
60
- rspec-core (3.10.0)
59
+ rspec-core (3.10.1)
61
60
  rspec-support (~> 3.10.0)
62
- rspec-expectations (3.10.0)
61
+ rspec-expectations (3.10.1)
63
62
  diff-lcs (>= 1.2.0, < 2.0)
64
63
  rspec-support (~> 3.10.0)
65
- rspec-mocks (3.10.0)
64
+ rspec-mocks (3.10.1)
66
65
  diff-lcs (>= 1.2.0, < 2.0)
67
66
  rspec-support (~> 3.10.0)
68
- rspec-support (3.10.0)
69
- rubocop (1.5.1)
67
+ rspec-support (3.10.1)
68
+ rubocop (1.7.0)
70
69
  parallel (~> 1.10)
71
70
  parser (>= 2.7.1.5)
72
71
  rainbow (>= 2.2.2, < 4.0)
73
- regexp_parser (>= 2.0)
72
+ regexp_parser (>= 1.8, < 3.0)
74
73
  rexml
75
- rubocop-ast (>= 1.2.0)
74
+ rubocop-ast (>= 1.2.0, < 2.0)
76
75
  ruby-progressbar (~> 1.7)
77
76
  unicode-display_width (>= 1.4.0, < 2.0)
78
- rubocop-ast (1.3.0)
77
+ rubocop-ast (1.4.0)
79
78
  parser (>= 2.7.1.5)
80
- ruby-progressbar (1.10.1)
81
- steep (0.39.0)
79
+ ruby-progressbar (1.11.0)
80
+ steep (0.41.0)
82
81
  activesupport (>= 5.1)
83
- ast_utils (~> 0.3.0)
82
+ ast_utils (>= 0.4.0)
84
83
  language_server-protocol (~> 3.15.0.1)
85
84
  listen (~> 3.0)
86
- parser (~> 2.7.0)
85
+ parser (>= 2.7)
87
86
  rainbow (>= 2.2.2, < 4.0)
88
- rbs (~> 1.0.0)
89
- thor (1.0.1)
87
+ rbs (~> 1.0.3)
90
88
  tzinfo (2.0.4)
91
89
  concurrent-ruby (~> 1.0)
92
90
  unicode-display_width (1.7.0)
@@ -103,4 +101,4 @@ DEPENDENCIES
103
101
  rubocop
104
102
 
105
103
  BUNDLED WITH
106
- 2.1.4
104
+ 2.2.3
data/README.md CHANGED
@@ -1,7 +1,15 @@
1
1
  # Gloss
2
+ [![Gem Version](https://badge.fury.io/rb/gloss.svg)](https://rubygems.org/gems/gloss)
3
+ [![Ruby Specs](https://github.com/johansenja/gloss/workflows/Ruby%20Specs/badge.svg)](https://github.com/johansenja/gloss/actions?query=workflow%3A%22Ruby+Specs%22)
4
+ [![Crystal Specs](https://github.com/johansenja/gloss/workflows/Crystal%20Specs/badge.svg)](https://github.com/johansenja/gloss/actions?query=workflow%3A%22Crystal+Specs%22)
5
+ [![Total Downloads](http://ruby-gem-downloads-badge.herokuapp.com/gloss?type=total&color=green&metric=true&label=downloads%20(total)&total_label=)](https://rubygems.org/gems/gloss)
6
+ [![Current Version](http://ruby-gem-downloads-badge.herokuapp.com/gloss?color=green&label=downloads%20(current%20version)&metric=true)](https://rubygems.org/gems/gloss)
7
+ [![Total Views](https://counter.gofiber.io/badge/johansenja/gloss)](https://rubygems.org/gems/gloss)
2
8
 
3
9
  [Gloss](https://en.wikipedia.org/wiki/Gloss_(annotation)) is a high-level programming language based on [Ruby](https://github.com/ruby/ruby) and [Crystal](https://github.com/crystal-lang/crystal), which compiles to ruby; its aims are on transparency,
4
- efficiency, and to enhance ruby's goal of developer happiness and productivity. Some of the features include:
10
+ efficiency, and to enhance ruby's goal of developer happiness and productivity.
11
+
12
+ ### Current features
5
13
 
6
14
  - Type checking, via optional type annotations
7
15
  - Compile-time macros
@@ -10,11 +18,26 @@ efficiency, and to enhance ruby's goal of developer happiness and productivity.
10
18
  - All ruby files are valid gloss files (a small exceptions for now; workarounds are mostly available)
11
19
  - Other syntactic sugar
12
20
 
13
- Coming soon:
14
- - abstract classes
21
+ ### Current Status
22
+
23
+ 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!
24
+
25
+ ### Approx. roadmap:
26
+
27
+ - Improve error handling and logging (currently almost non-existant)
28
+ - Address Linux compatibility (currently more or less non-existant)
29
+ - Implement different strictnesses of type checking
30
+ - Metaprogramming helpers/safety:*
31
+ - Abstract classes and methods
32
+ - Method lookup/existence checking at compile time
33
+ - Method overloading
34
+
35
+ #### Related items:
36
+
37
+ - Rails helpers; probably some time away*
38
+ - Editor plugins/syntax highlighting/langserver; probably some time away*
15
39
 
16
- Maybe on the roadmap:
17
- - Method overloading
40
+ *__Dependent on popularity__
18
41
 
19
42
  ## Examples:
20
43
 
@@ -223,4 +246,12 @@ then
223
246
 
224
247
  then
225
248
 
249
+ `mkdir src && echo "puts 'hello world'" > src/hello_world.gl`
250
+
251
+ then
252
+
226
253
  `gloss build`
254
+
255
+ then
256
+
257
+ `ruby ./hello_world.rb`
data/exe/gloss CHANGED
@@ -1,6 +1,17 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ ##### This file was generated by Gloss; any changes made here will be overwritten.
5
+ ##### See src/ to make changes
2
6
 
3
7
  require "bundler/setup"
4
8
  require "gloss"
5
-
6
- Gloss::CLI.new(ARGV).run
9
+ begin
10
+ Gloss::CLI.new(ARGV)
11
+ .run
12
+ rescue SystemExit
13
+ rescue => e
14
+ abort(" Unexpected error: #{e.class
15
+ .name}\n Message: #{e.message}\n Trace:\n #{e.backtrace
16
+ .join("\n")}\n\n This is probably a bug and may warrant a bug report at https://github.com/johansenja/gloss/issues")
17
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ module Gloss
2
+ class Any; end
3
+ end
@@ -16,13 +16,13 @@ module Gloss
16
16
  Gloss.parse_string("hsh = {}").should be_truthy
17
17
  end
18
18
 
19
- it "parses all kinds of method args" do
20
- output = %q|{"type":"DefNode","name":"abc","body":null,"rp_args":[{"type":"Arg","name":"a","external_name":"a","default_value":null,"restriction":{"type":"Path","value":"Float"},"keyword_arg":false},{"type":"Arg","name":"b","external_name":"b","default_value":null,"restriction":null,"keyword_arg":false},{"type":"Arg","name":"c","external_name":"c","default_value":null,"restriction":null,"keyword_arg":false,splat: "true"},{"type":"Arg","name":"d","external_name":"d","default_value":{"type":"LiteralNode","value":"nil","rb_type":"NilClass"},"restriction":{"type":"Union","types":[{"type":"Path","value":"String"},{"type":"Path","value":"Nil"}]},"keyword_arg":false},{"type":"Arg","name":"e","external_name":"e","default_value":null,"restriction":{"type":"Path","value":"Integer"},"keyword_arg":true},{"type":"Arg","name":"f","external_name":"f","default_value":null,"restriction":null,"keyword_arg":true},{"type":"Arg","name":"g","external_name":"g","default_value":{"type":"LiteralNode","value":"nil","rb_type":"NilClass"},"restriction":{"type":"Path","value":"String"},"keyword_arg":true}],"receiver":null,"return_type":null,"rest_kw_args":{"type":"Arg","name":"h","external_name":"h","default_value":null,"restriction":null,"keyword_arg":false}}|
21
- Gloss.parse_string(<<-GLS).should eq output
22
- def abc(a : Float, b, *c, d : String? = nil, e: : Integer, f:, g: : String = nil, **h)
23
- end
24
- GLS
25
- end
19
+ # it "parses all kinds of method args" do
20
+ # output = %q|{"type":"DefNode","name":"abc","body":null,"rp_args":[{"type":"Arg","name":"a","external_name":"a","default_value":null,"restriction":{"type":"Path","value":"Float"},"keyword_arg":false},{"type":"Arg","name":"b","external_name":"b","default_value":null,"restriction":null,"keyword_arg":false},{"type":"Arg","name":"c","external_name":"c","default_value":null,"restriction":null,"keyword_arg":false,splat: "true"},{"type":"Arg","name":"d","external_name":"d","default_value":{"type":"LiteralNode","value":"nil","rb_type":"NilClass"},"restriction":{"type":"Union","types":[{"type":"Path","value":"String"},{"type":"Path","value":"Nil"}]},"keyword_arg":false},{"type":"Arg","name":"e","external_name":"e","default_value":null,"restriction":{"type":"Path","value":"Integer"},"keyword_arg":true},{"type":"Arg","name":"f","external_name":"f","default_value":null,"restriction":null,"keyword_arg":true},{"type":"Arg","name":"g","external_name":"g","default_value":{"type":"LiteralNode","value":"nil","rb_type":"NilClass"},"restriction":{"type":"Path","value":"String"},"keyword_arg":true}],"receiver":null,"return_type":null,"rest_kw_args":{"type":"Arg","name":"h","external_name":"h","default_value":null,"restriction":null,"keyword_arg":false}}|
21
+ # Gloss.parse_string(<<-GLS).should eq output
22
+ # def abc(a : Float, b, *c, d : String? = nil, e: : Integer, f:, g: : String = nil, **h)
23
+ # end
24
+ # GLS
25
+ # end
26
26
 
27
27
  it "parses rescue with ruby syntax" do
28
28
  Gloss.parse_string(<<-GLOSS).should be_truthy
@@ -35,57 +35,90 @@ module Gloss
35
35
  end
36
36
  GLOSS
37
37
  end
38
- end
39
38
 
40
- it "parses shorthand blocks with ruby syntax" do
41
- Gloss.parse_string("[1].map(&:to_s)").should eq(
42
- %q<{"type":"Call","name":"map","args":[],"object":{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"1","rb_type":"Integer"}],"frozen":false},"block":null,"block_arg":{"type":"LiteralNode","value":":to_s","rb_type":"Symbol"}}>
43
- )
44
- end
39
+ # it "parses shorthand blocks with ruby syntax" do
40
+ # Gloss.parse_string("[1].map(&:to_s)").should eq(
41
+ # %q<{"type":"Call","name":"map","args":[],"object":{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"1","rb_type":"Integer"}],"frozen":false},"block":null,"block_arg":{"type":"LiteralNode","value":":to_s","rb_type":"Symbol"}}>
42
+ # )
43
+ # end
45
44
 
46
- it "parses tuples as frozen arrays" do
47
- Gloss.parse_string("{ 'hello', 'world' }").should eq(
48
- %q<{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"\"hello\"","rb_type":"String"},{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}],"frozen":true}>
49
- )
50
- end
45
+ it "parses tuples as frozen arrays" do
46
+ Gloss.parse_string("{ 'hello', 'world' }").should eq(
47
+ %q<{"type":"ArrayLiteral","elements":[{"type":"LiteralNode","value":"\"hello\"","rb_type":"String"},{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}],"frozen":true}>
48
+ )
49
+ end
51
50
 
52
- it "parses named tuples as frozen hashes" do
53
- Gloss.parse_string("{ hello: 'world' }").should eq(
54
- %q<{"type":"HashLiteral","elements":[["hello",{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}]],"frozen":true}>
55
- )
56
- end
51
+ it "parses named tuples as frozen hashes" do
52
+ Gloss.parse_string("{ hello: 'world' }").should eq(
53
+ %q<{"type":"HashLiteral","elements":[["hello",{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}]],"frozen":true}>
54
+ )
55
+ end
57
56
 
58
- it "parses the and operator" do
59
- Gloss.parse_string("puts 'hello world' if 1 and 2").should be_truthy
60
- end
57
+ # it "parses the and operator" do
58
+ # Gloss.parse_string("puts 'hello world' if 1 and 2").should be_truthy
59
+ # end
61
60
 
62
- it "parses the or operator" do
63
- Gloss.parse_string("puts 'hello world' if true or false").should be_truthy
64
- end
61
+ # it "parses the or operator" do
62
+ # Gloss.parse_string("puts 'hello world' if true or false").should be_truthy
63
+ # end
65
64
 
66
- it "parses the not operator" do
67
- Gloss.parse_string("puts 'hello world' if true and not false").should be_truthy
68
- end
65
+ # it "parses the not operator" do
66
+ # Gloss.parse_string("puts 'hello world' if true and not false").should be_truthy
67
+ # end
69
68
 
70
- it "parses global variables" do
71
- Gloss.parse_string("$var : String = 'hello world'").should eq(
72
- %q|{"type":"TypeDeclaration","var":{"type":"GlobalVar","name":"$var"},"declared_type":{"type":"Path","value":"String"},"value":{"type":"LiteralNode","value":"\"hello world\"","rb_type":"String"},"var_type":"GlobalVar"}|
73
- )
74
- end
69
+ it "parses global variables" do
70
+ Gloss.parse_string("$var : String = 'hello world'").should eq(
71
+ %q|{"type":"TypeDeclaration","var":{"type":"GlobalVar","name":"$var"},"declared_type":{"type":"Path","value":"String"},"value":{"type":"LiteralNode","value":"\"hello world\"","rb_type":"String"},"var_type":"GlobalVar"}|
72
+ )
73
+ end
75
74
 
76
- it "parses for loops" do
77
- Gloss.parse_string(<<-GLS).should be_truthy
78
- for k, v in { hello: world }
79
- puts key: k, value: v
80
- end
81
- GLS
82
- end
75
+ # it "parses for loops" do
76
+ # Gloss.parse_string(<<-GLS).should be_truthy
77
+ # for k, v in { hello: world }
78
+ # puts key: k, value: v
79
+ # end
80
+ # GLS
81
+ # end
82
+
83
+ it "parses generics as RBS generics" do
84
+ expected =
85
+ %q|{"type":"TypeDeclaration","var":{"type":"Var","name":"hsh"},"declared_type":{"type":"Generic","name":{"type":"Path","value":"Hash"},"args":[{"type":"Path","value":"String"},{"type":"Path","value":"String"}]},"value":{"type":"HashLiteral","elements":[[{"type":"LiteralNode","value":"\"hello\"","rb_type":"String"},{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}]],"frozen":false},"var_type":"Var"}|
86
+ Gloss.parse_string(<<-GLS).should eq expected
87
+ hsh : Hash[String, String] = { "hello" => "world" }
88
+ GLS
89
+ end
90
+
91
+ # it "parses method calls in case statements" do
92
+ # expected =
93
+ # %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}|
94
+ # Gloss.parse_string(<<-GLS).should eq expected
95
+ # case "abc"
96
+ # when .start_with? 'a'
97
+ # 1
98
+ # else
99
+ # 0
100
+ # end
101
+ # GLS
102
+ # end
103
+
104
+ # it "allows constant methods" do
105
+ # Gloss.parse_string(<<-GLS).should be_truthy
106
+ # def Hello(arg = nil)
107
+ # end
108
+
109
+ # Hello()
110
+
111
+ # Hello("a")
112
+ # GLS
113
+ # end
114
+
115
+ # it "requires constant methods to be called with ()" do
116
+ # Gloss.parse_string(<<-GLS).should be_falsey
117
+ # def Hello(arg = nil)
118
+ # end
83
119
 
84
- it "parses generics as RBS generics" do
85
- expected =
86
- %q|{"type":"TypeDeclaration","var":{"type":"Var","name":"hsh"},"declared_type":{"type":"Generic","name":{"type":"Path","value":"Hash"},"args":[{"type":"Path","value":"String"},{"type":"Path","value":"String"}]},"value":{"type":"HashLiteral","elements":[[{"type":"LiteralNode","value":"\"hello\"","rb_type":"String"},{"type":"LiteralNode","value":"\"world\"","rb_type":"String"}]],"frozen":false},"var_type":"Var"}|
87
- Gloss.parse_string(<<-GLS).should eq expected
88
- hsh : Hash[String, String] = { "hello" => "world" }
89
- GLS
120
+ # Hello
121
+ # GLS
122
+ # end
90
123
  end
91
124
  end
@@ -5,7 +5,7 @@ require "./rb_ast"
5
5
  module Crystal
6
6
  abstract class ASTNode
7
7
  def to_rb
8
- Rb::AST::EmptyNode.new(self.class.name)
8
+ Rb::AST::EmptyNode.new(self.class.name, @location)
9
9
  end
10
10
  end
11
11
 
@@ -17,13 +17,13 @@ module Crystal
17
17
 
18
18
  class Expressions < ASTNode
19
19
  def to_rb
20
- Rb::AST::CollectionNode.new(@expressions.map(&.to_rb))
20
+ Rb::AST::CollectionNode.new(@expressions.map(&.to_rb), @location)
21
21
  end
22
22
  end
23
23
 
24
24
  class NilLiteral < ASTNode
25
25
  def to_rb
26
- Rb::AST::LiteralNode.new("nil", Rb::AST::RbLiteral::NilClass)
26
+ Rb::AST::LiteralNode.new("nil", Rb::AST::RbLiteral::NilClass, @location)
27
27
  end
28
28
  end
29
29
 
@@ -31,112 +31,129 @@ module Crystal
31
31
  def to_rb
32
32
  Rb::AST::LiteralNode.new(
33
33
  @value.inspect,
34
- @value ? Rb::AST::RbLiteral::TrueClass : Rb::AST::RbLiteral::FalseClass
35
- )
34
+ @value ? Rb::AST::RbLiteral::TrueClass : Rb::AST::RbLiteral::FalseClass, @location)
36
35
  end
37
36
  end
38
37
 
39
38
  class NumberLiteral < ASTNode
40
39
  def to_rb
41
- Rb::AST::LiteralNode.new(@value, Rb::AST::RbLiteral::Integer)
40
+ Rb::AST::LiteralNode.new(@value, Rb::AST::RbLiteral::Integer, @location)
42
41
  end
43
42
  end
44
43
 
45
44
  class CharLiteral < ASTNode
46
45
  def to_rb
47
- Rb::AST::LiteralNode.new(@value.inspect, Rb::AST::RbLiteral::String)
46
+ Rb::AST::LiteralNode.new(@value.inspect, Rb::AST::RbLiteral::String, @location)
48
47
  end
49
48
  end
50
49
 
51
50
  class StringLiteral < ASTNode
52
51
  def to_rb
53
- Rb::AST::LiteralNode.new(@value.inspect, Rb::AST::RbLiteral::String)
52
+ Rb::AST::LiteralNode.new(@value.inspect, Rb::AST::RbLiteral::String, @location)
54
53
  end
55
54
  end
56
55
 
57
56
  class StringInterpolation < ASTNode
58
57
  def to_rb
59
- Rb::AST::StringInterpolation.new(@expressions.map &.to_rb)
58
+ Rb::AST::StringInterpolation.new(@expressions.map &.to_rb, @location)
60
59
  end
61
60
  end
62
61
 
63
62
  class SymbolLiteral < ASTNode
64
63
  def to_rb
65
- Rb::AST::LiteralNode.new(":#{@value.to_s}", Rb::AST::RbLiteral::Symbol)
64
+ Rb::AST::LiteralNode.new(%{:"#{@value.to_s}"}, Rb::AST::RbLiteral::Symbol, @location)
66
65
  end
67
66
  end
68
67
 
69
68
  class ArrayLiteral < ASTNode
70
69
  def to_rb
71
- Rb::AST::ArrayLiteral.new(@elements.map(&.to_rb))
70
+ Rb::AST::ArrayLiteral.new(@elements.map(&.to_rb), @location)
72
71
  end
73
72
  end
74
73
 
75
74
  class HashLiteral < ASTNode
76
75
  def to_rb
77
- Rb::AST::HashLiteral.new(@entries.map { |e| { e.key.to_rb, e.value.to_rb }})
76
+ Rb::AST::HashLiteral.new(@entries.map { |e| {e.key.to_rb, e.value.to_rb} }, @location)
78
77
  end
79
78
  end
80
79
 
81
80
  class NamedTupleLiteral < ASTNode
82
81
  def to_rb
83
- Rb::AST::HashLiteral.new(@entries.map { |e| { e.key, e.value.to_rb }}, frozen: true)
82
+ Rb::AST::HashLiteral.new(@entries.map { |e| {e.key, e.value.to_rb} }, @location, frozen: true)
84
83
  end
85
84
  end
86
85
 
87
86
  class RangeLiteral < ASTNode
88
87
  def to_rb
89
- Rb::AST::RangeLiteral.new(@from.to_rb, @to.to_rb, @exclusive)
88
+ Rb::AST::RangeLiteral.new(@from.to_rb, @to.to_rb, @exclusive, @location)
90
89
  end
91
90
  end
92
91
 
93
92
  class RegexLiteral < ASTNode
94
93
  def to_rb
95
- Rb::AST::RegexLiteral.new("//")
94
+ Rb::AST::RegexLiteral.new(@value.to_rb, @location)
96
95
  end
97
96
  end
98
97
 
99
98
  class TupleLiteral < ASTNode
100
99
  def to_rb
101
- Rb::AST::ArrayLiteral.new(@elements.map(&.to_rb), frozen: true)
100
+ Rb::AST::ArrayLiteral.new(@elements.map(&.to_rb), @location, frozen: true)
102
101
  end
103
102
  end
104
103
 
105
104
  class Def < ASTNode
106
105
  def to_rb
107
- Rb::AST::DefNode.new(@name, @args.map(&.to_rb), @body.to_rb, receiver.try(&.to_rb),
108
- return_type.try(&.to_rb), @double_splat.try(&.to_rb))
106
+ positional_args = args.dup
107
+ splat = @splat_index ? positional_args.delete_at(@splat_index.as(Int32)) : nil
108
+ Rb::AST::DefNode.new(
109
+ receiver.try(&.to_rb),
110
+ @name,
111
+ positional_args.map(&.to_rb),
112
+ splat.try(&.to_rb),
113
+ @double_splat.try(&.to_rb),
114
+ @body.to_rb,
115
+ return_type.try(&.to_rb),
116
+ @yields,
117
+ @block_arg.try &.to_rb, @location)
109
118
  end
110
119
  end
111
120
 
112
121
  class ClassDef < ASTNode
113
122
  def to_rb
114
- Rb::AST::ClassNode.new(@name.to_rb, @body.to_rb, @superclass.try(&.to_rb), @type_vars, @abstract)
123
+ Rb::AST::ClassNode.new(@name.to_rb, @body.to_rb, @superclass.try(&.to_rb), @type_vars, @abstract, @location)
115
124
  end
116
125
  end
117
126
 
118
127
  class ModuleDef < ASTNode
119
128
  def to_rb
120
- Rb::AST::ModuleNode.new(@name.to_rb, @body.to_rb, @type_vars)
129
+ Rb::AST::ModuleNode.new(@name.to_rb, @body.to_rb, @type_vars, @location)
121
130
  end
122
131
  end
123
132
 
124
133
  class Var < ASTNode
125
134
  def to_rb
126
- Rb::AST::Var.new(@name)
135
+ Rb::AST::Var.new(@name, @location)
127
136
  end
128
137
  end
129
138
 
130
139
  class Block < ASTNode
131
140
  def to_rb
132
- Rb::AST::Block.new(@args.map(&.to_rb), @body.to_rb)
141
+ positional_args = args.dup
142
+ splat = @splat_index ? positional_args.delete_at(@splat_index.as(Int32)) : nil
143
+ Rb::AST::Block.new(positional_args.map(&.to_rb), splat.try &.to_rb, @body.to_rb, @location)
133
144
  end
134
145
  end
135
146
 
136
147
  class Call < ASTNode
137
148
  def to_rb
138
- Rb::AST::Call.new(@obj.try(&.to_rb), @name, @args.map(&.to_rb), @block.try(&.to_rb),
139
- @block_arg.try(&.to_rb))
149
+ Rb::AST::Call.new(
150
+ @obj.try(&.to_rb),
151
+ @name,
152
+ @args.map(&.to_rb),
153
+ @named_args.try(&.map(&.to_rb.as(Rb::AST::Arg))),
154
+ @block.try(&.to_rb),
155
+ @block_arg.try(&.to_rb),
156
+ @has_parentheses, @location)
140
157
  end
141
158
  end
142
159
 
@@ -145,121 +162,121 @@ module Crystal
145
162
 
146
163
  def to_rb
147
164
  Rb::AST::Arg.new(@name, @external_name, @restriction.try(&.to_rb),
148
- @default_value.try(&.to_rb), @keyword_arg)
165
+ @default_value.try(&.to_rb), @keyword_arg, @location)
149
166
  end
150
167
  end
151
168
 
152
169
  class NamedArgument < ASTNode
153
170
  def to_rb
154
- Rb::AST::EmptyNode.new(self.class.name)
171
+ Rb::AST::Arg.new(@name, @name, nil, @value.to_rb, true, @location)
155
172
  end
156
173
  end
157
174
 
158
175
  class If < ASTNode
159
176
  def to_rb
160
- Rb::AST::If.new(@cond.to_rb, @then.to_rb, @else.to_rb)
177
+ Rb::AST::If.new(@cond.to_rb, @then.to_rb, @else.to_rb, @location)
178
+ end
179
+ end
180
+
181
+ class Unless < ASTNode
182
+ def to_rb
183
+ Rb::AST::Unless.new(@cond.to_rb, @then.to_rb, @else.to_rb, @location)
161
184
  end
162
185
  end
163
186
 
164
187
  class Assign < ASTNode
165
188
  def to_rb
166
- Rb::AST::Assign.new(@target.to_rb, @value.to_rb)
189
+ Rb::AST::Assign.new(@target.to_rb, @value.to_rb, nil, @location)
167
190
  end
168
191
  end
169
192
 
170
193
  class OpAssign < ASTNode
171
194
  def to_rb
172
- Rb::AST::Assign.new(@target.to_rb, @value.to_rb, @op)
195
+ Rb::AST::Assign.new(@target.to_rb, @value.to_rb, @op, @location)
173
196
  end
174
197
  end
175
198
 
176
199
  class MultiAssign < ASTNode
177
200
  def to_rb
178
- Rb::AST::EmptyNode.new(self.class.name)
201
+ Rb::AST::MultiAssign.new(@targets.map(&.to_rb), @values.map(&.to_rb), @location)
179
202
  end
180
203
  end
181
204
 
182
205
  class InstanceVar < ASTNode
183
206
  def to_rb
184
- Rb::AST::InstanceVar.new(@name)
207
+ Rb::AST::InstanceVar.new(@name, @location)
185
208
  end
186
209
  end
187
210
 
188
211
  class ReadInstanceVar < ASTNode
189
212
  def to_rb
190
- Rb::AST::EmptyNode.new(self.class.name)
213
+ Rb::AST::EmptyNode.new(self.class.name, @location)
191
214
  end
192
215
  end
193
216
 
194
217
  class ClassVar < ASTNode
195
218
  def to_rb
196
- Rb::AST::EmptyNode.new(self.class.name)
219
+ Rb::AST::EmptyNode.new(self.class.name, @location)
197
220
  end
198
221
  end
199
222
 
200
223
  class Global < ASTNode
201
224
  def to_rb
202
- Rb::AST::GlobalVar.new(@name)
225
+ Rb::AST::GlobalVar.new(@name, @location)
203
226
  end
204
227
  end
205
228
 
206
229
  class Annotation < ASTNode
207
230
  def to_rb
208
- Rb::AST::EmptyNode.new(self.class.name)
209
- end
210
- end
211
-
212
- class MacroExpression < ASTNode
213
- def to_rb
214
- Rb::AST::EmptyNode.new(self.class.name)
231
+ Rb::AST::EmptyNode.new(self.class.name, @location)
215
232
  end
216
233
  end
217
234
 
218
235
  class MacroIf < ASTNode
219
236
  def to_rb
220
- Rb::AST::MacroIf.new(@cond.to_rb, @then.to_rb, @else.to_rb)
237
+ Rb::AST::MacroIf.new(@cond.to_rb, @then.to_rb, @else.to_rb, @location)
221
238
  end
222
239
  end
223
240
 
224
241
  class MacroFor < ASTNode
225
242
  def to_rb
226
- Rb::AST::MacroFor.new(@vars.map(&.to_rb), @exp.to_rb, @body.to_rb)
243
+ Rb::AST::MacroFor.new(@vars.map(&.to_rb), @exp.to_rb, @body.to_rb, @location)
227
244
  end
228
245
  end
229
246
 
230
247
  class MacroVar < ASTNode
231
248
  def to_rb
232
- Rb::AST::EmptyNode.new(self.class.name)
249
+ Rb::AST::EmptyNode.new(self.class.name, @location)
233
250
  end
234
251
  end
235
252
 
236
253
  class MacroExpression < ASTNode
237
254
  def to_rb
238
- Rb::AST::MacroExpression.new(@exp.to_rb, @output)
255
+ Rb::AST::MacroExpression.new(@exp.to_rb, @output, @location)
239
256
  end
240
257
  end
241
258
 
242
259
  class MacroLiteral < ASTNode
243
260
  def to_rb
244
- Rb::AST::MacroLiteral.new(@value)
261
+ Rb::AST::MacroLiteral.new(@value, @location)
245
262
  end
246
263
  end
247
264
 
248
265
  class Annotation < ASTNode
249
266
  def to_rb
250
- Rb::AST::EmptyNode.new(self.class.name)
267
+ Rb::AST::EmptyNode.new(self.class.name, @location)
251
268
  end
252
269
  end
253
270
 
254
271
  class EnumDef < ASTNode
255
272
  def to_rb
256
- Rb::AST::Enum.new(@name, @members.map(&.to_rb))
273
+ Rb::AST::Enum.new(@name, @members.map(&.to_rb), @location)
257
274
  end
258
275
  end
259
276
 
260
277
  class Path < ASTNode
261
278
  def to_rb
262
- Rb::AST::Path.new(full_name)
279
+ Rb::AST::Path.new(full_name, @location)
263
280
  end
264
281
 
265
282
  def full_name
@@ -271,13 +288,13 @@ module Crystal
271
288
 
272
289
  class Require < ASTNode
273
290
  def to_rb
274
- Rb::AST::Require.new(@string)
291
+ Rb::AST::Require.new(@string, @location)
275
292
  end
276
293
  end
277
294
 
278
295
  class TypeDeclaration < ASTNode
279
296
  def to_rb
280
- Rb::AST::TypeDeclaration.new(@var.to_rb, @declared_type.to_rb, @value.try(&.to_rb))
297
+ Rb::AST::TypeDeclaration.new(@var.to_rb, @declared_type.to_rb, @value.try(&.to_rb), @location)
281
298
  end
282
299
  end
283
300
 
@@ -287,18 +304,28 @@ module Crystal
287
304
  @cond.try(&.to_rb),
288
305
  @whens.map(&.to_rb),
289
306
  @else.try(&.to_rb),
290
- @exhaustive
291
- )
307
+ @exhaustive, @location)
292
308
  end
293
309
  end
294
310
 
295
311
  class When < ASTNode
296
312
  def to_rb
297
313
  Rb::AST::When.new(
298
- @conds.map(&.to_rb),
314
+ @conds.map do |c|
315
+ if c.is_a? Call
316
+ arg_name = "x"
317
+ ProcLiteral.new(
318
+ Def.new(
319
+ "->",
320
+ [Arg.new(arg_name)],
321
+ c.tap { |call| call.obj = Var.new(arg_name) })
322
+ ).to_rb
323
+ else
324
+ c.to_rb
325
+ end
326
+ end,
299
327
  @body.to_rb,
300
- @exhaustive
301
- )
328
+ @exhaustive, @location)
302
329
  end
303
330
  end
304
331
 
@@ -318,8 +345,7 @@ module Crystal
318
345
  Rb::AST::UnaryExpr.new(
319
346
  @exp.to_rb,
320
347
  op,
321
- requires_parentheses
322
- )
348
+ requires_parentheses ,@location)
323
349
  end
324
350
  end
325
351
  {% end %}
@@ -334,8 +360,7 @@ module Crystal
334
360
  "||",
335
361
  {% end %}
336
362
  @left.to_rb,
337
- @right.to_rb
338
- )
363
+ @right.to_rb ,@location)
339
364
  end
340
365
  end
341
366
  {% end %}
@@ -343,7 +368,7 @@ module Crystal
343
368
  {% for class_name in %w[Return Break Next] %}
344
369
  class {{class_name.id}} < ControlExpression
345
370
  def to_rb
346
- Rb::AST::{{class_name.id}}.new(@exp.try(&.to_rb))
371
+ Rb::AST::{{class_name.id}}.new(@exp.try(&.to_rb),@location)
347
372
  end
348
373
  end
349
374
  {% end %}
@@ -351,45 +376,94 @@ 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
- @ensure.try(&.to_rb))
379
+ @ensure.try(&.to_rb), @location)
355
380
  end
356
381
  end
357
382
 
358
383
  class Rescue < ASTNode
359
384
  def to_rb
360
- Rb::AST::Rescue.new(@body.to_rb, @types.try(&.map(&.to_rb)), @name)
385
+ Rb::AST::Rescue.new(@body.to_rb, @types.try(&.map(&.to_rb)), @name, @location)
361
386
  end
362
387
  end
363
388
 
364
389
  class Union < ASTNode
365
390
  def to_rb
366
- Rb::AST::Union.new(@types.map(&.to_rb))
391
+ Rb::AST::Union.new(@types.map(&.to_rb), @location)
367
392
  end
368
393
  end
369
394
 
370
395
  class Generic < ASTNode
371
396
  def to_rb
372
- Rb::AST::Generic.new(@name.to_rb, @type_vars.map(&.to_rb))
397
+ Rb::AST::Generic.new(@name.to_rb, @type_vars.map(&.to_rb), @location)
398
+ end
399
+ end
400
+
401
+ class ProcLiteral < ASTNode
402
+ def to_rb
403
+ Rb::AST::Proc.new(@def.to_rb, @location)
404
+ end
405
+ end
406
+
407
+ class Include < ASTNode
408
+ def to_rb
409
+ Rb::AST::Include.new(@name.to_rb, @location)
410
+ end
411
+ end
412
+
413
+ class Extend < ASTNode
414
+ def to_rb
415
+ Rb::AST::Extend.new(@name.to_rb, @location)
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
+ false, @location)
429
+ end
430
+ end
431
+
432
+ class VisibilityModifier < ASTNode
433
+ def to_rb
434
+ Rb::AST::VisibilityModifier.new(@modifier, @exp.to_rb, @location)
435
+ end
436
+ end
437
+
438
+ class Yield < ASTNode
439
+ def to_rb
440
+ Rb::AST::Call.new(
441
+ nil,
442
+ "yield",
443
+ @exps.map(&.to_rb),
444
+ nil,
445
+ nil,
446
+ nil,
447
+ !@exps.empty?, @location)
373
448
  end
374
449
  end
375
450
 
376
- {% for class_name in %w[ProcNotation Macro OffsetOf VisibilityModifier IsA RespondsTo
451
+ {% for class_name in %w[ProcNotation Macro OffsetOf RespondsTo
377
452
  Select ImplicitObj AnnotationDef While Until UninitializedVar
378
- ProcLiteral ProcPointer Self Yield Include
379
- Extend LibDef FunDef TypeDef CStructOrUnionDef ExternalVar Alias
380
- Metaclass Cast NilableCast TypeOf Annotation
453
+ ProcPointer Self LibDef FunDef TypeDef CStructOrUnionDef
454
+ ExternalVar Alias Metaclass Cast NilableCast TypeOf Annotation
381
455
  Underscore MagicConstant Asm AsmOperand] %}
382
456
  class {{class_name.id}} < ASTNode
383
457
  def to_rb
384
- Rb::AST::EmptyNode.new(self.class.name)
458
+ Rb::AST::EmptyNode.new(self.class.name,@location)
385
459
  end
386
460
  end
387
461
  {% end %}
388
462
 
389
- {% for class_name in %w[PointerOf SizeOf InstanceSizeOf Out MacroVerbatim DoubleSplat] %}
463
+ {% for class_name in %w[PointerOf SizeOf InstanceSizeOf Out MacroVerbatim] %}
390
464
  class {{class_name.id}} < UnaryExpression
391
465
  def to_rb
392
- Rb::AST::EmptyNode.new(self.class.name)
466
+ Rb::AST::EmptyNode.new(self.class.name,@location)
393
467
  end
394
468
  end
395
469
  {% end %}