gloss 0.0.4 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +3 -0
  3. data/.github/workflows/{crystal.yml → crystal_specs.yml} +1 -1
  4. data/.github/workflows/{ruby.yml → ruby_specs.yml} +2 -2
  5. data/.gloss.yml +1 -0
  6. data/.rspec +1 -0
  7. data/Gemfile.lock +9 -11
  8. data/README.md +35 -5
  9. data/Rakefile +1 -1
  10. data/exe/gloss +13 -2
  11. data/ext/gloss/Makefile +8 -19
  12. data/ext/gloss/spec/parser_spec.cr +83 -83
  13. data/ext/gloss/src/cr_ast.cr +63 -77
  14. data/ext/gloss/src/gloss.cr +1 -2
  15. data/ext/gloss/src/rb_ast.cr +40 -38
  16. data/lib/gloss.rb +15 -7
  17. data/lib/gloss/cli.rb +75 -32
  18. data/lib/gloss/config.rb +10 -3
  19. data/lib/gloss/errors.rb +1 -1
  20. data/lib/gloss/initializer.rb +6 -5
  21. data/lib/gloss/logger.rb +29 -0
  22. data/lib/gloss/parser.rb +17 -2
  23. data/lib/gloss/prog_loader.rb +141 -0
  24. data/lib/gloss/scope.rb +1 -1
  25. data/lib/gloss/source.rb +1 -1
  26. data/lib/gloss/type_checker.rb +80 -32
  27. data/lib/gloss/utils.rb +44 -0
  28. data/lib/gloss/version.rb +5 -5
  29. data/lib/gloss/{builder.rb → visitor.rb} +125 -74
  30. data/lib/gloss/watcher.rb +47 -11
  31. data/lib/gloss/writer.rb +22 -11
  32. data/sig/core.rbs +2 -0
  33. data/sig/fast_blank.rbs +4 -0
  34. data/sig/{gloss.rbs → gls.rbs} +0 -0
  35. data/sig/optparse.rbs +6 -0
  36. data/sig/rubygems.rbs +9 -0
  37. data/sig/yaml.rbs +3 -0
  38. data/src/exe/gloss +19 -0
  39. data/src/lib/gloss.gl +26 -0
  40. data/src/lib/gloss/cli.gl +53 -24
  41. data/src/lib/gloss/config.gl +9 -3
  42. data/src/lib/gloss/initializer.gl +4 -6
  43. data/src/lib/gloss/logger.gl +21 -0
  44. data/src/lib/gloss/parser.gl +17 -5
  45. data/src/lib/gloss/prog_loader.gl +133 -0
  46. data/src/lib/gloss/scope.gl +0 -2
  47. data/src/lib/gloss/type_checker.gl +85 -39
  48. data/src/lib/gloss/utils.gl +38 -0
  49. data/src/lib/gloss/version.gl +1 -1
  50. data/src/lib/gloss/{builder.gl → visitor.gl} +123 -68
  51. data/src/lib/gloss/watcher.gl +44 -10
  52. data/src/lib/gloss/writer.gl +16 -14
  53. metadata +23 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a630a77074bd1fa44113b542bd04b312957e3d59834dc9dec0282466e60d50a
4
- data.tar.gz: 653fc89b0793a114f9d6a04348a63d76368db464bf93a713268467140551680c
3
+ metadata.gz: 598f28c63b98dc26491f81b56112a067e53700f36136e9da1f2a4fbda60e14fc
4
+ data.tar.gz: 0f39f4a5cd5202bdc280c81b0fac581d06bc9303e58df7ed39ffb993cdfe577f
5
5
  SHA512:
6
- metadata.gz: 0f8573f5596495a00d31c102edf033f010f07092a6441a26809dc7d0044e906651058191ff9b37a87d840cae4fb16916aad76e27d219688824cd06366ef46c3c
7
- data.tar.gz: 22a085469dd74a3c88d3334ac8c75c44ea8e43fbca211acc5e25cd83230bc435b48b262787d6eccacf2efff2f4ed5324aa11a3e102e1aa9bc0ebe1dba04d2564
6
+ metadata.gz: 1d3687951054a991b8c13eae82be7d7ccdb1fd5c2a730ced1b7472a3aa1b59a4fca5471ecc0e2dca00b3abf337a3ebb79bc9e06c3677fc55d30c52f682b332b0
7
+ data.tar.gz: 0b14828108ea3fa140a560a04313ff6c0321f1e968e168532ae9ab092e41291affe9f4feac1f4309d5be63fd6b0b0cb63e48bce1ea6b5652bb947b051913d07e
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:
@@ -16,7 +16,7 @@ on:
16
16
  jobs:
