/
procedure.ced~
executable file
·272 lines (218 loc) · 12.3 KB
/
procedure.ced~
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
% Procedures
signature(cpi:procedureCommand(Proc, Command) :: proc, [Proc::procedure, Command::command]).
signature(procedure(Proc, Command)::statement, [Proc::procedure, Command::command]).
procedure(Proc, Command) ~> cpi:procedureCommand(Proc, Command) :- builtin:true.
signature(function(Expr, T, Result, Command) :: statement, [Expr::expr(T), T::type, Result::ref(T), Command::command]).
signature(cpi:func(Proc, Result, T) :: procedure, [Proc::procedure, Result::ref(T), T::type]).
function(Expr, T, Result, Command) ~> procedure(cpi:func(Expr, Result, T), Command).
signature(cpi:termClass(TTerm, ClassName)::pred, [TTerm::typedTerm, ClassName::string]).
signature(class(TTerm, ClassName)::statement, [TTerm::typedTerm, ClassName::string]).
commandClass(Cmd, ClassName) ~> cpi:termClass(Cmd::command, ClassName) :- builtin:true.
signature(doAll(List)::command, [List::list(command)]).
commandClass(doAll(_), s('net.nansore.cedalion.cmd.DoAll')).
signature(assign(Ref, Expr, Type)::command, [Ref::ref(Type), Expr::expr(Type), Type::type]).
commandClass(assign(_, _, _), s('net.nansore.cedalion.cmd.Assign')).
signature(doProc(Proc)::command, [Proc::procedure]).
commandClass(doProc(_), s('net.nansore.cedalion.cmd.DoProc')).
signature(readFile(FileName, Namespace, FileContent)::command, [FileName::string, Namespace::string, FileContent::fileContent]).
commandClass(readFile(FileName, Namespace, FileContent), s('net.nansore.cedalion.cmd.ReadFile')).
signature(writeFile(FileName, FileContent)::command, [FileName::string, FileContent::fileContent]).
commandClass(writeFile(FileName, FileContent), s('net.nansore.cedalion.cmd.WriteFile')).
signature(assignFinal(Var, Expr, T)::command, [Var::T, Expr::expr(T), T::type]).
commandClass(assignFinal(Var, Expr, T), s('net.nansore.cedalion.cmd.AssignFinal')).
signature(dbInsert(Statement)::command, [Statement::statement]).
commandClass(dbInsert(Statement), s('net.nansore.cedalion.cmd.DBInsert')).
signature(dbRemove(Statement)::command, [Statement::statement]).
commandClass(dbRemove(Statement), s('net.nansore.cedalion.cmd.DBRemove')).
signature(termToString(TTerm, VarNames, Depth, NsList, Str)::command, [TTerm::typedTerm, VarNames::list(varName), Depth::number, NsList::list(namespacePair), Str::ref(string)]).
commandClass(termToString(TTerm, VarNames, Depth, NsList, Str), s('net.nansore.cedalion.cmd.TermToString')).
signature(stringToTerm(StringRef, NsList, TTerm, VarNames)::command, [StringRef::ref(string), NsList::list(namespacePair), TTerm::typedTerm, VarNames::list(varName)]).
commandClass(stringToTerm(StringRef, NsList, TTerm, VarNames), s('net.nansore.cedalion.cmd.StringToTerm')).
% Open a file
procedure(cpi:openFile(FileName, ResourceName, Namespace),
doAll([
readFile(FileName, Namespace, FileContent),
assignFinal(Model, fileToModel(FileContent), model),
dbInsert(loadedFile(ResourceName, FileName, Model)),
dbInsert(editState(ResourceName, [], [], 0))
])).
procedure(cpi:closeFile(ResourceName),
doAll([
dbRemove(loadedFile(ResourceName, _, _)),
dbRemove(editState(ResourceName, _, _, _))
])).
loadedFile(ResourceName, FileName, Model) ~> fileIsLoaded(ResourceName, FileName, Model) :- builtin:true.
editState(ResourceName, UndoStack, RedoStack, ModifiedCounter) ~> editStateIs(ResourceName, UndoStack, RedoStack, ModifiedCounter) :- builtin:true.
cpi:procedureCommand(cpi:func(fileToModel(fileContent(Terms, NsList)), ModelRef, model), assign(ModelRef, cpi:constExpr(model(Statements, VarNames, NsList)), model)) :-
fileModel(Terms, Statements, VarNames).
signature(fileModel(Terms, Statements, VarNames)::pred, [Terms::list(annotatedTerm), Statements::list(statement), VarNames::list(varName)]).
fileModel([], [], []) :- builtin:true.
fileModel([statement(S, VN1) | Terms], [S | Statements], VarNames) :-
fileModel(Terms, Statements, VN2),
mergeVarNames(VN1, VN2, VarNames).
mergeVarNames([], VarNames, VarNames) :- builtin:true.
mergeVarNames([varName(Var::T, Name) | VN1], VN2, VarNames) :-
builtin:if(varInVarNames(Var::T, VN2),
mergeVarNames(VN1, VN2, VarNames),
%else
mergeVarNames(VN1, [varName(Var::T, Name) | VN2], VarNames)).
varInVarNames(Var::T, [varName(Var1::T, _) | _]) :-
builtin:equals(Var1::T, Var::T).
varInVarNames(Var::T, [_ | VN]) :-
varInVarNames(Var::T, VN).
% Save a file
cpi:procedureCommand(cpi:saveFile(ResourceName, FileName), writeFile(FileName, Content)) :-
fileIsLoaded(ResourceName, _, Model),
modelToContent(Model, Content).
modelToContent(model(Statements, VarNames, NsList), fileContent(AnnoStatements, NsList)) :-
annotateStatements(Statements, VarNames, AnnoStatements).
annotateStatements([], _, []) :- builtin:true.
annotateStatements([Statement | Statements], VarNames, [statement(Statement, VN1) | AnnoStatements]) :-
selectVarNamesFor(Statement::statement, VarNames, VN1),
annotateStatements(Statements, VarNames, AnnoStatements).
selectVarNamesFor(_, [], []) :- builtin:true.
selectVarNamesFor(TTerm, [varName(Var::T, Name) | VarNames], VN) :-
selectVarNamesFor(TTerm, VarNames, VN1),
builtin:if(varIn(Var::T, TTerm),
VN = [varName(Var::T, Name) | VN1],
% else
VN = VN1).
varIn(Var::VarType, Term::TermType) :-
builtin:if(builtin:var(Term::TermType),
builtin:equals(Var::VarType, Term::TermType),
(% else
builtin:compound(Term::TermType),
builtin:parseTerm(Term::TermType, _, Args),
varInList(Var::VarType, Args)
)).
varInList(Var::VarType, [First::FirstType | _]) :-
varIn(Var::VarType, First::FirstType).
varInList(Var::VarType, [_ | Tail]) :-
varInList(Var::VarType, Tail).
% Retrieve a term at a given path
cpi:termAtPath(cpi:path(ResourceName, []), Statements::list(statement), VarNames) :-
fileIsLoaded(ResourceName, _, model(Statements, VarNames, _)).
cpi:termAtPath(cpi:path(ResourceName, [Innermost | Rest]), TTerm, CroppedVarNames) :-
cpi:termAtPath(cpi:path(ResourceName, Rest), TParent, VarNames),
builtin:parseTerm(TParent, _, TArgs),
element(TTerm, Innermost, TArgs, typedTerm),
% selectVarNamesFor(TTerm, VarNames, CroppedVarNames).
CroppedVarNames = VarNames.
% The n'th element of a list (1-based)
signature(element(Elem, Index, List, Type)::pred, [Elem::Type, Index::number, List::list(Type), Type::type]).
element(First, 1, [First | _], _) :- builtin:true.
element(Elem, Index, [_ | Rest], Type) :-
builtin:succ(IndexMinusOne, Index),
element(Elem, IndexMinusOne, Rest, Type).
% Modify the n'th element of a list (1-based) to produce a new list
signature(setElement(Index, List, Elem, NewList, Type)::pred, [Index::number, List::list(Type), Elem::Type, NewList::Type, Type::type]).
setElement(1, [_ | Rest], Elem, [Elem | Rest], _) :- builtin:true.
setElement(Index, [First | Rest], Elem, [First | ModRest], Type) :-
builtin:succ(IndexMinusOne, Index),
setElement(IndexMinusOne, Rest, Elem, ModRest, Type).
% Modify a term at a given path
cpi:procedureCommand(cpi:setAtPath(cpi:path(ResourceName, []), Statements::list(statement), VarNames2), doAll([
dbRemove(loadedFile(ResourceName, _, _)),
dbInsert(loadedFile(ResourceName, FileName, model(Statements, VarNames, NsList)))])) :-
fileIsLoaded(ResourceName, FileName, model(_, VarNames1, NsList)),
mergeVarNames(VarNames1, VarNames2, VarNames).
cpi:procedureCommand(cpi:setAtPath(cpi:path(ResourceName, [Innermost | Rest]), TTerm, VarNames1), Command) :-
cpi:termAtPath(cpi:path(ResourceName, Rest), TParent, VarNames2),
mergeVarNames(VarNames1, VarNames2, VarNames),
builtin:parseTerm(TParent, Func, TArgs),
setElement(Innermost, TArgs, TTerm, TModArgs, typedTerm),
builtin:parseTerm(TModParent, Func, TModArgs),
cpi:procedureCommand(cpi:setAtPath(cpi:path(ResourceName, Rest), TModParent, VarNames), Command).
% Edit operation: Modify and update the undo stack
cpi:procedureCommand(cpi:edit(cpi:path(ResourceName, Path), TTerm, VarNames), doAll([
doProc(cpi:setAtPath(cpi:path(ResourceName, Path), TTerm, VarNames)),
dbRemove(editState(ResourceName, _, _, _)),
dbInsert(editState(ResourceName, [editOp(cpi:path(ResourceName, Path), OldTypedContent, OldVarNames) | UndoStack], [], NewModifiedCounter))
])) :-
editStateIs(ResourceName, UndoStack, _, OldModifiedCounter),
cpi:termAtPath(cpi:path(ResourceName, Path), OldTypedContent, OldVarNames),
builtin:if(OldModifiedCounter < 0,
NewModifiedCounter::number = 99999::number,
%else
builtin:succ(OldModifiedCounter, NewModifiedCounter)).
% Undo editing
cpi:procedureCommand(cpi:undo(ResourceName), doAll([
doProc(cpi:setAtPath(cpi:path(ResourceName, Path), TypedContent, VarNames)),
assignFinal(NewModifiedCounter, cpi:constExpr(OldModifiedCounter) - cpi:constExpr(1), number),
dbRemove(editState(ResourceName, _, _, _)),
dbInsert(editState(ResourceName, UndoStack, [editOp(cpi:path(ResourceName, Path), OldTypedContent, OldVarNames) | RedoStack], NewModifiedCounter))
])) :-
editStateIs(ResourceName, [editOp(cpi:path(ResourceName, Path), TypedContent, VarNames) | UndoStack], RedoStack, OldModifiedCounter),
cpi:termAtPath(cpi:path(ResourceName, Path), OldTypedContent, OldVarNames).
% Redo editing
cpi:procedureCommand(cpi:redo(ResourceName), doAll([
doProc(cpi:setAtPath(cpi:path(ResourceName, Path), TypedContent, VarNames)),
assignFinal(NewModifiedCounter, cpi:constExpr(OldModifiedCounter) - cpi:constExpr(1), number),
dbRemove(editState(ResourceName, _, _, _)),
dbInsert(editState(ResourceName, [editOp(cpi:path(ResourceName, Path), OldTypedContent, OldVarNames) | UndoStack], RedoStack, NewModifiedCounter))
])) :-
editStateIs(ResourceName, UndoStack, [editOp(cpi:path(ResourceName, Path), TypedContent, VarNames) | RedoStack], OldModifiedCounter),
cpi:termAtPath(cpi:path(ResourceName, Path), OldTypedContent, OldVarNames).
% Arithmetic functions
signature((X+Y)::number, [X::number, Y::number]).
function(X+Y, number, Z, plus(X, Y, Z)).
commandClass(plus(X, Y, Z), s('net.nansore.cedalion.cmd.Plus')).
signature((X-Y)::number, [X::number, Y::number]).
function(X-Y, number, Z, minus(X, Y, Z)).
commandClass(minus(X, Y, Z), s('net.nansore.cedalion.cmd.Minus')).
% Path to string
cpi:procedureCommand(cpi:func(cpi:termAsString(cpi:path(ResourceName, Path), Depth), Str, string), termToString(TTerm, VarNames, Depth, NsList, Str)) :-
cpi:termAtPath(cpi:path(ResourceName, Path), TTerm, VarNames),
fileIsLoaded(ResourceName, _, model(_, _, NsList)).
% Edit a certain path with the given string
cpi:procedureCommand(cpi:editFromString(cpi:path(ResourceName, Path), StringRef), doAll([
stringToTerm(StringRef, NsList, TTerm, VarNames),
doProc(cpi:edit(cpi:path(ResourceName, Path), TTerm, VarNames))
])) :-
fileIsLoaded(ResourceName, _, model(_, _, NsList)).
%%%%% Visualization %%%%%%%
cpi:visualizePath(Path, Vis) :-
cpi:termAtPath(Path, Term::Type, VarNames),
builtin:if(builtin:var(Term::Type),
visualizeVar(Term::Type, VarNames, Vis),
% else
builtin:if(builtin:number(Term::Type),
visualizeNumber(Term::Type, Vis),
% else
builtin:if(builtin:string(Term::Type),
visualizeString(Term::Type, Vis),
% else
visualizeCompound(Path, Term::Type, Vis)
)
)
).
visualizeVar(_, [varName(_, Name)], italic(color(label(Name), rgb(0, 128, 0)))) :- builtin:true.
visualizeNumber(Num::number, numLabel(Num)) :- builtin:true.
visualizeString(Str::string, label(Str)) :- builtin:true.
visualizeCompound(Path, TTerm, Vis) :-
builtin:parseTerm(TTerm, Func, TArgs),
builtin:length(TArgs, typedTerm, Arity),
subPaths(Path, 0, Arity, SubPaths),
visualizeNameSubpaths(Func, SubPaths, Vis).
subPaths(_, Last, Last, []) :- builtin:true.
subPaths(cpi:path(Res, Path), BeforeFirst, Last, [cpi:path(Res, [First | Path]) | SubPaths]) :-
builtin:succ(BeforeFirst, First),
subPaths(cpi:path(Res, Path), First, Last, SubPaths).
visualizeNameSubpaths(Func, SubPaths, Vis) :-
builtin:if(userVisualization(Func, SubPaths, Vis),
builtin:true,
% else
defaultVisualization(Func, SubPaths, Vis)).
defaultVisualization(Func, SubPaths, Vis) :-
builtin:if(SubPaths::list(cpi:path) = []::list(cpi:path),
Vis::visualization = label(Func)::visualization,
(% else
argListForPathList(SubPaths, ArgList),
Vis::visualization = horiz([label(Func), label(s('(')), horiz(ArgList), label(s(')'))])::visualization
)
).
argListForPathList([Path], [vis(Path)]) :- builtin:true.
argListForPathList([First | Rest], [vis(First), label(s(',')) | ArgList]) :-
argListForPathList(Rest, ArgList).
signature(visualize(Func, Args, Vis)::statement, [Func::string, Args::list(cpi:path), Vis::visualization]).
visualize(Func, Args, Vis) ~> userVisualization(Func, Args, Vis) :- builtin:true.