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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
Spree: module
{
MAXPLAYERS: con 100;
Attribute: adt {
name: string;
val: string;
visibility: Sets->Set; # set of members that can see attr
needupdate: Sets->Set; # set of members that have not got an update queued
};
Attributes: adt {
a: array of list of ref Attribute;
set: fn(attr: self ref Attributes, name, val: string, vis: Sets->Set): (int, ref Attribute);
get: fn(attr: self ref Attributes, name: string): ref Attribute;
new: fn(): ref Attributes;
};
Range: adt {
start: int;
end: int;
};
Object: adt {
id: int;
attrs: ref Attributes;
visibility: Sets->Set;
parentid: int;
children: cyclic array of ref Object; # not actually cyclic
cliqueid: int;
objtype: string;
transfer: fn(o: self ref Object, r: Range, dst: ref Object, i: int);
setvisibility: fn(o: self ref Object, visibility: Sets->Set);
setattrvisibility: fn(o: self ref Object, name: string, visibility: Sets->Set);
setattr: fn(o: self ref Object, name: string, val: string, vis: Sets->Set);
getattr: fn(o: self ref Object, name: string): string;
delete: fn(o: self ref Object);
deletechildren: fn(o: self ref Object, r: Range);
};
Rq: adt {
pick {
Init =>
opts: string;
Command =>
member: ref Member;
cmd: string;
Join =>
member: ref Member;
cmd: string;
suspended: int;
Leave =>
member: ref Member;
Notify =>
srcid: int;
cmd: string;
}
};
# this might also be known as a "group", as there's nothing
# inherently clique-like about it; it's just a group of members
# mutually creating and manipulating objects.
Clique: adt {
id: int;
fileid: int;
fname: string;
objects: array of ref Object;
archive: ref Archives->Archive;
freelist: list of int;
mod: Engine;
memberids: Sets->Set; # set of allocated member ids
suspended: list of ref Member;
request: chan of ref Rq;
reply: chan of string;
hungup: int;
started: int;
parentid: int;
notes: list of (int, int, string); # (src, dest, note)
new: fn(parent: self ref Clique, archive: ref Archives->Archive, owner: string): (int, string, string); # returns (cliqueid, filename, error)
newobject: fn(clique: self ref Clique, parent: ref Object, visibility: Sets->Set, objtype: string): ref Object;
start: fn(clique: self ref Clique);
action: fn(clique: self ref Clique, cmd: string,
objs: list of int, rest: string, whoto: Sets->Set);
breakmsg: fn(clique: self ref Clique, whoto: Sets->Set);
show: fn(clique: self ref Clique, member: ref Member);
member: fn(clique: self ref Clique, id: int): ref Member;
membernamed: fn(clique: self ref Clique, name: string): ref Member;
members: fn(clique: self ref Clique): list of ref Member;
owner: fn(clique: self ref Clique): string;
hangup: fn(clique: self ref Clique);
fcreate: fn(clique: self ref Clique, i: int, pq: int, d: Sys->Dir): string;
fremove: fn(clique: self ref Clique, i: int): string;
notify: fn(clique: self ref Clique, cliqueid: int, msg: string);
};
# a Member is involved in one clique only
Member: adt {
id: int;
cliqueid: int;
obj2ext: array of int;
ext2obj: array of ref Object;
freelist: list of int;
name: string;
updating: int;
suspended: int;
ext: fn(member: self ref Member, id: int): int;
obj: fn(member: self ref Member, id: int): ref Object;
del: fn(member: self ref Member, suspend: int);
};
init: fn(ctxt: ref Draw->Context, argv: list of string);
archivenames: fn(): list of string;
newarchivename: fn(): string;
rand: fn(n: int): int;
};
Engine: module {
init: fn(srvmod: Spree, clique: ref Spree->Clique, argv: list of string): string;
command: fn(member: ref Spree->Member, e: string): string;
join: fn(member: ref Spree->Member , e: string, suspended: int): string;
leave: fn(member: ref Spree->Member): int;
notify: fn(fromid: int, s: string);
readfile: fn(f: int, offset: big, count: int): array of byte;
};
Archives: module {
PATH: con "/dis/spree/archives.dis";
Archive: adt {
argv: list of string; # how to restart the session.
members: array of string; # members involved.
info: list of (string, string); # any other information.
objects: array of ref Spree->Object;
};
init: fn(mod: Spree);
write: fn(clique: ref Spree->Clique, info: list of (string, string), file: string, members: Sets->Set): string;
read: fn(file: string): (ref Archive, string);
readheader: fn(file: string): (ref Archive, string);
};
|