Nano
the nanny of pico
user manual v0.2

Naam : Van Belle Werner
e-mail : we47091@is2.vub.ac.be
programmeerproject
1e licentie Computerwetenschappen

Projectbegeleider: Wolgang De Meuter


Warranty

Alle schade die voorkomt door het gebruik van dit programma wordt volledig genegeerd door de auteur van dit programma. (waarschijnlijk zal hij eens goed lachen).

System requirements

Een pc die  draait moet voldoende zijn om nano te draaien. Merk op dat het geheugengebruik vergroot naarmate de parse-tree groter wordt. Nano kan maximaal 32 MB aanspreken.

Hoe te installeren

1.     Zorg eerst dat de compiler goed geïnstalleerd is.  (dus ook  'set PATH=c:\java\bin;%path%')

 

2.     Maak dan ergens een subdirectory op uw harddisk en kopieer alle files naartoe. Stel dat de subdirectory '\nano\' heet. (Merk verder op dat de directory PicoRuntime wel degenlijk 'PicoRuntime' moet heten)

 

3.     Voeg aan de dos-environment 'CLASSPATH=\nano' toe. Als volgt: set CLASSPATH=\nano

 

4.     chdir naar '\nano\PicoRuntime'. Type hier 'namethem'. (een batchfile) Hierdoor krijgen al de korte filenames hun lange juiste filename.

 

5.     typ 'javac *.java'. Hiermee wordt normaal de pico-runtime library gecompileerd. Deze mag geen fouten geven.

Wat moet dit programma doen

Dit programma is gemaakt om van een gegeven pico-source file automatisch een -file te genereren. Deze  file zou na compileren hetzelfde resultaat moeten geven als de geïnterpreteerde pico-source.

Om een vergelijking te kunnen maken met de oorspronkelijke pico is er een pico-interpreter toegevoegd (pico.exe).

How to use it (command-line-parameters ...)

nano inputfile [outputclasse]

 

Nogal simpel:

 

                inputfile: wat is de invoerfile... (typ de extentie er bij)

                outputfile: wat is de naam van de output-classe (ZONDER extentie)

Voorbeeldprogramma

Tussen de installatie-files steekt een file 'showdown.pic'. Laat ons deze pico-source eens omzetten naar ...

 

Typ 'nano tests\showdown.pic'. De uitvoer is te zien op het volgende blad.

 

Nu is er een file 'RunMe.jav' gecreeerd. Rename deze file naar 'RunMe.java'. Ik slaag er namelijk niet in vanuit dos de langere bestandsnamen van windoos windows '95 te acceseren.

 

Deze file moet nu gecompileerd worden naar de juiste class-files. Doe dit als volgt: 'javac RunMe.java'. Deze staat een tijdje te denken en zal dan terugkeren naar de prompt. Nu zijn er class-files gegenereerd.

 

Het runnen van de showdown gebeurt nu als volgt: 'java RunMe'

 

(om eventueel een vergelijking te maken met de oorspronkelijke pico kan je 'pico tests\showdown.pic' starten.)

Beperkingen van de ingevoerde picosource

     De ingevoerde pico heeft een aantal beperkingen die die oorspronkelijke pico niet heeft. Bijvoorbeeld: de functionele formele parameters die zelf parameters hebben worden niet aanvaard. Samengevat:

  begin(
    a(b(x)):b(12),
    display(a(x*x)))

zal 144 printen terwijl nano zal klagen dat x niet gekend is.

 

     De function-assignment uit pico wordt ook niet ondersteund. Ik heb eigenlijk zelfs nog niet uitgevist wat hij betekend.

Kwaliteit van de uitgevoerde java

De uitgeveorde code is uitermate efficiënt, hoewel het blijkbaar toch nog steeds zo is dat de uitgevoerde code trager blijkt te gaan dan de geïnterpreteerde pico. Waarschijnlijk ligt dit aan de sloomheid

van de -interpreter en/of compiler.

 

De truc die ik gebruik om code te optimiseren bestaat er uit actuele parameters direct uit te rekenen en mee te geven indien dat mogelijk is. Merk op dat in pico de callee bepaalt onder welke vorm de actuele parameters

binnen moeten komen.

 

De intermediate code generator genereert variabelen als kosten ze niets. Het weghalen van redundante variabelen beschouw ik als een taak voor de -compiler.

