mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-14 22:29:17 +00:00
perf(packages/codegen): printNonNegativeFloat write mapping directly (#25968)
Small perf optimization and code simplification. `printNonNegativeFloat` previously passed the `node` parameter through a long chain of helper functions, so that they could call `writeWithMap` with `node` on their first write. Instead create the sourcemapping at the start of the chain, so there's no need to pass `node` down and helpers can just use `write` / `writeLast`.
This commit is contained in:
1 parent
7f70606ea1
commit
7e2b4b36a1
1 file changed
+23
-37
@@ -9,14 +9,7 @@
|
||||
// Each form is written to the output in pieces, so no candidate string is ever built.
|
||||
|
||||
import { debugAssert } from "../asserts.ts";
|
||||
import {
|
||||
CAT_IDENT,
|
||||
CAT_INT_DIGIT,
|
||||
write,
|
||||
writeNoLast,
|
||||
writeWithMap,
|
||||
writeWithMapNoLast,
|
||||
} from "./write.ts";
|
||||
import { CAT_IDENT, CAT_INT_DIGIT, markWithMapNoName, write, writeNoLast } from "./write.ts";
|
||||
|
||||
import type { State } from "../state.ts";
|
||||
import type * as ESTree from "../../../../npm/oxc-types/types.d.ts";
|
||||
@@ -32,14 +25,16 @@ import type * as ESTree from "../../../../npm/oxc-types/types.d.ts";
|
||||
* from a following `.` already.
|
||||
*/
|
||||
export function printNonNegativeFloat(state: State, value: number, node: ESTree.Node): void {
|
||||
markWithMapNoName(state, node);
|
||||
|
||||
if (Number.isInteger(value)) {
|
||||
if (value < 1000) {
|
||||
writeWithMap(state, String(value), CAT_INT_DIGIT, node);
|
||||
write(state, String(value), CAT_INT_DIGIT);
|
||||
} else {
|
||||
printShortestInteger(state, value, node);
|
||||
printShortestInteger(state, value);
|
||||
}
|
||||
} else {
|
||||
printShortestFraction(state, value, node);
|
||||
printShortestFraction(state, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,19 +44,19 @@ export function printNonNegativeFloat(state: State, value: number, node: ESTree.
|
||||
* `String` gives plain digits below 1e21 and exponent notation from there up, which have different forms
|
||||
* available to them, so they are separate cases. Both can go hexadecimal.
|
||||
*/
|
||||
function printShortestInteger(state: State, value: number, node: ESTree.Node): void {
|
||||
function printShortestInteger(state: State, value: number): void {
|
||||
const formatted = String(value);
|
||||
|
||||
if (value >= 1e21) {
|
||||
debugAssert(formatted.includes("e+"), "`String` gives `e+` notation from 1e21 up");
|
||||
// The `+` always goes, so the text is one shorter than `formatted`
|
||||
if (printHexIfShorter(state, value, formatted.length - 1, node)) return;
|
||||
printExponent(state, formatted, formatted.indexOf("e"), node);
|
||||
if (printHexIfShorter(state, value, formatted.length - 1)) return;
|
||||
printExponent(state, formatted, formatted.indexOf("e"));
|
||||
return;
|
||||
}
|
||||
|
||||
const { length } = formatted;
|
||||
if (printHexIfShorter(state, value, length, node)) return;
|
||||
if (printHexIfShorter(state, value, length)) return;
|
||||
|
||||
// A run of trailing zeros as an exponent: `1000` -> `1e3`
|
||||
if (formatted.charCodeAt(length - 1) === 48 /* 0 */) {
|
||||
@@ -72,14 +67,14 @@ function printShortestInteger(state: State, value: number, node: ESTree.Node): v
|
||||
// Worth it when the `e` and the exponent cost less than the zeros they replace
|
||||
const exponent = String(zeros);
|
||||
if (exponent.length + 1 < zeros) {
|
||||
writeWithMapNoLast(state, formatted.slice(0, length - zeros), node);
|
||||
writeNoLast(state, formatted.slice(0, length - zeros));
|
||||
writeNoLast(state, "e");
|
||||
write(state, exponent, CAT_IDENT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
writeWithMap(state, formatted, CAT_INT_DIGIT, node);
|
||||
write(state, formatted, CAT_INT_DIGIT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +84,7 @@ function printShortestInteger(state: State, value: number, node: ESTree.Node): v
|
||||
* below 1e-7. The first always loses its leading zero, and may trade a run of zeros after the point
|
||||
* for a negative exponent. The second is already as short as it gets.
|
||||
*/
|
||||
function printShortestFraction(state: State, value: number, node: ESTree.Node): void {
|
||||
function printShortestFraction(state: State, value: number): void {
|
||||
const formatted = String(value);
|
||||
|
||||
// The trailing-zero form `printShortestInteger` uses can never win here, so it is not tried.
|
||||
@@ -117,24 +112,24 @@ function printShortestFraction(state: State, value: number, node: ESTree.Node):
|
||||
// Both forms keep the digits, so it comes down to the `e-` and the exponent against the `.`
|
||||
// and the zeros they replace
|
||||
if (exponent.length + 2 < start - 1) {
|
||||
writeWithMapNoLast(state, formatted.slice(start), node);
|
||||
writeNoLast(state, formatted.slice(start));
|
||||
writeNoLast(state, "e-");
|
||||
write(state, exponent, CAT_IDENT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
writeWithMap(state, formatted.slice(1), CAT_IDENT, node);
|
||||
write(state, formatted.slice(1), CAT_IDENT);
|
||||
return;
|
||||
}
|
||||
|
||||
const exponentIndex = formatted.indexOf("e");
|
||||
if (exponentIndex === -1) {
|
||||
writeWithMap(state, formatted, CAT_IDENT, node);
|
||||
write(state, formatted, CAT_IDENT);
|
||||
return;
|
||||
}
|
||||
|
||||
printExponent(state, formatted, exponentIndex, node);
|
||||
printExponent(state, formatted, exponentIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,15 +139,11 @@ function printShortestFraction(state: State, value: number, node: ESTree.Node):
|
||||
* `1.5e+21` -> `15e20`. That drops the `.`, so it wins whenever the exponent it leaves is no longer to write
|
||||
* than the one it replaces. The `+` of a positive exponent always goes.
|
||||
*
|
||||
* @param state - Printer state
|
||||
* @param formatted - `String(value)`, which is in exponent notation
|
||||
* @param exponentIndex - Index of the `e` in `formatted`
|
||||
*/
|
||||
function printExponent(
|
||||
state: State,
|
||||
formatted: string,
|
||||
exponentIndex: number,
|
||||
node: ESTree.Node,
|
||||
): void {
|
||||
function printExponent(state: State, formatted: string, exponentIndex: number): void {
|
||||
const exponent =
|
||||
formatted.charCodeAt(exponentIndex + 1) === "+".charCodeAt(0)
|
||||
? formatted.slice(exponentIndex + 2)
|
||||
@@ -166,7 +157,7 @@ function printExponent(
|
||||
|
||||
const folded = String(Number(exponent) - (exponentIndex - 2));
|
||||
if (folded.length <= exponent.length) {
|
||||
writeWithMapNoLast(state, formatted[0], node);
|
||||
writeNoLast(state, formatted[0]);
|
||||
writeNoLast(state, formatted.slice(2, exponentIndex));
|
||||
writeNoLast(state, "e");
|
||||
write(state, folded, CAT_IDENT);
|
||||
@@ -174,7 +165,7 @@ function printExponent(
|
||||
}
|
||||
}
|
||||
|
||||
writeWithMapNoLast(state, formatted.slice(0, exponentIndex + 1), node);
|
||||
writeNoLast(state, formatted.slice(0, exponentIndex + 1));
|
||||
write(state, exponent, CAT_IDENT);
|
||||
}
|
||||
|
||||
@@ -193,18 +184,13 @@ function printExponent(
|
||||
*
|
||||
* @param length - Length of the shortest text found for `value` so far
|
||||
*/
|
||||
function printHexIfShorter(
|
||||
state: State,
|
||||
value: number,
|
||||
length: number,
|
||||
node: ESTree.Node,
|
||||
): boolean {
|
||||
function printHexIfShorter(state: State, value: number, length: number): boolean {
|
||||
if (length < 13) return false;
|
||||
|
||||
const hex = BigInt(value).toString(16);
|
||||
if (hex.length + 2 >= length) return false;
|
||||
|
||||
writeWithMapNoLast(state, "0x", node);
|
||||
writeNoLast(state, "0x");
|
||||
write(state, hex, CAT_IDENT);
|
||||
|
||||
return true;
|
||||
|
||||
Reference in new issue
Block a user