public ClassReferenceLiteral(Token firstToken, ClassDefinition cd, Node owner) : base(firstToken, owner) { this.ClassDefinition = cd; }
public ClassReference(Token token, ClassDefinition clazz, TopLevelConstruct owner) : base(token, owner) { this.ClassDefinition = clazz; }
internal override Executable ResolveNames(ParserContext parser) { this.BatchExecutableNameResolver(parser, this.TryBlock); Common.TODO.GetCoreNameFromMetadataWithLocale(); string coreExceptionName = "Core.Exception"; ClassDefinition simpleException = Node.DoClassLookup(this.Owner, null, coreExceptionName); foreach (CatchBlock cb in this.CatchBlocks) { string[] types = cb.Types; Token[] typeTokens = cb.TypeTokens; int typeCount = types.Length; cb.TypeClasses = new ClassDefinition[typeCount]; for (int i = 0; i < typeCount; ++i) { string typeName = types[i] ?? coreExceptionName; Token token = typeTokens[i] ?? cb.CatchToken; ClassDefinition resolvedType = Node.DoClassLookup(this.Owner, token, typeName, true); if (resolvedType == null) { throw new ParserException(token, "Could not resolve class name for catch."); } if (!resolvedType.ExtendsFrom(simpleException)) { if (resolvedType.BaseClass == null && resolvedType.Library == null) { throw new ParserException(token, "This class does not extend from Core.Exception."); } else { throw new ParserException(token, "Only classes that extend from Core.Exception may be caught."); } } cb.TypeClasses[i] = resolvedType; // There's only one type, it doesn't resolve into a class, there's no variable, and there's no '.' in the type name. if (resolvedType == null && typeCount == 1 && cb.ExceptionVariableToken == null && !typeName.Contains(".")) { // ...that means this is not a type but is actually a variable. // Change the type to "Core.Exception", move this token to a variable types[0] = coreExceptionName; cb.ExceptionVariableToken = token; typeTokens[0] = null; --i; // and then try resolving again. } } /* * TODO: throw an error or warning if an exception catch is followed by a more specific catch. * e.g. * try { ... } * catch (Exception) { ... } * catch (InvalidArgumentException) { ... } */ this.BatchExecutableNameResolver(parser, cb.Code); } if (this.FinallyBlock != null) { this.BatchExecutableNameResolver(parser, this.FinallyBlock); } return(this); }
private void EnsureModifiersAndTypeSignatureConsistencyForClassMethods() { ClassDefinition classDef = (ClassDefinition)this.Owner; ClassDefinition baseClass = classDef.BaseClass; bool hasBaseClass = baseClass != null; if (hasBaseClass) { FieldDefinition hiddenField = baseClass.GetField(this.NameToken.Value, true); if (hiddenField != null) { throw new ParserException(this, "This function definition hides a field from a parent class."); } } if (!hasBaseClass) { if (this.Modifiers.HasOverride) { throw new ParserException(this, "Cannot mark a method as 'override' if it has no base class."); } } else { FunctionDefinition overriddenFunction = baseClass.GetMethod(this.NameToken.Value, true); if (overriddenFunction != null) { if (!this.Modifiers.HasOverride) { if (this.CompilationScope.IsCrayon) { // TODO: just warn if not present } else { throw new ParserException(this, "This function hides another function from a parent class. If overriding is intentional, use the 'override' keyword."); } } if (overriddenFunction.Modifiers.HasStatic) { throw new ParserException(this, "Cannot override a static method."); } if (overriddenFunction.Modifiers.AccessModifierType != this.Modifiers.AccessModifierType) { throw new ParserException(this, "This method defines a different access modifier than its overridden parent."); } if (overriddenFunction.Modifiers.AccessModifierType == AccessModifierType.PRIVATE) { throw new ParserException(this, "Cannot override a private method."); } if (overriddenFunction.Modifiers.HasInternal && overriddenFunction.CompilationScope != this.CompilationScope) { throw new ParserException(this, "Cannot override this method. It is marked as internal and is located in a different assembly."); } if (overriddenFunction.ResolvedReturnType != this.ResolvedReturnType) { if (overriddenFunction.ResolvedReturnType == ResolvedType.ANY && this.ResolvedReturnType == ResolvedType.OBJECT) { // This is fine. } else { throw new ParserException(this, "This function returns a different type than its overridden parent."); } } if (overriddenFunction.ArgTypes.Length != this.ArgTypes.Length) { throw new ParserException(this, "This function has a different number of arguments than its overridden parent."); } if (overriddenFunction.MinArgCount != this.MinArgCount) { throw new ParserException(this, "This function has a different number of optional arguments than its overridden parent."); } // TODO: if you are overridding a function between a statically and dynamically typed languagte, // the dynamic language should pick up the types from the statically typed language or the // statically typed language should require "object" types in its signature for the other direction. for (int i = 0; i < this.ArgTypes.Length; ++i) { ResolvedType expected = overriddenFunction.ResolvedArgTypes[i]; ResolvedType actual = this.ResolvedArgTypes[i]; if (actual != expected && !(actual == ResolvedType.OBJECT && expected == ResolvedType.ANY)) { throw new ParserException(this, "This function has arguments that are different types than its overridden parent."); } } } else { if (this.Modifiers.HasOverride) { throw new ParserException(this, "This function is marked as 'override', but there is no method in a parent class with the same name."); } } } }
internal override Expression ResolveNames(ParserContext parser) { this.BatchExpressionNameResolver(parser, this.Args); this.Class = Node.DoClassLookup(this.Owner, this.NameToken, this.Name); return(this); }