#rakulang: yet another attempt at Basic/Asm

I just can’t seem to stop playing around with language creation.

In a previous attempt, I emitted ARM assembler. I’m now thinking this is probably the wrong way to go. Instead, I’m experimenting with a stack virtual machine.

So far, precious little has been implemented as an instruction set: CALL, PUSH, HALT

You can push an integer to the stack, call a primitive, or halt execution. The primitives implemented so far are:

  • emit: print the top of the stack as a char
  • print: print the top of the stack as an integer
  • hello: print a greeting

Jump and arithmetic functions still need to be implemented.

Eventually, I hope to implement a complete BASIC, but with a twist: VM instructions should be available in BASIC. There’s nothing novel about this, of course, plenty of Basics allow you to mix in native assembler.

But I want to achieve a little more: I want to incorporate some kind of parsing ability in with the language.

Schorre’s 1962 paper, Meta II A Syntax-Oriented Compiler Writing Language, uses a separate VM assembler to construct a parser. I figured: what if I tried to combine assembling instructions which were tailored to parsing with a high-level language. Maybe I could get a better bootstrapping experience, and maybe I could create a BASIC with easily-extendable syntax.

I still have to complete a simple VM, mind, let alone figure out how to meld a high-level language in with it. But it seems an interesting idea.

The code so far is pretty trivial (not surprising seeings how little it does):

enum Bcode <Add Call Div Drop Dup Halt Inc Jlt Mul Push Sub>;
 my @bcodes;
 my @bvals;
 my @sstack; # regular stack
 sub spush(int32 $val) { @sstack.push($val); }
 sub spop() { return pop(@sstack); }
 sub bpush(Bcode $code, int32 $val) { @bcodes.push($code) ; @bvals.push($val); }

sub do-emit() { print chr(spop()); }
 sub do-print() { print spop; }
 sub do-hello() { say "Hello from raku blang"; }
 my @prims = (
         ["emit", &do-emit],
         ["print", &do-print], 
         ["hello", &do-hello]);
 sub find-prim($name) {
         loop (my $i=0; $i <elems(@prims); $i++)  {
                 my ($key, $f) = @prims[$i];
                 #say "key is $key";
                 if $name eq $key { return $i; }
         }
 }
 sub found($str) { say "Found: $str"; }
 sub xfound($str) {  }
 grammar G {
         rule TOP { ^  $ }
         rule stmts { * }
         rule statement {  |  |  }
         rule push { 'push'   { bpush Push, $.Int; }}
         rule call { 'call'  {bpush Call, find-prim $; } }
         rule halt { 'halt'  {xfound "halt"; bpush Halt, 0;} }
         #rule prin { 'print'  { push-int $.Int ; push $pri ; } }
         token id { <[a..zA..Z]>+ }
         token int       { <[0..9]>+ }
 }
 my $input = slurp;
 my $m = G.parse($input);
 say @bcodes;
 say @bvals;
 my $ip = 0;
 loop {
         my $bcode = @bcodes[$ip];
         my $val = @bvals[$ip];
         $ip++;
         given $bcode {
                 when Call {
                         #say @prims;
                         my $func = @prims[$val][1];
                         #say "func is $func";
                         $func();
                         }             
                 when Halt { last; }
                   when Push { spush $val;}
                   default { say "Unknown opcode"; }     }
 }
 say "Bye";

A simple program:

call hello
 push 120
 call emit
 push 10
 call emit
 halt

It prints a simple welcome message to the screen, an “x” (ASCII 120), a newline, then halts.

It will be interesting to see how far I will take this.

Code is here.

Update: A recent commit added the VM instructions dup, inc, sub, jlt and drop. Here’s how you’d output the string “ABCD”

     # print ABCD 
     push 65 # A
 loop:
     #call hello
     dup
     call emit
     inc
     dup
     push 69
     sub
     jlt loop
     drop
     halt

Pretty neat. The work involved wasn’t too difficult, and worked nearly first time, with only a minor bug. Onward and upward.

About mcturra2000

Computer programmer living in Scotland.
This entry was posted in Uncategorized. Bookmark the permalink.

3 Responses to #rakulang: yet another attempt at Basic/Asm

  1. Pingback: #rakulang blang: addition and subtraction | Mark Carter's blog

  2. Pingback: 2020.44 Comma Comma – Rakudo Weekly News

  3. Clifton Wood says:

    Great post! One thing though, your enum “BCode” had its contents eaten by the < >—- you might want to rewrite them as &lt and &gt

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s