Skip to content

Commit

Permalink
Merge branch 'master' into 66-repl-bug-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ppolesiuk committed May 6, 2024
2 parents 11b3486 + eac7cc7 commit 73507c7
Show file tree
Hide file tree
Showing 37 changed files with 686 additions and 274 deletions.
4 changes: 3 additions & 1 deletion examples/LWT.dbl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
time using first class labels. In opposite to LWT_lexical example, this
implementation does not lead to memory leaks, because the newly created
thread do not share an unreachable continuation with the parent thread. *)

import List

(* We start with defining the standard State effect, together with default
functions for accessing the state. See LWT_lexical example for more
Expand Down Expand Up @@ -62,7 +64,7 @@ let sched () =

(* Put a thread to the scheduler queue *)
let enqueue thr =
update (fn q => append q [Thread thr])
update (fn q => List.append q [Thread thr])

(* Here, we handle LWT effect. Note that the handler does not provide any
capability. It only plays a role of the delimiter (reset0) on given label.
Expand Down
4 changes: 3 additions & 1 deletion examples/LWT_lexical.dbl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
to effect capabilities we can separate an interface from an implementation
of algebraic effects. *)

import List

(* We start by defining the standard State effect representing a single
mutable cell. Note that in DBL an effect signature is an ordinary record
of functions. A special type parameter `(effect E)` is the effect of these
Expand Down Expand Up @@ -58,7 +60,7 @@ handle {effect=Sched} `st =
mechanism of implicit parameters, this function uses `st capability, without
mentioning it explicitly. *)
let enqueue thr =
update (fn queue => append queue [thr])
update (fn queue => List.append queue [thr])

(* Run the scheduler. It picks one thread from the queue and runs it. *)
let sched _ =
Expand Down
3 changes: 3 additions & 0 deletions examples/Modules/A.dbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import B/C/D

pub let foo = D.id 42
2 changes: 2 additions & 0 deletions examples/Modules/B/A.dbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub let id x = x
pub let bar = 13
4 changes: 4 additions & 0 deletions examples/Modules/B/C/D.dbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(* This import resolves to the absolute path `/Main/B/A`. *)
import A

pub let id = A.id
1 change: 1 addition & 0 deletions examples/Modules/C.dbl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub let mod_C_value = 0
38 changes: 38 additions & 0 deletions examples/Modules/Main.dbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(** This example serves to showcase the files-as-modules feature.

The module hierarchy is as follows.
```
/
├─ Main
│ ├─ Main (this file)
│ ├─ A (imports B/C/D, resolving to /Main/B/C/D)
│ ├─ B
│ │  ├─ A
│ │  └─ C
│ │  └─ D (imports A, resolving to /Main/B/A)
│ └─ C
├─ List
```
Modules under `/Main/` are local to this example and follow its directory
structure. Additionaly, the module `/List` from the standard library is
imported.

Relative imports refer to the module which is the closest to the importing
module, working upwards through the hierarchy. In this example the module
`/Main/B/C/D` imports the relative path `A`, and the nearest matching
module is `/Main/B/A`. *)

import List

import A
import B/C/D as X
import /Main/B/C/D as Y (* The same import, but as an absolute path. *)
import B/A as A2

(* Rather than binding a module name, import the module's contents *)
import open C

let _ =
List.iter (fn x => printInt x; printStr "\n")
[ X.id A.foo, Y.id A2.bar, mod_C_value ]
24 changes: 13 additions & 11 deletions examples/Prolog.dbl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
(* This example implements a simplified version of Prolog and serves to
illustrate the combination of implicit parameters and effect capabilities. *)

import List

(* Prolog terms and clauses are fairly standard. Here variables are
identified by integers and functors by strings. *)
data rec Term = TVar of Int | TFun of String, List Term
Expand Down Expand Up @@ -94,11 +96,11 @@ implicit `eq
let nub = fix (fn nub xs =>
match xs with
| [] => []
| x :: xs => x :: nub (filter (fn y => not (`eq x y)) xs)
| x :: xs => x :: nub (List.filter (fn y => not (`eq x y)) xs)
end)

let union xs ys = nub (append xs ys)
let unions xss = nub (concat xss)
let union xs ys = nub (List.append xs ys)
let unions xss = nub (List.concat xss)

let assoc x = fix (fn assoc xs =>
match xs with
Expand All @@ -115,12 +117,12 @@ method vars =
fix (fn vars t =>
match t with
| TVar x => [x]
| TFun _ ts => unions (map vars ts)
| TFun _ ts => unions (List.map vars ts)
end) self

method vars { self = Cl t ts } =
let `eq (x : Int) = x.equal in
union t.vars (unions (map (fn (t : Term) => t.vars) ts))
union t.vars (unions (List.map (fn (t : Term) => t.vars) ts))

method rename sub =
let `eq (x : Int) = x.equal in
Expand All @@ -131,11 +133,11 @@ method rename sub =
| Some y => TVar y
| None => TVar x
end
| TFun f ts => TFun f (map rename ts)
| TFun f ts => TFun f (List.map rename ts)
end) self

method rename { self = Cl t ts } sub =
Cl (t.rename sub) (map (fn (t : Term) => t.rename sub) ts)
Cl (t.rename sub) (List.map (fn (t : Term) => t.rename sub) ts)

(* ========================================================================= *)

Expand Down Expand Up @@ -182,10 +184,10 @@ let fresh () = `fresh.fresh ()
all the variables in terms with fresh unification variables. *)

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

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

(* ========================================================================= *)

Expand Down Expand Up @@ -214,7 +216,7 @@ let unify = fix (fn unify (t1 : Term) (t2 : Term) =>
| t, TVar x =>
if t.occurs x then fail () else setVar x t
| TFun f ts1, TFun g ts2 =>
if f == g then iter2 {`re = fail} unify ts1 ts2
if f == g then List.iter2 {`re = fail} unify ts1 ts2
else fail ()
end)

Expand All @@ -225,7 +227,7 @@ let kbChoose () = `bt.choose (`kb.ask ())
let eval = fix (fn eval (t : Term) =>
let Cl t' ts = (kbChoose ()).refresh in
let _ = unify t t' in
iter eval ts)
List.iter eval ts)

