Jun
05
2009

Designing code: Statements

Note: this is the second part of in a group of 3.

imageAll the different statement types, the general neuron types, some common static neurons, all the operators and the instructions can be accessed from the toolbox. You can easily drag and drop them on the editor.

Assignment

image

An assignment is used to assign one or more neurons to a variable. After the operation, the variable will reference the result of the right part of the assignment. The left part must always be a variable: regular or global, but no system variables are allowed.  What exactly is assigned to the left part, depends on the type of the right part.

  • If it is another variable, the contents of the right part are assigned to the left part.
  • It can also be a result statement, in which case the statement is executed and it’s result is assigned to the variable.
  • ByRef statements are also resolved: the content of the ByRef statement will be assigned to the variable. This is useful if you want to assign a variable or a result statement to a variable and not it’s contents or results.
  • In all other cases, the right part is assigned to the left part, so if you put a code block in the right section, it will not executed, instead, the variable will point to the code block.

(Result) Statement

image

A statement is used to call an instruction and provide all the parameter values for this instruction. You can call any type of instruction with a statement, even those that return values, although that’s not very useful cause any result values are lost when used in a statement.

You select the instruction using the drop down box.  The instruction itself is also just another neuron, that the statement links to.  This has some consequences.  For instance, if you want to find all the statements that use a specific instruction, just check the incoming links on the instruction.

Most instructions require 1 or more arguments. The values for these arguments are displayed in a list that comes after the instruction. This is a regular drop list, like a code list. Each  instruction should have a little description (you can see/edit this in the description tool-frame if you select the instruction in the toolbox).  This description should say all the required arguments and any possible result values.

A result statement works similar to a normal statement, except that it return a value and tend to be used as part of another statement, like an assignment, a Boolean expression or as an argument value.  Result statements are depicted using the same template, but with a slightly different color to make a distinction.

Code block

image

A code block is used to group other statements together. This allows you to reuse common functionality.  It is a bit similar to a function in traditional programming languages (like C, Pascal,..), except that there are no arguments allowed and it doesn’t allow for local variable values (scope locality), see Variables for more info on this one. Internally, a code block stores all the statements in a cluster that is linked to the statement.

It is possible to see the statements of a code block inline, by using the expand button in front of the name.  Note that this can slow the editor down dramatically.  Better is to open the code block in a new editor frame (make certain that ‘Statements‘ tab is selected).  You can do this through the context menu’s ‘View code’ command (can also be triggered from the main toolbar). If you want to reuse a code block, you can simply drag it from the explorer frame to the editor.

Even though you define parameters on code blocks, it’s still possible to pass along argument values.  Because the content of a variable isn’t reset when a code block is called, you can create some Variables that function as parameters, fill them before you call the block and access them inside the subroutine.  The same can be done for result values, you can return as many as you want, simply  define some variables and assign a value to them in your code block.

Conditional statement and it’s parts

A conditional statement is used by the processor to perform execution jumps (if, case, while, foreach,…).  Each conditional should contain at least 1 conditional part, but can have more. This depends on how it is set up. You add parts by dropping them in the ‘Children’ section of the UI element (which moves to the right).  You can also move them around, just make certain that the entire part is selected, and not just the ‘conditional’ section. When correctly selected, the part will have a selection border.

Visually, a conditional statement is always represented as a horizontal split in the vertical code branch.  When there is a repetition in the statement (for-each, looped, until, case-looped), 2 vertical lines are also visible, making the conditional statement boxed in. This is an easy visual queue to identify repetitions (so you can have a bit of a birds eye on the code to see the structure, without the details).

There are currently 5 different types of conditional statements (which can be selected from the drop down box): these are:

If statement

image

An ‘If’ statement can be compared with a structural language’s if statement. It can contain multiple parts, with only the last one allowed to have no condition. The first part who’s condition evaluates to true will have it’s code executed, all other parts are skipped from then on (so there is no fall through possible like in C’s case statement). After all the code in the part has been executed, the next statement after the if is performed, so there is no repetition in this type of conditional.

