/// <summary> /// Tries to evaluate an application of a standard arithmetic operator. /// </summary> /// <param name="prototype"> /// The full intrinsic prototype for the arithmetic operator. /// </param> /// <param name="arguments"> /// The operator application's arguments. /// </param> /// <param name="result"> /// The operator application's result, if it can be computed. /// </param> /// <returns> /// <c>true</c> if the operator application can be evaluated; otherwise, /// <c>false</c>. /// </returns> public static bool TryEvaluate( IntrinsicPrototype prototype, IReadOnlyList <Constant> arguments, out Constant result) { string operatorName; bool isChecked; if (!TryParseArithmeticIntrinsicName(prototype.Name, out operatorName, out isChecked)) { throw new InvalidOperationException($"Cannot evaluate non-arithmetic intrinsic '{prototype.Name}'."); } else if (TryEvaluateUnchecked(operatorName, prototype, arguments, out result)) { if (isChecked) { return(result is IntegerConstant && ((IntegerConstant)result).IsValid); } else { return(true); } } else { result = null; return(false); } }
/// <summary> /// Creates a memory intrinsic prototype. /// </summary> /// <param name="operatorName"> /// The name of the operator represented by the memory intrinsic. /// </param> /// <param name="resultType"> /// The type of value produced by the intrinsic to create. /// </param> /// <param name="parameterTypes"> /// The types of the values the intrinsic takes as arguments. /// </param> /// <returns> /// A memory intrinsic prototype. /// </returns> public static IntrinsicPrototype CreatePrototype( string operatorName, IType resultType, IReadOnlyList <IType> parameterTypes) { return(IntrinsicPrototype.Create( Namespace.GetIntrinsicName(operatorName), resultType, parameterTypes)); }
/// <summary> /// Creates an arithmetic intrinsic prototype. /// </summary> /// <param name="operatorName"> /// The name of the operator represented by the arithmetic intrinsic. /// </param> /// <param name="isChecked"> /// Tells if the arithmetic intrinsic is checked, that is, /// if it throws on overflow. /// </param> /// <param name="resultType"> /// The type of value produced by the intrinsic to create. /// </param> /// <param name="parameterTypes"> /// The types of the values the intrinsic takes as arguments. /// </param> /// <returns> /// An arithmetic intrinsic prototype. /// </returns> public static IntrinsicPrototype CreatePrototype( string operatorName, bool isChecked, IType resultType, IReadOnlyList <IType> parameterTypes) { return(IntrinsicPrototype.Create( GetArithmeticIntrinsicName(operatorName, isChecked), resultType, parameterTypes)); }
/// <summary> /// Creates an arithmetic intrinsic prototype. /// </summary> /// <param name="operatorName"> /// The name of the operator represented by the arithmetic intrinsic. /// </param> /// <param name="resultType"> /// The type of value produced by the intrinsic to create. /// </param> /// <param name="parameterTypes"> /// The types of the values the intrinsic takes as arguments. /// </param> /// <returns> /// An arithmetic intrinsic prototype. /// </returns> public static IntrinsicPrototype CreatePrototype( string operatorName, IType resultType, IReadOnlyList <IType> parameterTypes) { // TODO: exception specification? return(IntrinsicPrototype.Create( GetArithmeticIntrinsicName(operatorName), resultType, parameterTypes)); }
private static bool TryEvaluateUnchecked( string operatorName, IntrinsicPrototype prototype, IReadOnlyList <Constant> arguments, out Constant result) { if (arguments.Count == 2) { var lhs = arguments[0]; var rhs = arguments[1]; if (prototype.ResultType.IsIntegerType() && lhs is IntegerConstant && rhs is IntegerConstant) { var resultSpec = prototype.ResultType.GetIntegerSpecOrNull(); var intLhs = (IntegerConstant)lhs; var intRhs = (IntegerConstant)rhs; var maxIntSpec = UnionIntSpecs( resultSpec, intLhs.Spec, intRhs.Spec); Func <IntegerConstant, IntegerConstant, IntegerConstant> impl; if (intBinaryOps.TryGetValue(operatorName, out impl)) { result = impl( intLhs.Cast(maxIntSpec), intRhs.Cast(maxIntSpec)).Cast(resultSpec); return(true); } } else if (prototype.ResultType == prototype.ParameterTypes[0] && lhs is Float64Constant && rhs is Float64Constant) { Func <double, double, double?> impl; if (doubleBinaryOps.TryGetValue(operatorName, out impl)) { var maybeResult = impl( ((Float64Constant)lhs).Value, ((Float64Constant)rhs).Value); if (maybeResult.HasValue) { result = new Float64Constant(maybeResult.Value); return(true); } } } else if (prototype.ResultType == prototype.ParameterTypes[0] && lhs is Float32Constant && rhs is Float32Constant) { Func <float, float, float?> impl; if (floatBinaryOps.TryGetValue(operatorName, out impl)) { var maybeResult = impl( ((Float32Constant)lhs).Value, ((Float32Constant)rhs).Value); if (maybeResult.HasValue) { result = new Float32Constant(maybeResult.Value); return(true); } } } } else if (arguments.Count == 1) { var operand = arguments[0]; if (operatorName == Operators.Convert && operand is IntegerConstant && prototype.ResultType.IsIntegerType()) { result = ((IntegerConstant)operand).Cast( prototype.ResultType.GetIntegerSpecOrNull()); return(true); } } result = null; return(false); }