public InlineArgumentsBlock(IEmitter emitter, ArgumentsInfo argsInfo, string inline) : base(emitter, argsInfo.Expression) { this.Emitter = emitter; this.ArgumentsInfo = argsInfo; this.InlineCode = inline; argsInfo.AddExtensionParam(); }
private bool CheckHasRefArgs(out string returnString, out string returnVarName) { returnString = returnVarName = null; InvocationExpression invocationExpression = this.InvocationExpression; Tuple<bool, bool, string> inlineInfo = this.Emitter.GetInlineCode(invocationExpression); var argsInfo = new ArgumentsInfo(this.Emitter, invocationExpression); var argsExpressions = argsInfo.ArgumentsExpressions; StringBuilder sb = new StringBuilder(); bool isFirst = true; foreach(var item in argsExpressions) { DirectionExpression itemExp = item as DirectionExpression; if(itemExp != null) { if(itemExp.FieldDirection == FieldDirection.Out || itemExp.FieldDirection == FieldDirection.Ref) { string name = itemExp.Expression.ToString(); string outName; if(this.Emitter.LocalsNamesMap.TryGetValue(name, out outName)) { name = outName; } if(isFirst) { isFirst = false; } else { sb.Append(", "); } sb.Append(name); } } } if(sb.Length > 0) { var resolveResult = (CSharpInvocationResolveResult)this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter); if(resolveResult.Member.ReturnType.Kind != TypeKind.Void) { if(invocationExpression.IsSingleExpression()) { sb.Insert(0, "_, "); } else { var iteratorVar = this.GetTempVarName(); var iteratorName = this.AddLocal(iteratorVar, AstType.Null); sb.Insert(0, iteratorName + ", "); returnVarName = iteratorName; } } sb.Append(" = "); returnString = sb.ToString(); return true; } return false; }
protected void VisitInvocationExpression() { InvocationExpression invocationExpression = this.InvocationExpression; int pos = this.Emitter.Output.Length; if (this.Emitter.IsForbiddenInvocation(invocationExpression)) { throw new EmitterException(invocationExpression, "This method cannot be invoked directly"); } var oldValue = this.Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling; if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling) { this.WriteAwaiters(invocationExpression); this.Emitter.ReplaceAwaiterByVar = true; this.Emitter.AsyncExpressionHandling = true; } Tuple<bool, bool, string> inlineInfo = this.Emitter.GetInlineCode(invocationExpression); var argsInfo = new ArgumentsInfo(this.Emitter, invocationExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; var argsCount = argsExpressions.Count(); if (inlineInfo != null) { bool isStaticMethod = inlineInfo.Item1; bool isInlineMethod = inlineInfo.Item2; string inlineScript = inlineInfo.Item3; if (isInlineMethod) { if (invocationExpression.Arguments.Count > 0) { var code = invocationExpression.Arguments.First(); var inlineExpression = code as PrimitiveExpression; if (inlineExpression == null) { throw new EmitterException(invocationExpression, "Only primitive expression can be inlined"); } string value = inlineExpression.Value.ToString().Trim(); if (value.Length > 0) { value = InlineArgumentsBlock.ReplaceInlineArgs(this, inlineExpression.Value.ToString(), invocationExpression.Arguments.Skip(1).ToArray()); this.Write(value); if (value[value.Length - 1] == ';') { this.Emitter.EnableSemicolon = false; this.WriteNewLine(); } } else { // Empty string, emit nothing. this.Emitter.EnableSemicolon = false; } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { MemberReferenceExpression targetMemberRef = invocationExpression.Target as MemberReferenceExpression; bool isBase = targetMemberRef != null && targetMemberRef.Target is BaseReferenceExpression; if (!String.IsNullOrEmpty(inlineScript) && (isBase || invocationExpression.Target is IdentifierExpression)) { argsInfo.ThisArgument = "this"; bool noThis = !inlineScript.Contains("{this}"); if (!isStaticMethod && noThis) { this.WriteThis(); this.WriteDot(); } new InlineArgumentsBlock(this.Emitter, argsInfo, inlineScript).Emit(); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } MemberReferenceExpression targetMember = invocationExpression.Target as MemberReferenceExpression; ResolveResult targetMemberResolveResult = null; if (targetMember != null) { targetMemberResolveResult = this.Emitter.Resolver.ResolveNode(targetMember.Target, this.Emitter); } if (targetMember != null) { var member = this.Emitter.Resolver.ResolveNode(targetMember.Target, this.Emitter); //var targetResolve = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter); var targetResolve = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter); if (targetResolve != null) { var csharpInvocation = targetResolve as CSharpInvocationResolveResult; InvocationResolveResult invocationResult; bool isExtensionMethodInvocation = false; if (csharpInvocation != null) { if (member != null && member.Type.Kind == TypeKind.Delegate && !csharpInvocation.IsExtensionMethodInvocation) { throw new EmitterException(invocationExpression, "Delegate's methods are not supported. Please use direct delegate invoke."); } if(csharpInvocation.TargetResult.IsCompileTimeConstant) { if(csharpInvocation.Member.Name == "ToString") { if(invocationExpression.IsSingleExpression()) { this.Write("--"); } if(csharpInvocation.TargetResult.Type.Kind == TypeKind.Enum) { MemberResolveResult reslut = (MemberResolveResult)csharpInvocation.TargetResult; this.Write("\"", reslut.Member.Name, "\""); } else { this.Write(csharpInvocation.TargetResult.ConstantValue); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { if(csharpInvocation.TargetResult.Type.Kind == TypeKind.Enum) { string attrName = Bridge.Translator.Translator.Bridge_ASSEMBLY + ".EnumExportAttribute"; var attr = csharpInvocation.Member.Attributes.FirstOrDefault(i => i.AttributeType.FullName == attrName); if(attr != null) { TransformCtx.ExportEnums.Add(csharpInvocation.TargetResult.Type); } } else if(csharpInvocation.TargetResult.Type.FullName == "System.Enum") { string attrName = Bridge.Translator.Translator.Bridge_ASSEMBLY + ".EnumExportAttribute"; var attr = csharpInvocation.Member.Attributes.FirstOrDefault(i => i.AttributeType.FullName == attrName); if(attr != null) { string typeName = attr.PositionalArguments[0].ConstantValue.ToString(); var typeArgument = argsInfo.TypeArguments.FirstOrDefault(i => i.Name == typeName); if(typeArgument != null) { if(typeArgument.IType != null) { TransformCtx.ExportEnums.Add(typeArgument.IType); } else { ResolveResult resolveResult = this.Emitter.Resolver.ResolveNode(typeArgument.AstType, this.Emitter); if(resolveResult != null) { TransformCtx.ExportEnums.Add(resolveResult.Type); } } } } } } if (csharpInvocation.IsExtensionMethodInvocation) { invocationResult = csharpInvocation; isExtensionMethodInvocation = true; var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && resolvedMethod.IsExtensionMethod) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (string.IsNullOrWhiteSpace(inline) && isNative) { invocationResult = null; } } } else { invocationResult = null; } if (this.IsEmptyPartialInvoking(csharpInvocation.Member as IMethod)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else { invocationResult = targetResolve as InvocationResolveResult; if (invocationResult != null && this.IsEmptyPartialInvoking(invocationResult.Member as IMethod)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } if (invocationResult == null) { invocationResult = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter) as InvocationResolveResult; } if (invocationResult != null) { var resolvedMethod = invocationResult.Member as IMethod; if (resolvedMethod != null && resolvedMethod.IsExtensionMethod) { string inline = this.Emitter.GetInline(resolvedMethod); bool isNative = this.IsNativeMethod(resolvedMethod); if (isExtensionMethodInvocation) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else if (!isNative) { var overloads = OverloadsCollection.Create(this.Emitter, resolvedMethod); string name = BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter) + "." + overloads.GetOverloadName(); var isIgnoreClass = resolvedMethod.DeclaringTypeDefinition != null && this.Emitter.Validator.IsIgnoreType(resolvedMethod.DeclaringTypeDefinition); this.Write(name); this.WriteOpenParentheses(); this.WriteThisExtension(invocationExpression.Target); if(invocationExpression.Arguments.Count > 0) { this.WriteComma(); } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression).Emit(); if(!isIgnoreClass && argsInfo.HasTypeArguments) { this.WriteComma(); new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } this.WriteCloseParentheses(); } if (!string.IsNullOrWhiteSpace(inline) || !isNative) { this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } else if (isNative) { if (!string.IsNullOrWhiteSpace(inline)) { this.Write(""); StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; new InlineArgumentsBlock(this.Emitter, argsInfo, inline).Emit(); } else { argsExpressions.First().AcceptVisitor(this.Emitter); this.WriteDot(); string name = this.Emitter.GetEntityName(resolvedMethod); this.Write(name); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions.Skip(1), paramsArg, invocationExpression).Emit(); this.WriteCloseParentheses(); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } } } } } var proto = false; if (targetMember != null && targetMember.Target is BaseReferenceExpression) { var rr = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter) as MemberResolveResult; if (rr != null) { proto = rr.IsVirtualCall; /*var method = rr.Member as IMethod; if (method != null && method.IsVirtual) { proto = true; } else { var prop = rr.Member as IProperty; if (prop != null && prop.IsVirtual) { proto = true; } }*/ } } if (proto) { var baseType = this.Emitter.GetBaseMethodOwnerTypeDefinition(targetMember.MemberName, targetMember.TypeArguments.Count); var method = invocationExpression.GetParent<MethodDeclaration>(); bool isIgnore = this.Emitter.Validator.IsIgnoreType(baseType); if (isIgnore) { //throw (System.Exception)this.Emitter.CreateException(targetMember.Target, "Cannot call base method, because parent class code is ignored"); } bool needComma = false; var resolveResult = this.Emitter.Resolver.ResolveNode(targetMember, this.Emitter); string name = null; if (this.Emitter.TypeInfo.GetBaseTypes(this.Emitter).Any()) { name = BridgeTypes.ToJsName(this.Emitter.TypeInfo.GetBaseClass(this.Emitter), this.Emitter); } else { name = BridgeTypes.ToJsName(baseType, this.Emitter); } string baseMethod; if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; baseMethod = OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(); } else if (resolveResult is MemberResolveResult) { MemberResolveResult memberResult = (MemberResolveResult)resolveResult; baseMethod = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); } else { baseMethod = targetMember.MemberName; baseMethod = this.Emitter.AssemblyInfo.PreserveMemberCase ? baseMethod : Object.Net.Utilities.StringUtils.ToLowerCamelCase(baseMethod); } this.Write(name, ".prototype.", baseMethod); if (!isIgnore && argsInfo.HasTypeArguments) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); this.WriteCloseParentheses(); } this.WriteDot(); this.Write("call"); this.WriteOpenParentheses(); this.WriteThis(); needComma = true; foreach (var arg in argsExpressions) { if (needComma) { this.WriteComma(); } needComma = true; arg.AcceptVisitor(this.Emitter); } this.WriteCloseParentheses(); } else { var dynamicResolveResult = this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter) as DynamicInvocationResolveResult; if (dynamicResolveResult != null) { var group = dynamicResolveResult.Target as MethodGroupResolveResult; if (group != null && group.Methods.Count() > 1) { throw new EmitterException(invocationExpression, "Cannot compile this dynamic invocation because there are two or more method overloads with the same parameter count. To work around this limitation, assign the dynamic value to a non-dynamic variable before use or call a method with different parameter count"); } } var targetResolveResult = this.Emitter.Resolver.ResolveNode(invocationExpression.Target, this.Emitter); var invocationResolveResult = targetResolveResult as MemberResolveResult; IMethod method = null; if (invocationResolveResult != null) { method = invocationResolveResult.Member as IMethod; } if (this.IsEmptyPartialInvoking(method)) { this.Emitter.SkipSemiColon = true; this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; return; } int count = this.Emitter.Writers.Count; invocationExpression.Target.AcceptVisitor(this.Emitter); if (this.Emitter.Writers.Count > count) { var tuple = this.Emitter.Writers.Pop(); if (method != null && method.IsExtensionMethod) { StringBuilder savedBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.WriteThisExtension(invocationExpression.Target); argsInfo.ThisArgument = this.Emitter.Output.ToString(); this.Emitter.Output = savedBuilder; } new InlineArgumentsBlock(this.Emitter, argsInfo, tuple.Item1).Emit(); var result = this.Emitter.Output.ToString(); this.Emitter.Output = tuple.Item2; this.Emitter.IsNewLine = tuple.Item3; this.Write(result); } else { var isIgnore = false; if (method != null && method.DeclaringTypeDefinition != null && this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { isIgnore = true; } this.WriteOpenParentheses(); if(method != null && !method.IsStatic && method.DeclaringType == TransformCtx.CurClass) { this.WriteThis(); if(argsExpressions.Length > 0) { this.WriteComma(); } } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg, invocationExpression).Emit(); if(!isIgnore && argsInfo.HasTypeArguments) { if(argsExpressions.Length > 0 || (!method.IsStatic && method.DeclaringType == TransformCtx.CurClass)) { this.WriteComma(); } new TypeExpressionListBlock(this.Emitter, argsInfo.TypeArguments).Emit(); } this.WriteCloseParentheses(); } } Helpers.CheckValueTypeClone(this.Emitter.Resolver.ResolveNode(invocationExpression, this.Emitter), invocationExpression, this, pos); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; }
protected virtual void EmitArrayAccess(IndexerExpression indexerExpression) { string targetVar = null; bool writeTargetVar = false; bool isStatement = false; string valueVar = null; var resolveResult = this.Emitter.Resolver.ResolveNode(indexerExpression, this.Emitter); if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = indexerExpression.Parent is UnaryOperatorExpression && indexerExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(resolveResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { var targetrr = this.Emitter.Resolver.ResolveNode(indexerExpression.Target, this.Emitter); var memberTargetrr = targetrr as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } if (this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } var oldIsAssignment = this.Emitter.IsAssignment; var oldUnary = this.Emitter.IsUnaryAccessor; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; indexerExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } this.WriteObjectColon(); var argsInfo = new ArgumentsInfo(this.Emitter, indexerExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(resolveResult.Type, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(resolveResult.Type); if (isStatement) { this.Write("set"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteComma(false); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenCloseParentheses(); } } else { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("set"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteComma(false); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.Write(valueVar); this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); var isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement; if (isPreOp) { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } if (targetVar != null) { this.RemoveTempVar(targetVar); } } else { this.Write("get"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); } } else { if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { var oldWriter = this.SaveWriter(); this.NewWriter(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); var paramsStr = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); if (targetVar != null) { this.PushWriter(string.Concat( "set(", targetVar, ".get(", paramsStr, "){0}, ", paramsStr, ")"), () => { this.RemoveTempVar(targetVar); }); } else { oldWriter = this.SaveWriter(); this.NewWriter(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; indexerExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; var trg = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); this.PushWriter(string.Concat( "set(", trg, ".get(", paramsStr, "){0}, ", paramsStr, ")")); } } else { this.Write("set"); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.PushWriter(", {0}", () => { this.WriteCloseParentheses(); }); } } }
protected void VisitIndexerExpression() { IndexerExpression indexerExpression = this.IndexerExpression; IAttribute inlineAttr = null; string inlineCode = null; var resolveResult = this.Emitter.Resolver.ResolveNode(indexerExpression, this.Emitter); var memberResolveResult = resolveResult as MemberResolveResult; var arrayAccess = resolveResult as ArrayAccessResolveResult; if (arrayAccess != null) { this.EmitArrayAccess(indexerExpression); return; } var isIgnore = true; var isAccessorsIndexer = false; var ignoreAccessor = false; IProperty member = null; var oldIsAssignment = this.Emitter.IsAssignment; var oldUnary = this.Emitter.IsUnaryAccessor; bool isName = false; if (memberResolveResult != null) { var resolvedMember = memberResolveResult.Member; isIgnore = this.Emitter.Validator.IsIgnoreType(resolvedMember.DeclaringTypeDefinition); isAccessorsIndexer = true; /*isAccessorsIndexer = resolvedMember.DeclaringTypeDefinition.DirectBaseTypes.Any( t => t.FullName == "Bridge.IAccessorsIndexer");*/ if (resolvedMember is IProperty) { member = (IProperty)resolvedMember; IMethod method = this.Emitter.IsAssignment ? member.Setter : member.Getter; inlineAttr = this.Emitter.GetAttribute(method.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute"); if (inlineAttr == null) { inlineAttr = Helpers.GetInheritedAttribute(method, Translator.Bridge_ASSEMBLY + ".NameAttribute"); isName = true; } ignoreAccessor = this.Emitter.Validator.IsIgnoreType(method); } } if (inlineAttr != null) { var inlineArg = inlineAttr.PositionalArguments[0]; if (inlineArg.ConstantValue != null) { inlineCode = inlineArg.ConstantValue.ToString(); if (inlineCode != null && isName) { inlineCode += "({0})"; } } } if (inlineCode != null && inlineCode.Contains("{this}")) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; indexerExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; inlineCode = inlineCode.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; this.PushWriter(inlineCode); new ExpressionListBlock(this.Emitter, indexerExpression.Arguments, null).Emit(); if (!this.Emitter.IsAssignment) { this.PopWriter(); } else { this.WriteComma(); } return; } if (inlineAttr != null || (isIgnore && !isAccessorsIndexer)) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; indexerExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } if (inlineAttr != null) { if (inlineCode != null) { this.WriteDot(); this.PushWriter(inlineCode); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; new ExpressionListBlock(this.Emitter, indexerExpression.Arguments, null).Emit(); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (!this.Emitter.IsAssignment) { this.PopWriter(); } else { this.WriteComma(); } } } else if (!(isIgnore || ignoreAccessor) || isAccessorsIndexer) { string targetVar = null; string valueVar = null; bool writeTargetVar = false; bool isStatement = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = indexerExpression.Parent is UnaryOperatorExpression && indexerExpression.Parent.Parent is ExpressionStatement; if (memberResolveResult != null && NullableType.IsNullable(memberResolveResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { var targetrr = this.Emitter.Resolver.ResolveNode(indexerExpression.Target, this.Emitter); var memberTargetrr = targetrr as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.Write(targetVar); this.Write(" = "); } } if (this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; indexerExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (targetVar != null) { if (this.Emitter.IsUnaryAccessor && !isStatement) { this.WriteComma(false); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.Write(targetVar); } else { this.WriteSemiColon(); this.WriteNewLine(); this.Write(targetVar); } } this.WriteObjectColon(); var argsInfo = new ArgumentsInfo(this.Emitter, indexerExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var paramsArg = argsInfo.ParamsExpression; var name = Helpers.GetPropertyRef(member, this.Emitter, this.Emitter.IsAssignment); if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { var oldWriter = this.SaveWriter(); this.NewWriter(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); var paramsStr = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); bool isDecimal = Helpers.IsDecimalType(member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(member, this.Emitter, true)); this.WriteOpenParentheses(); this.Write(paramsStr); this.WriteComma(false); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member, this.Emitter, false)); this.WriteOpenParentheses(); this.Write(paramsStr); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member, this.Emitter, false)); this.WriteOpenParentheses(); this.Write(paramsStr); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenCloseParentheses(); } } else { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member, this.Emitter, false)); this.WriteOpenParentheses(); this.Write(paramsStr); this.WriteCloseParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); } else { this.Write(Helpers.GetPropertyRef(member, this.Emitter, false)); this.WriteOpenParentheses(); this.Write(paramsStr); this.WriteCloseParentheses(); this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member, this.Emitter, true)); this.WriteOpenParentheses(); this.Write(paramsStr); this.WriteComma(false); if (isDecimal) { if (isNullable) { this.Write("Bridge.Nullable.lift1"); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript("inc"); } else { this.WriteScript("dec"); } this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); } else { this.Write(valueVar); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenCloseParentheses(); } } else { this.Write(valueVar); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("+"); } else { this.Write("-"); } this.Write("1"); } this.WriteCloseParentheses(); this.WriteComma(); bool isPreOp = this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement; if (isPreOp) { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member, this.Emitter, false)); this.WriteOpenParentheses(); this.Write(paramsStr); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } if (targetVar != null) { this.RemoveTempVar(targetVar); } } else { this.Write(name); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); } } else { if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { var oldWriter = this.SaveWriter(); this.NewWriter(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); var paramsStr = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); if (targetVar != null) { this.PushWriter(string.Concat( name, "(", paramsStr, ", ", targetVar, ".", Helpers.GetPropertyRef(member, this.Emitter, false), "(", paramsStr, "){0})")); this.RemoveTempVar(targetVar); } else { oldWriter = this.SaveWriter(); this.NewWriter(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; indexerExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; var trg = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); this.PushWriter(string.Concat( name, "(", paramsStr, ", ", trg, ".", Helpers.GetPropertyRef(member, this.Emitter, false), "(", paramsStr, "){0})")); } } else { this.Write(name); this.WriteOpenParentheses(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.PushWriter(", {0})"); } } } else { if (indexerExpression.Arguments.Count != 1) { throw new EmitterException(indexerExpression, "Only one index is supported"); } var index = indexerExpression.Arguments.First(); var primitive = index as PrimitiveExpression; if (primitive != null && primitive.Value != null && Regex.Match(primitive.Value.ToString(), "^[_$a-z][_$a-z0-9]*$", RegexOptions.IgnoreCase).Success) { this.WriteDot(); this.Write(primitive.Value); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; this.WriteOpenBracket(); index.AcceptVisitor(this.Emitter); this.WriteCloseBracket(); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } } }
protected void VisitObjectCreateExpression() { ObjectCreateExpression objectCreateExpression = this.ObjectCreateExpression; int pos = this.Emitter.Output.Length; var resolveResult = this.Emitter.Resolver.ResolveNode(objectCreateExpression.Type, this.Emitter) as TypeResolveResult; bool isTypeParam = resolveResult.Type.Kind == TypeKind.TypeParameter; var type = isTypeParam ? null : this.Emitter.GetTypeDefinition(objectCreateExpression.Type); if (type != null && type.BaseType != null && type.BaseType.FullName == "System.MulticastDelegate") { bool wrap = false; var parent = objectCreateExpression.Parent as InvocationExpression; if (parent != null && parent.Target == objectCreateExpression) { wrap = true; } if (wrap) { this.WriteOpenParentheses(); } objectCreateExpression.Arguments.First().AcceptVisitor(this.Emitter); if (wrap) { this.WriteCloseParentheses(); } return; } var argsInfo = new ArgumentsInfo(this.Emitter, objectCreateExpression); var argsExpressions = argsInfo.ArgumentsExpressions; var argsNames = argsInfo.ArgumentsNames; var paramsArg = argsInfo.ParamsExpression; var argsCount = argsExpressions.Count(); var invocationResolveResult = this.Emitter.Resolver.ResolveNode(objectCreateExpression, this.Emitter) as InvocationResolveResult; string inlineCode = null; if (invocationResolveResult != null) { inlineCode = this.Emitter.GetInline(invocationResolveResult.Member); } var customCtor = isTypeParam ? "" : (this.Emitter.Validator.GetCustomConstructor(type) ?? ""); var hasInitializer = !objectCreateExpression.Initializer.IsNull && objectCreateExpression.Initializer.Elements.Count > 0; bool isCollectionInitializer = false; AstNodeCollection<Expression> elements = null; if (hasInitializer) { elements = objectCreateExpression.Initializer.Elements; isCollectionInitializer = elements.Count > 0 && elements.First() is ArrayInitializerExpression; } if (inlineCode == null && Regex.Match(customCtor, @"\s*\{\s*\}\s*").Success) { this.WriteOpenBrace(); this.WriteSpace(); if (hasInitializer) { this.WriteObjectInitializer(objectCreateExpression.Initializer.Elements, this.Emitter.AssemblyInfo.PreserveMemberCase, type, invocationResolveResult); this.WriteSpace(); } else if (this.Emitter.Validator.IsObjectLiteral(type)) { this.WriteObjectInitializer(null, this.Emitter.AssemblyInfo.PreserveMemberCase, type, invocationResolveResult); this.WriteSpace(); } this.WriteCloseBrace(); } else { if (hasInitializer) { this.Write(Bridge.Translator.Emitter.ROOT); this.WriteDot(); this.Write(Bridge.Translator.Emitter.MERGE_OBJECT); this.WriteOpenParentheses(); } if (inlineCode != null) { new InlineArgumentsBlock(this.Emitter, argsInfo, inlineCode).Emit(); } else { if (String.IsNullOrEmpty(customCtor)) { objectCreateExpression.Type.AcceptVisitor(this.Emitter); this.WriteOpenParentheses(); } else { this.Write(customCtor); } if (!isTypeParam && !this.Emitter.Validator.IsIgnoreType(type) && type.Methods.Count(m => m.IsConstructor && !m.IsStatic) > (type.IsValueType ? 0 : 1)) { string name = OverloadsCollection.Create(this.Emitter, ((InvocationResolveResult)this.Emitter.Resolver.ResolveNode(objectCreateExpression, this.Emitter)).Member).GetOverloadName(); int index = ConstructorBlock.GetCtorIndex(name); this.Write(index); this.WriteComma(); } if(invocationResolveResult != null) { string index = Bridge.Translator.Lua.Emitter.GetConstructorIndex(invocationResolveResult.Member); if(index != null) { this.Write(index); this.WriteSpace(); this.WriteComma(); } } new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseParentheses(); } if (hasInitializer) { this.WriteComma(); this.WriteFunction(); this.WriteOpenParentheses(); this.Write("t"); this.WriteCloseParentheses(); this.BeginFunctionBlock(); bool needComma = false; /* if (isCollectionInitializer) { this.Write("{"); this.WriteNewLine(); } else { this.BeginBlock(); }*/ foreach (Expression item in elements) { if (needComma) { this.WriteSemiColon(true); } needComma = true; if (item is NamedExpression) { var namedExpression = (NamedExpression)item; new NameBlock(this.Emitter, namedExpression.Name, namedExpression, namedExpression.Expression).Emit(); } else if (item is NamedArgumentExpression) { var namedArgumentExpression = (NamedArgumentExpression)item; new NameBlock(this.Emitter, namedArgumentExpression.Name, namedArgumentExpression, namedArgumentExpression.Expression).Emit(); } else if (item is ArrayInitializerExpression) { var arrayInitializer = (ArrayInitializerExpression)item; this.Write("t:add"); this.WriteOpenParentheses(); foreach(var el in arrayInitializer.Elements) { this.EnsureComma(false); el.AcceptVisitor(this.Emitter); this.Emitter.Comma = true; } this.WriteCloseParentheses(); this.Emitter.Comma = false; } else if (item is IdentifierExpression) { var identifierExpression = (IdentifierExpression)item; new IdentifierBlock(this.Emitter, identifierExpression).Emit(); } } this.WriteNewLine(); this.EndFunctionBlock(); this.WriteCloseParentheses(); } } //Helpers.CheckValueTypeClone(invocationResolveResult, this.ObjectCreateExpression, this, pos); }
protected virtual void EmitInlineExpressionList(ArgumentsInfo argsInfo, string inline) { IEnumerable<NamedParamExpression> expressions = argsInfo.NamedExpressions; IEnumerable<TypeParamExpression> typeParams = argsInfo.TypeArguments; this.Write(""); inline = _formatArg.Replace(inline, delegate(Match m) { int count = this.Emitter.Writers.Count; string key = m.Groups[2].Value; bool isRaw = m.Groups[1].Success && m.Groups[1].Value == "*"; bool ignoreArray = isRaw || argsInfo.ParamsExpression == null; string modifier = m.Groups[1].Success ? m.Groups[4].Value : null; string paramsName = null; if (argsInfo.ResolveResult != null) { var paramsParam = argsInfo.ResolveResult.Member.Parameters.FirstOrDefault(p => p.IsParams); if (paramsParam != null) { paramsName = paramsParam.Name; } } if (modifier == "array") { ignoreArray = false; } StringBuilder oldSb = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (key == "this" || key == argsInfo.ThisName || (key == "0" && argsInfo.IsExtensionMethod)) { string thisValue = argsInfo.GetThisValue(); if (thisValue != null) { this.Write(thisValue); } } else if(key == "class") { var resolverResult = (MemberResolveResult)this.Emitter.Resolver.ResolveNode(argsInfo.Expression, this.Emitter); string typeName = BridgeTypes.ToJsName(resolverResult.TargetResult.Type, this.Emitter); this.Write(typeName); } else { IList<Expression> exprs = this.GetExpressionsByKey(expressions, key); if (exprs.Count > 0) { if (exprs.Count > 1 || paramsName == key) { if (exprs.Count == 1 && exprs[0] != null && exprs[0].Parent != null) { var exprrr = this.Emitter.Resolver.ResolveNode(exprs[0], this.Emitter); if (exprrr.Type.Kind == TypeKind.Array) { ignoreArray = true; } } if (!ignoreArray) { this.Write("["); } if (exprs.Count == 1 && exprs[0] == null) { this.Write("null"); } else { new ExpressionListBlock(this.Emitter, exprs, null).Emit(); } if (!ignoreArray) { this.Write("]"); } } else { string s; if (exprs[0] != null) { var writer = this.SaveWriter(); this.NewWriter(); exprs[0].AcceptVisitor(this.Emitter); s = this.Emitter.Output.ToString(); this.RestoreWriter(writer); if (modifier == "raw") { s = s.Trim('"'); } } else { s = "null"; } this.Write(this.WriteIndentToString(s)); } } else if (typeParams != null) { var type = this.GetAstTypeByKey(typeParams, key); if (type != null) { type.AcceptVisitor(this.Emitter); } else { var iType = this.GetITypeByKey(typeParams, key); if (iType != null) { new CastBlock(this.Emitter, iType).Emit(); } } } } if (this.Emitter.Writers.Count != count) { this.PopWriter(); } string replacement = this.Emitter.Output.ToString(); this.Emitter.Output = oldSb; return replacement; }); this.Write(inline); }