protected override Expression VisitLambda <T>(Expression <T> node) { Visit(node.Body); constructed = Js.Function(node.Name, new[] { Js.Return(constructed) }, node.Parameters.Select(p => p.Name).ToArray()); return(node); }
protected override void OnBaseStateGenerated() { var lastStatement = CurrentState.Statements.LastOrDefault(); if (lastStatement is JsContinueStatement || lastStatement is JsBreakStatement || lastStatement is JsReturnStatement) { return; } CurrentState.Add(Js.Return(Js.Primitive(false))); }
public static JsReturnStatement GenerateYieldReturnStatement(IMethod me) { //JsReturnStatement node2; //if (me != null && me.ReturnType != null && me.ReturnType.FullName.StartsWith("System.Collections.Generic.IEnumerator")) // node2 = Js.Return(Js.Member("$yield").Member("GetEnumerator").Invoke()); //else // node2 = Js.Return(Js.Member("$yield")); //return node2; return(Js.Return()); }
void YieldReturnInCurrentStep(JsExpression item) { var result = Js.Value(true); var stepIndex = Steps.Count - 1; AddToCurrentStep(Js.This().Member("_current").Assign(item).Statement()); AddToCurrentStep(_state().Assign(Js.Value(stepIndex + 1)).Statement()); AddToCurrentStep(Js.Member("result").Assign(result).Statement()); AddToCurrentStep(Js.Return(result)); }
public override JsNode Visit(JsReturnStatement node) { escapeStatements.Add(new EscapeStatement { Type = Return }); return(Js.Return(Js.Object( Js.Item(EscapeTypeField, Js.Primitive(Return)), Js.Item(EscapeValueField, node.Expression != null ? node.Expression : Js.Null()), Js.Item(EscapeDepthField, Js.Primitive(loopDepth)) ).Compact())); }
public override JsNode Visit(JsBreakStatement node) { escapeStatements.Add(new EscapeStatement { Type = Break, Label = node.Label }); return(Js.Return(Js.Object( Js.Item(EscapeTypeField, Js.Primitive(Break)), Js.Item(EscapeLabelField, node.Label != null ? Js.Primitive(node.Label) : Js.Null()), Js.Item(EscapeDepthField, node.Label != null ? Js.Primitive(transformer.GetLabelDepth(node.Label)) : Js.Primitive(0)) ).Compact())); }
private JsNode ImportAttributeValue(ResolveResult res) { var node = AstNodeConverter.Visit(res); if (node.NodeType == JsNodeType.InvocationExpression) { var exp = (JsInvocationExpression)node; var me = exp.Member as JsMemberExpression; if (me != null && me.Name == "Typeof") { node = Js.Function().AddStatements(Js.Return(exp)); } } return(node); }
public void SetResult(ExpressionSyntax result = null) { var setResult = Js.Reference(builder).Member("SetResult"); if (result != null) { var statement = setResult.Invoke((JsExpression)result.Accept(Transformer)).Express(); CurrentState.Add(statement); } else { CurrentState.Add(setResult.Invoke().Express()); } CurrentState.Add(Js.Return()); }
public void Process() { AfterFunction = BeforeFunction; SetParents(BeforeFunction.Block); foreach (var me in BeforeFunction.Block.Descendants <JsMemberExpression>().ToList()) { if (me.PreviousMember == null && me.NodeType == JsNodeType.MemberExpression) { me.PreviousMember = Js.This(); } } BeginNewStep(); ProcessStatement(BeforeFunction.Block); BeforeFunction.Block.Statements.Clear(); var func = new JsFunction { Block = new JsBlock { Statements = new List <JsStatement>() } }; var i = 0; func.Block.Statements.Add(Js.Var("result").Statement()); var stSwitch = Js.Switch(_state()); var lastStep = Js.Block().Add(_state().Assign(Js.Value(Steps.Count)).Statement()).Add(new JsBreakStatement()); Steps.Add(new YieldStep { Statements = { lastStep } }); foreach (var step in Steps) { stSwitch.Case(Js.Value(i), step.Statements); i++; } func.Block.Statements.Add(stSwitch); func.Block.Statements.Add(Js.Member("result").Assign(Js.Value(false)).Statement()); func.Block.Statements.Add(Js.Return(Js.Member("result"))); BeforeFunction.Block.Statements.Add(Js.Return(Js.New(Js.Member("CustomEnumerable"), func))); return; }
/// <summary> /// Wraps a setter invocation with a js function that returns the setter value back, if another assignment operation occurs /// var x = contact.Name = "Shooki"; /// var x = contact.setName("Shooki"); //error /// var x = (function(arg){contact.setName(arg);return arg;}).call(this, "Shooki"); /// </summary> /// <param name="res"></param> /// <param name="node2"></param> /// <returns></returns> internal JsNode WrapSetterToReturnValueIfNeeded(OperatorResolveResult res, JsNode node2) { var node3 = node2 as JsInvocationExpression; if (node3 == null) { return(node2); } if (RequiresWrapSetterToReturnValue(res)) { var lastArg = node3.Arguments.Last(); var prmName = "$p" + ParameterNameCounter++; node3.Arguments[node3.Arguments.Count - 1] = Js.Member(prmName); var func = Js.Function(prmName).Add(((JsExpression)node2).Statement()); func.Add(Js.Return(Js.Member(prmName))); node2 = WrapFunctionAndInvoke(res, func, lastArg); } return(node2); }
private JsStatement TransformBody(JsStatement body) { var block = body is JsBlockStatement ? (JsBlockStatement)body : Js.Block(body); if (!escapeStatements.Any()) { return(Js.Express(idioms.Wrap(block))); } else { if (!(block.Statements.Last() is JsReturnStatement)) { block.Return(Js.Object(Js.Item(EscapeTypeField, Js.Primitive(0))).Compact()); } var wrapped = idioms.Wrap(block); var outerBlock = new JsBlockStatement(); var loopResult = outerBlock.Local("$loopResult", wrapped); if (escapeStatements.Any(x => x.Type == Return)) { outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Return)), Js.Return(loopResult.GetReference().Member(EscapeValueField))); } if (escapeStatements.Any(x => x.Type == Continue)) { var escapes = escapeStatements.Where(x => x.Type == Continue).Distinct(); JsStatement ifTrue; if (!escapes.Any(x => x.Label != null)) { ifTrue = Js.Continue(); } else { ifTrue = Js.Switch( loopResult.GetReference().Member(EscapeLabelField), escapes .Where(x => x.Label == null) .Select(x => Js.Section(Js.Null()).Statement(Js.Continue())) .Concat(escapes .Where(x => x.Label != null && transformer.GetLabelDepth(x.Label) == loopDepth) .Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Continue(x.Label)))) .Concat(new[] { Js.Section(Js.DefaultLabel()).Statements(Js.Return(loopResult.GetReference())) }) .ToArray()); } outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Continue)), ifTrue); } if (escapeStatements.Any(x => x.Type == Break)) { var escapes = escapeStatements.Where(x => x.Type == Break).Distinct(); JsStatement ifTrue; if (!escapes.Any(x => x.Label != null)) { ifTrue = Js.Break(); } else { ifTrue = Js.Switch(loopResult.GetReference().Member(EscapeLabelField), escapes.Select(x => Js.Section(Js.Primitive(x.Label)).Statement(Js.Break(x.Label))).ToArray()); } outerBlock.If(loopResult.GetReference().Member(EscapeTypeField).EqualTo(Js.Primitive(Break)), ifTrue); } return(outerBlock); } }
public JsNode VisitInvocationResolveResultAsCtor(CSharpInvocationResolveResult res) { if (res.Type.Kind == TypeKind.Delegate) { return(Visit(res.Arguments.Single())); } var me = (IMethod)res.Member; var meAtt = Sk.GetJsMethodAttribute(me); var ce = me.GetDeclaringTypeDefinition(); var att = ce == null ? null : ce.GetJsTypeAttribute(); if (att != null && att.Mode == JsMode.Json && (meAtt == null || meAtt.Name == null)) { var jtfn = ce == null ? null : Sk.GetJsonTypeFieldName(ce); var node2 = VisitInvocationResolveResult(res); var json = Importer.InitializersToJson(res.InitializerStatements, res.Type); if (jtfn != null) { var x = json as JsJsonObjectExpression; if (x != null) { x.Add(jtfn, SkJs.EntityTypeRefToMember(res.Type)); } } return(json); } else { var invokeExp = (JsInvocationExpression)VisitInvocationResolveResult(res); var newExp = new JsNewObjectExpression { Invocation = invokeExp }; JsExpression finalExp; if (meAtt != null && meAtt.OmitNewOperator) { finalExp = invokeExp; } else { finalExp = newExp; } if (meAtt != null && meAtt.JsonInitializers) { var json = Importer.InitializersToJson(res.InitializerStatements, res.Type); invokeExp.Arguments.Add(json); } else if (res.InitializerStatements.IsNotNullOrEmpty()) { var func = Js.Function(); var inits2 = res.InitializerStatements.Select(t => Visit(t)).ToList(); //var init1 = res.InitializerStatements[0]; var target = AstNodeConverter.FindInitializedObjectResolveResult(res);// ((init1 as OperatorResolveResult).Operands[0] as MemberResolveResult).TargetResult as InitializedObjectResolveResult; var varName = Importer.Initializers[target]; func.Add(Js.Var(varName, finalExp).Statement()); foreach (var init in inits2) { var exp = ((JsExpression)init); func.Add(exp.Statement()); } func.Add(Js.Return(Js.Member(varName))); finalExp = Importer.WrapFunctionAndInvoke(res, func); } return(finalExp); } }
public JsNode VisitReturnStatement(ReturnStatement node) { return(Js.Return(VisitExpression(node.Expression))); }
protected JsBlock ExportMethodBody(IMethod me) { if (CompilerConfiguration.Current.EnableLogging) { Log.Debug("JsTypeImporter: Visit Method: " + me.ToString()); } var nativeCode = Sk.GetNativeCode(me); if (nativeCode != null) { var block = Js.Block().Add(Js.CodeStatement(nativeCode)); //TODO: double semicolon? return(block); } var def = me.GetDefinition(); if (def == null || def.IsNull) { if (me.IsAutomaticEventAccessor()) { if (me.IsEventAddAccessor()) { var node = GenerateAutomaticEventAccessor((IEvent)me.GetOwner(), false); return(node.Block); } else if (me.IsEventRemoveAccessor()) { var node = GenerateAutomaticEventAccessor((IEvent)me.GetOwner(), true); return(node.Block); } } else if (me.IsAutomaticPropertyAccessor()) { var bf = Js.Member(AutoPropertyPrefix + SkJs.GetEntityJsName(me.AccessorOwner)); if (!me.IsStatic) { bf.PreviousMember = Js.This(); } else if (!Sk.IsGlobalMethod(me)) { bf.PreviousMember = SkJs.EntityToMember(me.DeclaringTypeDefinition); } if (me.IsGetter()) { return(Js.Block().Add(Js.Return(bf))); } else { return(Js.Block().Add(bf.Assign(Js.Member("value")).Statement())); } } return(null); } var block2 = (JsBlock)AstNodeConverter.Visit(def); block2.ContainsYield = false; if (def.Descendants.OfType <YieldReturnStatement>().FirstOrDefault() != null) { block2.ContainsYield = true; if (!AstNodeConverter.SupportClrYield) { if (block2.Statements == null) { block2.Statements = new List <JsStatement>(); } //block2.Statements.Insert(0, Js.Var("$yield", Js.NewJsonArray()).Statement()); //block2.Statements.Add(AstNodeConverter.GenerateYieldReturnStatement(me)); } } return(block2); }
void TransformIntoBaseMethodCallIfNeeded(CSharpInvocationResolveResult res, JsInvocationExpression node2) { var target = res.TargetResult as ThisResolveResult; if (target != null && target.CausesNonVirtualInvocation) //base. { //var info = res.GetInfo(); //var node = info.Nodes.FirstOrDefault(); var ce = target.Type;// node.FindThisEntity(); if (ce != null && Sk.IsExtJsType(ce.GetDefinitionOrArrayType())) { node2.Member = Js.This().Member("callParent"); if (node2.Arguments.IsNotNullOrEmpty()) { node2.Arguments = new List <JsExpression> { Js.NewJsonArray(node2.Arguments.ToArray()) } } ; //var me2 = (node2.Member as JsMemberExpression); //me2.Name = "callParent"; return; } IMethod me2; var me = res.Member; if (me is IProperty) { me2 = ((IProperty)me).Getter; } else if (me is IMethod) { me2 = (IMethod)res.Member; } else { throw new Exception("Can't resolve method from member: " + res.Member); } var member = SkJs.EntityMethodToJsFunctionRef(me2); member = member.Member("call"); node2.Member = member; if (node2.Arguments == null) { node2.Arguments = new List <JsExpression>(); } node2.Arguments.Insert(0, Js.This()); } } void ProcessByRefs1() { ByRefs = new List <ByReferenceResolveResult>(); ByRefIndexes = new List <int>(); RefToRefs = new List <int>(); var c = 0; foreach (var bin in PrmBindings) { var binding = bin.Binding; var byRef = binding.CallResult as ByReferenceResolveResult; if (byRef == null) { c++; continue; } var x = byRef.ElementResult as LocalResolveResult; if (x != null && x.Variable != null && x.Variable.Type.Kind == TypeKind.ByReference) { if (binding.Parameter.IsRef || binding.Parameter.IsOut) { RefToRefs.Add(c); } c++; continue; } ByRefs.Add(byRef); ByRefIndexes.Add(c); c++; } } void ProcessByRefs2() { var c = 0; for (var i = 0; i < Node2.Arguments.Count; i++) { if (Node2.Arguments[i] is JsMemberExpression) { JsMemberExpression jsmex = Node2.Arguments[i] as JsMemberExpression; if (RefToRefs.Contains(i)) { Node2.Arguments[i] = jsmex.PreviousMember; //remove the .Value ref wrapper } else if (ByRefIndexes.Contains(i)) { Node2.Arguments[i] = Js.Member(RefIndexToName(c)); c++; } } else if (Node2.Arguments[i] is JsIndexerAccessExpression) { if (ByRefIndexes.Contains(i)) { Node2.Arguments[i] = Js.Member(RefIndexToName(c)); c++; } } } } void ProcessByRefs3() { if (ByRefs.IsNotNullOrEmpty()) { var func = Js.Function(); //It must assigned to a temporary variable, because typed arrays do not acceppt json. //调整原来使用临时对象.Value的赋值方式,修改为Object.defineProperty定义get|set方法的实现 //临时对象统一调用jsclr里的$Ref方法进行创建 for (var i = 0; i < ByRefs.Count; i++) { var byRef = ByRefs[i]; var expr = VisitExpression(byRef); if (expr is JsMemberExpression) { var memberExpr = expr as JsMemberExpression; if (memberExpr.PreviousMember != null) { var refFuncInvoke = new JsInvocationExpression { Member = new JsMemberExpression { Name = "$Ref" }, Arguments = new List <JsExpression> { memberExpr.PreviousMember, Js.String(memberExpr.Name) } }; func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement()); } else { //如果是局部变量的话使用旧实现方式 var refFuncInvoke = new JsInvocationExpression { Member = new JsMemberExpression { Name = "$Ref" }, Arguments = new List <JsExpression> { Js.Member("null"), memberExpr } }; func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement()); } } else if (expr is JsIndexerAccessExpression) { var indexerExpr = expr as JsIndexerAccessExpression; var indexArg = indexerExpr.Arguments[0]; var refFuncInvoke = new JsInvocationExpression { Member = new JsMemberExpression { Name = "$Ref" }, Arguments = new List <JsExpression> { indexerExpr.Member, indexArg } }; func.Add(Js.Var(RefIndexToName(i), refFuncInvoke).Statement()); } } func.Add(Js.Var("$res", Node2).Statement()); for (var i = 0; i < ByRefs.Count; i++) { var byRef = ByRefs[i]; var memberExpr = VisitExpression(byRef) as JsMemberExpression; if (memberExpr != null && memberExpr.PreviousMember == null) { func.Add(memberExpr.Assign(Js.Member(RefIndexToName(i)).Member("Value")).Statement()); } } func.Add(Js.Return(Js.Member("$res"))); Node2 = Importer.WrapFunctionAndInvoke(Res, func); } }
public override JsNode VisitAwaitExpression(AwaitExpressionSyntax node) { var operand = (JsExpression)node.Expression.Accept(this); /* * var expressionInfo = stateGenerator.Transformer.model.GetAwaitExpressionInfo(node); * if (expressionInfo.GetResultMethod == null) * { * var classText = node.FirstAncestorOrSelf<ClassDeclarationSyntax>().NormalizeWhitespace().ToString(); * var diagnostics = model.GetDiagnostics().Select(x => x.ToString()).ToArray(); * } * * var returnsVoid = expressionInfo.GetResultMethod.ReturnsVoid; */ var expressionInfo = stateGenerator.Transformer.model.GetTypeInfo(node).ConvertedType; var returnsVoid = expressionInfo.SpecialType == SpecialType.System_Void; var operandType = model.GetTypeInfo(node.Expression).ConvertedType; var awaiterMethodName = ((INamedTypeSymbol)operandType).GetMethodByName("GetAwaiter").GetMemberName(); // Store the awaiter in a field var awaiterIdentifier = stateGenerator.HoistVariable(new LiftedVariableKey("$awaiter")); var awaiter = awaiterIdentifier.GetReference(); stateGenerator.CurrentState.Add(awaiter.Assign(operand.Member(awaiterMethodName).Invoke()).Express()); var nextState = stateGenerator.InsertState(); JsExpression result = null; if (!returnsVoid) { // If the await returns a value, store it in a field var resultIdentifier = stateGenerator.HoistVariable(new LiftedVariableKey("$result")); result = resultIdentifier.GetReference(); // Make sure the field gets set from the awaiter at the beginning of the next state. nextState.Add(result.Assign(awaiter.Member("GetResult").Invoke()).Express()); } else { // We still need to call GetResult even if void in order to propagate exceptions nextState.Add(awaiter.Member("GetResult").Invoke().Express()); } // Set the state to the next state stateGenerator.CurrentState.Add(stateGenerator.ChangeState(nextState)); stateGenerator.CurrentState.Add(Js.If( awaiter.Member("get_IsCompleted").Invoke(), // If the awaiter is already completed, go to the next state stateGenerator.GotoTop(), // Otherwise await for completion Js.Block( // Start the async process Js.Reference(builder) .Member("TrueAwaitOnCompleted") .Invoke(awaiterIdentifier.GetReference(), Js.Reference(stateMachine)) .Express(), Js.Return() ) )); stateGenerator.CurrentState = nextState; return(result ?? Js.Null()); }
private JsBlockStatement CreateProperty(IPropertySymbol property) { var block = new JsBlockStatement(); var propertyName = property.GetMemberName(); var backingField = property.GetBackingFieldName(); var valueParameter = Js.Parameter("value"); block.Add(idioms.StoreInPrototype(backingField, Js.Null())); if (property.GetMethod != null) { block.Add(idioms.StoreInPrototype(property.GetMethod.GetMemberName(), Js.Function().Body(Js.Return(Js.This().Member(backingField))))); } if (property.SetMethod != null) { block.Add(idioms.StoreInPrototype(property.SetMethod.GetMemberName() + propertyName, Js.Function(valueParameter).Body( Js.Assign(Js.This().Member(backingField), valueParameter.GetReference())))); } return(block); }