public JsNode VisitLambdaResolveResult(LambdaResolveResult res) { //var prmTypes = res.Parameters.Select(t => t.Type).ToArray(); //var retType = res.GetInferredReturnType(prmTypes); //var conv = res.IsValid(prmTypes, retType, CSharpConversions.Get(Project.Compilation)); //return Visit(conv); var func = new JsFunction { Parameters = res.Parameters.Select(t => JsIdentifier(t.Name)).ToList() }; var body = res.Body; JsNode body2; var info = res.GetInfo(); if (body.GetType() == typeof(ResolveResult) && body.Type.IsVoid()) { var x = res.GetType().GetProperty("BodyExpression", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(res, null); var astNode = (AstNode)x; body2 = Visit(astNode); } else { body2 = Visit(res.Body); } var currentMember = res.GetCurrentMember(); var delType = info.ConversionTargetType; if (body2 is JsExpression) { var delMethod = delType.GetDelegateInvokeMethod(); JsStatement st = new JsReturnStatement { Expression = (JsExpression)body2 }; if (delMethod != null && delMethod.ReturnType.IsVoid()) { st = new JsExpressionStatement { Expression = (JsExpression)body2 } } ; func.Block = new JsBlock { Statements = new List <JsStatement> { st } }; } else if (body2 is JsBlock) { func.Block = (JsBlock)body2; } if (delType == null || currentMember == null) { Log.Warn(res.GetFirstNode(), "Cannot resolve delegate type / parent method"); return(func); } else { return(CreateJsDelegateIfNeeded(func, currentMember, delType, true)); } }
public virtual JsNode Visit(JsExpressionStatement node) { return(DefaultVisit(node, x => { x.Expression = (JsExpression)x.Expression.Accept(this); return x; })); }
public object VisitExpressionStatement(JsExpressionStatement statement, bool addNewline) { VisitExpression(statement.Expression, statement.Expression is JsFunctionDefinitionExpression); _cb.Append(";"); if (addNewline) { _cb.AppendLine(); } return(null); }
public object VisitExpressionStatement(JsExpressionStatement statement, bool addNewline) { VisitExpression(statement.Expression, ParenthesizeExpressionAsStatement(statement.Expression)); _cb.Append(";"); if (addNewline) { _cb.AppendLine(); } return(null); }
public virtual void Visit(JsExpressionStatement node) { DefaultVisit(node); node.Expression.Accept(this); }
public JsNode VisitMethodGroupResolveResult(MethodGroupResolveResult res) { var info = res.GetInfo(); IMethod me; if (info != null && info.Conversion != null && info.Conversion.Method != null) { me = info.Conversion.Method; } else //happens when invoking a method with overloads, and a parameter is dynamic { var list = res.Methods.ToList(); if (list.Count == 0) { throw new Exception("Method group not resolved to any method"); } else if (list.Count == 1) { me = list[0]; } else { me = list[0]; } //TODO: verify all methods has the same js name } var isExtensionMethodStyle = me.IsExtensionMethod && !(res.TargetResult is TypeResolveResult) && info != null && info.Conversion != null && info.Conversion.DelegateCapturesFirstArgument;//TODO: IsExtensionMethodStyle(new CsInvocationExpression { entity = me, expression = node }); JsExpression firstPrm = null; if (isExtensionMethodStyle) { firstPrm = (JsExpression)Visit(res.TargetResult); } var node2 = SkJs.EntityToMember(me); JsExpression node3; JsExpression instanceContext = null; if (me.IsStatic || res.TargetResult == null) //getting ThisResolveResult even on static methods, getting TargetResult=null when MethodGroupResolveResult when using delegates { node3 = node2; } else { instanceContext = VisitExpression(res.TargetResult); node3 = instanceContext.Member(node2); } if (info != null && (instanceContext != null || firstPrm != null)) { if (info.ConversionTargetType != null && !UseNativeFunctions(info.ConversionTargetType))//delegate type { var parentMethod = info.Nodes.FirstOrDefault().GetCurrentMethod(); if (parentMethod == null || !Sk.ForceDelegatesAsNativeFunctions(parentMethod)) { if (parentMethod == null) { Log.Warn(info.Nodes.FirstOrDefault(), "GetParentMethod() returned null"); } var func = (JsExpression)node2; if (instanceContext != null) { node3 = CreateJsDelegate(instanceContext, func); } else if (firstPrm != null) { node3 = CreateJsExtensionDelegate(firstPrm, func); } } } } // 其实以下的处理,也可以改代码,改成 Lambda 写法即可 // 这样子引用的并不是同一个函数,可能会造成内存泄露 if (res.TypeArguments.Count > 0 && info.Conversion.IsImplicit && me is SpecializedMethod) { var delegateFunc = node3 as JsInvocationExpression; var sme = (SpecializedMethod)me; var pars = sme.TypeArguments.Select(type => SkJs.EntityTypeRefToMember(type, false)).ToList(); pars.AddRange(sme.Parameters.Select(t => new JsCodeExpression { Code = JsIdentifier(t.Name), })); var body = delegateFunc == null?node3.Invoke(pars.ToArray()) : delegateFunc.Arguments[1].Invoke(pars.ToArray()); var func = new JsFunction() { Parameters = sme.Parameters.Select(t => JsIdentifier(t.Name)).ToList(), }; JsStatement st; if (sme.ReturnType.IsVoid()) { st = new JsExpressionStatement { Expression = body }; } else { st = new JsReturnStatement { Expression = body }; } func.Block = new JsBlock { Statements = new List <JsStatement> { st } }; if (delegateFunc == null) { node3 = func; } else { delegateFunc.Arguments[1] = func; } } return(node3); }
public override void VisitExpressionStatement(JsExpressionStatement node) { node.Expression.Accept(this); output.AppendLine(";"); }
private JsBlockStatement GenerateUsingBlock(LocalResolveResult resource, Expression aquisitionExpression, DomRegion tempVariableRegion, JsBlockStatement body) { SetRegion(aquisitionExpression.GetRegion()); var boolType = _compilation.FindType(KnownTypeCode.Boolean); var systemIDisposable = _compilation.FindType(KnownTypeCode.IDisposable); var disposeMethod = systemIDisposable.GetMethods().Single(m => m.Name == "Dispose"); var conversions = CSharpConversions.Get(_compilation); var compiledAquisition = CompileExpression(aquisitionExpression, true); var stmts = new List<JsStatement>(); stmts.AddRange(compiledAquisition.AdditionalStatements); stmts.Add(new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[resource.Variable].Name, compiledAquisition.Expression))); bool isDynamic = resource.Type.Kind == TypeKind.Dynamic; if (isDynamic) { var newResource = CreateTemporaryVariable(systemIDisposable, tempVariableRegion); var castExpr = _expressionCompiler.Compile(new ConversionResolveResult(systemIDisposable, resource, conversions.ExplicitConversion(resource, systemIDisposable)), true); stmts.AddRange(castExpr.AdditionalStatements); stmts.Add(new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[newResource].Name, castExpr.Expression))); resource = new LocalResolveResult(newResource); } var compiledDisposeCall = _expressionCompiler.Compile( new CSharpInvocationResolveResult( new ConversionResolveResult(systemIDisposable, resource, conversions.ImplicitConversion(resource, systemIDisposable)), disposeMethod, new ResolveResult[0] ), false); if (compiledDisposeCall.AdditionalStatements.Count > 0) _errorReporter.InternalError("Type test cannot return additional statements."); JsStatement releaseStmt; if (isDynamic) { releaseStmt = new JsExpressionStatement(compiledDisposeCall.Expression); } else { // if (d != null) ((IDisposable)d).Dispose() var compiledTest = _expressionCompiler.Compile(new OperatorResolveResult(boolType, ExpressionType.NotEqual, resource, new ConstantResolveResult(resource.Type, null)), true); if (compiledTest.AdditionalStatements.Count > 0) _errorReporter.InternalError("Null test cannot return additional statements."); releaseStmt = new JsIfStatement(compiledTest.Expression, new JsExpressionStatement(compiledDisposeCall.Expression), null); } stmts.Add(new JsTryStatement(body, null, releaseStmt)); return new JsBlockStatement(stmts); }
public override void VisitForeachStatement(ForeachStatement foreachStatement) { var ferr = (ForEachResolveResult)_resolver.Resolve(foreachStatement); var iterator = (LocalResolveResult)_resolver.Resolve(foreachStatement.VariableNameToken); var systemArray = _compilation.FindType(KnownTypeCode.Array); var inExpression = ResolveWithConversion(foreachStatement.InExpression); if (Equals(inExpression.Type, systemArray) || inExpression.Type.DirectBaseTypes.Contains(systemArray)) { var arrayResult = CompileExpression(foreachStatement.InExpression, true); _result.AddRange(arrayResult.AdditionalStatements); var array = arrayResult.Expression; if (ExpressionCompiler.IsJsExpressionComplexEnoughToGetATemporaryVariable.Process(array)) { var tmpArray = CreateTemporaryVariable(ferr.CollectionType, foreachStatement.GetRegion()); _result.Add(new JsVariableDeclarationStatement(_variables[tmpArray].Name, array)); array = JsExpression.Identifier(_variables[tmpArray].Name); } var length = systemArray.GetProperties().SingleOrDefault(p => p.Name == "Length"); if (length == null) { _errorReporter.InternalError("Property Array.Length not found."); return; } var lengthSem = _metadataImporter.GetPropertySemantics(length); if (lengthSem.Type != PropertyScriptSemantics.ImplType.Field) { _errorReporter.InternalError("Property Array.Length is not implemented as a field."); return; } var index = CreateTemporaryVariable(_compilation.FindType(KnownTypeCode.Int32), foreachStatement.GetRegion()); var jsIndex = JsExpression.Identifier(_variables[index].Name); var body = new[] { new JsVariableDeclarationStatement(_variables[iterator.Variable].Name, JsExpression.Index(array, jsIndex)) } .Concat(CreateInnerCompiler().Compile(foreachStatement.EmbeddedStatement).Statements); _result.Add(new JsForStatement(new JsVariableDeclarationStatement(_variables[index].Name, JsExpression.Number(0)), JsExpression.Lesser(jsIndex, JsExpression.MemberAccess(array, lengthSem.FieldName)), JsExpression.PostfixPlusPlus(jsIndex), new JsBlockStatement(body))); } else { var getEnumeratorCall = _expressionCompiler.Compile(ferr.GetEnumeratorCall, true); _result.AddRange(getEnumeratorCall.AdditionalStatements); var enumerator = CreateTemporaryVariable(ferr.EnumeratorType, foreachStatement.GetRegion()); _result.Add(new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[enumerator].Name, getEnumeratorCall.Expression))); var moveNextInvocation = _expressionCompiler.Compile(new CSharpInvocationResolveResult(new LocalResolveResult(enumerator), ferr.MoveNextMethod, new ResolveResult[0]), true); if (moveNextInvocation.AdditionalStatements.Count > 0) _errorReporter.InternalError("MoveNext() invocation is not allowed to require additional statements."); var getCurrent = _expressionCompiler.Compile(new MemberResolveResult(new LocalResolveResult(enumerator), ferr.CurrentProperty), true); var preBody = getCurrent.AdditionalStatements.Concat(new[] { new JsVariableDeclarationStatement(new JsVariableDeclaration(_variables[iterator.Variable].Name, getCurrent.Expression)) }).ToList(); var body = CreateInnerCompiler().Compile(foreachStatement.EmbeddedStatement); body = new JsBlockStatement(preBody.Concat(body.Statements)); JsStatement disposer; var systemIDisposable = _compilation.FindType(KnownTypeCode.IDisposable); var disposeMethod = systemIDisposable.GetMethods().Single(m => m.Name == "Dispose"); var conversions = CSharpConversions.Get(_compilation); var disposableConversion = conversions.ImplicitConversion(enumerator.Type, systemIDisposable); if (disposableConversion.IsValid) { // If the enumerator is implicitly convertible to IDisposable, we should dispose it. var compileResult = _expressionCompiler.Compile(new CSharpInvocationResolveResult(new ConversionResolveResult(systemIDisposable, new LocalResolveResult(enumerator), disposableConversion), disposeMethod, new ResolveResult[0]), false); if (compileResult.AdditionalStatements.Count != 0) _errorReporter.InternalError("Call to IDisposable.Dispose must not return additional statements."); disposer = new JsExpressionStatement(compileResult.Expression); } else if (enumerator.Type.GetDefinition().IsSealed) { // If the enumerator is sealed and not implicitly convertible to IDisposable, we need not dispose it. disposer = null; } else { // We don't know whether the enumerator is convertible to IDisposable, so we need to conditionally dispose it. var test = _expressionCompiler.Compile(new TypeIsResolveResult(new LocalResolveResult(enumerator), systemIDisposable, _compilation.FindType(KnownTypeCode.Boolean)), true); if (test.AdditionalStatements.Count > 0) _errorReporter.InternalError("\"is\" test must not return additional statements."); var innerStatements = _expressionCompiler.Compile(new CSharpInvocationResolveResult(new ConversionResolveResult(systemIDisposable, new LocalResolveResult(enumerator), conversions.ExplicitConversion(enumerator.Type, systemIDisposable)), disposeMethod, new ResolveResult[0]), false); disposer = new JsIfStatement(test.Expression, new JsBlockStatement(innerStatements.AdditionalStatements.Concat(new[] { new JsExpressionStatement(innerStatements.Expression) })), null); } JsStatement stmt = new JsWhileStatement(moveNextInvocation.Expression, body); if (disposer != null) stmt = new JsTryStatement(stmt, null, disposer); _result.Add(stmt); } }
public virtual JsStatement VisitExpressionStatement(JsExpressionStatement statement, TData data) { var after = VisitExpression(statement.Expression, data); return(ReferenceEquals(after, statement.Expression) ? statement : new JsExpressionStatement(after)); }
public virtual void VisitExpressionStatement(JsExpressionStatement node) { }
public void Visit(JsExpressionStatement node) { BeforeVisit(node); DefaultVisit(node, VisitExpressionStatement); AfterVisit(node); }
/// <summary> /// Equalses the specified other. /// </summary> /// <param name="other">The other.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> protected bool Equals(JsExpressionStatement other) => Equals(Expression, other.Expression);