Skip to content

Commit 6f8bcc6

Browse files
authored
Merge pull request #2671 from ruby/parser
Backport pure-C parser
2 parents 8777b31 + 3a9f441 commit 6f8bcc6

71 files changed

Lines changed: 34706 additions & 8640 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clang-format

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
Language: Cpp
3+
4+
# Indentation
5+
UseTab: Never
6+
IndentWidth: 4
7+
BreakBeforeBraces: Attach
8+
IndentCaseLabels: false
9+
NamespaceIndentation: None
10+
ContinuationIndentWidth: 4
11+
IndentPPDirectives: None
12+
IndentWrappedFunctionNames: false
13+
AccessModifierOffset: -2
14+
15+
# Alignment
16+
AlignAfterOpenBracket: BlockIndent
17+
AlignConsecutiveAssignments: false
18+
AlignConsecutiveDeclarations: false
19+
AlignConsecutiveMacros: false
20+
AlignEscapedNewlines: Left
21+
AlignOperands: false
22+
AlignTrailingComments: true
23+
DerivePointerAlignment: false
24+
PointerAlignment: Right
25+
26+
# Function calls formatting
27+
BinPackArguments: false
28+
BinPackParameters: false
29+
AllowAllArgumentsOnNextLine: false
30+
ExperimentalAutoDetectBinPacking: false
31+
PenaltyBreakBeforeFirstCallParameter: 1
32+
AlwaysBreakAfterDefinitionReturnType: None
33+
34+
# Wrapping and Breaking
35+
ColumnLimit: 0
36+
AllowShortBlocksOnASingleLine: Never
37+
AllowShortCaseLabelsOnASingleLine: false
38+
AllowShortFunctionsOnASingleLine: All
39+
AllowShortIfStatementsOnASingleLine: Always
40+
AllowShortLoopsOnASingleLine: false
41+
AlwaysBreakAfterReturnType: None
42+
AlwaysBreakBeforeMultilineStrings: false
43+
AlwaysBreakTemplateDeclarations: No
44+
BreakBeforeBinaryOperators: None
45+
BreakBeforeTernaryOperators: false
46+
BreakConstructorInitializers: BeforeColon
47+
BreakInheritanceList: BeforeColon
48+
BreakStringLiterals: false
49+
CompactNamespaces: false
50+
ConstructorInitializerAllOnOneLineOrOnePerLine: false
51+
Cpp11BracedListStyle: false
52+
ReflowComments: false
53+
SortIncludes: Never
54+
55+
# Spaces
56+
SpaceAfterCStyleCast: true
57+
SpaceAfterLogicalNot: false
58+
SpaceAfterTemplateKeyword: true
59+
SpaceBeforeAssignmentOperators: true
60+
SpaceBeforeCpp11BracedList: true
61+
SpaceBeforeCtorInitializerColon: true
62+
SpaceBeforeInheritanceColon: true
63+
SpaceBeforeParens: ControlStatements
64+
SpaceBeforeRangeBasedForLoopColon: true
65+
SpaceBeforeSquareBrackets: false
66+
SpaceInEmptyBlock: false
67+
SpaceInEmptyParentheses: false
68+
SpacesBeforeTrailingComments: 1
69+
SpacesInAngles: false
70+
SpacesInCStyleCastParentheses: false
71+
SpacesInConditionalStatement: false
72+
SpacesInContainerLiterals: true
73+
SpacesInParentheses: false
74+
SpacesInSquareBrackets: false

.github/workflows/c-check.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: C Code Generation and Formatting Check
2+
3+
on:
4+
push:
5+
pull_request: {}
6+
merge_group: {}
7+
8+
jobs:
9+
format-check:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: ruby/setup-ruby@v1
14+
with:
15+
ruby-version: "3.4"
16+
bundler-cache: none
17+
- name: Set working directory as safe
18+
run: git config --global --add safe.directory $(pwd)
19+
- name: Install dependencies
20+
run: |
21+
sudo apt-get update
22+
sudo apt-get install -y libdb-dev curl autoconf automake m4 libtool
23+
- name: Install clang-format from LLVM
24+
run: |
25+
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
26+
sudo apt-add-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-20 main"
27+
sudo apt-get update
28+
sudo apt-get install -y clang-format-20
29+
sudo ln -sf /usr/bin/clang-format-20 /usr/local/bin/clang-format
30+
clang-format --version
31+
- name: Count processors
32+
run: nproc
33+
- name: Install Re2c
34+
run: |
35+
cd /tmp
36+
curl -L https://github.com/skvadrik/re2c/archive/refs/tags/4.3.tar.gz > re2c-4.3.tar.gz
37+
tar xf re2c-4.3.tar.gz
38+
cd re2c-4.3
39+
autoreconf -i -W all
40+
./configure
41+
make -j"$(nproc)" -l"$(nproc)"
42+
sudo make install
43+
- name: Update rubygems & bundler
44+
run: |
45+
ruby -v
46+
gem update --system
47+
- name: bin/setup
48+
run: |
49+
bin/setup
50+
- name: Check C code generation and formatting
51+
run: |
52+
clang-format --version
53+
bundle exec rake lexer templates compile confirm_lexer confirm_templates
54+
bundle exec rake format:c_check

