Skip to content

Commit 220800d

Browse files
eanders-msriknoll
andauthored
Compiler perf: Count line numbers progressively (microsoft#7288)
* Don't use regexp to get line number * Update pxtlib/jsoutput.ts Co-authored-by: Richard Knoll <riknoll@users.noreply.github.com> * Update conditional to check for string type Co-authored-by: Richard Knoll <riknoll@users.noreply.github.com>
1 parent b6734c2 commit 220800d

File tree

1 file changed

+25
-16
lines changed

1 file changed

+25
-16
lines changed

pxtlib/jsoutput.ts

+25-16
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,15 @@ namespace pxt.blocks {
284284
let output = ""
285285
let indent = ""
286286
let variables: Map<string>[] = [{}];
287+
let currentLine = 0;
288+
289+
function append(s: string) {
290+
// At runtime sometimes `s` is a number.
291+
if (typeof(s) === 'string') {
292+
currentLine += (s.match(/\n/g) || []).length;
293+
}
294+
output += s;
295+
}
287296

288297
function flatten(e0: JsNode) {
289298
function rec(e: JsNode, outPrio: number) {
@@ -340,50 +349,50 @@ namespace pxt.blocks {
340349

341350
// never return empty string - TS compiler service thinks it's an error
342351
if (!output)
343-
output += "\n"
352+
append("\n");
344353

345354
return { output, sourceMap }
346355

347356
function emit(n: JsNode) {
348357
if (n.glueToBlock) {
349358
removeLastIndent()
350359
if (n.glueToBlock == GlueMode.WithSpace) {
351-
output += " "
360+
append(" ");
352361
}
353362
}
354363

355-
let startLine = getCurrentLine();
364+
let startLine = currentLine;
356365
let startPos = output.length;
357366

358367
switch (n.type) {
359368
case NT.Infix:
360369
U.oops("no infix should be left")
361370
break
362371
case NT.NewLine:
363-
output += "\n" + indent
372+
append("\n" + indent)
364373
break
365374
case NT.Block:
366375
block(n)
367376
break
368377
case NT.Prefix:
369378
if (n.canIndentInside)
370-
output += n.op.replace(/\n/g, "\n" + indent + " ")
379+
append(n.op.replace(/\n/g, "\n" + indent + " "))
371380
else
372-
output += n.op
381+
append(n.op)
373382
n.children.forEach(emit)
374383
break
375384
case NT.Postfix:
376385
n.children.forEach(emit)
377386
if (n.canIndentInside)
378-
output += n.op.replace(/\n/g, "\n" + indent + " ")
387+
append(n.op.replace(/\n/g, "\n" + indent + " "))
379388
else
380-
output += n.op
389+
append(n.op)
381390
break
382391
default:
383392
break
384393
}
385394

386-
let endLine = getCurrentLine();
395+
let endLine = currentLine;
387396
// end position is non-inclusive
388397
let endPos = Math.max(output.length, 1);
389398

@@ -406,16 +415,16 @@ namespace pxt.blocks {
406415
}
407416
}
408417

409-
function getCurrentLine() {
410-
return (output.match(/\n/g) || []).length;
411-
}
412-
413418
function write(s: string) {
414-
output += s.replace(/\n/g, "\n" + indent)
419+
append(s.replace(/\n/g, "\n" + indent))
415420
}
416421

417422
function removeLastIndent() {
418-
output = output.replace(/\n *$/, "")
423+
// Note: performance of this regular expression degrades with program size, and could therefore become a perf issue.
424+
output = output.replace(/\n *$/, function () {
425+
currentLine--;
426+
return "";
427+
});
419428
}
420429

421430
function block(n: JsNode) {
@@ -463,4 +472,4 @@ namespace pxt.blocks {
463472
}
464473
return false;
465474
}
466-
}
475+
}

0 commit comments

Comments
 (0)