Skip to content

Commit bba277c

Browse files
committed
Start documenting the QAST nodes.
1 parent 4b84f41 commit bba277c

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

docs/qast.markdown

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# QAST Nodes
2+
3+
The "Q" Abstract Syntax Tree is a set of nodes used to represent the runtime
4+
behavior of a program that is being compiled. Parsing a program with a grammar
5+
produces a parse tree. As the name suggests, this is strongly tied to the
6+
syntax of the language being parsed, and reflects the structure of the grammar.
7+
This parse tree is mapped by action methods into an abstract syntax tree - a
8+
tree of QAST nodes. Rather than talking about program syntax, they talk about
9+
what happens at runtime: loops, conditionals, variable lookups, etc. This
10+
document describes the available nodes and what they are for.
11+
12+
## QAST::CompUnit
13+
While it's not mandatory, most QAST trees that are produced should have a
14+
QAST::CompUnit at the top. It should have a single QAST::Block child. This
15+
child block represents the outermost scope of the compilation unit.
16+
17+
QAST::CompUnit incorporates information that is relevant to the entire
18+
unit of code that is being compiled. This includes:
19+
20+
* **hll** - the name of the high level language that this QAST tree was
21+
produced from, for example, "perl6", "tcl", "bf".
22+
23+
* **load** - code to evaluate at the point that the compilation unit is
24+
loaded as a module (but not if it is invoked as a mainline program).
25+
Happens after any deserialization and deserialization related actions
26+
have executed.
27+
28+
* **main** - like load, but instead this contains code to execute if the
29+
compilation unit is invoked as the mainline
30+
31+
Example usage:
32+
33+
QAST::CompUnit.new(
34+
# Set the HLL.
35+
:hll('perl6'),
36+
37+
# This variable contains the outermost QAST::Block of the
38+
# program.
39+
$top_block,
40+
41+
# If we run the program as the mainline, then call the top
42+
# block automatically.
43+
:main(QAST::Op.new(
44+
:op('call'),
45+
QAST::BVal.new( :value($top_block) )
46+
))
47+
)
48+
49+
Additional adverbs that can be set on a QAST:CompUnit relate to bounded
50+
serialization, which will be covered separately.
51+
52+
## QAST::Block
53+
A QAST::Block is both a unit of invocation and a unit of lexical scoping.
54+
To clarify, this means that if:
55+
56+
* You want to create something that can be called, such as a subroutine,
57+
closure block or method
58+
* You want a fresh lexical environment
59+
60+
Then you want to use a QAST::Block. A block can have as many children as
61+
you wish, and the final child should evaluate to the return value of the
62+
block. A simple example of a block is:
63+
64+
QAST::Block.new(
65+
QAST::IVal.new( :value(42) )
66+
)
67+
68+
This will compile to a block of code that, when invoked, returns 42.
69+
70+
A block can be given a name and a compilation unit unique ID. The name
71+
is user facing, and will appear in any automatically generated backtraces.
72+
It does not need to be unique within the compilation unit. The compilation
73+
unit unique ID, as the name suggests, does need to be. You typically do
74+
not need to worry about it much, however; it will be generated for you the
75+
first time it is needed, if you do not specify it up front. Often, you will
76+
not need to worry about it at all. Here's a block with a name.
77+
78+
QAST::Block.new(
79+
:name('answer'),
80+
QAST::IVal.new( :value(42) )
81+
)
82+
83+
Note that giving a block a name does not imply *any* installation of the
84+
block under this name. It's not installed automatically for you as a
85+
method or subroutine. That's for you to do.
86+
87+
Blocks can be placed within other blocks. This nesting represents the static
88+
chain that will be used for the lookup of lexically scoped variables. When
89+
you nest one block inside of another, you may wish for it to be invoked
90+
automatically when it is encountered, or you may wish that it be treated as
91+
an object (for example, which you can bind somewhere). You can configure this
92+
by setting the blocktype:
93+
94+
QAST::Block.new(
95+
QAST::Op.new(
96+
:op('say'),
97+
QAST::SVal.new( :value('before') )
98+
),
99+
QAST::Block.new(
100+
:blocktype('immediate'),
101+
QAST::Op.new(
102+
:op('say'),
103+
QAST::SVal.new( :value('nested') )
104+
)
105+
),
106+
QAST::Op.new(
107+
:op('say'),
108+
QAST::SVal.new( :value('after') )
109+
)
110+
)
111+
112+
Here, 'immediate' indicates that this block should be executed immediately,
113+
whenever it is reached during program execution. The default, 'declaration',
114+
does not have these semantics. You use it when you plan to bind the block,
115+
for example into a lexical variable, or you are installing it elsewhere
116+
(for example, as a method).
117+
118+
Block has one more handy feature: it can be used to maintain a symbol table.
119+
It provides you with a hash per symbol (typically, these correspond to the
120+
variables you declare in the block, but you can put whatever you want in it).
121+
122+
$my_block.symbol('$foo', :scope('lexical'), :readonly(1));
123+
124+
The named parameters you pass are stored in a hash for the symbol '$foo'. If
125+
you call it again:
126+
127+
$my_block.symbol('$foo', :scope('local'), :optimized(1));
128+
129+
Then the updated value for 'scope' will be put in place, the new 'optimized'
130+
value will be stored and the existing 'readonly' value will be left intact.
131+
That is to say, you can safely add extra information over time. To get all
132+
the known facts about a symbol in a hash, simply do:
133+
134+
my %sym := $my_block.symbol('$foo');
135+
136+
Two keys have special significance to the QAST to VM compiler:
137+
138+
* **scope** is used to find a default scope for a variable, if none is
139+
set in a QAST::Var node that is doing a lookup
140+
141+
* **type** is used to know the type of the variable. This matters if the
142+
variable is natively typed, since it influences the code generation
143+
144+
## QAST::Stmts and QAST::Stmt
145+
146+
## QAST::IVal, QAST::NVal and QAST::SVal
147+
148+
## QAST::Var
149+
150+
## QAST::Op
151+
152+
## QAST::VarWithFallback
153+
154+
## QAST::BVal
155+
156+
## QAST::WVal
157+
158+
## QAST::Want
159+
160+
## QAST::VM

0 commit comments

Comments
 (0)