mkvsynth/mkvsynth — pull request #8 by lukechampine (2014-01-12 02:39:09+00:00)
Title: Language overhaul

These changes implement a significant overhaul of both the Mkvsynth scripting language and its interpreter, delbrot.

Major changes:
- New language syntax. Check out [documentation.md](https://github.com/lukechampine/mkvsynth/blob/newlang/delbrot/documentation.md) for the full specification.
- Operator precedence works now. It's hard to believe (and a bit embarrassing), but the current interpreter will evaluate `1 + 2 * 3` as `9`.
- Boolean type added. Only booleans can be used in conditional expressions, as opposed to the C convention of non-zero == True.
- Ternary expressions added, along with some additional syntactic sugar that allows you to construct guard-like expressions.
- Assert statements added. `printf`-style syntax is planned.
- Optional argument support greatly improved. User-defined functions now support optional arguments, which can be set using the `default` statement.
- Functions that do not encounter a `return` statement now return an empty function node. Avisynth's approach (returning the last evaluated expression) is tempting, but I feel that it's convenient at best and confusing at worst. I'm open to debate on this issue.
- Variable lookups no longer recurse to their parent environment. The justification for this is that because the language lacks a `var` keyword, there's no way to distinguish between a local variable declaration (e.g. `x = 12`) and a statement that modifies a global variable (e.g. `x = 12`). In practice, I don't think this will be a big deal, since you can always pass in global vars as arguments. Avisynth has the `global` keyword, but I don't think it fully solves the problem. I'm open to debate here as well.
- Removed `for` loops, `while` loops, and the increment/decrement operators. Turns out these aren't very useful for our purposes.
- `go()` is now called automatically at the end of every script (it can still be called anywhere else as well). Scripts that do not queue up any filters should not be affected, though I haven't been able to test this myself. (@DavidVorick?)

Possible future steps:
- Make functions first-class citizens, allowing constructs such as closures and higher-order functions. This would be possible, but it seems like a hairy problem any way I look at it. I'm not sure if the language would really benefit from it.
- Add a new `=>` operator, combining the chaining and assignment operators. When I was converting the old unit tests, I saw a lot of statements of the form `a = crop(a, 5, 5, 5, 5)`, which would be converted to `a = a -> crop 5 5 5 5`. The `=>` operator would allow you to condense that to `a => crop 5 5 5 5`, which IMHO preserves the original meaning fairly well.
- An `eval` function for evaluating a string as code. Avisynth has this, but mainly people seem to use it with the ternary expression to simulate if/else blocks, which isn't a problem for us. I'm not sure how I would go about implementing this, though I'm sure it's possible.