PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/dotnet/Metadata/Definition.cs

https://bitbucket.org/bartwe/plukc
C# | 1086 lines | 1009 code | 74 blank | 3 comment | 208 complexity | 7c47ac498fe75da2c3191614651755e5 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace Compiler.Metadata
  5. {
  6. public class Definition : NodeBase
  7. {
  8. private const int fixedFields = 4;
  9. private Modifiers modifiers;
  10. private TypeName name;
  11. private DefinitionTypeReference typeReference;
  12. private List<Field> localFields = new List<Field>();
  13. private List<Field> fields;
  14. private List<Field> staticFields;
  15. private List<Constructor> constructors = new List<Constructor>();
  16. private List<Method> localMethods = new List<Method>();
  17. private List<Method> localTemplateMethods = new List<Method>();
  18. private List<Method> methods;
  19. private List<Property> localProperties = new List<Property>();
  20. private List<Property> properties;
  21. private Dictionary<string, Method> methodsMap = new Dictionary<string, Method>();
  22. private Dictionary<string, Property> propertiesMap = new Dictionary<string, Property>();
  23. private Region runtimeStructure;
  24. private List<TypeName> extendsTypeNames = new List<TypeName>();
  25. private List<DefinitionTypeReference> extends = new List<DefinitionTypeReference>();
  26. private List<DefinitionTypeReference> sparseExtends;
  27. private Set<string> imports;
  28. private List<Identifier> templateParamaters = new List<Identifier>();
  29. private DefinitionCastFunction castFunction;
  30. private Region classDescription;
  31. private List<Statement> staticInitializers = new List<Statement>();
  32. private Placeholder staticInitializerFunctionPointer;
  33. private Set<TypeReference> dependsUpon = new Set<TypeReference>();
  34. private bool fieldsInitialized;
  35. private bool staticFieldsInitialized;
  36. private List<Statement> initializers = new List<Statement>();
  37. private List<Method> templateMethods = new List<Method>();
  38. public int InstanceSize { get { return fields.Count; } }
  39. public List<Field> Fields { get { return fields; } }
  40. public List<Field> LocalFields { get { return localFields; } }
  41. public List<Method> LocalMethods { get { return localMethods; } }
  42. public List<Method> LocalTemplateMethods { get { return localTemplateMethods; } }
  43. public List<Constructor> Constructors { get { return constructors; } }
  44. public bool IsTemplate { get { return templateParamaters.Count > 0; } }
  45. public DefinitionTypeReference TypeReference { get { return typeReference; } }
  46. public List<DefinitionTypeReference> Extends { get { return extends; } }
  47. public List<DefinitionTypeReference> SparseExtends { get { Require.Assigned(sparseExtends); return sparseExtends; } }
  48. public Modifiers Modifiers { get { return modifiers; } }
  49. public Placeholder StaticInitializerFunctionPointer { get { return staticInitializerFunctionPointer; } }
  50. public int DependsOrder;
  51. public bool FieldsInitialized { get { return fieldsInitialized; } }
  52. public bool StaticFieldsInitialized { get { return staticFieldsInitialized; } }
  53. public bool GarbageCollectable
  54. {
  55. get
  56. {
  57. if ((name.DataModifierLess == "pluk.base.Bool") ||
  58. (name.DataModifierLess == "pluk.base.Byte") ||
  59. (name.DataModifierLess == "pluk.base.Int") ||
  60. (name.DataModifierLess == "pluk.base.Float") ||
  61. (name.DataModifierLess == "pluk.base.Type") ||
  62. (name.DataModifierLess == "pluk.base.StaticString"))
  63. return false;
  64. return true;
  65. }
  66. }
  67. public Placeholder RuntimeStruct
  68. {
  69. get { return runtimeStructure.BaseLocation; }
  70. }
  71. public Definition(ILocation location, Set<string> imports, Modifiers modifiers)
  72. : base(location)
  73. {
  74. if (imports == null)
  75. throw new ArgumentNullException("imports");
  76. if (modifiers == null)
  77. throw new ArgumentNullException("modifiers");
  78. this.imports = imports;
  79. this.modifiers = modifiers;
  80. typeReference = new DefinitionTypeReference(this, this);
  81. }
  82. public TypeName Name { get { return name; } }
  83. public Definition InstantiateTemplate(TypeName typeName, List<TypeReference> parameters)
  84. {
  85. if (parameters.Count != templateParamaters.Count)
  86. {
  87. TypeName myTypeName = new TypeName(name.PrimaryName);
  88. foreach (Identifier param in templateParamaters)
  89. myTypeName.AddTemplateParameter(new TypeName(param));
  90. throw new CompilerException(typeName, string.Format(Resource.Culture, Resource.TemplateParameterMismatch, typeName.Data, myTypeName.Data));
  91. }
  92. Dictionary<string, TypeName> parameterMapping = new Dictionary<string, TypeName>();
  93. for (int i = 0; i < parameters.Count; ++i)
  94. parameterMapping[templateParamaters[i].Data] = parameters[i].TypeName;
  95. Definition result = new Definition(this, imports, modifiers);
  96. TypeName definitionName = new TypeName(typeName.PrimaryName, Compiler.Metadata.Nullability.NotNullable);
  97. foreach (TypeReference tr in parameters)
  98. definitionName.AddTemplateParameter(tr.TypeName);
  99. result.name = definitionName;
  100. foreach (Field field in localFields)
  101. {
  102. Field fieldMetadata = field.InstantiateTemplate(parameterMapping);
  103. fieldMetadata.SetParentDefinition(result);
  104. result.localFields.Add(fieldMetadata);
  105. }
  106. foreach (Method method in localMethods)
  107. {
  108. Method methodMetadata = method.InstantiateTemplate(parameterMapping);
  109. methodMetadata.SetParentDefinition(result);
  110. result.localMethods.Add(methodMetadata);
  111. }
  112. foreach (Property property in localProperties)
  113. {
  114. Property propertyMetadata = property.InstantiateTemplate(parameterMapping);
  115. propertyMetadata.SetParentDefinition(result);
  116. result.localProperties.Add(propertyMetadata);
  117. }
  118. foreach (Method method in localTemplateMethods)
  119. {
  120. Method methodMetadata = method.InstantiateTemplate(parameterMapping);
  121. methodMetadata.SetParentDefinition(result);
  122. result.localTemplateMethods.Add(methodMetadata);
  123. }
  124. foreach (Constructor constructor in constructors)
  125. {
  126. Constructor c = constructor.InstantiateTemplate(parameterMapping);
  127. c.SetParentDefinition(result);
  128. result.Constructors.Add(c);
  129. }
  130. foreach (TypeName extends in extendsTypeNames)
  131. result.extendsTypeNames.Add(extends.InstantiateTemplate(parameterMapping));
  132. foreach (Statement statement in staticInitializers)
  133. result.staticInitializers.Add(statement.InstantiateTemplate(parameterMapping));
  134. foreach (Statement statement in initializers)
  135. result.initializers.Add(statement.InstantiateTemplate(parameterMapping));
  136. return result;
  137. }
  138. public bool Supports(DefinitionTypeReference type)
  139. {
  140. if (type == typeReference)
  141. return true;
  142. if (extends.Contains(type))
  143. return true;
  144. return false;
  145. }
  146. public int SupportsDistance(DefinitionTypeReference type)
  147. {
  148. if (type == typeReference)
  149. return 0;
  150. if (sparseExtends.Contains(type))
  151. return 1;
  152. int lowest = int.MaxValue - 1;
  153. foreach (DefinitionTypeReference extends in sparseExtends)
  154. {
  155. int c = extends.Definition.SupportsDistance(type);
  156. if (c < lowest)
  157. lowest = c;
  158. }
  159. return lowest + 1;
  160. }
  161. public void DependsUpon(TypeReference type)
  162. {
  163. Require.Assigned(type);
  164. dependsUpon.Put(type);
  165. }
  166. private bool updatingDepends;
  167. private void SetDependsOrder(int order)
  168. {
  169. if (updatingDepends)
  170. return;
  171. if (order > DependsOrder)
  172. {
  173. DependsOrder = order;
  174. InnerUpdateDependsOrder();
  175. }
  176. }
  177. public void UpdateDependsOrder()
  178. {
  179. if (DependsOrder == 0)
  180. {
  181. DependsOrder = 1;
  182. InnerUpdateDependsOrder();
  183. }
  184. }
  185. public void InnerUpdateDependsOrder()
  186. {
  187. int d = DependsOrder + 1;
  188. updatingDepends = true;
  189. foreach (TypeReference t in dependsUpon)
  190. if (t.IsDefinition)
  191. {
  192. Definition def = ((DefinitionTypeReference)t).Definition;
  193. def.SetDependsOrder(d);
  194. }
  195. updatingDepends = false;
  196. }
  197. public IEnumerable<KeyValuePair<int, DefinitionTypeReference>> GetSupportedTypesMap()
  198. {
  199. List<KeyValuePair<int, DefinitionTypeReference>> result = new List<KeyValuePair<int, DefinitionTypeReference>>();
  200. result.Add(new KeyValuePair<int, DefinitionTypeReference>(-1, typeReference));
  201. foreach (DefinitionTypeReference ex in extends)
  202. result.Add(new KeyValuePair<int, DefinitionTypeReference>(GetConversionOffset(ex), ex));
  203. return result;
  204. }
  205. public void SetName(Identifier name)
  206. {
  207. if (this.name != null)
  208. throw new InvalidOperationException();
  209. if (name == null)
  210. throw new ArgumentNullException("name");
  211. this.name = new TypeName(name, Nullability.NotNullable);
  212. this.name.SetHasNamespace();
  213. if (name.Data != "pluk.base.Object")
  214. AddExtends(new TypeName(new Identifier(this, "pluk.base.Object")));
  215. }
  216. public void AddStaticInitializer(Statement statement)
  217. {
  218. Require.Assigned(statement);
  219. staticInitializers.Add(statement);
  220. }
  221. public void AddInitializer(Statement statement)
  222. {
  223. Require.Assigned(statement);
  224. initializers.Add(statement);
  225. }
  226. public void AddTemplateParameter(Identifier parameter)
  227. {
  228. templateParamaters.Add(parameter);
  229. }
  230. public void AddExtends(TypeName type)
  231. {
  232. extendsTypeNames.Add(new TypeName(type, Nullability.NotNullable));
  233. }
  234. public void GetExtends(Set<DefinitionTypeReference> set)
  235. {
  236. set.PutRange(extends);
  237. }
  238. private bool SupportsType(DefinitionTypeReference type)
  239. {
  240. return extends.Contains(type);
  241. }
  242. public void AddConstructor(Constructor constructorMetadata)
  243. {
  244. if (constructorMetadata == null)
  245. throw new ArgumentNullException("constructorMetadata");
  246. constructors.Add(constructorMetadata);
  247. constructorMetadata.SetParentDefinition(this);
  248. }
  249. public void AddField(Field fieldMetadata)
  250. {
  251. CheckFieldName(fieldMetadata.Name, false);
  252. localFields.Add(fieldMetadata);
  253. fieldMetadata.SetParentDefinition(this);
  254. }
  255. public void AddMethod(Method methodMetadata)
  256. {
  257. CheckFieldName(methodMetadata.Name, true);
  258. if (methodMetadata.IsTemplateMethod)
  259. localTemplateMethods.Add(methodMetadata);
  260. else
  261. localMethods.Add(methodMetadata);
  262. methodMetadata.SetParentDefinition(this);
  263. }
  264. public void AddProperty(Property propertyMetadata)
  265. {
  266. CheckFieldName(propertyMetadata.Name, false);
  267. localProperties.Add(propertyMetadata);
  268. propertyMetadata.SetParentDefinition(this);
  269. }
  270. private void CheckFieldName(Identifier name, bool skipMethods)
  271. {
  272. foreach (Field field in localFields)
  273. if (field.Name.Data == name.Data)
  274. throw new CompilerException(name, string.Format(Resource.Culture, Resource.FieldWithNameAlreadyDefiniedOnClass, name.Data));
  275. if (!skipMethods)
  276. {
  277. foreach (Method method in localMethods)
  278. if (method.Name.Data == name.Data)
  279. throw new CompilerException(name, string.Format(Resource.Culture, Resource.FieldWithNameAlreadyDefiniedOnClass, name.Data));
  280. foreach (Method method in localTemplateMethods)
  281. if (method.Name.Data == name.Data)
  282. throw new CompilerException(name, string.Format(Resource.Culture, Resource.FieldWithNameAlreadyDefiniedOnClass, name.Data));
  283. }
  284. foreach (Property property in localProperties)
  285. if (property.Name.Data == name.Data)
  286. throw new CompilerException(name, string.Format(Resource.Culture, Resource.FieldWithNameAlreadyDefiniedOnClass, name.Data));
  287. }
  288. private void CheckIfMethodsAreUnique()
  289. {
  290. foreach (Method method in localMethods)
  291. foreach (Method inner in localMethods)
  292. if ((inner != method) && (inner.Name.Data == method.Name.Data))
  293. {
  294. if (method.Parameters.Same(inner.Parameters))
  295. throw new CompilerException(method.Name, string.Format(Resource.Culture, Resource.FieldWithNameAlreadyDefiniedOnClass, method.Signature()));
  296. }
  297. }
  298. public void Complete()
  299. {
  300. if (name == null)
  301. throw new InvalidOperationException();
  302. }
  303. private bool resolved;
  304. public void Resolve(Generator generator)
  305. {
  306. Require.False(resolved);
  307. resolved = true;
  308. generator.Resolver.SetImportsContext(imports);
  309. Require.Equals(typeReference, generator.Resolver.ResolveDefinitionType(name, name));
  310. foreach (TypeName typeName in extendsTypeNames)
  311. extends.Add(generator.Resolver.ResolveDefinitionType(typeName, typeName));
  312. if (constructors.Count == 0)
  313. {
  314. Constructor c = new Constructor(this, new Modifiers(this), new Parameters());
  315. AddConstructor(c);
  316. c.SetBody(new EmptyStatement(this));
  317. }
  318. foreach (Field field in localFields)
  319. field.Resolve(generator);
  320. foreach (Property property in localProperties)
  321. property.Resolve(generator);
  322. foreach (Method method in localMethods)
  323. method.Resolve(generator);
  324. CheckIfMethodsAreUnique();
  325. foreach (Constructor constructor in constructors)
  326. constructor.Resolve(generator);
  327. foreach (Statement statement in staticInitializers)
  328. statement.Resolve(generator);
  329. foreach (Statement statement in initializers)
  330. statement.Resolve(generator);
  331. }
  332. // collects all extends, and the extends their extends
  333. // sort it so that dependencies are earlier in the list
  334. public void PrepareExtends()
  335. {
  336. Set<DefinitionTypeReference> toVisit = new Set<DefinitionTypeReference>();
  337. Set<DefinitionTypeReference> newVisitables = new Set<DefinitionTypeReference>();
  338. newVisitables.AddRange(extends);
  339. Set<DefinitionTypeReference> loop = new Set<DefinitionTypeReference>();
  340. while (newVisitables.Count > 0)
  341. {
  342. foreach (DefinitionTypeReference typeReference in newVisitables)
  343. if (!toVisit.Contains(typeReference))
  344. loop.Add(typeReference);
  345. toVisit.AddRange(loop);
  346. newVisitables.Clear();
  347. foreach (DefinitionTypeReference typeReference in loop)
  348. typeReference.Definition.GetExtends(newVisitables);
  349. loop.Clear();
  350. }
  351. List<DefinitionTypeReference> preSortables = new List<DefinitionTypeReference>(toVisit);
  352. preSortables.Sort(SortExtends);
  353. Queue<DefinitionTypeReference> sortables = new Queue<DefinitionTypeReference>(preSortables);
  354. extends.Clear();
  355. while (sortables.Count > 0)
  356. {
  357. DefinitionTypeReference item = sortables.Dequeue();
  358. foreach (DefinitionTypeReference type in sortables)
  359. if (item.Definition.SupportsType(type))
  360. {
  361. // woops failue, try again later
  362. sortables.Enqueue(item);
  363. item = null;
  364. break;
  365. }
  366. if (item != null)
  367. extends.Add(item);
  368. }
  369. sparseExtends = new List<DefinitionTypeReference>();
  370. foreach (DefinitionTypeReference e in extends)
  371. {
  372. bool hit = true;
  373. foreach (DefinitionTypeReference x in extends)
  374. {
  375. if (x != e)
  376. if (e.Supports(x))
  377. {
  378. hit = false;
  379. break;
  380. }
  381. }
  382. if (hit)
  383. sparseExtends.Add(e);
  384. }
  385. }
  386. private int SortExtends(DefinitionTypeReference l, DefinitionTypeReference r)
  387. {
  388. return l.Definition.Name.Data.CompareTo(r.Definition.Name.Data);
  389. }
  390. private void AddProperties(List<Property> properties)
  391. {
  392. foreach (Property property in properties)
  393. {
  394. string name = property.Name.Data;
  395. if (propertiesMap.ContainsKey(name))
  396. {
  397. if (((!property.GetModifiers.Override) || (!property.SetModifiers.Override)) && (Name.Data == property.ParentDefinition.Name.Data))
  398. throw new CompilerException(property, string.Format(Resource.MissingPropertyOverride, property.Name.Data, Name.Data));
  399. this.properties.Remove(propertiesMap[name]);
  400. propertiesMap.Remove(name);
  401. }
  402. else
  403. if ((property.GetModifiers.Override) || (property.SetModifiers.Override))
  404. throw new CompilerException(property, string.Format(Resource.MissingPropertyOverrideTarget, property.Name.Data, Name.Data));
  405. propertiesMap.Add(name, property);
  406. this.properties.Add(property);
  407. }
  408. }
  409. private void AddMethods(List<Method> methods)
  410. {
  411. foreach (Method method in methods)
  412. {
  413. string name = method.Signature();
  414. if (methodsMap.ContainsKey(name))
  415. {
  416. Method baseMethod = methodsMap[name];
  417. if ((!method.Modifiers.Override) && (Name.Data == method.ParentDefinition.Name.Data))
  418. throw new CompilerException(method, string.Format(Resource.MissingMethodOverride, method.Name.Data, Name.Data));
  419. if (!baseMethod.ReturnType.Equals(method.ReturnType))
  420. throw new CompilerException(method, string.Format(Resource.MethodOverrideReturnTypeMismatch, method.Name.Data, Name.Data));
  421. this.methods.Remove(baseMethod);
  422. methodsMap.Remove(name);
  423. }
  424. else
  425. if (method.Modifiers.Override)
  426. throw new CompilerException(method, string.Format(Resource.MissingMethodOverrideTarget, method.Name.Data, Name.Data));
  427. methodsMap.Add(name, method);
  428. this.methods.Add(method);
  429. }
  430. }
  431. private void AddTemplateMethods(List<Method> methods)
  432. {
  433. foreach (Method method in methods)
  434. {
  435. templateMethods.Add(method);
  436. }
  437. }
  438. public void BeforePrepare()
  439. {
  440. Require.Unassigned(fields);
  441. Require.Unassigned(staticFields);
  442. fields = new List<Field>();
  443. staticFields = new List<Field>();
  444. foreach (Field field in localFields)
  445. {
  446. if (!field.GetModifiers.Static)
  447. fields.Add(field);
  448. else
  449. staticFields.Add(field);
  450. }
  451. properties = new List<Property>();
  452. methods = new List<Method>();
  453. foreach (DefinitionTypeReference extend in extends)
  454. {
  455. foreach (Field field in extend.Definition.LocalFields)
  456. if (!field.GetModifiers.Static)
  457. fields.Add(field);
  458. else
  459. staticFields.Add(field);
  460. AddProperties(extend.Definition.localProperties);
  461. AddMethods(extend.Definition.LocalMethods);
  462. AddTemplateMethods(extend.Definition.LocalTemplateMethods);
  463. }
  464. AddProperties(localProperties);
  465. AddMethods(localMethods);
  466. AddTemplateMethods(localTemplateMethods);
  467. templateMethods.Reverse(); // prefer early entries
  468. if (!Modifiers.Abstract)
  469. {
  470. foreach (Method method in methods)
  471. if (method.Modifiers.Abstract)
  472. throw new CompilerException(this, string.Format(Resource.MethodIsAbstract, method.Name.Data, Name.Data));
  473. foreach (Property property in properties)
  474. if (property.GetModifiers.Abstract || property.SetModifiers.Abstract)
  475. throw new CompilerException(this, string.Format(Resource.PropertyIsAbstract, property.Name.Data, Name.Data));
  476. }
  477. }
  478. public void Prepare(Generator generator)
  479. {
  480. foreach (TypeReference e in extends)
  481. dependsUpon.Put(e);
  482. generator.Resolver.EnterDefinitionContext(this);
  483. foreach (Field field in localFields)
  484. field.Prepare(generator, dependsUpon);
  485. foreach (Field field in staticFields)
  486. field.PrepareStatic(generator, dependsUpon);
  487. foreach (Constructor constructor in constructors)
  488. constructor.Prepare(generator, dependsUpon);
  489. foreach (Method method in localMethods)
  490. method.Prepare(generator, dependsUpon);
  491. foreach (Property property in localProperties)
  492. property.Prepare(generator, dependsUpon);
  493. runtimeStructure = generator.AllocateDataRegion();
  494. classDescription = generator.AllocateDataRegion();
  495. WriteTypeDescription(classDescription, generator);
  496. generator.Resolver.LeaveContext();
  497. }
  498. private void WriteTypeDescription(Region description, Generator generator)
  499. {
  500. description.WriteNumber(1);
  501. description.WritePlaceholder(generator.AddTextLengthPrefix(name.DataModifierLess));
  502. }
  503. public void PrepareNestedConstructors(Generator generator)
  504. {
  505. generator.Resolver.EnterDefinitionContext(this);
  506. foreach (Constructor constructor in constructors)
  507. constructor.PrepareNestedConstructors(generator);
  508. generator.Resolver.LeaveContext();
  509. }
  510. public void Generate(Generator generator)
  511. {
  512. generator.Resolver.EnterDefinitionContext(this);
  513. GenerateStaticInitializer(generator);
  514. staticFieldsInitialized = true;
  515. foreach (Constructor constructor in constructors)
  516. constructor.Generate(generator);
  517. fieldsInitialized = true;
  518. generator.Resolver.CheckContextEmpty();
  519. foreach (Method method in localMethods)
  520. {
  521. method.Generate(generator);
  522. generator.Resolver.CheckContextEmpty();
  523. }
  524. foreach (Property property in localProperties)
  525. property.Generate(generator);
  526. generator.Resolver.LeaveContext();
  527. castFunction = new DefinitionCastFunction(this);
  528. castFunction.Generate(generator);
  529. GenerateRuntimeStructure(generator);
  530. }
  531. private void GenerateStaticInitializer(Generator generator)
  532. {
  533. if (staticInitializers.Count == 0)
  534. return;
  535. generator.AllocateAssembler();
  536. generator.Resolver.EnterContext();
  537. int staticThisSlot = generator.Assembler.AddVariable();
  538. StaticTypeReference staticThisType = new StaticTypeReference(this, TypeReference);
  539. generator.Resolver.AddVariable(new Identifier(this, "this"), staticThisType, staticThisSlot, true);
  540. foreach (Statement statement in staticInitializers)
  541. {
  542. generator.Resolver.EnterContext();
  543. statement.Prepare(generator);
  544. generator.Resolver.LeaveAndMergeContext();
  545. }
  546. generator.Assembler.StartFunction();
  547. generator.Resolver.SetImplicitFields(staticThisSlot, staticThisType);
  548. TypeExpression te = new TypeExpression(this, staticThisType);
  549. te.Resolve(generator);
  550. te.Prepare(generator, null);
  551. te.Generate(generator);
  552. generator.Assembler.StoreVariable(staticThisSlot);
  553. foreach (Statement statement in staticInitializers)
  554. {
  555. generator.Resolver.EnterContext();
  556. statement.Generate(generator, null);
  557. generator.Resolver.LeaveAndMergeContext();
  558. }
  559. CheckAllStaticFieldsAssigned(this, generator.Resolver, true);
  560. generator.Assembler.StopFunction();
  561. generator.Symbols.Source(generator.Assembler.Region.CurrentLocation, this, SourceMark.EndSequence);
  562. generator.Symbols.WriteCode(generator.Assembler.Region.BaseLocation, generator.Assembler.Region.Length, "staticInitializer:" + Name.Data);
  563. staticInitializerFunctionPointer = generator.Assembler.Region.BaseLocation;
  564. generator.Resolver.LeaveContext();
  565. }
  566. public void PrepareInitializer(Generator generator)
  567. {
  568. if (initializers.Count == 0)
  569. return;
  570. generator.Resolver.EnterContext();
  571. foreach (Statement statement in initializers)
  572. {
  573. generator.Resolver.EnterContext();
  574. statement.Prepare(generator);
  575. generator.Resolver.LeaveAndMergeContext();
  576. }
  577. generator.Resolver.LeaveAndMergeContext();
  578. }
  579. public void GenerateInitializer(Generator generator)
  580. {
  581. if (initializers.Count == 0)
  582. return;
  583. generator.Resolver.EnterContext();
  584. foreach (Statement statement in initializers)
  585. {
  586. generator.Resolver.EnterContext();
  587. statement.Generate(generator, null);
  588. generator.Resolver.LeaveAndMergeContext();
  589. }
  590. generator.Resolver.LeaveAndMergeContext();
  591. }
  592. private void GenerateRuntimeStructure(Generator generator)
  593. {
  594. Dictionary<Definition, Region> types = new Dictionary<Definition, Region>();
  595. Dictionary<Definition, Placeholder> implicitTypeConversions = new Dictionary<Definition, Placeholder>();
  596. types[this] = runtimeStructure;
  597. implicitTypeConversions[this] = runtimeStructure.BaseLocation;
  598. foreach (DefinitionTypeReference tr in extends)
  599. {
  600. Region rts = generator.AllocateDataRegion();
  601. types.Add(tr.Definition, rts);
  602. implicitTypeConversions.Add(tr.Definition, rts.BaseLocation);
  603. }
  604. Dictionary<string, int> fieldOffsets = new Dictionary<string, int>();
  605. int fieldIndex = 0;
  606. foreach (Field field in fields)
  607. {
  608. if (fieldOffsets.ContainsKey(field.LocalName))
  609. throw new CompilerException(this, string.Format(Resource.FieldNameCollision, field.Name.Data));
  610. fieldOffsets.Add(field.LocalName, fieldIndex);
  611. fieldIndex++;
  612. }
  613. Dictionary<string, Method> methodOverrides = new Dictionary<string, Method>();
  614. foreach (Method method in methods)
  615. methodOverrides.Add(method.Signature(), method);
  616. Dictionary<string, Property> propertyOverrides = new Dictionary<string, Property>();
  617. foreach (Property property in properties)
  618. propertyOverrides.Add(property.Name.Data, property);
  619. foreach (Definition definition in types.Keys)
  620. definition.GenerateRuntimeStructure(generator, this, types[definition], implicitTypeConversions, fieldOffsets, methodOverrides, propertyOverrides);
  621. foreach (DefinitionTypeReference tr in extends)
  622. {
  623. Region rts = types[tr.Definition];
  624. generator.Symbols.WriteData(rts.BaseLocation, rts.Length, "class:" + name.Data + ":" + tr.Definition.Name.Data);
  625. }
  626. }
  627. private void GenerateRuntimeStructure(Generator generator, Definition baseDefinition, Region runtimeStructure, Dictionary<Definition, Placeholder> implicitTypeConversions, Dictionary<string, int> slotOffsets, Dictionary<string, Method> methodOverrides, Dictionary<string, Property> propertyOverrides)
  628. {
  629. Placeholder rsl = runtimeStructure.CurrentLocation;
  630. if (baseDefinition.GarbageCollectable)
  631. runtimeStructure.WriteNumber(1);
  632. else
  633. runtimeStructure.WriteNumber(0);
  634. runtimeStructure.WritePlaceholder(baseDefinition.castFunction.FunctionPointer);
  635. runtimeStructure.WritePlaceholder(baseDefinition.classDescription.BaseLocation);
  636. runtimeStructure.WriteNumber(0);
  637. foreach (Constructor constructor in constructors)
  638. runtimeStructure.WritePlaceholder(constructor.MakeRuntimeStruct(generator, implicitTypeConversions));
  639. foreach (Method localMethod in methods)
  640. {
  641. Method method = methodOverrides[localMethod.Signature()];
  642. runtimeStructure.WritePlaceholder(method.MakeMethodStruct(generator, baseDefinition, implicitTypeConversions[method.ParentDefinition]));
  643. }
  644. foreach (Property localProperty in properties)
  645. {
  646. Property property = propertyOverrides[localProperty.Name.Data];
  647. runtimeStructure.WritePlaceholder(property.MakeGetPropertyStruct(generator, baseDefinition, implicitTypeConversions[property.ParentDefinition]));
  648. runtimeStructure.WritePlaceholder(property.MakeSetPropertyStruct(generator, baseDefinition, implicitTypeConversions[property.ParentDefinition]));
  649. }
  650. foreach (Field field in fields)
  651. runtimeStructure.WriteNumberTimesBitness(slotOffsets[field.LocalName] * 2);
  652. foreach (DefinitionTypeReference tr in extends)
  653. runtimeStructure.WritePlaceholder(implicitTypeConversions[tr.Definition]);
  654. generator.Symbols.WriteData(rsl, runtimeStructure.CurrentLocation.MemoryDistanceFrom(rsl), "class:" + name.Data);
  655. }
  656. public Method FindMethod(Identifier name, bool staticRef, TypeReference inferredType, Definition context, bool throws)
  657. {
  658. List<Method> results = new List<Method>();
  659. foreach (Method method in methods)
  660. {
  661. if (!staticRef || method.Modifiers.Static)
  662. if (method.Name.Data == name.Data)
  663. results.Add(method);
  664. }
  665. foreach (Method method in templateMethods)
  666. {
  667. if (!staticRef || method.Modifiers.Static)
  668. if (method.Name.Data == name.Data)
  669. results.Add(method);
  670. }
  671. if ((inferredType != null) && (inferredType.IsNullable))
  672. inferredType = ((NullableTypeReference)inferredType).Parent;
  673. FunctionTypeReference ftr = inferredType as FunctionTypeReference;
  674. if (ftr == null)
  675. {
  676. if (results.Count == 1)
  677. {
  678. Method method = results[0];
  679. if (context != null)
  680. if (!method.Modifiers.CheckVisibility(method.ParentDefinition, context))
  681. {
  682. throw new Compiler.CompilerException(name, string.Format(Resource.NoVisibleMethod, name.Data));
  683. }
  684. if (method.IsTemplateMethod)
  685. throw new Compiler.CompilerException(name, string.Format(Resource.AmbiguousMethodReference, name.Data));
  686. return method;
  687. }
  688. if (!throws)
  689. return null;
  690. throw new Compiler.CompilerException(name, string.Format(Resource.AmbiguousMethodReference, name.Data));
  691. }
  692. Stack<Method> filtered = new Stack<Method>();
  693. bool matching = false;
  694. foreach (Method method in results)
  695. if (method.Parameters.Match(ftr.FunctionParameters))
  696. {
  697. matching = true;
  698. if (context != null)
  699. if (!method.Modifiers.CheckVisibility(method.ParentDefinition, context))
  700. continue;
  701. filtered.Push(method);
  702. }
  703. if (filtered.Count == 0)
  704. {
  705. if (!throws)
  706. return null;
  707. if (matching)
  708. throw new Compiler.CompilerException(name, string.Format(Resource.NoVisibleMethod, name.Data));
  709. if (results.Count == 0)
  710. throw new Compiler.CompilerException(name, string.Format(Resource.NoMatchingMethod, name.Data));
  711. if (results.Count == 1)
  712. throw new Compiler.CompilerException(name, string.Format(Resource.NoMatchingMethodOption, name.Data, results[0].AsTypeReference().TypeName.Data));
  713. else
  714. throw new Compiler.CompilerException(name, string.Format(Resource.NoMatchingMethodMultiple, name.Data));
  715. }
  716. Method preferred = filtered.Pop();
  717. while (filtered.Count > 0)
  718. {
  719. Method m = filtered.Pop();
  720. int c = preferred.Parameters.CompareTo(m.Parameters, ftr.FunctionParameters);
  721. if (c == 0)
  722. {
  723. if (!throws)
  724. return null;
  725. throw new Compiler.CompilerException(name, string.Format(Resource.AmbiguousMethodReference, name.Data));
  726. }
  727. if (c < 0)
  728. preferred = m;
  729. }
  730. return preferred;
  731. }
  732. public Constructor FindConstructor(ILocation location, TypeReference inferredType, Definition context)
  733. {
  734. List<Constructor> results = new List<Constructor>(constructors);
  735. if ((inferredType != null) && inferredType.IsNullable)
  736. inferredType = ((NullableTypeReference)inferredType).Parent;
  737. FunctionTypeReference ftr = inferredType as FunctionTypeReference;
  738. Stack<Constructor> filtered = new Stack<Constructor>();
  739. bool matching = false;
  740. foreach (Constructor constructor in results)
  741. {
  742. if ((ftr == null) || constructor.Parameters.Match(ftr.FunctionParameters))
  743. {
  744. matching = true;
  745. if (constructor.Modifiers.CheckVisibility(constructor.ParentDefinition, context))
  746. filtered.Push(constructor);
  747. }
  748. }
  749. if (filtered.Count == 0)
  750. {
  751. if (matching)
  752. throw new CompilerException(location, string.Format(Resource.Culture, Resource.NoVisibleConstructor, this.TypeReference.TypeName.Data));
  753. if (ftr != null)
  754. throw new CompilerException(location, string.Format(Resource.Culture, Resource.NoMatchingConstructorSignature, this.TypeReference.TypeName.Data, ftr.TypeName.Data));
  755. else
  756. throw new CompilerException(location, string.Format(Resource.Culture, Resource.NoMatchingConstructor, this.TypeReference.TypeName.Data));
  757. }
  758. if ((ftr == null) && (filtered.Count != 1))
  759. {
  760. throw new CompilerException(location, string.Format(Resource.Culture, Resource.AmbiguousConstructorReference, this.TypeReference.TypeName.Data));
  761. }
  762. Constructor preferred = filtered.Pop();
  763. while (filtered.Count > 0)
  764. {
  765. Constructor m = filtered.Pop();
  766. int c = preferred.Parameters.CompareTo(m.Parameters, ftr.FunctionParameters);
  767. if (c == 0)
  768. throw new CompilerException(location, string.Format(Resource.Culture, Resource.AmbiguousConstructorReference, this.TypeReference.TypeName.Data));
  769. if (c < 0)
  770. preferred = m;
  771. }
  772. return preferred;
  773. }
  774. public bool HasMethod(Identifier name, bool staticRef)
  775. {
  776. foreach (Method method in methods)
  777. {
  778. if (!staticRef || method.Modifiers.Static)
  779. if (method.Name.Data == name.Data)
  780. return true;
  781. }
  782. foreach (Method method in localTemplateMethods)
  783. {
  784. if (!staticRef || method.Modifiers.Static)
  785. if (method.Name.Data == name.Data)
  786. return true;
  787. }
  788. return false;
  789. }
  790. public bool HasMethod(Identifier name)
  791. {
  792. return HasMethod(name, false);
  793. }
  794. public int GetMethodOffset(ILocation location, Method method, Definition context)
  795. {
  796. int i = fixedFields + constructors.Count; // skip constructor and flags
  797. foreach (Method m in methods)
  798. {
  799. if (m == method)
  800. {
  801. if (!method.Modifiers.CheckVisibility(method.ParentDefinition, context))
  802. throw new CompilerException(location, string.Format(Resource.MethodNotVisible, method.Name.Data));
  803. return i;
  804. }
  805. ++i;
  806. }
  807. Require.NotCalled();
  808. return -1;
  809. }
  810. public bool HasProperty(Identifier name, bool staticRef)
  811. {
  812. foreach (Property property in properties)
  813. {
  814. if (!staticRef || (property.GetModifiers.Static && property.SetModifiers.Static))
  815. if (property.Name.Data == name.Data)
  816. return true;
  817. }
  818. return false;
  819. }
  820. public bool HasProperty(Identifier name)
  821. {
  822. foreach (Property property in properties)
  823. {
  824. if (property.Name.Data == name.Data)
  825. return true;
  826. }
  827. return false;
  828. }
  829. public int GetGetPropertyOffset(ILocation location, Identifier name, Definition context)
  830. {
  831. int i = fixedFields + constructors.Count + methods.Count; // skip flags and methods
  832. foreach (Property property in properties)
  833. {
  834. if (property.Name.Data == name.Data)
  835. {
  836. if (!property.GetModifiers.CheckVisibility(property.ParentDefinition, context))
  837. throw new CompilerException(location, string.Format(Resource.GetPropertyNotVisible, property.Name.Data));
  838. return i;
  839. }
  840. i += 2;
  841. }
  842. Require.NotCalled();
  843. return -1;
  844. }
  845. public int GetSetPropertyOffset(ILocation location, Identifier name, Definition context)
  846. {
  847. int i = fixedFields + constructors.Count + methods.Count + 1; // skip constructor and flags and methods
  848. foreach (Property property in properties)
  849. {
  850. if (property.Name.Data == name.Data)
  851. {
  852. if (!property.SetModifiers.CheckVisibility(property.ParentDefinition, context))
  853. throw new CompilerException(location, string.Format(Resource.SetPropertyNotVisible, property.Name.Data));
  854. return i;
  855. }
  856. i += 2;
  857. }
  858. Require.NotCalled();
  859. return -1;
  860. }
  861. public Property GetProperty(Identifier name)
  862. {
  863. foreach (Property property in properties)
  864. if (property.Name.Data == name.Data)
  865. return property;
  866. Require.NotCalled();
  867. return null;
  868. }
  869. public bool CheckAllFieldsAssigned(ILocation location, Resolver resolver, bool completeConstrucor)
  870. {
  871. foreach (Field field in fields)
  872. if (!field.CheckAssigned(resolver))
  873. {
  874. if (completeConstrucor)
  875. throw new CompilerException(location, string.Format(Resource.Culture, Resource.ObjectNotFullyAssignedConstructor, name.Data, field.Name.Data));
  876. return false;
  877. }
  878. return CheckAllStaticFieldsAssigned(location, resolver, completeConstrucor);
  879. }
  880. public bool CheckAllStaticFieldsAssigned(ILocation location, Resolver resolver, bool completeConstrucor)
  881. {
  882. if (staticFieldsInitialized)
  883. return true;
  884. foreach (Field field in staticFields)
  885. if (!field.CheckAssigned(resolver))
  886. {
  887. if (completeConstrucor)
  888. throw new CompilerException(location, string.Format(Resource.Culture, Resource.ObjectNotFullyAssignedConstructor, name.Data, field.Name.Data));
  889. return false;
  890. }
  891. return true;
  892. }
  893. public bool HasField(Identifier name, bool staticRef)
  894. {
  895. if (!staticRef)
  896. foreach (Field field in fields)
  897. if (field.Name.Data == name.Data)
  898. return true;
  899. foreach (Field field in staticFields)
  900. if (field.Name.Data == name.Data)
  901. return true;
  902. return false;
  903. }
  904. public bool HasField(Identifier name)
  905. {
  906. foreach (Field field in fields)
  907. if (field.Name.Data == name.Data)
  908. return true;
  909. foreach (Field field in staticFields)
  910. if (field.Name.Data == name.Data)
  911. return true;
  912. return false;
  913. }
  914. public int GetFieldOffset(ILocation location, Identifier name, Definition context, bool forWrite)
  915. {
  916. int i = fixedFields + constructors.Count + methods.Count + (2 * properties.Count); // skip constructor, flags and methods
  917. foreach (Field field in fields)
  918. {
  919. if (field.Name.Data == name.Data)
  920. {
  921. if (forWrite)
  922. {
  923. if (!field.SetModifiers.CheckVisibility(field.ParentDefinition, context))
  924. throw new CompilerException(location, string.Format(Resource.FieldNotVisible, field.Name.Data));
  925. }
  926. else
  927. {
  928. if (!field.GetModifiers.CheckVisibility(field.ParentDefinition, context))
  929. throw new CompilerException(location, string.Format(Resource.FieldNotVisible, field.Name.Data));
  930. }
  931. return i;
  932. }
  933. ++i;
  934. }
  935. Require.NotCalled();
  936. return -1;
  937. }
  938. public Field GetField(Identifier name, bool staticRef)
  939. {
  940. if (!staticRef)
  941. foreach (Field field in fields)
  942. {
  943. if (field.Name.Data == name.Data)
  944. return field;
  945. }
  946. foreach (Field field in staticFields)
  947. {
  948. if (field.Name.Data == name.Data)
  949. return field;
  950. }
  951. Require.NotCalled();
  952. return null;
  953. }
  954. public int GetConversionOffset(DefinitionTypeReference type)
  955. {
  956. Require.True(Supports(type));
  957. int i = fixedFields + constructors.Count + methods.Count + (2 * properties.Count) + fields.Count; // skip constructor, flags, methods and fields
  958. foreach (TypeReference tr in extends)
  959. {
  960. if (tr == type)
  961. return i;
  962. ++i;
  963. }
  964. Require.NotCalled();
  965. return -1;
  966. }
  967. public override string ToString()
  968. {
  969. return name.Data;
  970. }
  971. private Method FindImplicitConversion(Definition from, Definition to)
  972. {
  973. Require.True((from == this) || (to == this));
  974. Method best = null;
  975. int distance = int.MaxValue;
  976. foreach (Method method in LocalMethods)
  977. if (method.ImplicitConverter)
  978. {
  979. if (method.ReturnType.Supports(to.TypeReference)
  980. && to.TypeReference.Supports(method.ReturnType)
  981. && method.Parameters.ParameterList[0].TypeReference.Supports(from.TypeReference))
  982. {
  983. int d = method.Parameters.ParameterList[0].TypeReference.Distance(from.TypeReference);
  984. if (d < distance)
  985. best = method;
  986. }
  987. }
  988. return best;
  989. }
  990. public bool SupportsImplicitConversion(Definition from, Definition to)
  991. {
  992. return FindImplicitConversion(from, to) != null;
  993. }
  994. public void CallImplicitConversion(Generator generator, Definition from, Definition to)
  995. {
  996. Method method = FindImplicitConversion(from, to);
  997. Require.Assigned(method);
  998. JumpToken skipNull = generator.Assembler.CreateJumpToken();
  999. generator.Assembler.JumpIfUnassigned(skipNull);
  1000. generator.Assembler.PushValue();
  1001. generator.Assembler.SetImmediateValue(RuntimeStruct, 0);
  1002. int offset = GetMethodOffset(this, method, generator.Resolver.CurrentDefinition);
  1003. generator.Assembler.FetchMethod(offset);
  1004. generator.Assembler.PushValue();
  1005. generator.Assembler.PeekValue(1);
  1006. generator.Assembler.PushValue();
  1007. generator.Assembler.CallFromStack(1);
  1008. generator.Assembler.DropStackTop();
  1009. generator.Assembler.SetDestination(skipNull);
  1010. }
  1011. }
  1012. }