gloss 0.0.4 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +3 -0
  3. data/.github/workflows/{crystal.yml → crystal_specs.yml} +1 -1
  4. data/.github/workflows/{ruby.yml → ruby_specs.yml} +2 -2
  5. data/.gloss.yml +1 -0
  6. data/.rspec +1 -0
  7. data/Gemfile.lock +9 -11
  8. data/README.md +35 -5
  9. data/Rakefile +1 -1
  10. data/exe/gloss +13 -2
  11. data/ext/gloss/Makefile +8 -19
  12. data/ext/gloss/spec/parser_spec.cr +83 -83
  13. data/ext/gloss/src/cr_ast.cr +63 -77
  14. data/ext/gloss/src/gloss.cr +1 -2
  15. data/ext/gloss/src/rb_ast.cr +40 -38
  16. data/lib/gloss.rb +15 -7
  17. data/lib/gloss/cli.rb +75 -32
  18. data/lib/gloss/config.rb +10 -3
  19. data/lib/gloss/errors.rb +1 -1
  20. data/lib/gloss/initializer.rb +6 -5
  21. data/lib/gloss/logger.rb +29 -0
  22. data/lib/gloss/parser.rb +17 -2
  23. data/lib/gloss/prog_loader.rb +141 -0
  24. data/lib/gloss/scope.rb +1 -1
  25. data/lib/gloss/source.rb +1 -1
  26. data/lib/gloss/type_checker.rb +80 -32
  27. data/lib/gloss/utils.rb +44 -0
  28. data/lib/gloss/version.rb +5 -5
  29. data/lib/gloss/{builder.rb → visitor.rb} +125 -74
  30. data/lib/gloss/watcher.rb +47 -11
  31. data/lib/gloss/writer.rb +22 -11
  32. data/sig/core.rbs +2 -0
  33. data/sig/fast_blank.rbs +4 -0
  34. data/sig/{gloss.rbs → gls.rbs} +0 -0
  35. data/sig/optparse.rbs +6 -0
  36. data/sig/rubygems.rbs +9 -0
  37. data/sig/yaml.rbs +3 -0
  38. data/src/exe/gloss +19 -0
  39. data/src/lib/gloss.gl +26 -0
  40. data/src/lib/gloss/cli.gl +53 -24
  41. data/src/lib/gloss/config.gl +9 -3
  42. data/src/lib/gloss/initializer.gl +4 -6
  43. data/src/lib/gloss/logger.gl +21 -0
  44. data/src/lib/gloss/parser.gl +17 -5
  45. data/src/lib/gloss/prog_loader.gl +133 -0
  46. data/src/lib/gloss/scope.gl +0 -2
  47. data/src/lib/gloss/type_checker.gl +85 -39
  48. data/src/lib/gloss/utils.gl +38 -0
  49. data/src/lib/gloss/version.gl +1 -1
  50. data/src/lib/gloss/{builder.gl → visitor.gl} +123 -68
  51. data/src/lib/gloss/watcher.gl +44 -10
  52. data/src/lib/gloss/writer.gl +16 -14
  53. metadata +23 -8
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 %}