internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { this.Expression = this.Expression.ResolveType(varScope, compiler); if (!this.Expression.ResolvedType.IsIdentical(PType.INT)) { throw new ParserException(this.IncrementToken, "++ and -- can only be applied to integer types."); } this.ResolvedType = PType.INT; return(this); }
public override Executable ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { if (this.Value == null) { throw new ParserException(this.FirstToken, "Cannot have variable declaration without a value."); } this.Value = this.Value.ResolveNamesAndCullUnusedCode(compiler); 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); }
internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler) { // This gets compiled as a wihle loop with the init added before the loop, so it should go in the same variable scope. // The implication is that multiple declarations in the init for successive loops will collide. Executable.ResolveTypes(this.InitCode, varScope, compiler); this.Condition = this.Condition.ResolveType(varScope, compiler); Executable.ResolveTypes(this.StepCode, varScope, compiler); VariableScope innerScope = new VariableScope(varScope); Executable.ResolveTypes(this.Code, innerScope, compiler); }
internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler) { this.Condition = this.Condition.ResolveType(varScope, compiler); if (this.Condition.ResolvedType.RootValue != "bool") { throw new ParserException(this.Condition.FirstToken, "Only booleans can be used in if statements."); } Executable.ResolveTypes(this.IfCode, new VariableScope(varScope), compiler); Executable.ResolveTypes(this.ElseCode, new VariableScope(varScope), compiler); }
internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { PType type = varScope.GetTypeOfVariable(this.Name); this.ResolvedType = type; if (type == null) { throw new ParserException(this.FirstToken, "The variable '" + this.Name + "' is not defined."); } return(this); }
public override Executable ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { this.InitCode = Executable.ResolveNamesAndCullUnusedCodeForBlock(this.InitCode, compiler).ToArray(); this.Condition = this.Condition.ResolveNamesAndCullUnusedCode(compiler); this.StepCode = Executable.ResolveNamesAndCullUnusedCodeForBlock(this.StepCode, compiler).ToArray(); // TODO: check Condition for falseness this.Code = Executable.ResolveNamesAndCullUnusedCodeForBlock(this.Code, compiler).ToArray(); return(this); }
internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { this.Root = this.Root.ResolveType(varScope, compiler); PType rootType = this.Root.ResolvedType; if (rootType.IsStructOrClass) { string fieldName = this.FieldName.Value; rootType.FinalizeType(compiler); if (rootType.IsStruct) { this.StructType = rootType.StructDef; int fieldIndex; if (!this.StructType.FlatFieldIndexByName.TryGetValue(fieldName, out fieldIndex)) { throw new ParserException(this.FieldName, "The struct '" + this.StructType.NameToken.Value + "' does not have a field called '" + fieldName + "'."); } this.ResolvedType = this.StructType.FlatFieldTypes[fieldIndex]; } else { this.ClassType = rootType.ClassDef; if (!this.ClassType.Members.ContainsKey(this.FieldName.Value)) { throw new ParserException(this.FieldName, "The class '" + this.ClassType.NameToken.Value + "' does not have a member called '" + fieldName + "'."); } ICompilationEntity ce = this.ClassType.Members[fieldName]; if (ce is FieldDefinition fd) { this.ResolvedType = fd.FieldType; } else { FunctionDefinition func = (FunctionDefinition)ce; this.ResolvedType = PType.FunctionOf(this.FieldName, func.ReturnType, func.ArgTypes); } } return(this); } this.CoreFunctionId = this.DetermineCoreFunctionId(this.Root.ResolvedType, this.FieldName.Value); if (this.CoreFunctionId != CoreFunction.NONE) { CoreFunctionReference cfr = new CoreFunctionReference(this.FirstToken, this.CoreFunctionId, this.Root, this.Owner); cfr.ResolvedType = new PType(this.Root.FirstToken, null, "@CoreFunc"); return(cfr); } throw new NotImplementedException(); }
public void ResolveTypes(PastelCompiler compiler) { this.Constructor.ResolveTypes(compiler); foreach (FieldDefinition fd in this.Fields) { fd.ResolveTypes(compiler); } foreach (FunctionDefinition fd in this.Methods) { fd.ResolveTypes(compiler); } }
public void ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { this.Constructor.ResolveNamesAndCullUnusedCode(compiler); foreach (FieldDefinition fd in this.Fields) { fd.ResolveNamesAndCullUnusedCode(compiler); } foreach (FunctionDefinition fd in this.Methods) { fd.ResolveNamesAndCullUnusedCode(compiler); } }
internal bool IsIdentical(PastelCompiler compiler, PType other) { if (!this.isTypeFinalized) { this.FinalizeType(compiler); } if (!other.isTypeFinalized) { other.FinalizeType(compiler); } if (this.Category != other.Category) { return(false); } if (this.Generics.Length != other.Generics.Length) { return(false); } if (this.IsStructOrClass) { return(this.structReference == other.structReference || this.classReference == other.classReference); } if (this.RootValue != other.RootValue) { string thisRoot = this.RootValue; string thatRoot = other.RootValue; if (thisRoot == "number" && (thatRoot == "double" || thatRoot == "int")) { return(true); } if (thatRoot == "number" && (thisRoot == "double" || thisRoot == "int")) { return(true); } return(false); } for (int i = this.Generics.Length - 1; i >= 0; --i) { if (!this.Generics[i].IsIdentical(compiler, other.Generics[i])) { return(false); } } return(true); }
public void ResolveTypes(PastelCompiler compiler) { VariableScope varScope = new VariableScope(this); for (int i = 0; i < this.ArgTypes.Length; ++i) { varScope.DeclareVariables(this.ArgNames[i], this.ArgTypes[i]); } for (int i = 0; i < this.Code.Length; ++i) { this.Code[i].ResolveTypes(varScope, compiler); } }
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 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; this.VerifyArgTypes(functionDefinition.ArgTypes, compiler); this.ResolvedType = functionDefinition.ReturnType; return(this); } else if (this.Root is CoreFunctionReference) { CoreFunctionReference nfr = (CoreFunctionReference)this.Root; CoreFunctionInvocation nfi; if (nfr.Context == null) { nfi = new CoreFunctionInvocation(this.FirstToken, nfr.CoreFunctionId, this.Args, this.Owner); } else { nfi = new CoreFunctionInvocation(this.FirstToken, nfr.CoreFunctionId, nfr.Context, this.Args, this.Owner); } return(nfi.ResolveType(varScope, compiler)); } else if (this.Root is ExtensibleFunctionReference) { return(new ExtensibleFunctionInvocation(this.FirstToken, (ExtensibleFunctionReference)this.Root, this.Args).ResolveType(varScope, compiler)); } else if (this.Root is ConstructorReference) { PType typeToConstruct = ((ConstructorReference)this.Root).TypeToConstruct; typeToConstruct.FinalizeType(compiler); return(new ConstructorInvocation(this.FirstToken, typeToConstruct, this.Args, this.Owner)); } else if (this.Root.ResolvedType.RootValue == "Func") { return(new FunctionPointerInvocation(compiler, this.FirstToken, this.Root, this.Args)); } throw new ParserException(this.OpenParenToken, "This expression cannot be invoked like a function."); }
public void ResolveTypes(PastelCompiler compiler) { Dictionary <string, VariableDeclaration> globals = compiler.SharedScope == null ? compiler.Globals : compiler.SharedScope.Globals; VariableScope varScope = new VariableScope(this, globals); for (int i = 0; i < this.ArgTypes.Length; ++i) { varScope.DeclareVariables(this.ArgNames[i], this.ArgTypes[i]); } for (int i = 0; i < this.Code.Length; ++i) { this.Code[i].ResolveTypes(varScope, compiler); } }
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 override Executable ResolveWithTypeContext(PastelCompiler compiler) { this.Condition = this.Condition.ResolveWithTypeContext(compiler); for (int i = 0; i < this.Chunks.Length; ++i) { SwitchChunk chunk = this.Chunks[i]; for (int j = 0; j < chunk.Cases.Length; ++j) { if (chunk.Cases[j] != null) { chunk.Cases[j] = chunk.Cases[j].ResolveWithTypeContext(compiler); } } Executable.ResolveWithTypeContext(compiler, chunk.Code); } return(this); }
internal override Executable ResolveWithTypeContext(PastelCompiler compiler) { this.Condition = this.Condition.ResolveWithTypeContext(compiler); Executable.ResolveWithTypeContext(compiler, this.IfCode); if (this.ElseCode.Length > 0) { Executable.ResolveWithTypeContext(compiler, this.ElseCode); } if (this.Condition is InlineConstant) { bool condition = (bool)((InlineConstant)this.Condition).Value; return(new ExecutableBatch(this.FirstToken, condition ? this.IfCode : this.ElseCode)); } return(this); }
internal override Executable ResolveWithTypeContext(PastelCompiler compiler) { Executable.ResolveWithTypeContext(compiler, this.InitCode); this.Condition = this.Condition.ResolveWithTypeContext(compiler); Executable.ResolveWithTypeContext(compiler, this.StepCode); Executable.ResolveWithTypeContext(compiler, this.Code); // Canonialize the for loop into a while loop. List <Executable> loopCode = new List <Executable>(this.Code); loopCode.AddRange(this.StepCode); WhileLoop whileLoop = new WhileLoop(this.FirstToken, this.Condition, loopCode); loopCode = new List <Executable>(this.InitCode); loopCode.Add(whileLoop); return(new ExecutableBatch(this.FirstToken, loopCode)); }
public override Executable ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { this.Condition = this.Condition.ResolveNamesAndCullUnusedCode(compiler); for (int i = 0; i < this.Chunks.Length; ++i) { SwitchChunk chunk = this.Chunks[i]; for (int j = 0; j < chunk.Cases.Length; ++j) { if (chunk.Cases[j] != null) { chunk.Cases[j] = chunk.Cases[j].ResolveNamesAndCullUnusedCode(compiler); } } chunk.Code = Executable.ResolveNamesAndCullUnusedCodeForBlock(chunk.Code, compiler).ToArray(); } return(this); }
internal override void ResolveTypes(VariableScope varScope, PastelCompiler compiler) { if (this.Expression != null) { this.Expression = this.Expression.ResolveType(varScope, compiler); if (!PType.CheckReturnType(varScope.RootFunctionDefinition.ReturnType, this.Expression.ResolvedType)) { throw new ParserException(this.Expression.FirstToken, "This expression is not the expected return type of this function."); } } else { if (!this.Expression.ResolvedType.IsIdentical(PType.VOID)) { throw new ParserException(this.FirstToken, "Must return a value in this function."); } } }
public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { string name = this.Name; InlineConstant constantValue = compiler.GetConstantDefinition(name); if (constantValue != null) { return(constantValue.CloneWithNewToken(this.FirstToken)); } if (name == "Core") { return(new CoreNamespaceReference(this.FirstToken, this.Owner)); } if (name == "Extension") { return(new ExtensibleNamespaceReference(this.FirstToken, this.Owner)); } FunctionDefinition functionDefinition = compiler.GetFunctionDefinition(name); if (functionDefinition != null) { return(new FunctionReference(this.FirstToken, functionDefinition, this.Owner)); } EnumDefinition enumDefinition = compiler.GetEnumDefinition(name); if (enumDefinition != null) { return(new EnumReference(this.FirstToken, enumDefinition, this.Owner)); } if (compiler.IncludedScopeNamespacesToIndex.ContainsKey(name)) { int index = compiler.IncludedScopeNamespacesToIndex[name]; PastelCompiler referencedScope = compiler.IncludedScopes[index]; return(new DependencyNamespaceReference(this.FirstToken, referencedScope, this.Owner)); } return(this); }
internal override Expression ResolveType(VariableScope varScope, PastelCompiler compiler) { this.Root = this.Root.ResolveType(varScope, compiler); this.Index = this.Index.ResolveType(varScope, compiler); PType rootType = this.Root.ResolvedType; PType indexType = this.Index.ResolvedType; bool badIndex = false; if (rootType.RootValue == "List" || rootType.RootValue == "Array") { badIndex = !indexType.IsIdentical(PType.INT); this.ResolvedType = rootType.Generics[0]; } else if (rootType.RootValue == "Dictionary") { badIndex = !indexType.IsIdentical(rootType.Generics[0]); this.ResolvedType = rootType.Generics[1]; } else if (rootType.RootValue == "string") { badIndex = !indexType.IsIdentical(PType.INT); this.ResolvedType = PType.CHAR; if (this.Root is InlineConstant && this.Index is InlineConstant) { string c = ((string)((InlineConstant)this.Root).Value)[(int)((InlineConstant)this.Index).Value].ToString(); InlineConstant newValue = new InlineConstant(PType.CHAR, this.FirstToken, c); newValue.ResolveType(varScope, compiler); return(newValue); } } else { badIndex = true; } if (badIndex) { throw new ParserException(this.BracketToken, "Cannot index into a " + rootType + " with a " + indexType + "."); } return(this); }
public override Executable ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { this.Condition = this.Condition.ResolveNamesAndCullUnusedCode(compiler); if (this.Condition is InlineConstant) { object value = ((InlineConstant)this.Condition).Value; if (value is bool) { return(new ExecutableBatch(this.FirstToken, Executable.ResolveNamesAndCullUnusedCodeForBlock( ((bool)value) ? this.IfCode : this.ElseCode, compiler))); } } this.IfCode = Executable.ResolveNamesAndCullUnusedCodeForBlock(this.IfCode, compiler).ToArray(); this.ElseCode = Executable.ResolveNamesAndCullUnusedCodeForBlock(this.ElseCode, compiler).ToArray(); return(this); }
internal override Expression ResolveWithTypeContext(PastelCompiler compiler) { this.Root = this.Root.ResolveWithTypeContext(compiler); if (this.Root is FunctionReference) { // this is okay. } else { throw new ParserException(this.OpenParenToken, "Cannot invoke this like a function."); } for (int i = 0; i < this.Args.Length; ++i) { this.Args[i] = this.Args[i].ResolveWithTypeContext(compiler); } return(this); }
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 Executable ResolveWithTypeContext(PastelCompiler compiler) { if (this.Target is BracketIndex) { if (this.OpToken.Value != "=") { // Java will need to be special as it will require things to be broken down into a get-then-set. throw new ParserException(this.OpToken, "Incremental assignment on a key/index is not currently supported (although it really ought to be)."); } BracketIndex bi = (BracketIndex)this.Target; string rootType = bi.Root.ResolvedType.RootValue; Expression[] args = new Expression[] { bi.Root, bi.Index, this.Value }; CoreFunction nf; if (rootType == "Array") { nf = CoreFunction.ARRAY_SET; } else if (rootType == "List") { nf = CoreFunction.LIST_SET; } else if (rootType == "Dictionary") { nf = CoreFunction.DICTIONARY_SET; } else { throw new ParserException(bi.BracketToken, "Can't use brackets here."); } return(new ExpressionAsExecutable(new CoreFunctionInvocation( this.FirstToken, nf, args, bi.Owner)).ResolveWithTypeContext(compiler)); } this.Target = this.Target.ResolveWithTypeContext(compiler); this.Value = this.Value.ResolveWithTypeContext(compiler); return(this); }
public override Expression ResolveNamesAndCullUnusedCode(PastelCompiler compiler) { string name = this.Name; InlineConstant constantValue = compiler.GetConstantDefinition(name); if (constantValue != null) { return(constantValue.CloneWithNewToken(this.FirstToken)); } FunctionDefinition functionDefinition = compiler.GetFunctionDefinitionAndMaybeQueueForResolution(name); if (functionDefinition != null) { return(new FunctionReference(this.FirstToken, functionDefinition)); } return(this); }
private bool IsParentOf(PastelCompiler compiler, PType moreSpecificTypeOrSame) { if (moreSpecificTypeOrSame == this) { return(true); } if (this.Category == TypeCategory.OBJECT) { return(true); } if (this.Generics.Length == 0) { // why no treatment of int as a subtype of double? because there needs to be an explicit type conversion // for languages that aren't strongly typed and won't auto-convert. return(this.RootValue == moreSpecificTypeOrSame.RootValue); } // All that's left are Arrays, Lists, and Dictionaries, which must match exactly. return(this.IsIdentical(compiler, moreSpecificTypeOrSame)); }
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); }