Tutorial: How to use Visual Zero VM

en español Lea este documento en español Zero (the plane fighter)

Visual Zero VM is the same virtual machine present in the command line tool zvm (Zero Virtual Machine), but adding a graphic user interface, which allows better interaction on the user's part, by means of the simple use of the structural reflection capabilities of Zero.

First of all, you should unzip the Zero bin package in a given directory, no matter which one (from now on, the Zero's directory), provided this has not been done before. Also, the standard library should be compiled. In order to do that, you should just open a console in the Zero's directory and type:

za IntStdLib

You can also try to drag and drop IntStdLib over the za executable. In some systems, it is needed to give execution permissions to some files:
chmod +x za
chmod +x zm
chmod +x zd
chmod +x zvm

Now you can try to compile the standard library again if the previous step didn't work.

The standard library must be compiled before using Zero: however, once it has been compiled this step won't be needed to be taken anymore.

The Visual Zero VM program is vzero.exe in Windows systems, which can be executed from command line by typing:

vzero

or by double-clicking the file in an explorer window showing the Zero's directory.

Beginning: basic concepts

Once started, Visual Zero VM shows the container explorer. Containers are similar to directories (or folders) or files, but storing objects instead of arhives. The container where all executions are carried out is the so called Exe, hanging directly form the Root container. In order to build a path through containers, the '.' must be used between two containers, as when an attribute is accessed through an object (Actually, containers are objects). The only exception to remember is that the root container doesn't have a name. For example, the path to get to the Exe container is .Exe.

intro to VZero VM

All possible values which one deal with inside the VM (Virtual Machine) are objects. In contrast to other VM's, there are not primitive values; primitive values are represented by objects as well. In the Zero VM, integer numbers, floating-point numbers, strings and vectors can be managed, again, represented by average objects.

In the picture above, some functionality of the main application window can be seen: the open folder allows the user to load containers in the system. The glass opens an object explorer, allowing you to explore the objects in the Exe container, initially.

The button in the lower left corner, labeled as Contenedor padre (parent container) makes possible to go upwards in the container's hierarchical relation graph. For example, from the Exe container the Root container would be shown by pressing this button.

The button labeled as nuevo (new) creates an object of the type shown by the combo box at its left. The possible types are: object (regular objects), integer, float, and vector.

Object creation

Under the container explorer there is a selection box and a button labeled as Nuevo (new). The list lets you choose among various different objects. This way, objeto lets you create a new average object; entero (integer) lets you create an integer number (a shortcut of sending the message copy to the object LiteralInt); flotante (float) lets you create a floating-point number; Cadena (string) lets you create a character string; Vector lets you create a vector of objects. Once the button nuevo is pressed, a dialog box is shown asking for some data. The name of the object in case of a regular one, or for example the numeric value to be represented by the object in case of choosing an integer or a float, or a text in case of a character string.

In case of choosing a vector to be created, the value to enter is a little bit more special.

Entering vector values

When vector is selected, and once nuevo is pressed, a dialog box asking for the contents of the new vector will be shown. The simplest vector is the empty one (o elements), which can be specified by typing the following:

{}

However, a vector of one element is specified with:

{ 1 }

making a vector of 1 elements (its size is 1) with an Int object of value 1. The index of this first value is 0.

When introducing various elements, they are separated by commas.

{ 1, 2, 3 }

The user must take into account that vectors can contain references to any object, it is not necessary to have all elements of the vector deriving of a given object. For example:

{ 1, "hello", 2.0 }

It is even possible to include other vectors:

{ 1, { 3, 4 }, 2.0 }

Erasing objects

Press the left button of the mouse over an object shown in the container explorer. Then press the right buton and choose eliminar (erase) from the list. Please note that this does only erase the object from the container ... if it is being referenced by other objects, it will remain in memory.

An exercise: persons and employees

Start the program and press nuevo, having objeto chosen in the list under the container explorer.

creating TraitsPersona

You will be asked for the name of the object. Please enter TraitsPersona (TraitsPerson). Then an object explorer will open, showing the properties of the new TraitsPersona object. The explorer is divided in three sections, up to down: attributes, inherited methods and methods.

TraitsPersona created

Look for addAttribute in the inherited methods section. Press the left button of the mouse over it, and then press the right button and choose ejecutar from the list.

executing addAttribute

A new dialog box will appear asking for the arguments the method will be invoked. In this case, we must provide the name of the attribute, and the object it will point to. The name of this new attribute is "nombre" (name), storing the name of the person. So this is the value for the first box, but in this case you have to enter it with double quotes, as it must be interpreted as a new String object. The contents of the attribute to be created is also a string, so for example "Juan Nadie" ("John Doe") will be an appropriate value. This way, the new objects will be created before invoking the method addAttribute with them. The last step is to press Aceptar, in order for the VM to execute the given method.

entering arguments for addAttribute

When a method is executed, the standard output is opened, as well as an object explorer with the properties of the object produced by the execution. In this case, they are not relevant, so both windows can be closed, going back to the TraitsPersona object explorer. The new attribute will appear in the list of attributes of the object, the one that appears at the top of the explorer. It is possible to doble-clic it (i.e., press the left button of the mouse quickly two times over it), in order to see the object it is pointing to.

The same steps taken for adding the nombre (name) attribute to the TraitsPersona object, can be taken in order to create the attribute "email" with its corresponding value (object) "Juan@nadie.com" ("john@doe.com"). Remember to use the doble-quote to express string objects.

A toString method for TraitsPersona would be really useful. This method exits in Object, the root of the inheritance hierarchy, returning the name of the object (or its value, provided it is an int, float, string, or even vector -a string with the result of executing the toString of each element-). For persons, it would be useful to return the most relevant information in a String.

So we need to create a method toString for TraitsPersona. This method will be tipically called when trying to print an object in standard output. In the Visual Zero VM, it is also a good way to obtain a summary of the data stored in the object.

Look for the method addMethod and select, by right-clicking it, the option ejecutar (execute) from the context menu. A dialog box similar to the one that was presented for the attributes will appear. This time, the name of the method, and a vector with the names of the attributes must be provided. The name of the method is "toString" (including the double quotes), and an emtpy vector {} must be entered for its arguments (the toString method doesn't need any).

entering arguments for addMethod (toString)

Once created (pressing the Aceptar button), the new method will appear in the methods section of the object explorer, the one at the middle of the window. We must enter its source code, so we enter the following Zero assembler (after double-clicking it):

SET nombre
ASG __rr

STR ": "
MSG __rr concat __acc
ASG __rr

SET email
MSG __rr concat __acc
ASG __rr
RET

This assembler code just assigns the object pointed by the nombre (name) attribute to the return reference register (__rr), and then concatenates the string literal ": ", followed by the string pointed by the attribute e.mail.

entering the toString body

Once it has been typed, the compilar button should be pressed, and almost immediately he message compilación realizada con éxito (compilation succesful) should appear on the screen.

The new method can be executed the same way any other one has been executed: the option execute of the context menu, once the method is right-clicked. Try it now, and you will obtain athe result as an object explorer of a String object containing:

Juan Nadie: juan@nadie.com

result of executing toString

... which you should discard (by closing its explorer). Now the new method has been verified.

It could be interesting to create a new pair of methods: setNombre (setName), with arguments { "n" }, and setEmail, with arguments { "e" }. Once created, introduce the following assembly code for each one:

method + setNombre( n )

SET n
ASG nombre
RET

method + setEmail( e )

SET e
ASG email
RET

argumentos para setNombre

This assembly code just assigns the objects passed as argument to the nombre and email attributes. We are assuming here that the objects received in these functions are strings containing the right information. At least, we could check whether the objects received are strings by placing the following instructions in-between the ASG and SET assembly instructions, in both methods:

IOF String
JOT assign
TRW ETypeMismatch
ETQ assign

With this new code, in case of receiving an object of the wrong "type", an exception is thrown. Please note that this exception throwing is not mandatory.

Now, using the controls below the container explorer of the main window, create a new object, called Persona.

creando Persona

Once created, please double-click it in order to make an object explorer to appear for it.

Persona creado

Select the parent attribute, and clicking it with the right button of the mouse, choose cambiar (change) from the contextual menu.

cambiar parent de Persona

Of the scrollable list in the assign object dialog, choose TraitsPersona, (TraitsPerson). Wiht this action, the prototype to be used in order to create new Persona (Person) objects has been created.

argumentos para cambiar parent de Persona

In order to create new person objects, just select the copy method of the inherited methods list for the object Persona. It will be needed to give the name of the new object, in double quotes. For an example of Person with one of the developers of Zero, the name could be personaBaltasar (baltasarPerson). Once created, the object will appear in an object explorer. It is not linked to any container, so it is going to be lost of the explorer is changed. You can make it part of the container, so this object will be more permanent. In order to achieve this, just press the button "Save in exe" on the top of the object explorer. It will appear in the container explorer.

Please note that it is possibe to avoid separating Persona and TraitsPersona, having only one object, say Persona. Each time an object was created, all methods and attributes would be copied at the same time, which would make the copy very expensive. With this separation, the methods exist in only one object (more or less similar to a class), while the state would be copied only each time a new object were created.

The object personaBaltasar has been created, though its attributes have not been set properly. In order to achieve this, both methods setEmail and setNombre should be called with the appropriate data, which is "jbgarcia@nospampofavo.uvigo.es" ("jbgarcia@nospamplease.uvigo.es") and "Baltasar", respectively.

It should be noted that attributes nombre and email are now part of the object personaBaltasar. This happens because while not modified they share the very same attributes with TraitsPersona, but as soon as they are modified a new instance of these attributes is created in the object. This technique is called "copy-on-write", which means that the duplication is done only when necessary.

Executing the method toString of personaBaltasar, the following is obtained:

Baltasar: jbgarcia@nospampofavo.uvigo.es

argumentos para cambiar parent de Persona

We could carry out now an exercise about inheritance. Please create a new object called TraitsEmpleado (TraitsEmployee), using the createChild method of the object TraitsPersona. This will create an empty object with its parent attribute pointing to TraitsPersona.

Create now the salario (salary) attribute, as described above (i.e., executing the method addAttribute), with value 0. This means that you have to give the name of the attribute, being "salario" (with double quotes), and 0 (without double quotes) as second argument.

Create the method setSalario (setSalary) by means of addMethod. Please give { "s" } as the vector of arguments for this method. Method's body should be completed as follows:

SET s
ASG salario
RET

Now, we can already create a new method toString for TraitsEmpleado:

MSG __this ^toString
ASG __rr

STR ", earns "
MSG __rr concat __acc
ASG __rr

MSG salario toString
MSG __rr concat __acc
ASG __rr
RET

Through the first message to __this (a register that stores a reference to the object which is executing the method), with ^toString, it is assured that the method of TraitsPersona will be called. If it were not done this way, a recursive call would be performed and would become and infinite loop.

Once we have the description of the info related to Persona, the salary must be concatenated, inserting the String ", earns" in-between.

A prototype object for employees must be created, now the traits object is ready. This can be done by simply creating a new object and changing its parent to point to TraitsEmpleado (TraitsEmployee), as explained previously. The same result can be achieved by invoking the method createChild on TraitsEmpleado.

It is now possible to experiment with dynamic inheritance. Open an object explorer for personaBaltasar and change its parent atttribute to point to TraitsEmpleado, instead of TraitsPersona. The information we had in our recently Persona instance is kept, but now can call also methods in TraitsEmpleado. For example, if setSalario is now executed, giving any amount, we will see through toString how this new information has been added to the object.

This change can be of course reverted, by simply changing again the parent attribute of personaBaltasar back to TraitsPersona. The salary information will still be there, though it won't be used for anything. This cna be checkde out by invoking its toString method.

A diagram showing the objects involved in this tutorial can be found below. The dotted line signals the parental relation changed from TraitsPersona to TraitsEmpleado.

diagrama de objetos


Tutorial: How to use Visual Zero
(c) 2005