17
17
  test:
18
18
 
19
- runs-on: ubuntu-latest
19
+ runs-on: ubuntu-20.04
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v2
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.4)
4
+ gloss (0.1.2)
5
5
  fast_blank
6
6
  listen
7
7
  rbs
@@ -17,16 +17,15 @@ GEM
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
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.7)
28
+ i18n (1.8.8)
30
29
  concurrent-ruby (~> 1.0)
31
30
  language_server-protocol (3.15.0.1)
32
31
  listen (3.4.1)
@@ -50,7 +49,7 @@ GEM
50
49
  rb-fsevent (0.10.4)
51
50
  rb-inotify (0.10.1)
52
51
  ffi (~> 1.0)
53
- rbs (1.0.3)
52
+ rbs (1.0.4)
54
53
  regexp_parser (2.0.3)
55
54
  rexml (3.2.4)
56
55
  rspec (3.10.0)
@@ -78,15 +77,14 @@ GEM
78
77
  rubocop-ast (1.4.0)
79
78
  parser (>= 2.7.1.5)
80
79
  ruby-progressbar (1.11.0)
81
- steep (0.39.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.1.0)
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)
data/README.md CHANGED
@@ -1,7 +1,14 @@
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)
2
7
 
3
8
  [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:
9
+ efficiency, and to enhance ruby's goal of developer happiness and productivity.
10
+
11
+ ### Current features
5
12
 
6
13
  - Type checking, via optional type annotations
7
14
  - Compile-time macros
@@ -10,11 +17,26 @@ efficiency, and to enhance ruby's goal of developer happiness and productivity.
10
17
  - All ruby files are valid gloss files (a small exceptions for now; workarounds are mostly available)
11
18
  - Other syntactic sugar
12
19
 
13
- Coming soon:
14
- - abstract classes
20
+ ### Current Status
21
+
22
+ 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!
23
+
24
+ ### Approx. roadmap:
25
+
26
+ - Improve error handling and logging (currently almost non-existant)
27
+ - Address Linux compatibility (currently more or less non-existant)
28
+ - Implement different strictnesses of type checking
29
+ - Metaprogramming helpers/safety:*
30
+ - Abstract classes and methods
31
+ - Method lookup/existence checking at compile time
32
+ - Method overloading
33
+
34
+ #### Related items:
35
+
36
+ - Rails helpers; probably some time away*
37
+ - Editor plugins/syntax highlighting/langserver; probably some time away*
15
38
 
16
- Maybe on the roadmap:
17
- - Method overloading
39
+ *__Dependent on popularity__
18
40
 
19
41
  ## Examples:
20
42
 
@@ -223,4 +245,12 @@ then
223
245
 
224
246
  then
225
247
 
248
+ `mkdir src && echo "puts 'hello world'" > src/hello_world.gl`
249
+
250
+ then
251
+
226
252
  `gloss build`
253
+
254
+ then
255
+
256
+ `ruby ./hello_world.rb`
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ RSpec::Core::RakeTask.new :spec do |spec|
18
18
  end
19
19
 
20
20
  task :build do
21
- `cd ext/gloss && make && cd -`
21
+ sh "cd", "ext/gloss", "&&", "make", "all", "&&", "cd", "-"
22
22
  end
23
23
 
24
24
  task :default => [:spec]
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
data/ext/gloss/Makefile CHANGED
@@ -1,26 +1,20 @@
1
1
  CRYSTAL = crystal
2
- TARGET = ../../lib/gls
3
-
4
2
  PLATFORM = $(shell uname -s)
5
3
 
6
4
  ifeq "$(PLATFORM)" "Darwin"
7
- install: all
8
-
9
- all: clean shards build
5
+ TARGET = ../../lib/gls.bundle
10
6
 
11
- shards:
12
- shards
7
+ clean:
8
+ rm -f $(TARGET) $(TARGET).dwarf
9
+ endif
13
10
 
14
- build: ./src/gloss.cr
15
- $(CRYSTAL) build --link-flags "-dynamic -bundle -Wl,-undefined,dynamic_lookup" $< -o $(TARGET).bundle
11
+ ifeq "$(PLATFORM)" "Linux"
12
+ TARGET = ../../lib/gls.so
16
13
 
17
14
  clean:
18
- rm -f $(TARGET).bundle
19
- rm -f $(TARGET).bundle.dwarf
15
+ rm -f $(TARGET)
20
16
  endif
21
17
 
22
- ifeq "$(PLATFORM)" "Linux"
23
- LLVM_TARGET = "$(shell uname -m)-unknown-linux-gnu"
24
18
  install: all
25
19
 
26
20
  all: clean shards build
@@ -29,9 +23,4 @@ shards:
29
23
  shards
30
24
 
31
25
  build: ./src/gloss.cr
32
- $(CRYSTAL) build $< --cross-compile --target $(LLVM_TARGET) --link-flags "-dynamic -bundle -Wl,-undefined,dynamic_lookup" -o $(TARGET)
33
-
34
- clean:
35
- rm -f $(TARGET).o
36
- rm -f $(TARGET).so
37
- endif
26
+ $(CRYSTAL) build --link-flags "-shared -dynamic -Wl,-undefined,dynamic_lookup" $< -o $(TARGET) --release
@@ -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,90 +35,90 @@ module Gloss
35
35
  end
36
36
  GLOSS
37
37
  end
38
- end
39
-
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
45
-
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
51
38
 
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
57
-
58
- it "parses the and operator" do
59
- Gloss.parse_string("puts 'hello world' if 1 and 2").should be_truthy
60
- end
61
-
62
- it "parses the or operator" do
63
- Gloss.parse_string("puts 'hello world' if true or false").should be_truthy
64
- end
65
-
66
- it "parses the not operator" do
67
- Gloss.parse_string("puts 'hello world' if true and not false").should be_truthy
68
- 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
69
44
 
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
75
-
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
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
83
50
 
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
90
- 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
91
56
 
92
- it "parses method calls in case statements" do
93
- expected =
94
- %q|{"type":"Case","condition":{"type":"LiteralNode","value":"\"abc\"","rb_type":"String"},"whens":[{"type":"When","conditions":[{"type":"Proc","function":{"type":"DefNode","name":"->","body":{"type":"Call","name":"start_with?","args":[{"type":"LiteralNode","value":"\"a\"","rb_type":"String"}],"object":{"type":"Var","name":"x"},"block":null,"block_arg":null},"rp_args":[{"type":"Arg","name":"x","external_name":"x","default_value":null,"restriction":null,"keyword_arg":false}],"receiver":null,"return_type":null,"rest_kw_args":null}}],"body":{"type":"LiteralNode","value":"1","rb_type":"Integer"},"exhaustive":false}],"else":{"type":"LiteralNode","value":"0","rb_type":"Integer"},"exhaustive":false}|
95
- Gloss.parse_string(<<-GLS).should eq expected
96
- case "abc"
97
- when .start_with? 'a'
98
- 1
99
- else
100
- 0
101
- end
102
- GLS
103
- end
57
+ # it "parses the and operator" do
58
+ # Gloss.parse_string("puts 'hello world' if 1 and 2").should be_truthy
59
+ # end
104
60
 
105
- it "allows constant methods" do
106
- Gloss.parse_string(<<-GLS).should be_truthy
107
- def Hello(arg = nil)
108
- end
61
+ # it "parses the or operator" do
62
+ # Gloss.parse_string("puts 'hello world' if true or false").should be_truthy
63
+ # end
109
64
 
110
- Hello()
65
+ # it "parses the not operator" do
66
+ # Gloss.parse_string("puts 'hello world' if true and not false").should be_truthy
67
+ # end
111
68
 
112
- Hello("a")
113
- GLS
114
- 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
115
74
 
116
- it "requires constant methods to be called with ()" do
117
- Gloss.parse_string(<<-GLS).should be_falsey
118
- def Hello(arg = nil)
119
- end
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
120
90
 
121
- Hello
122
- GLS
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
119
+
120
+ # Hello
121
+ # GLS
122
+ # end
123
123
  end
124
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,74 +31,73 @@ 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(@value.to_rb)
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
 
@@ -115,32 +114,33 @@ module Crystal
115
114
  @body.to_rb,
116
115
  return_type.try(&.to_rb),
117
116
  @yields,
118
- @block_arg.try &.to_rb
119
- )
117
+ @block_arg.try &.to_rb, @location)
120
118
  end
