Here is a syntax highlighted code block. Notice that you can add a marker to the code by inserting `[]`, which can be helpful if you need to refer to a particular line in the surrounding content.
Memory diagrams allow you to embed short diagrams showcasing the structure of memory at some point in a program. For example, here is an example showing the allocation of a vector on the stack/heap:
Stack
main
vec
Vector<int>
size
4
capacity
10
data
●
Heap
1
2
3
4
_
_
_
_
_
_
As you can see, diagrams consist of a series of assignments (vec = ...) on the stack (which may occur inside of a frame like main:) along with heap allocations (data => ...). Diagram elements can be styled either with a CSS class or by embedding a raw CSS object. Here's a more complicated example that uses subdiagrams (note how each subdiagram now has a title like L2, L3):
intmain(){
std::cout << "I love C++!" << std::endl;
return0;
}
A Custom Title
This is the diagram subtitle.
intmain(){}
Stream
std::cin
●
B
j
a
r
n
e
S
t
r
o
u
s
t
r
u
p
L2
This one has a red subtitle.
Stack
main
foo
●
Heap
1
2
3
L3
Stack
x
1
foo
y
2
Note how in the above, placing a diagram immediately below a code block causes the two to appear merged together.
Use = to indicate an assignment to a variable on the stack. Assignments can optionally live inside of stack frames.
Stack
v
106
main
x
1
y
4
foo
x
3
y
6
Two stack frames and/or global variables may not share the same name, and variable names within a stack frame must be unique. That said, you can change the displayed label of a variable/stack frame using special syntax, while keeping its programmatic name:
Stack
custom name
106
not a problem
x
1
y
4
not a problem
x
3
x
6
Variable names follow the same rules as C-style variables (alphanumeric characters and underscores), with the exception that they are allowed to start with a number.
Use => to refer to an allocation on the heap. All allocations will be lumped together, so you can intersperse stack assignments and heap allocations freely, but the order of => statements determines the order that they appear in the heap. Note that the names of heap allocations are purely internal (e.g. for creating pointers, styling, etc.)
Use => with any number of equal signs to refer to a different section of the heap. This is useful when representing a complicated memory layout, for example an array of arrays (for example when representing an std::deque):
A literal value is a catch all. If no other value could be parsed, the literal catches it. The only restrictions on literals are that they contain no grouping symbols that might confuse the parser, e.g. []{},: or newlines.
These function like Python or C++ strings, and can get around the grouping character restriction for literals. Single character escapes will be escaped into their true value, e.g. \n becomes a newline.
These work like Python lists, and can be nested. By default, only nested arrays have a border around them. To change this, you can doubly nest a single array.
Strings with a b in front of them, e.g. b"hello world", will be treated as character arrays. Single character escapes are unescaped and treated as one character. These function exactly like arrays above, but are a shorthand so you don't have to write out all the [, , and ] characters.
Objects are simple key-value pair collections, and work similarly to JavaScript object literals. An object can optionally have a label attached to it (e.g. to indicate its type) which can either be a variable name or a string literal. Objects can be nested. Object field names must be variables with unique names, but like variables, they can be renamed using the ("label") syntax.
An unlabelled object can be created by replacing the {} with [] in the object notation. This still represents a collection of named fields--the only difference is that the field names are hidden. This might be useful, for example, to show a vertical array.
Pointers visualize an arrow from one section of memory to another. Use the special value null to represent nullptr. Otherwise, use &[loc] to draw an arrow to the memory at loc.
Stack
np
⦻
p
●
Heap
1
There is no restriction on where pointers may originate from or point to, e.g. stack-stack, stack-heap, heap-heap etc.
Stack
x
106
y
●
z
●
Heap
1
2
●
Heap
●
●
●
Heap
W
e
l
c
o
m
e
\0
b
a
c
k
t
o
\0
C
!
\0
There is still a lot of work to do internally on getting pointer paths to render in a visually pleasing way. For now, you can make use of #style:link directives to get the right path options.
To style the diagram, you can use a #style directive. The syntax is:
#style [cssClassOrObject] [loc ...] // Styles a node's surrounding container#style:name [cssClassOrObject] [loc ...] // For fields/variables, styles the name of the node#style:row [cssClassOrObject] [loc ...] // For fields/variables, styles the entire name/value row#style:value [cssClassOrObject] [loc ...] // Styles the innermost contents of a node#style:link [lineOptions] [loc ...] // Styles the arrow for a pointer#style:label [cssClassOrObject] [labelLoc ...] // Styles a diagram label
[cssClassOrObject] is either a CSS classname or a JSON-esque object containing CSS properties. [lineOptions] are the LeaderLine options for the arrow connecting a pointer to its pointee. [labelLoc] is the location of a label, e.g. stack, heap, title, subtitle, =>, ==>, etc.
Note that you can use Python style array slicing, e.g.
#style highlight data[2:10:2]
would highlight elements [2, 10), skipping every other element. Negative indexes are allowed to refer to locations relative to the end of the array, e.g. data[-1].
To have an individual diagram occupy the width of the screen, use the #layout wide directive within that diagram. Diagrams by default will attempt to stack horizontally, wrapping if they become too wide.
Use the label directive to custom diagram labels. All of the labels support multi-line markdown strings:
#label title "**A title**"// The title of the diagram#label subtitle "A subtitle"// The subtitle of the diagram#label stack "Stack"// The label of the stack section#label heap "Heap"// The label of all the heap sections#label => "Heap"// The label of a specific heap section// Also works for ==>, ===>, etc.