Actually just three programming languages in a trenchcoat
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 492 lines 17 kB view raw
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}