Clarify division behavior in tests

This commit is contained in:
Tangent Wantwight 2024-05-20 20:39:12 -04:00
parent ce991fd12a
commit 7e21e71a07
2 changed files with 37 additions and 14 deletions

View file

@ -10,12 +10,24 @@ describe("expr", () => {
["1 - 2", "-1"],
["1 * 2", "2"],
["1 / 2", "0.5"],
["1 // 2", "0"],
["1 % 2", "1"],
["3 % 2", "1"],
["-1 % 2", "1"],
// TODO: might change this! negative dividend is weird no matter what, but positive modulo is arguably the better call?
["1 % -2", "-1"],
// floored division
["1 // 5", "0"],
["6 // 5", "1"],
["-1 // 5", "-1"],
["-6 // 5", "-2"],
["1 // -5", "-1"],
["6 // -5", "-2"],
["-1 // -5", "0"],
["-6 // -5", "1"],
// floored modulo
["1 % 5", "1"],
["6 % 5", "1"],
["-6 % 5", "4"],
["-1 % 5", "4"],
["1 % -5", "-4"],
["6 % -5", "-4"],
["-6 % -5", "-1"],
["-1 % -5", "-1"],
// TODO: operator precedence
// TODO: parentheses
])("%s", (expression, result) => {

View file

@ -12,8 +12,8 @@ export function Expr({}, argv: TextPiece[]): ProcResult {
const parser = new ExpressionParser(expression);
const result = parser.parseSubExpression(0);
if(parser.pos != expression.length) {
return {error: "Couldn't parse full expression"}
if (parser.pos != expression.length) {
return { error: "Couldn't parse full expression" };
}
if ("value" in result) {
@ -59,13 +59,20 @@ function map(
}
}
function makeInfixOp(token:RegExp, leftBindingPower: number,rightBindingPower: number, op: (left: number, right: number) => Value | ErrorResult):TokenHandler {
function makeInfixOp(
token: RegExp,
leftBindingPower: number,
rightBindingPower: number,
op: (left: number, right: number) => Value | ErrorResult
): TokenHandler {
return {
leftBindingPower,
token,
parse: ({ value: left }, matched, parser) =>
map(parser.parseSubExpression(rightBindingPower), (right) => op(left, right)),
}
map(parser.parseSubExpression(rightBindingPower), (right) =>
op(left, right)
),
};
}
const Operators: TokenHandler[] = [
@ -78,14 +85,18 @@ const Operators: TokenHandler[] = [
leftBindingPower: -1,
token: MINUS_TOKEN,
parse: (left, matched, parser) =>
map(parser.parseSubExpression(99), (right) => ({value: -right})),
map(parser.parseSubExpression(99), (right) => ({ value: -right })),
},
makeInfixOp(PLUS_TOKEN, 10, 11, (left, right) => ({ value: left + right })),
makeInfixOp(MINUS_TOKEN, 10, 11, (left, right) => ({ value: left - right })),
makeInfixOp(TIMES_TOKEN, 20, 21, (left, right) => ({ value: left * right })),
makeInfixOp(FLOOR_TOKEN, 20, 21, (left, right) => ({ value: Math.floor(left / right) })),
makeInfixOp(FLOOR_TOKEN, 20, 21, (left, right) => ({
value: Math.floor(left / right),
})),
makeInfixOp(DIV_TOKEN, 20, 21, (left, right) => ({ value: left / right })),
makeInfixOp(MOD_TOKEN, 20, 21, (left, right) => ({ value: ((left % right) + right) % right })),
makeInfixOp(MOD_TOKEN, 20, 21, (left, right) => ({
value: ((left % right) + right) % right,
})),
];
const ZERO = { value: 0 };