internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { // Args already resolved by FunctionInvocation.ResolveType(). string name = this.FunctionRef.Name; ExtensibleFunction extensibleFunction; if (!compiler.ExtensibleFunctions.TryGetValue(name, out extensibleFunction)) { throw new ParserException(this.FirstToken, "Type information for '" + name + "' extensible function is not defined."); } this.ResolvedType = extensibleFunction.ReturnType; PType[] argTypes = extensibleFunction.ArgTypes; if (argTypes.Length != this.Args.Length) { throw new ParserException(this.FirstToken, "Incorrect number of args for this function. Expected " + argTypes.Length + " but instead found " + this.Args.Length + "."); } for (int i = 0; i < this.Args.Length; ++i) { if (!PType.CheckAssignment(compiler, argTypes[i], this.Args[i].ResolvedType)) { throw new ParserException(this.Args[i].FirstToken, "Invalid argument type. Expected '" + argTypes[i] + "' but found '" + this.Args[i].ResolvedType + "'."); } } return(this); }
internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { for (int i = 0; i < this.Args.Length; ++i) { this.Args[i] = this.Args[i].ResolveType(varScope, compiler); } this.Root = this.Root.ResolveType(varScope, compiler); if (this.Root is FunctionReference) { FunctionDefinition functionDefinition = ((FunctionReference)this.Root).Function; PType[] expectedTypes = functionDefinition.ArgTypes; if (expectedTypes.Length != this.Args.Length) { throw new ParserException(this.OpenParenToken, "This function invocation has the wrong number of parameters. Expected " + expectedTypes.Length + " but found " + this.Args.Length + "."); } for (int i = 0; i < this.Args.Length; ++i) { if (!PType.CheckAssignment(expectedTypes[i], this.Args[i].ResolvedType)) { throw new ParserException(this.Args[i].FirstToken, "Wrong function arg type. Cannot convert a " + this.Args[i].ResolvedType + " to a " + expectedTypes[i]); } } this.ResolvedType = functionDefinition.ReturnType; return(this); } else if (this.Root is NativeFunctionReference) { NativeFunctionReference nfr = (NativeFunctionReference)this.Root; NativeFunctionInvocation nfi; if (nfr.Context == null) { nfi = new NativeFunctionInvocation(this.FirstToken, nfr.NativeFunctionId, this.Args); } else { nfi = new NativeFunctionInvocation(this.FirstToken, nfr.NativeFunctionId, nfr.Context, this.Args); } return(nfi.ResolveType(varScope, compiler)); } else if (this.Root is LibraryNativeFunctionReference) { return(new LibraryNativeFunctionInvocation(this.FirstToken, (LibraryNativeFunctionReference)this.Root, this.Args).ResolveType(varScope, compiler)); } else if (this.Root is ConstructorReference) { return(new ConstructorInvocation(this.FirstToken, ((ConstructorReference)this.Root).TypeToConstruct, this.Args)); } else { throw new NotImplementedException(); } }
internal override Expression ResolveWithTypeContext(PastelCompiler compiler) { for (int i = 0; i < this.Args.Length; ++i) { this.Args[i] = this.Args[i].ResolveWithTypeContext(compiler); } string type = this.Type.RootValue; switch (type) { case "Array": case "List": case "Dictionary": case "StringBuilder": break; default: PType[] resolvedArgTypes; if (this.Type.IsStruct) { StructDefinition sd = this.Type.StructDef; this.StructDefinition = sd; resolvedArgTypes = sd.FlatFieldTypes; } else if (this.Type.IsClass) { ClassDefinition cd = this.Type.ClassDef; this.ClassDefinition = cd; resolvedArgTypes = cd.Constructor.ArgTypes; } else { throw new ParserException(this.FirstToken, "Cannot instantiate this item."); } int fieldCount = resolvedArgTypes.Length; if (fieldCount != this.Args.Length) { throw new ParserException(this.FirstToken, "Incorrect number of args in constructor. Expected " + fieldCount + ", found " + this.Args.Length); } for (int i = 0; i < fieldCount; ++i) { PType actualType = this.Args[i].ResolvedType; PType expectedType = resolvedArgTypes[i]; if (!PType.CheckAssignment(compiler, expectedType, actualType)) { throw new ParserException(this.Args[i].FirstToken, "Cannot use an arg of this type for this " + (this.Type.IsClass ? "constructor argument" : "struct field") + ". Expected " + expectedType.ToString() + " but found " + actualType.ToString()); } } break; } return(this); }
internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler) { this.Value = this.Value.ResolveType(varScope, compiler); if (!PType.CheckAssignment(this.Type, this.Value.ResolvedType)) { throw new ParserException(this.Value.FirstToken, "Cannot assign this type to a " + this.Type); } varScope.DeclareVariables(this.VariableNameToken, this.Type); }
private void VerifyArgTypes(PType[] expectedTypes, PastelCompiler compiler) { if (expectedTypes.Length != this.Args.Length) { throw new ParserException(this.OpenParenToken, "This function invocation has the wrong number of parameters. Expected " + expectedTypes.Length + " but found " + this.Args.Length + "."); } for (int i = 0; i < this.Args.Length; ++i) { if (!PType.CheckAssignment(compiler, expectedTypes[i], this.Args[i].ResolvedType)) { throw new ParserException(this.Args[i].FirstToken, "Wrong function arg type. Cannot convert a " + this.Args[i].ResolvedType + " to a " + expectedTypes[i]); } } }
internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler) { this.Value = this.Value.ResolveType(varScope, compiler); this.Target = this.Target.ResolveType(varScope, compiler); if (!PType.CheckAssignment(this.Target.ResolvedType, this.Value.ResolvedType)) { if (this.OpToken.Value != "=" && this.Target.ResolvedType.IsIdentical(PType.DOUBLE) && this.Value.ResolvedType.IsIdentical(PType.INT)) { // You can apply incremental ops such as += with an int to a float and that is fine without explicit conversion in any platform. } else { throw new ParserException(this.OpToken, "Cannot assign a " + this.Value.ResolvedType + " to a " + this.Target.ResolvedType); } } }
internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { // The args were already resolved. // This ensures that they match the native function definition PType[] expectedTypes = NativeFunctionUtil.GetNativeFunctionArgTypes(this.Function); bool[] isArgRepeated = NativeFunctionUtil.GetNativeFunctionIsArgTypeRepeated(this.Function); switch (this.Function) { case NativeFunction.FORCE_PARENS: if (this.Args.Length != 1) { throw new ParserException(this.FirstToken, "Expected 1 arg."); } return(new ForcedParenthesis(this.FirstToken, this.Args[0])); case NativeFunction.IS_DEBUG: #if DEBUG bool value = true; #else bool value = false; #endif return(new InlineConstant(PType.BOOL, this.FirstToken, value)); } Dictionary <string, PType> templateLookup = new Dictionary <string, PType>(); int verificationLength = expectedTypes.Length; if (verificationLength > 0 && isArgRepeated[isArgRepeated.Length - 1]) { verificationLength--; } for (int i = 0; i < verificationLength; ++i) { if (!PType.CheckAssignmentWithTemplateOutput(expectedTypes[i], this.Args[i].ResolvedType, templateLookup)) { throw new ParserException(this.Args[i].FirstToken, "Incorrect type. Expected " + expectedTypes[i] + " but found " + this.Args[i].ResolvedType + "."); } } if (expectedTypes.Length < this.Args.Length) { if (isArgRepeated[isArgRepeated.Length - 1]) { PType expectedType = expectedTypes[expectedTypes.Length - 1]; for (int i = expectedTypes.Length; i < this.Args.Length; ++i) { if (!PType.CheckAssignment(expectedType, this.Args[i].ResolvedType)) { throw new ParserException(this.Args[i].FirstToken, "Incorrect type. Expected " + expectedTypes[i] + " but found " + this.Args[i].ResolvedType + "."); } } } else { throw new ParserException(this.FirstToken, "Too many arguments."); } } PType returnType = NativeFunctionUtil.GetNativeFunctionReturnType(this.Function); if (returnType.HasTemplates) { returnType = returnType.ResolveTemplates(templateLookup); } this.ResolvedType = returnType; return(this); }