gloss 0.0.2 → 0.1.0

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