Basic I/O

From PROSE Programming Language - Wiki
Revision as of 13:52, 4 August 2010 by Cambridge (Talk | contribs)

Jump to: navigation, search

PAL Tutorial - Basic I/O

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.

It is suggested you begin with the following articles before attempting this tutorial.

  • Introduction to PROSE
  • Quick start guide
  • Running your first program
  • Short tour of PAL

A full list of available tutorials for the PROSE Assembly Language can be found on the tutorials index page.

This tutorial discusses basic I/O features.

The basics

Basic input/output (I/O) can be achieved in the PROSE Assembly Language by reading and writing to a special object in the nexus called .prose.io. This object has a number of attributes:

  • psStreamIn to read from standard input
  • psStreamOut to write to standard output
  • psStreamError to write to standard error
  • psStreamDebug to write to standard debug
  • psByteStream to read binary data from standard input

The standard input stream will take user input unless a file has been redirected into the input when the PROSE engine is executed. The standard output stream will send buffered output to the display unless the output has been redirected to a file. The standard error stream will send unbuffered output to the display unless the error channel has been redirected to a file. The standard debug stream at this time is the same as the error stream, although in future releases of PROSE this will change to be a dedicated channel for debug information.

Assembling and executing the obj/dump ![.prose.io] instruction will show the structure of the .prose.io object. Here is a sample assembly file:

    ._init
    obj/dump ![.prose.io]

Once assembled and executed the output of the above example is:

   .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: no main() function found, nothing to do

Here you can see that the .prose.io object has three classes (top, psContainer and psIOStream) and six attributes (pn, psStreamIn, psStreamOut, psStreamError, psStreamDebug and psByteStream).

To read from standard input, use the attr/copy or attr/direct instructions, as if copying the value of the psStreamIn attribute. This will read one line at a time and will strip carriage returns (ASCII 12). Alternatively using the psByteStream attribute will read all input until exhausted ignoring newlines, and will preserve carriage returns.

To write to any of the output channels, use the attr/mod or attr/direct instructions, as if modifying the value of the output attribute.

The following example, once assembled and executed, sends the text Hello, world! to the standard output. Note that, as in C, newlines must be explicitly requested using the escape code \n.

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

    .main
    attr/mod ![.prose.io], [psStreamOut], [Hello, world!\n]
    func/rtn

Copying input to output

To write a program that copies standard input and sends it to standard output requires the use of the attr/direct instruction. This instruction is used for copying an attribute value from one object to another. Once the input is exhausted the error .prose.error.sys.AttributeEmpty will be generated, so it will be necessary to catch this:

    %
    % Reads data from stdin and writes to stdout
    %
    ._init
    func/def [main], &[.main]
    local/rtn

    .main
    error/jmp &[.trap], ![.prose.error.sys.AttributeEmpty]

For efficiency, we should then pre-load registers with pointers to the .prose.io object as well as the psStreamIn and psStreamOut attribute definitions before we enter a read/write loop. We don't want to lookup this information in each iteration of the loop, because it is an unnecessary overhead:

    reg/load P0, ![.prose.io]
    attr/load P1, [psStreamIn], P2, [psStreamOut]

Now we enter a loop copying the attribute value identified by register P1 (psStreamIn) to the attribute identified by P2 (psStreamOut):

    .loop
    attr/direct P0, P2, P0, P1
    local/jmp &[.loop]

This would appear to be an infinite loop, but once input is exhausted the AttributeEmpty error is thrown which triggers our error trap:

    .trap
    error/clr
    func/rtn

Once assembled, try directing a file into the standard input and you should see the contents of that file sent to standard output. In the example below the source code was saved as cat.pal, and the assembled bytecode is called cat.pro:

    $ prose cat < /etc/passwd

Resources from this tutorial

Further reading

See the other tutorials available for the PROSE Assembly Language on the tutorials index page.

PROSE is released with detailed manual pages that describe how PAL operates, and how each instruction is used. These manual pages can be read using the man command, for example man pal_intro or man pal_commands, or from the project links on the main page of this wiki.