public override Ast.Node Transform(ParseScope Scope) { ResultType = Type.Void; Condition = Condition.Transform(Scope); Body = Body.Transform(Scope); return this; }
public virtual void EmitInstructions(ParseScope DeclarationScope, VirtualMachine.InstructionList Into) { if (Instructions != null) throw new InvalidOperationException("Instructions should not be emitted twice"); CleanupPoint = Into.Count; if (CleanupCall >= 0) Into[CleanupCall] = CleanupPoint; Into.AddInstructions("CLEANUP NEXT #Cleanup " + Name, DeclarationScope.Owner.ActualParameterCount, "RETURN POP"); Instructions = Into; EntryPoint = Into.Count; Instructions.AddInstructions("MOVE F PUSH #Enter " + Name, "MARK_STACK F"); Body.Emit(Instructions, Ast.OperationDestination.Discard); //Instructions.AddInstructions("MOVE NEXT R", 0); //If a function has no return statement, it returns 0. var returnJumpPoint = Instructions.Count; Instructions.AddInstructions( "RESTORE_STACK F", "MOVE POP F", "RETURN POP"); System.Diagnostics.Debug.Assert(DeclarationScope.Type == ScopeType.Function); System.Diagnostics.Debug.Assert(DeclarationScope.ReturnJumpSources != null); foreach (var point in DeclarationScope.ReturnJumpSources) Instructions[point] = returnJumpPoint; }
public void ResolveType(ParseScope ActiveScope) { if (String.IsNullOrEmpty(DeclaredTypeName)) DeclaredType = Type.Generic; else { DeclaredType = ActiveScope.FindType(DeclaredTypeName); if (DeclaredType == null) throw new CompileError("Could not find type '" + DeclaredTypeName + "'."); } }
public override void EmitInstructions(ParseScope DeclarationScope, VirtualMachine.InstructionList Into) { if (Instructions != null) throw new InvalidOperationException("Instructions should not be emitted twice"); CleanupPoint = Into.Count; if (CleanupCall >= 0) Into[CleanupCall] = CleanupPoint; Into.AddInstructions("CLEANUP NEXT #Cleanup when clause for " + Name, DeclarationScope.Owner.ActualParameterCount, "RETURN POP"); Instructions = Into; EntryPoint = Into.Count; Instructions.AddInstructions("MOVE F PUSH #Enter " + Name, "MARK_STACK F"); Body.Emit(Instructions, Ast.OperationDestination.R); Instructions.AddInstructions( "RESTORE_STACK F", "MOVE POP F", "RETURN POP"); }
public void ResolveTypes(ParseScope ActiveScope) { if (String.IsNullOrEmpty(SuperTypename)) Super = null; else { Super = ActiveScope.FindType(SuperTypename); if (Super == null) throw new CompileError("Could not find type '" + SuperTypename + "'."); } if (Super == null) Members.Insert(0, new Variable { Name = "__type", DeclaredTypeName = "NUMBER", StorageMethod = VariableStorageMethod.Member }); var search = Super; while (search != null) { if (Object.ReferenceEquals(search, this)) throw new CompileError("Inheritance loop detected."); search = search.Super; } if (Origin == TypeOrigin.Script) foreach (var member in Members) { if (String.IsNullOrEmpty(member.DeclaredTypeName)) member.DeclaredType = Type.Generic; else { member.DeclaredType = ActiveScope.FindType(member.DeclaredTypeName); if (member.DeclaredType == null) throw new CompileError("Could not find type '" + member.DeclaredTypeName + "'."); } } }
public static Ast.Node CreateConversionInvokation( ParseScope Scope, Declaration ConversionMacro, Ast.Node Value) { return Ast.StaticInvokation.CreateCorrectInvokationNode(Value.Source, Scope, ConversionMacro, new List<Ast.Node>(new Ast.Node[] { Value })); }
public static TypeCompatibilityResult AreTypesCompatible(Type Source, Type Destination, ParseScope Scope) { if (Object.ReferenceEquals(Destination, Generic)) return TypeCompatibilityResult.NoConversionRequired; if (Object.ReferenceEquals(Source, Destination)) return TypeCompatibilityResult.NoConversionRequired; var super = Source.Super; while (super != null) { if (Object.ReferenceEquals(super, Destination)) return TypeCompatibilityResult.NoConversionRequired; super = super.Super; } var conversionArguments = new List<Ast.Node>(); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "convert" })); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "0" }) { ResultType = Source }); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "to" })); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = Destination.Name })); var possibleConversions = Scope.FindAllPossibleMacroMatches(conversionArguments); Declaration matchingConversion = null; foreach (var possibleConversion in possibleConversions) if (Object.ReferenceEquals(Source, possibleConversion.Terms[1].DeclaredType)) { matchingConversion = possibleConversion; break; } if (matchingConversion != null) { if (!Object.ReferenceEquals(matchingConversion.ReturnType, Destination)) throw new CompileError("Conversion function does not return the correct type.", matchingConversion.Body.Body.Source); return new TypeCompatibilityResult { Compatible = true, ConversionRequired = true, ConversionMacro = matchingConversion }; } return TypeCompatibilityResult.Incompatible; }
public void ResolveTypes(ParseScope Scope) { try { DeclarationScope = Scope.Push(ScopeType.Function); DeclarationScope.Owner = this; if (!String.IsNullOrEmpty(ReturnTypeName)) { ReturnType = Scope.FindType(ReturnTypeName); if (ReturnType == null) { if (Body != null && Body.Body != null) throw new CompileError("Could not find type '" + ReturnTypeName + "'.", Body.Body.Source); else throw new CompileError("Could not find type '" + ReturnTypeName + "'."); } } else ReturnType = EtcScriptLib.Type.Void; CreateParameterDescriptors(); var header = DescriptiveHeader; if (Body != null) Body.Name = header; if (WhenClause != null) WhenClause.Name = header + " : when ..."; } catch (Exception e) { throw new CompileError(e.Message + " while resolving types on " + DescriptiveHeader + "\n" + e.StackTrace); } }
public override Ast.Node Transform(ParseScope Scope) { List = List.Transform(Scope); ResultType = List.ResultType; //Try to find an access macro for this type. var getterArguments = DummyArguments(Keyword("GET"), Keyword("AT"), Term(Scope.FindType("NUMBER")), Keyword("FROM"), Term(List.ResultType)); var indexerMacro = Scope.FindAllPossibleMacroMatches(getterArguments).Where(d => ExactDummyMatch(d.Terms, getterArguments)).FirstOrDefault(); if (indexerMacro == null) throw new CompileError("No macro of the form GET AT NUMBER FROM " + List.ResultType.Name + " found.", Source); var lengthArguments = DummyArguments(Keyword("LENGTH"), Keyword("OF"), Term(List.ResultType)); var lengthMacro = Scope.FindAllPossibleMacroMatches(lengthArguments).Where(d => ExactDummyMatch(d.Terms, lengthArguments)).FirstOrDefault(); if (lengthMacro == null) throw new CompileError("No macro of the form LENGTH OF " + List.ResultType.Name + " found.", Source); var nestedScope = Scope.Push(ScopeType.Block); ResultVariable = nestedScope.NewLocal("__result@" + VariableName, Scope.FindType("LIST")); ListVariable = nestedScope.NewLocal("__list@" + VariableName, Scope.FindType("LIST")); TotalVariable = nestedScope.NewLocal("__total@" + VariableName, Scope.FindType("NUMBER")); CounterVariable = nestedScope.NewLocal("__counter@" + VariableName, Scope.FindType("NUMBER")); ValueVariable = nestedScope.NewLocal(VariableName, indexerMacro.ReturnType); Indexer = Ast.StaticInvokation.CreateCorrectInvokationNode(Source, nestedScope, indexerMacro, new List<Ast.Node>(new Ast.Node[] { new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "__counter@"+VariableName }), new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "__list@"+VariableName }) })).Transform(nestedScope); LengthFunc = Ast.StaticInvokation.CreateCorrectInvokationNode(Source, nestedScope, lengthMacro, new List<Ast.Node>(new Ast.Node[] { new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "__list@"+VariableName }) })).Transform(nestedScope); Condition = Condition.Transform(nestedScope); if (Condition.ResultType.Name != "BOOLEAN") throw new CompileError("Condition to where clause must return boolean", Source); return this; }
public void Transform(ParseScope DeclarationScope) { Body = Body.Transform(DeclarationScope); }
public ParseScope Push(ScopeType Type) { var r = new ParseScope(Type); r.Parent = this; r.VariableIndex = (Type == ScopeType.Function ? 0 : this.VariableIndex); r.EnvironmentContext = this.EnvironmentContext; return r; }
public override EtcScriptLib.Ast.Node Transform(ParseScope Scope) { var rulebook = Scope.EnvironmentContext.Rules.FindMatchingRulebook(Arguments); if (rulebook == null) return null; //Rulebook does not exist... no, this isn't an error! var arguments = Declaration.GenerateParameterListSyntaxTree(Arguments, rulebook.DeclarationTerms).Members; var boxedArguments = new List<Ast.Node>(arguments.Select(n => { n = n.Transform(Scope); if (n.ResultType.Origin != TypeOrigin.Script) return new Ast.Box(n.Source, n).Transform(Scope); else return n; })); //This only works because rulebook consider functions take only generics. return Ast.StaticInvokation.CreateCorrectInvokationNode(Source, Scope, rulebook.ConsiderFunction, boxedArguments) .Transform(Scope); }
public override EtcScriptLib.Ast.Node Transform(ParseScope Scope) { DeclarationScope = Scope; BoxType = Scope.FindType("BOXED"); ResultType = Rulebook.ResultType; return this; }
public ParseContext() { ActiveScope = new ParseScope(ScopeType.Root) { EnvironmentContext = this }; TopScope = ActiveScope; }
public void PushNewScope(ScopeType Type) { var newScope = new ParseScope(Type) { Parent = ActiveScope, EnvironmentContext = this }; ActiveScope = newScope; }
public override Ast.Node Transform(ParseScope Scope) { ResultType = Type.Void; Max = Max.Transform(Scope); var nestedScope = Scope.Push(ScopeType.Block); TotalVariable = nestedScope.NewLocal("__total@" + VariableName, Scope.FindType("NUMBER")); Min = Min.Transform(nestedScope); CounterVariable = nestedScope.NewLocal("__counter@" + VariableName, Scope.FindType("NUMBER")); ValueVariable = nestedScope.NewLocal(VariableName, Scope.FindType("NUMBER")); Body = Body.Transform(nestedScope); return this; }