121
119
  end
122
120
 
123
121
  class ClassDef < ASTNode
124
122
  def to_rb
125
- 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)
126
124
  end
127
125
  end
128
126
 
129
127
  class ModuleDef < ASTNode
130
128
  def to_rb
131
- 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)
132
130
  end
133
131
  end
134
132
 
135
133
  class Var < ASTNode
136
134
  def to_rb
137
- Rb::AST::Var.new(@name)
135
+ Rb::AST::Var.new(@name, @location)
138
136
  end
139
137
  end
140
138
 
141
139
  class Block < ASTNode
142
140
  def to_rb
143
- 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)
144
144
  end
145
145
  end
146
146
 
@@ -153,8 +153,7 @@ module Crystal
153
153
  @named_args.try(&.map(&.to_rb.as(Rb::AST::Arg))),
154
154
  @block.try(&.to_rb),
155
155
  @block_arg.try(&.to_rb),
156
- @has_parentheses
157
- )
156
+ @has_parentheses, @location)
158
157
  end
159
158
  end
160
159
 
@@ -163,127 +162,121 @@ module Crystal
163
162
 
164
163
  def to_rb
165
164
  Rb::AST::Arg.new(@name, @external_name, @restriction.try(&.to_rb),
166
- @default_value.try(&.to_rb), @keyword_arg)
165
+ @default_value.try(&.to_rb), @keyword_arg, @location)
167
166
  end
