mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-02-11 19:05:01 +00:00
Commit initial emulator register class mockup as of 2012-04-27.
This commit is contained in:
23
emulator/Pow2.html
Normal file
23
emulator/Pow2.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var x;
|
||||
var p=1;
|
||||
|
||||
document.write("pow2 = [1");
|
||||
for (x=1; x<=52; x++) {
|
||||
p += p;
|
||||
document.write(", " + p);
|
||||
}
|
||||
document.writeln("]");
|
||||
|
||||
p = 1;
|
||||
document.write("mask2 = [0");
|
||||
for (x=1; x<=52; x++) {
|
||||
p += p;
|
||||
document.write(", " + (p-1));
|
||||
}
|
||||
document.writeln("]");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
102
emulator/Register-CrockfordStyle.js
Normal file
102
emulator/Register-CrockfordStyle.js
Normal file
@@ -0,0 +1,102 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator Register.js
|
||||
* Copyright (c) 2005, Paradigm Corporation, All Rights Reserved.
|
||||
************************************************************************
|
||||
* JavaScript object definition for the generalized Register prototype.
|
||||
* Maximum register length is 52 bits, since Javascript stores numbers
|
||||
* internally as 64-bit IEEE 754 floating point numbers. All registers
|
||||
* implement unsigned arithmetic modulo their bit length.
|
||||
*
|
||||
* Constructor spec members:
|
||||
* length: size of the register in bits.
|
||||
* value: initial register value (defaults to 0).
|
||||
*
|
||||
* This constructor follows the pattern described by Douglas Crockford in
|
||||
* chapter 5 of "Javascript: the Good Parts", O'Reilly Media Inc., 2008,
|
||||
* ISBN 978-0-596-51774-8.
|
||||
************************************************************************
|
||||
* Modification Log.
|
||||
* 2012-04-28 P.Kimpel
|
||||
* Original version, from many frustrating attempts to wrap my head
|
||||
* around this technique.
|
||||
***********************************************************************/
|
||||
|
||||
var Register = function(spec, shared) {
|
||||
var that = {}; // inherits from Object.
|
||||
|
||||
// Additional private members are declared here.
|
||||
var length = // register size
|
||||
(spec.length > Register.maxBits ? Register.maxBits : spec.length);
|
||||
var modulus = Register.pow2[length];
|
||||
|
||||
var isolate = function(start, count) {
|
||||
var ue = length-start; // upper power exponent
|
||||
var le = ue-count; // lower power exponent
|
||||
|
||||
return (le > 0 ?
|
||||
Math.floor(bits/Register.pow2[lw]) % Register.pow2[count] :
|
||||
bits % Register.pow2[count]);
|
||||
}
|
||||
|
||||
var insert = function(start, count, value) {
|
||||
var ue = length-start; // upper power exponent
|
||||
var le = ue-count; // lower power exponent
|
||||
var tpower; // top portion power of 2
|
||||
var bpower = Register.pow2[le]; // bottom portion power of 2
|
||||
var top; // unaffected top portion of register
|
||||
var bottom; // unaffected bottom portion of register
|
||||
|
||||
if (start < 1) {
|
||||
top = 0;
|
||||
} else {
|
||||
tpower = Register.pow2[start];
|
||||
top = Math.floor(bits/tpower)*bpower;
|
||||
}
|
||||
if (le < 1) {
|
||||
bottom = 0;
|
||||
} else {
|
||||
bottom = bits % bpower;
|
||||
|
||||
bits = (value % Register.pow2[count])*bpower + top + bottom;
|
||||
}
|
||||
|
||||
var bitSet = function(bit) {
|
||||
insert(bit, 1, 1);
|
||||
}
|
||||
|
||||
var bitReset = function(bit) {
|
||||
insert(bit, 1, 0);
|
||||
}
|
||||
|
||||
var add = function(value) {
|
||||
bits = (bits + value) % modulus;
|
||||
}
|
||||
|
||||
var sub = function(value) {
|
||||
bits = (bits - value) % modulus;
|
||||
if (bits < 0) {
|
||||
bits = modulus-bits;
|
||||
}
|
||||
}
|
||||
|
||||
// Add any items to the shared-secrets object.
|
||||
shared = shared || {}; // create it if necessary
|
||||
|
||||
// Add public members to "that".
|
||||
that.bits = (spec.value % modulus) || 0; // register value
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
// Class constant: register maximum size
|
||||
Register.maxBits = 52;
|
||||
|
||||
// Class constant: Powers of two from 0-52
|
||||
Register.pow2 = [
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536,
|
||||
131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864,
|
||||
134217728, 268435456, 536870912, 1073741824, 2147483648, 4294967296, 8589934592,
|
||||
17179869184, 34359738368, 68719476736, 137438953472, 274877906944, 549755813888,
|
||||
1099511627776, 2199023255552, 4398046511104, 8796093022208, 17592186044416,
|
||||
35184372088832, 70368744177664, 140737488355328, 281474976710656, 562949953421312,
|
||||
1125899906842624, 2251799813685248, 4503599627370496];
|
||||
191
emulator/Register.js
Normal file
191
emulator/Register.js
Normal file
@@ -0,0 +1,191 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator Register.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT Licensed, see http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* JavaScript object definition for the generalized Register prototype.
|
||||
* Maximum register width is 52 bits, since Javascript stores numbers
|
||||
* internally as 64-bit IEEE 754 floating point numbers. All registers
|
||||
* implement unsigned arithmetic modulo their bit width.
|
||||
*
|
||||
* Constructor spec members:
|
||||
* width: size of the register in bits.
|
||||
* value: initial register value (defaults to 0).
|
||||
************************************************************************
|
||||
* Modification Log.
|
||||
* 2012-04-28 P.Kimpel
|
||||
* Original version, from many frustrating attempts to wrap my head
|
||||
* around this technique.
|
||||
***********************************************************************/
|
||||
|
||||
define(["exports", "emu/compose"], function(exports, Compose) {
|
||||
|
||||
/***********************************************************************
|
||||
* Register() supports binary registers up to 31 bits in width. Where
|
||||
* applicable, this constructor is more efficient than LongRegister(),
|
||||
* since it can use Javascript bitmask operators, which are limited to
|
||||
* operating on 32-bit SIGNED integers.
|
||||
***********************************************************************/
|
||||
var Register = Compose(function(width, value) {
|
||||
this.width = (width > this.maxBits ? this.maxBits : width);
|
||||
this.mask = Register.mask2[this.width];
|
||||
this.modulus = Register.pow2[this.width];
|
||||
this.bits = (value ? value % this.modulus : 0); // initial register value
|
||||
},{
|
||||
maxBits: 31, // maximum register size
|
||||
|
||||
isolate: function(start, width) {
|
||||
var ue = this.width-start; // upper power exponent
|
||||
var le = ue-width; // lower power exponent
|
||||
|
||||
return (le > 0 ? this.bits >>> le : this.bits) & Register.mask2[width];
|
||||
},
|
||||
|
||||
bit: function(bit) {
|
||||
var e = this.width - bit - 1;
|
||||
|
||||
return (e > 0 ? this.bits >>> e : this.bits) & 1;
|
||||
},
|
||||
|
||||
insert: function(start, width, value) {
|
||||
var ue = this.width-start; // upper power exponent
|
||||
var le = ue-width; // lower power exponent
|
||||
|
||||
this.bits = (this.bits & ((this.mask & ~Register.mask2[ue]) | Register.mask2[le])) |
|
||||
((value & Register.mask2[width]) << le);
|
||||
},
|
||||
|
||||
bitSet: function(bit) {
|
||||
this.bits |= Register.pow2[bit];
|
||||
},
|
||||
|
||||
bitReset: function(bit) {
|
||||
this.bits &= ~Register.pow2[bit];
|
||||
},
|
||||
|
||||
add: function(value) {
|
||||
var temp = this.bits + value;
|
||||
|
||||
this.bits = (temp < 0 ? (this.modulus + temp) : temp) & this.mask;
|
||||
},
|
||||
|
||||
sub: function(value) {
|
||||
var temp = this.bits - value;
|
||||
|
||||
this.bits = (temp < 0 ? (this.modulus + temp) : temp) & this.mask;
|
||||
},
|
||||
|
||||
set: function(value) {
|
||||
this.bits = (value < 0 ? -value : value) & this.mask;
|
||||
},
|
||||
|
||||
valueOf: function() {
|
||||
return this.bits;
|
||||
},
|
||||
|
||||
toString: function(radix) {
|
||||
return this.bits.toString(radix)
|
||||
}
|
||||
});
|
||||
|
||||
Register.pow2 = [ // powers of 2 from 0 to 52
|
||||
1, 2, 4, 8,
|
||||
16, 32, 64, 128,
|
||||
256, 512, 1024, 2048,
|
||||
4096, 8192, 16384, 32768,
|
||||
65536, 131072, 262144, 524288,
|
||||
1048576, 2097152, 4194304, 8388608,
|
||||
16777216, 33554432, 67108864, 134217728,
|
||||
268435456, 536870912, 1073741824, 2147483648,
|
||||
4294967296, 8589934592, 17179869184, 34359738368,
|
||||
68719476736, 137438953472, 274877906944, 549755813888,
|
||||
1099511627776, 2199023255552, 4398046511104, 8796093022208,
|
||||
17592186044416, 35184372088832, 70368744177664, 140737488355328,
|
||||
281474976710656, 562949953421312, 1125899906842624, 2251799813685248,
|
||||
4503599627370496];
|
||||
|
||||
Register.mask2 = [ // (2**n)-1 for n from 0 to 52
|
||||
0, 1, 3, 7,
|
||||
15, 31, 63, 127,
|
||||
255, 511, 1023, 2047,
|
||||
4095, 8191, 16383, 32767,
|
||||
65535, 131071, 262143, 524287,
|
||||
1048575, 2097151, 4194303, 8388607,
|
||||
16777215, 33554431, 67108863, 134217727,
|
||||
268435455, 536870911, 1073741823, 2147483647,
|
||||
4294967295, 8589934591, 17179869183, 34359738367,
|
||||
68719476735, 137438953471, 274877906943, 549755813887,
|
||||
1099511627775, 2199023255551, 4398046511103, 8796093022207,
|
||||
17592186044415, 35184372088831, 70368744177663, 140737488355327,
|
||||
281474976710655, 562949953421311, 1125899906842623, 2251799813685247,
|
||||
4503599627370495];
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* LongRegister() supports binary registers up to 52 bits in width.
|
||||
* Since Javascript bitmask operators only with up to 32 bits, this
|
||||
* contructor must use div/mod operations to manipulate the bit fields.
|
||||
***********************************************************************/
|
||||
var LongRegister = Compose(Register, {
|
||||
maxBits: 52, // maximum register size
|
||||
|
||||
isolate: function(start, width) {
|
||||
var ue = this.width-start; // upper power exponent
|
||||
var le = ue-width; // lower power exponent
|
||||
|
||||
return (le > 0 ? Math.floor(this.bits/Register.pow2[le]) : this.bits) % Register.pow2[width];
|
||||
},
|
||||
|
||||
bit: function(bit) {
|
||||
var e = this.width - bit - 1;
|
||||
|
||||
return (e > 0 ? Math.floor(this.bits/Register.pow2[e]) : this.bits) % 2;
|
||||
},
|
||||
|
||||
insert: function(start, width, value) {
|
||||
var ue = this.width-start; // upper power exponent
|
||||
var le = ue-width; // lower power exponent
|
||||
var tpower; // top portion power of 2
|
||||
var bpower = Register.pow2[le]; // bottom portion power of 2
|
||||
var top = 0; // unaffected top portion of register
|
||||
var bottom = 0; // unaffected bottom portion of register
|
||||
|
||||
if (start > 0) {
|
||||
tpower = Register.pow2[ue];
|
||||
top = Math.floor(this.bits/tpower)*tpower;
|
||||
}
|
||||
if (le > 0) {
|
||||
bottom = this.bits % bpower;
|
||||
}
|
||||
this.bits = (value % Register.pow2[width])*bpower + top + bottom;
|
||||
},
|
||||
|
||||
bitSet: function(bit) {
|
||||
this.insert(bit, 1, 1);
|
||||
},
|
||||
|
||||
bitReset: function(bit) {
|
||||
this.insert(bit, 1, 0);
|
||||
},
|
||||
|
||||
add: function(value) {
|
||||
var temp = this.bits + value;
|
||||
|
||||
this.bits = (temp < 0 ? (this.modulus + temp) : temp) % this.modulus;
|
||||
},
|
||||
|
||||
sub: function(value) {
|
||||
var temp = this.bits - value;
|
||||
|
||||
this.bits = (temp < 0 ? (this.modulus + temp) : temp) % this.modulus;
|
||||
},
|
||||
|
||||
set: function(value) {
|
||||
this.bits = (value < 0 ? -value : value) % this.modulus;
|
||||
}
|
||||
});
|
||||
|
||||
exports.Register = Register;
|
||||
exports.LongRegister = LongRegister;
|
||||
});
|
||||
51
emulator/RegisterTest.html
Normal file
51
emulator/RegisterTest.html
Normal file
@@ -0,0 +1,51 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Register Module tests</title>
|
||||
<!-- Configure Dojo first -->
|
||||
<script>
|
||||
dojoConfig = {
|
||||
parseOnLoad: false,
|
||||
packages: [
|
||||
{name: "emu", location: "http://localhost/b5500"
|
||||
}
|
||||
],
|
||||
cacheBust: false
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Load Dojo, Dijit, and DojoX resources from Google CDN -->
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js"></script>
|
||||
|
||||
<body>
|
||||
<pre id=pad>
|
||||
</pre>
|
||||
<script>
|
||||
require(["emu/Register", "dojo/dom", "dojo/domReady!"], function(reg) {
|
||||
var pad = document.getElementById("pad");
|
||||
var S = new reg.Register(15, 256);
|
||||
var A = new reg.LongRegister(48);
|
||||
|
||||
pad.innerHTML += "S=" + S.toString(8) + "\n";
|
||||
pad.innerHTML += "S.6=" + S.bit(6) + "\n";
|
||||
S.bitReset(8);
|
||||
pad.innerHTML += "S=" + S.toString(8) + "\n";
|
||||
S.insert(0, 9, 7);
|
||||
pad.innerHTML += "S=" + S.toString(8) + "\n";
|
||||
pad.innerHTML += "S.[6:3]=" + S.isolate(6, 3) + "\n";
|
||||
S.sub(449); // @701
|
||||
pad.innerHTML += "S=" + S.toString(8) + "\n";
|
||||
|
||||
|
||||
pad.innerHTML += "A=" + A.toString(8) + "\n";
|
||||
A.bitSet(45);
|
||||
pad.innerHTML += "A=" + A.toString(8) + "\n";
|
||||
pad.innerHTML += "A.45=" + A.bit(45) + "\n";
|
||||
A.insert(18, 15, 0x7fff);
|
||||
pad.innerHTML += "A=" + A.toString(8) + "\n";
|
||||
pad.innerHTML += "A.[30:4]=" + A.isolate(30,4) + "\n";
|
||||
A.sub(A.bits+1);
|
||||
pad.innerHTML += "A=" + A.toString(8) + "\n";
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
290
emulator/compose.js
Normal file
290
emulator/compose.js
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* ComposeJS, object composition for JavaScript, featuring
|
||||
* JavaScript-style prototype inheritance and composition, multiple inheritance,
|
||||
* mixin and traits-inspired conflict resolution and composition
|
||||
*/
|
||||
(function(define){
|
||||
"use strict";
|
||||
define([], function(){
|
||||
// function for creating instances from a prototype
|
||||
function Create(){
|
||||
}
|
||||
var delegate = Object.create ?
|
||||
function(proto){
|
||||
return Object.create(typeof proto == "function" ? proto.prototype : proto || Object.prototype);
|
||||
} :
|
||||
function(proto){
|
||||
Create.prototype = typeof proto == "function" ? proto.prototype : proto;
|
||||
var instance = new Create();
|
||||
Create.prototype = null;
|
||||
return instance;
|
||||
};
|
||||
function validArg(arg){
|
||||
if(!arg){
|
||||
throw new Error("Compose arguments must be functions or objects");
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
// this does the work of combining mixins/prototypes
|
||||
function mixin(instance, args, i){
|
||||
// use prototype inheritance for first arg
|
||||
var value, argsLength = args.length;
|
||||
for(; i < argsLength; i++){
|
||||
var arg = args[i];
|
||||
if(typeof arg == "function"){
|
||||
// the arg is a function, use the prototype for the properties
|
||||
var prototype = arg.prototype;
|
||||
for(var key in prototype){
|
||||
value = prototype[key];
|
||||
var own = prototype.hasOwnProperty(key);
|
||||
if(typeof value == "function" && key in instance && value !== instance[key]){
|
||||
var existing = instance[key];
|
||||
if(value == required){
|
||||
// it is a required value, and we have satisfied it
|
||||
value = existing;
|
||||
}
|
||||
else if(!own){
|
||||
// if it is own property, it is considered an explicit override
|
||||
// TODO: make faster calls on this, perhaps passing indices and caching
|
||||
if(isInMethodChain(value, key, getBases([].slice.call(args, 0, i), true))){
|
||||
// this value is in the existing method's override chain, we can use the existing method
|
||||
value = existing;
|
||||
}else if(!isInMethodChain(existing, key, getBases([arg], true))){
|
||||
// the existing method is not in the current override chain, so we are left with a conflict
|
||||
console.error("Conflicted method " + key + ", final composer must explicitly override with correct method.");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(value && value.install && own && !isInMethodChain(existing, key, getBases([arg], true))){
|
||||
// apply modifier
|
||||
value.install.call(instance, key);
|
||||
}else{
|
||||
instance[key] = value;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// it is an object, copy properties, looking for modifiers
|
||||
for(var key in validArg(arg)){
|
||||
var value = arg[key];
|
||||
if(typeof value == "function"){
|
||||
if(value.install){
|
||||
// apply modifier
|
||||
value.install.call(instance, key);
|
||||
continue;
|
||||
}
|
||||
if(key in instance){
|
||||
if(value == required){
|
||||
// required requirement met
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// add it to the instance
|
||||
instance[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
// allow for override (by es5 module)
|
||||
Compose._setMixin = function(newMixin){
|
||||
mixin = newMixin;
|
||||
};
|
||||
function isInMethodChain(method, name, prototypes){
|
||||
// searches for a method in the given prototype hierarchy
|
||||
for(var i = 0; i < prototypes.length;i++){
|
||||
var prototype = prototypes[i];
|
||||
if(prototype[name] == method){
|
||||
// found it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Decorator branding
|
||||
function Decorator(install, direct){
|
||||
function Decorator(){
|
||||
if(direct){
|
||||
return direct.apply(this, arguments);
|
||||
}
|
||||
throw new Error("Decorator not applied");
|
||||
}
|
||||
Decorator.install = install;
|
||||
return Decorator;
|
||||
}
|
||||
Compose.Decorator = Decorator;
|
||||
// aspect applier
|
||||
function aspect(handler){
|
||||
return function(advice){
|
||||
return Decorator(function install(key){
|
||||
var baseMethod = this[key];
|
||||
(advice = this[key] = baseMethod ? handler(this, baseMethod, advice) : advice).install = install;
|
||||
}, advice);
|
||||
};
|
||||
};
|
||||
// around advice, useful for calling super methods too
|
||||
Compose.around = aspect(function(target, base, advice){
|
||||
return advice.call(target, base);
|
||||
});
|
||||
Compose.before = aspect(function(target, base, advice){
|
||||
return function(){
|
||||
var results = advice.apply(this, arguments);
|
||||
if(results !== stop){
|
||||
return base.apply(this, results || arguments);
|
||||
}
|
||||
};
|
||||
});
|
||||
var stop = Compose.stop = {};
|
||||
var undefined;
|
||||
Compose.after = aspect(function(target, base, advice){
|
||||
return function(){
|
||||
var results = base.apply(this, arguments);
|
||||
var adviceResults = advice.apply(this, arguments);
|
||||
return adviceResults === undefined ? results : adviceResults;
|
||||
};
|
||||
});
|
||||
|
||||
// rename Decorator for calling super methods
|
||||
Compose.from = function(trait, fromKey){
|
||||
if(fromKey){
|
||||
return (typeof trait == "function" ? trait.prototype : trait)[fromKey];
|
||||
}
|
||||
return Decorator(function(key){
|
||||
if(!(this[key] = (typeof trait == "string" ? this[trait] :
|
||||
(typeof trait == "function" ? trait.prototype : trait)[fromKey || key]))){
|
||||
throw new Error("Source method " + fromKey + " was not available to be renamed to " + key);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Composes an instance
|
||||
Compose.create = function(base){
|
||||
// create the instance
|
||||
var instance = mixin(delegate(base), arguments, 1);
|
||||
var argsLength = arguments.length;
|
||||
// for go through the arguments and call the constructors (with no args)
|
||||
for(var i = 0; i < argsLength; i++){
|
||||
var arg = arguments[i];
|
||||
if(typeof arg == "function"){
|
||||
instance = arg.call(instance) || instance;
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
// The required function, just throws an error if not overriden
|
||||
function required(){
|
||||
throw new Error("This method is required and no implementation has been provided");
|
||||
};
|
||||
Compose.required = required;
|
||||
// get the value of |this| for direct function calls for this mode (strict in ES5)
|
||||
|
||||
function extend(){
|
||||
var args = [this];
|
||||
args.push.apply(args, arguments);
|
||||
return Compose.apply(0, args);
|
||||
}
|
||||
// Compose a constructor
|
||||
function Compose(base){
|
||||
var args = arguments;
|
||||
var prototype = (args.length < 2 && typeof args[0] != "function") ?
|
||||
args[0] : // if there is just a single argument object, just use that as the prototype
|
||||
mixin(delegate(validArg(base)), args, 1); // normally create a delegate to start with
|
||||
function Constructor(){
|
||||
var instance;
|
||||
if(this instanceof Constructor){
|
||||
// called with new operator, can proceed as is
|
||||
instance = this;
|
||||
}else{
|
||||
// we allow for direct calls without a new operator, in this case we need to
|
||||
// create the instance ourself.
|
||||
Create.prototype = prototype;
|
||||
instance = new Create();
|
||||
}
|
||||
// call all the constructors with the given arguments
|
||||
for(var i = 0; i < constructorsLength; i++){
|
||||
var constructor = constructors[i];
|
||||
var result = constructor.apply(instance, arguments);
|
||||
if(typeof result == "object"){
|
||||
if(result instanceof Constructor){
|
||||
instance = result;
|
||||
}else{
|
||||
for(var j in result){
|
||||
if(result.hasOwnProperty(j)){
|
||||
instance[j] = result[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
// create a function that can retrieve the bases (constructors or prototypes)
|
||||
Constructor._getBases = function(prototype){
|
||||
return prototype ? prototypes : constructors;
|
||||
};
|
||||
// now get the prototypes and the constructors
|
||||
var constructors = getBases(args),
|
||||
constructorsLength = constructors.length;
|
||||
if(typeof args[args.length - 1] == "object"){
|
||||
args[args.length - 1] = prototype;
|
||||
}
|
||||
var prototypes = getBases(args, true);
|
||||
Constructor.extend = extend;
|
||||
if(!Compose.secure){
|
||||
prototype.constructor = Constructor;
|
||||
}
|
||||
Constructor.prototype = prototype;
|
||||
return Constructor;
|
||||
};
|
||||
|
||||
Compose.apply = function(thisObject, args){
|
||||
// apply to the target
|
||||
return thisObject ?
|
||||
mixin(thisObject, args, 0) : // called with a target object, apply the supplied arguments as mixins to the target object
|
||||
extend.apply.call(Compose, 0, args); // get the Function.prototype apply function, call() it to apply arguments to Compose (the extend doesn't matter, just a handle way to grab apply, since we can't get it off of Compose)
|
||||
};
|
||||
Compose.call = function(thisObject){
|
||||
// call() should correspond with apply behavior
|
||||
return mixin(thisObject, arguments, 1);
|
||||
};
|
||||
|
||||
function getBases(args, prototype){
|
||||
// this function registers a set of constructors for a class, eliminating duplicate
|
||||
// constructors that may result from diamond construction for classes (B->A, C->A, D->B&C, then D() should only call A() once)
|
||||
var bases = [];
|
||||
function iterate(args, checkChildren){
|
||||
outer:
|
||||
for(var i = 0; i < args.length; i++){
|
||||
var arg = args[i];
|
||||
var target = prototype && typeof arg == "function" ?
|
||||
arg.prototype : arg;
|
||||
if(prototype || typeof arg == "function"){
|
||||
var argGetBases = checkChildren && arg._getBases;
|
||||
if(argGetBases){
|
||||
iterate(argGetBases(prototype)); // don't need to check children for these, this should be pre-flattened
|
||||
}else{
|
||||
for(var j = 0; j < bases.length; j++){
|
||||
if(target == bases[j]){
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
bases.push(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
iterate(args, true);
|
||||
return bases;
|
||||
}
|
||||
// returning the export of the module
|
||||
return Compose;
|
||||
});
|
||||
})(typeof define != "undefined" ?
|
||||
define: // AMD/RequireJS format if available
|
||||
function(deps, factory){
|
||||
if(typeof module !="undefined"){
|
||||
module.exports = factory(); // CommonJS environment, like NodeJS
|
||||
// require("./configure");
|
||||
}else{
|
||||
Compose = factory(); // raw script, assign to Compose global
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user