Difference between revisions of "Running your first program"
m |
m |
||
Line 1: | Line 1: | ||
− | |||
− | |||
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. | 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. | ||
Revision as of 11:46, 4 August 2010
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.