Comments (7)
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
from porth.
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.
from porth.
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.
from porth.
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.
from porth.
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.
from porth.
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.
from porth.
Other examples:
macro repeat \
while dup 0 < do \
1 - \
end
5 repeat
"test\n" 1 1 syscall3 drop
end
from porth.
Related Issues (20)
- Type checking of swap/over/etc.
- Macro naming convension for porth.porth
- Invalid syntax with MEM_CAPACITY = 640_000 HOT 3
- Parity error between numbers in simulation and compilation HOT 1
- [DISC] Take into account PRs with porth code that's unrelated to the main compiler HOT 3
- Do you consider porth to have a packaging and published on pypi? HOT 3
- Discrepancy between com and sim modes for handling utf-8 characters. HOT 2
- Produce less jump points to enable optimization HOT 2
- I translated the `porth sim` to Go.
- Unable to use control flow in macros HOT 3
- run `porthy.py com -r` can be dangerous if the user do not send the correct `file_path`
- Supporting Intrinsic `LOAD` and `STORE` 64 bit values HOT 5
- `compile_tokens_to_program` there's no need to reverse the tokens HOT 2
- `porth sim` and `porth com -r` diverges in code execution HOT 6
- [FEATURE REQUEST] make std.porth accesible anywhere when you move it to `/usr/include/porth/*.porth` or `/usr/include/*.porth` HOT 1
- macros are TOO safe HOT 7
- Discussions HOT 1
- compiling code is not working HOT 4
- typo
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from porth.