168
167
  end
169
168
 
170
169
  class NamedArgument < ASTNode
171
170
  def to_rb
172
- Rb::AST::Arg.new(@name, @name, nil, @value.to_rb, true)
171
+ Rb::AST::Arg.new(@name, @name, nil, @value.to_rb, true, @location)
173
172
  end
174
173
  end
175
174
 
176
175
  class If < ASTNode
177
176
  def to_rb
178
- 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)
179
178
  end
180
179
  end
181
180
 
182
181
  class Unless < ASTNode
183
182
  def to_rb
184
- Rb::AST::Unless.new(@cond.to_rb, @then.to_rb, @else.to_rb)
183
+ Rb::AST::Unless.new(@cond.to_rb, @then.to_rb, @else.to_rb, @location)
185
184
  end
186
185
  end
187
186
 
188
187
  class Assign < ASTNode
189
188
  def to_rb
190
- Rb::AST::Assign.new(@target.to_rb, @value.to_rb)
189
+ Rb::AST::Assign.new(@target.to_rb, @value.to_rb, nil, @location)
191
190
  end
192
191
  end
193
192
 
194
193
  class OpAssign < ASTNode
195
194
  def to_rb
196
- Rb::AST::Assign.new(@target.to_rb, @value.to_rb, @op)
195
+ Rb::AST::Assign.new(@target.to_rb, @value.to_rb, @op, @location)
197
196
  end
198
197
  end
199
198
 
200
199
  class MultiAssign < ASTNode
201
200
  def to_rb
202
- Rb::AST::MultiAssign.new(@targets.map(&.to_rb), @values.map(&.to_rb))
201
+ Rb::AST::MultiAssign.new(@targets.map(&.to_rb), @values.map(&.to_rb), @location)
203
202
  end
204
203
  end
205
204
 
206
205
  class InstanceVar < ASTNode
207
206
  def to_rb
208
- Rb::AST::InstanceVar.new(@name)
207
+ Rb::AST::InstanceVar.new(@name, @location)
209
208
  end
210
209
  end
211
210
 
212
211
  class ReadInstanceVar < ASTNode
213
212
  def to_rb
214
- Rb::AST::EmptyNode.new(self.class.name)
213
+ Rb::AST::EmptyNode.new(self.class.name, @location)
215
214
  end
216
215
  end
217
216
 
218
217
  class ClassVar < ASTNode
219
218
  def to_rb
