Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let's Write a Qi Compiler! #74

Merged
merged 441 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
441 commits
Select commit Hold shift + click to select a range
a63dc73
add tests to check known counterexamples to seeming equivalences
countvajhula Oct 12, 2022
c7d781e
collapse singleton threading form
countvajhula Mar 1, 2023
54ce045
Commit wip from today's meeting
countvajhula Aug 4, 2023
be0d12b
wip from today's meeting (ignition!)
countvajhula Aug 11, 2023
d529721
implement filter-map using multiple values instead of allocated data
countvajhula Aug 11, 2023
f5c691c
add version from ben with partially evaluated match, for completeness
countvajhula Aug 12, 2023
f6432ea
add the hand-coded iteration (upper bound on performance)
countvajhula Aug 15, 2023
2be8e56
add `range-map-sum` benchmark (used in St-Amour's writeup)
countvajhula Aug 18, 2023
aef7f88
minimally incorporate stream fusion into the compiler
countvajhula Aug 18, 2023
d06df52
restore restorative optimization that was accidentally dropped
countvajhula Aug 24, 2023
931585e
test for the `filter-map` functional pipeline
countvajhula Aug 26, 2023
f3d5550
use `racket -y` in running all tests to recompile if needed
countvajhula Aug 26, 2023
d215fea
fix stream fusion (from today's qi meeting)
countvajhula Aug 26, 2023
b398594
tidy - remove deforestation wip from benchmarking module
countvajhula Sep 1, 2023
0970f7c
WIP from today's meeting
countvajhula Sep 2, 2023
8039a5c
use the much-anticipated syntax-spec-v1 from the package index :)
countvajhula Sep 2, 2023
b59139d
a couple more nonlocal testcases, using folds
countvajhula Sep 15, 2023
679de88
add starter tests to validate compiler rewrite rules
countvajhula Sep 15, 2023
b2b620f
benchmark for functional pipeline using foldr
countvajhula Sep 15, 2023
6ae27fd
foldr fusable stream terminator
countvajhula Sep 16, 2023
9ea1c97
WIP from today's meeting
countvajhula Sep 22, 2023
cca3691
remove old unused deforestation code
countvajhula Sep 29, 2023
3b22288
Implement `foldl` as a stream
countvajhula Sep 30, 2023
c4aff58
fix compiler tests by adding chirality
countvajhula Oct 1, 2023
cc3c666
consistent naming in rewrite rules
countvajhula Oct 5, 2023
c875f60
add a benchmark using `foldl`
countvajhula Oct 6, 2023
7a7af5d
rename stream-related syntax classes for clarity
countvajhula Oct 7, 2023
0c1794f
Use macro-debugger-emit to see the process-bindings expansion step in…
dzoep Oct 7, 2023
624fa3b
Make fix procedure compatible with syntax-parse rules following the f…
dzoep Oct 7, 2023
b527858
macros for emitting expansion events for the macro stepper
countvajhula Oct 14, 2023
c89a3a3
Fix nonlocal tests (use right threading) for deforestation optimizati…
dzoep Oct 20, 2023
317ba4b
Revert "Fix nonlocal tests (use right threading) for deforestation op…
dzoep Nov 5, 2023
ab19e1e
Fix the tests again.
dzoep Nov 5, 2023
c13bc24
Remove redundant inlining hint.
dzoep Nov 5, 2023
4e8f82d
Preliminary fusion for no-argument range, supporting 1 or 2 values.
dzoep Nov 5, 2023
1af613a
Support for multiple arguments to curry in producer syntax class.
dzoep Nov 5, 2023
ae1b744
Full support for range fusion.
dzoep Nov 5, 2023
db9ae68
Finish stream fusion for producers, transformers, consumers and all t…
dzoep Nov 6, 2023
11ee6f8
Move the current deforestation (both syntax and implementation parts)…
dzoep Nov 11, 2023
196096a
Fix missing requires (for ~literal matching), streamline procedures n…
dzoep Nov 11, 2023
3011919
Cleanup unused pattern variable, implement car deforestation.
dzoep Nov 11, 2023
71a7a94
Re-add begin-encourage-inline based on the benchmarks.
dzoep Nov 17, 2023
8bbc6a7
add `range-map` benchmark
countvajhula Nov 17, 2023
539fef6
fix compiler tests
countvajhula Nov 17, 2023
388b466
add a (failing) test for deforestation in nested positions
countvajhula Nov 17, 2023
77e54df
remove testing-related nesting in qi deforestation benchmark
countvajhula Nov 17, 2023
9b0bb41
validate that `range` deforestation doesn't harm performance
countvajhula Nov 17, 2023
ec912d4
fix (most) compiler tests again
countvajhula Nov 17, 2023
e367192
remove outdated compiler rewrite rule
countvajhula Nov 18, 2023
af597f1
normalization rule to collapse `values` inside a threading form
countvajhula Nov 18, 2023
a8ef2db
Add initial tests for the normalization pass
countvajhula Nov 18, 2023
6e9d7c1
improve `range-map-sum` benchmark
countvajhula Nov 20, 2023
4ff81d9
add a "long functional pipeline" benchmark
countvajhula Nov 20, 2023
0166ade
remove unused code
countvajhula Nov 20, 2023
c3ead6f
Replace `range-map` benchmark with `range-map-car`
countvajhula Nov 20, 2023
b282410
failing unit test for range-map-car
countvajhula Nov 20, 2023
a06de73
Partial implementation of producer prepare contract.
dzoep Nov 20, 2023
523004e
Refactor normalize pass into its own module
countvajhula Nov 20, 2023
d03d30e
note a todo for normalization, and remove an outdated comment
countvajhula Nov 20, 2023
4bc3b0d
Fix car stream consumer, generate all possible contracts for range va…
dzoep Nov 21, 2023
7831720
Deforestation producers - currying prepare in the right order, contra…
dzoep Nov 22, 2023
5d5f798
Preliminary implementation of consumer contracts with car as an example.
dzoep Nov 22, 2023
e82fdb1
Unified range producer syntax class + currying contracted pipeline.
dzoep Nov 23, 2023
5f4b382
fusable-stream-producer: limit the number of arguments to range to 1 …
dzoep Nov 24, 2023
0a05ecc
move a simplification from the code generation step to normalization
countvajhula Nov 22, 2023
c6236a1
Simplify deforestation tests to high level assertions
countvajhula Nov 22, 2023
f8eb731
Handle a simplified host expression in the compiler
countvajhula Nov 26, 2023
ab28b13
failing compiler tests for deforesting templates
countvajhula Nov 29, 2023
4f2331a
Rewrite partial application to a use of a blanket template
countvajhula Nov 29, 2023
302b8f3
A test to validate pre-supplying keyword arguments
countvajhula Nov 29, 2023
b8ec517
remove unused import
countvajhula Nov 29, 2023
a6281ca
match blanket templates in transformers and consumers
countvajhula Nov 29, 2023
99c11e6
add a failing test to show an issue with bindings and currying
countvajhula Nov 29, 2023
a4cad12
Add support for #%fine-template in deforested consumers.
dzoep Nov 25, 2023
f05b068
Add missing literal.
dzoep Nov 25, 2023
7a6b10e
Matching _ as ~datum.
dzoep Nov 25, 2023
3bd39cd
deforestation error reporting: implement partial de-expander for flows
dzoep Nov 26, 2023
5801a0b
Currying for #%fine-template deforested producers.
dzoep Nov 27, 2023
7e3101b
Work on simplifying deforestation pass.
dzoep Nov 29, 2023
cbcc972
deforestation: simplify consumer syntax patterns
dzoep Nov 29, 2023
bcb9c8a
add a few compiler tests for deforestation
countvajhula Nov 29, 2023
6285a06
deforestation: fix blanket template with all arguments, expand transf…
dzoep Nov 29, 2023
c3ce843
reorganize compiler tests along producer, transformer, etc.
countvajhula Nov 29, 2023
687b8db
combinatorial deforestation tests for producers using templates
countvajhula Nov 29, 2023
b007d98
Simplify compiler tests
countvajhula Nov 30, 2023
a123aba
fix invalid test
countvajhula Nov 30, 2023
d1a522c
Fix "anaphoric references" issue (resolves failing test)
countvajhula Nov 30, 2023
0bb126b
tests for keyword arguments in templates
countvajhula Nov 30, 2023
aca1a38
deforestation: fix blanket template currying
dzoep Nov 30, 2023
410cb59
deforestation: report too many arguments for blanket templates in syn…
dzoep Nov 30, 2023
c1dacb4
deforestation: preliminary support for argument count limits in synta…
dzoep Nov 30, 2023
c0636ba
deforestation: update prettify-flow-syntax de-expander to reflect lat…
dzoep Nov 30, 2023
354f337
deforestation: unify range producer syntax patterns into one
dzoep Nov 30, 2023
0787fc0
deforestation: do not duplicate producer name for contracts and error…
dzoep Nov 30, 2023
da22297
deforestation: unified producer curry maker
dzoep Nov 30, 2023
052e5d7
deforestation: fix new producer curry semantics for implicit list->cs…
dzoep Nov 30, 2023
d5fc793
deforestation: more patterns unification
dzoep Nov 30, 2023
4b3b93e
deforestation: improve invalid argument count error messages for stat…
dzoep Nov 30, 2023
37d3643
deforestation: fix error message
dzoep Nov 30, 2023
f72a2aa
deforestation: full blame information at runtime
dzoep Nov 30, 2023
eb54077
deforestation: add range producer semantic tests
dzoep Nov 30, 2023
928fbb9
deforestation: fix support for #%fine-template in fusable-stream-tran…
dzoep Nov 30, 2023
89f5cb7
include the new producer tests in the deforestation test suite
countvajhula Nov 30, 2023
f5071d5
add a couple more tests for kwargs in a blanket template
countvajhula Nov 30, 2023
bea9ea0
reorganize compiler tests into a dedicated folder (collection)
countvajhula Nov 30, 2023
74f5fe8
avoid division by zero in comparing benchmark results
countvajhula Nov 30, 2023
3be7a17
Make higher benchmark threshold the same ratio as lower one
countvajhula Nov 30, 2023
2852fbe
Normalization tests and improvements
countvajhula Dec 1, 2023
16274d0
remove old comment which I think has been addressed
countvajhula Dec 1, 2023
95db922
add a basic threading test
countvajhula Dec 6, 2023
f582ceb
remove outdated todo (again?)
countvajhula Dec 6, 2023
7db8b7c
move general and debugging-related functions into their own modules
countvajhula Dec 6, 2023
6d27154
simplify definitions and imports across phases
countvajhula Dec 6, 2023
80b08af
fix literal `range` in tests
countvajhula Dec 6, 2023
e3a1433
declare macro-debugger dependency
countvajhula Dec 7, 2023
e065803
use test-equal? in test-normalize
countvajhula Dec 10, 2023
26292ab
unit tests for `find-and-map/qi`
countvajhula Dec 10, 2023
5c539ab
organize high level compilation sequence more clearly
countvajhula Dec 10, 2023
4215189
"fix" bad test
countvajhula Dec 10, 2023
fb9641b
simplify some definitions
countvajhula Dec 11, 2023
b6e3ee0
Fix collapsing `values` in normalization
countvajhula Dec 11, 2023
849ea89
clean up normalization rules by declaring datum literals
countvajhula Dec 11, 2023
dc74148
revert phase changes to deforest.rkt for now
countvajhula Dec 11, 2023
8d7d447
Comment out failing test
countvajhula Dec 11, 2023
0b73678
deforest: format some brackets
benknoble Dec 12, 2023
897f55a
fix tests not being run on `make test`
countvajhula Dec 14, 2023
013961d
Add more counterexamples found by Ben
countvajhula Dec 13, 2023
4117389
counterexamples...
countvajhula Dec 14, 2023
9c88685
don't duplicate left and right identity rule
countvajhula Dec 14, 2023
39de7ca
remove unsound normalization rules
countvajhula Dec 14, 2023
d738621
remove failing compiler tests for the unsound rules
countvajhula Dec 14, 2023
d2d0e53
define qi functions in a uniform way
countvajhula Feb 24, 2023
acb5f25
fix "not currently expanding" issue
countvajhula Dec 14, 2023
8e4db77
Make error pattern in ~> more specific to avoid bad error message
countvajhula Dec 15, 2023
4067182
Remove invalid (yet passing on main) test
countvajhula Dec 15, 2023
a9d1dda
reorder some tests
countvajhula Dec 15, 2023
862d9f5
failing unit tests for desired binding behavior with `switch`
countvajhula Dec 15, 2023
7bc1554
add binding spec for `if` (inherited by `switch`)
countvajhula Dec 15, 2023
03fb1b1
don't look for fixed point in deforestation as it's unnecessary
countvajhula Dec 15, 2023
bc5702d
starter tests for the expander
countvajhula Dec 15, 2023
94077a9
a few more tests for the expander
countvajhula Dec 15, 2023
4316909
declare missing build dependency on syntax-spec
countvajhula Dec 15, 2023
aa141ff
clarify a comment
countvajhula Dec 15, 2023
df43041
Use de-expander to fix (in a temporary way) #134
countvajhula Dec 16, 2023
f390ced
commit missing moved de-expander
countvajhula Dec 16, 2023
2ed742c
expand de-expander to full core language (except feedback)
countvajhula Dec 16, 2023
425f672
Tests for more compile-time errors
countvajhula Dec 13, 2022
4cd21b0
test to catch a syntax error
countvajhula Dec 14, 2022
226dcac
cover de-expander in tests
countvajhula Dec 17, 2023
0b3a9ff
a comment
countvajhula Dec 18, 2023
a376715
some refactoring and tests for coverage
countvajhula Dec 20, 2023
90c4e2e
remove unused arity default in `loom-compose`
countvajhula Dec 20, 2023
b759c20
removed unused functions from core (these are in extended/impl now)
countvajhula Dec 20, 2023
940f7e0
more tests for coverage
countvajhula Dec 20, 2023
c52be32
whoops, call the right function for deforestation
countvajhula Dec 20, 2023
06c2abf
Add a test to validate that deforestation is applied anywhere
countvajhula Dec 20, 2023
9056cc8
comment out test since it doesn't pass (why?)
countvajhula Dec 20, 2023
38c36d7
Fix numeric `fanout` not getting optimized implementation
countvajhula Dec 20, 2023
f4bc60d
Remove unused literal parser from the compiler
countvajhula Dec 20, 2023
976d9a5
more test coverage
countvajhula Dec 20, 2023
a6b251f
uncommenting test since it seems like a legitimate failure
countvajhula Dec 20, 2023
57d99d2
fix test to use `deforest-pass` (still correctly failing)
countvajhula Dec 20, 2023
dc7cc53
fix deforesting of nested positions
countvajhula Dec 20, 2023
7de1212
convert compile time error in a test instead of using `eval`
countvajhula Dec 20, 2023
af6d056
make `make test` much faster by excluding the qi-doc package
countvajhula Dec 20, 2023
2fcd15b
add tests to reveal premature termination of normalization
countvajhula Dec 20, 2023
57012c6
tests to check deforestation is applied in nested and independent pos…
countvajhula Dec 20, 2023
7f374e1
Attempt to fix mutual inconsistency between `fix` and `find-and-map`
countvajhula Dec 21, 2023
b9ee296
comment out a mysteriously failing test...
countvajhula Dec 21, 2023
b688d79
More tests to cover deforestation
dzoep Dec 21, 2023
8dd5d11
Add an optimization "rules" test for the "weird bug"
countvajhula Dec 21, 2023
d299370
Add a failing test to reveal another case we should optimize
countvajhula Dec 21, 2023
8a0ef7c
bind `introduce-qi-syntax` once and use it everywhere (CR)
countvajhula Dec 21, 2023
4d51e37
Use a private submodule for `reference-qi`
countvajhula Dec 22, 2023
b62fc47
fix jumbling of clauses in de-expander for `partition` and `try`
countvajhula Dec 22, 2023
f9e6f3f
Fix(?) weird syntax pair bug
countvajhula Dec 22, 2023
84337eb
recipe for tagging syntax for testing using a template metafunction
countvajhula Dec 23, 2023
d93a561
Commit improved "weird syntax pair bug" fix from the meeting
countvajhula Dec 23, 2023
eb7bb69
First attempt at fixing the tests with the new syntax property
countvajhula Dec 23, 2023
5b81d3f
Fix failing compiler utils tests
countvajhula Dec 23, 2023
4c962e2
Fix remaining compiler tests by attaching `nonterminal` syntax property
countvajhula Dec 23, 2023
323adf9
improve test doc
countvajhula Dec 23, 2023
f6d1dd7
improve a macro used in testing for comparing syntax
countvajhula Dec 23, 2023
b4b2007
Organize utilities related to the `nonterminal` property
countvajhula Dec 27, 2023
d6f4e0b
Expose the ability to invoke the expander on demand
countvajhula Dec 27, 2023
6fd05b5
Failing test to reveal bug with multiple passes
countvajhula Dec 27, 2023
38adbd9
propagate srcloc and props in tagging with syntax property
countvajhula Dec 27, 2023
6e616d6
rename a `util` module to (compiler) `pass`
countvajhula Dec 27, 2023
8ba7aad
simplify expander tests by defining a `test-expand` macro
countvajhula Dec 27, 2023
0207d90
add an expander test and some comments
countvajhula Dec 27, 2023
7c3a1b4
provide a "getter" for the `nonterminal` syntax property
countvajhula Dec 28, 2023
507828a
Simplify and fix compiler rules tests with macros
countvajhula Dec 28, 2023
9986578
simplify deforestation rules tests further with macros
countvajhula Dec 28, 2023
2122a90
Use on-demand expansion in normalization tests
countvajhula Dec 28, 2023
dd11d60
Fix normalization bugs revealed by the new tests!
countvajhula Dec 28, 2023
6122096
(Redundantly) tag expansion output with the nonterminal property
countvajhula Dec 28, 2023
b9ee7e0
Uncomment a test that is now mysteriously working ¯\_(ツ)_/¯
countvajhula Dec 28, 2023
1ffc504
refile another `nonterminal` property related utility
countvajhula Dec 28, 2023
649d233
move normalization and deforestation rules tests into dedicated modules
countvajhula Dec 28, 2023
f2341dd
restore one test to a (legimately) failing state
countvajhula Dec 28, 2023
212406c
remove unused test suite
countvajhula Dec 29, 2023
c1dee81
Fix "full cycle" test so it runs in phase 1
countvajhula Dec 29, 2023
6f2a668
Propagage `nonterminal` property after normalization
countvajhula Dec 29, 2023
fbb0740
Move remaining compiler rules tests into phase 1
countvajhula Dec 29, 2023
687069a
remove Racket 8.5 from CI matrix for testing purposes...
countvajhula Dec 29, 2023
b5add8e
bump racket test matrix version to 8.6
countvajhula Dec 29, 2023
a71be35
bump racket version to 8.7?
countvajhula Dec 29, 2023
8203828
bump to 8.10
countvajhula Dec 29, 2023
0c8a02a
actually bump to 8.10..
countvajhula Dec 29, 2023
e100735
try racket 8.9
countvajhula Dec 29, 2023
305ea0d
Adjust test matrix to reflect known compatibility
countvajhula Dec 30, 2023
578d6c4
only attach the nonterminal property to the toplevel expression
countvajhula Dec 30, 2023
9090dc4
update a comment
countvajhula Dec 30, 2023
a2fe501
try BC 8.5 again just in case
countvajhula Dec 30, 2023
0d27f0f
revert to version 8.9 in the test matrix
countvajhula Dec 30, 2023
ec73d9e
update some comments
countvajhula Dec 30, 2023
2744c68
add 8.5 back; modify test workflow to run all jobs even if some fail
countvajhula Jan 3, 2024
59fedaa
fix CI workflow so it wouldn't always show success
countvajhula Jan 3, 2024
73e1fa0
try quoting srcloc structure
countvajhula Jan 5, 2024
c09b926
restore test workflow config
countvajhula Jan 5, 2024
6c066c0
fix source location marshalling by converting to vector
countvajhula Jan 5, 2024
8851b15
Link to the wiki doc on deforestation from the compiler module
countvajhula Jan 6, 2024
a14fc4f
Merge pull request #147 from countvajhula/fix-marshalling-issue
countvajhula Jan 6, 2024
d63cbaa
add a common utility to construct a sandbox evaluator for docs
countvajhula Jan 6, 2024
3bd04eb
Use `define-qi-syntax` to simplify some macro definitions
countvajhula Jan 6, 2024
ff65551
Add a cautionary comment re: the form property
countvajhula Jan 6, 2024
db2e27e
Remove old comment advocating use of literal matching in the compiler
countvajhula Jan 6, 2024
c2c1522
Make `qi-expansion-step` a function and don't `provide` it
countvajhula Jan 6, 2024
7046c56
Use `quote-syntax` instead of `syntax`
countvajhula Jan 6, 2024
2586bec
Merge pull request #148 from countvajhula/address-mb-code-review
countvajhula Jan 6, 2024
ff84ac4
doc: update grammar for the flow macro
countvajhula Jan 5, 2024
5ac92d3
update advice on currying and partial application quirks
countvajhula Jan 5, 2024
3dbd5d3
minor capitalization in a comment
countvajhula Jan 5, 2024
568d336
basic doc for the `as` binding form
countvajhula Jan 5, 2024
5118880
doc: counting flows
countvajhula Jan 5, 2024
cc35173
mention performance gains in some parts of the docs
countvajhula Jan 5, 2024
16ddc9a
add a placeholder doc page for the compiler (and expander)
countvajhula Jan 5, 2024
36e9896
document an error re: ambiguous binding
countvajhula Jan 5, 2024
e4ddfe7
fix tab indent
countvajhula Jan 5, 2024
e52aeda
fix a typo
countvajhula Jan 6, 2024
9b2e6a3
remove unused test dependency on syntax-spec
countvajhula Jan 11, 2024
009fa0e
doc: avoid empty production of `literal`
countvajhula Jan 11, 2024
30fdffe
doc: basic example of binding more than one value with `as`
countvajhula Jan 11, 2024
87758ad
doc: variable scoping rules
countvajhula Jan 11, 2024
e425d93
doc: minor improvements
countvajhula Jan 11, 2024
3e4f7d9
doc: try `only-space-in` to link qi form literals
countvajhula Jan 12, 2024
a97879a
remove draft "under the hood" doc
countvajhula Jan 12, 2024
f6e7e1e
doc: relating to deforestation and order of effects
countvajhula Jan 12, 2024
58ed04e
doc: fix hierarchy
countvajhula Jan 12, 2024
64976db
Merge pull request #146 from countvajhula/update-docs-for-qi4
countvajhula Jan 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
run: make install-sdk
- name: Run benchmark
shell: 'bash --noprofile --norc -eo pipefail {0}'
run: make report-benchmarks | tee benchmarks.txt
run: make performance-report | tee benchmarks.txt
- name: Store benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: true
matrix:
racket-variant: ['BC', 'CS']
racket-version: ['8.3', 'stable']
racket-version: ['8.5', 'stable']
experimental: [false]
include:
- racket-version: 'current'
Expand Down
68 changes: 48 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ DEPS-FLAGS=--check-pkg-deps --unused-pkg-deps

help:
@echo "install - install package along with dependencies"
@echo "install-sdk - install the SDK which includes developer tools"
@echo "remove - remove package"
@echo "remove-sdk - remove SDK; this will not remove SDK dependencies"
@echo "build - Compile libraries"
@echo "build-docs - Build docs"
@echo "build-standalone-docs - Build self-contained docs that could be hosted somewhere"
@echo "build-all - Compile libraries, build docs, and check dependencies"
@echo "clean - remove all build artifacts"
@echo "clean-sdk - remove all build artifacts in SDK paths"
@echo "check-deps - check dependencies"
@echo "test - run tests"
@echo "test-with-errortrace - run tests with error tracing"
Expand All @@ -27,6 +30,8 @@ help:
@echo " definitions"
@echo " macro"
@echo " util"
@echo " expander"
@echo " compiler"
@echo " probe"
@echo " Note: As probe is not in qi-lib, it isn't part of"
@echo " the tests run in the 'test' target."
Expand All @@ -37,9 +42,14 @@ help:
@echo "docs - view docs in a browser"
@echo "profile - Run comprehensive performance benchmarks"
@echo "profile-competitive - Run competitive benchmarks"
@echo "profile-forms - Run benchmarks for individual Qi forms"
@echo "profile-local - Run benchmarks for individual Qi forms"
@echo "profile-nonlocal - Run nonlocal benchmarks exercising many components at once"
@echo "profile-selected-forms - Run benchmarks for Qi forms by name (command only)"
@echo "report-benchmarks - Run benchmarks for Qi forms and produce results for use in CI"
@echo "performance-report - Run benchmarks for Qi forms and produce results for use in CI and for measuring regression"
@echo " For use in regression: make performance-report > /path/to/before.json"
@echo "performance-regression-report - Run benchmarks for Qi forms against a reference report."
@echo " make performance-regression-report REF=/path/to/before.json"


# Primarily for use by CI.
# Installs dependencies as well as linking this as a package.
Expand Down Expand Up @@ -82,36 +92,47 @@ build-standalone-docs:
clean:
raco setup --fast-clean --pkgs $(PACKAGE-NAME)-{lib,test,doc,probe}

clean-sdk:
raco setup --fast-clean --pkgs $(PACKAGE-NAME)-sdk

# Primarily for use by CI, after make install -- since that already
# does the equivalent of make setup, this tries to do as little as
# possible except checking deps.
check-deps:
raco setup --no-docs $(DEPS-FLAGS) $(PACKAGE-NAME)

# Suitable for both day-to-day dev and CI
# Note: we don't test qi-doc since there aren't any tests there atm
# and it also seems to make things extremely slow to include it.
test:
raco test -exp $(PACKAGE-NAME)-{lib,test,doc,probe}
raco test -exp $(PACKAGE-NAME)-{lib,test,probe}

test-flow:
racket $(PACKAGE-NAME)-test/tests/flow.rkt
racket -y $(PACKAGE-NAME)-test/tests/flow.rkt

test-on:
racket $(PACKAGE-NAME)-test/tests/on.rkt
racket -y $(PACKAGE-NAME)-test/tests/on.rkt

test-threading:
racket $(PACKAGE-NAME)-test/tests/threading.rkt
racket -y $(PACKAGE-NAME)-test/tests/threading.rkt

test-switch:
racket $(PACKAGE-NAME)-test/tests/switch.rkt
racket -y $(PACKAGE-NAME)-test/tests/switch.rkt

test-definitions:
racket $(PACKAGE-NAME)-test/tests/definitions.rkt
racket -y $(PACKAGE-NAME)-test/tests/definitions.rkt

test-macro:
racket $(PACKAGE-NAME)-test/tests/macro.rkt
racket -y $(PACKAGE-NAME)-test/tests/macro.rkt

test-util:
racket $(PACKAGE-NAME)-test/tests/util.rkt
racket -y $(PACKAGE-NAME)-test/tests/util.rkt

test-expander:
racket -y $(PACKAGE-NAME)-test/tests/expander.rkt

test-compiler:
racket -y $(PACKAGE-NAME)-test/tests/compiler.rkt

test-probe:
raco test -exp $(PACKAGE-NAME)-probe
Expand Down Expand Up @@ -159,20 +180,27 @@ cover: coverage-check coverage-report
cover-coveralls:
raco cover -b -f coveralls -p $(PACKAGE-NAME)-{lib,test}

profile-forms:
echo "Profiling forms..."
racket $(PACKAGE-NAME)-sdk/profile/forms.rkt
profile-local:
racket $(PACKAGE-NAME)-sdk/profile/local/report.rkt

profile-loading:
racket $(PACKAGE-NAME)-sdk/profile/loading/report.rkt

profile-selected-forms:
@echo "Use 'racket profile/forms.rkt' directly, with -f form-name for each form."
@echo "Use 'racket $(PACKAGE-NAME)-sdk/profile/local/report.rkt' directly, with -s form-name for each form."

profile-competitive:
echo "Running competitive benchmarks..."
racket $(PACKAGE-NAME)-sdk/profile/competitive.rkt
cd $(PACKAGE-NAME)-sdk/profile/nonlocal; racket report-competitive.rkt

profile-nonlocal:
cd $(PACKAGE-NAME)-sdk/profile/nonlocal; racket report-intrinsic.rkt -l qi

profile: profile-local profile-nonlocal profile-loading

profile: profile-competitive profile-forms
performance-report:
@racket $(PACKAGE-NAME)-sdk/profile/report.rkt -f json

report-benchmarks:
@racket $(PACKAGE-NAME)-sdk/profile/report.rkt
performance-regression-report:
@racket $(PACKAGE-NAME)-sdk/profile/report.rkt -r $(REF)

.PHONY: help install remove build build-docs build-all clean check-deps test test-flow test-on test-threading test-switch test-definitions test-macro test-util test-probe test-with-errortrace errortrace errortrace-flow errortrace-on errortrace-threading errortrace-switch errortrace-definitions errortrace-macro errortrace-util errortrace-probe docs cover coverage-check coverage-report cover-coveralls profile-forms profile-selected-forms profile-competitive profile report-benchmarks
.PHONY: help install remove build build-docs build-all clean check-deps test test-flow test-on test-threading test-switch test-definitions test-macro test-util test-expander test-compiler test-probe test-with-errortrace errortrace errortrace-flow errortrace-on errortrace-threading errortrace-switch errortrace-definitions errortrace-macro errortrace-util errortrace-probe docs cover coverage-check coverage-report cover-coveralls profile-local profile-loading profile-selected-forms profile-competitive profile-nonlocal profile performance-report performance-regression-report
30 changes: 30 additions & 0 deletions qi-doc/scribblings/eval.rkt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#lang racket/base

(provide make-eval-for-docs)

(require racket/sandbox)

(define (make-eval-for-docs . exprs)
;; The "trusted" sandbox configuration is needed possibly
;; because of the interaction of binding spaces with
;; sandbox evaluator. For more context, see the Qi wiki
;; "Qi Compiler Sync Sept 2 2022."
(call-with-trusted-sandbox-configuration
(lambda ()
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-memory-limit #f])
(apply make-evaluator
'racket/base
'(require qi
qi/probe
(only-in racket/list range first rest)
racket/format
racket/string
(only-in racket/function curry)
(for-syntax syntax/parse
racket/base))
'(define (sqr x)
(* x x))
'(define ->string number->string)
exprs)))))
53 changes: 30 additions & 23 deletions qi-doc/scribblings/field-guide.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,12 @@
@require[scribble/manual
scribble-abbrevs/manual
scribble/example
racket/sandbox
"eval.rkt"
@for-label[qi
qi/probe
racket]]

