All --

Attached is a diff for assemble.pl that does a somewhat messy job of
solving the problem posed in the TODO file. It does it by parsing
the root of each opcode when parsing the opcode table and creating a
hash with the opcode root and the formal argument types (qualifiers)
so that, e.g. $opqual{'add'}{'i:ic'} == 'add_i_ic'.

This appears to work. I've tested the output of assembling euclid.pasm
and got the same results as before. YMMV.

I left some debugging printfs in the file but commented out. A cooler
approach would do some sort of partial matching if you specified some
qualifiers, such as "add_i I4, I4, 3" mapping to "add_i_ic I4, I4, 3".

Anyway, enjoy.


Regards,

-- Gregor
 _____________________________________________________________________ 
/     perl -e 'srand(-2091643526); print chr rand 90 for (0..4)'      \

   Gregor N. Purdy                          [EMAIL PROTECTED]
   Focus Research, Inc.                http://www.focusresearch.com/
   8080 Beckett Center Drive #203                   513-860-3570 vox
   West Chester, OH 45069                           513-860-3579 fax
\_____________________________________________________________________/
Index: assemble.pl
===================================================================
RCS file: /home/perlcvs/parrot/assemble.pl,v
retrieving revision 1.8
diff -u -r1.8 assemble.pl
--- assemble.pl 2001/09/12 09:54:46     1.8
+++ assemble.pl 2001/09/12 21:13:55
@@ -4,7 +4,7 @@
 
 use strict;
 
-my(%opcodes, %labels);
+my(%opcodes, %opqual, %labels);
 my ($output, $opt_c);
 if (@ARGV and $ARGV[0] eq "-c") {
     shift @ARGV;
@@ -24,6 +24,14 @@
               's'=>'i',
               'D'=>'i');
 
+my %qual_type=('i'=>'ic',
+              'n'=>'nc',
+              'N'=>'n',
+              'I'=>'i',
+              'S'=>'s',
+              's'=>'sc',
+              'D'=>'ic');
+
 my $sizeof_packi = length(pack($pack_type{i},1024));
 
 open GUTS, "interp_guts.h";
@@ -45,8 +53,19 @@
     $opcodes{$name}{ARGS} = $args;
     $opcodes{$name}{TYPES} = [@types];
     $opcodes{$name}{RTYPES}=[@rtypes];
+
+    my ($root, @qual) = split /_/, $name;
+    my $qual = join(':', map { $qual_type{$_} } @rtypes);
+    $opqual{$root}{$qual} = $name;
 }
 
+#print STDERR "Opcode Table:\n";
+#foreach my $op (sort keys %opqual) {
+#    foreach my $qual (sort keys %{$opqual{$op}}) {
+#      printf STDERR  "    %-10s  %-15s  %-10s\n", $op, $qual, $opqual{$op}{$qual};
+#    }
+#}
+
 my $pc = 0;
 my @code;
 my %constants;
@@ -77,6 +96,46 @@
 
     my ($opcode, @args) = split /\s+/, $_;
 
+    if ($opcode =~ m/^[a-z]+$/i and ref $opqual{$opcode}) {     # If it doesn't have 
+any argument qualifiers
+#      print STDERR "Seeking opcode for '$opcode'...\n";
+       my @qual = ();
+
+       my $arg;
+       foreach $arg (@args) {   # Scan arguments after destination register
+#          print STDERR "    ... Arg: $arg\n";
+
+           if      ($arg =~ m/^I\d+$/) {     # Treat integer registers as 'i'
+               push @qual, 'i';
+           } elsif ($arg =~ m/^N\d+$/) {     # Treat numeric registers as 'n'
+               push @qual, 'n';
+           } elsif ($arg =~ m/^S\d+$/) {     # Treat numeric registers as 'n'
+               push @qual, 's';
+           } elsif ($arg =~ m/^\d+$/) {      # Treat manifest integers as 'ic'
+               push @qual, 'ic';
+           } elsif ($arg =~ m/^\d+\.\d*$/) { # Treat manifest decimals as 'nc'
+               push @qual, 'nc';
+           } elsif ($arg =~ m/^\$/) {       # Treat manifest strings as 'sc'
+               push @qual, 'sc';
+               $arg =~ s/^\$//; # Strip off the constant tag
+           } elsif ($labels{$arg}) {         # Treat labels as 'ic'
+               push @qual, 'ic';
+           } else {
+               die "Unrecognizable argument: '$arg'!";
+           }
+       }
+
+       if (@qual) {
+           my $qual = join(':', @qual);
+#          print STDERR "Qualifiers: $qual\n";
+           my $name = $opqual{$opcode}{$qual};
+           die "Cannot find opcode for root '$opcode' and qualifiers ($qual)!" unless 
+$name;
+           $opcode = $name;
+       } else {
+           die "Cannot determine qualifiers for root '$opcode' and arguments (" . 
+join(', ', @args) . ")!"
+               if $opcodes{$opcode}{ARGS};
+       }
+    }
+
     if (!exists $opcodes{lc $opcode}) {
        die "No opcode $opcode at line $line:\n  <$_>\n";
     }
@@ -111,7 +170,8 @@
     my $s = shift;
     return $constants{$s} if exists $constants{$s};
     push @constants, $s;
-    return $constants{$s} = $#constants;
+    $constants{$s} = $#constants;
+    return '$' . $constants{$s}; # We use the '$' prefix later to identify strings.
 }
 
 sub emit_magic { $output .= pack($pack_type{i}, 0x13155a1) }

Reply via email to