1 | // $Source$ |
---|
2 | // $Revision: 686 $ |
---|
3 | // $Date: 2003-04-27 14:59:09 +0000 (Sun, 27 Apr 2003) $ |
---|
4 | |
---|
5 | $use "rfpc"; |
---|
6 | $use "rfp_err"; |
---|
7 | $use "rfp_list"; |
---|
8 | $use "rfp_helper"; |
---|
9 | $use "rfp_check"; |
---|
10 | $use "rfp_as2as"; |
---|
11 | $use "rfp_format"; |
---|
12 | $use "rfp_vars"; |
---|
13 | $use "rfp_const"; |
---|
14 | |
---|
15 | $use StdIO; |
---|
16 | $use Table; |
---|
17 | $use Box; |
---|
18 | $use Arithm; |
---|
19 | $use Access; |
---|
20 | $use Compare; |
---|
21 | $use Convert; |
---|
22 | $use Class; |
---|
23 | $use Apply; |
---|
24 | $use Dos; |
---|
25 | |
---|
26 | /* |
---|
27 | * Tables for storing $const'ant values and their lengthes. |
---|
28 | */ |
---|
29 | $table Const-Len; |
---|
30 | |
---|
31 | /* |
---|
32 | * Table for storing object names. |
---|
33 | */ |
---|
34 | $table Objects; |
---|
35 | |
---|
36 | /* |
---|
37 | * Table for storing referenced functions. |
---|
38 | */ |
---|
39 | $table Ref-To-Funcs; |
---|
40 | |
---|
41 | /* |
---|
42 | * Box for storing function out format |
---|
43 | */ |
---|
44 | $box Out-Format; |
---|
45 | |
---|
46 | /* |
---|
47 | * Box for storing names for function result variables |
---|
48 | */ |
---|
49 | $box Res-Vars; |
---|
50 | |
---|
51 | /* |
---|
52 | * Following table is used by Gener-Label function for obtaining unical (for |
---|
53 | * certain function) label name. |
---|
54 | * e.Key ::= e.QualifiedName (parameter given to Gener-Label) |
---|
55 | * e.Val ::= [Int] (last index used with such e.QualifiedName) |
---|
56 | */ |
---|
57 | $table Labels; |
---|
58 | |
---|
59 | //$box Var-Stack; |
---|
60 | $table Vars-Tab; |
---|
61 | |
---|
62 | $box Last-Re; |
---|
63 | |
---|
64 | $box Greater-Ineqs; |
---|
65 | $box Less-Ineqs; |
---|
66 | |
---|
67 | $const New-Clash-Tags = Unknown-length Ties Check-symbols Dereference Compare; |
---|
68 | |
---|
69 | $table Static-Exprs; |
---|
70 | |
---|
71 | $func Compile (e.targets) (e.headers) e.Items = e.Compiled-Items (INTERFACE e.headers); |
---|
72 | |
---|
73 | $func Print-Pragma s.channel t.Pragma = ; |
---|
74 | |
---|
75 | $func AS-To-Ref e.AS-Expr = e.Refal-Expr; |
---|
76 | |
---|
77 | $func Length-of e.Re = e.length; |
---|
78 | |
---|
79 | $func Ref-Len t.name = s.length; |
---|
80 | |
---|
81 | $func? Hard-Exp? e.expr = ; |
---|
82 | |
---|
83 | $func Comp-Func-Stubs = e.asail-funcs; |
---|
84 | |
---|
85 | $func Comp-Func s.tag t.name e.params-and-body = e.compiled-func; |
---|
86 | |
---|
87 | $func Set-Drops (e.declared-exprs) e.comp-func = (e.declared-exprs) e.result-func; |
---|
88 | |
---|
89 | $func Comp-Sentence e.Sentence = e.asail-sentence; |
---|
90 | |
---|
91 | $func Save-Snt-State = ; |
---|
92 | |
---|
93 | $func Recall-Snt-State = ; |
---|
94 | |
---|
95 | $func Pop-Snt-State = ; |
---|
96 | |
---|
97 | $func Extract-Calls e.Re = (e.last-Re) e.calls; |
---|
98 | |
---|
99 | $func Comp-Static-Exprs e.Reult-exprs = e.Result-exprs; |
---|
100 | |
---|
101 | $func Get-Clash-Sequence (e.last-Re) e.Snt = (e.clashes) e.rest-of-the-Sentence; |
---|
102 | |
---|
103 | $func Comp-Pattern t.Pattern e.Snt = e.asail-Snt; |
---|
104 | |
---|
105 | $func? Without-Calls? e.Re = ; |
---|
106 | |
---|
107 | //$func Old-Vars e.expr = e.expr; |
---|
108 | |
---|
109 | //$func Find-Known-Lengths e.clashes = (e.known-len-clashes) e.clashes; |
---|
110 | |
---|
111 | //$func? Known-Vars? e.vars = ; |
---|
112 | |
---|
113 | $func Comp-Clashes (e.clashes) s.tail? (v.fails) e.Sentence = e.asail-sentence; |
---|
114 | |
---|
115 | $func? Find-Var-Length e.clashes = e.cond (e.clashes); |
---|
116 | |
---|
117 | $func Update-Ties t.var e.clashes = e.clashes; |
---|
118 | |
---|
119 | $func Known-Length-of e.expr = e.known-length (e.unknown-vars); |
---|
120 | |
---|
121 | $func? Cyclic-Restrictions e.clashes = e.cond (e.clashes); |
---|
122 | |
---|
123 | $func Cyclic-Min t.var = e.min; |
---|
124 | |
---|
125 | $func? Cyclic-Max t.var = e.max; |
---|
126 | |
---|
127 | $func? Check-Symbols e.clashes = e.cond (e.clashes) s.new?; |
---|
128 | |
---|
129 | $func? Check-Ft t.Ft (e.pos) (e.right-pos) t.name s.dir = e.Ft-cond s.stop?; |
---|
130 | |
---|
131 | $func? Dereference-Subexpr e.clashes = e.cond (e.clashes); |
---|
132 | |
---|
133 | $func Compare-Subexpr e.clashes = e.cond (e.asserts) (e.clashes) s.new?; |
---|
134 | |
---|
135 | $func Compare-Ft t.Ft = e.Ft-cond s; |
---|
136 | |
---|
137 | $func? Get-Source e.clashes = e.cond (e.clashes); |
---|
138 | |
---|
139 | $func Compose-Expr e.expr = e.compose (e.not-instantiated-vars) s.flat?; |
---|
140 | |
---|
141 | $func? Comp-Cyclic e.clashes = e.cond (e.clashes) (e.fail); |
---|
142 | |
---|
143 | $func Get-Subexprs e.vars = e.asail-decls; |
---|
144 | |
---|
145 | $func Unknown-Vars e.expr = e.known-expr (e.unknown-vars); |
---|
146 | |
---|
147 | $func Split-Hard-Left e.expr = e.hard; |
---|
148 | |
---|
149 | $func Split-Hard-Right e.expr = e.hard; |
---|
150 | |
---|
151 | $func Gener-Label e.QualifiedName = t.label; |
---|
152 | |
---|
153 | $func Add-To-Label t.label e.name = t.label; |
---|
154 | |
---|
155 | $func Comp-Calls e.Re = e.calls; |
---|
156 | |
---|
157 | $func Comp-Assigns e.assignments = e.asail-assignments; |
---|
158 | |
---|
159 | $func Comp-Format (e.last-Re) e.He = e.assignments; |
---|
160 | |
---|
161 | $func Get-Static-Exprs e.expr = e.expr (e.decls); |
---|
162 | |
---|
163 | $func Get-Static-Var e.expr = e.var (e.decl); |
---|
164 | |
---|
165 | |
---|
166 | |
---|
167 | ************ Get AS-Items and targets, and pass it to Compile ************ |
---|
168 | |
---|
169 | RFP-Compile e.Items = |
---|
170 | { <Lookup &RFP-Options ITEMS>;; } :: e.targets, |
---|
171 | <Init-Consts>, |
---|
172 | <Compile (e.targets) () e.Items> :: e.Items t.Interface, |
---|
173 | t.Interface (MODULE <Comp-Consts> e.Items); |
---|
174 | |
---|
175 | |
---|
176 | |
---|
177 | ****************** Choose needed items and compile them ****************** |
---|
178 | |
---|
179 | Compile (e.targets) (e.headers) e.Items, { |
---|
180 | e.Items : e t.item e.rest, |
---|
181 | { |
---|
182 | e.targets : v = |
---|
183 | e.targets : e t.name e, |
---|
184 | t.item : (t t t t.name e);; |
---|
185 | }, \{ |
---|
186 | t.item : (s.link s.tag t.pragma t.name (e.in) (e.out) e.body) = |
---|
187 | // <WriteLN s.link s.tag t.name>, |
---|
188 | { s.link : EXPORT = (DECL-FUNC t.name);; } :: e.decl, |
---|
189 | { |
---|
190 | e.body : (BRANCH t.p e.branch) = |
---|
191 | <Comp-Func s.tag t.name <Del-Pragmas (e.in) (e.out) e.branch>>;; |
---|
192 | } :: e.comp-func, |
---|
193 | (e.decl) e.comp-func; |
---|
194 | t.item : (s.link CONST t.pragma t.name e.expr) = |
---|
195 | { |
---|
196 | s.link : IMPORT = () (DECL-CONST t.name); |
---|
197 | <Del-Pragmas e.expr> :: e.expr, |
---|
198 | (CONSTEXPR s.link t.name (e.expr) e.expr) :: e.const, |
---|
199 | { |
---|
200 | s.link : EXPORT = (e.const) /*empty*/; |
---|
201 | () e.const; |
---|
202 | }; |
---|
203 | }; |
---|
204 | } :: (e.decl) e.item = |
---|
205 | e.item <Compile (e.targets) (e.headers e.decl) e.rest>; |
---|
206 | /*<Comp-Func-Stubs>*/ (INTERFACE e.headers); |
---|
207 | }; |
---|
208 | |
---|
209 | /* |
---|
210 | * For each referenced function generate a stub one with format e = e. |
---|
211 | */ |
---|
212 | Comp-Func-Stubs = |
---|
213 | <Domain &Ref-To-Funcs> () $iter { |
---|
214 | e.funcs : ((e.QualifiedName)) e.rest, |
---|
215 | (e.QualifiedName 0) :: t.Fname, |
---|
216 | // <Bind &Ref-To-Funcs ((e.QualifiedName)) (t.Fname)>, |
---|
217 | // { |
---|
218 | // <In-Table? &Fun? (e.QualifiedName)> = |
---|
219 | // <Bind &Back-Funcs (t.Fname) ()>;; |
---|
220 | // }, |
---|
221 | // <Bind &Fin (t.Fname) ((EVAR))>, |
---|
222 | // <Bind &Fout (t.Fname) ((EVAR))>, |
---|
223 | <Lookup-Func (e.QualifiedName)> :: s.linkage s.tag t.pragma (e.Fin) (e.Fout), |
---|
224 | <Gener-Vars (e.Fin) "stub"> :: e.He, |
---|
225 | <Comp-Func s.tag t.Fname ((EVAR ("arg" 1))) ((EVAR ("res" 1))) |
---|
226 | (LEFT e.He) (RESULT (CALL (e.QualifiedName) e.He)) |
---|
227 | > :: e.asail, |
---|
228 | e.rest (e.asail-funcs e.asail); |
---|
229 | } :: e.funcs (e.asail-funcs), |
---|
230 | e.funcs : /*empty*/ = |
---|
231 | // Here is place to define expressions - references to stub functions. |
---|
232 | // Use &Ref-To-Funcs for that. |
---|
233 | e.asail-funcs; |
---|
234 | |
---|
235 | Comp-Func s.tag t.name (e.in) (e.out) e.Sentence = |
---|
236 | <RFP-Clear-Table &Labels>, |
---|
237 | <RFP-Clear-Table &Static-Exprs>, |
---|
238 | <Store &Greater-Ineqs /*empty*/>, |
---|
239 | <Store &Less-Ineqs /*empty*/>, |
---|
240 | //! <RFP-Clear-Table &Vars-Tab>, |
---|
241 | <Init-Vars>, |
---|
242 | <Ref-To-Var e.Sentence> :: e.Sentence, |
---|
243 | //! <Store-Vars <Vars e.out>> :: e.res-vars, |
---|
244 | <Vars <Gener-Vars (e.out) "res">> :: e.res-vars, |
---|
245 | <Vars-Decl e.res-vars> : e, |
---|
246 | <Store &Res-Vars e.res-vars>, |
---|
247 | <Store &Out-Format <Format-Exp e.out>>, |
---|
248 | //! <Norm-Vars (<Vars e.in>) e.Sentence> :: (e.arg-vars) e.Sentence, |
---|
249 | //! <Declare-Vars Expr e.arg-vars> : e, |
---|
250 | <Vars <Gener-Vars (e.in) "arg">> :: e.arg-vars, |
---|
251 | <Vars-Decl e.res-vars> : e, |
---|
252 | * <Instantiate-Vars e.arg-vars>, |
---|
253 | <Store &Last-Re /*empty*/>, |
---|
254 | s.tag : { |
---|
255 | FUNC = FATAL; |
---|
256 | FUNC? = RETFAIL; |
---|
257 | } :: t.retfail, |
---|
258 | (FUNC t.name (<Vars-Print e.arg-vars>) (<Vars-Print e.res-vars>) |
---|
259 | <Comp-Sentence Tail ((t.retfail)) () e.Sentence> |
---|
260 | ) :: e.comp-func, |
---|
261 | <Set-Drops () <Gener-Var-Names e.comp-func>> :: t e.comp-func, |
---|
262 | //! <Post-Comp (e.res-vars) e.comp-func> :: t e.result, |
---|
263 | //! e.result; |
---|
264 | e.comp-func; |
---|
265 | // :: (e.func-decl) e.func-body, |
---|
266 | // () <Domain &Declarations> $iter { |
---|
267 | // e.vars : (t.var) e.rest-vars, |
---|
268 | // (e.var-decls (DECL t.var)) e.rest-vars; |
---|
269 | // } :: (e.var-decls) e.vars, |
---|
270 | // e.vars : /*empty*/, |
---|
271 | // (e.func-decl e.var-decls e.func-body); |
---|
272 | |
---|
273 | Ref-To-Var e.Snt = |
---|
274 | () e.Snt $iter { |
---|
275 | e.Snt : t.Statement e.rest, t.Statement : { |
---|
276 | (REF t.name) = (e.new-Snt /*<New-Vars (VAR REF t.name)>*/) e.rest; |
---|
277 | |
---|
278 | //! <Table> :: s.tab, |
---|
279 | //! <Bind &Vars-Tab (t.name) (s.tab)>, |
---|
280 | //! <Set-Var t.name (Format) (<Format-Exp (REF t.name)>)>, |
---|
281 | //! <Set-Var t.name (Declared) (True)>, |
---|
282 | //! <Set-Var t.name (Instantiated) (True)>, |
---|
283 | //! <Set-Var t.name (Left-compare) ()>, |
---|
284 | //! <Set-Var t.name (Right-compare) ()>, |
---|
285 | //! <Set-Var t.name (Left-checks) ()>, |
---|
286 | //! <Set-Var t.name (Right-checks) ()>, |
---|
287 | //! (e.new-Snt (VAR t.name)) e.rest; |
---|
288 | |
---|
289 | (e.expr) = (e.new-Snt (<Ref-To-Var e.expr>)) e.rest; |
---|
290 | t = (e.new-Snt t.Statement) e.rest; |
---|
291 | }; |
---|
292 | } :: (e.new-Snt) e.Snt, |
---|
293 | e.Snt : /*empty*/ = |
---|
294 | e.new-Snt; |
---|
295 | |
---|
296 | Set-Drops (e.declared) e.comp-func = |
---|
297 | e.comp-func () (e.declared) $iter { |
---|
298 | e.comp-func : t.first e.rest, { |
---|
299 | t.first : \{ |
---|
300 | (EXPR t.var e) = (DROP t.var) (t.first) t.var Init; |
---|
301 | (DEREF t.var e) = (DROP t.var) (t.first) t.var Init; |
---|
302 | (SUBEXPR t.var e) = (DROP t.var) (t.first) t.var Init; |
---|
303 | (DECL Expr t.var) = (DROP t.var) () t.var Decl; |
---|
304 | (DECL "int" t.var) = /*empty*/ () t.var Decl; |
---|
305 | } :: e.drop (e.constr) t.var s.init, |
---|
306 | { |
---|
307 | e.declared : e1 t.var s.old-init e2, s.old-init : { |
---|
308 | Init, { |
---|
309 | t.var : (VAR ("const" e)) = |
---|
310 | e.rest (e.result-func) (e.declared); |
---|
311 | e.rest (e.result-func e.drop e.constr) (e.declared); |
---|
312 | }; |
---|
313 | Decl, s.init : { |
---|
314 | Decl = |
---|
315 | e.rest (e.result-func) (e.declared); |
---|
316 | Init = |
---|
317 | t.first : (s.method t.var e.args), |
---|
318 | e.rest (e.result-func (ASSIGN t.var (s.method e.args))) |
---|
319 | (e1 e2 t.var s.init); |
---|
320 | /* |
---|
321 | * FIXME: if s.method is EXPR, it shouldn't be written. |
---|
322 | */ |
---|
323 | }; |
---|
324 | }; |
---|
325 | e.rest (e.result-func t.first) (e.declared t.var s.init); |
---|
326 | }; |
---|
327 | t.first : (LABEL t.label e.expr) = |
---|
328 | <Set-Drops (e.declared) e.expr> :: (e.declared) e.expr, |
---|
329 | e.rest (e.result-func (LABEL t.label e.expr)) (e.declared); |
---|
330 | t.first : (e.expr) = |
---|
331 | <Set-Drops (e.declared) e.expr> :: t e.expr, |
---|
332 | e.rest (e.result-func (e.expr)) (e.declared); |
---|
333 | t.first : s.symbol = |
---|
334 | e.rest (e.result-func s.symbol) (e.declared); |
---|
335 | }; |
---|
336 | } :: e.comp-func (e.result-func) (e.declared), |
---|
337 | e.comp-func : /*empty*/ = |
---|
338 | (e.declared) e.result-func; |
---|
339 | |
---|
340 | |
---|
341 | Comp-Sentence s.tail? (v.fails) (e.last-Re) e.Sentence, e.Sentence : { |
---|
342 | |
---|
343 | /*empty*/ = /*empty*/; |
---|
344 | |
---|
345 | /* |
---|
346 | * In case of Re look if we should do a tailcall. If not, then compile |
---|
347 | * function calls from the Re and assign results to the out parameters or |
---|
348 | * use them in compilation of the rest of the sentence. |
---|
349 | */ |
---|
350 | (RESULT e.Re) e.Snt = |
---|
351 | { |
---|
352 | /* |
---|
353 | * If the Re is the last action in the sentence then we can do |
---|
354 | * tailcall if one of the following is true: |
---|
355 | * - Re is a call of non-failable function; |
---|
356 | * - Re is a call of a failable function, current function is |
---|
357 | * failable, and the failures stack is empty. |
---|
358 | * In both cases out format of the called function should coincide |
---|
359 | * with those of compiled one. |
---|
360 | * FIXME: really we can do tailcall if all the parameters of |
---|
361 | * compiled function that won't get their values from the call can |
---|
362 | * be assigned from other sources. Some support from runtime is |
---|
363 | * needed though. |
---|
364 | */ |
---|
365 | e.Snt : /*empty*/, s.tail? : Tail, e.Re : (CALL t.name e.arg), |
---|
366 | { <In-Table? &Fun? t.name> = v.fails : (RETFAIL);; }, |
---|
367 | <Lookup-Func t.name> :: s.linkage s.tag t.pragma (e.Fin) (e.Fout), |
---|
368 | <Subformat? (e.Fout) (<? &Out-Format>)> = |
---|
369 | <Extract-Calls e.arg> :: (e.last-Re) e.calls, |
---|
370 | <Comp-Static-Exprs <Split-Re (e.Fin) e.last-Re>> :: e.splited-Re, |
---|
371 | <Comp-Calls <R 0 v.fails> e.calls> |
---|
372 | (TAILCALL t.name (e.splited-Re) (<? &Res-Vars>)); |
---|
373 | |
---|
374 | <Extract-Calls e.Re> :: (e.last-Re) e.calls, |
---|
375 | <Comp-Calls <R 0 v.fails> e.calls> :: e.comp-calls, |
---|
376 | { |
---|
377 | e.Snt : /*empty*/, s.tail? : Tail = |
---|
378 | <Split-Re (<? &Out-Format>) e.last-Re> :: e.splited-Re, |
---|
379 | <Comp-Static-Exprs e.splited-Re> :: e.splited-Re, |
---|
380 | e.comp-calls <Comp-Assigns <Zip (<? &Res-Vars>) (e.splited-Re)>>; |
---|
381 | |
---|
382 | e.comp-calls <Comp-Sentence s.tail? (v.fails) (e.last-Re) e.Snt>; |
---|
383 | }; |
---|
384 | }; |
---|
385 | |
---|
386 | /* |
---|
387 | * In case of He compile assignments from last Re and then (with new state |
---|
388 | * of variables) proceed with the rest of the sentence. |
---|
389 | */ |
---|
390 | (FORMAT e.He) e.Snt = |
---|
391 | <Comp-Format (e.last-Re) e.He> |
---|
392 | <Comp-Sentence s.tail? (v.fails) () e.Snt>; |
---|
393 | |
---|
394 | /* |
---|
395 | * In case of Pe get from the begining of the sentence a maximum possible |
---|
396 | * sequence of clashes and compile it. New values of variables from the |
---|
397 | * clashes use in the compilation of the rest of the sentence. |
---|
398 | */ |
---|
399 | (s.dir e.Pattern) e.Snt, s.dir : \{ LEFT; RIGHT; } = |
---|
400 | <Get-Clash-Sequence (e.last-Re) e.Sentence> :: (e.clashes) e.Sentence, |
---|
401 | // <WriteLN !!! e.clashes>, |
---|
402 | <Comp-Clashes (e.clashes) s.tail? (v.fails) e.Sentence>; |
---|
403 | |
---|
404 | (s.block) e, BLOCK BLOCK? : e s.block e = <WriteLN! &StdErr "Empty block?">, $fail; |
---|
405 | |
---|
406 | /* |
---|
407 | * In case of a block first see if its results are needed for something |
---|
408 | * after the block and determine whether the block is a source. Then |
---|
409 | * compile each branch in turn. |
---|
410 | */ |
---|
411 | (s.block e.branches) e.Snt, |
---|
412 | s.block : \{ |
---|
413 | BLOCK = (FATAL); |
---|
414 | BLOCK?; |
---|
415 | } :: e.fatal? = |
---|
416 | /* |
---|
417 | * If the block initializes an $iter then extract from the $iter the He |
---|
418 | * for placing it in the end of each branch. |
---|
419 | * Then look if the block is used by a pattern or format expression. |
---|
420 | * If so, we should declare variables from that expression before |
---|
421 | * entering any branch -- those should be visible after the block. |
---|
422 | * If next after the block is (Comp Error) then block results should be |
---|
423 | * used as values for $error, so place (Comp Error) in the end of each |
---|
424 | * branch. |
---|
425 | */ |
---|
426 | { |
---|
427 | e.Snt : (ITER t.body t.format t.cond) e.rest = |
---|
428 | t.format (Comp Iter t.body t.format t.cond) e.rest; |
---|
429 | e.Snt; |
---|
430 | } :: e.Snt, |
---|
431 | e.Snt : { |
---|
432 | t.first e.rest, t.first : \{ |
---|
433 | (LEFT e.pattern) = e.pattern; |
---|
434 | (RIGHT e.pattern) = e.pattern; |
---|
435 | (FORMAT e.format) = e.format; |
---|
436 | } :: e.expr = |
---|
437 | <Vars e.expr> :: e.vars, |
---|
438 | * <New-Vars e.vars>, |
---|
439 | (<Vars-Decl e.vars>) (t.first) ((Comp Source)) e.rest; |
---|
440 | (Comp Error) e.rest = |
---|
441 | () ((Comp Error)) () /*empty*/; |
---|
442 | e = () () () e.Snt; |
---|
443 | } :: (e.decls) (e.next-term) (e.source?) e.Snt, |
---|
444 | /* |
---|
445 | * The block is a source if after it goes pattern or format expression |
---|
446 | * (in that case e.source? isn't empty) or e.Snt isn't empty. |
---|
447 | * Branches in the block are tail sentences if the current sentence is |
---|
448 | * tail and the block isn't a source. |
---|
449 | */ |
---|
450 | { |
---|
451 | \{ e.source? : v; e.Snt : v; } = ((Comp Source)) Notail; |
---|
452 | s.tail? : Tail = () Tail; |
---|
453 | () Notail; |
---|
454 | } :: (e.source?) s.tail-branch?, |
---|
455 | /* |
---|
456 | * In case our block is a source we should mark the position in the |
---|
457 | * failures stack, so that we can jump to it after CUTALL. And if our |
---|
458 | * block isn't failable we should add (FATAL) to the end of the stack. |
---|
459 | */ |
---|
460 | v.fails e.source? e.fatal? :: v.branch-fails, |
---|
461 | /* |
---|
462 | * We put all compiled branches in a block, so positive return from a |
---|
463 | * branch is a break from that block. |
---|
464 | * Each branch in its turn is placed in its own block, so for a $fail |
---|
465 | * to the next branch we should just break from that inner block. |
---|
466 | * Each branch is compiled with the current sentence state and the |
---|
467 | * state is recalled after that. When all branches are compiled the |
---|
468 | * state is popped out from the stack. |
---|
469 | * If last branch fails then the whole block fails, and return from the |
---|
470 | * last branch is return from the block. So the last branch isn't |
---|
471 | * placed in a block and is processed with the failures stack that was |
---|
472 | * before entering the block. Note: this trick helps us find more |
---|
473 | * tailcalls. If the call of a failable function is on the last branch |
---|
474 | * of the block and the failures stack is empty we can do tailcall. |
---|
475 | * When the last branch is compiled with the block's stack, all we |
---|
476 | * should do is to check it. |
---|
477 | */ |
---|
478 | <Gener-Label "block"> :: t.label, |
---|
479 | <Save-Snt-State>, |
---|
480 | (e.branches) /*e.comp-branches*/ $iter { |
---|
481 | e.branches : (BRANCH e.branch) e.rest-br = |
---|
482 | <Add-To-Label t.label "branch"> :: t.br-label, |
---|
483 | <Comp-Sentence |
---|
484 | s.tail-branch? |
---|
485 | (v.branch-fails ((BREAK t.br-label))) |
---|
486 | (e.last-Re) |
---|
487 | e.branch e.next-term |
---|
488 | > :: e.comp-br, |
---|
489 | <Recall-Snt-State>, |
---|
490 | (e.rest-br) e.comp-branches (LABEL t.br-label e.comp-br (BREAK t.label)); |
---|
491 | } :: (e.branches) e.comp-branches, |
---|
492 | e.branches : (BRANCH e.branch) = |
---|
493 | <Comp-Sentence |
---|
494 | s.tail-branch? (v.branch-fails) (e.last-Re) e.branch e.next-term |
---|
495 | > :: e.last-branch, |
---|
496 | <Pop-Snt-State>, |
---|
497 | e.decls (LABEL t.label e.comp-branches e.last-branch) |
---|
498 | <Comp-Sentence s.tail? (v.fails) () e.Snt>; |
---|
499 | |
---|
500 | /* |
---|
501 | * In case of $iter first of all compile initial assignment to the hard |
---|
502 | * expression. |
---|
503 | */ |
---|
504 | (ITER t.body t.format t.cond) e.Snt = |
---|
505 | <Comp-Sentence s.tail? (v.fails) (e.last-Re) |
---|
506 | t.format (Comp Iter t.body t.format t.cond) e.Snt |
---|
507 | >; |
---|
508 | |
---|
509 | /* |
---|
510 | * Then compile $iter condition and body both with the current state of the |
---|
511 | * sentence. |
---|
512 | * e.Snt can contain only (Comp Error), so compile it together with the |
---|
513 | * condition. |
---|
514 | * If condition fails we should compute the body, so put the compiled |
---|
515 | * condition in a block and place a break from it to the failures stack. |
---|
516 | */ |
---|
517 | (Comp Iter (BRANCH e.body) t.format (BRANCH e.condition)) e.Snt = |
---|
518 | <Gener-Label "iter"> :: t.label, |
---|
519 | <Save-Snt-State>, |
---|
520 | <Comp-Sentence s.tail? (v.fails ((BREAK t.label))) () e.condition e.Snt> |
---|
521 | :: e.comp-condition, |
---|
522 | <Pop-Snt-State>, |
---|
523 | <Comp-Sentence Notail (v.fails) () e.body t.format> :: e.comp-body, |
---|
524 | (FOR () () () (LABEL t.label e.comp-condition) e.comp-body); |
---|
525 | |
---|
526 | /* |
---|
527 | * In case of $trap/$with at first compile try-sentence. All $fails from |
---|
528 | * it should become errors. |
---|
529 | * Then recall the state of the sentence and compile catching of an error |
---|
530 | * with a variable err. |
---|
531 | * e.Snt can be only (Comp Error), so compile it together with both |
---|
532 | * sentences -- when either of it comuptes to an object expression it |
---|
533 | * becomes a value of the $error. |
---|
534 | */ |
---|
535 | (TRY (BRANCH e.try) e.catch) e.Snt = |
---|
536 | <Save-Snt-State>, |
---|
537 | <Comp-Sentence Notail ((FATAL)) () e.try e.Snt> :: e.comp-try, |
---|
538 | <Pop-Snt-State>, |
---|
539 | <Comp-Sentence s.tail? (v.fails) () (RESULT (EVAR ("err" 0))) e.catch e.Snt> |
---|
540 | :: e.comp-catch, |
---|
541 | (TRY e.comp-try) (CATCH-ERROR e.comp-catch); |
---|
542 | |
---|
543 | /* |
---|
544 | * In case of \? add Stake to the failures stack. Add last fail after it |
---|
545 | * for <R 0 v.fails> continue to work. |
---|
546 | */ |
---|
547 | (STAKE) e.Snt = |
---|
548 | <Comp-Sentence s.tail? (v.fails (Comp Stake) <R 0 v.fails>) () e.Snt>; |
---|
549 | |
---|
550 | /* |
---|
551 | * In case of \! forget all failure catchers after last \?. |
---|
552 | * If there is no Stake then we are inside negation or error (we assume the |
---|
553 | * program is correct). So the right failure catcher is in the bottom of |
---|
554 | * the stack. |
---|
555 | */ |
---|
556 | (CUT) e.Snt = |
---|
557 | { |
---|
558 | v.fails : $r v.earlier-fails (Comp Stake) e = v.earlier-fails; |
---|
559 | <L 0 v.fails>; |
---|
560 | } :: v.fails, |
---|
561 | <Comp-Sentence s.tail? (v.fails) () e.Snt>; |
---|
562 | |
---|
563 | /* |
---|
564 | * In case of = clear the failures stack up to the closest source. |
---|
565 | */ |
---|
566 | (CUTALL) e.Snt = |
---|
567 | { |
---|
568 | v.fails : $r v.earlier-fails (Comp Source) e = v.earlier-fails; |
---|
569 | <L 0 v.fails>; |
---|
570 | } :: v.fails, |
---|
571 | <Comp-Sentence s.tail? (v.fails) () e.Snt>; |
---|
572 | |
---|
573 | /* |
---|
574 | * In case of = in the Refal-6 sense (non-transparent hedge for the fails), |
---|
575 | * $fail(k) should become $error(Fname "Unexpected fail"), so clear the |
---|
576 | * failures stack and put that value in it. |
---|
577 | */ |
---|
578 | NOFAIL e.Snt = |
---|
579 | <Comp-Sentence s.tail? ((FATAL)) (e.last-Re) e.Snt>; |
---|
580 | |
---|
581 | /* |
---|
582 | * In case of $fail return last failure catcher. |
---|
583 | */ |
---|
584 | (FAIL) e.Snt = |
---|
585 | v.fails : e (e.last-fail), |
---|
586 | e.last-fail; |
---|
587 | |
---|
588 | /* |
---|
589 | * In case of # we should proceed with the rest if the source is computed |
---|
590 | * to $fail. |
---|
591 | * We could compile the rest of the sentence and place it in the |
---|
592 | * failures stack. But then the compiled sentence would be copied as many |
---|
593 | * times as there are $fail's to the upper level in the source. So we |
---|
594 | * place compiled source in the block and put the break to exit from it in |
---|
595 | * the stack. |
---|
596 | * When compiling the source mark it as Notail as usual. |
---|
597 | * If the source isn't computed to $fail we should proceed with the last |
---|
598 | * failure catcher. |
---|
599 | */ |
---|
600 | (NOT (BRANCH e.branch)) e.Snt = |
---|
601 | <Gener-Label "negation"> :: t.label, |
---|
602 | v.fails : e (e.last-fail), |
---|
603 | // <Save-Snt-State>, |
---|
604 | <Comp-Sentence Notail (((BREAK t.label))) () e.branch> e.last-fail |
---|
605 | :: e.comp-negation, |
---|
606 | // <Pop-Snt-State>, |
---|
607 | (LABEL t.label e.comp-negation) <Comp-Sentence s.tail? (v.fails) () e.Snt>; |
---|
608 | |
---|
609 | // (Comp Verbatim expr) = expr; |
---|
610 | |
---|
611 | /* |
---|
612 | * In case of $error all fails become $error(Fname "Unexpected fail"). So |
---|
613 | * place that value in the failures stack and then compile the computation |
---|
614 | * of the rest of the sentence and the last Re which should be the value of |
---|
615 | * $error. |
---|
616 | */ |
---|
617 | (ERROR) e.Snt = |
---|
618 | <Comp-Sentence Notail ((FATAL)) e.Snt () (Comp Error)>; |
---|
619 | |
---|
620 | (Comp Error) e.Snt = (ERROR e.last-Re); |
---|
621 | |
---|
622 | // (Comp Fatal) = FATAL; |
---|
623 | |
---|
624 | // (Comp Retfail) = RETFAIL; |
---|
625 | |
---|
626 | }; |
---|
627 | |
---|
628 | |
---|
629 | |
---|
630 | ********** Sentence state stack and functions for work with it. ********** |
---|
631 | |
---|
632 | $box Snt-State; |
---|
633 | |
---|
634 | /* |
---|
635 | * Put current state in the stack. |
---|
636 | */ |
---|
637 | Save-Snt-State = <Put &Snt-State <Vars-Copy-State>>; |
---|
638 | |
---|
639 | /* |
---|
640 | * Set current state to that at the top of the stack. |
---|
641 | */ |
---|
642 | Recall-Snt-State = <Vars-Set-State <R 0 <? &Snt-State>>>; |
---|
643 | |
---|
644 | /* |
---|
645 | * Pop the top from the stack and set current state to it. |
---|
646 | */ |
---|
647 | Pop-Snt-State = |
---|
648 | <Recall-Snt-State>, |
---|
649 | <Store &Snt-State <Middle 0 1 <? &Snt-State>>>; |
---|
650 | |
---|
651 | |
---|
652 | |
---|
653 | ********************** Function calls compilation. *********************** |
---|
654 | |
---|
655 | /* |
---|
656 | * $func Extract-Calls e.Re = (e.last-Re) e.calls; |
---|
657 | * |
---|
658 | * |
---|
659 | * |
---|
660 | */ |
---|
661 | Extract-Calls { |
---|
662 | (CALL t.name e.arg) e.rest = |
---|
663 | <Lookup-Func t.name> :: s.linkage s.tag t.pragma (e.Fin) (e.Fout), |
---|
664 | <Extract-Calls e.arg> :: (e.last-Re) e.calls, |
---|
665 | <Comp-Static-Exprs <Split-Re (e.Fin) e.last-Re>> :: e.splited-Re, |
---|
666 | <RFP-Extract-Qualifiers t.name> :: t e.prefix, |
---|
667 | * <Del-Pragmas <Gener-Vars 0 (e.Fout) e.prefix>> : e.Re s, |
---|
668 | //! <Store-Vars <Vars e.res-Re>> :: e.ress, |
---|
669 | //! <Instantiate-Vars e.ress>, |
---|
670 | //! <Ref-To-Var <Strip-STVE e.res-Re>> :: e.res-Re, |
---|
671 | //! e.decls <Declare-Vars "Expr" e.ress> :: e.decls, |
---|
672 | <Gener-Vars (e.Fout) e.prefix> :: /*(e.vars)*/ e.Re, |
---|
673 | <Vars e.Re> :: e.vars, |
---|
674 | * <Instantiate-Vars e.vars>, |
---|
675 | { |
---|
676 | s.tag : FUNC? = (Failable (CALL t.name (e.splited-Re) (e.vars))); |
---|
677 | (CALL t.name (e.splited-Re) (e.vars)); |
---|
678 | } :: t.call, |
---|
679 | <Extract-Calls e.rest> :: (e.rest-Re) e.rest-calls, |
---|
680 | (e.Re e.rest-Re) e.calls <Vars-Decl e.vars> t.call e.rest-calls; |
---|
681 | (PAREN e.Re) e.rest = |
---|
682 | <Extract-Calls e.Re> :: (e.last-Re) e.calls, |
---|
683 | <Extract-Calls e.rest> :: (e.rest-Re) e.rest-calls, |
---|
684 | ((PAREN e.last-Re) e.rest-Re) e.calls e.rest-calls; |
---|
685 | t.Rt e.Re = |
---|
686 | <Extract-Calls e.Re> :: (e.last-Re) e.calls, |
---|
687 | (t.Rt e.last-Re) e.calls; |
---|
688 | /*empty*/ = () /*empty*/; |
---|
689 | }; |
---|
690 | |
---|
691 | |
---|
692 | Comp-Calls (e.fail) e.calls, e.calls : { |
---|
693 | (Failable t.call) e.rest = |
---|
694 | (IF ((NOT t.call)) e.fail) <Comp-Calls (e.fail) e.rest>; |
---|
695 | t.call e.rest = |
---|
696 | t.call <Comp-Calls (e.fail) e.rest>; |
---|
697 | /*empty*/ = /*empty*/; |
---|
698 | }; |
---|
699 | |
---|
700 | |
---|
701 | |
---|
702 | *********** Compilation of static parts of result expressions ************ |
---|
703 | |
---|
704 | $func Static-Expr? s.create? e.Re = static? e.Re; |
---|
705 | |
---|
706 | $func Static-Term? t.Rt = static? t.Rt; |
---|
707 | |
---|
708 | |
---|
709 | /* |
---|
710 | * Extract static parts from each Re. |
---|
711 | */ |
---|
712 | Comp-Static-Exprs { |
---|
713 | (e.Re) e.rest = <Static-Expr? Create e.Re> :: s e.Re, (e.Re) <Comp-Static-Exprs e.rest>; |
---|
714 | /*empty*/ = /*empty*/; |
---|
715 | }; |
---|
716 | |
---|
717 | |
---|
718 | /* |
---|
719 | * Find all the longest static parts in the upper level of Re. Create STATIC |
---|
720 | * form in place of each one. |
---|
721 | * Return a tag pointing whether the whole expression is static and expression |
---|
722 | * with static parts replaced by STATIC forms. Dynamic parts are returned |
---|
723 | * unchanged. |
---|
724 | */ |
---|
725 | Static-Expr? { |
---|
726 | s.create? t.Rt e.Re = |
---|
727 | <Static-Term? t.Rt> : { |
---|
728 | Static t.Rt = |
---|
729 | { |
---|
730 | e.Re : e1 t2 e3, <Static-Term? t2> : Dynamic t.dyn-Rt = |
---|
731 | <Static-Expr? Create e.Re> :: s e.Re, |
---|
732 | Dynamic <Create-Static t.Rt e1> t.dyn-Rt e.Re; |
---|
733 | { |
---|
734 | s.create? : Create = Static <Create-Static t.Rt e.Re>; |
---|
735 | Static t.Rt e.Re; |
---|
736 | }; |
---|
737 | }; |
---|
738 | Dynamic t.dyn-Rt = |
---|
739 | <Static-Expr? Create e.Re> :: s e.Re, |
---|
740 | Dynamic t.dyn-Rt e.Re; |
---|
741 | }; |
---|
742 | s.create? /*empty*/ = Static; |
---|
743 | }; |
---|
744 | |
---|
745 | |
---|
746 | /* |
---|
747 | * The same as Static-Expr? but for terms. |
---|
748 | */ |
---|
749 | Static-Term? { |
---|
750 | symbol = Static symbol; |
---|
751 | (PAREN e.Re) = <Static-Expr? Not-Create e.Re> :: static? e.Re, static? (PAREN e.Re); |
---|
752 | (REF t.name) = Static (REF t.name); |
---|
753 | t.var = Dynamic t.var; |
---|
754 | }; |
---|
755 | |
---|
756 | |
---|
757 | |
---|
758 | ***************** Compilation of assignment to variables ***************** |
---|
759 | |
---|
760 | $func Comp-Assign-to-Var e = e; |
---|
761 | |
---|
762 | Comp-Assign-to-Var (t.var (e.Re)), { |
---|
763 | t.var : e.Re = /*empty*/; |
---|
764 | <Generated-Var? e.Re> = <Gener-Var-Assign t.var e.Re>; |
---|
765 | <Declared? t.var> = (ASSIGN <Vars-Print t.var> e.Re); |
---|
766 | <Vars-Decl t.var> : e, (EXPR <Vars-Print t.var> e.Re); |
---|
767 | }; |
---|
768 | |
---|
769 | Comp-Assigns e.assigns = <Map &Comp-Assign-to-Var (e.assigns)>; |
---|
770 | |
---|
771 | |
---|
772 | |
---|
773 | ************************** FORMAT compilation. *************************** |
---|
774 | |
---|
775 | $box Aux-Index; |
---|
776 | |
---|
777 | $func Gener-Aux-Var = t.new-aux-var; |
---|
778 | |
---|
779 | Gener-Aux-Var = |
---|
780 | <? &Aux-Index> : s.n, |
---|
781 | <Store &Aux-Index <"+" s.n 1>>, |
---|
782 | (VAR ("aux" s.n)); |
---|
783 | |
---|
784 | |
---|
785 | $func Create-Aux-Vars (e.vars) e.splited-Re = e.assigns; |
---|
786 | |
---|
787 | |
---|
788 | Comp-Format (e.last-Re) e.He = |
---|
789 | <Vars e.He> :: e.vars, |
---|
790 | <Comp-Static-Exprs <Split-Re (<Format-Exp e.He>) e.last-Re>> :: e.splited-Re, |
---|
791 | <Store &Aux-Index 1>, |
---|
792 | <Create-Aux-Vars (e.vars) e.splited-Re> :: e.assigns, |
---|
793 | <Comp-Assigns e.assigns>; |
---|
794 | |
---|
795 | /* |
---|
796 | * Итак, e.vars -- все переменные, входящие в форматное выражение. Каждая |
---|
797 | * переменная может входить в форматное выражение только один раз, поэтому |
---|
798 | * повторяющихся среди них нет. |
---|
799 | * e.splited-Re -- набор результатных выражений. На каждую переменную из |
---|
800 | * e.vars по выражению, которое должно быть ей присвоено. |
---|
801 | * |
---|
802 | * Если переменная t.var_i используется в выражении e.Re_j, и i /= j, то |
---|
803 | * переменной t.var_j значение должно быть присвоено раньше, чем перeменной |
---|
804 | * t.var_i. Если же, по аналогичным соображениям, t.var_i должна получить |
---|
805 | * значение раньше t.var_j, необходимо завести вспомогательную переменную. |
---|
806 | * |
---|
807 | * Пример: |
---|
808 | * |
---|
809 | * t1 (t1 t2) (t1 t3) :: t2 t1 t3 |
---|
810 | * |
---|
811 | * t3 = (t1 + t3)(); |
---|
812 | * aux_1 = t1; |
---|
813 | * t1 = (t1 + t2)() |
---|
814 | * t2 = aux_1; |
---|
815 | * |
---|
816 | * В общем случае вспомогательная переменная требуется, если двум переменным |
---|
817 | * необходимы старые значения друг друга (возможно, не напрямую, а через |
---|
818 | * промежуточные переменные). |
---|
819 | * |
---|
820 | * Вместо того, чтобы искать и анализировать такие циклы, будем действовать по |
---|
821 | * методу "наибольшей пользы". А именно: |
---|
822 | * |
---|
823 | * - Для каждой переменной выпишем все другие переменные, которым требуется |
---|
824 | * её старое значение, а также отдельно те, старые значения которых |
---|
825 | * требуются ей. |
---|
826 | * |
---|
827 | * - Всем переменным, от старых значений которых ничего не зависит, можно |
---|
828 | * смело присвоить новые значения. При этом они исчезают из списков |
---|
829 | * зависимостей оставшихся переменных. |
---|
830 | * |
---|
831 | * - Все переменные, новые значения которых ни от чего не зависят, можно |
---|
832 | * отложить, чтобы присвоить им значения тогда, когда будет удобно. Т.е. |
---|
833 | * тогда, когда списки зависящих от них переменных опустеют. |
---|
834 | * |
---|
835 | * - Чтобы означить оставшиеся, нужны вспомогательные переменные. Выберем |
---|
836 | * одну из переменных, с максимальным списком тех, от которых она зависит, |
---|
837 | * и положим её значение во вспомогательную переменную. Так как мы сразу |
---|
838 | * уменьшили кол-во зависимостей у максимального кол-ва переменных, |
---|
839 | * локально мы добились наибольшей пользы, хотя не исключено, что глобально |
---|
840 | * такой метод и не даст наименьшего кол-ва вспомогательных переменных. |
---|
841 | * Кроме того, мы не пытаемся выбрать наилучшую переменную из нескольких с |
---|
842 | * максимальным списком зависимостей. |
---|
843 | * |
---|
844 | * - Повторяем всё это до тех пор, пока у каждой переменной не опустеет |
---|
845 | * список зависящих от неё. |
---|
846 | * |
---|
847 | * |
---|
848 | * Для нашего примера: |
---|
849 | * |
---|
850 | * t1 (t1 t2) (t1 t3) :: t2 t1 t3 |
---|
851 | * |
---|
852 | * t1 -- (t2 t3) (t2) |
---|
853 | * t2 -- (t1) (t1) |
---|
854 | * t3 -- () (t1) |
---|
855 | * |
---|
856 | * |
---|
857 | * Для каждой переменной var_i найдём все j /= i, такие что в Re_j встречается |
---|
858 | * var_i -- provide[i], и а также все j /= i, такие что var_j нужна для |
---|
859 | * подсчёта var_i, т.е. встречается в Re_i. |
---|
860 | * |
---|
861 | * Res-vars <- <Map &Vars (Res)> |
---|
862 | * for var_i in vars |
---|
863 | * provide[i] <- |
---|
864 | * for vars-Re_j in Res-vars, j /= i |
---|
865 | * vars-Re_j : e var_i e = j |
---|
866 | * require[i] <- <Res-vars[i] `*` vars[^i]> : e var_j e, j |
---|
867 | * |
---|
868 | * Res-vars = map Vars Res |
---|
869 | * provide, require = |
---|
870 | * { [ j | vars-Re_j <- Res-vars, j /= i, var_i `in` vars-Re_j ] |
---|
871 | * , [ j | var_j <- Res-vars[i] `*` vars, i /= j] |
---|
872 | * | var_i <- vars |
---|
873 | * } |
---|
874 | * |
---|
875 | */ |
---|
876 | |
---|
877 | $func CAV e.vars (e.assigns) (e.delayed) = e.assigns; |
---|
878 | |
---|
879 | $func Get-Vars e = e; |
---|
880 | Get-Vars (e.Re) = (<Vars e.Re>); |
---|
881 | |
---|
882 | Create-Aux-Vars (e.vars) e.splited-Re = |
---|
883 | <Zip (<Map &Get-Vars (e.splited-Re)>) (e.vars)> :: e.list, |
---|
884 | <Box> :: s.box, |
---|
885 | <Box> :: s.provide-i, |
---|
886 | <Box> :: s.require-i, |
---|
887 | { |
---|
888 | e.vars : e1 t.var-i e2, |
---|
889 | { |
---|
890 | e.list : e ((e.vars-Re) t.var-j) e, |
---|
891 | \{ |
---|
892 | t.var-i : t.var-j = <Put s.require-i <And (e1 e2) e.vars-Re>>; |
---|
893 | e.vars-Re : e t.var-i e = <Put s.provide-i t.var-j>; |
---|
894 | }, |
---|
895 | $fail; |
---|
896 | <L <Length e1> e.splited-Re> :: t.Re-i, |
---|
897 | <Put s.box (t.var-i t.Re-i (<? s.provide-i>) (<? s.require-i>))>, |
---|
898 | <Store s.provide-i /*empty*/>, |
---|
899 | <Store s.require-i /*empty*/>; |
---|
900 | }, |
---|
901 | $fail;; |
---|
902 | }, |
---|
903 | <CAV <? s.box> (/*assigns*/) (/*delayed*/)>; |
---|
904 | |
---|
905 | |
---|
906 | /* |
---|
907 | * Если есть переменная, у которой список provide пуст, её можно посчитать. |
---|
908 | * Это выражается в том, что она (вместе с присваиваемым значением) добавляется |
---|
909 | * в список assigns, убирается из списка vars, а также из всех списков provide |
---|
910 | * и delayed. В списках require её не было. |
---|
911 | * |
---|
912 | * CAV Res vars provide require assigns delayed = |
---|
913 | * { i | var_i <- vars, provide_i == [] } -> // Здесь неверно! На переменные |
---|
914 | * из delayed тоже надо смотреть. |
---|
915 | * vars = vars - var_i |
---|
916 | * provide = [ provide_j - i | provide_j <- provide ] |
---|
917 | * assigns = assigns++[(var_i, Res[i])] |
---|
918 | * delayed = [ (var_j, provide_j - i) | (var_j, provide_j) <- delayed ] |
---|
919 | * CAV Res vars provide require assigns delayed |
---|
920 | */ |
---|
921 | |
---|
922 | $func Assign-Empty-Provides e.vars = e.assigns (e.vars); |
---|
923 | |
---|
924 | Assign-Empty-Provides { |
---|
925 | e1 (t.var-i t.Re-i (/*empty provide_i*/) (e.require-i)) e2 = |
---|
926 | <Box> :: s.vars, |
---|
927 | { |
---|
928 | e1 e2 : e (t.var-j t.Re-j (e.provide-j) (e.require-j)) e, |
---|
929 | <Put s.vars (t.var-j t.Re-j (<Sub (e.provide-j) t.var-i>) (e.require-j))>, |
---|
930 | $fail;; |
---|
931 | }, |
---|
932 | (t.var-i t.Re-i) <Assign-Empty-Provides <? s.vars>>; |
---|
933 | e.vars = /*empty*/ (e.vars); |
---|
934 | }; |
---|
935 | |
---|
936 | |
---|
937 | /* |
---|
938 | * Если есть переменная, у которой список require пуст, кладём её в delayed. |
---|
939 | * Она будет посчитана, когда у неё опустеет список provide, т.е. когда не |
---|
940 | * останется переменных, у которых она в списке require. |
---|
941 | */ |
---|
942 | $func Delay-Empty-Requires e.vars = e.delayed (e.vars); |
---|
943 | |
---|
944 | Delay-Empty-Requires { |
---|
945 | e1 t.var e2, t.var : (t.var-i t.Re-i (e.provide-i) (/*empty require_i*/)) = |
---|
946 | <Delay-Empty-Requires e2> :: e.delayed (e.vars), |
---|
947 | t.var e.delayed (e1 e.vars); |
---|
948 | e.vars = /*empty*/ (e.vars); |
---|
949 | }; |
---|
950 | |
---|
951 | |
---|
952 | /* |
---|
953 | * Выбор переменной (из двух) с более длинным списком требуемых ей значений. |
---|
954 | */ |
---|
955 | $func Max-Require e = e; |
---|
956 | |
---|
957 | Max-Require t.arg1 t.arg2 = |
---|
958 | t.arg1 : (t.var1 t.Re1 t.provide1 (e.require1)), |
---|
959 | t.arg2 : (t.var2 t.Re2 t.provide2 (e.require2)), |
---|
960 | { |
---|
961 | <"<" (<Length e.require1>) (<Length e.require2>)> = t.arg2; |
---|
962 | t.arg1; |
---|
963 | }; |
---|
964 | |
---|
965 | |
---|
966 | /* |
---|
967 | * Подставить вспомогательную переменную вместо исходной во всех результатных выражениях. |
---|
968 | * Присваивание к исходной переменной убрать (оно к этому моменту уже выполнено). |
---|
969 | * Убрать переменную из списков зависимостей. |
---|
970 | */ |
---|
971 | $func Subst-Aux-Var e = e; |
---|
972 | |
---|
973 | Subst-Aux-Var t.var t.aux (t.v t.Re (e.provide) (e.require)), { |
---|
974 | t.var : t.v = /*empty*/; |
---|
975 | ( |
---|
976 | t.v |
---|
977 | <Subst (t.var) ((t.aux)) t.Re> |
---|
978 | (<Sub (e.provide) t.var>) |
---|
979 | (<Sub (e.require) t.var>) |
---|
980 | ); |
---|
981 | }; |
---|
982 | |
---|
983 | |
---|
984 | /* |
---|
985 | * Извлечь присваивание из всей информации о переменной. |
---|
986 | */ |
---|
987 | $func Extract-Assigns e = e; |
---|
988 | Extract-Assigns (t.var t.Re e) = (t.var t.Re); |
---|
989 | |
---|
990 | |
---|
991 | /* |
---|
992 | * Основной цикл обработки присваиваний. |
---|
993 | * |
---|
994 | * 1) Из всех переменных (в том числе и отложенных), от которых больше ничего |
---|
995 | * не зависит, сделать присваивания. |
---|
996 | * 2) Все переменные, которые больше ни от чего не зависят, отложить. |
---|
997 | * 3) Если осталось хотя бы две неотложенных переменных, выбирать из них ту, |
---|
998 | * которая зависит от наибольшего числа переменных, подставить везде вместо |
---|
999 | * неё вспомогательную, перейти к пункту 1. |
---|
1000 | */ |
---|
1001 | CAV e.vars (e.assigns) (e.delayed) = |
---|
1002 | <Assign-Empty-Provides e.vars> :: e.new-assigns (e.vars), |
---|
1003 | e.assigns e.new-assigns <Assign-Empty-Provides e.delayed> :: e.assigns (e.delayed), |
---|
1004 | e.delayed <Delay-Empty-Requires e.vars> :: e.delayed (e.vars), |
---|
1005 | { |
---|
1006 | e.vars : t t e = |
---|
1007 | <Foldr1 &Max-Require (e.vars)> : (t.var t.Re e), |
---|
1008 | <Gener-Aux-Var> :: t.aux, |
---|
1009 | e.assigns (t.aux (t.var)) (t.var t.Re) :: e.assigns, |
---|
1010 | <Map &Subst-Aux-Var t.var t.aux (e.vars)> :: e.vars, |
---|
1011 | <Map &Subst-Aux-Var t.var t.aux (e.delayed)> :: e.delayed, |
---|
1012 | <CAV e.vars (e.assigns) (e.delayed)>; |
---|
1013 | e.assigns <Map &Extract-Assigns (e.vars e.delayed)>; |
---|
1014 | }; |
---|
1015 | |
---|
1016 | |
---|
1017 | |
---|
1018 | |
---|
1019 | Get-Clash-Sequence (e.last-Re) t.Pattern e.Snt = |
---|
1020 | ((e.last-Re) t.Pattern) e.Snt $iter { |
---|
1021 | e.Snt : (RESULT e.Re) t.Pt e.rest = |
---|
1022 | (e.clashes (e.Re) t.Pt) e.rest; |
---|
1023 | } :: (e.clashes) e.Snt, |
---|
1024 | # \{ |
---|
1025 | e.Snt : \{ |
---|
1026 | (RESULT e.Re) (LEFT e) e = e.Re; |
---|
1027 | (RESULT e.Re) (RIGHT e) e = e.Re; |
---|
1028 | } :: e.Re, |
---|
1029 | <Without-Calls? e.Re>; |
---|
1030 | } = |
---|
1031 | (e.clashes) e.Snt; |
---|
1032 | |
---|
1033 | |
---|
1034 | Comp-Pattern (s.dir e.PatternExp) e.Sentence = |
---|
1035 | <Norm-Vars (<Vars e.PatternExp>) (s.dir e.PatternExp) e.Sentence> |
---|
1036 | : t t.Pattern e.Snt, |
---|
1037 | // (Unwatched (<? &Last-Re>) t.Pattern) e.Snt $iter { |
---|
1038 | /* |
---|
1039 | * Uncomment previous line and delete next one to activate Split-Clashes |
---|
1040 | * function |
---|
1041 | */ |
---|
1042 | ((<? &Last-Re>) t.Pattern) e.Snt $iter { |
---|
1043 | e.Snt : (RESULT e.Re) (s.d e.Pe) e = |
---|
1044 | // <WriteLN Matching (RESULT e.Re) (s.d e.Pe)>, |
---|
1045 | <Norm-Vars (<Vars e.Pe>) e.Snt> : t t.R t.P e.rest, |
---|
1046 | // (e.clashes Unwatched (e.Re) t.P) e.rest; |
---|
1047 | /* |
---|
1048 | * Uncomment previous line and delete next one to activate |
---|
1049 | * Split-Clashes function |
---|
1050 | */ |
---|
1051 | (e.clashes (e.Re) t.P) e.rest; |
---|
1052 | } :: (e.clashes) e.Snt, |
---|
1053 | # \{ |
---|
1054 | e.Snt : \{ |
---|
1055 | (RESULT e.Re) (LEFT e) e = e.Re; |
---|
1056 | (RESULT e.Re) (RIGHT e) e = e.Re; |
---|
1057 | } :: e.Re, |
---|
1058 | <Without-Calls? e.Re>; |
---|
1059 | } = |
---|
1060 | e.Snt : e.Current-Snt (Comp Sentence) e.Other-Snts = |
---|
1061 | <Comp-Sentence () e.Other-Snts> :: e.asail-Others, |
---|
1062 | { |
---|
1063 | // <Split-Clashes (e.clashes) e.Current-Snt> |
---|
1064 | // :: (e.greater) (e.less) (e.hards) (e.clashes) e.Current-Snt = |
---|
1065 | // <WriteLN "Hards: " e.hards>, |
---|
1066 | // <WriteLN "Less: " e.less>, |
---|
1067 | // <WriteLN "Greater: " e.greater>, |
---|
1068 | // <WriteLN "Current-Snt: " e.Current-Snt>, |
---|
1069 | //! <Comp-Clashes (e.clashes) |
---|
1070 | //! (e.Current-Snt (Comp Sentence)) e.Other-Snts> :: e.asail-Clashes, |
---|
1071 | // e.asail-Clashes (e.greater) $iter { |
---|
1072 | // e.greater : (e.vars s.num) e.rest, |
---|
1073 | // <Old-Vars e.vars> :: e.vars, // temporary step |
---|
1074 | // (IF ((INFIX ">=" ((LENGTH e.vars)) (s.num))) |
---|
1075 | // e.asail-Clashes |
---|
1076 | // ) (e.rest); |
---|
1077 | // } :: e.asail-Clashes (e.greater), |
---|
1078 | // e.greater : /*empty*/ = |
---|
1079 | // e.asail-Clashes (e.less) $iter { |
---|
1080 | // e.less : (e.vars s.num) e.rest, |
---|
1081 | // <Old-Vars e.vars> :: e.vars, // temporary step |
---|
1082 | // (IF ((INFIX "<=" ((LENGTH e.vars)) (s.num))) |
---|
1083 | // e.asail-Clashes |
---|
1084 | // ) (e.rest); |
---|
1085 | // } :: e.asail-Clashes (e.less), |
---|
1086 | // e.less : /*empty*/ = |
---|
1087 | // e.asail-Clashes (e.hards) $iter { |
---|
1088 | // e.hards : (e.Re) (e.Pe) e.rest, |
---|
1089 | // <Old-Vars e.Re> :: e.Re, // temporary step |
---|
1090 | // <Old-Vars e.Pe> :: e.Pe, // temporary step |
---|
1091 | // (IF ((INFIX "==" (e.Re) (e.Pe))) e.asail-Clashes) (e.rest); |
---|
1092 | // } :: e.asail-Clashes (e.hards), |
---|
1093 | // e.hards : /*empty*/ = |
---|
1094 | //! e.asail-Clashes |
---|
1095 | e.asail-Others; |
---|
1096 | e.asail-Others; |
---|
1097 | // <Comp-Sentence () e.Other-Snts>; |
---|
1098 | }; |
---|
1099 | |
---|
1100 | Without-Calls? e.Re = |
---|
1101 | e.Re $iter { |
---|
1102 | e.Re : t.Rt e.rest = |
---|
1103 | t.Rt : { |
---|
1104 | (CALL e) = $fail; |
---|
1105 | (BLOCK e) = $fail; |
---|
1106 | (PAREN e.Re1) = <Without-Calls? e.Re1>; |
---|
1107 | t.symbol-or-var = /*empty*/; |
---|
1108 | }, |
---|
1109 | e.rest; |
---|
1110 | } :: e.Re, |
---|
1111 | e.Re : /*empty*/; |
---|
1112 | |
---|
1113 | //Comp-Clashes (e.clashes) (e.Current-Snt) e.Other-Snts = |
---|
1114 | // <WriteLN Clashes e.clashes>, |
---|
1115 | //// /* |
---|
1116 | //// * Collect in e.vars all varibles from all clashes. |
---|
1117 | //// */ |
---|
1118 | //// () e.clashes $iter { |
---|
1119 | //// e.not-watched : (e.expr) e.rest = (e.vars <Vars e.expr>) e.rest; |
---|
1120 | //// } :: (e.vars) e.not-watched, |
---|
1121 | //// e.not-watched : /*empty*/ = |
---|
1122 | //// /* |
---|
1123 | //// * Rename all collected variables in all clashes. Never mind multiple |
---|
1124 | //// * occurences. |
---|
1125 | //// */ |
---|
1126 | //// (e.clashes) e.vars $iter { |
---|
1127 | //// e.vars : (s.var-tag s.m (e.n) e.var-id) e.rest, { |
---|
1128 | //// <Known-Vars? (s.var-tag e.var-id)> = |
---|
1129 | //// e.var-id : e.NEW (e.QualifiedName), |
---|
1130 | //// <Subst ((s.var-tag s.m (e.n) e.var-id)) |
---|
1131 | //// (((s.var-tag (s.var-tag NEW ("len" e.QualifiedName)) |
---|
1132 | //// s.m (e.n) e.var-id))) e.clashes>; |
---|
1133 | //// s.m : e.n = |
---|
1134 | //// <Subst ((s.var-tag s.m (e.n) e.var-id)) |
---|
1135 | //// (((s.var-tag (s.m) s.m (e.n) e.var-id))) e.clashes>; |
---|
1136 | //// } :: e.clashes, |
---|
1137 | //// (e.clashes) e.rest; |
---|
1138 | //// } :: (e.clashes) e.vars, |
---|
1139 | //// e.vars : /*empty*/ = |
---|
1140 | //// /* |
---|
1141 | //// * Now all variables with known length have ref. term after s.var-tag. |
---|
1142 | //// * Well, lets see if there are closed variables and compute their lengthes |
---|
1143 | //// * too. |
---|
1144 | //// */ |
---|
1145 | //// e.clashes (e.clashes) () $iter { |
---|
1146 | //// e.not-watched : (e.Re) (s.dir e.Pe) e.rest, { |
---|
1147 | //// <Find-Closed-Var e.Pe> :: t.old-var t.new-var e.new-cond, |
---|
1148 | //// <Subst (t.old-var) ((t.new-var)) e.clashes> :: e.clashes, |
---|
1149 | //// e.clashes (e.clashes) (e.cond e.new-cond); |
---|
1150 | //// e.rest (e.clashes) (e.cond); |
---|
1151 | //// }; |
---|
1152 | //// } :: e.not-watched (e.clashes) (e.cond), |
---|
1153 | //// e.not-watched : /*empty*/ = |
---|
1154 | // |
---|
1155 | // /* |
---|
1156 | // * Parenthesize each clash, so from now on they can be seen as a sequence |
---|
1157 | // * of such terms: (e.temp-tags (e.Re) t.P) |
---|
1158 | // */ |
---|
1159 | // e.clashes () $iter { |
---|
1160 | // e.old-clashes : t.R t.P e.rest = |
---|
1161 | // e.rest (e.clashes (t.R t.P)); |
---|
1162 | // } :: e.old-clashes e.clashes, |
---|
1163 | // e.old-clashes : /*empty*/ = |
---|
1164 | // |
---|
1165 | // <Find-Known-Lengths e.clashes> :: (e.known-len-clashes) e.clashes, |
---|
1166 | // { |
---|
1167 | // e.known-len-clashes : /*empty*/ = |
---|
1168 | // <Find-Symbol-Checks e.clashes> :: (e.sym-check-clashes) e.clashes, |
---|
1169 | // { |
---|
1170 | // e.sym-check-clashes : /*empty*/ = |
---|
1171 | // e.clashes : { |
---|
1172 | // (e.Re) (s.dir e.Pe) e.rest = |
---|
1173 | // <Gener-Label L> :: t.label, |
---|
1174 | // <Comp-Clashes (e.rest) (e.Current-Snt) |
---|
1175 | // (Comp Continue t.label) e.Other-Snts> |
---|
1176 | // :: e.asail-Snt, |
---|
1177 | // (FOR t.label () () () |
---|
1178 | // e.asail-Snt |
---|
1179 | // ) |
---|
1180 | // <Comp-Sentence () e.Other-Snts>; |
---|
1181 | // /*empty*/ = |
---|
1182 | // <Comp-Sentence () e.Current-Snt e.Other-Snts>; |
---|
1183 | // }; |
---|
1184 | // <Comp-Clashes (e.clashes) (e.Current-Snt) e.Other-Snts> :: e.asail-Snt, |
---|
1185 | // (e.sym-check-clashes) e.asail-Snt $iter { |
---|
1186 | // e.sym-check-clashes : e.something (e (e.Re) (s.dir e.Pe)), |
---|
1187 | // |
---|
1188 | // <Comp-Clashes (e.clashes) (e.Current-Snt) e.Other-Snts> :: e.asail-Snt, |
---|
1189 | // (e.known-len-clashes) e.asail-Snt $iter { |
---|
1190 | // e.known-len-clashes : e.something (e.tags (e.Re) (s.dir e.Pe)), |
---|
1191 | // (e.something) |
---|
1192 | // (IF ((INFIX "==" (<Length-of e.Re>) (<Length-of e.Pe>))) |
---|
1193 | // e.asail-Snt |
---|
1194 | // ); |
---|
1195 | // } :: (e.known-len-clashes) e.asail-Snt, |
---|
1196 | // e.known-len-clashes : /*empty*/ = |
---|
1197 | // e.asail-Snt |
---|
1198 | // <Comp-Sentence () e.Other-Snts>; |
---|
1199 | // }; |
---|
1200 | // |
---|
1201 | //Find-Known-Lengths e.clashes = |
---|
1202 | // e.clashes () () $iter { |
---|
1203 | // e.old-clashes : t.first e.rest, t.first : { |
---|
1204 | // (e1 Known-length e2) = |
---|
1205 | // e.rest (e.known) (e.clashes t.first); |
---|
1206 | // (e.tags (e.Re) (s.dir e.Pe)) = |
---|
1207 | //// Known <Vars e.Re> <Vars e.Pe> $iter { |
---|
1208 | //// e.vars : (VAR t.name) e.rest-vars, { |
---|
1209 | //// <?? t.name Length> : e = Known; |
---|
1210 | //// <?? t.name Instantiated> : True = Known; |
---|
1211 | //// Unknown; |
---|
1212 | //// } :: s.known? = |
---|
1213 | //// s.known? e.rest-vars; |
---|
1214 | //// } :: s.known? e.vars, |
---|
1215 | //// \{ |
---|
1216 | //// s.known? : Unknown = |
---|
1217 | //// e.rest (e.known) (e.clashes t.first); |
---|
1218 | //// e.vars : /*empty*/ = |
---|
1219 | //// e.rest (e.known t.first) |
---|
1220 | //// (e.clashes (e.tags Known-length (e.Re) (s.dir e.Pe))); |
---|
1221 | //// }; |
---|
1222 | // { |
---|
1223 | // <Hard-Exp? <Vars e.Re> <Vars e.Pe>> = |
---|
1224 | // e.rest (e.known t.first) |
---|
1225 | // (e.clashes (e.tags Known-length (e.Re) (s.dir e.Pe))); |
---|
1226 | // e.rest (e.known) (e.clashes t.first); |
---|
1227 | // }; |
---|
1228 | // }; |
---|
1229 | // } :: e.old-clashes (e.known) (e.clashes), |
---|
1230 | // e.old-clashes : /*empty*/ = |
---|
1231 | // (e.known) e.clashes; |
---|
1232 | // |
---|
1233 | //Known-Vars? e.vars = |
---|
1234 | // <? &Var-Stack> :: e.known-vars, |
---|
1235 | // e.vars $iter { |
---|
1236 | // e.vars : t.var e.rest = |
---|
1237 | // e.known-vars : e t.var e, |
---|
1238 | // e.rest; |
---|
1239 | // } :: e.vars, |
---|
1240 | // e.vars : /*empty*/; |
---|
1241 | |
---|
1242 | Comp-Clashes (e.clashes) s.tail? (v.fails) e.Sentence = |
---|
1243 | // <WriteLN Clashes e.clashes>, |
---|
1244 | /* |
---|
1245 | * Parenthesize each clash, so from now on they can be seen as a sequence |
---|
1246 | * of such terms: (e.temp-tags (e.Re) t.P) |
---|
1247 | */ |
---|
1248 | e.clashes () $iter { |
---|
1249 | e.old-clashes : t.R t.P e.rest = |
---|
1250 | e.rest (e.clashes (<Gener-Label "clash"> &New-Clash-Tags t.R t.P)); |
---|
1251 | } :: e.old-clashes (e.clashes), |
---|
1252 | e.old-clashes : /*empty*/ = |
---|
1253 | |
---|
1254 | /*empty*/ (/*!e.clashes!*/) () $iter { |
---|
1255 | /* |
---|
1256 | * First of all see if we have a clash with all variables of known length |
---|
1257 | * and without length conditions written out. |
---|
1258 | */ |
---|
1259 | e.clashes : e1 (e.t1 Known-length e.t2 (e.Re) (s.dir e.Pe)) e2, |
---|
1260 | <Hard-Exp? e.Re e.Pe> = |
---|
1261 | e.cond |
---|
1262 | (Cond IF ((INFIX "==" (<Length-of e.Re>) (<Length-of e.Pe>)))) |
---|
1263 | (e1 (e.t1 Checked-length e.t2 (e.Re) (s.dir e.Pe)) e2) (e.fail); |
---|
1264 | /* |
---|
1265 | * Next see if we can compute length of some variable. |
---|
1266 | */ |
---|
1267 | e.cond <Find-Var-Length e.clashes> (e.fail); |
---|
1268 | /* |
---|
1269 | * Write out restrictions for the cyclic variables. |
---|
1270 | */ |
---|
1271 | e.cond <Cyclic-Restrictions e.clashes> (e.fail); |
---|
1272 | // <Cyclic-Restrictions e.clashes> :: e.new-cond (e.clashes), |
---|
1273 | // { |
---|
1274 | // e.fail : v = e.cond e.new-cond (Clear-Restricted) (e.clashes) (e.fail); |
---|
1275 | // e.cond e.new-cond (e.clashes) (e.fail); |
---|
1276 | // }; |
---|
1277 | /* |
---|
1278 | * After checking all possible lengthes at the upper level change |
---|
1279 | * <<current_label_if_fail>>. |
---|
1280 | */ |
---|
1281 | e.fail : v = |
---|
1282 | (Contin e.fail) e.cond (Fail e.fail) (Clear-Restricted) (e.clashes) (); |
---|
1283 | /* |
---|
1284 | * For all clashes with known left part check unwatched terms whether they |
---|
1285 | * are symbols or reference terms or not any. |
---|
1286 | */ |
---|
1287 | \? |
---|
1288 | { |
---|
1289 | <Check-Symbols e.clashes> : { |
---|
1290 | v.new-cond (e.new-clashes) s = |
---|
1291 | e.cond (Cond IF (v.new-cond)) (e.new-clashes) (); |
---|
1292 | (e.new-clashes) New = e.cond (e.new-clashes) (); |
---|
1293 | e \! $fail; |
---|
1294 | }; |
---|
1295 | <PrintLN "Check-Symbols: don't know what to do... ;-)">, $fail; |
---|
1296 | }; |
---|
1297 | /* |
---|
1298 | * And then try to compose new clash by dereferencing a part of some one. |
---|
1299 | */ |
---|
1300 | e.cond <Dereference-Subexpr e.clashes> (); |
---|
1301 | /* |
---|
1302 | * If previous doesn't work then compare recursively all known |
---|
1303 | * subexpressions and all unknown repeated subexpressions with |
---|
1304 | * corresponding parts of source. |
---|
1305 | */ |
---|
1306 | <Compare-Subexpr e.clashes> :: e.new-cond (e.asserts) (e.new-clashes) s.new?, |
---|
1307 | \{ |
---|
1308 | e.new-cond : v, { |
---|
1309 | e.asserts : v = |
---|
1310 | e.cond (Assert e.asserts) (Cond IF (e.new-cond)) (e.new-clashes) (); |
---|
1311 | e.cond (Cond IF (e.new-cond)) (e.new-clashes) (); |
---|
1312 | }; |
---|
1313 | e.asserts : v = e.cond (Assert e.asserts) (e.new-clashes) (); |
---|
1314 | s.new? : New = e.cond (e.new-clashes) (); |
---|
1315 | }; |
---|
1316 | /* |
---|
1317 | * Then get first uncatenated source and bring it to the normal |
---|
1318 | * form, i.e. concatenate and parenthesize until it became single |
---|
1319 | * known expression. |
---|
1320 | */ |
---|
1321 | e.cond <Get-Source e.clashes> (); |
---|
1322 | /* |
---|
1323 | * Now it's time to deal with cycles. |
---|
1324 | */ |
---|
1325 | e.cond <Comp-Cyclic e.clashes>; |
---|
1326 | /* |
---|
1327 | * At last initialize all new subexpressions from all clashes. |
---|
1328 | */ |
---|
1329 | e.clashes () $iter { |
---|
1330 | e.clashes : (e t.Re (s.dir e.Pe)) e.rest, |
---|
1331 | e.rest (e.new-cond <Get-Subexprs <Vars e.Pe>>); |
---|
1332 | } :: e.clashes (e.new-cond), |
---|
1333 | e.clashes : /*empty*/ = |
---|
1334 | { |
---|
1335 | e.new-cond : /*empty*/ = e.cond () (); |
---|
1336 | e.cond (Assert e.new-cond) () (); |
---|
1337 | }; |
---|
1338 | } :: e.cond (e.clashes) (e.fail), |
---|
1339 | // <WriteLN CC-Clashes e.clashes>, |
---|
1340 | // <WriteLN CC-Cond e.cond>, |
---|
1341 | e.clashes : /*empty*/ = |
---|
1342 | |
---|
1343 | e.cond () 0 $iter { |
---|
1344 | e.cond : (Contin (CONTINUE t.label)) e.rest = |
---|
1345 | e.rest (e.contin (Comp Continue t.label)) 0; |
---|
1346 | e.cond (e.contin) 1; |
---|
1347 | } :: e.cond (e.contin) s.stop?, |
---|
1348 | s.stop? : 1 = |
---|
1349 | //! <Comp-Sentence () e.Current-Snt e.contin e.Other-Snts> :: e.asail-Snt, |
---|
1350 | <Comp-Sentence s.tail? (v.fails) () e.Sentence> :: e.asail-Snt, |
---|
1351 | e.cond (e.asail-Snt) () $iter { |
---|
1352 | e.cond : e.some (e.last), |
---|
1353 | e.last : { |
---|
1354 | Cond e.condition = |
---|
1355 | e.some ((e.condition e.asail-Snt)) (e.vars); |
---|
1356 | Assert e.assertion = |
---|
1357 | e.some (e.assertion e.asail-Snt) (e.vars); |
---|
1358 | Fail e.fail1 = |
---|
1359 | e.some (e.asail-Snt e.fail1) (e.vars); |
---|
1360 | Restricted t.var = |
---|
1361 | e.some (e.asail-Snt) (e.vars t.var); |
---|
1362 | If-not-restricted t.var e.restr-cond, { |
---|
1363 | e.vars : e t.var e = e.some (e.asail-Snt) (e.vars); |
---|
1364 | e.some e.restr-cond (e.asail-Snt) (e.vars); |
---|
1365 | }; |
---|
1366 | Clear-Restricted = e.some (e.asail-Snt) (); |
---|
1367 | }; |
---|
1368 | } :: e.cond (e.asail-Snt) (e.vars), |
---|
1369 | e.cond : /*empty*/ = |
---|
1370 | e.asail-Snt/* <Comp-Sentence () e.Other-Snts>*/; |
---|
1371 | |
---|
1372 | Find-Var-Length e.clashes = |
---|
1373 | // <WriteLN Find-Var-Length e.clashes>, |
---|
1374 | e.clashes : e1 (e.t1 Unknown-length e.t2 (e.Re) (s.dir e.Pe)) e2 \? |
---|
1375 | <Unknown-Vars e.Pe> :: e.new-Pe (e.Pe-unknown), |
---|
1376 | <Unknown-Vars e.Re> :: e.new-Re (e.Re-unknown), |
---|
1377 | // <Write Unknown>, <Write (e.Re-unknown)>, <WriteLN (e.Pe-unknown)>, |
---|
1378 | e.Re-unknown e.Pe-unknown : { |
---|
1379 | /*empty*/ = |
---|
1380 | (e1 (e.t1 Known-length e.t2 (e.Re) (s.dir e.Pe)) e2); |
---|
1381 | (VAR t.name) e.rest, |
---|
1382 | e.rest $iter \{ |
---|
1383 | e.unknown : (VAR t.name) e.rest1 = e.rest1; |
---|
1384 | } :: e.unknown, |
---|
1385 | e.unknown : /*empty*/, |
---|
1386 | <"-" <Length e.Re-unknown> <Length e.Pe-unknown>> : { |
---|
1387 | 0 \! $fail; |
---|
1388 | s.diff, { |
---|
1389 | <"<" (s.diff) (0)> = |
---|
1390 | <"*" s.diff -1> |
---|
1391 | (INFIX "-" (<Length-of e.new-Re>) (<Length-of e.new-Pe>)); |
---|
1392 | <">" (s.diff) (0)> = |
---|
1393 | s.diff |
---|
1394 | (INFIX "-" (<Length-of e.new-Pe>) (<Length-of e.new-Re>)); |
---|
1395 | } :: s.mult e.diff, |
---|
1396 | t.name : (e.QualifiedName), |
---|
1397 | (VAR ("len" e.QualifiedName)) :: t.len-var, |
---|
1398 | { |
---|
1399 | <?? t.name Max> :: e.max = |
---|
1400 | (INFIX "<=" |
---|
1401 | (t.len-var) |
---|
1402 | ((INFIX "*" (s.mult) (e.max))) |
---|
1403 | ); |
---|
1404 | /*empty*/; |
---|
1405 | } :: e.cond, |
---|
1406 | e.cond |
---|
1407 | (INFIX ">=" |
---|
1408 | (t.len-var) |
---|
1409 | ((INFIX "*" (s.mult) (<?? t.name Min>))) |
---|
1410 | ) |
---|
1411 | (NOT (INFIX "%" |
---|
1412 | (t.len-var) |
---|
1413 | (s.mult) |
---|
1414 | )) :: e.cond, |
---|
1415 | <Set-Var t.name (Max) (//(LENGTH (VAR t.name)) |
---|
1416 | (INFIX "/" (t.len-var) (s.mult)) |
---|
1417 | )>, |
---|
1418 | <Set-Var t.name (Min) (<?? t.name Max>)>, |
---|
1419 | <Set-Var t.name (Length) (<?? t.name Max>)>, |
---|
1420 | // <WriteLN Unknown-Num s.mult> = |
---|
1421 | (Restricted (VAR t.name)) |
---|
1422 | (Assert |
---|
1423 | <Declare-Vars "int" t.len-var> |
---|
1424 | (ASSIGN t.len-var e.diff) |
---|
1425 | ) |
---|
1426 | (Cond IF (e.cond)) |
---|
1427 | (<Update-Ties (VAR t.name) e1> |
---|
1428 | (e.t1 Checked-length e.t2 (e.Re) (s.dir e.Pe)) |
---|
1429 | <Update-Ties (VAR t.name) e2>); |
---|
1430 | }; |
---|
1431 | e.unknown \! |
---|
1432 | e.t1 Unknown-length e.t2 : e.t3 Ties e.t4 = |
---|
1433 | e.t1 : t.id e, |
---|
1434 | e.unknown () $iter { |
---|
1435 | e.unknown : (VAR t.name) e.rest, { |
---|
1436 | e.tied : e (VAR t.name) e = e.rest (e.tied); |
---|
1437 | <Entries (VAR t.name) (e.Re)> :: s.Re-ent e.new-Re, |
---|
1438 | <Entries (VAR t.name) (e.Pe)> :: s.Pe-ent e.new-Pe, |
---|
1439 | <"-" s.Re-ent s.Pe-ent> :: s.diff, |
---|
1440 | { |
---|
1441 | s.diff : 0 = e.rest (e.tied (VAR t.name)); |
---|
1442 | { |
---|
1443 | <"<" (s.diff) (0)> = |
---|
1444 | <"*" s.diff -1> (e.new-Re) (e.new-Pe); |
---|
1445 | s.diff (e.new-Pe) (e.new-Re); |
---|
1446 | } :: s.diff (e.plus) (e.minus), |
---|
1447 | ( |
---|
1448 | t.id |
---|
1449 | (<Known-Length-of e.plus>) |
---|
1450 | (<Known-Length-of e.minus>) |
---|
1451 | s.diff |
---|
1452 | ) :: t.tie, |
---|
1453 | { |
---|
1454 | <?? t.name Ties> : { |
---|
1455 | e.c1 (t.id e) e.c2 = e.c1 e.c2; |
---|
1456 | e.ties = e.ties; |
---|
1457 | }; |
---|
1458 | /*empty*/; |
---|
1459 | } :: e.ties, |
---|
1460 | { |
---|
1461 | e.ties : e t.tie e; |
---|
1462 | <Set-Var t.name (Ties) (e.ties t.tie)>; |
---|
1463 | }, |
---|
1464 | e.rest (e.tied (VAR t.name)); |
---|
1465 | }; |
---|
1466 | }; |
---|
1467 | } :: e.unknown (e.tied), |
---|
1468 | e.unknown : /*empty*/ = |
---|
1469 | { |
---|
1470 | e.t3 e.t4 : e Cyclic e = e.t3 e.t4; |
---|
1471 | e.t3 e.t4 Cyclic; |
---|
1472 | } :: e.tags, |
---|
1473 | (e1 (e.tags (e.Re) (s.dir e.Pe)) e2); |
---|
1474 | }; |
---|
1475 | |
---|
1476 | Known-Length-of e.expr = |
---|
1477 | <Unknown-Vars e.expr> :: e.expr (e.vars), |
---|
1478 | <Length-of e.expr> (e.vars); |
---|
1479 | |
---|
1480 | Update-Ties t.var e.clashes = |
---|
1481 | e.clashes () $iter { |
---|
1482 | e.clashes : t.clash e.rest, |
---|
1483 | t.clash : (e.tags (e.Re) (s.dir e.Pe)), |
---|
1484 | { |
---|
1485 | e.tags : e Ties e = e.rest (e.new-clashes t.clash); |
---|
1486 | e.Re e.Pe : e t.var e = |
---|
1487 | e.rest (e.new-clashes (e.tags Ties (e.Re) (s.dir e.Pe))); |
---|
1488 | e.rest (e.new-clashes t.clash); |
---|
1489 | }; |
---|
1490 | } :: e.clashes (e.new-clashes), |
---|
1491 | e.clashes : /*empty*/ = |
---|
1492 | e.new-clashes; |
---|
1493 | |
---|
1494 | Cyclic-Restrictions e.clashes = |
---|
1495 | e.clashes : e1 (e.t1 Cyclic e.t2 (e.Re) (s.dir e.Pe)) e2 = |
---|
1496 | <Unknown-Vars e.Re e.Pe> :: e (e.unknown), |
---|
1497 | e.unknown () $iter { |
---|
1498 | e.unknown : t.var e.rest, |
---|
1499 | t.var : (VAR (e.QualifiedName)), |
---|
1500 | (VAR ("min" e.QualifiedName)) :: t.min-var, |
---|
1501 | <Cyclic-Min t.var> :: e.min, |
---|
1502 | { |
---|
1503 | <Cyclic-Max t.var> :: e.max = |
---|
1504 | e.rest (e.cond (Restricted t.var) (If-not-restricted t.var |
---|
1505 | (Assert |
---|
1506 | <Declare-Vars "int" t.min-var> (ASSIGN t.min-var e.min) |
---|
1507 | ) |
---|
1508 | (Cond IF ((INFIX "<=" (t.min-var) (e.max)))) |
---|
1509 | )); |
---|
1510 | e.rest (e.cond); |
---|
1511 | }; |
---|
1512 | } :: e.unknown (e.cond), |
---|
1513 | e.unknown : /*empty*/ = |
---|
1514 | e.cond (e1 (e.t1 e.t2 (e.Re) (s.dir e.Pe)) e2); |
---|
1515 | |
---|
1516 | Cyclic-Min (VAR t.name) = |
---|
1517 | <?? t.name Ties> () $iter { |
---|
1518 | e.ties : (t (e.plus (e.plus-vars)) (e.minus (e.minus-vars)) s.mult) e.rest, { |
---|
1519 | e.minus-vars () $iter \{ |
---|
1520 | e.minus-vars : t.var e.vars-rest, |
---|
1521 | e.vars-rest (e.minus-maxes <Cyclic-Max t.var>); |
---|
1522 | } :: e.minus-vars (e.minus-maxes), |
---|
1523 | e.minus-vars : /*empty*/ = |
---|
1524 | e.plus-vars () $iter { |
---|
1525 | e.plus-vars : (VAR t.var-name) e.vars-rest = |
---|
1526 | e.vars-rest (e.plus-mins <?? t.var-name Min>); |
---|
1527 | } :: e.plus-vars (e.plus-mins), |
---|
1528 | e.plus-vars : /*empty*/ = |
---|
1529 | e.rest (e.mins ((INFIX "/" |
---|
1530 | ((INFIX "-" (e.plus e.plus-mins) (e.minus e.minus-maxes))) (s.mult) |
---|
1531 | ))); |
---|
1532 | e.rest (e.mins); |
---|
1533 | }; |
---|
1534 | } :: e.ties (e.mins), |
---|
1535 | e.ties : /*empty*/ = |
---|
1536 | (<?? t.name Min>) e.mins :: e.mins, |
---|
1537 | { |
---|
1538 | e.mins : (e.min) = e.min; |
---|
1539 | (MAX e.mins); |
---|
1540 | }; |
---|
1541 | |
---|
1542 | Cyclic-Max (VAR t.name) = |
---|
1543 | <?? t.name Ties> () $iter { |
---|
1544 | e.ties : (t (e.plus (e.plus-vars)) (e.minus (e.minus-vars)) s.mult) e.rest, { |
---|
1545 | e.plus-vars () $iter \{ |
---|
1546 | e.plus-vars : (VAR t.var-name) e.vars-rest, |
---|
1547 | e.vars-rest (e.plus-maxes <?? t.var-name Max>); |
---|
1548 | } :: e.plus-vars (e.plus-maxes), |
---|
1549 | e.plus-vars : /*empty*/ = |
---|
1550 | e.minus-vars () $iter { |
---|
1551 | e.minus-vars : (VAR t.var-name) e.vars-rest = |
---|
1552 | e.vars-rest (e.minus-mins <?? t.var-name Min>); |
---|
1553 | } :: e.minus-vars (e.minus-mins), |
---|
1554 | e.minus-vars : /*empty*/ = |
---|
1555 | e.rest (e.maxes ((INFIX "/" |
---|
1556 | ((INFIX "-" (e.plus e.plus-maxes) (e.minus e.minus-mins))) (s.mult) |
---|
1557 | ))); |
---|
1558 | e.rest (e.maxes); |
---|
1559 | }; |
---|
1560 | } :: e.ties (e.maxes), |
---|
1561 | e.ties : /*empty*/ = |
---|
1562 | { |
---|
1563 | (<?? t.name Max>) e.maxes; |
---|
1564 | e.maxes; |
---|
1565 | } :: e.maxes, |
---|
1566 | { |
---|
1567 | e.maxes : /*empty*/ = $fail; |
---|
1568 | e.maxes : (e.max) = e.max; |
---|
1569 | (MIN e.maxes); |
---|
1570 | }; |
---|
1571 | |
---|
1572 | Check-Symbols e.clashes = |
---|
1573 | e.clashes () () Old $iter { |
---|
1574 | e.clashes : t.clash e.rest, { |
---|
1575 | t.clash : (e.t1 Check-symbols e.t2 (e.Re) (s.dir e.Pe)), |
---|
1576 | e.Re : (VAR t.name), |
---|
1577 | <?? t.name Instantiated> : True = |
---|
1578 | // <Format e.Pe> () () Continue $iter { |
---|
1579 | e.Pe () () Continue $iter { |
---|
1580 | e.format : t.Ft e.Fe = |
---|
1581 | <Length-of e.left> :: e.pos, |
---|
1582 | <Check-Ft t.Ft (e.pos) (1 <Length-of e.Fe>) t.name Left-checks> : { |
---|
1583 | /*empty*/ s.stop??? = /*empty*/ s.stop???; |
---|
1584 | Sym s.stop??? = |
---|
1585 | (Used e.Re) (SYMBOL? e.Re (e.pos)) s.stop???; |
---|
1586 | Ref s.stop??? = |
---|
1587 | (Used e.Re) (NOT (SYMBOL? e.Re (e.pos))) s.stop???; |
---|
1588 | Flat e.len s.stop??? = |
---|
1589 | (Used e.Re) (FLAT-SUBEXPR? e.Re (e.pos) (e.len)) s.stop???; |
---|
1590 | } :: e.Ft-cond s.stop? = |
---|
1591 | e.Fe (e.left t.Ft) (e.new-cond e.Ft-cond) s.stop?; |
---|
1592 | } :: e.format (e.left) (e.new-cond) s.stop?, |
---|
1593 | \{ |
---|
1594 | e.format : /*empty*/ = |
---|
1595 | e.rest (e.cond e.new-cond) |
---|
1596 | (e.new-clashes (e.t1 e.t2 (e.Re) (s.dir e.Pe))) New; |
---|
1597 | s.stop? : Stop = |
---|
1598 | e.format () (e.new-cond) Continue $iter { |
---|
1599 | e.format : e.Fe t.Ft = |
---|
1600 | 1 <Length-of e.right> :: e.pos, |
---|
1601 | <Check-Ft t.Ft (e.pos) () t.name Right-checks> |
---|
1602 | :: e.Ft-cond s.stop?, |
---|
1603 | e.Ft-cond : { |
---|
1604 | /*empty*/ = /*empty*/; |
---|
1605 | Sym = |
---|
1606 | (Used e.Re) |
---|
1607 | (SYMBOL? e.Re ( |
---|
1608 | (INFIX "-" (<Length-of e.Re>) (e.pos)) |
---|
1609 | )); |
---|
1610 | Ref = |
---|
1611 | (Used e.Re) |
---|
1612 | (NOT (SYMBOL? e.Re ( |
---|
1613 | (INFIX "-" (<Length-of e.Re>) (e.pos)) |
---|
1614 | ))); |
---|
1615 | Flat e.len s.stop??? = |
---|
1616 | (Used e.Re) |
---|
1617 | (FLAT-SUBEXPR? e.Re ( |
---|
1618 | (INFIX "-" (<Length-of e.Re>) (e.pos)) |
---|
1619 | ) e.len) s.stop???; |
---|
1620 | } :: e.Ft-cond, |
---|
1621 | e.Fe (t.Ft e.right) (e.new-cond e.Ft-cond) s.stop?; |
---|
1622 | } :: e.format (e.right) (e.new-cond) s.stop?, |
---|
1623 | s.stop? : Stop = |
---|
1624 | e.rest (e.cond e.new-cond) (e.new-clashes t.clash) s.new?; |
---|
1625 | }; |
---|
1626 | e.rest (e.cond) (e.new-clashes t.clash) s.new?; |
---|
1627 | }; |
---|
1628 | } :: e.clashes (e.cond) (e.new-clashes) s.new?, |
---|
1629 | // <WriteLN Check-Symbols e.clashes (e.cond) (e.new-clashes) s.new?>, |
---|
1630 | e.clashes : /*empty*/ = |
---|
1631 | e.cond (e.new-clashes) s.new?; |
---|
1632 | |
---|
1633 | Check-Ft t.Ft (e.pos) (e.right-pos) t.name s.dir, t.Ft : { |
---|
1634 | s.ObjectSymbol, { |
---|
1635 | <?? t.name s.dir> : \{ |
---|
1636 | e (e.pos Sym) e = /*empty*/ Continue; |
---|
1637 | e (e.pos (Ref e)) e = $fail; |
---|
1638 | }; |
---|
1639 | s.dir : Left-checks, |
---|
1640 | <?? t.name Right-checks> : \{ |
---|
1641 | e (e.right-pos Sym) e = /*empty*/ Continue; |
---|
1642 | e (e.right-pos (Ref e)) e = $fail; |
---|
1643 | }; |
---|
1644 | <Set-Var t.name (s.dir) (<?? t.name s.dir> (e.pos Sym))> = Sym Continue; |
---|
1645 | }; |
---|
1646 | (PAREN e.expr), { |
---|
1647 | <?? t.name s.dir> : \{ |
---|
1648 | e (e.pos (Ref e)) e = /*empty*/ Continue; |
---|
1649 | e (e.pos Sym) e = $fail; |
---|
1650 | }; |
---|
1651 | s.dir : Left-checks, |
---|
1652 | <?? t.name Right-checks> : \{ |
---|
1653 | e (e.right-pos (Ref e)) e = /*empty*/ Continue; |
---|
1654 | e (e.right-pos Sym) e = $fail; |
---|
1655 | }; |
---|
1656 | s.dir : { |
---|
1657 | Left-checks = "lderef"; |
---|
1658 | Right-checks = "rderef"; |
---|
1659 | } :: s.name-dir, |
---|
1660 | t.name : (e.QualifiedName), |
---|
1661 | <Gener-Label s.name-dir e.QualifiedName> :: t.ref-name, |
---|
1662 | // <Declare-Vars "Expr" (VAR t.ref-name)> : e, |
---|
1663 | <Set-Var t.name (s.dir) (<?? t.name s.dir> (e.pos (Ref t.ref-name)))> = |
---|
1664 | Ref Continue; |
---|
1665 | }; |
---|
1666 | //! (VAR t.Ft-name), { |
---|
1667 | (s t.Ft-name), { // STUB! |
---|
1668 | <Hard-Exp? t.Ft>, { |
---|
1669 | <?? t.Ft-name Flat> : True, { |
---|
1670 | <?? t.Ft-name Length> : 1, { |
---|
1671 | <?? t.name s.dir> : \{ |
---|
1672 | e (e.pos Sym) e = /*empty*/ Continue; |
---|
1673 | e (e.pos (Ref e)) e = $fail; |
---|
1674 | }; |
---|
1675 | s.dir : Left-checks, |
---|
1676 | <?? t.name Right-checks> : \{ |
---|
1677 | e (e.right-pos Sym) e = /*empty*/ Continue; |
---|
1678 | e (e.right-pos (Ref e)) e = $fail; |
---|
1679 | }; |
---|
1680 | // <?? t.Ft-name Instantiated> : True = |
---|
1681 | // /*empty*/ Continue; |
---|
1682 | <Set-Var t.name (s.dir) (<?? t.name s.dir> (e.pos Sym))> = |
---|
1683 | Sym Continue; |
---|
1684 | }; |
---|
1685 | <Set-Var t.name (s.dir) (<?? t.name s.dir> (e.pos Flat))> = |
---|
1686 | Flat <Length-of t.Ft> Continue; |
---|
1687 | }; |
---|
1688 | /*empty*/ Continue; |
---|
1689 | }; |
---|
1690 | /*empty*/ Stop; |
---|
1691 | }; |
---|
1692 | }; |
---|
1693 | |
---|
1694 | Dereference-Subexpr e.clashes = |
---|
1695 | e.clashes : e1 (e.t1 Dereference e.t2 (e.Re) (s.dir e.Pe)) e2 \? |
---|
1696 | e.Re : (VAR t.name), |
---|
1697 | <?? t.name Instantiated> : True, |
---|
1698 | // <WriteLN Dereference!!! t.name <?? t.name Right-checks>>, |
---|
1699 | // <Format e.Pe> : e.f1 t.Ft e.f2 \? |
---|
1700 | e.Pe : e.f1 t.Ft e.f2 \? |
---|
1701 | \{ |
---|
1702 | t.Ft : (PAREN e.expr), |
---|
1703 | <Length-of e.f1> :: e.pos, |
---|
1704 | { |
---|
1705 | <?? t.name Left-checks> : e (e.pos (Ref t.ref-name)) e \! |
---|
1706 | # \{ <?? t.ref-name Instantiated> : True; } = |
---|
1707 | <Declare-Vars "Expr" (VAR t.ref-name)> : e, |
---|
1708 | <Instantiate-Vars (VAR t.ref-name)>, |
---|
1709 | (Assert (DEREF (VAR t.ref-name) e.Re (e.pos))) :: e.cond, |
---|
1710 | (e.t1 Dereference e.t2 (e.Re) (s.dir e.Pe)) :: t.old-clash, |
---|
1711 | { |
---|
1712 | e.t1 e.t2 : e Without-object-symbols e = Without-object-symbols; |
---|
1713 | /*empty*/; |
---|
1714 | } :: e.wos, |
---|
1715 | (<Gener-Label "clash"> &New-Clash-Tags e.wos |
---|
1716 | ((VAR t.ref-name)) (s.dir e.expr) |
---|
1717 | ) :: t.new-clash, |
---|
1718 | s.dir : { |
---|
1719 | LEFT = |
---|
1720 | e.cond (e1 t.new-clash t.old-clash e2); |
---|
1721 | RIGHT = |
---|
1722 | e.cond (e1 t.old-clash t.new-clash e2); |
---|
1723 | }; |
---|
1724 | t.Ft e.f2 : $r e.f3 (PAREN e.expr1) e.f4 \? |
---|
1725 | 1 <Length-of e.f4> :: e.pos, |
---|
1726 | { |
---|
1727 | <?? t.name Right-checks> : e (e.pos (Ref t.ref-name)) e \! |
---|
1728 | # \{ <?? t.ref-name Instantiated> : True; } = |
---|
1729 | <Declare-Vars "Expr" (VAR t.ref-name)> : e, |
---|
1730 | <Instantiate-Vars (VAR t.ref-name)>, |
---|
1731 | (Assert |
---|
1732 | (DEREF (VAR t.ref-name) e.Re ( |
---|
1733 | (INFIX "-" (<Length-of e.Re>) (e.pos)) |
---|
1734 | )) |
---|
1735 | ) :: e.cond, |
---|
1736 | (e.t1 Dereference e.t2 (e.Re) (s.dir e.Pe)) :: t.old-clash, |
---|
1737 | { |
---|
1738 | e.t1 e.t2 : e Without-object-symbols e = |
---|
1739 | Without-object-symbols; |
---|
1740 | /*empty*/; |
---|
1741 | } :: e.wos, |
---|
1742 | (<Gener-Label "clash"> &New-Clash-Tags e.wos |
---|
1743 | ((VAR t.ref-name)) (s.dir e.expr1) |
---|
1744 | ) :: t.new-clash, |
---|
1745 | s.dir : { |
---|
1746 | RIGHT = |
---|
1747 | e.cond (e1 t.new-clash t.old-clash e2); |
---|
1748 | LEFT = |
---|
1749 | e.cond (e1 t.old-clash t.new-clash e2); |
---|
1750 | }; |
---|
1751 | \!\!\! $fail; |
---|
1752 | }; |
---|
1753 | \!\! $fail; |
---|
1754 | }; |
---|
1755 | e.f2 : /*empty*/ = |
---|
1756 | (e1 (e.t1 e.t2 (e.Re) (s.dir e.Pe)) e2); |
---|
1757 | }; |
---|
1758 | |
---|
1759 | Compare-Subexpr e.clashes = |
---|
1760 | e.clashes () () () Old $iter e.clashes : { |
---|
1761 | (e.t1 Compare e.t2 (e.Re) (s.dir e.Pe)) e.rest, |
---|
1762 | e.Re : (VAR t.name), |
---|
1763 | <?? t.name Instantiated> : True = |
---|
1764 | { |
---|
1765 | e.t1 e.t2 : e Without-object-symbols e = |
---|
1766 | /*empty*/ (e.t2) (e.Re) (e.Pe); |
---|
1767 | <Get-Static-Exprs e.Re> :: e.Re (e.Re-decls), |
---|
1768 | <Get-Static-Exprs e.Pe> :: e.Pe (e.Pe-decls) = |
---|
1769 | e.Re-decls e.Pe-decls (e.t2 Without-object-symbols) (e.Re) (e.Pe); |
---|
1770 | } :: e.new-asserts (e.t2) (e.Re) (e.Pe), |
---|
1771 | e.Pe () () Continue $iter { |
---|
1772 | e.format : t.Ft e.Fe, |
---|
1773 | <Length-of e.left> :: e.pos, |
---|
1774 | <Length-of t.Ft> :: e.len, |
---|
1775 | <Length-of e.Fe> :: e.right-pos, |
---|
1776 | { |
---|
1777 | \{ |
---|
1778 | <?? t.name Left-compare> : |
---|
1779 | e (t.Ft Left (0) (e.pos) e.len) e; |
---|
1780 | <?? t.name Right-compare> : |
---|
1781 | e (t.Ft Left (0) (e.right-pos) e.len) e; |
---|
1782 | } = |
---|
1783 | /*empty*/ Continue; |
---|
1784 | <Compare-Ft t.Ft> : { |
---|
1785 | /*empty*/ s.stop??? = /*empty*/ s.stop???; |
---|
1786 | e.compare s.eq = |
---|
1787 | // <WriteLN Compare e.compare s.eq>, |
---|
1788 | t.Ft : (VAR t.Ft-name), |
---|
1789 | <Set-Var t.name (Left-compare) (<?? t.name Left-compare> |
---|
1790 | (t.Ft Left (0) (e.pos) e.len))>, |
---|
1791 | <Set-Var t.Ft-name (Left-compare) |
---|
1792 | (<?? t.Ft-name Left-compare> |
---|
1793 | (e.Re Left (e.pos) (0) e.len))>, |
---|
1794 | e.compare : { |
---|
1795 | Empty = /*empty*/ Continue; |
---|
1796 | Instantiated = |
---|
1797 | (t.Ft) (0) (e.len) :: e.sub1, |
---|
1798 | (e.Re) (e.pos) (e.len) :: e.sub2, |
---|
1799 | { s.eq : EQ = 0; 1; } :: s.R, |
---|
1800 | (Used t.Ft e.Re) |
---|
1801 | (s.eq <Middle 0 s.R e.sub1> e.sub2) Continue; |
---|
1802 | // (s.eq ((FIRST t.Ft)) ((LAST t.Ft)) |
---|
1803 | // ((FIRST e.Re) e.pos) ((FIRST e.Re) e.pos e.len) |
---|
1804 | // ) Continue; |
---|
1805 | (t.var s.dir1 (e.pos1) (0) e.len), s.dir1 : { |
---|
1806 | Left = |
---|
1807 | (t.var) (e.pos1) (e.len) :: e.sub1, |
---|
1808 | (e.Re) (e.pos) (e.len) :: e.sub2, |
---|
1809 | { s.eq : EQ = 0; 1; } :: s.R, |
---|
1810 | (Used t.var e.Re) |
---|
1811 | (s.eq <Middle 0 s.R e.sub1> e.sub2) Continue; |
---|
1812 | // (s.eq ((FIRST t.var) e.pos1) |
---|
1813 | // ((FIRST t.var) e.pos1 e.len) |
---|
1814 | // ((FIRST e.Re) e.pos) |
---|
1815 | // ((FIRST e.Re) e.pos e.len) |
---|
1816 | // ) Continue; |
---|
1817 | Right = |
---|
1818 | (t.var) |
---|
1819 | ((INFIX "-" ((LENGTH t.var)) (e.pos1) (e.len))) |
---|
1820 | (e.len) :: e.sub1, |
---|
1821 | (e.Re) (e.pos) (e.len) :: e.sub2, |
---|
1822 | { s.eq : EQ = 0; 1; } :: s.R, |
---|
1823 | (Used t.var e.Re) |
---|
1824 | (s.eq <Middle 0 s.R e.sub1> e.sub2) Continue; |
---|
1825 | // (s.eq |
---|
1826 | // ((INFIX "-" |
---|
1827 | // ((LAST t.var)) (e.pos1) (e.len)) |
---|
1828 | // ) |
---|
1829 | // ((INFIX "-" ((LAST t.var)) (e.pos1))) |
---|
1830 | // ((FIRST e.Re) e.pos) |
---|
1831 | // ((FIRST e.Re) e.pos e.len) |
---|
1832 | // ) Continue; |
---|
1833 | // <Set-Var t.name Left-compare |
---|
1834 | // <?? t.name Left-compare> |
---|
1835 | // (t.name1 s.dir (e.pos1) (e.pos) e.len) |
---|
1836 | }; |
---|
1837 | }; |
---|
1838 | }; |
---|
1839 | } :: e.Ft-cond s.stop? = |
---|
1840 | e.Fe (e.left t.Ft) (e.new-cond e.Ft-cond) s.stop?; |
---|
1841 | } :: e.format (e.left) (e.new-cond) s.stop?, |
---|
1842 | \{ |
---|
1843 | e.format : /*empty*/ = |
---|
1844 | e.rest (e.cond e.new-cond) (e.new-asserts) |
---|
1845 | (e.new-clashes (e.t1 e.t2 (e.Re) (s.dir e.Pe))) New; |
---|
1846 | s.stop? : Stop = e.format () (e.new-cond) Continue $iter { |
---|
1847 | e.format : e.Fe t.Ft, |
---|
1848 | <Length-of e.right> :: e.pos, |
---|
1849 | <Length-of t.Ft> :: e.len, |
---|
1850 | { |
---|
1851 | <?? t.name Right-compare> : e (t.Ft Left (0) (e.pos) e.len) e = |
---|
1852 | /*empty*/ Continue; |
---|
1853 | <Compare-Ft t.Ft> : { |
---|
1854 | /*empty*/ s.stop??? = /*empty*/ s.stop???; |
---|
1855 | e.compare s.eq = |
---|
1856 | t.Ft : (VAR t.Ft-name), |
---|
1857 | <Set-Var t.name (Right-compare) |
---|
1858 | (<?? t.name Right-compare> |
---|
1859 | (t.Ft Left (0) (e.pos) e.len))>, |
---|
1860 | <Set-Var t.Ft-name (Left-compare) |
---|
1861 | (<?? t.Ft-name Left-compare> |
---|
1862 | (e.Re Right (e.pos) (0) e.len))>, |
---|
1863 | e.compare : { |
---|
1864 | Empty = /*empty*/ Continue; |
---|
1865 | Instantiated = |
---|
1866 | (t.Ft) (0) (e.len) :: e.sub1, |
---|
1867 | (e.Re) |
---|
1868 | ((INFIX "-" ((LENGTH e.Re)) (e.pos) (e.len))) |
---|
1869 | (e.len) :: e.sub2, |
---|
1870 | { s.eq : EQ = 0; 1; } :: s.R, |
---|
1871 | (Used t.Ft e.Re) |
---|
1872 | (s.eq <Middle 0 s.R e.sub1> e.sub2) Continue; |
---|
1873 | // (s.eq ((FIRST t.Ft)) ((LAST t.Ft)) |
---|
1874 | // ((INFIX "-" ((LAST e.Re)) (e.pos) (e.len))) |
---|
1875 | // ((INFIX "-" ((LAST e.Re)) (e.pos))) |
---|
1876 | // ) Continue; |
---|
1877 | (t.var s.dir1 (e.pos1) (0) e.len), s.dir1 : { |
---|
1878 | Left = |
---|
1879 | (t.var) (e.pos1) (e.len) :: e.sub1, |
---|
1880 | (e.Re) |
---|
1881 | ((INFIX "-" |
---|
1882 | ((LENGTH e.Re)) (e.pos) (e.len) |
---|
1883 | )) (e.len) :: e.sub2, |
---|
1884 | { s.eq : EQ = 0; 1; } :: s.R, |
---|
1885 | (Used t.var e.Re) |
---|
1886 | (s.eq <Middle 0 s.R e.sub1> e.sub2) |
---|
1887 | Continue; |
---|
1888 | // (s.eq ((FIRST t.var) e.pos1) |
---|
1889 | // ((FIRST t.var) e.pos1 e.len) |
---|
1890 | // ((INFIX "-" |
---|
1891 | // ((LAST e.Re)) (e.pos) (e.len) |
---|
1892 | // )) |
---|
1893 | // ((INFIX "-" ((LAST e.Re)) (e.pos))) |
---|
1894 | // ) Continue; |
---|
1895 | Right = |
---|
1896 | (t.var) |
---|
1897 | ((INFIX "-" |
---|
1898 | ((LENGTH t.var)) (e.pos1) (e.len) |
---|
1899 | )) (e.len) :: e.sub1, |
---|
1900 | (e.Re) |
---|
1901 | ((INFIX "-" |
---|
1902 | ((LENGTH e.Re)) (e.pos) (e.len) |
---|
1903 | )) (e.len) :: e.sub2, |
---|
1904 | { s.eq : EQ = 0; 1; } :: s.R, |
---|
1905 | (Used t.var e.Re) |
---|
1906 | (s.eq <Middle 0 s.R e.sub1> e.sub2) |
---|
1907 | Continue; |
---|
1908 | // (s.eq |
---|
1909 | // ((INFIX "-" |
---|
1910 | // ((LAST t.var)) (e.pos1) (e.len) |
---|
1911 | // )) |
---|
1912 | // ((INFIX "-" ((LAST t.var)) (e.pos1))) |
---|
1913 | // ((INFIX "-" |
---|
1914 | // ((LAST e.Re)) (e.pos) (e.len) |
---|
1915 | // )) |
---|
1916 | // ((INFIX "-" ((LAST e.Re)) (e.pos))) |
---|
1917 | // ) Continue; |
---|
1918 | }; |
---|
1919 | }; |
---|
1920 | }; |
---|
1921 | } :: e.Ft-cond s.stop? = |
---|
1922 | e.Fe (t.Ft e.right) (e.new-cond e.Ft-cond) s.stop?; |
---|
1923 | } :: e.format (e.right) (e.new-cond) s.stop?, |
---|
1924 | s.stop? : Stop = |
---|
1925 | e.rest (e.cond e.new-cond) (e.new-asserts) |
---|
1926 | (e.new-clashes (e.t1 Compare e.t2 (e.Re) (s.dir e.Pe))) s.new?; |
---|
1927 | }; |
---|
1928 | t.clash e.rest = e.rest (e.cond) (e.asserts) (e.new-clashes t.clash) s.new?; |
---|
1929 | } :: e.clashes (e.cond) (e.asserts) (e.new-clashes) s.new?, |
---|
1930 | // <WriteLN Compare-Subexpr e.clashes (e.cond) (e.asserts) (e.new-clashes) s.new?>, |
---|
1931 | e.clashes : /*empty*/ = |
---|
1932 | e.cond (e.asserts) (e.new-clashes) s.new?; |
---|
1933 | |
---|
1934 | Compare-Ft { |
---|
1935 | s.ObjectSymbol = |
---|
1936 | <PrintLN "Compare-Ft: can't compare object symbols!">, $fail; |
---|
1937 | (PAREN e.expr) = |
---|
1938 | /*empty*/ Continue; |
---|
1939 | //! (VAR t.name), { |
---|
1940 | (s t.name), { // STUB! |
---|
1941 | <Hard-Exp? (VAR t.name)>, { |
---|
1942 | <?? t.name Instantiated> : True = Instantiated; |
---|
1943 | <?? t.name Left-compare> : { |
---|
1944 | t.compare e = t.compare; |
---|
1945 | /*empty*/ = Empty; |
---|
1946 | }; |
---|
1947 | } :: e.compare, |
---|
1948 | { |
---|
1949 | <?? t.name Flat> : True, |
---|
1950 | <?? t.name Length> : 1 = FLAT-EQ; |
---|
1951 | EQ; |
---|
1952 | } :: s.eq = |
---|
1953 | e.compare s.eq; |
---|
1954 | /*empty*/ Stop; |
---|
1955 | }; |
---|
1956 | }; |
---|
1957 | |
---|
1958 | Get-Source e.clashes = |
---|
1959 | e.clashes : e1 (e.tags (e.Re) (s.dir e.Pe)) e2, |
---|
1960 | \{ |
---|
1961 | /* |
---|
1962 | * If source is an instantiated variable then go to the next clash. |
---|
1963 | */ |
---|
1964 | e.Re : (VAR t.name), |
---|
1965 | <?? t.name Instantiated> : True = $fail; |
---|
1966 | /* |
---|
1967 | * If in source there is unknown variable then we can't compute it, so |
---|
1968 | * go to the next clash. |
---|
1969 | */ |
---|
1970 | e.Re $iter e.Re : { |
---|
1971 | (VAR t.name) e.rest = |
---|
1972 | \{ |
---|
1973 | <?? t.name Instantiated> : True; |
---|
1974 | <?? t.name Left-compare> : v; |
---|
1975 | }, e.rest; |
---|
1976 | t e.rest = e.rest; |
---|
1977 | } :: e.Re, |
---|
1978 | e.Re : /*empty*/; |
---|
1979 | } = |
---|
1980 | // <WriteLN Get-Source (e.tags (e.Re) (s.dir e.Pe))>, |
---|
1981 | { |
---|
1982 | e.Re : /*empty*/ = |
---|
1983 | <Store-Vars (EVAR ("empty" 0))> : t.empty, |
---|
1984 | <Set-Var ("empty") (Instantiated) (True)>, |
---|
1985 | () () (e.tags (t.empty) (s.dir e.Pe)); |
---|
1986 | e.Re : (VAR t.name) = |
---|
1987 | (e.Re) () (e.tags (e.Re) (s.dir e.Pe)); |
---|
1988 | { |
---|
1989 | e.tags : e Without-object-symbols e = |
---|
1990 | /*empty*/ (e.tags (e.Re) (s.dir e.Pe)); |
---|
1991 | <Get-Static-Exprs e.Re> :: e.Re (e.Re-decls), |
---|
1992 | <Get-Static-Exprs e.Pe> :: e.Pe (e.Pe-decls) = |
---|
1993 | e.Re-decls e.Pe-decls (e.tags Without-object-symbols (e.Re) (s.dir e.Pe)); |
---|
1994 | } :: e.asserts (e.tags (e.Re) (s.dir e.Pe)), { |
---|
1995 | e.Re : (VAR t.name) = |
---|
1996 | () (e.asserts) (e.tags (e.Re) (s.dir e.Pe)); |
---|
1997 | <Compose-Expr e.Re> :: e.compose (e.not-inst) s.flat?, |
---|
1998 | <Gener-Label "compose"> :: t.name, |
---|
1999 | <Declare-Vars "Expr" (VAR t.name)> :: e.decl, |
---|
2000 | <Instantiate-Vars (VAR t.name)>, |
---|
2001 | { |
---|
2002 | s.flat? : 0 = <Set-Var t.name (Flat) (True)>;; |
---|
2003 | }, |
---|
2004 | <Set-Var t.name (Length) (<Length-of e.Re>)>, |
---|
2005 | <Set-Var t.name (Format) (<Format-Exp e.Re>)> = |
---|
2006 | (e.not-inst) (e.asserts e.decl (ASSIGN (VAR t.name) e.compose)) |
---|
2007 | (e.tags ((VAR t.name)) (s.dir e.Pe)); |
---|
2008 | }; |
---|
2009 | } :: (e.not-inst) (e.decl) t.clash, |
---|
2010 | (Assert <Get-Subexprs e.not-inst> e.decl) (e1 t.clash e2); |
---|
2011 | |
---|
2012 | Compose-Expr e.Re = |
---|
2013 | e.Re () () 0 $iter { |
---|
2014 | e.Re : t.Rt e.rest, t.Rt : { |
---|
2015 | s.ObjectSymbol = |
---|
2016 | <PrintLN "Compose-Expr: can't deal with object symbols!">, $fail; |
---|
2017 | (PAREN e.expr) = |
---|
2018 | <Compose-Expr e.expr> :: e.expr (e.new-not-inst) s, |
---|
2019 | (PAREN e.expr) (e.new-not-inst) 1; |
---|
2020 | (VAR t.name) = |
---|
2021 | { |
---|
2022 | <?? t.name Instantiated> : True = /*empty*/; |
---|
2023 | t.Rt; |
---|
2024 | } :: e.new-not-inst, |
---|
2025 | { |
---|
2026 | <?? t.name Flat> : True = 0; |
---|
2027 | 1; |
---|
2028 | } :: s.new-flat?, |
---|
2029 | (Used t.Rt) t.Rt (e.new-not-inst) s.new-flat?; |
---|
2030 | t = t.Rt () 0; // STUB! |
---|
2031 | } :: e.new-compose (e.new-not-inst) s.new-flat? = |
---|
2032 | e.rest (e.compose e.new-compose) (e.not-inst e.new-not-inst) |
---|
2033 | <"+" s.flat? s.new-flat?>; |
---|
2034 | } :: e.Re (e.compose) (e.not-inst) s.flat?, |
---|
2035 | e.Re : /*empty*/ = |
---|
2036 | e.compose (e.not-inst) s.flat?; |
---|
2037 | |
---|
2038 | Comp-Cyclic e.clashes = |
---|
2039 | <WriteLN ??? e.clashes>, |
---|
2040 | e.clashes : e1 (e.t1 Unknown-length e.t2 (e.Re) (s.dir e.Pe)) e2 = |
---|
2041 | e.Re : (VAR (e.QualifiedName)), |
---|
2042 | <Split-Hard-Left e.Pe> :: e.left-hard, |
---|
2043 | <Split-Hard-Right e.Pe> :: e.right-hard, |
---|
2044 | e.Pe : e.left-hard e.Cycle e.right-hard, |
---|
2045 | { |
---|
2046 | e.left-hard e.right-hard : /*empty*/ = /*empty*/ (e.QualifiedName) (); |
---|
2047 | <Gener-Label "ref" e.QualifiedName> :: t.name, |
---|
2048 | t.name : (e.CycleName), |
---|
2049 | <Declare-Vars "Expr" (VAR t.name)> : e, |
---|
2050 | <Instantiate-Vars (VAR t.name)>, |
---|
2051 | <Set-Var t.name (Format) (<Format-Exp e.Cycle>)>, |
---|
2052 | (INFIX "-" (<Length-of e.Re>) (<Length-of e.right-hard>)) :: e.len, |
---|
2053 | (Used e.Re) |
---|
2054 | (SUBEXPR (VAR t.name) e.Re (<Length-of e.left-hard>) (e.len)) :: e.decl, |
---|
2055 | <Set-Var t.name (Left-compare) |
---|
2056 | ((e.Re Left (<Length-of e.left-hard>) (0) <Length-of (VAR t.name)>))>, |
---|
2057 | <Set-Var (e.QualifiedName) (Left-compare) (( |
---|
2058 | (VAR t.name) Left (0) (<Length-of e.left-hard>) <Length-of (VAR t.name)> |
---|
2059 | ))> = |
---|
2060 | (e.t1 Checked-length e.t2 (e.Re) (s.dir e.left-hard (VAR t.name) e.right-hard)) |
---|
2061 | (e.CycleName) (e.decl); |
---|
2062 | } :: e.old-clash (e.CycleName) (e.decl), |
---|
2063 | (VAR (e.CycleName)) :: t.var, |
---|
2064 | <Gener-Label L "For" "Break"> :: t.break-label, |
---|
2065 | <Gener-Label L "For" "Cont"> :: t.cont-label, |
---|
2066 | s.dir : { |
---|
2067 | LEFT = |
---|
2068 | <WriteLN XXXXX e.Cycle>, |
---|
2069 | e.Cycle : t.var-e1 e.rest, |
---|
2070 | //! t.var-e1 : (VAR (e.SplitName)), |
---|
2071 | t.var-e1 : (s (e.SplitName)), //STUB! |
---|
2072 | { |
---|
2073 | // e.rest : t.var-e2 = t.var-e2; |
---|
2074 | (VAR <Gener-Label "lsplit" e.CycleName>); |
---|
2075 | } :: t.var-e2, |
---|
2076 | <Declare-Vars "Expr" t.var-e2> : e, |
---|
2077 | //! <Instantiate-Vars t.var-e1 t.var-e2> |
---|
2078 | (Assert |
---|
2079 | e.decl |
---|
2080 | (LSPLIT t.var ((VAR ("min" e.SplitName))) t.var-e1 t.var-e2) |
---|
2081 | ) |
---|
2082 | (Cond LABEL t.break-label) |
---|
2083 | (Cond FOR (t.cont-label) () ((INC-ITER t.var))) |
---|
2084 | (Fail (BREAK t.break-label)) |
---|
2085 | (Clear-Restricted) |
---|
2086 | (<Update-Ties t.var-e2 <Update-Ties t.var-e1 e1>> |
---|
2087 | e.old-clash |
---|
2088 | (<Gener-Label "clash"> &New-Clash-Tags (t.var-e2) (s.dir e.rest)) |
---|
2089 | <Update-Ties t.var-e2 <Update-Ties t.var-e1 e2>>) |
---|
2090 | ((CONTINUE t.cont-label)); |
---|
2091 | RIGHT = |
---|
2092 | e.Cycle : e.rest t.var-e2, |
---|
2093 | t.var-e2 : (VAR (e.SplitName)), |
---|
2094 | { |
---|
2095 | // e.rest : t.var-e2 = t.var-e2; |
---|
2096 | (VAR <Gener-Label "lsplit" e.CycleName>); |
---|
2097 | } :: t.var-e1, |
---|
2098 | <Declare-Vars "Expr" t.var-e1> : e, |
---|
2099 | <Instantiate-Vars t.var-e1 t.var-e2> |
---|
2100 | (Assert |
---|
2101 | e.decl |
---|
2102 | (RSPLIT t.var ((VAR ("min" e.SplitName))) t.var-e1 t.var-e2) |
---|
2103 | ) |
---|
2104 | (Cond LABEL t.break-label) |
---|
2105 | (Cond FOR (t.cont-label) () ((INC-ITER t.var))) |
---|
2106 | (Fail (BREAK t.break-label)) |
---|
2107 | (Clear-Restricted) |
---|
2108 | (<Update-Ties t.var-e2 <Update-Ties t.var-e1 e1>> |
---|
2109 | e.old-clash |
---|
2110 | (<Gener-Label "clash"> &New-Clash-Tags (t.var-e1) (s.dir e.rest)) |
---|
2111 | <Update-Ties t.var-e2 <Update-Ties t.var-e1 e2>>) |
---|
2112 | ((CONTINUE t.cont-label)); |
---|
2113 | }; |
---|
2114 | |
---|
2115 | Get-Subexprs e.vars = |
---|
2116 | // <WriteLN Get-Subexprs e.vars>, |
---|
2117 | e.vars () $iter { |
---|
2118 | e.vars : (VAR t.name) e.rest, |
---|
2119 | # \{ <?? t.name Instantiated> : True; }, |
---|
2120 | <?? t.name Left-compare> : (t.var s.dir (e.pos) (0) e.len) e = |
---|
2121 | <Instantiate-Vars (VAR t.name)>, |
---|
2122 | <Declare-Vars "Expr" (VAR t.name)> : e, |
---|
2123 | { |
---|
2124 | s.dir : Right = |
---|
2125 | (INFIX "-" (<Length-of t.var>) (e.pos e.len)); |
---|
2126 | e.pos; |
---|
2127 | } :: e.pos, |
---|
2128 | e.rest (e.decls (Used t.var) (SUBEXPR (VAR t.name) t.var (e.pos) (e.len))); |
---|
2129 | // STUB: |
---|
2130 | e.vars : t e.rest = e.rest (e.decls); |
---|
2131 | } :: e.vars (e.decls), |
---|
2132 | e.vars : /*empty*/ = |
---|
2133 | e.decls; |
---|
2134 | |
---|
2135 | /* |
---|
2136 | * Returns those parts of e.expr which lengthes are known. Also returns a list |
---|
2137 | * of variables with unknown lengthes. |
---|
2138 | */ |
---|
2139 | Unknown-Vars e.expr = |
---|
2140 | e.expr () () $iter { |
---|
2141 | e.expr : t.first e.rest, { |
---|
2142 | t.first : (VAR t.name), { |
---|
2143 | <?? t.name Instantiated> : True = |
---|
2144 | e.new-expr t.first (e.unknown); |
---|
2145 | <?? t.name Max> :: e.max, <?? t.name Min> : e.max = |
---|
2146 | e.new-expr t.first (e.unknown); |
---|
2147 | e.new-expr (e.unknown t.first); |
---|
2148 | }; |
---|
2149 | e.new-expr t.first (e.unknown); |
---|
2150 | } :: e.new-expr (e.unknown) = |
---|
2151 | e.rest (e.new-expr) (e.unknown); |
---|
2152 | } :: e.expr (e.new-expr) (e.unknown), |
---|
2153 | e.expr : /*empty*/ = |
---|
2154 | e.new-expr (e.unknown); |
---|
2155 | |
---|
2156 | Split-Hard-Left e.expr = |
---|
2157 | e.expr () $iter { |
---|
2158 | e.expr : t.Pt e.rest, { |
---|
2159 | <Hard-Exp? t.Pt> = e.rest (e.hard t.Pt); |
---|
2160 | (e.hard); |
---|
2161 | }; |
---|
2162 | } :: e.expr (e.hard), |
---|
2163 | e.expr : /*empty*/ = |
---|
2164 | e.hard; |
---|
2165 | |
---|
2166 | Split-Hard-Right e.expr = |
---|
2167 | e.expr () $iter { |
---|
2168 | e.expr : e.some t.Pt, { |
---|
2169 | <Hard-Exp? t.Pt> = e.some (t.Pt e.hard); |
---|
2170 | (e.hard); |
---|
2171 | }; |
---|
2172 | } :: e.expr (e.hard), |
---|
2173 | e.expr : /*empty*/ = |
---|
2174 | e.hard; |
---|
2175 | |
---|
2176 | Gener-Label e.QualifiedName = |
---|
2177 | { |
---|
2178 | <Lookup &Labels e.QualifiedName> : s.num, |
---|
2179 | <"+" s.num 1>; |
---|
2180 | 1; |
---|
2181 | } :: s.num, |
---|
2182 | <Bind &Labels (e.QualifiedName) (s.num)>, |
---|
2183 | (e.QualifiedName s.num); |
---|
2184 | |
---|
2185 | Add-To-Label (e.label) e.name = <Gener-Label e.label "_" e.name>; |
---|
2186 | |
---|
2187 | Get-Static-Exprs e.Re = |
---|
2188 | e.Re () () () $iter { |
---|
2189 | e.Re : t.Rt e.rest, t.Rt : { |
---|
2190 | s.ObjectSymbol, { |
---|
2191 | <Char? t.Rt> = |
---|
2192 | e.rest (e.new-Re) (e.decls) (e.expr t.Rt); |
---|
2193 | <Get-Static-Var "chars" e.expr> :: e.expr-var (e.expr-decl), |
---|
2194 | { |
---|
2195 | <Int? t.Rt> = "int"; |
---|
2196 | <Word? t.Rt> = "word"; |
---|
2197 | } :: s.prefix, |
---|
2198 | <Get-Static-Var s.prefix t.Rt> :: e.Rt-var (e.Rt-decl) = |
---|
2199 | e.rest (e.new-Re e.expr-var e.Rt-var) |
---|
2200 | (e.decls e.expr-decl e.Rt-decl) (); |
---|
2201 | }; |
---|
2202 | (PAREN e.paren-Re) = |
---|
2203 | <Get-Static-Exprs e.paren-Re> :: e.new-paren-Re (e.paren-decls), |
---|
2204 | <Get-Static-Var "chars" e.expr> :: e.expr-var (e.expr-decl), |
---|
2205 | e.rest (e.new-Re e.expr-var (PAREN e.new-paren-Re)) |
---|
2206 | (e.decls e.expr-decl e.paren-decls) (); |
---|
2207 | t.var = |
---|
2208 | <Get-Static-Var "chars" e.expr> :: e.expr-var (e.expr-decl), |
---|
2209 | e.rest (e.new-Re e.expr-var t.var) (e.decls e.expr-decl) (); |
---|
2210 | }; |
---|
2211 | } :: e.Re (e.new-Re) (e.decls) (e.expr), |
---|
2212 | // <WriteLN Get-Static-Exprs e.Re>, |
---|
2213 | e.Re : /*empty*/ = |
---|
2214 | <Get-Static-Var "chars" e.expr> :: e.expr-var (e.expr-decl), |
---|
2215 | e.new-Re e.expr-var (e.decls e.expr-decl); |
---|
2216 | |
---|
2217 | Get-Static-Var s.prefix e.expr, { |
---|
2218 | e.expr : /*empty*/ = /*empty*/ (); |
---|
2219 | { |
---|
2220 | <Lookup &Static-Exprs s.prefix e.expr> : t.var = t.var (); |
---|
2221 | ("const" s.prefix e.expr) :: t.name, |
---|
2222 | <Bind &Static-Exprs (s.prefix e.expr) ((VAR t.name))>, |
---|
2223 | <Declare-Vars "Expr" (VAR t.name)> : e, |
---|
2224 | <Instantiate-Vars (VAR t.name)>, |
---|
2225 | <Set-Var t.name (Flat) (True)>, |
---|
2226 | <Length e.expr> :: s.len, |
---|
2227 | <Set-Var t.name (Length) (s.len)>, |
---|
2228 | <Set-Var t.name (Min) (s.len)>, |
---|
2229 | <Set-Var t.name (Max) (s.len)>, |
---|
2230 | <Set-Var t.name (Format) (e.expr)> = |
---|
2231 | (VAR t.name) ((EXPR (VAR t.name) e.expr)); |
---|
2232 | }; |
---|
2233 | }; |
---|
2234 | |
---|
2235 | Length-of { |
---|
2236 | /*empty*/ = 0; |
---|
2237 | e.Re = |
---|
2238 | e.Re () $iter { |
---|
2239 | e.Re : t.Rt e.rest, t.Rt : { |
---|
2240 | s.ObjectSymbol = 1; |
---|
2241 | (PAREN e) = 1; |
---|
2242 | (REF t.name) = <Ref-Len t.name>; |
---|
2243 | (VAR t.name), { |
---|
2244 | <?? t.name Length>; |
---|
2245 | (Used t.Rt) (LENGTH t.Rt); |
---|
2246 | }; |
---|
2247 | t = (LENGTH t.Rt); // STUB! |
---|
2248 | } :: e.new-len, |
---|
2249 | e.rest (e.Length e.new-len); |
---|
2250 | } :: e.Re (e.Length), |
---|
2251 | e.Re : /*empty*/ = |
---|
2252 | // (INFIX "+" e.Length); |
---|
2253 | // <WriteLN Length e.Length>, |
---|
2254 | e.Length; |
---|
2255 | }; |
---|
2256 | |
---|
2257 | Ref-Len t.name = { |
---|
2258 | <To-Int <Lookup &Const-Len t.name>>; |
---|
2259 | <Length <Length-of <Lookup &Const t.name>>> :: s.len = |
---|
2260 | <Bind &Const-Len (t.name) (s.len)>, |
---|
2261 | s.len; |
---|
2262 | }; |
---|
2263 | |
---|
2264 | /* |
---|
2265 | * Ends good if lengths of all variables in e.expr can be calculated. |
---|
2266 | */ |
---|
2267 | Hard-Exp? e.expr = |
---|
2268 | e.expr $iter { |
---|
2269 | e.expr : t.first e.rest = |
---|
2270 | { |
---|
2271 | t.first : (VAR t.name), { |
---|
2272 | <?? t.name Instantiated> : True; |
---|
2273 | <?? t.name Max> :: e.max, <?? t.name Min> : e.max; |
---|
2274 | = $fail; |
---|
2275 | };; |
---|
2276 | }, |
---|
2277 | e.rest; |
---|
2278 | } :: e.expr, |
---|
2279 | e.expr : /*empty*/, |
---|
2280 | = $fail; // STUB! |
---|
2281 | |
---|
2282 | Print-Error s.WE e.Descrip t.Pragma = |
---|
2283 | <? &Error-Counter> : s.n, |
---|
2284 | <Store &Error-Counter <"+" s.n 1>>, |
---|
2285 | <Print-Pragma &StdErr t.Pragma>, |
---|
2286 | <Print! &StdErr " " s.WE " ">, |
---|
2287 | s.WE e.Descrip : { |
---|
2288 | Error! Re = <PrintLN! &StdErr "Wrong format of result expression">; |
---|
2289 | Error! Call = <PrintLN! &StdErr "Wrong argument format in function call">; |
---|
2290 | Error! Pattern = <PrintLN! &StdErr "Wrong format of pattern expression">; |
---|
2291 | Warning! Pattern = <PrintLN! &StdErr "Clash can't be solved">; |
---|
2292 | Error! Var-Re t.var = |
---|
2293 | <PrintLN! &StdErr "Unknown variable '" |
---|
2294 | <AS-To-Ref t.var> "' in result expression">; |
---|
2295 | Error! Var-Hard t.var = |
---|
2296 | <PrintLN! &StdErr "Repeated occurence of the variable '" |
---|
2297 | <AS-To-Ref t.var> "' in hard expression">; |
---|
2298 | Error! Var-Type t.var s.type = |
---|
2299 | <PrintLN! &StdErr "Incorrect type '" <AS-To-Ref s.type> |
---|
2300 | "' of the variable '" <AS-To-Ref t.var> "'">; |
---|
2301 | Error! Cut = <PrintLN! &StdErr "'\\\\!' without corresponding '\\\\?'">; |
---|
2302 | }; |
---|
2303 | |
---|
2304 | Print-Pragma s.channel (PRAGMA e.pragmas), |
---|
2305 | e.pragmas : { |
---|
2306 | e (FILE e.file-name) e, <Print! s.channel e.file-name>, $fail; |
---|
2307 | e (LINE s.line s.col) e, <Print! s.channel (s.line ", " s.col)>, $fail; |
---|
2308 | e = <Print! s.channel ":">; |
---|
2309 | }; |
---|
2310 | |
---|
2311 | AS-To-Ref { |
---|
2312 | SVAR = 's'; |
---|
2313 | TVAR = 't'; |
---|
2314 | VVAR = 'v'; |
---|
2315 | EVAR = 'e'; |
---|
2316 | (s.tag t (e.name)) = <AS-To-Ref s.tag> '.' <To-Chars e.name>; |
---|
2317 | }; |
---|
2318 | |
---|
2319 | Lookup-Func t.Fname, \{ |
---|
2320 | <Lookup &Fun t.Fname>; |
---|
2321 | <Lookup &Fun? t.Fname>; |
---|
2322 | } : s.linkage s.tag t.pragma (e.Fin) (e.Fout) = |
---|
2323 | s.linkage s.tag t.pragma (e.Fin) (e.Fout); |
---|
2324 | |
---|