diff --git a/src/lib/expr.test.ts b/src/lib/expr.test.ts index 3ed361f..fbb0edb 100644 --- a/src/lib/expr.test.ts +++ b/src/lib/expr.test.ts @@ -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) => { diff --git a/src/lib/expr.ts b/src/lib/expr.ts index 9d6afb2..81df33e 100644 --- a/src/lib/expr.ts +++ b/src/lib/expr.ts @@ -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 };