public JsNode VisitOperatorResolveResult(OperatorResolveResult res) { if (res.Operands.Count == 1) { return(Unary(res)); } else if (res.Operands.Count == 2) { res = WorkaroundIssue501(res); var node2 = Binary(res); if (Importer.ForceIntegers) { if (Importer.IsInteger(res.Type) && res.OperatorType == ExpressionType.Divide) { node2 = Importer.ForceInteger(node2); } } return(node2); } else if (res.Operands.Count == 3) { return(Trinary(res)); } else { throw new NotImplementedException(); } }
/// <summary> /// Wraps a setter invocation with a js function that returns the setter value back, if another assignment operation occurs /// var x = contact.Name = "Shooki"; /// var x = contact.setName("Shooki"); //error /// var x = (function(arg){contact.setName(arg);return arg;}).call(this, "Shooki"); /// </summary> /// <param name="res"></param> /// <param name="node2"></param> /// <returns></returns> private JNode WrapSetterToReturnValueIfNeeded(OperatorResolveResult res, JNode node2) { var node3 = node2 as JInvocationExpression; if (node3 == null) { return(node2); } var parent = res.GetParent(Project); if (parent is OperatorResolveResult) { var parentOp = (OperatorResolveResult)parent; if (RequiresWrapSetterToReturnValueIfNeeded(res, parentOp)) { var lastArg = node3.Arguments.Last(); var prmName = "$p" + ParameterNameCounter++; node3.Arguments[node3.Arguments.Count - 1] = J.Member(prmName); var func = J.Function(prmName).Add(((JExpression)node2).Statement()); func.Add(J.Return(J.Member(prmName))); node2 = WrapFunctionAndInvoke(res, func.Block, lastArg); } } return(node2); }
private object GetConstValue(OperatorResolveResult orr, bool isLeft, bool isChar) { var result = isLeft ? orr.Operands.First() : orr.Operands.Last(); if (result.IsCompileTimeConstant) { return(WrapConstValue(result.ConstantValue)); } ConversionResolveResult rr = result as ConversionResolveResult; if (rr != null && rr.Input.IsCompileTimeConstant) { if (isChar) { return(isLeft ? this.BinaryOperatorExpression.Left.ToString() : this.BinaryOperatorExpression.Right.ToString()); } else if (rr.Input.Type.Kind == TypeKind.Enum) { MemberResolveResult reslut = (MemberResolveResult)rr.Input; return("\"" + reslut.Member.Name + "\""); } return(WrapConstValue(rr.Input.ConstantValue)); } return(null); }
public ArgumentsInfo(IEmitter emitter, BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult operatorResolveResult, IMethod method) { Emitter = emitter; Expression = binaryOperatorExpression; OperatorResolveResult = operatorResolveResult; BuildOperatorArgumentsList(new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, operatorResolveResult.UserDefinedOperatorMethod ?? method); BuildOperatorTypedArguments(); }
public ArgumentsInfo(IEmitter emitter, UnaryOperatorExpression unaryOperatorExpression, OperatorResolveResult operatorResolveResult, IMethod method) { Emitter = emitter; Expression = unaryOperatorExpression; OperatorResolveResult = operatorResolveResult; BuildOperatorArgumentsList(new Expression[] { unaryOperatorExpression.Expression }, operatorResolveResult.UserDefinedOperatorMethod ?? method); BuildOperatorTypedArguments(); }
private JsNode Unary(OperatorResolveResult res) { if (res.UserDefinedOperatorMethod != null && !Sk.UseNativeOperatorOverloads(res.UserDefinedOperatorMethod.DeclaringTypeDefinition)) { var fake = Cs.InvokeMethod(res.UserDefinedOperatorMethod, null, res.Operands[0]); return(Visit(fake)); } var isProperty = false; var meRes = res.Operands[0] as MemberResolveResult; if (meRes != null && meRes.Member != null && IsEntityFunctionProperty(meRes.Member, res)) { isProperty = true; } JsExpression node2; if (res.OperatorType.IsAny(ExpressionType.Negate, ExpressionType.PreDecrementAssign, ExpressionType.PreIncrementAssign, ExpressionType.Not, ExpressionType.OnesComplement)) { var simpler = res.OperatorType.ExtractCompoundAssignment(); if (isProperty && simpler != null) { var fakeCs = meRes.ShallowClone().Binary(simpler.Value, Cs.Value(1, Project), meRes.Type); node2 = VisitExpression(fakeCs); } else { node2 = new JsPreUnaryExpression { Operator = Visit(res.OperatorType), Right = VisitExpression(res.Operands[0]) }; } } else if (res.OperatorType.IsAny(ExpressionType.PostIncrementAssign, ExpressionType.PostDecrementAssign, ExpressionType.PreIncrementAssign, ExpressionType.PreDecrementAssign)) { if (isProperty) { var simpler = res.OperatorType.ExtractCompoundAssignment(); var fakeCs = meRes.ShallowClone().Binary(simpler.Value, Cs.Value(1, Project), meRes.Type); node2 = VisitExpression(fakeCs); } else { node2 = new JsPostUnaryExpression { Operator = Visit(res.OperatorType), Left = VisitExpression(res.Operands[0]) }; } } else { throw new NotImplementedException(); } return(node2); }
bool RequiresWrapSetterToReturnValueIfNeeded(OperatorResolveResult op, OperatorResolveResult parentOp) { if (parentOp.OperatorType == System.Linq.Expressions.ExpressionType.Assign) { return(true); } if (parentOp.OperatorType == System.Linq.Expressions.ExpressionType.Conditional && parentOp.Operands.IndexOf(op) > 0) { return(true); } return(false); }
public override JsExpression VisitOperatorResolveResult(OperatorResolveResult rr, object data) { bool isUserDefined = (rr.UserDefinedOperatorMethod != null && _metadataImporter.GetMethodSemantics(rr.UserDefinedOperatorMethod).Type != MethodScriptSemantics.ImplType.NativeOperator); var arguments = new JsExpression[rr.Operands.Count + 1]; for (int i = 0; i < rr.Operands.Count; i++) arguments[i] = VisitResolveResult(rr.Operands[i], null); arguments[arguments.Length - 1] = isUserDefined ? _getMember(rr.UserDefinedOperatorMethod) : _instantiateType(rr.Type); if (rr.OperatorType == ExpressionType.Conditional) return CompileFactoryCall("Condition", new[] { typeof(Expression), typeof(Expression), typeof(Expression), typeof(Type) }, arguments); else { return CompileFactoryCall(rr.OperatorType.ToString(), rr.Operands.Count == 1 ? new[] { typeof(Expression), isUserDefined ? typeof(MethodInfo) : typeof(Type) } : new[] { typeof(Expression), typeof(Expression), isUserDefined ? typeof(MethodInfo) : typeof(Type) }, arguments); } }
Value VisitUnaryOperator(OperatorResolveResult result, UnaryOperatorType operatorType, bool checkForOverflow = false) { Debug.Assert(result.Operands.Count == 1); var operand = Convert(result.Operands[0]).ToResolveResult(context); CSharpResolver resolver = new CSharpResolver(debuggerTypeSystem).WithCheckForOverflow(checkForOverflow); var val = resolver.ResolveUnaryOperator(operatorType, operand); if (val.IsCompileTimeConstant) { return(Convert(val)); } throw new GetValueException("Operator {0} is not supported for {1}!", operatorType, new CSharpAmbience().ConvertType(operand.Type)); }
private JsNode Trinary(OperatorResolveResult res) { if (res.OperatorType == ExpressionType.Conditional) { var node5 = new JsConditionalExpression { Condition = VisitExpression(res.Operands[0]), TrueExpression = VisitExpression(res.Operands[1]), FalseExpression = VisitExpression(res.Operands[2]) }; return(node5); } else { throw new NotImplementedException(); } }
private void VisitStringConcat(OperatorResolveResult orr, bool isLeft, bool isChar) { object constValue = GetConstValue(orr, isLeft, isChar); if (constValue != null) { this.Write(constValue); } else { var express = isLeft ? this.BinaryOperatorExpression.Left : this.BinaryOperatorExpression.Right; if (isChar) { this.Write("string.char"); this.WriteOpenParentheses(); express.AcceptVisitor(this.Emitter); this.WriteCloseParentheses(); } else if (express is IdentifierExpression || express is InvocationExpression) { var resolverResult = this.Emitter.Resolver.ResolveNode(express, this.Emitter); if (resolverResult.Type.Kind == TypeKind.Struct) { express.AcceptVisitor(this.Emitter); } else if (resolverResult.Type.Kind == TypeKind.Enum) { TransformCtx.ExportEnums.Add(resolverResult.Type); this.Write("System.Enum.toString"); this.WriteOpenParentheses(); express.AcceptVisitor(this.Emitter); this.WriteComma(); string typeName = BridgeTypes.ToJsName(resolverResult.Type, this.Emitter); this.Write(typeName); this.WriteCloseParentheses(); } else { this.Write("System.strconcat"); this.WriteOpenParentheses(); express.AcceptVisitor(this.Emitter); this.WriteCloseParentheses(); } } else { express.AcceptVisitor(this.Emitter); } } }
/// <summary> /// https://github.com/icsharpcode/NRefactory/issues/501 /// </summary> OperatorResolveResult WorkaroundIssue501(OperatorResolveResult res) { if (res.UserDefinedOperatorMethod == null) { return(res); } if ((res.OperatorType == ExpressionType.AndAlso && res.UserDefinedOperatorMethod.Name == "op_BitwiseAnd") || (res.OperatorType == ExpressionType.OrElse && res.UserDefinedOperatorMethod.Name == "op_BitwiseOr")) { var fake = new OperatorResolveResult(res.Type, res.OperatorType, null, res.IsLiftedOperator, res.Operands); return(fake); } return(res); }
Value VisitTernaryOperator(OperatorResolveResult result) { Debug.Assert(result.Operands.Count == 3); var condition = Convert(result.Operands[0]); if (!condition.Type.IsKnownType(KnownTypeCode.Boolean)) { throw new GetValueException("Boolean expression expected!"); } if ((bool)condition.PrimitiveValue) { return(Convert(result.Operands[1])); } return(Convert(result.Operands[2])); }
bool RequiresWrapSetterToReturnValue(OperatorResolveResult op) { var node = op.GetFirstNode(); if (node == null) { return(false); } var parentNode = node.Parent; if (parentNode == null) { return(false); } if (parentNode is ReturnStatement) { return(true); } var parentRes = parentNode.Resolve(); if (parentRes is OperatorResolveResult) { var parentOp = (OperatorResolveResult)parentRes; if (parentOp.OperatorType == ExpressionType.Assign) { return(true); } if (parentOp.OperatorType == ExpressionType.Conditional && parentOp.Operands.IndexOf(op) > 0) { return(true); } return(false); } if (parentRes is LocalResolveResult && parentRes.GetFirstNode() is VariableInitializer) { return(true); } return(false); }
public override string VisitOperatorResolveResult(OperatorResolveResult rr, object data) { bool isUserDefined = rr.UserDefinedOperatorMethod != null && !this._emitter.Validator.IsExternalType(rr.UserDefinedOperatorMethod.DeclaringTypeDefinition); var arguments = new string[rr.Operands.Count + 1]; for (int i = 0; i < rr.Operands.Count; i++) { arguments[i] = VisitResolveResult(rr.Operands[i], null); } arguments[arguments.Length - 1] = isUserDefined ? this.GetMember(rr.UserDefinedOperatorMethod) : ExpressionTreeBuilder.GetTypeName(rr.Type, this._emitter); if (rr.OperatorType == ExpressionType.Conditional) { return(CompileFactoryCall("Condition", new[] { typeof(Expression), typeof(Expression), typeof(Expression), typeof(Type) }, arguments)); } else { return(CompileFactoryCall(rr.OperatorType.ToString(), rr.Operands.Count == 1 ? new[] { typeof(Expression), isUserDefined ? typeof(MethodInfo) : typeof(Type) } : new[] { typeof(Expression), typeof(Expression), isUserDefined ? typeof(MethodInfo) : typeof(Type) }, arguments)); } }
protected bool IsUserOperator(OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { return(true); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { return(true); } } return(false); }
/// <summary> /// Wraps a setter invocation with a js function that returns the setter value back, if another assignment operation occurs /// var x = contact.Name = "Shooki"; /// var x = contact.setName("Shooki"); //error /// var x = (function(arg){contact.setName(arg);return arg;}).call(this, "Shooki"); /// </summary> /// <param name="res"></param> /// <param name="node2"></param> /// <returns></returns> internal JsNode WrapSetterToReturnValueIfNeeded(OperatorResolveResult res, JsNode node2) { var node3 = node2 as JsInvocationExpression; if (node3 == null) { return(node2); } if (RequiresWrapSetterToReturnValue(res)) { var lastArg = node3.Arguments.Last(); var prmName = "$p" + ParameterNameCounter++; node3.Arguments[node3.Arguments.Count - 1] = Js.Member(prmName); var func = Js.Function(prmName).Add(((JsExpression)node2).Statement()); func.Add(Js.Return(Js.Member(prmName))); node2 = WrapFunctionAndInvoke(res, func, lastArg); } return(node2); }
Value VisitConditionalOperator(OperatorResolveResult result, BinaryOperatorType bitwiseOperatorType) { Debug.Assert(result.Operands.Count == 2); var lhs = Convert(result.Operands[0]).GetPermanentReference(evalThread); CSharpResolver resolver = new CSharpResolver(debuggerTypeSystem); Value condVal; if (bitwiseOperatorType == BinaryOperatorType.BitwiseAnd) { condVal = Convert(resolver.ResolveConditionFalse(lhs.ToResolveResult(context))); } else { condVal = Convert(resolver.ResolveCondition(lhs.ToResolveResult(context))); } if ((bool)condVal.PrimitiveValue) { return(lhs); } var rhs = Convert(result.Operands[1]); var val = resolver.ResolveBinaryOperator(bitwiseOperatorType, lhs.ToResolveResult(context), rhs.ToResolveResult(context)); return(Convert(val)); }
protected void VisitBinaryOperatorExpression() { BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression; var resolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; var leftResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter); if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver))) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { this.HandleDecimal(resolveOperator); return; } var delegateOperator = false; if (this.ResolveOperator(binaryOperatorExpression, orr)) { return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver)) )) { this.Write("Bridge.Int.div("); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.Write(", "); binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); this.Write(")"); return; } if (binaryOperatorExpression.Operator == BinaryOperatorType.Add || binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add; if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) && this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult)) { delegateOperator = true; this.Write(Bridge.Translator.Emitter.ROOT + "." + (add ? Bridge.Translator.Emitter.DELEGATE_COMBINE : Bridge.Translator.Emitter.DELEGATE_REMOVE)); this.WriteOpenParentheses(); } } bool nullable = orr != null && orr.IsLiftedOperator; bool isCoalescing = binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing; string root = Bridge.Translator.Emitter.ROOT + ".Nullable."; bool special = nullable || isCoalescing; bool rootSpecial = nullable; if (rootSpecial) { this.Write(root); } else if (isCoalescing) { this.Write(Bridge.Translator.Emitter.ROOT + "."); } else { binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); } if (!delegateOperator) { if (!special) { this.WriteSpace(); } bool isBool = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean); switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: this.Write(rootSpecial ? "add" : "+"); break; case BinaryOperatorType.BitwiseAnd: if (isBool) { this.Write(rootSpecial ? "and" : "&&"); } else { this.Write(rootSpecial ? "band" : "&"); } break; case BinaryOperatorType.BitwiseOr: if (isBool) { this.Write(rootSpecial ? "or" : "||"); } else { this.Write(rootSpecial ? "bor" : "|"); } break; case BinaryOperatorType.ConditionalAnd: this.Write(rootSpecial ? "and" : "&&"); break; case BinaryOperatorType.NullCoalescing: this.Write("coalesce"); break; case BinaryOperatorType.ConditionalOr: this.Write(rootSpecial ? "or" : "||"); break; case BinaryOperatorType.Divide: this.Write(rootSpecial ? "div" : "/"); break; case BinaryOperatorType.Equality: this.Write(rootSpecial ? "eq" : "==="); break; case BinaryOperatorType.ExclusiveOr: this.Write(rootSpecial ? "xor" : "^"); break; case BinaryOperatorType.GreaterThan: this.Write(rootSpecial ? "gt" : ">"); break; case BinaryOperatorType.GreaterThanOrEqual: this.Write(rootSpecial ? "gte" : ">="); break; case BinaryOperatorType.InEquality: this.Write(rootSpecial ? "neq" : "!=="); break; case BinaryOperatorType.LessThan: this.Write(rootSpecial ? "lt" : "<"); break; case BinaryOperatorType.LessThanOrEqual: this.Write(rootSpecial ? "lte" : "<="); break; case BinaryOperatorType.Modulus: this.Write(rootSpecial ? "mod" : "%"); break; case BinaryOperatorType.Multiply: this.Write(rootSpecial ? "mul" : "*"); break; case BinaryOperatorType.ShiftLeft: this.Write(rootSpecial ? "sl" : "<<"); break; case BinaryOperatorType.ShiftRight: this.Write(rootSpecial ? "sr" : ">>"); break; case BinaryOperatorType.Subtract: this.Write(rootSpecial ? "sub" : "-"); break; default: throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString()); } } else { this.WriteComma(); } if (special) { this.WriteOpenParentheses(); binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); this.WriteComma(); } else { this.WriteSpace(); } binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); if (delegateOperator || special) { this.WriteCloseParentheses(); } }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable.lift("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null).Emit(); this.WriteCloseParentheses(); return(true); } } return(false); }
public JsNode VisitOperatorResolveResult(OperatorResolveResult res) { return(new ResolveResultVisitor_Operator { Compiler = Compiler, Importer = this, Project = Project }.VisitOperatorResolveResult(res)); }
public static int CheckConversion(ConversionBlock block, Expression expression) { try { var rr = block.Emitter.Resolver.ResolveNode(expression, block.Emitter); var conversion = block.Emitter.Resolver.Resolver.GetConversion(expression); var expectedType = block.Emitter.Resolver.Resolver.GetExpectedType(expression); var level = ConversionBlock.CheckDecimalConversion(block, expression, rr, expectedType, conversion) ? 1 : 0; if (Helpers.IsDecimalType(expectedType, block.Emitter.Resolver) && !conversion.IsUserDefined) { return(level); } if (conversion == null) { return(level); } if (conversion.IsIdentityConversion) { return(level); } var isNumLifted = conversion.IsImplicit && conversion.IsLifted && conversion.IsNumericConversion && !(expression is BinaryOperatorExpression); if (isNumLifted && !conversion.IsUserDefined) { return(level); } bool isLifted = conversion.IsLifted && !isNumLifted && !(block is CastBlock) && !Helpers.IsDecimalType(expectedType, block.Emitter.Resolver); if (isLifted) { level++; 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(level); } 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(level); } else { if (method.DeclaringTypeDefinition != null && block.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { // Still returns true if Nullable.lift( was written. return(level); } 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(); level++; } var arg = method.Parameters[0]; if (Helpers.IsDecimalType(arg.Type, block.Emitter.Resolver, arg.IsParams) && !Helpers.IsDecimalType(rr.Type, block.Emitter.Resolver) && !expression.IsNull) { block.Write("Bridge.Decimal"); if (NullableType.IsNullable(arg.Type) && ConversionBlock.ShouldBeLifted(expression)) { block.Write(".lift"); } block.WriteOpenParentheses(); level++; } return(level); } // Still returns true if Nullable.lift( was written. return(level); } catch { } return(0); }
public virtual TResult VisitOperatorResolveResult(OperatorResolveResult rr, TData data) { VisitChildResolveResults(rr, data); return(default(TResult)); }
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) { var prop = memberArgResolverResult.Member as IProperty; if (prop != null) { var isIgnore = memberArgResolverResult.Member.DeclaringTypeDefinition != null && this.Emitter.Validator.IsExternalType(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.IsExternalType(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; }
protected bool ResolveOperator(UnaryOperatorExpression unaryOperatorExpression, OperatorResolveResult orr) { if (orr != null && orr.UserDefinedOperatorMethod != null) { var method = orr.UserDefinedOperatorMethod; var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, unaryOperatorExpression, orr, method), inline).Emit(); return(true); } else { if (orr.IsLiftedOperator) { this.Write(JS.Types.SYSTEM_NULLABLE + "." + JS.Funcs.Math.LIFT + "("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] { unaryOperatorExpression.Expression }, null, null, 0).Emit(); this.WriteCloseParentheses(); return(true); } } return(false); }
protected bool ResolveOperator(BinaryOperatorExpression binaryOperatorExpression, OperatorResolveResult orr) { var method = orr != null ? orr.UserDefinedOperatorMethod : null; if (method != null) { var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, binaryOperatorExpression, orr, method), inline).Emit(); return(true); } else if (!this.Emitter.Validator.IsIgnoreType(method.DeclaringTypeDefinition)) { string name = OverloadsCollection.Create(this.Emitter, method).GetOverloadName(); if (Helpers.GetOperatorMapping(name) != null) { return(false); } if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable."); string action = "lift"; switch (this.BinaryOperatorExpression.Operator) { case BinaryOperatorType.GreaterThan: action = "liftcmp"; break; case BinaryOperatorType.GreaterThanOrEqual: action = "liftcmp"; break; case BinaryOperatorType.Equality: action = "lifteq"; break; case BinaryOperatorType.InEquality: action = "liftne"; break; case BinaryOperatorType.LessThan: action = "liftcmp"; break; case BinaryOperatorType.LessThanOrEqual: action = "liftcmp"; break; } this.Write(action + "("); } this.Write(BridgeTypes.ToJsName(method.DeclaringType, this.Emitter)); this.WriteDot(); this.Write(name); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] { binaryOperatorExpression.Left, binaryOperatorExpression.Right }, null).Emit(); this.WriteCloseParentheses(); return(true); } } return(false); }
protected bool ResolveOperator(UnaryOperatorExpression unaryOperatorExpression, OperatorResolveResult orr) { if (orr != null && orr.UserDefinedOperatorMethod != null) { var method = orr.UserDefinedOperatorMethod; var inline = this.Emitter.GetInline(method); if (!string.IsNullOrWhiteSpace(inline)) { new InlineArgumentsBlock(this.Emitter, new ArgumentsInfo(this.Emitter, unaryOperatorExpression, orr), inline).Emit(); return(true); } else { if (orr.IsLiftedOperator) { this.Write(Bridge.Translator.Emitter.ROOT + ".Nullable.lift("); } this.Write(this.Emitter.ShortenTypeName(Helpers.GetScriptFullName(method.DeclaringType))); this.WriteDot(); this.Write(OverloadsCollection.Create(this.Emitter, method).GetOverloadName()); if (orr.IsLiftedOperator) { this.WriteComma(); } else { this.WriteOpenParentheses(); } new ExpressionListBlock(this.Emitter, new Expression[] { unaryOperatorExpression.Expression }, null).Emit(); this.WriteCloseParentheses(); return(true); } } return(false); }
string Visit(OperatorResolveResult result) { throw new NotImplementedException(); }
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 (Exception)this.Emitter.CreateException(unaryOperatorExpression, "Unsupported unary operator: " + unaryOperatorExpression.Operator.ToString()); } } this.Emitter.UnaryOperatorType = oldType; }
protected void VisitBinaryOperatorExpression() { BinaryOperatorExpression binaryOperatorExpression = this.BinaryOperatorExpression; var resolveOperator = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression, this.Emitter); var expectedType = this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression); bool isDecimalExpected = Helpers.IsDecimalType(expectedType, this.Emitter.Resolver); bool isDecimal = Helpers.IsDecimalType(resolveOperator.Type, this.Emitter.Resolver); OperatorResolveResult orr = resolveOperator as OperatorResolveResult; var leftResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Left, this.Emitter); var rightResolverResult = this.Emitter.Resolver.ResolveNode(binaryOperatorExpression.Right, this.Emitter); var charToString = -1; string variable = null; bool leftIsNull = this.BinaryOperatorExpression.Left is NullReferenceExpression; bool rightIsNull = this.BinaryOperatorExpression.Right is NullReferenceExpression; bool isStringConcat = false; /* * if ((leftIsNull || rightIsNull) && (binaryOperatorExpression.Operator == BinaryOperatorType.Equality || binaryOperatorExpression.Operator == BinaryOperatorType.InEquality)) * { * if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) * { * this.Write("!"); * } * * this.Write(LuaHelper.Root,".hasValue"); * * this.WriteOpenParentheses(); * * if (leftIsNull) * { * binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); * } * else * { * binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); * } * * this.WriteCloseParentheses(); * return; * }*/ if (orr != null && orr.Type.IsKnownType(KnownTypeCode.String)) { isStringConcat = true; 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; } } } if (resolveOperator is ConstantResolveResult) { this.WriteScript(((ConstantResolveResult)resolveOperator).ConstantValue); return; } if (!((expectedType.IsKnownType(KnownTypeCode.String) || resolveOperator.Type.IsKnownType(KnownTypeCode.String)) && binaryOperatorExpression.Operator == BinaryOperatorType.Add) && (Helpers.IsDecimalType(leftResolverResult.Type, this.Emitter.Resolver) || Helpers.IsDecimalType(rightResolverResult.Type, this.Emitter.Resolver))) { isDecimal = true; isDecimalExpected = true; } if (isDecimal && isDecimalExpected && binaryOperatorExpression.Operator != BinaryOperatorType.NullCoalescing) { this.HandleDecimal(resolveOperator); return; } var delegateOperator = false; if (this.ResolveOperator(binaryOperatorExpression, orr)) { return; } /* * if (binaryOperatorExpression.Operator == BinaryOperatorType.Divide && * ( * (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && * Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || * * (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && * Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver)) * )) * { * this.Write("{0}.Number.div(".F(LuaHelper.Root)); * binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); * this.Write(", "); * binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); * this.Write(")"); * return; * } */ if (binaryOperatorExpression.Operator == BinaryOperatorType.Add || binaryOperatorExpression.Operator == BinaryOperatorType.Subtract) { var add = binaryOperatorExpression.Operator == BinaryOperatorType.Add; if (this.Emitter.Validator.IsDelegateOrLambda(leftResolverResult) || this.Emitter.Validator.IsDelegateOrLambda(rightResolverResult)) { delegateOperator = true; this.Write(Bridge.Translator.Emitter.ROOT + "." + (add ? Bridge.Translator.Emitter.DELEGATE_COMBINE : Bridge.Translator.Emitter.DELEGATE_REMOVE)); this.WriteOpenParentheses(); } } bool isBool = NullableType.IsNullable(resolveOperator.Type) ? NullableType.GetUnderlyingType(resolveOperator.Type).IsKnownType(KnownTypeCode.Boolean) : resolveOperator.Type.IsKnownType(KnownTypeCode.Boolean); bool isBitwise = (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseAnd && !isBool) || (binaryOperatorExpression.Operator == BinaryOperatorType.BitwiseOr && !isBool) || binaryOperatorExpression.Operator == BinaryOperatorType.ExclusiveOr || binaryOperatorExpression.Operator == BinaryOperatorType.ShiftLeft || binaryOperatorExpression.Operator == BinaryOperatorType.ShiftRight; bool isIntDiv = binaryOperatorExpression.Operator == BinaryOperatorType.Divide && ( (Helpers.IsIntegerType(leftResolverResult.Type, this.Emitter.Resolver) && Helpers.IsIntegerType(rightResolverResult.Type, this.Emitter.Resolver)) || (Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Left), this.Emitter.Resolver) && Helpers.IsIntegerType(this.Emitter.Resolver.Resolver.GetExpectedType(binaryOperatorExpression.Right), this.Emitter.Resolver)) ); bool nullable = orr != null && orr.IsLiftedOperator; bool isCoalescing = binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing; string root = Bridge.Translator.Emitter.ROOT + ".Nullable."; bool special = nullable; bool rootSpecial = nullable; if (!nullable) { if (isBitwise || isIntDiv) { root = Bridge.Translator.Emitter.ROOT + "."; special = true; rootSpecial = true; } } if (rootSpecial) { this.Write(root); } else if (isStringConcat) { VisitStringConcat(orr, true, charToString == 0); } else { if (isCoalescing) { this.Write("("); variable = this.GetTempVarName(); this.Write(variable); this.Write(" = "); } else if (charToString == 0) { this.Write("string.char("); } binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); if (isCoalescing) { this.Write(", {0}.hasValue(".F(LuaHelper.Root)); this.Write(variable); this.Write(") ? "); this.Write(variable); } else if (charToString == 0) { this.Write(")"); } } if (!delegateOperator) { if (!special) { this.WriteSpace(); } bool isUint = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt16) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt32) || resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64); bool is64bit = resolveOperator.Type.IsKnownType(KnownTypeCode.UInt64) || resolveOperator.Type.IsKnownType(KnownTypeCode.Int64); if (isBitwise && is64bit) { throw new EmitterException(this.BinaryOperatorExpression, "Bitwise operations are not allowed on 64-bit types"); } switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: if (isStringConcat) { this.Write(rootSpecial ? "and" : ".."); } else { this.Write(rootSpecial ? "and" : "+"); } break; case BinaryOperatorType.BitwiseAnd: if (isBool) { this.Write(rootSpecial ? "and" : "and"); } else { this.Write(rootSpecial ? "band" : "&"); } break; case BinaryOperatorType.BitwiseOr: if (isBool) { this.Write(rootSpecial ? "or" : "or"); } else { this.Write(rootSpecial ? "bor" : "|"); } break; case BinaryOperatorType.ConditionalAnd: this.Write(rootSpecial ? "and" : "and"); break; case BinaryOperatorType.NullCoalescing: this.Write(":"); break; case BinaryOperatorType.ConditionalOr: this.Write(rootSpecial ? "or" : "or"); break; case BinaryOperatorType.Divide: this.Write(rootSpecial ? "div" : "/"); break; case BinaryOperatorType.Equality: this.Write(rootSpecial ? "eq" : "=="); break; case BinaryOperatorType.ExclusiveOr: this.Write(rootSpecial ? "xor" : "^"); break; case BinaryOperatorType.GreaterThan: this.Write(rootSpecial ? ">" : ">"); break; case BinaryOperatorType.GreaterThanOrEqual: this.Write(rootSpecial ? "gte" : ">="); break; case BinaryOperatorType.InEquality: this.Write(rootSpecial ? "neq" : "~="); break; case BinaryOperatorType.LessThan: this.Write(rootSpecial ? "lt" : "<"); break; case BinaryOperatorType.LessThanOrEqual: this.Write(rootSpecial ? "lte" : "<="); break; case BinaryOperatorType.Modulus: this.Write(rootSpecial ? "mod" : "%"); break; case BinaryOperatorType.Multiply: this.Write(rootSpecial ? "mul" : "*"); break; case BinaryOperatorType.ShiftLeft: this.Write(rootSpecial ? "sl" : "<<"); break; case BinaryOperatorType.ShiftRight: if (isUint) { this.Write(rootSpecial ? "srr" : ">>>"); } else { this.Write(rootSpecial ? "sr" : ">>"); } break; case BinaryOperatorType.Subtract: this.Write(rootSpecial ? "sub" : "-"); break; default: throw new EmitterException(binaryOperatorExpression, "Unsupported binary operator: " + binaryOperatorExpression.Operator.ToString()); } } else { this.WriteComma(); } if (isStringConcat) { this.WriteSpace(); VisitStringConcat(orr, false, charToString == 1); } else { if (special) { this.WriteOpenParentheses(); if (charToString == 0) { this.Write("string.char("); } binaryOperatorExpression.Left.AcceptVisitor(this.Emitter); if (charToString == 0) { this.Write(")"); } this.WriteComma(); } else { this.WriteSpace(); } if (charToString == 1) { this.Write("string.char("); } binaryOperatorExpression.Right.AcceptVisitor(this.Emitter); if (charToString == 1 || isCoalescing) { this.Write(")"); } if (delegateOperator || special) { this.WriteCloseParentheses(); } } }