Difference between revisions of "Running your first program"

From PROSE Programming Language - Wiki
Jump to: navigation, search
m
m
Line 419: Line 419:
  
 
For more examples of how to use the assembly language, follow the [[Short tour of PAL]].
 
For more examples of how to use the assembly language, follow the [[Short tour of PAL]].
 
== Headline text ==
 

Revision as of 11:45, 4 August 2010

Running your first PROSE program

In release 0.6.x, only the PROSE Assembly Language (PAL) is available, and then only a subset of those instructions. So be aware, it's very low-level programming at this time. To learn more about the PROSE Programming Language, visit http://prose.sourceforge.net.

The 'nxdump' program

The best program to try out first is copied below. This walks the nexus, which is the internal tree hierarchy, dumping out each object it finds.

    ~Module
    EQUS {[loft.util]}

    ._init
    func/def [main], &[.dump]
    local/rtn

    .dump
    stack/lock
    reg/load PUSH, (![.prose])
    obj/dump PEEK

    .loop
    reg/load P0, (PEEK)
    reg/jmpeq &[.loop_next], P0, NULL
    obj/dump P0
    reg/load P1, (P0)
    reg/jmpeq &[.loop], P1, NULL

    stack/push P1
    local/jmp &[.loop]

    .loop_next
    reg/clr PULL
    reg/jmpneq &[.loop], PEEK, LOCK
    stack/unlock
    func/rtn

