Commit 0b4552c7 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbolizer] Display instruction ranges in turbolizer

Bug: v8:7327
Change-Id: I8cd57abf612393852532a695663175dff8e3a199
Reviewed-on: https://chromium-review.googlesource.com/1098955
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53713}
parent e5e15e57
...@@ -255,11 +255,12 @@ class CodeView extends View { ...@@ -255,11 +255,12 @@ class CodeView extends View {
} }
lineElement.insertBefore(lineNumberElement, lineElement.firstChild) lineElement.insertBefore(lineNumberElement, lineElement.firstChild)
// Don't add lines to source positions of not in backwardsCompatibility mode. // Don't add lines to source positions of not in backwardsCompatibility mode.
if (typeof this.source['backwardsCompatibility'] === undefined) return; if (this.source.backwardsCompatibility === true) {
for (const sourcePosition of this.sourceResolver.linetoSourcePositions(lineNumber - 1)) { for (const sourcePosition of this.sourceResolver.linetoSourcePositions(lineNumber - 1)) {
view.addHtmlElementToSourcePosition(sourcePosition, lineElement); view.addHtmlElementToSourcePosition(sourcePosition, lineElement);
} }
} }
}
deleteContent() { } deleteContent() { }
detachSelection() { return null; } detachSelection() { return null; }
......
...@@ -22,24 +22,34 @@ class DisassemblyView extends TextView { ...@@ -22,24 +22,34 @@ class DisassemblyView extends TextView {
return pane; return pane;
} }
constructor(parentId, broker) { constructor(parentId, broker: SelectionBroker) {
super(parentId, broker, null); super(parentId, broker, null);
let view = this; let view = this;
const sourceResolver = broker.sourceResolver;
let ADDRESS_STYLE = { let ADDRESS_STYLE = {
css: 'tag', css: 'tag',
assignSourcePosition: function (text) {
return SOURCE_POSITION_HEADER_STYLE.currentSourcePosition;
},
linkHandler: function (text, fragment) { linkHandler: function (text, fragment) {
if (fragment.sourcePosition === undefined) return undefined; const matches = text.match(/0x[0-9a-f]{8,16}\s*(?<offset>[0-9a-f]+)/);
const offset = Number.parseInt(matches.groups["offset"], 16);
if (!Number.isNaN(offset)) {
const [nodes, blockId] = sourceResolver.nodesForPCOffset(offset)
console.log("nodes for", offset, offset.toString(16), " are ", nodes);
if (nodes.length > 0) {
for (const nodeId of nodes) {
view.addHtmlElementForNodeId(nodeId, fragment);
}
return (e) => { return (e) => {
console.log(offset, nodes);
e.stopPropagation(); e.stopPropagation();
if (!e.shiftKey) { if (!e.shiftKey) {
view.sourcePositionSelectionHandler.clear(); view.selectionHandler.clear();
} }
view.sourcePositionSelectionHandler.select([fragment.sourcePosition], true); view.selectionHandler.select(nodes, true);
}; };
} }
}
return undefined;
}
}; };
let ADDRESS_LINK_STYLE = { let ADDRESS_LINK_STYLE = {
css: 'tag' css: 'tag'
...@@ -82,27 +92,18 @@ class DisassemblyView extends TextView { ...@@ -82,27 +92,18 @@ class DisassemblyView extends TextView {
} }
}; };
const SOURCE_POSITION_HEADER_STYLE = { const SOURCE_POSITION_HEADER_STYLE = {
css: 'com', css: 'com'
currentSourcePosition: undefined,
sourcePosition: function (text) {
let matches = view.SOURCE_POSITION_HEADER_REGEX.exec(text);
if (!matches) return undefined;
const scriptOffset = Number(matches[3]);
const inliningId = matches[1] === 'not inlined' ? -1 : Number(matches[2]);
const sp = { scriptOffset: scriptOffset, inliningId: inliningId };
SOURCE_POSITION_HEADER_STYLE.currentSourcePosition = sp;
return sp;
},
}; };
view.SOURCE_POSITION_HEADER_REGEX = /^\s*--[^<]*<.*(not inlined|inlined\((\d+)\)):(\d+)>\s*--/; view.SOURCE_POSITION_HEADER_REGEX = /^\s*--[^<]*<.*(not inlined|inlined\((\d+)\)):(\d+)>\s*--/;
let patterns = [ let patterns = [
[ [
[/^0x[0-9a-f]{8,16}/, ADDRESS_STYLE, 1], [/^0x[0-9a-f]{8,16}\s*[0-9a-f]+\ /, ADDRESS_STYLE, 1],
[view.SOURCE_POSITION_HEADER_REGEX, SOURCE_POSITION_HEADER_STYLE, -1], [view.SOURCE_POSITION_HEADER_REGEX, SOURCE_POSITION_HEADER_STYLE, -1],
[/^\s+-- B\d+ start.*/, BLOCK_HEADER_STYLE, -1], [/^\s+-- B\d+ start.*/, BLOCK_HEADER_STYLE, -1],
[/^.*/, UNCLASSIFIED_STYLE, -1] [/^.*/, UNCLASSIFIED_STYLE, -1]
], ],
[ [
[/^\s+[0-9a-f]+\s+/, NUMBER_STYLE, 2],
[/^\s+[0-9a-f]+\s+[0-9a-f]+\s+/, NUMBER_STYLE, 2], [/^\s+[0-9a-f]+\s+[0-9a-f]+\s+/, NUMBER_STYLE, 2],
[/^.*/, null, -1] [/^.*/, null, -1]
], ],
......
...@@ -6,20 +6,17 @@ ...@@ -6,20 +6,17 @@
class ScheduleView extends TextView implements PhaseView { class ScheduleView extends TextView implements PhaseView {
schedule: Schedule; schedule: Schedule;
sourceResolver: SourceResolver;
createViewElement() { createViewElement() {
const pane = document.createElement('div'); const pane = document.createElement('div');
pane.setAttribute('id', "schedule"); pane.setAttribute('id', "schedule");
pane.innerHTML =
`<pre id='schedule-text-pre' class='prettyprint prettyprinted'>
<ul id='schedule-list' class='nolinenums noindent'>
</ul>
</pre>`;
return pane; return pane;
} }
constructor(parentId, broker) { constructor(parentId, broker) {
super(parentId, broker, null); super(parentId, broker, null);
this.sourceResolver = broker.sourceResolver;
} }
attachSelection(s) { attachSelection(s) {
...@@ -27,19 +24,29 @@ class ScheduleView extends TextView implements PhaseView { ...@@ -27,19 +24,29 @@ class ScheduleView extends TextView implements PhaseView {
if (!(s instanceof Set)) return; if (!(s instanceof Set)) return;
view.selectionHandler.clear(); view.selectionHandler.clear();
view.blockSelectionHandler.clear(); view.blockSelectionHandler.clear();
view.sourcePositionSelectionHandler.clear();
const selected = new Array(); const selected = new Array();
for (const key of s) selected.push(key); for (const key of s) selected.push(key);
view.selectionHandler.select(selected, true); view.selectionHandler.select(selected, true);
} }
detachSelection() {
this.blockSelection.clear();
return this.selection.detachSelection();
}
initializeContent(data, rememberedSelection) {
this.divNode.innerHTML = '';
this.schedule = data.schedule
this.addBlocks(data.schedule.blocks);
this.attachSelection(rememberedSelection);
}
createElementFromString(htmlString) { createElementFromString(htmlString) {
var div = document.createElement('div'); var div = document.createElement('div');
div.innerHTML = htmlString.trim(); div.innerHTML = htmlString.trim();
return div.firstChild; return div.firstChild;
} }
elementForBlock(block) { elementForBlock(block) {
const view = this; const view = this;
function createElement(tag: string, cls: string | Array<string>, content?: string) { function createElement(tag: string, cls: string | Array<string>, content?: string) {
...@@ -63,8 +70,31 @@ class ScheduleView extends TextView implements PhaseView { ...@@ -63,8 +70,31 @@ class ScheduleView extends TextView implements PhaseView {
}; };
} }
function getMarker(start, end) {
if (start != end) {
return ["&#8857;", `This node generated instructions in range [${start},${end}). ` +
`This is currently unreliable for constants.`];
}
if (start != -1) {
return ["&#183;", `The instruction selector did not generate instructions ` +
`for this node, but processed the node at instruction ${start}. ` +
`This usually means that this node was folded into another node; ` +
`the highlighted machine code is a guess.`];
}
return ["", `This not is not in the final schedule.`]
}
function createElementForNode(node) { function createElementForNode(node) {
const nodeEl = createElement("div", "node"); const nodeEl = createElement("div", "node");
const [start, end] = view.sourceResolver.getInstruction(node.id);
const [marker, tooltip] = getMarker(start, end);
const instrMarker = createElement("div", ["instr-marker", "com"], marker);
instrMarker.setAttribute("title", tooltip);
instrMarker.onclick = mkNodeLinkHandler(node.id);
nodeEl.appendChild(instrMarker);
const node_id = createElement("div", ["node-id", "tag", "clickable"], node.id); const node_id = createElement("div", ["node-id", "tag", "clickable"], node.id);
node_id.onclick = mkNodeLinkHandler(node.id); node_id.onclick = mkNodeLinkHandler(node.id);
view.addHtmlElementForNodeId(node.id, node_id); view.addHtmlElementForNodeId(node.id, node_id);
...@@ -81,6 +111,7 @@ class ScheduleView extends TextView implements PhaseView { ...@@ -81,6 +111,7 @@ class ScheduleView extends TextView implements PhaseView {
} }
nodeEl.appendChild(node_parameters); nodeEl.appendChild(node_parameters);
} }
return nodeEl; return nodeEl;
} }
...@@ -95,6 +126,13 @@ class ScheduleView extends TextView implements PhaseView { ...@@ -95,6 +126,13 @@ class ScheduleView extends TextView implements PhaseView {
} }
const schedule_block = createElement("div", "schedule-block"); const schedule_block = createElement("div", "schedule-block");
const [start, end] = view.sourceResolver.getInstructionRangeForBlock(block.id);
const instrMarker = createElement("div", ["instr-marker", "com"], "&#8857;");
instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`)
instrMarker.onclick = mkBlockLinkHandler(block.id);
schedule_block.appendChild(instrMarker);
const block_id = createElement("div", ["block-id", "com", "clickable"], block.id); const block_id = createElement("div", ["block-id", "com", "clickable"], block.id);
block_id.onclick = mkBlockLinkHandler(block.id); block_id.onclick = mkBlockLinkHandler(block.id);
schedule_block.appendChild(block_id); schedule_block.appendChild(block_id);
...@@ -128,19 +166,6 @@ class ScheduleView extends TextView implements PhaseView { ...@@ -128,19 +166,6 @@ class ScheduleView extends TextView implements PhaseView {
} }
} }
initializeContent(data, rememberedSelection) {
this.clearText();
this.schedule = data.schedule
this.addBlocks(data.schedule.blocks);
this.attachSelection(rememberedSelection);
}
detachSelection() {
this.blockSelection.clear();
this.sourcePositionSelection.clear();
return this.selection.detachSelection();
}
lineString(node) { lineString(node) {
return `${node.id}: ${node.label}(${node.inputs.join(", ")})` return `${node.id}: ${node.label}(${node.inputs.join(", ")})`
} }
......
...@@ -84,6 +84,10 @@ class SourceResolver { ...@@ -84,6 +84,10 @@ class SourceResolver {
phaseNames: Map<string, number>; phaseNames: Map<string, number>;
disassemblyPhase: Phase; disassemblyPhase: Phase;
lineToSourcePositions: Map<string, Array<AnyPosition>>; lineToSourcePositions: Map<string, Array<AnyPosition>>;
nodeIdToInstructionRange: Array<[number, number]>;
blockIdToInstructionRange: Array<[number, number]>;
instructionToPCOffset: Array<number>;
pcOffsetToInstructions: Map<number, Array<number>>;
constructor() { constructor() {
...@@ -105,6 +109,14 @@ class SourceResolver { ...@@ -105,6 +109,14 @@ class SourceResolver {
this.disassemblyPhase = undefined; this.disassemblyPhase = undefined;
// Maps line numbers to source positions // Maps line numbers to source positions
this.lineToSourcePositions = new Map(); this.lineToSourcePositions = new Map();
// Maps node ids to instruction ranges.
this.nodeIdToInstructionRange = [];
// Maps block ids to instruction ranges.
this.blockIdToInstructionRange = [];
// Maps instruction numbers to PC offsets.
this.instructionToPCOffset = [];
// Maps PC offsets to instructions.
this.pcOffsetToInstructions = new Map();
} }
setSources(sources, mainBackup) { setSources(sources, mainBackup) {
...@@ -298,6 +310,72 @@ class SourceResolver { ...@@ -298,6 +310,72 @@ class SourceResolver {
} }
} }
readNodeIdToInstructionRange(nodeIdToInstructionRange) {
for (const [nodeId, range] of Object.entries<[number, number]>(nodeIdToInstructionRange)) {
this.nodeIdToInstructionRange[nodeId] = range;
}
}
readBlockIdToInstructionRange(blockIdToInstructionRange) {
for (const [blockId, range] of Object.entries<[number, number]>(blockIdToInstructionRange)) {
this.blockIdToInstructionRange[blockId] = range;
}
}
getInstruction(nodeId):[number, number] {
const X = this.nodeIdToInstructionRange[nodeId];
if (X === undefined) return [-1, -1];
return X;
}
getInstructionRangeForBlock(blockId):[number, number] {
const X = this.blockIdToInstructionRange[blockId];
if (X === undefined) return [-1, -1];
return X;
}
readInstructionOffsetToPCOffset(instructionToPCOffset) {
for (const [instruction, offset] of Object.entries<number>(instructionToPCOffset)) {
this.instructionToPCOffset[instruction] = offset;
if (!this.pcOffsetToInstructions.has(offset)) {
this.pcOffsetToInstructions.set(offset, []);
}
this.pcOffsetToInstructions.get(offset).push(instruction);
}
console.log(this.pcOffsetToInstructions);
}
hasPCOffsets() {
return this.pcOffsetToInstructions.size > 0;
}
nodesForPCOffset(offset): [Array<String>, Array<String>] {
const keys = Array.from(this.pcOffsetToInstructions.keys()).sort((a, b) => b - a);
if (keys.length === 0) return [[],[]];
for (const key of keys) {
if (key <= offset) {
const instrs = this.pcOffsetToInstructions.get(key);
const nodes = [];
const blocks = [];
for (const instr of instrs) {
for (const [nodeId, range] of this.nodeIdToInstructionRange.entries()) {
if (!range) continue;
const [start, end] = range;
if (start == end && instr == start) {
nodes.push("" + nodeId);
}
if (start <= instr && instr < end) {
nodes.push("" + nodeId);
}
}
}
return [nodes, blocks];
}
}
return [[],[]];
}
parsePhases(phases) { parsePhases(phases) {
for (const [phaseId, phase] of Object.entries<Phase>(phases)) { for (const [phaseId, phase] of Object.entries<Phase>(phases)) {
if (phase.type == 'disassembly') { if (phase.type == 'disassembly') {
...@@ -305,6 +383,16 @@ class SourceResolver { ...@@ -305,6 +383,16 @@ class SourceResolver {
} else if (phase.type == 'schedule') { } else if (phase.type == 'schedule') {
this.phases.push(this.parseSchedule(phase)) this.phases.push(this.parseSchedule(phase))
this.phaseNames.set(phase.name, this.phases.length); this.phaseNames.set(phase.name, this.phases.length);
} else if (phase.type == 'instructions') {
if (phase.nodeIdToInstructionRange) {
this.readNodeIdToInstructionRange(phase.nodeIdToInstructionRange);
}
if (phase.blockIdtoInstructionRange) {
this.readBlockIdToInstructionRange(phase.blockIdtoInstructionRange);
}
if (phase.instructionOffsetToPCOffset) {
this.readInstructionOffsetToPCOffset(phase.instructionOffsetToPCOffset);
}
} else { } else {
this.phases.push(phase); this.phases.push(phase);
this.recordOrigins(phase); this.recordOrigins(phase);
......
...@@ -12,14 +12,11 @@ abstract class TextView extends View { ...@@ -12,14 +12,11 @@ abstract class TextView extends View {
selectionHandler: NodeSelectionHandler; selectionHandler: NodeSelectionHandler;
blockSelectionHandler: BlockSelectionHandler; blockSelectionHandler: BlockSelectionHandler;
nodeSelectionHandler: NodeSelectionHandler; nodeSelectionHandler: NodeSelectionHandler;
sourcePositionSelectionHandler: SelectionHandler;
selection: MySelection; selection: MySelection;
blockSelection: MySelection; blockSelection: MySelection;
sourcePositionSelection: MySelection;
textListNode: HTMLUListElement; textListNode: HTMLUListElement;
nodeIdToHtmlElementsMap: Map<string, Array<HTMLElement>>; nodeIdToHtmlElementsMap: Map<string, Array<HTMLElement>>;
blockIdToHtmlElementsMap: Map<string, Array<HTMLElement>>; blockIdToHtmlElementsMap: Map<string, Array<HTMLElement>>;
sourcePositionToHtmlElementsMap: Map<string, Array<HTMLElement>>;
blockIdtoNodeIds: Map<string, Array<string>>; blockIdtoNodeIds: Map<string, Array<string>>;
nodeIdToBlockId: Array<string>; nodeIdToBlockId: Array<string>;
patterns: any; patterns: any;
...@@ -31,12 +28,10 @@ abstract class TextView extends View { ...@@ -31,12 +28,10 @@ abstract class TextView extends View {
view.patterns = patterns; view.patterns = patterns;
view.nodeIdToHtmlElementsMap = new Map(); view.nodeIdToHtmlElementsMap = new Map();
view.blockIdToHtmlElementsMap = new Map(); view.blockIdToHtmlElementsMap = new Map();
view.sourcePositionToHtmlElementsMap = new Map();
view.blockIdtoNodeIds = new Map(); view.blockIdtoNodeIds = new Map();
view.nodeIdToBlockId = []; view.nodeIdToBlockId = [];
view.selection = new MySelection(anyToString); view.selection = new MySelection(anyToString);
view.blockSelection = new MySelection(anyToString); view.blockSelection = new MySelection(anyToString);
view.sourcePositionSelection = new MySelection(sourcePositionToStringKey);
const selectionHandler = { const selectionHandler = {
clear: function () { clear: function () {
view.selection.clear(); view.selection.clear();
...@@ -45,17 +40,12 @@ abstract class TextView extends View { ...@@ -45,17 +40,12 @@ abstract class TextView extends View {
}, },
select: function (nodeIds, selected) { select: function (nodeIds, selected) {
view.selection.select(nodeIds, selected); view.selection.select(nodeIds, selected);
const blockIds = view.blockIdsForNodeIds(nodeIds);
view.blockSelection.select(blockIds, selected);
view.updateSelection(); view.updateSelection();
broker.broadcastNodeSelect(selectionHandler, view.selection.selectedKeys(), selected); broker.broadcastNodeSelect(selectionHandler, view.selection.selectedKeys(), selected);
broker.broadcastBlockSelect(view.blockSelectionHandler, blockIds, selected);
}, },
brokeredNodeSelect: function (nodeIds, selected) { brokeredNodeSelect: function (nodeIds, selected) {
const firstSelect = view.blockSelection.isEmpty(); const firstSelect = view.blockSelection.isEmpty();
view.selection.select(nodeIds, selected); view.selection.select(nodeIds, selected);
const blockIds = view.blockIdsForNodeIds(nodeIds);
view.blockSelection.select(blockIds, selected);
view.updateSelection(firstSelect); view.updateSelection(firstSelect);
}, },
brokeredClear: function () { brokeredClear: function () {
...@@ -93,29 +83,6 @@ abstract class TextView extends View { ...@@ -93,29 +83,6 @@ abstract class TextView extends View {
}; };
this.blockSelectionHandler = blockSelectionHandler; this.blockSelectionHandler = blockSelectionHandler;
broker.addBlockHandler(blockSelectionHandler); broker.addBlockHandler(blockSelectionHandler);
const sourcePositionSelectionHandler = {
clear: function () {
view.sourcePositionSelection.clear();
view.updateSelection();
broker.broadcastClear(sourcePositionSelectionHandler);
},
select: function (sourcePositions, selected) {
view.sourcePositionSelection.select(sourcePositions, selected);
view.updateSelection();
broker.broadcastSourcePositionSelect(sourcePositionSelectionHandler, sourcePositions, selected);
},
brokeredSourcePositionSelect: function (sourcePositions, selected) {
const firstSelect = view.sourcePositionSelection.isEmpty();
view.sourcePositionSelection.select(sourcePositions, selected);
view.updateSelection(firstSelect);
},
brokeredClear: function () {
view.sourcePositionSelection.clear();
view.updateSelection();
}
};
view.sourcePositionSelectionHandler = sourcePositionSelectionHandler;
broker.addSourcePositionHandler(sourcePositionSelectionHandler);
} }
addHtmlElementForNodeId(anyNodeId: any, htmlElement: HTMLElement) { addHtmlElementForNodeId(anyNodeId: any, htmlElement: HTMLElement) {
...@@ -126,14 +93,6 @@ abstract class TextView extends View { ...@@ -126,14 +93,6 @@ abstract class TextView extends View {
this.nodeIdToHtmlElementsMap.get(nodeId).push(htmlElement); this.nodeIdToHtmlElementsMap.get(nodeId).push(htmlElement);
} }
addHtmlElementForSourcePosition(sourcePosition, htmlElement) {
const key = sourcePositionToStringKey(sourcePosition);
if (!this.sourcePositionToHtmlElementsMap.has(key)) {
this.sourcePositionToHtmlElementsMap.set(key, []);
}
this.sourcePositionToHtmlElementsMap.get(key).push(htmlElement);
}
addHtmlElementForBlockId(anyBlockId, htmlElement) { addHtmlElementForBlockId(anyBlockId, htmlElement) {
const blockId = anyToString(anyBlockId); const blockId = anyToString(anyBlockId);
if (!this.blockIdToHtmlElementsMap.has(blockId)) { if (!this.blockIdToHtmlElementsMap.has(blockId)) {
...@@ -165,13 +124,6 @@ abstract class TextView extends View { ...@@ -165,13 +124,6 @@ abstract class TextView extends View {
if (this.divNode.parentNode == null) return; if (this.divNode.parentNode == null) return;
const mkVisible = new ViewElements(this.divNode.parentNode as HTMLElement); const mkVisible = new ViewElements(this.divNode.parentNode as HTMLElement);
const view = this; const view = this;
for (const [nodeId, elements] of this.nodeIdToHtmlElementsMap.entries()) {
const isSelected = view.selection.isSelected(nodeId);
for (const element of elements) {
mkVisible.consider(element, isSelected);
element.classList.toggle("selected", isSelected);
}
}
for (const [blockId, elements] of this.blockIdToHtmlElementsMap.entries()) { for (const [blockId, elements] of this.blockIdToHtmlElementsMap.entries()) {
const isSelected = view.blockSelection.isSelected(blockId); const isSelected = view.blockSelection.isSelected(blockId);
for (const element of elements) { for (const element of elements) {
...@@ -179,11 +131,17 @@ abstract class TextView extends View { ...@@ -179,11 +131,17 @@ abstract class TextView extends View {
element.classList.toggle("selected", isSelected); element.classList.toggle("selected", isSelected);
} }
} }
for (const [sourcePositionKey, elements] of this.sourcePositionToHtmlElementsMap.entries()) { for (const key of this.nodeIdToHtmlElementsMap.keys()) {
const isSelected = view.sourcePositionSelection.isKeySelected(sourcePositionKey); for (const element of this.nodeIdToHtmlElementsMap.get(key)) {
element.classList.toggle("selected", false);
}
}
for (const nodeId of view.selection.selectedKeys()) {
const elements = this.nodeIdToHtmlElementsMap.get(nodeId);
if (!elements) continue;
for (const element of elements) { for (const element of elements) {
mkVisible.consider(element, isSelected); mkVisible.consider(element, true);
element.classList.toggle("selected", isSelected); element.classList.toggle("selected", true);
} }
} }
mkVisible.apply(scrollIntoView); mkVisible.apply(scrollIntoView);
...@@ -229,19 +187,6 @@ abstract class TextView extends View { ...@@ -229,19 +187,6 @@ abstract class TextView extends View {
} }
} }
if (typeof style.sourcePosition === 'function') {
const sourcePosition = style.sourcePosition(text);
if (sourcePosition != undefined) {
fragment.sourcePosition = sourcePosition;
//this.addHtmlElementForNodeId(nodeId, fragment);
}
}
if (typeof style.assignSourcePosition === 'function') {
fragment.sourcePosition = style.assignSourcePosition();
this.addHtmlElementForSourcePosition(fragment.sourcePosition, fragment)
}
if (typeof style.assignBlockId === 'function') { if (typeof style.assignBlockId === 'function') {
fragment.blockId = style.assignBlockId(); fragment.blockId = style.assignBlockId();
this.addNodeIdToBlockId(fragment.nodeId, fragment.blockId); this.addNodeIdToBlockId(fragment.nodeId, fragment.blockId);
...@@ -310,7 +255,7 @@ abstract class TextView extends View { ...@@ -310,7 +255,7 @@ abstract class TextView extends View {
for (let line of textLines) { for (let line of textLines) {
let li = document.createElement("LI"); let li = document.createElement("LI");
li.className = "nolinenums"; li.className = "nolinenums";
li.lineNo = lineNo++; li.dataset.lineNo = "" + lineNo++;
let fragments = view.processLine(line); let fragments = view.processLine(line);
for (let fragment of fragments) { for (let fragment of fragments) {
li.appendChild(fragment); li.appendChild(fragment);
......
...@@ -487,17 +487,20 @@ text { ...@@ -487,17 +487,20 @@ text {
#schedule { #schedule {
font-family: monospace; font-family: monospace;
margin-top: 50px;
} }
.schedule-block { .schedule-block {
margin: 5px; margin: 5px;
background-color: white; background-color: white;
padding-left: 5px;
} }
.schedule-block .block-id { .schedule-block .block-id {
display: inline-block; display: inline-block;
font-size:large; font-size:large;
text-decoration: underline; text-decoration: underline;
padding-left: 1ex;
} }
.schedule-block .block-id:hover { .schedule-block .block-id:hover {
...@@ -538,10 +541,6 @@ text { ...@@ -538,10 +541,6 @@ text {
padding-right: 1ex; padding-right: 1ex;
} }
.schedule-block .nodes {
padding-left: 5px;
}
.schedule-block .nodes .node * { .schedule-block .nodes .node * {
display:inline-block; display:inline-block;
} }
...@@ -568,6 +567,18 @@ text { ...@@ -568,6 +567,18 @@ text {
content: ")"; content: ")";
} }
.schedule-block .instr-marker {
padding-right: .5ex;
padding-left: .5ex;
min-width: 1ex;
background: #EEEEEE;
/* display: none; */
}
.schedule-block > .instr-marker {
display: inline;
}
.clickable:hover { .clickable:hover {
text-decoration: underline; text-decoration: underline;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment