Re: Designing Lisp from scratch

[email protected] Tue, 20 Mar 2007 01:12:37 EDT
Newsgroups gmane.comp.lang.lightweight
Message-ID <[email protected]>
 
 
In a message dated 3/17/07 9:48:40 PM Eastern Standard Time,  
[email protected] writes:

So  what's really special that companies should license?  It looks like  
the same things can be done with LEX, YACC, PLY, etc.

#  Steve


The basic idea is that it would be significantly easier to implement and  
maintain a language using uCalc Language Builder instead of Lex / Yacc.
 
Lex / Yacc is everywhere you turn, and I've done some reading on it.   But I 
must admit that I haven't actually used it myself to build a  language.  From 
what I understand, creating a language with Lex / Yacc  requires multiple 
stages.  You feed a definition file to the Lex  program.  You feed more code to 
the separate Yacc program.  There  might be some additional intermediate steps 
(maybe even including further code  adjusted by hand), after which you compile 
the final source code before you have  an interpreter you can run.
 
As I've mentioned, I haven't done a language with Lex / Yacc.  So I  may be 
missing something.  I'd like to turn the question around and ask if  someone 
can point me to how I'd go about creating Lisp (CL, Scheme, or whatever  
interesting variation) with Lex / Yacc.  This is not a rhetorical question,  as I'd 
really like to look at a Lex / Yacc implementation of Lisp (or maybe  Forth), 
so I can compare it with what I've done in uCalc.
 
Meanwhile, here's how it is done with uCalc Language Builder, which I think  
should be much easier.  First, you skip all these multi-stage steps  mentioned 
above.  Splitting source code into tokens etc is interesting,  though I don't 
see why the programmer needs to concern herself with such  details.  With 
uCalc, you end up writing less code to define the language,  which can all be 
placed in the same file (if you want) and can be loaded  all in one step.  
Definitions consist of syntax closely coupled with  matching semantics.  This makes 
it easier to get the whole picture by  glancing at the language definition 
code.
 
When I look at the tutorial or manual for a programming language, I think  to 
myself that it would be nice if I could reproduce a working version of that  
language simply by pasting the syntax that's presented in front of me, 
followed  by a little bit of code representing what the documentation says this 
syntax  represents.  I'd move along to the next page of the tutorial, and do  the 
same until I reached the end, at which point I'd have a working  implementation 
of that language, with which I could run the examples found in  the tutorial. 
 (Actually I'd be able to run the tutorial examples up to  each chapter I've 
reached so far).
 
I implemented my version of Common Lisp pretty much that way, as I went  
through the tutorial at mypage.iu.edu/~colallen/lp (I did occasionally jump to  
other sections of the tutorial, and visited sources elsewhere for further  
details, and went back and revised things, but overall all it was constructed as  I 
more or less sequentially made my way through the tutorial).  I did  
something similar with Forth, using the tutorial found at 
_www.softsynth.com/pforth/pf_tut.htm_ (http://www.softsynth.com/pforth/pf_tut.htm)  .   Basically, if you 
look at the short Lisp.uc file, which contains the source code  for my Lisp 
implementation, you'll see for instance a line that starts  with:
 
(if {test} {then})
 
followed by code to the right of it which says what to do when the  
interpreter encounters a line of code such as (if a b).  It is mapped out  to a 
generalized IIF method (defined in Library.uc) that is used in my Basic  
implementation as well, though the Basic syntax that maps onto it is entirely  different.  
Since IF can also optionally have an {else} clause in Lisp,  you'll find 
another definition line that starts with:
 
(if {test} {then} {else})
 
It also maps onto the same IIF method (though in the other case, the  
non-existant {else} clause is ignored).  Things are highly  bootstrapped.  So using 
this same way of defining a syntax, other Lisp  constructs such as "and", "or", 
and "cond" are defined, and mapped onto this new  (if) function.  The whole 
Lisp definition is done in less than 200  lines of code.  It's not a full 
implementation, but captures the  essence of the language and can easily be 
expanded.  For the most part,  every line you look at gives you a sense of what a 
given syntax should look  like, and what it should do.
 
You can visit _www.ucalc.com/newbeta.html_ 
(http://www.ucalc.com/newbeta.html)  and  download the beta and inspect Lisp.uc, and even run it if you're under 
Windows  (run Lisp.Bat, or else run uCalc.Exe, and load the Lisp.uc file).
 
You mentioned PLY.  Since its goal is to be faithful to the  traditional Lex 
/ Yacc way of doing things, I assume that whatever I said  concerning Lex / 
Yacc applies pretty much to PLY as well.
 
Daniel  Corbier
uCalc Language  Builder
www.ucalc.com




************************************** AOL now offers free email to everyone. 
 Find out more about what's free from AOL at http://www.aol.com.