Type in the above program (or copy and paste if you're feeling lazy), and save it as nxdump.pal. Assemble it into bytecode using the following command:

    $ prism nxdump

This command takes a source assembly file with a .pal suffix, and creates a bytecode file with a .pro suffix. To execute the bytecode file within the PROSE engine, simply pass it to the prose tool:

    $ prose nxdump
    .prose:objectClass=psContainer
    .prose:objectClass=top
    .prose:objectClass=psRoot
    .prose:pn=[prose]
    .prose:psVersion=[0.6.0]
    .prose.schema:objectClass=top
    .prose.schema:objectClass=psContainer
    .prose.schema:pn=[schema]
    .prose.schema.oc:objectClass=top
    .prose.schema.oc:objectClass=psContainer
    .prose.schema.oc:pn=[oc]
    .prose.schema.at:objectClass=top
    .prose.schema.at:objectClass=psContainer
    .prose.schema.at:pn=[at]
    .prose.io:objectClass=psContainer
    .prose.io:objectClass=top
    .prose.io:objectClass=psIOStream
    .prose.io:pn=[io]
    .prose.io:psStreamIn=[]
    .prose.io:psStreamOut=[]
    .prose.io:psStreamError=[]
    .prose.io:psStreamDebug=[]
    .prose.io:psByteStream=[]
    .prose.error:objectClass=top
    .prose.error:objectClass=psContainer
    .prose.error:pn=[error]
    .prose.error.sys:objectClass=top
    .prose.error.sys:objectClass=psContainer
    .prose.error.sys:pn=[sys]
    .prose.error.sys.BadDevice:objectClass=psContainer
    .prose.error.sys.BadDevice:objectClass=top
    .prose.error.sys.BadDevice:objectClass=psErrorType
    .prose.error.sys.BadDevice:pn=[BadDevice]
    .prose.error.sys.BadDevice:description=[No such device or address]
    .prose.error.sys.AlreadyExists:objectClass=psContainer
    .prose.error.sys.AlreadyExists:objectClass=top
    .prose.error.sys.AlreadyExists:objectClass=psErrorType
    .prose.error.sys.AlreadyExists:pn=[AlreadyExists]
    .prose.error.sys.AlreadyExists:description=[Entry already exists]
    .prose.error.sys.BadRegister:objectClass=psContainer
    .prose.error.sys.BadRegister:objectClass=top
    .prose.error.sys.BadRegister:objectClass=psErrorType
    .prose.error.sys.BadRegister:pn=[BadRegister]
    .prose.error.sys.BadRegister:description=[Unknown register code]
    .prose.error.sys.HiddenData:objectClass=psContainer
    .prose.error.sys.HiddenData:objectClass=top
    .prose.error.sys.HiddenData:objectClass=psErrorType
    .prose.error.sys.HiddenData:pn=[HiddenData]
    .prose.error.sys.HiddenData:description=[Operation not allowed on hidden data]
    .prose.error.sys.OutOfRange:objectClass=psContainer
    .prose.error.sys.OutOfRange:objectClass=top
    .prose.error.sys.OutOfRange:objectClass=psErrorType
    .prose.error.sys.OutOfRange:pn=[OutOfRange]
    .prose.error.sys.OutOfRange:description=[Number or index out of range]
    .prose.error.sys.SchemaError:objectClass=psContainer
    .prose.error.sys.SchemaError:objectClass=top
    .prose.error.sys.SchemaError:objectClass=psErrorType
    .prose.error.sys.SchemaError:pn=[SchemaError]
    .prose.error.sys.SchemaError:description=[Operation failed schema check]
    .prose.error.sys.StackNotFlushed:objectClass=psContainer
    .prose.error.sys.StackNotFlushed:objectClass=top
    .prose.error.sys.StackNotFlushed:objectClass=psErrorType
    .prose.error.sys.StackNotFlushed:pn=[StackNotFlushed]
    .prose.error.sys.StackNotFlushed:description=[Stack not flushed]
    .prose.error.sys.OutOfMemory:objectClass=psContainer
    .prose.error.sys.OutOfMemory:objectClass=top
    .prose.error.sys.OutOfMemory:objectClass=psErrorType
    .prose.error.sys.OutOfMemory:pn=[OutOfMemory]
    .prose.error.sys.OutOfMemory:description=[Out of memory]
    .prose.error.sys.StackNotLocked:objectClass=psContainer
    .prose.error.sys.StackNotLocked:objectClass=top
    .prose.error.sys.StackNotLocked:objectClass=psErrorType
    .prose.error.sys.StackNotLocked:pn=[StackNotLocked]
    .prose.error.sys.StackNotLocked:description=[Stack lock marker not found]
    .prose.error.sys.TooManyLinks:objectClass=psContainer
    .prose.error.sys.TooManyLinks:objectClass=top
    .prose.error.sys.TooManyLinks:objectClass=psErrorType
    .prose.error.sys.TooManyLinks:pn=[TooManyLinks]
    .prose.error.sys.TooManyLinks:description=[Too many links]
    .prose.error.sys.AttributeEmpty:objectClass=psContainer
    .prose.error.sys.AttributeEmpty:objectClass=top
    .prose.error.sys.AttributeEmpty:objectClass=psErrorType
    .prose.error.sys.AttributeEmpty:pn=[AttributeEmpty]
    .prose.error.sys.AttributeEmpty:description=[Attribute data value is empty]
    .prose.error.sys.IoError:objectClass=psContainer
    .prose.error.sys.IoError:objectClass=top
    .prose.error.sys.IoError:objectClass=psErrorType
    .prose.error.sys.IoError:pn=[IoError]
    .prose.error.sys.IoError:description=[I/O error]
    .prose.error.sys.AccessDenied:objectClass=psContainer
    .prose.error.sys.AccessDenied:objectClass=top
    .prose.error.sys.AccessDenied:objectClass=psErrorType
    .prose.error.sys.AccessDenied:pn=[AccessDenied]
    .prose.error.sys.AccessDenied:description=[Permission denied]
    .prose.error.sys.IncompleteCode:objectClass=psContainer
    .prose.error.sys.IncompleteCode:objectClass=top
    .prose.error.sys.IncompleteCode:objectClass=psErrorType
    .prose.error.sys.IncompleteCode:pn=[IncompleteCode]
    .prose.error.sys.IncompleteCode:description=[Incomplete bytecode]
    .prose.error.sys.AttributeNotFound:objectClass=psContainer
    .prose.error.sys.AttributeNotFound:objectClass=top
    .prose.error.sys.AttributeNotFound:objectClass=psErrorType
    .prose.error.sys.AttributeNotFound:pn=[AttributeNotFound]
    .prose.error.sys.AttributeNotFound:description=[Attribute definition not found in schema]
    .prose.error.sys.NoEntry:objectClass=psContainer
    .prose.error.sys.NoEntry:objectClass=top
    .prose.error.sys.NoEntry:objectClass=psErrorType
    .prose.error.sys.NoEntry:pn=[NoEntry]
    .prose.error.sys.NoEntry:description=[No such entry or object]
    .prose.error.sys.StringsFull:objectClass=psContainer
    .prose.error.sys.StringsFull:objectClass=top
    .prose.error.sys.StringsFull:objectClass=psErrorType
    .prose.error.sys.StringsFull:pn=[StringsFull]
    .prose.error.sys.StringsFull:description=[No space left in string table]
    .prose.error.sys.DataFull:objectClass=psContainer
    .prose.error.sys.DataFull:objectClass=top
    .prose.error.sys.DataFull:objectClass=psErrorType
    .prose.error.sys.DataFull:pn=[DataFull]
    .prose.error.sys.DataFull:description=[No space left in data segment table]
    .prose.error.sys.StackFull:objectClass=psContainer
    .prose.error.sys.StackFull:objectClass=top
    .prose.error.sys.StackFull:objectClass=psErrorType
    .prose.error.sys.StackFull:pn=[StackFull]
    .prose.error.sys.StackFull:description=[Stack overflow]
    .prose.error.sys.BadObject:objectClass=psContainer
    .prose.error.sys.BadObject:objectClass=top
    .prose.error.sys.BadObject:objectClass=psErrorType
    .prose.error.sys.BadObject:pn=[BadObject]
    .prose.error.sys.BadObject:description=[Operation not valid on this object]
    .prose.error.sys.ObjectHasChild:objectClass=psContainer
    .prose.error.sys.ObjectHasChild:objectClass=top
    .prose.error.sys.ObjectHasChild:objectClass=psErrorType
    .prose.error.sys.ObjectHasChild:pn=[ObjectHasChild]
    .prose.error.sys.ObjectHasChild:description=[Operation not valid on parent object]
    .prose.error.sys.GenericError:objectClass=psContainer
    .prose.error.sys.GenericError:objectClass=top
    .prose.error.sys.GenericError:objectClass=psErrorType
    .prose.error.sys.GenericError:pn=[GenericError]
    .prose.error.sys.BadAddress:objectClass=psContainer
    .prose.error.sys.BadAddress:objectClass=top
    .prose.error.sys.BadAddress:objectClass=psErrorType
    .prose.error.sys.BadAddress:pn=[BadAddress]
    .prose.error.sys.BadAddress:description=[Bad address or object]
    .prose.error.sys.BadOpcode:objectClass=psContainer
    .prose.error.sys.BadOpcode:objectClass=top
    .prose.error.sys.BadOpcode:objectClass=psErrorType
    .prose.error.sys.BadOpcode:pn=[BadOpcode]
    .prose.error.sys.BadOpcode:description=[Unknown opcode]
    .prose.error.sys.SiOverflow:objectClass=psContainer
    .prose.error.sys.SiOverflow:objectClass=top
    .prose.error.sys.SiOverflow:objectClass=psErrorType
    .prose.error.sys.SiOverflow:pn=[SiOverflow]
    .prose.error.sys.SiOverflow:description=[String index overflow]
    .prose.error.sys.ClassNotFound:objectClass=psContainer
    .prose.error.sys.ClassNotFound:objectClass=top
    .prose.error.sys.ClassNotFound:objectClass=psErrorType
    .prose.error.sys.ClassNotFound:pn=[ClassNotFound]
    .prose.error.sys.ClassNotFound:description=[Class definition not found in schema]
    .prose.error.sys.StackNoSpace:objectClass=psContainer
    .prose.error.sys.StackNoSpace:objectClass=top
    .prose.error.sys.StackNoSpace:objectClass=psErrorType
    .prose.error.sys.StackNoSpace:pn=[StackNoSpace]
    .prose.error.sys.StackNoSpace:description=[No space left in stack]
    .prose.error.sys.BadCode:objectClass=psContainer
    .prose.error.sys.BadCode:objectClass=top
    .prose.error.sys.BadCode:objectClass=psErrorType
    .prose.error.sys.BadCode:pn=[BadCode]
    .prose.error.sys.BadCode:description=[Invalid bytecode]
    .prose.error.sys.ValueTooBig:objectClass=psContainer
    .prose.error.sys.ValueTooBig:objectClass=top
    .prose.error.sys.ValueTooBig:objectClass=psErrorType
    .prose.error.sys.ValueTooBig:pn=[ValueTooBig]
    .prose.error.sys.ValueTooBig:description=[Value too big]
    .prose.error.sys.StackEmpty:objectClass=psContainer
    .prose.error.sys.StackEmpty:objectClass=top
    .prose.error.sys.StackEmpty:objectClass=psErrorType
    .prose.error.sys.StackEmpty:pn=[StackEmpty]
    .prose.error.sys.StackEmpty:description=[Stack underflow]
    .prose.error.sys.HashNoSpace:objectClass=psContainer
    .prose.error.sys.HashNoSpace:objectClass=top
    .prose.error.sys.HashNoSpace:objectClass=psErrorType
    .prose.error.sys.HashNoSpace:pn=[HashNoSpace]
    .prose.error.sys.HashNoSpace:description=[No space left in hash table]
    .prose.error.sys.BadInstruction:objectClass=psContainer
    .prose.error.sys.BadInstruction:objectClass=top
    .prose.error.sys.BadInstruction:objectClass=psErrorType
    .prose.error.sys.BadInstruction:pn=[BadInstruction]
    .prose.error.sys.BadInstruction:description=[Unknown instruction]
    .prose.error.sys.NoSpace:objectClass=psContainer
    .prose.error.sys.NoSpace:objectClass=top
    .prose.error.sys.NoSpace:objectClass=psErrorType
    .prose.error.sys.NoSpace:pn=[NoSpace]
    .prose.error.sys.NoSpace:description=[No space left]
    .prose.error.sys.VectorNoSpace:objectClass=psContainer
    .prose.error.sys.VectorNoSpace:objectClass=top
    .prose.error.sys.VectorNoSpace:objectClass=psErrorType
    .prose.error.sys.VectorNoSpace:pn=[VectorNoSpace]
    .prose.error.sys.VectorNoSpace:description=[No space left in vector]
    .prose.error.sys.NoPathEnt:objectClass=psContainer
    .prose.error.sys.NoPathEnt:objectClass=top
    .prose.error.sys.NoPathEnt:objectClass=psErrorType
    .prose.error.sys.NoPathEnt:pn=[NoPathEnt]
    .prose.error.sys.NoPathEnt:description=[Object not found in search path]
    .prose.error.sys.InvalidArgument:objectClass=psContainer
    .prose.error.sys.InvalidArgument:objectClass=top
    .prose.error.sys.InvalidArgument:objectClass=psErrorType
    .prose.error.sys.InvalidArgument:pn=[InvalidArgument]
    .prose.error.sys.InvalidArgument:description=[Invalid or missing argument]
    .prose.error.sys.ListNoSpace:objectClass=psContainer
    .prose.error.sys.ListNoSpace:objectClass=top
    .prose.error.sys.ListNoSpace:objectClass=psErrorType
    .prose.error.sys.ListNoSpace:pn=[ListNoSpace]
    .prose.error.sys.ListNoSpace:description=[No space left in linked list]
    .prose.error.sys.ArchTooBig:objectClass=psContainer
    .prose.error.sys.ArchTooBig:objectClass=top
    .prose.error.sys.ArchTooBig:objectClass=psErrorType
    .prose.error.sys.ArchTooBig:pn=[ArchTooBig]
    .prose.error.sys.ArchTooBig:description=[Address too big for this architecture]
    .prose.error.sys.NoSupport:objectClass=psContainer
    .prose.error.sys.NoSupport:objectClass=top
    .prose.error.sys.NoSupport:objectClass=psErrorType
    .prose.error.sys.NoSupport:pn=[NoSupport]
    .prose.error.sys.NoSupport:description=[Operation or data type not supported]
    .prose.error.sys.StackLocked:objectClass=psContainer
    .prose.error.sys.StackLocked:objectClass=top
    .prose.error.sys.StackLocked:objectClass=psErrorType
    .prose.error.sys.StackLocked:pn=[StackLocked]
    .prose.error.sys.StackLocked:description=[Stack is locked]
    .prose.code:objectClass=top
    .prose.code:objectClass=psContainer
    .prose.code:pn=[code]
    .prose.code.sys:objectClass=top
    .prose.code.sys:objectClass=psContainer
    .prose.code.sys:pn=[sys]
    .prose.code.loft:objectClass=top
    .prose.code.loft:objectClass=psContainer
    .prose.code.loft:pn=[loft]
    .prose.code.loft.util:objectClass=psContainer
    .prose.code.loft.util:objectClass=top
    .prose.code.loft.util:objectClass=psModule
    .prose.code.loft.util:pn=[util]
    .prose.code.loft.util:psObjectFileId=[mb.pro]
    .prose.code.loft.util.main:objectClass=psContainer
    .prose.code.loft.util.main:objectClass=top
    .prose.code.loft.util.main:objectClass=psFunction
    .prose.code.loft.util.main:pn=[main]
    .prose.code.loft.util.main:psObjectFileRd=[mb.pro]
    .prose.code.loft.util.main:psObjectCodeRef=[0x0006]
    .prose.code.loft.util.main:psModuleRoot=[.prose.code.loft.util]
    .prose.code.loft.util.main._i0#0:objectClass=psContainer
    .prose.code.loft.util.main._i0#0:objectClass=top
    .prose.code.loft.util.main._i0#0:objectClass=psInstance
    .prose.code.loft.util.main._i0#0:pn=[_i0#0]
    .prose.code.loft.util.main._i0#0:psWalker=[.prose]
    .prose.code.loft.util.main._i0#0:psWalker=[.prose.code]
    .prose.code.loft.util.main._i0#0:psWalker=[.prose.code.loft]
    .prose.code.loft.util.main._i0#0:psWalker=[.prose.code.loft.util]
    .prose.code.loft.util.main._i0#0:psWalker=[.prose.code.loft.util.main]
    .prose.code._tid:objectClass=top
    .prose.code._tid:objectClass=psContainer
    .prose.code._tid:pn=[_tid]
    .prose.code._tid.0:objectClass=psContainer
    .prose.code._tid.0:objectClass=top
    .prose.code._tid.0:objectClass=psThread
    .prose.code._tid.0:pn=[0]
    .prose.code._tid.0:psRunningObject=[.prose.code.loft.util.main]
    .prose.code._tid.0:psStackSize=[4]

Analysing the output of this program will tell you something about the way the PROSE engine structures its data. Each line takes the format object:objectClass=class or object:attribute=[value] where object is the address of the node in the nexus, class is the name of a class assigned to that object, attribute is the name of an attribute assigned to the object and value is the value assigned to the attribute.

Understanding how the program works is left as an exercise for the reader. I suggest you start with man pal_intro.

You can't view the bytecode file in a text editor, because it's in a binary format. However, you can reverse engineer it if you like. The prism tool also allows you to view the sections inside a bytecode file, or disassemble it (i.e. put it back into human-readable symbols). These tasks are achieved as follows:

    $ prism -v nxdump
    ------------------------------------------------------------
    PROSE HEADER
      File: nxdump.pro
      Size: 169 bytes
      Compiled by: prism
      Compiler version code: 0.6.0
      Compile date: Wed Sep 30 11:49:17 2009
    ------------------------------------------------------------
    INSTRUCTION CODE

      000000 :  c0 4c 01 5c 03 c8 84 d0   1e 48 02 91 1c d0 00 1c
      000010 :  cb 5c 13 00 1f 91 00 d0   01 00 cb 5d 0e 01 1f 81
      000020 :  01 c6 5d 15 d1 1d cc 5d   1a 1c 1a 85 c3

      Size: 45 bytes
    ------------------------------------------------------------
    CODE LABELS

      idx 000000 len 000005 [_init]
      idx 000001 len 000004 [dump]
      idx 000002 len 000004 [loop]
      idx 000003 len 000009 [loop_next]

      Size: 30 bytes
    ------------------------------------------------------------
    CODE ADDRESSES

      idx 000000 ref 000000
      idx 000001 ref 000006
      idx 000002 ref 00000d
      idx 000003 ref 000024

      Size: 4 bytes
    ------------------------------------------------------------
    TEXT DATA

      idx 000000 len 000009 [loft.util]
      idx 000001 len 000004 [main]
      idx 000002 len 000006 [.prose]

      Size: 25 bytes
    ------------------------------------------------------------
    DATA LABELS

      idx 000000 len 000006 [Module]

      Size: 8 bytes
    ------------------------------------------------------------
    DATA XREF TABLE

      idx 000000 ref 000000

      Size: 1 bytes
    ------------------------------------------------------------
    DATA SEGMENTS

      idx 000000 len 000002 {
            80 80                                             ..
      }

      Size: 3 bytes
    ------------------------------------------------------------
    END OF FILE
    $ prism -d nxdump
    ~Module
      EQUS { [sys.tools] }

    ._init
      func/def [nxdump], &[.dump]
      local/rtn
    .dump
      stack/lock
      reg/load PUSH, (![.prose])
      obj/dump PEEK
    .loop
      reg/load P0, (PEEK)
      reg/jmpeq &[.loop_next], P0, NULL
      obj/dump P0
      reg/load P1, (P0)
      reg/jmpeq &[.loop], P1, NULL
      stack/push P1
      local/jmp &[.loop]
    .loop_next
      reg/clr PULL
      reg/jmpneq &[.loop], PEEK, LOCK
      stack/unlock
      func/rtn

Where to go next

For more examples of how to use the assembly language, follow the Short tour of PAL.