REFAL

Linguaggio funzionale

Refal (REcursive Functions Algorithmic Language) è un linguaggio di programmazione funzionale orientato alla manipolazione simbolica, traduzione e intelligenza artificiale, sviluppato a partire dal 1968 in Russia da Valentin F. Turchin: Refal 2 (1970) e Refal-5.

Refal  genera uno pseudo codice interpretato successivamente: RASL (Refal ASsembly Language). Refal Plus è un compilatore.

L’input di Refal non è un insiemi asintattici, nel senso che certi caratteri come spazi, parentesi, apici, sono dei delimitatori che individuano simboli (un numero, una stringa di caratteri o un carattere all’interno di apici) ed espressioni (simboli o  entità entro parentesi). I simboli terminano, per qualche motivo recondito, con uno spazio, tranne quando derivano da stringhe di caratteri delimitate.

Essenzialmente Refal opera con pattern matching e sostituzione basato su di un semplice meccanismo di riconoscimento: nel riconoscimento intervengono stringhe di costanti e variabili libere appartenenti a tre categorie:

·      simboli, individuati da s.nome,

La struttura basilare di Refal è dunque la sostituzione guidata da pattern (sentence), la sintassi basilare è:

    pattern = espressione di sostituzione;    

ADD t.1 t.2 = t.1 '+ ' t.2;

Il pattern può essere ulteriormente specificato da una condizione (where clause), separata dal pattern da una virgola, la forma completa di una sentence è quindi:

pattern

,

espressione

:

pattern    

=

espressione di sostituzione;

t.1 t.2 t.3

,

'+-*/'     

:

e.A t.2 e.B

=

t.2 '(' t.1 ' ' t.3 ')';

* l’esempio controlla che l’espressione contenga un operatore valido

 

 

 

 

                     

Nella parte destra delle sentence (ed in quella a sinistra delle where clause), possono comparire delle funzioni la cui sintassi di richiamo è <NomeFunzione parametri>, ed il corpo: NomeFunzione {sentence; ...}. Il corpo delle funzioni è una elencazioni di coppie di pattern con il relativo valore restituito dalla funzione, valore che può essere una costante, può contenere variabili presenti nel pattern o il risultato di funzioni. Refal non ha un concetto stretto di parametri,  in quanto l’argomento della funzione è una stringa qualsivoglia così come il valore ritornato. L’esempio che segue, il calcolo di un valore della successione di Fibonacci , illustra le caratteristiche appena viste.

$ENTRY Go {= <Prout <Fibo 12>>}

Fibo {s.1, 1 2 : e.1 s.1 e.2 = 1;  /* for 1 and 2 */

       s.1, <Type s.1> : 'N0' e.S = s.1 'Fibonacci\'s ' <Fibo 1 1 <Sub s.1 1>>;

       t.1  t.2 1 = 'is ' t.2;                 /* answer */

       t.1  t.2  t.3 = <Fibo t.2 <Add t.1 t.2>

                       <Sub t.3 1>>;

       e.1 = 'NaN';

}

H:\Refal>refc eval

Refal-5 Compiler. Version PZ Oct 29 2004

Copyright: Refal Systems Inc.

H:\Refal>refgo eval

12 Fibonacci's is 144

Fra le funzioni primitive sono presenti funzioni aritmetiche (aritmetica intera) , di input output, di sistema, di gestione delle stringhe e di analisi del tipo di termine.

Importante le funzioni <Br 'variabile=' espressione> e <Dg 'variabile'> rispettivamente per inserire un valore o prelevarlo dallo stack (di nome variabile), sono affiancate rispettivamente da due funzioni:

<Rp 'variabile=' espressione>   /* sostituisce il valore in cima allo stack  variabile */

<Cp 'variabile'> /* copia il contenuto dello stack */

Questo è un modo per memorizzare delle variabili; le costanti sono semplicemente delle funzioni senza parametri e con il solo pattern vuoto, vedasi la funzione Alfa nell’esempio riportato qui sotto, una variante di Bubble Sort leggermente più efficiente.

$ENTRY Go { = <Prout <BbFastSort 'wvonmzyxlutsrpqcbakjihgfed'>>;}

BbFastSort { = 'Sort ended ';

             e.1, <Urder e.1>: e.2 s.1 = <BbFastSort e.2> s.1;

}  

Urder {

   s.1 = s.1;

   s.1 s.2 s.3 e.tail,<Alfa>: e.A s.3 e.B s.2 e.C s.1 e.D = s.3 s.2 <Urder s.1 e.tail>;

   s.1 s.2 e.tail, <Alfa> : e.A s.2 e.B s.1 e.C = s.2 <Urder s.1 e.tail>;      

   s.1 e.tail = s.1 <Urder e.tail>;

}

Alfa {= 'abcdefghijklmnopqrstuvwxyz';}

D:\Refal>refgo eval