Adding statements to a part is done by dropping them in the ‘children’ section of the UI element. Because a condition must evaluate to either true or false, a Bool expression tends to be used, but a result statement can also be used. Simply drop an item in the ‘condition’ section.

Case statement

image

The case statement is, like the ‘if’ statement, very similar to it’s structural equivalent: the content of a value is compared against a number of different possibilities.  Each possibility is provided through the ‘condition’ of the part, which can be a static or another statement that returns a result. Only the last part can be empty, which will be executed if none of the previous values matched the variable.  An empty part is not required though. There is no fall through possible (unlike the switch in C).

When you select this type of conditional statement, the UI element will display an extra drop target for you to specify the variable  who’s content needs to be checked.  This has to be a variable (or global).

Looped statement

image

A looped conditional is comparable with  the ‘while’ statement, but with a twist: it is possible to define multiple parts.  It’s actually a bit like C’s while and if combined. The loop will run for as long as the condition in one of the parts evaluates to true.  Like the if statement, this part’s sub-statements will be executed.  The last part doesn’t require a condition, in that case, the loop will run for ever and will only stop when a break or one of the exit instructions is called. These instructions will always terminate a loop. If there  is no ‘empty part, the loop will stop when none of the conditions evaluates to true.

Until statement

The until conditional is similar to the looped variant in that it is repetitive, but it only allows 1 part that must always have a condition which is evaluated after all the sub statements have been executed.  When the condition evaluates to true, the repetition is stopped. This type of conditional is very similar with C’s do until loops.

Case looped statement

This conditional is a looped statement, but instead of using an ‘if’ kind of testing style, a case is used. This means that you need to provide an extra case item variable, like the case statement. The statement will loop for as long as a condition in one of the parts equals to the content of the case variable. The conditions in the parts should be static values, result statements, ByRefs, bool expression, variables or globals (so anything that can return a result). You can also specify an empty condition in the last part which will be activated if all of the other parts were different than the case variable.  This results in a never ending loop, which will only stop when the break or one of the exit instructions is called.

The case looped statement is a bit of a strange beast.  It’s origins can be traced back to Gene, where it made a lot of sense for parsing or generating stream.  Id don’t know if it’s useful in this context, so I simply left it in, you never know where this might end up: could be the dumpster, could be some cool trick.

For each statement

image

This type of conditional statement can probably best be compared to C#’s ForEach loop: it executes a peace of code for each neuron  in a list. Only 1 part is allowed. It’s condition should be a statement that returns some neurons.  This can be a variable or global that contains multiple items, or a result-statement that returns a number of items, like the one that returns all the children of a cluster.

When this type of conditional is selected, an extra drop target is visualized, which should reference a variable (or global) that will receive the current item from the list, as it’s content. This allows you to reference the loop item from within  the subroutine.  After the loop is done, this will still reference the last item in the list.

Bool expression

image

A Boolean expression is evaluated to the ‘True’ or ‘False’ neurons. It can be used as a conditional part’s condition. The left part is compared with the right part, using the specified operator. This statement type is probably recognizable from more classical programming languages.  There are a couple of important twists to this type of statement though:

First of all, because the operator is also a neuron, it can just as well be another result statement, or variable.   As long as you have something that can be evaluated to 1 or more operators, it’s ok. And this brings us to the second wrinkle:

Because variables, globals and result statements can return a list of neurons, so that the left, operator and/or right sides can have multiple items, the expression evaluates the lists using the following algorithm:

  • If the left part has no result (no neurons) and all the operators are all ‘!=’ and the right side is not empty, true is returned, otherwise false.
  • Otherwise: for all items in the left part, compare each item in the right using every operator.

Note, when there are multiple operators, it is like having an ‘and’ operator for conditions that work with the same left and right side, but different operators.  This will probably not be used a lot (I haven’t yet).  It’s just a result of the structure, so I let it be available.

