Skip to content

Commit 31b79b2

Browse files
committed
Fix indentation, use pre code
1 parent 21ca4eb commit 31b79b2

File tree

6 files changed

+81
-111
lines changed

6 files changed

+81
-111
lines changed

.editorconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[*.html]
2+
indent_size = space
3+
indent_size = 2
4+
5+
[*.css]
6+
indent_style = tab
7+
indent_size = 4

assets/main.css

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ p {
4747
display: block;
4848
width: 70%;
4949
margin: auto;
50-
margin-block-start: 1em;
51-
margin-block-end: 1em;
50+
margin-block-start: 1em;
51+
margin-block-end: 1em;
5252
}
5353

5454
a {
@@ -57,15 +57,15 @@ a {
5757
}
5858

5959
code {
60-
font-family: monospace;
61-
font-size: 1.2em;
62-
background-color: #eeeeee;
60+
font-family: monospace;
61+
font-size: 1.2rem;
62+
background-color: #eeeeee;
6363
}
6464

65-
pre {
66-
font-size: 2em;
65+
pre code {
66+
font-size: 1.6rem;
6767
font-family: monospace;
6868
color: #333333;
6969
background-color: #ffffff;
7070
margin-bottom: 0;
71-
}
71+
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div class="code">
2-
<pre>
3-
{{- .Inner | safeHTML }}
4-
</pre>
2+
<pre><code>
3+
{{- .Inner | safeHTML -}}
4+
</code></pre>
55
</div>

public/index.html

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<h1 id="cognate">Cognate</h1>
1414
<h2 id="readable-and-concise-concatenative-programming">Readable and concise concatenative programming</h2>
1515
<div class="code">
16-
<pre>~~ Fizzbuzz in Cognate
16+
<pre><code>~~ Fizzbuzz in Cognate
1717

1818
Def Multiple as (Zero? Modulo);
1919

@@ -23,11 +23,10 @@ <h2 id="readable-and-concise-concatenative-programming">Readable and concise con
2323
Case (Multiple of 5) is "buzz"
2424
otherwise ();
2525

26-
For each in Range 1 to 100 (Print Fizzbuzz)
27-
</pre>
26+
For each in Range 1 to 100 (Print Fizzbuzz)</code></pre>
2827
</div><p>Cognate is a project aiming to create a human readable programming language with as little syntax as possible. Where natural language programming usually uses many complex syntax rules, instead Cognate takes them away. What it adds is simple, a way to embed comments into statements.</p>
2928
<div class="code">
30-
<pre>~~ Towers of Hanoi in Cognate
29+
<pre><code>~~ Towers of Hanoi in Cognate
3130

3231
Def Move discs as (
3332

@@ -43,19 +42,17 @@ <h2 id="readable-and-concise-concatenative-programming">Readable and concise con
4342
)
4443
);
4544

46-
Move 5 discs from "a" via "b" to "c"
47-
</pre>
45+
Move 5 discs from "a" via "b" to "c"</code></pre>
4846
</div><p>As you can see, Cognate ignores words starting with lowercase letters, allowing them to be used to describe functionality and enhance readability. This makes Cognate codebases intuitive and maintainable.</p>
4947
<div class="code">
50-
<pre>~~ Square numbers in Cognate
48+
<pre><code>~~ Square numbers in Cognate
5149

5250
Def Square as (* Twin);
5351
Map (Square) over Range 1 to 10;
54-
Print
55-
</pre>
52+
Print</code></pre>
5653
</div><p>Cognate is a stack-oriented programming language similar to Forth or Factor, except statements are evaluated right to left. This gives the expressiveness of concatenative programming as well as the readability of prefix notation. Statements can be delimited at arbitrary points, allowing them to read as sentences would in English.</p>
5754
<div class="code">
58-
<pre>~~ Prime numbers in Cognate
55+
<pre><code>~~ Prime numbers in Cognate
5956

6057
Def Factor (Zero? Modulo Swap);
6158

@@ -72,8 +69,7 @@ <h2 id="readable-and-concise-concatenative-programming">Readable and concise con
7269
)
7370
);
7471

75-
Print Primes up to 1000;
76-
</pre>
72+
Print Primes up to 1000;</code></pre>
7773
</div><p>Cognate borrows from other concatenative languages, but also adds unique features of its own.</p>
7874
<ul>
7975
<li>Point-free functions</li>

public/learn/index.html

