Skip to content

Commit e5220f6

Browse files
changed comment syntax as requested (#164)
* Changed comment syntax as requested. New line comments starts with `#`, while block comments starts with `{#` and ends with `#}`. * Character `#` is now disallowed as an operator character. * Fixed `test.sh` --------- Co-authored-by: Piotr Polesiuk <[email protected]>
1 parent c646592 commit e5220f6

27 files changed

+148
-149
lines changed

examples/LWT_lexical.fram

+21-21
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
(* In this example we show that lexical handlers are capable of expressing
1+
{# In this example we show that lexical handlers are capable of expressing
22
lightweight threads with yield and spawn operations. The solution is not
33
satisfactory, but it is still interesting since it shows how our in approach
44
to effect capabilities we can separate an interface from an implementation
5-
of algebraic effects. *)
5+
of algebraic effects. #}
66

77
import List
88

9-
(* We start by defining the standard State effect representing a single
9+
{# We start by defining the standard State effect representing a single
1010
mutable cell. Note that in Fram an effect signature is an ordinary record
1111
of functions. A special type parameter `(effect E)` is the effect of these
1212
effectful function, and this parameter will be automatically instantiated
@@ -16,21 +16,21 @@ import List
1616
troublesome, as a handler of `update f` should call function `f` at the call
1717
site of `update`, where potentially more effects (described by `Row`) are
1818
available. In Fram, update function can be implemented on top of more
19-
primitive `get` and `put`, even if it is a part of the interface. *)
19+
primitive `get` and `put`, even if it is a part of the interface. #}
2020
data State (effect E) X = State of
2121
{ get : Unit ->[E] X
2222
, put : X ->[E] Unit
2323
, update : {Row} -> (X ->[E|Row] X) ->[E|Row] Unit
2424
}
2525

26-
(* We declare implicit parameter named `~st`. Now, the following function may
26+
{# We declare implicit parameter named `~st`. Now, the following function may
2727
use `~st` as a regular variable. In such a case, `~st` together with the
28-
associated effect E_st will be implicitly generalized. *)
28+
associated effect E_st will be implicitly generalized. #}
2929
implicit ~st {E_st} : State E_st _
3030

31-
(* We define get operation that works on implicit capability `~st`. It can be
31+
{# We define get operation that works on implicit capability `~st`. It can be
3232
used in any context, where a variable named ~st is available (or can be
33-
implicitly generalized). We also define similar put and update functions. *)
33+
implicitly generalized). We also define similar put and update functions. #}
3434
let get x =
3535
let (State { get }) = ~st in
3636
get x
@@ -43,11 +43,11 @@ let update f =
4343
let (State { update }) = ~st in
4444
update f
4545

46-
(* Now, we put the standard handler for state, that will become the state of the
46+
{# Now, we put the standard handler for state, that will become the state of the
4747
scheduler. Note that an expression that provides capability `~st` is not just
4848
a value, but more complex series of let-expressions. First, we define
4949
standard get and put operations, and then on top of them we define the update
50-
function. All three functions becomes part of the interface. *)
50+
function. All three functions becomes part of the interface. #}
5151
handle {effect=Sched} ~st =
5252
let get = effect x / r => fn s => r s s
5353
let put = effect s / r => fn _ => r () s
@@ -56,13 +56,13 @@ handle {effect=Sched} ~st =
5656
return x => fn _ => x
5757
finally c => c []
5858

59-
(* Enqueue a ready thread to the scheduler queue. Note that thanks to the
59+
{# Enqueue a ready thread to the scheduler queue. Note that thanks to the
6060
mechanism of implicit parameters, this function uses `~st` capability, without
61-
mentioning it explicitly. *)
61+
mentioning it explicitly. #}
6262
let enqueue thr =
6363
update (fn queue => List.append queue [thr])
6464

65-
(* Run the scheduler. It picks one thread from the queue and runs it. *)
65+
{# Run the scheduler. It picks one thread from the queue and runs it. #}
6666
let sched _ =
6767
match get () with
6868
| [] => ()
@@ -71,29 +71,29 @@ let sched _ =
7171
thr ()
7272
end
7373

74-
(* The effect signature of lightweight threads, again as a record. We have two
74+
{# The effect signature of lightweight threads, again as a record. We have two
7575
operations: yield for voluntarily passing control to an another thread, and
7676
spawn for creating new threads. The spawn function is particularly
7777
troublesome for lexical handlers, as newly created thread should share
7878
the handler with the parent thread without sharing parent's continuation.
7979
With dynamic handlers we can just create a new handler for the same effect,
80-
but this is not possible with lexical handlers. *)
80+
but this is not possible with lexical handlers. #}
8181
data LWT_S Row = LWT of
8282
{ yield : Unit ->[|Row] Unit
8383
, spawn : (Unit ->[|Row] Unit) ->[|Row] Unit
8484
}
8585

86-
(* For accessing operations of LWT effect we use an another mechanism
86+
{# For accessing operations of LWT effect we use an another mechanism
8787
available in Fram, i.e., methods. We can associate functions with each
8888
datatype and use usual dot syntax for accessing them. The main advantage of
8989
methods is that the same name of the method can be used with many different
90-
datatypes leading to a more concise and readable code. *)
90+
datatypes leading to a more concise and readable code. #}
9191
method yield {self = LWT {yield}} = yield
9292
method spawn {self = LWT {spawn}} = spawn
9393

94-
(* Here we handle the LWT effect using pure lexical handlers. The problematic
94+
{# Here we handle the LWT effect using pure lexical handlers. The problematic
9595
spawn operation is implemented via more primitive fork and exit functions,
96-
not accessible directly via the LWT interface. *)
96+
not accessible directly via the LWT interface. #}
9797
handle {effect=LWT} (lwt : LWT_S [LWT,IO]) =
9898
let yield = effect _ / r => let _ = enqueue r in sched ()
9999
let exit = effect _ / _ => sched ()
@@ -108,8 +108,8 @@ handle {effect=LWT} (lwt : LWT_S [LWT,IO]) =
108108
in LWT { yield, spawn }
109109
return _ => sched ()
110110

111-
(* Example code using LWT interface. Methods yield and spawn are accessible
112-
via the `lwt` object. *)
111+
{# Example code using LWT interface. Methods yield and spawn are accessible
112+
via the `lwt` object. #}
113113
let startThread (name : String) = lwt.spawn (fn _ =>
114114
let _ = printStrLn (name + "1") in
115115
let _ = lwt.yield () in

examples/Modules/B/C/D.fram

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(* This import resolves to the absolute path `/Main/B/A`. *)
1+
{# This import resolves to the absolute path `/Main/B/A`. #}
22
import A
33

44
pub let id = A.id

examples/Modules/Main.fram

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
(** This example serves to showcase the files-as-modules feature.
1+
{## This example serves to showcase the files-as-modules feature.
22

33
The module hierarchy is as follows.
44
```
@@ -21,16 +21,16 @@
2121
Relative imports refer to the module which is the closest to the importing
2222
module, working upwards through the hierarchy. In this example the module
2323
`/Main/B/C/D` imports the relative path `A`, and the nearest matching
24-
module is `/Main/B/A`. *)
24+
module is `/Main/B/A`. #}
2525

2626
import List
2727

2828
import A
2929
import B/C/D as X
30-
import /Main/B/C/D as Y (* The same import, but as an absolute path. *)
30+
import /Main/B/C/D as Y {# The same import, but as an absolute path. #}
3131
import B/A as A2
3232

33-
(* Rather than binding a module name, import the module's contents *)
33+
{# Rather than binding a module name, import the module's contents #}
3434
import open C
3535

3636
let _ =

examples/Prolog.fram

+49-49
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
(* This example implements a simplified version of Prolog and serves to
2-
illustrate the combination of implicit parameters and effect capabilities. *)
1+
{# This example implements a simplified version of Prolog and serves to
2+
illustrate the combination of implicit parameters and effect capabilities. #}
33

44
import List
55

6-
(* Prolog terms and clauses are fairly standard. Here variables are
7-
identified by integers and functors by strings. *)
6+
{# Prolog terms and clauses are fairly standard. Here variables are
7+
identified by integers and functors by strings. #}
88
data rec Term = TVar of Int | TFun of String, List Term
99

1010
data Clause = Cl of Term, List Term
1111

12-
(* The signature of the standard reader effect, with a single operation
12+
{# The signature of the standard reader effect, with a single operation
1313
used to obtain a value of type X. While we do not need to wrap functions
1414
`{effect=E} -> Unit ->[E] X` in a data type to use them as capabilities,
15-
this improves readability and allows us to define methods on the type. *)
15+
this improves readability and allows us to define methods on the type. #}
1616
data Reader (effect E) X = Reader of (Unit ->[E] X)
1717

18-
(* We expose the `ask` operation of `Reader` as a method. *)
18+
{# We expose the `ask` operation of `Reader` as a method. #}
1919
method ask {E, self = Reader ask : Reader E _} = ask
2020

21-
(* The standard state effect, with its accompanying methods. *)
21+
{# The standard state effect, with its accompanying methods. #}
2222
data State (effect E) X = State of
2323
{ get : Unit ->[E] X
2424
, put : X ->[E] Unit
@@ -29,7 +29,7 @@ method put {E, self = State { put } : State E _} = put
2929

3030
method update {E, self : State E _} f = self.put (f (self.get ()))
3131

32-
(* The standard backtracking effect. *)
32+
{# The standard backtracking effect. #}
3333
data BT (effect E) = BT of
3434
{ flip : Unit ->[E] Bool
3535
, fail : {type X} -> Unit ->[E] X
@@ -38,8 +38,8 @@ data BT (effect E) = BT of
3838
method flip {E, self = BT { flip } : BT E} = flip
3939
method fail {E, self = BT { fail } : BT E} = fail
4040

41-
(* The method `choose` on `BT` non-deterministically selects an element
42-
from a list. *)
41+
{# The method `choose` on `BT` non-deterministically selects an element
42+
from a list. #}
4343
method choose {E, self : BT E} =
4444
let rec choose xs =
4545
match xs with
@@ -48,15 +48,15 @@ method choose {E, self : BT E} =
4848
end
4949
in choose
5050

51-
(* The `Fresh` effect is used to model the generation of fresh variable
52-
identifiers in the evaluator. *)
51+
{# The `Fresh` effect is used to model the generation of fresh variable
52+
identifiers in the evaluator. #}
5353
data Fresh (effect E) X = Fresh of (Unit ->[E] X)
5454

5555
method fresh {E, self = Fresh fresh : Fresh E _} = fresh
5656

57-
(* ========================================================================= *)
57+
{# ========================================================================= #}
5858

59-
(* The standard state handler, defined as a higher order function. *)
59+
{# The standard state handler, defined as a higher order function. #}
6060
let hState init (f : {effect=E} -> State E _ ->[E|_] _) =
6161
handle st = State
6262
{ get = effect () / r => fn s => r s s
@@ -66,8 +66,8 @@ let hState init (f : {effect=E} -> State E _ ->[E|_] _) =
6666
finally f => f init
6767
in f st
6868

69-
(* A handler for backtracking which returns the first result wrapped in Some,
70-
or None if no result is available. *)
69+
{# A handler for backtracking which returns the first result wrapped in Some,
70+
or None if no result is available. #}
7171
let hBT (f : {effect=E} -> BT E ->[E|_] _) =
7272
handle bt = BT
7373
{ flip = effect () / r =>
@@ -80,9 +80,9 @@ let hBT (f : {effect=E} -> BT E ->[E|_] _) =
8080
return x => Some x
8181
in f bt
8282

83-
(* ========================================================================= *)
84-
(* The following few functions on lists require a notion of equality, which is
85-
passed as the implicit parameter `~eq`. *)
83+
{# ========================================================================= #}
84+
{# The following few functions on lists require a notion of equality, which is
85+
passed as the implicit parameter `~eq`. #}
8686

8787
implicit ~eq
8888

@@ -101,9 +101,9 @@ let rec assoc x xs =
101101
| (y, v) :: xs => if ~eq x y then Some v else assoc x xs
102102
end
103103

104-
(* ========================================================================= *)
105-
(* Methods on terms and clauses that are useful for implementing variable
106-
refreshing. *)
104+
{# ========================================================================= #}
105+
{# Methods on terms and clauses that are useful for implementing variable
106+
refreshing. #}
107107

108108
method vars =
109109
let ~eq (x : Int) = x.equal in
@@ -134,26 +134,26 @@ method rename sub =
134134
method rename { self = Cl t ts } sub =
135135
Cl (t.rename sub) (List.map (fn (t : Term) => t.rename sub) ts)
136136

137-
(* ========================================================================= *)
137+
{# ========================================================================= #}
138138

139-
(* The instantiation of unification variables is represented using `State`
139+
{# The instantiation of unification variables is represented using `State`
140140
containing an association list of instantiations. As this effect is pervasive
141141
throughout our implementation, we declare it as an implicit, so that it and
142-
the associated effect variable E_st are generalized automatically. *)
142+
the associated effect variable E_st are generalized automatically. #}
143143
implicit ~st {E_st} : State E_st (List (Pair Int Term))
144144

145-
(* We also define a pair of functions that let us modify and read `~st`. *)
145+
{# We also define a pair of functions that let us modify and read `~st`. #}
146146

147147
let setVar (x : Int) t = ~st.update (fn xs => (x, t) :: xs)
148148

149149
let getVar x =
150150
let ~eq (x : Int) = x.equal in
151151
assoc x (~st.get ())
152152

153-
(* The `view` method on terms can be used to view the outer-most shape of a
153+
{# The `view` method on terms can be used to view the outer-most shape of a
154154
term, accounting for the instantiation of unification variables.
155155
In a realistic implementation we would keep terms that haven't been viewed
156-
abstract to prevent accidentally pattern-matching on them. *)
156+
abstract to prevent accidentally pattern-matching on them. #}
157157
method rec view {self : Term} =
158158
match self with
159159
| TVar x =>
@@ -167,34 +167,34 @@ method rec view {self : Term} =
167167
| TFun f ts => self
168168
end
169169

170-
(* As with `~st`, the capability to generate fresh identifiers ~fresh is also
171-
declared implicit. *)
170+
{# As with `~st`, the capability to generate fresh identifiers ~fresh is also
171+
declared implicit. #}
172172
implicit ~fresh {E_fresh} : Fresh E_fresh Int
173173

174-
(* To further reduce verbosity, we define a function `fresh` to call the
175-
`fresh` method of the implicit capability. *)
174+
{# To further reduce verbosity, we define a function `fresh` to call the
175+
`fresh` method of the implicit capability. #}
176176
let fresh () = ~fresh.fresh ()
177177

178-
(* We attach additional `refresh` methods to terms and clauses, which replace
179-
all the variables in terms with fresh unification variables. *)
178+
{# We attach additional `refresh` methods to terms and clauses, which replace
179+
all the variables in terms with fresh unification variables. #}
180180

181181
method refresh {self : Term} =
182182
self.rename (List.map (fn x => (x, fresh ())) self.vars)
183183

184184
method refresh {self : Clause} =
185185
self.rename (List.map (fn x => (x, fresh ())) self.vars)
186186

187-
(* ========================================================================= *)
187+
{# ========================================================================= #}
188188

189-
(* Finally, we make the interpreter's knowledge base and the backtracking
189+
{# Finally, we make the interpreter's knowledge base and the backtracking
190190
capability implicit as well. The knowledge base is represented as a reader
191-
effect providing a simple list of clauses. *)
191+
effect providing a simple list of clauses. #}
192192
implicit ~kb {E_kb} : Reader E_kb (List Clause)
193193
implicit ~bt {E_bt} : BT E_bt
194194

195195
let fail () = ~bt.fail ()
196196

197-
(* Check whether a variable occurs in a term. *)
197+
{# Check whether a variable occurs in a term. #}
198198
method occurs (x : Int) =
199199
let rec occurs (t : Term) =
200200
match t.view with
@@ -203,7 +203,7 @@ method occurs (x : Int) =
203203
end
204204
in occurs self
205205

206-
(* Attempt to unify two terms, and signal the need to backtrack on failure. *)
206+
{# Attempt to unify two terms, and signal the need to backtrack on failure. #}
207207
let rec unify (t1 : Term) (t2 : Term) =
208208
match t1.view, t2.view with
209209
| TVar x, TVar y =>
@@ -217,24 +217,24 @@ let rec unify (t1 : Term) (t2 : Term) =
217217
else fail ()
218218
end
219219

220-
(* Retrieve some clause from the knowledge base non-deterministically. *)
220+
{# Retrieve some clause from the knowledge base non-deterministically. #}
221221
let kbChoose () = ~bt.choose (~kb.ask ())
222222

223-
(* Try to derive a term using the knowledge base. *)
223+
{# Try to derive a term using the knowledge base. #}
224224
let rec eval (t : Term) =
225225
let Cl t' ts = (kbChoose ()).refresh in
226226
let _ = unify t t' in
227227
List.iter eval ts
228228

229-
(* Perform a query by substituting fresh unification variables in a term and
230-
calling the `eval` function. *)
229+
{# Perform a query by substituting fresh unification variables in a term and
230+
calling the `eval` function. #}
231231
let query (t : Term) = eval t.refresh
232232

233-
(* ========================================================================= *)
234-
(* Below we finally install some handlers for the interpreter and show its
235-
use on a simple hardcoded query. *)
233+
{# ========================================================================= #}
234+
{# Below we finally install some handlers for the interpreter and show its
235+
use on a simple hardcoded query. #}
236236

237-
(* Example database. *)
237+
{# Example database. #}
238238
let kb = [Cl (TFun "f" [TVar 0, TVar 0]) []]
239239

240240
handle ~kb = Reader (fn () => kb)
@@ -247,7 +247,7 @@ let _ =
247247
match
248248
hBT (fn ~bt =>
249249
hState [] (fn ~st =>
250-
(* Example query. *)
250+
{# Example query. #}
251251
query (TFun "f" [TFun "a" [], TFun "a" []])))
252252
with
253253
| Some _ => printStrLn "Yes."

0 commit comments

Comments
 (0)