Compare commits
No commits in common. "fee5666971fd3fb6510da9ddee1f1183c5907601" and "b2bdf471f096b7c1d7a83fe4c00a856389b1ae6f" have entirely different histories.
fee5666971
...
b2bdf471f0
@ -22,8 +22,6 @@ export const Ops = {
|
||||
Jump: 0x0e,
|
||||
JumpIfTrue: 0x0f,
|
||||
Builtin: 0x10,
|
||||
Duplicate: 0x11,
|
||||
Swap: 0x12,
|
||||
Add: 0x20,
|
||||
Subtract: 0x21,
|
||||
Multiply: 0x22,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { opToString } from "./arch.ts";
|
||||
import { Ops, opToString } from "./arch.ts";
|
||||
|
||||
export type Line = { labels?: string[]; ins: Ins };
|
||||
|
||||
@ -14,28 +14,7 @@ export type Refs = { [key: number]: string };
|
||||
export class Assembler {
|
||||
private lines: Line[] = [];
|
||||
private addedLabels: string[] = [];
|
||||
|
||||
private constructor(private labelCounter: number) {}
|
||||
|
||||
public static newRoot(): Assembler {
|
||||
return new Assembler(0);
|
||||
}
|
||||
|
||||
public fork(): Assembler {
|
||||
return new Assembler(this.labelCounter);
|
||||
}
|
||||
|
||||
public join(assembler: Assembler) {
|
||||
this.labelCounter = assembler.labelCounter;
|
||||
if (assembler.lines.length < 0) {
|
||||
return;
|
||||
}
|
||||
if (assembler.lines[0].labels !== undefined) {
|
||||
this.addedLabels.push(...assembler.lines[0].labels);
|
||||
}
|
||||
this.add(...assembler.lines[0].ins);
|
||||
this.lines.push(...assembler.lines.slice(1));
|
||||
}
|
||||
private labelCounter = 0;
|
||||
|
||||
public add(...ins: Ins): Assembler {
|
||||
if (this.addedLabels.length > 0) {
|
||||
@ -47,6 +26,17 @@ export class Assembler {
|
||||
return this;
|
||||
}
|
||||
|
||||
public concat(assembler: Assembler) {
|
||||
if (assembler.lines.length < 0) {
|
||||
return;
|
||||
}
|
||||
if (assembler.lines[0].labels !== undefined) {
|
||||
this.addedLabels.push(...assembler.lines[0].labels);
|
||||
}
|
||||
this.add(...assembler.lines[0].ins);
|
||||
this.lines.push(...assembler.lines.slice(1));
|
||||
}
|
||||
|
||||
public makeLabel(): Label {
|
||||
return { label: `.L${(this.labelCounter++).toString()}` };
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import { Pos } from "./token.ts";
|
||||
export type FnNamesMap = { [pc: number]: string };
|
||||
|
||||
export class Lowerer {
|
||||
private program = Assembler.newRoot();
|
||||
private program = new Assembler();
|
||||
private locals: Locals = new LocalsFnRoot();
|
||||
private fnStmtIdLabelMap: { [stmtId: number]: string } = {};
|
||||
private fnLabelNameMap: { [name: string]: string } = {};
|
||||
@ -19,16 +19,16 @@ export class Lowerer {
|
||||
|
||||
public lower(stmts: Stmt[]) {
|
||||
this.addClearingSourceMap();
|
||||
this.program.add(Ops.PushPtr, { label: "main" });
|
||||
this.program.add(Ops.Call, 0);
|
||||
this.program.add(Ops.PushPtr, { label: "_exit" });
|
||||
this.program.add(Ops.PushPtr, { label: "_start" });
|
||||
this.program.add(Ops.Jump);
|
||||
this.scoutFnHeaders(stmts);
|
||||
for (const stmt of stmts) {
|
||||
this.lowerStaticStmt(stmt);
|
||||
}
|
||||
this.program.setLabel({ label: "_exit" });
|
||||
this.program.setLabel({ label: "_start" });
|
||||
this.addSourceMap(this.lastPos);
|
||||
this.program.add(Ops.PushPtr, { label: "main" });
|
||||
this.program.add(Ops.Call, 0);
|
||||
this.program.add(Ops.Pop);
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ export class Lowerer {
|
||||
const returnLabel = this.program.makeLabel();
|
||||
this.returnStack.push(returnLabel);
|
||||
|
||||
this.program = outerProgram.fork();
|
||||
this.program = new Assembler();
|
||||
this.locals = fnRoot;
|
||||
for (const { ident } of stmt.kind.params) {
|
||||
this.locals.allocSym(ident);
|
||||
@ -185,17 +185,18 @@ export class Lowerer {
|
||||
}
|
||||
this.locals = outerLocals;
|
||||
|
||||
this.returnStack.pop();
|
||||
this.program.setLabel(returnLabel);
|
||||
|
||||
const localAmount = fnRoot.stackReserved() -
|
||||
stmt.kind.params.length;
|
||||
for (let i = 0; i < localAmount; ++i) {
|
||||
outerProgram.add(Ops.PushNull);
|
||||
}
|
||||
|
||||
this.returnStack.pop();
|
||||
this.program.setLabel(returnLabel);
|
||||
this.program.add(Ops.Return);
|
||||
|
||||
outerProgram.join(this.program);
|
||||
outerProgram.concat(this.program);
|
||||
this.program = outerProgram;
|
||||
}
|
||||
|
||||
@ -352,8 +353,9 @@ export class Lowerer {
|
||||
switch (expr.kind.unaryType) {
|
||||
case "-": {
|
||||
this.program.add(Ops.PushInt, 0);
|
||||
this.program.add(Ops.Swap);
|
||||
this.program.add(Ops.PushInt, 1);
|
||||
this.program.add(Ops.Subtract);
|
||||
this.program.add(Ops.Multiply);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
@ -371,25 +373,9 @@ export class Lowerer {
|
||||
if (expr.kind.type !== "binary") {
|
||||
throw new Error();
|
||||
}
|
||||
this.lowerExpr(expr.kind.left);
|
||||
this.lowerExpr(expr.kind.right);
|
||||
const vtype = expr.kind.left.vtype!;
|
||||
if (vtype.type === "bool") {
|
||||
if (["or", "and"].includes(expr.kind.binaryType)) {
|
||||
const shortCircuitLabel = this.program.makeLabel();
|
||||
this.lowerExpr(expr.kind.left);
|
||||
this.program.add(Ops.Duplicate);
|
||||
if (expr.kind.binaryType === "and") {
|
||||
this.program.add(Ops.Not);
|
||||
}
|
||||
this.program.add(Ops.PushPtr, shortCircuitLabel);
|
||||
this.program.add(Ops.JumpIfTrue);
|
||||
this.program.add(Ops.Pop);
|
||||
this.lowerExpr(expr.kind.right);
|
||||
this.program.setLabel(shortCircuitLabel);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.lowerExpr(expr.kind.left);
|
||||
this.lowerExpr(expr.kind.right);
|
||||
if (vtype.type === "int") {
|
||||
switch (expr.kind.binaryType) {
|
||||
case "+":
|
||||
@ -401,9 +387,6 @@ export class Lowerer {
|
||||
case "*":
|
||||
this.program.add(Ops.Multiply);
|
||||
return;
|
||||
case "/":
|
||||
this.program.add(Ops.Multiply);
|
||||
return;
|
||||
case "==":
|
||||
this.program.add(Ops.Equal);
|
||||
return;
|
||||
@ -414,15 +397,6 @@ export class Lowerer {
|
||||
case "<":
|
||||
this.program.add(Ops.LessThan);
|
||||
return;
|
||||
case ">":
|
||||
this.program.add(Ops.Swap);
|
||||
this.program.add(Ops.LessThan);
|
||||
return;
|
||||
case "<=":
|
||||
this.program.add(Ops.Swap);
|
||||
this.program.add(Ops.LessThan);
|
||||
this.program.add(Ops.Not);
|
||||
return;
|
||||
case ">=":
|
||||
this.program.add(Ops.LessThan);
|
||||
this.program.add(Ops.Not);
|
||||
@ -445,6 +419,16 @@ export class Lowerer {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (vtype.type === "bool") {
|
||||
if (expr.kind.binaryType === "or") {
|
||||
this.program.add(Ops.Or);
|
||||
return;
|
||||
}
|
||||
if (expr.kind.binaryType === "and") {
|
||||
this.program.add(Ops.And);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
`unhandled binaryType` +
|
||||
` '${vtypeToString(expr.vtype!)}' aka. ` +
|
||||
|
@ -7,8 +7,10 @@ fn string_to_int_impl(text: string) -> int {
|
||||
|
||||
let len = string_length(text);
|
||||
if len == 0 {
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
println("hello world");
|
||||
|
||||
if text[0] == "0"[0] {
|
||||
if len == 1 {
|
||||
0
|
||||
@ -39,10 +41,10 @@ fn parse_digits(text: string, base: int, digit_set: string) -> int {
|
||||
}
|
||||
|
||||
fn char_val(ch: int) -> int {
|
||||
if ch >= "0"[0] and ch <= "9"[0] {
|
||||
if ch >= "0"[0] and "9"[0] >= ch {
|
||||
ch - "0"[0]
|
||||
} else if ch >= "a"[0] and ch <= "f"[0] {
|
||||
ch - "a"[0] + 10
|
||||
} else if ch >= "a"[0] and "f"[0] >= ch {
|
||||
ch - "a"[0]
|
||||
} else {
|
||||
-1
|
||||
}
|
||||
@ -50,17 +52,16 @@ fn char_val(ch: int) -> int {
|
||||
|
||||
fn test_string_to_int_impl() -> bool {
|
||||
test("should convert zero", assert_int_equal(string_to_int_impl("0"), 0))
|
||||
and test("should convert decimal", assert_int_equal(string_to_int_impl("10"), 10))
|
||||
and test("should convert binary", assert_int_equal(string_to_int_impl("0b110"), 6))
|
||||
and test("should convert octal", assert_int_equal(string_to_int_impl("071"), 57))
|
||||
and test("should convert hex", assert_int_equal(string_to_int_impl("0xaa"), 170))
|
||||
and test("should fail", assert_int_equal(string_to_int_impl("john"), -1))
|
||||
and test("should fail", assert_int_equal(string_to_int_impl(""), -1))
|
||||
or test("should convert decimal", assert_int_equal(string_to_int_impl("10"), 10))
|
||||
or test("should convert binary", assert_int_equal(string_to_int_impl("0b110"), 6))
|
||||
or test("should convert octal", assert_int_equal(string_to_int_impl("071"), 51))
|
||||
or test("should convert hexadecimal", assert_int_equal(string_to_int_impl("0xaa"), 170))
|
||||
or test("should fail", assert_int_equal(string_to_int_impl("john"), -1))
|
||||
}
|
||||
|
||||
fn assert_int_equal(value: int, target: int) -> bool {
|
||||
if value != target {
|
||||
println("assertion failed: " + itos(value) + " != " + itos(target));
|
||||
println("assertion failed: " + int_to_string(value) + " != " + int_to_string(target));
|
||||
return false;
|
||||
}
|
||||
true
|
||||
@ -108,8 +109,6 @@ fn file_read_to_string(file: int) -> string #[builtin(FileReadToString)] {}
|
||||
fn file_flush(file: int) #[builtin(FileFlush)] {}
|
||||
fn file_eof(file: int) -> bool #[builtin(FileEof)] {}
|
||||
|
||||
fn itos(number: int) -> string #[builtin(IntToString)] {}
|
||||
fn stoi(str: string) -> int #[builtin(StringToInt)] {}
|
||||
|
||||
fn stdin() -> int { 0 }
|
||||
fn stdout() -> int { 1 }
|
||||
@ -176,11 +175,11 @@ fn string_split(str: string, seperator: int) -> [string] {
|
||||
fn string_slice(str: string, from: int, to: int) -> string {
|
||||
let result = "";
|
||||
let len = string_length(str);
|
||||
let abs_to =
|
||||
let actual_to =
|
||||
if to >= len { len }
|
||||
else if to < 0 { len + to + 1 }
|
||||
else if to < 0 { len - to }
|
||||
else { to };
|
||||
for (let i = from; i < abs_to; i += 1) {
|
||||
for (let i = from; i < actual_to; i += i) {
|
||||
result = string_push_char(result, str[i]);
|
||||
}
|
||||
result
|
||||
|
@ -24,8 +24,6 @@ enum class Op : uint32_t {
|
||||
Jump = 0x0e,
|
||||
JumpIfTrue = 0x0f,
|
||||
Builtin = 0x10,
|
||||
Duplicate = 0x11,
|
||||
Swap = 0x12,
|
||||
Add = 0x20,
|
||||
Subtract = 0x21,
|
||||
Multiply = 0x22,
|
||||
|
@ -33,8 +33,6 @@ size_t VM::instruction_size(size_t i) const
|
||||
return 1;
|
||||
case Op::Builtin:
|
||||
return 2;
|
||||
case Op::Duplicate:
|
||||
case Op::Swap:
|
||||
case Op::Add:
|
||||
case Op::Subtract:
|
||||
case Op::Multiply:
|
||||
|
@ -25,8 +25,6 @@ auto sliger::maybe_op_to_string(uint32_t value) -> std::string
|
||||
case Op::Jump: return "Jump";
|
||||
case Op::JumpIfTrue: return "JumpIfTrue";
|
||||
case Op::Builtin: return "Builtin";
|
||||
case Op::Duplicate: return "Duplicate";
|
||||
case Op::Swap: return "Swap";
|
||||
case Op::Add: return "Add";
|
||||
case Op::Subtract: return "Subtract";
|
||||
case Op::Multiply: return "Multiply";
|
||||
@ -40,9 +38,10 @@ auto sliger::maybe_op_to_string(uint32_t value) -> std::string
|
||||
case Op::Not: return "Not";
|
||||
case Op::SourceMap: return "SourceMap";
|
||||
/* clang-format on */
|
||||
}
|
||||
default:
|
||||
return std::to_string(value);
|
||||
}
|
||||
}
|
||||
|
||||
auto sliger::maybe_builtin_to_string(uint32_t value) -> std::string
|
||||
{
|
||||
|
@ -177,21 +177,6 @@ void VM::run_instruction()
|
||||
run_builtin(static_cast<Builtin>(builtin_id));
|
||||
break;
|
||||
}
|
||||
case Op::Duplicate: {
|
||||
assert_stack_has(1);
|
||||
auto value = stack_pop();
|
||||
stack_push(value);
|
||||
stack_push(value);
|
||||
break;
|
||||
}
|
||||
case Op::Swap: {
|
||||
assert_stack_has(2);
|
||||
auto right = stack_pop();
|
||||
auto left = stack_pop();
|
||||
stack_push(right);
|
||||
stack_push(left);
|
||||
break;
|
||||
}
|
||||
case Op::Add: {
|
||||
assert_stack_has(2);
|
||||
auto right = stack_pop().as_int().value;
|
||||
|
@ -27,8 +27,6 @@ fn file_read_to_string(file: int) -> string #[builtin(FileReadToString)] {}
|
||||
fn file_flush(file: int) #[builtin(FileFlush)] {}
|
||||
fn file_eof(file: int) -> bool #[builtin(FileEof)] {}
|
||||
|
||||
fn itos(number: int) -> string #[builtin(IntToString)] {}
|
||||
fn stoi(str: string) -> int #[builtin(StringToInt)] {}
|
||||
|
||||
fn stdin() -> int { 0 }
|
||||
fn stdout() -> int { 1 }
|
||||
|
@ -2,11 +2,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100..700;1,100..700&display=swap" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="dist/bundle.js" type="module" defer></script>
|
||||
</head>
|
||||
|
@ -27,7 +27,7 @@ export function loadFlameGraph(
|
||||
canvas.width = 1000;
|
||||
canvas.height = 500;
|
||||
|
||||
const fnNameFont = "600 14px 'Roboto Mono'";
|
||||
const fnNameFont = "600 14px monospace";
|
||||
|
||||
const ctx = canvas.getContext("2d")!;
|
||||
ctx.font = fnNameFont;
|
||||
@ -39,7 +39,7 @@ export function loadFlameGraph(
|
||||
h: number;
|
||||
title: string;
|
||||
percent: string;
|
||||
fgNode: data.FlameGraphNode;
|
||||
fgNode: FlameGraphNode;
|
||||
};
|
||||
|
||||
function calculateNodeRects(
|
||||
@ -91,40 +91,14 @@ export function loadFlameGraph(
|
||||
for (const node of nodes) {
|
||||
const { x, y, w, h } = node;
|
||||
ctx.fillStyle = "rgb(255, 125, 0)";
|
||||
ctx.fillRect(x + 2, y + 2, w - 4, h - 4);
|
||||
|
||||
const textCanvas = drawTextCanvas(node);
|
||||
ctx.drawImage(textCanvas, x + 4, y);
|
||||
|
||||
const edgePadding = 4;
|
||||
const edgeWidth = 8;
|
||||
|
||||
const leftGradient = ctx.createLinearGradient(
|
||||
x + 2 + edgePadding,
|
||||
0,
|
||||
x + 2 + edgeWidth,
|
||||
0,
|
||||
);
|
||||
leftGradient.addColorStop(1, "rgba(255, 125, 0, 0.0)");
|
||||
leftGradient.addColorStop(0, "rgba(255, 125, 0, 1.0)");
|
||||
ctx.fillStyle = leftGradient;
|
||||
ctx.fillRect(x + 2, y + 2, Math.min(edgeWidth, (w - 4) / 2), h - 4);
|
||||
|
||||
const rightGradient = ctx.createLinearGradient(
|
||||
x + w - 2 - edgeWidth,
|
||||
0,
|
||||
x + w - 2 - edgePadding,
|
||||
0,
|
||||
);
|
||||
rightGradient.addColorStop(0, "rgba(255, 125, 0, 0.0)");
|
||||
rightGradient.addColorStop(1, "rgba(255, 125, 0, 1.0)");
|
||||
ctx.fillStyle = rightGradient;
|
||||
ctx.fillRect(
|
||||
x + w - 2 - Math.min(edgeWidth, (w - 4) / 2),
|
||||
x + 2,
|
||||
y + 2,
|
||||
Math.min(edgeWidth, (w - 4) / 2),
|
||||
w - 4,
|
||||
h - 4,
|
||||
);
|
||||
const textCanvas = drawTextCanvas(node);
|
||||
ctx.drawImage(textCanvas, x + 4, y);
|
||||
}
|
||||
const tooltip = document.getElementById("flame-graph-tooltip")!;
|
||||
|
||||
|
@ -40,200 +40,6 @@ async function checkStatus(): Promise<"running" | "done"> {
|
||||
return "done";
|
||||
}
|
||||
|
||||
function syntaxHighlight(code: string): string {
|
||||
const colors = {
|
||||
colorBackground: "#282828",
|
||||
colorForeground: "#fbf1c7",
|
||||
colorKeyword: "#fb4934",
|
||||
colorIdentifier: "#83a598",
|
||||
colorOperator: "#fe8019",
|
||||
colorSpecial: "#fe8019",
|
||||
colorType: "#fabd2f",
|
||||
colorBoolean: "#d3869b",
|
||||
colorNumber: "#d3869b",
|
||||
colorString: "#b8bb26",
|
||||
colorComment: "#928374",
|
||||
colorFunction: "#b8bb26",
|
||||
colorLineNumber: "#7c6f64",
|
||||
} as const;
|
||||
|
||||
/*
|
||||
Keyword = { link = "GruvboxRed" },
|
||||
Identifier = { link = "GruvboxBlue" },
|
||||
Operator = { fg = colors.orange, italic = config.italic.operators },
|
||||
Special = { link = "GruvboxOrange" },
|
||||
Type = { link = "GruvboxYellow" },
|
||||
Boolean = { link = "GruvboxPurple" },
|
||||
Number = { link = "GruvboxPurple" },
|
||||
String = { fg = colors.green, italic = config.italic.strings },
|
||||
Comment = { fg = colors.gray, italic = config.italic.comments },
|
||||
Function = { link = "GruvboxGreenBold" },
|
||||
*/
|
||||
|
||||
let matches: {
|
||||
index: number;
|
||||
length: number;
|
||||
color: string;
|
||||
extra: string;
|
||||
}[] = [];
|
||||
|
||||
function addMatches(color: string, re: RegExp, extra = "") {
|
||||
for (const match of code.matchAll(re)) {
|
||||
matches.push({
|
||||
index: match.index,
|
||||
length: match[1].length,
|
||||
color,
|
||||
extra,
|
||||
});
|
||||
}
|
||||
}
|
||||
function addKeywordMatches(color: string, keywords: string[]) {
|
||||
addMatches(
|
||||
color,
|
||||
new RegExp(
|
||||
`(?<!\\w)(${
|
||||
keywords.map((kw) => `(?:${kw})`).join("|")
|
||||
})(?!\\w)`,
|
||||
"g",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
for (let i = 0; i < code.length; ++i) {
|
||||
if (code[i] !== '"') {
|
||||
continue;
|
||||
}
|
||||
let last = code[i];
|
||||
const index = i;
|
||||
i += 1;
|
||||
while (i < code.length && !(code[i] === '"' && last !== "\\")) {
|
||||
last = code[i];
|
||||
i += 1;
|
||||
}
|
||||
if (i < code.length) {
|
||||
i += 1;
|
||||
}
|
||||
matches.push({
|
||||
index,
|
||||
length: i - index,
|
||||
color: colors.colorString,
|
||||
extra: "font-style: italic;",
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
let last = "";
|
||||
for (let i = 0; i < code.length; ++i) {
|
||||
if (last === "/" && code[i] === "/") {
|
||||
const index = i - 1;
|
||||
while (i < code.length && code[i] !== "\n") {
|
||||
i += 1;
|
||||
}
|
||||
matches.push({
|
||||
index,
|
||||
length: i - index,
|
||||
color: colors.colorComment,
|
||||
extra: "font-style: italic;",
|
||||
});
|
||||
}
|
||||
last = code[i];
|
||||
}
|
||||
}
|
||||
|
||||
addKeywordMatches(
|
||||
colors.colorKeyword,
|
||||
[
|
||||
"break",
|
||||
"return",
|
||||
"let",
|
||||
"fn",
|
||||
"if",
|
||||
"else",
|
||||
"struct",
|
||||
"import",
|
||||
"or",
|
||||
"and",
|
||||
"not",
|
||||
"while",
|
||||
"for",
|
||||
"in",
|
||||
],
|
||||
);
|
||||
addKeywordMatches(colors.colorSpecial, ["null"]);
|
||||
addKeywordMatches(colors.colorType, ["int", "string", "bool"]);
|
||||
addKeywordMatches(colors.colorBoolean, ["false", "true"]);
|
||||
addMatches(
|
||||
colors.colorOperator,
|
||||
new RegExp(
|
||||
`(${
|
||||
[
|
||||
"\\+=",
|
||||
"\\-=",
|
||||
"\\+",
|
||||
"\\->",
|
||||
"\\-",
|
||||
"\\*",
|
||||
"/",
|
||||
"==",
|
||||
"!=",
|
||||
"<=",
|
||||
">=",
|
||||
"=",
|
||||
"<",
|
||||
">",
|
||||
"\\.",
|
||||
"::<",
|
||||
"::",
|
||||
":",
|
||||
].map((kw) => `(?:${kw})`).join("|")
|
||||
})`,
|
||||
"g",
|
||||
),
|
||||
);
|
||||
addMatches(
|
||||
colors.colorNumber,
|
||||
/(0|(?:[1-9][0-9]*)|(?:0[0-7]+)|(?:0x[0-9a-fA-F]+)|(?:0b[01]+))/g,
|
||||
);
|
||||
addMatches(
|
||||
colors.colorFunction,
|
||||
/([a-zA-Z_]\w*(?=\())/g,
|
||||
"font-weight: 700;",
|
||||
);
|
||||
addMatches(colors.colorIdentifier, /([a-z_]\w*)/g);
|
||||
addMatches(colors.colorType, /([A-Z_]\w*)/g);
|
||||
|
||||
matches = matches.reduce<typeof matches>(
|
||||
(acc, match) =>
|
||||
acc.find((m) => m.index === match.index) === undefined
|
||||
? (acc.push(match), acc)
|
||||
: acc,
|
||||
[],
|
||||
);
|
||||
matches.sort((a, b) => a.index - b.index);
|
||||
|
||||
let highlighted = "";
|
||||
let i = 0;
|
||||
for (const match of matches) {
|
||||
if (match.index < i) {
|
||||
continue;
|
||||
}
|
||||
while (i < match.index) {
|
||||
highlighted += code[i];
|
||||
i += 1;
|
||||
}
|
||||
const section = code.slice(match.index, match.index + match.length);
|
||||
highlighted +=
|
||||
`<span style="color: ${match.color};${match.extra}">${section}</span>`;
|
||||
i += section.length;
|
||||
}
|
||||
while (i < code.length) {
|
||||
highlighted += code[i];
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return highlighted;
|
||||
}
|
||||
|
||||
function sourceCode(view: Element, codeData: string) {
|
||||
const outerContainer = document.createElement("div");
|
||||
outerContainer.classList.add("code-container");
|
||||
@ -245,7 +51,7 @@ function sourceCode(view: Element, codeData: string) {
|
||||
const code = document.createElement("pre");
|
||||
|
||||
code.classList.add("code-source");
|
||||
code.innerHTML = syntaxHighlight(codeData);
|
||||
code.innerText = codeData;
|
||||
innerContainer.append(lines, code);
|
||||
outerContainer.append(innerContainer);
|
||||
view.replaceChildren(outerContainer);
|
||||
|
@ -11,10 +11,6 @@
|
||||
--white: #ecebe9;
|
||||
--white-transparent: #ecebe9aa;
|
||||
--code-status: var(--white);
|
||||
|
||||
--code-bg: #282828;
|
||||
--code-fg: #fbf1c7;
|
||||
--code-linenr: #7c6f64;
|
||||
}
|
||||
|
||||
* {
|
||||
@ -103,21 +99,11 @@ main #cover {
|
||||
#view .code-container {
|
||||
max-height: 100%;
|
||||
overflow: scroll;
|
||||
background-color: var(--code-bg);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
#view .code-container pre {
|
||||
font-family: "Roboto Mono", monospace;
|
||||
font-weight: 500;
|
||||
color: var(--code-fg);
|
||||
}
|
||||
|
||||
#view .code-container pre.code-lines {
|
||||
color: var(--code-linenr);
|
||||
}
|
||||
|
||||
#view .code-container.code-coverage {
|
||||
max-height: calc(100% - 103px);
|
||||
}
|
||||
@ -130,6 +116,7 @@ main #cover {
|
||||
}
|
||||
|
||||
#view .code-lines {
|
||||
color: var(--white-transparent);
|
||||
border-right: 1px solid currentcolor;
|
||||
padding-right: 0.5rem;
|
||||
margin: 0;
|
||||
|
Loading…
Reference in New Issue
Block a user