Syn

How is this different from the LISP and scheme macro system? The
program source is available to the programmer at both compile and
run-time and may be operated on arbitrarily (transforming code, adding
code, removing code, specializing code, making new "primitives",
modifying other macros, etc). There is a reason for LISP's syntax, it
is so you can program arbitrary semantics on top of it. [...]

Andrew

  I'm not familiar with Scheme specifically, but just from my general
knowledge of Lisp:

  Syn essentially _is_ Lisp, with a couple of minor exceptions:

  - The universal datatypes, rather than being car/cdr tuples and
      atoms, are parse-tree nodes and atoms. This difference is
      almost meaningless, since, for instance, many parsers
      represent their parse trees in Lisp-like lists already...

  - Unrecognized constructs are expanded as if they were functions
    that evaled to themselves -- which is to say, their children
    _are_ evaled, and then the results are re-assembled as a clone
    of the parent using the evaled children. This means you can
    send in a quite large and complicated data structure, and only
    the "recognized" functions, wherever they lie, will be evaled,
    while the rest is left alone. (Does Lisp or Scheme do this? I'm
    not sufficiently familiar.)

  - There's a stateful primitive which makes it easy to generate
      unique names that are consistent within the scope of a single
    macro expansion/function invocation. (This isn't really
    possible in a pure functional language, nor would it be
    necessary if not for the fact that the parse tree
    itself--largely unevaluated--is destined to be the final
    output.)

  Really, that's about it for differences. But the point isn't meant
to be that Syn is better or different than Lisp -- rather, it's just a
way of using a Lisp-like language to do something neat. I could pitch
the whole thing as: here's something cool that can be done with Lisp,
and just leave Syn out of it. And that pitch would go something like:

  - Make it easy for people to specify their own syntax (or modify/
    extend existing ones), and have the parser just output a parse
    tree as a Lisp data structure.

  - Allow a single project to support multiple syntaxes (which is easy
    since they're all just converted to a universal parse tree
    format by the parser).

  Surprisingly, at this point you've actually got quite a powerful
system, assuming you're ultimately programming to Lisp as your back end,
because you can now introduce new syntactic constructs that express high
level concepts well, and can specify their semantics in any lower level
syntax. This can be layered to good effect. But one final
consideration is:

  - Either allow pass-through of non-recognized functions, or write a
    set of functions which are effectively pass-through for the parse
    tree components of some other target language (i.e., not Lisp).

  Now you can use Lisp to implement layers of higher-level syntax and
associated semantics for some other, non-Lisp target language, like
LLVM. Normally one wouldn't think of coding directly to LLVM, but with
this approach it's actually quite quick and easy to implement each
successive level of abstraction, so you're programming in some
high-level language next thing you know, even though it's all really
just "macros" up from LLVM.

  What I'm describing ultimately is effectively an approach to writing
a compiler, but it's an approach that's sufficiently simple and
transparent as to make it practical to expose it at the individual project
level--i.e., such that it's normal and reasonable to, effectively,
modify the compiler itself in order to best support the needs of one
particular project (or, more likely, one particular class of projects).
And it also has the side effect of keeping all run-time semantic support
implemented in the target language (LLVM) in a way that opens up a lot
more optimization opportunities than one would normally get without some
specific effort.

  What it all comes down to is: you shouldn't ever have to envy
another language's higher level constructs, you should be able to
implement whatever you like. There are always limitations imposed
by the core execution model (imperative vs. declarative vs. relational,
for instance), but within a single family, the Syn approach should pretty
much let you have it all. LLVM plus the Syn approach seems like a natural
"univeral imperative language". The Syn approach straight down onto
Lisp might be a good universal functional language. And so on. I'm
pretty sure you could even use it meaningfully on top of Prolog...

  Anyway, hope this answers your Q.

  -Simon