Skip to content

Commit c98ef4d

Browse files
committed
Patch up links to new posts
1 parent 5daad57 commit c98ef4d

5 files changed

+16
-16
lines changed

_posts/2025-08-31-classic-clojure-compiler-contemplation.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ The other posts in the series are:
1414
- [C4: Symbolic of what?]({{site.baseurl}}{% post_url 2025-09-02-symbolic-of-what %}) - A little digression on what symbols represent
1515
- [C4: ISeq clarity]({{site.baseurl}}{% post_url 2025-09-03-iseq-clarity %}) - How to analyze an `ISeq`
1616
- [C4: Functional anatomy]({{site.baseurl}}{% post_url 2025-09-04-functional-anatomy %}) - How functions are implemented in Clojure
17-
- __C4: fn*: talkin' 'bout my generation__ - Code-gen for functions
18-
- __C4: Tag! You're int!__ - Type analysis by the compiler
19-
- __C4: Primitive urges__ -- How primitive types are handled
20-
- __C4: Inline skating__ - How inlining is used to optimize performance
21-
- __C4: Key in-site__ Keyword callsites
22-
- __C4: Is there a protocol for that?__ -- Protocol implementation
17+
- [C4: fn*: talkin' 'bout my generation]({{site.baseurl}}{% post_url 2025-10-15-fn-star-talkin-bout-my-generation %}) - Code-gen for functions
18+
- [C4: Tag! You're int!]({{site.baseurl}}{% post_url 2025-10-16-tag-youre-int %}) - Type analysis by the compiler
19+
- [C4: Primitive urges]({{site.baseurl}}{% post_url 2025-10-17-primitive-urges %}) - How primitive types are handled
20+
- [C4: Inline skating]({{site.baseurl}}{% post_url 2025-10-18-inline-skating %}) - How inlining is used to optimize performance
21+
- [C4: Key in-site]({{site.baseurl}}{% post_url 2025-10-19-key-in-site %}) - Keyword callsites
22+
- [C4: Is there a protocol for that?]({{site.baseurl}}{% post_url 2025-10-20-is-there-a-protocol-for-that %}) - Protocol implementation
2323
- __C4: A time for reflection__ -- Reflection and dynamic callsites
2424
- __C4: Out of control__ -- Some points about flow of control and data in the compiler
2525
- __C4: Some assembly required__ -- Assembly generation for AOT compilation

_posts/2025-10-15-fn-star-talkin-bout-my-generation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The `ObjExpr` class maintains the following collections:
5555
- `ProtocolCallsites`: places where protocol methods are called.
5656

5757

58-
`Constants` contributes static fields to the function class. `Closes` defines the values needed for the constructor of the function class. `KeywordCallsites` and `ProtocolCallsites` also contribute static fields. We'll discuss keyword callsites in [C4: Key in-site][TBD]. We'll discuss protocol callsites in [C4: Is there a protocol for that?][TBD].
58+
`Constants` contributes static fields to the function class. `Closes` defines the values needed for the constructor of the function class. `KeywordCallsites` and `ProtocolCallsites` also contribute static fields. We'll discuss keyword callsites in [C4: Key in-site]{{site.baseurl}}{% post_url 2025-10-19-key-in-site %}. We'll discuss protocol callsites in [C4: Is there a protocol for that?]{{site.baseurl}}{% post_url 2025-10-20-is-there-a-protocol-for-that %}.
5959

6060
Let's look at some examples.
6161

_posts/2025-10-16-tag-youre-int.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Clojurists by nature are type-loose; they'd prefer not to think about types. Bu
1313

1414
The Clojure compiler computes and propagates type information throughout the abstract syntax tree (AST) as it is constructed. These calculations combine user-supplied type hints, characteristics of individual functions (return types, signatures of host platform methods), and inherent characteristics of the each basic expression class.
1515

16-
This post explores how typing information is propagated through the AST. In post [Primitive urges][TBD], we will see how the compiler uses this information to avoid boxing of numeric values. How reflection is avoided will be covered in [C4: A time for reflection][TBD].
16+
This post explores how typing information is propagated through the AST. In post [C4: Primitive urges]({{site.baseurl}}{% post_url 2025-10-17-primitive-urges %}), we will see how the compiler uses this information to avoid boxing of numeric values. How reflection is avoided will be covered in [C4: A time for reflection][TBD].
1717

1818
## Just a hint
1919

@@ -256,7 +256,7 @@ The only remaining `HostExpr` derivative is `InstanceZeroArityCallExpr`. This i
256256

257257
That leaves us with `NewExpr`. For `NewExpr`, we know the type we are creating; that gives us our `ClrType`.
258258

259-
I'll toss one more in here. Though not derived from `HostExpr`, `StaticInvokeExpr` is just a special case of `StaticMethodExpr` where the method is an `invokeStatic` on an `IFn`-derived class. This node type comes up in direct linking of function calls. For more information, refer to [C4: Functional anatomy]({{site.baseurl}}{% post_url 2025-09-04-functional-anatomy %}) and [C4: fn*: talkin' 'bout my generation][TBD].
259+
I'll toss one more in here. Though not derived from `HostExpr`, `StaticInvokeExpr` is just a special case of `StaticMethodExpr` where the method is an `invokeStatic` on an `IFn`-derived class. This node type comes up in direct linking of function calls. For more information, refer to [C4: Functional anatomy]({{site.baseurl}}{% post_url 2025-09-04-functional-anatomy %}) and [C4: fn*: talkin' 'bout my generation]({{site.baseurl}}{% post_url 2025-10-15-fn-star-talkin-bout-my-generation %}).
260260

261261

262262
## Symbols and bindings
@@ -348,7 +348,7 @@ _cachedHasType = Tag != null || (Init != null && Init.HasClrType);
348348
```
349349

350350
We have a type if either we have a tag or we have an initialization form and _it_ has a type.
351-
There is a condition above this which negates having a type. In English: if there is an initialization form, and it has a type and its type is a primitive type (this would have to be a tag on the initialization expression), but the initialization expression is not a `MaybePrimitiveExpr` -- something capable of emitting a primitive value -- then we are in trouble. We want to hold a primitive value without boxing, but our initialization is at best going to yield a boxed value. So we say we don't have a type. We discuss primitive types in great detail in [C4: Primitive urges][TBD].
351+
There is a condition above this which negates having a type. In English: if there is an initialization form, and it has a type and its type is a primitive type (this would have to be a tag on the initialization expression), but the initialization expression is not a `MaybePrimitiveExpr` -- something capable of emitting a primitive value -- then we are in trouble. We want to hold a primitive value without boxing, but our initialization is at best going to yield a boxed value. So we say we don't have a type. We discuss primitive types in great detail in [C4: Primitive urges]({{site.baseurl}}{% post_url 2025-10-17-primitive-urges %}).
352352

353353
If we do have a type, a user-supplied tag takes precedence over the type of the initialization expression, per usual.
354354

@@ -476,7 +476,7 @@ else
476476
method._retType = typeof(object);
477477
```
478478

479-
By the time you get through this code, `method._retType` is either `typeof(long)`, `typeof(double)`, or `typeof(object)`. Hmmm. Where have we seen this combo before? ODL ... primitive interfaces. We retain just enough information to calculate which prim interface we should implement. (See [C4: Primitive urges][TBD].)
479+
By the time you get through this code, `method._retType` is either `typeof(long)`, `typeof(double)`, or `typeof(object)`. Hmmm. Where have we seen this combo before? ODL ... primitive interfaces. We retain just enough information to calculate which prim interface we should implement. (See [C4: Primitive urges]({{site.baseurl}}{% post_url 2025-10-17-primitive-urges %}).)
480480

481481
We've handled:
482482

@@ -543,7 +543,7 @@ Does your head hurt yet? I've been whistling past this graveyard for 15 years.
543543

544544
## Recur-ing nightmares
545545

546-
We've had enough. I'll put off discussion of how type information plays into `RecurExpr` until later. See [C4: Primitive urges][TBD].
546+
We've had enough. I'll put off discussion of how type information plays into `RecurExpr` until later. See [C4: Primitive urges]({{site.baseurl}}{% post_url 2025-10-17-primitive-urges %}).
547547

548548
## Processing tags
549549

_posts/2025-10-17-primitive-urges.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ A given instance of a `MaybePrimitiveExpr`-implementating class may or may not b
4949

5050
For most of these, the computation of `CanEmitPrimitive` is straightforward. For example, `NumberExpr` can always emit a primitive value; it can emit only `long` and `double` values. Whether a `BodyExpr` can emit a primitive value depends on whether its last expression can emit a primitive value. `HostExpr`-derived classes can emit a primitive value if they are not reflections: we have the explicit `MethodInfo`/`PropertyInfo`/`FieldInfo` to work with and the return type of that is primitive. Many of the others have an explicit return type calculated; `CanEmitPrimitive` is true if that type is primitive.
5151

52-
The most complicated formula for `CanEmitPrimitive` is in `IfExpr`. We need both the 'then' and the 'else' expressions to be `MaybePrimitiveExpr`. They both must have `CanEmitPrimitive` be true, and they must be of the same primitive type -- or one of them can have a return type of type `Recur.RecurType`. You might recall from [C4: Tag! You're int!][TBD] that `Recur.RecurType` is a special type used as the return type of a `RecurExpr`. The only reason `RecurExpr` implements `MaybePrimitiveExpr` is to make this code work:
52+
The most complicated formula for `CanEmitPrimitive` is in `IfExpr`. We need both the 'then' and the 'else' expressions to be `MaybePrimitiveExpr`. They both must have `CanEmitPrimitive` be true, and they must be of the same primitive type -- or one of them can have a return type of type `Recur.RecurType`. You might recall from [C4: Tag! You're int!]({{site.baseurl}}{% post_url 2025-10-16-tag-youre-int %}) that `Recur.RecurType` is a special type used as the return type of a `RecurExpr`. The only reason `RecurExpr` implements `MaybePrimitiveExpr` is to make this code work:
5353

5454
```c#
5555
_thenExpr is MaybePrimitiveExpr tExpr
@@ -291,7 +291,7 @@ Just doing a rough timing in a loop, `calling2` is about 5x as fast as `calling1
291291

292292
## Intrinsics
293293

294-
Why `fp` has a direct IL `add` instruction but `fb` has to go through `Numbers.add` is a story worthy of its own post. See [C4: Inline skating][TBD].
294+
Why `fp` has a direct IL `add` instruction but `fb` has to go through `Numbers.add` is a story worthy of its own post. See [C4: Inline skating]({{site.baseurl}}{% post_url 2025-10-18-inline-skating %}).
295295

296296
## CLR considerations
297297

_posts/2025-10-18-inline-skating.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Inlining allows the compiler to replace some function calls with direct code ins
99

1010
After the heavy lifting of the last few posts, this post is just a little palate cleanser.
1111

12-
In [C4 - Primitive urges][TBD], we looked at how unnecessary boxing of primitive types can be avoided. That is accomplished by signficant compiler magic spread over a large number of classes.
12+
In [C4: Primitive urges]({{site.baseurl}}{% post_url 2025-10-17-primitive-urges %}), we looked at how unnecessary boxing of primitive types can be avoided. That is accomplished by signficant compiler magic spread over a large number of classes.
1313

1414
In contrast, inlining and intrinsic operations are very localized and easy to understand.
1515

@@ -140,7 +140,7 @@ Inlining will help us. `f` will compile directly to a call to `clojure.lang.Num
140140

141141
There are a lot of overloads of `Numbers.add` to handle different types of arguments. In this case, because we do not have more specific type information about `x` and `y`, we will end up calling the version that takes two `object` arguments. This will result in boxing if `x` and `y` are primitive type values, and a bunch of type checking and dispatching inside `Numbers.add`.
142142

143-
We learned in [C4 - Primitive urges][TBD] how to avoid boxing. If we restrict the types of `x` and `y` to, say, `double`, we can avoid boxing:
143+
We learned in [C4: Primitive urges]({{site.baseurl}}{% post_url 2025-10-17-primitive-urges %}) how to avoid boxing. If we restrict the types of `x` and `y` to, say, `double`, we can avoid boxing:
144144

145145

146146
```clojure

0 commit comments

Comments
 (0)