forked from glen/fostr
132 lines
3.4 KiB
Cheetah
132 lines
3.4 KiB
Cheetah
module basic
|
|
language fostr
|
|
|
|
/** md
|
|
Title: A whirlwind tour of fostr
|
|
|
|
## Whirlwind tour
|
|
|
|
fostr is just in its infancy, so it's not yet even ready for
|
|
Hello, World. The best we can offer now is this little snippet
|
|
that writes the sum of the ASCII codes for 'H', 'W', and '!' to standard output:
|
|
```fostr
|
|
**/
|
|
|
|
/** md */ test emit_sum [[
|
|
stdio << 72 + 87 + 33
|
|
]]/* **/ parse to TopLevel(Receives(Stdio(),
|
|
Sum([Int("72"), Int("87"), Int("33")])))
|
|
/** writes
|
|
192**/
|
|
|
|
/** md
|
|
```
|
|
|
|
At the moment, there are only two ways to run a file containing fostr code
|
|
(you can find the above in `tests/emit_sum.fos`). They both start by
|
|
cloning this fostr project. Then, either:
|
|
|
|
1. Open the project in Eclipse and build it, visit your program file,
|
|
generate code from it in your preferred target language (among
|
|
the options available in the "Spoofax > Generate" menu), and execute the
|
|
resulting code.
|
|
|
|
1. Use the `bin/fosgen` bash script to generate code in a target language,
|
|
and execute the resulting code.
|
|
|
|
For example, this snippet generates the following Python:
|
|
```python
|
|
{! ../tests/emit_sum.py extract:
|
|
start: 'Stdio\s='
|
|
!}
|
|
```
|
|
(which writes "192" to standard output), or this non-idiomatic, inefficient, but
|
|
working Javascript:
|
|
```javascript
|
|
{! ../tests/emit_sum.js extract:
|
|
start: '^}'
|
|
!}
|
|
```
|
|
In either case, there's also a preamble defining Stdio that's generated.
|
|
(Haskell code generation is also currently supported.)
|
|
|
|
### Everything has a value
|
|
|
|
As mentioned in the [Introduction](../README.md), everything in a fostr
|
|
program (including the entire program itself) is an expression and has
|
|
a value. So what's the value of that expression above? Well, `stdio` is our
|
|
first example of a stream, and for convenience, the value of a stream
|
|
receiving an item is just the stream back again. The `<<` operator is also
|
|
left-associative, so that way we can chain insertions into a stream:
|
|
```fostr
|
|
**/
|
|
|
|
/** md */ test emit_twice [[
|
|
stdio << 72 + 87 + 33 << 291
|
|
]]/* **/ parse to TopLevel(
|
|
Receives(Receives(Stdio(), Sum([Int("72"), Int("87"), Int("33")])),
|
|
Int("291")))
|
|
/** writes
|
|
192291**/
|
|
|
|
/** md
|
|
```
|
|
Running this program produces a nice palindromic output: "192291".
|
|
|
|
And because sometimes you want to emphasize the value and propagate that
|
|
instead of the stream, you can also write these expressions "the other way"
|
|
with `>>`; both forms return the first argument:
|
|
```fostr
|
|
**/
|
|
|
|
/** md */ test enters_twice [[
|
|
(7 + 8 >> stdio + 9) >> stdio
|
|
]]/* **/ parse to TopLevel(
|
|
Enters(Sum([Int("7"), Enters(Int("8"), Stdio()), Int("9")]), Stdio()))
|
|
/** writes
|
|
824**/
|
|
|
|
/** md
|
|
```
|
|
|
|
### Layout in fostr
|
|
|
|
Expressions may be laid out onto multiple lines, as long as all continuation
|
|
lines are indented from the start of the initial line:
|
|
```fostr
|
|
**/
|
|
|
|
/** md */ test receive_enter_break [[
|
|
stdio <<
|
|
7
|
|
+ 8 >> stdio
|
|
+ 9
|
|
]]/* **/ parse to TopLevel(
|
|
Receives(Stdio(), Sum([Int("7"), Enters(Int("8"), Stdio()), Int("9")])))
|
|
/** writes
|
|
824**/
|
|
|
|
/** md
|
|
```
|
|
(So for example you will get a parse error with something like this:)
|
|
```fostr
|
|
**/
|
|
|
|
/** md */ test enter_receive_bad_break [[
|
|
(7 + 8 >> stdio + 9)
|
|
>> (stdio << 9 + 2)
|
|
]] /* **/ parse fails
|
|
|
|
/* Extra tests not in the tour */
|
|
test enter_receive [[
|
|
(7 + 8 >> stdio + 9) >> (stdio << 9 + 2)
|
|
]]/* **/ parse to TopLevel(
|
|
Enters(Sum([Int("7"),Enters(Int("8"),Stdio()),Int("9")]),
|
|
Receives(Stdio(),Sum([Int("9"),Int("2")]))))
|
|
/** writes
|
|
81124**/
|
|
|
|
/** md
|
|
```
|
|
**/
|