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) { 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 == ResolvedType.ANY && expectedType != ResolvedType.OBJECT && expectedType != ResolvedType.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); } }
internal override Expression Resolve(ParserContext parser) { for (int i = 0; i < this.Args.Length; ++i) { this.Args[i] = this.Args[i].Resolve(parser); } if (this.Class == null) { throw new ParserException(this.FirstToken, "No class named '" + this.Name + "'"); } if (this.Class.StaticToken != null) { throw new ParserException(this.FirstToken, "Cannot instantiate a static class."); } ConstructorDefinition cons = this.Class.Constructor; if (cons.Annotations.IsPrivate()) { bool isValidUsage = this.Class == this.Owner || // used in a field where the owner is the class directly this.Class == this.Owner.Owner; // used in a function where the owner is the method whose owner is the class. if (!isValidUsage) { throw new ParserException(this.FirstToken, "The constructor for " + this.Class.NameToken.Value + " is private and cannot be invoked from outside the class."); } } if (this.Args.Length < cons.MinArgCount || this.Args.Length > cons.MaxArgCount) { string message = "This constructor has the wrong number of arguments. "; if (cons.MinArgCount == cons.MaxArgCount) { message += "Expected " + cons.MinArgCount + " but found " + this.Args.Length; } else if (this.Args.Length < cons.MinArgCount) { message += " At least " + cons.MinArgCount + " are required but found only " + this.Args.Length + "."; } else { message += " At most " + cons.MaxArgCount + " are allowed but found " + this.Args.Length + "."; } throw new ParserException(this.FirstToken, message); } return(this); }
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 Expression ResolveNames(ParserContext parser) { if (this.Name == "$$$") { throw new ParserException(this.FirstToken, "Core function invocations cannot stand alone and must be immediately invoked."); } if (this.Name.StartsWith("$$")) { return(new LibraryFunctionReference(this.FirstToken, this.Name.Substring(2), this.Owner)); } if (this.Name == "this" || this.Name == "base") { TopLevelConstruct container = parser.CurrentCodeContainer; if (container is FunctionDefinition) { FunctionDefinition funcDef = (FunctionDefinition)this.Owner; if (funcDef.IsStaticMethod) { throw new ParserException(this.FirstToken, "Cannot use '" + this.Name + "' in a static method"); } if (funcDef.Owner == null) { throw new ParserException(this.FirstToken, "Cannot use '" + this.Name + "' in a function that isn't a class method."); } } if (container is FieldDeclaration) { if (((FieldDeclaration)container).IsStaticField) { throw new ParserException(this.FirstToken, "Cannot use '" + this.Name + "' in a static field value."); } } if (container is ConstructorDefinition) { ConstructorDefinition constructor = (ConstructorDefinition)container; if (constructor == ((ClassDefinition)constructor.Owner).StaticConstructor) // TODO: This check is silly. Add an IsStatic field to ConstructorDefinition. { throw new ParserException(this.FirstToken, "Cannot use '" + this.Name + "' in a static constructor."); } } if (this.Name == "this") { return(new ThisKeyword(this.FirstToken, this.Owner)); } return(new BaseKeyword(this.FirstToken, this.Owner)); } NamespaceReferenceTemplate nrt = this.Owner.FileScope.FileScopeEntityLookup.DoNamespaceLookup(this.Name, this.Owner); if (nrt != null) { return(new NamespaceReference(this.FirstToken, this.Owner, nrt)); } TopLevelConstruct exec = this.Owner.FileScope.FileScopeEntityLookup.DoEntityLookup(this.Name, this.Owner); if (exec != null) { return(Resolver.ResolverPipeline.ConvertStaticReferenceToExpression(exec, this.FirstToken, this.Owner)); } return(this); }