Running your first program
In release 0.9.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.9.0] .prose:psEnableExtraDebug=[FALSE] .prose:psEnableRegScan=[TRUE] .prose:psWithMemWatch=[FALSE] .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.sys:objectClass=top .prose.sys:objectClass=psContainer .prose.sys:pn=[sys] .prose.sys.io:objectClass=psContainer .prose.sys.io:objectClass=top .prose.sys.io:objectClass=psIOStream .prose.sys.io:pn=[io] .prose.sys.io:psStreamIn=[] .prose.sys.io:psStreamOut=[] .prose.sys.io:psStreamError=[] .prose.sys.io:psStreamDebug=[] .prose.sys.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.Mismatch:objectClass=psContainer .prose.error.sys.Mismatch:objectClass=top .prose.error.sys.Mismatch:objectClass=psErrorType .prose.error.sys.Mismatch:pn=[Mismatch] .prose.error.sys.Mismatch:description=[Argument or array index mismatch] .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.TooManyArgs:objectClass=psContainer .prose.error.sys.TooManyArgs:objectClass=top .prose.error.sys.TooManyArgs:objectClass=psErrorType .prose.error.sys.TooManyArgs:pn=[TooManyArgs] .prose.error.sys.TooManyArgs:description=[Too many arguments] .prose.error.sys.BadNumber:objectClass=psContainer .prose.error.sys.BadNumber:objectClass=top .prose.error.sys.BadNumber:objectClass=psErrorType .prose.error.sys.BadNumber:pn=[BadNumber] .prose.error.sys.BadNumber:description=[Bad number] .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.BadStack:objectClass=psContainer .prose.error.sys.BadStack:objectClass=top .prose.error.sys.BadStack:objectClass=psErrorType .prose.error.sys.BadStack:pn=[BadStack] .prose.error.sys.BadStack:description=[Illegal stack operation] .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.BadPointer:objectClass=psContainer .prose.error.sys.BadPointer:objectClass=top .prose.error.sys.BadPointer:objectClass=psErrorType .prose.error.sys.BadPointer:pn=[BadPointer] .prose.error.sys.BadPointer:description=[Pointer does not match target type] .prose.error.sys.TypeNoSupport:objectClass=psContainer .prose.error.sys.TypeNoSupport:objectClass=top .prose.error.sys.TypeNoSupport:objectClass=psErrorType .prose.error.sys.TypeNoSupport:pn=[TypeNoSupport] .prose.error.sys.TypeNoSupport:description=[Data type not supported] .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.BadReturn:objectClass=psContainer .prose.error.sys.BadReturn:objectClass=top .prose.error.sys.BadReturn:objectClass=psErrorType .prose.error.sys.BadReturn:pn=[BadReturn] .prose.error.sys.BadReturn:description=[Return type does not match function definition] .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.AttributeMulti:objectClass=psContainer .prose.error.sys.AttributeMulti:objectClass=top .prose.error.sys.AttributeMulti:objectClass=psErrorType .prose.error.sys.AttributeMulti:pn=[AttributeMulti] .prose.error.sys.AttributeMulti:description=[Operation not valid on a multi-value attribute] .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.BadList:objectClass=psContainer .prose.error.sys.BadList:objectClass=top .prose.error.sys.BadList:objectClass=psErrorType .prose.error.sys.BadList:pn=[BadList] .prose.error.sys.BadList:description=[List contains invalid entries] .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.ModuleData:objectClass=psContainer .prose.error.sys.ModuleData:objectClass=top .prose.error.sys.ModuleData:objectClass=psErrorType .prose.error.sys.ModuleData:pn=[ModuleData] .prose.error.sys.ModuleData:description=[Module returned illegal data] .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.OpNoSupport:objectClass=psContainer .prose.error.sys.OpNoSupport:objectClass=top .prose.error.sys.OpNoSupport:objectClass=psErrorType .prose.error.sys.OpNoSupport:pn=[OpNoSupport] .prose.error.sys.OpNoSupport:description=[Operation not supported] .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.RegisterViolation:objectClass=psContainer .prose.error.sys.RegisterViolation:objectClass=top .prose.error.sys.RegisterViolation:objectClass=psErrorType .prose.error.sys.RegisterViolation:pn=[RegisterViolation] .prose.error.sys.RegisterViolation:description=[Pointer overwrite without clear register] .prose.error.sys.DivideByZero:objectClass=psContainer .prose.error.sys.DivideByZero:objectClass=top .prose.error.sys.DivideByZero:objectClass=psErrorType .prose.error.sys.DivideByZero:pn=[DivideByZero] .prose.error.sys.DivideByZero:description=[Divide by zero] .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.error.sys.RegisterDuplication:objectClass=psContainer .prose.error.sys.RegisterDuplication:objectClass=top .prose.error.sys.RegisterDuplication:objectClass=psErrorType .prose.error.sys.RegisterDuplication:pn=[RegisterDuplication] .prose.error.sys.RegisterDuplication:description=[Register or parameter duplication] .prose.error.sys.OutOfBounds:objectClass=psContainer .prose.error.sys.OutOfBounds:objectClass=top .prose.error.sys.OutOfBounds:objectClass=psErrorType .prose.error.sys.OutOfBounds:pn=[OutOfBounds] .prose.error.sys.OutOfBounds:description=[Array index out of bounds] .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. 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: 167 bytes Compiled by: prism Compiler version code: 0.9.0 Compile date: Sat Mar 16 23:12:48 2013 ------------------------------------------------------------ INSTRUCTION CODE 000000 : c0 4c 01 5c 03 c6 84 d0 1e 48 02 8d 1c d0 00 1c 000010 : cd 5c 13 00 1f 8d 00 d0 01 00 cd 5d 0e 01 1f 81 000020 : 01 c5 5d 15 d1 1d cd 21 5d 1b 1c 1a 85 c2 Size: 46 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 { [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
Where to go next
For more examples of how to use the assembly language, follow the Short tour of PAL.