Skip to content

Commit b47c367

Browse files
authored
Merge pull request #4 from 0xpantera/feature/binary-operators
Binary Operators
2 parents d7c84e3 + 0dbca4b commit b47c367

File tree

19 files changed

+786
-253
lines changed

19 files changed

+786
-253
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ writing-a-c-compiler-tests/
22
dist-newstyle/
33
flake.lock
44
c-programs/
5+
.DS_Store
6+
ai-context.txt

CHANGELOG.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,19 @@
5555
- Added record syntax for multi-field data constructors
5656
- Standardized naming conventions in core types
5757
- Simplified token type names
58-
- Made qualified imports consistent across modules
58+
- Made qualified imports consistent across modules
59+
60+
## 0.3.0.0 -- 2024-11-27
61+
62+
### Added
63+
- Support for binary operators:
64+
- Addition
65+
- Subtraction
66+
- Multiplication
67+
- Division
68+
- Remainder
69+
- Precedence climbing parser for handling operator precedence
70+
- New assembly instructions for binary operations (add, sub, imul, idiv)
71+
- Proper handling of division and remainder with EAX/EDX registers
72+
- Sign extension support using cdq instruction
73+
- Updated instruction fix-up pass for binary operation constraints

README.md

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,50 +29,49 @@ Programs are represented internally using a series of increasingly lower-level d
2929
1. **Abstract Syntax Tree (AST)**:
3030
```haskell
3131
data Program = Program Function
32-
data Function = Function
33-
{ name :: Text
34-
, body :: Statement
35-
}
32+
data Function = Function Text Statement
3633
data Statement = Return Expr
3734
data Expr
38-
= Constant { value :: Int }
39-
| Unary { operator :: UnaryOp, operand :: Expr }
35+
= Constant Int
36+
| Unary UnaryOp Expr
37+
| Binary BinaryOp Expr Expr
4038
data UnaryOp = Complement | Negate
39+
data BinaryOp = Add | Subtract | Multiply | Divide | Remainder
4140
```
4241

4342
2. **TACKY IR**:
4443
```haskell
4544
data Program = Program Function
46-
data Function = Function
47-
{ name :: Text
48-
, body :: [Instruction]
49-
}
45+
data Function = Function Text [Instruction]
5046
data Instruction
51-
= Return { value :: Val }
52-
| Unary { operator :: UnaryOp, src :: Val, dst :: Val }
47+
= Return Val
48+
| Unary UnaryOp Val Val
49+
| Binary BinaryOp Val Val Val
5350
data Val = Constant Int | Var Text
5451
data UnaryOp = Complement | Negate
52+
data BinaryOp = Add | Subtract | Multiply | Divide | Remainder
5553
```
5654

5755
3. **Assembly AST**:
5856
```haskell
5957
data Program = Program Function
60-
data Function = Function
61-
{ name :: Text
62-
, instructions :: [Instruction]
63-
}
58+
data Function = Function Text [Instruction]
6459
data Instruction
65-
= Mov { src :: Operand, dst :: Operand }
66-
| Unary { operator :: UnaryOp, operand :: Operand }
67-
| AllocateStack { bytes :: Int }
60+
= Mov Operand Operand
61+
| Unary UnaryOp Operand
62+
| Binary BinaryOp Operand Operand
63+
| Idiv Operand
64+
| Cdq
65+
| AllocateStack Int
6866
| Ret
6967
data Operand
7068
= Imm Int
7169
| Register Reg
7270
| Pseudo Text
7371
| Stack Int
7472
data UnaryOp = Neg | Not
75-
data Reg = Ax | R10
73+
data BinaryOp = Add | Sub | Mult
74+
data Reg = Ax | DX | R10 | R11
7675
```
7776

7877

@@ -220,7 +219,7 @@ The compiler provides detailed error reporting for:
220219
### The Basics
221220
- [x] A minimal compiler
222221
- [x] Unary operators
223-
- [ ] Binary operators
222+
- [x] Binary operators
224223
- [ ] Logical and relational operators
225224
- [ ] Local variables
226225
- [ ] if statements and conditional expressions

