Actually just three programming languages in a trenchcoat
1\section{Syntax and Semantics}
2\label{sec:syntax}
3
4As previously mentioned, grammars in this document are
5\href{https://en.wikipedia.org/wiki/Parsing_expression_grammar}{PEGs},
6albeit lacking in all syntax sugar.
7
8In this section, terminals each refer to token types, though for tokens
9with a single source text representation, their textual representation
10is preferred for readability. The productions refer to nodes in the
11abstract syntax tree, and are named as they are in the implementation
12source code.
13
14Following relevant blocks describing the syntax of \Trilogy{} code is some
15approximation of a formalization of the semantics of that code, using some
16loose understanding of the notation and rules of what might be natural
17deduction, which I may or may not have learned briefly some years ago.
18I am no expert, and if some expert ever sees this I will gladly accept any
19corrections to these notes, as I am sure they will be conflicting themselves
20in more than a few places.
21
22Seeing as I am not an expert, some symbols used in potentially non-
23standard ways in the following documentation are summarized here.
24Some are further formalized later.
25
26\begin{itemize}
27 \item $\Gamma :> \Phi$ --- Extends from, as a scope. Names looked up in the
28 context $\Phi$ will search $\Phi$ first; if not found, the context $\Gamma$
29 is searched. New names bound are bound in $\Phi$ without affecting $\Gamma$.
30 Names which are rebound (e.g.\ in assignment) are rebound in the scope in
31 which they are found.
32 \item $P = E$ --- Unifies, via the pattern unification algorithm. Given the
33 pattern $P$ and value $E$, find values for the free variables in $P$ such that
34 that $P$ and $E$ represent the same value.
35 \item $a := P$ --- Declares, as a name. $P$ is a pattern and $a$ is a name
36 bound by that pattern. Patterns often declare more than one name.
37 \item $\text{read}(\sigma)$ --- Read, as a file. $\sigma$ is a String which is interpreted
38 as a URL, and $\text{read}(\sigma)$ is the contents of the file located by that URL.
39 \item $e \in E$ --- Is an element of, via iteration. The value $E$ is a value
40 which can be converted to an Iterator. Each $e$ is an element of that iterator.
41 \item $X \Rightarrow \Phi$ --- Continues execution in context. After evaluation
42 of the code $X$, the evaluation of the program continues at least once. Due to
43 branching, there may be multiple executions remaining at this time. The
44 continuing context of the program in each of these branches is denoted as
45 $\Phi$.
46 \item $X : \top$ --- Continues execution. $\Gamma\vdash X : \top$ could be
47 seen as equivalent to $\Gamma \vdash X \Rightarrow \Gamma$, in that execution
48 continues, possibly more than once, but without modifying the context.
49 \item $X : \bot$ --- Ends execution. After evaluation of the code $X$,
50 no further code is executed. This may be due to failed branching (fizzling),
51 or as a result of certain control flow (e.g. \kw{return}).
52 \item $X : \tau$ --- Is of type. More specifically than execution, a value may
53 be of a particular type. This is treated similarly to $\top$ in terms of
54 execution continuing, possibly more than once, but we have additional
55 information about the type of the value that the expression $X$ evaluated to.
56 \item $X \vartriangle \eta$ --- Yields, as an effect. The expression $X$ causes
57 an effect $\eta$ to be yielded. That effect will be handled later.
58 \item $P\ \triangleleft\ B$ --- Inverts with, as a handler. A construct that is
59 held in scope, when an effect matching $P$ is yielded, $B$ is used as a handler.
60 \item $X\ \triangledown\ \tau$ --- Resumes with. The expression $X$ causes
61 the recently yielded effect to resume with a value of type $\tau$.
62 \item $X\ \triangleright\ \tau$ --- Cancels to. The expression $X$ causes the
63 continuation of the recently yielded effect to be cancelled, resuming execution
64 from its limit, which evaluates to a value of type $\tau$.
65 \item $\text{addr}(X)$ --- Address of, as an instance. The address of the value
66 of the evaluated value of $X$ is used, rather than the actual value of $X$
67 itself. Values of reference type have such addresses, values of structural type
68 do not, but you could imagine that every distinct value of structural type has
69 its own unique pseudo-address that is used equivalently.
70\end{itemize}
71
72\subsection{Trilogy}
73
74While the specifics of most of the executable code in \Trilogy{} are separated into
75the three sublanguages, the non-executable parts of the language are considered
76to be part of \Trilogy{} as a whole.
77
78\subsubsection{Whitespace}
79
80Between any two tokens may be any number of comment nodes. Additionally,
81any whitespace (including line breaks) may occur between any two tokens
82without issue. In certain marked cases, however, line breaks are required
83as a statement terminator; in such cases, the line break is always interpreted
84as a statement terminator, and not as meaningless whitespace.
85
86The required end of line rule is formalized as follows:
87
88\begin{bnf*}
89 \bnfprod{EOL}{
90 \bnfts{EndOfLine}\bnfor
91 \bnfts{CommentLine}\bnfor
92 \bnfts{CommentBlock}
93 }
94\end{bnf*}
95
96Documentation comments, though they include line breaks, do not count as a line
97break because when attached to a declaration, as seen in the next section, they
98too require being placed on a separate line from any previous definition.
99
100\subsubsection{The Document}
101
102The top level of a \Trilogy{} file is not considered to be written in any
103of the sublanguages. This section of the program may only contain definitions.
104
105A \Trilogy{} document \emph{should} end with a final line break, but files
106without such a final line break may be accepted (with warning). This line break
107is not represented in the grammar, but should be checked nonetheless.
108
109As a notable exception, rule~\ref{bnf:empty} indicates that a truly empty
110file \emph{is} accepted, regardless of the fact that it does not end with
111a line break.
112
113A byte order mark \emph{may} be accepted (with warning) at the start of
114the file. It is optional to implement rule~\ref{bnf:bom}.
115
116Interestingly, since documentation comments have specfic meaning in relation
117to defined items, they are only permitted in some locations and are included
118in the resulting syntax tree. These comments have no meaning to the program
119as it runs, but may be used by other tools which are likely to be based on the
120syntax tree, so having the documentation inside is simply useful.
121
122\begin{bnf}
123 \bnfprod*{Document}{
124 \bnfpn{Preamble}
125 \bnfsp
126 \bnfpn{InnerDocumentation}
127 } \\
128 \bnfmore{
129 \bnfpn{Definitions}
130 \bnfsp
131 \bnfpn{Postamble}
132 \bnfor
133 } \\
134 \bnfmore{\label{bnf:empty}\bnfpn{Preamble}\bnfsp\bnfts{EndOfFile}} \\
135 \bnfprod*{Preamble}{\bnfts{StartOfFile}\bnfor} \\
136 \bnfmore{
137 \label{bnf:bom}
138 \bnfts{StartOfFile}
139 \bnfsp
140 \bnfts{ByteOrderMark}
141 } \\
142 \bnfprod*{Postamble}{\bnfts{EndOfFile}} \\
143 \bnfprod*{InnerDocumentation}{
144 \bnfpn{DocInner}
145 \bnfsp
146 \bnfpn{InnerDocumentation}
147 \bnfor
148 \bnfes
149 } \\
150 \bnfprod*{Definitions}{
151 \bnfpn{Definition}
152 \bnfsp
153 \bnfpn{EOL}
154 \bnfsp
155 \bnfpn{Definitions}
156 \bnfor
157 \bnfpn{Definition}
158 } \\
159 \bnfprod*{Definition}{
160 \bnfpn{OuterDocumentation}
161 \bnfsp
162 \bnfpn{DefinitionItem}
163 } \\
164 \bnfprod*{OuterDocumentation}{
165 \bnfpn{DocOuter}
166 \bnfsp
167 \bnfpn{OuterDocumentation}
168 \bnfor
169 \bnfes
170 } \\
171 \bnfprod*{DefinitionItem}{
172 \bnfpn{TypeDefinition}\bnfor
173 \bnfpn{FunctionDefinition}\bnfor
174 } \\
175 \bnfmore*{
176 \bnfpn{ProcedureDefinition}\bnfor
177 \bnfpn{RuleDefinition}\bnfor
178 } \\
179 \bnfmore*{
180 \bnfpn{SlotDefinition}\bnfor
181 } \\
182 \bnfmore*{
183 \bnfpn{ExternProcedureDefinition}\bnfor
184 } \\
185 \bnfmore*{
186 \bnfpn{ExternTypeDefinition}\bnfor
187 } \\
188 \bnfmore*{
189 \bnfpn{Test}\bnfor
190 \bnfpn{Import}\bnfor
191 \bnfpn{Export}
192 }
193\end{bnf}
194
195\subsubsection{Modules}
196
197In \Trilogy{}, modules are defined using the \kw{type} keyword, and may someday
198be expanded upon in ways that make them more similar to existing type systems.
199
200Modules act as containers for definitions, including procedures, functions, rules,
201and further submodules. Every \Trilogy{} document is implicitly an anonymous
202module, meaning a document may export any of its defined items, and may be
203imported by other modules that wish to make use of those definitions. Any item
204defined at the top level of a module may be exported: procedures, functions,
205rules, and submodules.
206
207The \Trilogy{} module system is modelled after that of OCaml: modules may
208be defined as functions which accept one or more values as parameters
209to generate a new module. Unlike in OCaml, such modules functions are \emph{generative}:
210if a module function is applied to the same arguments multiple times, it will
211generate a distinct module. At this time, a document cannot specify parameters,
212so such function modules may only be defined as a local submodule within some
213existing module.
214
215\begin{bnf*}
216 \bnfprod{TypeDefinition}{
217 \bnfts{\kw{type}}
218 \bnfsp
219 \bnfpn{TypeHead}
220 \bnfsp
221 \bnfts{\{}
222 \bnfsp
223 \bnfpn{Definitions}
224 \bnfsp
225 \bnfts{\}}
226 } \\
227 \bnfprod{TypeHead}{
228 \bnfpn{Identifier}
229 \bnfsp
230 \bnfpn{TypeParameters}
231 } \\
232 \bnfprod{TypeParameters}{
233 \bnfpn{Identifier}
234 \bnfsp
235 \bnfpn{TypeParameters}
236 \bnfor
237 \bnfes
238 }
239\end{bnf*}
240
241\subsubsection{Imports and Exports}
242
243Imported documents, defined using the \kw{import}-\texttt{String} construct
244are resolved as documents located via the canonical absolute URL designated
245by the (potentially relative) path \texttt{String} in rule~\ref{bnf:import}.
246If two external module definitions paths resolve to the same canonical absolute
247URL, those two modules will be considered identical, despite being ``defined''
248in two places in the source code. The full details of the path resolution
249algorithm are defined in \S\ref{sec:module-resolution}.
250
251Modules can also be imported from using the \kw{import}-\texttt{Expression}
252form, working in much the same way but for modules that are defined locally or
253require passing parameters. The expression in this case must be a constant
254expression.
255
256\begin{bnf}
257 \bnfprod{Import}{
258 \label{bnf:import}
259 \bnfts{\kw{import}}
260 \bnfsp
261 \bnfpn{String}
262 \bnfsp
263 \bnfpn{ImportAs}
264 \bnfsp
265 \bnfpn{ImportUse}
266 \bnfor
267 } \\
268 \bnfmore*{
269 \bnfts{\kw{import}}
270 \bnfsp
271 \bnfpn{Expression}
272 \bnfsp
273 \bnfpn{ImportAs}
274 \bnfsp
275 \bnfpn{ImportUse}
276 } \\
277 \bnfprod*{ImportUse}{
278 \bnfts{\kw{use}}
279 \bnfsp
280 \bnfpn{NameList}
281 \bnfor
282 \bnfes
283 } \\
284 \bnfprod*{ImportAs}{
285 \bnfts{\kw{as}}
286 \bnfsp
287 \bnfpn{Identifier}
288 \bnfor
289 \bnfes
290 } \\
291 \bnfprod*{Export}{
292 \bnfts{\kw{export}}
293 \bnfsp
294 \bnfpn{NameList}
295 } \\
296 \bnfprod*{NameList}{
297 \bnfpn{Name}
298 \bnfsp
299 \bnfts{,}
300 \bnfsp
301 \bnfpn{NameList}
302 \bnfor
303 \bnfpn{Name}
304 \bnfor
305 \bnfes
306 } \\
307 \bnfprod*{Name}{
308 \bnfpn{Identifier}
309 \bnfor
310 \bnfpn{Identifier}
311 \bnfsp
312 \bnfts{\kw{as}}
313 \bnfsp
314 \bnfpn{Identifier}
315 }
316\end{bnf}
317
318A \kw{type} definition puts into scope a namespace in which all \kw{export}ed
319definitions contained within the module may be accessed. An \kw{import}-\kw{as}
320puts such a namespace defined externally into scope, while the \kw{use} list
321exposes the \kw{export}ed members into the current module's scope directly.
322Otherwise, such members would need to be accessed using the module access
323operator (\S\ref{sec:module-access}).
324
325When a module is defined as a submodule (directly in the same file as its parent
326module), the definitions within the module may access all definitions (including
327private definitions) of the containing module. The reverse is not true; the
328private members of a submodule remain private unless exported. Modules defined
329externally also may not access members of the module in which they are declared.
330
331\begin{prooftree}
332 \AxiomC{$\Gamma,m_{1\hdots n},\Phi \vdash p$}
333 \AxiomC{$\kw{type}\ m\ m_{1\hdots n}\ \block{K}$}
334 \AxiomC{$K \Rightarrow \kw{export}\ p$}
335 \LeftLabel{Export}
336 \TrinaryInfC{$\Gamma \vdash m\ \text{exports}\ p$}
337\end{prooftree}
338
339\begin{prooftree}
340 \AxiomC{$\Phi \vdash p$}
341 \AxiomC{$\kw{import}\ \sigma\ \kw{as}\ m$}
342 \AxiomC{$\text{read}(\sigma) \Rightarrow \kw{export}\ p$}
343 \LeftLabel{External Module}
344 \TrinaryInfC{$\Gamma \vdash m\ \text{exports}\ p$}
345\end{prooftree}
346
347\begin{prooftree}
348 \AxiomC{$\Phi \vdash p$}
349 \AxiomC{$\Gamma \vdash m\ \text{exports}\ p$}
350 \AxiomC{$\kw{import}\ m\ \kw{use}\ p$}
351 \LeftLabel{Use}
352 \TrinaryInfC{$\Gamma \vdash p$}
353\end{prooftree}
354
355\subsubsection{Slots}
356
357Slots are the most basic type of definition, consisting of a name and an expression
358to bind as the value for that name. The expression is evaluated once, at the time the
359module in which the slot is declared is instantiated.
360
361Slots may be declared as mutable, allowing the value in the slot to be reassigned later.
362
363\begin{bnf*}
364 \bnfprod{SlotDefinition}{
365 \bnfts{\kw{slot}}
366 \bnfsp
367 \bnfpn{Identifier}
368 \bnfsp
369 \bnfts{=}
370 \bnfsp
371 \bnfpn{Expression}
372 \bnfor
373 } \\
374 \bnfmore{
375 \bnfts{\kw{slot}}
376 \bnfsp
377 \bnfts{\kw{mut}}
378 \bnfsp
379 \bnfpn{Identifier}
380 \bnfsp
381 \bnfts{=}
382 \bnfsp
383 \bnfpn{Expression}
384 }
385\end{bnf*}
386
387\begin{prooftree}
388 \AxiomC{$\Gamma \vdash E : \tau$}
389 \AxiomC{$\kw{const}\ k\ \texttt{=}\ E$}
390 \LeftLabel{Slot}
391 \BinaryInfC{$\Gamma \vdash k : \tau$}
392\end{prooftree}
393
394Though there is no restriction on what value can be stored in a slot, the initial value
395expression must be a valid ``constant expression''. Constant expressions may not involve
396effect handlers, function calls, procedure calls, or comprehensions as those may perform
397side effects which are not permitted at constant time. Only literals, basic operators, module
398applications, module lookups may occur. References to other constants are also permitted, as
399long as they do not cause a circular self-reference.
400
401\subsubsection{Definitions}
402
403The other types of definitions each hand off to their respective child
404languages.
405
406\begin{bnf*}
407 \bnfprod{ProcedureDefinition}{
408 \bnfts{\kw{proc}}
409 \bnfsp
410 \bnfpn{ProcedureHead}
411 \bnfsp
412 \bnfts{\{}
413 \bnfsp
414 \bnfpn{ProcedureBody}
415 \bnfsp
416 \bnfts{\}}
417 } \\
418 \bnfprod{FunctionDefinition}{
419 \bnfts{\kw{func}}
420 \bnfsp
421 \bnfpn{FunctionHead}
422 \bnfsp
423 \bnfts{=}
424 \bnfsp
425 \bnfpn{FunctionBody}
426 } \\
427 \bnfprod{RuleDefinition}{\bnfts{\kw{rule}}\bnfsp\bnfpn{RuleHead}\bnfor} \\
428 \bnfmore{\bnfts{\kw{rule}}\bnfsp\bnfpn{RuleHead}\bnfsp{\op{<-}}\bnfsp\bnfpn{RuleBody}}
429\end{bnf*}
430
431For name resolution purposes, defintions of all types are stored in the same
432scope. For example, a procedure and a function defined in the same module may
433not have the same name.
434
435\subsubsection{External Definitions}
436
437\begin{bnf*}
438 \bnfprod{ExternTypeDefinition}{
439 \bnfts{\kw{extern}}
440 \bnfsp
441 \bnfpn{String}
442 \bnfsp
443 \bnfts{\kw{type}}
444 \bnfsp
445 \bnfpn{TypeHead}
446 \bnfsp
447 } \\
448 \bnfmore{
449 \bnfts{\{}
450 \bnfsp
451 \bnfpn{ExternDefinitions}
452 \bnfsp
453 \bnfts{\}}
454 } \\
455 \bnfprod{ExternProcedureDefinition}{
456 \bnfts{\kw{extern}}
457 \bnfsp
458 \bnfts{\kw{proc}}
459 \bnfsp
460 \bnfpn{ProcedureHead}
461 \bnfsp
462 } \\
463 \bnfprod{ExternDefinitions}{
464 \bnfpn{ExternDefinition}
465 \bnfsp
466 \bnfpn{ExternDefinitions}
467 \bnfor
468 \bnfes
469 } \\
470 \bnfprod{ExternDefinition}{
471 \bnfpn{ExternProcedureDefinition}
472 }
473\end{bnf*}
474
475Worth noting is the use of the \kw{extern} keyword: a type or procedure can be declared as
476external indicating that it is not implemented within the current file but will be
477available at compilation or link time from some externally provided native library.
478The string following the \kw{extern} keyword names the calling convention by which the
479externally defined function is to be called. Valid options are \texttt{"c"} or \texttt{"trilogy"}.
480
481At this time, it is likely incorrect to use the \kw{extern} keyword in any user program,
482but it is frequently used within the core library.
483
484\subimport{law/}{index.tex}
485
486\subimport{prose/}{index.tex}
487
488\subimport{poetry/}{index.tex}
489
490\subimport{effects/}{index.tex}
491
492\subimport{tests/}{index.tex}