Open Magnogen opened 2 years ago
Yeah I had considered loop { ... }
because that's also the syntax used in other languages. The choice for loop;
is mostly aesthetics, as I don't want it to look too similar to a for
loop, because then it begs the question why it isn't. Whereas loop;
is more symmetric with goto end;
in that both are "jump statements" instead of language constructs.
Additionally, the current syntax gels well with if
statements:
if x == y
{
// some other code
loop;
}
is allowed, so you don't need to do this:
if x == y
{
loop {
// some other code
}
}
But I like your idea of using a label at the start of a codeblock to signify that it loops. What do you think of this?
{
increment:
// some other code
goto increment;
}
The reason I put the label inside the braces is that goto
statements are currently not allowed to jump backwards, but "a goto
at the end of a block may jump to a label at the start of that block" could be a nice exception to that rule, given that the label's scope starts and ends at the {
.
That's some great reasons, I can understand your thought process. Why can't gotos jump backwards? Is it like a lint bug, that can easily result in infinite loops, so it's banned altogether?
Love what you're doing with this language too btw, I've been intrigued by gotos ever since I read about them in the goto Design Note on Crafting Interpreters, which also has a really tidy use case for goto as well.
The main reason is to try to keep the code understandable. Early return and breaking out of a nested loop are two valid use cases for gotos, and they both only require jumping forward. I think backwards jumps, especially when they cross eachother like
// ...
a:
// ...
{
b:
// ...
if x == y
goto a;
}
// ...
if u == v
goto b;
get very unintuitive very quickly.
Jumps that are not attached to their own scopes (like for
and if
are) also introduce semantical issues that other language constructs don't really have. Although I'll admit I didn't really think about them until after I settled on goto
and loop
. Take the following example:
var x = foo();
var p: &i32 = &x;
foo:
var y = x + 1;
if x == 0
{
&p = &y;
x = x + 1;
goto foo;
}
This is perfectly valid if foo()
returns something other than 0, but what does it mean for var y = x;
to be executed twice? And what value does p
point to in that case? I assume in practice a C compiler will put y
in the same place on the stack twice, so it will "work", but it doesn't feel great. At least with
var x = foo();
var p: &i32 = &x;
{
var y = x + 1;
if x != 0
goto end;
&p = &y;
x = x + 1;
loop;
}
end:
you can point to the }
where the scope of y
ends and say that the line &p = &y;
is invalid or UB.
Anyway that's just me rambling. Glad that you like the language.
That's a really interesting thought process, I never thought about combine scopes with gotos before, it kind of makes sense, but at the same time, I kind of doesn't.
I supppose with the loop syntax you currently have (as opposed to using a goto to explicitly go back) makes a lot more sense with scoping, but if the user were to try and explicitly go back for whatever reason and result in defining y
again, it would usually result in an error, like this program:
var x = foo();
var p: &i32 = &x;
var y = x + 1;
if x == 0
{
&p = &y;
x = x + 1;
var y = x + 1;
// Error: "y" is already defined
if x == 0
{
&p = &y;
x = x + 1;
// more nested 'iterations'
}
}
And that's essentially how the goto would work from another perspective.
And creating a whole new "call frame" for each goto is definitely not the way to go, but that would solve this problem.
Certainly an interesting conundrum. And you're welcome! ^^
At the moment, you'd need to scan down to the end of a block to see if it
loop
s, whereas with anif
, you can tell right from the start that the following scope can have a possibly of not running, as well as what condition is required to make it do so.Perhaps instead of putting the
loop;
at the end of the block, it would be easier to read putting it near the start. Perhaps something like:(example taken from your readme).
Another option is, instead of using
loop
, you could instead use the wordforever
as it gives more of an idea as to what happens.I can understand why not though, as
goto
statements go at the end of the code to repeat. But then again if that's the case, why not use this syntax and remove loop altogether?