bin/halcyon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
/Users/francos/dev/halcyon/dist-newstyle/build/aarch64-osx/ghc-9.10.1/halcyon-0.1.0.0/x/halcyon/build/halcyon/halcyon
1+
/Users/francos/dev/halcyon/dist-newstyle/build/aarch64-osx/ghc-9.10.1/halcyon-0.2.2.0/x/halcyon/build/halcyon/halcyon

halcyon.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cabal-version: 3.0
22
name: halcyon
3-
version: 0.2.2.0
3+
version: 0.3.0.0
44
-- synopsis:
55
-- description:
66
license: BSD-3-Clause

justfile

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# Default recipe to show help
2+
default:
3+
@just --list
4+
5+
# Build variables
6+
binary := "halcyon"
7+
test_dir := "writing-a-c-compiler-tests"
8+
9+
# Build the project
10+
build:
11+
cabal build
12+
13+
# Build in watch mode - recompiles on file changes
14+
watch:
15+
cabal build --enable-tests --file-watch
16+
17+
# Run compiler on a file with specific stage
18+
run FILE STAGE="":
19+
cabal run {{binary}} -- {{FILE}} {{STAGE}}
20+
21+
# Run all tests
22+
test:
23+
cabal test
24+
25+
# Run specific test file or directory
26+
test-file FILE:
27+
cabal test --test-options="--match '{{FILE}}'"
28+
29+
# Run compiler test suite
30+
test-compiler:
31+
cd {{test_dir}} && ./test_compiler ../bin/{{binary}}
32+
33+
# Run compiler test suite for specific chapter
34+
test-chapter CHAPTER:
35+
cd {{test_dir}} && ./test_compiler ../bin/{{binary}} --chapter {{CHAPTER}}
36+
37+
# Run tests in watch mode
38+
test-watch:
39+
cabal test --enable-tests --file-watch
40+
41+
# Check setup for compiler test suite
42+
check-setup:
43+
cd {{test_dir}} && ./test_compiler --check-setup
44+
45+
# Format Haskell source files using ormolu
46+
fmt:
47+
find lib test -name "*.hs" -exec ormolu --mode inplace {} \;
48+
49+
# Check formatting without making changes
50+
fmt-check:
51+
find lib test -name "*.hs" -exec ormolu --mode check {} \;
52+
53+
# Run HLint suggestions
54+
lint:
55+
hlint lib test
56+
57+
# Apply HLint suggestions automatically where possible
58+
lint-apply:
59+
hlint lib test --refactor --refactor-options="--inplace"
60+
61+
# Update symlink to latest build (if needed)
62+
link:
63+
rm -f bin/{{binary}}
64+
ln -s "$(cabal list-bin {{binary}})" bin/{{binary}}
65+
66+
# Clean build artifacts
67+
clean:
68+
cabal clean
69+
rm -f bin/{{binary}}
70+
71+
# Clean and rebuild everything
72+
rebuild: clean build
73+
74+
# Create new test file from template
75+
new-test NAME:
76+
#!/usr/bin/env bash
77+
file="test/Test/{{NAME}}.hs"
78+
echo "{-# LANGUAGE OverloadedStrings #-}" > ${file}
79+
echo "module Test.{{NAME}} ({{NAME}}Specs) where" >> ${file}
80+
echo "" >> ${file}
81+
echo "import Test.Hspec" >> ${file}
82+
echo "" >> ${file}
83+
echo "{{NAME}}Specs :: Spec" >> ${file}
84+
echo "{{NAME}}Specs = describe \"{{NAME}}\" $ do" >> ${file}
85+
echo " it \"placeholder test\" $ do" >> ${file}
86+
echo " True \`shouldBe\` True" >> ${file}
87+
88+
# Generate documentation
89+
docs:
90+
cabal haddock --enable-documentation
91+
92+
# Run ghci with project modules
93+
repl:
94+
cabal repl
95+
96+
# Initialize a new test C file
97+
new-c-test CHAPTER NAME:
98+
#!/usr/bin/env bash
99+
dir="{{test_dir}}/tests/chapter_{{CHAPTER}}/valid"
100+
file="${dir}/{{NAME}}.c"
101+
mkdir -p ${dir}
102+
echo "int main(void) {" > ${file}
103+
echo " return 0;" >> ${file}
104+
echo "}" >> ${file}
105+
106+
# Show project dependency tree
107+
deps:
108+
cabal-plan deps
109+
110+
# Update cabal index
111+
update:
112+
cabal update
113+
114+
# Build project with profiling
115+
build-profile:
116+
cabal build --enable-profiling
117+
118+
# Count lines of code
119+
loc:
120+
find lib test -name "*.hs" | xargs wc -l
121+
122+
# Check for outdated dependencies
123+
outdated:
124+
cabal outdated
125+
126+
# List all modules in the project
127+
modules:
128+
find lib test -name "*.hs" -exec basename {} .hs \;
129+
130+
# Generate comprehensive project context for AI assistance
131+
context *FILENAME="ai-context.txt":
132+
#!/bin/bash
133+
echo "<documents>" > {{FILENAME}}
134+
135+
# Project Structure Document
136+
echo "<document index=\"1\">" >> {{FILENAME}}
137+
echo "<source>structure.txt</source>" >> {{FILENAME}}
138+
echo "<document_content>" >> {{FILENAME}}
139+
# Add git status and recent history
140+
echo "<git_status>" >> {{FILENAME}}
141+
git status -s >> {{FILENAME}}
142+
echo "</git_status>" >> {{FILENAME}}
143+
echo "<git_history>" >> {{FILENAME}}
144+
git log --oneline -n 10 >> {{FILENAME}} # Last 10 commits
145+
echo "</git_history>" >> {{FILENAME}}
146+
# Add directory tree
147+
echo "<directory_tree>" >> {{FILENAME}}
148+
eza -T --git-ignore >> {{FILENAME}}
149+
echo "</directory_tree>" >> {{FILENAME}}
150+
echo "</document_content>" >> {{FILENAME}}
151+
echo "</document>" >> {{FILENAME}}
152+
153+
# Cabal Configuration Document
154+
echo "<document index=\"3\">" >> {{FILENAME}}
155+
echo "<source>project-config.txt</source>" >> {{FILENAME}}
156+
echo "<document_content>" >> {{FILENAME}}
157+
cat halcyon.cabal >> {{FILENAME}}
158+
echo "</document_content>" >> {{FILENAME}}
159+
echo "</document>" >> {{FILENAME}}
160+
161+
# Source Files Document
162+
echo "<document index=\"4\">" >> {{FILENAME}}
163+
echo "<source>source-files.txt</source>" >> {{FILENAME}}
164+
echo "<document_content>" >> {{FILENAME}}
165+
find . -name "*.hs" -type f \
166+
-not -path "./dist-newstyle/*" \
167+
-not -path "./writing-a-c-compiler-tests/*" \
168+
-not -path "./c-programs/*" \
169+
-exec sh -c 'echo "<file>{}" && echo "<content>" && cat "{}" && echo "</content>"' \; >> {{FILENAME}}
170+
echo "</document_content>" >> {{FILENAME}}
171+
echo "</document>" >> {{FILENAME}}
172+
173+
echo "</documents>" >> {{FILENAME}}
174+
175+
echo "Project context saved to {{FILENAME}}"
176+
177+
# Generate module dependency graph in DOT format
178+
deps-graph *FILENAME="module-deps.dot":
179+
#!/bin/bash
180+
if ! command -v dot &> /dev/null; then \
181+
echo "graphviz not found. Install with: brew install graphviz"; \
182+
exit 1; \
183+
fi
184+
if ! command -v graphmod &> /dev/null; then \
185+
echo "graphmod not found. Install with: cabal install graphmod"; \
186+
exit 1; \
187+
fi
188+
# Generate module graph excluding external modules
189+
graphmod -i Data.Text,Data.Set,Control.Monad,System.IO \
190+
--no-cluster \
191+
-q lib/Halcyon lib/Halcyon.hs | dot -Tdot -o {{FILENAME}}
192+
echo "Module dependency graph saved to {{FILENAME}}"
193+
194+
# Install development tools needed for context generation
195+
setup-context-tools:
196+
cabal install graphmod
197+
# Ensure dot (graphviz) is installed
198+
@if ! command -v dot &> /dev/null; then \
199+
echo "Graphviz not installed. Please install:"; \
200+
echo " brew install graphviz # on macOS"; \
201+
echo " apt install graphviz # on Ubuntu"; \
202+
fi

0 commit comments

Comments
 (0)