220
- Rb::AST::EmptyNode.new(self.class.name)
219
+ Rb::AST::EmptyNode.new(self.class.name, @location)
221
220
  end
222
221
  end
223
222
 
224
223
  class Global < ASTNode
225
224
  def to_rb
226
- Rb::AST::GlobalVar.new(@name)
225
+ Rb::AST::GlobalVar.new(@name, @location)
227
226
  end
228
227
  end
229
228
 
230
229
  class Annotation < ASTNode
231
230
  def to_rb
232
- Rb::AST::EmptyNode.new(self.class.name)
233
- end
234
- end
235
-
236
- class MacroExpression < ASTNode
237
- def to_rb
238
- Rb::AST::EmptyNode.new(self.class.name)
231
+ Rb::AST::EmptyNode.new(self.class.name, @location)
239
232
  end
240
233
  end
241
234
 
242
235
  class MacroIf < ASTNode
243
236
  def to_rb
244
- 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)
245
238
  end
246
239
  end
247
240
 
248
241
  class MacroFor < ASTNode
249
242
  def to_rb
250
- 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)
251
244
  end
252
245
  end
253
246
 
254
247
  class MacroVar < ASTNode
255
248
  def to_rb
256
- Rb::AST::EmptyNode.new(self.class.name)
249
+ Rb::AST::EmptyNode.new(self.class.name, @location)
257
250
  end
258
251
  end
259
252
 
260
253
  class MacroExpression < ASTNode
261
254
  def to_rb
262
- Rb::AST::MacroExpression.new(@exp.to_rb, @output)
255
+ Rb::AST::MacroExpression.new(@exp.to_rb, @output, @location)
263
256
  end
264
257
  end
265
258
 
266
259
  class MacroLiteral < ASTNode
267
260
  def to_rb
268
- Rb::AST::MacroLiteral.new(@value)
261
+ Rb::AST::MacroLiteral.new(@value, @location)
269
262
  end
270
263
  end
271
264
 
272
265
  class Annotation < ASTNode
273
266
  def to_rb
274
- Rb::AST::EmptyNode.new(self.class.name)
267
+ Rb::AST::EmptyNode.new(self.class.name, @location)
275
268
  end
276
269
  end
277
270
 
278
271
  class EnumDef < ASTNode
279
272
  def to_rb
280
- Rb::AST::Enum.new(@name, @members.map(&.to_rb))
273
+ Rb::AST::Enum.new(@name, @members.map(&.to_rb), @location)
281
274
  end
282
275
  end
283
276
 
284
277
  class Path < ASTNode
285
278
  def to_rb
286
- Rb::AST::Path.new(full_name)
279
+ Rb::AST::Path.new(full_name, @location)
287
280
  end
288
281
 
289
282
  def full_name
@@ -295,13 +288,13 @@ module Crystal
295
288
 
296
289
  class Require < ASTNode
297
290
  def to_rb
298
- Rb::AST::Require.new(@string)
291
+ Rb::AST::Require.new(@string, @location)
299
292
  end
300
293
  end
301
294
 
302
295
  class TypeDeclaration < ASTNode
303
296
  def to_rb
304
- 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)
305
298
  end
306
299
  end
307
300
 
@@ -311,8 +304,7 @@ module Crystal
311
304
  @cond.try(&.to_rb),
312
305
  @whens.map(&.to_rb),
313
306
  @else.try(&.to_rb),
314
- @exhaustive
315
- )
307
+ @exhaustive, @location)
316
308
  end
317
309
  end
318
310
 
@@ -326,16 +318,14 @@ module Crystal
326
318
  Def.new(
327
319
  "->",
328
320
  [Arg.new(arg_name)],
329
- c.tap { |call| call.obj = Var.new(arg_name) }
330
- )
321
+ c.tap { |call| call.obj = Var.new(arg_name) })
331
322
  ).to_rb
332
323
  else
333
324
  c.to_rb
334
325
  end
335
326
  end,
336
327
  @body.to_rb,
337
- @exhaustive
338
- )
328
+ @exhaustive, @location)
339
329
  end
340
330
  end
341
331
 
@@ -355,8 +345,7 @@ module Crystal
355
345
  Rb::AST::UnaryExpr.new(
356
346
  @exp.to_rb,
357
347
  op,
358
- requires_parentheses
359
- )
348
+ requires_parentheses ,@location)
360
349
  end