(* Perform a query by substituting fresh unification variables in a term and
calling the `eval` function. *)
Expand Down
4 changes: 3 additions & 1 deletion examples/Pythagorean.dbl
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
(* This example demonstrates the use of effect handlers
to implement a backtracking search for Pythagorean triples. *)

import List

data Triples = Triple of Int, Int, Int

(* The standard backtracking effect. *)
Expand Down Expand Up @@ -46,7 +48,7 @@ let takeFirst (f : {effect=E} -> BT E -> Int ->[E|_] _) (n: Int) =
(* The function `takeAll` returns list of all triples found. *)
let takeAll (f : {effect=E} -> BT E -> Int ->[E|_] _) (n: Int) =
handle bt = BT
{ flip = effect () / r => append (r True) (r False)
{ flip = effect () / r => List.append (r True) (r False)
, fail = effect () => []
}
return x => [x]
Expand Down
4 changes: 3 additions & 1 deletion examples/Tick.dbl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
effects used internally by `f`. This would not be true for dynamic handlers.
*)

import List

let count (f : {type E} -> (_ ->[|E] _) ->[|E] _) g =
handle tick = effect _ / k => fn (n : Int) => k () (n + 1)
return _ => fn n => n
Expand All @@ -30,7 +32,7 @@ let count (f : {type E} -> (_ ->[|E] _) ->[|E] _) g =

(* We can use `count` function to compute a length of a list, by counting
how many times map function calls identity argument. *)
let length xs = count (flip map xs) id
let length xs = count (flip List.map xs) id

(* This code should print 2. *)
let _ =
Expand Down
37 changes: 37 additions & 0 deletions lib/List.dbl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
pub let map f = fix (fn map xs =>
match xs with
| [] => []
| x :: xs => f x :: map xs
end)

pub let filter f = fix (fn filter xs =>
match xs with
| [] => []
| x :: xs => if f x then x :: filter xs else filter xs
end)

pub let append xs ys = fix (fn append xs =>
match xs with
| [] => ys
| x :: xs => x :: append xs
end) xs

pub let concat = fix (fn concat xss =>
match xss with
| [] => []
| xs :: xss => append xs (concat xss)
end)

pub let iter f = fix (fn iter xs =>
match xs with
| [] => ()
| x :: xs => let () = f x in iter xs
end)

pub let iter2 {`re : {type X} -> Unit ->[|_] X} f =
fix (fn iter xs ys =>
match xs, ys with
| [], [] => ()
| x :: xs, y :: ys => let () = f x y in iter xs ys
| _ => `re ()
end)
Loading

0 comments on commit 73507c7

Please sign in to comment.