scratch0-5 / vm.instruction.printer.js
soiz1's picture
Upload folder using huggingface_hub
8f3f8db verified
"use strict";
/*
* Copyright (c) 2013-2025 Vanessa Freudenberg
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
Object.subclass('Squeak.InstructionPrinter',
'initialization', {
initialize: function(method, vm) {
this.method = method;
this.vm = vm;
},
},
'printing', {
printInstructions: function(indent, highlight, highlightPC) {
// all args are optional
this.indent = indent; // prepend to every line except if highlighted
this.highlight = highlight; // prepend to highlighted line
this.highlightPC = highlightPC; // PC of highlighted line
this.innerIndents = {};
this.result = '';
this.scanner = this.method.methodSignFlag()
? new Squeak.InstructionStreamSista(this.method, this.vm)
: new Squeak.InstructionStream(this.method, this.vm);
this.oldPC = this.scanner.pc;
this.endPC = 0; // adjusted while scanning
this.done = false;
try {
while (!this.done)
this.scanner.interpretNextInstructionFor(this);
} catch(ex) {
this.print("!!! " + ex.message);
}
return this.result;
},
print: function(instruction) {
if (this.oldPC === this.highlightPC) {
if (this.highlight) this.result += this.highlight;
} else {
if (this.indent) this.result += this.indent;
}
this.result += this.oldPC;
for (var i = 0; i < this.innerIndents[this.oldPC] || 0; i++)
this.result += " ";
this.result += " <";
for (var i = this.oldPC; i < this.scanner.pc; i++) {
if (i > this.oldPC) this.result += " ";
this.result += (this.method.bytes[i]+0x100).toString(16).substr(-2).toUpperCase(); // padded hex
}
this.result += "> " + instruction + "\n";
this.oldPC = this.scanner.pc;
}
},
'decoding', {
blockReturnConstant: function(obj) {
this.print('blockReturn: ' + obj.toString());
this.done = this.scanner.pc > this.endPC; // full block
},
blockReturnTop: function() {
this.print('blockReturn');
this.done = this.scanner.pc > this.endPC; // full block
},
doDup: function() {
this.print('dup');
},
doPop: function() {
this.print('pop');
},
jump: function(offset) {
this.print('jumpTo: ' + (this.scanner.pc + offset));
if (this.scanner.pc + offset > this.endPC) this.endPC = this.scanner.pc + offset;
},
jumpIf: function(condition, offset) {
this.print((condition ? 'jumpIfTrue: ' : 'jumpIfFalse: ') + (this.scanner.pc + offset));
if (this.scanner.pc + offset > this.endPC) this.endPC = this.scanner.pc + offset;
},
methodReturnReceiver: function() {
this.print('return: receiver');
this.done = this.scanner.pc > this.endPC;
},
methodReturnTop: function() {
this.print('return: topOfStack');
this.done = this.scanner.pc > this.endPC;
},
methodReturnConstant: function(obj) {
this.print('returnConst: ' + obj.toString());
this.done = this.scanner.pc > this.endPC;
},
nop: function() {
this.print('nop');
},
popIntoLiteralVariable: function(anAssociation) {
this.print('popIntoBinding: ' + anAssociation.assnKeyAsString());
},
popIntoReceiverVariable: function(offset) {
this.print('popIntoInstVar: ' + offset);
},
popIntoTemporaryVariable: function(offset) {
this.print('popIntoTemp: ' + offset);
},
pushActiveContext: function() {
this.print('push: thisContext');
},
pushConstant: function(obj) {
var value = obj.sqInstName ? obj.sqInstName() : obj.toString();
this.print('pushConst: ' + value);
},
pushLiteralVariable: function(anAssociation) {
this.print('pushBinding: ' + anAssociation.assnKeyAsString());
},
pushReceiver: function() {
this.print('push: self');
},
pushReceiverVariable: function(offset) {
this.print('pushInstVar: ' + offset);
},
pushTemporaryVariable: function(offset) {
this.print('pushTemp: ' + offset);
},
send: function(selector, numberArguments, supered) {
this.print( (supered ? 'superSend: #' : 'send: #') + (selector.bytesAsString ? selector.bytesAsString() : selector));
},
sendSuperDirected: function(selector) {
this.print('directedSuperSend: #' + (selector.bytesAsString ? selector.bytesAsString() : selector));
},
storeIntoLiteralVariable: function(anAssociation) {
this.print('storeIntoBinding: ' + anAssociation.assnKeyAsString());
},
storeIntoReceiverVariable: function(offset) {
this.print('storeIntoInstVar: ' + offset);
},
storeIntoTemporaryVariable: function(offset) {
this.print('storeIntoTemp: ' + offset);
},
pushNewArray: function(size) {
this.print('push: (Array new: ' + size + ')');
},
popIntoNewArray: function(numElements) {
this.print('pop: ' + numElements + ' into: (Array new: ' + numElements + ')');
},
pushRemoteTemp: function(offset , arrayOffset) {
this.print('push: ' + offset + ' ofTemp: ' + arrayOffset);
},
storeIntoRemoteTemp: function(offset , arrayOffset) {
this.print('storeInto: ' + offset + ' ofTemp: ' + arrayOffset);
},
popIntoRemoteTemp: function(offset , arrayOffset) {
this.print('popInto: ' + offset + ' ofTemp: ' + arrayOffset);
},
pushClosureCopy: function(numCopied, numArgs, blockSize) {
var from = this.scanner.pc,
to = from + blockSize;
this.print('closure(' + from + '-' + (to-1) + '): ' + numCopied + ' copied, ' + numArgs + ' args');
for (var i = from; i < to; i++)
this.innerIndents[i] = (this.innerIndents[i] || 0) + 1;
if (to > this.endPC) this.endPC = to;
},
pushFullClosure: function(literalIndex, numCopied, numArgs) {
this.print('pushFullClosure: (self literalAt: ' + (literalIndex + 1) + ') numCopied: ' + numCopied + ' numArgs: ' + numArgs);
},
callPrimitive: function(primitiveIndex) {
this.print('primitive: ' + primitiveIndex);
},
});