I have made some significant improvements to Parakeet since I last
"released" it, enough that I am now confident that it can become a
complete Parrot language that exposes all of the OO features of the VM. 
So I'm calling it 0.1 with the anticipation that several more releases
will follow to finish the language.

http://www.daca.net:8080/Parakeet-0.1.tgz

Just unzip it into languages/parakeet and your ready to go.

Here's a little introduction to Parakeet:

Parakeet is a stack language like Forth.  You could call it Forth by
many people's definition, but it *isn't* standard Forth.  Parakeet is a
Forth that is extremely machine specific to the Parrot VM.  Parakeet
also has a lot of features not found in standard Forth, like local
variables, nested words and classes and (as a result) nested
compile-time and run-time lexical word, class and variable scopes.

Parakeet is fully dynamic and unprototyped, all variables and bindings
are looked up at run-time using Parrot's lexical scratchpad stacks.  In
many ways its level of object dynamics approaches that of Python, while
still retaining that Forth minimalistic thing.

Parakeet is written in PIR and compiles new words directly to PIR. 
There is no "inner loop" above the Parrot VM and core words are not
"threaded" (in the Forth sense of the word), they are directly inlined
into the new word's body.  Consider a simple example:


0> def count do i i println loop end 
0> 5 0 count
0
1
2
3
4
0> 

The new word 'count' accepts two arguments on the stack, the start on
top of the limit (in Pararkeet 'def' and 'end' correlate roughly to
Forth's ':' and ';').  I typed in the example above on one line, but it
becomes clearer when indented:

def count
  do i
    i println
  loop
end

The PIR code that a word compiles to can be shown with the word 'see':

0> see count
.include "languages/parakeet/macros.imc"
.pcc_sub _count
$P99 = P1 # save return cont.
.POP2
push .CSTACK, .NOS
push .CSTACK, .TOS
find_lex $P0, "i"
assign $P0, .TOS
do2:
find_lex .TOS, "i"
.PUSH
.POP
print .TOS
print "\n"
pop .TOS, .CSTACK
pop .NOS, .CSTACK
inc .TOS
find_lex $P0, "i"
assign $P0, .TOS
push .CSTACK, .NOS
push .CSTACK, .TOS
ne .TOS, .NOS,  do2
pop .TOS, .CSTACK
pop .NOS, .CSTACK
invoke $P99
.end
0> 

If you're familiar with Forth, you might notice that Parakeet's 'do' has
a following argument unlike Forth.  This argument binds to the index
value each time through the loop.  This removes two of historical and
standard Forth's horrible hardwired words 'I' and 'J'.  Loops can be
nested to any depth:

def foo 
  3 0 do i 
    3 0 do j 
      3 0 do k 
        i j k + + println 
      loop 
    loop 
  loop 
end

I also have hook words 'for i ... next' for when I figure out Parrot
iterators.  

Simple variables can be created with 'var':

0> 2 var x 3 var y
0> x y + println
5
0>

Classes are not so fully baked yet.  Parakeet uses the following syntax:

  class foo

    def bar "hi!" println end

  endclass

Classes can be instanciated with 'foo new':

  0> foo new var f  

And instances can bind to "methods" which are inner words:

  0> f -> bar
  hi!
  0>

Classes can contain classes:

  class ned 
    class flanders endclass 

    def joe flanders new var f end 
  endclass

There is no subclassing, yet, and I haven't figured out how to tie these
classes into other Parrot classes, yet, but the idea is there.

Curiously unlike Forth, words can also contain words and classes:

  def foo

    class ned endclass

    def bar 
      "hi!" println 
      ned new var n  # use inner class
    end  

    bar  # use inner word
  end

  0> foo
  hi!
  0>

Given these rules there are lots of ways to structure words and classes
within each other.  Words and classes can be considered "static" (in the
Java sense of the word) structures.  Classes can be instantiated to
provide objects with methods.  When you call a word on an class instance
with '->' (bind) the instance is passed in the normal PCC way.

I haven't gotten to arguments yet to allow calling out of Parakeet, but
I plan to use '(' and ')' like so:

0> ( arg1 arg2 arg3 ) object -> method

The word '(' pushes a special marker on the stack, the arguments are
pushed on the stack, the word ')' searches down the stack for the marker
building an argument array, and the word '->' (which might have to be
renamed to handle the no-arg and arg cases) folds this up for PCC before
it makes the call. 

There will be more ideas like that coming as I continue to get a better
grasp on Parrot.  If there is any interest in helping develop Parakeet
(particularly if you are better at rx4 than me!) feel free to contact me
and I'll put it up on sourceforge or somewhere.

-Michel


Reply via email to