Author: kjs
Date: Sat Apr  7 02:34:20 2007
New Revision: 18024

Modified:
   trunk/compilers/pirc/doc/design.pod
   trunk/compilers/pirc/src/pirparser.c
   trunk/compilers/pirc/t/sub.t

Log:
compilers/pirc:
* changed the test file, testing is not working right now, and it failed.
* added more to design.pod about design of pirc.exe
* minor changes to the parser.

Modified: trunk/compilers/pirc/doc/design.pod
==============================================================================
--- trunk/compilers/pirc/doc/design.pod (original)
+++ trunk/compilers/pirc/doc/design.pod Sat Apr  7 02:34:20 2007
@@ -14,8 +14,9 @@
 
 Documentation of the lexer and the parser can be generated by running:
 
- pod2html src/pirlexer.c > doc/pirlexer.html
- pod2html src/pirparser.c > doc/pirparser.html
+ make docs
+
+which will generate html files in the C<doc> directory.
 
 This document will only provide a high-level overview.
 
@@ -30,7 +31,6 @@
 for each character, as I/O is relatively slow.
 
 
-
 =head1 THE PARSER
 
 The parser is defined in C<pirparser.c>. The header file only predeclares the
@@ -50,13 +50,192 @@
 
 The parser calls at a number of places C<emit> functions. These are I<hooks> to
 which a function can be hooked, that will be called when the parser calls that
-function. This is implemented using vtables.
+function. This is implemented using vtables. Of course, not all hooks need to 
be
+used. If a hook is not assigned a function by the user, the default empty 
function
+is invoked. This is done to prevent NULL checks; let's just hope the optimizer
+sees the invoked function is empty, so the overhead of calling it is removed.
+
+=head2 Example Vtable methods
+
+This section gives a simple example to show how things are used.
+Let's consider a simplified version of a C<long_invocation>. Syntactically, it
+looks like this (this is the simplified version):
+
+ long-invocation -> '.pcc_begin' '\n'
+                    arguments
+                    '.pcc_call' invokable '\n'
+                    results
+                    '.pcc_end' '\n'
+
+ invocant -> IDENTIFIER | PREG
+
+The parsing routine for long-invocation (again, its simplified version) looks
+as follows:
+
+ static void
+ long_invocation(parser_state *p) {
+      emit_invocation_start(p); /* indicate start of invocation */
+      match(p, T_PCC_BEGIN);
+      match(p, T_NEWLINE);
+      arguments(p);
+
+      match(p, T_PCC_CALL); /* check for token '.pcc_call' */
+      match(p, T_NEWLINE);  /* check for a newline */
+
+      /* get current token from lexer and store it as the invokable object */
+      emit_invokable(p, get_current_token(p->lexer));
+
+      /* check whether it was an invokable object and get next token */
+      switch (p->curtoken) {
+          case T_IDENTIFIER:
+          case T_PREG:
+              emit_invokable(p, get_current_token(p->lexer));
+              break;
+          default:
+              syntax_error(p, 1, "invokable object expected");
+              break;
+      }
+
+      results(p);
+
+      match(p, T_PCC_END); /* accept token '.pcc_end' */
+      match(p, T_NEWLINE); /* accept the newline token */
+      emit_invocation_end(p); /* close down invocation sequence */
+
+ }
+
+ static void
+ arguments(parser_state *p) {
+      emit_args_start(p);   /* start sequence of arguments */
+      /* handle arguments */
+      emit_args_end(p); /* stop sequence of arguments */
+ }
+
+ static void
+ results(p) {
+      emit_results_start(p); /* start sequence of results */
+      /* handle results */
+      emit_results_end(p); /* stop sequence of results */
+ }
+
+To each of the emit_* function calls, the writer of the back-end can
+hook a custom function, that does the Appropiate Thing. What is
+appropiate, depends on the back-end. Some back-ends need to construct
+a data structure (AST) (for example the PBC backend would need this),
+others can just spit out what they get (like the PIR back-end).
 
-Currently, there are two back-end targets: Parrot Abstract Syntax Tree (PAST),
-and simply PIR.
+
+=head2 Supported back-ends
+
+Currently, there are the following back-end targets:
+
+=over 4
+
+=item *
+
+PAST - textual form of PAST using Data::Dumper format.
+
+=item *
+
+PIR - PIR output, which I<may> change PIR syntax into PASM syntax.
+
+=item *
+
+JSON - JSON is extremely simple, and adding this back-end was pretty easy.
+
+=item *
+
+PBC - but this one is not implemented at all. Just a stub file.
+
+=back
 
 See src/pirvtable.{c,h} for details.
 
+Please note that none of the back-ends is complete.
+
+
+=head2 VTable Methods
+
+Now, you might ask yourself, who or what decides where these hooks, or vtable 
method calls
+are done. "Why is there a hook over I<here>?" Well, that's done by figuring 
out at what
+moment a back-end might need to get some information of the parser. As the 
parser continues,
+the tokens being read are lost, if they're not stored anywhere. So, every once 
and a while
+the back-end needs to be able to store stuff, so it can do its job properly.
+
+The vtable is not complete yet. There are a number of parsing routines that do 
not have
+associated vtable methods (invocations). Of course, we don't want the parser 
to do too
+much vtable invocations. On the other hand, if the parser does too few, 
constructing a
+back-end might be impossible. It's a bit of a trade-off.
+
+
+=head1 OVERVIEW
+
+This section gives an overview of what functionality is in what file:
+
+=over 4
+
+=item *
+
+src/pirlexer.{c,h} - implementation of the lexer
+
+=item *
+
+src/pirparser.{c,h} - implementation of the parser
+
+=item *
+
+src/pirvtable.{c,h} - constructor of an empty vtable
+
+=item *
+
+src/pirout.{c,h} - back-end that implements the vtable methods to output PIR
+
+=item *
+
+src/pastout.{c,h} - back-end that implements the vtable methods to output PAST 
(in Data::Dumper format)
+
+=item *
+
+src/pbcout.{c,h} - dummy back-end for PBC. This file only creates a vtable, 
but no implementation yet.
+
+=item *
+
+src/jsonout.{c,h} - back-end that implements the vtable methods to output JSON.
+
+=item *
+
+src/pirmain.c - main file for C<pirc>. Execution starts here.
+
+=back
+
+=head1 WHAT NEEDS TO BE DONE
+
+There are some major TODOs:
+
+=over 4
+
+=item *
+
+Check whether an identifier is actually a Parrot op. In IMCC, this is done by 
calling
+Parrot_is_builtin(). However, for that, we need a Parrot_Interp. Currently I 
have problems
+getting things to link correctly.
+
+=item *
+
+Complete at least 1 back-end, to see what more vtable entries we need. And of 
course,
+to generate PBC in the end.
+
+=item *
+
+Complete the vtable structure with all needed vtable methods.
+
+=item *
+
+Memory management; not all memory is freed at this moment. Does it need to be 
done
+by the back-end, or by the parser?
+
+=back
+
 =head1 AUTHOR
 
 Klaas-Jan Stol <parrotcode at gmail dot com>

Modified: trunk/compilers/pirc/src/pirparser.c
==============================================================================
--- trunk/compilers/pirc/src/pirparser.c        (original)
+++ trunk/compilers/pirc/src/pirparser.c        Sat Apr  7 02:34:20 2007
@@ -60,6 +60,7 @@
 #include <stdarg.h>
 #include <string.h>
 
+
 /*
 
 =head1 PARSER INTERNALS
@@ -69,7 +70,7 @@
  typedef struct parser_state {
     struct     lexer_state *lexer;     -- the lexer
     token      curtoken;               -- the current token as returned by the 
lexer
-    char      *heredoc_ids[10];        -- array for holding heredoc arguments. 
XXX Limited to 10 currently XXX
+    char     **heredoc_ids;            -- array for holding heredoc arguments. 
XXX Limited to 10 currently XXX
     unsigned   heredoc_index;          -- index to keep track of heredoc ids 
in the array
     unsigned   parse_errors;           -- counter for parse_errors
     pirvtable *vtable;                 -- vtable holding pointers for output 
routines
@@ -88,6 +89,8 @@
     unsigned   parse_errors;
     pirvtable *vtable;
 
+    /* Parrot_Interp interp; */
+
 } parser_state;
 
 
@@ -1318,7 +1321,7 @@
 
 */
 static void
-invocant(parser_state *p) {
+invokable(parser_state *p) {
     switch (p->curtoken) {
         case T_IDENTIFIER:
         case T_PREG:
@@ -1338,7 +1341,7 @@
 
   long-invocation -> '.pcc_begin' '\n'
                      { '.arg' expression arg_flags }
-                     ( '.pcc_call'|'.nci_call') invocant '\n'
+                     ( '.pcc_call'|'.nci_call') invokable '\n'
                      | '.invocant' invocant '\n'
                        '.meth_call' method '\n'
                      )
@@ -1369,15 +1372,15 @@
 
     /* the invocant and/or sub to be called */
     switch (p->curtoken) {
-        case T_PCC_CALL:                /* '.pcc_call' invocant '\n' */
-        case T_NCI_CALL:                /* '.nci_call' invocant '\n' */
+        case T_PCC_CALL:                /* '.pcc_call' invokable '\n' */
+        case T_NCI_CALL:                /* '.nci_call' invokable '\n' */
             next(p);
-            invocant(p);
+            invokable(p);
             match(p, T_NEWLINE);
             break;
         case T_INVOCANT:                /* '.invocant' invocant '\n' */
             next(p);
-            invocant(p);
+            invokable(p);
             match(p, T_NEWLINE);
             match(p, T_METH_CALL);      /* .meth_call method '\n' */
             method(p);

Modified: trunk/compilers/pirc/t/sub.t
==============================================================================
--- trunk/compilers/pirc/t/sub.t        (original)
+++ trunk/compilers/pirc/t/sub.t        Sat Apr  7 02:34:20 2007
@@ -23,8 +23,6 @@
 .sub test :main, :load, :init
 .end
 
-.sub myAdd :vtable('add')
-.end
 
 .sub X :anon
 .end
@@ -34,6 +32,9 @@
 
 
 pir_output_is( <<'CODE', <<'OUTPUT', "parameters" );
+.sub main
+.end
+
 .sub test
        .param int i
        .param num n
@@ -44,6 +45,8 @@
 OUTPUT
 
 pir_output_is( <<'CODE', <<'OUTPUT', "parameters and flags" );
+.sub main
+.end
 .sub test
        .param int i :optional
        .param int o :opt_flag

Reply via email to