internal override Expression ResolveNames(Parser 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)); } TopLevelConstruct exec = this.Owner.FileScope.FileScopeEntityLookup.DoLookup(this.Name, this.Owner); if (exec != null) { return(Resolver.ConvertStaticReferenceToExpression(exec, this.FirstToken, this.Owner)); } return(this); }
internal override Expression Resolve(Parser parser) { string className = this.NameToken.Value; if (parser.IsTranslateMode) { StructDefinition structDefinition = parser.GetStructDefinition(className); if (structDefinition != null) { if (this.Args.Length != structDefinition.Fields.Length) { throw new ParserException(this.FirstToken, "Args length did not match struct field count for '" + structDefinition.Name.Value + "'."); } StructInstance si = new StructInstance(this.FirstToken, this.NameToken, this.Args, this.FunctionOrClassOwner); si = (StructInstance)si.Resolve(parser); return(si); } } 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.PrivateAnnotation != null) { if (this.Class != this.FunctionOrClassOwner.FunctionOrClassOwner) { string errorMessage = "The constructor for " + this.Class.NameToken.Value + " is private and cannot be invoked from outside the class."; if (cons.PrivateAnnotation.Args.Length > 0) { StringConstant stringMessage = cons.PrivateAnnotation.Args[0] as StringConstant; if (stringMessage != null) { errorMessage += " " + stringMessage.Value.Trim(); } } throw new ParserException(this.FirstToken, errorMessage); } } 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 override Expression Resolve(Parser 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.PrivateAnnotation != null) { bool isValidUsage = this.Class == this.FunctionOrClassOwner || this.Class == this.FunctionOrClassOwner.FunctionOrClassOwner; if (!isValidUsage) { string errorMessage = "The constructor for " + this.Class.NameToken.Value + " is private and cannot be invoked from outside the class."; if (cons.PrivateAnnotation.Args.Length > 0) { StringConstant stringMessage = cons.PrivateAnnotation.Args[0] as StringConstant; if (stringMessage != null) { errorMessage += " " + stringMessage.Value.Trim(); } } throw new ParserException(this.FirstToken, errorMessage); } } 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); }
private void CompileConstructor(Parser parser, ByteBuffer buffer, ConstructorDefinition constructor) { // TODO: throw parser exception in the resolver if a return appears with any value ByteBuffer tBuffer = new ByteBuffer(); ClassDefinition cd = (ClassDefinition)constructor.FunctionOrClassOwner; List<int> offsetsForOptionalArgs = new List<int>(); this.CompileFunctionArgs(parser, tBuffer, constructor.ArgNames, constructor.DefaultValues, offsetsForOptionalArgs); int minArgs = 0; int maxArgs = constructor.ArgNames.Length; for (int i = 0; i < constructor.ArgNames.Length; ++i) { if (constructor.DefaultValues[i] == null) { minArgs++; } else { break; } } if (constructor.BaseToken != null) { this.CompileExpressionList(parser, tBuffer, constructor.BaseArgs, true); tBuffer.Add( constructor.BaseToken, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.BASE_CONSTRUCTOR, constructor.BaseArgs.Length, cd.BaseClass.Constructor.FunctionID, 0, cd.BaseClass.ClassID); } this.Compile(parser, tBuffer, constructor.Code); tBuffer.Add(null, OpCode.RETURN, 0); bool isStatic = constructor == cd.StaticConstructor; List<int> args = new List<int>() { constructor.FunctionID, -1, minArgs, maxArgs, isStatic ? 4 : 3, cd.ClassID, constructor.LocalScopeSize, tBuffer.Size, offsetsForOptionalArgs.Count, }; args.AddRange(offsetsForOptionalArgs); buffer.Add(constructor.FirstToken, OpCode.FUNCTION_DEFINITION, args.ToArray()); buffer.Concat(tBuffer); }