.github/workflows/ruby.yml

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ jobs:
2828
- ruby: "3.4"
2929
job: stdlib_test
3030
rubyopt: "--enable-frozen-string-literal"
31-
- ruby: "3.4"
32-
job: lexer templates compile confirm_lexer confirm_templates
3331
- ruby: "3.4"
3432
job: rubocop validate test_doc build test_generate_stdlib raap
3533
- ruby: "3.4"
@@ -48,17 +46,6 @@ jobs:
4846
run: |
4947
sudo apt-get update
5048
sudo apt-get install -y libdb-dev curl autoconf automake m4 libtool python3
51-
- name: Install Re2c
52-
if: ${{ contains(matrix.job, 'lexer') }}
53-
run: |
54-
cd /tmp
55-
curl -L https://github.com/skvadrik/re2c/archive/refs/tags/3.1.tar.gz > re2c-3.1.tar.gz
56-
tar xf re2c-3.1.tar.gz
57-
cd re2c-3.1
58-
autoreconf -i -W all
59-
./configure
60-
make
61-
sudo make install
6249
- name: Update rubygems & bundler
6350
run: |
6451
ruby -v
@@ -102,3 +89,31 @@ jobs:
10289
- run: bundle exec rake test:valgrind
10390
env:
10491
RUBY_FREE_AT_EXIT: 1
92+
C99_compile:
93+
runs-on: macos-latest
94+
strategy:
95+
fail-fast: false
96+
matrix:
97+
ruby: ['3.4', head]
98+
steps:
99+
- uses: actions/checkout@v4
100+
- name: Install dependencies
101+
run: |
102+
brew install ruby-build
103+
- uses: ruby/setup-ruby@v1
104+
with:
105+
ruby-version: ${{ matrix.ruby }}
106+
bundler: none
107+
- name: Set working directory as safe
108+
run: git config --global --add safe.directory $(pwd)
109+
- name: Update rubygems & bundler
110+
run: |
111+
ruby -v
112+
gem update --system
113+
- name: clang version
114+
run: clang --version
115+
- name: bin/setup
116+
run: |
117+
bin/setup
118+
- run: bundle exec rake clean compile_c99
119+

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,43 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
198198

199199
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
200200

201+
### C Code Formatting
202+
203+
This project uses `clang-format` to enforce consistent formatting of C code with a `.clang-format` configuration in the root directory.
204+
205+
#### Setup
206+
207+
First, install clang-format:
208+
209+
```bash
210+
# macOS
211+
brew install clang-format
212+
213+
# Ubuntu/Debian
214+
sudo apt-get install clang-format
215+
216+
# Windows
217+
choco install llvm
218+
```
219+
220+
#### Usage
221+
222+
Format all C source files:
223+
224+
```bash
225+
rake format:c
226+
```
227+
228+
Check formatting without making changes:
229+
230+
```bash
231+
rake format:c_check
232+
```
233+
234+
#### Editor Integration
235+
236+
For VS Code users, install the "clangd" extension which will automatically use the project's `.clang-format` file.
237+
201238
## Contributing
202239

203240
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/rbs.

Rakefile

Lines changed: 117 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,98 @@ end
3636
multitask :default => [:test, :stdlib_test, :typecheck_test, :rubocop, :validate, :test_doc]
3737

3838
task :lexer do
39-
sh "re2c -W --no-generation-date -o ext/rbs_extension/lexer.c ext/rbs_extension/lexer.re"
39+
sh "re2c -W --no-generation-date -o src/lexer.c src/lexer.re"
40+
sh "clang-format -i -style=file src/lexer.c"
4041
end
4142

4243
task :confirm_lexer => :lexer do
4344
puts "Testing if lexer.c is updated with respect to lexer.re"
44-
sh "git diff --exit-code ext/rbs_extension/lexer.c"
45+
sh "git diff --exit-code src/lexer.c"
4546
end
4647

4748
task :confirm_templates => :templates do
4849
puts "Testing if generated code under include and src is updated with respect to templates"
4950
sh "git diff --exit-code -- include src"
5051
end
5152

