Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/prolog/prolog.dart

Issue 1259553002: Emit program and dependency information as relations in a Prolog database. Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 library prolog;
2
3 import '../common.dart';
4 import 'dart:async';
5 import 'dart:collection';
6
7 abstract class Node {
8 const Node();
9 }
10
11 abstract class Term extends Node {
12 const Term();
13 }
14
15 class Atom extends Term {
16 final String text;
17 const Atom(this.text);
18
19 get hashCode => text.hashCode;
20
21 operator ==(other) => text == other.text;
22
23 static const Atom AND = const Atom(",");
24 static const Atom OR = const Atom(";");
25 static const Atom IMPLY = const Atom(":-");
26 }
27
28 class Compound extends Term {
29 final Atom functor;
30 final List<Term> arguments;
31 const Compound(this.functor, [this.arguments = const <Term>[]]);
32 bool get isAnd => functor == Atom.AND;
33 bool get isOr => functor == Atom.OR;
34 bool get isImply => functor == Atom.IMPLY;
35 }
36
37 class And extends Compound {
38 const And(List<Term> arguments) : super(Atom.AND, arguments);
39 }
40
41 class Or extends Compound {
42 const Or(List<Term> arguments) : super(Atom.OR, arguments);
43 }
44
45 class Clause extends Compound {
46 Clause(Term head, [List<Term> body = const <Term>[]])
47 : super(Atom.IMPLY, <Term>[head]..addAll(body));
48
49 Atom get predicate {
50 Term head = arguments.first;
51 return head is Compound ? head.functor : head;
52 }
53
54 Term get head => arguments.first;
55
56 Iterable<Term> get body => arguments.skip(1);
57 }
58
59
60 class Program {
61 Map<Atom, List<Clause>> clauses = <Atom, List<Clause>>{};
62
63 void add(Clause clause) {
64 assert(clause != null);
65 clauses.putIfAbsent(clause.predicate, () => <Clause>[]).add(clause);
66 }
67
68 void addClause(Term head, List<Term> body) => add(new Clause(head, body));
69
70 Iterable<Clause> getClausesFor(Atom predicate) {
71 return clauses.containsKey(predicate)
72 ? clauses[predicate]
73 : const <Clause>[];
74 }
75
76 Program mergeWith(Program other) {
77 clauses.addAll(other.clauses);
78 return this;
79 }
80 }
81
82
83 class ProgramEmitter {
84 final EventSink<String> _sink;
85
86 ProgramEmitter(this._sink);
87
88 String _quoteAtom(Atom atom) {
89 String text = atom.text;
90 if (text == "" ||
91 text.contains(new RegExp(r'[^_0-9a-zA-Z]')) ||
92 text.indexOf(new RegExp('[_0-9A-Z]')) == 0) {
93 return "'$text'";
94 } else {
95 return text;
96 }
97 }
98
99 void _emit(String text) => _sink.add(text);
100
101 void _emitAtom(Atom atom, {quote: true}) {
102 _emit(quote ? _quoteAtom(atom) : atom.text);
103 }
104
105 void _emitTerm(Term term) {
106 if (term is Atom) {
107 _emitAtom(term);
108 } else if (term is Compound) {
109 _emitAtom(term.functor);
110 _open();
111 _emitList(term.arguments);
112 _close();
113 } else {
114 throw 'unsupported $term';
115 }
116 }
117
118 void _emitList(Iterable<Term> terms, {separator: ', '}) {
119 if (terms.isEmpty) return;
120 _emitTerm(terms.first);
121 for (Term term in terms.skip(1)) {
122 _emit(separator);
123 _emitTerm(term);
124 }
125 }
126
127 void _open() => _emit('(');
128
129 void _close() => _emit(')');
130
131 void _space() => _emit(' ');
132
133 void _endClause() => _emit('.\n');
134
135 void emitProgram(Program program) {
136 for (Atom predicate in program.clauses.keys) {
137 if (program.clauses[predicate] == null) print(predicate.text);
138 for (Clause clause in program.clauses[predicate]) {
139 _emitTerm(clause.head);
140 Iterable<Term> body = clause.body;
141 if (body.isNotEmpty) {
142 _space();
143 _emitAtom(Atom.IMPLY, quote: false);
144 _space();
145 _emitList(body);
146 }
147 _endClause();
148 }
149 }
150 }
151 }
152
153
154 /// Used to build a program from recorded relations and the element model.
155 class ProgramBuilder {
156 Program _program = new Program();
157
158 Map<String, dynamic> _usedNames = <String, dynamic>{};
159
160 bool _alreadyUsed(entity, String name) {
161 return _usedNames.containsKey(name) && entity != _usedNames[name];
162 }
163
164 Map<Element, Atom> _identifiers = <Element, Atom>{};
165
166 Queue<Function> _queue = new Queue<Function>();
167
168 void defer(f()) {
169 _queue.add(f);
170 }
171
172 void _addFact(Atom predicate, List<Term> arguments) {
173 _program.add(new Clause(new Compound(predicate, arguments)));
174 }
175
176 void _addClause(Clause clause) {
177 _program.add(clause);
178 }
179
180 void _addContains(Atom container, Atom element) {
181 _addFact(const Atom('contains'), <Atom>[container, element]);
182 }
183
184 Atom _elementPredicate(Element element) => new Atom(element.kind.id);
185
186 // TODO(karlklose): Extract a strategy object for these two functions.
187 Clause _elementDefinition(Element element, Atom reference) {
188 Atom name = new Atom(element.name);
189 Atom kind = new Atom(element.kind.id);
190 List<Term> properties = <Term>[reference, name];
191 return new Clause(new Compound(kind, properties));
192 }
193
194 String _getNameProposal(entity) {
195 if (entity is CompilationUnitElement) {
196 return 'file_${entity.script.readableUri.pathSegments.last}';
197 } else if (entity is LibraryElement) {
198 return 'lib_${entity.canonicalUri.pathSegments.last}';
199 } else if (entity is Element) {
200 return entity.name;
201 } else {
202 return entity.toString();
203 }
204 }
205
206 Atom _elementReference(Element element) {
207 if (_identifiers.containsKey(element)) return _identifiers[element];
208 Atom reference = new Atom(_getName(element));
209 Element container = element.enclosingElement;
210 if (container != null) {
211 defer(() {
212 _addContains(_elementReference(container), reference);
213 _addClause(_elementDefinition(element, reference));
214 });
215 }
216 return _identifiers[element] = reference;
217 }
218
219 String _makeUniqueName(entity, String base) {
220 int nr = 0;
221 String proposal = base;
222 while (_alreadyUsed(entity, proposal)) {
223 proposal = '$base$nr';
224 nr++;
225 }
226 _usedNames[proposal] = entity;
227 return proposal;
228 }
229
230 String _getName(entity) => _makeUniqueName(entity, _getNameProposal(entity));
231
232 Term _terminize(object) {
233 return object is Element ? _elementReference(object)
234 : new Atom(object.toString());
235 }
236
237 void addRelation(String relation, List elements) {
238 List<Term> references = elements.map(_terminize).toList();
239 _addFact(new Atom(relation), references);
240 while (_queue.isNotEmpty) {
241 Function continuation = _queue.removeFirst();
242 continuation();
243 }
244 }
245
246 Program get program {
247 Program result = _program;
248 _program = null;
249 return result;
250 }
251 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698