gloss 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/crystal.yml +26 -0
- data/.github/workflows/ruby.yml +33 -0
- data/.gitignore +2 -1
- data/Gemfile +0 -1
- data/Gemfile.lock +5 -11
- data/LICENSE +21 -0
- data/README.md +23 -2
- data/Rakefile +4 -0
- data/ext/gloss/Makefile +27 -5
- data/ext/gloss/extconf.rb +3 -25
- data/ext/gloss/spec/parser_spec.cr +91 -0
- data/ext/gloss/spec/spec_helper.cr +2 -0
- data/ext/gloss/src/cr_ast.cr +23 -9
- data/ext/gloss/src/gloss.cr +11 -17
- data/ext/gloss/src/parser.cr +544 -250
- data/ext/gloss/src/rb_ast.cr +34 -2
- data/gloss.gemspec +1 -0
- data/lib/gloss.rb +3 -1
- data/lib/gloss/builder.rb +24 -73
- data/lib/gloss/cli.rb +4 -1
- data/lib/gloss/parser.rb +18 -0
- data/lib/gloss/type_checker.rb +75 -0
- data/lib/gloss/version.rb +1 -1
- metadata +23 -3
- data/lib/gloss.bundle.dwarf +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0bcae87434234732f58cc6d0bb9a1408a72fae1f51b9fe0c1dcf86249784fe2
|
4
|
+
data.tar.gz: d3db73f4c6e907a0b11eaba71f4428680372b56df1e3e6d8df973e80c8346e26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d58d4583ec2c703c023741bc6fd211fd146d81e3e90b3c882b5c4e37aa4cb12de2ad8cf46f6c26a7bf392cfd6accc1372cbaa01be8eb763468918d0a60d05eba
|
7
|
+
data.tar.gz: ab6244066db5797def1d7225598c87e5bd9cde3385b303854e176332a96c16f8fbbe6f4a531dadb6fe6e22e9d860152daab4b5d4282af79646f7421ce4cde0e3
|
@@ -0,0 +1,26 @@
|
|
1
|
+
name: Crystal CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
defaults:
|
10
|
+
run:
|
11
|
+
working-directory: ext/gloss
|
12
|
+
|
13
|
+
jobs:
|
14
|
+
build:
|
15
|
+
|
16
|
+
runs-on: ubuntu-latest
|
17
|
+
|
18
|
+
container:
|
19
|
+
image: crystallang/crystal
|
20
|
+
|
21
|
+
steps:
|
22
|
+
- uses: actions/checkout@v2
|
23
|
+
- name: Install dependencies
|
24
|
+
run: shards install
|
25
|
+
- name: Run tests
|
26
|
+
run: crystal spec
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: Ruby
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ master ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ master ]
|
15
|
+
|
16
|
+
jobs:
|
17
|
+
test:
|
18
|
+
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
|
21
|
+
steps:
|
22
|
+
- uses: actions/checkout@v2
|
23
|
+
- name: Set up Ruby
|
24
|
+
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
25
|
+
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
26
|
+
# uses: ruby/setup-ruby@v1
|
27
|
+
uses: ruby/setup-ruby@21351ecc0a7c196081abca5dc55b08f085efe09a
|
28
|
+
with:
|
29
|
+
ruby-version: 2.7
|
30
|
+
- name: Install dependencies
|
31
|
+
run: bundle install
|
32
|
+
- name: Run tests
|
33
|
+
run: bundle exec rake build && bundle exec rake spec
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,16 +1,10 @@
|
|
1
|
-
GIT
|
2
|
-
remote: git@github.com:duderman/rbs.git
|
3
|
-
revision: cb347ab605c6409d5ad38ba7439b170ed5996fae
|
4
|
-
branch: file-open-block
|
5
|
-
specs:
|
6
|
-
rbs (1.0.0)
|
7
|
-
|
8
1
|
PATH
|
9
2
|
remote: .
|
10
3
|
specs:
|
11
|
-
gloss (0.0.
|
4
|
+
gloss (0.0.2)
|
12
5
|
fast_blank
|
13
6
|
listen
|
7
|
+
rbs
|
14
8
|
steep
|
15
9
|
|
16
10
|
GEM
|
@@ -32,10 +26,10 @@ GEM
|
|
32
26
|
diff-lcs (1.4.4)
|
33
27
|
fast_blank (1.0.0)
|
34
28
|
ffi (1.14.2)
|
35
|
-
i18n (1.8.
|
29
|
+
i18n (1.8.6)
|
36
30
|
concurrent-ruby (~> 1.0)
|
37
31
|
language_server-protocol (3.15.0.1)
|
38
|
-
listen (3.
|
32
|
+
listen (3.4.0)
|
39
33
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
40
34
|
rb-inotify (~> 0.9, >= 0.9.10)
|
41
35
|
method_source (1.0.0)
|
@@ -56,6 +50,7 @@ GEM
|
|
56
50
|
rb-fsevent (0.10.4)
|
57
51
|
rb-inotify (0.10.1)
|
58
52
|
ffi (~> 1.0)
|
53
|
+
rbs (1.0.0)
|
59
54
|
regexp_parser (2.0.0)
|
60
55
|
rexml (3.2.4)
|
61
56
|
rspec (3.10.0)
|
@@ -104,7 +99,6 @@ DEPENDENCIES
|
|
104
99
|
gloss!
|
105
100
|
pry-byebug
|
106
101
|
rake-compiler
|
107
|
-
rbs!
|
108
102
|
rspec
|
109
103
|
rubocop
|
110
104
|
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2021 Joseph Johansen
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Gloss
|
2
2
|
|
3
|
-
Gloss 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,
|
3
|
+
[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
4
|
efficiency, and to enhance ruby's goal of developer happiness and productivity. Some of the features include:
|
5
5
|
|
6
6
|
- Type checking, via optional type annotations
|
@@ -38,7 +38,7 @@ result.length # OK => 11
|
|
38
38
|
#### Macros:
|
39
39
|
|
40
40
|
```crystal
|
41
|
-
# src/lib/http_client.
|
41
|
+
# src/lib/http_client.gl
|
42
42
|
|
43
43
|
class HttpClient
|
44
44
|
|
@@ -119,6 +119,8 @@ class Language
|
|
119
119
|
puts "my favourite language is #{language}"
|
120
120
|
end
|
121
121
|
end
|
122
|
+
|
123
|
+
Language.new.favourite_language(Language::Lang::R)
|
122
124
|
```
|
123
125
|
|
124
126
|
#### Tuples + Named Tuples:
|
@@ -183,6 +185,25 @@ when String
|
|
183
185
|
end
|
184
186
|
```
|
185
187
|
|
188
|
+
#### Abstract classes (roadmap)
|
189
|
+
|
190
|
+
```crystal
|
191
|
+
abstract class BaseClass
|
192
|
+
attr_reader :var
|
193
|
+
|
194
|
+
def initialize(@var); end
|
195
|
+
end
|
196
|
+
|
197
|
+
class Child < BaseClass
|
198
|
+
def what_is_var
|
199
|
+
"var is #{var}"
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
BaseClass.new(123) # Error - can't instantiate abstract class
|
204
|
+
Child.new(123).what_is_var # Ok - "var is 123"
|
205
|
+
```
|
206
|
+
|
186
207
|
## Usage:
|
187
208
|
|
188
209
|
```ruby
|
data/Rakefile
CHANGED
data/ext/gloss/Makefile
CHANGED
@@ -1,15 +1,37 @@
|
|
1
1
|
CRYSTAL = crystal
|
2
|
-
TARGET = ../../lib/
|
2
|
+
TARGET = ../../lib/gls
|
3
3
|
|
4
|
+
PLATFORM = $(shell uname -s)
|
5
|
+
|
6
|
+
ifeq "$(PLATFORM)" "Darwin"
|
7
|
+
install: all
|
8
|
+
|
9
|
+
all: clean shards build
|
10
|
+
|
11
|
+
shards:
|
12
|
+
shards
|
13
|
+
|
14
|
+
build: ./src/gloss.cr
|
15
|
+
$(CRYSTAL) build --link-flags "-dynamic -bundle -Wl,-undefined,dynamic_lookup" $< -o $(TARGET).bundle
|
16
|
+
|
17
|
+
clean:
|
18
|
+
rm -f $(TARGET).bundle
|
19
|
+
rm -f $(TARGET).bundle.dwarf
|
20
|
+
endif
|
21
|
+
|
22
|
+
ifeq "$(PLATFORM)" "Linux"
|
23
|
+
LLVM_TARGET = "$(shell uname -m)-unknown-linux-gnu"
|
4
24
|
install: all
|
5
25
|
|
6
|
-
all: clean shards
|
26
|
+
all: clean shards build
|
7
27
|
|
8
28
|
shards:
|
9
29
|
shards
|
10
30
|
|
11
|
-
|
12
|
-
$(CRYSTAL) build --link-flags "-dynamic -bundle -Wl,-undefined,dynamic_lookup"
|
31
|
+
build: ./src/gloss.cr
|
32
|
+
$(CRYSTAL) build $< --cross-compile --target $(LLVM_TARGET) --link-flags "-dynamic -bundle -Wl,-undefined,dynamic_lookup" -o $(TARGET)
|
13
33
|
|
14
34
|
clean:
|
15
|
-
rm -f
|
35
|
+
rm -f $(TARGET).o
|
36
|
+
rm -f $(TARGET).so
|
37
|
+
endif
|
data/ext/gloss/extconf.rb
CHANGED
@@ -1,32 +1,10 @@
|
|
1
1
|
require "mkmf"
|
2
|
-
# $makefile_created = true
|
3
2
|
find_executable("crystal") or abort <<~ERR
|
4
3
|
You need crystal installed to use this gem.
|
5
4
|
Please check out https://crystal-lang.org/ for information on how to install it.
|
6
5
|
ERR
|
7
|
-
# $LDFLAGS = "-rdynamic -L/usr/local/Cellar/crystal/0.35.1_1/embedded/lib -L/usr/local/lib -lpcre -lgc -lpthread /usr/local/Cellar/crystal/0.35.1_1/src/ext/libcrystal.a -L/usr/local/Cellar/libevent/2.1.12/lib -levent -liconv -ldl -Llib -lgloss"
|
8
|
-
# $LDFLAGS << " -Wl,-undefined,dynamic_lookup -Llib -lgloss "
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# I feel like a bad person
|
14
|
-
# File.open(File.join(__dir__, "Makefile"), "w") do |f|
|
15
|
-
# f.write <<~MAKEFILE
|
16
|
-
# CRYSTAL = crystal
|
17
|
-
# TARGET = ../../lib/gloss.bundle
|
18
|
-
|
19
|
-
# install: all
|
20
|
-
|
21
|
-
# all: clean shards $(TARGET)
|
7
|
+
# patch it to be no-op
|
8
|
+
def create_makefile(_, _ = nil); end
|
22
9
|
|
23
|
-
|
24
|
-
# shards
|
25
|
-
|
26
|
-
# $(TARGET): ./src/gloss.cr
|
27
|
-
# $(CRYSTAL) build --link-flags "-dynamic -bundle -Wl,-undefined,dynamic_lookup" $< -o $(TARGET)
|
28
|
-
|
29
|
-
# clean:
|
30
|
-
# rm -f ../../**/*.bundle*
|
31
|
-
# MAKEFILE
|
32
|
-
# end
|
10
|
+
create_makefile "gloss"
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "./spec_helper"
|
2
|
+
|
3
|
+
module Gloss
|
4
|
+
describe Parser do
|
5
|
+
it "allows single quoted strings" do
|
6
|
+
Gloss.parse_string("puts 'hello world'").should be_truthy
|
7
|
+
end
|
8
|
+
|
9
|
+
it "doesn't require 'of' after empty arrays" do
|
10
|
+
Gloss.parse_string("arr = []").should eq(
|
11
|
+
%q|{"type":"Assign","op":null,"target":{"type":"Var","name":"arr"},"value":{"type":"ArrayLiteral","elements":[],"frozen":false}}|
|
12
|
+
)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't require 'of' after empty hashes" do
|
16
|
+
Gloss.parse_string("hsh = {}").should be_truthy
|
17
|
+
end
|
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
|
26
|
+
|
27
|
+
it "parses rescue with ruby syntax" do
|
28
|
+
Gloss.parse_string(<<-GLOSS).should be_truthy
|
29
|
+
begin
|
30
|
+
raise "Abc"
|
31
|
+
rescue RuntimeError => e
|
32
|
+
p e.message
|
33
|
+
rescue NoMethodError
|
34
|
+
rescue => e
|
35
|
+
end
|
36
|
+
GLOSS
|
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
|
+
|
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
|
69
|
+
|
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
|
83
|
+
|
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
|
91
|
+
end
|
data/ext/gloss/src/cr_ast.cr
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "compiler/crystal/syntax/*"
|
2
2
|
require "json"
|
3
|
+
require "./rb_ast"
|
3
4
|
|
4
5
|
module Crystal
|
5
6
|
abstract class ASTNode
|
@@ -139,17 +140,18 @@ module Crystal
|
|
139
140
|
end
|
140
141
|
end
|
141
142
|
|
142
|
-
class
|
143
|
+
class Arg < ASTNode
|
144
|
+
property keyword_arg : Bool = false
|
145
|
+
|
143
146
|
def to_rb
|
144
|
-
Rb::AST::
|
147
|
+
Rb::AST::Arg.new(@name, @external_name, @restriction.try(&.to_rb),
|
148
|
+
@default_value.try(&.to_rb), @keyword_arg)
|
145
149
|
end
|
146
150
|
end
|
147
151
|
|
148
|
-
class
|
149
|
-
property keyword_arg : Bool = false
|
150
|
-
|
152
|
+
class NamedArgument < ASTNode
|
151
153
|
def to_rb
|
152
|
-
Rb::AST::
|
154
|
+
Rb::AST::EmptyNode.new(self.class.name)
|
153
155
|
end
|
154
156
|
end
|
155
157
|
|
@@ -197,7 +199,7 @@ module Crystal
|
|
197
199
|
|
198
200
|
class Global < ASTNode
|
199
201
|
def to_rb
|
200
|
-
Rb::AST::
|
202
|
+
Rb::AST::GlobalVar.new(@name)
|
201
203
|
end
|
202
204
|
end
|
203
205
|
|
@@ -359,9 +361,21 @@ module Crystal
|
|
359
361
|
end
|
360
362
|
end
|
361
363
|
|
364
|
+
class Union < ASTNode
|
365
|
+
def to_rb
|
366
|
+
Rb::AST::Union.new(@types.map(&.to_rb))
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
class Generic < ASTNode
|
371
|
+
def to_rb
|
372
|
+
Rb::AST::Generic.new(@name.to_rb, @type_vars.map(&.to_rb))
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
362
376
|
{% for class_name in %w[ProcNotation Macro OffsetOf VisibilityModifier IsA RespondsTo
|
363
|
-
Select ImplicitObj AnnotationDef While Until
|
364
|
-
ProcLiteral ProcPointer
|
377
|
+
Select ImplicitObj AnnotationDef While Until UninitializedVar
|
378
|
+
ProcLiteral ProcPointer Self Yield Include
|
365
379
|
Extend LibDef FunDef TypeDef CStructOrUnionDef ExternalVar Alias
|
366
380
|
Metaclass Cast NilableCast TypeOf Annotation
|
367
381
|
Underscore MagicConstant Asm AsmOperand] %}
|