OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class LibraryImport { | 5 class LibraryImport { |
6 String prefix; | 6 String prefix; |
7 Library library; | 7 Library library; |
8 LibraryImport(this.library, [this.prefix = null]); | 8 LibraryImport(this.library, [this.prefix = null]); |
9 } | 9 } |
10 | 10 |
| 11 |
11 /** Represents a Dart library. */ | 12 /** Represents a Dart library. */ |
12 class Library { | 13 class Library extends Element { |
13 final SourceFile baseSource; | 14 final SourceFile baseSource; |
14 Map<String, DefinedType> types; | 15 Map<String, DefinedType> types; |
15 List<LibraryImport> imports; | 16 List<LibraryImport> imports; |
16 String sourceDir; | 17 String sourceDir; |
17 String name; | |
18 List<SourceFile> natives; | 18 List<SourceFile> natives; |
19 List<SourceFile> sources; | 19 List<SourceFile> sources; |
20 | 20 |
21 Map<String, MemberSet> _privateMembers; | 21 Map<String, MemberSet> _privateMembers; |
22 | 22 |
23 /** The type that holds top level types in the library. */ | 23 /** The type that holds top level types in the library. */ |
24 DefinedType topType; | 24 DefinedType topType; |
25 | 25 |
26 /** Set to true by [WorldGenerator] once this type has been written. */ | 26 /** Set to true by [WorldGenerator] once this type has been written. */ |
27 bool isWritten = false; | 27 bool isWritten = false; |
28 | 28 |
29 /** | 29 /** |
30 * Set to true by [WorldGenerator] once this library has been marked as used. | 30 * Set to true by [WorldGenerator] once this library has been marked as used. |
31 * Only used with the compileAll flag. */ | 31 * Only used with the compileAll flag. */ |
32 bool isMarked = false; | 32 bool isMarked = false; |
33 | 33 |
34 String _jsname; | 34 Library(this.baseSource) : super(null, null) { |
35 | |
36 Library(this.baseSource) { | |
37 sourceDir = dirname(baseSource.filename); | 35 sourceDir = dirname(baseSource.filename); |
38 topType = new DefinedType(null, this, null, true); | 36 topType = new DefinedType(null, this, null, true); |
39 types = { '': topType }; | 37 types = { '': topType }; |
40 imports = []; | 38 imports = []; |
41 natives = []; | 39 natives = []; |
42 sources = []; | 40 sources = []; |
43 _privateMembers = {}; | 41 _privateMembers = {}; |
44 } | 42 } |
45 | 43 |
| 44 Element get enclosingElement() => null; |
| 45 Library get library() => this; |
| 46 |
| 47 bool get isNative() => topType.isNative; |
| 48 |
46 bool get isCore() => this == world.corelib; | 49 bool get isCore() => this == world.corelib; |
47 bool get isCoreImpl() => this == world.coreimpl; | 50 bool get isCoreImpl() => this == world.coreimpl; |
48 | 51 |
49 String get jsname() { | |
50 if (_jsname == null) { | |
51 // TODO(jimhug): Expand to handle all illegal id characters | |
52 _jsname = name.replaceAll('.', '_').replaceAll(':', '_').replaceAll( | |
53 ' ', '_'); | |
54 } | |
55 return _jsname; | |
56 } | |
57 | |
58 SourceSpan get span() => new SourceSpan(baseSource, 0, 0); | 52 SourceSpan get span() => new SourceSpan(baseSource, 0, 0); |
59 | 53 |
60 String makeFullPath(String filename) { | 54 String makeFullPath(String filename) { |
61 if (filename.startsWith('dart:')) return filename; | 55 if (filename.startsWith('dart:')) return filename; |
62 // TODO(jmesserly): replace with node.js path.resolve | 56 // TODO(jmesserly): replace with node.js path.resolve |
63 if (filename.startsWith('/')) return filename; | 57 if (filename.startsWith('/')) return filename; |
64 if (filename.startsWith('file:///')) return filename; | 58 if (filename.startsWith('file:///')) return filename; |
65 if (filename.startsWith('http://')) return filename; | 59 if (filename.startsWith('http://')) return filename; |
66 return joinPaths(sourceDir, filename); | 60 return joinPaths(sourceDir, filename); |
67 } | 61 } |
(...skipping 23 matching lines...) Expand all Loading... |
91 if (member.declaringType.isTop) { | 85 if (member.declaringType.isTop) { |
92 world._addTopName(member); | 86 world._addTopName(member); |
93 } | 87 } |
94 return; | 88 return; |
95 } | 89 } |
96 | 90 |
97 var mset = _privateMembers[member.name]; | 91 var mset = _privateMembers[member.name]; |
98 if (mset == null) { | 92 if (mset == null) { |
99 // TODO(jimhug): Make this lazier! | 93 // TODO(jimhug): Make this lazier! |
100 for (var lib in world.libraries.getValues()) { | 94 for (var lib in world.libraries.getValues()) { |
101 if (lib._privateMembers.containsKey(member.name)) { | 95 if (lib._privateMembers.containsKey(member.jsname)) { |
102 member.jsname = '_$jsname${member.name}'; | 96 member._jsname = '_$jsname${member.jsname}'; |
103 break; | 97 break; |
104 } | 98 } |
105 } | 99 } |
106 | 100 |
107 mset = new MemberSet(member); | 101 mset = new MemberSet(member); |
108 _privateMembers[member.name] = mset; | 102 _privateMembers[member.name] = mset; |
109 } else { | 103 } else { |
110 mset.members.add(member); | 104 mset.members.add(member); |
111 } | 105 } |
112 } else { | 106 } else { |
113 world._addMember(member); | 107 world._addMember(member); |
114 } | 108 } |
115 } | 109 } |
116 | 110 |
117 // TODO(jimhug): Cache and share the types as interfaces? | 111 // TODO(jimhug): Cache and share the types as interfaces! |
118 Type getOrAddFunctionType(String name, FunctionDefinition func, Type inType) { | 112 Type getOrAddFunctionType(Element enclosingElement, String name, |
| 113 FunctionDefinition func) { |
| 114 // TODO(jimhug): This is redundant now that FunctionDef has type params. |
119 final def = new FunctionTypeDefinition(func, null, func.span); | 115 final def = new FunctionTypeDefinition(func, null, func.span); |
120 final type = new DefinedType(name, this, def, false); | 116 final type = new DefinedType(name, this, def, false); |
121 type.addMethod('\$call', func); | 117 type.addMethod('\$call', func); |
122 type.members['\$call'].resolve(inType); | 118 var m = type.members['\$call']; |
| 119 m.enclosingElement = enclosingElement; |
| 120 m.resolve(); |
123 // Function types implement the Function interface. | 121 // Function types implement the Function interface. |
124 type.interfaces = [world.functionType]; | 122 type.interfaces = [world.functionType]; |
125 return type; | 123 return type; |
126 } | 124 } |
127 | 125 |
128 /** Adds a type to the library. */ | 126 /** Adds a type to the library. */ |
129 DefinedType addType(String name, Node definition, bool isClass) { | 127 DefinedType addType(String name, Node definition, bool isClass) { |
130 if (types.containsKey(name)) { | 128 if (types.containsKey(name)) { |
131 var existingType = types[name]; | 129 var existingType = types[name]; |
132 if (isCore && existingType.definition == null) { | 130 if (isCore && existingType.definition == null) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 if (ret != null && ret != newRet) { | 182 if (ret != null && ret != newRet) { |
185 world.error('conflicting types for "$name"', ret.span, newRet.span); | 183 world.error('conflicting types for "$name"', ret.span, newRet.span); |
186 } else { | 184 } else { |
187 ret = newRet; | 185 ret = newRet; |
188 } | 186 } |
189 } | 187 } |
190 } | 188 } |
191 return ret; | 189 return ret; |
192 } | 190 } |
193 | 191 |
| 192 Type resolveType(TypeReference node, bool typeErrors) { |
| 193 if (node == null) return world.varType; |
| 194 |
| 195 if (node.type != null) return node.type; |
| 196 |
| 197 node.type = findType(node); |
| 198 |
| 199 if (node.type == null) { |
| 200 var message = 'cannot find type ${_getDottedName(node)}'; |
| 201 if (typeErrors) { |
| 202 world.error(message, node.span); |
| 203 node.type = world.objectType; |
| 204 } else { |
| 205 world.warning(message, node.span); |
| 206 node.type = world.varType; |
| 207 } |
| 208 } |
| 209 return node.type; |
| 210 } |
| 211 |
| 212 static String _getDottedName(NameTypeReference type) { |
| 213 if (type.names != null) { |
| 214 var names = map(type.names, (n) => n.name); |
| 215 return type.name.name + '.' + Strings.join(names, '.'); |
| 216 } else { |
| 217 return type.name.name; |
| 218 } |
| 219 } |
| 220 |
194 Member lookup(String name, SourceSpan span) { | 221 Member lookup(String name, SourceSpan span) { |
195 var retType = findTypeByName(name); | 222 var retType = findTypeByName(name); |
196 var ret = null; | 223 var ret = null; |
197 | 224 |
198 if (retType != null) { | 225 if (retType != null) { |
199 ret = retType.typeMember; | 226 ret = retType.typeMember; |
200 } | 227 } |
201 | 228 |
202 var newRet = topType.getMember(name); | 229 var newRet = topType.getMember(name); |
203 // TODO(jimhug): Shares too much code with body of loop. | 230 // TODO(jimhug): Shares too much code with body of loop. |
(...skipping 30 matching lines...) Expand all Loading... |
234 name = baseSource.filename; | 261 name = baseSource.filename; |
235 var index = name.lastIndexOf('/', name.length); | 262 var index = name.lastIndexOf('/', name.length); |
236 if (index >= 0) { | 263 if (index >= 0) { |
237 name = name.substring(index+1); | 264 name = name.substring(index+1); |
238 } | 265 } |
239 index = name.indexOf('.', 0); | 266 index = name.indexOf('.', 0); |
240 if (index > 0) { | 267 if (index > 0) { |
241 name = name.substring(0, index); | 268 name = name.substring(0, index); |
242 } | 269 } |
243 } | 270 } |
| 271 // TODO(jimhug): Expand to handle all illegal id characters |
| 272 _jsname = |
| 273 name.replaceAll('.', '_').replaceAll(':', '_').replaceAll(' ', '_'); |
| 274 |
244 for (var type in types.getValues()) { | 275 for (var type in types.getValues()) { |
245 type.resolve(); | 276 type.resolve(); |
246 } | 277 } |
247 } | 278 } |
248 | 279 |
249 visitSources() { | 280 visitSources() { |
250 var visitor = new _LibraryVisitor(this); | 281 var visitor = new _LibraryVisitor(this); |
251 visitor.addSource(baseSource); | 282 visitor.addSource(baseSource); |
252 } | 283 } |
253 | 284 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 } | 343 } |
313 | 344 |
314 var name; | 345 var name; |
315 switch (node.name.name) { | 346 switch (node.name.name) { |
316 case "library": | 347 case "library": |
317 name = getSingleStringArg(node); | 348 name = getSingleStringArg(node); |
318 if (library.name == null) { | 349 if (library.name == null) { |
319 library.name = name; | 350 library.name = name; |
320 // TODO(jimhug): Hack to get native fields for io and dom - generalize
. | 351 // TODO(jimhug): Hack to get native fields for io and dom - generalize
. |
321 if (name == 'node' || name == 'dom') { | 352 if (name == 'node' || name == 'dom') { |
322 library.topType.isNativeType = true; | 353 library.topType.isNative = true; |
323 } | 354 } |
324 if (seenImport || seenSource || seenResource) { | 355 if (seenImport || seenSource || seenResource) { |
325 world.error('#library must be first directive in file', node.span); | 356 world.error('#library must be first directive in file', node.span); |
326 } | 357 } |
327 } else { | 358 } else { |
328 world.error('already specified library name', node.span); | 359 world.error('already specified library name', node.span); |
329 } | 360 } |
330 break; | 361 break; |
331 | 362 |
332 case "import": | 363 case "import": |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 | 480 |
450 void visitFunctionDefinition(FunctionDefinition node) { | 481 void visitFunctionDefinition(FunctionDefinition node) { |
451 currentType.addMethod(node.name.name, node); | 482 currentType.addMethod(node.name.name, node); |
452 } | 483 } |
453 | 484 |
454 void visitFunctionTypeDefinition(FunctionTypeDefinition node) { | 485 void visitFunctionTypeDefinition(FunctionTypeDefinition node) { |
455 var type = library.addType(node.func.name.name, node, false); | 486 var type = library.addType(node.func.name.name, node, false); |
456 type.addMethod('\$call', node.func); | 487 type.addMethod('\$call', node.func); |
457 } | 488 } |
458 } | 489 } |
OLD | NEW |