tagged release 0.6.4
[parrot.git] / compilers / pirc / doc / design.pod
blob0db80da317417d70a5f76cd28325f57bc25ff040
1 =head1 NAME
3 design.pod - description PIRC's design.
5 =head1 DESCRIPTION
7 This document describes the design and implementation of PIRC, a PIR Compiler.
9 =head1 OVERVIEW
11 PIRC currently consists of a PIR parser, together with a lexer. It also has
12 the beginning of semantic actions in the parser. Through the use of a vtable,
13 several back-ends can be implemented, leaving the parser untouched.
15 Documentation of the lexer and the parser can be generated by running:
17  make docs
19 which will generate html files in the C<doc> directory.
21 This document will only provide a high-level overview.
24 =head1 THE LEXER
26 The lexer is defined in C<pirlexer.c>. The header file lists all tokens that
27 may be returned by the lexer.
29 The lexer reads the complete file contents into a buffer, from which it reads
30 the individual words, or I<tokens>. A buffer is much faster than using C<getc()>
31 for each character, as I/O is relatively slow.
34 =head1 THE PARSER
36 The parser is defined in C<pirparser.c>. The header file only predeclares the
37 C<parser_state> structure, but its definition is written in the C file, to hide
38 the implementation details from other files. Access to specific fields is done
39 through accessor functions, defined in the header file as well.
41 The parser communicates with the lexer through the lexer's accessor function. Of
42 these, the C<next_token()> function is most important: it requests the next token
43 from the lexer.
45 The parser does not know anything about the spelling of tokens, although it can
46 request these through C<find_keyword()>.
49 =head1 SEMANTIC ACTIONS
51 The parser calls at a number of places C<emit> functions. These are I<hooks> to
52 which a function can be hooked, that will be called when the parser calls that
53 function. This is implemented using vtables. Of course, not all hooks need to be
54 used. If a hook is not assigned a function by the user, the default empty function
55 is invoked. This is done to prevent NULL checks; let's just hope the optimizer
56 sees the invoked function is empty, so the overhead of calling it is removed.
58 =head2 Example Vtable methods
60 This section gives a simple example to show how things are used.
61 Let's consider a simplified version of a C<long_invocation>. Syntactically, it
62 looks like this (this is the simplified version):
64  long-invocation -> '.begin_call' '\n'
65                     arguments
66                     '.call' invokable '\n'
67                     results
68                     '.end_call' '\n'
70  invocant -> IDENTIFIER | PREG
72 The parsing routine for long-invocation (again, its simplified version) looks
73 as follows:
75  static void
76  long_invocation(parser_state *p) {
77       emit_invocation_start(p); /* indicate start of invocation */
78       match(p, T_PCC_BEGIN);
79       match(p, T_NEWLINE);
80       arguments(p);
82       match(p, T_PCC_CALL); /* check for token '.call' */
83       match(p, T_NEWLINE);  /* check for a newline */
85       /* get current token from lexer and store it as the invokable object */
86       emit_invokable(p, get_current_token(p->lexer));
88       /* check whether it was an invokable object and get next token */
89       switch (p->curtoken) {
90           case T_IDENTIFIER:
91           case T_PREG:
92               emit_invokable(p, get_current_token(p->lexer));
93               break;
94           default:
95               syntax_error(p, 1, "invokable object expected");
96               break;
97       }
99       results(p);
101       match(p, T_PCC_END); /* accept token '.end_call' */
102       match(p, T_NEWLINE); /* accept the newline token */
103       emit_invocation_end(p); /* close down invocation sequence */
107  static void
108  arguments(parser_state *p) {
109       emit_args_start(p);   /* start sequence of arguments */
110       /* handle arguments */
111       emit_args_end(p); /* stop sequence of arguments */
114  static void
115  results(p) {
116       emit_results_start(p); /* start sequence of results */
117       /* handle results */
118       emit_results_end(p); /* stop sequence of results */
121 To each of the emit_* function calls, the writer of the back-end can
122 hook a custom function, that does the Appropiate Thing. What is
123 appropiate, depends on the back-end. Some back-ends need to construct
124 a data structure (AST) (for example the PBC backend would need this),
125 others can just spit out what they get (like the PIR back-end).
128 =head2 Supported back-ends
130 Currently, there are the following back-end targets:
132 =over 4
134 =item *
136 PAST - textual form of PAST using Data::Dumper format.
138 =item *
140 PIR - PIR output, which I<may> change PIR syntax into PASM syntax.
142 =item *
144 JSON - JSON is extremely simple, and adding this back-end was pretty easy.
146 =item *
148 PBC - but this one is not implemented at all. Just a stub file.
150 =back
152 See src/pirvtable.{c,h} for details.
154 Please note that none of the back-ends is complete.
157 =head2 VTable Methods
159 Now, you might ask yourself, who or what decides where these hooks, or vtable method calls
160 are done. "Why is there a hook over I<here>?" Well, that's done by figuring out at what
161 moment a back-end might need to get some information of the parser. As the parser continues,
162 the tokens being read are lost, if they're not stored anywhere. So, every once and a while
163 the back-end needs to be able to store stuff, so it can do its job properly.
165 The vtable is not complete yet. There are a number of parsing routines that do not have
166 associated vtable methods (invocations). Of course, we don't want the parser to do too
167 much vtable invocations. On the other hand, if the parser does too few, constructing a
168 back-end might be impossible. It's a bit of a trade-off.
171 =head1 OVERVIEW
173 This section gives an overview of what functionality is in what file:
175 =over 4
177 =item *
179 src/pirlexer.{c,h} - implementation of the lexer
181 =item *
183 src/pirparser.{c,h} - implementation of the parser
185 =item *
187 src/pirvtable.{c,h} - constructor of an empty vtable
189 =item *
191 src/pirout.{c,h} - back-end that implements the vtable methods to output PIR
193 =item *
195 src/pastout.{c,h} - back-end that implements the vtable methods to output PAST
196 (in Data::Dumper format)
198 =item *
200 src/pbcout.{c,h} - dummy back-end for PBC. This file only creates a vtable,
201 but no implementation yet.
203 =item *
205 src/jsonout.{c,h} - back-end that implements the vtable methods to output JSON.
207 =item *
209 src/pirmain.c - main file for C<pirc>. Execution starts here.
211 =back
213 =head1 WHAT NEEDS TO BE DONE
215 There are some major TODOs:
217 =over 4
219 =item *
221 Check whether an identifier is actually a Parrot op. In IMCC, this is done by calling
222 Parrot_is_builtin(). However, for that, we need a Parrot_Interp. Currently I have problems
223 getting things to link correctly.
225 =item *
227 Complete at least 1 back-end, to see what more vtable entries we need. And of course,
228 to generate PBC in the end.
230 =item *
232 Complete the vtable structure with all needed vtable methods.
234 =item *
236 Memory management; not all memory is freed at this moment. Does it need to be done
237 by the back-end, or by the parser?
239 =back
241 =head1 AUTHOR
243 Klaas-Jan Stol <parrotcode at gmail dot com>
245 =cut