Warnings

     Dereferencing variable who's value is never used (%s) : de gegeven identifier wordt opgevraagd maar het resultaat wordt volledig genegeerd.

     Er wordt mij gevraagd een nutteloos nummer te creeeren : er moet een nummer gemaakt worden dat nadien gewoon niet meer gebruikt wordt.

     Nutteloze table-referentie : in dezelfde trend voortgaand wordt hier de inhoud van een table opgevraagd terwijl deze ook direct vergeten wordt. Rather nutteloos nietwaar ?

     Er wordt mij gevraagd een doelloze string te genereren : hoeft geen uitleg meer dacht ik zo...

     Couldn't open 'natives.dat' file : de beschrijving van de natives kon niet gevonden worden...

Errors

     wrong parametercount : het aantal parameters dat meegegeven wordt aan een functie is fout. Merk op dat deze error niet altijd gegeven kan worden.

Fatals

Failed assertions are considered fatal internal errors. Please report them.

 

     Internal compiler error : bug in het programma, waarschijnlijk.

     Undefined variabele : ongedefiniëerde variabele. De gebruikte scoping is de gewone lexicale scoop.

     invalid argument list; invalid argument list2 : in de argumentenlijst van een functiedefinitie zit een constructie die niet katholiek is.

     unkown character; unkown char : de mapping van pico identifiers naar unieke  identifiers gebeurt met een soort escape characters. U hebt zonet een karakter gevonden dat nog niet gecovered is door de escape karakters.

     dictionary full : u gebruikt te veel identifiers.

     out of memory : het geugen is op.

     can't open file %s : de gegeven filename kan niet geopend worden. Hoogst waarschijnlijk bestaat hij niet.

     can't open outputfile %s : de outputfile met de gegeven filename kan niet aangemaakt worden. Disk full ?

     Parametercount in natives.dat moet <80: nano kan maar 80 parameters uitlezen.

    Parametercount missing in natives.dat : er ontbreekt een parametercount.

    Writeout name missing in natives.dat (pico-name = %s) : de write-out constructor ontbreekt.

    corrupted 'natives.dat' file: er zit een onverwacht token in natives.dat (btw: rems zijn niet toegelaten in deze file)

Toevoegen van native-functions

Omdat de picoruntime nog lang niet af is heb ik een mogelijkheid toegevoegd waarmee zelf natives toegevoegd kunnen worden.

 

De native function beschrijvingen verblijven in een file 'natives.dat'. Elke native wordt beschreven door 1 lijn waarbij eerst de pico-name wordt gegeven, nadien de java-allocatie-methode en daarachter een beschrijving van de parameters. De beschrijving van de parameters bestaat eerst uit het aantal parameters en dan voor elke parameter een 1 of een 0. Een 1 duidt aan dat die parameter normal moet gepassed worden. Een parameter-table (de @ operator) wordt meegegeven als een count die -1 is.

 

Een paar voorbeeldjes:

 

`//'       `new nat_div()'        2 0 0

`\\'       `new nat_mod()'        -1

`display'  `new nat_display()'    -1

`lazy_and' `new nat_lazy_and()'   2 0 1

 

De volgende functies kunnen niet geherdefiniëerd worden door eigen natives omdat de compiler ze vanzelf zal optimizeren, dit wil zeggen : inline coderen (de begin zal bijvoorbeeld gewoon niet gecalled worden !):

 

  begin

  if

  until

  while

 

hoewel ze wel at runtime een andere toekenning kunnen krijgen...

 

De interface tot de runtime kan duidelijk afgelezen worden in de .java sourcefiles die verblijven in PicoRuntime. Als conventie stel ik voor elke native function te laten voorafgaan door 'nat_'. Daardoor worden name-conflicten vermijden.

Technical support

Mail naar we47091@vub.ac.be of contacteer me persoonlijk.

Troubleshooting

Nog geen troubles ontdekt... (ook nog niet deftig gebeta-test)

Referenties

Ik heb het 'pico-manifest' toegevoegd zodat de gebruiker toch al weet (kan weten) wat pico is. Indien er vragen zijn omtrent pico zouden deze aan Prof. Theo D'Hondt gesteld moeten worden.

 

De taal  is volledig gedocumenteerd en kan gevonden worden te http://java.sun.com/...

Redistribution rights

You may freely distribute this product as long as no payment is involved and you keep my name in it.

 


Pico : computer programming in 10 hours

 

Theo D’Hondt

Programming Technology Lab V.U.B.

June 1995

 

Aims:

 

