internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { if (this.Root is Variable && ((Variable)this.Root).Name == "Native") { string name = this.FieldName.Value; return(new ExtensibleFunctionReference(this.FirstToken, name)); } this.Root = this.Root.ResolveType(varScope, compiler); string possibleStructName = this.Root.ResolvedType.RootValue; StructDefinition structDef = compiler.GetStructDefinition(possibleStructName); if (structDef != null) { this.StructType = structDef; int fieldIndex; if (!structDef.ArgIndexByName.TryGetValue(this.FieldName.Value, out fieldIndex)) { throw new ParserException(this.FieldName, "The struct '" + structDef.NameToken.Value + "' does not have a field called '" + this.FieldName.Value + "'"); } this.ResolvedType = structDef.ArgTypes[fieldIndex]; return(this); } this.NativeFunctionId = this.DetermineNativeFunctionId(this.Root.ResolvedType, this.FieldName.Value); if (this.NativeFunctionId != NativeFunction.NONE) { return(new NativeFunctionReference(this.FirstToken, this.NativeFunctionId, this.Root)); } 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": break; default: StructDefinition sd = compiler.GetStructDefinition(this.Type.RootValue); if (sd != null) { this.StructType = sd; } break; } return(this); }
public void ResolveParentChain( Dictionary <string, StructDefinition> structDefinitions, Dictionary <StructDefinition, int> cycleCheck) { int resolutionStatus = cycleCheck[this]; if (resolutionStatus == 2) { return; // this has already been resolved } if (resolutionStatus == 1) { throw new ParserException(this.FirstToken, "The parent chain for this struct has a cycle."); } cycleCheck[this] = 1; if (this.ParentName != null) { if (!structDefinitions.ContainsKey(this.ParentName.Value)) { throw new ParserException(this.ParentName, "There is no struct by the name of '" + this.ParentName.Value + "'"); } this.Parent = structDefinitions[this.ParentName.Value]; this.Parent.ResolveParentChain(structDefinitions, cycleCheck); } cycleCheck[this] = 2; }
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 void FinalizeType(PastelCompiler compilerContext) { if (this.isTypeFinalized) { return; } this.isTypeFinalized = true; if (this.Category == TypeCategory.STRUCT_OR_CLASS) { PastelCompiler targetContext = compilerContext; if (this.Namespace != null) { if (!compilerContext.IncludedScopeNamespacesToIndex.ContainsKey(this.Namespace)) { targetContext = null; } else { int index = compilerContext.IncludedScopeNamespacesToIndex[this.Namespace]; targetContext = compilerContext.IncludedScopes[index]; } } if (targetContext != null) { this.structReference = targetContext.GetStructDefinition(this.TypeName); this.classReference = targetContext.GetClassDefinition(this.TypeName); this.Category = this.structReference == null ? TypeCategory.CLASS : TypeCategory.STRUCT; } if (this.structReference == null && this.classReference == null) { throw new ParserException(this.FirstToken, "Could not find a class or struct by the name of '" + this.RootValue + "'"); } if (this.structReference != null && this.classReference != null) { throw new System.InvalidOperationException(); // this shouldn't happen. name conflicts should have been caught by now. } } for (int i = 0; i < this.Generics.Length; ++i) { this.Generics[i].FinalizeType(compilerContext); } }
internal bool IsIdenticalOrChildOf(PastelCompiler compiler, PType other) { if (this.IsIdentical(compiler, other)) { return(true); } // only structs or classes should be here if this is to return true. If not, then it's a no. if (!this.IsStructOrClass || !other.IsStructOrClass) { return(false); } if (this.IsStruct != other.IsStruct) { return(false); } if (this.IsStruct) { if (this.StructDef == null || other.StructDef == null) { throw new System.Exception("This check cannot occur without resolving struct information for PTypes."); } StructDefinition walker = this.StructDef; StructDefinition target = other.StructDef; while (walker != null) { if (walker == target) { return(true); } walker = walker.Parent; } } if (this.IsClass) { throw new System.NotImplementedException(); } return(false); }