I'm working on a Lisp variant that recognizes the difference between expressions and... non-expressions? But taking the opposite approach: I found a way to make it so that everything is an expression while allowing one to do everything you would do with a non-expression via expressions. To achieve this, there are two kinds of expression: mutations and functions.
There are two things to understand about this:
1. All expressions take in the environment. Most functions don't use it, while most mutations do.
2. All expressions run inside a trampoline that evaluates them. The difference between a mutation and a function is that when the trampoline evaluates a function, it places its result into the return register (where it can be picked up by something else). In contrast, when the trampoline evaluates a mutation, it replaces the environment with the result. This is why mutations typically use the environment--rather than destroying the environment, you usually want to build the new environment with most of the old environment.
Some examples:
((mut () env (assoc env :foo 1))) ; equivalent to (define foo 1)
((mut () env
(assoc env :my-define (mut (dest src) env (assoc env dest src)))))
; this is actually how `define` is defined
((mut () env (map)))
((+ 1 1)) ; throws exception "undefined symbol +" because previous line emptied the environment
I think "statements" is the usual term, with "sentences" being the general term which encompasses both (a "sentence" in this context is something recognized by your formal grammar).
Can your Lisp variant handle unrestricted continuations?
I must admit I have no idea what an unrestricted continuation is. I'm not an academic, just a guy writing a lisp on his spare time.
Here's what I'm doing with continuations:
At the bytecode level, call/cc is trivial to implement given my current design. All you need is the current instruction pointer, the current environment (environments right now are just immutable A-lists), and the current return pointer. But it's not obvious to me how to translate call/cc from the syntax to the bytecode.
Tail call elimination is the next thing I'm implementing, and unless there's something wrong with my design I haven't noticed yet, it won't be hard to do. Another step to take down that direction, though, is adding a pass transforming to continuation-passing style. I think this is going to be one of the last things I do, because I'd like to explore other optimizations so I can compare performance.
Where are the terms used like that? I've only seen statement used as "a thing you do", with expression "a thing that evaluates", and optional conversion in each direction.
I'm not sure what you mean by sentences being "recognized" by the grammar. Keep in mind that there are languages where only a series of 'statements' is allowed, no freestanding expressions.
I'm working on a Lisp variant that recognizes the difference between expressions and... non-expressions? But taking the opposite approach: I found a way to make it so that everything is an expression while allowing one to do everything you would do with a non-expression via expressions. To achieve this, there are two kinds of expression: mutations and functions.
There are two things to understand about this:
1. All expressions take in the environment. Most functions don't use it, while most mutations do.
2. All expressions run inside a trampoline that evaluates them. The difference between a mutation and a function is that when the trampoline evaluates a function, it places its result into the return register (where it can be picked up by something else). In contrast, when the trampoline evaluates a mutation, it replaces the environment with the result. This is why mutations typically use the environment--rather than destroying the environment, you usually want to build the new environment with most of the old environment.
Some examples:
The "everything takes env" bit is inspired by J. Shutt's paper on his Kernel programming language: https://www.wpi.edu/Pubs/ETD/Available/etd-090110-124904/unr... and a lot of what I'm working on is built on his work.