Recently, I got my first egg script running. Here it is:
var s = 0;
for (var i = 0; i < 100; ++i) {
s += i;
}
print(s);
You'll be unsurprised to hear that this printed out "
4950" (it was a pleasant surprise to
me when it first happened, though, I can tell you!)
There are three things worth mentioning in this script.
Firstly, the "
var" keyword initiates type inference for variables "
s" and "
i". In both cases, "
int" is inferred (there are no unsigned integers in egg).
Secondly, the "
print" function is a built-in method that will probably be removed, but is useful for testing, at the moment.
Finally, the syntax of "
for" statements turns out to be non-trivial. Like C++, I adopted two forms:
for (before ; condition ; step) { ... }
for (iterator : collection) { ... }
The latter form is for iterating around collections, which we won't discuss here.
My main concern with the former form of the "
for" loop is:
Which syntactic elements are valid for "before", "condition" and "step"?
The easiest of the three clauses is "
condition". It's optional, but I only allow expressions that evaluate to Boolean values. This is similar to all the main curly-brace languages (C/C++/Java/JavaScript).
The "
before" statement is also optional, but it must be a statement. This includes variable declarations: the scope of such variables is limited to the "
for" statement, including the "
condition" and "
step" clauses. Again this is similar to the other languages (if we ignore JavaScript's problematic scoping rules).
The "
step" statement is optional too, but cannot be a declaration. As mentioned previously, the increment and decrement operators are supported in egg purely to allow the classic for-loop idiom seen in this example.
But then I got a bit confused with which egg statements should be valid for "
before" and "
step". Can you use "
break" and "
continue"? If so, what do they do?
So I asked my C++ compiler, and it says that I cannot use "
break" or "
continue", but I can "
throw" exceptions. The reason you cannot "
break" or "
continue" in "
before" and "
step" clauses is because those statements are just that:
statements. The "
before" and "
step" clauses in C++ expect C++
expressions.
But why can you "
throw" exceptions in those clauses in C++?
for (auto i = 0; i < 100; throw "Bang!") {} // Valid C++
Well, it turns out that what
I think of as throw
statements are actually throw
expressions (of type "
void") in the
formal syntax. It's a cul-de-sac that
others have found themselves in too!
As egg is meant to be an easy-to-learn language, with few surprises, I decided to classify "
throw" as a statement and explicitly forbid it in expressions and "
before" and "
step" clauses of "
for" statements.