more content

This commit is contained in:
2025-07-05 11:00:24 +02:00
parent daedadb35f
commit 277c3c485d
3 changed files with 106 additions and 12 deletions

View File

@@ -212,6 +212,22 @@
] ]
} }
#let spoiler(content) = {
[#context if is-html() {
html-style(class:"hide", "", content)
} else {
content
}]
}
#let inline-block(content) = {
[#context if is-html() {
html-style("white-space:nowrap;", content)
} else {
block(breakable:false, content)
}]
}
#let table-of-contents() = { #let table-of-contents() = {
html-style(class:"table-of-contents", "", box( html-style(class:"table-of-contents", "", box(
stroke: black, stroke: black,
@@ -235,14 +251,18 @@
] ]
}) })
])) + html-style(class:"table-of-contents", "", html-script-dom-onload(" ])) + html-style(class:"table-of-contents", "", html-script-dom-onload("
let tags = ['h2','h3','h4'].flatMap(x => Array.from(document.getElementsByTagName(x))); let tags = ['h2', 'h3', 'h4'].flatMap(x => Array.from(document.getElementsByTagName(x))).sort((a, b) => a.getBoundingClientRect().top - b.getBoundingClientRect().top);
document.getElementById('headingr-0').classList.add('current') let pageHeight = document.documentElement.scrollHeight-window.innerHeight;
document.addEventListener('scroll', (event) => { document.addEventListener('scroll', (event) => {
let curr = tags.map(x => [x, (x.getBoundingClientRect().top + x.getBoundingClientRect().bottom) / 2]).filter(x => x[1] >= 0).sort((a,b) => a[1] > b[1])[0][0]; let progress = -(document.documentElement.getBoundingClientRect().y / pageHeight);
let idx = tags.sort((a,b) => a.getBoundingClientRect().top > b.getBoundingClientRect().top).map((x, idx) => [idx, x]).filter(x => x[1] == curr)[0][0]; let delta = progress * window.innerHeight;
Array.from(document.getElementsByClassName('headingr')).map(x => x.classList.remove('current')) let idx = tags.map(x => 0 > x.getBoundingClientRect().top - delta).lastIndexOf(true);
document.getElementById('headingr-'+idx).classList.add('current') Array.from(document.getElementsByClassName('headingr')).map(x => x.classList.remove('current'));
}); if (idx != -1) {
document.getElementById('headingr-' + idx).classList.add('current');
}
}
);
") + [ ") + [
#context if is-html() { #context if is-html() {
html.elem("style", " html.elem("style", "

View File

@@ -59,7 +59,7 @@
Doing pattern matching this way has many disadvantages. Doing pattern matching this way has many disadvantages.
\ \
Some (but not all) disadvantages: Some (but not all):
- debugging pattern match rules can be hard - debugging pattern match rules can be hard
- IR rewrites need to be tracked manually (for debugging) - IR rewrites need to be tracked manually (for debugging)
- source locations and debug information also need to be tracked manually, which often isn't implemented very well. - source locations and debug information also need to be tracked manually, which often isn't implemented very well.
@@ -166,7 +166,7 @@
- the compiler could AOT compile patterns - the compiler could AOT compile patterns
- the compiler could optimize, analyze, and combine patterns to reduce compile time. - the compiler could optimize, analyze, and combine patterns to reduce compile time.
- IR (de-)serialization infrastructure in the compiler can also be used to exchange peephole optimizations. - IR (de-)serialization infrastructure in the compiler can also be used to exchange peephole optimizations.
- bragging rights: your compiler represents it's own patterns in it's own IR - bragging rights: your compiler represents its patterns in it's own IR
] ]
#section[ #section[
@@ -177,6 +177,29 @@
The advantage of this over just having a rewrite dialect is that it makes patterns even more readable (and maintainable!) The advantage of this over just having a rewrite dialect is that it makes patterns even more readable (and maintainable!)
] ]
#section[
== egg
Some people might say: "bUt Im JuSt GoInG tO uSe EgG, i DoNt NeEd A pAtTeRn MaTcHiNg DiAlEcT"
(specifically #spoiler[otesunki] said something like that)
#flink("https://egraphs-good.github.io/")[egg] is a IR pattern matching and transformation library
that uses #inline-block(flink("https://en.wikipedia.org/wiki/E-graph")[E-Graphs]) to
magically solves (almost) all problems regarding IR pattern matching.
Even though egg solves most problems, I still recommend using a pattern matching dialect, especially in multi-level compilers,
to be more flexible, and have more future-proof pattern matching, if for example there suddenly is a better alternative to egg,
or you decide that you want to match some complex patterns manually.
]
#section[
A problem with using egg in combination with pattern matching dialects is that it might be harder
to write the code to convert the pattern matching dialect to egg patterns.
Additionally, some more complex transformations (not the matches) can't always be directly converted to egg transformations
(depending on the feature set provided by the transformation dialect),
but that can be solved by using a custom ```rust egg::Applier```
]
#section[ #section[
= More Advantages of Structured Pattern Matching = More Advantages of Structured Pattern Matching
@@ -192,7 +215,7 @@
#section[ #section[
== Reversible Transformations == Reversible Transformations
I don't think that there currently is any compiler that does this. I don't think that there currently is any compiler that does this.
If you do know one, again, please #flink(alex_contact_url)[contact me.] If you do know one, again, please contact me.
] ]
#section[ #section[
@@ -207,7 +230,7 @@
#section[ #section[
This is not just the case for "low-level" things like bit tests, but also high level concepts, This is not just the case for "low-level" things like bit tests, but also high level concepts,
like a reduction over an array, or even the implementation of a whole algorithm. like a reduction over an array, or even the implementation of a whole algorithm.
For example LLVM, since recently, can detect implementations of #flink("https://en.wikipedia.org/wiki/Cyclic_redundancy_check")[CRC]. For example LLVM, since recently, can detect implementations of #flink("https://en.wikipedia.org/wiki/Cyclic_redundancy_check")[CRC.]
] ]
#section[ #section[
@@ -244,6 +267,54 @@
I don't think any compiler currently does this either. I don't think any compiler currently does this either.
] ]
#section[
= Problems with Pattern Matching
The main problem is ordering the patterns.
As an example, consider these three patterns:
#context html-frame[```lisp
;; A
(add x:Const y) => (add y x)
;; B
(sub (add x y:Const) z:Const) => (lea x y (const_neg z))
;; C
(add x 1) => (inc x)
```]
]
#section[
Now what should the compiler do when it sees this?
#context html-frame[```lisp (sub (add 5 1) 2)```]
]
#section[
All three patterns would match:
#context html-frame[```lisp
;; apply A
(sub (add 5 1) 2) => (sub (add 1 5) 2)
;; only B applies now
(sub (add 1 5) 2) => (lea 1 5 (const_neg 2))
;; nothing applies anymore
;; alternatively apply B
(sub (add 5 1) 2) => (lea 5 1 (const_neg 2))
;; nothing applies anymore
;; atlernatively apply C
(sub (add 5 1) 2) => (sub (inc 5) 2)
;; nothing applies anymore
```]
]
#section[
Now which of those transformations should be performed?
This is not as easy to solve as it seems, especially in the context of instruction selection (specifically scheduling),
where the performance on processors depends on a sequence of instructions, instead of just a single instruction.
]
#section[ #section[
= Conclusion = Conclusion
One can see how pattern matching dialects are the best option by far. One can see how pattern matching dialects are the best option by far.

View File

@@ -60,6 +60,9 @@
width: 100% !important; width: 100% !important;
} }
} }
.hide { display: inline; background: black; transition: background 0.3s linear; }
.hide:hover, .hide:focus { background: transparent; }
") ")
}], }],
)), )),