/// <summary> /// AnalyzeScript: Check if any uninitialized variable is used. /// </summary> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); // Finds all functionAst IEnumerable<Ast> functionAsts = ast.FindAll(testAst => testAst is FunctionDefinitionAst, true); foreach (FunctionDefinitionAst funcAst in functionAsts) { if (funcAst.Body != null && funcAst.Body.ParamBlock != null && funcAst.Body.ParamBlock.Attributes != null && funcAst.Body.ParamBlock.Parameters != null) { // only raise this rule for function with cmdletbinding if (!funcAst.Body.ParamBlock.Attributes.Any(attr => attr.TypeName.GetReflectionType() == typeof(CmdletBindingAttribute))) { continue; } foreach (var paramAst in funcAst.Body.ParamBlock.Parameters) { bool mandatory = false; // check that param is mandatory foreach (var paramAstAttribute in paramAst.Attributes) { if (paramAstAttribute is AttributeAst) { var namedArguments = (paramAstAttribute as AttributeAst).NamedArguments; if (namedArguments != null) { foreach (NamedAttributeArgumentAst namedArgument in namedArguments) { if (String.Equals(namedArgument.ArgumentName, "mandatory", StringComparison.OrdinalIgnoreCase)) { // 2 cases: [Parameter(Mandatory)] and [Parameter(Mandatory=$true)] if (namedArgument.ExpressionOmitted || (!namedArgument.ExpressionOmitted && String.Equals(namedArgument.Argument.Extent.Text, "$true", StringComparison.OrdinalIgnoreCase))) { mandatory = true; break; } } } } } } if (!mandatory) { break; } if (paramAst.DefaultValue != null) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidDefaultValueForMandatoryParameterError, paramAst.Name.VariablePath.UserPath), paramAst.Name.Extent, GetName(), DiagnosticSeverity.Warning, fileName, paramAst.Name.VariablePath.UserPath); } } } } }
/// <summary> /// AnalyzeDSCResource: Analyzes given DSC Resource /// </summary> /// <param name="ast">The script's ast</param> /// <param name="fileName">The name of the script file being analyzed</param> /// <returns>The results of the analysis</returns> public IEnumerable<DiagnosticRecord> AnalyzeDSCResource(Ast ast, string fileName) { // we are given a script definition, do not analyze if (String.IsNullOrWhiteSpace(fileName)) { yield break; } String fileNameOnly = Path.GetFileName(fileName); String resourceName = Path.GetFileNameWithoutExtension(fileNameOnly); String examplesQuery = String.Format("*{0}*", resourceName); Boolean examplesPresent = false; String expectedExamplesPath = Path.Combine(new String[] {fileName, "..", "..", "..", "Examples"}); // Verify examples are present if (Directory.Exists(expectedExamplesPath)) { DirectoryInfo examplesFolder = new DirectoryInfo(expectedExamplesPath); FileInfo[] exampleFiles = examplesFolder.GetFiles(examplesQuery); if (exampleFiles.Length != 0) { examplesPresent = true; } } // Return error if no examples present if (!examplesPresent) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.DscExamplesPresentNoExamplesError, resourceName), ast.Extent, GetName(), DiagnosticSeverity.Information, fileName); } }
public void Visit(Ast.DictNode dict) { IDictionary obj = new Hashtable(dict.Elements.Count); foreach(Ast.KeyValueNode kv in dict.Elements) { kv.Key.Accept(this); object key = generated.Pop(); kv.Value.Accept(this); object value = generated.Pop(); obj[key] = value; } if(dictToInstance==null || !obj.Contains("__class__")) { generated.Push(obj); } else { object result = dictToInstance(obj); if(result==null) generated.Push(obj); else generated.Push(result); } }
/// <summary> /// AnalyzeDSCResource: Analyzes the ast to check that Write-Verbose is called for DSC Resources /// <param name="ast">The script's ast</param> /// <param name="fileName">The script's file name</param> /// </summary> public IEnumerable<DiagnosticRecord> AnalyzeDSCResource(Ast ast, string fileName) { if (ast == null) { throw new ArgumentNullException(Strings.NullAstErrorMessage); } IEnumerable<Ast> functionDefinitionAsts = Helper.Instance.DscResourceFunctions(ast); foreach (FunctionDefinitionAst functionDefinitionAst in functionDefinitionAsts) { var commandAsts = functionDefinitionAst.Body.FindAll(testAst => testAst is CommandAst, false); bool hasVerbose = false; if (null != commandAsts) { foreach (CommandAst commandAst in commandAsts) { hasVerbose |= String.Equals(commandAst.GetCommandName(), "Write-Verbose", StringComparison.OrdinalIgnoreCase); } } if (!hasVerbose) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseVerboseMessageInDSCResourceErrorFunction, functionDefinitionAst.Name), functionDefinitionAst.Extent, GetName(), DiagnosticSeverity.Information, fileName); } } }
/// <summary> /// MisleadingBacktick: Checks that lines don't end with a backtick followed by a whitespace /// </summary> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); string[] lines = NewlineRegex.Split(ast.Extent.Text); if((ast.Extent.EndLineNumber - ast.Extent.StartLineNumber + 1) != lines.Length) { // Did not match the number of lines that the extent indicated yield break; } foreach (int i in Enumerable.Range(0, lines.Length)) { string line = lines[i]; Match match = TrailingEscapedWhitespaceRegex.Match(line); if(match.Success) { int lineNumber = ast.Extent.StartLineNumber + i; ScriptPosition start = new ScriptPosition(fileName, lineNumber, match.Index, line); ScriptPosition end = new ScriptPosition(fileName, lineNumber, match.Index + match.Length, line); yield return new DiagnosticRecord( string.Format(CultureInfo.CurrentCulture, Strings.MisleadingBacktickError), new ScriptExtent(start, end), GetName(), DiagnosticSeverity.Warning, fileName); } } }
/// <summary> /// AnalyzeScript: Analyzes the ast to check for reserved parameters in function definitions. /// </summary> /// <param name="ast">The script's ast</param> /// <param name="fileName">The script's file name</param> /// <returns>A List of diagnostic results of this rule</returns> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); IEnumerable<Ast> funcAsts = ast.FindAll(item => item is FunctionDefinitionAst, true); List<string> commonParamNames = typeof(CommonParameters).GetProperties().Select(param => param.Name).ToList(); foreach (FunctionDefinitionAst funcAst in funcAsts) { // this rule only applies to function with param block if (funcAst.Body != null && funcAst.Body.ParamBlock != null && funcAst.Body.ParamBlock.Attributes != null && funcAst.Body.ParamBlock.Parameters != null) { // no cmdlet binding if (!funcAst.Body.ParamBlock.Attributes.Any(attr => attr.TypeName.GetReflectionType() == typeof(CmdletBindingAttribute))) { continue; } foreach (ParameterAst paramAst in funcAst.Body.ParamBlock.Parameters) { string paramName = paramAst.Name.VariablePath.UserPath; if (commonParamNames.Contains(paramName, StringComparer.OrdinalIgnoreCase)) { yield return new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.ReservedParamsError, funcAst.Name, paramName), paramAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName); } } } } }
internal Scope(IParameterMetadataProvider ast, ScopeType scopeType) { _ast = (Ast)ast; _scopeType = scopeType; _typeTable = new Dictionary<string, TypeLookupResult>(StringComparer.OrdinalIgnoreCase); _variableTable = new Dictionary<string, Ast>(StringComparer.OrdinalIgnoreCase); }
internal Ast.Expression Visit(Ast.Expression expression) { switch (expression.CodeType) { case CodeType.BlockExpression: return VisitBlockExpression((Ast.BlockExpression)expression); case CodeType.TypeExpression: return VisitTypeExpression((Ast.TypeExpression)expression); case CodeType.LambdaExpresion: return VisitLambdaExpression((Ast.LambdaExpression)expression); case CodeType.LogicalExpression: return VisitLogicalExpression((Ast.LogicalExpression)expression); case CodeType.BinaryExpression: return VisitBinaryExpression((Ast.BinaryExpression)expression); case CodeType.LiteralExpression: return VisitLiteralExpression((Ast.LiteralExpression)expression); case CodeType.MemberExpression: return VisitMemberExpression((Ast.MemberExpression)expression); case CodeType.OrderbyExpression: return VisitOrderbyExpression((Ast.OrderbyExpression)expression); case CodeType.MethodCallExpression: return VisitMethodCallExpression((Ast.MethodCallExpression)expression); } throw new ArgumentException("Expression type is not supported"); }
public virtual Ast.Expression VisitBinaryExpression(Ast.BinaryExpression expression) { this.Visit(expression.Left); this.Visit(expression.Right); return expression; }
/// <summary> /// AnalyzeScript: Check that cmdlets are invoked with the correct mandatory parameter /// </summary> /// <param name="ast"></param> /// <param name="fileName"></param> /// <returns></returns> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); // Finds all CommandAsts. IEnumerable<Ast> foundAsts = ast.FindAll(testAst => testAst is CommandAst, true); // Iterates all CommandAsts and check the command name. foreach (Ast foundAst in foundAsts) { CommandAst cmdAst = (CommandAst)foundAst; // Handles the exception caused by commands like, {& $PLINK $args 2> $TempErrorFile}. // You can also review the remark section in following document, // MSDN: CommandAst.GetCommandName Method if (cmdAst.GetCommandName() == null) continue; // Checks mandatory parameters. if (!IsMandatoryParameterExisted(cmdAst)) { yield return new DiagnosticRecord(String.Format(CultureInfo.CurrentCulture, Strings.UseCmdletCorrectlyError, cmdAst.GetCommandName()), cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName); } } }
public virtual Ast.Expression VisitBlockExpression(Ast.BlockExpression blockExpression) { foreach (var expression in blockExpression.Expressions) this.Visit(expression); return blockExpression; }
public Ast.Statements.BlockStatement Process(Decompiler.DecompilationContext context, Ast.Statements.BlockStatement body) { HashSet<Instruction> mappedInstructions = new HashSet<Instruction>(body.UnderlyingSameMethodInstructions); if (context.MethodContext.IsMethodBodyChanged) { context.MethodContext.Method.RefreshBody(); context.MethodContext.IsMethodBodyChanged = false; } List<Instruction> unmappedInstructions = new List<Instruction>(); foreach (Instruction instruction in context.MethodContext.Method.Body.Instructions) { if (!mappedInstructions.Contains(instruction)) { unmappedInstructions.Add(instruction); } } if (unmappedInstructions.Count > 0) { StringBuilder stringBuilder = new StringBuilder("Found unmapped instructions.\n"); foreach (Instruction unmappedInstruction in unmappedInstructions) { stringBuilder.AppendLine(unmappedInstruction.ToString()); } throw new Exception(stringBuilder.ToString()); } return body; }
public void AstBuilder_ComplexExpression_Build() { var tree = new Ast("+", true); tree.Operands.Add(new Ast("4")); tree.Operands.Add(new Ast("6")); var buffer = new Ast("/", true); buffer.Operands.Add(new Ast("81")); buffer.Operands.Add(new Ast("-3")); var anotherBuffer = new Ast("*", true); anotherBuffer.Operands.Add(new Ast("3")); anotherBuffer.Operands.Add(new Ast("3")); buffer.Operands.Add(anotherBuffer); tree.Operands.Add(buffer); buffer = new Ast("-", true); buffer.Operands.Add(new Ast("10")); buffer.Operands.Add(new Ast("12")); tree.Operands.Add(buffer); var input = "(+ 4 6 (/ 81 -3 (* 3 3 ))( - 10 12 ))"; var actualTree = new AstBuilder().Build(new Tokenizer().GetTokens(input)); Assert.IsTrue(actualTree.Equals(tree)); }
private static List<string> GetSingleAstRequiredModules(Ast ast, Token[] tokens) { List<string> modules = new List<string>(); List<string> resources = new List<string>(); var imports = tokens.Where(token => String.Compare(token.Text, "Import-DscResource", StringComparison.OrdinalIgnoreCase) == 0); // // Create a function with the same name as Import-DscResource keyword and use powershell // argument function binding to emulate Import-DscResource argument binding. // InitialSessionState initialSessionState = InitialSessionState.Create(); SessionStateFunctionEntry importDscResourcefunctionEntry = new SessionStateFunctionEntry( "Import-DscResource", @"param($Name, $ModuleName) if ($ModuleName) { foreach ($m in $ModuleName) { $global:modules.Add($m) } } else { foreach ($n in $Name) { $global:resources.Add($n) } } "); initialSessionState.Commands.Add(importDscResourcefunctionEntry); initialSessionState.LanguageMode = PSLanguageMode.RestrictedLanguage; var moduleVarEntry = new SessionStateVariableEntry("modules", modules, ""); var resourcesVarEntry = new SessionStateVariableEntry("resources", resources, ""); initialSessionState.Variables.Add(moduleVarEntry); initialSessionState.Variables.Add(resourcesVarEntry); using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create(initialSessionState)) { foreach (var import in imports) { int startOffset = import.Extent.StartOffset; var asts = ast.FindAll(a => IsCandidateForImportDscResourceAst(a, startOffset), true); int longestLen = -1; Ast longestCandidate = null; foreach (var candidatAst in asts) { int curLen = candidatAst.Extent.EndOffset - candidatAst.Extent.StartOffset; if (curLen > longestLen) { longestCandidate = candidatAst; longestLen = curLen; } } // longestCandidate should contain AST for import-dscresource, like "Import-DSCResource -Module x -Name y". if (longestCandidate != null) { string importText = longestCandidate.Extent.Text; // We invoke-command "importText" here. Script injection is prevented: // We checked that file represents a valid AST without errors. powerShell.AddScript(importText); powerShell.Invoke(); powerShell.Commands.Clear(); } } } modules.AddRange(resources.Select(GetModuleNameForDscResource)); return modules; }
public override void VisitMethodInvocationExpression(Ast.Expressions.MethodInvocationExpression node) { MethodDefinition methodDef = node.MethodExpression.MethodDefinition; if (methodDef == null) { base.VisitMethodInvocationExpression(node); return; } Visit(node.MethodExpression); for (int i = 0; i < node.Arguments.Count; i++) { UnaryExpression unaryArgument = node.Arguments[i] as UnaryExpression; if (methodDef.Parameters[i].IsOutParameter() && (unaryArgument != null && unaryArgument.Operator == UnaryOperator.AddressReference && CheckExpression(unaryArgument.Operand) || CheckExpression(node.Arguments[i]))) { this.searchResult = UsageFinderSearchResult.Assigned; return; } else { Visit(node.Arguments[i]); if (this.searchResult != UsageFinderSearchResult.NotFound) { return; } } } }
/// <summary> /// AvoidUsingPlainTextForPassword: Check that parameter "password", "passphrase" and do not use plaintext. /// </summary> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); // Finds all ParamAsts. IEnumerable<Ast> paramAsts = ast.FindAll(testAst => testAst is ParameterAst, true); List<String> passwords = new List<String>() {"Password", "Passphrase", "Auth", "Cred", "Credential"}; // Iterrates all ParamAsts and check if their names are on the list. foreach (ParameterAst paramAst in paramAsts) { TypeInfo paramType = (TypeInfo) paramAst.StaticType; bool hasPwd = false; String paramName = paramAst.Name.VariablePath.ToString(); foreach (String password in passwords) { if (paramName.IndexOf(password, StringComparison.OrdinalIgnoreCase) != -1) { hasPwd = true; break; } } if (hasPwd && ((!paramType.IsArray && (paramType == typeof(String) || paramType == typeof(object))) || (paramType.IsArray && (paramType.GetElementType() == typeof(String) || paramType.GetElementType() == typeof(object))))) { yield return new DiagnosticRecord( String.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingPlainTextForPasswordError, paramAst.Name), paramAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName); } } }
internal CompletionAnalysis(Ast ast, Token[] tokens, IScriptPosition cursorPosition, Hashtable options) { _ast = ast; _tokens = tokens; _cursorPosition = cursorPosition; _options = options; }
private bool IncorrectComparisonWithNull(BinaryExpressionAst binExpressionAst, Ast ast) { if ((binExpressionAst.Operator.Equals(TokenKind.Equals) || binExpressionAst.Operator.Equals(TokenKind.Ceq) || binExpressionAst.Operator.Equals(TokenKind.Cne) || binExpressionAst.Operator.Equals(TokenKind.Ine) || binExpressionAst.Operator.Equals(TokenKind.Ieq)) && binExpressionAst.Right.Extent.Text.Equals("$null", StringComparison.OrdinalIgnoreCase)) { if (binExpressionAst.Left.StaticType.IsArray) { return true; } else if (binExpressionAst.Left is VariableExpressionAst) { // ignores if the variable is a special variable if (!Helper.Instance.HasSpecialVars((binExpressionAst.Left as VariableExpressionAst).VariablePath.UserPath)) { Type lhsType = Helper.Instance.GetTypeFromAnalysis(binExpressionAst.Left as VariableExpressionAst, ast); if (lhsType == null) { return true; } else if (lhsType.IsArray || lhsType == typeof(object) || lhsType == typeof(Undetermined) || lhsType == typeof(Unreached)) { return true; } } } else if (binExpressionAst.Left.StaticType == typeof(object)) { return true; } } return false; }
public ClosureExpression(Ast.PythonVariable/*!*/ variable, Expression/*!*/ closureCell, Expression parameter) { Assert.NotNull(closureCell); _variable = variable; _closureCell = closureCell; _parameter = parameter; }
/// <summary> /// AnalyzeScript: Analyze the script to check if cmdlet alias is used. /// </summary> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); // Finds all CommandAsts. IEnumerable<Ast> foundAsts = ast.FindAll(testAst => testAst is CommandAst, true); // Iterates all CommandAsts and check the command name. foreach (Ast foundAst in foundAsts) { CommandAst cmdAst = (CommandAst)foundAst; string aliasName = cmdAst.GetCommandName(); // Handles the exception caused by commands like, {& $PLINK $args 2> $TempErrorFile}. // You can also review the remark section in following document, // MSDN: CommandAst.GetCommandName Method if (aliasName == null) { continue; } string cmdletName = Helper.Instance.GetCmdletNameFromAlias(aliasName); if (!String.IsNullOrEmpty(cmdletName)) { yield return new DiagnosticRecord( string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingCmdletAliasesError, aliasName, cmdletName), cmdAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, aliasName, suggestedCorrections: GetCorrectionExtent(cmdAst, cmdletName)); } } }
/// <summary> /// AnalyzeScript: Analyzes the ast to check that $null is on the left side of any equality comparisons. /// <param name="ast">The script's ast</param> /// <param name="fileName">The script's file name</param> /// <returns>The diagnostic results of this rule</returns> /// </summary> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); IEnumerable<Ast> binExpressionAsts = ast.FindAll(testAst => testAst is BinaryExpressionAst, false); foreach (BinaryExpressionAst binExpressionAst in binExpressionAsts) { if ((binExpressionAst.Operator.Equals(TokenKind.Equals) || binExpressionAst.Operator.Equals(TokenKind.Ceq) || binExpressionAst.Operator.Equals(TokenKind.Cne) || binExpressionAst.Operator.Equals(TokenKind.Ine) || binExpressionAst.Operator.Equals(TokenKind.Ieq)) && binExpressionAst.Right.Extent.Text.Equals("$null", StringComparison.OrdinalIgnoreCase)) { if (IncorrectComparisonWithNull(binExpressionAst, ast)) { yield return new DiagnosticRecord(Strings.PossibleIncorrectComparisonWithNullError, binExpressionAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName); } } } IEnumerable<Ast> funcAsts = ast.FindAll(item => item is FunctionDefinitionAst, true).Union(ast.FindAll(item => item is FunctionMemberAst, true)); foreach (Ast funcAst in funcAsts) { IEnumerable<Ast> binAsts = funcAst.FindAll(item => item is BinaryExpressionAst, true); foreach (BinaryExpressionAst binAst in binAsts) { if (IncorrectComparisonWithNull(binAst, funcAst)) { yield return new DiagnosticRecord(Strings.PossibleIncorrectComparisonWithNullError, binAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName); } } } }
/// <summary> /// Finds the symbol (always Command type) at a given file location /// </summary> /// <param name="scriptAst">The abstract syntax tree of the given script</param> /// <param name="lineNumber">The line number of the cursor for the given script</param> /// <param name="columnNumber">The column number of the cursor for the given script</param> /// <returns>SymbolReference of found command</returns> public static SymbolReference FindCommandAtPosition(Ast scriptAst, int lineNumber, int columnNumber) { FindCommandVisitor commandVisitor = new FindCommandVisitor(lineNumber, columnNumber); scriptAst.Visit(commandVisitor); return commandVisitor.FoundCommandReference; }
/// <summary> /// AnalyzeScript: Run Test Module Manifest to check that none of the required fields are missing. From the ILintScriptRule interface. /// </summary> /// <param name="ast">The script's ast</param> /// <param name="fileName">The script's file name</param> /// <returns>A List of diagnostic results of this rule</returns> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); if (String.Equals(System.IO.Path.GetExtension(fileName), ".psd1", StringComparison.OrdinalIgnoreCase)) { IEnumerable<ErrorRecord> errorRecords; var psModuleInfo = Helper.Instance.GetModuleManifest(fileName, out errorRecords); if (errorRecords != null) { foreach (var errorRecord in errorRecords) { if (Helper.IsMissingManifestMemberException(errorRecord)) { System.Diagnostics.Debug.Assert( errorRecord.Exception != null && !String.IsNullOrWhiteSpace(errorRecord.Exception.Message), Strings.NullErrorMessage); var hashTableAst = ast.Find(x => x is HashtableAst, false); if (hashTableAst == null) { yield break; } yield return new DiagnosticRecord( errorRecord.Exception.Message, hashTableAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, suggestedCorrections:GetCorrectionExtent(hashTableAst as HashtableAst)); } } } } }
public override void Emit(VirtualMachine.InstructionList into, Ast.OperationDestination Destination) { //Prepare loop control variables List.Emit(into, Ast.OperationDestination.Stack); //__list@ LengthFunc.Emit(into, Ast.OperationDestination.Stack); //__total@ into.AddInstructions("MOVE NEXT PUSH # SET __COUNTER@", 0); //__counter@ var LoopStart = into.Count; into.AddInstructions( "LOAD_PARAMETER NEXT R #" + TotalVariable.Name, TotalVariable.Offset, "GREATER_EQUAL PEEK R R #PEEK = __COUNTER@", "IF_TRUE R", "JUMP NEXT", 0); var BreakPoint = into.Count - 1; Indexer.Emit(into, Ast.OperationDestination.Stack); Body.Emit(into, Ast.OperationDestination.Discard); into.AddInstructions( "MOVE POP #REMOVE __VALUE@", "INCREMENT PEEK PEEK", "JUMP NEXT", LoopStart); into[BreakPoint] = into.Count; into.AddInstructions("CLEANUP NEXT #REMOVE __COUNTER@, __TOTAL@, __LIST@", 3); }
/// <summary> /// AnalyzeScript: Analyzes the script to check if any non-constant members have been invoked. /// </summary> public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) throw new ArgumentNullException(Strings.NullAstErrorMessage); IEnumerable<Ast> memberExpression = ast.FindAll(testAst => testAst is MemberExpressionAst, true); foreach (MemberExpressionAst member in memberExpression) { string context = member.Member.Extent.ToString(); if (context.Contains("(")) { //check if parenthesis and have non-constant members IEnumerable<Ast> binaryExpression = member.FindAll( binaryAst => binaryAst is BinaryExpressionAst, true); if (binaryExpression.Any()) { foreach (BinaryExpressionAst bin in binaryExpression) { if (!bin.Operator.Equals(null)) { yield return new DiagnosticRecord( string.Format(CultureInfo.CurrentCulture, Strings.AvoidInvokingEmptyMembersError, context), member.Extent, GetName(), DiagnosticSeverity.Warning, fileName); } } } } } }
public Ast.Statements.BlockStatement Process(Decompiler.DecompilationContext context, Ast.Statements.BlockStatement body) { this.methodContext = context.MethodContext; mappedInstructions.UnionWith(body.UnderlyingSameMethodInstructions); Visit(body); return body; }
public ForeachIn(Token Source, String VariableName, Ast.Node List, Ast.Node Body) : base(Source) { this.VariableName = VariableName; this.List = List; this.Body = Body; }
public LuaFile Compile(Ast.Chunk c, string name) { file = new LuaFile(); block = new Block(); block.Chunk.Name = name; block.Chunk.ArgumentCount = 0; block.Chunk.Vararg = 2; DoChunk(c); file.Main = block.Chunk; file.Main.ArgumentCount = 0; file.Main.Vararg = 2; file.Main.UpvalueCount = file.Main.Upvalues.Count; bool addRet = file.Main.Instructions.Count == 0; if (addRet == false) addRet = file.Main.Instructions[file.Main.Instructions.Count - 1].Opcode != Instruction.LuaOpcode.RETURN; if (addRet) { Instruction ret = new Instruction("RETURN"); ret.A = 0; ret.B = 1; ret.C = 0; file.Main.Instructions.Add(ret); } return file; }
public static bool IsConstant(Ast ast, out object constantValue, bool forAttribute = false, bool forRequires = false) { try { if ((bool)ast.Accept(new IsConstantValueVisitor { CheckingAttributeArgument = forAttribute, CheckingRequiresArgument = forRequires })) { Ast parent = ast.Parent; while (parent != null) { if (parent is DataStatementAst) { break; } parent = parent.Parent; } if (parent == null) { constantValue = ast.Accept(new ConstantValueVisitor { AttributeArgument = forAttribute, RequiresArgument = forRequires }); return true; } } } catch (Exception e) { // If we get an exception, ignore it and assume the expression isn't constant. // This can happen, e.g. if a cast is invalid: // [int]"zed" CommandProcessorBase.CheckForSevereException(e); } constantValue = null; return false; }
/// <summary> /// Finds all files dot sourced in a script /// </summary> /// <param name="scriptAst">The abstract syntax tree of the given script</param> /// <returns></returns> public static string[] FindDotSourcedIncludes(Ast scriptAst) { FindDotSourcedVisitor dotSourcedVisitor = new FindDotSourcedVisitor(); scriptAst.Visit(dotSourcedVisitor); return dotSourcedVisitor.DotSourcedFiles.ToArray(); }
internal MSA.Expression /*!*/ TransformName(AstGenerator /*!*/ gen) { return(Ast.Constant(_name)); }
private MSAst.Expression AddModulePublishing(MSAst.Expression body) { if (_isModule) { PythonCompilerOptions pco = _compilerContext.Options as PythonCompilerOptions; string moduleName = ModuleName; if ((pco.Module & ModuleOptions.Initialize) != 0) { var tmp = Ast.Variable(typeof(object), "$originalModule"); // TODO: Should be try/fault body = Ast.Block( new[] { tmp }, AstUtils.Try( Ast.Assign(tmp, Ast.Call(AstMethods.PublishModule, LocalContext, Ast.Constant(moduleName))), body ).Catch( typeof(Exception), Ast.Call(AstMethods.RemoveModule, LocalContext, Ast.Constant(moduleName), tmp), Ast.Rethrow(body.Type) ) ); } } return(body); }
internal MSAst.Expression ReduceWorker() { var retStmt = _body as ReturnStatement; if (retStmt != null && (_languageFeatures == ModuleOptions.None || _languageFeatures == (ModuleOptions.ExecOrEvalCode | ModuleOptions.Interpret) || _languageFeatures == (ModuleOptions.ExecOrEvalCode | ModuleOptions.Interpret | ModuleOptions.LightThrow))) { // for simple eval's we can construct a simple tree which just // leaves the value on the stack. Return's can't exist in modules // so this is always safe. Debug.Assert(!_isModule); var ret = (ReturnStatement)_body; Ast simpleBody; if ((_languageFeatures & ModuleOptions.LightThrow) != 0) { simpleBody = LightExceptions.Rewrite(retStmt.Expression.Reduce()); } else { simpleBody = retStmt.Expression.Reduce(); } var start = IndexToLocation(ret.Expression.StartIndex); var end = IndexToLocation(ret.Expression.EndIndex); return(Ast.Block( Ast.DebugInfo( _document, start.Line, start.Column, end.Line, end.Column ), AstUtils.Convert(simpleBody, typeof(object)) )); } ReadOnlyCollectionBuilder <MSAst.Expression> block = new ReadOnlyCollectionBuilder <MSAst.Expression>(); AddInitialiation(block); if (_isModule) { block.Add(AssignValue(GetVariableExpression(_docVariable), Ast.Constant(GetDocumentation(_body)))); } if (!(_body is SuiteStatement) && _body.CanThrow) { // we only initialize line numbers in suite statements but if we don't generate a SuiteStatement // at the top level we can miss some line number updates. block.Add(UpdateLineNumber(_body.Start.Line)); } block.Add(_body); MSAst.Expression body = Ast.Block(block.ToReadOnlyCollection()); body = WrapScopeStatements(body, Body.CanThrow); // new ComboActionRewriter().VisitNode(Transform(ag)) body = AddModulePublishing(body); body = AddProfiling(body); if ((((PythonCompilerOptions)_compilerContext.Options).Module & ModuleOptions.LightThrow) != 0) { body = LightExceptions.Rewrite(body); } body = Ast.Label(FunctionDefinition._returnLabel, AstUtils.Convert(body, typeof(object))); if (body.Type == typeof(void)) { body = Ast.Block(body, Ast.Constant(null)); } return(body); }
public static Expression MakeRecordTypeDescriptor(Expression[] obj) { if ((obj.Length == 6 || obj.Length == 7) && IronScheme.Compiler.Generator.VarHint != SymbolId.Empty) { try { var name = Unwrap(obj[0]); var parent = Unwrap(obj[1]); var uid = Unwrap(obj[2]); var issealed = Unwrap(obj[3]); var isopaque = Unwrap(obj[4]); var fields = obj[5]; if (fields is BoundExpression) { return(null); } if (name is BoundExpression) { return(null); } var rname = ((ConstantExpression)name).Value; var ruid = ((ConstantExpression)uid).Value; var rsealed = ((ConstantExpression)issealed).Value; var ropaque = ((ConstantExpression)isopaque).Value; object[] rfields = { }; if (fields is NewArrayExpression) { var ff = ((NewArrayExpression)fields).Expressions; var dfields = new Expression[ff.Count]; ff.CopyTo(dfields, 0); rfields = Array.ConvertAll(dfields, x => ((ConstantExpression)x).Value); } object[] tfields = Array.ConvertAll(rfields, x => SymbolTable.StringToObject("Object")); if (obj.Length == 7) { var ftypes = obj[6]; if (ftypes is NewArrayExpression) { var ff = ((NewArrayExpression)ftypes).Expressions; var dfields = new Expression[ff.Count]; ff.CopyTo(dfields, 0); tfields = Array.ConvertAll(dfields, x => ((ConstantExpression)((UnaryExpression)x).Operand).Value); } } if (!Builtins.IsTrue(ruid)) { ruid = Guid.NewGuid().ToString(); //TODO: recall why this was done :\ Change to gensym if possible obj[2] = Ast.Convert(Ast.Constant(ruid), typeof(object)); } object par = null; if (parent is BoundExpression) { par = ((BoundExpression)parent).Variable.Name; } var rtdc = new RecordTypeDescriptorConstant { RecordName = rname, Uid = ruid, Sealed = rsealed, Opaque = ropaque, Parent = par, Fields = rfields, FieldTypes = tfields, NameHint = IronScheme.Compiler.Generator.VarHint, }; var at = rtdc.Generate(); if (at != null) { ClrGenerator.AddCompileTimeType(at); } var e = Ast.Constant(rtdc); return(Ast.Comma(e, Ast.Call(typeof(Records).GetMethod("MakeRecordTypeDescriptor"), obj))); } catch { throw; //kaboom, redirect to runtime } } return(null); }
/// <summary> /// For each spread (named or inline) defined in the document. /// Let fragment be the target of spread /// Let fragmentType be the type condition of fragment /// Let parentType be the type of the selection set containing spread /// Let applicableTypes be the intersection of GetPossibleTypes(fragmentType) and GetPossibleTypes(parentType) /// applicableTypes must not be empty. /// </summary> /// <returns></returns> public static CombineRule R5523FragmentSpreadIsPossible() { return((context, rule) => { var fragments = context.Document.Definitions.OfType <GraphQLFragmentDefinition>() .ToDictionary(f => f.Name.Value); rule.EnterFragmentSpread += node => { var fragment = fragments[node.Name.Value]; var fragmentType = Ast.TypeFromAst(context.Schema, fragment.TypeCondition); var parentType = context.Tracker.GetParentType(); var applicableTypes = GetPossibleTypes(fragmentType, context.Schema) .Intersect(GetPossibleTypes(parentType, context.Schema)); if (!applicableTypes.Any()) { context.Error( ValidationErrorCodes.R5523FragmentSpreadIsPossible, "Fragments are declared on a type and will only apply " + "when the runtime object type matches the type condition. They " + "also are spread within the context of a parent type. A fragment " + "spread is only valid if its type condition could ever apply within " + "the parent type. " + $"FragmentSpread: '{node.Name?.Value}'", node); } }; rule.EnterInlineFragment += node => { var fragmentType = Ast.TypeFromAst(context.Schema, node.TypeCondition); var parentType = context.Tracker.GetParentType(); var applicableTypes = GetPossibleTypes(fragmentType, context.Schema) .Intersect(GetPossibleTypes(parentType, context.Schema)); if (!applicableTypes.Any()) { context.Error( ValidationErrorCodes.R5523FragmentSpreadIsPossible, "Fragments are declared on a type and will only apply " + "when the runtime object type matches the type condition. They " + "also are spread within the context of a parent type. A fragment " + "spread is only valid if its type condition could ever apply within " + "the parent type.", node); } }; }); ObjectType[] GetPossibleTypes(IType type, ISchema schema) { switch (type) { case ObjectType objectType: return(new[] { objectType }); case InterfaceType interfaceType: return(schema.GetPossibleTypes(interfaceType).ToArray()); case UnionType unionType: return(schema.GetPossibleTypes(unionType).ToArray()); default: return(new ObjectType[] { }); } } }
protected abstract void VisitTokens(Ast ast);
protected string GetDslInstanceName(ReadOnlyCollection <CommandElementAst> commandElements, Ast parent) { // todo: what with "configuration" in legacy mode? if (commandElements == null || commandElements.Count < 2) { return(null); } // in order to be possibly a DSL expression, first element must be StringConstant AND second must not be = // AND (first element must start with PSDesiredStateConfiguration - legacy OR (last must be ScriptBlockExpression, and last but 1 must not be CommandParameter)) if (!(commandElements[0] is StringConstantExpressionAst) || ((commandElements[1] is StringConstantExpressionAst && ((StringConstantExpressionAst)commandElements[1]).Value == "="))) { return(null); } string dslTypeName = ((StringConstantExpressionAst)commandElements[0]).Value; if (!dslTypeName.StartsWith("PSDesiredStateConfiguration") && !this.dslCustomDictionary.Contains(dslTypeName.ToLowerInvariant()) && (!this.dslAutoDiscovery || (!(commandElements[commandElements.Count - 1] is ScriptBlockExpressionAst || commandElements[commandElements.Count - 1] is HashtableAst) || commandElements[commandElements.Count - 2] is CommandParameterAst))) { return(null); } // additionally, parent must not be a Pipeline that has more than 1 element if (parent is PipelineAst && ((PipelineAst)parent).PipelineElements.Count > 1) { return(null); } return(this.TrimQuotes(this.GetDslInstanceName(dslTypeName, commandElements))); }
static Statement MakeTailCallReturn(bool allowtailcall, Expression e) { //if (allowtailcall) { if (e is MethodCallExpression) { MethodCallExpression mce = ((MethodCallExpression)e); mce.TailCall = /*!mce.Method.ReturnType.IsValueType &&*/ allowtailcall; } else if (e is ConditionalExpression) { ConditionalExpression ce = (ConditionalExpression)e; Statement truestmt = OptimizeBody(MakeTailCallReturn(allowtailcall, ce.IfTrue)); Statement falsestmt = OptimizeBody(MakeTailCallReturn(allowtailcall, ce.IfFalse)); return(Ast.IfThenElse(ce.Test, truestmt, falsestmt)); } else if (e is CommaExpression) { CommaExpression ce = (CommaExpression)e; if (ce.ValueIndex + 1 == ce.Expressions.Count) { List <Statement> ss = new List <Statement>(); for (int i = 0; i < ce.Expressions.Count - 1; i++) { ss.Add(Ast.Statement(ce.Expressions[i])); } ss.Add(MakeTailCallReturn(allowtailcall, ce.Expressions[ce.Expressions.Count - 1])); return(OptimizeBody(Ast.Block(ss))); } } else if (e is NewExpression || e is BoundExpression || e is ConstantExpression || e is MemberExpression) { // ignore } else if (e is UnaryExpression && e.NodeType == AstNodeType.Convert) { var op = ((UnaryExpression)e).Operand; if (op is ConditionalExpression) { ConditionalExpression ce = (ConditionalExpression)op; Statement truestmt = OptimizeBody(MakeTailCallReturn(allowtailcall, Ast.ConvertHelper(ce.IfTrue, e.Type))); Statement falsestmt = OptimizeBody(MakeTailCallReturn(allowtailcall, Ast.ConvertHelper(ce.IfFalse, e.Type))); return(Ast.IfThenElse(ce.Test, truestmt, falsestmt)); } } else if (e is VoidExpression) { return(Ast.Return(Ast.Comma(e, Ast.ReadField(null, Unspecified)))); } else { } } return(Ast.Return(e)); }
protected internal static void FillBody(CodeBlock cb, List <Statement> stmts, Cons body, bool allowtailcall) { Cons c = body; while (c != null) { Expression e = GetAst(c.car, cb, c.cdr == null); Statement s = null; if (c.cdr == null) { if (e.Type != cb.ReturnType) { Expression ee = e; while (ee is UnaryExpression) { var ue = ee as UnaryExpression; if (ue.NodeType != AstNodeType.Convert) { break; } if (ue.Operand.Type == cb.ReturnType) { e = ue.Operand; break; } ee = ue.Operand; } if (!(e is VoidExpression)) { e = Ast.ConvertHelper(e, cb.ReturnType); } } s = MakeTailCallReturn(allowtailcall, e); } else { s = Ast.Statement(e); } stmts.Add(s); c = c.cdr as Cons; } if (stmts.Count == 0) { stmts.Add(Ast.Return(Ast.ReadField(null, Unspecified))); } if (cb.Body != null) { stmts.InsertRange(0, (cb.Body as BlockStatement).Statements); } cb.Body = Ast.Block(stmts); cb.Body = OptimizeBody(cb.Body); if (cb.Parent == null || (cb.Parent.IsGlobal && cb.ParameterCount < 9)) { cb.ExplicitCodeContextExpression = Ast.CodeContext(); } }
// TODO: BRING THIS BACK /// <summary> /// Gets completions for the symbol found in the Ast at /// the given file offset. /// </summary> /// <param name="scriptAst"> /// The Ast which will be traversed to find a completable symbol. /// </param> /// <param name="currentTokens"> /// The array of tokens corresponding to the scriptAst parameter. /// </param> /// <param name="fileOffset"> /// The 1-based file offset at which a symbol will be located. /// </param> /// <param name="powerShellContext"> /// The PowerShellContext to use for gathering completions. /// </param> /// <param name="logger">An ILogger implementation used for writing log messages.</param> /// <param name="cancellationToken"> /// A CancellationToken to cancel completion requests. /// </param> /// <returns> /// A CommandCompletion instance that contains completions for the /// symbol at the given offset. /// </returns> public static async Task <CommandCompletion> GetCompletionsAsync( Ast scriptAst, Token[] currentTokens, int fileOffset, PowerShellContextService powerShellContext, ILogger logger, CancellationToken cancellationToken) { if (!s_completionHandle.Wait(0, CancellationToken.None)) { return(null); } try { IScriptPosition cursorPosition = (IScriptPosition)s_extentCloneWithNewOffset.Invoke( scriptAst.Extent.StartScriptPosition, new object[] { fileOffset }); logger.LogTrace( string.Format( "Getting completions at offset {0} (line: {1}, column: {2})", fileOffset, cursorPosition.LineNumber, cursorPosition.ColumnNumber)); if (!powerShellContext.IsAvailable) { return(null); } var stopwatch = new Stopwatch(); // If the current runspace is out of process we can use // CommandCompletion.CompleteInput because PSReadLine won't be taking up the // main runspace. if (powerShellContext.IsCurrentRunspaceOutOfProcess()) { using (RunspaceHandle runspaceHandle = await powerShellContext.GetRunspaceHandleAsync(cancellationToken).ConfigureAwait(false)) using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create()) { powerShell.Runspace = runspaceHandle.Runspace; stopwatch.Start(); try { return(CommandCompletion.CompleteInput( scriptAst, currentTokens, cursorPosition, options: null, powershell: powerShell)); } finally { stopwatch.Stop(); logger.LogTrace($"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms."); } } } CommandCompletion commandCompletion = null; await powerShellContext.InvokeOnPipelineThreadAsync( pwsh => { stopwatch.Start(); commandCompletion = CommandCompletion.CompleteInput( scriptAst, currentTokens, cursorPosition, options: null, powershell: pwsh); }).ConfigureAwait(false); stopwatch.Stop(); logger.LogTrace($"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms."); return(commandCompletion); } finally { s_completionHandle.Release(); } }
protected static Expression MakeCaseClosure(string name, List <CodeBlockDescriptor> cases) { List <Expression> targets = new List <Expression>(); List <Expression> arities = new List <Expression>(); foreach (CodeBlockDescriptor c in cases) { targets.Add(c.codeblock); arities.Add(Ast.Constant(c.arity)); } return(Ast.SimpleCallHelper(Closure_MakeCase, Ast.NewArrayHelper(typeof(Delegate[]), targets), Ast.NewArrayHelper(typeof(int[]), arities))); }
// interesting flow control... :S static Expression OptimizeExpression(Expression e, List <Statement> stmts) { if (e is ConstantExpression) { return(null); } if (e is BoundExpression) { // fails for (begin wtf 1) where wtf is undefined //return null; } if (e is MethodCallExpression) { //remove methods without side effects } if (IsUnspecified(e) && !ScriptDomainManager.Options.LightweightDebugging) { return(null); } if (e is ConditionalExpression) { ConditionalExpression ce = e as ConditionalExpression; if (IsUnspecified(ce.IfFalse)) { stmts.Add(Ast.If(ce.Test, OptimizeBody(Ast.Statement(ce.IfTrue)))); } else { stmts.Add(Ast.If(ce.Test, OptimizeBody(Ast.Statement(ce.IfTrue))).Else(OptimizeBody(Ast.Statement(ce.IfFalse)))); } return(null); } return(e); }
private void EnsureTracingTarget() { if (_tracingTarget == null) { PythonContext pc = (PythonContext)Ast.CompilerContext.SourceUnit.LanguageContext; var debugProperties = new PythonDebuggingPayload(null); var debugInfo = new Microsoft.Scripting.Debugging.CompilerServices.DebugLambdaInfo( null, // IDebugCompilerSupport null, // lambda alias false, // optimize for leaf frames null, // hidden variables null, // variable aliases debugProperties // custom payload ); var lambda = (Expression <LookupCompilationDelegate>)pc.DebugContext.TransformLambda((MSAst.LambdaExpression)Ast.GetLambda().Reduce(), debugInfo); LookupCompilationDelegate func; if (ShouldInterpret(pc)) { func = (LookupCompilationDelegate)CompilerHelpers.LightCompile(lambda, pc.Options.CompilationThreshold); } else { func = (LookupCompilationDelegate)lambda.Compile(pc.EmitDebugSymbols(Ast.CompilerContext.SourceUnit)); } _tracingTarget = func; debugProperties.Code = EnsureFunctionCode(_tracingTarget, true, true); } }
protected static Expression MakeClosure(CodeBlock cb, bool varargs, bool typed) { if (varargs) { return(Ast.SimpleCallHelper(Closure_MakeVarArgsX, Ast.CodeBlockExpression(cb, false, typed), Ast.Constant(cb.ParameterCount))); } else { return(Ast.SimpleCallHelper(Closure_Make, Ast.CodeBlockExpression(cb, false, typed), Ast.Constant(cb.ParameterCount))); } }
/// <summary> /// Report some telemetry about the scripts that are run /// </summary> internal static void ReportScriptTelemetry(Ast ast, bool dotSourced, long compileTimeInMS) { if (ast.Parent != null || !TelemetryWrapper.IsEnabled) { return; } Task.Run(() => { var extent = ast.Extent; var text = extent.Text; var hash = text.GetHashCode(); // Ignore 'prompt' so we don't generate an event for every 'prompt' that is invoked. // (We really should only create 'prompt' once, but we don't. if (hash == s_promptHashCode) { return; } var visitor = new ScriptBlockTelemetry(); ast.Visit(visitor); var scriptFileType = ScriptFileType.None; var fileName = extent.File; if (fileName != null) { var ext = System.IO.Path.GetExtension(fileName); if (".ps1".Equals(ext, StringComparison.OrdinalIgnoreCase)) { scriptFileType = ScriptFileType.Ps1; } else if (".psd1".Equals(ext, StringComparison.OrdinalIgnoreCase)) { scriptFileType = ScriptFileType.Psd1; } else if (".psm1".Equals(ext, StringComparison.OrdinalIgnoreCase)) { scriptFileType = ScriptFileType.Psm1; } else { // Reachable? scriptFileType = ScriptFileType.Other; } } TelemetryWrapper.TraceMessage("PSScriptDetails", new { Hash = hash, IsDotSourced = dotSourced, ScriptFileType = scriptFileType, Length = text.Length, LineCount = extent.EndLineNumber - extent.StartLineNumber, CompileTimeInMS = compileTimeInMS, StatementCount = visitor.StatementCount, CountOfCommands = visitor.CountOfCommands, CountOfDotSourcedCommands = visitor.CountOfDotSourcedCommands, MaxArrayLength = visitor.MaxArraySize, ArrayLiteralCount = visitor.ArrayLiteralCount, ArrayLiteralCumulativeSize = visitor.ArrayLiteralCumulativeSize, MaxStringLength = visitor.MaxStringSize, StringLiteralCount = visitor.StringLiteralCount, StringLiteralCumulativeSize = visitor.StringLiteralCumulativeSize, MaxPipelineDepth = visitor.MaxPipelineDepth, PipelineCount = visitor.PipelineCount, FunctionCount = visitor.FunctionCount, ScriptBlockCount = visitor.ScriptBlockCount, ClassCount = visitor.ClassCount, EnumCount = visitor.EnumCount, CommandsCalled = visitor.CommandsCalled, }); }); }
static Expression Read(SymbolId name, CodeBlock cb, Type type) { SymbolId sname = name; Variable v = cb.Lookup(sname); if (v == null) { if (assigns.ContainsKey(sname)) { return(Ast.Read(sname)); } else { CodeBlock tl = GetTopLevel(cb); v = tl.CreateVariable(sname, Variable.VariableKind.Global, typeof(object), Ast.Read(sname)); return(Ast.Read(v)); } } return(Ast.ReadDefined(v)); }
private Expression MakeReturn(Expression expression) { return(Ast.Return(_return, AstUtils.Convert(expression, _return.Type))); }
/// <summary> /// AnalyzeScript: Check if any uninitialized variable is used. /// </summary> public IEnumerable <DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { // TODO : We need to find another way for using S.M.A.L.Compiler.GetExpressionValue. // Following code are not working for certain scenarios;, like: // for ($i=1; $i -le 10; $i++){Write-Host $i} if (ast == null) { throw new ArgumentNullException(Strings.NullAstErrorMessage); } // Finds all VariableExpressionAst IEnumerable <Ast> foundAsts = ast.FindAll(testAst => testAst is VariableExpressionAst, true); // Iterates all VariableExpressionAst and check the command name. foreach (VariableExpressionAst varAst in foundAsts) { if (Helper.Instance.IsUninitialized(varAst, ast)) { yield return(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUninitializedVariableError, varAst.VariablePath.UserPath), varAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, varAst.VariablePath.UserPath)); } } IEnumerable <Ast> funcAsts = ast.FindAll(item => item is FunctionDefinitionAst, true); IEnumerable <Ast> funcMemberAsts = ast.FindAll(item => item is FunctionMemberAst, true); // Checks whether this is a dsc resource file (we don't raise this rule for get, set and test-target resource bool isDscResourceFile = Helper.Instance.IsDscResourceModule(fileName); List <string> targetResourcesFunctions = new List <string>(new string[] { "get-targetresource", "set-targetresource", "test-targetresource" }); foreach (FunctionDefinitionAst funcAst in funcAsts) { // Finds all VariableExpressionAst. IEnumerable <Ast> varAsts = funcAst.FindAll(testAst => testAst is VariableExpressionAst, true); HashSet <string> paramVariables = new HashSet <string>(); if (isDscResourceFile && targetResourcesFunctions.Contains(funcAst.Name, StringComparer.OrdinalIgnoreCase)) { // don't raise the rules for variables in the param block. if (funcAst.Body != null && funcAst.Body.ParamBlock != null && funcAst.Body.ParamBlock.Parameters != null) { paramVariables.UnionWith(funcAst.Body.ParamBlock.Parameters.Select(paramAst => paramAst.Name.VariablePath.UserPath)); } } // Iterates all VariableExpressionAst and check the command name. foreach (VariableExpressionAst varAst in varAsts) { if (Helper.Instance.IsUninitialized(varAst, funcAst) && !paramVariables.Contains(varAst.VariablePath.UserPath)) { yield return(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUninitializedVariableError, varAst.VariablePath.UserPath), varAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, varAst.VariablePath.UserPath)); } } } foreach (FunctionMemberAst funcMemAst in funcMemberAsts) { // Finds all VariableExpressionAst. IEnumerable <Ast> varAsts = funcMemAst.FindAll(testAst => testAst is VariableExpressionAst, true); // Iterates all VariableExpressionAst and check the command name. foreach (VariableExpressionAst varAst in varAsts) { if (Helper.Instance.IsUninitialized(varAst, funcMemAst)) { yield return(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.AvoidUninitializedVariableError, varAst.VariablePath.UserPath), varAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, varAst.VariablePath.UserPath)); } } } }
private DynamicMetaObject TryPythonConversion(DynamicMetaObjectBinder conversion, Type type) { if (!type.IsEnum()) { switch (type.GetTypeCode()) { case TypeCode.Object: if (type == typeof(Complex)) { return(MakeConvertRuleForCall(conversion, type, this, "__complex__", "ConvertToComplex", (() => MakeConvertRuleForCall(conversion, type, this, "__float__", "ConvertToFloat", (() => FallbackConvert(conversion)), (x) => Ast.Call(null, typeof(PythonOps).GetMethod("ConvertFloatToComplex"), x))), (x) => x)); } else if (type == typeof(BigInteger)) { return(MakeConvertRuleForCall(conversion, type, this, "__long__", "ConvertToLong")); } else if (type == typeof(IEnumerable)) { return(PythonConversionBinder.ConvertToIEnumerable(conversion, Restrict(Value.GetType()))); } else if (type == typeof(IEnumerator)) { return(PythonConversionBinder.ConvertToIEnumerator(conversion, Restrict(Value.GetType()))); } else if (type.IsSubclassOf(typeof(Delegate))) { return(MakeDelegateTarget(conversion, type, Restrict(Value.GetType()))); } break; case TypeCode.Int32: return(MakeConvertRuleForCall(conversion, type, this, "__int__", "ConvertToInt")); case TypeCode.Double: return(MakeConvertRuleForCall(conversion, type, this, "__float__", "ConvertToFloat")); case TypeCode.Boolean: return(PythonProtocol.ConvertToBool( conversion, this )); case TypeCode.String: if (!typeof(Extensible <string>).IsAssignableFrom(this.LimitType)) { return(MakeConvertRuleForCall(conversion, type, this, "__str__", "ConvertToString")); } break; } } return(null); }
internal static DynamicMetaObject Call(DynamicMetaObjectBinder /*!*/ call, DynamicMetaObject target, DynamicMetaObject /*!*/[] /*!*/ args) { Assert.NotNull(call, args); Assert.NotNullItems(args); if (target.NeedsDeferral()) { return(call.Defer(ArrayUtils.Insert(target, args))); } foreach (DynamicMetaObject mo in args) { if (mo.NeedsDeferral()) { RestrictTypes(args); return(call.Defer( ArrayUtils.Insert(target, args) )); } } DynamicMetaObject self = target.Restrict(target.GetLimitType()); ValidationInfo valInfo = BindingHelpers.GetValidationInfo(target); PythonType pt = DynamicHelpers.GetPythonType(target.Value); PythonContext pyContext = PythonContext.GetPythonContext(call); // look for __call__, if it's present dispatch to it. Otherwise fall back to the // default binder PythonTypeSlot callSlot; if (!typeof(Delegate).IsAssignableFrom(target.GetLimitType()) && pt.TryResolveSlot(pyContext.SharedContext, "__call__", out callSlot)) { ConditionalBuilder cb = new ConditionalBuilder(call); Expression body; callSlot.MakeGetExpression( pyContext.Binder, PythonContext.GetCodeContext(call), self, GetPythonType(self), cb ); if (!cb.IsFinal) { cb.FinishCondition(GetCallError(call, self)); } Expression[] callArgs = ArrayUtils.Insert( PythonContext.GetCodeContext(call), cb.GetMetaObject().Expression, DynamicUtils.GetExpressions(args) ); body = DynamicExpression.Dynamic( PythonContext.GetPythonContext(call).Invoke( BindingHelpers.GetCallSignature(call) ), typeof(object), callArgs ); body = Ast.TryFinally( Ast.Block( Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPushFrame)), Ast.Constant(pyContext)), body ), Ast.Call(typeof(PythonOps).GetMethod(nameof(PythonOps.FunctionPopFrame))) ); return(BindingHelpers.AddDynamicTestAndDefer( call, new DynamicMetaObject(body, self.Restrictions.Merge(BindingRestrictions.Combine(args))), args, valInfo )); } return(null); }
protected override bool Build(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, bool defaultFallback) { RubyModule currentDeclaringModule; string currentMethodName; var scope = args.Scope; var scopeExpr = AstUtils.Convert(args.MetaScope.Expression, typeof(RubyScope)); RubyScope targetScope; int scopeNesting = scope.GetSuperCallTarget(out currentDeclaringModule, out currentMethodName, out targetScope); if (scopeNesting == -1) { metaBuilder.AddCondition(Methods.IsSuperOutOfMethodScope.OpCall(scopeExpr)); metaBuilder.SetError(Methods.MakeTopLevelSuperException.OpCall()); return(true); } object target = targetScope.SelfObject; var targetExpression = metaBuilder.GetTemporary(typeof(object), "#super-self"); var assignTarget = Ast.Assign( targetExpression, Methods.GetSuperCallTarget.OpCall(scopeExpr, AstUtils.Constant(scopeNesting)) ); if (_signature.HasImplicitArguments && targetScope.Kind == ScopeKind.BlockMethod) { metaBuilder.AddCondition(Ast.NotEqual(assignTarget, Ast.Field(null, Fields.NeedsUpdate))); metaBuilder.SetError(Methods.MakeImplicitSuperInBlockMethodError.OpCall()); return(true); } // If we need to update we return RubyOps.NeedsUpdate instance that will cause the subsequent conditions to fail: metaBuilder.AddInitialization(assignTarget); args.SetTarget(targetExpression, target); Debug.Assert(currentDeclaringModule != null); RubyMemberInfo method; RubyMemberInfo methodMissing = null; // MRI bug: Uses currentDeclaringModule for method look-up so we can end up with an instance method of class C // called on a target of another class. See http://redmine.ruby-lang.org/issues/show/2419. // we need to lock the hierarchy of the target class: var targetClass = scope.RubyContext.GetImmediateClassOf(target); using (targetClass.Context.ClassHierarchyLocker()) { // initialize all methods in ancestors: targetClass.InitializeMethodsNoLock(); // target is stored in a local, therefore it cannot be part of the restrictions: metaBuilder.TreatRestrictionsAsConditions = true; metaBuilder.AddTargetTypeTest(target, targetClass, targetExpression, args.MetaContext, new[] { Symbols.MethodMissing } // currentMethodName is resolved for super, which cannot be an instance singleton ); metaBuilder.TreatRestrictionsAsConditions = false; method = targetClass.ResolveSuperMethodNoLock(currentMethodName, currentDeclaringModule).InvalidateSitesOnOverride().Info; if (_signature.ResolveOnly) { metaBuilder.Result = AstUtils.Constant(method != null); return(true); } if (method == null) { // MRI: method_missing is called for the targetClass, not for the super: methodMissing = targetClass.ResolveMethodMissingForSite(currentMethodName, RubyMethodVisibility.None); } } if (method != null) { method.BuildSuperCall(metaBuilder, args, currentMethodName, currentDeclaringModule); } else { return(RubyCallAction.BuildMethodMissingCall(metaBuilder, args, currentMethodName, methodMissing, RubyMethodVisibility.None, true, defaultFallback)); } return(true); }
private DynamicMetaObject /*!*/ MakeConvertRuleForCall(DynamicMetaObjectBinder /*!*/ convertToAction, Type toType, DynamicMetaObject /*!*/ self, string name, string returner, Func <DynamicMetaObject> fallback, Func <Expression, Expression> resultConverter) { PythonType pt = ((IPythonObject)self.Value).PythonType; PythonTypeSlot pts; CodeContext context = PythonContext.GetPythonContext(convertToAction).SharedContext; ValidationInfo valInfo = BindingHelpers.GetValidationInfo(this, pt); if (pt.TryResolveSlot(context, name, out pts) && !IsBuiltinConversion(context, pts, name, pt)) { ParameterExpression tmp = Ast.Variable(typeof(object), "func"); Expression callExpr = resultConverter( Ast.Call( PythonOps.GetConversionHelper(returner, GetResultKind(convertToAction)), Ast.Dynamic( PythonContext.GetPythonContext(convertToAction).InvokeNone, typeof(object), PythonContext.GetCodeContext(convertToAction), tmp ) ) ); if (typeof(Extensible <>).MakeGenericType(toType).IsAssignableFrom(self.GetLimitType())) { // if we're doing a conversion to the underlying type and we're an // Extensible<T> of that type: // if an extensible type returns it's self in a conversion, then we need // to actually return the underlying value. If an extensible just keeps // returning more instances of it's self a stack overflow occurs - both // behaviors match CPython. callExpr = AstUtils.Convert(AddExtensibleSelfCheck(convertToAction, toType, self, callExpr), typeof(object)); } return(BindingHelpers.AddDynamicTestAndDefer( convertToAction, new DynamicMetaObject( Ast.Condition( MakeTryGetTypeMember( PythonContext.GetPythonContext(convertToAction), pts, self.Expression, tmp ), callExpr, AstUtils.Convert( ConversionFallback(convertToAction), typeof(object) ) ), self.Restrict(self.GetRuntimeType()).Restrictions ), new DynamicMetaObject[] { this }, valInfo, tmp )); } return(fallback()); }
private DynamicMetaObject TryToCharConversion(DynamicMetaObject /*!*/ self) { DynamicMetaObject res; // we have an implicit conversion to char if the // string length == 1, but we can only represent // this is implicit via a rule. string strVal = self.Value as string; Expression strExpr = self.Expression; if (strVal == null) { if (self.Value is Extensible <string> extstr) { strVal = extstr.Value; strExpr = Ast.Property( AstUtils.Convert( strExpr, typeof(Extensible <string>) ), typeof(Extensible <string>).GetProperty(nameof(Extensible <string> .Value)) ); } } // we can only produce a conversion if we have a string value... if (strVal != null) { self = self.Restrict(self.GetRuntimeType()); Expression getLen = Ast.Property( AstUtils.Convert( strExpr, typeof(string) ), typeof(string).GetProperty("Length") ); if (strVal.Length == 1) { res = new DynamicMetaObject( Ast.Call( AstUtils.Convert(strExpr, typeof(string)), typeof(string).GetMethod("get_Chars", new[] { typeof(int) }), AstUtils.Constant(0) ), self.Restrictions.Merge(BindingRestrictions.GetExpressionRestriction(Ast.Equal(getLen, AstUtils.Constant(1)))) ); } else { res = new DynamicMetaObject( this.Throw( Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.TypeError)), AstUtils.Constant("expected string of length 1 when converting to char, got '{0}'"), Ast.NewArrayInit(typeof(object), self.Expression) ), ReturnType ), self.Restrictions.Merge(BindingRestrictions.GetExpressionRestriction(Ast.NotEqual(getLen, AstUtils.Constant(1)))) ); } } else { // let the base class produce the rule res = null; } return(res); }
public ScriptEntryInfo(Ast script) { _start = script.Extent.StartOffset; _end = script.Extent.EndOffset; }
internal override MSAst.Expression TransformSet(SourceSpan span, MSAst.Expression right, PythonOperationKind op) { // if we just have a simple named multi-assignment (e.g. a, b = 1,2) // then go ahead and step over the entire statement at once. If we have a // more complex statement (e.g. a.b, c.d = 1, 2) then we'll step over the // sets individually as they could be property sets the user wants to step // into. TODO: Enable stepping of the right hand side? bool emitIndividualSets = false; foreach (Expression e in _items) { if (IsComplexAssignment(e)) { emitIndividualSets = true; break; } } SourceSpan rightSpan = SourceSpan.None; SourceSpan leftSpan = (Span.Start.IsValid && span.IsValid) ? new SourceSpan(Span.Start, span.End) : SourceSpan.None; SourceSpan totalSpan = SourceSpan.None; if (emitIndividualSets) { rightSpan = span; leftSpan = SourceSpan.None; totalSpan = (Span.Start.IsValid && span.IsValid) ? new SourceSpan(Span.Start, span.End) : SourceSpan.None; } // 1. Evaluate the expression and assign the value to the temp. MSAst.ParameterExpression right_temp = Ast.Variable(typeof(object), "unpacking"); // 2. Add the assignment "right_temp = right" into the suite/block MSAst.Expression assignStmt1 = MakeAssignment(right_temp, right); int expected = _items.Length; int argcntafter = -1; for (var i = 0; i < _items.Length; i++) { var item = _items[i]; if (item is StarredExpression) { expected = i; argcntafter = _items.Length - i - 1; break; } } // 3. Call GetEnumeratorValues on the right side (stored in temp) MSAst.Expression enumeratorValues = Expression.Convert(LightExceptions.CheckAndThrow( Expression.Call( // method argcntafter != -1 ? AstMethods.UnpackIterable : emitIndividualSets ? AstMethods.GetEnumeratorValues : AstMethods.GetEnumeratorValuesNoComplexSets, // arguments Parent.LocalContext, right_temp, AstUtils.Constant(expected), AstUtils.Constant(argcntafter) ) ), typeof(object[])); // 4. Create temporary variable for the array MSAst.ParameterExpression array_temp = Ast.Variable(typeof(object[]), "array"); // 5. Assign the value of the method call (mce) into the array temp // And add the assignment "array_temp = Ops.GetEnumeratorValues(...)" into the block MSAst.Expression assignStmt2 = MakeAssignment( array_temp, enumeratorValues, rightSpan ); ReadOnlyCollectionBuilder <MSAst.Expression> sets = new ReadOnlyCollectionBuilder <MSAst.Expression>(_items.Length + 1); for (int i = 0; i < _items.Length; i++) { // target = array_temp[i] Expression target = _items[i]; if (target == null) { continue; } // 6. array_temp[i] MSAst.Expression element = Ast.ArrayAccess( array_temp, // array expression AstUtils.Constant(i) // index ); // 7. target = array_temp[i], and add the transformed assignment into the list of sets MSAst.Expression set = target.TransformSet( emitIndividualSets ? // span target.Span : SourceSpan.None, element, PythonOperationKind.None ); sets.Add(set); } // 9. add the sets as their own block so they can be marked as a single span, if necessary. sets.Add(AstUtils.Empty()); MSAst.Expression itemSet = GlobalParent.AddDebugInfo(Ast.Block(sets.ToReadOnlyCollection()), leftSpan); // 10. Return the suite statement (block) return(GlobalParent.AddDebugInfo(Ast.Block(new[] { array_temp, right_temp }, assignStmt1, assignStmt2, itemSet, AstUtils.Empty()), totalSpan)); }
internal override void BuildCallNoFlow(MetaObjectBuilder /*!*/ metaBuilder, CallArguments /*!*/ args, string /*!*/ name) { var visibleOverloads = GetVisibleOverloads(args, MethodBases, false); if (visibleOverloads.Count == 0) { metaBuilder.SetError(Methods.MakeClrProtectedMethodCalledError.OpCall( args.MetaContext.Expression, args.MetaTarget.Expression, Ast.Constant(name) )); } else { BuildCallNoFlow(metaBuilder, args, name, visibleOverloads, CallConvention, ImplicitProtocolConversions); } }
/// <summary> /// Used to analyze scriptblock, functionmemberast or functiondefinitionast /// </summary> /// <param name="ast"></param> /// <returns></returns> public void AnalyzeImpl(Ast ast, VariableAnalysis outerAnalysis) { #if PSV3 if (!(ast is ScriptBlockAst || ast is FunctionDefinitionAst)) #else if (!(ast is ScriptBlockAst || ast is FunctionMemberAst || ast is FunctionDefinitionAst)) #endif { return; } _variables = FindAllVariablesVisitor.Visit(ast); Init(); #if PSV3 if (ast is FunctionDefinitionAst) #else if (ast is FunctionMemberAst || ast is FunctionDefinitionAst) #endif { IEnumerable <ParameterAst> parameters = FindParameters(ast, ast.GetType()); if (parameters != null) { ProcessParameters(parameters); } } else { ScriptBlockAst sbAst = ast as ScriptBlockAst; if (sbAst != null && sbAst.ParamBlock != null && sbAst.ParamBlock.Parameters != null) { ProcessParameters(sbAst.ParamBlock.Parameters); } } #if PSV3 if (ast is FunctionDefinitionAst) #else if (ast is FunctionMemberAst) { (ast as FunctionMemberAst).Body.Visit(this.Decorator); } else if (ast is FunctionDefinitionAst) #endif { (ast as FunctionDefinitionAst).Body.Visit(this.Decorator); } else { ast.Visit(this.Decorator); } Ast parent = ast; while (parent.Parent != null) { parent = parent.Parent; } #if !PSV3 List <TypeDefinitionAst> classes = parent.FindAll(item => item is TypeDefinitionAst && (item as TypeDefinitionAst).IsClass, true) .Cast <TypeDefinitionAst>().ToList(); #endif if (outerAnalysis != null) { // Initialize the variables from outside var outerDictionary = outerAnalysis.InternalVariablesDictionary; foreach (var details in outerDictionary.Values) { if (details.DefinedBlock != null) { var assignTarget = new AssignmentTarget(details.RealName, details.Type); assignTarget.Constant = details.Constant; if (!_variables.ContainsKey(assignTarget.Name)) { _variables.Add(assignTarget.Name, new VariableAnalysisDetails { Name = assignTarget.Name, RealName = assignTarget.Name, Type = assignTarget.Type }); } Entry.AddFirstAst(assignTarget); } } foreach (var key in _variables.Keys) { if (outerDictionary.ContainsKey(key)) { var outerItem = outerDictionary[key]; var innerItem = _variables[key]; innerItem.Constant = outerItem.Constant; innerItem.Name = outerItem.Name; innerItem.RealName = outerItem.RealName; innerItem.Type = outerItem.Type; } } } #if PSV3 var dictionaries = Block.SparseSimpleConstants(_variables, Entry); #else var dictionaries = Block.SparseSimpleConstants(_variables, Entry, classes); #endif VariablesDictionary = dictionaries.Item1; InternalVariablesDictionary = new Dictionary <string, VariableAnalysisDetails>(StringComparer.OrdinalIgnoreCase); foreach (var KVP in dictionaries.Item2) { var analysis = KVP.Value; if (analysis == null) { continue; } if (!InternalVariablesDictionary.ContainsKey(analysis.RealName)) { InternalVariablesDictionary.Add(analysis.RealName, analysis); } else { InternalVariablesDictionary[analysis.RealName] = analysis; } } }
internal DynamicMetaObject FallbackConvert(Type returnType, DynamicMetaObject self, DynamicMetaObject errorSuggestion) { Type type = Type; DynamicMetaObject res = null; switch (type.GetTypeCode()) { case TypeCode.Boolean: res = MakeToBoolConversion(self); break; case TypeCode.Char: res = TryToCharConversion(self); break; case TypeCode.String: break; case TypeCode.Object: // !!! Deferral? if (type.IsArray && self.Value is PythonTuple && type.GetArrayRank() == 1) { res = MakeToArrayConversion(self, type); } else if (type == typeof(IBufferProtocol) && !type.IsAssignableFrom(self.GetLimitType())) { Type fromType = CompilerHelpers.GetType(self.Value); if (fromType == typeof(Memory <byte>)) { res = ConvertFromMemoryToBufferProtocol(self.Restrict(self.GetLimitType()), typeof(Memory <byte>)); } else if (fromType == typeof(ReadOnlyMemory <byte>)) { res = ConvertFromMemoryToBufferProtocol(self.Restrict(self.GetLimitType()), typeof(ReadOnlyMemory <byte>)); } else if (Converter.HasImplicitConversion(fromType, typeof(Memory <byte>))) { res = ConvertFromMemoryToBufferProtocol(self.Restrict(self.GetLimitType()), typeof(Memory <byte>)); } else if (Converter.HasImplicitConversion(fromType, typeof(ReadOnlyMemory <byte>))) { res = ConvertFromMemoryToBufferProtocol(self.Restrict(self.GetLimitType()), typeof(ReadOnlyMemory <byte>)); } } else if (type.IsGenericType && !type.IsAssignableFrom(CompilerHelpers.GetType(self.Value))) { Type genTo = type.GetGenericTypeDefinition(); // Interface conversion helpers... if (type == typeof(IReadOnlyList <byte>) && self.Value is IBufferProtocol) { res = ConvertFromBufferProtocolToByteList(self.Restrict(self.GetLimitType()), typeof(IReadOnlyList <byte>)); } else if (type == typeof(IList <byte>) && self.Value is IBufferProtocol) { res = ConvertFromBufferProtocolToByteList(self.Restrict(self.GetLimitType()), typeof(IList <byte>)); } else if (genTo == typeof(IList <>)) { res = TryToGenericInterfaceConversion(self, type, typeof(IList <object>), typeof(ListGenericWrapper <>)); } else if (genTo == typeof(IDictionary <,>)) { res = TryToGenericInterfaceConversion(self, type, typeof(IDictionary <object, object>), typeof(DictionaryGenericWrapper <,>)); } else if (genTo == typeof(IEnumerable <>)) { res = TryToGenericInterfaceConversion(self, type, typeof(IEnumerable), typeof(IEnumerableOfTWrapper <>)); } } else if (type == typeof(IEnumerable)) { if (!typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) { res = ConvertToIEnumerable(this, self.Restrict(self.GetLimitType())); } } else if (type == typeof(IEnumerator)) { if (!typeof(IEnumerator).IsAssignableFrom(self.GetLimitType()) && !typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) { res = ConvertToIEnumerator(this, self.Restrict(self.GetLimitType())); } } break; } if (type.IsEnum && Enum.GetUnderlyingType(type) == self.GetLimitType()) { // numeric type to enum, this is ok if the value is zero object value = Activator.CreateInstance(type); return(new DynamicMetaObject( Ast.Condition( Ast.Equal( AstUtils.Convert(self.Expression, Enum.GetUnderlyingType(type)), AstUtils.Constant(Activator.CreateInstance(self.GetLimitType())) ), AstUtils.Constant(value), Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.TypeErrorForBadEnumConversion)).MakeGenericMethod(type), AstUtils.Convert(self.Expression, typeof(object)) ) ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, self.GetLimitType())), value )); } return(res ?? EnsureReturnType(returnType, Context.Binder.ConvertTo(Type, ResultKind, self, _context.SharedOverloadResolverFactory, errorSuggestion))); }
internal override Expression ToExpression(OverloadResolver resolver, IList <ArgBuilder> builders, RestrictedArguments args, Expression ret) { List <Expression> sets = new List <Expression>(); ParameterExpression tmp = resolver.GetTemporary(ret.Type, "val"); sets.Add( Ast.Assign(tmp, ret) ); for (int i = 0; i < _indexesUsed.Length; i++) { Expression value = args.GetObject(args.Length - _kwArgCount + _indexesUsed[i]).Expression; PropertyInfo pi; FieldInfo fi; if ((fi = _membersSet[i] as FieldInfo) != null) { if (!fi.IsLiteral && !fi.IsInitOnly) { sets.Add( Ast.Assign( Ast.Field(tmp, fi), ConvertToHelper(resolver, value, fi.FieldType) ) ); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"), AstUtils.Constant(true), AstUtils.Constant(fi.Name) ), fi.FieldType ) ); } } else if ((pi = _membersSet[i] as PropertyInfo) != null) { if (pi.GetSetMethod(_privateBinding) != null) { sets.Add( Ast.Assign( Ast.Property(tmp, pi), ConvertToHelper(resolver, value, pi.PropertyType) ) ); } else { // call a helper which throws the error but "returns object" sets.Add( Ast.Convert( Ast.Call( typeof(ScriptingRuntimeHelpers).GetMethod("ReadOnlyAssignError"), AstUtils.Constant(false), AstUtils.Constant(pi.Name) ), pi.PropertyType ) ); } } } sets.Add( tmp ); Expression newCall = Ast.Block( sets.ToArray() ); return(_builder.ToExpression(resolver, builders, args, newCall)); }
public Call(Ast function, params Ast[] parametersValues) { Function = function; ParametersValues = parametersValues; }