@(define eval-for-docs
(parameterize ([sandbox-output 'string]
[sandbox-error-output 'string]
[sandbox-memory-limit #f])
(make-evaluator 'racket/base
'(require qi
qi/probe
(only-in racket/list range)
racket/string
(for-syntax syntax/parse
racket/base))
'(define (sqr x)
(* x x)))))
@(define eval-for-docs (make-eval-for-docs))

@title{Field Guide}

Expand All @@ -41,6 +29,10 @@ Decompose your @tech{flow} into its smallest components, and name each so that t

A journeyman of one's craft -- a woodworker, electrician, or a plumber, say -- always goes to work with a trusty toolbox that contains the tools of the trade, some perhaps even of their own design. An electrician, for instance, may have a voltage tester, a multimeter, and a continuity tester in her toolbox. Although these are "debugging" tools, they aren't just for identifying bugs -- by providing rapid feedback, they enable her to explore and find creative solutions quickly and reliably. It's the same with Qi. Learn to use the @seclink["Debugging"]{debugging tools}, and use them often.

@subsection{Be Intentional About Effects}

Qi encourages a style that avoids "accidental" effects. A flow should either be pure (that is, it should be free of "side effects" such as printing to the screen or writing to a file), or its entire purpose should be to fulfill a side effect. It is considered inadvisable to have a function with sane inputs and outputs (resembling a pure function) that also performs a side effect. It would be better to decouple the effect from the rest of your function (@seclink["Use_Small_Building_Blocks"]{splitting it into smaller functions}, as necessary) and perform the effect explicitly via the @racket[effect] form, or otherwise escape from Qi using something like @racket[esc] (note that @seclink["Identifiers"]{function identifiers} used in a flow context are implicitly @racket[esc]aped) in order to perform the effect. This will ensure that there are no surprises with regard to @seclink["Order_of_Effects"]{order of effects}.

@section{Debugging}

There are three prominent debugging strategies which may be used independently or in tandem -- @seclink["Using_Side_Effects"]{side effects}, @seclink["Using_a_Probe"]{probing}, and @seclink["Using_Fixtures"]{fixtures}.
Expand Down Expand Up @@ -208,6 +200,17 @@ Methodical use of @racket[gen] together with the @seclink["Using_a_Probe"]{probe

@bold{Common example}: Syntax patterns are defined in the @seclink["stxparse" #:doc '(lib "syntax/scribblings/syntax.scrbl")]{syntax/parse} library. If you are using them in Qi macros, you will need to @racket[(require syntax/parse)] at the appropriate phase level.

@subsubsection{Identifier's Binding is Ambiguous}

@codeblock{
; count: identifier's binding is ambiguous
; in: count
}

@bold{Meaning}: The @tech/guide{expander} attempted to resolve a @tech/reference{reference} and found more than one possible @tech/reference{binding}.

@bold{Common example}: Having a Racket function in scope that has the same name as a Qi form, and attempting to use this @seclink["Identifiers"]{unqualified identifier} as a flow. To avoid the issue, rename the Racket function to something else, or use an explicit @racket[esc] to indicate the Racket binding.

@subsubsection{Not Defined as Syntax Class}

@codeblock{
Expand Down Expand Up @@ -322,7 +325,7 @@ But in an idle moment, this clever shortcut may tempt you:
(~> (3) ((get-f 1)))
]

That is, since Qi typically interprets parenthesized expressions as @seclink["Templates_and_Partial_Application"]{partial application templates}, you might expect that this would pass the value @racket[3] to the function resulting from @racket[(get-f 1)]. In fact, that isn't what happens, and an error is raised instead. As there is only one datum within the outer pair of parentheses in @racket[((get-f 1))], the usual interpretation as partial application would not be useful, and could even lead to unexpected behavior (at least, with the current implementation that uses Racket's @racket[curry]). So instead, Qi attempts to interpret the expression as written, that is, as if it were wrapped in @racket[esc]. As a result, it attempts to evaluate @racket[((get-f 1))] and expects to receive a value that can be used as a @tech{flow} here. If, as in the above expression, the function resulting from @racket[(get-f 1)] expects a single argument, this is now an error as it is being invoked with none.
That is, since Qi typically interprets parenthesized expressions as @seclink["Templates_and_Partial_Application"]{partial application templates}, you might expect that this would pass the value @racket[3] to the function resulting from @racket[(get-f 1)]. In fact, that isn't what happens, and an error is raised instead. As there is only one datum within the outer pair of parentheses in @racket[((get-f 1))], the usual interpretation as partial application would not typically be useful, so Qi opts to treat it as invalid syntax.

One way to dodge this is by using an explicit template:

Expand All @@ -332,14 +335,6 @@ One way to dodge this is by using an explicit template:

This works in most cases, but it has different semantics than the version using @racket[esc], as that version evaluates the escaped expression first to yield the @tech{flow} that will be applied to inputs, while this one only evaluates the (up to that point, incomplete) expression when it is actually invoked with arguments. In the most common cases there will be no difference to the result, but if the flow is invoked multiple times (for instance, if it were first defined as @racket[(define-flow my-flow (☯ ((get-f 1) _)))]), then the expression too would be evaluated multiple times, producing different functions each time. This may be computationally more expensive than using @racket[esc], and also, if either @racket[get-f] or the function it produces is stateful in any way (for instance, if it is a @hyperlink["https://www.gnu.org/software/guile/manual/html_node/Closure.html"]{closure} or if there is any randomness involved), then this version would also produce different results than the @racket[esc] version.

Another way to do it is to simply promote the expression out of the nest:

@racketblock[
(~> (3) (get-f 1))
]

Now, you might, once again, expect this to be treated as a partial application template, so that this would be equivalent to @racket[(get-f 3 1)] and would raise an error. But in fact, since the expression @racket[(get-f 1)] happens to be fully qualified with all the arguments it needs, the currying employed under the hood to implement partial application in this case @seclink["Using_Racket_to_Define_Flows"]{evaluates to a function result right away}. This then receives the value @racket[3], and consequently, this expression produces the correct result.

So in sum, it's perhaps best to rely on @racket[esc] in such cases to be as explicit as possible about what you mean, rather than rely on quirks of the implementation that are revealed at this boundary between two languages.

@subsubsection{Mutable Values Defy the Laws of Flows}
Expand All @@ -359,6 +354,18 @@ Worse still, even though this computation raises an error, we find that the orig

So in general, use mutable values with caution. Such values can be useful as side effects, for instance to capture some idea of statefulness, perhaps keeping track of the number of times a @tech{flow} was invoked. But they should generally not be used as inputs to a flow, especially if they are to be mutated.

@subsubsection{Order of Effects}

Qi flows may exhibit a different order of effects (in the functional programming sense) than equivalent Racket functions.

Consider the Racket expression: @racket[(map sqr (filter odd? (list 1 2 3 4 5)))]. As this invokes @racket[odd?] on all of the elements of the input list, followed by @racket[sqr] on all of the elements of the intermediate list, if we imagine that @racket[odd?] and @racket[sqr] print their inputs as a side effect before producing their results, then executing this program would print the numbers in the sequence @racket[1,2,3,4,5,1,3,5].

The equivalent Qi flow is @racket[(~> ((list 1 2 3 4 5)) (filter odd?) (map sqr))]. As this sequence is @seclink["Don_t_Stop_Me_Now"]{"deforested" by Qi's compiler} to avoid multiple passes over the data and the memory overhead of intermediate representations, it invokes the functions in sequence @emph{on each element} rather than @emph{on all of the elements of each list in turn}. The printed sequence with Qi would be @racket[1,1,2,3,3,4,5,5].

Yet, either implementation produces the same output: @racket[(list 1 9 25)].

So, to reiterate, while the output of Qi flows will be the same as the output of equivalent Racket expressions, they may nevertheless exhibit a different order of effects.

@section{Effectively Using Feedback Loops}

@racket[feedback] is Qi's most powerful looping form, useful for arbitrary recursion. As it encourages quite a different way of thinking than Racket's usual looping forms do, here are some tips on "grokking" it.
Expand Down
Loading