-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
248 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#!/usr/bin/env bash | ||
|
||
# sanity check | ||
if (( CHAPTER < 1 | CHAPTER > 20)); then | ||
echo "Bogus chapter number" | ||
exit 1 | ||
fi | ||
|
||
# define the stages we're going to test | ||
declare -a STAGES | ||
if ((CHAPTER == 1)); then | ||
# no --tacky or --validate stage yet | ||
STAGES=(lex parse codegen run) | ||
elif ((CHAPTER < 5)); then | ||
# --tacky but not --validate | ||
STAGES=(lex parse tacky codegen run) | ||
elif ((CHAPTER < 19)); then | ||
# all the stages! | ||
STAGES=(lex parse tacky validate codegen run) | ||
else | ||
# don't run intermediate stages for optimization tests | ||
STAGES=(run) | ||
fi | ||
readonly STAGES | ||
|
||
for stage in "${STAGES[@]}"; do | ||
./test_compiler "${CC}" --chapter "${CHAPTER}" --stage "${stage}" | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# Build tagged versions of the reference implementation compiler | ||
name: Build the compiler | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
chapter: | ||
required: true | ||
type: string | ||
os: | ||
required: true | ||
default: ubuntu-latest | ||
|
||
workflow_call: | ||
inputs: | ||
chapter: | ||
required: true | ||
type: number | ||
os: | ||
type: string | ||
required: true | ||
default: ubuntu-latest | ||
branch: | ||
type: string | ||
required: false | ||
default: main | ||
|
||
env: | ||
EXE_DIR: _build/default/bin/ | ||
EXE_PATH: _build/default/bin/main.exe | ||
|
||
jobs: | ||
|
||
build: | ||
runs-on: ${{ inputs.os }} | ||
env: | ||
CHAPTER: ${{ inputs.chapter }} | ||
|
||
steps: | ||
|
||
# first check out at specified branch so we can find commit hash for this chapter | ||
- uses: actions/checkout@v4 | ||
with: | ||
repository: nlsandler/nqcc2 | ||
ref: ${{ inputs.branch }} | ||
fetch-depth: 0 # need this to get commit history | ||
|
||
- name: Get commit hash | ||
run: | | ||
git log --grep "chapter $CHAPTER:" -i --format='%H' | ||
commit=$(git log --grep "chapter $CHAPTER:" -i --format='%H') | ||
echo "commit=$commit" >> $GITHUB_ENV | ||
- name: Check out NQCC at chapter ${{ inputs.chapter }} | ||
uses: actions/checkout@v4 | ||
with: | ||
repository: nlsandler/nqcc2 | ||
ref: ${{ env.commit }} | ||
|
||
- name: Construct cache key | ||
id: make-key | ||
env: | ||
runner_os: ${{ runner.os }} | ||
run: | | ||
commit=$(git rev-parse --short "$commit") | ||
echo "cache-key=${runner_os}-${commit}-nqcc" >> $GITHUB_OUTPUT | ||
- name: Cache build result | ||
id: cache-nqcc | ||
uses: actions/cache@v4 | ||
with: | ||
path: ${{ env.EXE_PATH }} | ||
key: ${{ steps.make-key.outputs.cache-key }} | ||
|
||
# skip building if we get a cache hit | ||
- name: Set up OCaml | ||
if: steps.cache-nqcc.outputs.cache-hit != 'true' | ||
uses: ocaml/setup-ocaml@v2 | ||
with: | ||
ocaml-compiler: 4.14.x | ||
# necessary to avoid random errors, see https://github.com/ocaml/setup-ocaml/issues/400 | ||
dune-cache: false | ||
|
||
- name: Build it | ||
if: steps.cache-nqcc.outputs.cache-hit != 'true' | ||
run: | | ||
opam install . --deps-only | ||
opam exec -- dune build | ||
- name: Upload binary | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: nqcc-${{inputs.os}}-${{ inputs.chapter }} | ||
path: ${{ env.EXE_PATH }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
name: Build and test the compiler | ||
|
||
on: | ||
workflow_call: | ||
inputs: | ||
os: | ||
required: true | ||
type: string | ||
chapter: | ||
required: true | ||
type: number | ||
|
||
jobs: | ||
build: | ||
uses: nlsandler/nqcc2/.github/workflows/build.yaml@main | ||
with: | ||
chapter: ${{ inputs.chapter }} | ||
os: ${{ inputs.os }} | ||
|
||
test: | ||
runs-on: ${{ inputs.os }} | ||
needs: [build] | ||
env: | ||
CHAPTER: ${{ inputs.chapter }} | ||
steps: | ||
|
||
- name: Check out tests | ||
uses: actions/checkout@v4 | ||
with: | ||
repository: nlsandler/writing-a-c-compiler-tests | ||
ref: complete-test-suite # TODO use main once this is merged | ||
|
||
- name: Check out test runner script | ||
uses: actions/checkout@v4 | ||
with: | ||
repository: nlsandler/nqcc2 | ||
sparse-checkout: | | ||
.github/run-tests.sh | ||
sparse-checkout-cone-mode: false | ||
|
||
- name: Download the compiler | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: nqcc-${{inputs.os}}-${{ inputs.chapter }} | ||
path: nqcc | ||
|
||
# make NQCC executable | ||
- run: chmod u+x nqcc/main.exe | ||
|
||
# Invoke the run-tests script to test each intermediate stage | ||
|
||
# use Rosetta on macOS since that's what most readers are doing | ||
- name: Run the tests (Apple Silicon) | ||
if: runner.arch == 'ARM64' | ||
run: arch -x86_64 ./github/run-tests.sh | ||
|
||
- name: Run the tests (x86-64) | ||
if: runner.arch != 'ARM64' | ||
run: ./github/run-tests.sh | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: Build and test each chapter | ||
|
||
on: | ||
workflow_dispatch: | ||
|
||
jobs: | ||
|
||
|
||
build-and-test: | ||
strategy: | ||
fail-fast: true | ||
matrix: | ||
os: [macos-latest, ubuntu-latest] | ||
chapter: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] | ||
uses: nlsandler/nqcc2/.github/workflows/build_and_test.yaml@main | ||
with: | ||
chapter: ${{ matrix.chapter }} | ||
os: ${{ matrix.os }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# NQCC2, the Not-Quite-C Compiler | ||
|
||
**CAUTION: FREQUENT FORCE PUSHES** | ||
|
||
This is the reference implementation for the upcoming book [Writing a C Compiler](https://nostarch.com/writing-c-compiler), a hands-on guide to writing your own compiler for a big chunk of C. | ||
|
||
Each commit corresponds to one chapter in the book, to illustrate what needs to change at each step. Because commits are structured this way, this repository sees frequent rebases and force pushes - fork with caution! | ||
|
||
This implementation is still a work in progress - the functionality is complete, but needs more work on the readability front. | ||
|
||
# Building the Compiler | ||
|
||
This compiler is written in OCaml. Building it requires opam, the OCaml package manager (installation instructions [here](https://opam.ocaml.org/doc/Install.html)). | ||
|
||
Then do: | ||
|
||
``` | ||
git clone https://github.com/nlsandler/nqcc2.git | ||
cd nqcc2 | ||
opam install . --deps-only | ||
dune build | ||
``` | ||
|
||
This puts the executable at `_build/default/bin/main.exe`. | ||
|
||
# Usage Example | ||
|
||
Assume we have this source file at ~/hello_world.c: | ||
```c | ||
int puts(char *c); | ||
|
||
int main(void) { | ||
puts("Hello, world!"); | ||
} | ||
``` | ||
To compile and run it: | ||
``` | ||
$ _build/default/bin/main.exe ~/hello_world.c | ||
$ ~/hello_world | ||
Hello, World! | ||
``` | ||