-
Notifications
You must be signed in to change notification settings - Fork 0
/
simpleTypedVarPointsTo.ts
125 lines (118 loc) · 2.82 KB
/
simpleTypedVarPointsTo.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
//
// Implements https://souffle-lang.github.io/examples#simple-typed-symbolpointsto in Souffle.js
//
import {
SouffleContext,
SouffleSyncExecutor,
relation,
rule,
atom,
body,
Type,
} from "../src";
// Initialize the Souffle context that keeps the created program entries.
const ctx = new SouffleContext("VarPointsTo");
// Add relation declarations:
// .decl assign( a:symbol , b:symbol )
// .decl new( v:symbol, o:symbol )
// .decl ld( a:symbol, b:symbol, f:symbol )
// .decl st( a:symbol, f:symbol, b:symbol )
ctx.add(
relation("assign", [
["a", Type.symbol()],
["b", Type.symbol()],
]),
);
ctx.add(
relation("new", [
["v", Type.symbol()],
["o", Type.symbol()],
]),
);
ctx.add(
relation("ld", [
["a", Type.symbol()],
["b", Type.symbol()],
["f", Type.symbol()],
]),
);
ctx.add(
relation("st", [
["a", Type.symbol()],
["f", Type.symbol()],
["b", Type.symbol()],
]),
);
// Add facts:
// assign("v1","v2").
// new("v1","h1").
// new("v2","h2").
// new("v3","h3").
// st("v1","f","v3").
// ld("v4","v1","f").
ctx.addFact("assign", ["v1", "v2"]);
ctx.addFact("new", ["v1", "h1"]);
ctx.addFact("new", ["v2", "h2"]);
ctx.addFact("new", ["v3", "h3"]);
ctx.addFact("st", ["v1", "f", "v3"]);
ctx.addFact("ld", ["v4", "v1", "f"]);
// Add rules:
// .decl alias( a:symbol, b:symbol )
// .output alias
// alias(X,X) :- assign(X,_).
// alias(X,X) :- assign(_,X).
// alias(X,Y) :- assign(X,Y).
// alias(X,Y) :- ld(X,A,F), alias(A,B), st(B,F,Y).
ctx.add(
relation(
"alias",
[
["a", Type.symbol()],
["b", Type.symbol()],
],
"output",
),
);
ctx.add(rule([atom("alias", ["X", "X"])], [body(atom("assign", ["X", "_"]))]));
ctx.add(rule([atom("alias", ["X", "X"])], [body(atom("assign", ["_", "X"]))]));
ctx.add(rule([atom("alias", ["X", "Y"])], [body(atom("assign", ["X", "Y"]))]));
ctx.add(
rule(
[atom("alias", ["X", "Y"])],
[
body(atom("ld", ["X", "A", "F"])),
body(atom("alias", ["A", "B"])),
body(atom("st", ["B", "F", "Y"])),
],
),
);
// .decl pointsTo( a:symbol, o:symbol )
// .output pointsTo
// pointsTo(X,Y) :- new(X,Y).
// pointsTo(X,Y) :- alias(X,Z), pointsTo(Z,Y).
ctx.add(
relation(
"pointsTo",
[
["a", Type.symbol()],
["o", Type.symbol()],
],
"output",
),
);
ctx.add(rule([atom("pointsTo", ["X", "Y"])], [body(atom("new", ["X", "Y"]))]));
ctx.add(
rule(
[atom("pointsTo", ["X", "Y"])],
[body(atom("alias", ["X", "Z"])), body(atom("pointsTo", ["Z", "Y"]))],
),
);
// Execute the generated Soufflé program containing all the added entries
const executor = new SouffleSyncExecutor();
const out = executor.execute(ctx);
if (out.kind !== "raw") {
throw new Error(
`Error executing Soufflé:\n${out.kind === "error" ? out.stderr : "impossible"}`,
);
}
console.log("Raw Soufflé output:\n", out.results);