OT: Ultimate Language Syntax Cleanness Comparison

Kaz Kylheku kaz at ashi.footprints.net
Mon Feb 10 19:18:16 EST 2003


holger krekel <pyth at devel.trillke.net> wrote in message news:<mailman.1044895117.5567.python-list at python.org>...
> Jeremy Fincher wrote:
> > holger krekel <pyth at devel.trillke.net> wrote in message news:<mailman.1044877956.27600.python-list at python.org>...
> > > If so can you send the snippet which parses *any* perl script? 
> > > If your deduction above is true, then it should be easy.
> > 
> > You originally claimed, "All the methods involve evaluating/executing
> > it at the same time."  I showed you that Perl's abstract syntax tree
> > (which is constructed by the code generated from perly.y in addition
> > to some other arcane machinery) is absolutely different from the
> > bytecode (an example of which is shown in bytecode.pl), which is
> > actually executed.
> 
> That sharp distinction is still a claim.  Pointing to some files 
> doesn't prove your point but example code does.  In python i do
> 
> >>> import compiler
> >>> p=compiler.parseFile('test.py')    
> >>> p                                    # Parse tree
>  Module(None, Stmt([Printnl([Const('hello world')], None)]))
> >>> p.filename='test.py' # fixup
> >>> c=compiler.pycodegen.ModuleCodeGenerator(p).getCode()
> >>> c
>  <code object <module> at 0x828a720, file "test.py", line 2>
> >>> exec c
>  hello world
> >>>

In Lisp, we do:

  (defvar *s* (with-open-file (f "foo.lisp") (read f)))

  *s*  ==>  (write-line "hello") 
  ;; the ``parse tree'' looks exactly like what is in foo.lisp

  (defvar *c* (compile nil `(lambda () ,*p*))

  *c*  ==>  #<compiled-closure ...>

  (funcall *c*)
  hello

Note the big differences. The (read s) reads the expression from the
file, producing a list object. This is just the reader at work, no
compiling is involved, just lexical analysis of tokens, and a
rudimentary parsing of the nested list structure. The same thing would
be done to read some structured data that is not intended to be code
at all.

That list object is already an abstract syntax tree, which we can
manipulate in straightforward ways. In Lisp, source *is* the syntax
tree; there is no meat-grinding, one-way transformation from one to
the other.

One manipulation we do with the syntax tree in this example is to
insert it into a (lambda ...) form to create the source code of a
function whose body incorporates that expression. The backquote syntax
helps here to make the insertion visually obvious: `(lambda () ,*p*)
-- insert the value of *p* at the end of the (lambda ...) list.

We could do other transformations or validations, like walking the
tree to verify that it conforms to a sandboxed subset of the language.

In any case, the resulting *data structure* is then fed into the
compiler, rather than raw text. Data structures are the source code;
text is just a printed notation for the data structure.

In the above, we could replace reading from a file by list
construction:

  ;; piece together data representing source code, then 
  ;; compile it to a function-object and call it.
  (let ((body (list 'write-line "hello")))
    (funcall (compile nil (list 'lambda () body))))

We now return you to the previously scheduled Perl bashing.




More information about the Python-list mailing list