private void AddMethod(MethodInfo methodInfo) { SprakConversionAttribute conversionAttribute = methodInfo.GetCustomAttribute <SprakConversionAttribute>(); bool isConversion = conversionAttribute != null; SprakOperatorAttribute opAttribute = methodInfo.GetCustomAttribute <SprakOperatorAttribute>(); bool isOperator = opAttribute != null; if (isConversion && isOperator) { throw new ArgumentException($"{MethodName(methodInfo)} is declared to be both an operator and a conversion"); } if (isConversion) { AddConversion(methodInfo, conversionAttribute.IsPerfect); } else if (isOperator) { AddOperator(methodInfo, opAttribute); } else { AddFunction(methodInfo); } }
private void AddOperator(MethodInfo methodInfo, SprakOperatorAttribute meta) { BuiltInFunction function = new BuiltInFunction(methodInfo, this); if (!Operator.TryParse(out Operator op, name: meta.OperatorName)) { string message = $"{MethodName(methodInfo)} is declared to be an unrecognized operator: \"{meta.OperatorName}\""; throw new ArgumentException(message); } int paramCount = function.Parameters.Count; bool binary = meta.InputsHint == InputSides.Both; int requiredCount = binary ? 2 : 1; if (paramCount != requiredCount) { string desc = binary ? "binary" : "unary"; string message = $"{MethodName(methodInfo)} was declared to be the {desc} operator \"{meta.OperatorName}\", " + $"but has {function.Parameters.Count} Sprak arguments"; throw new ArgumentException(message); } InputSides inputs = meta.InputsHint; SprakType left = null; SprakType right = null; switch (inputs) { case InputSides.Both: left = function.Parameters[0]; right = function.Parameters[1]; break; case InputSides.Left: left = function.Parameters[0]; break; case InputSides.Right: right = function.Parameters[0]; break; } OperatorTypeSignature typeSignature = new OperatorTypeSignature(left, right, inputs); OperatorSignature signature = new OperatorSignature(op.Name, typeSignature); _operators.Add(signature, function); }