Prograph: A Visual Programming Language - CiteSeerX
-
Upload
khangminh22 -
Category
Documents
-
view
1 -
download
0
Transcript of Prograph: A Visual Programming Language - CiteSeerX
Prograph: A Visual Programming Language
David Heise & Tomas Joyner
[email protected] [email protected]
EECS 330: Introduction to Programming Languages
Fall 2004
Visual Programming Languages:
For years, programmers have interacted with their computers via a command prompt.
Programs were run, and windows were opened, one line at a time. Then came the revolution.
When a GUI was applied to an operating system, things began to change. The visual
representation of file structures became more relevant. Navigating the system and its commands
became trivial. People who ten years before would not even approach the seemingly magical
box were now classified as “users”. As a direct result of the GUI upgrade, the computer has
become a staple in every home.
There is a similar tremor in the waters of the programming world. Often, when handed a
problem, a programmer first determines a sort of flow chart for the program's functionality. The
programmer must then translate the visual concept into textual code. This mapping typically
proves difficult due to “the use of a one-dimensional textual formalism to represent a multi-
dimensional process”[1]. The solution in the works is Visual Programming Languages. Like
Windows to DOS, so is Visual Programming to traditional text-based languages.
There has been theoretical work on Visual Programming since the late 60's. Some of the
thinking of yesteryear has come to fruition in the form of GPL, LabVIEW, APPWare, and
Prograph, among others.
A Brief History:
As with the creation of most Visual Programming Languages, Prograph was formed with
the intent of making programming easier for the programmer. Prograph graphically shows data
movement. In this respect it differs from languages such as C and Java, whose focus is on control
passing – that is, stepping through a series of commands.
Prograph was conceived in 1983 as the brainchild of Tomasz Pietrzykowski and Philip T.
Cox. While Pietrzykowski soon moved on to other projects, Cox stayed with the language
adding improvements over the years. In '85 Prograph was distributed with the additional feature
of a compiler. When Object-Oriented Programming became the big buzz, Cox announced the
advantages of Prograph's modularity and Object abilities.
Prograph hit the markets and was used for various applications, though primarily distributed
on the Macintosh. Games, HTML editors, and spreadsheets have all claimed primary usage of
the graphical language. Businesses also turned to Prograph for some in-house applications.
Today Prograph is dead. Programming software for Prograph is still existent, and sold, but
the language has grown stagnant. Pictorius, the primary distributor of Prograph (with Cox at the
head), went under in 1996.
The Prograph Language:
Prograph is a functional language. It's data flow can be
compared to Scheme's (or any other functional language) with
the primary difference that the programmer does not have to
keep track of parenthesis. Prograph use is simple: data is
represented with lines and methods are various boxes. Each box
contains nodes for inputs (terminals) and outputs (roots). Prograph methods have more than just
variable arity; they also have output arity. The methods have an I->O mapping from one or more
inputs (I) to one or more outputs (O).
Figure 1 – A Simple “Hello World” Program in Prograph
The data in Prograph is passed by value. This enables several methods the use of a single
output from another method. These receiving methods can then be run in parallel without one
method altering the data in another. This feature will find its usefulness if ever the von Neumann
model for parallel processing is upgraded to its more visionary counterparts.
Heretofore, method inputs and outputs have been referred to as data as opposed to
variables. Strictly speaking, Prograph does not have variables. Inputs and outputs are named
only as a convenience to the programmer. A consequences of this is lower overhead for a
method's environment (if there are no variables, there is no need for an environment). Scoping,
in this context, becomes irrelevant.
Object-Oriented Programming comes naturally
with Prograph's modularity. A class is defined just as
readily as a persistent, and is still visually expressive. A
class contains methods and variables. In this case,
variables are simply persistents with another name.
Inheritance is easily shown via a line from the parent
class to the child class.
Figure 2 – Classes and Inheritance. Classes a through e are depicted and inheritance is shown bottom to top (i.e. class e inherits from class c which inherits from class a)
Learning to use Prograph is time consuming. After getting acquainted with the graphical
nature of the language, the programmer must then prepare for the challenge associated with
learning the variety of constructs. On top of that, some universal constructs (such as
conditionals) have their own Prograph version that requires attention. The conditional, for
example, has 16 different possible implementations.
The greatest disadvantage of programming in Prograph is the challenge of all Visual
Programming Languages: spaghetti code. For a simple program with 15 methods, each with
three inputs and three outputs, the potential for readability loss is great. This difficulty is
overcome with experience. In practice, Prograph is quite readable (perhaps “viewable” would be
more descriptive).
Constructs and Syntax
In Prograph there exits 9 basic
constructs, 6 external constructs, 4 main
constructs, and 10 control constructs. These
constructs, in addition to the other symbols
and cases, provide the ability to program as
in any other language. The four main
constructs are named: section, universal,
class, and persistent. These are the overall
constructs that allow for creation of
programs. Sections consist of universals,
classes, and persistents. Universals are
methods (i.e. functions, procedures, subprograms). Classes, as in other languages, are data
structures that allow for the combining of data and the methods that operate on that data. Classes
consist of methods and fields. The class methods and fields are essentially the same as universals
and persistents respectively. Persistents are most similar to global variables in most other
languages; however their data persists from run-time to run-time such that the data retains its
value until changed or the entire process is destroyed.
Figure 3 – Some Prograph Constructs
Methods (whether class methods or universals) consist of the remaining 15 constructs.
The basic nine constructs are: simple, constant, match, persistent, instance, get, set, local, and
evaluate. These constructs provide for the main program execution and are at the heart of
Prograph. All of these constructs have some combination of terminals and roots. Not all
constructs have both or either, and a construct could have an arbitrary number of roots and/or
terminals. For example the + primitive has two terminals and one root (i.e. two inputs and one
output). Methods also have cases. All methods end with either a success, failure, or error
message. These messages provide the control logic for the constructs and make the cases
possible.
Cases are similar to the 'if-then-else' construct, and variations thereof, found in most
languages. When a method is initially called the first case is run, if, during the course of the first
case, a “next-case” control is found and applied then the second case of the method will be run.
The second case is called with the exact same inputs as the previous case. If no second case
exists, a run-time error is thrown. This is applicably recursive, in that the second case will call
the third case and so on.
Figure 4 – An iterative factorial program
Within a case of a method the nine basic constructs in conjunction with the control
operators provide the framework for programming. A simple construct, denoted by the rounded
corner rectangle, is simply a call to another method. There are five additional graphical
annotations to a simple, not including control symbols, which reveal additional information
about the method call. A bar under the method name indicates that the method call is to a
primitive. A bar over the method name indicates that it is to an external method call (i.e. from a
DLL, or external program of some sort). A single slash before the method name indicates that the
method is a class method and Prograph will determine the proper method to call from the
instance that is required as the leftmost root. A double slash before the method name indicates
that the method is context-determined thus, for instance, the method might be another method
within the same class. Also an up arrow next to the simple indicates that it is a call to a class
method of its parent class (i.e. super).
A Constant construct, denoted by the constant value with a bar and a root underneath,
allow for constants as in other languages. A Constant value can be any valid value and will be
automatically typed.
A Match construct, denoted by a terminal and bar over a constant value and nearly
always with a control construct to the right, allow for if statements. A match will attempt to see if
the data input is the same as the constant supplied. Depending on the control operation associated
with the match, they may do as the control indicates (controls will be discussed in further detail
later in this discussion).
Persistent constructs access the value of the persistent (i.e. global values). It has at most
one terminal and one root, to allow for both reading and writing to the persistent.
Instance constructs create an instance of the class. It has one terminal and one root. If no
values flow into the terminal then the class is initialized with no parameters, however the
permission of the terminal indicates that class constructors can take inputs.
Get and Set constructs allow for reading and writing of class attributes. Both constructs
take in an instance into its terminal, and an instance out of its root. The Get has an additional root
to provide for the data requested, and the Set has an additional terminal to provide for the storage
of the requested data in the requested attribute.
Local constructs allow for grouping of a section of code into a single graphical element.
This provides for a better view of the program as Locals allow for better space management of
the development environment, which is identical to the expensive silicon real estate in circuit
design.
The Evaluate construct provides mathematical expressions into the language. An
Evaluate has one root, and as many terminals as desired. The expression uses the alphabet (case
insensitive ‘a’ to ‘z’ only) as designations for terminals within the expression. For example the
expression “a/b+c” would have three terminals, starting on the left with a, then b in the middle,
and c on the right. The Evaluate will have as many terminals as letters used, however letters must
be used in alphabetical order (i.e. using the letter x will automatically make 24 terminals to the
Evaluate construct). The expression may contain the following mathematical operations: @
(exponentiation), + (binary and unary addition), - (binary and unary subtraction), *
(multiplication), / (floating point division), // (integer division), % (remainder from integer
division), & (bitwise AND), | (bitwise OR), ^ (bitwise XOR), ~ (unary bitwise NOT), << (bit
shift left), and >> (bit shift right).
The External constructs simply allow the Simple, Constant, Match, Persistent, Get, and
Set to reference external data stored in a DLL, etc. In addition to these there is also an External
Address construct that takes an external structure as input and returns a pointer to that structure.
The External Persistent is called External Global to point out the differences between a Prograph
Persistent and the idea of Global variables in other languages.
The Controls in Prograph allow for change of the control flow based on how constructs
terminate. The most common use of controls is on a Match construct. The logic for the control is
denoted by a check or an x beside the construct. Also a control will dictate what course of action
should be taken upon a successful check: Next Case, Terminate, Finish, Continue, and Fail. The
check indicates that it is true, while the x indicates it is not true. For example say we have a
Match named “STRING” with a check next to the name. If the input into the Match is also
“STRING” then it would do the appropriate action dictated by the control (i.e. Fail, Continue,
etc). The control action directs the program execution. The Next Case action will cause the
method to execute the next case with its current inputs and is depicted with a rounded box
around the check or x. The Terminate action will cause the method to immediately end execution
with a successful result and is depicted with rounded box and a bar above the check or x. The
Finish action will cause the method to complete the current case then immediately end execution
with a successful result and is depicted with a rounded box and a bar below the check or x. The
Fail action will halt the current method and send a fail signal to the calling method and is
depicted with a circle around the check or x. The Continue action will cause execution to
continue in the current case and is depicted with a rounded box and a bar above and a bar below
the check or x.
In addition to the aforementioned constructs, individual constructs can be connected by a
Datalink and/or a Syncro link. A Datalink connects a root and a terminal depicting flow of
information. It is this depiction and functionality that make Prograph a functional language. A
Syncro link directionally connects two constructs guaranteeing that start node will execute before
the end node. Since any construct could execute at any time (and is chosen randomly at design
time), the Syncro link provides a way to have the traditional
imperative execution to the degree chosen by the developer.
Other constructs not explained here include (but are not
limited to): Repeat annotations (construct is repeated until a fail,
terminate, or finish signal is sent), List annotation (construct will
apply itself to every member of the list), Loop annotations
(construct is repetitively called with the outputs sent as inputs to
otations (splitting a list based on Boolean criteria), and the Inject
control (allowing for the name of the operation to be supplied at run-time).
Figure 5 – Syncro Links; a will run before both b and
c; both b and c will run before d, but no guarantee
about the order of execution for b and c
the next iteration), Partition ann
ypesT
In Prograph there exist the following types: boolean, integer, list, none, null, point, real,
rectangle, rgb, string, and undefined. Boolean values are denoted and displayed as TRUE or
FALSE (case sensitive). Integers consist of traditional signed integers (2^32), a number of any
base (i.e. a binary number 2#10010101), and a 1, 2, or 4 byte ASCII character sequence. A list is
identical to a list in scheme or lisp with a limited number of elements (2^16 - 1 in the interpreter,
and 2^32 -1 in the complier). The none type is used by Prograph to depict a type when a terminal
is not connected to a datalink. The Null type indicates no value on a root or a class attribute. The
point type is two integers enclosed by curly brackets (“{}”) and separated by a space; it
represents the coordinates for a two dimensional point in space. Reals are the same as traditional
real numbers allowing for values from -1.1E+4932 to +1.1E+4932. A Rectangle type depicts the
coordinates for two points defining the upper left and lower right corners of a rectangle; this type
is like a point but with four values instead of two. The RBG type indicates a color denoted by the
red blue and green values that compose it; this is similar to a point but with three values. A string
in Prograph consists of any sequence of typeable characters limited in length to the same
constraints of the list type. Finally the undefined type is another internal type used by Prograph
when an operation/construct is skipped during execution.
Types may be specified on roots and terminals, but are not required. In addition to the
orem
onclusion
af entioned types, the specified type may also be: pointer, direct, a class name, a list of
types, or “<<>>” (which indicates that the type must be of the same class the method is in). For
more exact specifics on type definitions see the BNF of the data types in the appendices.
C
Like all languages, Prograph has its positive and negative aspects. It provides an easy
way to depict programs following a flow model, and the translation from flow chart to code is
very simple, as code is just as graphical as the flow chart. One of the biggest disadvantages of all
visual languages is the longer than normal learning curve that a programmer must go through
before becoming proficient in the language. Also to Prograph specifically, it is a dead language
in that it is not widely used and as a language is not being developed. However Prograph, with
other visual languages, provide for a new dimension to traditional programming not found
elsewhere.
Appendix A: Type BNF
<simple value> ::= <delimited value> | <default string> <string> ::= <quoted string> | <atomic string> | <default string> <default string> ::= any string which is not a <delimited value> <delimited value> ::= <quoted string> | <atomic string> | <integer> | <real>
| <boolean> | <null> | <undefined> | <none>| <list> | <simple ext>
<atomic string> ::= any <atom> other than FALSE, TRUE, NULL, UNDEFINED, or NONE
<boolean> ::= FALSE | TRUE <null> ::= NULL <undefined> ::= UNDEFINED <none> ::= NONE <list> ::= (<value*>) <value*> ::= <delimited value> <space><value*> | <delimited value> |
<empty> <simple ext>::= <point> | <rectangle> | <RGB> <point> ::= {<integer> <space> <integer>} <rectangle> ::= {<integer> <space> <integer> <space> <integer> <space>
<integer>} <RGB> ::= {<integer> <space> <integer> <space> <integer>} <space> ::= any nonempty string of characters whose ASCII values are less
than or equal to that of blank <quoted string> ::= <no double>"<quoted string> | "<no double>" <no double> ::= any string of characters, except " <atom> ::= <letter atom> | <special atom> <letter atom> ::= <letter> <alphanumeric> | <letter> <special atom> ::= any nonempty string of characters having ASCII values
greater than that of blank except those included in <alphanumeric>
<integer> ::= <sign> <unsigned integer> <unsigned integer> ::= <decimal integer> | <based integer> | <ascii integer> <decimal integer> ::= <digit> <spaced digits> <spaced digits> ::= <digit> <spaced digits> | _<spaced digits> | <empty> <based integer> ::= <digit+>#<alphanumeric> <alphanumeric> ::= <letter> <alphanumeric> | <digit> <alphanumeric>|
<letter> | <digit> <letter> ::= a | b | c | d | e | f | g | h | i | j | k | l |m | n |
o | p | q | r | s | t | u | v | w | x | y | z | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | _
<ascii integer> ::= '<no single>' | '<no single><no single>' | '<no single><no single><no single><no single>' <no single> ::= any string of characters having ASCII values greater than
that of blank, except ' | ' ' <real> ::= <sign> <mantissa> <exponent> <mantissa> ::= <digit+> | <digit+>.<digit*> | <digit*>.<digit+> <exponent> ::= <sign> <digit+> | E<sign> <digit+> | <empty> <sign> ::= - | - | <empty> <digit*> ::= <digit+> | <empty> <digit+> ::= <digit> <digit*> <digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <empty> ::= the empty string
Appendix B: Primitives by Category
Bit bit-and bit-not bit-or bit-shift-l bit-shift-r bit-xor test-all? test-bit? test-one? Callbacks dispose-method-pointer make-method-pointer COM COM-create-object COM-dispose-object Data copy get-resource-info get-resource-list get-string-resource inst-to-list list-to-inst shallow copy File close create delete file-size get-file get-position open put-file read read-line rename resource-file set-position write write-line Graphics find-bounds ints-to-point ints-to-rect ints-to-rgb point-to-ints points-to-rect rect-to-ints rect-to-points rgb-to-ints Input/Output accept answer answer-v ask display print-text select set-dialog-font show Interpreter control abort abort-callback compiled? debug call execute find-method halt lookup-external-constant open-info-window open-method-window switch-to-prograph trace yield-cpu Lists (in) (join) (length) attach-l attach-r detach-l detach-nth detach-r find-instance find-sorted get-nth insert-nth make-list pack reverse set-nth set-nth! sort split-nth unpack
Load & Save/Data Clustering clear-bytes-map cluster-dispose cluster-new cluster-size from-bytes load save set-undefined-class to-bytes Logical < <= = > >= and choose not or switch xor ~= Math * ** + ++ +1 - -- -1 abs acos annuity asin atan atan2 compound cos div exp idiv ln log10 max min pi power rand round round-down round-up set-seed sign sign-extend sin sqrt tan trunc Memory address-to-object block-address block-size compact-memory dispose-pointer from-handle from-pointer get-cstring get-external-size get-integer get-point get-process-refcon get-real get-rect get-string get-text heap-size lock-block lock-string make-direct make-handle make-pointer memory-callback new-block object-to-address put-cstring put-integer put-point put-real put-rect put-string put-text set-process-refcon string-address to-handle to-pointer unlock-block unlock-string valid-heap? String format byte-length from-ascii from-string ‘inÓ integer-to-string ‘joinÓ ‘lengthÓ middle munge-string prefix string-length string-to-integer suffix to-ascii to-string tokenize System ancestors attr-com attributes called-from-get called-from-meth called-from-set
calls-to-get calls-to-meth calls-to-set children class-com class-section classes create-class create-method descendants editor-methods meth-com meth-com-g meth-com-s meth-io-com meth-io-com-g meth-io-com-s method-arity method-classes method-section methods pers-com persistent-section persistents section-com section-contents sections set-attr-com set-class-com set-meth-com set-meth-com-g set-meth-com-s set-pers-com set-section-com Type boolean? instance? integer? list? external-type number? real? string? type Win32 get-application-instances get-application-main-window get-command-line MakeIntResource set-application-window
Appendix C: Optimus Prime
As part of this project we wrote code in Prograph to implement the Sieve of Eratosthenes.
This took quite a bit of work as learning Prograph was not as easy as learning new syntax, but it
was an entirely different way of programming. The following image shows the entire program:
This code will be made available along with the freeware Prolog Windows Interpreter on
our website at http://students.cs.byu.edu/~dheise/cs330. The code is run by executing the method
“start_Loop”. This will prompt the user for a number and then, using the algorithm, compute all
the prime numbers smaller than the given number. One draw back of the freeware interpreter is
the limited number of ways to show information to the user. The show primitive has a limited
number of lines available to the user and going beyond this limit is possible, but futile since the
user cannot see that information. Therefore, although the algorithm correctly computes the
information, the user can only see a limited number of results using the show primitive.