git @ Cat's Eye Technologies beta-Juliet / master
Update README. Chris Pressey 2 months ago
2 changed file(s) with 303 addition(s) and 295 deletion(s). Raw diff Collapse all Expand all
+0
-295
README.markdown less more
0 β-Juliet
1 ========
2
3 β-Juliet is a minimal event-oriented language which, as of version 2.0, is
4 probably Turing-complete.
5
6 NOTE
7 ----
8
9 I've decided that the languages β-Juliet and 2Iota are really too similar
10 to be seperate languages. So, as of this repo, they've been merged like this:
11
12 * This language is called β-Juliet (a.k.a. beta-Juliet).
13 * The language previously referred to as β-Juliet is now β-Juliet 1.0.
14 * The language previously referred to as 2Iota (plus minor modifications) is
15 now β-Juliet 2.0.
16 * The reference interpreter for β-Juliet 2.0 is called `2iota`.
17 * The file extension of a β-Juliet source file is typically `.bj`,
18 although you may see `.2i` used as well. The latter suggests that
19 the source relies on features only in version 2.0.
20 * The optional pre-processor for β-Juliet 1.0 is still called Portia.
21 Portia is not needed with β-Juliet 2.0, and may or may not work with it; I
22 don't know yet.
23
24 Description
25 -----------
26
27 β-Juliet is a fairly minimal event-oriented language. In β-Juliet, the world
28 is modelled as a set of _events_ which have no inherent organization or order.
29 Each event can be denoted with a _symbol_, such as `DominoFalls`, `CatMeows`,
30 or `SunSets`, or (in version 2.0) a string of symbols, such as `Address Line
31 Six Goes High` or `Greengrocer Falls Asleep on Subway`.
32
33 Each event can cause other events to occur — these are termed _consequences_
34 of the event. In addition, this causation may be conditional, but the only
35 condition that is possible to check is: _given two events, which one happened
36 more recently?_
37
38 Example
39 -------
40
41 // Description of a weather-sensitive robot tarpaulin in beta-Juliet
42
43 event RainBegins;
44 event RainEnds;
45
46 event SystemActivated;
47 event SystemDeactivated;
48
49 event CloseTarpaulin,
50 caused after RainBegins when SystemActivated > SystemDeactivated;
51
52 event OpenTarpaulinTimer,
53 duration 10 m,
54 caused after RainEnds when SystemActivated > SystemDeactivated;
55
56 event OpenTarpaulin,
57 caused after OpenTarpaulinTimer.
58
59 Basic Grammar
60 -------------
61
62 The basic grammar of β-Juliet is given here in EBNF. Version 1.0 uses this
63 grammar as it stands; version 2.0 extends many of the productions.
64
65 betaJuliet ::= Decl {";" Decl} ".".
66 Decl ::= Event.
67 Event ::= "event" EventDecl {"," Property}.
68 EventDecl ::= Symbol.
69 Property ::= Caused | Causes | Duration.
70 Caused ::= "caused" TimePrep EventAppl {WhenTerm}.
71 Causes ::= "causes" EventAppl ["immediately"] {WhenTerm}
72 Duration ::= "duration" TimeSpec.
73 TimePrep ::= "before" | "after" | "by".
74 TimeSpec ::= RationalNumber TimeUnit.
75 TimeUnit ::= "ms" | "s" | "m" | "h" | "d".
76 EventAppl ::= Symbol.
77 WhenTerm ::= "when" EventAppl ">" EventAppl.
78 Symbol ::= <<one or more alphanumeric characters>>.
79 Number ::= <<rational number in decimal format>>.
80
81 ### Some Explanations ###
82
83 The syntax `A > B` can be read as "`A` has occurred more recently than `B`".
84 If `A` has occurred but `B` has never occurred, `A > B` is still true;
85 however, if neither event has ever occurred, both `A > B` and `B > A` are
86 false.
87
88 `caused` and `causes` are two equivalent ways of expressing the causality
89 rules between events. If we say one event is `caused by` or `caused after`
90 some other event, that is equivalent to saying the other event `causes` the
91 one event. Similarly, if we say one event is `caused before` some other
92 event, that is equivalent to saying the other event `causes` the one event
93 `immediately`.
94
95 When we define an event like
96
97 event Foo,
98 causes Bar,
99 causes Baz.
100
101 or like this
102
103 event Bar, caused by Foo;
104 event Baz, caused by Foo.
105
106 ...and during execution, after `Foo` happens, it is not guaranteed that
107 either `Baz > Bar` or `Bar > Baz` is true; the order in which these two
108 consequences occur does not necessarily follow source code order. (But it
109 is guaranteed that one or the other will be true, as both events will have
110 happened.)
111
112 If you require an ordering guarantee in a case like this, you should use
113 an intermediate event, like
114
115 event Foo,
116 causes Temp,
117 causes Bar;
118 event Temp,
119 causes Baz.
120
121 After `Temp` happens, `Baz > Bar` should be true.
122
123 ### `caused before` ###
124
125 Alternately, in theory, you can use `caused before`, as in:
126
127 event Bar, caused before Foo;
128 event Baz, caused after Foo.
129
130 After `Foo` happens, `Baz > Bar` should be true.
131
132 Some words on the purpose of `caused before` are in order. In the original
133 vision, `after` and `by` were synonyms, but `before` was meant to actually
134 cause the event on which the `caused before` clause was attached, strictly
135 *before* the event named in the clause.
136
137 However, unless the event being caused can somehow *cancel* the event that
138 it's being caused before, there is no semantic difference between `before`
139 and `after` when it comes to "when" the event is triggered -- except, as we
140 note here, the ordering guarantee.
141
142 So `before` does not now necessarily mean strictly before the event; it could
143 mean after the event, but before any other consequences that are given in
144 `after` clauses.
145
146 Still, multiple `before` consequences are nondeterministic, so in
147
148 event Bar, caused before Foo;
149 event Baz, caused before Foo.
150
151 ...after `Foo` happens, it is still not guaranteed that either `Baz > Bar`
152 or `Bar > Baz` is true.
153
154 Portia
155 ------
156
157 *Portia* is a pre-processor language designed specifically for β-Juliet
158 version 1.0. It is solely concerned with expanding parameterized events
159 into series of concrete events, for example creating events `DominoOneFalls`,
160 `DominoTwoFalls`, etc., from the generalized event schema
161 `Domino(N=Domino)Falls` where `Domino` is an _alphabet_ over the range of
162 dominoes.
163
164 This mechanism (in fact, an extended form of it) is included in version 2.0
165 of the β-Juliet language itself, so no pre-processor is needed for it.
166
167 Computational Power
168 -------------------
169
170 The state space of a system described in β-Juliet version 1.0 is always
171 finite, so β-Juliet version 1.0 cannot be Turing-complete. The state space
172 of a system described using Portia and β-Juliet version 1.0 may be much,
173 much bigger than one described using just β-Juliet version 1.0, but it is
174 still finite.
175
176 Since β-Juliet version 2.0 allows unbounded sets of events to be described,
177 it is more likely that it is Turing-complete.
178
179 Patterns
180 --------
181
182 β-Juliet version 2.0 introduces _event patterns_. When the name of an event
183 is given by a string of symbols, some of those symbols may actually be
184 _parameters_ which act something like wildcards. Each parameter ranges over
185 a specified _alphabet_. When an event occurs which matches the name of an
186 event, the parameters in that name are bound to the literal symbols in the
187 occurring event. These bound parameters may then be used in substitutions in
188 the consequences.
189
190 For example, if we have an alphabet called `Animal` that consists of the
191 symbols `Dog` `Cat` `Ferret`, we can have an event `(X=Animal) Licks Itself`
192 which has, as a consequence, `(X) Becomes Clean`. Here `X` is a parameter.
193 This event will happen should some other event cause `Cat Licks Itself`, and
194 in this case, `X` will be bound to `Cat`, and this event will thus
195 subsequently cause the event `Cat Becomes Clean`.
196
197 Modifiers
198 ---------
199
200 Unlike events, alphabets are ordered. Each symbol (except the first) in an
201 alphabet has one and only one _predecessor_, and each symbol (except the last)
202 has one and only one _successor_.
203
204 So the range of symbols in an alphabet is bounded. However, when considering
205 a string of symbols (which I'll call a _symbol-string_), such as the name of
206 an event, we can use lexicographic ordering to concoct something resembling
207 Peano arithmetic to generate an unbounded sequence of symbol-strings, so long
208 as each symbol in a string is in the same alphabet.
209
210 Thus, for some alphabet, every symbol-string has one and only one successor.
211 Again, though, there is one symbol-string which has no predecessor — the
212 symbol-string which is one symbol long, where that symbol is the first symbol
213 of the alphabet.
214
215 These concepts are implemented in β-Juliet version 2.0 with _modifiers_.
216 When a parameter is named in a consequence, it is replaced by the value it is
217 bound to, and this can be altered by one of the following modifiers:
218
219 * `next` — assuming the value is a single symbol, use the next symbol
220 in its alphabet instead;
221 * `prev` — assuming the value is a single symbol, use the previous symbol
222 in its alphabet instead;
223 * `succ` — assuming the value is a symbol-string, use the successor
224 symbol-string over its alphabet;
225 * `pred` — assuming the value is a symbol-string, use the predecessor
226 symbol-string over its alphabet instead.
227
228 Note that all of these modifiers (except `succ`) can fail. In this case,
229 an alternate or `failure-mode` modifier or symbol can be given, and this
230 will be used instead.
231
232 Extended Grammar
233 ----------------
234
235 The grammar for β-Juliet version 2.0 builds on the productions from
236 version 1.0, while replacing or adding the following productions.
237
238 First, it allows alphabets as well as events to be declared. It also
239 explicitly reserves syntax for implementation-specific pragmas and
240 system events (but does not define the meaning of any of these itself.)
241
242 Decl ::= Pragma | Alphabet | Event.
243 Pragma ::= "pragma" <<<implementation-specific>>>.
244 Alphabet ::= "alphabet" AlphabetName {"," Symbol}.
245 AlphabetName ::= Symbol.
246
247 It extends the `causes` syntax to include specifying a duration as part
248 of it, using the `after` keyword. The `duration` syntax is still supported;
249 if it is given as a property of an event, the duration specified in it will
250 be applied to all `causes` clauses on the event which do *not* include their
251 own `after` delay.
252
253 Note also that `caused` clauses do not support an `after` delay.
254
255 Causes ::= "causes" EventAppl ["after" TimeSpec] {WhenTerm}.
256
257 Lastly, it significantly extends the syntax for declaring, and using, an
258 event, to include multi-symbol events and event patterns.
259
260 EventDecl ::= EventDeclComp {EventDeclComp}.
261 EventDeclComp ::= Symbol | "(" ParamName "=" MatchExpr ")".
262 ParamName ::= Symbol.
263 MatchExpr ::= AlphabetName ["+"].
264
265 EventAppl ::= EventApplComp {EventApplComp}.
266 EventApplComp ::= SymbolName | "(" AlphabetExpr ")".
267
268 AlphabetExpr ::= AlphabetTerm {"|" AlphabetTerm}.
269 AlphabetTerm ::= "succ" ParamName
270 | "pred" ParamName
271 | "next" ParamName
272 | "prev" ParamName
273 | "first" AlphabetName
274 | "last" AlphabetName
275 | SymbolName
276 .
277
278 Extra conditions, however, are placed on `caused by` clauses. Both the name
279 of the event which is the cause, and the name of the event which is being
280 caused, must be literal symbol strings, not patterns.
281
282 Implementations
283 ---------------
284
285 There is a crude implementation of β-Juliet version 1.0 in the form of a
286 Perl 5 script. It does not implement delays, but it does implement the
287 ordering guarantees between `caused before` and `caused after`.
288
289 The reference implementation of β-Juliet version 2.0, called `2iota`, is
290 written in C. It implements delays (when compiled as ANSI C they have
291 second granularity; when compiled as C99 with POSIX, they have millisecond
292 granularity.) It does not yet, however, properly implement the ordering
293 guarantees between `caused before` and `caused after` clauses; nor does it
294 parse `immediately`.
0 β-Juliet
1 ========
2
3 Version 2.0
4 | _Entry_ [@ catseye.tc](https://catseye.tc/node/beta-Juliet)
5 | _Wiki entry_ [@ esolangs.org](https://esolangs.org/wiki/2iota)
6 | _See also:_ [Squishy2K](https://github.com/catseye/Squishy2K#readme)
7 ∘ [Nested Modal Transducers](https://github.com/catseye/Nested-Modal-Transducers#readme)
8
9 - - - -
10
11 β-Juliet is a minimal event-oriented language which, as of version 2.0
12 (see [historical note](#historical-note) below), is probably Turing-complete.
13
14 Description
15 -----------
16
17 β-Juliet is a fairly minimal event-oriented language. In β-Juliet, the world
18 is modelled as a set of _events_ which have no inherent organization or order.
19 Each event can be denoted with a _symbol_, such as `DominoFalls`, `CatMeows`,
20 or `SunSets`, or (in version 2.0) a string of symbols, such as `Address Line
21 Six Goes High` or `Greengrocer Falls Asleep on Subway`.
22
23 Each event can cause other events to occur — these are termed _consequences_
24 of the event. In addition, this causation may be conditional, but the only
25 condition that is possible to check is: _given two events, which one happened
26 more recently?_
27
28 Example
29 -------
30
31 // Description of a weather-sensitive robot tarpaulin in beta-Juliet
32
33 event RainBegins;
34 event RainEnds;
35
36 event SystemActivated;
37 event SystemDeactivated;
38
39 event CloseTarpaulin,
40 caused after RainBegins when SystemActivated > SystemDeactivated;
41
42 event OpenTarpaulinTimer,
43 duration 10 m,
44 caused after RainEnds when SystemActivated > SystemDeactivated;
45
46 event OpenTarpaulin,
47 caused after OpenTarpaulinTimer.
48
49 Basic Grammar
50 -------------
51
52 The basic grammar of β-Juliet is given here in EBNF. Version 1.0 uses this
53 grammar as it stands; version 2.0 extends many of the productions.
54
55 betaJuliet ::= Decl {";" Decl} ".".
56 Decl ::= Event.
57 Event ::= "event" EventDecl {"," Property}.
58 EventDecl ::= Symbol.
59 Property ::= Caused | Causes | Duration.
60 Caused ::= "caused" TimePrep EventAppl {WhenTerm}.
61 Causes ::= "causes" EventAppl ["immediately"] {WhenTerm}
62 Duration ::= "duration" TimeSpec.
63 TimePrep ::= "before" | "after" | "by".
64 TimeSpec ::= RationalNumber TimeUnit.
65 TimeUnit ::= "ms" | "s" | "m" | "h" | "d".
66 EventAppl ::= Symbol.
67 WhenTerm ::= "when" EventAppl ">" EventAppl.
68 Symbol ::= <<one or more alphanumeric characters>>.
69 Number ::= <<rational number in decimal format>>.
70
71 ### Some Explanations ###
72
73 The syntax `A > B` can be read as "`A` has occurred more recently than `B`".
74 If `A` has occurred but `B` has never occurred, `A > B` is still true;
75 however, if neither event has ever occurred, both `A > B` and `B > A` are
76 false.
77
78 `caused` and `causes` are two equivalent ways of expressing the causality
79 rules between events. If we say one event is `caused by` or `caused after`
80 some other event, that is equivalent to saying the other event `causes` the
81 one event. Similarly, if we say one event is `caused before` some other
82 event, that is equivalent to saying the other event `causes` the one event
83 `immediately`.
84
85 When we define an event like
86
87 event Foo,
88 causes Bar,
89 causes Baz.
90
91 or like this
92
93 event Bar, caused by Foo;
94 event Baz, caused by Foo.
95
96 ...and during execution, after `Foo` happens, it is not guaranteed that
97 either `Baz > Bar` or `Bar > Baz` is true; the order in which these two
98 consequences occur does not necessarily follow source code order. (But it
99 is guaranteed that one or the other will be true, as both events will have
100 happened.)
101
102 If you require an ordering guarantee in a case like this, you should use
103 an intermediate event, like
104
105 event Foo,
106 causes Temp,
107 causes Bar;
108 event Temp,
109 causes Baz.
110
111 After `Temp` happens, `Baz > Bar` should be true.
112
113 ### `caused before` ###
114
115 Alternately, in theory, you can use `caused before`, as in:
116
117 event Bar, caused before Foo;
118 event Baz, caused after Foo.
119
120 After `Foo` happens, `Baz > Bar` should be true.
121
122 Some words on the purpose of `caused before` are in order. In the original
123 vision, `after` and `by` were synonyms, but `before` was meant to actually
124 cause the event on which the `caused before` clause was attached, strictly
125 *before* the event named in the clause.
126
127 However, unless the event being caused can somehow *cancel* the event that
128 it's being caused before, there is no semantic difference between `before`
129 and `after` when it comes to "when" the event is triggered -- except, as we
130 note here, the ordering guarantee.
131
132 So `before` does not now necessarily mean strictly before the event; it could
133 mean after the event, but before any other consequences that are given in
134 `after` clauses.
135
136 Still, multiple `before` consequences are nondeterministic, so in
137
138 event Bar, caused before Foo;
139 event Baz, caused before Foo.
140
141 ...after `Foo` happens, it is still not guaranteed that either `Baz > Bar`
142 or `Bar > Baz` is true.
143
144 Portia
145 ------
146
147 *Portia* is a pre-processor language designed specifically for β-Juliet
148 version 1.0. It is solely concerned with expanding parameterized events
149 into series of concrete events, for example creating events `DominoOneFalls`,
150 `DominoTwoFalls`, etc., from the generalized event schema
151 `Domino(N=Domino)Falls` where `Domino` is an _alphabet_ over the range of
152 dominoes.
153
154 This mechanism (in fact, an extended form of it) is included in version 2.0
155 of the β-Juliet language itself, so no pre-processor is needed for it.
156
157 Computational Power
158 -------------------
159
160 The state space of a system described in β-Juliet version 1.0 is always
161 finite, so β-Juliet version 1.0 cannot be Turing-complete. The state space
162 of a system described using Portia and β-Juliet version 1.0 may be much,
163 much bigger than one described using just β-Juliet version 1.0, but it is
164 still finite.
165
166 Since β-Juliet version 2.0 allows unbounded sets of events to be described,
167 it is more likely that it is Turing-complete.
168
169 Patterns
170 --------
171
172 β-Juliet version 2.0 introduces _event patterns_. When the name of an event
173 is given by a string of symbols, some of those symbols may actually be
174 _parameters_ which act something like wildcards. Each parameter ranges over
175 a specified _alphabet_. When an event occurs which matches the name of an
176 event, the parameters in that name are bound to the literal symbols in the
177 occurring event. These bound parameters may then be used in substitutions in
178 the consequences.
179
180 For example, if we have an alphabet called `Animal` that consists of the
181 symbols `Dog` `Cat` `Ferret`, we can have an event `(X=Animal) Licks Itself`
182 which has, as a consequence, `(X) Becomes Clean`. Here `X` is a parameter.
183 This event will happen should some other event cause `Cat Licks Itself`, and
184 in this case, `X` will be bound to `Cat`, and this event will thus
185 subsequently cause the event `Cat Becomes Clean`.
186
187 Modifiers
188 ---------
189
190 Unlike events, alphabets are ordered. Each symbol (except the first) in an
191 alphabet has one and only one _predecessor_, and each symbol (except the last)
192 has one and only one _successor_.
193
194 So the range of symbols in an alphabet is bounded. However, when considering
195 a string of symbols (which I'll call a _symbol-string_), such as the name of
196 an event, we can use lexicographic ordering to concoct something resembling
197 Peano arithmetic to generate an unbounded sequence of symbol-strings, so long
198 as each symbol in a string is in the same alphabet.
199
200 Thus, for some alphabet, every symbol-string has one and only one successor.
201 Again, though, there is one symbol-string which has no predecessor — the
202 symbol-string which is one symbol long, where that symbol is the first symbol
203 of the alphabet.
204
205 These concepts are implemented in β-Juliet version 2.0 with _modifiers_.
206 When a parameter is named in a consequence, it is replaced by the value it is
207 bound to, and this can be altered by one of the following modifiers:
208
209 * `next` — assuming the value is a single symbol, use the next symbol
210 in its alphabet instead;
211 * `prev` — assuming the value is a single symbol, use the previous symbol
212 in its alphabet instead;
213 * `succ` — assuming the value is a symbol-string, use the successor
214 symbol-string over its alphabet;
215 * `pred` — assuming the value is a symbol-string, use the predecessor
216 symbol-string over its alphabet instead.
217
218 Note that all of these modifiers (except `succ`) can fail. In this case,
219 an alternate or `failure-mode` modifier or symbol can be given, and this
220 will be used instead.
221
222 Extended Grammar
223 ----------------
224
225 The grammar for β-Juliet version 2.0 builds on the productions from
226 version 1.0, while replacing or adding the following productions.
227
228 First, it allows alphabets as well as events to be declared. It also
229 explicitly reserves syntax for implementation-specific pragmas and
230 system events (but does not define the meaning of any of these itself.)
231
232 Decl ::= Pragma | Alphabet | Event.
233 Pragma ::= "pragma" <<<implementation-specific>>>.
234 Alphabet ::= "alphabet" AlphabetName {"," Symbol}.
235 AlphabetName ::= Symbol.
236
237 It extends the `causes` syntax to include specifying a duration as part
238 of it, using the `after` keyword. The `duration` syntax is still supported;
239 if it is given as a property of an event, the duration specified in it will
240 be applied to all `causes` clauses on the event which do *not* include their
241 own `after` delay.
242
243 Note also that `caused` clauses do not support an `after` delay.
244
245 Causes ::= "causes" EventAppl ["after" TimeSpec] {WhenTerm}.
246
247 Lastly, it significantly extends the syntax for declaring, and using, an
248 event, to include multi-symbol events and event patterns.
249
250 EventDecl ::= EventDeclComp {EventDeclComp}.
251 EventDeclComp ::= Symbol | "(" ParamName "=" MatchExpr ")".
252 ParamName ::= Symbol.
253 MatchExpr ::= AlphabetName ["+"].
254
255 EventAppl ::= EventApplComp {EventApplComp}.
256 EventApplComp ::= SymbolName | "(" AlphabetExpr ")".
257
258 AlphabetExpr ::= AlphabetTerm {"|" AlphabetTerm}.
259 AlphabetTerm ::= "succ" ParamName
260 | "pred" ParamName
261 | "next" ParamName
262 | "prev" ParamName
263 | "first" AlphabetName
264 | "last" AlphabetName
265 | SymbolName
266 .
267
268 Extra conditions, however, are placed on `caused by` clauses. Both the name
269 of the event which is the cause, and the name of the event which is being
270 caused, must be literal symbol strings, not patterns.
271
272 Implementations
273 ---------------
274
275 There is a crude implementation of β-Juliet version 1.0 in the form of a
276 Perl 5 script. It does not implement delays, but it does implement the
277 ordering guarantees between `caused before` and `caused after`.
278
279 The reference implementation of β-Juliet version 2.0, called `2iota`, is
280 written in C. It implements delays (when compiled as ANSI C they have
281 second granularity; when compiled as C99 with POSIX, they have millisecond
282 granularity.) It does not yet, however, properly implement the ordering
283 guarantees between `caused before` and `caused after` clauses; nor does it
284 parse `immediately`.
285
286 Historical Note
287 ---------------
288
289 In 2012 I decided that the languages β-Juliet and 2Iota are really too similar
290 to be seperate languages. So, as of this repo, they've been merged like this:
291
292 * This language is called β-Juliet (a.k.a. beta-Juliet).
293 * The language previously referred to as β-Juliet is now β-Juliet 1.0.
294 * The language previously referred to as 2Iota (plus minor modifications) is
295 now β-Juliet 2.0.
296 * The reference interpreter for β-Juliet 2.0 is called `2iota`.
297 * The file extension of a β-Juliet source file is typically `.bj`,
298 although you may see `.2i` used as well. The latter suggests that
299 the source relies on features only in version 2.0.
300 * The optional pre-processor for β-Juliet 1.0 is still called Portia.
301 Portia is not needed with β-Juliet 2.0, and may or may not work with it; I
302 don't know yet.