1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
-module(my_digraph_adt).
-export([new/0, new/1]).
-record(my_digraph, {vtab = notable,
etab = notable,
ntab = notable,
cyclic = true :: boolean()}).
-opaque my_digraph() :: #my_digraph{}.
-type d_protection() :: 'private' | 'protected'.
-type d_cyclicity() :: 'acyclic' | 'cyclic'.
-type d_type() :: d_cyclicity() | d_protection().
-spec new() -> my_digraph().
new() -> new([]).
-spec new([atom()]) -> my_digraph().
new(Type) ->
try check_type(Type, protected, []) of
{Access, Ts} ->
V = ets:new(vertices, [set, Access]),
E = ets:new(edges, [set, Access]),
N = ets:new(neighbours, [bag, Access]),
ets:insert(N, [{'$vid', 0}, {'$eid', 0}]),
set_type(Ts, #my_digraph{vtab=V, etab=E, ntab=N})
catch
throw:Error -> throw(Error)
end.
-spec check_type([atom()], d_protection(), [{'cyclic', boolean()}]) ->
{d_protection(), [{'cyclic', boolean()}]}.
check_type([acyclic|Ts], A, L) ->
check_type(Ts, A,[{cyclic,false} | L]);
check_type([cyclic | Ts], A, L) ->
check_type(Ts, A, [{cyclic,true} | L]);
check_type([protected | Ts], _, L) ->
check_type(Ts, protected, L);
check_type([private | Ts], _, L) ->
check_type(Ts, private, L);
check_type([T | _], _, _) ->
throw({error, {unknown_type, T}});
check_type([], A, L) -> {A, L}.
-spec set_type([{'cyclic', boolean()}], my_digraph()) -> my_digraph().
set_type([{cyclic,V} | Ks], G) ->
set_type(Ks, G#my_digraph{cyclic = V});
set_type([], G) -> G.
|