The fundamental aim of Pico is to introduce the essentials of computer programming to undergraduate students in the basic sciences other than computer science[1]. In conceiving Pico we were strongly inspired by the approach used in Abelson and Sussman’s book “Structure and Interpretation of Computer Programs”[2] and equally strongly repulsed by the various standards efforts to teach computer programming at the high-school and academic level. Pico can actually be viewed as an effort to render Scheme palatable and even enjoyable to people unable or unwilling to make the intellectual effort necessary to grasp its elegance and power. We do so by adapting Scheme’s syntax (significantly) and semantics (subtly) in order to use what (little) understanding the novice science student has of (specification) languages.

 

The word Pico should be interpreted as synonymous with very small (according to Webster’s). The idea was indeed to have a very small language with a very general impact. The 10 hours in the title refers to the fact that in a 30 hour course we limit to one third the time spent on teaching computer programming. The other two thirds are spent on using computer programming in various interesting ways.

 

We were also strongly driven by the ambition to return to the original attraction exerted by computer programming on young people; we strongly deplore the current situation where most of these regard programming as a mindnumbing chore. Pico is essentially the result of sugarcoating the hard essentials of computer programming in such a way that students cannot help but enjoy it.

 

 

Strategy:

 

The basic rules for establishing Pico as a programming language result from the following concerns:

 

o the semantics of Pico should be as simple as possible even if this means that a number of Scheme features become inaccessible

 

o the syntax of Pico should diverge as little as possible from the syntax used in elementary calculus

o Pico must be presented in as attractive a way as possible, sacrificing any performance constraint that stands in the way of ease–of–use, portability, interactivity and other similar concerns

 

o Pico as a language should coincide with Pico as a tutoring system; the boundaries between programming and learning must be totally removed

 

As mentioned in the introduction, we have briefly considered using Scheme for this purpose. On the basis of our (extensive) experience with using Scheme in the Computer Science curriculum we chose not to do so. Although extremely well–suited for the more computer science oriented student, Scheme’s cryptic notation makes it unsuitable for our purposes.

 

 

Basic syntax of Pico

 

In Pico the basic syntactical entities are —not unexpectedly— numbers, symbols, variable definitions, variable references, function definitions and function applications. Symbols are specified as quote-delimited character strings while numbers follow the generally accepted rules. Variables are alphanumerical strings starting with a letter. Every isolated instance of the name of a variable constitutes a reference to it; defining a variable is done by associating it with an initial value:

 

Pi: 3.14159

 

Function applications are formulated in elementary calculus style:

 

min(f(x),0)

 

i.e. a name followed by a parenthesis–delimited, comma-separated argument list. Functions are defined by associating an implementation with a function application prototype:

 

min(x,y): if(smaller(x,y),x,y)

 

Function names are extended to cover operators; unary or binary operators may be invoked in prefix or infix notation, again to reflect elementary calculus. For instance

 

x<<n: x*2^n

 

255<<4

 

illustrates the definition and application of a shift operator. Precedence among operators is determined by each operator’s initial character and is hardwired into the syntax.

 

Operators are nothing more than syntactic sugar and do not have any impact on Pico’s semantics.

   

Basic semantics of Pico

 

In the spirit of Scheme, we have opted for a functional, dynamically typed, statically scoped language. There are, however, two major differences at the level of the basic semantics.

 

In the first place, we impose universal naming of functions:

 

comb(p,q): fac(p)/(fac(q)*fac(p-q))

 

defines the expression to the right of the colon as the implementation of a function called comb taking p and q for arguments. Compared to Scheme this slightly reduces the expressiveness of Pico but eliminates most of the confusing recursion-related issues in Scheme such as the let, let* and letrec variants of block structures.

 

In the second place we extend the Scheme-like argument binding rule to include formal functional parameters. For instance:

 

and(p,q()): if(p,q(),false)

 

defines a lazy Boolean and. Evaluating the expression:

 

and(a>0,a<10)

 

will result in the value of a>0 being bound to p and q to be bound to reflect the definition of a parameterless function:

   

q(): a<10

 

Laziness results from q being called only when needed.

 

Formal functional parameters allow us to bypass the need for Scheme’s special forms and to have totally uniform function call semantics. It is for instance very straightforward to introduce a l-calculus styled Boolean system:

 

 

true(then(), else()): then()                 

                                              

false(then(), else()): else()                

                                              

and(left, right()): left(right(), false)     

                                              

or(left, right()): left(true, right())       

                                              

not(pred): pred(false, true)                 

                                              

if(cond, then(), else()): cond(then(), else())

 

 

 

