static protected MalNum ProcessNumbers(MalList args, NumericOp op) { double result = 0; // Initiate the calculation with the first arg. switch (args[0]) { case MalNum num: result = (double)num; // Handle the special case of (- 1). if (args.Count() == 1 && op == NumericOp.Subtract) { double negative = (double)num; return(new MalNum(-negative)); } break; default: // Should have already detected this but just in case. throw new MalInternalError("Non-number while calculating numbers: '" + args[0].ToString(true)); } double divTest = 0; // Now apply the op to the remaining args. for (var i = 1; i < args.Count(); i++) { switch (args[i]) { case MalNum num: switch (op) { case NumericOp.Plus: result += (double)num; break; case NumericOp.Multiply: result *= (double)num; break; case NumericOp.Subtract: result -= (double)num; break; case NumericOp.Divide: divTest = (double)num; if (i > 0 && divTest == 0) { throw new MalEvalError("Can't divide by zero"); } result /= divTest; break; } break; default: throw new MalInternalError("Non-number while calculating numbers: '" + args[i].ToString(true)); } } return(new MalNum(result)); }
// Mixing floats and integers introduces loads of special cases. I decided to // move the things that are type-dependent into helper functions to keep the // numeric Builtins themselves cleaner. static protected MalInt ProcessIntegers(MalList args, NumericOp op) { int result = (int)(MalInt)args[0]; int divTest = 0; // Handle the special case of (- 1). if (args.Count() == 1 && op == NumericOp.Subtract) { return(new MalInt(-result)); } for (var i = 1; i < args.Count(); i++) { switch (op) { case NumericOp.Plus: result += (int)(MalInt)args[i]; break; case NumericOp.Multiply: result *= (int)(MalInt)args[i]; break; case NumericOp.Subtract: result -= (int)(MalInt)args[i]; break; case NumericOp.Divide: divTest = (int)(MalInt)args[i]; if (i > 0 && divTest == 0) { throw new MalEvalError("Can't divide by zero"); } result /= divTest; break; } } return(new MalInt(result)); }