-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update esterel-rhombus-lib and add examples, tests, and documentation for Rhombus Esterel #9
Open
ellifteria
wants to merge
11
commits into
rfindler:main
Choose a base branch
from
ellifteria:squashing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
3e861a1
Fix bugs in Rhombus implementation and add features from Racket
ellifteria aad0fce
Fix signal definition, signal value, react issues; add some tests for…
LLazarek 7db12ff
tab-bar example is working
LLazarek 2933fa9
Continue adding features from Racket implementation
ellifteria b7c0cb9
examples: add rhombus version of traffic light
LLazarek aaccea4
Fix rhombus is_present
ellifteria 1593ea4
Add into_par reducer macro, but it can't be exported?
LLazarek ce2feb3
Begin adding rhombus tests
ellifteria 0954501
examples: update traffic-light.rhm to use rhombus pict
LLazarek 6820860
Prepare Rhombus Esterel for merging
ellifteria 8e3d0f9
Begin Rhombus Esterel documentation
ellifteria File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
*~ | ||
compiled/ | ||
.DS_Store | ||
**/.DS_Store | ||
**/doc/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,324 @@ | ||
#lang scribble/rhombus/manual | ||
|
||
@(import: | ||
meta_label: | ||
rhombus open | ||
esterel/full open) | ||
|
||
@title{Rhombus Esterel Reference} | ||
|
||
@docmodule(esterel/full) | ||
|
||
The @rhombusmodname(esterel/full) Rhombus library is built on the Racket @racketmodname(esterel/full) library. | ||
As in the Racket @racketmodname(esterel/full) library, it provides all of the names documented here as well as the names documented in @rhombusmodname(esterel/kernel). | ||
|
||
@(def esterel_full_eval = make_rhombus_eval()) | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
~hidden: | ||
import: | ||
esterel/full open | ||
) | ||
|
||
@doc(fun halt()){ | ||
Pauses in every instant, forever. | ||
} | ||
|
||
@doc( | ||
fun sustain(s) | ||
fun sustain(s, v) | ||
){ | ||
Emits @rhombus(s) and pauses in every instant, forever. | ||
|
||
As with @rhombus(emit), if @rhombus(s) is a valued signal, | ||
two arguments must be supplied and if @rhombus(s) is not a | ||
valued signal, two arguments may not be supplied. | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S, T ~combine (fun (x, y): x + y)] | ||
def strl: | ||
esterel: | ||
sustain(S) ||| sustain(T, 8) | ||
~check: | ||
react(strl) | ||
~is {S: #true, T: 8} | ||
~check: | ||
react(strl) | ||
~is {S: #true, T: 8} | ||
~check: | ||
react(strl) | ||
~is {S: #true, T: 8} | ||
) | ||
} | ||
|
||
@doc( | ||
expr.macro 'loop: | ||
$body | ||
... | ||
~each $restart' | ||
expr.macro 'loop: | ||
$body' | ||
){ | ||
In the first form, runs @rhombus(body) over and over. | ||
In the second form, starts by running @rhombus(body) and then @rhombus(halt)ing. | ||
Restarts @rhombus(body) when @rhombus(restart) becomes true. | ||
|
||
For example, this program emits @rhombus(S1) in every instant that @rhombus(S2) is not present. | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S1, S2] | ||
def strl: | ||
esterel: | ||
loop: | ||
emit(S1) | ||
~each !is_present(S2) | ||
|
||
~check: | ||
react(strl) | ||
~is {S1: #true} | ||
~check: | ||
react(strl) | ||
~is {S1: #true, S2: #false} | ||
~check: | ||
react(strl, ~emit: [S2]) | ||
~is {S2: #true} | ||
~check: | ||
react(strl, ~emit: [S2]) | ||
~is {S2: #true} | ||
~check: | ||
react(strl) | ||
~is {S1: #true, S2: #false} | ||
~check: | ||
react(strl) | ||
~is {S1: #true, S2: #false} | ||
) | ||
} | ||
|
||
|
||
@doc( | ||
expr.macro 'abort: | ||
$body ... | ||
~when $when ...' | ||
expr.macro 'abort ~weak: | ||
$body ... | ||
~when $when ...' | ||
expr.macro 'abort ~weak: | ||
$body ... | ||
~when_immediate $when ...' | ||
){ | ||
Terminates when @rhombus(body) terminates or when @rhombus(when) returns a true value. If @rhombus(~weak) is present, the @rhombus(body)s are executed when @rhombus(when) is true; they are skipped if @rhombus(~weak) is not present. | ||
If @rhombus(~when) is used, the @rhombus(body)s are executed at least once and the @rhombus(abort) runs for at least one instant; if @rhombus(~when_immediate) is used, the @rhombus(when) is tested in the first instant and the expression terminates in the first instant if @rhombus(when) returns a true value. | ||
|
||
For example, this repeatedly emits @rhombus(S1) until @rhombus(S2) is present, in which case the entire loop terminates and we fall through to the emit of @rhombus(S3). | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S1, S2, S3] | ||
def strl: | ||
esterel: | ||
abort: | ||
block: | ||
fun Loop(): | ||
emit(S1) | ||
pause | ||
Loop() | ||
Loop() | ||
~when is_present(S2) | ||
emit(S3) | ||
~check: | ||
react(strl) | ||
~is {S1: #true} | ||
~check: | ||
react(strl) | ||
~is {S1: #true, S2: #false} | ||
~check: | ||
react(strl) | ||
~is {S1: #true, S2: #false} | ||
~check: | ||
react(strl, ~emit: [S2]) | ||
~is {S2: #true, S3: #true} | ||
) | ||
|
||
If @rhombus(S2) had been present in the first instant, that program would not have terminated in the first instant, but in the second: | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S1, S2, S3] | ||
def strl: | ||
esterel: | ||
abort: | ||
block: | ||
fun Loop(): | ||
emit(S1) | ||
pause | ||
Loop() | ||
Loop() | ||
~when is_present(S2) | ||
emit(S3) | ||
~check: | ||
react(strl, ~emit: [S2]) | ||
~is {S1: #true, S2: #true} | ||
~check: | ||
react(strl, ~emit: [S2]) | ||
~is {S2: #true, S3: #true} | ||
) | ||
|
||
To terminate in the first instant, use @rhombus(~when_immediate), so that the @rhombus(when) is evaluated in the first instant. | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S1, S2, S3] | ||
def strl: | ||
esterel: | ||
abort ~weak: | ||
block: | ||
fun Loop(): | ||
emit(S1) | ||
pause | ||
Loop() | ||
Loop() | ||
~when_immediate is_present(S2) | ||
emit(S3) | ||
~check: | ||
react(strl, ~emit: [S2]) | ||
~is {S1: #true, S2: #true, S3: #true} | ||
) | ||
|
||
However, note that @rhombus(~when_immediate) requires @rhombus(~weak), so @rhombus(S1) is also emitted. | ||
} | ||
|
||
|
||
@doc( | ||
expr.macro 'await $when ...' | ||
expr.macro 'await $when ... ~n $n ...' | ||
expr.macro 'await ~immediate $when ...' | ||
){ | ||
In the first form, @rhombus(pause)s until @rhombus(when) returns a true value, but at least one instant. | ||
In the second form, @rhombus(pause) until @rhombus(when) returns a true value @rhombus(~n) times. | ||
In the third form, the value of @rhombus(when) is tested in the first instant, and thus the @rhombus(await) might terminate immediately. | ||
|
||
For example, this program waits two instants before emitting @rhombus(S1). When that happens, the @rhombus(await) terminates and thus so does the @rhombus(par), leading to the emission of @rhombus(S2). | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S1, S2] | ||
def strl: | ||
esterel: | ||
par | ||
| pause | ||
pause | ||
emit(S1) | ||
| await is_present(S1) | ||
emit(S2) | ||
~check: | ||
react(strl) | ||
~is {} | ||
~check: | ||
react(strl) | ||
~is {S1: #false} | ||
~check: | ||
react(strl) | ||
~is {S1: #true, S2: #true} | ||
) | ||
|
||
As an example of the second form, this program emits @rhombus(S2) in the fifth instant; it pauses for three instants where @rhombus(S1) was present and two where it is not. | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S1, S2] | ||
def strl: | ||
esterel: | ||
await is_present(S1) ~n 3 | ||
emit(S2) | ||
~check: | ||
react(strl) | ||
~is {} | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true} | ||
~check: | ||
react(strl) | ||
~is {S1: #false} | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true} | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true, S2: #true} | ||
|
||
) | ||
|
||
As an example of the third form, this program emits @rhombus(O) in the first instant, as both of the @rhombus(await)s terminate in the first instant. | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S, O] | ||
def strl: | ||
esterel: | ||
await ~immediate !is_present(S) | ||
await ~immediate !is_present(S) | ||
emit(O) | ||
~check: | ||
react(strl) | ||
~is {S: #false, O: #true} | ||
) | ||
} | ||
|
||
@doc( | ||
expr.macro 'every $s ...: | ||
$body' | ||
expr.macro 'every $s ... ~n $n ...: | ||
$body' | ||
expr.macro 'every ~immediate $s ...: | ||
$body' | ||
){ | ||
In the first form, @rhombus(await)s @rhombus(s) evaluating to a true value and then starts running the @rhombus(body); when whenever @rhombus(s) becomes true, restarts @rhombus(body). | ||
The second form is similar to the first, except that it waits for @rhombus(s) to be true @rhombus(n) times before restarting @rhombus(body). | ||
In the third form, if @rhombus(s) evaluates to a true value in the current instant, the @rhombus(body) is evaluated in the current instant. | ||
|
||
For example, this program emits @rhombus(S2) whenever @rhombus(S1) is present. | ||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [S1, S2] | ||
def strl: | ||
esterel: | ||
every is_present(S1): | ||
emit(S2) | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true} | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true, S2: #true} | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true, S2: #true} | ||
~check: | ||
react(strl) | ||
~is {S1: #false} | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true, S2: #true} | ||
~check: | ||
react(strl, ~emit: [S1]) | ||
~is {S1: #true, S2: #true} | ||
) | ||
} | ||
|
||
@doc(reducer.macro '|||'){ | ||
A reducer used with @rhombus(for), passes values to @rhombus(par). | ||
|
||
@examples( | ||
~eval: esterel_full_eval | ||
def_signal [x, y, z] | ||
def signal_list: [x, y, z] | ||
def strl: | ||
esterel: | ||
for ||| (i: 0..3): | ||
emit(signal_list[i]) | ||
react(strl) | ||
) | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably
doc
should not be ignored (it shouldn't be checked in).