Lines changed: 54 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,24 @@ <h2 id="install">Install</h2>
1515
<p>First install <code>CognaC</code> the Cognate Compiler from here using the provided instructions. Currently <code>CognaC</code> will run on recent Linux or Mac systems. Windows users can install it onto the Windows Subsystem for Linux - native Windows support is planned.</p>
1616
<p>Invoking <code>CognaC</code> is simple. If you have a file named <code>foo.cog</code> containing a Cognate program, it can be compiled into an executable named <code>foo</code> with the following command.</p>
1717
<div class="code">
18-
<pre>cognac foo.cog
19-
</pre>
18+
<pre><code>cognac foo.cog</code></pre>
2019
</div><p>To compile a debug executable, which will run slower but give a nice backtrace if there&rsquo;s an error, you can use the <code>-debug</code> flag.</p>
2120
<p>Alternatively, you can use the interactive web playground <a href="https://cognate-playground.hedy.dev/">here</a> which runs Cognate programs client-side in the browser. It also has intelligent syntax highlighting, code folding, and error reporting in the editor</p>
2221
<h2 id="first-programs">First Programs</h2>
2322
<div class="code">
24-
<pre>Print "Hello world!";
25-
</pre>
23+
<pre><code>Print "Hello world!";</code></pre>
2624
</div><p>Fairly simple right? This example calls the <code>Print</code> function with one parameter - the string <code>&quot;Hello world!&quot;</code>. Now let&rsquo;s do another simple example, adding two numbers.</p>
2725
<div class="code">
28-
<pre>Print + 2 3;
29-
</pre>
26+
<pre><code>Print + 2 3;</code></pre>
3027
</div><p>Wait what? That isn&rsquo;t how maths works!</p>
3128
<p>Cognate doesn&rsquo;t care how maths works. Where in most programming languages, <code>+</code> would be an operator and would be used in the infix position, in Cognate <code>+</code> is a function. Like <code>Print</code>, the <code>+</code> function is called by being written before its arguments like shown above.</p>
3229
<div class="code">
33-
<pre>Print - 10 36; ~~ Subtracts 10 from 36
34-
</pre>
30+
<pre><code>Print - 10 36; ~~ Subtracts 10 from 36</code></pre>
3531
</div><p>Another thing to note is that the order of parameters for <code>-</code> and <code>/</code> are backwards. The reason for this will become clear later. Also note that line comments are started with <code>~~</code>.</p>
3632
<h2 id="the-stack">The Stack</h2>
3733
<p>Let&rsquo;s have a more complex example, this subtracts 12 from 15 and then multiplies the result by 2.</p>
3834
<div class="code">
39-
<pre>Print * 2 - 12 15;
40-
</pre>
35+
<pre><code>Print * 2 - 12 15;</code></pre>
4136
</div><p>By now you may have realised that Cognate is evaluating our programs backwards - right to left. The subtraction is being performed before the multiplication above. This is being done using a stack, as explained here.</p>
4237
<ul>
4338
<li>Place 15 on top of the stack</li>
@@ -49,193 +44,166 @@ <h2 id="the-stack">The Stack</h2>
4944
</ul>
5045
<p>Cognate comes with functions to manipulate the stack. The simplest of these is <code>Twin</code>, which takes the top element from the stack, and puts it back on again - twice. The below snippet uses <code>Twin</code> to square a number by multiplying it by itself.</p>
5146
<div class="code">
52-
<pre>Print * Twin 8;
53-
</pre>
47+
<pre><code>Print * Twin 8;</code></pre>
5448
</div><p>Now we don&rsquo;t want to write this every time we square a number right? So let&rsquo;s create a <code>Square</code> function to do this for us.</p>
5549
<h2 id="first-functions">First Functions</h2>
5650
<p>Functions in Cognate are defined using <code>Def</code> and the name of the function. The function body is put in brackets after this.</p>
5751
<div class="code">
58-
<pre>Def Square (* Twin);
59-
Print Square 8;
60-
</pre>
52+
<pre><code>Def Square (* Twin);
53+
Print Square 8;</code></pre>
6154
</div><p>This is great, but it certainly could flow better. Cognate ignores words starting with lowercase letters, allowing them to be used as comments. This lets us write:</p>
6255
<div class="code">
63-
<pre>Print the Square of 8;
64-
</pre>
56+
<pre><code>Print the Square of 8;</code></pre>
6557
</div><p>In this example the readability isn&rsquo;t really improved much, but in more complex programs this informal syntax can be invaluable.</p>
6658
<p>By now you&rsquo;ve probably noticed the semicolons. These delimit statements so that Cognate knows what order to evaluate functions in (remember that these are executed backwards). Definitions should also be terminated with semicolons. The stack persists between statements, letting us do things like this.</p>
6759
<div class="code">
68-
<pre>8 ; Square ; Print ;
69-
</pre>
60+
<pre><code>8 ; Square ; Print ;</code></pre>
7061
</div><p>or this</p>
7162
<div class="code">
72-
<pre>Square 8 ; Print ;
73-
</pre>
63+
<pre><code>Square 8 ; Print ;</code></pre>
7464
</div><p>or this</p>
7565
<div class="code">
76-
<pre>8 ; Print the Square ;
77-
</pre>
66+
<pre><code>8 ; Print the Square ;</code></pre>
7867
</div><p>This flexible syntax allows Cognate programs to flow as if written in sentences. It also means that much of the time variables are not even needed. Of course, Cognate <em>does</em> have variables.</p>
7968
<h2 id="variables">Variables</h2>
8069
<p>Variables are defined in a fairly similar manner to functions using <code>Let</code> and their name. This takes a value from the stack, binding it to this name. Variables are referenced with the same syntax in which functions are called.</p>
8170
<div class="code">
82-
<pre>Let X be 4;
83-
Print X;
84-
</pre>
71+
<pre><code>Let X be 4;
72+
Print X;</code></pre>
8573
</div><p>We can use variables to define functions that take named parameters - here&rsquo;s an alternate version of the <code>Square</code> function.</p>
8674
<div class="code">
87-
<pre>Def Square as (
75+
<pre><code>Def Square as (
8876
Let X;
8977
* X X
90-
);
91-
</pre>
78+
);</code></pre>
9279
</div><p>Notice that the last statement before a closing bracket does not need to be terminated with a semicolon. Also there is no return statement, since values are implicitly returned on the stack. This means we can actually define functions that return multiple values, such as the <code>Twin</code> function we saw earlier.</p>
9380
<div class="code">
94-
<pre>Def Twin as (
81+
<pre><code>Def Twin as (
9582
Let X;
9683
X X
97-
);
98-
</pre>
84+
);</code></pre>
9985
</div><h2 id="control-flow">Control Flow</h2>
10086
<p>Like most programming languages, Cognate has if statements and loops and all that jazz. The simplest form of control flow is <code>When</code>, which simply executes a block of code if given <code>True</code> or not if <code>False</code>.</p>
10187
<div class="code">
102-
<pre>When == 1 1 (
88+
<pre><code>When == 1 1 (
10389
Print "Who'd have guessed?"
104-
);
105-
</pre>
90+
);</code></pre>
10691
</div><p>There is also <code>Unless</code> that evaluates the block if given <code>False</code>. <code>While</code> takes a condition in brackets and evaluates the block of code until the condition is <code>False</code>. <code>Until</code>, you guessed it, is the opposite of <code>While</code> and runs until the condition is <code>True</code>.</p>
10792
<div class="code">
108-
<pre>While (True) (
93+
<pre><code>While (True) (
10994
Print "This may well print forever"
110-
);
111-
</pre>
95+
);</code></pre>
11296
</div><p>What&rsquo;s with the second set of brackets? <code>When</code> doesn&rsquo;t have them, so why should <code>While</code>? This is because brackets denote blocks! These prevent code being instantly evaluated and instead push a reference onto the stack. Blocks also control variable scopes. We can evaluate a block using the <code>Do</code> function - which is how our control flow functions are implemented.</p>
11397
<div class="code">
114-
<pre>Do (
98+
<pre><code>Do (
11599
Print "Hello from inside a block!"
116-
);
117-
</pre>
100+
);</code></pre>
118101
</div><p>This explains the syntax for functions: <code>Def</code> simply binds a block to a name, much like <code>Let</code>. Blocks can be passed around the program like any other value - even if they reference variables that go out of scope.</p>
119102
<p>Now that this (hopefully) makes some sense, we can finally introduce the <code>If</code> statement! <code>If</code> is a function that takes three parameters. The first is a boolean, if this is <code>True</code> then the second argument is returned. If not, the third argument is returned. We can chain <code>If</code>s together to have more complex control flow.</p>
120103
<div class="code">
121-
<pre>Print
104+
<pre><code>Print
122105
If == X 1 then "foo"
123106
If == X 2 then "bar"
124-
else "baz";
125-
</pre>
107+
else "baz";</code></pre>
126108
</div><p>We can combine this with <code>Do</code> to have conditional code execution.</p>
127109
<div class="code">
128-
<pre>Do
110+
<pre><code>Do
129111
If == X 1 then ( Print "foo" )
130112
If == X 2 then ( Print "bar" )
131-
else ( Print "baz" );
132-
</pre>
113+
else ( Print "baz" );</code></pre>
133114
</div><p>Now, lets use our knowledge of blocks to define our own control flow function <code>Thrice</code>, which should evaluate a block three times in a row. This demonstrates a different use of <code>Def</code> in which we bind a block from the stack.</p>
134115
<div class="code">
135-
<pre>Def Thrice as (
116+
<pre><code>Def Thrice as (
136117
Def F;
137118
F F F
138119
);
139120

140121
Thrice (
141122
Print "hip hip hooray!"
142-
);
143-
</pre>
123+
);</code></pre>
144124
</div><p>A more general version of this function, <code>Times</code> can be defined using recursion.</p>
145125
<div class="code">
146-
<pre>Def Times (
126+
<pre><code>Def Times (
147127
Let N number of repetitions;
148128
Def F function to repeat;
149129
Unless Zero? N ( F ; Times - 1 N (F) );
150130
);
151131

152132
Times 5 (
153133
Print "wow!";
154-
);
155-
</pre>
134+
);</code></pre>
156135
</div><p>Now you may see a small problem with this. If the user calls <code>Times</code> with a non-integer parameter it will loop forever - that won&rsquo;t do at all! We use the <code>Integer!</code> function to throw a type error if a decimal is given.</p>
157136
<div class="code">
158-
<pre>Def Times (
137+
<pre><code>Def Times (
159138
Let N is Integer! number of repetitions;
160139
Def F function to repeat;
161140
Unless Zero? N ( F ; Times - 1 N (F) );
162-
);
163-
</pre>
141+
);</code></pre>
164142
</div><p>We could also use the <code>Block!</code> function for <code>F</code> but we&rsquo;ll already get a type error when we use <code>Def</code> to bind anything that isn&rsquo;t a block, so there is no point.</p>
165143
<p>The <code>Times</code> function is also our first loop. We don&rsquo;t need to define it every time though as it&rsquo;s also in the standard library. Another loop is <code>While</code>.</p>
166144
<div class="code">
167-
<pre>While (!= "done" Twin Input) (
145+
<pre><code>While (!= "done" Twin Input) (
168146
Print
169147
);
170-
Drop;
171-
</pre>
148+
Drop;</code></pre>
172149
</div><p><code>While</code> takes two block parameters. The first one is the condition and is evaluated immediately, returning a boolean. If this is <code>True</code> then the second block (the loop body) is evaluated and then the loop repeats, if not the loop finishes. The example above shows the use of a <code>While</code> loop. The program simply echoes the user&rsquo;s inputs back to them until they write <code>&quot;done&quot;</code>.</p>
173150
<p>This loop is most useful in imperative code where intermediary values are passed on the stack between iterations. It is less useful for iterating over data structures such as lists. Lists?</p>
174151
<h2 id="lists">Lists</h2>
175152
<p>In Cognate, lists are generated using - you guessed it - a function. The <code>List</code> function takes a block as a parameter. It evaluates this block <em>in a new stack</em> and then returns that stack as a list.</p>
176153
<div class="code">
177-
<pre>Print List (1 2 3 4 5);
178-
</pre>
154+
<pre><code>Print List (1 2 3 4 5);</code></pre>
179155
</div><p>This allows Cognate&rsquo;s list creation to be much more flexible than other languages - for example what if we wanted a list of 100 ones?</p>
180156
<div class="code">
181-
<pre>Print List ( Times 100 (1) );
182-
</pre>
157+
<pre><code>Print List ( Times 100 (1) );</code></pre>
183158
</div><p>The three most fundamental list functions are <code>Push</code>, <code>First</code>, and <code>Rest</code>.</p>
184159
<p>The <code>Push</code> function takes a value and a list as parameters, and returns the list with the value <em>pushed</em> to it&rsquo;s first element. <code>First</code> simply returns the first element of a list. <code>Rest</code> returns a list without its first element.</p>
185160
<div class="code">
186-
<pre>Let L be Push "foo" to List ( "bar" "baz" );
161+
<pre><code>Let L be Push "foo" to List ( "bar" "baz" );
187162
Print First element of L;
188-
Print Rest of L;
189-
</pre>
163+
Print Rest of L;</code></pre>
190164
</div><p><code>Range</code> creates a list of numbers from a starting (inclusive) and an ending (exclusive) number. <code>For</code> is a higher order function that applied an operation to each element of a list - it is the loop for iterating over lists.</p>
191165
<div class="code">
192-
<pre>Def Square as (* Twin);
193-
For each in Range 1 to 20 (Print the Square);
194-
</pre>
166+
<pre><code>Def Square as (* Twin);
167+
For each in Range 1 to 20 (Print the Square);</code></pre>
195168
</div><p><code>Map</code> is like <code>For</code> but the result of the computation is stored in a new list.</p>
196169
<div class="code">
197-
<pre>Let Evens be Map (* 2) over Range 1 to 50;
198-
Print Evens;
199-
</pre>
170+
<pre><code>Let Evens be Map (* 2) over Range 1 to 50;
171+
Print Evens;</code></pre>
200172
</div><p><code>Filter</code> applies a function to each element of a list also. This function should return a boolean - if this is <code>False</code> then the function is removed from the returned list.</p>
201173
<div class="code">
202-
<pre>Let Even? be (Zero? Modulo 2);
174+
<pre><code>Let Even? be (Zero? Modulo 2);
203175
Let Evens be Filter (Even?) over Range 1 to 100;
204-
Print Evens;
205-
</pre>
176+
Print Evens;</code></pre>
206177
</div><p>The functional programmers reading this are likely expecting a Fold or Reduce function next - which applies an operation to a list with an accumulator. However Cognate needs no fold function, as <code>For</code> can store intermediary values on the stack, acting like a fold.</p>
207178
<div class="code">
208-
<pre>Def Factorial as (
179+
<pre><code>Def Factorial as (
209180
Let N be Integer!;
210181
For each in Range 1 to N (*) from 1;
211182
);
212183

213-
Print Factorial 10;
214-
</pre>
184+
Print Factorial 10;</code></pre>
215185
</div><h2 id="boxes">Boxes</h2>
216186
<p>While storing state between loop iterations is very useful, in some cases you just need mutable variables. Cognate&rsquo;s boxes are references used to generalise the concept of mutation.</p>
217187
<p>The <code>Box</code> function takes a value and places it in a box. <code>Unbox</code> returns the item stored in a box. <code>Set</code> takes a box and a value as parameters and mutates the box to hold the value, updating all references to it.</p>
218188
<div class="code">
219-
<pre>Let X be Box 1;
189+
<pre><code>Let X be Box 1;
220190
Print Unbox X; ~~ prints 1
221191

222192
Set X to 2;
223-
Print Unbox X; ~~ prints 2
224-
</pre>
193+
Print Unbox X; ~~ prints 2</code></pre>
225194
</div><p>Boxes aren&rsquo;t limited to mutating variables, they can be used for any value.</p>
226195
<div class="code">
227-
<pre>Let L be Map (Box) over Range 1 to 10;
196+
<pre><code>Let L be Map (Box) over Range 1 to 10;
228197
Print L;
229198

230199
For each in L (
231200
Let X;
232201
Set X to * 2 Unbox X; ~~ double the element in place
233202
);
234-
Print L;
235-
</pre>
203+
Print L;</code></pre>
236204
</div><p>While boxes may not seem as ergonomic as mutation in other languages, they are both more flexible than mutable variables and more predictable than implicit references. We can also easily extend mutation, like this:</p>
237205
<div class="code">
238-
<pre>Def Box-list as ( Map (Box) );
206+
<pre><code>Def Box-list as ( Map (Box) );
239207

240208
Def Inplace-map as (
241209
Def F;
@@ -247,8 +215,7 @@ <h2 id="lists">Lists</h2>
247215
Print L;
248216

249217
Inplace-map (* 2) over L;
250-
Print L;
251-
</pre>
218+
Print L;</code></pre>
252219
</div><h2 id="todo">Todo</h2>
253220
<p>This tutorial isn&rsquo;t finished yet!</p>
254221

0 commit comments

Comments
 (0)