Finalize the X Macro article
Signed-off-by: Danila Fedorin <danila.fedorin@gmail.com>
This commit is contained in:
parent
dd232cedb5
commit
c189da3671
|
@ -1,7 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "My Favorite C++ Pattern: X Macros"
|
title: "My Favorite C++ Pattern: X Macros"
|
||||||
date: 2023-10-09T15:06:11-07:00
|
date: 2023-10-09T15:06:11-07:00
|
||||||
draft: true
|
|
||||||
tags: ["C++", "Chapel", "Compilers"]
|
tags: ["C++", "Chapel", "Compilers"]
|
||||||
description: "In this post, I talk about my favorite C/C++ pattern involving macros."
|
description: "In this post, I talk about my favorite C/C++ pattern involving macros."
|
||||||
---
|
---
|
||||||
|
@ -12,7 +11,7 @@ then, I've used the pattern many more times, and have been very satisfied with
|
||||||
how it turned out. However, it feels like the pattern is relatively unknown, so
|
how it turned out. However, it feels like the pattern is relatively unknown, so
|
||||||
I thought I'd show it off, and some of its applications in the
|
I thought I'd show it off, and some of its applications in the
|
||||||
[Chapel compiler](https://github.com/chapel-lang/chapel/). I've slightly tweaked
|
[Chapel compiler](https://github.com/chapel-lang/chapel/). I've slightly tweaked
|
||||||
a lot of the snippets I directly present in this article for the sake of simpler
|
a lot of the snippets I directly show in this article for the sake of simpler
|
||||||
presentation; I've included links to the original code (available on GitHub)
|
presentation; I've included links to the original code (available on GitHub)
|
||||||
if you want to see the unabridged version.
|
if you want to see the unabridged version.
|
||||||
|
|
||||||
|
@ -44,7 +43,7 @@ returned. Some strings, however, occur a lot in the compiler, to the point that
|
||||||
it would be inefficient to perform the whole "find-or-create" operation every
|
it would be inefficient to perform the whole "find-or-create" operation every
|
||||||
time. One example is the `"this"` string, which is an identifier with a lot of
|
time. One example is the `"this"` string, which is an identifier with a lot of
|
||||||
special behavior in the language (much like `this` in languages such as Java).
|
special behavior in the language (much like `this` in languages such as Java).
|
||||||
To support these frequent flier strings, the compiler initializes them once,
|
To support such frequent flier strings, the compiler initializes them once,
|
||||||
and creates a variable per-string that can be accessed to get that string's value.
|
and creates a variable per-string that can be accessed to get that string's value.
|
||||||
|
|
||||||
There's that repetitive code. Defining a brand new variable for each string,
|
There's that repetitive code. Defining a brand new variable for each string,
|
||||||
|
@ -75,11 +74,11 @@ X(bytes , "bytes")
|
||||||
// A lot more of these...
|
// A lot more of these...
|
||||||
{{< /githubsnippet >}}
|
{{< /githubsnippet >}}
|
||||||
|
|
||||||
What's This `X` thing? That right there is the essence of the pattern: the macro
|
What's this `X` thing? That right there is the essence of the pattern: the macro
|
||||||
`X` _isn't defined in the header!_. Effectively, `all-global-strings.h` is just
|
`X` _isn't defined in the header!_ Effectively, `all-global-strings.h` is just
|
||||||
a list, and we can "iterate" over this list to generate some code for each
|
a list, and we can "iterate" over this list to generate some code for each
|
||||||
one of its elements, in as many places as we want. What I mean by this is
|
one of its elements, in as many places as we want. What I mean by this is
|
||||||
that we can then write code like this:
|
that we can then write code like the following:
|
||||||
|
|
||||||
{{< githubsnippet "chapel-lang/chapel" "cd108338d321d0b3edf6258e0b2a58459d88a348" "frontend/include/chpl/framework/global-strings.h" "C++" 76 >}}
|
{{< githubsnippet "chapel-lang/chapel" "cd108338d321d0b3edf6258e0b2a58459d88a348" "frontend/include/chpl/framework/global-strings.h" "C++" 76 >}}
|
||||||
struct GlobalStrings {
|
struct GlobalStrings {
|
||||||
|
@ -150,8 +149,8 @@ that _use_ the compiler. I'll go through the use cases in turn.
|
||||||
|
|
||||||
#### Tags and Dynamic Casting
|
#### Tags and Dynamic Casting
|
||||||
First, to deal with a general absence of
|
First, to deal with a general absence of
|
||||||
[RTTI](https://en.wikipedia.org/wiki/Run-time_type_information), it is used
|
[RTTI](https://en.wikipedia.org/wiki/Run-time_type_information), the hierarchy header
|
||||||
to declare an "tag" enum. Each AST node has a tag matching its class;
|
is used to declare a "tag" enum. Each AST node has a tag matching its class;
|
||||||
this allows us inspect the AST and perform safe casts similar to `dynamic_cast`.
|
this allows us inspect the AST and perform safe casts similar to `dynamic_cast`.
|
||||||
Note that for parent classes (defined via `BEGIN_SUBCLASSES`), we actually
|
Note that for parent classes (defined via `BEGIN_SUBCLASSES`), we actually
|
||||||
end up creating _two_ tags: one `START_...` and one `END_...`. The reason
|
end up creating _two_ tags: one `START_...` and one `END_...`. The reason
|
||||||
|
@ -240,7 +239,7 @@ isLoop(AstTag::While) // Returns true; a 'while' loop is a loop.
|
||||||
```
|
```
|
||||||
|
|
||||||
On the top-level AST node class, we generate `isWhateverNode` and
|
On the top-level AST node class, we generate `isWhateverNode` and
|
||||||
`toWhateverNode` for each AST class. Thus, user code is able to inspect the
|
`toWhateverNode` for each AST subclass. Thus, user code is able to inspect the
|
||||||
AST and perform (checked) casts using plain methods. I omit `isWhateverNode`
|
AST and perform (checked) casts using plain methods. I omit `isWhateverNode`
|
||||||
here for brevity (its definition is very simple), and include only
|
here for brevity (its definition is very simple), and include only
|
||||||
`toWhateverNode`.
|
`toWhateverNode`.
|
||||||
|
@ -288,7 +287,7 @@ random snippet of code I pulled out:
|
||||||
Thus, developers adding new AST nodes are not required to manually implement
|
Thus, developers adding new AST nodes are not required to manually implement
|
||||||
the `isWhatever`, `toWhatever`, and other functions. This and a fair bit
|
the `isWhatever`, `toWhatever`, and other functions. This and a fair bit
|
||||||
of other AST functionality (which I will cover in the next subsection) is
|
of other AST functionality (which I will cover in the next subsection) is
|
||||||
automatically generating using X Macros.
|
automatically generated using X Macros.
|
||||||
|
|
||||||
{{< dialog >}}
|
{{< dialog >}}
|
||||||
{{< message "question" "reader" >}}
|
{{< message "question" "reader" >}}
|
||||||
|
@ -599,7 +598,8 @@ struct PerNodeInfo {
|
||||||
};
|
};
|
||||||
{{< /githubsnippet >}}
|
{{< /githubsnippet >}}
|
||||||
|
|
||||||
Then, when I need to add methods, I do something like the following:
|
Then, when I need to add methods, I use template specialization by writing
|
||||||
|
something like the following:
|
||||||
|
|
||||||
```C++
|
```C++
|
||||||
template <>
|
template <>
|
||||||
|
@ -673,7 +673,7 @@ unfortunate remnants of C++'s past. However, I think that what I've demonstrated
|
||||||
demonstrates the versatility of the X Macro pattern -- feel free to apply it to
|
demonstrates the versatility of the X Macro pattern -- feel free to apply it to
|
||||||
the degree that you find appropriate.
|
the degree that you find appropriate.
|
||||||
|
|
||||||
The thing I like the most pattern is that the header files read quite nicely:
|
The thing I like the most about this pattern is that the header files read quite nicely:
|
||||||
you end up with a very declarative "scaffold" of what's going on. The
|
you end up with a very declarative "scaffold" of what's going on. The
|
||||||
`uast-classes-list.h` makes for an excellent and fairly readable reference of
|
`uast-classes-list.h` makes for an excellent and fairly readable reference of
|
||||||
all the AST nodes in the Chapel compiler. The `method-tables.h` header provides
|
all the AST nodes in the Chapel compiler. The `method-tables.h` header provides
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
title: "Proving My Compiler Code Incorrect With Alloy"
|
title: "Proving My Compiler Code Incorrect With Alloy"
|
||||||
date: 2023-06-04T21:56:00-07:00
|
date: 2023-10-14T15:38:17-07:00
|
||||||
tags: ["Chapel", "Compilers", "Alloy"]
|
tags: ["Chapel", "Compilers", "Alloy"]
|
||||||
description: "In this post, I apply Alloy to a piece of code in the Chapel compiler to find a bug."
|
description: "In this post, I apply Alloy to a piece of code in the Chapel compiler to find a bug."
|
||||||
---
|
---
|
||||||
|
|
Loading…
Reference in New Issue
Block a user