|
1 | 1 | // import * as evaluator from './compiled/agreval_module.mjs';
|
2 |
| -import { compileToConstructor, compileToModuleSrc, deltaSource, instance2dot, metaInstance } from 'rulespace'; |
| 2 | +import { assertTrue, MutableMaps, Sets } from '@rulespace/common'; |
| 3 | +import { compileToConstructor, compileToModuleSrc, instance2dot, computeMeta } from '@rulespace/rulespace'; |
3 | 4 | import { SchemeParser, Sym, Pair } from './sexp-reader.js';
|
4 |
| -import { assertTrue, MutableMaps, Sets } from 'common'; |
5 | 5 |
|
6 | 6 | import { specification } from './agreval-rsp.js';
|
7 | 7 |
|
| 8 | +export { lattice_conc, lattice_prim } from './lattice-rsp.js'; |
| 9 | +export { kalloc_conc, kalloc_0cfa } from './kalloc-rsp.js'; |
| 10 | +export { specification as semantics_scheme }; |
| 11 | +export { computeMeta }; |
| 12 | + |
| 13 | +export { instance2dot }; |
8 | 14 |
|
9 | 15 | function param2tuples(lam)
|
10 | 16 | {
|
@@ -190,7 +196,6 @@ function* filterPred(tuples, pred)
|
190 | 196 |
|
191 | 197 | export function create_agreval(configSrc)
|
192 | 198 | {
|
193 |
| - |
194 | 199 | const evaluatorCtr = compileToConstructor(specification + configSrc);
|
195 | 200 |
|
196 | 201 | return function agreval(src, options = {})
|
@@ -220,102 +225,145 @@ export function create_agreval(configSrc)
|
220 | 225 | debug(evaluator);
|
221 | 226 | }
|
222 | 227 |
|
223 |
| - return evaluator; |
| 228 | + return new Evaluator(evaluator); |
224 | 229 | }
|
225 | 230 | }
|
226 | 231 |
|
227 |
| -function* result(evaluator) |
| 232 | +class Evaluator |
228 | 233 | {
|
229 |
| - for (const t of filterPred(evaluator.tuples(), 'evaluate')) |
| 234 | + constructor(evaluator) |
230 | 235 | {
|
231 |
| - yield t.t1; |
| 236 | + this.evaluator = evaluator; |
232 | 237 | }
|
233 |
| -} |
234 | 238 |
|
235 |
| -function initialState(evaluator) |
236 |
| -{ |
237 |
| - return [...filterPred(evaluator.tuples(), 'initial_state')][0].t0; |
238 |
| -} |
| 239 | + computeFlowGraph() |
| 240 | + { |
| 241 | + const evaluator = this.evaluator; |
| 242 | + const todo = [this.initialState()]; |
| 243 | + const states = new Set(); |
| 244 | + const transitions = []; |
| 245 | + while (todo.length > 0) |
| 246 | + { |
| 247 | + const current = todo.pop(); |
| 248 | + if (states.has(current)) |
| 249 | + { |
| 250 | + continue; |
| 251 | + } |
| 252 | + states.add(current); |
| 253 | + for (const succ of this.successorStates(current)) |
| 254 | + { |
| 255 | + transitions.push([current, succ]); |
| 256 | + todo.push(succ); |
| 257 | + } |
| 258 | + } |
| 259 | + return {states:[...states], transitions}; |
| 260 | + } |
239 | 261 |
|
240 |
| -function successorStates(evaluator, state) |
241 |
| -{ |
242 |
| - const result = []; |
243 |
| - for (const t of filterPred(evaluator.tuples(), 'step')) |
| 262 | + *result() |
244 | 263 | {
|
245 |
| - if (t.t0 === state) |
| 264 | + const evaluator = this.evaluator; |
| 265 | + for (const t of filterPred(evaluator.tuples(), 'evaluate')) |
246 | 266 | {
|
247 |
| - result.push(t.t1); |
| 267 | + yield t.t1; |
248 | 268 | }
|
249 | 269 | }
|
250 |
| - return result; |
251 |
| -} |
252 | 270 |
|
253 |
| -function astTuple(evaluator, tag) |
254 |
| -{ |
255 |
| - for (const t of evaluator.tuples()) |
| 271 | + initialState() |
256 | 272 | {
|
257 |
| - if (t.constructor.name.startsWith('$')) |
| 273 | + const evaluator = this.evaluator; |
| 274 | + return [...filterPred(evaluator.tuples(), 'initial_state')][0].t0; |
| 275 | + } |
| 276 | + |
| 277 | + successorStates(state) |
| 278 | + { |
| 279 | + const evaluator = this.evaluator; |
| 280 | + const result = []; |
| 281 | + for (const t of filterPred(evaluator.tuples(), 'step')) |
258 | 282 | {
|
259 |
| - if (t.t0 === tag) |
| 283 | + if (t.t0 === state) |
260 | 284 | {
|
261 |
| - return t; |
| 285 | + result.push(t.t1); |
262 | 286 | }
|
263 | 287 | }
|
| 288 | + return result; |
264 | 289 | }
|
265 |
| - throw new Error(`tuple with tag ${tag} not found`); |
266 |
| -} |
267 |
| - |
268 |
| -function expToString(evaluator, tag) |
269 |
| -{ |
270 |
| - function helper(tag) |
| 290 | + |
| 291 | + astTuple(tag) |
271 | 292 | {
|
272 |
| - const t = astTuple(tag); |
273 |
| - switch (t.constructor.name) |
| 293 | + const evaluator = this.evaluator; |
| 294 | + for (const t of evaluator.tuples()) |
274 | 295 | {
|
275 |
| - case '$id': return t.t1; |
276 |
| - case '$lit': return t.t1; |
277 |
| - case '$let': return `(let ((${helper(t.t1)} ${helper(t.t2)})) ${helper(t.t3)})`; |
278 |
| - case '$letrec': return `(letrec ((${helper(t.t1)} ${helper(t.t2)})) ${helper(t.t3)})`; |
279 |
| - case '$lam': return `(lambda ... ${helper(t.t1)})`; |
280 |
| - case '$if': return `(if ${helper(t.t1)} ${helper(t.t2)} ${helper(t.t3)})`; |
281 |
| - case '$set': return `(set! ${helper(t.t1)} ${helper(t.t2)})`; |
282 |
| - case '$cons': return `(cons ${helper(t.t1)} ${helper(t.t2)})`; |
283 |
| - case '$car': return `(car ${helper(t.t1)})`; |
284 |
| - case '$cdr': return `(cdr ${helper(t.t1)})`; |
285 |
| - case '$setcar': return `(set-car! ${helper(t.t1)} ${helper(t.t2)})`; |
286 |
| - case '$setcdr': return `(set-cdr! ${helper(t.t1)} ${helper(t.t2)})`; |
287 |
| - case '$app': |
| 296 | + if (t.constructor.name.startsWith('$')) |
| 297 | + { |
| 298 | + if (t.t0 === tag) |
288 | 299 | {
|
289 |
| - const randTuples = []; |
290 |
| - for (const t_rand of filterPred(evaluator.tuples(), 'rand')) |
| 300 | + return t; |
| 301 | + } |
| 302 | + } |
| 303 | + } |
| 304 | + throw new Error(`tuple with tag ${tag} not found`); |
| 305 | + } |
| 306 | + |
| 307 | + expToString(tag) |
| 308 | + { |
| 309 | + const evaluator = this.evaluator; |
| 310 | + const self = this; |
| 311 | + function helper(tag) |
| 312 | + { |
| 313 | + const t = self.astTuple(tag); |
| 314 | + switch (t.constructor.name) |
| 315 | + { |
| 316 | + case '$id': return t.t1; |
| 317 | + case '$lit': return t.t1; |
| 318 | + case '$let': return `(let ((${helper(t.t1)} ${helper(t.t2)})) ${helper(t.t3)})`; |
| 319 | + case '$letrec': return `(letrec ((${helper(t.t1)} ${helper(t.t2)})) ${helper(t.t3)})`; |
| 320 | + case '$lam': return `(lambda ... ${helper(t.t1)})`; |
| 321 | + case '$if': return `(if ${helper(t.t1)} ${helper(t.t2)} ${helper(t.t3)})`; |
| 322 | + case '$set': return `(set! ${helper(t.t1)} ${helper(t.t2)})`; |
| 323 | + case '$cons': return `(cons ${helper(t.t1)} ${helper(t.t2)})`; |
| 324 | + case '$car': return `(car ${helper(t.t1)})`; |
| 325 | + case '$cdr': return `(cdr ${helper(t.t1)})`; |
| 326 | + case '$setcar': return `(set-car! ${helper(t.t1)} ${helper(t.t2)})`; |
| 327 | + case '$setcdr': return `(set-cdr! ${helper(t.t1)} ${helper(t.t2)})`; |
| 328 | + case '$app': |
291 | 329 | {
|
292 |
| - if (t_rand.t1 === t.t0) |
| 330 | + const randTuples = []; |
| 331 | + for (const t_rand of filterPred(evaluator.tuples(), 'rand')) |
293 | 332 | {
|
294 |
| - randTuples.push(t_rand); |
| 333 | + if (t_rand.t1 === t.t0) |
| 334 | + { |
| 335 | + randTuples.push(t_rand); |
| 336 | + } |
295 | 337 | }
|
| 338 | + randTuples.sort((ta, tb) => ta.t2 - tb.t2); |
| 339 | + const rands = randTuples.map(t => t.t0); |
| 340 | + return `(${helper(t.t1)} ${rands.map(helper).join(' ')})`; |
296 | 341 | }
|
297 |
| - randTuples.sort((ta, tb) => ta.t2 - tb.t2); |
298 |
| - const rands = randTuples.map(t => t.t0); |
299 |
| - return `(${helper(t.t1)} ${rands.map(helper).join(' ')})`; |
300 |
| - } |
301 |
| - default: throw new Error(t.constructor.name); |
| 342 | + default: throw new Error(t.constructor.name); |
| 343 | + } |
302 | 344 | }
|
| 345 | + |
| 346 | + return helper(tag); |
303 | 347 | }
|
304 | 348 |
|
305 |
| - return helper(tag); |
306 |
| -} |
307 |
| - |
308 |
| -function evaluate(evaluator, exp, state) |
309 |
| -{ |
310 |
| - const result = []; |
311 |
| - for (const t of filterPred(evaluator.tuples(), 'greval')) |
| 349 | + evaluate(exp, state) |
312 | 350 | {
|
313 |
| - if (t.t0 === exp && t.t1 === state) |
| 351 | + const evaluator = this.evaluator; |
| 352 | + const result = []; |
| 353 | + for (const t of filterPred(evaluator.tuples(), 'greval')) |
314 | 354 | {
|
315 |
| - result.push(t.t2); |
| 355 | + if (t.t0 === exp && t.t1 === state) |
| 356 | + { |
| 357 | + result.push(t.t2); |
| 358 | + } |
316 | 359 | }
|
| 360 | + return result; |
| 361 | + } |
| 362 | + |
| 363 | + meta() |
| 364 | + { |
| 365 | + return computeMeta(this.evaluator); |
317 | 366 | }
|
318 |
| - return result; |
319 | 367 | }
|
320 | 368 |
|
321 | 369 | function debug(evaluator)
|
@@ -425,70 +473,68 @@ function debug(evaluator)
|
425 | 473 | // })
|
426 | 474 | // }
|
427 | 475 |
|
428 |
| -function dotFlowGraph(evaluator, nodeToString) |
429 |
| -{ |
430 |
| - const todo = [initialState(evaluator)]; |
431 |
| - const nodes = []; |
432 |
| - const transitions = new Map(); |
433 |
| - while (todo.length > 0) |
434 |
| - { |
435 |
| - const current = todo.pop(); |
436 |
| - let index = nodes.indexOf(current); |
437 |
| - if (index > -1) |
438 |
| - { |
439 |
| - continue; |
440 |
| - } |
441 |
| - nodes.push(current); |
442 |
| - for (const succ of evaluator.successorStates(current)) |
443 |
| - { |
444 |
| - MutableMaps.putPushArray(transitions, current, succ); |
445 |
| - todo.push(succ); |
446 |
| - } |
447 |
| - } |
448 |
| - const dotNodes = nodes.map((node, i) => `${i} [label="${nodeToString(node)}"];`); |
449 |
| - const dotTransitions = []; |
450 |
| - for (const [source, dests] of transitions) |
451 |
| - { |
452 |
| - const tagSource = nodes.indexOf(source); |
453 |
| - for (const dest of dests) |
454 |
| - { |
455 |
| - dotTransitions.push(`${tagSource} -> ${nodes.indexOf(dest)}`); |
456 |
| - } |
457 |
| - } |
| 476 | +// function dotFlowGraph(evaluator, nodeToString) |
| 477 | +// { |
| 478 | +// const todo = [initialState(evaluator)]; |
| 479 | +// const nodes = []; |
| 480 | +// const transitions = new Map(); |
| 481 | +// while (todo.length > 0) |
| 482 | +// { |
| 483 | +// const current = todo.pop(); |
| 484 | +// let index = nodes.indexOf(current); |
| 485 | +// if (index > -1) |
| 486 | +// { |
| 487 | +// continue; |
| 488 | +// } |
| 489 | +// nodes.push(current); |
| 490 | +// for (const succ of successorStates(evaluator, current)) |
| 491 | +// { |
| 492 | +// MutableMaps.putPushArray(transitions, current, succ); |
| 493 | +// todo.push(succ); |
| 494 | +// } |
| 495 | +// } |
| 496 | +// const dotNodes = nodes.map((node, i) => `${i} [label="${nodeToString(node)}"];`); |
| 497 | +// const dotTransitions = []; |
| 498 | +// for (const [source, dests] of transitions) |
| 499 | +// { |
| 500 | +// const tagSource = nodes.indexOf(source); |
| 501 | +// for (const dest of dests) |
| 502 | +// { |
| 503 | +// dotTransitions.push(`${tagSource} -> ${nodes.indexOf(dest)}`); |
| 504 | +// } |
| 505 | +// } |
458 | 506 |
|
459 |
| - return ` |
460 |
| - digraph G { |
461 |
| - node [style=filled,fontname="Roboto Condensed"]; |
| 507 | +// return ` |
| 508 | +// digraph G { |
| 509 | +// node [style=filled,fontname="Roboto Condensed"]; |
462 | 510 |
|
463 |
| - ${dotNodes.join('\n')} |
| 511 | +// ${dotNodes.join('\n')} |
464 | 512 |
|
465 |
| - ${dotTransitions.join('\n')} |
| 513 | +// ${dotTransitions.join('\n')} |
466 | 514 |
|
467 |
| - } |
468 |
| - `; |
469 |
| -} |
| 515 | +// } |
| 516 | +// `; |
| 517 | +// } |
470 | 518 |
|
471 |
| -function dotProvenanceGraph() |
472 |
| -{ |
473 |
| - return instance2dot(evaluator); |
474 |
| -} |
475 | 519 |
|
476 |
| -import { lattice_conc as lattice } from './lattice-rsp.js'; |
477 |
| -import { kalloc_0cfa as kalloc } from './kalloc-rsp.js'; |
| 520 | +// export function dotProvenanceGraph() |
| 521 | +// { |
| 522 | +// return instance2dot(evaluator); |
| 523 | +// } |
| 524 | + |
| 525 | +// import { lattice_conc as lattice } from './lattice-rsp.js'; |
| 526 | +// import { kalloc_conc as kalloc } from './kalloc-rsp.js'; |
| 527 | + |
| 528 | +// const agreval = create_agreval(lattice + kalloc); |
| 529 | +// const start = Date.now(); |
| 530 | +// const evaluator = agreval(` |
478 | 531 |
|
479 |
| -const agreval = create_agreval(lattice + kalloc); |
480 |
| -const start = Date.now(); |
481 |
| -const evaluator = agreval(` |
| 532 | +// (+ 1 2) |
482 | 533 |
|
483 |
| -(let ((x 1)) |
484 |
| - (let ((y 2)) |
485 |
| - (let ((u "piano")) |
486 |
| - (let ((z (+ x y))) |
487 |
| - z)))) |
488 | 534 |
|
489 |
| -`, {debug:false}); |
490 |
| -console.log(`${Date.now() - start} ms`); |
491 |
| -console.log([...result(evaluator)]); |
492 |
| -// console.log(dotFlowGraph(evaluator, t => `${evaluator.expToString(t.t0)} | ${t.t1} | ${evaluator.evaluate(t.t0, t)}`)); |
493 |
| -console.log(dotProvenanceGraph()); |
| 535 | +// `, {debug:false}); |
| 536 | +// console.log(`${Date.now() - start} ms`); |
| 537 | +// console.log([...result(evaluator)]); |
| 538 | +// // console.log(dotFlowGraph(evaluator, t => `${evaluator.expToString(t.t0)} | ${t.t1} | ${evaluator.evaluate(t.t0, t)}`)); |
| 539 | +// console.log(dotProvenanceGraph()); |
494 | 540 |
|
0 commit comments