All the operators are represented by statically declared neurons (so you can’t add your own). Most are recognizable from classical programming languages like C(++). You have:

==   equal
<   less than
<=   less or equal than
>   more than
>=   more or equal than
!=   different
||   logical or
&&   logical and
contains   contained in the child or clustered-by list

image

The ‘Contains’ operator is a bit different. First of, there is no equivalent in traditional programming languages and it  requires a little more information to work properly: it needs to know which list to search: in the child list (in which case the left part should be a cluster),  or in the clustered-by list, which contains all the clusters that contain the neuron (this list is available in every neuron type, so the left part can be any type).

There is no operator precedence defined as in most traditional languages, since it is the structure of the neurons that defines the order.  This is visually verifiable by the statement’s container: first the left part is evaluated, next the operator and finally the right part.  If left or right has a sub bool expression, this is recursively repeated.

Search expression

This type of statement has already become deprecated. It’s been surpassed by the instructions, which provide more functionality and flexibility.  Nothing more to say about this, I guess.

Variable

imageA variable is a neuron that is able to store a reference to other neurons in the context of a processor. That is to  say, the content of a variable is only valid for as long as the processor running the code is still alive.  The contents of a variable can also be different for each processor. It will also be reset after the processor has completed evaluating all the links on a neuron and when a split callback function is called (scope locality).

A variable doesn’t have an initial value by default. It is possible to provide one though.  You need to unfold the drop location to make it accessible. This value can be another result statement, variable, global byref, or bool expression, in which case it is first resolved. In all other cases, the value is treated as a static.

Global

image

A global is similar to a variable, except that it has a different scope.  Globals are able to retain the same value for as long as the processor is alive while normal variables are reset at different times during the execution process of a processor. This is useful to pass along data generated during the execution of one link to another one.

Globals are also able to define what should happen during a split operation.  Possible values are:

  • Empty: clear all values from the global in the new processors
  • Duplicate: create duplicates from the content of the globals. A duplicate is a neuron with the same incoming and outgoing links, same value (in case of Int-, double- and Text-Neurons) and same children, but a different ID and not clustered by any item (so the clustered-by list is not duplicated, cause the clusters don’t get new neurons added because of a split).
  • Copy: simply copy the content of the global to the new processors.

ByRef

image

The ByRef statement can best be compared with C’s ‘&’ operator, but instead of getting the address of the memory location, in a neural network, it prevents a statement that return a result (like a variable, result statement, bool expression) from calculating that result, but instead returns the statement itself.

Although this statement probably wont be used that much, it is very important for the split instruction to work properly, since this requires a variable neuron as one of it’s arguments.  Often, this statement is the only way to provide this value.  There are other situations where this statement can be used, but less often.

Lock

image (Added 11/July/2010) The lock is used to combine a number of statements into a single  unit of execution, relative to 1 or more neurons and/or links. This statement can best be compared with C#’s lock keyword. When you lock a link, you need to specify from and to, but not the meaning, so each link lock actually requires 2 neurons to lock.

When you lock a neuron, the entire object is locked: incoming and outgoing links, value, parent cluster list and children. When you lock a link, only the incoming or outgoing section of the neuron is locked. This is important to keep in mind, if the locked items are operated on from other processors.

Don’t use the ‘duplicate’ instruction or perform any splits (with the split instruction) inside the lock. Although technically possible and allowed, it is not advised since this can and probably will cause deadlocks. Any object that needs to be duplicated during a split and which references the locked object, will cause the network the hang in a deadlock (although you can still terminate all the processors from the designer).

This concludes the overview of all the different statements.  Up next, some tips and tricks.

tags: , ,
posted in Getting started, N²D by admin

Follow comments via the RSS Feed | Leave a comment | Trackback URL

Leave Your Comment

 
Powered by Wordpress and MySQL. Theme by openark.org