private void HandleType(ResolveResult resolveOperator, string variable, string op_name, KnownTypeCode typeCode) { if (this.AssignmentExpression.Operator == AssignmentOperatorType.Assign) { if (variable != null) { this.Write(variable); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Right }, null, null, 0).Emit(); } return; } var orr = resolveOperator as OperatorResolveResult; var method = orr != null ? orr.UserDefinedOperatorMethod : null; var assigmentType = Helpers.TypeOfAssignment(this.AssignmentExpression.Operator); if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(assigmentType); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = this.Emitter.GetInline(method); if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.AssignmentExpression, orr, method), inline).Emit(); } else if (!this.Emitter.Validator.IsExternalType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); this.Write(", " + variable); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.WriteCloseParentheses(); } } else { if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); string action = JS.Funcs.Math.LIFT2; this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); if (variable != null) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left }, null, null, 0).Emit(); } else { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null, null, 0).Emit(); } this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } else { this.AssignmentExpression.Left.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.AssignmentExpression.Right.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, op_name); this.WriteCloseParentheses(); } } }
public static void CheckInteger(ConversionBlock block, Expression expression, IType type) { NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type, false, true, NullableType.IsNullable(type)); }
protected virtual bool WriteObject(string objectName, List <TypeConfigItem> members, string format, string interfaceFormat) { bool hasProperties = this.HasProperties(objectName, members); if (hasProperties && objectName != null) { this.EnsureComma(); this.Write(objectName); this.WriteColon(); this.BeginBlock(); } bool isProperty = JS.Fields.PROPERTIES == objectName; foreach (var member in members) { object constValue = null; bool isPrimitive = false; var primitiveExpr = member.Initializer as PrimitiveExpression; bool write = false; bool writeScript = false; if (primitiveExpr != null) { isPrimitive = true; constValue = primitiveExpr.Value; //writeScript = true; } if (constValue is RawValue) { constValue = constValue.ToString(); write = true; writeScript = false; } var isNull = member.Initializer.IsNull || member.Initializer is NullReferenceExpression; if (!isNull && !isPrimitive) { var constrr = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter); if (constrr != null && constrr.IsCompileTimeConstant) { isPrimitive = true; constValue = constrr.ConstantValue; writeScript = true; } } var isNullable = false; if (isPrimitive && constValue is AstType) { var itype = this.Emitter.Resolver.ResolveNode((AstType)constValue, this.Emitter); if (NullableType.IsNullable(itype.Type)) { isNullable = true; } } if (!isNull && (!isPrimitive || (constValue is AstType))) { string value = null; bool needContinue = false; string defValue = ""; if (!isPrimitive) { var oldWriter = this.SaveWriter(); this.NewWriter(); member.Initializer.AcceptVisitor(this.Emitter); value = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); ResolveResult rr = null; AstType astType = null; if (member.VarInitializer != null) { rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter); } else { astType = member.Entity.ReturnType; rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter); } constValue = Inspector.GetDefaultFieldValue(rr.Type, astType); isNullable = NullableType.IsNullable(rr.Type); needContinue = constValue is IType; writeScript = true; if (needContinue && !(member.Initializer is ObjectCreateExpression)) { defValue = " || " + Inspector.GetStructDefaultValue((IType)constValue, this.Emitter); } } else { value = isNullable ? "null" : Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter); constValue = value; write = true; needContinue = !isProperty && !isNullable; } var name = member.GetName(this.Emitter); if (isProperty && isPrimitive) { constValue = "null"; this.Injectors.Add(string.Format(name.StartsWith("\"") ? "this[{0}] = {1};" : "this.{0} = {1};", name, value)); } else { this.Injectors.Add(string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value + defValue)); } if (needContinue) { continue; } } this.EnsureComma(); XmlToJsDoc.EmitComment(this, member.Entity); this.Write(member.GetName(this.Emitter, true)); this.WriteColon(); if (constValue is AstType) { if (isNullable) { this.Write("null"); } else { this.Write(Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter)); } } else if (constValue is IType) { if (isNullable) { this.Write("null"); } else { this.Write(Inspector.GetStructDefaultValue((IType)constValue, this.Emitter)); } } else if (write) { this.Write(constValue); } else if (writeScript) { this.WriteScript(constValue); } else { member.Initializer.AcceptVisitor(this.Emitter); } this.Emitter.Comma = true; } if (hasProperties && objectName != null) { this.WriteNewLine(); this.EndBlock(); } return(hasProperties); }
/// <summary> /// Determines whether a variable should be inlined in non-aggressive mode, even though it is not a generated variable. /// </summary> /// <param name="next">The next top-level expression</param> /// <param name="loadInst">The load within 'next'</param> /// <param name="inlinedExpression">The expression being inlined</param> static bool NonAggressiveInlineInto(ILInstruction next, ILInstruction loadInst, ILInstruction inlinedExpression, ILVariable v) { Debug.Assert(loadInst.IsDescendantOf(next)); // decide based on the source expression being inlined switch (inlinedExpression.OpCode) { case OpCode.DefaultValue: case OpCode.StObj: case OpCode.CompoundAssignmentInstruction: case OpCode.Await: return(true); case OpCode.LdLoc: if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) { // Roslyn likes to put the result of fetching a state machine field into a temporary variable, // so inline more aggressively in such cases. return(true); } break; } var parent = loadInst.Parent; if (parent is ILiftableInstruction liftable && liftable.IsLifted) { return(true); // inline into lifted operators } if (parent is NullCoalescingInstruction && NullableType.IsNullable(v.Type)) { return(true); // inline nullables into ?? operator } // decide based on the target into which we are inlining switch (next.OpCode) { case OpCode.Leave: return(parent == next); case OpCode.IfInstruction: while (parent.MatchLogicNot(out _)) { parent = parent.Parent; } return(parent == next); case OpCode.BlockContainer: if (((BlockContainer)next).EntryPoint.Instructions[0] is SwitchInstruction switchInst) { next = switchInst; goto case OpCode.SwitchInstruction; } else { return(false); } case OpCode.SwitchInstruction: return(parent == next || (parent.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub) && parent.Parent == next)); default: return(false); } }
private static void NarrowingNumericOrEnumerationConversion(ConversionBlock block, Expression expression, IType targetType, bool fromFloatingPoint, bool isChecked, bool isNullable, bool isExplicit = true) { if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)) { return; } if (isChecked) { block.Write(JS.Types.BRIDGE_INT + ".check("); if (fromFloatingPoint) { block.Write(JS.Types.BRIDGE_INT + ".trunc"); block.WriteOpenParentheses(); } //expression.AcceptVisitor(block.Emitter); if (fromFloatingPoint) { block.AfterOutput += ")"; } block.AfterOutput += ", "; block.AfterOutput += BridgeTypes.ToJsName(targetType, block.Emitter); block.AfterOutput += ")"; } else { if (isNullable || fromFloatingPoint) { targetType = NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType; string action = null; if (targetType.IsKnownType(KnownTypeCode.Char)) { action = "clipu16"; } else if (targetType.IsKnownType(KnownTypeCode.SByte)) { action = "clip8"; } else if (targetType.IsKnownType(KnownTypeCode.Byte)) { action = "clipu8"; } else if (targetType.IsKnownType(KnownTypeCode.Int16)) { action = "clip16"; } else if (targetType.IsKnownType(KnownTypeCode.UInt16)) { action = "clipu16"; } else if (targetType.IsKnownType(KnownTypeCode.Int32)) { action = "clip32"; } else if (targetType.IsKnownType(KnownTypeCode.UInt32)) { action = "clipu32"; } else if (targetType.IsKnownType(KnownTypeCode.Int64)) { action = "clip64"; } else if (targetType.IsKnownType(KnownTypeCode.UInt64)) { action = "clipu64"; } else { throw new ArgumentException("Can not narrow to " + targetType, "targetType"); } block.Write(JS.Types.BRIDGE_INT + "."); block.Write(action); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } else { var skipOuterWrap = (expression.Parent is VariableInitializer) || (expression.Parent is AssignmentExpression) || targetType.IsKnownType(KnownTypeCode.Int64) || targetType.IsKnownType(KnownTypeCode.UInt64) || targetType.IsKnownType(KnownTypeCode.Int16) || targetType.IsKnownType(KnownTypeCode.SByte); bool skipInnerWrap = false; var rr = block.Emitter.Resolver.ResolveNode(expression is CastExpression ? ((CastExpression)expression).Expression : expression, block.Emitter); var memberTargetrr = rr as MemberResolveResult; bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (rr is ThisResolveResult || rr is LocalResolveResult || rr is ConstantResolveResult || isField) { skipInnerWrap = true; } if (!skipOuterWrap) { block.WriteOpenParentheses(); } if (targetType.IsKnownType(KnownTypeCode.Char)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535"; } else if (targetType.IsKnownType(KnownTypeCode.SByte)) { block.Write(JS.Types.BRIDGE_INT + ".sxb("); if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 255)"; } else if (targetType.IsKnownType(KnownTypeCode.Byte)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 255"; } else if (targetType.IsKnownType(KnownTypeCode.Int16)) { block.Write(JS.Types.BRIDGE_INT + ".sxs("); if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535)"; } else if (targetType.IsKnownType(KnownTypeCode.UInt16)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " & 65535"; } else if (targetType.IsKnownType(KnownTypeCode.Int32)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " | 0"; } else if (targetType.IsKnownType(KnownTypeCode.UInt32)) { if (!skipInnerWrap) { block.WriteOpenParentheses(); block.AfterOutput += ")"; } block.AfterOutput += " >>> 0"; } else if (targetType.IsKnownType(KnownTypeCode.Int64)) { block.Write(JS.Types.BRIDGE_INT + ".clip64("); block.AfterOutput += ")"; } else if (targetType.IsKnownType(KnownTypeCode.UInt64)) { block.Write(JS.Types.BRIDGE_INT + ".clipu64("); block.AfterOutput += ")"; } else { throw new ArgumentException("Can not narrow to " + targetType, "targetType"); } if (!skipOuterWrap) { block.AfterOutput += ")"; } } } }
protected virtual void EmitCastExpression(Expression expression, AstType type, string method) { var itype = this.Emitter.BridgeTypes.ToType(type); bool isCastAttr; string castCode = this.GetCastCode(expression, type, out isCastAttr); var enumType = itype; if (NullableType.IsNullable(enumType)) { enumType = NullableType.GetUnderlyingType(enumType); } var castToEnum = enumType.Kind == TypeKind.Enum; if (castToEnum) { itype = enumType.GetDefinition().EnumUnderlyingType; var enumMode = this.Emitter.Validator.EnumEmitMode(enumType); if (enumMode >= 3 && enumMode < 7) { itype = this.Emitter.Resolver.Compilation.FindType(KnownTypeCode.String); } } if (expression is NullReferenceExpression || (method != CS.Ops.IS && Helpers.IsIgnoreCast(type, this.Emitter))) { if (expression is ParenthesizedExpression) { expression = ((ParenthesizedExpression)expression).Expression; } expression.AcceptVisitor(this.Emitter); return; } var expressionrr = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); var typerr = this.Emitter.Resolver.ResolveNode(type, this.Emitter); if (expressionrr.Type.Kind == TypeKind.Enum) { var enumMode = this.Emitter.Validator.EnumEmitMode(expressionrr.Type); if (enumMode >= 3 && enumMode < 7 && Helpers.IsIntegerType(itype, this.Emitter.Resolver)) { throw new EmitterException(this.CastExpression, "Enum underlying type is string and cannot be casted to number"); } } if (method == CS.Ops.CAST && expressionrr.Type.Kind != TypeKind.Enum) { var cast_rr = this.Emitter.Resolver.ResolveNode(this.CastExpression, this.Emitter); if (cast_rr is ConstantResolveResult) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)cast_rr).ConstantValue; this.WriteCastValue(value, expectedType); return; } else { var conv_rr = cast_rr as ConversionResolveResult; if (conv_rr != null && conv_rr.Input is ConstantResolveResult && !conv_rr.Conversion.IsUserDefined) { var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(this.CastExpression); var value = ((ConstantResolveResult)conv_rr.Input).ConstantValue; this.WriteCastValue(value, expectedType); return; } } } if (method == CS.Ops.IS && castToEnum) { this.Write(JS.Types.Bridge.IS); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); this.Write(", "); this.Write(BridgeTypes.ToJsName(itype, this.Emitter)); this.Write(")"); return; } if (expressionrr.Type.Equals(itype)) { if (method == CS.Ops.IS) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); } expression.AcceptVisitor(this.Emitter); if (method == CS.Ops.IS) { this.Write(")"); } return; } bool isResultNullable = NullableType.IsNullable(typerr.Type); if (castCode != null) { this.EmitInlineCast(expressionrr, expression, type, castCode, isCastAttr, method); return; } bool isCast = method == CS.Ops.CAST; if (isCast) { if (ConversionBlock.IsUserDefinedConversion(this, this.CastExpression.Expression) || ConversionBlock.IsUserDefinedConversion(this, this.CastExpression)) { expression.AcceptVisitor(this.Emitter); return; } } var conversion = this.Emitter.Resolver.Resolver.GetConversion(expression); if (conversion.IsNumericConversion || conversion.IsEnumerationConversion || (isCast && conversion.IsIdentityConversion)) { expression.AcceptVisitor(this.Emitter); return; } var simpleType = type as SimpleType; bool hasValue = false; if (simpleType != null && simpleType.Identifier == "dynamic") { if (method == CS.Ops.CAST || method == CS.Ops.AS) { expression.AcceptVisitor(this.Emitter); return; } else if (method == CS.Ops.IS) { hasValue = true; method = "hasValue"; } } bool unbox = !(itype.IsReferenceType.HasValue ? itype.IsReferenceType.Value : true) && !NullableType.IsNullable(itype) && isCast && conversion.IsUnboxingConversion; if (unbox) { this.Write("System.Nullable.getValue("); } this.Write(JS.NS.BRIDGE); this.WriteDot(); this.Write(method); this.WriteOpenParentheses(); expression.AcceptVisitor(this.Emitter); if (!hasValue) { this.WriteComma(); this.EmitCastType(itype); } if (isResultNullable && method != CS.Ops.IS) { this.WriteComma(); this.WriteScript(true); } this.WriteCloseParentheses(); if (unbox) { this.Write(")"); } }
protected virtual bool WriteObject(string objectName, List <TypeConfigItem> members, Func <TypeConfigItem, string, string> format, FieldTypeEnum type) { bool hasProperties = this.HasProperties(members); if (hasProperties && objectName != null) { this.EnsureComma(); this.Write(objectName); this.WriteEqualsSign(); this.BeginBlock(); } foreach (var member in members) { object constValue = null; bool isPrimitive = false; var primitiveExpr = member.Initializer as PrimitiveExpression; if (primitiveExpr != null) { isPrimitive = true; constValue = primitiveExpr.Value; } var isNull = member.Initializer.IsNull || member.Initializer is NullReferenceExpression; if (!isNull && !isPrimitive) { var resolveResult = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter); if (resolveResult != null && resolveResult.IsCompileTimeConstant) { isPrimitive = true; constValue = resolveResult.ConstantValue; } } var isNullable = false; if (isPrimitive && constValue is AstType) { var itype = this.Emitter.Resolver.ResolveNode((AstType)constValue, this.Emitter); if (NullableType.IsNullable(itype.Type)) { isNullable = true; } } if (type == FieldTypeEnum.Property || type == FieldTypeEnum.Event) { this.PushWriter("{0}"); member.Initializer.AcceptVisitor(this.Emitter); string value = this.PopWriter(true); this.Injectors.Add(format(member, value)); continue; } if (!isNull && (!isPrimitive || (constValue is AstType))) { string value = null; if (!isPrimitive) { this.PushWriter("{0}"); member.Initializer.AcceptVisitor(this.Emitter); value = this.PopWriter(true); //var oldWriter = this.SaveWriter(); //this.NewWriter(); //member.Initializer.AcceptVisitor(this.Emitter); //value = this.Emitter.Output.ToString(); //this.RestoreWriter(oldWriter); } else { if (isNullable) { value = LuaHelper.Nil; } else { AstType astType = (AstType)constValue; var rr = Emitter.Resolver.ResolveNode(astType, Emitter); var def = Inspector.GetDefaultFieldValue(rr.Type); if (def == rr.Type) { value = Inspector.GetStructDefaultValue(rr.Type, this.Emitter); } else { value = def.ToString(); } } } this.Injectors.Add(format(member, value)); continue; } PushWriter("{0}"); if (constValue is AstType) { if (isNullable) { this.Write(LuaHelper.Nil); } else { AstType astType = (AstType)constValue; var rr = Emitter.Resolver.ResolveNode(astType, Emitter); var def = Inspector.GetDefaultFieldValue(rr.Type); if (def == rr.Type) { this.Write(Inspector.GetStructDefaultValue(rr.Type, this.Emitter)); } else { this.WriteScript(def); } } } else { member.Initializer.AcceptVisitor(this.Emitter); } string fieldValue = PopWriter(true); if (fieldValue != LuaHelper.Nil) { this.EnsureComma(); XmlToJsDoc.EmitComment(this, member.Entity); this.Write(member.GetName(this.Emitter)); this.WriteEqualsSign(); this.Write(fieldValue); this.Emitter.Comma = true; } } if (hasProperties && objectName != null) { this.WriteNewLine(); this.EndBlock(); } return(hasProperties); }
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.WriteDot(); 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(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); 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(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); 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(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); 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(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); this.WriteCloseParentheses(); this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("set"); this.WriteOpenParentheses(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); 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(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { indexerExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write("get"); this.WriteOpenParentheses(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); 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(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); 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(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); 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([", paramsStr, "],", targetVar, ".get([", 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( "set([", paramsStr, "],", trg, ".get([", paramsStr, "]){0})")); } } else { this.Write("set"); this.WriteOpenParentheses(); this.WriteOpenBracket(); new ExpressionListBlock(this.Emitter, argsExpressions, paramsArg).Emit(); this.WriteCloseBracket(); this.PushWriter(", {0})"); } } }
public static bool CheckConversion(ConversionBlock block, Expression expression) { Conversion conversion = null; try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); var invocationExpression = expression.Parent as InvocationExpression; if (invocationExpression != null && invocationExpression.Arguments.Any(a => a == expression)) { var index = invocationExpression.Arguments.ToList().IndexOf(expression); var methodResolveResult = block.Emitter.Resolver.ResolveNode(invocationExpression, block.Emitter) as MemberResolveResult; var m = methodResolveResult.Member as IMethod; var arg = m.Parameters[index < m.Parameters.Count ? index : (m.Parameters.Count - 1)]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var namedArgExpression = expression.Parent as NamedArgumentExpression; if (namedArgExpression != null) { var namedArgResolveResult = block.Emitter.Resolver.ResolveNode(namedArgExpression, block.Emitter) as NamedArgumentResolveResult; if (Helpers.IsDecimalType(namedArgResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedArgResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var namedExpression = expression.Parent as NamedExpression; if (namedExpression != null) { var namedResolveResult = block.Emitter.Resolver.ResolveNode(namedExpression, block.Emitter); if (Helpers.IsDecimalType(namedResolveResult.Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(namedResolveResult.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var binaryOpExpr = expression.Parent as BinaryOperatorExpression; if (binaryOpExpr != null) { var idx = binaryOpExpr.Left == expression ? 0 : 1; var binaryOpRr = block.Emitter.Resolver.ResolveNode(binaryOpExpr, block.Emitter) as OperatorResolveResult; if (Helpers.IsDecimalType(binaryOpRr.Operands[idx].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(binaryOpRr.Operands[idx].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var assignmentExpr = expression.Parent as AssignmentExpression; if (assignmentExpr != null) { var assigmentRr = block.Emitter.Resolver.ResolveNode(assignmentExpr, block.Emitter) as OperatorResolveResult; if (Helpers.IsDecimalType(assigmentRr.Operands[1].Type, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(assigmentRr.Operands[1].Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } var arrayInit = expression.Parent as ArrayInitializerExpression; if (arrayInit != null) { while (arrayInit.Parent is ArrayInitializerExpression) { arrayInit = (ArrayInitializerExpression)arrayInit.Parent; } IType elementType = null; var arrayCreate = arrayInit.Parent as ArrayCreateExpression; if (arrayCreate != null) { var rrArrayType = block.Emitter.Resolver.ResolveNode(arrayCreate, block.Emitter); if (rrArrayType.Type is TypeWithElementType) { elementType = ((TypeWithElementType)rrArrayType.Type).ElementType; } else { elementType = rrArrayType.Type; } } else { var rrElemenet = block.Emitter.Resolver.ResolveNode(arrayInit.Parent, block.Emitter); var pt = rrElemenet.Type as ParameterizedType; if (pt != null) { elementType = pt.TypeArguments.Count > 0 ? pt.TypeArguments.First() : null; } else { var arrayType = rrElemenet.Type as TypeWithElementType; if (arrayType != null) { elementType = arrayType.ElementType; } else { elementType = rrElemenet.Type; } } } if (elementType != null && Helpers.IsDecimalType(elementType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(elementType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver)) { var castExpr = expression.Parent as CastExpression; ResolveResult castTypeRr = null; if (castExpr != null) { castTypeRr = block.Emitter.Resolver.ResolveNode(castExpr.Type, block.Emitter); } if (castTypeRr == null || !Helpers.IsDecimalType(castTypeRr.Type, block.Emitter.Resolver)) { if (expression.IsNull) { return(false); } block.Write("Bridge.Decimal"); if (NullableType.IsNullable(expectedType) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); return(true); } } if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver)) { return(false); } if (conversion == null) { return(false); } if (conversion.IsIdentityConversion) { return(false); } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return(false); } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock); if (isLifted) { block.Write("Bridge.Nullable.lift("); } if (conversion.IsUserDefined) { var method = conversion.Method; string inline = block.Emitter.GetInline(method); if (conversion.IsExplicit && !string.IsNullOrWhiteSpace(inline)) { // Still returns true if Nullable.lift( was written. return(isLifted); } if (!string.IsNullOrWhiteSpace(inline)) { if (expression is InvocationExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is ObjectCreateExpression) { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, (InvocationExpression)expression), inline).Emit(); } else if (expression is UnaryOperatorExpression) { var unaryExpression = (UnaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(unaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, unaryExpression, orr, method), inline).Emit(); } else if (expression is BinaryOperatorExpression) { var binaryExpression = (BinaryOperatorExpression)expression; var resolveOperator = block.Emitter.Resolver.ResolveNode(binaryExpression, block.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, binaryExpression, orr, method), inline).Emit(); } else { new InlineArgumentsBlock(block.Emitter, new ArgumentsInfo(block.Emitter, expression), inline).Emit(); } block.DisableEmitConversionExpression = true; // Still returns true if Nullable.lift( was written. return(isLifted); } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return(isLifted); } block.Write(BridgeTypes.ToJsName(method.DeclaringType, block.Emitter)); block.WriteDot(); block.Write(OverloadsCollection.Create(block.Emitter, method).GetOverloadName()); } if (isLifted) { block.WriteComma(); } else { block.WriteOpenParentheses(); } return(true); } // Still returns true if Nullable.lift( was written. return(isLifted); } catch { } return(false); }
public static object GetDefaultFieldValue(IType type, AstType astType, bool wrapType = true) { if (type.Kind == TypeKind.TypeParameter && astType != null) { var parameter = type as ITypeParameter; if (parameter != null && ( parameter.Owner.Attributes.Any(a => a.AttributeType.FullName == "Bridge.IgnoreGenericAttribute") || parameter.Owner.DeclaringTypeDefinition != null && parameter.Owner.DeclaringTypeDefinition.Attributes.Any(a => a.AttributeType.FullName == "Bridge.IgnoreGenericAttribute"))) { return(null); } return(new RawValue(JS.Funcs.BRIDGE_GETDEFAULTVALUE + "(" + astType.ToString() + ")")); } if (type.IsKnownType(KnownTypeCode.Decimal)) { return(0m); } if (type.IsKnownType(KnownTypeCode.Int64)) { return(0L); } if (type.IsKnownType(KnownTypeCode.UInt64)) { return(0UL); } if (type.IsKnownType(KnownTypeCode.Char) || type.IsKnownType(KnownTypeCode.Int16) || type.IsKnownType(KnownTypeCode.Int32) || type.IsKnownType(KnownTypeCode.UInt16) || type.IsKnownType(KnownTypeCode.UInt32) || type.IsKnownType(KnownTypeCode.Byte) || type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.SByte) || type.IsKnownType(KnownTypeCode.Single) || type.IsKnownType(KnownTypeCode.Enum)) { return(0); } if (NullableType.IsNullable(type)) { return(null); } if (type.IsKnownType(KnownTypeCode.Boolean)) { return(false); } if (type.IsKnownType(KnownTypeCode.Enum) || type.Kind == TypeKind.Enum) { return(0); } if (type.Kind == TypeKind.Struct && wrapType) { return(type); } return(null); }
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 && arrayAccess.Indexes.Count > 1) { this.EmitArrayAccess(indexerExpression); return; } var isIgnore = true; var isAccessorsIndexer = false; var ignoreAccessor = false; IProperty member = null; IMethod method = null; var oldIsAssignment = this.Emitter.IsAssignment; var oldUnary = this.Emitter.IsUnaryAccessor; if (memberResolveResult != null) { var resolvedMember = memberResolveResult.Member; isIgnore = this.Emitter.Validator.IsIgnoreType(resolvedMember.DeclaringTypeDefinition); isAccessorsIndexer = resolvedMember.DeclaringTypeDefinition.DirectBaseTypes.Any( t => t.FullName == "Bridge.IAccessorsIndexer"); if (resolvedMember is IProperty) { member = (IProperty)resolvedMember; method = this.Emitter.IsAssignment ? member.Setter : member.Getter; inlineAttr = this.Emitter.GetAttribute(method.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute"); ignoreAccessor = this.Emitter.Validator.HasAttribute(method.Attributes, "Bridge.IgnoreAttribute"); } } if (inlineAttr != null) { var inlineArg = inlineAttr.PositionalArguments[0]; if (inlineArg.ConstantValue != null) { inlineCode = inlineArg.ConstantValue.ToString(); } } 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.WriteDot(); 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 virtual bool WriteObject(string objectName, List <TypeConfigItem> members, string format, string interfaceFormat) { bool hasProperties = this.HasProperties(objectName, members); int pos = 0; IWriterInfo writer = null; bool beginBlock = false; if (hasProperties && objectName != null && !this.IsObjectLiteral) { beginBlock = true; pos = this.Emitter.Output.Length; writer = this.SaveWriter(); this.EnsureComma(); this.Write(objectName); this.WriteColon(); this.BeginBlock(); } bool isProperty = JS.Fields.PROPERTIES == objectName; bool isField = JS.Fields.FIELDS == objectName; int count = 0; foreach (var member in members) { object constValue = null; bool isPrimitive = false; var primitiveExpr = member.Initializer as PrimitiveExpression; bool write = false; bool writeScript = false; if (primitiveExpr != null) { //isPrimitive = true; constValue = primitiveExpr.Value; ResolveResult rr = null; if (member.VarInitializer != null) { rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter); } else { rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter); } if (rr != null && rr.Type.Kind == TypeKind.Enum) { constValue = Helpers.GetEnumValue(this.Emitter, rr.Type, constValue); writeScript = true; } } if (constValue is RawValue) { constValue = constValue.ToString(); write = true; writeScript = false; } var isNull = member.Initializer.IsNull || member.Initializer is NullReferenceExpression || member.Initializer.Parent == null; if (!isNull && !isPrimitive) { var constrr = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter); if (constrr != null && constrr.IsCompileTimeConstant) { //isPrimitive = true; constValue = constrr.ConstantValue; var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(member.Initializer); if (!expectedType.Equals(constrr.Type) && expectedType.Kind != TypeKind.Dynamic) { try { constValue = Convert.ChangeType(constValue, ReflectionHelper.GetTypeCode(expectedType)); } catch (Exception) { this.Emitter.Log.Warn($"FieldBlock: Convert.ChangeType is failed. Value type: {constrr.Type.FullName}, Target type: {expectedType.FullName}"); } } if (constrr.Type.Kind == TypeKind.Enum) { constValue = Helpers.GetEnumValue(this.Emitter, constrr.Type, constrr.ConstantValue); } writeScript = true; } } var isNullable = false; if (isPrimitive && constValue is AstType) { var itype = this.Emitter.Resolver.ResolveNode((AstType)constValue, this.Emitter); if (NullableType.IsNullable(itype.Type)) { isNullable = true; } } string tpl = null; IMember templateMember = null; MemberResolveResult init_rr = null; if (isField && member.VarInitializer != null) { init_rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter) as MemberResolveResult; tpl = init_rr != null?this.Emitter.GetInline(init_rr.Member) : null; if (tpl != null) { templateMember = init_rr.Member; } } bool isAutoProperty = false; if (isProperty) { var member_rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter) as MemberResolveResult; var property = (IProperty)member_rr.Member; isAutoProperty = Helpers.IsAutoProperty(property); } bool written = false; if (!isNull && (!isPrimitive || constValue is AstType || tpl != null) && !(isProperty && !IsObjectLiteral && !isAutoProperty)) { string value = null; bool needContinue = false; string defValue = ""; if (!isPrimitive) { var oldWriter = this.SaveWriter(); this.NewWriter(); member.Initializer.AcceptVisitor(this.Emitter); value = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); ResolveResult rr = null; AstType astType = null; if (member.VarInitializer != null) { rr = this.Emitter.Resolver.ResolveNode(member.VarInitializer, this.Emitter); } else { astType = member.Entity.ReturnType; rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter); } constValue = Inspector.GetDefaultFieldValue(rr.Type, astType); if (rr.Type.Kind == TypeKind.Enum) { constValue = Helpers.GetEnumValue(this.Emitter, rr.Type, constValue); } isNullable = NullableType.IsNullable(rr.Type); needContinue = constValue is IType; writeScript = true; /*if (needContinue && !(member.Initializer is ObjectCreateExpression)) * { * defValue = " || " + Inspector.GetStructDefaultValue((IType)constValue, this.Emitter); * }*/ } else if (constValue is AstType) { value = isNullable ? "null" : Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter); constValue = value; write = true; needContinue = !isProperty && !isNullable; } var name = member.GetName(this.Emitter); bool isValidIdentifier = Helpers.IsValidIdentifier(name); if (isProperty && isPrimitive) { constValue = "null"; if (this.IsObjectLiteral) { written = true; if (isValidIdentifier) { this.Write(string.Format("this.{0} = {1};", name, value)); } else { this.Write(string.Format("this[{0}] = {1};", AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value)); } this.WriteNewLine(); } else { this.Injectors.Add(string.Format(name.StartsWith("\"") || !isValidIdentifier ? "this[{0}] = {1};" : "this.{0} = {1};", isValidIdentifier ? name : AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value)); } } else { if (this.IsObjectLiteral) { written = true; if (isValidIdentifier) { this.Write(string.Format("this.{0} = {1};", name, value + defValue)); } else { this.Write(string.Format("this[{0}] = {1};", AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value + defValue)); } this.WriteNewLine(); } else if (tpl != null) { if (!tpl.Contains("{0}")) { tpl = tpl + " = {0};"; } string v = null; if (!isNull && (!isPrimitive || constValue is AstType)) { v = value + defValue; } else { if (write) { v = constValue != null?constValue.ToString() : ""; } else if (writeScript) { v = AbstractEmitterBlock.ToJavaScript(constValue, this.Emitter); } else { var oldWriter = this.SaveWriter(); this.NewWriter(); member.Initializer.AcceptVisitor(this.Emitter); v = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); } } tpl = Helpers.ConvertTokens(this.Emitter, tpl, templateMember); tpl = tpl.Replace("{this}", "this").Replace("{0}", v); if (!tpl.EndsWith(";")) { tpl += ";"; } this.Injectors.Add(tpl); } else { var rr = this.Emitter.Resolver.ResolveNode(member.Initializer, this.Emitter) as CSharpInvocationResolveResult; bool isDefaultInstance = rr != null && rr.Member.SymbolKind == SymbolKind.Constructor && rr.Arguments.Count == 0 && rr.InitializerStatements.Count == 0 && rr.Type.Kind == TypeKind.Struct; if (!isDefaultInstance) { if (isField && !isValidIdentifier) { this.Injectors.Add(string.Format("this[{0}] = {1};", name.StartsWith("\"") ? name : AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value + defValue)); } else { this.Injectors.Add(string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value + defValue)); } } } } } count++; if (written) { continue; } bool withoutTypeParams = true; MemberResolveResult m_rr = null; if (member.Entity != null) { m_rr = this.Emitter.Resolver.ResolveNode(member.Entity, this.Emitter) as MemberResolveResult; if (m_rr != null) { withoutTypeParams = OverloadsCollection.ExcludeTypeParameterForDefinition(m_rr); } } var mname = member.GetName(this.Emitter, withoutTypeParams); if (this.TypeInfo.IsEnum && m_rr != null) { mname = this.Emitter.GetEntityName(m_rr.Member); } bool isValid = Helpers.IsValidIdentifier(mname); if (!isValid) { if (this.IsObjectLiteral) { mname = "[" + AbstractEmitterBlock.ToJavaScript(mname, this.Emitter) + "]"; } else { mname = AbstractEmitterBlock.ToJavaScript(mname, this.Emitter); } } if (this.IsObjectLiteral) { this.WriteThis(); if (isValid) { this.WriteDot(); } this.Write(mname); this.Write(" = "); } else { this.EnsureComma(); XmlToJsDoc.EmitComment(this, member.Entity, null, member.Entity is FieldDeclaration ? member.VarInitializer : null); this.Write(mname); this.WriteColon(); } bool close = false; if (isProperty && !IsObjectLiteral && !isAutoProperty) { var oldTempVars = this.Emitter.TempVariables; this.BeginBlock(); new VisitorPropertyBlock(this.Emitter, (PropertyDeclaration)member.Entity).Emit(); this.WriteNewLine(); this.EndBlock(); this.Emitter.Comma = true; this.Emitter.TempVariables = oldTempVars; continue; } if (constValue is AstType || constValue is IType) { this.Write("null"); if (!isNullable) { var name = member.GetName(this.Emitter); bool isValidIdentifier = Helpers.IsValidIdentifier(name); var value = constValue is AstType?Inspector.GetStructDefaultValue((AstType)constValue, this.Emitter) : Inspector.GetStructDefaultValue((IType)constValue, this.Emitter); if (!isValidIdentifier) { this.Injectors.Insert(BeginCounter++, string.Format("this[{0}] = {1};", name.StartsWith("\"") ? name : AbstractEmitterBlock.ToJavaScript(name, this.Emitter), value)); } else { this.Injectors.Insert(BeginCounter++, string.Format(name.StartsWith("\"") ? interfaceFormat : format, name, value)); } } } else if (write) { this.Write(constValue); } else if (writeScript) { this.WriteScript(constValue); } else { member.Initializer.AcceptVisitor(this.Emitter); } if (close) { this.Write(" }"); } if (this.IsObjectLiteral) { this.WriteSemiColon(true); } this.Emitter.Comma = true; } if (count > 0 && objectName != null && !IsObjectLiteral) { this.WriteNewLine(); this.EndBlock(); } else if (beginBlock) { this.Emitter.IsNewLine = writer.IsNewLine; this.Emitter.ResetLevel(writer.Level); this.Emitter.Comma = writer.Comma; this.Emitter.Output.Length = pos; } return(count > 0); }
protected void VisitUnaryOperatorExpression() { var unaryOperatorExpression = this.UnaryOperatorExpression; var oldType = this.Emitter.UnaryOperatorType; var oldAccessor = this.Emitter.IsUnaryAccessor; var resolveOperator = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression, this.Emitter); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(unaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; int count = this.Emitter.Writers.Count; if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } if (Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver)) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await) { this.HandleDecimal(resolveOperator); return; } if (this.ResolveOperator(unaryOperatorExpression, orr)) { return; } if (Helpers.Is64Type(resolveOperator.Type, this.Emitter.Resolver)) { isLong = true; isLongExpected = true; } if (isLong && isLongExpected && unaryOperatorExpression.Operator != UnaryOperatorType.Await) { this.HandleDecimal(resolveOperator, true); return; } if (this.ResolveOperator(unaryOperatorExpression, orr)) { return; } var op = unaryOperatorExpression.Operator; var argResolverResult = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression, this.Emitter); bool nullable = NullableType.IsNullable(argResolverResult.Type); if (nullable) { if (op != UnaryOperatorType.Increment && op != UnaryOperatorType.Decrement && op != UnaryOperatorType.PostIncrement && op != UnaryOperatorType.PostDecrement) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); } } bool isAccessor = false; var memberArgResolverResult = argResolverResult as MemberResolveResult; if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty) { var prop = (IProperty)memberArgResolverResult.Member; var isIgnore = this.Emitter.Validator.IsIgnoreType(memberArgResolverResult.Member.DeclaringTypeDefinition); var inlineAttr = prop.Getter != null?this.Emitter.GetAttribute(prop.Getter.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute") : null; var ignoreAccessor = prop.Getter != null && this.Emitter.Validator.IsIgnoreType(prop.Getter); var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member); isAccessor = true; if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer) { isAccessor = false; } } else if (argResolverResult is ArrayAccessResolveResult) { isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1; } this.Emitter.UnaryOperatorType = op; if ((isAccessor) && (op == UnaryOperatorType.Increment || op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostIncrement || op == UnaryOperatorType.PostDecrement)) { this.Emitter.IsUnaryAccessor = true; if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.Emitter.IsUnaryAccessor = false; unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.Emitter.IsUnaryAccessor = true; unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } this.Emitter.IsUnaryAccessor = oldAccessor; if (this.Emitter.Writers.Count > count) { this.PopWriter(); } } else { switch (op) { case UnaryOperatorType.BitNot: if (nullable) { this.Write("bnot("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { this.Write("~"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Decrement: if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.Write("--"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { this.Write("--"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Increment: if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.Write("++"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { this.Write("++"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Minus: if (nullable) { this.Write("neg("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { this.Write("-"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Not: if (nullable) { this.Write("not("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { this.Write("!"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Plus: if (nullable) { this.Write("pos("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.PostDecrement: if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("--"); this.Write(" : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("--"); } break; case UnaryOperatorType.PostIncrement: if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("++"); this.Write(" : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("++"); } break; case UnaryOperatorType.Await: if (this.Emitter.ReplaceAwaiterByVar) { var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1; this.Write(JS.Vars.ASYNC_TASK_RESULT + index); } else { var oldValue = this.Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling; if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling) { this.WriteAwaiters(unaryOperatorExpression.Expression); this.Emitter.ReplaceAwaiterByVar = true; this.Emitter.AsyncExpressionHandling = true; } this.WriteAwaiter(unaryOperatorExpression.Expression); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; } break; default: throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString()); } if (this.Emitter.Writers.Count > count) { this.PopWriter(); } } this.Emitter.UnaryOperatorType = oldType; }
private void HandleDecimal(ResolveResult resolveOperator, bool isLong = false) { var orr = resolveOperator as OperatorResolveResult; var op = this.UnaryOperatorExpression.Operator; var oldType = this.Emitter.UnaryOperatorType; var oldAccessor = this.Emitter.IsUnaryAccessor; var typeCode = isLong ? KnownTypeCode.Int64 : KnownTypeCode.Decimal; this.Emitter.UnaryOperatorType = op; var argResolverResult = this.Emitter.Resolver.ResolveNode(this.UnaryOperatorExpression.Expression, this.Emitter); bool nullable = NullableType.IsNullable(argResolverResult.Type); bool isAccessor = false; var memberArgResolverResult = argResolverResult as MemberResolveResult; if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty) { var isIgnore = this.Emitter.Validator.IsIgnoreType(memberArgResolverResult.Member.DeclaringTypeDefinition); var inlineAttr = this.Emitter.GetAttribute(memberArgResolverResult.Member.Attributes, Translator.Bridge_ASSEMBLY + ".TemplateAttribute"); var ignoreAccessor = this.Emitter.Validator.IsIgnoreType(((IProperty)memberArgResolverResult.Member).Getter); var isAccessorsIndexer = this.Emitter.Validator.IsAccessorsIndexer(memberArgResolverResult.Member); isAccessor = true; if (inlineAttr == null && (isIgnore || ignoreAccessor) && !isAccessorsIndexer) { isAccessor = false; } } else if (argResolverResult is ArrayAccessResolveResult) { isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1; } var isOneOp = op == UnaryOperatorType.Increment || op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostIncrement || op == UnaryOperatorType.PostDecrement; if (isAccessor && isOneOp) { this.Emitter.IsUnaryAccessor = true; if (nullable) { this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.Emitter.IsUnaryAccessor = false; this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.Emitter.IsUnaryAccessor = true; this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } this.Emitter.UnaryOperatorType = oldType; this.Emitter.IsUnaryAccessor = oldAccessor; return; } var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (orr != null && method == null) { var name = Helpers.GetUnaryOperatorMethodName(this.UnaryOperatorExpression.Operator); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (orr.IsLiftedOperator) { if (!isOneOp) { this.Write(JS.Types.SYSTEM_NULLABLE + "."); } string action = JS.Funcs.Math.LIFT1; string op_name = null; switch (this.UnaryOperatorExpression.Operator) { case UnaryOperatorType.Minus: op_name = JS.Funcs.Math.NEG; break; case UnaryOperatorType.Plus: op_name = "clone"; break; case UnaryOperatorType.BitNot: op_name = "not"; break; case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "('" + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "', "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true); this.Write(")"); this.WriteCloseParentheses(); this.Write(" : null"); break; case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: this.Write(JS.Funcs.BRIDGE_HASVALUE); this.WriteOpenParentheses(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = " + JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1 + "('" + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "', "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, true); this.Write(")"); this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); this.Write(" : null"); break; } if (!isOneOp) { this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit(); this.AddOveflowFlag(typeCode, op_name, true); this.WriteCloseParentheses(); } } else if (method == null) { string op_name = null; var isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement; if (isStatement) { if (op == UnaryOperatorType.PostIncrement) { op = UnaryOperatorType.Increment; } else if (op == UnaryOperatorType.PostDecrement) { op = UnaryOperatorType.Decrement; } } switch (op) { case UnaryOperatorType.Minus: op_name = JS.Funcs.Math.NEG; break; case UnaryOperatorType.Plus: op_name = "clone"; break; case UnaryOperatorType.BitNot: op_name = "not"; break; case UnaryOperatorType.Increment: case UnaryOperatorType.Decrement: if (!isStatement) { this.WriteOpenParentheses(); } this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("." + (op == UnaryOperatorType.Decrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "("); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false); this.Write(")"); if (!isStatement) { this.WriteCloseParentheses(); } break; case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("." + (op == UnaryOperatorType.PostDecrement ? JS.Funcs.Math.DEC : JS.Funcs.Math.INC) + "("); this.AddOveflowFlag(typeCode, JS.Funcs.Math.DEC, false); this.Write("), "); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); break; } if (!isOneOp) { this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteDot(); this.Write(op_name); this.WriteOpenParentheses(); this.AddOveflowFlag(typeCode, op_name, false); this.WriteCloseParentheses(); } } else { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { if (isOneOp) { var isStatement = this.UnaryOperatorExpression.Parent is ExpressionStatement; if (isStatement || this.UnaryOperatorExpression.Operator == UnaryOperatorType.Increment || this.UnaryOperatorExpression.Operator == UnaryOperatorType.Decrement) { if (!isStatement) { this.WriteOpenParentheses(); } this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit (); if (!isStatement) { this.WriteCloseParentheses(); } } else { this.WriteOpenParentheses(); var valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.WriteComma(); this.UnaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" = "); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit(); this.WriteComma(); this.Write(valueVar); this.WriteCloseParentheses(); this.RemoveTempVar(valueVar); } } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.UnaryOperatorExpression, orr, method), inline).Emit(); } } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, new Expression[] { this.UnaryOperatorExpression.Expression }, null, null, 0).Emit(); this.WriteCloseParentheses(); } } this.Emitter.UnaryOperatorType = oldType; }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; bool isConstTarget = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (targetrr is ConstantResolveResult) { isConstTarget = true; } var memberTargetrr = targetrr as MemberResolveResult; if (memberTargetrr != null) { if (memberTargetrr.Type.Kind == TypeKind.Enum && memberTargetrr.Member is DefaultResolvedField) { isConstTarget = true; } else if (memberTargetrr.IsCompileTimeConstantToString()) { isConstTarget = true; } } if (memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression)) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } if (resolveResult is DynamicInvocationResolveResult) { resolveResult = ((DynamicInvocationResolveResult)resolveResult).Target; } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; Tuple <bool, bool, string> inlineInfo = member != null?this.Emitter.GetInlineCode(memberReferenceExpression) : null; //string inline = member != null ? this.Emitter.GetInline(member.Member) : null; string inline = inlineInfo != null ? inlineInfo.Item3 : null; bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && inline.Contains("{this}"); if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; inline = inline.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference"); } else { this.Write(inline); } } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && !hasInline) { this.WriteScript(member.ConstantValue); } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { if (member != null && member.Member is IMethod) { var r = new Regex(@"([$\w\.]+)\(\s*\S.*\)"); var match = r.Match(inline); if (match.Success) { this.Write(match.Groups[1].Value); } else { throw new EmitterException(memberReferenceExpression, "The templated method (" + member.Member.FullName + ") cannot be used like reference"); } } else { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as DefaultResolvedTypeDefinition; if (typeDef != null) { var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsIgnoreType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3) { string enumStringName = member.Member.Name; var attr = Helpers.GetInheritedAttribute(member.Member, Translator.Bridge_ASSEMBLY + ".NameAttribute"); if (attr != null) { enumStringName = this.Emitter.GetEntityName(member.Member); } else { switch (enumMode) { case 3: enumStringName = Object.Net.Utilities.StringUtils.ToLowerCamelCase(member.Member.Name); break; case 4: break; case 5: enumStringName = enumStringName.ToLowerInvariant(); break; case 6: enumStringName = enumStringName.ToUpperInvariant(); break; } } this.WriteScript(enumStringName); return; } } } bool isInvokeInCurClass = false; if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); /* * var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition()); * if(isNative) { * this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); * } * else { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter) + ")"); * }*/ return; } else if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); if (!isStatic) { this.Write(")"); } return; } else { bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { bool isField = memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult); if (!(targetrr is ThisResolveResult || targetrr is TypeResolveResult || targetrr is LocalResolveResult || isField)) { targetVar = this.GetTempVarName(); this.WriteVar(); this.Write(targetVar); this.Write(" = "); } } } if (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (isConstTarget) { this.Write("("); } isInvokeInCurClass = resolveResult is InvocationResolveResult && member.Member.IsInternalMember(); if (!isInvokeInCurClass) { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } if (isConstTarget) { this.Write(")"); } 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); } } } if (member != null && member.Member != null) { if (!isInvokeInCurClass) { if (!member.Member.IsStatic && ((member.Member.SymbolKind == SymbolKind.Method && !this.Emitter.Validator.IsDelegateOrLambda(expressionResolveResult)) || (member.Member.SymbolKind == SymbolKind.Property && !Helpers.IsFieldProperty(member.Member, this.Emitter)))) { this.WriteObjectColon(); } else { this.WriteDot(); } } } else { this.WriteDot(); } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { var proto = false; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && member != null) { var prop = member.Member as IProperty; if (prop != null && (prop.IsVirtual || prop.IsOverride)) { proto = true; } } if (Helpers.IsFieldProperty(member.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isNullable = NullableType.IsNullable(member.Member.ReturnType); bool isDecimal = Helpers.IsDecimalType(member.Member.ReturnType, this.Emitter.Resolver); if (isStatement) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } 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 { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } } else { if (targetVar != null) { this.Write(targetVar); } else { if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } } this.WriteObjectColon(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); 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.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { if (isConstTarget) { this.Write("("); } memberReferenceExpression.Target.AcceptVisitor(this.Emitter); if (isConstTarget) { this.Write(")"); } } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } 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.WriteOpenParentheses(); this.WriteCloseParentheses(); } } 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 { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } if (targetVar != null) { this.RemoveTempVar(targetVar); } } else { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { if (targetVar != null) { this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true), proto ? ".call(this, " : "(", targetVar, ".", Helpers.GetPropertyRef(member.Member, this.Emitter, false), proto ? ".call(this)" : "()", "{0})"), () => { this.RemoveTempVar(targetVar); }); } else { var oldWriter = this.SaveWriter(); this.NewWriter(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; var trg = this.Emitter.Output.ToString(); this.RestoreWriter(oldWriter); this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})"); /* * this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true), * proto ? ".call(this, " : "(", * trg, * ".", * Helpers.GetPropertyRef(member.Member, this.Emitter, false), * proto ? ".call(this)" : "()", * "{0})"));*/ } } else { if (proto) { this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + ".call(this, {0})"); } else { this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})"); } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst) { this.WriteScript(member.ConstantValue); } else { this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName()); } else { string name = OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName(); if (isInvokeInCurClass && Emitter.LocalsNamesMap.ContainsKey(name)) { string newName = this.GetUniqueName(name); this.IntroduceTempVar(newName + " = " + name); name = newName; } this.Write(name); } } else if (member.Member is DefaultResolvedEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write( OverloadsCollection.Create(this.Emitter, member.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); this.WriteOpenParentheses(); } else { this.Write(this.Emitter.GetEntityName(member.Member, true)); } } else { this.Write(this.Emitter.GetEntityName(member.Member)); } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this, pos); } }
/// <summary> /// Determines whether a variable should be inlined in non-aggressive mode, even though it is not a generated variable. /// </summary> /// <param name="next">The next top-level expression</param> /// <param name="v">The variable being eliminated by inlining.</param> /// <param name="inlinedExpression">The expression being inlined</param> static bool NonAggressiveInlineInto(ILInstruction next, FindResult findResult, ILInstruction inlinedExpression, ILVariable v) { if (findResult.Type == FindResultType.NamedArgument) { var originalStore = (StLoc)inlinedExpression.Parent; return(!originalStore.ILStackWasEmpty); } Debug.Assert(findResult.Type == FindResultType.Found); var loadInst = findResult.LoadInst; Debug.Assert(loadInst.IsDescendantOf(next)); // decide based on the source expression being inlined switch (inlinedExpression.OpCode) { case OpCode.DefaultValue: case OpCode.StObj: case OpCode.NumericCompoundAssign: case OpCode.UserDefinedCompoundAssign: case OpCode.Await: case OpCode.SwitchInstruction: return(true); case OpCode.LdLoc: if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) { // Roslyn likes to put the result of fetching a state machine field into a temporary variable, // so inline more aggressively in such cases. return(true); } break; } if (inlinedExpression.ResultType == StackType.Ref) { // VB likes to use ref locals for compound assignment // (the C# compiler uses ref stack slots instead). // We want to avoid unnecessary ref locals, so we'll always inline them if possible. return(true); } var parent = loadInst.Parent; if (NullableLiftingTransform.MatchNullableCtor(parent, out _, out _)) { // inline into nullable ctor call in lifted operator parent = parent.Parent; } if (parent is ILiftableInstruction liftable && liftable.IsLifted) { return(true); // inline into lifted operators } // decide based on the new parent into which we are inlining: switch (parent.OpCode) { case OpCode.NullCoalescingInstruction: if (NullableType.IsNullable(v.Type)) { return(true); // inline nullables into ?? operator } break; case OpCode.NullableUnwrap: return(true); // inline into ?. operator case OpCode.UserDefinedLogicOperator: case OpCode.DynamicLogicOperatorInstruction: return(true); // inline into (left slot of) user-defined && or || operator case OpCode.DynamicGetMemberInstruction: case OpCode.DynamicGetIndexInstruction: if (parent.Parent.OpCode == OpCode.DynamicCompoundAssign) { return(true); // inline into dynamic compound assignments } break; case OpCode.DynamicCompoundAssign: return(true); case OpCode.GetPinnableReference: case OpCode.LocAllocSpan: return(true); // inline size-expressions into localloc.span case OpCode.Call: case OpCode.CallVirt: // Aggressive inline into property/indexer getter calls for compound assignment calls // (The compiler generates locals for these because it doesn't want to evalute the args twice for getter+setter) if (parent.SlotInfo == CompoundAssignmentInstruction.TargetSlot) { return(true); } if (((CallInstruction)parent).Method is SyntheticRangeIndexAccessor) { return(true); } break; case OpCode.LdElema: if (((LdElema)parent).WithSystemIndex) { return(true); } break; case OpCode.Leave: case OpCode.YieldReturn: return(true); case OpCode.SwitchInstruction: //case OpCode.BinaryNumericInstruction when parent.SlotInfo == SwitchInstruction.ValueSlot: case OpCode.StringToInt when parent.SlotInfo == SwitchInstruction.ValueSlot: return(true); } // decide based on the top-level target instruction into which we are inlining: switch (next.OpCode) { case OpCode.IfInstruction: while (parent.MatchLogicNot(out _)) { parent = parent.Parent; } return(parent == next); default: return(false); } }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; this.isRefArg = this.Emitter.IsRefArg; this.Emitter.IsRefArg = false; resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id) && resolveResult is LocalResolveResult) { var lrr = (LocalResolveResult)resolveResult; if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(lrr.Variable) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[lrr.Variable]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); return; } if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); /*if (this.Emitter.Validator.IsExternalType(resolveResult.Type.GetDefinition()) || resolveResult.Type.Kind == TypeKind.Enum) * { * this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); * } * else * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(resolveResult.Type, this.Emitter) + ")"); * }*/ return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; var isInvoke = identifierExpression.Parent is InvocationExpression && (((InvocationExpression)(identifierExpression.Parent)).Target == identifierExpression); if (memberResult != null && memberResult.Member is IMethod && isInvoke) { var i_rr = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter) as CSharpInvocationResolveResult; if (i_rr != null && !i_rr.IsExpandedForm) { var tpl = this.Emitter.GetAttribute(memberResult.Member.Attributes, JS.NS.BRIDGE + ".TemplateAttribute"); if (tpl != null && tpl.PositionalArguments.Count == 2) { inlineCode = tpl.PositionalArguments[1].ConstantValue.ToString(); } } } if (string.IsNullOrEmpty(inlineCode) && memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var method = (IMethod)memberResult.Member; if (method.TypeArguments.Count > 0) { inlineCode = MemberReferenceBlock.GenerateInlineForMethodReference(method, this.Emitter); } } bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasInline && inlineCode.StartsWith("<self>")) { hasThis = true; inlineCode = inlineCode.Substring(6); } if (hasThis) { Emitter.ThisRefCounter++; this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); /*if (!this.Emitter.Validator.IsExternalType(memberResult.Member.DeclaringTypeDefinition) && memberResult.Member.DeclaringTypeDefinition.Kind != TypeKind.Enum) * { * this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); * } * else * { * this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { this.WriteThis(); } var oldInline = inlineCode; var thisArg = this.Emitter.Output.ToString(); int thisIndex = inlineCode.IndexOf("{this}"); inlineCode = inlineCode.Replace("{this}", thisArg); this.Emitter.Output = oldBuilder; int[] range = null; if (thisIndex > -1) { range = new[] { thisIndex, thisIndex + thisArg.Length }; } if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode, null, thisArg, range); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), oldInline, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else if (memberResult != null && memberResult.Member is IField && inlineCode.Contains("{0}")) { this.PushWriter(inlineCode, null, thisArg, range); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode)) { this.PushWriter(inlineCode, null, thisArg, range); } else { this.Write(inlineCode); } } return; } if (hasInline) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { if (memberResult.Member is IMethod) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.IdentifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else if (InlineArgumentsBlock.FormatArgRegex.IsMatch(inlineCode)) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } return; } string appendAdditionalCode = null; if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { if (!string.IsNullOrEmpty(inlineCode)) { ResolveResult targetrr = null; if (memberResult.Member.IsStatic) { targetrr = new TypeResolveResult(memberResult.Member.DeclaringType); } new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, identifierExpression, resolveResult), inlineCode, (IMethod)memberResult.Member, targetrr).EmitFunctionReference(); } else { var resolvedMethod = (IMethod)memberResult.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(isExtensionMethod ? JS.Funcs.BRIDGE_BIND_SCOPE : JS.Funcs.BRIDGE_CACHE_BIND); this.WriteOpenParentheses(); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(memberResult.Member) && this.Emitter.IsInlineConst(memberResult.Member)) { this.WriteScript(memberResult.ConstantValue); return; } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { //this.Write(inlineCode); if (resolveResult is InvocationResolveResult || (memberResult.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } else if (memberResult.Member is IProperty) { var name = Helpers.GetPropertyRef(memberResult.Member, this.Emitter); this.WriteIdentifier(name); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.DEC); } this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); 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(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); if (isDecimal || isLong) { if (isNullable) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT1); this.WriteOpenParentheses(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.WriteScript(JS.Funcs.Math.INC); } else { this.WriteScript(JS.Funcs.Math.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(JS.Funcs.Math.INC); } else { this.Write(JS.Funcs.Math.DEC); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } 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(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { string trg; if (memberResult.Member.IsStatic) { trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); } else { trg = "this"; } bool isBool = memberResult != null && NullableType.IsNullable(memberResult.Member.ReturnType) ? NullableType.GetUnderlyingType(memberResult.Member.ReturnType).IsKnownType(KnownTypeCode.Boolean) : memberResult.Member.ReturnType.IsKnownType(KnownTypeCode.Boolean); bool skipGet = false; var orr = this.Emitter.Resolver.ResolveNode(identifierExpression.Parent, this.Emitter) as OperatorResolveResult; bool special = orr != null && orr.IsLiftedOperator; if (!special && isBool && (this.Emitter.AssignmentType == AssignmentOperatorType.BitwiseAnd || this.Emitter.AssignmentType == AssignmentOperatorType.BitwiseOr)) { skipGet = true; } if (skipGet) { this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "({0})")); } else { this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), "(", trg, ".", Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), "()", "{0})")); } } else { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); } } else if (memberResult != null && memberResult.Member is IEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(Helpers.GetAddOrRemove(this.Emitter.AssignmentType == AssignmentOperatorType.Add)); this.Write( OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is LocalResolveResult) { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } else if (memberResult != null) { this.WriteTarget(memberResult); string name = OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName(); if (isRefArg) { this.WriteScript(name); } else if (memberResult.Member is IField) { this.WriteIdentifier(name); } else { this.Write(name); } } else { this.Write(resolveResult.ToString()); } } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); }
protected void VisitMemberReferenceExpression() { MemberReferenceExpression memberReferenceExpression = this.MemberReferenceExpression; ResolveResult resolveResult = null; ResolveResult expressionResolveResult = null; string targetVar = null; string valueVar = null; bool isStatement = false; var targetrr = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Target, this.Emitter); if (memberReferenceExpression.Parent is InvocationExpression && (((InvocationExpression)(memberReferenceExpression.Parent)).Target == memberReferenceExpression)) { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); expressionResolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); if (expressionResolveResult is InvocationResolveResult) { resolveResult = expressionResolveResult; } } else { resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression, this.Emitter); } bool oldIsAssignment = this.Emitter.IsAssignment; bool oldUnary = this.Emitter.IsUnaryAccessor; if (resolveResult == null) { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; this.WriteDot(); string name = memberReferenceExpression.MemberName; this.Write(name.ToLowerCamelCase()); return; } if (resolveResult is DynamicInvocationResolveResult) { resolveResult = ((DynamicInvocationResolveResult)resolveResult).Target; } if (resolveResult is MethodGroupResolveResult) { var oldResult = (MethodGroupResolveResult)resolveResult; resolveResult = this.Emitter.Resolver.ResolveNode(memberReferenceExpression.Parent, this.Emitter); if (resolveResult is DynamicInvocationResolveResult) { var method = oldResult.Methods.Last(); resolveResult = new MemberResolveResult(new TypeResolveResult(method.DeclaringType), method); } } MemberResolveResult member = resolveResult as MemberResolveResult; var globalTarget = member != null?this.Emitter.IsGlobalTarget(member.Member) : null; if (globalTarget != null && globalTarget.Item1) { var target = globalTarget.Item2; if (!string.IsNullOrWhiteSpace(target)) { bool assign = false; var memberExpression = member.Member is IMethod ? memberReferenceExpression.Parent.Parent : memberReferenceExpression.Parent; var targetExpression = member.Member is IMethod ? memberReferenceExpression.Parent : memberReferenceExpression; var assignment = memberExpression as AssignmentExpression; if (assignment != null && assignment.Right == targetExpression) { assign = true; } else { var varInit = memberExpression as VariableInitializer; if (varInit != null && varInit.Initializer == targetExpression) { assign = true; } else if (memberExpression is InvocationExpression) { var targetInvocation = (InvocationExpression)memberExpression; if (targetInvocation.Arguments.Any(a => a == targetExpression)) { assign = true; } } } if (assign) { if (resolveResult is InvocationResolveResult) { this.PushWriter(target); } else { this.Write(target); } return; } } if (resolveResult is InvocationResolveResult) { this.PushWriter(""); } return; } string inline = member != null?this.Emitter.GetInline(member.Member) : null; bool hasInline = !string.IsNullOrEmpty(inline); bool hasThis = hasInline && inline.Contains("{this}"); if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; inline = inline.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { this.Write(inline); } return; } if (member != null && member.Member.SymbolKind == SymbolKind.Field && this.Emitter.IsMemberConst(member.Member) && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(member.ConstantValue); } else if (hasInline && member.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inline); } else { //this.Write(inline); new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, memberReferenceExpression, resolveResult), inline).Emit(); } } else { if (member != null && member.IsCompileTimeConstant && member.Member.DeclaringType.Kind == TypeKind.Enum) { var typeDef = member.Member.DeclaringType as DefaultResolvedTypeDefinition; if (typeDef != null) { var enumMode = this.Emitter.Validator.EnumEmitMode(typeDef); if ((this.Emitter.Validator.IsIgnoreType(typeDef) && enumMode == -1) || enumMode == 2) { this.WriteScript(member.ConstantValue); return; } if (enumMode >= 3) { string enumStringName = member.Member.Name; var attr = this.Emitter.GetAttribute(member.Member.Attributes, Translator.Bridge_ASSEMBLY + ".NameAttribute"); if (attr != null) { enumStringName = this.Emitter.GetEntityName(member.Member); } else { switch (enumMode) { case 3: enumStringName = Object.Net.Utilities.StringUtils.ToLowerCamelCase(member.Member.Name); break; case 4: break; case 5: enumStringName = enumStringName.ToLowerInvariant(); break; case 6: enumStringName = enumStringName.ToUpperInvariant(); break; } } this.WriteScript(enumStringName); return; } } } if (resolveResult is TypeResolveResult) { TypeResolveResult typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); return; } else if (member != null && member.Member is IMethod && !(member is InvocationResolveResult) && !( memberReferenceExpression.Parent is InvocationExpression && memberReferenceExpression.NextSibling != null && memberReferenceExpression.NextSibling.Role is TokenRole && ((TokenRole)memberReferenceExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)member.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; if (!isStatic) { this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Write(", "); } this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; if (isExtensionMethod) { this.Write(BridgeTypes.ToJsName(resolvedMethod.DeclaringType, this.Emitter)); } else { this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.Target.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldIsAssignment; this.Emitter.IsUnaryAccessor = oldUnary; } this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); if (!isStatic) { this.Write(")"); } return; } else { bool isProperty = false; if (member != null && member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { isProperty = true; bool writeTargetVar = false; if (this.Emitter.IsAssignment && this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { writeTargetVar = true; } else if (this.Emitter.IsUnaryAccessor) { writeTargetVar = true; isStatement = memberReferenceExpression.Parent is UnaryOperatorExpression && memberReferenceExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(member.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); } } if (writeTargetVar) { 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 (isProperty && this.Emitter.IsUnaryAccessor && !isStatement && targetVar == null) { valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.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); } } } var targetResolveResult = targetrr as MemberResolveResult; if (targetResolveResult == null || this.Emitter.IsGlobalTarget(targetResolveResult.Member) == null) { this.WriteDot(); } if (member == null) { if (targetrr != null && targetrr.Type.Kind == TypeKind.Dynamic) { this.Write(memberReferenceExpression.MemberName); } else { this.Write(memberReferenceExpression.MemberName.ToLowerCamelCase()); } } else if (!string.IsNullOrEmpty(inline)) { if (resolveResult is InvocationResolveResult || (member.Member.SymbolKind == SymbolKind.Property && this.Emitter.IsAssignment)) { this.PushWriter(inline); } else { this.Write(inline); } } else if (member.Member.SymbolKind == SymbolKind.Property && member.TargetResult.Type.Kind != TypeKind.Anonymous && !this.Emitter.Validator.IsObjectLiteral(member.Member.DeclaringTypeDefinition)) { var proto = false; if (this.MemberReferenceExpression.Target is BaseReferenceExpression && member != null) { var prop = member.Member as IProperty; if (prop != null && prop.IsVirtual) { proto = true; } } if (Helpers.IsFieldProperty(member.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isNullable = NullableType.IsNullable(member.Member.ReturnType); bool isDecimal = Helpers.IsDecimalType(member.Member.ReturnType, this.Emitter.Resolver); if (isStatement) { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } 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 { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteCloseParentheses(); } else { if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } } else { if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); 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.Member, this.Emitter, false)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } this.WriteComma(); if (targetVar != null) { this.Write(targetVar); } else { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, true)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteComma(); } else { this.WriteOpenParentheses(); } 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.WriteOpenParentheses(); this.WriteCloseParentheses(); } } 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 { memberReferenceExpression.Target.AcceptVisitor(this.Emitter); } this.WriteDot(); this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } if (targetVar != null) { this.RemoveTempVar(targetVar); } } else { this.Write(Helpers.GetPropertyRef(member.Member, this.Emitter)); if (proto) { this.Write(".call"); this.WriteOpenParentheses(); this.WriteThis(); this.WriteCloseParentheses(); } else { this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { if (targetVar != null) { this.PushWriter(string.Concat(Helpers.GetPropertyRef(member.Member, this.Emitter, true), proto ? ".call(this, " : "(", targetVar, ".", Helpers.GetPropertyRef(member.Member, this.Emitter, false), proto ? ".call(this)" : "()", "{0})"), () => { this.RemoveTempVar(targetVar); }); } else { var oldWriter = this.SaveWriter(); this.NewWriter(); this.Emitter.IsAssignment = false; this.Emitter.IsUnaryAccessor = false; memberReferenceExpression.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(Helpers.GetPropertyRef(member.Member, this.Emitter, true), proto ? ".call(this, " : "(", trg, ".", Helpers.GetPropertyRef(member.Member, this.Emitter, false), proto ? ".call(this)" : "()", "{0})")); } } else { if (proto) { this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + ".call(this, {0})"); } else { this.PushWriter(Helpers.GetPropertyRef(member.Member, this.Emitter, true) + "({0})"); } } } else if (member.Member.SymbolKind == SymbolKind.Field) { bool isConst = this.Emitter.IsMemberConst(member.Member); if (isConst && this.Emitter.IsInlineConst(member.Member)) { this.WriteScript(member.ConstantValue); } else { this.Write(OverloadsCollection.Create(this.Emitter, member.Member).GetOverloadName()); } } else if (resolveResult is InvocationResolveResult) { InvocationResolveResult invocationResult = (InvocationResolveResult)resolveResult; CSharpInvocationResolveResult cInvocationResult = (CSharpInvocationResolveResult)resolveResult; var expresssionMember = expressionResolveResult as MemberResolveResult; if (expresssionMember != null && cInvocationResult != null && cInvocationResult.IsDelegateInvocation && invocationResult.Member != expresssionMember.Member) { this.Write(OverloadsCollection.Create(this.Emitter, expresssionMember.Member).GetOverloadName()); } else { this.Write(OverloadsCollection.Create(this.Emitter, invocationResult.Member).GetOverloadName()); } } else if (member.Member is DefaultResolvedEvent && this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write(OverloadsCollection.Create(this.Emitter, member.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); this.WriteOpenParentheses(); } else { this.Write(this.Emitter.GetEntityName(member.Member)); } Helpers.CheckValueTypeClone(resolveResult, memberReferenceExpression, this); } }
protected virtual string GetCastCode(Expression expression, AstType astType, out bool isCastAttr) { var resolveResult = this.Emitter.Resolver.ResolveNode(astType, this.Emitter) as TypeResolveResult; isCastAttr = false; if (resolveResult == null) { return(null); } var exprResolveResult = this.Emitter.Resolver.ResolveNode(expression, this.Emitter); string inline = null; var method = this.GetCastMethod(exprResolveResult.Type, resolveResult.Type, out inline); if (method == null && (NullableType.IsNullable(exprResolveResult.Type) || NullableType.IsNullable(resolveResult.Type))) { method = this.GetCastMethod(NullableType.IsNullable(exprResolveResult.Type) ? NullableType.GetUnderlyingType(exprResolveResult.Type) : exprResolveResult.Type, NullableType.IsNullable(resolveResult.Type) ? NullableType.GetUnderlyingType(resolveResult.Type) : resolveResult.Type, out inline); } if (inline != null) { this.InlineMethod = method; return(inline); } IEnumerable <IAttribute> attributes = null; var type = resolveResult.Type.GetDefinition(); if (type != null) { attributes = type.Attributes; } else { ParameterizedType paramType = resolveResult.Type as ParameterizedType; if (paramType != null) { attributes = paramType.GetDefinition().Attributes; } } if (attributes != null) { var attribute = this.Emitter.GetAttribute(attributes, Translator.Bridge_ASSEMBLY + ".CastAttribute"); if (attribute != null) { isCastAttr = true; return(attribute.PositionalArguments[0].ConstantValue.ToString()); } } return(null); }
/// <summary> /// Determines whether a variable should be inlined in non-aggressive mode, even though it is not a generated variable. /// </summary> /// <param name="next">The next top-level expression</param> /// <param name="loadInst">The load within 'next'</param> /// <param name="inlinedExpression">The expression being inlined</param> static bool NonAggressiveInlineInto(ILInstruction next, ILInstruction loadInst, ILInstruction inlinedExpression, ILVariable v) { Debug.Assert(loadInst.IsDescendantOf(next)); // decide based on the source expression being inlined switch (inlinedExpression.OpCode) { case OpCode.DefaultValue: case OpCode.StObj: case OpCode.NumericCompoundAssign: case OpCode.UserDefinedCompoundAssign: case OpCode.Await: return(true); case OpCode.LdLoc: if (v.StateMachineField == null && ((LdLoc)inlinedExpression).Variable.StateMachineField != null) { // Roslyn likes to put the result of fetching a state machine field into a temporary variable, // so inline more aggressively in such cases. return(true); } break; } var parent = loadInst.Parent; if (NullableLiftingTransform.MatchNullableCtor(parent, out _, out _)) { // inline into nullable ctor call in lifted operator parent = parent.Parent; } if (parent is ILiftableInstruction liftable && liftable.IsLifted) { return(true); // inline into lifted operators } // decide based on the new parent into which we are inlining: switch (parent.OpCode) { case OpCode.NullCoalescingInstruction: if (NullableType.IsNullable(v.Type)) { return(true); // inline nullables into ?? operator } break; case OpCode.NullableUnwrap: return(true); // inline into ?. operator case OpCode.UserDefinedLogicOperator: case OpCode.DynamicLogicOperatorInstruction: return(true); // inline into (left slot of) user-defined && or || operator case OpCode.DynamicGetMemberInstruction: case OpCode.DynamicGetIndexInstruction: case OpCode.LdObj: if (parent.Parent.OpCode == OpCode.DynamicCompoundAssign) { return(true); // inline into dynamic compound assignments } break; case OpCode.ArrayToPointer: case OpCode.LocAllocSpan: return(true); // inline size-expressions into localloc.span } // decide based on the top-level target instruction into which we are inlining: switch (next.OpCode) { case OpCode.Leave: case OpCode.YieldReturn: return(parent == next); case OpCode.IfInstruction: while (parent.MatchLogicNot(out _)) { parent = parent.Parent; } return(parent == next); case OpCode.BlockContainer: if (((BlockContainer)next).EntryPoint.Instructions[0] is SwitchInstruction switchInst) { next = switchInst; goto case OpCode.SwitchInstruction; } else { return(false); } case OpCode.SwitchInstruction: if (parent == next) { return(true); } if (parent.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub) && parent.Parent == next) { return(true); } if (parent is StringToInt stringToInt && stringToInt.Parent == next) { return(true); } return(false); default: return(false); } }
public Expression ResolveUnaryOperator(ResolveContext rc, UnaryOperatorType op, Expression expression) { // V# 4.0 spec: §7.3.3 Unary operator overload resolution string overloadableOperatorName = GetOverloadableOperatorName(op); if (overloadableOperatorName == null) { switch (op) { case UnaryOperatorType.Dereference: PointerTypeSpec p = expression.Type as PointerTypeSpec; if (p != null) { return(SetOperationInformations(rc, p.ElementType, op, expression)); } else { return(ErrorResult); } case UnaryOperatorType.AddressOf: return(SetOperationInformations(rc, new PointerTypeSpec(expression.Type), op, expression)); default: return(ErrorExpression.UnknownError); } } // If the type is nullable, get the underlying type: IType type = NullableType.GetUnderlyingType(expression.Type); bool isNullable = NullableType.IsNullable(expression.Type); // the operator is overloadable: OverloadResolution userDefinedOperatorOR = rc.CreateOverloadResolution(new[] { expression }); foreach (var candidate in rc.GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) { userDefinedOperatorOR.AddCandidate(candidate); } if (userDefinedOperatorOR.FoundApplicableCandidate) { return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR)); } expression = UnaryNumericPromotion(rc, op, ref type, isNullable, expression); VSharpOperators.OperatorMethod[] methodGroup; VSharpOperators operators = VSharpOperators.Get(rc.compilation); switch (op) { case UnaryOperatorType.PreIncrement: case UnaryOperatorType.Decrement: case UnaryOperatorType.PostIncrement: case UnaryOperatorType.PostDecrement: // V# 4.0 spec: §7.6.9 Postfix increment and decrement operators // V# 4.0 spec: §7.7.5 Prefix increment and decrement operators TypeCode code = ReflectionHelper.GetTypeCode(type); if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer) { return(SetOperationInformations(rc, expression.Type, op, expression, isNullable)); } else { return(new ErrorExpression(expression.Type)); } case UnaryOperatorType.UnaryPlus: methodGroup = operators.UnaryPlusOperators; break; case UnaryOperatorType.UnaryNegation: methodGroup = rc.checkForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators; break; case UnaryOperatorType.LogicalNot: methodGroup = operators.LogicalNegationOperators; break; case UnaryOperatorType.OnesComplement: if (type.Kind == TypeKind.Enum) { if (expression.IsCompileTimeConstant && !isNullable && expression.ConstantValue != null) { // evaluate as (E)(~(U)x); var U = rc.compilation.FindType(expression.ConstantValue.GetType()); var unpackedEnum = Constant.CreateConstantFromValue(rc, U, expression.ConstantValue, loc); var rr = ResolveUnaryOperator(rc, op, unpackedEnum); ResolveContext ovfrc = rc.WithCheckForOverflow(false); rr = new CastExpression(type, rr).DoResolve(ovfrc); if (rr.IsCompileTimeConstant) { return(rr); } } return(SetOperationInformations(rc, expression.Type, op, expression, isNullable)); } else { methodGroup = operators.BitwiseComplementOperators; break; } default: throw new InvalidOperationException(); } OverloadResolution builtinOperatorOR = rc.CreateOverloadResolution(new[] { expression }); foreach (var candidate in methodGroup) { builtinOperatorOR.AddCandidate(candidate); } VSharpOperators.UnaryOperatorMethod m = (VSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate; IType resultType = m.ReturnType; if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { if (userDefinedOperatorOR.BestCandidate != null) { // If there are any user-defined operators, prefer those over the built-in operators. // It'll be a more informative error. return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR)); } else if (builtinOperatorOR.BestCandidateAmbiguousWith != null) { // If the best candidate is ambiguous, just use the input type instead // of picking one of the ambiguous overloads. return(new ErrorExpression(expression.Type)); } else { return(new ErrorExpression(resultType)); } } else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) { object val; try { val = m.Invoke(rc, expression.ConstantValue); } catch (ArithmeticException) { return(new ErrorExpression(resultType)); } return(Constant.CreateConstantFromValue(rc, resultType, val, loc)); } else { expression = rc.Convert(expression, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]); return(SetOperationInformations(rc, resultType, op, expression, builtinOperatorOR.BestCandidate is OverloadResolution.ILiftedOperator)); } }
public static string ToJavascriptName(IType type, IEmitter emitter) { if (type.Kind == TypeKind.Delegate) { var delegateName = H5Types.ConvertName(type.FullName); if (!emitter.JsDoc.Callbacks.Contains(delegateName)) { var method = type.GetDelegateInvokeMethod(); JsDocComment comment = new JsDocComment(); var parameters = method.Parameters; if (parameters != null && parameters.Count > 0) { foreach (var param in parameters) { var jsParam = new JsDocParam(); jsParam.Name = param.Name; jsParam.Type = XmlToJsDoc.ToJavascriptName(param.Type, emitter); comment.Parameters.Add(jsParam); } } comment.Returns.Add(new JsDocParam { Type = XmlToJsDoc.ToJavascriptName(method.ReturnType, emitter) }); comment.Callback = delegateName; comment.MemberOf = type.Namespace; if (!emitter.JsDoc.Namespaces.Contains(type.Namespace)) { emitter.JsDoc.Namespaces.Add(type.Namespace); comment.Namespace = type.Namespace; } emitter.JsDoc.Callbacks.Add(delegateName); emitter.WriteIndented(comment.ToString() + newLine + newLine, 0); } return(delegateName); } if (type.IsKnownType(KnownTypeCode.String)) { return("string"); } if (type.IsKnownType(KnownTypeCode.Boolean)) { return("boolean"); } if (type.IsKnownType(KnownTypeCode.Void)) { return("void"); } if (type.IsKnownType(KnownTypeCode.Byte) || type.IsKnownType(KnownTypeCode.Char) || type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Int16) || type.IsKnownType(KnownTypeCode.Int32) || type.IsKnownType(KnownTypeCode.SByte) || type.IsKnownType(KnownTypeCode.Single) || type.IsKnownType(KnownTypeCode.UInt16) || type.IsKnownType(KnownTypeCode.UInt32)) { return("number"); } if (type.Kind == TypeKind.Array) { ICSharpCode.NRefactory.TypeSystem.ArrayType arrayType = (ICSharpCode.NRefactory.TypeSystem.ArrayType)type; return(JS.Types.ARRAY + ".<" + XmlToJsDoc.ToJavascriptName(arrayType.ElementType, emitter) + ">"); } if (type.Kind == TypeKind.Dynamic) { return("object"); } if (type.Kind == TypeKind.Enum && type.DeclaringType != null) { return("number"); } if (NullableType.IsNullable(type)) { return("?" + XmlToJsDoc.ToJavascriptName(NullableType.GetUnderlyingType(type), emitter)); } H5Type h5Type = emitter.H5Types.Get(type, true); //string name = H5Types.ConvertName(type.FullName); var name = type.Namespace; var hasTypeDef = h5Type != null && h5Type.TypeDefinition != null; bool isNested = false; if (hasTypeDef) { var typeDef = h5Type.TypeDefinition; if (typeDef.IsNested) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.GetParentNames(emitter, typeDef); isNested = true; } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.ConvertName(typeDef.Name); } else { if (type.DeclaringType != null) { name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.GetParentNames(emitter, type); if (type.DeclaringType.TypeArguments.Count > 0) { name += Helpers.PrefixDollar(type.TypeArguments.Count); } isNested = true; } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + H5Types.ConvertName(type.Name); } bool isCustomName = false; if (h5Type != null) { name = H5Types.AddModule(name, h5Type, false, isNested, out isCustomName); } if (!hasTypeDef && !isCustomName && type.TypeArguments.Count > 0) { name += Helpers.PrefixDollar(type.TypeArguments.Count); } return(name); }
private static void CheckLong(ConversionBlock block, Expression expression, IType expectedType, IType fromType, bool isChecked) { if (!NeedsNarrowingNumericConversion(fromType, expectedType)) { return; } if (isChecked) { block.Write(JS.Types.System.Int64.CHECK); block.WriteOpenParentheses(); block.AfterOutput += ", "; block.AfterOutput += BridgeTypes.ToJsName(expectedType, block.Emitter); block.AfterOutput += ")"; } else { string action = null; expectedType = NullableType.IsNullable(expectedType) ? NullableType.GetUnderlyingType(expectedType) : expectedType; if (block.Emitter.IsJavaScriptOverflowMode && !InsideOverflowContext(block.Emitter, expression)) { action = "toNumber"; } else if (expectedType.IsKnownType(KnownTypeCode.Char)) { action = "clipu16"; } else if (expectedType.IsKnownType(KnownTypeCode.SByte)) { action = "clip8"; } else if (expectedType.IsKnownType(KnownTypeCode.Byte)) { action = "clipu8"; } else if (expectedType.IsKnownType(KnownTypeCode.Int16)) { action = "clip16"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt16)) { action = "clipu16"; } else if (expectedType.IsKnownType(KnownTypeCode.Int32)) { action = "clip32"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt32)) { action = "clipu32"; } else if (expectedType.IsKnownType(KnownTypeCode.Int64)) { action = "clip64"; } else if (expectedType.IsKnownType(KnownTypeCode.UInt64)) { action = "clipu64"; } else { throw new ArgumentException("Can not narrow to " + expectedType, "expectedType"); } block.Write(JS.Types.System.Int64.NAME + "."); block.Write(action); if (!(expression is CastExpression && ((CastExpression)expression).Expression is ParenthesizedExpression)) { block.Write("("); block.AfterOutput += ")"; } } }
protected void VisitIdentifierExpression() { IdentifierExpression identifierExpression = this.IdentifierExpression; int pos = this.Emitter.Output.Length; ResolveResult resolveResult = null; resolveResult = this.Emitter.Resolver.ResolveNode(identifierExpression, this.Emitter); var id = identifierExpression.Identifier; var isResolved = resolveResult != null && !(resolveResult is ErrorResolveResult); var memberResult = resolveResult as MemberResolveResult; if (this.Emitter.Locals != null && this.Emitter.Locals.ContainsKey(id)) { if (this.Emitter.LocalsMap != null && this.Emitter.LocalsMap.ContainsKey(id) && !(identifierExpression.Parent is DirectionExpression)) { this.Write(this.Emitter.LocalsMap[id]); } else if (this.Emitter.LocalsNamesMap != null && this.Emitter.LocalsNamesMap.ContainsKey(id)) { this.Write(this.Emitter.LocalsNamesMap[id]); } else { this.Write(id); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); return; } if (resolveResult is TypeResolveResult) { this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); /* * if (this.Emitter.Validator.IsIgnoreType(resolveResult.Type.GetDefinition())) * { * this.Write(BridgeTypes.ToJsName(resolveResult.Type, this.Emitter)); * } * else * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(resolveResult.Type, this.Emitter) + ")"); * }*/ return; } string inlineCode = memberResult != null?this.Emitter.GetInline(memberResult.Member) : null; bool hasInline = !string.IsNullOrEmpty(inlineCode); bool hasThis = hasInline && inlineCode.Contains("{this}"); if (hasThis) { this.Write(""); var oldBuilder = this.Emitter.Output; this.Emitter.Output = new StringBuilder(); if (memberResult.Member.IsStatic) { this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); /* * if (!this.Emitter.Validator.IsIgnoreType(memberResult.Member.DeclaringTypeDefinition)) * { * this.Write("(Bridge.get(" + BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter) + "))"); * } * else * { * this.Write(BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter)); * }*/ } else { this.WriteThis(); } inlineCode = inlineCode.Replace("{this}", this.Emitter.Output.ToString()); this.Emitter.Output = oldBuilder; if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } return; } if (hasInline && memberResult.Member.IsStatic) { if (resolveResult is InvocationResolveResult) { this.PushWriter(inlineCode); } else { this.Write(inlineCode); } } string appendAdditionalCode = null; if (memberResult != null && memberResult.Member is IMethod && !(memberResult is InvocationResolveResult) && !( identifierExpression.Parent is InvocationExpression && identifierExpression.NextSibling != null && identifierExpression.NextSibling.Role is TokenRole && ((TokenRole)identifierExpression.NextSibling.Role).Token == "(" ) ) { var resolvedMethod = (IMethod)memberResult.Member; bool isStatic = resolvedMethod != null && resolvedMethod.IsStatic; if (!isStatic) { var isExtensionMethod = resolvedMethod.IsExtensionMethod; this.Write(Bridge.Translator.Emitter.ROOT + "." + (isExtensionMethod ? Bridge.Translator.Emitter.DELEGATE_BIND_SCOPE : Bridge.Translator.Emitter.DELEGATE_BIND) + "("); this.WriteThis(); this.Write(", "); appendAdditionalCode = ")"; } } if (memberResult != null && memberResult.Member.SymbolKind == SymbolKind.Property && memberResult.TargetResult.Type.Kind != TypeKind.Anonymous) { bool isStatement = false; string valueVar = null; if (this.Emitter.IsUnaryAccessor) { isStatement = identifierExpression.Parent is UnaryOperatorExpression && identifierExpression.Parent.Parent is ExpressionStatement; if (NullableType.IsNullable(memberResult.Type)) { isStatement = false; } if (!isStatement) { this.WriteOpenParentheses(); valueVar = this.GetTempVarName(); this.Write(valueVar); this.Write(" = "); } } this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (Helpers.IsFieldProperty(memberResult.Member, this.Emitter)) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); } else if (!this.Emitter.IsAssignment) { if (this.Emitter.IsUnaryAccessor) { bool isDecimal = Helpers.IsDecimalType(memberResult.Member.ReturnType, this.Emitter.Resolver); bool isNullable = NullableType.IsNullable(memberResult.Member.ReturnType); if (isStatement) { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); 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.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteCloseParentheses(); } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteDot(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.PostIncrement) { this.Write("inc"); } else { this.Write("dec"); } this.WriteOpenParentheses(); this.WriteCloseParentheses(); } } else { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); 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(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); this.WriteComma(); this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true)); this.WriteOpenParentheses(); 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.WriteOpenParentheses(); this.WriteCloseParentheses(); } } 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(); if (this.Emitter.UnaryOperatorType == UnaryOperatorType.Increment || this.Emitter.UnaryOperatorType == UnaryOperatorType.Decrement) { this.WriteTarget(memberResult); this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false)); this.WriteOpenParentheses(); this.WriteCloseParentheses(); } else { this.Write(valueVar); } this.WriteCloseParentheses(); if (valueVar != null) { this.RemoveTempVar(valueVar); } } } else { this.Write(Helpers.GetPropertyRef(memberResult.Member, this.Emitter)); this.WriteOpenParentheses(); if (!memberResult.Member.IsStatic && memberResult.Member.IsInternalMember()) { this.WriteThis(); } this.WriteCloseParentheses(); } } else if (this.Emitter.AssignmentType != AssignmentOperatorType.Assign) { this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + "({0})"); /* * string trg; * * if (memberResult.Member.IsStatic) * { * trg = BridgeTypes.ToJsName(memberResult.Member.DeclaringType, this.Emitter); * } * else * { * trg = "this"; * } * * this.PushWriter(string.Concat(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true), * "(", * trg, * ".", * Helpers.GetPropertyRef(memberResult.Member, this.Emitter, false), * "()", * "{0})"));*/ } else { string argsFormatStr; if (!memberResult.Member.IsStatic && memberResult.Member.DeclaringType == TransformCtx.CurClass) { argsFormatStr = "(this, {0})"; } else { argsFormatStr = "({0})"; } this.PushWriter(Helpers.GetPropertyRef(memberResult.Member, this.Emitter, true) + argsFormatStr); } } else if (memberResult != null && memberResult.Member is DefaultResolvedEvent) { if (this.Emitter.IsAssignment && (this.Emitter.AssignmentType == AssignmentOperatorType.Add || this.Emitter.AssignmentType == AssignmentOperatorType.Subtract)) { this.WriteTarget(memberResult); if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else { this.Write(this.Emitter.AssignmentType == AssignmentOperatorType.Add ? "add" : "remove"); this.Write( OverloadsCollection.Create(this.Emitter, memberResult.Member, this.Emitter.AssignmentType == AssignmentOperatorType.Subtract).GetOverloadName()); } this.WriteOpenParentheses(); } else { this.WriteTarget(memberResult); this.Write(this.Emitter.GetEntityName(memberResult.Member, true)); } } else { if (!string.IsNullOrWhiteSpace(inlineCode)) { this.Write(inlineCode); } else if (isResolved) { if (resolveResult is TypeResolveResult) { var typeResolveResult = (TypeResolveResult)resolveResult; this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); /* * var isNative = this.Emitter.Validator.IsIgnoreType(typeResolveResult.Type.GetDefinition()); * if (!isNative) * { * this.Write("Bridge.get(" + BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); * } * else * { * this.Write(BridgeTypes.ToJsName(typeResolveResult.Type, this.Emitter)); * }*/ if (typeResolveResult.Type.TypeParameterCount > 0) { this.WriteOpenParentheses(); new TypeExpressionListBlock(this.Emitter, this.IdentifierExpression.TypeArguments).Emit(); this.WriteCloseParentheses(); } /* * if (!isNative) * { * this.Write(")"); * }*/ } else if (resolveResult is LocalResolveResult) { if (resolveResult.IsCompileTimeConstant) { this.Write(resolveResult.ConstantValue); } else { var localResolveResult = (LocalResolveResult)resolveResult; this.Write(localResolveResult.Variable.Name); } } else if (memberResult != null) { if (this.Emitter.IsMemberConst(memberResult.Member)) { this.Write(memberResult.ConstantValue); } else { this.WriteTarget(memberResult); this.Write(OverloadsCollection.Create(this.Emitter, memberResult.Member).GetOverloadName()); } } else { this.Write(resolveResult.ToString()); } } else { throw new EmitterException(identifierExpression, "Cannot resolve identifier: " + id); } } if (appendAdditionalCode != null) { this.Write(appendAdditionalCode); } Helpers.CheckValueTypeClone(resolveResult, identifierExpression, this, pos); }
public static void ClipInteger(ConversionBlock block, Expression expression, IType type, bool isExplicit) { var specialType = NullableType.IsNullable(type) ? NullableType.GetUnderlyingType(type) : type; if (!isExplicit && (specialType.IsKnownType(KnownTypeCode.UInt64) || specialType.IsKnownType(KnownTypeCode.Int64))) { //expression.AcceptVisitor(block.Emitter); return; } NarrowingNumericOrEnumerationConversion(block, expression, specialType, false, false, NullableType.IsNullable(type), isExplicit); }
public static string ToTypeScriptName(IType type, IEmitter emitter, bool asDefinition = false, bool excludens = false, bool ignoreDependency = false, List <string> guard = null) { if (type.Kind == TypeKind.Delegate) { if (guard == null) { guard = new List <string>(); } if (guard.Contains(type.FullName)) { return("Function"); } guard.Add(type.FullName); var method = type.GetDelegateInvokeMethod(); StringBuilder sb = new StringBuilder(); sb.Append("{"); sb.Append("("); var last = method.Parameters.LastOrDefault(); foreach (var p in method.Parameters) { var ptype = BridgeTypes.ToTypeScriptName(p.Type, emitter, guard: guard); if (p.IsOut || p.IsRef) { ptype = "{v: " + ptype + "}"; } sb.Append(p.Name + ": " + ptype); if (p != last) { sb.Append(", "); } } sb.Append(")"); sb.Append(": "); sb.Append(BridgeTypes.ToTypeScriptName(method.ReturnType, emitter, guard: guard)); sb.Append("}"); guard.Remove(type.FullName); return(sb.ToString()); } var oname = ObjectLiteralSignature(type, emitter); if (oname != null) { return(oname); } if (type.IsKnownType(KnownTypeCode.String)) { return("string"); } if (type.IsKnownType(KnownTypeCode.Boolean)) { return("boolean"); } if (type.IsKnownType(KnownTypeCode.Void)) { return("void"); } if (type.IsKnownType(KnownTypeCode.Array)) { return("any[]"); } if (type.IsKnownType(KnownTypeCode.Byte) || type.IsKnownType(KnownTypeCode.Char) || type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Int16) || type.IsKnownType(KnownTypeCode.Int32) || type.IsKnownType(KnownTypeCode.SByte) || type.IsKnownType(KnownTypeCode.Single) || type.IsKnownType(KnownTypeCode.UInt16) || type.IsKnownType(KnownTypeCode.UInt32)) { return("number"); } if (type.Kind == TypeKind.Array) { ICSharpCode.NRefactory.TypeSystem.ArrayType arrayType = (ICSharpCode.NRefactory.TypeSystem.ArrayType)type; return(BridgeTypes.ToTypeScriptName(arrayType.ElementType, emitter, asDefinition, excludens, guard: guard) + "[]"); } if (type.Kind == TypeKind.Dynamic || type.IsKnownType(KnownTypeCode.Object)) { return("any"); } if (type.Kind == TypeKind.Enum && type.DeclaringType != null && !excludens) { return("number"); } if (NullableType.IsNullable(type)) { return(BridgeTypes.ToTypeScriptName(NullableType.GetUnderlyingType(type), emitter, asDefinition, excludens, guard: guard)); } BridgeType bridgeType = emitter.BridgeTypes.Get(type, true); //string name = BridgeTypes.ConvertName(excludens ? type.Name : type.FullName); var name = excludens ? "" : type.Namespace; var hasTypeDef = bridgeType != null && bridgeType.TypeDefinition != null; bool isNested = false; if (hasTypeDef) { var typeDef = bridgeType.TypeDefinition; if (typeDef.IsNested && !excludens) { //name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(emitter, typeDef); name = BridgeTypes.ToJsName(typeDef.DeclaringType, emitter, true, ignoreVirtual: true); isNested = true; } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(emitter.GetTypeName(bridgeType.Type.GetDefinition(), typeDef)); } else { if (type.DeclaringType != null && !excludens) { //name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.GetParentNames(emitter, type); name = BridgeTypes.ToJsName(type.DeclaringType, emitter, true, ignoreVirtual: true); if (type.DeclaringType.TypeArguments.Count > 0) { name += Helpers.PrefixDollar(type.TypeArguments.Count); } isNested = true; } name = (string.IsNullOrEmpty(name) ? "" : (name + ".")) + BridgeTypes.ConvertName(type.Name); } bool isCustomName = false; if (bridgeType != null) { if (!ignoreDependency && emitter.AssemblyInfo.OutputBy != OutputBy.Project && bridgeType.TypeInfo != null && bridgeType.TypeInfo.Namespace != emitter.TypeInfo.Namespace) { var info = BridgeTypes.GetNamespaceFilename(bridgeType.TypeInfo, emitter); var ns = info.Item1; var fileName = info.Item2; if (!emitter.CurrentDependencies.Any(d => d.DependencyName == fileName)) { emitter.CurrentDependencies.Add(new ModuleDependency() { DependencyName = fileName }); } } name = BridgeTypes.GetCustomName(name, bridgeType, excludens, isNested, ref isCustomName, null); } if (!hasTypeDef && !isCustomName && type.TypeArguments.Count > 0) { name += Helpers.PrefixDollar(type.TypeArguments.Count); } if (!asDefinition && type.TypeArguments.Count > 0 && !Helpers.IsIgnoreGeneric(type, emitter, true)) { StringBuilder sb = new StringBuilder(name); bool needComma = false; sb.Append("<"); foreach (var typeArg in type.TypeArguments) { if (needComma) { sb.Append(","); } needComma = true; sb.Append(BridgeTypes.ToTypeScriptName(typeArg, emitter, asDefinition, excludens, guard: guard)); } sb.Append(">"); name = sb.ToString(); } return(name); }
public static void FloatToInt(ConversionBlock block, Expression expression, IType sourceType, IType targetType, bool isChecked) { NarrowingNumericOrEnumerationConversion(block, expression, NullableType.IsNullable(targetType) ? NullableType.GetUnderlyingType(targetType) : targetType, true, isChecked, NullableType.IsNullable(sourceType)); }
private void HandleDecimal(ResolveResult resolveOperator) { if (this.AssignmentExpression.Operator == AssignmentOperatorType.Assign) { new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Right }, null).Emit(); return; } var orr = resolveOperator as OperatorResolveResult; var method = orr != null ? orr.UserDefinedOperatorMethod : null; var assigmentType = Helpers.TypeOfAssignment(this.AssignmentExpression.Operator); if (orr != null && method == null) { var name = Helpers.GetBinaryOperatorMethodName(assigmentType); var type = NullableType.IsNullable(orr.Type) ? NullableType.GetUnderlyingType(orr.Type) : orr.Type; method = type.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault(); } if (method != null) { var inline = this.Emitter.GetInline(method); if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable."); string action = "lift2"; string op_name = null; switch (assigmentType) { case BinaryOperatorType.GreaterThan: op_name = "gt"; break; case BinaryOperatorType.GreaterThanOrEqual: op_name = "gte"; break; case BinaryOperatorType.Equality: op_name = "equals"; break; case BinaryOperatorType.InEquality: op_name = "ne"; break; case BinaryOperatorType.LessThan: op_name = "lt"; break; case BinaryOperatorType.LessThanOrEqual: op_name = "lte"; break; case BinaryOperatorType.Add: op_name = "add"; break; case BinaryOperatorType.Subtract: op_name = "sub"; break; case BinaryOperatorType.Multiply: op_name = "mul"; break; case BinaryOperatorType.Divide: op_name = "div"; break; case BinaryOperatorType.Modulus: op_name = "mod"; break; default: throw new ArgumentOutOfRangeException(); } this.Write(action); this.WriteOpenParentheses(); this.WriteScript(op_name); this.WriteComma(); new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null).Emit(); this.WriteCloseParentheses(); } else if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, this.AssignmentExpression, orr, method), inline).Emit(); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); this.WriteOpenParentheses(); new ExpressionListBlock(this.Emitter, new Expression[] { this.AssignmentExpression.Left, this.AssignmentExpression.Right }, null).Emit(); this.WriteCloseParentheses(); } } }
protected void VisitUnaryOperatorExpression() { var unaryOperatorExpression = this.UnaryOperatorExpression; var oldType = this.Emitter.UnaryOperatorType; var oldAccessor = this.Emitter.IsUnaryAccessor; var resolveOperator = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression, this.Emitter); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } if (this.ResolveOperator(unaryOperatorExpression, orr)) { return; } var op = unaryOperatorExpression.Operator; var argResolverResult = this.Emitter.Resolver.ResolveNode(unaryOperatorExpression.Expression, this.Emitter); bool nullable = NullableType.IsNullable(argResolverResult.Type); if (nullable) { if (op != UnaryOperatorType.Increment && op != UnaryOperatorType.Decrement && op != UnaryOperatorType.PostIncrement && op != UnaryOperatorType.PostDecrement) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable."); } } bool isAccessor = false; var memberArgResolverResult = argResolverResult as MemberResolveResult; if (memberArgResolverResult != null && memberArgResolverResult.Member is IProperty) { isAccessor = true; } else if (argResolverResult is ArrayAccessResolveResult) { isAccessor = ((ArrayAccessResolveResult)argResolverResult).Indexes.Count > 1; } this.Emitter.UnaryOperatorType = op; if (isAccessor && (op == UnaryOperatorType.Increment || op == UnaryOperatorType.Decrement || op == UnaryOperatorType.PostIncrement || op == UnaryOperatorType.PostDecrement)) { this.Emitter.IsUnaryAccessor = true; if (nullable) { this.Write("(Bridge.hasValue("); this.Emitter.IsUnaryAccessor = false; unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); this.Emitter.IsUnaryAccessor = true; unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } this.Emitter.IsUnaryAccessor = oldAccessor; } else { switch (op) { case UnaryOperatorType.BitNot: if (nullable) { this.Write("bnot("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { this.Write("~"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Decrement: if (nullable) { this.Write("(Bridge.hasValue("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? --"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { this.Write("--"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Increment: if (nullable) { this.Write("(Bridge.hasValue("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? ++"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(" : null)"); } else { this.Write("++"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Minus: if (nullable) { this.Write("neg("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { this.Write("-"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Not: if (nullable) { this.Write("not("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { this.Write("!"); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.Plus: if (nullable) { this.Write("pos("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(")"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); } break; case UnaryOperatorType.PostDecrement: if (nullable) { this.Write("(Bridge.hasValue("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("-- : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("--"); } break; case UnaryOperatorType.PostIncrement: if (nullable) { this.Write("(Bridge.hasValue("); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write(") ? "); unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("++ : null)"); } else { unaryOperatorExpression.Expression.AcceptVisitor(this.Emitter); this.Write("++"); } break; case UnaryOperatorType.Await: if (this.Emitter.ReplaceAwaiterByVar) { var index = System.Array.IndexOf(this.Emitter.AsyncBlock.AwaitExpressions, unaryOperatorExpression.Expression) + 1; this.Write("$taskResult" + index); } else { var oldValue = this.Emitter.ReplaceAwaiterByVar; var oldAsyncExpressionHandling = this.Emitter.AsyncExpressionHandling; if (this.Emitter.IsAsync && !this.Emitter.AsyncExpressionHandling) { this.WriteAwaiters(unaryOperatorExpression.Expression); this.Emitter.ReplaceAwaiterByVar = true; this.Emitter.AsyncExpressionHandling = true; } this.WriteAwaiter(unaryOperatorExpression.Expression); this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = oldAsyncExpressionHandling; } break; default: throw new EmitterException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString()); } } this.Emitter.UnaryOperatorType = oldType; }
protected void VisitAssignmentExpression() { AssignmentExpression assignmentExpression = this.AssignmentExpression; var oldAssigment = this.Emitter.IsAssignment; var oldAssigmentType = this.Emitter.AssignmentType; string variable = null; bool needReturnValue = !(assignmentExpression.Parent is ExpressionStatement); if (needReturnValue && assignmentExpression.Parent is LambdaExpression) { var lambdarr = this.Emitter.Resolver.ResolveNode(assignmentExpression.Parent, this.Emitter) as LambdaResolveResult; if (lambdarr != null && lambdarr.ReturnType.Kind == TypeKind.Void) { needReturnValue = false; } } var delegateAssigment = false; bool isEvent = false; var initCount = this.Emitter.Writers.Count; var asyncExpressionHandling = this.Emitter.AsyncExpressionHandling; this.WriteAwaiters(assignmentExpression.Left); this.WriteAwaiters(assignmentExpression.Right); var leftResolverResult = this.Emitter.Resolver.ResolveNode(assignmentExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(assignmentExpression.Right, this.Emitter); var rr = this.Emitter.Resolver.ResolveNode(assignmentExpression, this.Emitter); var orr = rr as OperatorResolveResult; bool isDecimal = Helpers.IsDecimalType(rr.Type, this.Emitter.Resolver); bool isLong = Helpers.Is64Type(rr.Type, this.Emitter.Resolver); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isLongExpected = Helpers.Is64Type(expectedType, this.Emitter.Resolver); bool isUserOperator = this.IsUserOperator(orr); bool isUint = rr.Type.IsKnownType(KnownTypeCode.UInt16) || rr.Type.IsKnownType(KnownTypeCode.UInt32) || rr.Type.IsKnownType(KnownTypeCode.UInt64); var charToString = -1; if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { for (int i = 0; i < orr.Operands.Count; i++) { var crr = orr.Operands[i] as ConversionResolveResult; if (crr != null && crr.Input.Type.IsKnownType(KnownTypeCode.Char)) { charToString = i; } } } var memberTargetrr = leftResolverResult as MemberResolveResult; bool isField = (memberTargetrr != null && memberTargetrr.Member is IField && (memberTargetrr.TargetResult is ThisResolveResult || memberTargetrr.TargetResult is LocalResolveResult)) || leftResolverResult is ThisResolveResult || leftResolverResult is LocalResolveResult || leftResolverResult is ConstantResolveResult; var rightMemberTargetrr = rightResolverResult as MemberResolveResult; bool isRightSimple = (rightMemberTargetrr != null && rightMemberTargetrr.Member is IField && (rightMemberTargetrr.TargetResult is ThisResolveResult || rightMemberTargetrr.TargetResult is LocalResolveResult)) || rightResolverResult is ThisResolveResult || rightResolverResult is LocalResolveResult || rightResolverResult is ConstantResolveResult; var needTempVar = needReturnValue && (!isRightSimple && !isField || assignmentExpression.Operator != AssignmentOperatorType.Assign); /*if (assignmentExpression.Operator == AssignmentOperatorType.Any) * { * needTempVar = false; * }*/ if (needReturnValue) { if (needTempVar) { variable = this.GetTempVarName(); this.Write("(" + variable + " = "); var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Write(", "); } else { this.Write("("); } } if (assignmentExpression.Operator == AssignmentOperatorType.Divide && this.Emitter.Rules.Integer == IntegerRule.Managed && !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, assignmentExpression)) && !isLong && !isLongExpected && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), this.Emitter.Resolver)) )) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; this.Write(JS.Types.BRIDGE_INT + "." + JS.Funcs.Math.DIV + "("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Write(")"); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needReturnValue && !isField) { if (needTempVar) { this.Write(", " + variable); } else { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } } if (needReturnValue) { this.Write(")"); } return; } if (assignmentExpression.Operator == AssignmentOperatorType.Multiply && this.Emitter.Rules.Integer == IntegerRule.Managed && !(this.Emitter.IsJavaScriptOverflowMode && !ConversionBlock.InsideOverflowContext(this.Emitter, assignmentExpression)) && !isLong && !isLongExpected && ( (Helpers.IsInteger32Type(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(rightResolverResult.Type, this.Emitter.Resolver) && Helpers.IsInteger32Type(rr.Type, this.Emitter.Resolver)) || (Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Left), this.Emitter.Resolver) && Helpers.IsInteger32Type(this.Emitter.Resolver.Resolver.GetExpectedType(assignmentExpression.Right), this.Emitter.Resolver) && Helpers.IsInteger32Type(rr.Type, this.Emitter.Resolver)) )) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; var oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; isUint = NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.UInt32); this.Write(JS.Types.BRIDGE_INT + "." + (isUint ? JS.Funcs.Math.UMUL : JS.Funcs.Math.MUL) + "("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); oldValue1 = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; assignmentExpression.Right.AcceptVisitor(this.Emitter); if (ConversionBlock.IsInCheckedContext(this.Emitter, assignmentExpression)) { this.Write(", 1"); } this.Write(")"); this.Emitter.ReplaceAwaiterByVar = oldValue1; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needReturnValue && !isField) { if (needTempVar) { this.Write(", " + variable); } else { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } } if (needReturnValue) { this.Write(")"); } return; } bool templateDelegateAssigment = false; if (assignmentExpression.Operator == AssignmentOperatorType.Add || assignmentExpression.Operator == AssignmentOperatorType.Subtract) { var add = assignmentExpression.Operator == AssignmentOperatorType.Add; if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult)) { delegateAssigment = true; var leftMemberResolveResult = leftResolverResult as MemberResolveResult; if (leftMemberResolveResult != null) { isEvent = leftMemberResolveResult.Member is IEvent; this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = assignmentExpression.Operator; templateDelegateAssigment = !string.IsNullOrWhiteSpace(this.Emitter.GetInline(leftMemberResolveResult.Member)); this.Emitter.IsAssignment = false; } if (!isEvent) { this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = AssignmentOperatorType.Assign; this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); this.Emitter.IsAssignment = false; if (this.Emitter.Writers.Count == initCount) { this.Write(" = "); } this.Write(add ? JS.Funcs.BRIDGE_COMBINE : JS.Funcs.BRIDGE_REMOVE); this.WriteOpenParentheses(); } } } bool nullable = orr != null && orr.IsLiftedOperator; string root = JS.Types.SYSTEM_NULLABLE + "."; bool special = nullable; this.Emitter.IsAssignment = true; this.Emitter.AssignmentType = assignmentExpression.Operator; var oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; bool thisAssignment = leftResolverResult is ThisResolveResult; if (!thisAssignment) { if (special || (isDecimal && isDecimalExpected) || (isLong && isLongExpected) || isUserOperator) { this.Emitter.AssignmentType = AssignmentOperatorType.Assign; } if (delegateAssigment && !isEvent) { this.Emitter.IsAssignment = false; } this.AcceptLeftExpression(assignmentExpression.Left, memberTargetrr); if (delegateAssigment) { this.Emitter.IsAssignment = true; } } else { this.Write("("); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AssignmentType = oldAssigmentType; this.Emitter.IsAssignment = oldAssigment; if (this.Emitter.Writers.Count == initCount && !delegateAssigment && !thisAssignment) { this.WriteSpace(); } if (isDecimal && isDecimalExpected) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.HandleDecimal(rr, variable); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } this.Emitter.ReplaceAwaiterByVar = oldValue; return; } if (isLong && isLongExpected) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; this.HandleLong(rr, variable, isUint); if (this.Emitter.Writers.Count > initCount) { this.PopWriter(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } this.Emitter.ReplaceAwaiterByVar = oldValue; return; } if (this.ResolveOperator(assignmentExpression, orr, initCount, thisAssignment)) { if (thisAssignment) { this.Write(")." + JS.Funcs.CLONE + "(this)"); } else if (needReturnValue) { this.Write(")"); } return; } bool isBool = NullableType.IsNullable(rr.Type) ? NullableType.GetUnderlyingType(rr.Type).IsKnownType(KnownTypeCode.Boolean) : rr.Type.IsKnownType(KnownTypeCode.Boolean); if (!delegateAssigment) { if (!special) { switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: this.Write("+"); break; case AssignmentOperatorType.BitwiseAnd: if (!isBool) { this.Write("&"); } break; case AssignmentOperatorType.BitwiseOr: if (!isBool) { this.Write("|"); } break; case AssignmentOperatorType.Divide: this.Write("/"); break; case AssignmentOperatorType.ExclusiveOr: this.Write("^"); break; case AssignmentOperatorType.Modulus: this.Write("%"); break; case AssignmentOperatorType.Multiply: this.Write("*"); break; case AssignmentOperatorType.ShiftLeft: this.Write("<<"); break; case AssignmentOperatorType.ShiftRight: this.Write(isUint ? ">>>" : ">>"); break; case AssignmentOperatorType.Subtract: this.Write("-"); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } } if (special) { if (this.Emitter.Writers.Count == initCount) { this.Write("= "); } this.Write(root); switch (assignmentExpression.Operator) { case AssignmentOperatorType.Assign: break; case AssignmentOperatorType.Add: this.Write(JS.Funcs.Math.ADD); break; case AssignmentOperatorType.BitwiseAnd: this.Write(isBool ? JS.Funcs.Math.AND : JS.Funcs.Math.BAND); break; case AssignmentOperatorType.BitwiseOr: this.Write(isBool ? JS.Funcs.Math.OR : JS.Funcs.Math.BOR); break; case AssignmentOperatorType.Divide: this.Write(JS.Funcs.Math.DIV); break; case AssignmentOperatorType.ExclusiveOr: this.Write(JS.Funcs.Math.XOR); break; case AssignmentOperatorType.Modulus: this.Write(JS.Funcs.Math.MOD); break; case AssignmentOperatorType.Multiply: this.Write(JS.Funcs.Math.MUL); break; case AssignmentOperatorType.ShiftLeft: this.Write(JS.Funcs.Math.SL); break; case AssignmentOperatorType.ShiftRight: this.Write(isUint ? JS.Funcs.Math.SRR : JS.Funcs.Math.SR); break; case AssignmentOperatorType.Subtract: this.Write(JS.Funcs.Math.SUB); break; default: throw new EmitterException(assignmentExpression, "Unsupported assignment operator: " + assignmentExpression.Operator.ToString()); } this.WriteOpenParentheses(); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); } if (this.Emitter.Writers.Count == initCount && !thisAssignment && !special) { this.Write("= "); } } else if (!isEvent) { this.WriteComma(); } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr)) { this.Write("!!("); assignmentExpression.Left.AcceptVisitor(this.Emitter); this.Write(assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd ? " & " : " | "); } oldValue = this.Emitter.ReplaceAwaiterByVar; this.Emitter.ReplaceAwaiterByVar = true; if (charToString == 1) { this.Write(JS.Funcs.STRING_FROMCHARCODE + "("); } if (needTempVar) { int pos = this.Emitter.Output.Length; this.Write(variable); Helpers.CheckValueTypeClone(rr, assignmentExpression.Right, this, pos); } else { var wrap = assignmentExpression.Operator != AssignmentOperatorType.Assign && this.Emitter.Writers.Count > initCount && !AssigmentExpressionHelper.CheckIsRightAssigmentExpression(assignmentExpression); if (wrap) { this.WriteOpenParentheses(); } assignmentExpression.Right.AcceptVisitor(this.Emitter); if (wrap) { this.WriteCloseParentheses(); } } if (!special && isBool && (assignmentExpression.Operator == AssignmentOperatorType.BitwiseAnd || assignmentExpression.Operator == AssignmentOperatorType.BitwiseOr)) { this.WriteCloseParentheses(); } if (charToString == 1) { this.WriteCloseParentheses(); } if (special) { this.WriteCloseParentheses(); } if (thisAssignment) { this.Write(")." + JS.Funcs.CLONE + "(this)"); } this.Emitter.ReplaceAwaiterByVar = oldValue; this.Emitter.AsyncExpressionHandling = asyncExpressionHandling; if (this.Emitter.Writers.Count > initCount) { var writerCount = this.Emitter.Writers.Count; for (int i = initCount; i < writerCount; i++) { this.PopWriter(); } } if (delegateAssigment && !templateDelegateAssigment) { this.WriteCloseParentheses(); } if (needTempVar) { this.Write(", " + variable + ")"); } else if (needReturnValue) { if (!isField) { this.Write(", "); this.Emitter.IsAssignment = false; assignmentExpression.Right.AcceptVisitor(this.Emitter); this.Emitter.IsAssignment = oldAssigment; } this.Write(")"); } }