Open IHateYourCode opened 2 years ago
What are the benefits this approach brings to the language? ifSmaller
is bigger than and harder to read than < if
.
Other thing is how macro
should guess that this end
is to close the macro itself and not the if
? Should we introduce a end_macro
keyword?
IMO introducing this kind of syntactic sugar to the language at this point will just make a lot harder to implement the language in itself in the future.
It allows for macros that can extend the head of any block statement, which opens quite a lot of possibilities.
Yes ifSmaller
is longer than < if
and I wouldn't call it that if I were
to use it, that misses the point though. The point is it abbreviates an
expression and makes it more readable, again I 'ifSmaller' was only
and example.
No, I of course wouldn't suggest a separate keyword for that, it's not needed for something like that, there are multiple ways to handle this.
Going by 'macros can only be implemented in top lvl scope' (not sure if nested macros were allowed), you could go by identation, something like:
'Macros can be written as one liners, in which case they end at the
current end of the line or if stretched over multiple lines have to be closed with
the keyword end
and their content has to be indented'
this would force indentation, which isn't nice, tho on the other hand
if you write a macro over multiple lines, not identing isn't something
you should do anyways.
A second approach could be the one C takes, similar one-liner policy but multiline proof through backslashes at the end of each line that should be continued.
Macros aren't anything new, neither is this problem, other languages offer existing, working solutions.
Personally I'd go for the second solutions since it's quite clean if one alines the backslashes.
'at this point will just make a lot harder to implement the language in itself in the future.' For a compiler, integral changes should be made ealier than later, considering how hard it may later become.
I think that this is not really necessary. I don't see myself in a scenario where this would be useful.
Aside from that, I wanted to point out a couple things:
Going by 'macros can only be implemented in top lvl scope' (not sure if nested macros were allowed), you could go by identation
The language isn't indentation based, this isn't python. The language is meant to identify blocks by having a keyword that starts the block (macro
, if
, while
) and having an end
keyword that signifies 'end of the current block'. It's meant to be a simple language, straightforward to lex, parse, and compile. Scope-based macros would be a nice thing if... there were actual reasons to scope them (such as modules inside modules, functions). Macros inside macros aren't possible because the contents of the macro is meant to be a list of tokens.
As for the C approach, I don't have anything to say, except that it breaks the consistency of having block_start
... end
define a comprised list of tokens that the language seems to be following.
As for the C approach, I don't have anything to say, except that it breaks the consistency of having block_start ... end define a comprised list of tokens that the language seems to be following.
Not quite, if you go with the following example code
macro ifTrue \
dup 1 = \
end
You can see that any line that is not supposed to be lexed,
within the macro is followed by a \
. This doesn't remove
the end
keyword, it just helps the compiler know where not
to search for it.
So it starts by seeing the macro
keyword, uses the next token
as the macro name, and following that it checks if the current
line ends with a backshlash. For as long as each next line ends
that way, the compiler ignores the lines (just takes note of them)
and continues.
Once a lines without backshlash appears it starts lexing again,
finding the end
keyword like normal and closing the macro.
Now, in the expansion of the macro, the backslahes are simply
removed, allowing for the content to be lexed.
Other examples:
macro repeat \
while dup 0 < do \
1 - \
end
5 repeat
"test\n" 1 1 syscall3 drop
end
allowing if
or other blocks inside a macro allows to create min
and max
macros:
macro max 2dup > if drop else swap drop end end
macro min 2dup < if drop else swap drop end end
I think that this is not really necessary. I don't see myself in a scenario where this would be useful.
That's as I see right now mostly for ease of the writing code. For example you wanna implementation python-like range and be able to do such thing
1 10 2 for_range
dup print
end drop drop drop
// 1 3 5 7 9
You can do this with partial while
in the for_range
// in: start end step
macro for_range
// end step (start - step)
rot over -
// end step num
while
// end step (num + step)
over +
// step (num + step) end
rot
// end step (num + step) ((num + step) < end)
if 2dup < do
rot rot true
else
rot rot false
end
do
// no `end` for `while`
end
So obviously your code gonna become nightmare if you will just expand this macro by hand every time you want this behaviour (image two nested ranges), and all that is because of impossibility to use partial macros.
Yeah, that not complete implementation of python range, because it doesn't work with negative step, but you got the idea.
'Half' macros like this sadly don't work currently
As far as I can see, the lexer goes through the macro content and actually evaluates the if end sequence instead of ignoring it until all macros are expanded.
Correct me if I'm wrong.