361
350
  end
362
351
  {% end %}
@@ -371,8 +360,7 @@ module Crystal
371
360
  "||",
372
361
  {% end %}
373
362
  @left.to_rb,
374
- @right.to_rb
375
- )
363
+ @right.to_rb ,@location)
376
364
  end
377
365
  end
378
366
  {% end %}
@@ -380,7 +368,7 @@ module Crystal
380
368
  {% for class_name in %w[Return Break Next] %}
381
369
  class {{class_name.id}} < ControlExpression
382
370
  def to_rb
383
- Rb::AST::{{class_name.id}}.new(@exp.try(&.to_rb))
371
+ Rb::AST::{{class_name.id}}.new(@exp.try(&.to_rb),@location)
384
372
  end
385
373
  end
386
374
  {% end %}
@@ -388,43 +376,43 @@ module Crystal
388
376
  class ExceptionHandler < ASTNode
389
377
  def to_rb
390
378
  Rb::AST::ExceptionHandler.new(@body.to_rb, @rescues.try(&.map(&.to_rb)), @else.try(&.to_rb),
391
- @ensure.try(&.to_rb))
379
+ @ensure.try(&.to_rb), @location)
392
380
  end
393
381
  end
394
382
 
395
383
  class Rescue < ASTNode
396
384
  def to_rb
397
- 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)
398
386
  end
399
387
  end
400
388
 
401
389
  class Union < ASTNode
402
390
  def to_rb
403
- Rb::AST::Union.new(@types.map(&.to_rb))
391
+ Rb::AST::Union.new(@types.map(&.to_rb), @location)
404
392
  end
405
393
  end
406
394
 
407
395
  class Generic < ASTNode
408
396
  def to_rb
409
- 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)
410
398
  end
411
399
  end
412
400
 
413
401
  class ProcLiteral < ASTNode
414
402
  def to_rb
415
- Rb::AST::Proc.new(@def.to_rb)
403
+ Rb::AST::Proc.new(@def.to_rb, @location)
416
404
  end
417
405
  end
418
406
 
419
407
  class Include < ASTNode
420
408
  def to_rb
421
- Rb::AST::Include.new(@name.to_rb)
409
+ Rb::AST::Include.new(@name.to_rb, @location)
422
410
  end
423
411
  end
424
412
 
425
413
  class Extend < ASTNode
426
414
  def to_rb
427
- Rb::AST::Extend.new(@name.to_rb)
415
+ Rb::AST::Extend.new(@name.to_rb, @location)
428
416
  end
429
417
  end
430
418
 
@@ -437,14 +425,13 @@ module Crystal
437
425
  nil,
438
426
  nil,
439
427
  nil,
440
- false
441
- )
428
+ false, @location)
442
429
  end
443
430
  end
444
431
 
445
432
  class VisibilityModifier < ASTNode
446
433
  def to_rb
447
- Rb::AST::VisibilityModifier.new(@modifier, @exp.to_rb)
434
+ Rb::AST::VisibilityModifier.new(@modifier, @exp.to_rb, @location)
448
435
  end
449
436
  end
450
437
 
@@ -457,8 +444,7 @@ module Crystal
457
444
  nil,
458
445
  nil,
459
446
  nil,
460
- !@exps.empty?
461
- )
447
+ !@exps.empty?, @location)
462
448
  end
463
449
  end
464
450
 
@@ -469,7 +455,7 @@ module Crystal
469
455
  Underscore MagicConstant Asm AsmOperand] %}
470
456
  class {{class_name.id}} < ASTNode
471
457
  def to_rb
472
- Rb::AST::EmptyNode.new(self.class.name)
458
+ Rb::AST::EmptyNode.new(self.class.name,@location)
473
459
  end
474
460
  end
475
461
  {% end %}
@@ -477,7 +463,7 @@ module Crystal
477
463
  {% for class_name in %w[PointerOf SizeOf InstanceSizeOf Out MacroVerbatim] %}
478
464
  class {{class_name.id}} < UnaryExpression
479
465
  def to_rb
480
- Rb::AST::EmptyNode.new(self.class.name)
466
+ Rb::AST::EmptyNode.new(self.class.name,@location)
481
467
  end
482
468
  end
483
469
  {% end %}