Skip to content

Commit 3a127c7

Browse files
author
Xy Ren
authored
Add support for the language Agda (#2430)
1 parent ae0327b commit 3a127c7

10 files changed

+396
-1
lines changed

components.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components.json

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@
9494
"title": "Ada",
9595
"owner": "Lucretia"
9696
},
97+
"agda": {
98+
"title": "Agda",
99+
"owner": "xy-ren"
100+
},
97101
"al": {
98102
"title": "AL",
99103
"owner": "RunDevelopment"

components/prism-agda.js

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(function (Prism) {
2+
3+
Prism.languages.agda = {
4+
'comment': /\{-[\s\S]*?(?:-\}|$)|--.*/,
5+
'string': {
6+
pattern: /"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,
7+
greedy: true,
8+
},
9+
'punctuation': /[(){}.;@]/,
10+
'class-name': {
11+
pattern: /((?:data|record) +)\S+/,
12+
lookbehind: true,
13+
},
14+
'function': {
15+
pattern: /(^[ \t]*)[^:\r\n]+?(?=:)/m,
16+
lookbehind: true,
17+
},
18+
'operator': {
19+
pattern: /(^\s*|\s)(?:[=|:λ\\?_]|->)(?=\s)/,
20+
lookbehind: true,
21+
},
22+
'keyword': /\b(?:Set|abstract|constructor|data|eta-equality|field|forall|forall|hiding|import|in|inductive|infix|infixl|infixr|instance|let|macro|module|mutual|no-eta-equality|open|overlap|pattern|postulate|primitive|private|public|quote|quoteContext|quoteGoal|quoteTerm|record|renaming|rewrite|syntax|tactic|unquote|unquoteDecl|unquoteDef|using|variable|where|with)\b/,
23+
};
24+
}(Prism));

components/prism-agda.min.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/prism-agda.html

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<h2>Agda Full Example</h2>
2+
<p>** Copyright - this piece of code is a modified version of [https://plfa.github.io/Naturals/] by Philip Wadler, Wen Kokke, Jeremy G Siek and contributors.</p>
3+
<pre><code>-- 1.1 Naturals
4+
5+
module plfa.part1.Naturals where
6+
7+
-- The standard way to enter Unicode math symbols in Agda
8+
-- is to use the IME provided by agda-mode.
9+
-- for example ℕ can be entered by typing \bN.
10+
11+
-- The inductive definition of natural numbers.
12+
-- In Agda, data declarations correspond to axioms.
13+
-- Also types correspond to sets.
14+
-- CHAR: \bN → ℕ
15+
data ℕ : Set where
16+
-- This corresponds to the `zero` rule in Dedekin-Peano's axioms.
17+
-- Note that the syntax resembles Haskell GADTs.
18+
-- Also note that the `has-type` operator is `:` (as in Idris), not `::` (as in Haskell).
19+
zero : ℕ
20+
-- This corresponds to the `succesor` rule in Dedekin-Peano's axioms.
21+
-- In such a constructive system in Agda, induction rules etc comes by nature.
22+
-- The function arrow can be either `->` or `→`.
23+
-- CHAR: \to or \-> or \r- → →
24+
suc : ℕ → ℕ
25+
26+
-- EXERCISE `seven`
27+
seven : ℕ
28+
seven = suc (suc (suc (suc (suc (suc (suc zero))))))
29+
30+
-- This line is a compiler pragma.
31+
-- It makes `ℕ` correspond to Haskell's type `Integer`
32+
-- and allows us to use number literals (0, 1, 2, ...) to express `ℕ`.
33+
{-# BUILTIN NATURAL ℕ #-}
34+
35+
-- Agda has a module system corresponding to the project file structure.
36+
-- e.g. `My.Namespace` is in
37+
-- `project path/My/Namespace.agda`.
38+
39+
-- The `import` statement does NOT expose the names to the top namespace.
40+
-- You'll have to use `My.Namespace.thing` instead of directly `thing`.
41+
import Relation.Binary.PropositionalEquality as Eq
42+
-- The `open` statement unpacks all the names in a imported namespace and exposes them to the top namespace.
43+
-- Alternatively the `open import` statement imports a namespace and opens it at the same time.
44+
-- The `using (a; ..)` clause can limit a range of names to expose, instead of all of them.
45+
-- Alternatively, the `hiding (a; ..)` clause can limit a range of names NOT to expose.
46+
-- Also the `renaming (a to b; ..)` clause can rename names.
47+
-- CHAR: \== → ≡
48+
-- \gt → ⟨
49+
-- \lt → ⟩
50+
-- \qed → ∎
51+
open Eq using (_≡_; refl)
52+
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _∎)
53+
54+
-- Addition of `ℕ`.
55+
-- Note that Agda functions are *like* Haskell functions.
56+
-- In Agda, operators can be mixfix (incl. infix, prefix, suffix, self-bracketing and many others).
57+
-- All the `holes` are represented by `_`s. Unlike Haskell, operator names don't need to be put in parentheses.
58+
-- Operators can also be called in the manner of normal functions.
59+
-- e.g. a + b = _+_ a b.
60+
-- Sections are also available, though somehow weird.
61+
-- e.g. a +_ = _+_ a.
62+
_+_ : ℕ → ℕ → ℕ
63+
-- Lhs can also be infix!
64+
-- This is the standard definition in both Peano and Agda stdlib.
65+
-- We do pattern match on the first parameter, it's both convention and for convenience.
66+
-- Agda does a termination check on recursive function.
67+
-- Here the first parameter decreases over evaluation thus it is *well-founded*.
68+
zero + n = n
69+
(suc m) + n = suc (m + n)
70+
71+
-- Here we take a glance at the *dependent type*.
72+
-- In dependent type, we can put values into type level, and vice versa.
73+
-- This is especially useful when we're expecting to make the types more precise.
74+
-- Here `_≡_` is a type that says that two values are *the same*, that is, samely constructed.
75+
_ : 2 + 3 ≡ 5
76+
-- We can do it by ≡-Reasoning, that is writing a (unreasonably long) chain of equations.
77+
_ =
78+
begin
79+
2 + 3
80+
≡⟨⟩ -- This operator means the lhs and rhs can be reduced to the same form so that they are equal.
81+
suc (1 + 3)
82+
≡⟨⟩
83+
suc (suc (0 + 3)) -- Just simulating the function evaluation
84+
≡⟨⟩
85+
suc (suc 3)
86+
≡⟨⟩
87+
5
88+
∎ -- The *tombstone*, QED.
89+
90+
-- Well actually we can also get this done by simply writing `refl`.
91+
-- `refl` is a proof that says "If two values evaluates to the same form, then they are equal".
92+
-- Since Agda can automatically evaluate the terms for us, this makes sense.
93+
_ : 2 + 3 ≡ 5
94+
_ = refl
95+
96+
-- Multiplication of `ℕ`, defined with addition.
97+
_*_ : ℕ → ℕ → ℕ
98+
-- Here we can notice that in Agda we prefer to indent by *visual blocks* instead by a fixed number of spaces.
99+
zero * n = zero
100+
-- Here the addition is at the front, to be consistent with addition.
101+
(suc m) * n = n + (m * n)
102+
103+
-- EXERCISE `_^_`, Exponentation of `ℕ`.
104+
_^_ : ℕ → ℕ → ℕ
105+
-- We can only pattern match the 2nd argument.
106+
m ^ zero = suc zero
107+
m ^ (suc n) = m * (m ^ n)
108+
109+
-- *Monus* (a wordplay on minus), the non-negative subtraction of `ℕ`.
110+
-- if less than 0 then we get 0.
111+
-- CHAR: \.- → ∸
112+
_∸_ : ℕ → ℕ → ℕ
113+
m ∸ zero = m
114+
zero ∸ suc n = zero
115+
suc m ∸ suc n = m ∸ n
116+
117+
-- Now we define the precedence of the operators, as in Haskell.
118+
infixl 6 _+_ _∸_
119+
infixl 7 _*_
120+
121+
-- These are some more pragmas. Should be self-explaining.
122+
{-# BUILTIN NATPLUS _+_ #-}
123+
{-# BUILTIN NATTIMES _*_ #-}
124+
{-# BUILTIN NATMINUS _∸_ #-}
125+
126+
-- EXERCISE `Bin`. We define a binary representation of natural numbers.
127+
-- Leading `O`s are acceptable.
128+
data Bin : Set where
129+
⟨⟩ : Bin
130+
_O : Bin → Bin
131+
_I : Bin → Bin
132+
133+
-- Like `suc` for `Bin`.
134+
inc : Bin → Bin
135+
inc ⟨⟩ = ⟨⟩ I
136+
inc (b O) = b I
137+
inc (b I) = (inc b) O
138+
139+
-- `ℕ` to `Bin`. This is a Θ(n) solution and awaits a better Θ(log n) reimpelementation.
140+
to : ℕ → Bin
141+
to zero = ⟨⟩ O
142+
to (suc n) = inc (to n)
143+
144+
-- `Bin` to `ℕ`.
145+
from : Bin → ℕ
146+
from ⟨⟩ = 0
147+
from (b O) = 2 * (from b)
148+
from (b I) = 1 + 2 * (from b)
149+
150+
-- Simple tests from 0 to 4.
151+
_ : from (to 0) ≡ 0
152+
_ = refl
153+
154+
_ : from (to 1) ≡ 1
155+
_ = refl
156+
157+
_ : from (to 2) ≡ 2
158+
_ = refl
159+
160+
_ : from (to 3) ≡ 3
161+
_ = refl
162+
163+
_ : from (to 4) ≡ 4
164+
_ = refl
165+
166+
-- EXERCISE END `Bin`
167+
168+
-- STDLIB: import Data.Nat using (ℕ; zero; suc; _+_; _*_; _^_; _∸_)
169+
</code></pre>
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{-
2+
This is a
3+
multiline comment
4+
-}
5+
-- This is a singleline comment
6+
7+
----------------------------------------------------
8+
9+
[
10+
["comment", "{-\n\tThis is a\n\tmultiline comment\n-}"],
11+
["comment", "-- This is a singleline comment"]
12+
]
13+
14+
----------------------------------------------------
15+
16+
In agda there are two kinds of comments:
17+
- Multiline comments wrapped by {- -}
18+
- Singleline comments leading by --
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
data _≐_ {ℓ} {A : Set ℓ} (x : A) : A → Prop ℓ where
2+
refl : x ≐ x
3+
4+
----------------------------------------------------
5+
6+
[
7+
["keyword", "data"],
8+
["class-name", "_≐_"],
9+
["punctuation", "{"],
10+
"ℓ",
11+
["punctuation", "}"],
12+
["punctuation", "{"],
13+
["function", "A "],
14+
["operator", ":"],
15+
["keyword", "Set"],
16+
" ℓ",
17+
["punctuation", "}"],
18+
["punctuation", "("],
19+
["function", "x "],
20+
["operator", ":"],
21+
" A",
22+
["punctuation", ")"],
23+
["function", " "],
24+
["operator", ":"],
25+
" A ",
26+
["operator", "→"],
27+
" Prop ℓ ",
28+
["keyword", "where"],
29+
["function", "refl "],
30+
["operator", ":"],
31+
" x ≐ x"
32+
]
33+
34+
----------------------------------------------------
35+
36+
The `data` keyword in Agda is used to declare a type (of course it can be dependent)
37+
in a fashion like Haskell's GADTs.
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
merge : {A : Set} (_<_ : A → A → Bool) → List A → List A → List A
2+
merge xs [] = xs
3+
merge [] ys = ys
4+
merge xs@(x ∷ xs₁) ys@(y ∷ ys₁) =
5+
if x < y then x ∷ merge xs₁ ys
6+
else y ∷ merge xs ys₁
7+
8+
----------------------------------------------------
9+
10+
[
11+
["function", "merge "],
12+
["operator", ":"],
13+
["punctuation", "{"],
14+
["function", "A "],
15+
["operator", ":"],
16+
["keyword", "Set"],
17+
["punctuation", "}"],
18+
["punctuation", "("],
19+
["function", "_<_ "],
20+
["operator", ":"],
21+
" A ",
22+
["operator", "→"],
23+
" A ",
24+
["operator", "→"],
25+
" Bool",
26+
["punctuation", ")"],
27+
["operator", "→"],
28+
" List A ",
29+
["operator", "→"],
30+
" List A ",
31+
["operator", "→"],
32+
" List A\nmerge xs [] ",
33+
["operator", "="],
34+
" xs\nmerge [] ys ",
35+
["operator", "="],
36+
" ys\nmerge xs",
37+
["punctuation", "@"],
38+
["punctuation", "("],
39+
"x ∷ xs₁",
40+
["punctuation", ")"],
41+
" ys",
42+
["punctuation", "@"],
43+
["punctuation", "("],
44+
"y ∷ ys₁",
45+
["punctuation", ")"],
46+
["operator", "="],
47+
"\n\tif x < y then x ∷ merge xs₁ ys\n\t\t\t\t\t else y ∷ merge xs ys₁"
48+
]
49+
50+
----------------------------------------------------
51+
52+
Functions in Agda are PURE and TOTAL.
53+
Different from Haskell, they can be *dependent* and they can receive implicit arguments.
54+
Functions can be infix, or even mixfix, and they become operators.
55+
So it is generally not possible to highlight all the "operators" as they are functions.
56+
(Also, types are functions too, so it is generally impossible to highlight types.)
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
module Test.test where
2+
import Relation.Binary.PropositionalEquality as Eq
3+
open Eq hiding (_≡_; refl)
4+
open Eq.≡-Reasoning using (begin_; _≡⟨⟩_; _∎) renaming (begin_ to start_)
5+
6+
----------------------------------------------------
7+
8+
[
9+
["keyword", "module"],
10+
" Test",
11+
["punctuation", "."],
12+
"test ",
13+
["keyword", "where"],
14+
["keyword", "import"],
15+
" Relation",
16+
["punctuation", "."],
17+
"Binary",
18+
["punctuation", "."],
19+
"PropositionalEquality as Eq\n",
20+
["keyword", "open"],
21+
" Eq ",
22+
["keyword", "hiding"],
23+
["punctuation", "("],
24+
"_≡_",
25+
["punctuation", ";"],
26+
" refl",
27+
["punctuation", ")"],
28+
["keyword", "open"],
29+
" Eq",
30+
["punctuation", "."],
31+
"≡-Reasoning ",
32+
["keyword", "using"],
33+
["punctuation", "("],
34+
"begin_",
35+
["punctuation", ";"],
36+
" _≡⟨⟩_",
37+
["punctuation", ";"],
38+
" _∎",
39+
["punctuation", ")"],
40+
["keyword", "renaming"],
41+
["punctuation", "("],
42+
"begin_ to start_",
43+
["punctuation", ")"]
44+
]
45+
46+
----------------------------------------------------
47+
48+
Agda's module system is one based on namespaces and corresponding to file structure.
49+
It supports namespace importing, open importing, partial hiding/using and renaming.

0 commit comments

Comments
 (0)