function.js.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JSDoc: Source: function.js</title>
  6. <script src="scripts/prettify/prettify.js"> </script>
  7. <script src="scripts/prettify/lang-css.js"> </script>
  8. <!--[if lt IE 9]>
  9. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  10. <![endif]-->
  11. <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
  12. <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
  13. </head>
  14. <body>
  15. <div id="main">
  16. <h1 class="page-title">Source: function.js</h1>
  17. <section>
  18. <article>
  19. <pre class="prettyprint source linenums"><code>/**
  20. * @namespace Sk.builtin
  21. */
  22. /**
  23. * Check arguments to Python functions to ensure the correct number of
  24. * arguments are passed.
  25. *
  26. * @param {string} name the name of the function
  27. * @param {Object} args the args passed to the function
  28. * @param {number} minargs the minimum number of allowable arguments
  29. * @param {number=} maxargs optional maximum number of allowable
  30. * arguments (default: Infinity)
  31. * @param {boolean=} kwargs optional true if kwargs, false otherwise
  32. * (default: false)
  33. * @param {boolean=} free optional true if free vars, false otherwise
  34. * (default: false)
  35. */
  36. Sk.builtin.pyCheckArgs = function (name, args, minargs, maxargs, kwargs, free) {
  37. var nargs = args.length;
  38. var msg = "";
  39. if (maxargs === undefined) {
  40. maxargs = Infinity;
  41. }
  42. if (kwargs) {
  43. nargs -= 1;
  44. }
  45. if (free) {
  46. nargs -= 1;
  47. }
  48. if ((nargs &lt; minargs) || (nargs > maxargs)) {
  49. if (minargs === maxargs) {
  50. msg = name + "() takes exactly " + minargs + " arguments";
  51. } else if (nargs &lt; minargs) {
  52. msg = name + "() takes at least " + minargs + " arguments";
  53. } else {
  54. msg = name + "() takes at most " + maxargs + " arguments";
  55. }
  56. msg += " (" + nargs + " given)";
  57. throw new Sk.builtin.TypeError(msg);
  58. }
  59. };
  60. goog.exportSymbol("Sk.builtin.pyCheckArgs", Sk.builtin.pyCheckArgs);
  61. /**
  62. * Check type of argument to Python functions.
  63. *
  64. * @param {string} name the name of the argument
  65. * @param {string} exptype string of the expected type name
  66. * @param {boolean} check truthy if type check passes, falsy otherwise
  67. */
  68. Sk.builtin.pyCheckType = function (name, exptype, check) {
  69. if (!check) {
  70. throw new Sk.builtin.TypeError(name + " must be a " + exptype);
  71. }
  72. };
  73. goog.exportSymbol("Sk.builtin.pyCheckType", Sk.builtin.pyCheckType);
  74. Sk.builtin.checkSequence = function (arg) {
  75. return (arg !== null &amp;&amp; arg.mp$subscript !== undefined);
  76. };
  77. goog.exportSymbol("Sk.builtin.checkSequence", Sk.builtin.checkSequence);
  78. /**
  79. * Use this to test whether or not a Python object is iterable. You should **not** rely
  80. * on the presence of tp$iter on the object as a good test, as it could be a user defined
  81. * class with `__iter__` defined or ``__getitem__`` This tests for all of those cases
  82. *
  83. * @param arg {Object} A Python object
  84. * @returns {boolean} true if the object is iterable
  85. */
  86. Sk.builtin.checkIterable = function (arg) {
  87. var ret = false;
  88. if (arg !== null ) {
  89. try {
  90. ret = Sk.abstr.iter(arg);
  91. if (ret) {
  92. return true;
  93. } else {
  94. return false;
  95. }
  96. } catch (e) {
  97. if (e instanceof Sk.builtin.TypeError) {
  98. return false;
  99. } else {
  100. throw e;
  101. }
  102. }
  103. }
  104. return ret;
  105. };
  106. goog.exportSymbol("Sk.builtin.checkIterable", Sk.builtin.checkIterable);
  107. Sk.builtin.checkCallable = function (arg) {
  108. if (typeof arg === "function") {
  109. return (!(arg instanceof Sk.builtin.none) &amp;&amp; (arg.ob$type !== undefined));
  110. } else {
  111. return ((arg.tp$call !== undefined) || (arg.__call__ !== undefined));
  112. }
  113. };
  114. Sk.builtin.checkNumber = function (arg) {
  115. return (arg !== null &amp;&amp; (typeof arg === "number" ||
  116. arg instanceof Sk.builtin.int_ ||
  117. arg instanceof Sk.builtin.float_ ||
  118. arg instanceof Sk.builtin.lng));
  119. };
  120. goog.exportSymbol("Sk.builtin.checkNumber", Sk.builtin.checkNumber);
  121. /**
  122. * Checks for complex type, delegates to internal method
  123. * Most skulpt users would search here!
  124. */
  125. Sk.builtin.checkComplex = function (arg) {
  126. return Sk.builtin.complex._complex_check(arg);
  127. };
  128. goog.exportSymbol("Sk.builtin.checkComplex", Sk.builtin.checkComplex);
  129. Sk.builtin.checkInt = function (arg) {
  130. return (arg !== null) &amp;&amp; ((typeof arg === "number" &amp;&amp; arg === (arg | 0)) ||
  131. arg instanceof Sk.builtin.int_ ||
  132. arg instanceof Sk.builtin.lng);
  133. };
  134. goog.exportSymbol("Sk.builtin.checkInt", Sk.builtin.checkInt);
  135. Sk.builtin.checkFloat = function (arg) {
  136. return (arg !== null) &amp;&amp; (arg instanceof Sk.builtin.float_);
  137. };
  138. goog.exportSymbol("Sk.builtin.checkFloat", Sk.builtin.checkFloat);
  139. Sk.builtin.checkString = function (arg) {
  140. return (arg !== null &amp;&amp; arg.__class__ == Sk.builtin.str);
  141. };
  142. goog.exportSymbol("Sk.builtin.checkString", Sk.builtin.checkString);
  143. Sk.builtin.checkClass = function (arg) {
  144. return (arg !== null &amp;&amp; arg.sk$type);
  145. };
  146. goog.exportSymbol("Sk.builtin.checkClass", Sk.builtin.checkClass);
  147. Sk.builtin.checkBool = function (arg) {
  148. return (arg instanceof Sk.builtin.bool);
  149. };
  150. goog.exportSymbol("Sk.builtin.checkBool", Sk.builtin.checkBool);
  151. Sk.builtin.checkNone = function (arg) {
  152. return (arg instanceof Sk.builtin.none);
  153. };
  154. goog.exportSymbol("Sk.builtin.checkNone", Sk.builtin.checkNone);
  155. Sk.builtin.checkFunction = function (arg) {
  156. return (arg !== null &amp;&amp; arg.tp$call !== undefined);
  157. };
  158. goog.exportSymbol("Sk.builtin.checkFunction", Sk.builtin.checkFunction);
  159. /**
  160. * @constructor
  161. * Sk.builtin.func
  162. *
  163. * @description
  164. * This function converts a Javascript function into a Python object that is callable. Or just
  165. * think of it as a Python function rather than a Javascript function now. This is an important
  166. * distinction in skulpt because once you have Python function you cannot just call it.
  167. * You must now use Sk.misceval.callsim to call the Python function.
  168. *
  169. * @param {Function} code the javascript implementation of this function
  170. * @param {Object=} globals the globals where this function was defined.
  171. * Can be undefined (which will be stored as null) for builtins. (is
  172. * that ok?)
  173. * @param {Object=} closure dict of free variables
  174. * @param {Object=} closure2 another dict of free variables that will be
  175. * merged into 'closure'. there's 2 to simplify generated code (one is $free,
  176. * the other is $cell)
  177. *
  178. * closure is the cell variables from the parent scope that we need to close
  179. * over. closure2 is the free variables in the parent scope that we also might
  180. * need to access.
  181. *
  182. * NOTE: co_varnames and co_name are defined by compiled code only, so we have
  183. * to access them via dict-style lookup for closure.
  184. *
  185. */
  186. Sk.builtin.func = function (code, globals, closure, closure2) {
  187. var k;
  188. this.func_code = code;
  189. this.func_globals = globals || null;
  190. if (closure2 !== undefined) {
  191. // todo; confirm that modification here can't cause problems
  192. for (k in closure2) {
  193. closure[k] = closure2[k];
  194. }
  195. }
  196. this.func_closure = closure;
  197. return this;
  198. };
  199. goog.exportSymbol("Sk.builtin.func", Sk.builtin.func);
  200. Sk.builtin.func.prototype.tp$name = "function";
  201. Sk.builtin.func.prototype.tp$descr_get = function (obj, objtype) {
  202. goog.asserts.assert(obj !== undefined &amp;&amp; objtype !== undefined);
  203. if (obj == null) {
  204. return this;
  205. }
  206. return new Sk.builtin.method(this, obj);
  207. };
  208. Sk.builtin.func.prototype.tp$call = function (args, kw) {
  209. var j;
  210. var i;
  211. var numvarnames;
  212. var varnames;
  213. var kwlen;
  214. var kwargsarr;
  215. var expectskw;
  216. var name;
  217. // note: functions expect 'this' to be globals to avoid having to
  218. // slice/unshift onto the main args
  219. if (this.func_closure) {
  220. // todo; OK to modify?
  221. args.push(this.func_closure);
  222. }
  223. expectskw = this.func_code["co_kwargs"];
  224. kwargsarr = [];
  225. if (this.func_code["no_kw"] &amp;&amp; kw) {
  226. name = (this.func_code &amp;&amp; this.func_code["co_name"] &amp;&amp; this.func_code["co_name"].v) || "&lt;native JS>";
  227. throw new Sk.builtin.TypeError(name + "() takes no keyword arguments");
  228. }
  229. if (kw) {
  230. // bind the kw args
  231. kwlen = kw.length;
  232. varnames = this.func_code["co_varnames"];
  233. numvarnames = varnames &amp;&amp; varnames.length;
  234. for (i = 0; i &lt; kwlen; i += 2) {
  235. // todo; make this a dict mapping name to offset
  236. for (j = 0; j &lt; numvarnames; ++j) {
  237. if (kw[i] === varnames[j]) {
  238. break;
  239. }
  240. }
  241. if (varnames &amp;&amp; j !== numvarnames) {
  242. args[j] = kw[i + 1];
  243. } else if (expectskw) {
  244. // build kwargs dict
  245. kwargsarr.push(new Sk.builtin.str(kw[i]));
  246. kwargsarr.push(kw[i + 1]);
  247. } else {
  248. name = (this.func_code &amp;&amp; this.func_code["co_name"] &amp;&amp; this.func_code["co_name"].v) || "&lt;native JS>";
  249. throw new Sk.builtin.TypeError(name + "() got an unexpected keyword argument '" + kw[i] + "'");
  250. }
  251. }
  252. }
  253. if (expectskw) {
  254. args.unshift(kwargsarr);
  255. }
  256. //print(JSON.stringify(args, null, 2));
  257. return this.func_code.apply(this.func_globals, args);
  258. };
  259. Sk.builtin.func.prototype.tp$getattr = function (key) {
  260. return this[key];
  261. };
  262. Sk.builtin.func.prototype.tp$setattr = function (key, value) {
  263. this[key] = value;
  264. };
  265. //todo; investigate why the other doesn't work
  266. //Sk.builtin.type.makeIntoTypeObj('function', Sk.builtin.func);
  267. Sk.builtin.func.prototype.ob$type = Sk.builtin.type.makeTypeObj("function", new Sk.builtin.func(null, null));
  268. Sk.builtin.func.prototype["$r"] = function () {
  269. var name = (this.func_code &amp;&amp; this.func_code["co_name"] &amp;&amp; this.func_code["co_name"].v) || "&lt;native JS>";
  270. return new Sk.builtin.str("&lt;function " + name + ">");
  271. };
  272. </code></pre>
  273. </article>
  274. </section>
  275. </div>
  276. <nav>
  277. <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="Sk.abstr.iter-seqIter.html">seqIter</a></li><li><a href="Sk.builtin.bool.html">bool</a></li><li><a href="Sk.builtin.float_.html">float_</a></li><li><a href="Sk.builtin.func.html">func</a></li><li><a href="Sk.builtin.int_.html">int_</a></li><li><a href="Sk.builtin.none.html">none</a></li><li><a href="Sk.builtin.NotImplemented.html">NotImplemented</a></li><li><a href="Sk.builtin.numtype.html">numtype</a></li><li><a href="Sk.builtin.object.html">object</a></li><li><a href="Sk.builtin.seqtype.html">seqtype</a></li><li><a href="Sk.misceval.Suspension.html">Suspension</a></li></ul><h3>Namespaces</h3><ul><li><a href="Sk.html">Sk</a></li><li><a href="Sk.abstr.html">abstr</a></li><li><a href="Sk.builtin.html">builtin</a></li><li><a href="Sk.ffi.html">ffi</a></li><li><a href="Sk.misceval.html">misceval</a></li></ul>
  278. </nav>
  279. <br class="clear">
  280. <footer>
  281. Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0</a> on Thu Aug 13 2015 08:14:27 GMT-0500 (CDT)
  282. </footer>
  283. <script> prettyPrint(); </script>
  284. <script src="scripts/linenumber.js"> </script>
  285. </body>
  286. </html>