The (informal) semantics of Pico are extremely simple:

 

                EVAL(nbr,env)       _ nbr

                EVAL(sym,env)       _ sym

            EVAL(var:ini,env)       _ DEFINE(var,EVAL(ini,env),env)

                EVAL(var,env)       _ LOOKUP(var,env)

     EVAL(fun(arg…):bod ,env)       _ DEFINE(fun,FUNCTION(arg…,bod,env),env)

          EVAL(fun(arg…),env)       _ APPLY(LOOKUP(fun,env),arg…,env)

In the above the DEFINE and LOOKUP functions act upon the environment in the usual way; FUNCTION and APPLY are identical to their Scheme equivalent, apart from the argument binding behaviour:

 

BIND(frm,act,env,callenv)

         _ DEFINE(var,EVAL(act,callenv),env)

                   if frm _ var is a variable reference

         _ DEFINE(fun,FUNCTION(arg…,act,callenv),env)

                   if frm _ fun(arg…) is a function application

 

The names frm and act denote respectively a formal and actual parameter; env represents the (extended) static environment and callenv represents the dynamic environment. This part of the (informal) semantics constitutes the major difference with Scheme; it is also the basis for the uniform function call semantics of Pico.

   

Data structures in Pico

 

With Pico’s target audience in mind, we have taken a pragmatic approach to data structures. We opted for simple arrays called tables,  which again according to Webster’s is a systematic arrangement of data. A Pico table is represented using an additional syntactical notation which again as closely as possible reflects convention. A table is an indexable structure of fixed size; for instance:

 

primeNumbers[N]: true

 

defines a table called primeNumbers of size N and with all members initialised to the value of true. Indexing is e.g. performed as follows:

 

primeNumbers[2*k+1]

 

with the index expression 2*k+1 dynamically checked to range from 1 through N.

 

Members of a table are arbitrary combinations of valid Pico values, i.e. numbers, symbols, functions or tables. This closely reflects the data structure called vector from Scheme. In order to complete this picture, we also introduce destructive operations:

 

primeNumbers[4]:= false

 

rebinds the fourth member of primeNumbers to the value of false. In order to maintain consistency, we have therefore also included destructive operations for variables and functions:

 

Pi:=3.14159265358979

 

comb(p,q):= (fac(p)/fac(p-q))/(fac(q)

 

The apply operator in Pico

 

A Pico interpreter is understood to operate upon an abstract grammar representation of a Pico program. In the spirit of Scheme, this abstract grammar is expressed as Pico tables; this makes it possible for us to define Pico in a metacircular way. A side-effect of this approach is that function argument lists are also represented as tables, which enables us to introduce an apply operator at no extra cost. Representing this operator by the symbol @, we can for instance define:

 

begin@list: list[size(list)]

 

i.e. a function begin taking at least one argument and returning the value of the last argument. Since non-functional formal parameter binding is eager in Pico, the begin function defines the equivalent of a Scheme expression sequence and consequently:

 

loop(value, boolean): boolean(loop(body(), cond()), value)

 

defines an iterator. Using functional formal parameters we easily get:

 

while(cond(),body()): loop(void, cond()) 

 

Another useful application of @ is the following function:

 

tab@list: list

 

which enables us to define tables in an alternative way:

 

primeNumbers:tab(true,true,true,false,true,false,true,false,false)

 

In analogy to Scheme, the apply operator can also be used to dynamically assemble function calls:

 

cell(start):

  begin(put(command,value):start:=value,

        get(command): start,

        dispatch@message:

          begin(op:if(message[1]='put',put,get),

                op@message))

             

shows that Scheme’s higher–order function features have been retained in Pico.

 

Examples

 

The elementary examples of recursion are obviously very straightforward:

 

fac(n): if(n>1, n*fac(n-1), 1)

 

but Pico is also very easy to express more sophisticated algorithms in, such as for instance the quicksort:

 

QuickSort(V,Low,High):

  begin(Left:Low,

        Right:High,

        Pivot:V[(Left+Right)//2],

        until(Left>Right,

          begin(while(V[Left]<Pivot,Left:=Left+1),

                while(V[Right]>Pivot,Right:=Right-1),

                if(not(Left>Right),

                   begin(Save:V[Left],

                         V[Left]:=V[Right],

                         V[Right]:=Save,

                         Left:=Left+1,

                         Right:=Right-1),

                         false))),

                if(Low<Right,QuickSort(V,Low,Right),false),

                if(High>Left,QuickSort(V,Left,High),false))

 



[1]actually in the context of “Introduction to Computer Science” as organised in the Sciences faculty of the V.U.B.

 

[2]extensively used in the Computer Science curriculum in the same faculty