- Source:
Classes
Members
(static) swappedOp_
for reversed comparison: Gt -> Lt, etc.
- Source:
Methods
(static) apply()
Wrap Sk.misceval.applyOrSuspend, but throw an error if we suspend
- Source:
(static) applyOrSuspend()
same as Sk.misceval.call except args is an actual array, rather than varargs.
- Source:
(static) applySlice()
return u[v:w]
- Source:
(static) arrayFromArguments()
Used by min() and max() to get an array from arbitrary input. Note that this does no validation, just coercion.
- Source:
(static) assignSlice()
u[v:w] = x
- Source:
(static) asyncToPromise()
Wraps anything that can return an Sk.misceval.Suspension, and returns a JS Promise with the result. Also takes an object map of suspension handlers: pass in {"suspType": function (susp) {} }, and your function will be called with the Suspension object if susp.type=="suspType". The type "*" will match all otherwise unhandled suspensions.
A suspension handler should return a Promise yielding the return value of r.resume() - ie, either the final return value of this call or another Suspension. That is, the null suspension handler is:
function handler(susp) {
return new Promise(function(resolve, reject) {
try {
resolve(susp.resume());
} catch(e) {
reject(e);
}
});
}
Alternatively, a handler can return null to perform the default action for that suspension type.
(Note: do not call asyncToPromise() in a suspension handler; this will create a new Promise object for each such suspension that occurs)
asyncToPromise() returns a Promise that will be resolved with the final return value, or rejected with an exception if one is thrown.
- Source:
(static) buildClass()
Constructs a class object given a code object representing the body of the class, the name of the class, and the list of bases.
There are no "old-style" classes in Skulpt, so use the user-specified metaclass (todo;) if there is one, the type of the 0th base class if there's bases, or otherwise the 'type' type.
The func code object is passed a (js) dict for its locals which it stores everything into.
The metaclass is then called as metaclass(name, bases, locals) and should return a newly constructed class object.
- Source:
(static) call(func, kwdictopt, varargseqopt, kwsopt, …args)
Notes on necessity for 'call()':
Classes are callable in python to create an instance of the class. If we're calling "C()" we cannot tell at the call site whether we're calling a standard function, or instantiating a class.
JS does not support user-level callables. So, we can't use the normal prototype hierarchy to make the class inherit from a 'class' type where the various tp$getattr, etc. methods would live.
Instead, we must copy all the methods from the prototype of our class type onto every instance of the class constructor function object. That way, both "C()" and "C.tp$getattr(...)" can still work. This is of course quite expensive.
The alternative would be to indirect all calls (whether classes or regular functions) through something like C.$call(...). In the case of class construction, $call could then call the constructor after munging arguments to pass them on. This would impose a penalty on regular function calls unfortunately, as they would have to do the same thing.
Note that the same problem exists for function objects too (a "def" creates a function object that also has properties). It just happens that attributes on classes in python are much more useful and common that the attributes on functions.
Also note, that for full python compatibility we have to do the $call method because any python object could have a call method which makes the python object callable too. So, unless we were to make all objects simply (function(){...}) and use the dict to create hierarchy, there would be no way to call that python user function. I think I'm prepared to sacrifice call support, or only support it post-ECMA5 or something.
Is using (function(){...}) as the only object type too crazy? Probably. Better or worse than having two levels of function invocation for every function call?
For a class C' with instance
inst' we have the following cases:
C.attr
C.staticmeth()
x = C.staticmeth; x()
inst = C()
inst.attr
inst.meth()
x = inst.meth; x()
inst(), where C defines a call
Because in general these are accomplished by a helper function (tp$getattr/setattr/slice/ass_slice/etc.) it seems appropriate to add a call that generally just calls through, but sometimes handles the unusual cases. Once ECMA-5 is more broadly supported we can revisit and hopefully optimize.
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
func |
Object | the thing to call |
|
kwdict |
Object |
<optional> |
**kwargs |
varargseq |
Object |
<optional> |
**args |
kws |
Object |
<optional> |
keyword args or undef |
args |
* |
<repeatable> |
stuff to pass it TODO I think all the above is out of date. |
- Source:
(static) callAsync(suspensionHandlersnullable, func, kwdictopt, varargseqopt, kwsopt, …args)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
suspensionHandlers |
Object |
<nullable> |
|
func |
Object | the thing to call |
|
kwdict |
Object |
<optional> |
**kwargs |
varargseq |
Object |
<optional> |
**args |
kws |
Object |
<optional> |
keyword args or undef |
args |
* |
<repeatable> |
stuff to pass it TODO I think all the above is out of date. |
- Source:
(static) callsim(func, …args)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
func |
Object | the thing to call |
|
args |
* |
<repeatable> |
stuff to pass it |
- Source:
(static) callsimArray(func, argsopt)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
func |
Object | the thing to call |
|
args |
Array |
<optional> |
an array of arguments to pass to the func Does the same thing as callsim without expensive call to Array.slice. Requires args to be a Javascript array. |
- Source:
(static) callsimAsync(suspensionHandlersnullable, func, …args)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
suspensionHandlers |
Object |
<nullable> |
any custom suspension handlers |
func |
Object | the thing to call |
|
args |
* |
<repeatable> |
stuff to pass it |
- Source:
(static) callsimOrSuspend(func, …args)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
func |
Object | the thing to call |
|
args |
* |
<repeatable> |
stuff to pass it |
- Source:
(static) callsimOrSuspendArray(func, argsopt)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
func |
Object | the thing to call |
|
args |
Array |
<optional> |
an array of arguments to pass to the func Does the same thing as callsimOrSuspend without expensive call to Array.slice. Requires args to be a Javascript array. |
- Source:
(static) chain(initialValue, …chainedFns)
Chain together a set of functions, each of which might return a value or an Sk.misceval.Suspension. Each function is called with the return value of the preceding function, but does not see any suspensions. If a function suspends, Sk.misceval.chain() returns a suspension that will resume the chain once an actual return value is available.
The idea is to allow a Promise-like chaining of possibly-suspending steps without repeating boilerplate suspend-and-resume code.
For example, imagine we call Sk.misceval.chain(x, f).
- If x is a value, we return f(x).
- If x is a suspension, we suspend. We will suspend and resume until we get a return value, and then we will return f(<resumed-value). This can be expanded to an arbitrary number of functions (eg Sk.misceval.chain(x, f, g), which is equivalent to chain(chain(x, f), g).)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
initialValue |
T | ||
chainedFns |
function |
<repeatable> |
- Source:
(static) isIndex(o) → {boolean}
Check if the given object is valid to use as an index. Only ints, or if the object has an __index__
method.
Parameters:
Name | Type | Description |
---|---|---|
o |
- Source:
Returns:
- Type
- boolean
(static) iterFor(iter, forFn, initialValueopt)
Perform a suspension-aware for-each on an iterator, without blowing up the stack. forFn() is called for each element in the iterator, with two arguments: the current element and the previous return value of forFn() (or initialValue on the first call). In this way, iterFor() can be used as a simple for loop, or alternatively as a 'reduce' operation. The return value of the final call to forFn() will be the return value of iterFor() (after all suspensions are resumed, that is; if the iterator is empty then initialValue will be returned.)
The iteration can be terminated early, by returning an instance of Sk.misceval.Break. If an argument is given to the Sk.misceval.Break() constructor, that value will be returned from iterFor(). It is therefore possible to use iterFor() on infinite iterators.
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
iter |
* | ||
forFn |
function | ||
initialValue |
* |
<optional> |
- Source:
(static) loadname(name, otheropt)
Parameters:
Name | Type | Attributes | Description |
---|---|---|---|
name |
string | ||
other |
Object |
<optional> |
generally globals |
- Source:
(static) promiseToSuspension()
Do the boilerplate suspension stuff.
- Source:
(static) retryOptionalSuspensionOrThrow()
Well this seems pretty obvious by the name what it should do..
- Source:
(static) richCompareBool()
- Source:
(static) tryCatch()
Catch any exceptions thrown by a function, or by resuming any suspension it returns.
var result = Sk.misceval.tryCatch(asyncFunc, function(err) {
console.log(err);
});
Because exceptions are returned asynchronously aswell you can't catch them with a try/catch. That's what this function is for.
- Source: