cvsuser     04/10/05 02:30:21

  Modified:    .        MANIFEST
  Added:       languages/parakeet README.txt parakeet.imc test.pk
  Log:
  parakeet 0.3
  Parakeet is an object-oriented Forth-like stack language for the Parrot
  VM.  It is written in PIR and compiled its code directly to PIR.
  Parakeet lets you do logical, numeric and string operations and
  comparisons, conditionals and loops, define variables, functions,
  classes methods, create instanciate and call methods on objects.
  
  Courtesy of Michel Pelletier <[EMAIL PROTECTED]>
  
  Revision  Changes    Path
  1.744     +3 -0      parrot/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /cvs/public/parrot/MANIFEST,v
  retrieving revision 1.743
  retrieving revision 1.744
  diff -u -w -r1.743 -r1.744
  --- MANIFEST  30 Sep 2004 23:58:58 -0000      1.743
  +++ MANIFEST  5 Oct 2004 09:30:20 -0000       1.744
  @@ -2195,6 +2195,9 @@
   languages/ook/hello.ook                           [ook]
   languages/ook/ook.pasm                            [ook]
   languages/ook/test.ook                            [ook]
  +languages/parakeet/README.txt                     [parakeet]
  +languages/parakeet/parakeet.imc                   [parakeet]
  +languages/parakeet/test.pk                        [parakeet]
   languages/parrot_compiler/parrot.pasm             []
   languages/parrot_compiler/sample.pasm             []
   languages/perl6/ChangeLog                         [perl6]
  
  
  
  1.1                  parrot/languages/parakeet/README.txt
  
  Index: README.txt
  ===================================================================
  Parakeet
  
    Parakeet is a Forth-like stack language for the Parrot VM.  It is
    written in PIR and compiles its code directly to PIR.
  
    By "Forth-like" I mean that it is not "Standard Forth".  Parrot has
    no intention of following the Forth standard, which is very specific
    to small, concrete micro-processors.  Parakeet is a Forth VM that
    fits naturally on top of the object oriented architecture of the
    Parrot VM.
  
    Parakeet comes with a small 'test.pk' file that flexes most of the
    features implemeted so far.  If you want to go right to the code,
    take a look at that.  If you want to use some kind of editor mode to
    highlight it, I suggest a shell mode.
  
    Parakeet can be used and learned through an interactive interpreter.
    To run the interpretor, point your Parrot interpreter to the
    parakeet.imc file, like:
  
      ./parrot language/parakeet/parakeet.imc
      0>
  
    The '0>' is the interactive prompt.  The number represents the
    number of objects on the "data stack".  Currently there are zero.
    Objects get "pushed" onto the stack depending on what you type here,
    for example, to push two numbers onto the stack, just type them in:
  
      0> 33 44
      2>
  
    The numbers '33' and '44' are now pushed onto the stack from left to
    right, '44' sits atop '33'.  Now to add the two numbers together,
    use the word '+' and print out the result with 'println':
  
      2> + println
      77
      0>
  
    Due to Parakeet's Forth syntax, the mathematical notiation is
    postfix, where the operator follows the operands.  The Python
    expression:
  
      print 3 * (4 + 2)
  
    in Parakeet is:
  
      4 2 + 3 * println
  
  Words
  
    Like in Forth, everything in Parakeet is a word.  Words are
    seperated by whitespace.  While in other languages the equivalent to
    '*' might be called an operator, and the equivalent to 'println'
    might be called a builtin, or a function, in Parakeet they are all
    just words.
  
    Some words like numbers, string, and certain primitive "core" words
    are built into Parakeet.  Other words you can define yourself as
    variable functions, classes, and methods.
  
    A variable is defined wit the word 'var'
  
     0> 3 var x
     0> x println
     3
     0>
  
    Var is the equivalent to a Python assignment.  You can call var many
    times with different values on the same variable.  The old reference
    will be replaced with the new:
  
     0> 4 var x x println
     4
     0>
  
    "Functions" are words that execute a block of Parakeet code.  They
    are defined with the words 'func' and 'end':
  
     0> func hello "hi!" println end
     0> hello
     hi!
     0>
  
    "Classes" are defined with the words 'class' and 'end', and their
    methods are defined with the words 'meth' and 'end':
  
      0> class Foo meth bar "hi!" println end end
      0>
  
    New instances of classes can be created with 'new':
  
      0> Foo new var f
  
    And methods can be called with '->' ("bind"):
  
      0> f -> bar
      hi!
  
    Words try to be a little helpful by allowing you to see their PIR
    code:
  
      0> see hello
      .sub _hello
      .TOS = new .PerlString
      .TOS = "hi!"
      .PUSH
      .POP
      print .TOS
      print "\n"
      invoke P1
      .end
      0> 
  
    The word 'see' shows you the PIR code that was compiled to create
    the word 'hello'.  Classes can also be seen:
  
      0> see Foo
      .namespace["Foo"]
      .sub _bar method
      inc .LEVEL
      new_pad .LEVEL
      .TOS = new .PerlString
      .TOS = "hi!"
      .PUSH
      .POP
      print .TOS
      print "\n"
      pop_pad
      dec .LEVEL
      .pcc_begin_return
      .pcc_end_return
      .end
      0> 
  
    Seeing a core word shows you a small description of that word:
  
      0> see println
      Core Word: Pop stack item and print it on own line.
      0> 
  
    Since the core words are still pretty flexible right now, please see
    the source file parakeet.imc for a list of all the current words.
  
  Control
  
    If blocks:
  
      0> 1 if "true" println then
      true
      0> 0 if "false" println then
      0>
  
    'else' is not yet implemented.
  
    Do loops in parakeet have a following named index variable.  So the
    Forth:
  
      10 0 do 
        i . 
      loop
  
    In Parakeet becomes:
  
      10 0 do i 
        i println 
      loop
  
    Notice that the 'i' follows the 'do'.  This is the variable name that
    Parakeet will assign the index value every time through the loop.
    Slightly more verbose, but removes Forth's terrible hardwired 'I' and
    'J' words and allows creative index var names like:
  
      xaxis do xpoint
        yaxis do ypoint
        zaxis do zpoint
           # use xpoint, ypoint, and zpoint
        loop
        loop
      loop
  
    Parakeet will also support interators with the words 'for' and
    'next', but this has not been implemented yet.
  
  
  
  1.1                  parrot/languages/parakeet/parakeet.imc
  
  Index: parakeet.imc
  ===================================================================
  
  # Parakeet is a stack machine language for the Parrot VM not entirely
  # unlike the Forth programming language.  Parakeet is extremely simple
  # and interactive.  Just run this file through Parrot and you will get
  # an interpreter prompt.  From there, you can type in Parakeet code.
  
  
  .macro IPROMPT "> " .endm
  .macro CPROMPT "... " .endm
  
  .const int Space = 32
  .const int Tab = 9
  
  # Registers used by machine.  These are hardwired to a register and
  # all core words expect them in these places.  User words compiled in
  # and executed save and restore these registers.
  
  .macro STACK  P30 .endm     # the data stack
  .macro CSTACK P29 .endm     # the control stack
  
  .macro PIRC   P28 .endm     # the PIR compiler
  .macro OBJ    P27 .endm     # a handy instance temp
  .macro KLASS P26 .endm      # currently compiling class
  
  .macro TOS P25 .endm        # Top Of Stack
  .macro NOS P24 .endm        # Next On Stack
  
  .macro STDIN P23 .endm      # standard input where source comes from
  .macro INTS P22 .endm       # array of pre-created integers for speed
  .macro FLAGS P21 .endm      # hash of flags for interpreter
  
  .macro LEVEL I30 .endm      # current lexical level 0 is interpret > 0 is compile
  .macro MODE I29 .endm       # current compile mode (func, class, meth)
  .macro ITMP I28 .endm
  
  .macro BODY S30 .endm       # Currently compiling word body
  .macro CURR S29 .endm       # current word
  .macro SRC  S28 .endm       # remaining source line to be interpreted
  .macro NAMESPACE  S27 .endm # currently compiling namespace
  .macro LOAD S26 .endm       # currently compiling module load body, non-interactive
  
  .macro NumInts 10 .endm      # increase to turn on integer preallocation
  
  .macro COMPILING .LEVEL > 0 .endm
  .macro INTERPRETING .LEVEL == 0 .endm
  
  .macro SAVEM  # this could probably be less bold...
    saveall
  .endm
  
  .macro RESTOREM
    restoreall
  .endm
  
  .macro SEEING
      .ITMP = .FLAGS["seeing"]
      unless .ITMP > 0 goto .$EndDebug
      print .BODY
      .local $EndDebug:
  .endm
  
  # compiling
  
  .macro emit(s)
      concat .BODY, .s
  .endm
  
  .macro NEXT
      goto Next
  .endm
  
  .macro NEXTLINE goto NextLine .endm
  
  # errors
  
  .macro atLeastOne
      .ITMP = .STACK
      if .ITMP > 0 goto .$NoError
      new $P0, .Exception
      $P0["_message"] = "Stack is Empty!"
      throw $P0
      .local $NoError:
  .endm
  
  .macro atLeastTwo
      .ITMP = .STACK
      if .ITMP > 1 goto .$NoError
      new $P0, .Exception
      $P0["_message"] = "Stack is Empty!"
      throw $P0
      .local $NoError:
  .endm
  
  # be careful with the macros below, most of them trounce .TOS so don't
  # rely on that register being preserved.
  
  # stackies
  
  .macro POP
    .atLeastOne
    pop .TOS, .STACK
  .endm
  
  .macro POP2
    .atLeastTwo
    pop .TOS, .STACK
    pop .NOS, .STACK
  .endm
  
  .macro PUSH
    push .STACK, .TOS
  .endm
  
  # bools
  
  .macro TRUE
    .PUSHI(1)
  .endm
  
  .macro FALSE
    .PUSHI(0)
  .endm
  
  # ints
  
  .macro getInt(x)
      lt .x, 0, .$createInt
      lt .x, .NumInts, .$fetchInt
    .local $createInt:
      .TOS = new .PerlInt
      .TOS = .x
      goto .$End
    .local $fetchInt:
      .TOS = .INTS[.x]
      clone .TOS, .TOS  # to prevent anyone modifying a "constant" int
    .local $End:
  .endm
  
  .macro PUSHI(x)
    .getInt(.x)
    .PUSH
  .endm
  
  # types of words
  
  .macro __CORE 0 .endm
  .macro __FUNC 1 .endm
  .macro __VAR 2 .endm
  .macro __CLASS 3 .endm
  .macro __METH 4 .endm
  
  # add words
  
  .macro addCore(name, lbl, doc)
    $P1 = new .PerlString
    $P1 = .doc
    .getInt(.__CORE)
    $P0 = .TOS
    set_addr .ITMP, .lbl
    .getInt(.ITMP)
    setprop .TOS, "__type__", $P0
    setprop .TOS, "__doc__", $P1
    store_lex .LEVEL, .name, .TOS
  .endm
  
  .macro addVar(name, val, lv)
    .getInt(.__VAR)
    setprop .val, "__type__", .TOS
    store_lex .lv, .name, .val
  .endm
  
  .macro addClass(name, klz, lv)
    .getInt(.__CLASS)
    setprop .klz, "__type__", .TOS
    store_lex .lv, .name, .klz
  .endm
  
  .macro findWord(wrd)
    newsub $P1, .Exception_Handler, .$NotFound
    set_eh $P1
    find_lex .TOS, .wrd
    goto .$End
  .local $NotFound:
    clear_eh
      $P0 = new .Exception
      $P0["_message"] = "UnknownWord"
      throw $P0
  .local $End:
  .endm
  
  
  # comparisons meta macros
  
  # this hack on branching comparisons is so we can use PIR's .local
  # macro target expansions. (way easier than keeping track of my own
  # expansions)
  
  .macro __EQ
      .POP2
      eq .NOS, .TOS, .$_IS
      .FALSE
      goto .$End
    .local $_IS:
      .TRUE
    .local $End:
  .endm
  
  .macro __NE
      .POP2
      ne .NOS, .TOS, .$_IS
      .FALSE
      goto .$End
    .local $_IS:
      .TRUE
    .local $End:
  .endm
  
  .macro __LT
      .POP2
      lt .NOS, .TOS, .$_IS
      .FALSE
      goto .$End
    .local $_IS:
      .TRUE
    .local $End:
  .endm
  
  .macro __GT
      .POP2
      gt .NOS, .TOS, .$_IS
      .FALSE
      goto .$End
    .local $_IS:
      .TRUE
    .local $End:
  .endm
  
  .macro __LE
      .POP2
      le .NOS, .TOS, .$_IS
      .FALSE
      goto .$End
    .local $_IS:
      .TRUE
    .local $End:
  .endm
  
  .macro __GE
      .POP2
      ge .NOS, .TOS, .$_IS
      .FALSE
      goto .$End
    .local $_IS:
      .TRUE
    .local $End:
  .endm
  
  .macro __ASSERT
      .POP
      if .TOS goto .$End
      $P0 = new .Exception
      $P0["_message"] = "AssertionError"
      throw $P0
    .local $End:
  .endm
  
  
  ##########################################################
  ##
  ## Interpreter entry point.
  ##
  ##########################################################
  
  .sub _main @MAIN
    .param PerlArray argv
  
    .STACK = new .PerlArray
    .CSTACK = new .PerlArray
    .INTS = new .PerlArray
    .FLAGS = new .PerlHash
    .BODY = ""
    .LOAD = ""
  
    .FLAGS["interactive"] = 1  # is the interpreter interactive?
    .FLAGS["seeing"] = 0       # print PIR blocks before compiling
  
    .ITMP = argv
  
    # name of the program
    .local string program_name
    program_name = shift argv
  
    if .ITMP > 1 goto OpenFile
    getstdin .STDIN
  
    # turn off output buffering
  
    getstdout $P0
    $P0."setbuf"(0)
  
    goto GotInput
  
    OpenFile:
  
    .FLAGS["interactive"] = 0
    .FLAGS["bye"] = 0
  
    $S0 = shift argv
    open .STDIN, $S0
  
    GotInput:
  
    .NAMESPACE = ""
    .LEVEL = 0
  
    newsub $P0, .Exception_Handler, _handler
    set_eh $P0
  
     new_pad .LEVEL
  
    compreg .PIRC, "PIR"
  
    # simple optimization hack, pre-create the first thousand or so
    # integer "constants".  See .getInt and .PUSHI.
  
    .ITMP = 0
    _fillInts:
      $P0 = new .PerlInt
      $P0 = .ITMP
      .INTS[.ITMP] = $P0
      inc .ITMP
      lt .ITMP, .NumInts, _fillInts
  
    # code objects
  
    .addCore("package", _PACKAGE, "Declare a package (unimplemented).")
  
    .addCore("func", _FUNC, "Defines a new function.")
    .addCore("class", _CLASS, "Defines a new class.")
    .addCore("meth", _METH, "Defines a new method.")
    .addCore("end", _END, "Ends the current function, class or method definition.")
  
    # inheritance and interfaces
  
    .addCore("extends", _EXTENDS, "Declare a superclass.")
    .addCore("implements", _IMPLEMENTS, "Declare a class implements an interface.")
  
    .addCore("attr", _ATTR, "Declare an attribute in a class.")
    .addCore("get", _GET, "Get an attribute from an object, push it on stack.")
    .addCore("set", _SET, "Set an attribute on an object.")
  
    # variables
  
    .addCore("var", _VAR, "Declare a local variable.")
    .addCore("self", _SELF, "Push self instance on stack.")
  
    # libraries
  
    .addCore("load-bytecode", _LOAD_BYTECODE, "Load bytecode from a Parrot file.")
    .addCore("include", _INCLUDE, "Include Parakeet code from another file.")
  
    # typish stuff
  
    .addCore("find-type", _FINDTYPE, "Pops type name and pushes type enumeration.")
    .addCore("new", _NEW, "Pops type enumeration and pushes new instance of that 
type.")
    .addCore("->", _BIND, "Binds an object to a word and executes it.")
  
    # wordish stuff
  
  #  .addCore("lit", _LIT, "Pushes the next word literally.")
    .addCore("execute", _EXECUTE, "Pops code object and executes it.")
  
    # misc
  
    .addCore("bye", _BYE, "Exits Parakeet.")
    .addCore("see", _SEE, "Examine a word.")
    .addCore("seeing", _SEEING, "Turn on underlying PIR printing.")
  
    # debugging
  
    .addCore("debug", _DEBUG, "Toggle Parrot debugging information.")
    .addCore("debug-init", _DEBUG_INIT, "Init debugger.  Must call before other debug 
words")
    .addCore("debug-break", _DEBUG_BREAK, "Break into debugger.  Segfaults?")
  
    .addCore("bounds", _BOUNDS, "Toggle Parrot bounds checking.")
    .addCore("profile", _PROFILE, "Toggle Parrot profiling.")
    .addCore("trace", _TRACE, "Toggle Parrot instruction tracing.")
  
  #   .addCore("interactive", _INTERACTIVE, "Swtiches to interactive mode.")
  #   .addCore("non-interactive", _NINTERACTIVE, "Switches to non-interactive mode.")
  
    .addCore("assert", _ASSERT, "Throws error if top stack item is non-true.")
  
    # exceptions
  
    .addCore("throw", _THROW, "Pop exception and throw it.")
  
    # i/o
  
    .addCore("readline", _READLINE, "Read a line.")
    .addCore("read", _READ, "Read a character.")
  
    .addCore("print", _PRINT, "Pop stack item and print it.")
    .addCore("println", _PRINTLN, "Pop stack item and print it on own line.")
  
    .addCore("open", _OPEN, "unimplemented.")
    .addCore("close", _CLOSE, "unimplemented.")
    .addCore("peek", _PEEK, "unimplimented.")
    .addCore("stat", _STAT, "unimplimented.")
    .addCore("seek", _SEEK, "unimplimented.")
    .addCore("tell", _TELL, "unimplimented.")
  
    # stackies
  
    .addCore("drop", _DROP, "Pop and discard top of stack.")
    .addCore("dup", _DUP, "Duplicate top of stack.")
    .addCore("depth", _DEPTH, "Push the current stack depth.")
  
    # control flow
  
    .addCore("if", _IF, "Execute block if TOS is true.")
    .addCore("then", _THEN, "End of conditional block started with 'if'.")
    .addCore("else", _ELSE, "Begining of alternate conditional block started with 
'if'.")
    .addCore("do", _DO, "Fast integer loop.")
    .addCore("loop", _LOOP, "Loop back to 'do'")
    .addCore("+loop", _PLOOP, "Loop back to do, incrementing index var by top of 
stack.")
    .addCore("for", _FOR, "Loop over iteration object on top of stack.")
    .addCore("next", _NEXT, "Loop back to 'for'.")
  
    # math
  
    .addCore("+", _ADD, "Add top stack items, push sum.")
    .addCore("-", _SUB, "Subtract top stack items, push difference.")
    .addCore("*", _MUL, "Multiple top stack items, push product.")
    .addCore("/", _DIV, "Divide top stack items, push result.")
    .addCore("%", _MOD, "Divide top stack items, push remainder.")
  
    # 'crementers
  
    .addCore("1+", _INC, "Increment top of stack.")
    .addCore("1-", _DEC, "Decrement top of stack.")
  
    # comparisons
  
    .addCore("cmp", _CMP, "Compare top two stack items.")
    .addCore("==", _EQ, "Compare top two stack items for equality.")
    .addCore("!=", _NE, "Compare top two stack items for inequality")
    .addCore(">", _GT, "Greater than comparison.")
    .addCore("<", _LT, "Less than comparison.")
    .addCore(">=", _GE, "Greater than or equal to comparison.")
    .addCore("<=", _LE, "Less than or equal to comparison.")
  
    # booleans
  
    .addCore("and", _AND, "Boolean And.")
    .addCore("or", _OR, "Boolean Or.")
    .addCore("xor", _XOR, "Boolean Xor.")
    .addCore("not", _NOT, "Boolean Not.")
  
    #######################################################
    # fetch a new line of code
  
    NextLine:
      .ITMP = length .BODY
      if .ITMP == 0 goto FreshLine
      if .COMPILING goto FreshLine
      .emit("invoke P1\n")
      .emit(".end\n")
      .SEEING
      compile $P0, .PIRC, .BODY
      .SAVEM
      invokecc $P0
      .RESTOREM
    FreshLine:
      .ITMP = .FLAGS["interactive"]
      unless .ITMP == 1 goto Prompted
      if .COMPILING goto CompilePrompt
      .ITMP = .STACK
      print .ITMP
      print .IPROMPT
      goto Prompted
  
    CompilePrompt:
      print .CPROMPT
  
    Prompted:
      .LOAD = ""
      unless .INTERPRETING goto Readline
      .BODY = ".sub xt\nnoop\n"
    Readline:
      readline .SRC, .STDIN
      length .ITMP, .SRC
      if .ITMP == 0 goto End
      dec .ITMP
      substr .SRC, .SRC, 0, .ITMP # slice off newline
  
    ########################################################
    # fetch the next word
  
  
  
    Next:
      .ITMP = .FLAGS["bye"]
      if .ITMP > 0 goto End
      .CURR = ""
      bsr CollectWord
      if .CURR == "" .NEXTLINE
      goto Comment
  
    Comment:
      substr $S0, .CURR, 0, 1
      unless $S0 == "#" goto Zero
      .NEXTLINE
  
    Zero:
      unless .CURR == "0" goto Integer
      .emit(".PUSHI(0)\n")
      goto Next
  
    Integer:
      .ITMP = .CURR
      unless .ITMP > 0 goto String
      .emit(".PUSHI(")
      .emit(.CURR)
      .emit(")\n")
      goto Next
  
    String:
  
      # This is lame-o.  figure out Rx4 to parse out string literals
  
      substr $S0, .CURR, 0, 1
      unless $S0 == "\"" goto Word
      substr .CURR, .CURR, 1              # slice leading quote
      substr $S0, .CURR, -1
  #    print $S0
      unless $S0 == "\"" goto moreString  # trailing quote?
      chopn .CURR, 1                      # slice it
      goto gotString                      # we're done
    moreString:                           # otherwise,
      index $I1, .SRC, "\""               # search for trailing quote
      substr $S0, .SRC, 0, $I1, ""        # when found, slice rest of string off
      concat .CURR, $S0                   # and concat
  #    print .CURR
  
    gotString:
      .emit(".TOS = new .PerlString\n.TOS = \"")
      .emit(.CURR)
      .emit("\"\n.PUSH\n")
      goto Next
  
    Word:
      newsub $P1, .Exception_Handler, _var_not_found
      set_eh $P1
  
      find_lex .TOS, .CURR
      goto FoundWord
  
    _var_not_found:
      clear_eh
      goto UnknownWord
  
    # at this point the word we are looking for is a lexical variable.
    # What to do with depends on it's "__type__" property.
  
    FoundWord:
      clear_eh
      getprop $P0, "__type__", .TOS
  
      if $P0 == .__CORE goto Core
      if $P0 == .__FUNC goto User
      if $P0 == .__VAR goto Variable
      if $P0 == .__CLASS goto Class
  
    Core:
      .ITMP = .TOS
      jump .ITMP
  
    User:
      .emit("find_lex .TOS, \"")
      .emit(.CURR)
      .emit("\"\n.SAVEM\ninvokecc .TOS\n.RESTOREM\n")
      goto Next
  
    Variable:
      .emit("find_lex .TOS, \"")
      .emit(.CURR)
      .emit("\"\n.PUSH\n")
      goto Next
  
    Class:
      .emit("find_type $I0, \"")
      .emit(.CURR)
      .emit("\"\n.PUSHI($I0)\n")
      goto Next
  
    UnknownWord:
      print "Unknown Word: "
      print .CURR
      print "\n"
      .LEVEL = 0
      .NEXTLINE
  
    _handler:
      print "An Exception was thrown: "
      set S0, P5["_message"]    # P5 is the exception object
      print S0
      print "\n"
      .LEVEL = 0
      .NEXTLINE
  
    End:
      # Current hack to really end the interpreter.
      # The problem is due to branching to different code segments.
      # Using "end" terminates the current run loop only, evaluating
      # compiled code branched to different code segments though, which
      # are ended but not the main one.
      # -leo
      clear_eh
      exit 0
  
  #  I need an rx expert!
  #
  #  CollectWord:
  #     pushi
  #     $I0 = 0  # index
  #     $I1 = 0  # start
  #     $I2 = 0  # length
  
  #     .CURR = ""
  
  #     $I3 = .SRC
  #     if $I3 > 0 goto begin_
  #     goto end_
  
  #   begin_:
  #     rx_is_s .SRC, $I0, beginword_
  #     goto begin_
  
  #   beginword_:
  #     $I1 = $I0
  #   moreword_:
  #     rx_is_s .SRC, $I0, advanceword_
  #     $I2 = $I0 - $I1
  #     dec $I2
  #     substr .CURR, .SRC, $I1, $I2, ""
  #     print "|"
  #     print .CURR
  #     print "|\n"
  #     goto end_
  
  #   advanceword_:
  #     rx_advance .SRC, $I0, end_
  #     goto moreword_
  
  #   end_:
  #     popi
  #     ret
  
    CollectWord:
      .CURR = ""
      length $I1, .SRC
      eq $I1, 0, DoneWhite
      set $I3, 0
      ord $I2, .SRC, $I3
      eq $I2, Space, EatWhite
      eq $I2, Tab, EatWhite
      branch DoneWhite
    EatWhite:
      inc $I3
      eq $I1, $I3, FinishWhite
      ord $I2, .SRC, $I3
      eq $I2, Space, EatWhite
      eq $I2, Tab, EatWhite
    FinishWhite:
      substr .SRC, 0, $I3, ""
    DoneWhite:
      length $I1, .SRC
      eq $I1, 0, DoneCollectWord
      set $I3, 0
    NextChar:
      eq $I3, $I1, EndDark
      ord $I2, .SRC, $I3
      eq $I2, Space, EndDark
      eq $I2, Tab, EndDark
      inc $I3
      branch NextChar
    EndDark:
      substr .CURR, .SRC, 0, $I3, ""
    DoneCollectWord:
      ret
  
  ################################################################
  # Core word definitions follow
  ################################################################
  
    _CLASS:
      bsr CollectWord
      unless .LEVEL > 0 goto _CLASS1
      save .KLASS
      save .MODE
    _CLASS1:
  
      .MODE = .__CLASS
      save .BODY
  
      inc .LEVEL
      new_pad .LEVEL
  
      newclass .KLASS, .CURR
  
      save .NAMESPACE
  
      .NAMESPACE = classname .KLASS
      .BODY = ".namespace[\""
      .emit(.NAMESPACE)
      .emit("\"]\n")
      .NEXT
  
    _FUNC:
  
      bsr CollectWord
  
      inc .LEVEL
     new_pad .LEVEL
  
      unless .LEVEL > 0 goto _FUNC1
      save .KLASS
      save .MODE
    _FUNC1:
  
      .MODE = .__FUNC
      save .BODY
      save .CURR
  
      .BODY = ".sub _"
      .emit(.CURR)
      .emit("\n")
      .NEXT
  
    _METH:
      bsr CollectWord
  
      inc .LEVEL
      new_pad .LEVEL
  
      save .MODE
      .MODE = .__METH
  
      .emit(".sub _")
      .emit(.CURR)
      .emit(" method\n")
      .emit("inc .LEVEL\nnew_pad .LEVEL\n")
      .NEXT
  
    _END:
      if .COMPILING goto _ENDFUNC
      print "Not inside a definition.\n"
      .NEXT
  
    _ENDFUNC:
  
      if .MODE == .__CLASS goto _ENDCLASS
      if .MODE == .__METH goto _ENDMETH
  
      unless .LEVEL == 0 goto _DOENDFUNC
      print "Nothing to end!\n"
      .NEXT
    _DOENDFUNC:
  
      .emit("invoke P1\n")
      .emit(".end\n")
  
      .SEEING
      compile $P0, .PIRC, .BODY
      $P1 = new .PerlString
      $P1 = .BODY
  
      setprop $P0, "__asm__", $P1
  
      dec .LEVEL
      peek_pad $P1
      pop_pad
  
  #    setprop $P0, "__dict__", $P1
  
      restore .CURR
      restore .BODY
  
      .getInt(.__FUNC)
      setprop $P0, "__type__", .TOS
  
      store_lex .LEVEL, .CURR, $P0
  
      if .LEVEL == 0 goto _ENDFUNC1
      restore .KLASS
      restore .BODY
      restore .MODE
  
    _ENDFUNC1:
      .NEXT
  
    _ENDMETH:
      .emit("pop_pad\ndec .LEVEL\n")
      .emit(".pcc_begin_return\n.pcc_end_return\n")
      .emit(".end\n")
     pop_pad
      dec .LEVEL
      restore .MODE
      .NEXT
  
    _ENDCLASS:
      .SEEING
      compile $P0, .PIRC, .BODY
      $P1 = new .PerlString
      $P1 = .BODY
  
      setprop .KLASS, "__asm__", $P1
      setprop .KLASS, "__bytecode__", $P0
  
      restore .BODY
  
      dec .LEVEL
      peek_pad $P1
      pop_pad
      setprop .KLASS, "__dict__", $P1
  
      $P1 = new .PerlInt
      $P1 = .__CLASS
      setprop .KLASS, "__type__", $P1
  
      $S0 = classname .KLASS
  
      store_lex .LEVEL, $S0, .KLASS
  
      restore .NAMESPACE
  
      if .LEVEL == 0 goto _ENDCLASS1
      restore .KLASS
      restore .MODE
    _ENDCLASS1:
      .NEXT
  
    _PACKAGE:
      .NEXT
  
    _EXTENDS:
      bsr CollectWord
      getclass $P1, .CURR
      addparent .KLASS, $P1
      .NEXT
  
    _IMPLEMENTS:
      bsr CollectWord
  #    adddoes .KLASS, .CURR
      .NEXT
  
    _ATTR:
      bsr CollectWord
      addattribute .KLASS, .CURR
      .NEXT
  
    _GET:
      bsr CollectWord
      .POP
  #    class $P0, .TOS
  #    classname $S0, $P0
  #    concat $S0, "\0"
  #    concat $S0, .CURR
      getattribute $P0, .TOS, .CURR
      .TOS = $P0
      .PUSH
      .NEXT
  
    _SET:
      bsr CollectWord
      .POP2
  #    class $P0, .TOS
  #    classname $S0, $P0
  #    concat $S0, "\0"
  #    concat $S0, .CURR
      setattribute .TOS, .CURR, .NOS
      .NEXT
  
    _SEE:
      unless .INTERPRETING goto _BLIND
      bsr CollectWord
  
      newsub $P1, .Exception_Handler, _word_not_found2
      set_eh $P1
      find_lex $P0, .CURR
      getprop $P1, "__type__", $P0
  
      if $P1 == .__CORE goto SeeCore
      if $P1 == .__FUNC goto SeeUser
      if $P1 == .__VAR goto SeeVariable
      if $P1 == .__CLASS goto SeeUser
  
    SeeCore:
      getprop $P1, "__doc__", $P0
      print "Core Word: "
      print $P1
      print "\n"
      clear_eh
      .NEXT
  
    SeeUser:
      getprop $P1, "__asm__", $P0
      print $P1
      clear_eh
      .NEXT
  
    SeeVariable:
      print .CURR
      print " is a variable.\n"
      print "\n"
      clear_eh
      .NEXT
  
    SeeClass:
      print .CURR
      print " is a class.\n"
      print "\n"
      clear_eh
      .NEXT
  
    _word_not_found2:
      print "Can't see word: "
      print .CURR
      print "\n"
      clear_eh
      .NEXT
  
    _BLIND:
      goto Next
  
    _LOAD_BYTECODE:
      .emit("load_bytecode \"")
      .emit(.CURR)
      .emit("\"\n")
      .NEXT
  
    _INCLUDE:
      .NEXT
  
    _SEEING:
      .emit(".POP\n$I0 = .TOS\n")
      .emit(".FLAGS[\"seeing\"] = $I0\n")
      .NEXT
  
    _TRACE:
      .emit(".POP\n")
      .emit("$I0 = .TOS\n")
      .emit("trace $I0\n")
      .NEXT
  
    _DEBUG:
      .emit(".POP\n")
      .emit("$I0 = .TOS\n")
      .emit("debug $I0\n")
      .NEXT
  
    _DEBUG_INIT:
      .emit("debug_init\n")
      .NEXT
  
    _DEBUG_BREAK:
      .emit("debug_break\n")
      .NEXT
  
    _BOUNDS:
      .emit(".POP\n")
      .emit("$I0 = .TOS\n")
      .emit("bounds $I0\n")
      .NEXT
  
    _PROFILE:
      .emit(".POP\n")
      .emit("$I0 = .TOS\n")
      .emit("profile $I0\n")
      .NEXT
  
  #   _INTERACTIVE:
  #     save .SRC
  #     save .STDIN
  #     getstdin .STDIN
  #     .FLAGS["interactive"] = 1
  #     .NEXT
  
  #   _NINTERACTIVE:
  #     .FLAGS["interactive"] = 0
  #     restore .STDIN
  #     restore .SRC
  #     .NEXT
  
     _ASSERT:
       .emit(".__ASSERT\n")
       .NEXT
  
    _BYE:
      .emit(".FLAGS[\"bye\"] = 1\n")
      .NEXT
  
    _VAR:
      bsr CollectWord
      # Also stash the var at compile time, so that later references
      # to it can be resolved.
  
      .getInt(0)
      $P0 = .TOS
      .getInt(.__VAR)
      setprop $P0, "__type__", .TOS
      store_lex -1, .CURR, $P0
  
      .emit(".POP\n$P0 = .TOS\n.getInt(.__VAR)\nsetprop $P0, \"__type__\", 
.TOS\nstore_lex -1, \"")
      .emit(.CURR)
      .emit("\", $P0\n")
  
      .NEXT
  
    _IS:
      bsr CollectWord
      .NEXT
  
    _SELF:
      .emit(".TOS = self\n")
      .emit(".PUSH\n")
      .NEXT
  
    _THROW:
      .emit(".POP\n")
      .emit("throw .TOS\n")
      .NEXT
  
    _OPEN:
      .NEXT
  
    _CLOSE:
      .NEXT
  
    _READLINE:
      .emit(".TOS = new .PerlString\n")
      .emit("readline $S0, .STDIN\n")
      .emit(".TOS = $S0\n")
      .emit(".PUSH\n")
      .NEXT
  
    _READ:
      .emit(".TOS = new .PerlString\n")
      .emit("read $S0, .STDIN\n")
      .emit(".TOS = $S0\n")
      .emit(".PUSH\n")
      .NEXT
  
    _PEEK:
      .NEXT
  
    _STAT:
      .NEXT
  
    _SEEK:
      .NEXT
  
    _TELL:
      .NEXT
  
    _PRINT:
      .emit(".POP\n")
      .emit("print .TOS\n")
      .NEXT
  
    _PRINTLN:
      .emit(".POP\n")
      .emit("print .TOS\n")
      .emit("print \"\\n\"\n")
      .NEXT
  
    _IF:
      inc .LEVEL
      .emit(".POP\n")
      .emit("unless .TOS, endif")
      $S0 = .LEVEL
      .emit($S0)
      .emit("\n")
    _ENDIF:
      .NEXT
  
    _ELSE:
    _ENDELSE:
      .NEXT
  
    _THEN:
      .emit("endif")
      $S0 = .LEVEL
      .emit($S0)
      .emit(":\n")
      dec .LEVEL
    _ENDTHEN:
      .NEXT
  
    _DO:
       bsr CollectWord
      inc .LEVEL
      .emit(".POP2\n")
      .emit("push .CSTACK, .NOS\n")
      .emit("push .CSTACK, .TOS\n")
      .emit("$P0 = new .PerlInt\nstore_lex -1, \"")
      .emit(.CURR)
      .emit("\", $P0\n")
      .emit("find_lex $P0, \"")
      .emit(.CURR)
      .emit("\"\nassign $P0, .TOS\n")
      save .CURR
  
      $P0 = new .PerlInt
      .getInt(.__VAR)
      setprop $P0, "__type__", .TOS
      store_lex -1, .CURR, $P0
  
      .emit("do")
      $S0 = .LEVEL
      .emit($S0)
      .emit(":\n")
    _ENDDO:
      .NEXT
  
    _LOOP:
      .emit("pop .TOS, .CSTACK\n")
      .emit("pop .NOS, .CSTACK\n")
      .emit("inc .TOS\n")
  
      restore .CURR
  
      .emit("find_lex $P0, \"")
      .emit(.CURR)
      .emit("\"\nassign $P0, .TOS\n")
      .emit("push .CSTACK, .NOS\n")
      .emit("push .CSTACK, .TOS\n")
      .emit("ne .TOS, .NOS,  do")
  
      $S0 = .LEVEL
  
      .emit($S0)
      .emit("\n")
      .emit("pop .TOS, .CSTACK\n")
      .emit("pop .NOS, .CSTACK\n")
  
      dec .LEVEL
    _ENDLOOP:
      .NEXT
  
    _PLOOP:
      .emit("pop .TOS, .CSTACK\n")
      .emit("pop .NOS, .CSTACK\n")
      .emit("pop $P0, .STACK\n")
      .emit(".TOS = .TOS + $P0\n")
  
      restore .CURR
  
      .emit("find_lex $P0, \"")
      .emit(.CURR)
      .emit("\"\nassign $P0, .TOS\n")
      .emit("push .CSTACK, .NOS\n")
      .emit("push .CSTACK, .TOS\n")
      .emit("ne .TOS, .NOS,  do")
  
      $S0 = .LEVEL
  
      .emit($S0)
      .emit("\n")
      .emit("pop .TOS, .CSTACK\n")
      .emit("pop .NOS, .CSTACK\n")
  
      dec .LEVEL
    _ENDPLOOP:
      .NEXT
  
    _FOR:
    _ENDFOR:
      .NEXT
  
    _NEXT:
    _ENDNEXT:
      .NEXT
  
  
    _NEW:
      .emit(".POP\n")
      .emit("$I0 = .TOS\n")
      .emit(".TOS = new $I0\n")
      .emit(".PUSH\n")
      .NEXT
  
    _EXECUTE:
      .emit(".POP\n")
      .emit(".SAVEM\n")
      .emit("invokecc .TOS\n")
      .emit(".RESTOREM\n")
      .NEXT
  
    _BIND:
      bsr CollectWord
      .emit(".POP\n")
      .emit("$S0 = \"_\"\n")
      .emit("fetchmethod $P0, .TOS, \"_")
      .emit(.CURR)
      .emit("\"\n")
      .emit(".SAVEM\n")
      .emit("invokecc $P0\n")
      .emit(".RESTOREM\n")
      .NEXT
  
  
    _FINDTYPE:
      .emit(".POP\n")
      .emit("$S0 = .TOS\n")
      .emit("find_type $I0, $S0\n")
      .emit(".TOS = $I0\n")
      .emit(".PUSH\n")
      .NEXT
  
    _DROP:
      .emit(".POP\n")
      .NEXT
  
    _DUP:
      .emit(".POP\n")
      .emit(".PUSH\n")
      .emit(".PUSH\n")
      .NEXT
  
    _DEPTH:
      .emit("$I0 = .STACK\n")
      .emit(".PUSHI($I0)\n")
      .NEXT
  
    _ADD:
      .emit(".POP2\n")
      .emit(".TOS = .NOS + .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _SUB:
      .emit(".POP2\n")
      .emit(".TOS = .NOS - .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _MUL:
      .emit(".POP2\n")
      .emit(".TOS = .NOS * .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _DIV:
      .emit(".POP2\n")
      .emit(".TOS = .NOS / .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _MOD:
      .emit(".POP2\n")
      .emit(".TOS = .NOS % .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _INC:
      .emit(".POP\n")
      .emit("inc .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _DEC:
      .emit(".POP\n")
      .emit("dec .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _CMP:
      .emit(".POP2\n")
      .emit("cmp $I0, .NOS, .TOS\n")
      .emit(".PUSHI($I0)\n")
      .NEXT
  
    _EQ:
      .emit(".__EQ\n")
      .NEXT
  
    _NE:
      .emit(".__NE")
      .NEXT
  
    _LT:
      .emit(".__LT")
      .NEXT
  
    _GT:
      .emit(".__GT")
      .NEXT
  
    _LE:
      .emit(".__LE")
      .NEXT
  
    _GE:
      .emit(".__GE")
      .NEXT
  
    _AND:
      .emit(".POP2\n")
      .emit("and .TOS, .NOS, .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _OR:
      .emit(".POP2\n")
      .emit("or .TOS, .NOS, .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _XOR:
      .emit(".POP2\n")
      .emit("xor .TOS, .NOS, .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  
    _NOT:
      .emit(".POP\n")
      .emit("not .TOS, .TOS\n")
      .emit(".PUSH\n")
      .NEXT
  .end
  
  
  
  
  1.1                  parrot/languages/parakeet/test.pk
  
  Index: test.pk
  ===================================================================
  
  # This is a comment in a test script for Parakeet.  Like shell
  # comments, they consume the whole line after the hash
  
  # 1 trace  # un/comment to toggle Parrot VM tracing (very verbose!)
             # You can sprinkle these anywhere to trace code.
             # Also useful are:
  
  # 1 seeing    # Dump PIR code during compilation
  # 1 debug     # Toggle Parrot VM debugging
  # 1 profile   # Toggle Parrot VM profiling
  # 1 bounds    # Toggle Parrot VM bounds checking
  # debug-init  # use to init debugger
  # debug-break # Break into debugger, seems to segfault on debug_break op for now.
  
  "Welcome!" println
  
  # You can inspect a word with 'see'
  
  # see println
  
  # Here is a simple function definition.
  
  func bob "bob" println end
  
  # now execute it.
  
  bob  # it prints the word "bob"
  
  # When you 'see' a function, it shows you the PIR source
  
  # see bob
  
  # Here is a simple class definition.  Methods are words bound to
  # objects.
  
  class A
    meth testMethod 1 end  # leaves an integer on stack
  end
  
  # Instances of classes are created with 'new'
  
  A new var a
  
  # Methods on objects are bound and called with '->'
  
  a -> testMethod println # print the integer left by testMethod
  
  # When you 'see' a class, it shows you the PIR source:
  
  see A
  
  # subclass and call base method
  
  class B
    extends A
  end
  
  B new var b
  b -> testMethod println
  
  # subclass and override base method
  
  class C 
    extends A
    meth testMethod 2 end
  end
  
  C new var c
  c -> testMethod println  # prints 2
  
  # another for multi-inheritance
  
  class X 
    meth xciting "exciting!" end
  end
  
  # multi-inheritance
  
  class D
    extends C 
    extends X
  end
  
  D new var d
  d -> testMethod println
  d -> xciting println
  
  # Some more boring tests:
   
  # 1 trace
  
  class TestWords
  
    meth testStack
      3 4 depth 2 == assert
      dup depth 3 == assert
      drop drop drop depth 0 == assert
      "Passed!" println
    end
  
    meth testMathWords
      2 2 + 4 == assert
      2 2 - 0 == assert
      2 2 * 4 == assert
      8 2 / 4 == assert
      2 8 % 2 == assert
      "Passed!" println
    end
  
    meth testCompareWords
      2 2 == 1 == assert
      2 2 != 0 == assert
      2 2 cmp 0 == assert
      "Passed!" println
    end
  
    # whitespace and newlines are meaningless in code
  
    meth testMathWordsUnreadable 2 2 + 4 == assert 2 2 - 0 == assert 2 2 * 4
    == assert 8 2 / 4 == assert 2 8 % 2 == assert 2 2 == 1 == assert 2 2
    != 0 == assert 2 2 cmp 0 == assert "Passed!" println end
  
    meth testBoolWords
      1 1 and 1 == assert
      0 0 and 0 == assert
      1 0 or 1 == assert
      1 0 xor 1 == assert
      1 not 0 == assert  
      0 not 1 == assert
      "Passed!" println
    end
  
    meth testOnStack     # ( 4 -- )
      4 == assert
      "Passed!" println
    end
  
    meth testDoLoop     # prints 0 to 3
      4 0 do i 
        i println 
      loop
      "Passed!" println
    end
  
    meth testLocalVars  # ( i i -- )
      var x
      var y
      x println
      y println
      99 var x
      x println
      "Passed!" println
    end
  
    meth testSelf
      self var z
      z -> testDoLoop
      "Passed!" println
    end
  
  end
  
  # create a new TestWords instance
  
  TestWords new var tests
  
  # now call individual test methods
  
  tests -> testStack
  tests -> testMathWords
  tests -> testCompareWords
  tests -> testMathWordsUnreadable
  tests -> testBoolWords
  4 tests -> testOnStack
  tests -> testDoLoop
  3 4 tests -> testLocalVars
  
  "Goodbye!" println
  
  
  
  

Reply via email to