developer.html 100 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6. <meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" />
  7. <title></title>
  8. <style type="text/css">
  9. /*
  10. :Author: David Goodger (goodger@python.org)
  11. :Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
  12. :Copyright: This stylesheet has been placed in the public domain.
  13. Default cascading style sheet for the HTML output of Docutils.
  14. See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
  15. customize this style sheet.
  16. */
  17. /* used to remove borders from tables and images */
  18. .borderless, table.borderless td, table.borderless th {
  19. border: 0 }
  20. table.borderless td, table.borderless th {
  21. /* Override padding for "table.docutils td" with "! important".
  22. The right padding separates the table cells. */
  23. padding: 0 0.5em 0 0 ! important }
  24. .first {
  25. /* Override more specific margin styles with "! important". */
  26. margin-top: 0 ! important }
  27. .last, .with-subtitle {
  28. margin-bottom: 0 ! important }
  29. .hidden {
  30. display: none }
  31. a.toc-backref {
  32. text-decoration: none ;
  33. color: black }
  34. blockquote.epigraph {
  35. margin: 2em 5em ; }
  36. dl.docutils dd {
  37. margin-bottom: 0.5em }
  38. object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
  39. overflow: hidden;
  40. }
  41. /* Uncomment (and remove this text!) to get bold-faced definition list terms
  42. dl.docutils dt {
  43. font-weight: bold }
  44. */
  45. div.abstract {
  46. margin: 2em 5em }
  47. div.abstract p.topic-title {
  48. font-weight: bold ;
  49. text-align: center }
  50. div.admonition, div.attention, div.caution, div.danger, div.error,
  51. div.hint, div.important, div.note, div.tip, div.warning {
  52. margin: 2em ;
  53. border: medium outset ;
  54. padding: 1em }
  55. div.admonition p.admonition-title, div.hint p.admonition-title,
  56. div.important p.admonition-title, div.note p.admonition-title,
  57. div.tip p.admonition-title {
  58. font-weight: bold ;
  59. font-family: sans-serif }
  60. div.attention p.admonition-title, div.caution p.admonition-title,
  61. div.danger p.admonition-title, div.error p.admonition-title,
  62. div.warning p.admonition-title, .code .error {
  63. color: red ;
  64. font-weight: bold ;
  65. font-family: sans-serif }
  66. /* Uncomment (and remove this text!) to get reduced vertical space in
  67. compound paragraphs.
  68. div.compound .compound-first, div.compound .compound-middle {
  69. margin-bottom: 0.5em }
  70. div.compound .compound-last, div.compound .compound-middle {
  71. margin-top: 0.5em }
  72. */
  73. div.dedication {
  74. margin: 2em 5em ;
  75. text-align: center ;
  76. font-style: italic }
  77. div.dedication p.topic-title {
  78. font-weight: bold ;
  79. font-style: normal }
  80. div.figure {
  81. margin-left: 2em ;
  82. margin-right: 2em }
  83. div.footer, div.header {
  84. clear: both;
  85. font-size: smaller }
  86. div.line-block {
  87. display: block ;
  88. margin-top: 1em ;
  89. margin-bottom: 1em }
  90. div.line-block div.line-block {
  91. margin-top: 0 ;
  92. margin-bottom: 0 ;
  93. margin-left: 1.5em }
  94. div.sidebar {
  95. margin: 0 0 0.5em 1em ;
  96. border: medium outset ;
  97. padding: 1em ;
  98. background-color: #ffffee ;
  99. width: 40% ;
  100. float: right ;
  101. clear: right }
  102. div.sidebar p.rubric {
  103. font-family: sans-serif ;
  104. font-size: medium }
  105. div.system-messages {
  106. margin: 5em }
  107. div.system-messages h1 {
  108. color: red }
  109. div.system-message {
  110. border: medium outset ;
  111. padding: 1em }
  112. div.system-message p.system-message-title {
  113. color: red ;
  114. font-weight: bold }
  115. div.topic {
  116. margin: 2em }
  117. h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
  118. h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  119. margin-top: 0.4em }
  120. h1.title {
  121. text-align: center }
  122. h2.subtitle {
  123. text-align: center }
  124. hr.docutils {
  125. width: 75% }
  126. img.align-left, .figure.align-left, object.align-left {
  127. clear: left ;
  128. float: left ;
  129. margin-right: 1em }
  130. img.align-right, .figure.align-right, object.align-right {
  131. clear: right ;
  132. float: right ;
  133. margin-left: 1em }
  134. img.align-center, .figure.align-center, object.align-center {
  135. display: block;
  136. margin-left: auto;
  137. margin-right: auto;
  138. }
  139. .align-left {
  140. text-align: left }
  141. .align-center {
  142. clear: both ;
  143. text-align: center }
  144. .align-right {
  145. text-align: right }
  146. /* reset inner alignment in figures */
  147. div.align-right {
  148. text-align: inherit }
  149. /* div.align-center * { */
  150. /* text-align: left } */
  151. ol.simple, ul.simple {
  152. margin-bottom: 1em }
  153. ol.arabic {
  154. list-style: decimal }
  155. ol.loweralpha {
  156. list-style: lower-alpha }
  157. ol.upperalpha {
  158. list-style: upper-alpha }
  159. ol.lowerroman {
  160. list-style: lower-roman }
  161. ol.upperroman {
  162. list-style: upper-roman }
  163. p.attribution {
  164. text-align: right ;
  165. margin-left: 50% }
  166. p.caption {
  167. font-style: italic }
  168. p.credits {
  169. font-style: italic ;
  170. font-size: smaller }
  171. p.label {
  172. white-space: nowrap }
  173. p.rubric {
  174. font-weight: bold ;
  175. font-size: larger ;
  176. color: maroon ;
  177. text-align: center }
  178. p.sidebar-title {
  179. font-family: sans-serif ;
  180. font-weight: bold ;
  181. font-size: larger }
  182. p.sidebar-subtitle {
  183. font-family: sans-serif ;
  184. font-weight: bold }
  185. p.topic-title {
  186. font-weight: bold }
  187. pre.address {
  188. margin-bottom: 0 ;
  189. margin-top: 0 ;
  190. font: inherit }
  191. pre.literal-block, pre.doctest-block, pre.math, pre.code {
  192. margin-left: 2em ;
  193. margin-right: 2em }
  194. pre.code .ln { color: grey; } /* line numbers */
  195. pre.code, code { background-color: #eeeeee }
  196. pre.code .comment, code .comment { color: #5C6576 }
  197. pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
  198. pre.code .literal.string, code .literal.string { color: #0C5404 }
  199. pre.code .name.builtin, code .name.builtin { color: #352B84 }
  200. pre.code .deleted, code .deleted { background-color: #DEB0A1}
  201. pre.code .inserted, code .inserted { background-color: #A3D289}
  202. span.classifier {
  203. font-family: sans-serif ;
  204. font-style: oblique }
  205. span.classifier-delimiter {
  206. font-family: sans-serif ;
  207. font-weight: bold }
  208. span.interpreted {
  209. font-family: sans-serif }
  210. span.option {
  211. white-space: nowrap }
  212. span.pre {
  213. white-space: pre }
  214. span.problematic {
  215. color: red }
  216. span.section-subtitle {
  217. /* font-size relative to parent (h1..h6 element) */
  218. font-size: 80% }
  219. table.citation {
  220. border-left: solid 1px gray;
  221. margin-left: 1px }
  222. table.docinfo {
  223. margin: 2em 4em }
  224. table.docutils {
  225. margin-top: 0.5em ;
  226. margin-bottom: 0.5em }
  227. table.footnote {
  228. border-left: solid 1px black;
  229. margin-left: 1px }
  230. table.docutils td, table.docutils th,
  231. table.docinfo td, table.docinfo th {
  232. padding-left: 0.5em ;
  233. padding-right: 0.5em ;
  234. vertical-align: top }
  235. table.docutils th.field-name, table.docinfo th.docinfo-name {
  236. font-weight: bold ;
  237. text-align: left ;
  238. white-space: nowrap ;
  239. padding-left: 0 }
  240. /* "booktabs" style (no vertical lines) */
  241. table.docutils.booktabs {
  242. border: 0px;
  243. border-top: 2px solid;
  244. border-bottom: 2px solid;
  245. border-collapse: collapse;
  246. }
  247. table.docutils.booktabs * {
  248. border: 0px;
  249. }
  250. table.docutils.booktabs th {
  251. border-bottom: thin solid;
  252. text-align: left;
  253. }
  254. h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
  255. h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  256. font-size: 100% }
  257. ul.auto-toc {
  258. list-style-type: none }
  259. </style>
  260. </head>
  261. <body>
  262. <div class="document">
  263. <div class="section" id="some-things-you-need-to-know-to-hack-on-skulpt">
  264. <h1>Some things you need to know to hack on Skulpt</h1>
  265. <p>Skulpt is a pretty complex system, and there is very little documentation about the core concepts in skulpt. This document is an attempt to create document answers to important questions developers might have who want to start hacking on skulpt.</p>
  266. <p>I started this document in response to issue #182 (thanks &#64;mseddon). Please check that issue and feel free to contribute to the discussion there.</p>
  267. <div class="section" id="the-source">
  268. <h2>The Source</h2>
  269. <p>The src directory contains the javascript that implements skulpt as well as parts of the standard library. library modules are in src/lib. The source files could roughly be divided into two pieces. The compiler and the runtime. The compiler files are: <tt class="docutils literal">ast.js, parser.js, symtable.js, compile.js, and tokenize.js</tt> The compiler part of skulpt reads python code and generates a Javascript program. If you want to change the syntax of Python these are the files to look at. The syntax used in skulpt is taken right from the Python 2.6.5 distribution.</p>
  270. <p>When you run the program in the browser the javascript part is 'evaled' by javascript. The runtime files roughly correspond to all of the major object types in Python plus builtins:</p>
  271. <ul class="simple">
  272. <li>abstract.js -- contains lots of abstract function defs</li>
  273. <li>biginteger.js -- implements Python's long integer type</li>
  274. <li>bool.js</li>
  275. <li>skulpt-stdlib.js -- builtin functions: range, min, max, etc. are defined here</li>
  276. <li>builtindict.js -- Provides a mapping from the standard Python name to the internal name in skulpt-stdlib.js</li>
  277. <li>dict.js</li>
  278. <li>enumerate.js</li>
  279. <li>env.js</li>
  280. <li>errors.js -- Exceptions are defined here</li>
  281. <li>file.js</li>
  282. <li>float.js</li>
  283. <li>function.js</li>
  284. <li>generator.js</li>
  285. <li>import.js</li>
  286. <li>int.js</li>
  287. <li>list.js</li>
  288. <li>long.js</li>
  289. <li>mergesort.js -- old version of mergesort. Not used anymore -- see timsort Should be removed</li>
  290. <li>method.js</li>
  291. <li>module.js</li>
  292. <li>native.js</li>
  293. <li>number.js</li>
  294. <li>object.js -- most things &quot;inherit&quot; from object this contains source for GenericXxx functions</li>
  295. <li>set.js</li>
  296. <li>slice.js</li>
  297. <li>str.js</li>
  298. <li>timsort.js</li>
  299. <li>tuple.js</li>
  300. <li>type.js</li>
  301. </ul>
  302. <p>Perhaps one of the trickiest things to remember about Skulpt is that we are always moving back and forth between Python objects and Javascript objects. For example Python string objects have a <tt class="docutils literal">v</tt> attribute that contains the Javascript string. Numeric objects also contain a <tt class="docutils literal">v</tt> object to represent the javascript number. functions are similar, Python functions are not the same as Javascript functions, and so need to be handled differently. You can't just call a user defined python function that has been compiled to javscript and expect it to behave. Thats what <tt class="docutils literal">Sk.misceval.callsim</tt> is for. The two files below are here to make the transition back and forth from Javascript to Python more clear. Although the code tends to be inconsistent about using some of the ffi functions and you will see <tt class="docutils literal">blah.v</tt> used in many places where it would be better to use <tt class="docutils literal">Sk.ffi.unwrapo(blah)</tt>.</p>
  303. <ul class="simple">
  304. <li>ffi.js</li>
  305. <li>misceval.js</li>
  306. </ul>
  307. </div>
  308. <div class="section" id="the-generated-code">
  309. <h2>The Generated Code</h2>
  310. <p>Perhaps one of the most instructive things you can do to understand Skulpt and how the pieces begin to fit together is to look at a simple Python program, and its translation to Javscript. So lets begin with Hello World.</p>
  311. <div class="section" id="python-version">
  312. <h3>Python Version</h3>
  313. <pre class="code python literal-block">
  314. <span class="keyword">print</span> <span class="literal string">&quot;hello world&quot;</span>
  315. </pre>
  316. </div>
  317. <div class="section" id="javascript-translation">
  318. <h3>Javascript Translation</h3>
  319. <pre class="code javascript literal-block">
  320. <span class="comment multiline">/* 1 */</span> <span class="keyword declaration">var</span> <span class="name other">$scope0</span> <span class="operator">=</span> <span class="punctuation">(</span><span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">$modname</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  321. <span class="comment multiline">/* 2 */</span> <span class="keyword declaration">var</span> <span class="name other">$blk</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">,</span>
  322. <span class="comment multiline">/* 3 */</span> <span class="name other">$exc</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="punctuation">],</span>
  323. <span class="comment multiline">/* 4 */</span> <span class="name other">$gbl</span> <span class="operator">=</span> <span class="punctuation">{</span><span class="punctuation">},</span>
  324. <span class="comment multiline">/* 5 */</span> <span class="name other">$loc</span> <span class="operator">=</span> <span class="name other">$gbl</span><span class="punctuation">,</span>
  325. <span class="comment multiline">/* 6 */</span> <span class="name other">$err</span> <span class="operator">=</span> <span class="keyword constant">undefined</span><span class="punctuation">;</span>
  326. <span class="comment multiline">/* 7 */</span> <span class="name other">$gbl</span><span class="punctuation">.</span><span class="name other">__name__</span> <span class="operator">=</span> <span class="name other">$modname</span><span class="punctuation">;</span>
  327. <span class="comment multiline">/* 8 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">globals</span> <span class="operator">=</span> <span class="name other">$gbl</span><span class="punctuation">;</span>
  328. <span class="comment multiline">/* 9 */</span> <span class="keyword">try</span> <span class="punctuation">{</span>
  329. <span class="comment multiline">/* 10 */</span> <span class="keyword">while</span> <span class="punctuation">(</span><span class="keyword constant">true</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  330. <span class="comment multiline">/* 11 */</span> <span class="keyword">try</span> <span class="punctuation">{</span>
  331. <span class="comment multiline">/* 12 */</span> <span class="keyword">switch</span> <span class="punctuation">(</span><span class="name other">$blk</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  332. <span class="comment multiline">/* 13 */</span> <span class="keyword">case</span> <span class="literal number integer">0</span><span class="operator">:</span>
  333. <span class="comment multiline">/* 14 */</span> <span class="comment multiline">/* --- module entry --- */</span>
  334. <span class="comment multiline">/* 15 */</span> <span class="comment single">//
  335. </span><span class="comment multiline">/* 16 */</span> <span class="comment single">// line 1:
  336. </span><span class="comment multiline">/* 17 */</span> <span class="comment single">// print &quot;hello world&quot;
  337. </span><span class="comment multiline">/* 18 */</span> <span class="comment single">// ^
  338. </span><span class="comment multiline">/* 19 */</span> <span class="comment single">//
  339. </span><span class="comment multiline">/* 20 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currLineNo</span> <span class="operator">=</span> <span class="literal number integer">1</span><span class="punctuation">;</span>
  340. <span class="comment multiline">/* 21 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currColNo</span> <span class="operator">=</span> <span class="literal number integer">0</span>
  341. <span class="comment multiline">/* 22 */</span>
  342. <span class="comment multiline">/* 23 */</span>
  343. <span class="comment multiline">/* 24 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currFilename</span> <span class="operator">=</span> <span class="literal string single">'./simple.py'</span><span class="punctuation">;</span>
  344. <span class="comment multiline">/* 25 */</span>
  345. <span class="comment multiline">/* 26 */</span> <span class="keyword declaration">var</span> <span class="name other">$str1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtins</span><span class="punctuation">[</span><span class="literal string single">'str'</span><span class="punctuation">](</span><span class="literal string single">'hello world'</span><span class="punctuation">);</span>
  346. <span class="comment multiline">/* 27 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">print_</span><span class="punctuation">(</span><span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtins</span><span class="punctuation">[</span><span class="literal string single">'str'</span><span class="punctuation">](</span><span class="name other">$str1</span><span class="punctuation">).</span><span class="name other">v</span><span class="punctuation">);</span>
  347. <span class="comment multiline">/* 28 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">print_</span><span class="punctuation">(</span><span class="literal string double">&quot;\n&quot;</span><span class="punctuation">);</span>
  348. <span class="comment multiline">/* 29 */</span> <span class="keyword">return</span> <span class="name other">$loc</span><span class="punctuation">;</span>
  349. <span class="comment multiline">/* 30 */</span> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">SystemError</span><span class="punctuation">(</span><span class="literal string single">'internal error: unterminated block'</span><span class="punctuation">);</span>
  350. <span class="comment multiline">/* 31 */</span> <span class="punctuation">}</span>
  351. <span class="comment multiline">/* 32 */</span> <span class="punctuation">}</span> <span class="keyword">catch</span> <span class="punctuation">(</span><span class="name other">err</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  352. <span class="comment multiline">/* 33 */</span> <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">$exc</span><span class="punctuation">.</span><span class="name other">length</span> <span class="operator">&gt;</span> <span class="literal number integer">0</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  353. <span class="comment multiline">/* 34 */</span> <span class="name other">$err</span> <span class="operator">=</span> <span class="name other">err</span><span class="punctuation">;</span>
  354. <span class="comment multiline">/* 35 */</span> <span class="name other">$blk</span> <span class="operator">=</span> <span class="name other">$exc</span><span class="punctuation">.</span><span class="name other">pop</span><span class="punctuation">(</span><span class="punctuation">);</span>
  355. <span class="comment multiline">/* 36 */</span> <span class="keyword">continue</span><span class="punctuation">;</span>
  356. <span class="comment multiline">/* 37 */</span> <span class="punctuation">}</span> <span class="keyword">else</span> <span class="punctuation">{</span>
  357. <span class="comment multiline">/* 38 */</span> <span class="keyword">throw</span> <span class="name other">err</span><span class="punctuation">;</span>
  358. <span class="comment multiline">/* 39 */</span> <span class="punctuation">}</span>
  359. <span class="comment multiline">/* 40 */</span> <span class="punctuation">}</span>
  360. <span class="comment multiline">/* 41 */</span> <span class="punctuation">}</span>
  361. <span class="comment multiline">/* 42 */</span> <span class="punctuation">}</span> <span class="keyword">catch</span> <span class="punctuation">(</span><span class="name other">err</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  362. <span class="comment multiline">/* 43 */</span> <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">err</span> <span class="keyword">instanceof</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">SystemExit</span> <span class="operator">&amp;&amp;</span> <span class="operator">!</span><span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">throwSystemExit</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  363. <span class="comment multiline">/* 44 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">print_</span><span class="punctuation">(</span><span class="name other">err</span><span class="punctuation">.</span><span class="name other">toString</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">+</span> <span class="literal string single">'\n'</span><span class="punctuation">);</span>
  364. <span class="comment multiline">/* 45 */</span> <span class="keyword">return</span> <span class="name other">$loc</span><span class="punctuation">;</span>
  365. <span class="comment multiline">/* 46 */</span> <span class="punctuation">}</span> <span class="keyword">else</span> <span class="punctuation">{</span>
  366. <span class="comment multiline">/* 47 */</span> <span class="keyword">throw</span> <span class="name other">err</span><span class="punctuation">;</span>
  367. <span class="comment multiline">/* 48 */</span> <span class="punctuation">}</span>
  368. <span class="comment multiline">/* 49 */</span> <span class="punctuation">}</span>
  369. <span class="comment multiline">/* 50 */</span> <span class="punctuation">});</span>
  370. </pre>
  371. <p>So, one line of python becomes 50 lines of Javscript. Luckily lots of this is boiler plate that is the same for every program. One important convention is that variables that start with a $ are variables that are generated by the compiler. So, in the above example $scope0, $blk, $str1, etc are all generated by the compiler not by the Python program. Each line of the python program gets a corresponding entry in the Sk.currLineNo so that runtime error messages or exceptions can reference the line that caused them.</p>
  372. <p>For now lets concentrate on the parts of the code that were generated specifically for our program. That would be lines 26-29 above.</p>
  373. <ul class="simple">
  374. <li>26: The compiler creates a variable to hold the string literal &quot;hello world&quot; A Python version of the string literal is created by calling the constructor <tt class="docutils literal"><span class="pre">Sk.builtins['str']</span></tt> passing the javascript string literal.</li>
  375. <li>27: The <tt class="docutils literal">Sk.misceval.print_</tt> function is called. Here is an interesting part of the runtime. The code for <a href="#id1"><span class="problematic" id="id2">Sk.misceval.print_</span></a> is below. The key line is <tt class="docutils literal">Sk.output(s.v)</tt> <tt class="docutils literal">Sk.output</tt> is configurable to be any function that the web developer might want to provide. For example you might write a function that takes a javascript string as a parameter and updates a pre element. Or you might simply write a function that calls alert. Notice that <tt class="docutils literal">print_</tt> simply expects to get an object. It converts this object into a Python string object by once again calling the string constructor <tt class="docutils literal">Sk.builtin.str</tt>. If you've been keeping close watch, this is actually the third time our string liter has undergone this transformation. Luckily the string constructor is smart enough to simply return its parameter if the parameter is already a Python string. You might logically ask why does the compiler emit a call on line 27 when the runtime function takes care of the same issue. Not sure, maybe this is an optimization.</li>
  376. </ul>
  377. <pre class="code javascript literal-block">
  378. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">print_</span> <span class="operator">=</span> <span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">x</span><span class="punctuation">)</span> <span class="comment single">// this was function print(x) not sure why...
  379. </span><span class="punctuation">{</span>
  380. <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">softspace_</span><span class="punctuation">)</span>
  381. <span class="punctuation">{</span>
  382. <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">x</span> <span class="operator">!==</span> <span class="literal string double">&quot;\n&quot;</span><span class="punctuation">)</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">output</span><span class="punctuation">(</span><span class="literal string single">' '</span><span class="punctuation">);</span>
  383. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">softspace_</span> <span class="operator">=</span> <span class="keyword constant">false</span><span class="punctuation">;</span>
  384. <span class="punctuation">}</span>
  385. <span class="keyword declaration">var</span> <span class="name other">s</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">str</span><span class="punctuation">(</span><span class="name other">x</span><span class="punctuation">);</span>
  386. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">output</span><span class="punctuation">(</span><span class="name other">s</span><span class="punctuation">.</span><span class="name other">v</span><span class="punctuation">);</span>
  387. <span class="keyword declaration">var</span> <span class="name other">isspace</span> <span class="operator">=</span> <span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">c</span><span class="punctuation">)</span>
  388. <span class="punctuation">{</span>
  389. <span class="keyword">return</span> <span class="name other">c</span> <span class="operator">===</span> <span class="literal string single">'\n'</span> <span class="operator">||</span> <span class="name other">c</span> <span class="operator">===</span> <span class="literal string single">'\t'</span> <span class="operator">||</span> <span class="name other">c</span> <span class="operator">===</span> <span class="literal string single">'\r'</span><span class="punctuation">;</span>
  390. <span class="punctuation">};</span>
  391. <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">s</span><span class="punctuation">.</span><span class="name other">v</span><span class="punctuation">.</span><span class="name other">length</span> <span class="operator">===</span> <span class="literal number integer">0</span> <span class="operator">||</span> <span class="operator">!</span><span class="name other">isspace</span><span class="punctuation">(</span><span class="name other">s</span><span class="punctuation">.</span><span class="name other">v</span><span class="punctuation">[</span><span class="name other">s</span><span class="punctuation">.</span><span class="name other">v</span><span class="punctuation">.</span><span class="name other">length</span> <span class="operator">-</span> <span class="literal number integer">1</span><span class="punctuation">])</span> <span class="operator">||</span> <span class="name other">s</span><span class="punctuation">.</span><span class="name other">v</span><span class="punctuation">[</span><span class="name other">s</span><span class="punctuation">.</span><span class="name other">v</span><span class="punctuation">.</span><span class="name other">length</span> <span class="operator">-</span> <span class="literal number integer">1</span><span class="punctuation">]</span> <span class="operator">===</span> <span class="literal string single">' '</span><span class="punctuation">)</span>
  392. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">softspace_</span> <span class="operator">=</span> <span class="keyword constant">true</span><span class="punctuation">;</span>
  393. <span class="punctuation">};</span>
  394. </pre>
  395. <ul class="simple">
  396. <li>28: print always results in a newline. So do it.</li>
  397. <li>29: done return. This gets us out of the while(true) loop.</li>
  398. </ul>
  399. </div>
  400. </div>
  401. <div class="section" id="naming-conventions">
  402. <h2>Naming Conventions</h2>
  403. <ul class="simple">
  404. <li><tt class="docutils literal">Sk</tt> The <tt class="docutils literal">Sk</tt> object contains all of the core Skulpt objects and functions. Its pretty easy to get from Sk.blah to its source. Usually you will see something like <tt class="docutils literal">Sk.builtin.foo</tt> which indicates that you should look in <tt class="docutils literal"><span class="pre">skulpt-stdlib.js</span></tt> to find the source for foo. Similarly <tt class="docutils literal">Sk.misceval.callsim</tt> tells you that you should look in <tt class="docutils literal">misceval.js</tt> for the callsim function.</li>
  405. <li>$xxx represents a compiler generated variable</li>
  406. <li>tp$xxx These things represent the <tt class="docutils literal">magic methods</tt> for an object that are defined by the Skulpt system itself. So for example <tt class="docutils literal">__str__</tt> is called <tt class="docutils literal">tp$str</tt>. I always think of tp as a mnemonic for type.</li>
  407. <li>mp$xxx similar to tp but for sequences. As best as I know these are almost always related to subscripts.</li>
  408. </ul>
  409. <p>Ok, lets look at a slightly more complex example:</p>
  410. <div class="section" id="python">
  411. <h3>Python</h3>
  412. <pre class="code python literal-block">
  413. <span class="name">x</span> <span class="operator">=</span> <span class="literal number integer">1</span>
  414. <span class="name">y</span> <span class="operator">=</span> <span class="literal number integer">2</span>
  415. <span class="name">z</span> <span class="operator">=</span> <span class="name">x</span> <span class="operator">+</span> <span class="name">y</span>
  416. <span class="keyword">print</span> <span class="name">z</span>
  417. </pre>
  418. </div>
  419. <div class="section" id="javascript">
  420. <h3>Javascript</h3>
  421. <pre class="code javascript literal-block">
  422. <span class="comment multiline">/* 1 */</span> <span class="keyword declaration">var</span> <span class="name other">$scope0</span> <span class="operator">=</span> <span class="punctuation">(</span><span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">$modname</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  423. <span class="comment multiline">/* 2 */</span> <span class="keyword declaration">var</span> <span class="name other">$blk</span> <span class="operator">=</span> <span class="literal number integer">0</span><span class="punctuation">,</span>
  424. <span class="comment multiline">/* 3 */</span> <span class="name other">$exc</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="punctuation">],</span>
  425. <span class="comment multiline">/* 4 */</span> <span class="name other">$gbl</span> <span class="operator">=</span> <span class="punctuation">{</span><span class="punctuation">},</span>
  426. <span class="comment multiline">/* 5 */</span> <span class="name other">$loc</span> <span class="operator">=</span> <span class="name other">$gbl</span><span class="punctuation">,</span>
  427. <span class="comment multiline">/* 6 */</span> <span class="name other">$err</span> <span class="operator">=</span> <span class="keyword constant">undefined</span><span class="punctuation">;</span>
  428. <span class="comment multiline">/* 7 */</span> <span class="name other">$gbl</span><span class="punctuation">.</span><span class="name other">__name__</span> <span class="operator">=</span> <span class="name other">$modname</span><span class="punctuation">;</span>
  429. <span class="comment multiline">/* 8 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">globals</span> <span class="operator">=</span> <span class="name other">$gbl</span><span class="punctuation">;</span>
  430. <span class="comment multiline">/* 9 */</span> <span class="keyword">try</span> <span class="punctuation">{</span>
  431. <span class="comment multiline">/* 10 */</span> <span class="keyword">while</span> <span class="punctuation">(</span><span class="keyword constant">true</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  432. <span class="comment multiline">/* 11 */</span> <span class="keyword">try</span> <span class="punctuation">{</span>
  433. <span class="comment multiline">/* 12 */</span> <span class="keyword">switch</span> <span class="punctuation">(</span><span class="name other">$blk</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  434. <span class="comment multiline">/* 13 */</span> <span class="keyword">case</span> <span class="literal number integer">0</span><span class="operator">:</span>
  435. <span class="comment multiline">/* 14 */</span> <span class="comment multiline">/* --- module entry --- */</span>
  436. <span class="comment multiline">/* 15 */</span> <span class="comment single">//
  437. </span><span class="comment multiline">/* 16 */</span> <span class="comment single">// line 1:
  438. </span><span class="comment multiline">/* 17 */</span> <span class="comment single">// x = 1
  439. </span><span class="comment multiline">/* 18 */</span> <span class="comment single">// ^
  440. </span><span class="comment multiline">/* 19 */</span> <span class="comment single">//
  441. </span><span class="comment multiline">/* 20 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currLineNo</span> <span class="operator">=</span> <span class="literal number integer">1</span><span class="punctuation">;</span>
  442. <span class="comment multiline">/* 21 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currColNo</span> <span class="operator">=</span> <span class="literal number integer">0</span>
  443. <span class="comment multiline">/* 22 */</span>
  444. <span class="comment multiline">/* 23 */</span>
  445. <span class="comment multiline">/* 24 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currFilename</span> <span class="operator">=</span> <span class="literal string single">'./simple.py'</span><span class="punctuation">;</span>
  446. <span class="comment multiline">/* 25 */</span>
  447. <span class="comment multiline">/* 26 */</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">x</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">nmber</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">,</span> <span class="literal string single">'int'</span><span class="punctuation">);</span>
  448. <span class="comment multiline">/* 27 */</span> <span class="comment single">//
  449. </span><span class="comment multiline">/* 28 */</span> <span class="comment single">// line 2:
  450. </span><span class="comment multiline">/* 29 */</span> <span class="comment single">// y = 2
  451. </span><span class="comment multiline">/* 30 */</span> <span class="comment single">// ^
  452. </span><span class="comment multiline">/* 31 */</span> <span class="comment single">//
  453. </span><span class="comment multiline">/* 32 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currLineNo</span> <span class="operator">=</span> <span class="literal number integer">2</span><span class="punctuation">;</span>
  454. <span class="comment multiline">/* 33 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currColNo</span> <span class="operator">=</span> <span class="literal number integer">0</span>
  455. <span class="comment multiline">/* 34 */</span>
  456. <span class="comment multiline">/* 35 */</span>
  457. <span class="comment multiline">/* 36 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currFilename</span> <span class="operator">=</span> <span class="literal string single">'./simple.py'</span><span class="punctuation">;</span>
  458. <span class="comment multiline">/* 37 */</span>
  459. <span class="comment multiline">/* 38 */</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">y</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">nmber</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">,</span> <span class="literal string single">'int'</span><span class="punctuation">);</span>
  460. <span class="comment multiline">/* 39 */</span> <span class="comment single">//
  461. </span><span class="comment multiline">/* 40 */</span> <span class="comment single">// line 3:
  462. </span><span class="comment multiline">/* 41 */</span> <span class="comment single">// z = x + y
  463. </span><span class="comment multiline">/* 42 */</span> <span class="comment single">// ^
  464. </span><span class="comment multiline">/* 43 */</span> <span class="comment single">//
  465. </span><span class="comment multiline">/* 44 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currLineNo</span> <span class="operator">=</span> <span class="literal number integer">3</span><span class="punctuation">;</span>
  466. <span class="comment multiline">/* 45 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currColNo</span> <span class="operator">=</span> <span class="literal number integer">0</span>
  467. <span class="comment multiline">/* 46 */</span>
  468. <span class="comment multiline">/* 47 */</span>
  469. <span class="comment multiline">/* 48 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currFilename</span> <span class="operator">=</span> <span class="literal string single">'./simple.py'</span><span class="punctuation">;</span>
  470. <span class="comment multiline">/* 49 */</span>
  471. <span class="comment multiline">/* 50 */</span> <span class="keyword declaration">var</span> <span class="name other">$loadname1</span> <span class="operator">=</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">x</span> <span class="operator">!==</span> <span class="keyword constant">undefined</span> <span class="operator">?</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">x</span> <span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">loadname</span><span class="punctuation">(</span><span class="literal string single">'x'</span><span class="punctuation">,</span> <span class="name other">$gbl</span><span class="punctuation">);</span>
  472. <span class="comment multiline">/* 51 */</span> <span class="keyword declaration">var</span> <span class="name other">$loadname2</span> <span class="operator">=</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">y</span> <span class="operator">!==</span> <span class="keyword constant">undefined</span> <span class="operator">?</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">y</span> <span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">loadname</span><span class="punctuation">(</span><span class="literal string single">'y'</span><span class="punctuation">,</span> <span class="name other">$gbl</span><span class="punctuation">);</span>
  473. <span class="comment multiline">/* 52 */</span> <span class="keyword declaration">var</span> <span class="name other">$binop3</span> <span class="operator">=</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">abstr</span><span class="punctuation">.</span><span class="name other">numberBinOp</span><span class="punctuation">(</span><span class="name other">$loadname1</span><span class="punctuation">,</span> <span class="name other">$loadname2</span><span class="punctuation">,</span> <span class="literal string single">'Add'</span><span class="punctuation">);</span>
  474. <span class="comment multiline">/* 53 */</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">z</span> <span class="operator">=</span> <span class="name other">$binop3</span><span class="punctuation">;</span>
  475. <span class="comment multiline">/* 54 */</span> <span class="comment single">//
  476. </span><span class="comment multiline">/* 55 */</span> <span class="comment single">// line 4:
  477. </span><span class="comment multiline">/* 56 */</span> <span class="comment single">// print z
  478. </span><span class="comment multiline">/* 57 */</span> <span class="comment single">// ^
  479. </span><span class="comment multiline">/* 58 */</span> <span class="comment single">//
  480. </span><span class="comment multiline">/* 59 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currLineNo</span> <span class="operator">=</span> <span class="literal number integer">4</span><span class="punctuation">;</span>
  481. <span class="comment multiline">/* 60 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currColNo</span> <span class="operator">=</span> <span class="literal number integer">0</span>
  482. <span class="comment multiline">/* 61 */</span>
  483. <span class="comment multiline">/* 62 */</span>
  484. <span class="comment multiline">/* 63 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">currFilename</span> <span class="operator">=</span> <span class="literal string single">'./simple.py'</span><span class="punctuation">;</span>
  485. <span class="comment multiline">/* 64 */</span>
  486. <span class="comment multiline">/* 65 */</span> <span class="keyword declaration">var</span> <span class="name other">$loadname4</span> <span class="operator">=</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">z</span> <span class="operator">!==</span> <span class="keyword constant">undefined</span> <span class="operator">?</span> <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">z</span> <span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">loadname</span><span class="punctuation">(</span><span class="literal string single">'z'</span><span class="punctuation">,</span> <span class="name other">$gbl</span><span class="punctuation">);</span>
  487. <span class="comment multiline">/* 66 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">print_</span><span class="punctuation">(</span><span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtins</span><span class="punctuation">[</span><span class="literal string single">'str'</span><span class="punctuation">](</span><span class="name other">$loadname4</span><span class="punctuation">).</span><span class="name other">v</span><span class="punctuation">);</span>
  488. <span class="comment multiline">/* 67 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">print_</span><span class="punctuation">(</span><span class="literal string double">&quot;\n&quot;</span><span class="punctuation">);</span>
  489. <span class="comment multiline">/* 68 */</span> <span class="keyword">return</span> <span class="name other">$loc</span><span class="punctuation">;</span>
  490. <span class="comment multiline">/* 69 */</span> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">SystemError</span><span class="punctuation">(</span><span class="literal string single">'internal error: unterminated block'</span><span class="punctuation">);</span>
  491. <span class="comment multiline">/* 70 */</span> <span class="punctuation">}</span>
  492. <span class="comment multiline">/* 71 */</span> <span class="punctuation">}</span> <span class="keyword">catch</span> <span class="punctuation">(</span><span class="name other">err</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  493. <span class="comment multiline">/* 72 */</span> <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">$exc</span><span class="punctuation">.</span><span class="name other">length</span> <span class="operator">&gt;</span> <span class="literal number integer">0</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  494. <span class="comment multiline">/* 73 */</span> <span class="name other">$err</span> <span class="operator">=</span> <span class="name other">err</span><span class="punctuation">;</span>
  495. <span class="comment multiline">/* 74 */</span> <span class="name other">$blk</span> <span class="operator">=</span> <span class="name other">$exc</span><span class="punctuation">.</span><span class="name other">pop</span><span class="punctuation">(</span><span class="punctuation">);</span>
  496. <span class="comment multiline">/* 75 */</span> <span class="keyword">continue</span><span class="punctuation">;</span>
  497. <span class="comment multiline">/* 76 */</span> <span class="punctuation">}</span> <span class="keyword">else</span> <span class="punctuation">{</span>
  498. <span class="comment multiline">/* 77 */</span> <span class="keyword">throw</span> <span class="name other">err</span><span class="punctuation">;</span>
  499. <span class="comment multiline">/* 78 */</span> <span class="punctuation">}</span>
  500. <span class="comment multiline">/* 79 */</span> <span class="punctuation">}</span>
  501. <span class="comment multiline">/* 80 */</span> <span class="punctuation">}</span>
  502. <span class="comment multiline">/* 81 */</span> <span class="punctuation">}</span> <span class="keyword">catch</span> <span class="punctuation">(</span><span class="name other">err</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  503. <span class="comment multiline">/* 82 */</span> <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">err</span> <span class="keyword">instanceof</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">SystemExit</span> <span class="operator">&amp;&amp;</span> <span class="operator">!</span><span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">throwSystemExit</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  504. <span class="comment multiline">/* 83 */</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">print_</span><span class="punctuation">(</span><span class="name other">err</span><span class="punctuation">.</span><span class="name other">toString</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">+</span> <span class="literal string single">'\n'</span><span class="punctuation">);</span>
  505. <span class="comment multiline">/* 84 */</span> <span class="keyword">return</span> <span class="name other">$loc</span><span class="punctuation">;</span>
  506. <span class="comment multiline">/* 85 */</span> <span class="punctuation">}</span> <span class="keyword">else</span> <span class="punctuation">{</span>
  507. <span class="comment multiline">/* 86 */</span> <span class="keyword">throw</span> <span class="name other">err</span><span class="punctuation">;</span>
  508. <span class="comment multiline">/* 87 */</span> <span class="punctuation">}</span>
  509. <span class="comment multiline">/* 88 */</span> <span class="punctuation">}</span>
  510. <span class="comment multiline">/* 89 */</span> <span class="punctuation">});</span>
  511. </pre>
  512. <p>So, here we create some local variables. x, y, do some math to create a third local variable z, and then print it. Line 26 illustrates creating a local variable <tt class="docutils literal">x</tt> (stored as an attribute of $loc) <tt class="docutils literal">new Sk.builtin.nmber(1, <span class="pre">'int');</span></tt> By now you can probably guess that <tt class="docutils literal">Sk.builtin.nmber</tt> is a constructor that creates a Python number object that is of type int, and has the value of 1. The same thing happens for <tt class="docutils literal">y</tt>.</p>
  513. <p>Next, on lines 40 -- 53 we see what happens in an assignment statement. first we load the values of x and y into temporary variables $loadname1 and $loadname2. Why not just use $loc.x ?? Well, we need to use Python's scoping rules. If $loc.x is undefined then we should check the outer scope to see if it exists there. <tt class="docutils literal">Sk.misceval.loadname</tt> If loadname does not find a name <tt class="docutils literal">x</tt> or <tt class="docutils literal">y</tt> it throws a NameError, and execution would abort. You can see where this works by changing the assignment statement to <tt class="docutils literal">z = x + t</tt> to purposely cause the error. The compiler blindly first tries $loc.t and then again calls loadname, which in this case does abort with an error!</p>
  514. <p>On lines 52 and 53 we perform the addition using <tt class="docutils literal"><span class="pre">Sk.abstr.numberBinOp($loadname1,</span> $loadname2, <span class="pre">'Add');</span></tt> Note the abstract (see abstract.js) nature of <tt class="docutils literal">numberBinOp</tt> -- two parameters for the operands, and one parameter <tt class="docutils literal">'Add'</tt> that indicates the operator. Finally the temporary result returned by numberBinOp is stored in $loc.z. Its important to note that $loc.z contains a Python number object. Down in the bowels of numberBinOp, the javascript numeric values for x and y are retrieved and result of adding two javascript numbers is converted to the appropriate type of Python object.</p>
  515. </div>
  516. <div class="section" id="function-calls-conditionals-and-loops">
  517. <h3>Function Calls, Conditionals, and Loops</h3>
  518. <p>Oh my! so what is the deal with this while(true)/try/switch thing? To understand this we need a bit more complicated example, so lets look at a program that contains an if/else conditional. We'll see that we now have a much more interesting switch statement.</p>
  519. <p>Without showing all of the generated code, lets consider a simple python program like the one below. There will be two scope functions generated by the compiler for this example. $scope0 is for the main program where foo is defined and there is an if statement. The second $scope1 is for when the foo function is actually called. The $scope1 while/switch combo contains four cases: 0, 1, 2, and 3. You can imagine this python code consisting of four blocks. The first block starts at the beginning and goes through the evaluation of the if condition. The second block is the if true block of the if. The third block is the else block of the if statement, and the final block is the rest of the program after the if/else is all done. You can verify this for yourself by putting this program into a file <tt class="docutils literal">simple.py</tt> and runing <tt class="docutils literal">./skulpt.py run simple.py</tt> If you examine the output you will see that the <tt class="docutils literal">$blk</tt> variable is manipulated to control which <tt class="docutils literal">case</tt> is executed the next time through the while loop. Very clever! If Javascript had <tt class="docutils literal">goto statements</tt> this would probably look a lot different.</p>
  520. <pre class="code python literal-block">
  521. <span class="comment"># &lt;--- $blk 0 starts</span>
  522. <span class="keyword">def</span> <span class="name function">foo</span><span class="punctuation">(</span><span class="name">bar</span><span class="punctuation">):</span>
  523. <span class="keyword">print</span> <span class="name">bar</span>
  524. <span class="name">x</span> <span class="operator">=</span> <span class="literal number integer">2</span>
  525. <span class="keyword">if</span> <span class="name">x</span> <span class="operator">%</span> <span class="literal number integer">2</span> <span class="operator">==</span> <span class="literal number integer">0</span><span class="punctuation">:</span> <span class="comment"># &lt;---- end of $blk 0</span>
  526. <span class="name">foo</span><span class="punctuation">(</span><span class="literal string">&quot;hello&quot;</span><span class="punctuation">)</span> <span class="comment"># &lt;---- $blk 3</span>
  527. <span class="keyword">else</span><span class="punctuation">:</span>
  528. <span class="name">foo</span><span class="punctuation">(</span><span class="literal string">&quot;goodbye&quot;</span><span class="punctuation">)</span> <span class="comment"># &lt;---- $blk 2</span>
  529. <span class="comment"># &lt;--- $blk 1 end of if</span>
  530. <span class="name">When</span> <span class="name">foo</span> <span class="operator word">is</span> <span class="name">called</span><span class="punctuation">,</span> <span class="name">it</span> <span class="name">has</span> <span class="name">its</span> <span class="name">own</span> <span class="name">scope</span> <span class="error">$</span><span class="name">scope1</span> <span class="name">created</span> <span class="operator word">and</span> <span class="name">called</span> <span class="name">using</span> <span class="name">Sk</span><span class="operator">.</span><span class="name">misceval</span><span class="operator">.</span><span class="name">callsim</span><span class="operator">.</span>
  531. </pre>
  532. </div>
  533. </div>
  534. <div class="section" id="how-do-i-add-feature-x-or-fix-bug-y">
  535. <h2>How do I add Feature X or Fix bug Y</h2>
  536. <p>Probably the biggest hurdle in working with skulpt is, &quot;where do I start?&quot; So, let me take you through a recent scenario, that is pretty illustrative of how I go about doing development on Skulpt.</p>
  537. <p>The question was &quot;how do I add keyword parameters (cmp, key, and reverse)&quot; to the builtin sorted function. This is pretty tricky as Javascript does not support keyword parameters so there is no real straightforward path. So start as follows:</p>
  538. <pre class="literal-block">
  539. x = [1,2,3]
  540. print(sorted(x,reverse=True))
  541. </pre>
  542. <p>Now run this using <tt class="docutils literal">skulpt.py run test.py</tt> and you will get a compiled program. With a little bit of sleuthing you find:</p>
  543. <pre class="literal-block">
  544. /* 35 */ // line 2:
  545. /* 36 */ // print(sorted(x,reverse=True))
  546. /* 37 */ // ^
  547. /* 38 */ //
  548. /* 39 */ Sk.currLineNo = 2;
  549. /* 40 */ Sk.currColNo = 0
  550. /* 41 */
  551. /* 42 */
  552. /* 43 */ Sk.currFilename = './sd.py';
  553. /* 44 */
  554. /* 45 */ var $loadname8 = $loc.sorted !== undefined ? $loc.sorted : Sk.misceval.loadname('sorted', $gbl);
  555. /* 46 */ var $loadname9 = $loc.x !== undefined ? $loc.x : Sk.misceval.loadname('x', $gbl);
  556. /* 47 */ var $call10 = Sk.misceval.call($loadname8, undefined, undefined, ['reverse', Sk.builtin.bool.true$], $loadname9);
  557. </pre>
  558. <p>Where the important thing is to notice how the call is formatted after it is compiled. The fourth parameter to <tt class="docutils literal">Sk.misceval.call</tt> is <tt class="docutils literal">['reverse', Sk.builtin.bool.true$]</tt> Now if you check the source for misceval, you will see that these parameters are passed on to the apply function. In the apply function you will see that there is an assertion that the fourth parameter should be empty. Ok, here's our starting point to add in what's needed to actually process these key value parameters successfully.</p>
  559. <p>In the case of a bug fix, you would do a similar thing, except that the line where your get an exception is likely to be closer to helping you figure out your next steps.</p>
  560. </div>
  561. </div>
  562. <div class="section" id="how-to">
  563. <h1>HOW TO</h1>
  564. <p>This section is for providing specific examples, or documentation on how to do a specific task. Suggestions for additional tasks are welcome!</p>
  565. <div class="section" id="default-parameters">
  566. <h2>Default Parameters</h2>
  567. <p>How do I add a function with named parameters with default values?</p>
  568. <p>The key to this is that as the author of either a builtin function, or a method in a module, you need to add some meta data to the function definition. Here's an example of how we added the named parameters to the <tt class="docutils literal">sorted</tt> function.</p>
  569. <pre class="code javascript literal-block">
  570. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">sorted</span> <span class="operator">=</span> <span class="keyword declaration">function</span> <span class="name other">sorted</span><span class="punctuation">(</span><span class="name other">iterable</span><span class="punctuation">,</span> <span class="name other">cmp</span><span class="punctuation">,</span> <span class="name other">key</span><span class="punctuation">,</span> <span class="name other">reverse</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  571. <span class="comment multiline">/* body of sorted here */</span>
  572. <span class="punctuation">}</span>
  573. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">sorted</span><span class="punctuation">.</span><span class="name other">co_varnames</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="literal string single">'cmp'</span><span class="punctuation">,</span> <span class="literal string single">'key'</span><span class="punctuation">,</span> <span class="literal string single">'reverse'</span><span class="punctuation">];</span>
  574. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">sorted</span><span class="punctuation">.</span><span class="name other">$defaults</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">none</span><span class="punctuation">,</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">none</span><span class="punctuation">,</span> <span class="keyword constant">false</span><span class="punctuation">];</span>
  575. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">sorted</span><span class="punctuation">.</span><span class="name other">co_numargs</span> <span class="operator">=</span> <span class="literal number integer">4</span><span class="punctuation">;</span>
  576. </pre>
  577. </div>
  578. <div class="section" id="kwargs">
  579. <h2>kwargs</h2>
  580. <p>How do I add a function with <tt class="docutils literal">**kwargs</tt>?</p>
  581. <p>Again the idea comes down to adding some meta-data after the function is defined. Here is an example of adding <tt class="docutils literal">**kwargs</tt> to a method in a module:</p>
  582. <pre class="code javascript literal-block">
  583. <span class="keyword declaration">var</span> <span class="name other">plotk_f</span> <span class="operator">=</span> <span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">kwa</span><span class="punctuation">)</span>
  584. <span class="punctuation">{</span>
  585. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">pyCheckArgs</span><span class="punctuation">(</span><span class="literal string double">&quot;plotk&quot;</span><span class="punctuation">,</span> <span class="name other">arguments</span><span class="punctuation">,</span> <span class="literal number integer">0</span><span class="punctuation">,</span> <span class="keyword constant">Infinity</span><span class="punctuation">,</span> <span class="keyword constant">true</span><span class="punctuation">,</span> <span class="keyword constant">false</span><span class="punctuation">)</span>
  586. <span class="name other">args</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtins</span><span class="punctuation">[</span><span class="literal string single">'tuple'</span><span class="punctuation">](</span><span class="name builtin">Array</span><span class="punctuation">.</span><span class="name other">prototype</span><span class="punctuation">.</span><span class="name other">slice</span><span class="punctuation">.</span><span class="name other">call</span><span class="punctuation">(</span><span class="name other">arguments</span><span class="punctuation">,</span> <span class="literal number integer">1</span><span class="punctuation">));</span> <span class="comment multiline">/*vararg*/</span>
  587. <span class="name other">kwargs</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtins</span><span class="punctuation">[</span><span class="literal string single">'dict'</span><span class="punctuation">](</span><span class="name other">kwa</span><span class="punctuation">);</span>
  588. <span class="keyword">return</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtins</span><span class="punctuation">[</span><span class="literal string single">'tuple'</span><span class="punctuation">](</span><span class="punctuation">[</span><span class="name other">args</span><span class="punctuation">,</span> <span class="name other">kwargs</span><span class="punctuation">]);</span>
  589. <span class="punctuation">};</span>
  590. <span class="name other">plotk_f</span><span class="punctuation">[</span><span class="literal string single">'co_kwargs'</span><span class="punctuation">]</span> <span class="operator">=</span> <span class="keyword constant">true</span><span class="punctuation">;</span>
  591. <span class="name other">mod</span><span class="punctuation">.</span><span class="name other">plotk</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">func</span><span class="punctuation">(</span><span class="name other">plotk_f</span><span class="punctuation">);</span>
  592. </pre>
  593. </div>
  594. <div class="section" id="adding-a-module">
  595. <h2>Adding a Module</h2>
  596. <p>This section is from a blog post I made in 2011, slightly updated.</p>
  597. <p>So, here's the deal. skulpt relies on two javascript files the first is skulpt.min.js and skulpt-stdlib.js A very minimal installation only uses skulpt.min.js, whereas if you want to use any modules they are in skulpt-stdlib.js. Looking around the distribution you will not immediately find skulpt.min.js because you need to build it. You get a sculpt.js file by using the m script that comes with the distribution. running m --help will give you the full list of commands, but the two that you probably most care about are m dist and m docbi The dist command builds both skulpt.min.js and skulpt-stdlib.js docbi builds skulpt-stdlib.js and puts a new copy of it in the doc/static directory.
  598. Lets begin with a quick tour of the source tree:</p>
  599. <ul class="simple">
  600. <li>src - contains the implementation of the Python interpreter</li>
  601. <li>src/lib - has the module implementations of webgl and goog. This is where turtle will live and any other modules I implement along the way.</li>
  602. <li>doc - This directory contains a google app engine application and is what you see on skulpt.org There are a couple of important files to check out in here. One of them is doc/static/env/editor.js This is the code that ties together the interactive editor on the home page with the skulpt interpreter and the codemirror editor. If you know how to build a google app engine app then this directory makes sense. One thing about the home page is that it is not set up to use any of the modules. The modules are used in the more advanced ide, which you can find in doc/ide/static. I'm going to tell you how to add modules to the simpler editor later in this article.</li>
  603. <li>test - this directory contains a bunch of files for testing the implementation in a batch mode. These tests are run whenever you run m dist, or m test.</li>
  604. <li>dist - This directory gets created and populated when you run the m dist command. It contains the built and compressed versions of skulpt.min.js and skulpt-stdlib.js</li>
  605. </ul>
  606. <p>To illustrate how to make use of modules, here's an extended version of my earlier hello world style example.</p>
  607. <pre class="code html literal-block">
  608. <span class="name tag">&lt;html&gt;</span>
  609. <span class="name tag">&lt;head&gt;</span>
  610. <span class="name tag">&lt;script </span><span class="name attribute">src=</span><span class="literal string">&quot;skulpt.min.js&quot;</span> <span class="name attribute">type=</span><span class="literal string">&quot;text/javascript&quot;</span><span class="name tag">&gt;&lt;/script&gt;</span>
  611. <span class="name tag">&lt;script </span><span class="name attribute">src=</span><span class="literal string">&quot;skulpt-stdlib.js&quot;</span> <span class="name attribute">type=</span><span class="literal string">&quot;text/javascript&quot;</span><span class="name tag">&gt;&lt;/script&gt;</span>
  612. <span class="name tag">&lt;/head&gt;</span>
  613. <span class="name tag">&lt;body&gt;</span>
  614. <span class="name tag">&lt;script </span><span class="name attribute">type=</span><span class="literal string">&quot;text/javascript&quot;</span><span class="name tag">&gt;</span>
  615. <span class="keyword declaration">function</span> <span class="name other">outf</span><span class="punctuation">(</span><span class="name other">text</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  616. <span class="keyword declaration">var</span> <span class="name other">mypre</span> <span class="operator">=</span> <span class="name builtin">document</span><span class="punctuation">.</span><span class="name other">getElementById</span><span class="punctuation">(</span><span class="literal string double">&quot;output&quot;</span><span class="punctuation">);</span>
  617. <span class="name other">mypre</span><span class="punctuation">.</span><span class="name other">innerHTML</span> <span class="operator">=</span> <span class="name other">mypre</span><span class="punctuation">.</span><span class="name other">innerHTML</span> <span class="operator">+</span> <span class="name other">text</span><span class="punctuation">;</span>
  618. <span class="punctuation">}</span>
  619. <span class="keyword declaration">function</span> <span class="name other">builtinRead</span><span class="punctuation">(</span><span class="name other">x</span><span class="punctuation">)</span>
  620. <span class="punctuation">{</span>
  621. <span class="keyword">if</span> <span class="punctuation">(</span><span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtinFiles</span> <span class="operator">===</span> <span class="keyword constant">undefined</span> <span class="operator">||</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtinFiles</span><span class="punctuation">[</span><span class="literal string double">&quot;files&quot;</span><span class="punctuation">][</span><span class="name other">x</span><span class="punctuation">]</span> <span class="operator">===</span> <span class="keyword constant">undefined</span><span class="punctuation">)</span>
  622. <span class="keyword">throw</span> <span class="literal string double">&quot;File not found: '&quot;</span> <span class="operator">+</span> <span class="name other">x</span> <span class="operator">+</span> <span class="literal string double">&quot;'&quot;</span><span class="punctuation">;</span>
  623. <span class="keyword">return</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtinFiles</span><span class="punctuation">[</span><span class="literal string double">&quot;files&quot;</span><span class="punctuation">][</span><span class="name other">x</span><span class="punctuation">];</span>
  624. <span class="punctuation">}</span>
  625. <span class="keyword declaration">function</span> <span class="name other">runit</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  626. <span class="keyword declaration">var</span> <span class="name other">prog</span> <span class="operator">=</span> <span class="name builtin">document</span><span class="punctuation">.</span><span class="name other">getElementById</span><span class="punctuation">(</span><span class="literal string double">&quot;yourcode&quot;</span><span class="punctuation">).</span><span class="name other">value</span><span class="punctuation">;</span>
  627. <span class="keyword declaration">var</span> <span class="name other">mypre</span> <span class="operator">=</span> <span class="name builtin">document</span><span class="punctuation">.</span><span class="name other">getElementById</span><span class="punctuation">(</span><span class="literal string double">&quot;output&quot;</span><span class="punctuation">);</span>
  628. <span class="name other">mypre</span><span class="punctuation">.</span><span class="name other">innerHTML</span> <span class="operator">=</span> <span class="literal string single">''</span><span class="punctuation">;</span>
  629. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">configure</span><span class="punctuation">(</span><span class="punctuation">{</span><span class="name other">output</span><span class="operator">:</span><span class="name other">outf</span><span class="punctuation">,</span>
  630. <span class="name other">read</span><span class="operator">:</span> <span class="name other">builtinRead</span>
  631. <span class="punctuation">});</span>
  632. <span class="keyword">try</span> <span class="punctuation">{</span>
  633. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">importMainWithBody</span><span class="punctuation">(</span><span class="literal string double">&quot;&lt;stdin&gt;&quot;</span><span class="punctuation">,</span><span class="keyword constant">false</span><span class="punctuation">,</span><span class="name other">prog</span><span class="punctuation">);</span>
  634. <span class="punctuation">}</span> <span class="keyword">catch</span> <span class="punctuation">(</span><span class="name other">e</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  635. <span class="name other">alert</span><span class="punctuation">(</span><span class="name other">e</span><span class="punctuation">);</span>
  636. <span class="punctuation">}</span>
  637. <span class="punctuation">}</span>
  638. <span class="name tag">&lt;/script&gt;</span>
  639. <span class="name tag">&lt;h3&gt;</span>Try This<span class="name tag">&lt;/h3&gt;</span>
  640. <span class="name tag">&lt;form&gt;</span>
  641. <span class="name tag">&lt;textarea</span> <span class="name attribute">edit_id=</span><span class="literal string">&quot;eta_5&quot;</span> <span class="name attribute">id=</span><span class="literal string">&quot;yourcode&quot;</span><span class="name tag">&gt;</span>
  642. print &quot;Hello World&quot;
  643. <span class="name tag">&lt;/textarea&gt;</span>
  644. <span class="name tag">&lt;button</span> <span class="name attribute">onclick=</span><span class="literal string">&quot;runit()&quot;</span> <span class="name attribute">type=</span><span class="literal string">&quot;button&quot;</span><span class="name tag">&gt;</span>Run<span class="name tag">&lt;/button&gt;</span>
  645. <span class="name tag">&lt;/form&gt;</span>
  646. <span class="name tag">&lt;pre</span> <span class="name attribute">id=</span><span class="literal string">&quot;output&quot;</span><span class="name tag">&gt;&lt;/pre&gt;</span>
  647. <span class="name tag">&lt;/body&gt;</span>
  648. <span class="name tag">&lt;/html&gt;</span>
  649. </pre>
  650. <p>There are some important differences between this version, and the version and the non-module version. First off, the call to Sk.configure contains another key value pair which sets up a specialized read function. This is the function that is responsible for returning your module out of the large array of files that are contained in the skulpt-stdlib.js file. You will see that all of the modules are contained in this one file, stored in a big JSON structure. The extra key value pair is:
  651. read: builtinRead</p>
  652. <p>The read function is just for loading modules and is called when you do an import statement of some kind. In this case the function accesses the variable builtinFiles which is created from the skulpt-stdlib.js file. The other difference, of course, is that you have to include skulpt-stdlib.js in your html file. Note that skulpt-stdlib.js must be included after skulpt.min.js</p>
  653. <p>Now as far as the module itself goes, the easiest thing to do is to start your module in the src/lib directory. This way it will automatically get built and included in skulpt-stdlib.js. If you don't put it there then you are going to have to modify the m script, specifically the docbi function in the m script to include your module. Suppose that you want to have a module called bnm.test Here's what you have to do. First, you need to make a bnm directory under lib. In this directory you will need to have either __init__.py or __init__.js or bnm.js to stand in for the bnm module. There doesn't need to be anything in the file as long as it exists. This is just like CPython by the way. Then to make a test module you can either make a test directory and put all your javascript code in __init__.js or you can simply create a test.js file in the bnm directory. Lets look at the test module.</p>
  654. <pre class="code javascript literal-block">
  655. <span class="keyword declaration">var</span> <span class="name other">$builtinmodule</span> <span class="operator">=</span> <span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">name</span><span class="punctuation">)</span>
  656. <span class="punctuation">{</span>
  657. <span class="keyword declaration">var</span> <span class="name other">mod</span> <span class="operator">=</span> <span class="punctuation">{</span><span class="punctuation">};</span>
  658. <span class="keyword declaration">var</span> <span class="name other">myfact</span> <span class="operator">=</span> <span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">n</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  659. <span class="keyword">if</span><span class="punctuation">(</span><span class="name other">n</span> <span class="operator">&lt;</span> <span class="literal number integer">1</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  660. <span class="keyword">return</span> <span class="literal number integer">1</span><span class="punctuation">;</span>
  661. <span class="punctuation">}</span> <span class="keyword">else</span> <span class="punctuation">{</span>
  662. <span class="keyword">return</span> <span class="name other">n</span> <span class="operator">*</span> <span class="name other">myfact</span><span class="punctuation">(</span><span class="name other">n</span><span class="operator">-</span><span class="literal number integer">1</span><span class="punctuation">);</span>
  663. <span class="punctuation">}</span>
  664. <span class="punctuation">}</span>
  665. <span class="name other">mod</span><span class="punctuation">.</span><span class="name other">fact</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">func</span><span class="punctuation">(</span><span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">a</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  666. <span class="keyword">return</span> <span class="name other">myfact</span><span class="punctuation">(</span><span class="name other">a</span><span class="punctuation">);</span>
  667. <span class="punctuation">});</span>
  668. <span class="name other">mod</span><span class="punctuation">.</span><span class="name other">Stack</span> <span class="operator">=</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">misceval</span><span class="punctuation">.</span><span class="name other">buildClass</span><span class="punctuation">(</span><span class="name other">mod</span><span class="punctuation">,</span> <span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">$gbl</span><span class="punctuation">,</span> <span class="name other">$loc</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  669. <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">__init__</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">func</span><span class="punctuation">(</span><span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  670. <span class="name other">self</span><span class="punctuation">.</span><span class="name other">stack</span> <span class="operator">=</span> <span class="punctuation">[</span><span class="punctuation">];</span>
  671. <span class="punctuation">});</span>
  672. <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">push</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">func</span><span class="punctuation">(</span><span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">self</span><span class="punctuation">,</span><span class="name other">x</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  673. <span class="name other">self</span><span class="punctuation">.</span><span class="name other">stack</span><span class="punctuation">.</span><span class="name other">push</span><span class="punctuation">(</span><span class="name other">x</span><span class="punctuation">);</span>
  674. <span class="punctuation">});</span>
  675. <span class="name other">$loc</span><span class="punctuation">.</span><span class="name other">pop</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">func</span><span class="punctuation">(</span><span class="keyword declaration">function</span><span class="punctuation">(</span><span class="name other">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
  676. <span class="keyword">return</span> <span class="name other">self</span><span class="punctuation">.</span><span class="name other">stack</span><span class="punctuation">.</span><span class="name other">pop</span><span class="punctuation">(</span><span class="punctuation">);</span>
  677. <span class="punctuation">});</span>
  678. <span class="punctuation">},</span>
  679. <span class="literal string single">'Stack'</span><span class="punctuation">,</span> <span class="punctuation">[</span><span class="punctuation">]);</span>
  680. <span class="keyword">return</span> <span class="name other">mod</span><span class="punctuation">;</span>
  681. <span class="punctuation">}</span>
  682. </pre>
  683. <p>All modules start out with the $var builtinmodule = statement.
  684. This test module exposes a single method to the outside world, called fact, There are a couple of key functions for building up a module. The Sk.builtin.func call for adding functions to your module, and the Sk.misceval.buildClass method. This test module defines a simple factorial function called fact, and a class called stack. Here's a simple Python program that exercises the module:</p>
  685. <pre class="code python literal-block">
  686. <span class="keyword namespace">import</span> <span class="name namespace">bnm.test</span>
  687. <span class="keyword">print</span> <span class="literal string">'starting'</span>
  688. <span class="keyword">print</span> <span class="name">bnm</span><span class="operator">.</span><span class="name">test</span><span class="operator">.</span><span class="name">fact</span><span class="punctuation">(</span><span class="literal number integer">10</span><span class="punctuation">)</span>
  689. <span class="name">x</span> <span class="operator">=</span> <span class="name">bnm</span><span class="operator">.</span><span class="name">test</span><span class="operator">.</span><span class="name">Stack</span><span class="punctuation">()</span>
  690. <span class="name">x</span><span class="operator">.</span><span class="name">push</span><span class="punctuation">(</span><span class="literal number integer">1</span><span class="punctuation">)</span>
  691. <span class="name">x</span><span class="operator">.</span><span class="name">push</span><span class="punctuation">(</span><span class="literal number integer">2</span><span class="punctuation">)</span>
  692. <span class="keyword">print</span> <span class="name">x</span><span class="operator">.</span><span class="name">pop</span><span class="punctuation">()</span>
  693. <span class="keyword">print</span> <span class="literal string">'done'</span>
  694. </pre>
  695. <p>Its not obvious, but the buildClass method takes four parameters: globals, func, name, bases
  696. It seems that you always pass the mod object itself as the globals parameter, the func parameter is a function that represents the class object, the Name is the external name of the class, and bases presumably would be if the class is inheriting from another class.</p>
  697. <p>The Sk.builtin.func method creates a function. For module creation we typically only have to worry about the one parameter, func, which is the javascript implementation of our Python function. The method can also take a globals object and two closure objects. Look at the comments in function.js if you want more explanation of how the builtin.func method works.</p>
  698. <p>Well, I think this should be enough to get you going. Its worth repeating, if you made it this far, don't forget to call m docbi or m dist after you make changes in your module, its easy to get into the mode of thinking that the new javascript is automatically loaded. But skulpt-stdlib.js is not automatically rebuilt!</p>
  699. </div>
  700. <div class="section" id="debugging">
  701. <h2>Debugging</h2>
  702. <p>How do I use the debugger in the browser to help me debug my code?</p>
  703. <p>Easy, just add the statement: <tt class="docutils literal">debugger;</tt> to your code. Now if you have the javscript deveoper tools open in the browser you will have it.</p>
  704. <p>If you want to start the debugger from a python function that you have written you can also add a debugger statement</p>
  705. <p>If you want to enable debugging generally for use with <tt class="docutils literal">debugbrowser</tt> follow these handy instructions:</p>
  706. <ul class="simple">
  707. <li>I make a new test using ./m nrt</li>
  708. <li>then add a debugger; to the start of the statement at <a class="reference external" href="https://github.com/skulpt/skulpt/blob/master/src/import.js#L179">https://github.com/skulpt/skulpt/blob/master/src/import.js#L179</a> the line would like this: <tt class="docutils literal">finalcode += &quot;\ndebugger;&quot; + co.funcname + &quot;(&quot; + namestr + <span class="pre">&quot;);&quot;;</span></tt></li>
  709. <li>run <tt class="docutils literal">./skulpt.py debugbrowser</tt> wait until all tests have run</li>
  710. <li>startup the developer tools cmd+alt+i on a mac or F12 on a PC in chrome that is</li>
  711. <li>run the test I added before and it stops right before you enter the compiled code!</li>
  712. </ul>
  713. </div>
  714. <div class="section" id="development-workflow">
  715. <h2>Development Workflow</h2>
  716. <ol class="arabic simple">
  717. <li>Make a fork of the repository on github. DO NOT simply clone <a class="reference external" href="http://github.com/bnmnetp/runestone">http://github.com/bnmnetp/runestone</a>. Make a Fork. If you don't know how to make a fork consult the documentation here: <a class="reference external" href="https://help.github.com/articles/fork-a-repo">https://help.github.com/articles/fork-a-repo</a></li>
  718. <li>Make a simple myabs.py file that contains a few lines of python that exercise the abs function. Say it looks like this:</li>
  719. </ol>
  720. <pre class="code python literal-block">
  721. <span class="keyword">print</span> <span class="name builtin">abs</span><span class="punctuation">(</span><span class="operator">-</span><span class="literal number float">1.0</span><span class="punctuation">)</span>
  722. <span class="keyword">print</span> <span class="name builtin">abs</span><span class="punctuation">(</span><span class="literal number integer">24</span><span class="punctuation">)</span>
  723. </pre>
  724. <ol class="arabic simple" start="3">
  725. <li>Now go edit the source. To implement abs you would edit the builtin.js file. Now abs is pretty easy to add, because you can just have our skulpt version of abs call Math.abs So here it is</li>
  726. </ol>
  727. <pre class="code javascript literal-block">
  728. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">abs</span> <span class="operator">=</span> <span class="keyword declaration">function</span> <span class="name other">abs</span><span class="punctuation">(</span><span class="name other">x</span><span class="punctuation">)</span>
  729. <span class="punctuation">{</span>
  730. <span class="keyword">return</span> <span class="name builtin">Math</span><span class="punctuation">.</span><span class="name other">abs</span><span class="punctuation">(</span><span class="name other">x</span><span class="punctuation">);</span>
  731. <span class="punctuation">};</span>
  732. </pre>
  733. <p>You are not done yet, because builtin functions also have to be declared in the builtindict.js object as follows:</p>
  734. <pre class="code javascript literal-block">
  735. <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtins</span> <span class="operator">=</span> <span class="punctuation">{</span>
  736. <span class="literal string single">'range'</span><span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">range</span><span class="punctuation">,</span>
  737. <span class="literal string single">'len'</span><span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">len</span><span class="punctuation">,</span>
  738. <span class="literal string single">'min'</span><span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">min</span><span class="punctuation">,</span>
  739. <span class="literal string single">'max'</span><span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">max</span><span class="punctuation">,</span>
  740. <span class="literal string single">'sum'</span><span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">sum</span><span class="punctuation">,</span>
  741. <span class="literal string single">'abs'</span><span class="operator">:</span> <span class="name other">Sk</span><span class="punctuation">.</span><span class="name other">builtin</span><span class="punctuation">.</span><span class="name other">abs</span><span class="punctuation">,</span>
  742. <span class="punctuation">...</span>
  743. <span class="punctuation">}</span>
  744. </pre>
  745. <p>Now you can test your modifications from the command line by running:</p>
  746. <pre class="literal-block">
  747. ./skulpt.py run myabs.py
  748. -----
  749. print abs(-1.0)
  750. print abs(24)
  751. -----
  752. /* 1 */ var $scope0 = (function($modname) {
  753. /* 2 */ var $blk = 0,
  754. /* 3 */ $exc = [],
  755. /* 4 */ $gbl = {},
  756. /* 5 */ $loc = $gbl;
  757. /* 6 */ $gbl.__name__ = $modname;
  758. /* 7 */ while (true) {
  759. /* 8 */ try {
  760. /* 9 */ switch ($blk) {
  761. /* 10 */ case 0:
  762. /* 11 */ /* --- module entry --- */
  763. /* 12 */ //
  764. /* 13 */ // line 1:
  765. /* 14 */ // print abs(-1.0)
  766. /* 15 */ // ^
  767. /* 16 */ //
  768. /* 17 */ Sk.currLineNo = 1;
  769. /* 18 */ Sk.currColNo = 0
  770. /* 19 */
  771. /* 20 */
  772. /* 21 */ Sk.currFilename = './myabs.py';
  773. /* 22 */
  774. /* 23 */ var $loadname1 = $loc.abs !== undefined ? $loc.abs : Sk.misceval.loadname('abs', $gbl);
  775. /* 24 */ var $call2 = Sk.misceval.callsim($loadname1, Sk.numberFromStr('-1.0'));
  776. /* 25 */ Sk.misceval.print_(new Sk.builtins['str']($call2).v);
  777. /* 26 */ Sk.misceval.print_(&quot;\n&quot;);
  778. /* 27 */ //
  779. /* 28 */ // line 2:
  780. /* 29 */ // print abs(24)
  781. /* 30 */ // ^
  782. /* 31 */ //
  783. /* 32 */ Sk.currLineNo = 2;
  784. /* 33 */ Sk.currColNo = 0
  785. /* 34 */
  786. /* 35 */
  787. /* 36 */ Sk.currFilename = './myabs.py';
  788. /* 37 */
  789. /* 38 */ var $loadname3 = $loc.abs !== undefined ? $loc.abs : Sk.misceval.loadname('abs', $gbl);
  790. /* 39 */ var $call4 = Sk.misceval.callsim($loadname3, Sk.numberFromStr('24'));
  791. /* 40 */ Sk.misceval.print_(new Sk.builtins['str']($call4).v);
  792. /* 41 */ Sk.misceval.print_(&quot;\n&quot;);
  793. /* 42 */ return $loc;
  794. /* 43 */ goog.asserts.fail('unterminated block');
  795. /* 44 */ }
  796. /* 45 */ } catch (err) {
  797. /* 46 */ if ($exc.length &gt; 0) {
  798. /* 47 */ $blk = $exc.pop();
  799. /* 48 */ continue;
  800. /* 49 */ } else {
  801. /* 50 */ throw err;
  802. /* 51 */ }
  803. /* 52 */ }
  804. /* 53 */ }
  805. /* 54 */ });
  806. 1
  807. 24
  808. </pre>
  809. <p>This is all incredibly useful information.</p>
  810. <p>First it demonstrates that your addition actually worked. You can see the output at the bottom.
  811. Second, you can see how skulpt 'compiled' your python program into its intermediate Javascript form. While this may not be all that helpful in this particular case it can be very very helpful in figuring out what skulpt is actually doing.
  812. Now you should run all of the unit tests to make sure you have broken anything else accidentally. This is really easy:</p>
  813. <pre class="literal-block">
  814. ./skulpt.py test
  815. </pre>
  816. <p>If any tests fail it will be obvious that they did, and you'll have to do some investigation to figure out why. At the time of this writing you should see:</p>
  817. <pre class="literal-block">
  818. run: 343/343 (+1 disabled)
  819. closure: skipped
  820. </pre>
  821. <p>Once you are satisfied that your extension is working fine. You should add a test case to test/run see: New Tests for instructions. This way we will have a permanent test in the bank of test cases in order to check for any future regressions.</p>
  822. <p>Finally make a pull request on github to have your new feature integrated into the master copy. I probably will not accept your pull request if you haven't done step 4.</p>
  823. <p>Outside of your editor, your browser, and your wits, the main development tool for skulpt is the skulpt.py command (also linked to m for historical compatibility).</p>
  824. <pre class="literal-block">
  825. ./skulpt.py --help
  826. Usage:
  827. skulpt.py &lt;command&gt; [&lt;options&gt;] [script.py]
  828. Commands:
  829. run Run a Python file using Skulpt
  830. test Run all test cases
  831. dist Build core and library distribution files
  832. docbi Build library distribution file only and copy to doc/static
  833. regenparser Regenerate parser tests
  834. regenasttests Regen abstract symbol table tests
  835. regenruntests Regenerate runtime unit tests
  836. regensymtabtests Regenerate symbol table tests
  837. regentests Regenerate all of the above
  838. help Display help information about Skulpt
  839. host Start a simple HTTP server for testing
  840. upload Run appcfg.py to upload doc to live GAE site
  841. doctest Run the GAE development server for doc testing
  842. nrt Generate a file for a new test case
  843. runopt Run a Python file optimized
  844. browser Run all tests in the browser
  845. shell Run a Python program but keep a shell open (like python -i)
  846. vfs Build a virtual file system to support Skulpt read tests
  847. debugbrowser Debug in the browser -- open your javascript console
  848. Options:
  849. -q, --quiet Only output important information
  850. -s, --silent Do not output anything, besides errors
  851. -u, --uncompressed Makes uncompressed core distribution file for debugging
  852. -v, --verbose Make output more verbose [default]
  853. --version Returns the version string in Bower configuration file.
  854. Options:
  855. --version show program's version number and exit
  856. -h, --help show this help message and exit
  857. -q, --quiet
  858. -s, --silent
  859. -u, --uncompressed
  860. -v, --verbose Make output more verbose [default]
  861. </pre>
  862. <div class="section" id="run">
  863. <h3>run</h3>
  864. <p>The command <tt class="docutils literal">./skulpt.py run foo.py</tt> compiles and runs a Python program generating output similar to the examples shown in the previous section. This is very common for development. For example if you find a bug, that you can express in a small Python program you can start by running the program from the command line and inspecting the generated code. Usually this will give you a pretty good idea where the bug might be.</p>
  865. </div>
  866. <div class="section" id="test">
  867. <h3>test</h3>
  868. <p>Run all the unit tests.</p>
  869. </div>
  870. <div class="section" id="dist">
  871. <h3>dist</h3>
  872. <p>Build the distribution files for skulpt:</p>
  873. <ul class="simple">
  874. <li>skulpt.min.js -- This is a minified version of the core interpreter files.</li>
  875. <li>skulpt-stdlib.js -- This is an unminified version of library functions. This file may contain javascript that implements a module, such as turtle or math, or it may contain pure python.</li>
  876. </ul>
  877. </div>
  878. </div>
  879. </div>
  880. <div class="system-messages section">
  881. <h1>Docutils System Messages</h1>
  882. <div class="system-message" id="id1">
  883. <p class="system-message-title">System Message: ERROR/3 (<tt class="docutils">HACKING.rst</tt>, line 125); <em><a href="#id2">backlink</a></em></p>
  884. Unknown target name: &quot;sk.misceval.print&quot;.</div>
  885. </div>
  886. </div>
  887. </body>
  888. </html>