Spaces:
Running
Running
; | |
/* | |
* 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.InterpreterProxy', | |
// provides function names exactly like the C interpreter, for ease of porting | |
// but maybe less efficiently because of the indirection | |
// mostly used for plugins translated from Slang (see plugins/*.js) | |
// built-in primitives use the interpreter directly | |
'initialization', { | |
VM_PROXY_MAJOR: 1, | |
VM_PROXY_MINOR: 11, | |
initialize: function(vm) { | |
this.vm = vm; | |
this.remappableOops = []; | |
Object.defineProperty(this, 'successFlag', { | |
get: function() { return vm.primHandler.success; }, | |
set: function(success) { vm.primHandler.success = success; }, | |
}); | |
}, | |
majorVersion: function() { | |
return this.VM_PROXY_MAJOR; | |
}, | |
minorVersion: function() { | |
return this.VM_PROXY_MINOR; | |
}, | |
}, | |
'success', | |
{ | |
failed: function() { | |
return !this.successFlag; | |
}, | |
primitiveFail: function() { | |
this.successFlag = false; | |
}, | |
primitiveFailFor: function(reasonCode) { | |
this.successFlag = false; | |
}, | |
success: function(boolean) { | |
if (!boolean) this.successFlag = false; | |
}, | |
}, | |
'stack access', | |
{ | |
pop: function(n) { | |
this.vm.popN(n); | |
}, | |
popthenPush: function(n, obj) { | |
this.vm.popNandPush(n, obj); | |
}, | |
push: function(obj) { | |
this.vm.push(obj); | |
}, | |
pushBool: function(bool) { | |
this.vm.push(bool ? this.vm.trueObj : this.vm.falseObj); | |
}, | |
pushInteger: function(int) { | |
this.vm.push(int); | |
}, | |
pushFloat: function(num) { | |
this.vm.push(this.floatObjectOf(num)); | |
}, | |
stackValue: function(n) { | |
return this.vm.stackValue(n); | |
}, | |
stackIntegerValue: function(n) { | |
var int = this.vm.stackValue(n); | |
if (typeof int === "number") return int; | |
this.successFlag = false; | |
return 0; | |
}, | |
stackFloatValue: function(n) { | |
this.vm.success = true; | |
var float = this.vm.stackIntOrFloat(n); | |
if (this.vm.success) return float; | |
this.successFlag = false; | |
return 0; | |
}, | |
stackObjectValue: function(n) { | |
var obj = this.vm.stackValue(n); | |
if (typeof obj !== "number") return obj; | |
this.successFlag = false; | |
return this.vm.nilObj; | |
}, | |
stackBytes: function(n) { | |
var oop = this.vm.stackValue(n); | |
if (oop.bytes) return oop.bytes; | |
if (typeof oop === "number" || !oop.isBytes()) this.successFlag = false; | |
return []; | |
}, | |
stackWords: function(n) { | |
var oop = this.vm.stackValue(n); | |
if (oop.words) return oop.words; | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
stackInt32Array: function(n) { | |
var oop = this.vm.stackValue(n); | |
if (oop.words) return oop.wordsAsInt32Array(); | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
stackInt16Array: function(n) { | |
var oop = this.vm.stackValue(n); | |
if (oop.words) return oop.wordsAsInt16Array(); | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
stackUint16Array: function(n) { | |
var oop = this.vm.stackValue(n); | |
if (oop.words) return oop.wordsAsUint16Array(); | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
}, | |
'object access', | |
{ | |
isBytes: function(obj) { | |
return typeof obj !== "number" && obj.isBytes(); | |
}, | |
isWords: function(obj) { | |
return typeof obj !== "number" && obj.isWords(); | |
}, | |
isWordsOrBytes: function(obj) { | |
return typeof obj !== "number" && obj.isWordsOrBytes(); | |
}, | |
isPointers: function(obj) { | |
return typeof obj !== "number" && obj.isPointers(); | |
}, | |
isIntegerValue: function(obj) { | |
return typeof obj === "number" && obj >= -0x40000000 && obj <= 0x3FFFFFFF; | |
}, | |
isArray: function(obj) { | |
return obj.sqClass === this.vm.specialObjects[Squeak.splOb_ClassArray]; | |
}, | |
isMemberOf: function(obj, className) { | |
var nameBytes = obj.sqClass.pointers[Squeak.Class_name].bytes; | |
if (className.length !== nameBytes.length) return false; | |
for (var i = 0; i < className.length; i++) | |
if (className.charCodeAt(i) !== nameBytes[i]) return false; | |
return true; | |
}, | |
booleanValueOf: function(obj) { | |
if (obj.isTrue) return true; | |
if (obj.isFalse) return false; | |
this.successFlag = false; | |
return false; | |
}, | |
positive32BitValueOf: function(obj) { | |
return this.vm.primHandler.positive32BitValueOf(obj); | |
}, | |
positive32BitIntegerFor: function(int) { | |
return this.vm.primHandler.pos32BitIntFor(int); | |
}, | |
floatValueOf: function(obj) { | |
if (obj.isFloat) return obj.float; | |
this.successFlag = false; | |
return 0; | |
}, | |
floatObjectOf: function(num) { | |
return this.vm.primHandler.makeFloat(num); | |
}, | |
fetchPointerofObject: function(n, obj) { | |
return obj.pointers[n]; | |
}, | |
fetchBytesofObject: function(n, obj) { | |
var oop = obj.pointers[n]; | |
if (oop.bytes) return oop.bytes; | |
if (oop.words) return oop.wordsAsUint8Array(); | |
if (typeof oop === "number" || !oop.isWordsOrBytes()) this.successFlag = false; | |
return []; | |
}, | |
fetchWordsofObject: function(n, obj) { | |
var oop = obj.pointers[n]; | |
if (oop.words) return oop.words; | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
fetchInt32ArrayofObject: function(n, obj) { | |
var oop = obj.pointers[n]; | |
if (oop.words) return oop.wordsAsInt32Array(); | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
fetchInt16ArrayofObject: function(n, obj) { | |
var oop = obj.pointers[n]; | |
if (oop.words) return oop.wordsAsInt16Array(); | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
fetchUint16ArrayofObject: function(n, obj) { | |
var oop = obj.pointers[n]; | |
if (oop.words) return oop.wordsAsUint16Array(); | |
if (typeof oop === "number" || !oop.isWords()) this.successFlag = false; | |
return []; | |
}, | |
fetchIntegerofObject: function(n, obj) { | |
var int = obj.pointers[n]; | |
if (typeof int === "number") return int; | |
this.successFlag = false; | |
return 0; | |
}, | |
fetchLong32ofObject: function(n, obj) { | |
return obj.words[n]; | |
}, | |
fetchFloatofObject: function(n, obj) { | |
return this.floatValueOf(obj.pointers[n]); | |
}, | |
storeIntegerofObjectwithValue: function(n, obj, value) { | |
if (typeof value === "number") | |
obj.pointers[n] = value; | |
else this.successFlag = false; | |
}, | |
storePointerofObjectwithValue: function(n, obj, value) { | |
obj.pointers[n] = value; | |
}, | |
stObjectatput: function(array, index, obj) { | |
if (array.sqClass !== this.classArray()) throw Error("Array expected"); | |
if (index < 1 || index > array.pointers.length) return this.successFlag = false; | |
array.pointers[index-1] = obj; | |
}, | |
}, | |
'constant access', | |
{ | |
isKindOfInteger: function(obj) { | |
return typeof obj === "number" || | |
obj.sqClass == this.classLargeNegativeInteger() || | |
obj.sqClass == this.classLargePositiveInteger(); | |
}, | |
classArray: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassArray]; | |
}, | |
classBitmap: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassBitmap]; | |
}, | |
classSmallInteger: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassInteger]; | |
}, | |
classLargePositiveInteger: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassLargePositiveInteger]; | |
}, | |
classLargeNegativeInteger: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassLargeNegativeInteger]; | |
}, | |
classPoint: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassPoint]; | |
}, | |
classString: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassString]; | |
}, | |
classByteArray: function() { | |
return this.vm.specialObjects[Squeak.splOb_ClassByteArray]; | |
}, | |
nilObject: function() { | |
return this.vm.nilObj; | |
}, | |
falseObject: function() { | |
return this.vm.falseObj; | |
}, | |
trueObject: function() { | |
return this.vm.trueObj; | |
}, | |
}, | |
'vm functions', | |
{ | |
clone: function(object) { | |
return this.vm.image.clone(object); | |
}, | |
instantiateClassindexableSize: function(aClass, indexableSize) { | |
return this.vm.instantiateClass(aClass, indexableSize); | |
}, | |
methodArgumentCount: function() { | |
return this.argCount; | |
}, | |
makePointwithxValueyValue: function(x, y) { | |
return this.vm.primHandler.makePointWithXandY(x, y); | |
}, | |
pushRemappableOop: function(obj) { | |
this.remappableOops.push(obj); | |
}, | |
popRemappableOop: function() { | |
return this.remappableOops.pop(); | |
}, | |
showDisplayBitsLeftTopRightBottom: function(form, left, top, right, bottom) { | |
if (left < right && top < bottom) { | |
var rect = {left: left, top: top, right: right, bottom: bottom}; | |
this.vm.primHandler.displayDirty(form, rect); | |
} | |
}, | |
ioLoadFunctionFrom: function(funcName, pluginName) { | |
return this.vm.primHandler.loadFunctionFrom(funcName, pluginName); | |
}, | |
}); | |