[svn:parrot] r44591 - branches/ops_pct/compilers/opsc/src/Ops/Compiler

bacek at svn.parrot.org bacek at svn.parrot.org
Tue Mar 2 11:13:44 UTC 2010


Author: bacek
Date: Tue Mar  2 11:13:43 2010
New Revision: 44591
URL: https://trac.parrot.org/parrot/changeset/44591

Log:
Add stub for munching body in ops2c style.

Modified:
   branches/ops_pct/compilers/opsc/src/Ops/Compiler/Actions.pm

Modified: branches/ops_pct/compilers/opsc/src/Ops/Compiler/Actions.pm
==============================================================================
--- branches/ops_pct/compilers/opsc/src/Ops/Compiler/Actions.pm	Tue Mar  2 11:13:18 2010	(r44590)
+++ branches/ops_pct/compilers/opsc/src/Ops/Compiler/Actions.pm	Tue Mar  2 11:13:43 2010	(r44591)
@@ -6,6 +6,7 @@
 our $CODE;
 
 INIT {
+    pir::load_bytecode("nqp-settings.pbc");
     $CODE := 0;
 }
 
@@ -216,10 +217,120 @@
     make PAST::Op.new(
         :node($/),
         :pasttype('inline'),
-        :inline(~$/)
+        :inline(munch_body(~$/))
     );
 }
 
+sub munch_body($body) {
+    #
+    # Macro substitutions:
+    #
+    # We convert the following notations:
+    #
+    #   .ops file          Op body  Meaning       Comment
+    #   -----------------  -------  ------------  ----------------------------------
+    #   goto OFFSET(X)     {{+=X}}  PC' = PC + X  Used for branches
+    #   goto NEXT()        {{+=S}}  PC' = PC + S  Where S is op size
+    #   goto ADDRESS(X)    {{=X}}   PC' = X       Used for absolute jumps
+    #   expr OFFSET(X)     {{^+X}}  PC + X        Relative address
+    #   expr NEXT()        {{^+S}}  PC + S        Where S is op size
+    #   expr ADDRESS(X)    {{^X}}   X             Absolute address
+    #   OP_SIZE            {{^S}}   S             op size
+    #
+    #   HALT()             {{=0}}   PC' = 0       Halts run_ops loop, no resume
+    #
+    #   restart OFFSET(X)  {{=0,+=X}}   PC' = 0   Restarts at PC + X
+    #   restart NEXT()     {{=0,+=S}}   PC' = 0   Restarts at PC + S
+    #
+    #   $X                 {{@X}}   Argument X    $0 is opcode, $1 is first arg
+    #
+    # For ease of parsing, if the argument to one of the above
+    # notations in a .ops file contains parentheses, then double the
+    # enclosing parentheses and add a space around the argument,
+    # like so:
+    #
+    #    goto OFFSET(( (void*)interp->happy_place ))
+    #
+    # Later transformations turn the Op body notations into C code, based
+    # on the mode of operation (function calls, switch statements, gotos
+    # with labels, etc.).
+    #
+
+    #subst($body, /\b/, { eval('{{$0}}') } );
+    $body := subst($body,
+                /goto \s+ ADDRESS '(' $<addr>=[.*?] ')'/,
+                -> $m { '{{=' ~ $m<addr> ~ '}}' }
+            );
+    $body := subst($body,
+                /expr \s+ ADDRESS '(' $<addr>=[.*?] ')'/,
+                -> $m { '{{^' ~ $m<addr> ~ '}}' }
+            );
+
+
+    $body;
+=begin
+
+    $absolute ||= $body =~ s/\bgoto\s+ADDRESS\(\( (.*?) \)\)/{{=$1}}/mg;
+                    $body =~ s/\bexpr\s+ADDRESS\(\( (.*?) \)\)/{{^$1}}/mg;
+    $absolute ||= $body =~ s/\bgoto\s+ADDRESS\((.*?)\)/{{=$1}}/mg;
+                    $body =~ s/\bexpr\s+ADDRESS\((.*?)\)/{{^$1}}/mg;
+
+    $branch   ||= $short_name =~ /runinterp/;
+    $branch   ||= $body =~ s/\bgoto\s+OFFSET\(\( (.*?) \)\)/{{+=$1}}/mg;
+                    $body =~ s/\bexpr\s+OFFSET\(\( (.*?) \)\)/{{^+$1}}/mg;
+    $branch   ||= $body =~ s/\bgoto\s+OFFSET\((.*?)\)/{{+=$1}}/mg;
+                    $body =~ s/\bexpr\s+OFFSET\((.*?)\)/{{^+$1}}/mg;
+
+    $next     ||= $short_name =~ /runinterp/;
+    $next     ||= $body =~ s/\bexpr\s+NEXT\(\)/{{^+$op_size}}/mg;
+                    $body =~ s/\bgoto\s+NEXT\(\)/{{+=$op_size}}/mg;
+
+    $body =~ s/\bHALT\(\)/{{=0}}/mg;
+    $body =~ s/\bOP_SIZE\b/{{^$op_size}}/mg;
+
+    if ( $body =~ s/\brestart\s+OFFSET\((.*?)\)/{{=0,+=$1}}/mg ) {
+        $branch  = 1;
+        $restart = 1;
+    }
+    elsif ( $body =~ s/\brestart\s+NEXT\(\)/{{=0,+=$op_size}}/mg ) {
+        $restart = 1;
+        $next    = 1;
+    }
+    elsif ( $body =~ s/\brestart\s+ADDRESS\((.*?)\)/{{=$1}}/mg ) {
+        $next    = 0;
+        $restart = 1;
+    }
+
+    $body =~ s/\$(\d+)/{{\@$1}}/mg;
+
+    # We can only reference as many parameters as we declare
+    my $max_arg_num = @$args;
+    my @found_args = ($body =~ m/{{@(\d+)}}/g);
+    foreach my $arg (@found_args) {
+        die "opcode '$short_name' uses '\$$arg' but only has $max_arg_num parameters.\n" if $arg > $max_arg_num;
+    }
+
+
+    my $file_escaped = $file;
+    $file_escaped =~ s|(\\)|$1$1|g;    # escape backslashes
+    $op->body( $nolines ? $body : qq{#line $line "$file_escaped"\n$body} );
+
+    # Constants here are defined in include/parrot/op.h
+    or_flag( \$jumps, "PARROT_JUMP_ADDRESS"  ) if $absolute;
+    or_flag( \$jumps, "PARROT_JUMP_RELATIVE" ) if $branch;
+    or_flag( \$jumps, "PARROT_JUMP_ENEXT"    ) if $next;
+    or_flag( \$jumps, "PARROT_JUMP_RESTART"  ) if $restart;
+
+    # I'm assuming the op branches to the value in the last argument.
+    if ( ($jumps)
+        && ( $fixedargs[ @fixedargs - 1 ] )
+        && ( $fixedargs[ @fixedargs - 1 ] eq 'i' ) ) {
+        or_flag( \$jumps, "PARROT_JUMP_GNEXT" );
+    }
+=end
+
+}
+
 # Local Variables:
 #   mode: perl6
 #   fill-column: 100


More information about the parrot-commits mailing list