53+
# Task to format C code using clang-format
54+
namespace :format do
55+
dirs = ["src", "ext", "include"]
56+
57+
# Find all C source and header files
58+
files = `find #{dirs.join(" ")} -type f \\( -name "*.c" -o -name "*.h" \\)`.split("\n")
59+
60+
desc "Format C source files using clang-format"
61+
task :c do
62+
puts "Formatting C files..."
63+
64+
# Check if clang-format is installed
65+
unless system("which clang-format > /dev/null 2>&1")
66+
abort "Error: clang-format not found. Please install clang-format first."
67+
end
68+
69+
if files.empty?
70+
puts "No C files found to format"
71+
next
72+
end
73+
74+
puts "Found #{files.length} files to format (excluding generated files)"
75+
76+
exit_status = 0
77+
files.each do |file|
78+
puts "Formatting #{file}"
79+
unless system("clang-format -i -style=file #{file}")
80+
puts "❌ Error formatting #{file}"
81+
exit_status = 1
82+
end
83+
end
84+
85+
exit exit_status unless exit_status == 0
86+
puts "✅ All files formatted successfully"
87+
end
88+
89+
desc "Check if C source files are properly formatted"
90+
task :c_check do
91+
puts "Checking C file formatting..."
92+
93+
# Check if clang-format is installed
94+
unless system("which clang-format > /dev/null 2>&1")
95+
abort "Error: clang-format not found. Please install clang-format first."
96+
end
97+
98+
if files.empty?
99+
puts "No C files found to check"
100+
next
101+
end
102+
103+
puts "Found #{files.length} files to check (excluding generated files)"
104+
105+
needs_format = false
106+
files.each do |file|
107+
formatted = `clang-format -style=file #{file}`
108+
original = File.read(file)
109+
110+
if formatted != original
111+
puts "❌ #{file} needs formatting"
112+
puts "Diff:"
113+
# Save formatted version to temp file and run diff
114+
temp_file = "#{file}.formatted"
115+
File.write(temp_file, formatted)
116+
system("diff -u #{file} #{temp_file}")
117+
File.unlink(temp_file)
118+
needs_format = true
119+
end
120+
end
121+
122+
if needs_format
123+
warn "Some files need formatting. Run 'rake format:c' to format them."
124+
exit 1
125+
else
126+
puts "✅ All files are properly formatted"
127+
end
128+
end
129+
end
130+
52131
rule ".c" => ".re" do |t|
53132
puts "⚠️⚠️⚠️ #{t.name} is older than #{t.source}. You may need to run `rake lexer` ⚠️⚠️⚠️"
54133
end
@@ -70,17 +149,22 @@ task :confirm_annotation do
70149
end
71150

72151
task :templates do
73-
sh "#{ruby} templates/template.rb include/rbs/constants.h"
74-
sh "#{ruby} templates/template.rb include/rbs/ruby_objs.h"
75-
sh "#{ruby} templates/template.rb src/constants.c"
76-
sh "#{ruby} templates/template.rb src/ruby_objs.c"
152+
sh "#{ruby} templates/template.rb ext/rbs_extension/ast_translation.h"
153+
sh "#{ruby} templates/template.rb ext/rbs_extension/ast_translation.c"
154+
155+
sh "#{ruby} templates/template.rb ext/rbs_extension/class_constants.h"
156+
sh "#{ruby} templates/template.rb ext/rbs_extension/class_constants.c"
157+
158+
sh "#{ruby} templates/template.rb include/rbs/ast.h"
159+
sh "#{ruby} templates/template.rb src/ast.c"
160+
161+
# Format the generated files
162+
Rake::Task["format:c"].invoke
77163
end
78164

79-
task :compile => "ext/rbs_extension/lexer.c"
80-
task :compile => "include/rbs/constants.h"
81-
task :compile => "include/rbs/ruby_objs.h"
82-
task :compile => "src/constants.c"
83-
task :compile => "src/ruby_objs.c"
165+
task :compile => "ext/rbs_extension/class_constants.h"
166+
task :compile => "ext/rbs_extension/class_constants.c"
167+
task :compile => "src/lexer.c"
84168

85169
task :test_doc do
86170
files = Dir.chdir(File.expand_path('..', __FILE__)) do
@@ -430,3 +514,25 @@ task :changelog do
430514
puts " (🤑 There is no *unreleased* pull request associated to the milestone.)"
431515
end
432516
end
517+
518+
desc "Compile extension without C23 extensions"
519+
task :compile_c99 do
520+
ENV["TEST_NO_C23"] = "true"
521+
Rake::Task[:"compile"].invoke
522+
ensure
523+
ENV.delete("TEST_NO_C23")
524+
end
525+
526+
task :prepare_bench do
527+
ENV.delete("DEBUG")
528+
Rake::Task[:"clobber"].invoke
529+
Rake::Task[:"templates"].invoke
530+
Rake::Task[:"compile"].invoke
531+
end
532+
533+
task :prepare_profiling do
534+
ENV["DEBUG"] = "1"
535+
Rake::Task[:"clobber"].invoke
536+
Rake::Task[:"templates"].invoke
537+
Rake::Task[:"compile"].invoke
538+
end

0 commit comments

Comments
 (0)