internal static void CheckIfThisOrBaseIsValid(Expression thisOrBase, ParserContext parser) { TopLevelEntity container = thisOrBase.TopLevelEntity; string thisOrBaseString = thisOrBase.FirstToken.Value; FunctionDefinition funcDef = container as FunctionDefinition; if (funcDef != null) { if (funcDef.Modifiers.HasStatic) { throw new ParserException(thisOrBase, "Cannot use '" + thisOrBaseString + "' in a static method"); } if (funcDef.Owner == null) { throw new ParserException(thisOrBase, "Cannot use '" + thisOrBaseString + "' in a function that isn't a class method."); } } else { FieldDefinition fieldDef = container as FieldDefinition; if (fieldDef != null) { if (fieldDef.Modifiers.HasStatic) { throw new ParserException(thisOrBase, "Cannot use '" + thisOrBaseString + "' in a static field value."); } } else { ConstructorDefinition ctorDef = container as ConstructorDefinition; if (ctorDef != null && ctorDef.Modifiers.HasStatic) { throw new ParserException(thisOrBase, "Cannot use '" + thisOrBaseString + "' in a static constructor."); } } } }
internal override void ResolveTypes(ParserContext parser, TypeResolver typeResolver) { for (int i = 0; i < this.ArgNames.Length; ++i) { this.ArgLocalIds[i].ResolvedType = typeResolver.ResolveType(this.ArgTypes[i]); } foreach (Expression defaultArg in this.DefaultValues) { if (defaultArg != null) { defaultArg.ResolveTypes(parser, typeResolver); } } ClassDefinition cd = (ClassDefinition)this.Owner; if (this.Modifiers.HasStatic) { // already verified that there's no base constructor invocation } else if (cd.BaseClass != null) { ConstructorDefinition baseConstructor = cd.BaseClass.Constructor; ResolvedType[] baseConstructorArgTypes = baseConstructor == null ? new ResolvedType[0] : baseConstructor.ResolvedArgTypes; Expression[] baseConstructorDefaultValues = baseConstructor == null ? new Expression[0] : baseConstructor.DefaultValues; int optionalArgCount = FunctionCall.CountOptionalArgs(baseConstructorDefaultValues); int maxArgCount = baseConstructorArgTypes.Length; int minArgCount = maxArgCount - optionalArgCount; if (this.BaseArgs.Length < minArgCount || this.BaseArgs.Length > maxArgCount) { if (this.FirstToken == null) { throw new ParserException(cd.FirstToken, "The class '" + cd.NameToken.Value + "' cannot have an implicit constructor since it needs to pass arguments to the base constructor of '" + cd.BaseClass.NameToken.Value + "'."); } if (this.BaseToken == null) { throw new ParserException(this, "You are missing a call to the base constructor, which is required because class '" + baseConstructor.ClassOwner.NameToken.Value + "' requires arguments for its constructor."); } throw new ParserException(this, "Incorrect number of arguments passed to base constructor."); } for (int i = 0; i < this.BaseArgs.Length; ++i) { this.BaseArgs[i] = this.BaseArgs[i].ResolveTypes(parser, typeResolver); ResolvedType actualType = this.BaseArgs[i].ResolvedType; ResolvedType expectedType = baseConstructorArgTypes[i]; if (!actualType.CanAssignToA(expectedType)) { throw new ParserException(this.BaseArgs[i], "Argument is incorrect type."); } if (actualType == parser.TypeContext.ANY && expectedType != parser.TypeContext.OBJECT && expectedType != parser.TypeContext.ANY) { this.BaseArgs[i] = new Cast(this.BaseArgs[i].FirstToken, expectedType, this.BaseArgs[i], this, false); } } } foreach (Executable line in this.Code) { line.ResolveTypes(parser, typeResolver); } }