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); | |
| }, | |
| }); | |