Aggiornamento per newLisp e Delphi

24 06 2008

google_translate.gif Translate To English!

Ho appena rilasciato una nota riguardante il precedente articolo: newLisp e Delphi. L’update si trova in fondo allo stesso articolo, ma per vostra comodità lo riporto anche qui:

AGGIORNAMENTO: Ho scritto anche una versione modificata per essere utilizzata con Lazarus Pascal, così da garantire l’uso cross-platform! Pubblicherò i sorgenti e un demo nei prossimi giorni (non appena sarò riuscito a far funzionare il mio nuovo sito internet ;-)  )

Grazie.





Usare newLisp da Delphi!

24 06 2008

google_translate.gif Translate To English!

L’idea di usare newLisp all’interno di un altro linguaggio mi ha sempre stuzzicato, ed il funzionamento di newLisp-GS (GUI grafica fatta in java, che comunica con newLisp tramite sockets) mi ha indotto a percorrere una strada alternativa: richiamare l’interprete newLisp tramite la sua DLL (quindi limitato all’ambiente Windows, ma sto facendo delle prove usando Lazarus Pascal, quindi cross-platform ;-)   ).

Il mio timore era che l’interprete newLisp, richiamato da una DLL, non fosse in grado di mantenere lo stato delle variabili, limitandone quindi l’uso. Invece, con mia (piacevole) sorpresa, non solo l’interfacciamento è stato possibile, ma i dati sono anche persistenti!!!

Vediamo come fare (è molto semplice).

Prima di tutto dobbiamo aprire la DLL newlisp.dll da Delphi:

var
  function newlispEvalStr(argExpression: pchar): pchar; stdcall; external 'c:\program files\newlisp\newlisp.dll';

Ho voluto mettere in evidenza il path della dll: questo significa che la libreria non deve stare necessariamente nella directory di Windows, nè in system32, e nemmeno nella directory in cui si trova il vostro programma.
Per passare i parametri, e leggere i risultati, ho utilizzato un pchar, cioè un puntatore ad un’area di memoria terminante con null-char (). Quindi…

var P: PChar;

P := 'Hello world!'

Equivale a…

const TempString: array[0..12] of Char = 'Hello world!';
var P: PChar;

P := @TempString[0];

(per chi non conoscesse il Pascal: il simbolo @ serve per ottenere l’indirizzo di memoria di una variabile; è equivalente al costrutto in C: p = &TempString[0] )

Ok, ora che abbiamo indicato a Delphi dove prendere la funzione, e in quale DLL si trova, dobbiamo semplicemente utilizzarla!
L’uso è semplicissimo (Delphi fà quasi tutto il “lavoro sporco”):

procedure TForm1.Button1Click(Sender: TObject);
var
  newLispCode: PChar;
  newLispResult: PChar;
begin
  newLispCode := '(+ 5 3)';
  newLispResult := newlispEvalStr(newLispCode);
  showMessage(newLispResult);
end;

Per comodità, ho messo il codice al’interno di un evento OnClick di un bottone (che si trova nella form TForm1). Ho scritto il programma esplicitando tutte le variabili, così da renderlo più facilmente comprensibile, ma potevamo anche scriverlo così:

procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(newlispEvalStr(pchar('(+ 5 3)')));
end;

In breve, ho semplicemente creato una stringa contenente il codice newLisp da passare al parser, e ho mostrato, con una showMessage(), il risultato. Il codice lo potete prelevare anche da un componente memo… pensate alla scrittura di un ambiente IDE, completo di editor, per newLisp…

procedure TForm1.Button1Click(Sender: TObject);
begin
  showmessage(newlispEvalStr(pchar(memo1.text)));
end;

La parte sottolineata mette in evidenza l’uso del componente visuale TMemo.

Provate a scrivere ed eseguire il seguente codice:

procedure TForm1.Button1Click(Sender: TObject);
begin
  newlispEvalStr(pchar('(setq a 10 b 20)'))
  showmessage(newlispEvalStr(pchar('(+ a b)')));
end;

Vi accorgerete che Delphi restituirà, correttamente, il valore 30. Ciò significa che il valore delle variabili è stato mantenuto tra una chiamata newlispEvalStr() e l’altra… meraviglioso :-)

Tutto il codice è estremamente elementare, e facilmente convertibile in altri linguaggi. Spero possa esservi utile…

AGGIORNAMENTO: Ho scritto anche una versione modificata per essere utilizzata con Lazarus Pascal, così da garantire l’uso cross-platform! Pubblicherò i sorgenti e un demo nei prossimi giorni (non appena sarò riuscito a far funzionare il mio nuovo sito internet ;-)  )

A presto!





(01) Code Pattern: Introduzione

23 06 2008

google_translate.gif Translate To English!

Come già anticipato, iniziamo una serie di puntate per parlare dei code patterns (una breve introduzione la potete trovare qui: http://newlisp.wordpress.com/2008/05/21/aggiornato-il-codepatterns/).

Essi sono elementi molto importanti, ed hanno diverse funzionalità:

  1. Insegnano il modo migliore per svolgere determinati compiti.
  2. Sono una fonte preziosa di codice o medotologie di programmazione già pronte all’uso.

Il documento originale, che useremo come guida “spirituale”, si trova qui: http://www.newlisp.org/CodePatterns.html

In alcuni punti ho aggiunto anche altre informazioni, al fine di chiarire dei concetti che potrebbero risultare poco chiari ai meno esperti. Ho inoltre aggiunto anche altri esempi, includendo delle opzioni o features non esplicitamente indicate nel documento originale.

Pronti… allora si inizia!!!

Script files

La linea comando

Nei sistemi Un*x-like (come Linux per esempio), potete eseguire gli script in modo automatico mettendo, nella prima riga dello script il comando seguente:

#!/usr/bin/newlisp

Per eseguire l’interprete, indicando però di allocare uno stack più grande, si può dare il comando:

#!/usr/bin/newlisp -s 100000

Oppure…

#!/usr/bin/newlisp -s100000

In base alla shell che usate (cmd per Windows, oppure una delle innumerevoli shell disponibile in Un*x), newLisp accetta sia i comandi attaccati che staccati. Per verificare tutto ciò potete usare il seguente codice:

#!/usr/bin/newlisp -s 100000 -m 10
(println (main-args))
(println (sys-info))

Richiamandolo questo script, dovreste ottenere qualcosa simile a:

("/usr/bin/newlisp" "-s" "100000" "-m" "10" "./arg-test")
(308 655360 299 2 0 100000 8410 2)

NOTA: lo stack allocato per default (se non diversamente specificato) è pari a 2048, considerando il fatto che, ad ogni cella corrispondono circa 80 bytes.

Usare le pipes

Per poter inviare i risultati di un comando shell in uno script newLisp si può usare il codice seguente (salvatelo con il nome uppercase.lsp):

#!/usr/bin/newlisp

# uppercase - converte un input in maiuscolo.
# usage (un*x):
#          ./uppercase < file-spec
# usage (Ms Windows):
#          newlisp uppercase.lsp < my-text

(while (read-line) (println (upper-case (current-line))))
(exit)

Il breve script convertirà tutte le righe che giungono dalla console in MAIUSCOLO.

Oltre alla sintassi sopra indicata (vedi lo script), potete digitare anche questo comando:

type my-text | uppercase.lsp

Per oggi è tutto, la prossima volta parleremo di:

  • Moduli;
  • Contexts;
  • Rendere un programma modulare e riutilizzabile.

A presto!