Skip to content

Commit

Permalink
Include more of S-corks's changes, bugfix for symtable
Browse files Browse the repository at this point in the history
  • Loading branch information
acbart committed Aug 6, 2020
1 parent 2026d37 commit 1fcc6d9
Show file tree
Hide file tree
Showing 17 changed files with 252 additions and 126 deletions.
70 changes: 4 additions & 66 deletions src/abstract.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Sk.abstr.boNameToSlotFuncLhs_ = function (obj, name) {
return obj.nb$or;
}
};
/**@suppress {checkTypes} */

Sk.abstr.boNameToSlotFuncRhs_ = function (obj, name) {
switch (name) {
case "Add":
Expand Down Expand Up @@ -126,7 +126,7 @@ Sk.abstr.boNameToSlotFuncRhs_ = function (obj, name) {
return obj.nb$reflected_or;
}
};
/**@suppress {checkTypes} */

Sk.abstr.iboNameToSlotFunc_ = function (obj, name) {
switch (name) {
case "Add":
Expand Down Expand Up @@ -612,7 +612,7 @@ Sk.abstr.objectNegative = function (obj) {
if (obj.nb$negative) {
return obj.nb$negative();
}
throw new Sk.builtin.TypeError("bad operand type for unary +: '" + Sk.abstr.typeName(obj) + "'");
throw new Sk.builtin.TypeError("bad operand type for unary -: '" + Sk.abstr.typeName(obj) + "'");
};

Sk.abstr.objectPositive = function (obj) {
Expand Down Expand Up @@ -801,68 +801,6 @@ Sk.abstr.setUpInheritance = function (childName, child, parent, metaclass) {
return child;
};

/**
* @summary
* Set up inheritance between type and object
*
* @description
* ```text
* type instanceof object => true
* object instanceof type => true
* type instanceof type => true
* object instanceof object => true
*
* type subclassof object => type.prototype instanceof object => true
* object subclassof type => object.prototype instanceof type => false
* ```
* this algorithm achieves the equivalent with the following prototypical chains
* using `Object.setPrototypeOf`
*
* ```
* type.__proto__ = type (type instanceof type)
* type.__proto__.__proto__ = object (type instanceof object)
* type.prototype.__proto__ = object (type subclassof object)
* object.__proto__ = type (object instanceof type)
* object.__proto__.__proto__ = object (object instanceof object)
* ```
*
* while `Object.setPrototypeOf` is not considered [good practice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf)
* this is a particularly unique use case and creates a lot of prototypical benefits
* all single inheritance classes (i.e. all builtins) now follow prototypical inheritance
* similarly it makes metclasses that much easier to implement
* Object.setPrototypeOf is also a feature built into the javascript language
*
* @function
* @suppress {checkTypes}
*
*/
Sk.abstr.setUpBaseInheritance = function () {
Object.setPrototypeOf(Sk.builtin.type.prototype, Sk.builtin.object.prototype);
Object.setPrototypeOf(Sk.builtin.type, Sk.builtin.type.prototype);
Object.setPrototypeOf(Sk.builtin.object, Sk.builtin.type.prototype);

// required so that type objects can be called!
Object.defineProperties(Sk.builtin.type.prototype, /**@lends {Sk.builtin.type.prototype}*/{
call: {value: Function.prototype.call},
apply: {value: Function.prototype.apply},
ob$type: {value: Sk.builtin.type, writable: true},
tp$name: {value: "type", writable: true},
tp$base: {value: Sk.builtin.object, writable: true},
sk$type: {value: true},
});
Object.defineProperties(Sk.builtin.object.prototype, /**@lends {Sk.builtin.object.prototype}*/{
ob$type: {value: Sk.builtin.object, writable: true},
tp$name: {value: "object", writable: true},
tp$base: {value: undefined, writable: true},
sk$object: {value: true},
});

Sk.builtin.object.sk$basetype = true;
Sk.builtin.type.sk$basetype = true;

Sk.abstr.setUpBuiltinMro(Sk.builtin.type);
Sk.abstr.setUpBuiltinMro(Sk.builtin.object);
};

/**
* This function is called in {@link Sk.doOneTimeInitialization}
Expand All @@ -874,7 +812,7 @@ Sk.abstr.setUpBaseInheritance = function () {
Sk.abstr.setUpBuiltinMro = function (child) {
let parent = child.prototype.tp$base || undefined;
const bases = parent === undefined ? [] : [parent];
if (parent === Sk.builtin.object) {
if (parent === Sk.builtin.object || parent === undefined) {
child.sk$basetype = true;
}
const mro = [child];
Expand Down
2 changes: 1 addition & 1 deletion src/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Sk.exportSymbol("Sk.builtin.checkComplex", Sk.builtin.checkComplex);
* @param {*} arg
*/
Sk.builtin.checkInt = function (arg) {
return arg != null && ((typeof arg === "number" && arg === (arg | 0)) || arg instanceof Sk.builtin.int_ || arg instanceof Sk.builtin.lng);
return arg instanceof Sk.builtin.int_ || (typeof arg === "number" && Number.isInteger(arg));
};
Sk.exportSymbol("Sk.builtin.checkInt", Sk.builtin.checkInt);

Expand Down
2 changes: 1 addition & 1 deletion src/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1968,7 +1968,7 @@ Compiler.prototype.buildcodeobj = function (n, coname, decorator_list, args, cal
this.u.varDeclsCode += "}";

// inject __class__ cell when running python3
if (Sk.python3 && class_for_super) {
if (Sk.__future__.python3 && class_for_super) {
this.u.varDeclsCode += "$gbl.__class__=$gbl." + class_for_super.v + ";";
}

Expand Down
4 changes: 1 addition & 3 deletions src/dict.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

/** @typedef {Sk.builtin.object} */ var pyObject;
/** @typedef {Sk.builtin.type|Function} */ var typeObject;

Expand All @@ -20,7 +19,7 @@ Sk.builtin.dict = Sk.abstr.buildNativeClass("dict", {
if (L === undefined) {
L = [];
}
Sk.asserts.assert(Array.isArray(L) && this instanceof Sk.builtin.dict, "bad call to dict constructor");
Sk.asserts.assert(Array.isArray(L) && L.length % 2 === 0 && this instanceof Sk.builtin.dict, "bad call to dict constructor");

this.size = 0;
this.entries = {};
Expand Down Expand Up @@ -321,7 +320,6 @@ Sk.builtin.dict.prototype.quick$lookup = function (pyName) {
return;
};


/**
* NB:
* We could put the following methods on the proto in the above object literal
Expand Down
8 changes: 5 additions & 3 deletions src/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,11 @@ Sk.exportSymbol("Sk.builtin.NegativePowerError", Sk.builtin.NegativePowerError);
* @param {*=} args
*/
Sk.builtin.ExternalError = function (...args) {
this.nativeError = args;
const msg = args.toString();
Sk.builtin.Exception.call(this, msg);
this.nativeError = args[0];
if (!Sk.builtin.checkString(this.nativeError)) {
args[0] = this.nativeError.toString();
}
Sk.builtin.Exception.apply(this, args);
};
Sk.abstr.setUpInheritance("ExternalError", Sk.builtin.ExternalError, Sk.builtin.Exception);
Sk.exportSymbol("Sk.builtin.ExternalError", Sk.builtin.ExternalError);
Expand Down
2 changes: 1 addition & 1 deletion src/import.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ Sk.importModuleInternal_ = function (name, dumpJS, modname, suppliedPyBody, rela
// - run module and set the module locals returned to the module __dict__
module = new Sk.builtin.module();

if (suppliedPyBody) {
if (typeof suppliedPyBody === "string") {
filename = name + ".py";
co = Sk.compile(suppliedPyBody, filename, "exec", canSuspend, true);
} else {
Expand Down
6 changes: 4 additions & 2 deletions src/int.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/**@constructor */
/**@constructor
* @ignore
*/
const JSBI = require("jsbi");

/**
Expand Down Expand Up @@ -28,7 +30,6 @@ Sk.builtin.int_ = Sk.abstr.buildNativeClass("int", {
} else {
Sk.asserts.fail("bad argument to int constructor");
}
/**@type {number|JSBI} */
this.v = v;
},
slots: /** @lends {Sk.builtin.int_.prototype}*/{
Expand Down Expand Up @@ -381,6 +382,7 @@ function compareSlot(number_func, bigint_func) {
*
* @param {function(number): number} number_func
* @param {function(JSBI): JSBI} bigint_func
* @ignore
*
*/
function numberUnarySlot(number_func, bigint_func) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/unittest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
'''


class _AssertRaisesContext(object):
class _AssertRaisesContext:
"""A context manager used to implement TestCase.assertRaises* methods."""

def __init__(self, expected, test_case):
Expand Down Expand Up @@ -66,7 +66,7 @@ def __exit__(self, exc_type, exc_value, tb):
return True


class TestCase(object):
class TestCase:
def __init__(self):
self.numPassed = 0
self.numFailed = 0
Expand Down
26 changes: 11 additions & 15 deletions src/misceval.js
Original file line number Diff line number Diff line change
Expand Up @@ -631,9 +631,9 @@ Sk.misceval.loadname = function (name, other) {
var bi;
var v = other[name];
if (v !== undefined) {
// if (typeof v === "function" && v["$d"] === undefined && v["tp$name"] === undefined) {
// return v();
// }
if (typeof v === "function" && v.sk$object === undefined) {
return v();
}
return v;
}

Expand Down Expand Up @@ -1117,7 +1117,7 @@ Sk.exportSymbol("Sk.misceval.iterFor", Sk.misceval.iterFor);
* Convert a Python iterable into a javascript array
*
* @param {pyObject} iterable
* @param {boolean=} canSuspend - Can this funciton suspend
* @param {boolean=} canSuspend - Can this function suspend
*
* @returns {!Array}
*/
Expand All @@ -1127,21 +1127,17 @@ Sk.misceval.arrayFromIterable = function (iterable, canSuspend) {
}
const hptype = iterable.hp$type || undefined;
if (hptype === undefined && iterable.sk$asarray !== undefined) {
// use sk$asarray only if we're a builtin
return iterable.sk$asarray();
}
const L = [];
const ret = Sk.misceval.iterFor(Sk.abstr.iter(iterable), (i) => {
const ret = Sk.misceval.chain(
Sk.misceval.iterFor(Sk.abstr.iter(iterable), (i) => {
L.push(i);
});
if (ret === undefined) {
return L;
} else if (canSuspend) {
return Sk.misceval.chain(ret, () => {
return L;
});
}
Sk.misceval.retryOptionalSuspensionOrThrow(ret);
return L;
}),
() => L
);
return canSuspend ? ret : Sk.misceval.retryOptionalSuspensionOrThrow(ret);
};
Sk.exportSymbol("Sk.misceval.arrayFromIterable", Sk.misceval.arrayFromIterable);

Expand Down
49 changes: 46 additions & 3 deletions src/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,51 @@ Sk.builtin.object = function object() {
Sk.asserts.assert(this instanceof Sk.builtin.object, "bad call to object, use 'new'");
};

// now that object has been created we setup the base inheritances
// between type and object
Sk.abstr.setUpBaseInheritance();
Object.defineProperties(Sk.builtin.object.prototype, /**@lends {Sk.builtin.object.prototype}*/ {
ob$type: { value: Sk.builtin.object, writable: true },
tp$name: { value: "object", writable: true },
tp$base: { value: undefined, writable: true },
sk$object: { value: true },
});

/**
* @description
* We aim to match python and javascript inheritance like
* type instanceof object => true
* object instanceof type => true
* type instanceof type => true
* object instanceof object => true
*
* type subclassof object => type.prototype instanceof object => true
* object subclassof type => object.prototype instanceof type => false
*
* this algorithm achieves the equivalent with the following prototypical chains
* using `Object.setPrototypeOf`
*
* ```
* type.__proto__ = type (type instanceof type)
* type.__proto__.__proto__ = object (type instanceof object)
* type.prototype.__proto__ = object (type subclasssof object)
* object.__proto__ = type (object instanceof type)
* object.__proto__.__proto__ = object (object instanceof object)
* ```
*
* while `Object.setPrototypeOf` is not considered [good practice](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf)
* this is a particularly unique use case and creates a lot of prototypical benefits
* all single inheritance classes (i.e. all builtins) now follow prototypical inheritance
* similarly it makes metclasses that much easier to implement
* Object.setPrototypeOf is also a feature built into the javascript language
*
* @ignore
*/
(function setUpBaseInheritance () {
Object.setPrototypeOf(Sk.builtin.type.prototype, Sk.builtin.object.prototype);
Object.setPrototypeOf(Sk.builtin.type, Sk.builtin.type.prototype);
Object.setPrototypeOf(Sk.builtin.object, Sk.builtin.type.prototype);
Sk.abstr.setUpBuiltinMro(Sk.builtin.type);
Sk.abstr.setUpBuiltinMro(Sk.builtin.object);
})();


/**
* worth noting that we don't use the new api for object since descr_objects are not yet initialized
Expand Down Expand Up @@ -41,6 +83,7 @@ Sk.builtin.object.prototype.tp$new = function (args, kwargs) {
/**
* @param {Array} args
* @param {Array=} kwargs
* @ignore
*/
Sk.builtin.object.prototype.tp$init = function (args, kwargs) {
// see cypthon object_init for algorithm details
Expand Down
1 change: 1 addition & 0 deletions src/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ Sk.builtin.frozenset = Sk.abstr.buildNativeClass("frozenset", {
/**
* @param {Array} args
* @param {Array=} kwargs
* @ignore
*/
tp$new: function (args, kwargs) {
if (this !== Sk.builtin.frozenset.prototype) {
Expand Down
Loading

0 comments on commit 1fcc6d9

Please sign in to comment.