Sort ended abcdefghijklmnopqrstuvwxyz

Press any key to exit

L’esempio seguente è un interprete di comandi OMMNITAB, uno dei primi esempi di fogli elettronici (1966) (v. OMNITAB ) . L’interprete genera un sorgente in Phrogram (v.Phrogram ) per disegnare la funzione ln(x-1) per |x| <1 con la serie di Taylor.

* Refal-5 System. Version PZ Oct 29 2004
$ENTRY Go { = <Open 'r' 1 'omnitab.src'> 
              <Open 'w' 2 'omnitab.kpl'>
              <InitialStatements><Elab <Get 1>> <FinalStatements>
}
Elab { 0 = ;                  /* end of file */
       e.X = <Prout e.X>
             <Write 2 <Translate e.X>>
             <Elab <Get 1>>; }
Translate { = ;
    'RAISE' e.1 = <RAISE e.1>;
    'MULT' e.1 = <MULT e.1>;
    'GENERATE' e.1 = <LOOP e.1>;
    'ROWSUM' e.1 = <ROWSUM e.1>;
    'PRINT' e.1 = <PRINTCOL e.1>;
    'OMNITAB'' ' e.1 = '\t\tPrintLine(\"' e.1 '\")\n';  
	e.1 = '// ' e.1 '\n';		/* comments */
}
LOOP { = 'Lack of data';
       e.from '\('  e.incr '\)' e.to ' IN ' e.col =
           '\t\tfIndx = ' e.from '\n\t\tJ = 0\n'
           '\t\tWhile fIndx < ' e.to '\n'
           '\t\t\tJ = J+1\n'
           '\t\t\tSh[J,' e.col '] = fIndx\n'
           '\t\t\tfIndx = fIndx + ' e.incr '\n'
           '\t\tEnd While\n';
       e.1 = 'syntax error';
     }

RAISE { = 'Lack of data';
       e.1 = <Push e.1>
             <FOR>
             '\t\t\tSh[Indx,' <Dg 'Op'> '] = ' 
             <Br 'Exp=' <Dg 'Op'>>
             ' Math.Power(Sh[Indx,' <Dg 'Op'> '] , ' <Dg 'Exp'> ')\n'
             '\t\tNext\n';
     }
MULT { = 'Lack of data'; 
      e.1 = <Push e.1><FOR>'\t\t\tSh[Indx,' <Dg 'Op'> '] = '
            <ColumnOrNumber <Dg 'Op'>> ' * ' <ColumnOrNumber <Dg 'Op'>> '\n'
            '\t\tNext\n';
      e.1 = 'Syntax error';
}
ROWSUM  { = 'Lack of data';
      e.1 = <Push e.1><FOR>'\t\t\tSh[Indx,' <Dg 'Op'> '] = '
      		<PopSh <Dg 'Op'>>
      		'\t\tNext\n';  
}
PRINTCOL { = 'Lack of data';
       e.1 = <Push e.1><FOR>'\t\t\tPrintLine('
      		 <PrepPrint <Dg 'Op'>><PopPrint <Dg 'Opx'>>
      		 '\t\tNext\n'; 
}      
Push {= ;
     ' ' e.1 = <Push e.1>;	/* skip space */
     e.1 ' ' e.2 = <Br 'Op=' e.1> <Push e.2>;
     e.1 = <Br 'Op=' e.1>}
PopSh {  = '0\n';
     e.1 = 'Sh[Indx,' e.1 ']+' <PopSh <Dg 'Op'>>; }
PrepPrint {  = <Br 'Trash=' <Dg 'Opx'>>;
     e.1 = <Br 'Opx=' 'Sh[Indx,' e.1 ']'><Br 'Opx=' '+\" \"+'><PrepPrint <Dg 'Op'>>; } 
PopPrint {  = ')\n';
        e.1 = e.1 <PopPrint <Dg 'Opx'>>; }              
ColumnOrNumber {= ;	  
     			e.1 '.' e.2 = e.1 '.' e.2;
     			e.1 = 'Sh[Indx,' e.1 ']'}     
FOR  { = '\t\tFor Indx = 1 To 46\n'; } 
InitialStatements { = 
       <Write 2 'Program Omnitab\n'>
       <Write 2 '\tMethod Main()\n'>
       <Write 2 '\t\tSetScreenSize( 320, 320 )\n'>
       <Write 2 '\t\tDefine Indx As Integer\n\t\tDefine J As Integer\n'>
       <Write 2 '\t\tDefine fIndx As Float\n'>
       <Write 2 '\t\tDefine Sh As float[46,101]\n'>
       <Write 2 '\t\tSetWindowTitle(\"Condor Informatique - OMNITAB Emulator\")\n'>
     }
FinalStatements { = 
       <Write 2 '\tEnd Method\n'>
       <Write 2 'End Program\n'>
     }
  

Evoluzione