saving
This commit is contained in:
parent
dbadcf267e
commit
49521ae595
24 changed files with 93 additions and 1093 deletions
13
acl.cool/singular.html
Normal file
13
acl.cool/singular.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>acl.cool</h1>
|
||||||
|
|
||||||
|
<p>Welcome to acl.cool.</p> <a href="recipes/">recipes</a>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
0
css/index.css
Normal file
0
css/index.css
Normal file
120
html/404.html
120
html/404.html
|
@ -1,120 +0,0 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
||||||
<head>
|
|
||||||
<title>The page is not found</title>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<style type="text/css">
|
|
||||||
/*<![CDATA[*/
|
|
||||||
body {
|
|
||||||
background-color: #FAF5F5;
|
|
||||||
color: #000;
|
|
||||||
font-size: 0.9em;
|
|
||||||
font-family: sans-serif,helvetica;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
:link {
|
|
||||||
color: #0B2335;
|
|
||||||
}
|
|
||||||
:visited {
|
|
||||||
color: #0B2335;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #0069DA;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.6em 2em 0.4em;
|
|
||||||
background-color: #0B2335;
|
|
||||||
color: #fff;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 1.75em;
|
|
||||||
border-bottom: 2px solid #000;
|
|
||||||
}
|
|
||||||
h1 strong {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
text-align: center;
|
|
||||||
background-color: #0B2335;
|
|
||||||
font-size: 1.1em;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #fff;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.5em;
|
|
||||||
border-bottom: 2px solid #000;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
text-align: center;
|
|
||||||
background-color: #ff0000;
|
|
||||||
padding: 0.5em;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
hr {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.content {
|
|
||||||
padding: 1em 5em;
|
|
||||||
}
|
|
||||||
.alert {
|
|
||||||
border: 2px solid #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
border: 2px solid #FAF5F5;
|
|
||||||
padding: 2px;
|
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
a:hover img {
|
|
||||||
border: 2px solid #294172;
|
|
||||||
}
|
|
||||||
.logos {
|
|
||||||
margin: 1em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
/*]]>*/
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1><strong>nginx error!</strong></h1>
|
|
||||||
|
|
||||||
<div class="content">
|
|
||||||
|
|
||||||
<h3>The page you are looking for is not found.</h3>
|
|
||||||
|
|
||||||
<div class="alert">
|
|
||||||
<h2>Website Administrator</h2>
|
|
||||||
<div class="content">
|
|
||||||
<p>Something has triggered missing webpage on your
|
|
||||||
website. This is the default 404 error page for
|
|
||||||
<strong>nginx</strong> that is distributed with
|
|
||||||
AlmaLinux. It is located
|
|
||||||
<tt>/usr/share/nginx/html/404.html</tt></p>
|
|
||||||
|
|
||||||
<p>You should customize this error page for your own
|
|
||||||
site or edit the <tt>error_page</tt> directive in
|
|
||||||
the <strong>nginx</strong> configuration file
|
|
||||||
<tt>/etc/nginx/nginx.conf</tt>.</p>
|
|
||||||
|
|
||||||
<p>For information on AlmaLinux, please visit the <a href="http://www.almalinux.org/">AlmaLinux website</a>.</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="logos">
|
|
||||||
<a href="http://nginx.net/"><img
|
|
||||||
src="nginx-logo.png"
|
|
||||||
alt="[ Powered by nginx ]"
|
|
||||||
width="121" height="32" /></a>
|
|
||||||
<a href="http://www.almalinux.org/"><img
|
|
||||||
src="poweredby.png"
|
|
||||||
alt="[ Powered by AlmaLinux ]"
|
|
||||||
width="124" height="32" /></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
120
html/50x.html
120
html/50x.html
|
@ -1,120 +0,0 @@
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
|
||||||
<head>
|
|
||||||
<title>The page is temporarily unavailable</title>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<style type="text/css">
|
|
||||||
/*<![CDATA[*/
|
|
||||||
body {
|
|
||||||
background-color: #FAF5F5;
|
|
||||||
color: #000;
|
|
||||||
font-size: 0.9em;
|
|
||||||
font-family: sans-serif,helvetica;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
:link {
|
|
||||||
color: #0B2335;
|
|
||||||
}
|
|
||||||
:visited {
|
|
||||||
color: #0B2335;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #0069DA;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.6em 2em 0.4em;
|
|
||||||
background-color: #0B2335;
|
|
||||||
color: #fff;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 1.75em;
|
|
||||||
border-bottom: 2px solid #000;
|
|
||||||
}
|
|
||||||
h1 strong {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
text-align: center;
|
|
||||||
background-color: #0B2335;
|
|
||||||
font-size: 1.1em;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #fff;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.5em;
|
|
||||||
border-bottom: 2px solid #000;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
text-align: center;
|
|
||||||
background-color: #ff0000;
|
|
||||||
padding: 0.5em;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
hr {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.content {
|
|
||||||
padding: 1em 5em;
|
|
||||||
}
|
|
||||||
.alert {
|
|
||||||
border: 2px solid #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
border: 2px solid #FAF5F5;
|
|
||||||
padding: 2px;
|
|
||||||
margin: 2px;
|
|
||||||
}
|
|
||||||
a:hover img {
|
|
||||||
border: 2px solid #294172;
|
|
||||||
}
|
|
||||||
.logos {
|
|
||||||
margin: 1em;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
/*]]>*/
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1><strong>nginx error!</strong></h1>
|
|
||||||
|
|
||||||
<div class="content">
|
|
||||||
|
|
||||||
<h3>The page you are looking for is temporarily unavailable. Please try again later.</h3>
|
|
||||||
|
|
||||||
<div class="alert">
|
|
||||||
<h2>Website Administrator</h2>
|
|
||||||
<div class="content">
|
|
||||||
<p>Something has triggered missing webpage on your
|
|
||||||
website. This is the default error page for
|
|
||||||
<strong>nginx</strong> that is distributed with
|
|
||||||
AlmaLinux. It is located
|
|
||||||
<tt>/usr/share/nginx/html/50x.html</tt></p>
|
|
||||||
|
|
||||||
<p>You should customize this error page for your own
|
|
||||||
site or edit the <tt>error_page</tt> directive in
|
|
||||||
the <strong>nginx</strong> configuration file
|
|
||||||
<tt>/etc/nginx/nginx.conf</tt>.</p>
|
|
||||||
|
|
||||||
<p>For information on AlmaLinux, please visit the <a href="http://www.almalinux.org/">AlmaLinux website</a>.</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="logos">
|
|
||||||
<a href="http://nginx.net/"><img
|
|
||||||
src="nginx-logo.png"
|
|
||||||
alt="[ Powered by nginx ]"
|
|
||||||
width="121" height="32" /></a>
|
|
||||||
<a href="http://www.almalinux.org/"><img
|
|
||||||
src="poweredby.png"
|
|
||||||
alt="[ Powered by AlmaLinux ]"
|
|
||||||
width="124" height="32" /></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,550 +0,0 @@
|
||||||
<h1 id="programming-language-general-purpose-1">Overview of the GP1 Programming Language</h1>
|
|
||||||
<h2 id="description">Description</h2>
|
|
||||||
<p>GP1 is a statically typed, multi-paradigm programming language with
|
|
||||||
an emphasis on brevity and explicitness. It provides both value and
|
|
||||||
reference types, as well as higher-order functions and first-class
|
|
||||||
support for many common programming patterns.</p><p>This document serves as a quick, informal reference for developers of GP1 (or anyone who's curious).</p>
|
|
||||||
<h2 id="variables-and-constants">Variables and Constants</h2>
|
|
||||||
<p>A given "variable" is defined with either the <code>var</code> or
|
|
||||||
<code>con</code> keyword, for mutable and immutable assignment
|
|
||||||
respectively, alonside the assignment operator, <code><-</code>. An
|
|
||||||
uninitialized variable MUST have an explicit type, and cannot be
|
|
||||||
accessed until it is assigned. A variable that is initialized in its
|
|
||||||
declaration may have an explicit type, but the type may be inferred
|
|
||||||
here, when possible, if one is omitted. Normal type-coercion rules apply
|
|
||||||
in assignments, as described in the <em>Coercion and Casting</em>
|
|
||||||
section.</p>
|
|
||||||
<p>Non-ascii unicode characters are allowed in variable names as long as
|
|
||||||
the character doesn't cause a parsing issue. For example, whitespace
|
|
||||||
tokens are not allowed in variable names.</p>
|
|
||||||
<p>Some examples of assigning variables:</p>
|
|
||||||
<pre class="gp1"><code>var x: i32; // x is an uninitialized 32-bit signed integer
|
|
||||||
var y <- x; // this won't work, because x has no value
|
|
||||||
x <- 7;
|
|
||||||
var y <- x; // this time it works, because x is now 7
|
|
||||||
|
|
||||||
con a: f64 <- 99.8; // a is immutable
|
|
||||||
a <- 44.12; // this doesn't work, because con variables cannot be reassigned</code></pre>
|
|
||||||
<p>The following lines are equivalent,</p>
|
|
||||||
<pre class="gp1"><code>con a <- f64(7.2);
|
|
||||||
con a: f64 <- 7.2;
|
|
||||||
con a <- 7.2; // 7.2 is implicitly of type f64
|
|
||||||
con a <- 7.2D; // With an explicit type suffix</code></pre>
|
|
||||||
<p>as are these.</p>
|
|
||||||
<pre class="gp1"><code>var c: f32 <- 9;
|
|
||||||
var c <- f32(9);
|
|
||||||
var c: f32 <- f32(9);
|
|
||||||
var c <- 9F;</code></pre>
|
|
||||||
<p>Variable assignments are expressions in GP1, which can enable some
|
|
||||||
very interesting code patterns. For example, it allows multiple
|
|
||||||
assignments on one line with the following syntax.
|
|
||||||
<code>con a <- var b <- "death and taxes"</code> assigns the
|
|
||||||
string <code>"death and taxes"</code> to both <code>a</code> and
|
|
||||||
<code>b</code>, leaving you with one constant and one variable
|
|
||||||
containing separate instances of identical data. This is equivalent to
|
|
||||||
writing <code>con a <- "death and taxes"</code> and
|
|
||||||
<code>var b <- "death and taxes"</code> each on their own line.
|
|
||||||
Assignment as an expression also eliminates much of the need to define
|
|
||||||
variables immediately before the control structure in which they're
|
|
||||||
used, which improves readability.</p>
|
|
||||||
<h2 id="intrinsic-types">Intrinsic Types</h2>
|
|
||||||
<h3 id="numeric-types">Numeric Types</h3>
|
|
||||||
<p><code>u8</code> <code>u16</code> <code>u32</code> <code>u64</code>
|
|
||||||
<code>u128</code> <code>u256</code> <code>usize</code>
|
|
||||||
<code>byte</code></p>
|
|
||||||
<p><code>i8</code> <code>i16</code> <code>i32</code> <code>i64</code>
|
|
||||||
<code>i128</code> <code>i256</code> <code>isize</code></p>
|
|
||||||
<p><code>f16</code> <code>f32</code> <code>f64</code> <code>f128</code>
|
|
||||||
<code>f256</code></p>
|
|
||||||
<p>GP1 has signed integer, unsigned integer, and floating point numeric
|
|
||||||
types. Numeric types take the form of a single-letter indicator followed
|
|
||||||
by the type's size in bits. The indicators are <strong>i</strong>
|
|
||||||
(signed integer), <strong>u</strong> (unsigned integer), and
|
|
||||||
<strong>f</strong> (floating point). <code>usize</code> and
|
|
||||||
<code>isize</code> are pointer-width types. For example, on a 64-bit
|
|
||||||
system, <code>usize</code> is a 64-bit unsigned integer. However, it
|
|
||||||
must be cast to <code>u64</code> when assigning to a <code>u64</code>
|
|
||||||
variable. The type <code>byte</code> is an alias for <code>u8</code>.
|
|
||||||
Numeric operators are as one expects from C, with the addition of
|
|
||||||
<code>**</code> as a power operator.</p>
|
|
||||||
<p>Numeric literals have an implicit type, or the type can be specified
|
|
||||||
by a case-insensitive suffix. For example:</p>
|
|
||||||
<pre class="gp1"><code>var i1 <- 1234; // implicitly i32
|
|
||||||
var f1 <- 1234.5; // implicitly f64
|
|
||||||
|
|
||||||
var i3 <- 1234L; // i64
|
|
||||||
var u3 <- 1234ui; // u32
|
|
||||||
var f2 <- 1234.6F; // f32</code></pre>
|
|
||||||
<p>The complete set of suffixes is given.</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr class="header">
|
|
||||||
<th>suffix</th>
|
|
||||||
<th>corresponding type</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr class="odd">
|
|
||||||
<td>s</td>
|
|
||||||
<td>i16</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="even">
|
|
||||||
<td>i</td>
|
|
||||||
<td>i32</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd">
|
|
||||||
<td>l</td>
|
|
||||||
<td>i64</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="even">
|
|
||||||
<td>p</td>
|
|
||||||
<td>isize</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd">
|
|
||||||
<td>b</td>
|
|
||||||
<td>byte</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="even">
|
|
||||||
<td>us</td>
|
|
||||||
<td>u16</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd">
|
|
||||||
<td>ui</td>
|
|
||||||
<td>u32</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="even">
|
|
||||||
<td>ul</td>
|
|
||||||
<td>u64</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd">
|
|
||||||
<td>up</td>
|
|
||||||
<td>usize</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="even">
|
|
||||||
<td>f</td>
|
|
||||||
<td>f32</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd">
|
|
||||||
<td>d</td>
|
|
||||||
<td>f64</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="even">
|
|
||||||
<td>q</td>
|
|
||||||
<td>f128</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h3 id="booleans">Booleans</h3>
|
|
||||||
<p><code>bool</code> is the standard boolean type with support for all
|
|
||||||
the usual operations. The boolean literals are <code>true</code> and
|
|
||||||
<code>false</code>. Bool operators are as one expects from C, with the
|
|
||||||
exception that NOT is <code>!!</code> instead of <code>!</code>.</p>
|
|
||||||
<h3 id="bitwise-operators">Bitwise Operators</h3>
|
|
||||||
<p>Bitwise operators can be applied only to integers and booleans. They
|
|
||||||
are single counterparts of the doubled boolean operators, e.g. boolean
|
|
||||||
negation is <code>!!</code>, so bitwise negation is <code>!</code>.</p>
|
|
||||||
<h3 id="strings-and-characters">Strings and Characters</h3>
|
|
||||||
<p><code>char</code> is a unicode character of variable size. Char
|
|
||||||
literals are single-quoted, e.g. <code>'c'</code>. Any single valid char
|
|
||||||
value can be used as a literal in this fasion.</p>
|
|
||||||
<p><code>string</code> is a unicode string. String literals are
|
|
||||||
double-quoted, e.g. <code>"Hello, World."</code>.</p>
|
|
||||||
<h3 id="arrays">Arrays</h3>
|
|
||||||
<p>GP supports typical array operations.</p>
|
|
||||||
<pre class="gp1"><code>var tuples : (int, int)[]; // declare array of tuples
|
|
||||||
var strings : string[]; // declare array of strings
|
|
||||||
|
|
||||||
var array <- i32[n]; // declare and allocate array of n elements
|
|
||||||
// n is any number that can be coerced to usize
|
|
||||||
|
|
||||||
con nums <- {1, 2, 3}; // immutable array of i32
|
|
||||||
</code></pre>
|
|
||||||
<p>Use the <code>length</code> property to access the number of elements
|
|
||||||
in an allocated array. Attempting to access <code>length</code> of an
|
|
||||||
unallocated array is an exception.</p>
|
|
||||||
<pre class="gp1"><code>
|
|
||||||
var colors <- {"Red", "White", "Blue"}; // allocate array
|
|
||||||
|
|
||||||
var count <- colors.length; // count is usize(3)
|
|
||||||
</code></pre>
|
|
||||||
<p>Arrays can be indexed with any integer type (signed or unsigned).
|
|
||||||
Negative values wrap from the end (-1 is the last element). An exception
|
|
||||||
occurs if the value is too big, i.e.no modulo operation is
|
|
||||||
performed.</p>
|
|
||||||
<pre class="gp1"><code>var w <- {1, 2, 3, 4, 5, 6, 7};
|
|
||||||
|
|
||||||
w[0] // first element, 1
|
|
||||||
w[-1] // last element, 7
|
|
||||||
|
|
||||||
var x <- isize(-5);
|
|
||||||
w[x] // 5th to last element, 3
|
|
||||||
</code></pre>
|
|
||||||
<h3 id="tuples">Tuples</h3>
|
|
||||||
<p>Tuples group multiple values into a single value with anonymous,
|
|
||||||
ordered fields. <code>()</code> is an empty tuple.
|
|
||||||
<code>("hello", i32(17))</code> is a tuple of type
|
|
||||||
<code>(string i32)</code>. Tuple fields are named like indices,
|
|
||||||
i.e.<code>(u128(4), "2").1</code> would be <code>"2"</code>.</p>
|
|
||||||
<p>The unit type, represented as a 0-tuple, is written
|
|
||||||
<code>()</code>.</p>
|
|
||||||
<h3 id="regex">Regex</h3>
|
|
||||||
<p><code>regex</code> is a regular expression. GP1 regex format is
|
|
||||||
identical to that of .NET 5 and very similar to that of gawk.</p>
|
|
||||||
<h2 id="named-functions">Named Functions</h2>
|
|
||||||
<p>Some examples of defining named functions:</p>
|
|
||||||
<pre class="gp1"><code>fn sum(a: f32, b: f32): f32 { a + b } // takes parameters and returns an f32
|
|
||||||
|
|
||||||
fn twice_println(s: string) { // takes parameters and implicitly returns ()
|
|
||||||
println("${s}\n${s}");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn join_println(a: string, b: string): () { // takes parameters and explicitly returns ()
|
|
||||||
println("${a} ${b}");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn seven(): u32 { 7 } // takes no parameters and returns the u32 value of 7</code></pre>
|
|
||||||
<p>There are a number of syntaxes allowed for calling a given function.
|
|
||||||
This is because the caller is allowed to assign to zero or more of that
|
|
||||||
function's parameters by name. Parameters assigned by name are freely
|
|
||||||
ordered, while those assigned normally bind to the first parameter
|
|
||||||
ordered from left to right in the function definition that is
|
|
||||||
unassigned. With regard to the <code>join_println</code> function
|
|
||||||
defined above, this means that all of the following are valid and behave
|
|
||||||
identically.</p>
|
|
||||||
<pre class="gp1"><code>join_println(a <- "Hello,", b <- "World.");
|
|
||||||
join_println(b <- "World.", a <- "Hello,");
|
|
||||||
join_println(b <- "World.", "Hello,");
|
|
||||||
join_println("Hello,", "World.");</code></pre>
|
|
||||||
<p>Function names may be overloaded. For example,
|
|
||||||
<code>join_println</code> could be additionally defined as</p>
|
|
||||||
<pre class="gp1"><code>fn join_println(a: string, b: string, sep: string) {
|
|
||||||
println("${a}${sep}${b}");
|
|
||||||
}</code></pre>
|
|
||||||
<p>and then both <code>join_println("Hello,", "World.", " ")</code> and
|
|
||||||
<code>join_println("Hello,", "World.")</code> would be valid calls.</p>
|
|
||||||
<p>Functions may be defined and called within other functions. You may
|
|
||||||
be familar with this pattern from functional languages like F#, wherein
|
|
||||||
a wrapper function is often used to guard an inner recursive function
|
|
||||||
(GP1 permits both single and mutual recursion in functions). For
|
|
||||||
example:</p>
|
|
||||||
<pre class="gp1"><code>fn factorial(n: u256): u256 {
|
|
||||||
fn aux(n: u256, accumulator: u256): u256 {
|
|
||||||
match n > 1 {
|
|
||||||
true => aux(n - 1, accumulator * n),
|
|
||||||
_ => accumulator,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aux(n, 1)
|
|
||||||
}</code></pre>
|
|
||||||
<p>Arguments are passed by value by default. For information on the
|
|
||||||
syntax used in this example, refer to <em>Control Flow</em>.</p>
|
|
||||||
<h2 id="anonymous-functions">Anonymous Functions</h2>
|
|
||||||
<h3 id="closures">Closures</h3>
|
|
||||||
<p>Closures behave as one would expect in GP1, exactly like they do in
|
|
||||||
most other programming languages that feature them. Closures look like
|
|
||||||
this:</p>
|
|
||||||
<pre class="gp1"><code>var x: u32 <- 8;
|
|
||||||
|
|
||||||
var foo <- { y, z => x * y * z}; // foo is a closure; its type is fn<u32 | u32>
|
|
||||||
assert(foo(3, 11) == (8 * 3 * 11)); // true
|
|
||||||
|
|
||||||
x <- 5;
|
|
||||||
assert(foo(3) == (8 * 3 * 11)); // true
|
|
||||||
|
|
||||||
con bar <- { => x * x }; // bar is a closure of type `fn<u32>`
|
|
||||||
|
|
||||||
assert(bar() == 25); // true because closure references already-defined x</code></pre>
|
|
||||||
<p>They are surrounded by curly braces. Within the curly braces goes an
|
|
||||||
optional, comma-separated parameter list, followed by a required
|
|
||||||
<code>=></code> symbol, followed by an optional expression. If no
|
|
||||||
expression is included, the closure implicitly returns
|
|
||||||
<code>()</code>.</p>
|
|
||||||
<p>The reason the match-expression uses the same <code>=></code>
|
|
||||||
symbol is because the <code>when</code> section of a match arm is an
|
|
||||||
implicit closure. The reason <code>=></code> in particular was chosen
|
|
||||||
for closures is twofold. One, arrows are conventional for expressing
|
|
||||||
anonymous functions, and two, the space between the lines of an equals
|
|
||||||
sign is enclosed by them.</p>
|
|
||||||
<h3 id="lambdas">Lambdas</h3>
|
|
||||||
<p>Lambdas are nearly identical to closures, but they don't close over
|
|
||||||
their environment, and they use the <code>-></code> symbol in place
|
|
||||||
of <code>=></code>. A few examples of lambdas:</p>
|
|
||||||
<pre class="gp1"><code>con x: u32 <- 4; // this line is totally irrelevant
|
|
||||||
|
|
||||||
con square <- { x -> x * x }; // this in not valid, because the type of the function is not known
|
|
||||||
con square <- { x: u32 -> x * x }; // this if fine, because the type is specified in the lambda
|
|
||||||
con square: fn<u32 | u32> <- { x -> x * x }; // also fine, because the type is specified in the declaration</code></pre>
|
|
||||||
<h2 id="function-types">Function Types</h2>
|
|
||||||
<p>Functions are first-class citizens in GP1, so you can assign them to
|
|
||||||
variables, pass them as arguments, &c.However, using the function
|
|
||||||
definition syntax is suboptimal when using function types. Instead,
|
|
||||||
there is a separate syntax for function types. Given the function
|
|
||||||
<code>fn sum(a: f64, b: f64): f64 { a + b }</code> the function type is
|
|
||||||
expressed <code>fn<f64 f64 | f64></code>, meaning a function that
|
|
||||||
accepts two f64 values and returns an f64. Therefore,</p>
|
|
||||||
<pre class="gp1"><code>fn sum(a: f64, b: f64): f64 { a + b } </code></pre>
|
|
||||||
<pre class="gp1"><code>con sum: fn<f64 f64 | f64> <- { a, b -> a + b };</code></pre>
|
|
||||||
<pre class="gp1"><code>con sum <- { a: f64, b: f64 -> a + b };</code></pre>
|
|
||||||
<p>are all equivalent ways of binding a function of type
|
|
||||||
<code>fn<f64 f64 | f64></code> to the constant <code>sum</code>.
|
|
||||||
Here's an example of how to express a function type for a function
|
|
||||||
argument.</p>
|
|
||||||
<pre class="gp1"><code>fn apply_op(a: i32, b: i32, op: fn<i32 i32 | i32>): i32 {
|
|
||||||
op(a, b)
|
|
||||||
}</code></pre>
|
|
||||||
<h3 id="function-type-inference">Function Type Inference</h3>
|
|
||||||
<p>The above example provides an explicit type for the argument
|
|
||||||
<code>op</code>. You could safely rewrite this as</p>
|
|
||||||
<pre class="gp1"><code>fn apply_op(a: i32, b: i32, op: fn): i32 {
|
|
||||||
op(a, b)
|
|
||||||
}</code></pre>
|
|
||||||
<p>because the compiler can safely infer the function type of
|
|
||||||
<code>op</code>. Type inference only works to figure out the function
|
|
||||||
signature, so <code>fn apply_op(a:i32, b:i32, op):i32 { . . . }</code>
|
|
||||||
is not allowed.</p>
|
|
||||||
<h2 id="coercion-and-casting">Coercion and Casting</h2>
|
|
||||||
<p>Refer to <em>Variables and Constants</em> for information on the
|
|
||||||
syntax used in this section.</p>
|
|
||||||
<p>Numeric types are automatically coerced into other numeric types as
|
|
||||||
long as that coercion is not lossy. For example,</p>
|
|
||||||
<pre class="gp1"><code>var x: i32 <- 10;
|
|
||||||
var y: i64 <- x;</code></pre>
|
|
||||||
<p>is perfectly legal (the 32-bit value fits nicely in the 64-bit
|
|
||||||
variable). However, automatic coercion doesn't work if it would be
|
|
||||||
lossy, so</p>
|
|
||||||
<pre class="gp1"><code>var x: i64 <- 10;
|
|
||||||
var y: i32 <- x;</code></pre>
|
|
||||||
<p>doesn't work. This holds for numeric literals as well.
|
|
||||||
Unsurprisingly, <code>var x: i32 <- 3.14</code> wouldn't compile. The
|
|
||||||
floating point value can't be automatically coerced to an integer type.
|
|
||||||
So what does work? Casting via the target type's pseudo-constructor
|
|
||||||
works.</p>
|
|
||||||
<pre class="gp1"><code>con x: f64 <- 1234.5; // okay because the literal can represent any floating point type
|
|
||||||
con y: f64 <- f16(1234.5); // also okay, because any f16 can be losslessly coerced to an f64
|
|
||||||
con z: i32 <- i32(x); // also okay; uses the i32 pseudo-constructor to 'cast' x to a 32-bit integer
|
|
||||||
|
|
||||||
assert(z == 1234)
|
|
||||||
|
|
||||||
con a: f64 <- 4 * 10 ** 38; // this value is greater than the greatest f32
|
|
||||||
con b: f32 <- f32(a); // the value of b is the maximum value of f32</code></pre>
|
|
||||||
<p>This approach is valid for all intrinsic types. For example,
|
|
||||||
<code>var flag: bool <- bool(0)</code> sets <code>flag</code> to
|
|
||||||
<code>false</code> and <code>var txt: string <- string(83.2)</code>
|
|
||||||
sets <code>txt</code> to the string value <code>"83.2"</code>. Such
|
|
||||||
behavior can be implemented by a programmer on their own types via a
|
|
||||||
system we'll discuss in the <em>Interfaces</em> section.</p>
|
|
||||||
<h2 id="program-structure">Program Structure</h2>
|
|
||||||
<p>Every GP1 program has an entry-point function. Within that function,
|
|
||||||
statements are executed from top to bottom and left to right. The
|
|
||||||
entry-point function can be declared with the <code>entry</code> keyword
|
|
||||||
in place of <code>fn</code> and returns an integer, which will be
|
|
||||||
provided to the host operating system as an exit code. Naturally, this
|
|
||||||
means that the handling of that code is platform-dependent once it
|
|
||||||
passes the program boundry, so it's important to keep in mind that a
|
|
||||||
system may implicitly downcast or otherwise modify it before it is made
|
|
||||||
available to the user. If no exit code is specified, or if the return
|
|
||||||
type of the function is not an integer, GP1 assumes an exit code of
|
|
||||||
<code>usize(0)</code> and returns that to the operating system.</p>
|
|
||||||
<p>The following program prints Hello, World. and exits with an error
|
|
||||||
code.</p>
|
|
||||||
<pre class="gp1"><code>entry main(): usize {
|
|
||||||
hello_world();
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hello_world() {
|
|
||||||
println("Hello, World.");
|
|
||||||
}</code></pre>
|
|
||||||
<p>The entry function may have any name; it's the <code>entry</code>
|
|
||||||
keyword that makes it the entry point. The entry function may also be
|
|
||||||
implicit. If one is not defined explicitly, the entire file is treated
|
|
||||||
as being inside an entry function. Therefore,</p>
|
|
||||||
<pre class="gp1"><code>println("Hello, World.");</code></pre>
|
|
||||||
<p>is a valid and complete program identical to</p>
|
|
||||||
<pre class="gp1"><code>entry main(): usize {
|
|
||||||
println("Hello, World.");
|
|
||||||
}</code></pre>
|
|
||||||
<p>This behavior can lend GP1 a very flexible feeling akin to many
|
|
||||||
scripting languages.</p>
|
|
||||||
<p>In a program where there is an entry-point specified, only
|
|
||||||
expressions made within that function will be evaluated. This means that
|
|
||||||
the following program does NOT print anything to the console.</p>
|
|
||||||
<pre class="gp1"><code>entry main(): usize {
|
|
||||||
con x: usize <- 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
println("This text will not be printed.");</code></pre>
|
|
||||||
<p>In fact, this program is invalid. Whenever there is an explicit entry
|
|
||||||
point, no statements may be made in the global scope.</p>
|
|
||||||
<h2 id="control-flow">Control Flow</h2>
|
|
||||||
<h3 id="conditionals">Conditionals</h3>
|
|
||||||
<p>At this time, GP1 has only one non-looping conditional control
|
|
||||||
structure, in two variants: <code>match</code> and
|
|
||||||
<code>match all</code>. The syntax is as follows, where
|
|
||||||
<code>*expr*</code> are expressions and <code>pattern*</code> are
|
|
||||||
pattern matching options (refer to <em>Pattern Matching</em> for more
|
|
||||||
info).</p>
|
|
||||||
<pre class="gp1"><code>match expr {
|
|
||||||
pattern1 => arm_expr1,
|
|
||||||
pattern2 => arm_expr2,
|
|
||||||
_ => arm_expr3,
|
|
||||||
}</code></pre>
|
|
||||||
<p>The <code>match</code> expression executes the first arm that matches
|
|
||||||
the pattern passed in <code>expr</code>. The <code>match all</code>
|
|
||||||
expression executes all arms that match the pattern. Both flavors return
|
|
||||||
their last executed expression.</p>
|
|
||||||
<p>The <code>when</code> keyword may be used in a given match arm to
|
|
||||||
further restrict the conditions of execution, e.g.</p>
|
|
||||||
<pre class="gp1"><code>con fs <- 43;
|
|
||||||
|
|
||||||
con is_even <- match fs {
|
|
||||||
n when n % 2 == 0 => " is "
|
|
||||||
_ => " is not "
|
|
||||||
};
|
|
||||||
|
|
||||||
print(fs + is_even + "even.")</code></pre>
|
|
||||||
<h3 id="loops">Loops</h3>
|
|
||||||
<p>Several looping structures are supported in GP1</p>
|
|
||||||
<ul>
|
|
||||||
<li><code>loop</code></li>
|
|
||||||
<li><code>for</code></li>
|
|
||||||
<li><code>while</code></li>
|
|
||||||
<li><code>do/while</code></li>
|
|
||||||
</ul>
|
|
||||||
<p>along with <code>continue</code> and <code>break</code> to help
|
|
||||||
control program flow. All of these are statements.</p>
|
|
||||||
<pre class="gp1"><code>loop { . . . } // an unconditional loop -- runs forever or until broken</code></pre>
|
|
||||||
<pre class="gp1"><code>for i in some_iterable { . . . } // loop over anything that is iterable</code></pre>
|
|
||||||
<pre class="gp1"><code>while some_bool { . . . } // classic conditional loop that executes until the predicate is false</code></pre>
|
|
||||||
<pre class="gp1"><code>do { . . .
|
|
||||||
} while some_bool // traditional do/while loop that ensures body executes at least once</code></pre>
|
|
||||||
<h2 id="pattern-matching">Pattern Matching</h2>
|
|
||||||
<p>Pattern matching behaves essentially as it does in SML, with support
|
|
||||||
for various sorts of destructuring. It works in normal assignment and in
|
|
||||||
<code>match</code> arms. It will eventually work in function parameter
|
|
||||||
assignment, but perhaps not at first.</p>
|
|
||||||
<p>For now, some examples.</p>
|
|
||||||
<pre class="gp1"><code>a <- ("hello", "world"); // a is a tuple of strings
|
|
||||||
(b, c) <- a;
|
|
||||||
|
|
||||||
assert(b == "hello" && c == "world")
|
|
||||||
|
|
||||||
fn u32_list_to_string(l: List<u32>): string { // this is assuming that square brackets are used for linked lists
|
|
||||||
con elements <- match l {
|
|
||||||
[] => "",
|
|
||||||
[e] => string(e),
|
|
||||||
h::t => string(h) + ", " + u32_list_to_string(t), // the bit before the arrow in each arm is a pattern
|
|
||||||
} // h::t matches the head and tail of the list to h and t, respectively
|
|
||||||
"[" + elements + "]" // [s] matches any single-element list
|
|
||||||
} // [] matches any empty list</code></pre>
|
|
||||||
<h2 id="interfaces">Interfaces</h2>
|
|
||||||
<p>Interfaces are in Version 2 on the roadmap.</p>
|
|
||||||
<h2 id="user-defined-types">User-Defined Types</h2>
|
|
||||||
<h3 id="enums">Enums</h3>
|
|
||||||
<p>Enums are pretty powerful in GP1. They can be the typical enumerated
|
|
||||||
type you'd expect, like</p>
|
|
||||||
<pre class="gp1"><code>enum Coin { penny, nickle, dime, quarter } // 'vanilla' enum
|
|
||||||
|
|
||||||
var a <- Coin.nickle
|
|
||||||
assert a == Coin.nickle
|
|
||||||
</code></pre>
|
|
||||||
<p>Or an enum can have an implicit field named <code>value</code></p>
|
|
||||||
<pre class="gp1"><code>enum Coin: u16 { penny(1), nickle(5), dime(10), quarter(25) }
|
|
||||||
|
|
||||||
var a <- Coin.nickle;
|
|
||||||
assert(a == Coin.nickle);
|
|
||||||
assert(a.value == 5);</code></pre>
|
|
||||||
<p>Or an enum can be complex with a user-defined set of fields, like</p>
|
|
||||||
<pre class="gp1"><code>enum CarModel(make: string, mass: f32, wheelbase: f32) { // enum with multiple fields
|
|
||||||
gt ( "ford", 1581, 2.71018 ),
|
|
||||||
c8_corvette ( "chevy", 1527, 2.72288 )
|
|
||||||
}</code></pre>
|
|
||||||
<p>A field can also have a function type. For example</p>
|
|
||||||
<pre class="gp1"><code>enum CarModel(make: string, mass: f32, wheelbase: f32, gasUsage: fn<f32 | f32>) {
|
|
||||||
gt ( "ford", 1581, 2.71018, { miles_traveled -> miles_traveled / 14 } ),
|
|
||||||
c8_corvette ( "chevy", 1527, 2.72288, { miles_traveled -> miles_traveled / 19 } )
|
|
||||||
}
|
|
||||||
|
|
||||||
var my_car <- CarModel.c8_corvette;
|
|
||||||
var gas_used <- my_car.gasUsage(200); // estimate how much gas I'd use on a 200 mile trip</code></pre>
|
|
||||||
<p>Equivalence of enums is not influenced by case values, e.g.</p>
|
|
||||||
<pre class="gp1"><code>enum OneOrAnother: u16 { one(0), another(0) }
|
|
||||||
|
|
||||||
con a <- OneOrAnother.one;
|
|
||||||
con b <- OneOrAnother.another;
|
|
||||||
|
|
||||||
assert(a != b);
|
|
||||||
assert(a.value == b.value);</code></pre>
|
|
||||||
<p>It's important to remember that enums are 100% always totally in
|
|
||||||
every concieveable fashion immutable. To make this easier to enforce,
|
|
||||||
only value types are allowed for enum fields.</p>
|
|
||||||
<h3 id="records">Records</h3>
|
|
||||||
<p>Records are record types, defined with the <code>record</code>
|
|
||||||
keyword. Fields are defined in the <code>record</code> block and
|
|
||||||
behavior is defined in the optional <code>impl</code> block.</p>
|
|
||||||
<p>For example,</p>
|
|
||||||
<pre class="gp1"><code>record Something {
|
|
||||||
label: i32 // field label followed by some type
|
|
||||||
} impl { . . . } // associated functions. This is different than having functions in the fields section because impl functions are not assignable.</code></pre>
|
|
||||||
<p>If the record implements some interface, <code>SomeInterface</code>,
|
|
||||||
the <code>impl</code> would be replaced with
|
|
||||||
<code>impl SomeInterface</code>, and the functions of
|
|
||||||
<code>SomeInterface</code> would be defined alongside any other
|
|
||||||
functions of the <code>Something</code> record.</p>
|
|
||||||
<h3 id="unions">Unions</h3>
|
|
||||||
<p>Unions are the classic discriminated sum type.</p>
|
|
||||||
<pre class="gp1"><code>union BinaryTree {
|
|
||||||
Empty,
|
|
||||||
Leaf: i32,
|
|
||||||
Node: (BinaryTree BinaryTree),
|
|
||||||
}</code></pre>
|
|
||||||
<h3 id="type-aliases">Type Aliases</h3>
|
|
||||||
<p>Refer to <em>Generics</em> for info on the syntax used in this
|
|
||||||
section.</p>
|
|
||||||
<p>Type aliasing is provided with the <code>type</code> keyword,
|
|
||||||
e.g.</p>
|
|
||||||
<pre class="gp1"><code>type TokenStream Sequence<Token>
|
|
||||||
type Ast Tree<AbstractNode>
|
|
||||||
|
|
||||||
fn parse(ts: TokenStream): Ast { . . . }</code></pre>
|
|
||||||
<p>Notice how much cleaner the function definition looks with the
|
|
||||||
aliased types. This keyword is useful mainly for readability and domain
|
|
||||||
modeling.</p>
|
|
||||||
<h2 id="generics">Generics</h2>
|
|
||||||
<p>Generics are in Version 2 on the official GP1 roadmap. They roughly
|
|
||||||
use C++ template syntax or Rust generic syntax.</p>
|
|
||||||
<h2 id="references-and-reference-types">References and Reference
|
|
||||||
Types</h2>
|
|
||||||
<p>GP1 has three operators involved in handling references,
|
|
||||||
<code>#</code>, <code>&</code>, and <code>@</code>. These are
|
|
||||||
immutable reference, mutable reference, and dereference, respectively.
|
|
||||||
Some examples of referencing/dereferencing values:</p>
|
|
||||||
<pre class="gp1"><code>var a <- "core dumped";
|
|
||||||
var b <- &a; // b is a mutable reference to a
|
|
||||||
|
|
||||||
assert(a == @b);
|
|
||||||
assert(a != b);
|
|
||||||
|
|
||||||
@b <- "missing ; at line 69, column 420";
|
|
||||||
assert(a == "missing ; at line 69, column 420");
|
|
||||||
|
|
||||||
b <- &"missing ; at line 420, column 69";
|
|
||||||
assert(a != "missing ; at line 420, column 69");
|
|
||||||
|
|
||||||
var c <- #b; // c is an immutable reference to b
|
|
||||||
assert(@c == b);
|
|
||||||
assert(@@c == a);
|
|
||||||
|
|
||||||
@c <- &"kablooey"; // this does not work. `c` is an immutable reference and cannot be used to assign its referent.</code></pre>
|
|
||||||
<p>Naturally, only <code>var</code> values can be mutated through
|
|
||||||
references.</p>
|
|
||||||
<p>The reference operators may be prepended to any type, T, to describe
|
|
||||||
the type of a reference to a value of type T, e.g.</p>
|
|
||||||
<pre class="gp1"><code>fn set_through(ref: &string) { // this function takes a mutable reference to a string and returns `()`
|
|
||||||
@ref <- "goodbye";
|
|
||||||
}
|
|
||||||
|
|
||||||
var a <- "hello";
|
|
||||||
set_through(&a);
|
|
||||||
|
|
||||||
assert(a == "goodbye");</code></pre>
|
|
70
html/cats.ml
70
html/cats.ml
|
@ -1,70 +0,0 @@
|
||||||
module type Functor = sig
|
|
||||||
type 'a t
|
|
||||||
val map : ('a -> 'b) -> 'a t -> 'b t
|
|
||||||
end
|
|
||||||
|
|
||||||
module type Applicative = sig
|
|
||||||
type 'a t
|
|
||||||
val pure : 'a -> 'a t
|
|
||||||
val apply : ('a -> 'b) t -> 'a t -> 'b t
|
|
||||||
end
|
|
||||||
|
|
||||||
module type Monad = sig
|
|
||||||
type 'a t
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
val bind : ('a -> 'b t) -> 'a t -> 'b t
|
|
||||||
end
|
|
||||||
|
|
||||||
module ApplicativeOfMonad (M : Monad) : Applicative with type 'a t = 'a M.t = struct
|
|
||||||
type 'a t = 'a M.t
|
|
||||||
let pure = M.return
|
|
||||||
let apply f x = M.(bind (fun y -> bind (fun g -> return (g y)) f) x)
|
|
||||||
end
|
|
||||||
|
|
||||||
module FunctorOfApplicative (A : Applicative) : Functor with type 'a t = 'a A.t = struct
|
|
||||||
type 'a t = 'a A.t
|
|
||||||
let map f x = A.(apply (pure f) x)
|
|
||||||
end
|
|
||||||
|
|
||||||
module FunctorOfMonad (M : Monad) : Functor with type 'a t = 'a M.t = struct
|
|
||||||
include FunctorOfApplicative(ApplicativeOfMonad(M))
|
|
||||||
end
|
|
||||||
|
|
||||||
module MonadDerive (M : Monad) = struct
|
|
||||||
include M
|
|
||||||
include ApplicativeOfMonad(M)
|
|
||||||
include FunctorOfMonad(M)
|
|
||||||
let (>>=) x f = bind f x
|
|
||||||
let (<$>) x f = map x f
|
|
||||||
let (<*>) x f = apply x f
|
|
||||||
end
|
|
||||||
|
|
||||||
module ListMonad = struct
|
|
||||||
type 'a t = 'a list
|
|
||||||
let return x = [x]
|
|
||||||
let rec bind (f : 'a -> 'b list) : 'a list -> 'b list = function
|
|
||||||
| [] -> []
|
|
||||||
| x :: xs -> f x @ bind f xs
|
|
||||||
end
|
|
||||||
|
|
||||||
module Dlm = MonadDerive(ListMonad)
|
|
||||||
|
|
||||||
let pair x y = x, y
|
|
||||||
let cart_prod xs ys = Dlm.(pair <$> xs <*> ys)
|
|
||||||
|
|
||||||
let () = cart_prod [1;2;3;4] ["7"; "hello there"; "forthwith!"]
|
|
||||||
|> List.iter (fun (x, y) -> print_endline @@ "(" ^ string_of_int x ^ ", " ^ y ^ ")")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(* ============================================================================================= *)
|
|
||||||
|
|
||||||
module StateMonad (S : sig type t end) = struct
|
|
||||||
type 'a t = S.t -> S.t * 'a
|
|
||||||
let return x s = (s, x)
|
|
||||||
let bind f x s = let s', a = x s in f a s'
|
|
||||||
end
|
|
||||||
|
|
||||||
module IntStateMonad = StateMonad(struct type t = int end)
|
|
||||||
|
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
module type Functor = sig
|
|
||||||
type 'a t
|
|
||||||
val map : ('a -> 'b) -> 'a t -> 'b t
|
|
||||||
end
|
|
||||||
|
|
||||||
module type Applicative = sig
|
|
||||||
type 'a t
|
|
||||||
val pure : 'a -> 'a t
|
|
||||||
val apply : ('a -> 'b) t -> 'a t -> 'b t
|
|
||||||
end
|
|
||||||
|
|
||||||
module type Monad = sig
|
|
||||||
type 'a t
|
|
||||||
val return : 'a -> 'a t
|
|
||||||
val bind : ('a -> 'b t) -> 'a t -> 'b t
|
|
||||||
end
|
|
||||||
|
|
||||||
module ApplicativeOfMonad (M : Monad) : Applicative with type 'a t = 'a M.t = struct
|
|
||||||
type 'a t = 'a M.t
|
|
||||||
let pure = M.return
|
|
||||||
let apply f x = M.(bind (fun y -> bind (fun g -> return (g y)) f) x)
|
|
||||||
end
|
|
||||||
|
|
||||||
module FunctorOfApplicative (A : Applicative) : Functor with type 'a t = 'a A.t = struct
|
|
||||||
type 'a t = 'a A.t
|
|
||||||
let map f x = A.(apply (pure f) x)
|
|
||||||
end
|
|
||||||
|
|
||||||
module FunctorOfMonad (M : Monad) : Functor with type 'a t = 'a M.t = struct
|
|
||||||
include FunctorOfApplicative(ApplicativeOfMonad(M))
|
|
||||||
end
|
|
||||||
|
|
||||||
module MonadDerive (M : Monad) = struct
|
|
||||||
include M
|
|
||||||
include ApplicativeOfMonad(M)
|
|
||||||
include FunctorOfMonad(M)
|
|
||||||
let (>>=) x f = bind f x
|
|
||||||
let (<$>) x f = map x f
|
|
||||||
let (<*>) x f = apply x f
|
|
||||||
end
|
|
||||||
|
|
||||||
module ListMonad = struct
|
|
||||||
type 'a t = 'a list
|
|
||||||
let return x = [x]
|
|
||||||
let rec bind (f : 'a -> 'b list) : 'a list -> 'b list = function
|
|
||||||
| [] -> []
|
|
||||||
| x :: xs -> f x @ bind f xs
|
|
||||||
end
|
|
||||||
|
|
||||||
module Dlm = MonadDerive(ListMonad)
|
|
||||||
|
|
||||||
let pair x y = x, y
|
|
||||||
let cart_prod xs ys = Dlm.(pair <$> xs <*> ys)
|
|
||||||
|
|
||||||
let () = cart_prod [1;2;3;4] ["7"; "hello there"; "forthwith!"]
|
|
||||||
|> List.iter (fun (x, y) -> print_endline @@ "(" ^ string_of_int x ^ ", " ^ y ^ ")")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(* ============================================================================================= *)
|
|
||||||
|
|
||||||
module StateMonad (S : sig type t end) = struct
|
|
||||||
type 'a t = S.t -> S.t * 'a
|
|
||||||
let return x s = (s, x)
|
|
||||||
let bind f x s = let s', a = x s in f a s'
|
|
||||||
end
|
|
||||||
|
|
||||||
module IntStateMonad = StateMonad(struct type t = int end)
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 113 KiB |
|
@ -1,114 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
|
||||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
||||||
<!-- Generated by graphviz version 12.1.0 (20240811.2233)
|
|
||||||
-->
|
|
||||||
<!-- Pages: 1 -->
|
|
||||||
<svg width="844pt" height="426pt"
|
|
||||||
viewBox="0.00 0.00 843.85 425.92" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 421.92)">
|
|
||||||
<polygon fill="white" stroke="none" points="-4,4 -4,-421.92 839.85,-421.92 839.85,4 -4,4"/>
|
|
||||||
<!-- cp -->
|
|
||||||
<g id="node1" class="node">
|
|
||||||
<title>cp</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="102.53" cy="-375" rx="96.17" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="42.53" y="-372.45" font-family="Open Sans" font-weight="bold" font-size="14.00">Consider Phlebas</text>
|
|
||||||
</g>
|
|
||||||
<!-- ltw -->
|
|
||||||
<g id="node7" class="node">
|
|
||||||
<title>ltw</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="102.53" cy="-209" rx="102.53" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="38.03" y="-206.45" font-family="Open Sans" font-weight="bold" font-size="14.00">Look to Windward</text>
|
|
||||||
</g>
|
|
||||||
<!-- cp->ltw -->
|
|
||||||
<g id="edge1" class="edge">
|
|
||||||
<title>cp->ltw</title>
|
|
||||||
<path fill="none" stroke="black" d="M102.53,-355.19C102.53,-327.09 102.53,-273.87 102.53,-240.26"/>
|
|
||||||
<polygon fill="black" stroke="black" points="106.03,-240.36 102.53,-230.36 99.03,-240.36 106.03,-240.36"/>
|
|
||||||
</g>
|
|
||||||
<!-- pog -->
|
|
||||||
<g id="node2" class="node">
|
|
||||||
<title>pog</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="392.53" cy="-375" rx="112.08" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="321.28" y="-372.45" font-family="Open Sans" font-weight="bold" font-size="14.00">The Player of Games</text>
|
|
||||||
</g>
|
|
||||||
<!-- uow -->
|
|
||||||
<g id="node3" class="node">
|
|
||||||
<title>uow</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="312.53" cy="-209" rx="89.8" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="257.03" y="-206.45" font-family="Open Sans" font-weight="bold" font-size="14.00">Use of Weapons</text>
|
|
||||||
</g>
|
|
||||||
<!-- sota -->
|
|
||||||
<g id="node4" class="node">
|
|
||||||
<title>sota</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="311.53" cy="-43" rx="107.3" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="243.66" y="-40.45" font-family="Open Sans" font-weight="bold" font-size="14.00">The State of the Art</text>
|
|
||||||
</g>
|
|
||||||
<!-- uow->sota -->
|
|
||||||
<g id="edge2" class="edge">
|
|
||||||
<title>uow->sota</title>
|
|
||||||
<path fill="none" stroke="black" d="M312.42,-189.19C312.24,-161.09 311.92,-107.87 311.71,-74.26"/>
|
|
||||||
<polygon fill="black" stroke="black" points="315.22,-74.34 311.65,-64.36 308.22,-74.38 315.22,-74.34"/>
|
|
||||||
</g>
|
|
||||||
<!-- ivs -->
|
|
||||||
<g id="node6" class="node">
|
|
||||||
<title>ivs</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="499.53" cy="-43" rx="62.23" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="463.53" y="-40.45" font-family="Open Sans" font-weight="bold" font-size="14.00">Inversions</text>
|
|
||||||
</g>
|
|
||||||
<!-- uow->ivs -->
|
|
||||||
<g id="edge3" class="edge">
|
|
||||||
<title>uow->ivs</title>
|
|
||||||
<path fill="none" stroke="black" d="M333.26,-189.82C366.71,-160.48 432.69,-102.62 470.71,-69.28"/>
|
|
||||||
<polygon fill="black" stroke="black" points="472.93,-71.98 478.14,-62.76 468.32,-66.72 472.93,-71.98"/>
|
|
||||||
</g>
|
|
||||||
<!-- sd -->
|
|
||||||
<g id="node9" class="node">
|
|
||||||
<title>sd</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="104.53" cy="-43" rx="80.26" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="55.78" y="-40.45" font-family="Open Sans" font-weight="bold" font-size="14.00">Surface Detail</text>
|
|
||||||
</g>
|
|
||||||
<!-- uow->sd -->
|
|
||||||
<g id="edge6" class="edge">
|
|
||||||
<title>uow->sd</title>
|
|
||||||
<path fill="none" stroke="black" d="M289.48,-189.82C252.21,-160.44 178.64,-102.44 136.39,-69.12"/>
|
|
||||||
<polygon fill="black" stroke="black" points="138.58,-66.39 128.56,-62.95 134.25,-71.89 138.58,-66.39"/>
|
|
||||||
</g>
|
|
||||||
<!-- ex -->
|
|
||||||
<g id="node5" class="node">
|
|
||||||
<title>ex</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="613.53" cy="-375" rx="58.51" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="580.16" y="-372.45" font-family="Open Sans" font-weight="bold" font-size="14.00">Excession</text>
|
|
||||||
</g>
|
|
||||||
<!-- mat -->
|
|
||||||
<g id="node8" class="node">
|
|
||||||
<title>mat</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="539.53" cy="-209" rx="45.25" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="515.53" y="-206.45" font-family="Open Sans" font-weight="bold" font-size="14.00">Matter</text>
|
|
||||||
</g>
|
|
||||||
<!-- ex->mat -->
|
|
||||||
<g id="edge5" class="edge">
|
|
||||||
<title>ex->mat</title>
|
|
||||||
<path fill="none" stroke="black" d="M605.19,-355.51C592.29,-326.93 567.44,-271.85 552.28,-238.27"/>
|
|
||||||
<polygon fill="black" stroke="black" points="555.66,-237.23 548.35,-229.56 549.28,-240.11 555.66,-237.23"/>
|
|
||||||
</g>
|
|
||||||
<!-- hs -->
|
|
||||||
<g id="node10" class="node">
|
|
||||||
<title>hs</title>
|
|
||||||
<ellipse fill="#cceedd" stroke="#aaaaaa" cx="719.53" cy="-209" rx="116.32" ry="19.45"/>
|
|
||||||
<text text-anchor="start" x="645.28" y="-206.45" font-family="Open Sans" font-weight="bold" font-size="14.00">The Hydrogen Sonata</text>
|
|
||||||
</g>
|
|
||||||
<!-- ex->hs -->
|
|
||||||
<g id="edge4" class="edge">
|
|
||||||
<title>ex->hs</title>
|
|
||||||
<path fill="none" stroke="black" d="M625.48,-355.51C644.01,-326.84 679.79,-271.49 701.48,-237.93"/>
|
|
||||||
<polygon fill="black" stroke="black" points="704.15,-240.25 706.64,-229.95 698.27,-236.45 704.15,-240.25"/>
|
|
||||||
</g>
|
|
||||||
<!-- ltw->sd -->
|
|
||||||
<g id="edge7" class="edge">
|
|
||||||
<title>ltw->sd</title>
|
|
||||||
<path fill="none" stroke="black" d="M102.76,-189.19C103.1,-161.09 103.75,-107.87 104.16,-74.26"/>
|
|
||||||
<polygon fill="black" stroke="black" points="107.66,-74.4 104.28,-64.36 100.66,-74.32 107.66,-74.4"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 5.3 KiB |
|
@ -1,21 +0,0 @@
|
||||||
digraph {
|
|
||||||
node [style=filled, fontname="Open Sans", fillcolor="#cceeddff", color="#aaaaaaff"];
|
|
||||||
ratio=0.5;
|
|
||||||
cp [label=<<B>Consider Phlebas</B>>];
|
|
||||||
pog [label=<<B>The Player of Games</B>>];
|
|
||||||
uow [label=<<B>Use of Weapons</B>>];
|
|
||||||
sota [label=<<B>The State of the Art</B>>];
|
|
||||||
ex [label=<<B>Excession</B>>];
|
|
||||||
ivs [label=<<B>Inversions</B>>];
|
|
||||||
ltw [label=<<B>Look to Windward</B>>];
|
|
||||||
mat [label=<<B>Matter</B>>];
|
|
||||||
sd [label=<<B>Surface Detail</B>>];
|
|
||||||
hs [label=<<B>The Hydrogen Sonata</B>>];
|
|
||||||
cp -> ltw; // It's about the Idiran War, dummy.
|
|
||||||
uow -> sota; // It's largely about Sma.
|
|
||||||
uow -> ivs; // This book gives the best idea about what SC is, and you should know that before reading Inversions.
|
|
||||||
ex -> hs; // Hydrogen Sonata is dual to Excession in many ways. Not a hard rule, but HS is better if you know Excession.
|
|
||||||
ex -> mat; // Sleeper Service mentioned as "The granddaddy, the exemplary hero figure, the very God...".
|
|
||||||
uow -> sd; // Zakalwe/chair killer is in this one, and you should know who that is.
|
|
||||||
ltw -> sd; // LTW is more impactful (with Chel heaven being specially real) without the knowledge of SD.
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
<p id="ENTIRE">Page script failed to run. Please enable javascript.</p>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let source = window.location.hostname;
|
|
||||||
if (source == "acl.cool" || source == "raedr7n.net") {
|
|
||||||
document.getElementById("ENTIRE").innerHTML = `<p>Welcome to ${source}.</p> <a href="recipes/">recipes</a>`;
|
|
||||||
} else if (source == "ytheleus.org") {
|
|
||||||
document.getElementById("ENTIRE").innerHTML =
|
|
||||||
`<p>You're at ${source}, home page of the <a href=yth-name.html>Ytheleus</a> programming language!</p>
|
|
||||||
<p>This is not implemented yet; Ytheleus does not exist. That said, here are my vague ideas of what it should be:</p>
|
|
||||||
<ul>
|
|
||||||
<li>It's Andreas Rossberg's 1ML, but computationally pure.</li>
|
|
||||||
<li>The implementation uses dynamic superinstructions for interpretation and compiles either via "Compiling without continuations", if I decide not to put first-class multiple-resumption continuations in the lanugage, or with CPS, otherwise.</li>
|
|
||||||
</ul>`;
|
|
||||||
} else {
|
|
||||||
document.getElementById("ENTIRE").innerHTML = `Welcome to ${source}. For something more interesting, try <a href="https://acl.cool">acl.cool</a> or <a href="https://ytheleus.org">ytheleus.org</a>.`;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 368 B |
BIN
html/resumE.pdf
BIN
html/resumE.pdf
Binary file not shown.
|
@ -1,9 +0,0 @@
|
||||||
body {
|
|
||||||
background-color: powderblue;
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: blue;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
color: red;
|
|
||||||
}
|
|
32
index.html
Normal file
32
index.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
iframe {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<iframe id="site-frame"></iframe>
|
||||||
|
<!-- At some point, make it so this can handle a missing `hostname` directory. -->
|
||||||
|
<script>
|
||||||
|
const target = `${window.location.hostname}/singular.html`;
|
||||||
|
document.getElementById('site-frame').src = target;
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
13
localhost/singular.html
Normal file
13
localhost/singular.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>(localhost)</h1>
|
||||||
|
|
||||||
|
<p>The server is running. View it online to see some contents.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
11
singular.html
Normal file
11
singular.html
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<p>Viewing this file directly doesn't work. View it online to see some contents.</p>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
24
ytheleus.org/singular.html
Normal file
24
ytheleus.org/singular.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>ytheleus.org</h1>
|
||||||
|
|
||||||
|
|
||||||
|
<p>You're at ytheleus.org, home page of the <a href=yth-name.html>Ytheleus</a> programming language!</p>
|
||||||
|
<p>This is not implemented yet; Ytheleus does not exist. That said, here are my vague ideas of what it should be:</p>
|
||||||
|
<ul>
|
||||||
|
<li>It's Andreas Rossberg's 1ML, but computationally pure.</li>
|
||||||
|
<li>The implementation uses dynamic superinstructions for interpretation and compiles either via "Compiling without
|
||||||
|
continuations", if I decide not to put first-class multiple-resumption continuations in the lanugage, or with CPS,
|
||||||
|
otherwise.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue