Deploy to GitHub Pages:

This commit is contained in:
Travis CI
2020-06-05 22:25:23 +00:00
parent 1e9d6c9ebc
commit d6e64707ff
73 changed files with 9469 additions and 5023 deletions

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Hello Wren &ndash; Wren</title> <title>Hello Wren &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -25,6 +28,7 @@
<li><a href="../getting-started.html">Getting Started</a></li> <li><a href="../getting-started.html">Getting Started</a></li>
<li><a href="../contributing.html">Contributing</a></li> <li><a href="../contributing.html">Contributing</a></li>
<li><a href="../blog">Blog</a></li> <li><a href="../blog">Blog</a></li>
<li><a href="../try">Try it!</a></li>
</ul> </ul>
</nav> </nav>
<nav class="small"> <nav class="small">
@ -37,44 +41,45 @@
</nav> </nav>
<main> <main>
<h2>Hello Wren</h2> <h2>Hello Wren</h2>
<p>4 Feb 2019 </p> <p>4 Feb 2019</p>
<hr /> <hr />
<p>Welcome to the new Wren development blog! </p> <p>Welcome to the new Wren development blog!</p>
<p>Around November 2018 on the Wren mailing list, munificent announced that a new maintainer is taking over the development and maintainence of the Wren language. <a href="https://groups.google.com/forum/#!topic/wren-lang/cMUwij-NIn0">The original post is here, with all the details.</a></p> <p>Around November 2018 on the Wren mailing list, munificent announced that a new maintainer is taking over the development and maintainence of the Wren language. <a href="https://groups.google.com/forum/#!topic/wren-lang/cMUwij-NIn0">The original post is here, with all the details.</a></p>
<p>In short, <a href="https://github.com/underscorediscovery">I&rsquo;m (underscorediscovery)</a> taking over from <a href="https://github.com/munificent">Bob (munificent)</a> as maintainer, but Bob is sticking around as a contributor!</p> <p>In short, <a href="https://github.com/ruby0x1">I&rsquo;m (ruby0x1)</a> taking over from <a href="https://github.com/munificent">Bob (munificent)</a> as maintainer, but Bob is sticking around as a contributor!</p>
<h3>The Wren blog <a href="#the-wren-blog" name="the-wren-blog" class="header-anchor">#</a></h3> <h3>The Wren blog <a href="#the-wren-blog" name="the-wren-blog" class="header-anchor">#</a></h3>
<p>One of the first things I felt Wren needed going forward is a consistent and centralized place to talk about the language. The existing design choices and goals, and especially the future and evolution of Wren are something a lot of people want to read about, in detail. Now we have a place to do exactly that! </p> <p>One of the first things I felt Wren needed going forward is a consistent and centralized place to talk about the language. The existing design choices and goals, and especially the future and evolution of Wren are something a lot of people want to read about, in detail. Now we have a place to do exactly that!</p>
<p>The blog will be keeping in the spirit of Wren by remaining simple. Posts are just regular markdown files in the repository alongside the rest of the site, and are considered part of the documentation. </p> <p>The blog will be keeping in the spirit of Wren by remaining simple. Posts are just regular markdown files in the repository alongside the rest of the site, and are considered part of the documentation.</p>
<p>Since Wren as a project aims to help others learn, having the in depth thought processes, development details and technical intricacy be documented in the same place, over a timeline, is valuable. </p> <p>Since Wren as a project aims to help others learn, having the in depth thought processes, development details and technical intricacy be documented in the same place, over a timeline, is valuable.</p>
<h3>What&rsquo;s next for Wren? <a href="#what's-next-for-wren" name="what's-next-for-wren" class="header-anchor">#</a></h3> <h3>What&rsquo;s next for Wren? <a href="#what's-next-for-wren" name="what's-next-for-wren" class="header-anchor">#</a></h3>
<p>First and foremost, I wanted to state explicitly that <strong>Wren is going to be changing</strong> but it is <strong>not going to become something else</strong>. </p> <p>First and foremost, I wanted to state explicitly that <strong>Wren is going to be changing</strong> but it is <strong>not going to become something else</strong>. </p>
<p>Wren attracted me as a language because of what it <em>is</em>, not because it isn&rsquo;t {<em>other language</em>}. If I wanted to use {<em>other language</em>} I would have, but I chose Wren because I wanted what it was. </p> <p>Wren attracted me as a language because of what it <em>is</em>, not because it isn&rsquo;t {<em>other language</em>}. If I wanted to use {<em>other language</em>} I would have, but I chose Wren because I wanted what it was. </p>
<p>So, Wren is going to be changing in ways that align with it&rsquo;s existing design intentions. Staying small, simple, learnable and hackable is all vital to what makes Wren valuable, and will remain. </p> <p>So, Wren is going to be changing in ways that align with it&rsquo;s existing design intentions. Staying small, simple, learnable and hackable is all vital to what makes Wren valuable, and will remain. </p>
<p>We&rsquo;re just as excited as you are to get to longer term changes and fun tweaks (we have lots of work done already in local projects like <a href="https://i.imgur.com/dazexnY.gifv">the debugger</a>). There&rsquo;s plenty of ideas we&rsquo;ve tried since we&rsquo;ve been <a href="https://luxeengine.com">using Wren full time</a> the last 2.5+ years, and can&rsquo;t wait to get started with bring those into master (and optional modules). There&rsquo;s a lot to do!</p> <p>We&rsquo;re just as excited as you are to get to longer term changes and fun tweaks (we have lots of work done already in local projects like <a href="https://i.imgur.com/dazexnY.gifv">the debugger</a>). There&rsquo;s plenty of ideas we&rsquo;ve tried since we&rsquo;ve been <a href="https://luxeengine.com">using Wren full time</a> the last 2.5+ years, and can&rsquo;t wait to get started with bring those into master (and optional modules). There&rsquo;s a lot to do!</p>
<p>In the next blog I want to try talk a bit more about the short to medium term goals and roadmap (rather than mixing it here with the meta/hello world post). Be sure to keep an eye out for that one, as it has more juicy details on what we&rsquo;re gonna get up to. </p> <p>In the next blog I want to try talk a bit more about the short to medium term goals and roadmap (rather than mixing it here with the meta/hello world post). Be sure to keep an eye out for that one, as it has more juicy details on what we&rsquo;re gonna get up to.</p>
<p>There are immediate term goals, though. </p> <p>There are immediate term goals, though.</p>
<h3>First steps <a href="#first-steps" name="first-steps" class="header-anchor">#</a></h3> <h3>First steps <a href="#first-steps" name="first-steps" class="header-anchor">#</a></h3>
<p>I think it&rsquo;s important to reset the baseline before we shake things up too much. Think of it as a ramp up to gain momentum, rather than running into a china store with arms flailing. </p> <p>I think it&rsquo;s important to reset the baseline before we shake things up too much. Think of it as a ramp up to gain momentum, rather than running into a china store with arms flailing. </p>
<ul> <ul>
<li>We&rsquo;re gonna clear out a bit of backlog, tidying up issues and PRs </li> <li>We&rsquo;re gonna clear out a bit of backlog, tidying up issues and PRs</li>
<li>Tidy up the website a bit, visually and structurally </li> <li>Tidy up the website a bit, visually and structurally</li>
<li>Make sure all documentation is up to date with the current development </li> <li>Make sure all documentation is up to date with the current development</li>
<li>Tag 0.2.0 with a list of relevant changes since 0.1.0 </li> <li>Tag 0.2.0 with a list of relevant changes since 0.1.0</li>
</ul> </ul>
<p>Once we tag 0.2.0, we&rsquo;ll be in a good place to move forward. And, everything up until now will have a well defined checkpoint preserved, if people want to refer to it. </p> <p>Once we tag 0.2.0, we&rsquo;ll be in a good place to move forward. And, everything up until now will have a well defined checkpoint preserved, if people want to refer to it.</p>
<h3>Steps so far <a href="#steps-so-far" name="steps-so-far" class="header-anchor">#</a></h3> <h3>Steps so far <a href="#steps-so-far" name="steps-so-far" class="header-anchor">#</a></h3>
<p>Since the announcement and transition, I&rsquo;ve been making my way through all the mailing list posts, issues and PRs in the backlog and reading all the way back to the early days. </p> <p>Since the announcement and transition, I&rsquo;ve been making my way through all the mailing list posts, issues and PRs in the backlog and reading all the way back to the early days. </p>
<p>I&rsquo;ve also been talking to community members one on one and getting personal experiences and thoughts on Wren. Forming a full picture will help us since we&rsquo;ll have an overview of what&rsquo;s most relevant (and what isn&rsquo;t) as time has passed, and gives us actionable things to do for the next milestone. I think it&rsquo;s an important step. </p> <p>I&rsquo;ve also been talking to community members one on one and getting personal experiences and thoughts on Wren. Forming a full picture will help us since we&rsquo;ll have an overview of what&rsquo;s most relevant (and what isn&rsquo;t) as time has passed, and gives us actionable things to do for the next milestone. I think it&rsquo;s an important step. </p>
<p>We&rsquo;ve also been investigating some of the PRs with the community to get those sorted out, since they&rsquo;re in the way. </p> <p>We&rsquo;ve also been investigating some of the PRs with the community to get those sorted out, since they&rsquo;re in the way.</p>
<p>Lastly, I&rsquo;ve already done a bit of clean up on the website and documentation theme, added a new logo, and of course added the blog. </p> <p>Lastly, I&rsquo;ve already done a bit of clean up on the website and documentation theme, added a new logo, and of course added the blog.</p>
<h3>Thanks! <a href="#thanks" name="thanks" class="header-anchor">#</a></h3> <h3>Thanks! <a href="#thanks" name="thanks" class="header-anchor">#</a></h3>
<p>Lastly, I wanted to say thanks to munificent, the community and all the contributors that have made Wren possible to this point. It&rsquo;s a wonderful thing and I look forward to seeing where we take it, together. </p> <p>Lastly, I wanted to say thanks to munificent, the community and all the contributors that have made Wren possible to this point. It&rsquo;s a wonderful thing and I look forward to seeing where we take it, together.</p>
<p>I hope you&rsquo;ll join us on the journey! </p> <p>I hope you&rsquo;ll join us on the journey!</p>
<h3>More <a href="#more" name="more" class="header-anchor">#</a></h3> <h3>More <a href="#more" name="more" class="header-anchor">#</a></h3>
<ul> <ul>
<li><a href="http://wren.io/blog/rss.xml">The Wren Blog RSS</a></li> <li><a href="http://wren.io/blog/rss.xml">The Wren Blog RSS</a></li>
<li>Visit the <a href="https://github.com/wren-lang">wren-lang organization</a> on Github.</li> <li>Join the <a href="https://discord.gg/Kx6PxSX">discord community</a></li>
<li>Follow <a href="https://twitter.com/munificentbob">@munificentbob</a> or <a href="https://twitter.com/___discovery">@___discovery</a> on twitter</li> <li>Visit the <a href="https://github.com/wren-lang">wren-lang organization</a> on GitHub.</li>
<li>Follow <a href="https://twitter.com/munificentbob">@munificentbob</a> or <a href="https://twitter.com/ruby0x1">@ruby0x1</a> on twitter</li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>0.2.0 and beyond &ndash; Wren</title> <title>0.2.0 and beyond &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -25,6 +28,7 @@
<li><a href="../getting-started.html">Getting Started</a></li> <li><a href="../getting-started.html">Getting Started</a></li>
<li><a href="../contributing.html">Contributing</a></li> <li><a href="../contributing.html">Contributing</a></li>
<li><a href="../blog">Blog</a></li> <li><a href="../blog">Blog</a></li>
<li><a href="../try">Try it!</a></li>
</ul> </ul>
</nav> </nav>
<nav class="small"> <nav class="small">
@ -37,62 +41,63 @@
</nav> </nav>
<main> <main>
<h2>0.2.0 and beyond</h2> <h2>0.2.0 and beyond</h2>
<p>30 Sep 2019 </p> <p>30 Sep 2019</p>
<hr /> <hr />
<h3>0.2.0 is here <a href="#0.2.0-is-here" name="0.2.0-is-here" class="header-anchor">#</a></h3> <h3>0.2.0 is here <a href="#0.2.0-is-here" name="0.2.0-is-here" class="header-anchor">#</a></h3>
<p>It&rsquo;s time to tag a release! <p>It&rsquo;s time to tag a release!
Let&rsquo;s check our goals from <a href="http://wren.io/blog/hello-wren.html">the last blog post</a>:</p> Let&rsquo;s check our goals from <a href="0-hello-wren.html">the last blog post</a>:</p>
<ul> <ul>
<li><s>We&rsquo;re gonna clear out a bit of backlog, tidying up issues and PRs</s> </li> <li><s>We&rsquo;re gonna clear out a bit of backlog, tidying up issues and PRs</s></li>
<li><s>Tidy up the website a bit, visually and structurally</s> </li> <li><s>Tidy up the website a bit, visually and structurally</s></li>
<li><s>Make sure all documentation is up to date with the current development</s> </li> <li><s>Make sure all documentation is up to date with the current development</s></li>
<li><s>Tag 0.2.0 with a list of relevant changes since 0.1.0</s> </li> <li><s>Tag 0.2.0 with a list of relevant changes since 0.1.0</s></li>
</ul> </ul>
<p>So far so good. </p> <p>So far so good.</p>
<h3>Backlog <a href="#backlog" name="backlog" class="header-anchor">#</a></h3> <h3>Backlog <a href="#backlog" name="backlog" class="header-anchor">#</a></h3>
<p>Clearing out the issues on a repo after some time has passed is always a bit tricky. </p> <p>Clearing out the issues on a repo after some time has passed is always a bit tricky. </p>
<p>Many issues are outdated (or unrelated), and some need a proper response. Some are related to future ideals, things that will take a while to get to. Some are related to the Wren CLI. It can be difficult to reason about the state of the tasks when they&rsquo;re all over the place, so we&rsquo;ve been consolidating. </p> <p>Many issues are outdated (or unrelated), and some need a proper response. Some are related to future ideals, things that will take a while to get to. Some are related to the Wren CLI. It can be difficult to reason about the state of the tasks when they&rsquo;re all over the place, so we&rsquo;ve been consolidating.</p>
<p>The good news is the issue list has been drastically reduced, 70+ issues being closed (or resolved). Around 21 of those are marked for future consideration, and 23 moved to the Wren CLI repository. More consolidation will still continue. </p> <p>The good news is the issue list has been drastically reduced, 70+ issues being closed (or resolved). Around 21 of those are marked for future consideration, and 23 moved to the Wren CLI repository. More consolidation will still continue.</p>
<p><strong>The goal is that the active issues are as relevant as possible in the immediate term.</strong> </p> <p><strong>The goal is that the active issues are as relevant as possible in the immediate term.</strong></p>
<p>A tricky but important aspect to mention here is the perception of closing an issue&hellip; <p>A tricky but important aspect to mention here is the perception of closing an issue&hellip;
A closed issue doesn&rsquo;t necessarily mean anything final, it&rsquo;s just a categorization tool! </p> A closed issue doesn&rsquo;t necessarily mean anything final, it&rsquo;s just a categorization tool!</p>
<p>The other categorization tool which operates <em>within</em> open/closed categories, is the <em>label</em>. Labels allow us to distinguish clearly the different types of issues, which makes open/closed less binary and more nuanced and rich. We rely on both to make sense of the list. </p> <p>The other categorization tool which operates <em>within</em> open/closed categories, is the <em>label</em>. Labels allow us to distinguish clearly the different types of issues, which makes open/closed less binary and more nuanced and rich. We rely on both to make sense of the list.</p>
<p>For example, discussions of future tasks, ideas or goals <a href="https://github.com/wren-lang/wren/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+label%3Afuture+">are tagged <code>future</code></a>. Now we can refer to them later, and re-open them when they become active and relevant again.</p> <p>For example, discussions of future tasks, ideas or goals <a href="https://github.com/wren-lang/wren/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+label%3Afuture+">are tagged <code>future</code></a>. Now we can refer to them later, and re-open them when they become active and relevant again.</p>
<p><strong>We&rsquo;re in this together.</strong> <p><strong>We&rsquo;re in this together.</strong> <br />
Please don&rsquo;t be discouraged if an issue is closed! Discussion is absolutely encouraged and ideas, proposals and input is very necessary. Feel free to keep a discussion going, even if the issue it&rsquo;s attached to has been marked as closed. </p> Please don&rsquo;t be discouraged if an issue is closed! Discussion is absolutely encouraged and ideas, proposals and input is very necessary. Feel free to keep a discussion going, even if the issue it&rsquo;s attached to has been marked as closed.</p>
<h3>0.2.0 <a href="#0.2.0" name="0.2.0" class="header-anchor">#</a></h3> <h3>0.2.0 <a href="#0.2.0" name="0.2.0" class="header-anchor">#</a></h3>
<p>We&rsquo;ve been hammering away on Wren since 0.1.0 for quite a while. The <a href="https://github.com/wren-lang/wren/compare/0.1.0...5338275dcdd97fd8d9fc614f420a645500836a59">change list on Github</a> is too long to display!</p> <p>We&rsquo;ve been hammering away on Wren since 0.1.0 for quite a while. The <a href="https://github.com/wren-lang/wren/compare/0.1.0...5338275dcdd97fd8d9fc614f420a645500836a59">change list on GitHub</a> is too long to display!</p>
<p>Most importantly, before we start iterating on the language further, I wanted to make sure we had a checkpoint to look back to. That&rsquo;s largely what 0.2.0 is about. </p> <p>Most importantly, before we start iterating on the language further, I wanted to make sure we had a checkpoint to look back to. That&rsquo;s largely what 0.2.0 is about.</p>
<p>There&rsquo;s quite a lot of good changes, with <strong>290 commits from 41 contributors!</strong> <p>There&rsquo;s quite a lot of good changes, with <strong>290 commits from 41 contributors!</strong>
Thanks to everyone getting involved, every little bit has helped Wren, no matter how small the contribution. </p> Thanks to everyone getting involved, every little bit has helped Wren, no matter how small the contribution.</p>
<h3>0.3.0 <a href="#0.3.0" name="0.3.0" class="header-anchor">#</a></h3> <h3>0.3.0 <a href="#0.3.0" name="0.3.0" class="header-anchor">#</a></h3>
<p>With 0.2.0 wrapped up, our next release won&rsquo;t be as far away this time. </p> <p>With 0.2.0 wrapped up, our next release won&rsquo;t be as far away this time.</p>
<p><strong>The primary goal for 0.3.0 is separating the VM from the CLI.</strong> </p> <p><strong>The primary goal for 0.3.0 is separating the VM from the CLI.</strong></p>
<p>This includes updated documentation, splitting the source repos, migrating all the tests, issues and more. <p>This includes updated documentation, splitting the source repos, migrating all the tests, issues and more.
All the code and documentation will still be easy to access in one place, but clarity around Wren as a project will improve a lot. </p> All the code and documentation will still be easy to access in one place, but clarity around Wren as a project will improve a lot.</p>
<p>The migration has already started, you can <a href="https://github.com/wren-lang/wren-cli">find the wren-cli repository here</a>. <p>The migration has already started, you can <a href="https://github.com/wren-lang/wren-cli">find the wren-cli repository here</a>.
I&rsquo;m working on some of the refactoring on the <a href="https://github.com/wren-lang/wren/tree/wren-cli-refactor">wren-cli-refactor branch.</a></p> I&rsquo;m working on some of the refactoring on the <a href="https://github.com/wren-lang/wren/tree/wren-cli-refactor">wren-cli-refactor branch.</a></p>
<p>With that, we&rsquo;ll also have a cleaner build process for the CLI. <p>With that, we&rsquo;ll also have a cleaner build process for the CLI.
On some platforms (Windows especially), there have been several pain points, these will be addressed. On some platforms (Windows especially), there have been several pain points, these will be addressed.
There&rsquo;s also gonna be an additional build target, namely emscripten, so we can easily run Wren examples on the Wren website and documentation. </p> There&rsquo;s also gonna be an additional build target, namely emscripten, so we can easily run Wren examples on the Wren website and documentation.</p>
<p>And finally, we&rsquo;ll have some proper prebuilt releases with 0.3.0. <p>And finally, we&rsquo;ll have some proper prebuilt releases with 0.3.0.
I know many people have just wanted to grab an executable and give the language a go, but that hasn&rsquo;t been an option. I know many people have just wanted to grab an executable and give the language a go, but that hasn&rsquo;t been an option.
We&rsquo;ll fix that with 0.3.0. </p> We&rsquo;ll fix that with 0.3.0.</p>
<p>The 0.3.0 goals in simple form: <p>The 0.3.0 goals in simple form:
- VM / CLI split - VM / CLI split
- Build consistency/reliablity - Build consistency/reliablity
- Web build for embedding in docs - Web build for embedding in docs
- Prebuilt releases </p> - Prebuilt releases</p>
<h3>Beyond <a href="#beyond" name="beyond" class="header-anchor">#</a></h3> <h3>Beyond <a href="#beyond" name="beyond" class="header-anchor">#</a></h3>
<p>I don&rsquo;t have any concrete plans for 0.4.0 right now, but once the dust settles from 0.3.0 we&rsquo;ll have a clearer view. </p> <p>I don&rsquo;t have any concrete plans for 0.4.0 right now, but once the dust settles from 0.3.0 we&rsquo;ll have a clearer view.</p>
<p>There&rsquo;s definitely things in the pipeline though, I&rsquo;ve been playing with <a href="https://github.com/wren-lang/wren/pull/701">adding compound assignments like <code>+=</code></a>.</p> <p>There&rsquo;s definitely things in the pipeline though, I&rsquo;ve been playing with <a href="https://github.com/wren-lang/wren/pull/701">adding compound assignments like <code>+=</code></a>.</p>
<p>More details about in development features and fixes can be found on the repo in the meantime. </p> <p>More details about in development features and fixes can be found on the repo in the meantime.</p>
<p>Thanks for reading! </p> <p>Thanks for reading!</p>
<h3>More <a href="#more" name="more" class="header-anchor">#</a></h3> <h3>More <a href="#more" name="more" class="header-anchor">#</a></h3>
<ul> <ul>
<li><a href="http://wren.io/blog/rss.xml">The Wren Blog RSS</a></li> <li><a href="http://wren.io/blog/rss.xml">The Wren Blog RSS</a></li>
<li>Visit the <a href="https://github.com/wren-lang">wren-lang organization</a> on Github to get involved.</li> <li>Join the <a href="https://discord.gg/Kx6PxSX">discord community</a></li>
<li>Follow the developers <a href="https://twitter.com/munificentbob">@munificentbob</a> or <a href="https://twitter.com/___discovery">@___discovery</a> on twitter</li> <li>Visit the <a href="https://github.com/wren-lang">wren-lang organization</a> on GitHub to get involved.</li>
<li>Follow the developers <a href="https://twitter.com/munificentbob">@munificentbob</a> or <a href="https://twitter.com/ruby0x1">@ruby0x1</a> on twitter</li>
</ul> </ul>
</main> </main>
</div> </div>

164
blog/2-0.3.0-released.html Normal file
View File

@ -0,0 +1,164 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>0.3.0 released! &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top">
<header>
<div class="page">
<div class="main-column">
<h1><a href="../">wren</a></h1>
<h2>a classy little scripting language</h2>
</div>
</div>
</header>
<div class="page">
<nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../getting-started.html">Getting Started</a></li>
<li><a href="../contributing.html">Contributing</a></li>
<li><a href="../blog">Blog</a></li>
<li><a href="../try">Try it!</a></li>
</ul>
</nav>
<nav class="small">
<table>
<tr>
<td><a href="getting-started.html">Getting Started</a></td>
<td><a href="contributing.html">Contributing</a></td>
</tr>
</table>
</nav>
<main>
<h2>0.3.0 released!</h2>
<p>5 June 2020</p>
<hr />
<p>In this post we&rsquo;ll cover 0.3.0 and the goals for 0.4.0 <a href="#goals-for-0.4.0">#</a>.</p>
<h2>About the 0.3.0 release <a href="#about-the-0.3.0-release" name="about-the-0.3.0-release" class="header-anchor">#</a></h2>
<p>Let&rsquo;s revisit our goals from <a href="1-0.2.0-and-beyond.html">the last blog post</a>, <br />
and mark what we managed to get done:</p>
<ul>
<li><s>VM / CLI split</s> <a href="#vm--cli-split">#</a></li>
<li><s>Build consistency/reliablity</s> <a href="#build-consistencyreliability">#</a></li>
<li><s>Web build for embedding in docs</s> <a href="#web-build-for-embedding-in-docs">#</a></li>
<li><s>Prebuilt releases</s> <a href="#prebuilt-releases">#</a></li>
</ul>
<h2>The details <a href="#the-details" name="the-details" class="header-anchor">#</a></h2>
<h3>VM / CLI split <a href="#vm--cli-split" name="vm--cli-split" class="header-anchor">#</a></h3>
<p>With 0.3.0 we&rsquo;ve separated the CLI from the Wren repo,
and updated the docs to make the distinction clearer.</p>
<p>The <a href="../cli">CLI now has it&rsquo;s own corner of the docs</a>, so that the modules
and API docs aren&rsquo;t overlapped like before. This opens up space for the
CLI to get better, fuller documentation, and removes confusion about
built in modules vs ones that are in the CLI only.</p>
<p>The code structure is clearer, too, and all the tests and utils are now specific.</p>
<h3>Build consistency/reliability <a href="#build-consistencyreliability" name="build-consistencyreliability" class="header-anchor">#</a></h3>
<p>Previously, builds on Windows could be a little fickle, and there was sometimes
issues with the dependencies on the CLI side.</p>
<p>To solve this, premake is now used to generate platform specific project files that
&lsquo;just work&rsquo;, making it a one step process to build the VM or CLI. Both projects
now have a <code>projects/</code> folder which includes ready to go project files for primary platforms.</p>
<p><small>The original <code>Makefile</code> and <code>util/wren.mk</code> no longer exist, so there might be some work needed
to reintegrate if you relied on those. You can find the updated makefile in <code>projects/make/</code>, or <code>projects/make.mac/</code>.</small></p>
<p>The <strong>amalgamated build</strong> was fixed too, so that embedding in your own project is as simple as
including a single c file (and the <code>wren.h</code> header).</p>
<p>On the <strong>CLI</strong> side, the pre-build steps were removed and dependencies vendored in repo,
so that the project just builds with less potential points of error, especially across platforms.</p>
<p>And finally the <strong>docs</strong>! Previously <a href="https://sass-lang.com/">SASS</a> was used, and code highlighting
was done at generation time using pygments, a python code highlighter. Both of these dependencies
have been removed, code highlighting is now done on the client side instead (see another reason why below).
The benefit here that it is now <em>easy</em> to edit the docs, just a simple python command, no setup!</p>
<h3>Web build for embedding in docs <a href="#web-build-for-embedding-in-docs" name="web-build-for-embedding-in-docs" class="header-anchor">#</a></h3>
<p>The goal was two part here, one is to have a page to just try out Wren.
Type in some code, run it. That&rsquo;s the first big step and we&rsquo;ve now got that on the docs page.</p>
<h4><a href="../try" target="_blank" class="dark-link">Try Wren directly in your browser!</a></h4>
<p>This should work on desktop or mobile, and will continue to be improved over time.</p>
<p>The second part of that goal is having the VM available to make examples on each page interactive.
This is implemented, <em>but not activated on any pages yet</em>.</p>
<p>In the near future inline doc examples will have a small button that you can
press to see the code result right there, live. Since there&rsquo;s a lot of examples,
and sometimes they&rsquo;re fragments of code that don&rsquo;t run in isolation,
it will take time to propagate it through the pages.</p>
<p>Mainly, I didn&rsquo;t want this to hold up 0.3.0, but expect to start seeing it soon.</p>
<h3>Prebuilt releases <a href="#prebuilt-releases" name="prebuilt-releases" class="header-anchor">#</a></h3>
<p>In addition to the browser based build that removes a barrier to trying out Wren,
Wren CLI has prebuilt binaries for Mac, Windows and Linux now! This gives
an easy path to just tinkering with Wren before embedding it.</p>
<hr />
<h2>Goals for 0.4.0 <a href="#goals-for-0.4.0" name="goals-for-0.4.0" class="header-anchor">#</a></h2>
<p>With 0.4.0 the goal is to address a couple of bigger todos, but also to push the language
itself, and the embedding experience forward.</p>
<p>You can see some of the <a href="https://github.com/wren-lang/wren/pulls?q=is%3Apr+is%3Aopen+label%3A0.4.0">work in progress tasks</a> here,
but there&rsquo;s a few things I&rsquo;d like to resolve in 0.4.0.</p>
<p><strong>Compound operators</strong> <br />
I&rsquo;ve really missed having <code>+=</code> and friends, <br />
so I&rsquo;ve been working on a (broken, wip) <a href="https://github.com/wren-lang/wren/pull/701">PR here</a>.
I&rsquo;ve since had a better idea to implement it and will hope to address that in 0.4.0.</p>
<p><strong>Chained methods (&lsquo;fluent interfaces&rsquo;)</strong> <br />
Currently in Wren it&rsquo;s required that the period (<code>.</code>) be on the same line as the method.
<pre class="snippet">
example.
some().
functions().
here()
</pre>
This isn&rsquo;t as elegant as we&rsquo;d want for this form of API,
so <strong>in 0.4.0 the goal is</strong> allowing a newline, as you&rsquo;d expect:
<pre class="snippet">
example
.some()
.functions()
.here()
</pre>
This doesn&rsquo;t seem like a big deal but when your calls are wider,
longer and possibly accept block functions. It&rsquo;s hard to read,
and can be less fun to track down a missing <code>.</code> in a big chunk of code.
<pre class="snippet">
example.
some {|args, and, stuff|
&hellip;
}.
here()
</pre></p>
<p><strong>C Side APIs</strong> <br />
Some APIs for dealing with <code>Map</code> have been proposed several times,
it&rsquo;s time to bring that into the API. There&rsquo;s some additions for <code>List</code> as well,
like a helper to set an element in a list.</p>
<p><strong>Other goals</strong> <br />
There&rsquo;s a few more things but I&rsquo;m still exploring their viability. <br />
Keep an eye on the <a href="https://github.com/wren-lang/wren">PRs/issues</a> or the <a href="https://github.com/wren-lang/wren/pulls?q=is%3Apr+is%3Aopen+label%3A0.4.0">0.4.0 label</a> to see when they&rsquo;re discussed.</p>
<h2>Till next time <a href="#till-next-time" name="till-next-time" class="header-anchor">#</a></h2>
<hr />
<ul>
<li><a href="http://wren.io/blog/rss.xml">The Wren Blog RSS</a></li>
<li>Join the <a href="https://discord.gg/Kx6PxSX">discord community</a></li>
<li>Visit the <a href="https://github.com/wren-lang">wren-lang organization</a> on GitHub to get involved.</li>
<li>Follow the developers <a href="https://twitter.com/munificentbob">@munificentbob</a> or <a href="https://twitter.com/ruby0x1">@ruby0x1</a> on twitter</li>
</ul>
</main>
</div>
<footer>
<div class="page">
<div class="main-column">
<p>Wren lives
<a href="https://github.com/wren-lang/wren">on GitHub</a>
&mdash; Made with &#x2764; by
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
<a href="https://github.com/wren-lang/wren/blob/master/AUTHORS">friends</a>.
</p>
<div class="main-column">
</div>
</footer>
</body>
</html>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Development blogs &ndash; Wren</title> <title>Development blogs &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -25,6 +28,7 @@
<li><a href="../getting-started.html">Getting Started</a></li> <li><a href="../getting-started.html">Getting Started</a></li>
<li><a href="../contributing.html">Contributing</a></li> <li><a href="../contributing.html">Contributing</a></li>
<li><a href="../blog">Blog</a></li> <li><a href="../blog">Blog</a></li>
<li><a href="../try">Try it!</a></li>
</ul> </ul>
</nav> </nav>
<nav class="small"> <nav class="small">
@ -37,13 +41,17 @@
</nav> </nav>
<main> <main>
<h2>Development blogs</h2> <h2>Development blogs</h2>
<p><a href="0.2.0-and-beyond.html"><h3>0.2.0 and beyond</h3></a> </p> <p><a href="2-0.3.0-released.html"><h3>0.3.0 released!</h3></a></p>
<blockquote> <blockquote>
<p><date>30 Sep 2019</date>Checkpoints, and the plans for 0.3.0. </p> <p><date>5 June 2020</date>0.3.0 release info! Plus some notes and goals for the next release, 0.4.0.</p>
</blockquote> </blockquote>
<p><a href="hello-wren.html"><h3>System.print(&ldquo;hello wren&rdquo;)</h3></a> </p> <p><a href="1-0.2.0-and-beyond.html"><h3>0.2.0 and beyond</h3></a></p>
<blockquote> <blockquote>
<p><date>4 Feb 2019</date>A short post introducing the blog, the new maintainer, and the immediate term plans for Wren. </p> <p><date>30 Sep 2019</date>Checkpoints, and the plans for 0.3.0.</p>
</blockquote>
<p><a href="0-hello-wren.html"><h3>System.print(&ldquo;hello wren&rdquo;)</h3></a></p>
<blockquote>
<p><date>4 Feb 2019</date> • A short post introducing the blog, the new maintainer, and the immediate term plans for Wren.</p>
</blockquote> </blockquote>
</main> </main>
</div> </div>

View File

@ -3,18 +3,25 @@
<link>https://wren.io/</link> <link>https://wren.io/</link>
<description>The development blog of the Wren programming language.</description> <description>The development blog of the Wren programming language.</description>
<language>en-us</language> <language>en-us</language>
<item>
<title>0.3.0 released</title>
<link>https://wren.io/blog/2-0.3.0-released.html</link>
<description>0.3.0 release info! Plus some notes and goals for the next release, 0.4.0.</description>
<guid>https://wren.io/blog/2-0.3.0-released.html</guid>
<pubDate>Mon, 30 Sep 2019 00:00:00 GMT</pubDate>
</item>
<item> <item>
<title>0.2.0 and beyond</title> <title>0.2.0 and beyond</title>
<link>https://wren.io/blog/0.2.0-and-beyond.html</link> <link>https://wren.io/blog/1-0.2.0-and-beyond.html</link>
<description>Checkpoints, and the plans for 0.3.0.</description> <description>Checkpoints, and the plans for 0.3.0.</description>
<guid>https://wren.io/blog/0.2.0-and-beyond.html</guid> <guid>https://wren.io/blog/1-0.2.0-and-beyond.html</guid>
<pubDate>Mon, 30 Sep 2019 00:00:00 GMT</pubDate> <pubDate>Mon, 30 Sep 2019 00:00:00 GMT</pubDate>
</item> </item>
<item> <item>
<title>System.print("hello wren")</title> <title>System.print("hello wren")</title>
<link>https://wren.io/blog/hello-wren.html</link> <link>https://wren.io/blog/0-hello-wren.html</link>
<description>A short post introducing the blog, the new maintainer, and the immediate term plans for Wren.</description> <description>A short post introducing the blog, the new maintainer, and the immediate term plans for Wren.</description>
<guid>https://wren.io/blog/hello-wren.html</guid> <guid>https://wren.io/blog/0-hello-wren.html</guid>
<pubDate>Mon, 04 Feb 2019 00:00:00 GMT</pubDate> <pubDate>Mon, 04 Feb 2019 00:00:00 GMT</pubDate>
</item> </item>
</channel> </channel>

File diff suppressed because it is too large Load Diff

108
cli/index.html Normal file
View File

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Wren CLI &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top">
<header>
<div class="page">
<div class="main-column">
<h1><a href="../">wren</a></h1>
<h2>a classy little scripting language</h2>
</div>
</div>
</header>
<div class="page">
<nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section>
<h2>Wren CLI</h2>
<ul>
<li><a href="./">About</a></li>
<li><a target="_blank" href="https://github.com/wren-lang/wren-cli/releases">Downloads</a></li>
<li><a href="usage.html">Usage</a></li>
</ul>
</section>
<section>
<h2>API docs</h2>
<ul>
<li><a href="modules">CLI Modules</a></li>
</ul>
</section>
</nav>
<nav class="small">
<table>
<tr>
<div><a href="../">Back to Wren</a></div>
</tr>
<tr>
<td><h2>CLI</h2></td>
<td><h2>API</h2></td>
</tr>
<tr>
<td>
<ul>
<li><a href="./">About</a></li>
<li><a target="_blank" href="https://github.com/wren-lang/wren-cli/releases">Downloads</a></li>
<li><a href="usage.html">Usage</a></li>
</ul>
</td>
<td>
<ul>
<li><a href="modules">CLI Modules</a></li>
</ul>
</td>
</tr>
</table>
</nav>
<main>
<h2>Wren CLI</h2>
<hr />
<h2>What is it? <a href="#what-is-it" name="what-is-it" class="header-anchor">#</a></h2>
<p><strong>The Wren Command-Line Interface</strong> is a tool you can run which gives you a way to run Wren code, and
also includes modules for talking to the operating system&mdash;file IO,
networking, stuff like that. It depends on <a href="http://libuv.org/">libuv</a> for that
functionality.</p>
<p>Wren as a language is intentionally designed to be minimal. <br />
That includes the built in language features, the standard library and the VM itself.</p>
<p>In order to access files, networks and other IO, you&rsquo;d need to make a tool <em>using</em> the language VM.
That&rsquo;s what the CLI project is! It is not bundled as part of the wren project,
instead it is it&rsquo;s own project as a standalone tool you can run.
It exposes it&rsquo;s own standard library and modules that may be of interest
if looking for a general purpose single binary scriptable tool.</p>
<p>Wren CLI is a work in progress, and contributions are welcome to make it more useful over time.</p>
<h2>Why does it exist? <a href="#why-does-it-exist" name="why-does-it-exist" class="header-anchor">#</a></h2>
<ul>
<li>It&rsquo;s fun to make things.</li>
<li>It&rsquo;s always a good idea to test the language you&rsquo;re making!</li>
<li>Interest was expressed in a scriptable tool using the Wren language.</li>
<li>It&rsquo;s helpful for others to learn from, since it is a real world usage example showing several concepts.</li>
</ul>
</main>
</div>
<footer>
<div class="page">
<div class="main-column">
<p>Wren lives
<a href="https://github.com/wren-lang/wren">on GitHub</a>
&mdash; Made with &#x2764; by
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
<a href="https://github.com/wren-lang/wren/blob/master/AUTHORS">friends</a>.
</p>
<div class="main-column">
</div>
</footer>
</body>
</html>

105
cli/modules/index.html Normal file
View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>CLI Modules &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top" class="module">
<header>
<div class="page">
<div class="main-column">
<h1><a href="../../">wren</a></h1>
<h2>a classy little scripting language</h2>
</div>
</div>
</header>
<div class="page">
<nav class="big">
<a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren CLI</a></li>
</ul>
<section>
<h2>Built In</h2>
<ul>
<li><a href="../../modules">Wren modules</a></li>
</ul>
</section>
<section>
<h2>CLI modules</h2>
<ul>
<li><a href="io">io</a></li>
<li><a href="os">os</a></li>
<li><a href="scheduler">scheduler</a></li>
<li><a href="timer">timer</a></li>
</ul>
</section>
</nav>
<nav class="small">
<table>
<tr>
<td><h2>core</h2></td>
<td><h2>optional</h2></td>
<td><h2>cli</h2></td>
</tr>
<tr>
<td>
<ul>
<li><a href="core">core</a></li>
</ul>
</td>
<td>
<ul>
<li><a href="meta">meta</a></li>
<li><a href="random">random</a></li>
</ul>
</td>
<td>
<ul>
<li><a href="io">io</a></li>
<li><a href="os">os</a></li>
<li><a href="scheduler">scheduler</a></li>
<li><a href="timer">timer</a></li>
</ul>
</td>
</tr>
</table>
</nav>
<main>
<h1>CLI Modules</h1>
<p>The Wren CLI executable extends the built in language modules with it&rsquo;s own,
which offer access to IO and other facilities for scripting.</p>
<p>The CLI modules are deeply tied to <a href="http://libuv.org">libuv</a>, each other, and other internals
of the command-line app, so can&rsquo;t easily be separated out and pulled into host
applications that want to embed Wren. Scripts written for the CLI then,
are specific to the CLI unless another host implements the same API.</p>
<ul>
<li><a href="io">io</a></li>
<li><a href="os">os</a></li>
<li><a href="scheduler">scheduler</a></li>
<li><a href="timer">timer</a></li>
</ul>
</main>
</div>
<footer>
<div class="page">
<div class="main-column">
<p>Wren lives
<a href="https://github.com/wren-lang/wren">on GitHub</a>
&mdash; Made with &#x2764; by
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
<a href="https://github.com/wren-lang/wren/blob/master/AUTHORS">friends</a>.
</p>
<div class="main-column">
</div>
</footer>
</body>
</html>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Directory Class &ndash; Wren</title> <title>Directory Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">io</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">io module</a></li>
</ul> </ul>
<section> <section>
<h2>io classes</h2> <h2>io classes</h2>
@ -40,8 +44,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">io</a></td> <td><a href="./">io module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>io classes</h2></td> <td colspan="2"><h2>io classes</h2></td>
@ -66,14 +70,14 @@
</nav> </nav>
<main> <main>
<h1>Directory Class</h1> <h1>Directory Class</h1>
<p>A directory on the file system. </p> <p>A directory on the file system.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>Directory.<strong>exists</strong>(path) <a href="#directory.exists(path)" name="directory.exists(path)" class="header-anchor">#</a></h3> <h3>Directory.<strong>exists</strong>(path) <a href="#directory.exists(path)" name="directory.exists(path)" class="header-anchor">#</a></h3>
<p>Whether a directory exists at <code>path</code>. This returns <code>false</code> for files or other <p>Whether a directory exists at <code>path</code>. This returns <code>false</code> for files or other
special file system entities. </p> special file system entities.</p>
<h3>Directory.<strong>list</strong>(path) <a href="#directory.list(path)" name="directory.list(path)" class="header-anchor">#</a></h3> <h3>Directory.<strong>list</strong>(path) <a href="#directory.list(path)" name="directory.list(path)" class="header-anchor">#</a></h3>
<p>Lists the contents of the directory at <code>path</code>. Returns a sorted list of path <p>Lists the contents of the directory at <code>path</code>. Returns a sorted list of path
strings for all of the contents of the directory. </p> strings for all of the contents of the directory.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>FileFlags Class &ndash; Wren</title> <title>FileFlags Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">io</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">io module</a></li>
</ul> </ul>
<section> <section>
<h2>io classes</h2> <h2>io classes</h2>
@ -40,8 +44,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">io</a></td> <td><a href="./">io module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>io classes</h2></td> <td colspan="2"><h2>io classes</h2></td>
@ -66,33 +70,33 @@
</nav> </nav>
<main> <main>
<h1>FileFlags Class</h1> <h1>FileFlags Class</h1>
<p>Contains constants for the various file flags used to open or create a file. <p>Contains constants for the various file flags used to open or create a file.
These correspond directly to the flags that can be passed to the POSIX These correspond directly to the flags that can be passed to the POSIX
<a href="http://linux.die.net/man/2/open"><code>open()</code></a> syscall. </p> <a href="http://linux.die.net/man/2/open"><code>open()</code></a> syscall.</p>
<p>They are integers and can be bitwise or&rsquo;ed together to produce a composite <p>They are integers and can be bitwise or&rsquo;ed together to produce a composite
flag. </p> flag.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>FileFlags.<strong>readOnly</strong> <a href="#fileflags.readonly" name="fileflags.readonly" class="header-anchor">#</a></h3> <h3>FileFlags.<strong>readOnly</strong> <a href="#fileflags.readonly" name="fileflags.readonly" class="header-anchor">#</a></h3>
<p>The file can be read from but not written. Equivalent to <code>O_RDONLY</code>. </p> <p>The file can be read from but not written. Equivalent to <code>O_RDONLY</code>.</p>
<h3>FileFlags.<strong>writeOnly</strong> <a href="#fileflags.writeonly" name="fileflags.writeonly" class="header-anchor">#</a></h3> <h3>FileFlags.<strong>writeOnly</strong> <a href="#fileflags.writeonly" name="fileflags.writeonly" class="header-anchor">#</a></h3>
<p>The file can be written but not read from. Equivalent to <code>O_WRONLY</code>. </p> <p>The file can be written but not read from. Equivalent to <code>O_WRONLY</code>.</p>
<h3>FileFlags.<strong>readWrite</strong> <a href="#fileflags.readwrite" name="fileflags.readwrite" class="header-anchor">#</a></h3> <h3>FileFlags.<strong>readWrite</strong> <a href="#fileflags.readwrite" name="fileflags.readwrite" class="header-anchor">#</a></h3>
<p>The file can be both read from and written to. Equivalent to <code>O_RDWR</code>. </p> <p>The file can be both read from and written to. Equivalent to <code>O_RDWR</code>.</p>
<h3>FileFlags.<strong>sync</strong> <a href="#fileflags.sync" name="fileflags.sync" class="header-anchor">#</a></h3> <h3>FileFlags.<strong>sync</strong> <a href="#fileflags.sync" name="fileflags.sync" class="header-anchor">#</a></h3>
<p>Writes will block until the data has been physically written to the underling <p>Writes will block until the data has been physically written to the underling
hardware. This does <em>not</em> affect whether or the file API is synchronous. File hardware. This does <em>not</em> affect whether or the file API is synchronous. File
operations are always asynchronous in Wren and may allow other scheduled fibers operations are always asynchronous in Wren and may allow other scheduled fibers
to run. </p> to run.</p>
<p>This is a lower-level flag that ensures that when a write completes, it has <p>This is a lower-level flag that ensures that when a write completes, it has
been flushed all the way to disc. </p> been flushed all the way to disc.</p>
<h3>FileFlags.<strong>create</strong> <a href="#fileflags.create" name="fileflags.create" class="header-anchor">#</a></h3> <h3>FileFlags.<strong>create</strong> <a href="#fileflags.create" name="fileflags.create" class="header-anchor">#</a></h3>
<p>Creates a new file if a file at the given path does not already exist. </p> <p>Creates a new file if a file at the given path does not already exist.</p>
<h3>FileFlags.<strong>truncate</strong> <a href="#fileflags.truncate" name="fileflags.truncate" class="header-anchor">#</a></h3> <h3>FileFlags.<strong>truncate</strong> <a href="#fileflags.truncate" name="fileflags.truncate" class="header-anchor">#</a></h3>
<p>If the file already exists and can be written to, its previous contents are <p>If the file already exists and can be written to, its previous contents are
discarded. </p> discarded.</p>
<h3>FileFlags.<strong>exclusive</strong> <a href="#fileflags.exclusive" name="fileflags.exclusive" class="header-anchor">#</a></h3> <h3>FileFlags.<strong>exclusive</strong> <a href="#fileflags.exclusive" name="fileflags.exclusive" class="header-anchor">#</a></h3>
<p>Ensures that a new file must be created. If a file already exists at the given <p>Ensures that a new file must be created. If a file already exists at the given
path, this flag will cause the operation to fail. </p> path, this flag will cause the operation to fail.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>File Class &ndash; Wren</title> <title>File Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">io</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">io module</a></li>
</ul> </ul>
<section> <section>
<h2>io classes</h2> <h2>io classes</h2>
@ -40,8 +44,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">io</a></td> <td><a href="./">io module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>io classes</h2></td> <td colspan="2"><h2>io classes</h2></td>
@ -66,103 +70,103 @@
</nav> </nav>
<main> <main>
<h1>File Class</h1> <h1>File Class</h1>
<p>Lets you work with files on the file system. An instance of this class <p>Lets you work with files on the file system. An instance of this class
represents an open file with a file descriptor. </p> represents an open file with a file descriptor.</p>
<p>When you are done with a file object, it&rsquo;s a good idea to explicitly close it. <p>When you are done with a file object, it&rsquo;s a good idea to explicitly close it.
If you don&rsquo;t, the GC will close it when the file is no longer used and gets If you don&rsquo;t, the GC will close it when the file is no longer used and gets
finalized, but that may take a while. In the meantime, leaving it open wastes finalized, but that may take a while. In the meantime, leaving it open wastes
a file descriptor. </p> a file descriptor.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>File.<strong>create</strong>(path, fn) <a href="#file.create(path,-fn)" name="file.create(path,-fn)" class="header-anchor">#</a></h3> <h3>File.<strong>create</strong>(path, fn) <a href="#file.create(path,-fn)" name="file.create(path,-fn)" class="header-anchor">#</a></h3>
<p>Opens the file at <code>path</code> for writing and passes it to <code>fn</code>. If there is already <p>Opens the file at <code>path</code> for writing and passes it to <code>fn</code>. If there is already
a file at that path, it is truncated. After the function returns, the file is a file at that path, it is truncated. After the function returns, the file is
automatically closed. </p> automatically closed.</p>
<div class="codehilite"><pre><span class="vg">File</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="s">&quot;numbers.txt&quot;</span><span class="p">)</span> <span class="p">{</span><span class="o">|</span><span class="n">file</span><span class="o">|</span> <pre class="snippet">
<span class="n">file</span><span class="o">.</span><span class="n">writeBytes</span><span class="p">(</span><span class="s">&quot;one two three&quot;</span><span class="p">)</span> File.create("numbers.txt") {|file|
<span class="p">}</span> file.writeBytes("one two three")
</pre></div> }
</pre>
<h3>File.<strong>delete</strong>(path) <a href="#file.delete(path)" name="file.delete(path)" class="header-anchor">#</a></h3> <h3>File.<strong>delete</strong>(path) <a href="#file.delete(path)" name="file.delete(path)" class="header-anchor">#</a></h3>
<p>Deletes the file at <code>path</code>. </p> <p>Deletes the file at <code>path</code>.</p>
<h3>File.<strong>exists</strong>(path) <a href="#file.exists(path)" name="file.exists(path)" class="header-anchor">#</a></h3> <h3>File.<strong>exists</strong>(path) <a href="#file.exists(path)" name="file.exists(path)" class="header-anchor">#</a></h3>
<p>Whether a regular file exists at <code>path</code>. This returns <code>false</code> for directories <p>Whether a regular file exists at <code>path</code>. This returns <code>false</code> for directories
or other special file system entities. </p> or other special file system entities.</p>
<h3>File.<strong>open</strong>(path, fn) <a href="#file.open(path,-fn)" name="file.open(path,-fn)" class="header-anchor">#</a></h3> <h3>File.<strong>open</strong>(path, fn) <a href="#file.open(path,-fn)" name="file.open(path,-fn)" class="header-anchor">#</a></h3>
<p>Opens the file at <code>path</code> for reading and passes it to <code>fn</code>. After the function <p>Opens the file at <code>path</code> for reading and passes it to <code>fn</code>. After the function
returns, the file is automatically closed. </p> returns, the file is automatically closed.</p>
<div class="codehilite"><pre><span class="vg">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&quot;words.txt&quot;</span><span class="p">)</span> <span class="p">{</span><span class="o">|</span><span class="n">file</span><span class="o">|</span> <pre class="snippet">
<span class="n">file</span><span class="o">.</span><span class="n">readBytes</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> File.open("words.txt") {|file|
<span class="p">}</span> file.readBytes(5)
</pre></div> }
</pre>
<h3>File.<strong>read</strong>(path) <a href="#file.read(path)" name="file.read(path)" class="header-anchor">#</a></h3> <h3>File.<strong>read</strong>(path) <a href="#file.read(path)" name="file.read(path)" class="header-anchor">#</a></h3>
<p>Reads the entire contents of the file at <code>path</code> and returns it as a string. </p> <p>Reads the entire contents of the file at <code>path</code> and returns it as a string.</p>
<div class="codehilite"><pre><span class="vg">File</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="s">&quot;words.txt&quot;</span><span class="p">)</span> <pre class="snippet">
</pre></div> File.read("words.txt")
</pre>
<p>No encoding or decoding is done. If the file is UTF-8, then the resulting
<p>No encoding or decoding is done. If the file is UTF-8, then the resulting string will be a UTF-8 string. Otherwise, it will be a string of bytes in
string will be a UTF-8 string. Otherwise, it will be a string of bytes in whatever encoding the file uses.</p>
whatever encoding the file uses. </p>
<h3>File.<strong>realPath</strong>(path) <a href="#file.realpath(path)" name="file.realpath(path)" class="header-anchor">#</a></h3> <h3>File.<strong>realPath</strong>(path) <a href="#file.realpath(path)" name="file.realpath(path)" class="header-anchor">#</a></h3>
<p>Resolves <code>path</code>, traversing symlinks and removining any unneeded <code>./</code> and <code>../</code> <p>Resolves <code>path</code>, traversing symlinks and removining any unneeded <code>./</code> and <code>../</code>
components. Returns the canonical absolute path to the file. </p> components. Returns the canonical absolute path to the file.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">path</span> <span class="o">=</span> <span class="s">&quot;/some/./symlink/a/../b/file.txt&quot;</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">File</span><span class="o">.</span><span class="n">realPath</span><span class="p">(</span><span class="n">path</span><span class="p">))</span> <span class="output">/real/path/a/file.txt</span> var path = "/some/./symlink/a/../b/file.txt"
</pre></div> System.print(File.realPath(path)) //> /real/path/a/file.txt
</pre>
<h3>File.<strong>size</strong>(path) <a href="#file.size(path)" name="file.size(path)" class="header-anchor">#</a></h3> <h3>File.<strong>size</strong>(path) <a href="#file.size(path)" name="file.size(path)" class="header-anchor">#</a></h3>
<p>Returns the size in bytes of the contents of the file at <code>path</code>. </p> <p>Returns the size in bytes of the contents of the file at <code>path</code>.</p>
<h2>Constructors <a href="#constructors" name="constructors" class="header-anchor">#</a></h2> <h2>Constructors <a href="#constructors" name="constructors" class="header-anchor">#</a></h2>
<h3>File.<strong>create</strong>(path) <a href="#file.create(path)" name="file.create(path)" class="header-anchor">#</a></h3> <h3>File.<strong>create</strong>(path) <a href="#file.create(path)" name="file.create(path)" class="header-anchor">#</a></h3>
<p>Opens the file at <code>path</code> for writing. If there is already a file at that path, <p>Opens the file at <code>path</code> for writing. If there is already a file at that path,
it is truncated. </p> it is truncated.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">file</span> <span class="o">=</span> <span class="vg">File</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="s">&quot;colors.txt&quot;</span><span class="p">)</span> <pre class="snippet">
<span class="n">file</span><span class="o">.</span><span class="n">writeBytes</span><span class="p">(</span><span class="s">&quot;chartreuse lime teal&quot;</span><span class="p">)</span> var file = File.create("colors.txt")
<span class="n">file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span> file.writeBytes("chartreuse lime teal")
</pre></div> file.close()
</pre>
<h3>File.<strong>open</strong>(path) <a href="#file.open(path)" name="file.open(path)" class="header-anchor">#</a></h3> <h3>File.<strong>open</strong>(path) <a href="#file.open(path)" name="file.open(path)" class="header-anchor">#</a></h3>
<p>Opens the file at <code>path</code> for reading. You are responsible for closing it when <p>Opens the file at <code>path</code> for reading. You are responsible for closing it when
done with it. </p> done with it.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>descriptor</strong> <a href="#descriptor" name="descriptor" class="header-anchor">#</a></h3> <h3><strong>descriptor</strong> <a href="#descriptor" name="descriptor" class="header-anchor">#</a></h3>
<p>The numeric file descriptor used to access the file. </p> <p>The numeric file descriptor used to access the file.</p>
<h3><strong>isOpen</strong> <a href="#isopen" name="isopen" class="header-anchor">#</a></h3> <h3><strong>isOpen</strong> <a href="#isopen" name="isopen" class="header-anchor">#</a></h3>
<p>Whether the file is still open or has been closed. </p> <p>Whether the file is still open or has been closed.</p>
<h3><strong>size</strong> <a href="#size" name="size" class="header-anchor">#</a></h3> <h3><strong>size</strong> <a href="#size" name="size" class="header-anchor">#</a></h3>
<p>The size of the contents of the file in bytes. </p> <p>The size of the contents of the file in bytes.</p>
<h3><strong>close</strong>() <a href="#close()" name="close()" class="header-anchor">#</a></h3> <h3><strong>close</strong>() <a href="#close()" name="close()" class="header-anchor">#</a></h3>
<p>Closes the file. After calling this, you can&rsquo;t read or write from it. </p> <p>Closes the file. After calling this, you can&rsquo;t read or write from it.</p>
<h3><strong>readBytes</strong>(count) <a href="#readbytes(count)" name="readbytes(count)" class="header-anchor">#</a></h3> <h3><strong>readBytes</strong>(count) <a href="#readbytes(count)" name="readbytes(count)" class="header-anchor">#</a></h3>
<p>Reads up to <code>count</code> bytes starting from the beginning of the file. </p> <p>Reads up to <code>count</code> bytes starting from the beginning of the file.</p>
<div class="codehilite"><pre><span class="c1">// Assume this file contains &quot;I am a file!&quot;.</span> <pre class="snippet">
<span class="vg">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&quot;example.txt&quot;</span><span class="p">)</span> <span class="p">{</span><span class="o">|</span><span class="n">file</span><span class="o">|</span> // Assume this file contains "I am a file!".
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">readBytes</span><span class="p">(</span><span class="mi">6</span><span class="p">))</span> <span class="output">I am a</span> File.open("example.txt") {|file|
<span class="p">}</span> System.print(file.readBytes(6)) //> I am a
</pre></div> }
</pre>
<h3><strong>readBytes</strong>(count, offset) <a href="#readbytes(count,-offset)" name="readbytes(count,-offset)" class="header-anchor">#</a></h3> <h3><strong>readBytes</strong>(count, offset) <a href="#readbytes(count,-offset)" name="readbytes(count,-offset)" class="header-anchor">#</a></h3>
<p>Reads up to <code>count</code> bytes starting at <code>offset</code> bytes from the beginning of <p>Reads up to <code>count</code> bytes starting at <code>offset</code> bytes from the beginning of
the file. </p> the file.</p>
<div class="codehilite"><pre><span class="c1">// Assume this file contains &quot;I am a file!&quot;.</span> <pre class="snippet">
<span class="vg">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&quot;example.txt&quot;</span><span class="p">)</span> <span class="p">{</span><span class="o">|</span><span class="n">file</span><span class="o">|</span> // Assume this file contains "I am a file!".
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">file</span><span class="o">.</span><span class="n">readBytes</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span> <span class="output">am a f</span> File.open("example.txt") {|file|
<span class="p">}</span> System.print(file.readBytes(6, 2)) //> am a f
</pre></div> }
</pre>
<h3><strong>writeBytes</strong>(bytes) <a href="#writebytes(bytes)" name="writebytes(bytes)" class="header-anchor">#</a></h3> <h3><strong>writeBytes</strong>(bytes) <a href="#writebytes(bytes)" name="writebytes(bytes)" class="header-anchor">#</a></h3>
<p>Writes the raw bytes of the string <code>bytes</code> to the end of the file. </p> <p>Writes the raw bytes of the string <code>bytes</code> to the end of the file.</p>
<h3><strong>writeBytes</strong>(bytes, offset) <a href="#writebytes(bytes,-offset)" name="writebytes(bytes,-offset)" class="header-anchor">#</a></h3> <h3><strong>writeBytes</strong>(bytes, offset) <a href="#writebytes(bytes,-offset)" name="writebytes(bytes,-offset)" class="header-anchor">#</a></h3>
<p>Writes the raw bytes of the string <code>bytes</code> to the to the file, starting at <p>Writes the raw bytes of the string <code>bytes</code> to the to the file, starting at
<code>offset</code>. Any overlapping bytes already in the file at the offset are <code>offset</code>. Any overlapping bytes already in the file at the offset are
overwritten. </p> overwritten.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Module "io" &ndash; Wren</title> <title>Module "io" &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">io</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">io module</a></li>
</ul> </ul>
<section> <section>
<h2>io classes</h2> <h2>io classes</h2>
@ -40,8 +44,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">io</a></td> <td><a href="./">io module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>io classes</h2></td> <td colspan="2"><h2>io classes</h2></td>
@ -66,13 +70,13 @@
</nav> </nav>
<main> <main>
<h1>Module "io"</h1> <h1>Module "io"</h1>
<p>Provides access to operating system streams and the file system. </p> <p>Provides access to operating system streams and the file system.</p>
<ul> <ul>
<li><a href="directory.html">Directory</a> </li> <li><a href="directory.html">Directory</a></li>
<li><a href="file.html">File</a> </li> <li><a href="file.html">File</a></li>
<li><a href="stat.html">Stat</a> </li> <li><a href="stat.html">Stat</a></li>
<li><a href="stdin.html">Stdin</a> </li> <li><a href="stdin.html">Stdin</a></li>
<li><a href="stdout.html">Stdout</a> </li> <li><a href="stdout.html">Stdout</a></li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Stat Class &ndash; Wren</title> <title>Stat Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">io</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">io module</a></li>
</ul> </ul>
<section> <section>
<h2>io classes</h2> <h2>io classes</h2>
@ -40,8 +44,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">io</a></td> <td><a href="./">io module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>io classes</h2></td> <td colspan="2"><h2>io classes</h2></td>
@ -66,37 +70,37 @@
</nav> </nav>
<main> <main>
<h1>Stat Class</h1> <h1>Stat Class</h1>
<p>A data structure describing the low-level details of a file system entry. </p> <p>A data structure describing the low-level details of a file system entry.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>Stat.<strong>path</strong>(path) <a href="#stat.path(path)" name="stat.path(path)" class="header-anchor">#</a></h3> <h3>Stat.<strong>path</strong>(path) <a href="#stat.path(path)" name="stat.path(path)" class="header-anchor">#</a></h3>
<p>&ldquo;Stats&rdquo; the file or directory at <code>path</code>. </p> <p>&ldquo;Stats&rdquo; the file or directory at <code>path</code>.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>blockCount</strong> <a href="#blockcount" name="blockcount" class="header-anchor">#</a></h3> <h3><strong>blockCount</strong> <a href="#blockcount" name="blockcount" class="header-anchor">#</a></h3>
<p>The number of system blocks allocated on disk for the file. </p> <p>The number of system blocks allocated on disk for the file.</p>
<h3><strong>blockSize</strong> <a href="#blocksize" name="blocksize" class="header-anchor">#</a></h3> <h3><strong>blockSize</strong> <a href="#blocksize" name="blocksize" class="header-anchor">#</a></h3>
<p>The preferred block size in bytes for interacting with the file. It may vary <p>The preferred block size in bytes for interacting with the file. It may vary
from file to file. </p> from file to file.</p>
<h3><strong>device</strong> <a href="#device" name="device" class="header-anchor">#</a></h3> <h3><strong>device</strong> <a href="#device" name="device" class="header-anchor">#</a></h3>
<p>The ID of the device containing the entry. </p> <p>The ID of the device containing the entry.</p>
<h3><strong>group</strong> <a href="#group" name="group" class="header-anchor">#</a></h3> <h3><strong>group</strong> <a href="#group" name="group" class="header-anchor">#</a></h3>
<p>Numeric group ID of the file&rsquo;s owner. </p> <p>Numeric group ID of the file&rsquo;s owner.</p>
<h3><strong>inode</strong> <a href="#inode" name="inode" class="header-anchor">#</a></h3> <h3><strong>inode</strong> <a href="#inode" name="inode" class="header-anchor">#</a></h3>
<p>The <a href="https://en.wikipedia.org/wiki/Inode">inode</a> number of the entry. </p> <p>The <a href="https://en.wikipedia.org/wiki/Inode">inode</a> number of the entry.</p>
<h3><strong>isDirectory</strong> <a href="#isdirectory" name="isdirectory" class="header-anchor">#</a></h3> <h3><strong>isDirectory</strong> <a href="#isdirectory" name="isdirectory" class="header-anchor">#</a></h3>
<p>Whether the file system entity is a directory. </p> <p>Whether the file system entity is a directory.</p>
<h3><strong>isFile</strong> <a href="#isfile" name="isfile" class="header-anchor">#</a></h3> <h3><strong>isFile</strong> <a href="#isfile" name="isfile" class="header-anchor">#</a></h3>
<p>Whether the file system entity is a regular file, as opposed to a directory or <p>Whether the file system entity is a regular file, as opposed to a directory or
other special entity. </p> other special entity.</p>
<h3><strong>linkCount</strong> <a href="#linkcount" name="linkcount" class="header-anchor">#</a></h3> <h3><strong>linkCount</strong> <a href="#linkcount" name="linkcount" class="header-anchor">#</a></h3>
<p>The number of hard links to the entry. </p> <p>The number of hard links to the entry.</p>
<h3><strong>mode</strong> <a href="#mode" name="mode" class="header-anchor">#</a></h3> <h3><strong>mode</strong> <a href="#mode" name="mode" class="header-anchor">#</a></h3>
<p>A bit field describing the entry&rsquo;s type and protection flags. </p> <p>A bit field describing the entry&rsquo;s type and protection flags.</p>
<h3><strong>size</strong> <a href="#size" name="size" class="header-anchor">#</a></h3> <h3><strong>size</strong> <a href="#size" name="size" class="header-anchor">#</a></h3>
<p>The size of the entry in bytes. </p> <p>The size of the entry in bytes.</p>
<h3><strong>specialDevice</strong> <a href="#specialdevice" name="specialdevice" class="header-anchor">#</a></h3> <h3><strong>specialDevice</strong> <a href="#specialdevice" name="specialdevice" class="header-anchor">#</a></h3>
<p>The device ID for the entry, if it&rsquo;s a special file. </p> <p>The device ID for the entry, if it&rsquo;s a special file.</p>
<h3><strong>user</strong> <a href="#user" name="user" class="header-anchor">#</a></h3> <h3><strong>user</strong> <a href="#user" name="user" class="header-anchor">#</a></h3>
<p>Numeric user ID of the file&rsquo;s owner. </p> <p>Numeric user ID of the file&rsquo;s owner.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Stdin Class &ndash; Wren</title> <title>Stdin Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">io</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">io module</a></li>
</ul> </ul>
<section> <section>
<h2>io classes</h2> <h2>io classes</h2>
@ -40,8 +44,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">io</a></td> <td><a href="./">io module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>io classes</h2></td> <td colspan="2"><h2>io classes</h2></td>
@ -66,33 +70,33 @@
</nav> </nav>
<main> <main>
<h1>Stdin Class</h1> <h1>Stdin Class</h1>
<p>The standard input stream. </p> <p>The standard input stream.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3><strong>isRaw</strong> <a href="#israw" name="israw" class="header-anchor">#</a></h3> <h3><strong>isRaw</strong> <a href="#israw" name="israw" class="header-anchor">#</a></h3>
<p>Returns <code>true</code> if stdin is in raw mode. When in raw mode, input is not echoed <p>Returns <code>true</code> if stdin is in raw mode. When in raw mode, input is not echoed
or buffered, and all characters, even non-printing and control characters go or buffered, and all characters, even non-printing and control characters go
into stdin. </p> into stdin.</p>
<p>Defaults to <code>false</code>. </p> <p>Defaults to <code>false</code>.</p>
<h3><strong>isRaw</strong>=(value) <a href="#israw=(value)" name="israw=(value)" class="header-anchor">#</a></h3> <h3><strong>isRaw</strong>=(value) <a href="#israw=(value)" name="israw=(value)" class="header-anchor">#</a></h3>
<p>Sets raw mode on or off. </p> <p>Sets raw mode on or off.</p>
<h3><strong>isTerminal</strong> <a href="#isterminal" name="isterminal" class="header-anchor">#</a></h3> <h3><strong>isTerminal</strong> <a href="#isterminal" name="isterminal" class="header-anchor">#</a></h3>
<p>Returns <code>true</code> if Stdin is connected to a &ldquo;TTY&rdquo;. This is true when the user is <p>Returns <code>true</code> if Stdin is connected to a &ldquo;TTY&rdquo;. This is true when the user is
running Wren in an interactive terminal, and false if it its input is coming running Wren in an interactive terminal, and false if it its input is coming
from a pipe. </p> from a pipe.</p>
<h3><strong>readByte</strong>() <a href="#readbyte()" name="readbyte()" class="header-anchor">#</a></h3> <h3><strong>readByte</strong>() <a href="#readbyte()" name="readbyte()" class="header-anchor">#</a></h3>
<p>Reads one byte of input from stdin. Blocks the current fiber until a byte has <p>Reads one byte of input from stdin. Blocks the current fiber until a byte has
been received. </p> been received.</p>
<p>Returns the byte value as a number or <code>null</code> if stdin is closed. </p> <p>Returns the byte value as a number or <code>null</code> if stdin is closed.</p>
<p>Note that output is not automatically flushed when calling this. If you want to <p>Note that output is not automatically flushed when calling this. If you want to
display a prompt before reading input, you&rsquo;ll want to call <code>Stdout.flush()</code> display a prompt before reading input, you&rsquo;ll want to call <code>Stdout.flush()</code>
after printing the prompt. </p> after printing the prompt.</p>
<h3><strong>readLine</strong>() <a href="#readline()" name="readline()" class="header-anchor">#</a></h3> <h3><strong>readLine</strong>() <a href="#readline()" name="readline()" class="header-anchor">#</a></h3>
<p>Reads one line of input from stdin. Blocks the current fiber until a full line <p>Reads one line of input from stdin. Blocks the current fiber until a full line
of input has been received. </p> of input has been received.</p>
<p>Returns the string of input or <code>null</code> if stdin is closed. </p> <p>Returns the string of input or <code>null</code> if stdin is closed.</p>
<p>Note that output is not automatically flushed when calling this. If you want to <p>Note that output is not automatically flushed when calling this. If you want to
display a prompt before reading input, you&rsquo;ll want to call <code>Stdout.flush()</code> display a prompt before reading input, you&rsquo;ll want to call <code>Stdout.flush()</code>
after printing the prompt. </p> after printing the prompt.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Stdout Class &ndash; Wren</title> <title>Stdout Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">io</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">io module</a></li>
</ul> </ul>
<section> <section>
<h2>io classes</h2> <h2>io classes</h2>
@ -40,8 +44,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">io</a></td> <td><a href="./">io module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>io classes</h2></td> <td colspan="2"><h2>io classes</h2></td>
@ -66,12 +70,12 @@
</nav> </nav>
<main> <main>
<h1>Stdout Class</h1> <h1>Stdout Class</h1>
<p>The standard output stream. </p> <p>The standard output stream.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3><strong>flush()</strong> <a href="#flush()" name="flush()" class="header-anchor">#</a></h3> <h3><strong>flush()</strong> <a href="#flush()" name="flush()" class="header-anchor">#</a></h3>
<p>Flushes all buffered data to the stream. Ensures any data written to stdout <p>Flushes all buffered data to the stream. Ensures any data written to stdout
that is in the buffer gets written to the file or terminal that stdout is that is in the buffer gets written to the file or terminal that stdout is
connected to. </p> connected to.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Module "os" &ndash; Wren</title> <title>Module "os" &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">os</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">os module</a></li>
</ul> </ul>
<section> <section>
<h2>os classes</h2> <h2>os classes</h2>
@ -36,8 +40,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">os</a></td> <td><a href="./">os module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>os classes</h2></td> <td colspan="2"><h2>os classes</h2></td>
@ -58,11 +62,11 @@
</nav> </nav>
<main> <main>
<h1>Module "os"</h1> <h1>Module "os"</h1>
<p>The os module exposes classes for accessing capabilities provided by the <p>The os module exposes classes for accessing capabilities provided by the
underlying operating system. </p> underlying operating system.</p>
<ul> <ul>
<li><a href="platform.html">Platform</a> </li> <li><a href="platform.html">Platform</a></li>
<li><a href="process.html">Process</a> </li> <li><a href="process.html">Process</a></li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Platform Class &ndash; Wren</title> <title>Platform Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">os</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">os module</a></li>
</ul> </ul>
<section> <section>
<h2>os classes</h2> <h2>os classes</h2>
@ -36,8 +40,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">os</a></td> <td><a href="./">os module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>os classes</h2></td> <td colspan="2"><h2>os classes</h2></td>
@ -58,27 +62,27 @@
</nav> </nav>
<main> <main>
<h1>Platform Class</h1> <h1>Platform Class</h1>
<p>The Platform class exposes basic information about the operating system Wren is <p>The Platform class exposes basic information about the operating system Wren is
running on top of. </p> running on top of.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3><strong>name</strong> <a href="#name" name="name" class="header-anchor">#</a></h3> <h3><strong>name</strong> <a href="#name" name="name" class="header-anchor">#</a></h3>
<p>The name of the platform. This roughly describes the operating system, and is <p>The name of the platform. This roughly describes the operating system, and is
usually one of: </p> usually one of:</p>
<ul> <ul>
<li>&ldquo;iOS&rdquo; </li> <li>&ldquo;iOS&rdquo;</li>
<li>&ldquo;Linux&rdquo; </li> <li>&ldquo;Linux&rdquo;</li>
<li>&ldquo;OS X&rdquo; </li> <li>&ldquo;OS X&rdquo;</li>
<li>&ldquo;POSIX&rdquo; </li> <li>&ldquo;POSIX&rdquo;</li>
<li>&ldquo;Unix&rdquo; </li> <li>&ldquo;Unix&rdquo;</li>
<li>&ldquo;Windows&rdquo; </li> <li>&ldquo;Windows&rdquo;</li>
</ul> </ul>
<p>If Wren was compiled for an unknown operating system, returns &ldquo;Unknown&rdquo;. </p> <p>If Wren was compiled for an unknown operating system, returns &ldquo;Unknown&rdquo;.</p>
<h3><strong>isPosix</strong> <a href="#isposix" name="isposix" class="header-anchor">#</a></h3> <h3><strong>isPosix</strong> <a href="#isposix" name="isposix" class="header-anchor">#</a></h3>
<p>Returns <code>true</code> if the host operating system is known to support the POSIX <p>Returns <code>true</code> if the host operating system is known to support the POSIX
standard. This is true for Linux and other Unices, as well as the various Apple standard. This is true for Linux and other Unices, as well as the various Apple
operating systems. </p> operating systems.</p>
<h3><strong>isWindows</strong> <a href="#iswindows" name="iswindows" class="header-anchor">#</a></h3> <h3><strong>isWindows</strong> <a href="#iswindows" name="iswindows" class="header-anchor">#</a></h3>
<p>Returns <code>true</code> if the host operating system is some flavor of Windows. </p> <p>Returns <code>true</code> if the host operating system is some flavor of Windows.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Process Class &ndash; Wren</title> <title>Process Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">os</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">os module</a></li>
</ul> </ul>
<section> <section>
<h2>os classes</h2> <h2>os classes</h2>
@ -36,8 +40,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">os</a></td> <td><a href="./">os module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>os classes</h2></td> <td colspan="2"><h2>os classes</h2></td>
@ -58,35 +62,32 @@
</nav> </nav>
<main> <main>
<h1>Process Class</h1> <h1>Process Class</h1>
<p>The Process class lets you work with operating system processes, including the <p>The Process class lets you work with operating system processes, including the
currently running one. </p> currently running one.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3><strong>allArguments</strong> <a href="#allarguments" name="allarguments" class="header-anchor">#</a></h3> <h3><strong>allArguments</strong> <a href="#allarguments" name="allarguments" class="header-anchor">#</a></h3>
<p>The list of command-line arguments that were passed when the Wren process was <p>The list of command-line arguments that were passed when the Wren process was
spawned. This includes the Wren executable itself, the path to the file being spawned. This includes the Wren executable itself, the path to the file being
run (if any), and any other options passed to Wren itself. </p> run (if any), and any other options passed to Wren itself.</p>
<p>If you run: </p> <p>If you run:</p>
<div class="codehilite"><pre><span class="nv">$ </span>wren file.wren arg <pre><code>$ wren file.wren arg
</pre></div> </code></pre>
<p>This returns:</p>
<pre class="snippet">
<p>This returns: </p> System.print(Process.allArguments) //> ["wren", "file.wren", "arg"]
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Process</span><span class="o">.</span><span class="n">allArguments</span><span class="p">)</span> <span class="output">[&quot;wren&quot;, &quot;file.wren&quot;, &quot;arg&quot;]</span> </pre>
</pre></div>
<h3><strong>arguments</strong> <a href="#arguments" name="arguments" class="header-anchor">#</a></h3> <h3><strong>arguments</strong> <a href="#arguments" name="arguments" class="header-anchor">#</a></h3>
<p>The list of command-line arguments that were passed to your program when the <p>The list of command-line arguments that were passed to your program when the
Wren process was spawned. This does not include arguments handled by Wren Wren process was spawned. This does not include arguments handled by Wren
itself. </p> itself.</p>
<p>If you run: </p> <p>If you run:</p>
<div class="codehilite"><pre><span class="nv">$ </span>wren file.wren arg <pre><code>$ wren file.wren arg
</pre></div> </code></pre>
<p>This returns:</p>
<pre class="snippet">
<p>This returns: </p> System.print(Process.arguments) //> ["arg"]
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Process</span><span class="o">.</span><span class="n">arguments</span><span class="p">)</span> <span class="output">[&quot;arg&quot;]</span> </pre>
</pre></div>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Module "scheduler" &ndash; Wren</title> <title>Module "scheduler" &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">scheduler</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">scheduler module</a></li>
</ul> </ul>
<section> <section>
<h2>scheduler classes</h2> <h2>scheduler classes</h2>
@ -35,8 +39,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">scheduler</a></td> <td><a href="./">scheduler module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>scheduler classes</h2></td> <td colspan="2"><h2>scheduler classes</h2></td>
@ -56,9 +60,9 @@
</nav> </nav>
<main> <main>
<h1>Module "scheduler"</h1> <h1>Module "scheduler"</h1>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<ul> <ul>
<li><a href="scheduler.html">Scheduler</a> </li> <li><a href="scheduler.html">Scheduler</a></li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Scheduler Class &ndash; Wren</title> <title>Scheduler Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">scheduler</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">scheduler module</a></li>
</ul> </ul>
<section> <section>
<h2>scheduler classes</h2> <h2>scheduler classes</h2>
@ -35,8 +39,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">scheduler</a></td> <td><a href="./">scheduler module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>scheduler classes</h2></td> <td colspan="2"><h2>scheduler classes</h2></td>
@ -56,9 +60,9 @@
</nav> </nav>
<main> <main>
<h1>Scheduler Class</h1> <h1>Scheduler Class</h1>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Module "timer" &ndash; Wren</title> <title>Module "timer" &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">timer</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">timer module</a></li>
</ul> </ul>
<section> <section>
<h2>timer classes</h2> <h2>timer classes</h2>
@ -35,8 +39,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">timer</a></td> <td><a href="./">timer module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>timer classes</h2></td> <td colspan="2"><h2>timer classes</h2></td>
@ -56,9 +60,9 @@
</nav> </nav>
<main> <main>
<h1>Module "timer"</h1> <h1>Module "timer"</h1>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<ul> <ul>
<li><a href="timer.html">Timer</a> </li> <li><a href="timer.html">Timer</a></li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,7 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Timer Class &ndash; Wren</title> <title>Timer Class &ndash; Wren</title>
<link rel="stylesheet" type="text/css" href="../../style.css" /> <script type="application/javascript" src="../../../prism.js" data-manual></script>
<script type="application/javascript" src="../../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. --> the viewport. -->
@ -13,17 +16,18 @@
<header> <header>
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="../../">wren</a></h1> <h1><a href="../../../">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../../"><img src="../../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../../">Back to Wren CLI</a></li>
<li><a href="./">timer</a></li> <li><a href="../">Back to CLI Modules</a></li>
<li><a href="./">timer module</a></li>
</ul> </ul>
<section> <section>
<h2>timer classes</h2> <h2>timer classes</h2>
@ -35,8 +39,8 @@
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><a href="../">Modules</a></td> <td><a href="../">Back to CLI Modules</a></td>
<td><a href="./">timer</a></td> <td><a href="./">timer module</a></td>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>timer classes</h2></td> <td colspan="2"><h2>timer classes</h2></td>
@ -56,9 +60,9 @@
</nav> </nav>
<main> <main>
<h1>Timer Class</h1> <h1>Timer Class</h1>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
</main> </main>
</div> </div>
<footer> <footer>

131
cli/usage.html Normal file
View File

@ -0,0 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Wren CLI Usage &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top">
<header>
<div class="page">
<div class="main-column">
<h1><a href="../">wren</a></h1>
<h2>a classy little scripting language</h2>
</div>
</div>
</header>
<div class="page">
<nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section>
<h2>Wren CLI</h2>
<ul>
<li><a href="./">About</a></li>
<li><a target="_blank" href="https://github.com/wren-lang/wren-cli/releases">Downloads</a></li>
<li><a href="usage.html">Usage</a></li>
</ul>
</section>
<section>
<h2>API docs</h2>
<ul>
<li><a href="modules">CLI Modules</a></li>
</ul>
</section>
</nav>
<nav class="small">
<table>
<tr>
<div><a href="../">Back to Wren</a></div>
</tr>
<tr>
<td><h2>CLI</h2></td>
<td><h2>API</h2></td>
</tr>
<tr>
<td>
<ul>
<li><a href="./">About</a></li>
<li><a target="_blank" href="https://github.com/wren-lang/wren-cli/releases">Downloads</a></li>
<li><a href="usage.html">Usage</a></li>
</ul>
</td>
<td>
<ul>
<li><a href="modules">CLI Modules</a></li>
</ul>
</td>
</tr>
</table>
</nav>
<main>
<h2>Wren CLI Usage</h2>
<hr />
<p>You can <a href="https://github.com/wren-lang/wren-cli/releases">download a build for your OS from the releases page</a>.</p>
<h3>Interactive mode <a href="#interactive-mode" name="interactive-mode" class="header-anchor">#</a></h3>
<p>If you just run <code>wren</code> without any arguments, it starts the interpreter in
interactive mode, where you can type in a line of code, and it immediately executes
it. You can exit the interpreter using good old Ctrl-C or Ctrl-D.</p>
<p>Here&rsquo;s something to try:</p>
<pre class="snippet">
System.print("Hello, world!")
</pre>
<p>Or a little more exciting:</p>
<pre class="snippet">
for (i in 1..10) System.print("Counting up %(i)")
</pre>
<h3>Running scripts <a href="#running-scripts" name="running-scripts" class="header-anchor">#</a></h3>
<p>The standalone interpreter can also load scripts from files and run them. Just
pass the name of the script to <code>wren</code>. Create a file named &ldquo;my_script.wren&rdquo; in
your favorite text editor and paste this into it:</p>
<pre class="snippet">
for (yPixel in 0...24) {
var y = yPixel / 12 - 1
for (xPixel in 0...80) {
var x = xPixel / 30 - 2
var x0 = x
var y0 = y
var iter = 0
while (iter < 11 && x0 * x0 + y0 * y0 <= 4) {
var x1 = (x0 * x0) - (y0 * y0) + x
var y1 = 2 * x0 * y0 + y
x0 = x1
y0 = y1
iter = iter + 1
}
System.write(" .-:;+=xX$& "[iter])
}
System.print("")
}
</pre>
<p>Now run:</p>
<pre><code>$ ./wren my_script.wren
</code></pre>
</main>
</div>
<footer>
<div class="page">
<div class="main-column">
<p>Wren lives
<a href="https://github.com/wren-lang/wren">on GitHub</a>
&mdash; Made with &#x2764; by
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
<a href="https://github.com/wren-lang/wren/blob/master/AUTHORS">friends</a>.
</p>
<div class="main-column">
</div>
</footer>
</body>
</html>

51
codejar-linenumbers.js Normal file
View File

@ -0,0 +1,51 @@
function withLineNumbers(highlight, options = {}) {
const opts = Object.assign({ class: "codejar-linenumbers", wrapClass: "codejar-wrap", width: "35px" }, options);
let lineNumbers;
return function (editor) {
highlight(editor);
if (!lineNumbers) {
lineNumbers = init(editor, opts);
}
const code = editor.textContent || "";
const linesCount = code.replace(/\n+$/, "\n").split("\n").length + 1;
let text = "";
for (let i = 1; i < linesCount; i++) {
text += `${i}\n`;
}
lineNumbers.innerText = text;
};
}
function init(editor, opts) {
const css = getComputedStyle(editor);
const wrap = document.createElement("div");
wrap.className = opts.wrapClass;
wrap.style.position = "relative";
const lineNumbers = document.createElement("div");
lineNumbers.className = opts.class;
wrap.appendChild(lineNumbers);
// Add own styles
lineNumbers.style.position = "absolute";
lineNumbers.style.top = "0px";
lineNumbers.style.left = "0px";
lineNumbers.style.bottom = "0px";
lineNumbers.style.width = opts.width;
lineNumbers.style.overflow = "hidden";
lineNumbers.style.backgroundColor = "rgba(255, 255, 255, 0.05)";
lineNumbers.style.color = "#fff";
lineNumbers.style.setProperty("mix-blend-mode", "difference");
// Copy editor styles
lineNumbers.style.fontFamily = css.fontFamily;
lineNumbers.style.fontSize = css.fontSize;
lineNumbers.style.lineHeight = css.lineHeight;
lineNumbers.style.paddingTop = css.paddingTop;
lineNumbers.style.paddingLeft = css.paddingLeft;
lineNumbers.style.borderTopLeftRadius = css.borderTopLeftRadius;
lineNumbers.style.borderBottomLeftRadius = css.borderBottomLeftRadius;
// Tweak editor styles
editor.style.paddingLeft = `calc(${opts.width} + ${lineNumbers.style.paddingLeft})`;
editor.style.whiteSpace = "pre";
// Swap editor with a wrap
editor.parentNode.insertBefore(wrap, editor);
wrap.appendChild(editor);
return lineNumbers;
}

401
codejar.js Normal file
View File

@ -0,0 +1,401 @@
function CodeJar(editor, highlight, opt = {}) {
const options = Object.assign({ tab: "\t" }, opt);
let listeners = [];
let history = [];
let at = -1;
let focus = false;
let callback;
let prev; // code content prior keydown event
let isFirefox = navigator.userAgent.toLowerCase().indexOf("firefox") > -1;
editor.setAttribute("contentEditable", isFirefox ? "true" : "plaintext-only");
editor.setAttribute("spellcheck", "false");
editor.style.outline = "none";
editor.style.overflowWrap = "break-word";
editor.style.overflowY = "auto";
editor.style.resize = "vertical";
editor.style.whiteSpace = "pre-wrap";
highlight(editor);
const debounceHighlight = debounce(() => {
const pos = save();
highlight(editor);
restore(pos);
}, 30);
let recording = false;
const shouldRecord = (event) => {
return !isUndo(event) && !isRedo(event)
&& event.key !== "Meta"
&& event.key !== "Control"
&& event.key !== "Alt"
&& !event.key.startsWith("Arrow");
};
const debounceRecordHistory = debounce((event) => {
if (shouldRecord(event)) {
recordHistory();
recording = false;
}
}, 300);
const on = (type, fn) => {
listeners.push([type, fn]);
editor.addEventListener(type, fn);
};
on("keydown", event => {
if (event.defaultPrevented)
return;
prev = toString();
handleNewLine(event);
handleTabCharacters(event);
handleJumpToBeginningOfLine(event);
handleSelfClosingCharacters(event);
handleUndoRedo(event);
if (shouldRecord(event) && !recording) {
recordHistory();
recording = true;
}
});
on("keyup", event => {
if (event.defaultPrevented)
return;
if (event.isComposing)
return;
if (prev !== toString())
debounceHighlight();
debounceRecordHistory(event);
if (callback)
callback(toString());
});
on("focus", _event => {
focus = true;
});
on("blur", _event => {
focus = false;
});
on("paste", event => {
recordHistory();
handlePaste(event);
recordHistory();
if (callback)
callback(toString());
});
function save() {
const s = window.getSelection();
const pos = { start: 0, end: 0, dir: undefined };
visit(editor, el => {
if (el === s.anchorNode && el === s.focusNode) {
pos.start += s.anchorOffset;
pos.end += s.focusOffset;
pos.dir = s.anchorOffset <= s.focusOffset ? "->" : "<-";
return "stop";
}
if (el === s.anchorNode) {
pos.start += s.anchorOffset;
if (!pos.dir) {
pos.dir = "->";
}
else {
return "stop";
}
}
else if (el === s.focusNode) {
pos.end += s.focusOffset;
if (!pos.dir) {
pos.dir = "<-";
}
else {
return "stop";
}
}
if (el.nodeType === Node.TEXT_NODE) {
if (pos.dir != "->")
pos.start += el.nodeValue.length;
if (pos.dir != "<-")
pos.end += el.nodeValue.length;
}
});
return pos;
}
function restore(pos) {
const s = window.getSelection();
let startNode, startOffset = 0;
let endNode, endOffset = 0;
if (!pos.dir)
pos.dir = "->";
if (pos.start < 0)
pos.start = 0;
if (pos.end < 0)
pos.end = 0;
// Flip start and end if the direction reversed
if (pos.dir == "<-") {
const { start, end } = pos;
pos.start = end;
pos.end = start;
}
let current = 0;
visit(editor, el => {
if (el.nodeType !== Node.TEXT_NODE)
return;
const len = (el.nodeValue || "").length;
if (current + len >= pos.start) {
if (!startNode) {
startNode = el;
startOffset = pos.start - current;
}
if (current + len >= pos.end) {
endNode = el;
endOffset = pos.end - current;
return "stop";
}
}
current += len;
});
// If everything deleted place cursor at editor
if (!startNode)
startNode = editor;
if (!endNode)
endNode = editor;
// Flip back the selection
if (pos.dir == "<-") {
[startNode, startOffset, endNode, endOffset] = [endNode, endOffset, startNode, startOffset];
}
s.setBaseAndExtent(startNode, startOffset, endNode, endOffset);
}
function beforeCursor() {
const s = window.getSelection();
const r0 = s.getRangeAt(0);
const r = document.createRange();
r.selectNodeContents(editor);
r.setEnd(r0.startContainer, r0.startOffset);
return r.toString();
}
function afterCursor() {
const s = window.getSelection();
const r0 = s.getRangeAt(0);
const r = document.createRange();
r.selectNodeContents(editor);
r.setStart(r0.endContainer, r0.endOffset);
return r.toString();
}
function handleNewLine(event) {
if (event.key === "Enter") {
const before = beforeCursor();
const after = afterCursor();
let [padding] = findPadding(before);
let newLinePadding = padding;
// If last symbol is "{" ident new line
if (before[before.length - 1] === "{") {
newLinePadding += options.tab;
}
if (isFirefox) {
preventDefault(event);
insert("\n" + newLinePadding);
}
else {
// Normal browsers
if (newLinePadding.length > 0) {
preventDefault(event);
insert("\n" + newLinePadding);
}
}
// Place adjacent "}" on next line
if (newLinePadding !== padding && after[0] === "}") {
const pos = save();
insert("\n" + padding);
restore(pos);
}
}
}
function handleSelfClosingCharacters(event) {
const open = `([{'"`;
const close = `)]}'"`;
const codeAfter = afterCursor();
if (close.includes(event.key) && codeAfter.substr(0, 1) === event.key) {
const pos = save();
preventDefault(event);
pos.start = ++pos.end;
restore(pos);
}
else if (open.includes(event.key)) {
const pos = save();
preventDefault(event);
const text = event.key + close[open.indexOf(event.key)];
insert(text);
pos.start = ++pos.end;
restore(pos);
}
}
function handleTabCharacters(event) {
if (event.key === "Tab") {
preventDefault(event);
if (event.shiftKey) {
const before = beforeCursor();
let [padding, start,] = findPadding(before);
if (padding.length > 0) {
const pos = save();
// Remove full length tab or just remaining padding
const len = Math.min(options.tab.length, padding.length);
restore({ start, end: start + len });
document.execCommand("delete");
pos.start -= len;
pos.end -= len;
restore(pos);
}
}
else {
insert(options.tab);
}
}
}
function handleJumpToBeginningOfLine(event) {
if (event.key === "ArrowLeft" && event.metaKey) {
preventDefault(event);
const before = beforeCursor();
let [padding, start, end] = findPadding(before);
if (before.endsWith(padding)) {
if (event.shiftKey) {
const pos = save();
restore({ start, end: pos.end }); // Select from line start.
}
else {
restore({ start, end: start }); // Jump to line start.
}
}
else {
if (event.shiftKey) {
const pos = save();
restore({ start: end, end: pos.end }); // Select from beginning of text.
}
else {
restore({ start: end, end }); // Jump to beginning of text.
}
}
}
}
function handleUndoRedo(event) {
if (isUndo(event)) {
preventDefault(event);
at--;
const record = history[at];
if (record) {
editor.innerHTML = record.html;
restore(record.pos);
}
if (at < 0)
at = 0;
}
if (isRedo(event)) {
preventDefault(event);
at++;
const record = history[at];
if (record) {
editor.innerHTML = record.html;
restore(record.pos);
}
if (at >= history.length)
at--;
}
}
function recordHistory() {
if (!focus)
return;
const html = editor.innerHTML;
const pos = save();
const lastRecord = history[at];
if (lastRecord) {
if (lastRecord.html === html
&& lastRecord.pos.start === pos.start
&& lastRecord.pos.end === pos.end)
return;
}
at++;
history[at] = { html, pos };
history.splice(at + 1);
const maxHistory = 300;
if (at > maxHistory) {
at = maxHistory;
history.splice(0, 1);
}
}
function handlePaste(event) {
preventDefault(event);
const text = (event.originalEvent || event).clipboardData.getData("text/plain");
const pos = save();
insert(text);
highlight(editor);
restore({ start: pos.end + text.length, end: pos.end + text.length });
}
function visit(editor, visitor) {
const queue = [];
if (editor.firstChild)
queue.push(editor.firstChild);
let el = queue.pop();
while (el) {
if (visitor(el) === "stop")
break;
if (el.nextSibling)
queue.push(el.nextSibling);
if (el.firstChild)
queue.push(el.firstChild);
el = queue.pop();
}
}
function isCtrl(event) {
return event.metaKey || event.ctrlKey;
}
function isUndo(event) {
return isCtrl(event) && !event.shiftKey && event.code === "KeyZ";
}
function isRedo(event) {
return isCtrl(event) && event.shiftKey && event.code === "KeyZ";
}
function insert(text) {
text = text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
document.execCommand("insertHTML", false, text);
}
function debounce(cb, wait) {
let timeout = 0;
return (...args) => {
clearTimeout(timeout);
timeout = window.setTimeout(() => cb(...args), wait);
};
}
function findPadding(text) {
// Find beginning of previous line.
let i = text.length - 1;
while (i >= 0 && text[i] !== "\n")
i--;
i++;
// Find padding of the line.
let j = i;
while (j < text.length && /[ \t]/.test(text[j]))
j++;
return [text.substring(i, j) || "", i, j];
}
function toString() {
return editor.textContent || "";
}
function preventDefault(event) {
event.preventDefault();
}
return {
updateOptions(options) {
options = Object.assign(Object.assign({}, options), options);
},
updateCode(code) {
editor.textContent = code;
highlight(editor);
},
onUpdate(cb) {
callback = cb;
},
toString,
destroy() {
for (let [type, fn] of listeners) {
editor.removeEventListener(type, fn);
}
},
};
}

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Concurrency &ndash; Wren</title> <title>Concurrency &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,165 +110,165 @@
</nav> </nav>
<main> <main>
<h2>Concurrency</h2> <h2>Concurrency</h2>
<p>Lightweight concurrency is a key feature of Wren and it is expressed using <p>Lightweight concurrency is a key feature of Wren and it is expressed using
<em>fibers</em>. They control how all code is executed, and take the place of <em>fibers</em>. They control how all code is executed, and take the place of
exceptions in <a href="error-handling.html">error handling</a>. </p> exceptions in <a href="error-handling.html">error handling</a>.</p>
<p>Fibers are a bit like threads except they are <em>cooperatively</em> scheduled. That <p>Fibers are a bit like threads except they are <em>cooperatively</em> scheduled. That
means Wren doesn&rsquo;t pause one fiber and switch to another until you tell it to. means Wren doesn&rsquo;t pause one fiber and switch to another until you tell it to.
You don&rsquo;t have to worry about context switches at random times and all of the You don&rsquo;t have to worry about context switches at random times and all of the
headaches those cause. </p> headaches those cause.</p>
<p>Wren takes care of all of the fibers in the VM, so they don&rsquo;t use OS thread <p>Wren takes care of all of the fibers in the VM, so they don&rsquo;t use OS thread
resources, or require heavyweight context switches. Each just needs a bit of resources, or require heavyweight context switches. Each just needs a bit of
memory for its stack. A fiber will get garbage collected like any other object memory for its stack. A fiber will get garbage collected like any other object
when not referenced any more, so you can create them freely. </p> when not referenced any more, so you can create them freely.</p>
<p>They are lightweight enough that you can, for example, have a separate fiber for <p>They are lightweight enough that you can, for example, have a separate fiber for
each entity in a game. Wren can handle thousands of them without breaking a each entity in a game. Wren can handle thousands of them without breaking a
sweat. For example, when you run Wren in interactive mode, it creates a new sweat. For example, when you run Wren in interactive mode, it creates a new
fiber for every line of code you type in. </p> fiber for every line of code you type in.</p>
<h2>Creating fibers <a href="#creating-fibers" name="creating-fibers" class="header-anchor">#</a></h2> <h2>Creating fibers <a href="#creating-fibers" name="creating-fibers" class="header-anchor">#</a></h2>
<p>All Wren code runs within the context of a fiber. When you first start a Wren <p>All Wren code runs within the context of a fiber. When you first start a Wren
script, a main fiber is created for you automatically. You can spawn new fibers script, a main fiber is created for you automatically. You can spawn new fibers
using the Fiber class&rsquo;s constructor: </p> using the Fiber class&rsquo;s constructor:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;This runs in a separate fiber.&quot;</span><span class="p">)</span> var fiber = Fiber.new {
<span class="p">}</span> System.print("This runs in a separate fiber.")
</pre></div> }
</pre>
<p>It takes a <a href="functions.html">function</a> containing the code the fiber should execute. The
<p>It takes a <a href="functions.html">function</a> containing the code the fiber should execute. The function can take zero or one parameter, but no more than that. Creating the
function can take zero or one parameter, but no more than that. Creating the fiber does not immediately run it. It just wraps the function and sits there,
fiber does not immediately run it. It just wraps the function and sits there, waiting to be activated.</p>
waiting to be activated. </p>
<h2>Invoking fibers <a href="#invoking-fibers" name="invoking-fibers" class="header-anchor">#</a></h2> <h2>Invoking fibers <a href="#invoking-fibers" name="invoking-fibers" class="header-anchor">#</a></h2>
<p>Once you&rsquo;ve created a fiber, you run it by calling its <code>call()</code> method: </p> <p>Once you&rsquo;ve created a fiber, you run it by calling its <code>call()</code> method:</p>
<div class="codehilite"><pre><span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> <pre class="snippet">
</pre></div> fiber.call()
</pre>
<p>This suspends the current fiber and executes the called one until it reaches the
end of its body or until it passes control to yet another fiber. If it reaches
the end of its body, it is considered <em>done</em>:</p>
<pre class="snippet">
var fiber = Fiber.new {
System.print("It's alive!")
}
<p>This suspends the current fiber and executes the called one until it reaches the System.print(fiber.isDone) //> false
end of its body or until it passes control to yet another fiber. If it reaches fiber.call() //> It's alive!
the end of its body, it is considered <em>done</em>: </p> System.print(fiber.isDone) //> true
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> </pre>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;It&#39;s alive!&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">fiber</span><span class="o">.</span><span class="n">isDone</span><span class="p">)</span> <span class="output">false</span> <p>When a called fiber finishes, it automatically passes control <em>back</em> to the
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> <span class="output">It&#39;s alive!</span> fiber that called it. It&rsquo;s a runtime error to try to call a fiber that is
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">fiber</span><span class="o">.</span><span class="n">isDone</span><span class="p">)</span> <span class="output">true</span> already done.</p>
</pre></div>
<p>When a called fiber finishes, it automatically passes control <em>back</em> to the
fiber that called it. It&rsquo;s a runtime error to try to call a fiber that is
already done. </p>
<h2>Yielding <a href="#yielding" name="yielding" class="header-anchor">#</a></h2> <h2>Yielding <a href="#yielding" name="yielding" class="header-anchor">#</a></h2>
<p>The main difference between fibers and functions is that a fiber can be <p>The main difference between fibers and functions is that a fiber can be
suspended in the middle of its operation and then resumed later. Calling suspended in the middle of its operation and then resumed later. Calling
another fiber is one way to suspend a fiber, but that&rsquo;s more or less the same another fiber is one way to suspend a fiber, but that&rsquo;s more or less the same
as one function calling another. </p> as one function calling another.</p>
<p>Things get interesting when a fiber <em>yields</em>. A yielded fiber passes control <p>Things get interesting when a fiber <em>yields</em>. A yielded fiber passes control
<em>back</em> to the fiber that ran it, but <em>remembers where it is</em>. The next time the <em>back</em> to the fiber that ran it, but <em>remembers where it is</em>. The next time the
fiber is called, it picks up right where it left off and keeps going. </p> fiber is called, it picks up right where it left off and keeps going.</p>
<p>You make a fiber yield by calling the static <code>yield()</code> method on Fiber: </p> <p>You make a fiber yield by calling the static <code>yield()</code> method on Fiber:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Before yield&quot;</span><span class="p">)</span> var fiber = Fiber.new {
<span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">()</span> System.print("Before yield")
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Resumed&quot;</span><span class="p">)</span> Fiber.yield()
<span class="p">}</span> System.print("Resumed")
}
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Before call&quot;</span><span class="p">)</span> <span class="output">Before call</span> System.print("Before call") //> Before call
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> <span class="output">Before yield</span> fiber.call() //> Before yield
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Calling again&quot;</span><span class="p">)</span> <span class="output">Calling again</span> System.print("Calling again") //> Calling again
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> <span class="output">Resumed</span> fiber.call() //> Resumed
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;All done&quot;</span><span class="p">)</span> <span class="output">All done</span> System.print("All done") //> All done
</pre></div> </pre>
<p>Note that even though this program uses <em>concurrency</em>, it is still
<p>Note that even though this program uses <em>concurrency</em>, it is still <em>deterministic</em>. You can reason precisely about what it&rsquo;s doing and aren&rsquo;t at
<em>deterministic</em>. You can reason precisely about what it&rsquo;s doing and aren&rsquo;t at the mercy of a thread scheduler playing Russian roulette with your code.</p>
the mercy of a thread scheduler playing Russian roulette with your code. </p>
<h2>Passing values <a href="#passing-values" name="passing-values" class="header-anchor">#</a></h2> <h2>Passing values <a href="#passing-values" name="passing-values" class="header-anchor">#</a></h2>
<p>Calling and yielding fibers is used for passing control, but it can also pass <p>Calling and yielding fibers is used for passing control, but it can also pass
<em>data</em>. When you call a fiber, you can optionally pass a value to it. </p> <em>data</em>. When you call a fiber, you can optionally pass a value to it.</p>
<p>If you create a fiber using a function that takes a parameter, you can pass a <p>If you create a fiber using a function that takes a parameter, you can pass a
value to it through <code>call()</code>: </p> value to it through <code>call()</code>:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span><span class="o">|</span><span class="n">param</span><span class="o">|</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">param</span><span class="p">)</span> var fiber = Fiber.new {|param|
<span class="p">}</span> System.print(param)
}
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;Here you go&quot;</span><span class="p">)</span> <span class="output">Here you go</span> fiber.call("Here you go") //> Here you go
</pre></div> </pre>
<p>If the fiber has yielded and is waiting to resume, the value you pass to call
becomes the return value of the <code>yield()</code> call when it resumes:</p>
<pre class="snippet">
var fiber = Fiber.new {|param|
System.print(param)
var result = Fiber.yield()
System.print(result)
}
<p>If the fiber has yielded and is waiting to resume, the value you pass to call fiber.call("First") //> First
becomes the return value of the <code>yield()</code> call when it resumes: </p> fiber.call("Second") //> Second
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span><span class="o">|</span><span class="n">param</span><span class="o">|</span> </pre>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">param</span><span class="p">)</span>
<span class="k">var</span> <span class="n">result</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">()</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
<span class="p">}</span>
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;First&quot;</span><span class="p">)</span> <span class="output">First</span> <p>Fibers can also pass values <em>back</em> when they yield. If you pass an argument to
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;Second&quot;</span><span class="p">)</span> <span class="output">Second</span> <code>yield()</code>, that will become the return value of the <code>call()</code> that was used to
</pre></div> invoke the fiber:</p>
<pre class="snippet">
var fiber = Fiber.new {
Fiber.yield("Reply")
}
System.print(fiber.call()) //> Reply
</pre>
<p>Fibers can also pass values <em>back</em> when they yield. If you pass an argument to <p>This is sort of like how a function call may return a value, except that a fiber
<code>yield()</code>, that will become the return value of the <code>call()</code> that was used to may return a whole sequence of values, one every time it yields.</p>
invoke the fiber: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span>
<span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">(</span><span class="s">&quot;Reply&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">())</span> <span class="output">Reply</span>
</pre></div>
<p>This is sort of like how a function call may return a value, except that a fiber
may return a whole sequence of values, one every time it yields. </p>
<h2>Full coroutines <a href="#full-coroutines" name="full-coroutines" class="header-anchor">#</a></h2> <h2>Full coroutines <a href="#full-coroutines" name="full-coroutines" class="header-anchor">#</a></h2>
<p>What we&rsquo;ve seen so far is very similar to what you can do with languages like <p>What we&rsquo;ve seen so far is very similar to what you can do with languages like
Python and C# that have <em>generators</em>. Those let you define a function call that Python and C# that have <em>generators</em>. Those let you define a function call that
you can suspend and resume. When using the function, it appears like a sequence you can suspend and resume. When using the function, it appears like a sequence
you can iterate over. </p> you can iterate over.</p>
<p>Wren&rsquo;s fibers can do that, but they can do much more. Like Lua, they are full <p>Wren&rsquo;s fibers can do that, but they can do much more. Like Lua, they are full
<em>coroutines</em>&mdash;they can suspend from anywhere in the callstack. The function <em>coroutines</em>&mdash;they can suspend from anywhere in the callstack. The function
you use to create a fiber can call a method that calls another method that calls you use to create a fiber can call a method that calls another method that calls
some third method which finally calls yield. When that happens, <em>all</em> of those some third method which finally calls yield. When that happens, <em>all</em> of those
method calls &mdash; the entire callstack &mdash; gets suspended. For example: </p> method calls &mdash; the entire callstack &mdash; gets suspended. For example:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">)</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span><span class="o">|</span><span class="err">i</span><span class="o">|</span> var fiber = Fiber.new {
<span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">(</span><span class="err">i</span><span class="p">)</span> (1..10).each {|i|
<span class="p">}</span> Fiber.yield(i)
<span class="p">}</span> }
</pre></div> }
</pre>
<p>Here, we&rsquo;re calling <code>yield()</code> from within a <a href="functions.html">function</a> being
<p>Here, we&rsquo;re calling <code>yield()</code> from within a <a href="functions.html">function</a> being passed to the <code>each()</code> method. This works fine in Wren because that inner
passed to the <code>each()</code> method. This works fine in Wren because that inner <code>yield()</code> call will suspend the call to <code>each()</code> and the function passed to it
<code>yield()</code> call will suspend the call to <code>each()</code> and the function passed to it as a callback.</p>
as a callback. </p>
<h2>Transferring control <a href="#transferring-control" name="transferring-control" class="header-anchor">#</a></h2> <h2>Transferring control <a href="#transferring-control" name="transferring-control" class="header-anchor">#</a></h2>
<p>Fibers have one more trick up their sleeves. When you execute a fiber using <p>Fibers have one more trick up their sleeves. When you execute a fiber using
<code>call()</code>, the fiber tracks which fiber it will return to when it yields. This <code>call()</code>, the fiber tracks which fiber it will return to when it yields. This
lets you build up a chain of fiber calls that will eventually unwind back to lets you build up a chain of fiber calls that will eventually unwind back to
the main fiber when all of the called ones yield or finish. </p> the main fiber when all of the called ones yield or finish.</p>
<p>This is usually what you want. But if you&rsquo;re doing something low level, like <p>This is usually what you want. But if you&rsquo;re doing something low level, like
writing your own scheduler to manage a pool of fibers, you may not want to treat writing your own scheduler to manage a pool of fibers, you may not want to treat
them explicitly like a stack. </p> them explicitly like a stack.</p>
<p>For rare cases like that, fibers also have a <code>transfer()</code> method. This switches <p>For rare cases like that, fibers also have a <code>transfer()</code> method. This switches
execution to the transferred fiber and &ldquo;forgets&rdquo; the fiber that was transferred execution to the transferred fiber and &ldquo;forgets&rdquo; the fiber that was transferred
<em>from</em>. The previous one is suspended, leaving it in whatever state it was in. <em>from</em>. The previous one is suspended, leaving it in whatever state it was in.
You can resume the previous fiber by explicitly transferring back to it, or even You can resume the previous fiber by explicitly transferring back to it, or even
calling it. If you don&rsquo;t, execution stops when the last transferred fiber calling it. If you don&rsquo;t, execution stops when the last transferred fiber
returns. </p> returns.</p>
<p>Where <code>call()</code> and <code>yield()</code> are analogous to calling and returning from <p>Where <code>call()</code> and <code>yield()</code> are analogous to calling and returning from
functions, <code>transfer()</code> works more like an unstructured goto. It lets you freely functions, <code>transfer()</code> works more like an unstructured goto. It lets you freely
switch control between a number of fibers, all of which act as peers to one switch control between a number of fibers, all of which act as peers to one
another. </p> another.</p>
<p><br><hr> <p><br><hr>
<a class="right" href="error-handling.html">Error Handling &rarr;</a> <a class="right" href="error-handling.html">Error Handling &rarr;</a>
<a href="classes.html">&larr; Classes</a> </p> <a href="classes.html">&larr; Classes</a></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Contributing &ndash; Wren</title> <title>Contributing &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,116 +110,101 @@
</nav> </nav>
<main> <main>
<h2>Contributing</h2> <h2>Contributing</h2>
<p>Like the bird, Wren&rsquo;s ecosystem is small but full of life. Almost everything is <p>Like the bird, Wren&rsquo;s ecosystem is small but full of life. Almost everything is
under active development and there&rsquo;s lots to do. We&rsquo;d be delighted to have you under active development and there&rsquo;s lots to do. We&rsquo;d be delighted to have you
help. </p> help.</p>
<p>The first thing to do is to join <a href="https://groups.google.com/forum/#!forum/wren-lang">the official mailing list</a> and say, <p>The first thing to do is to join <a href="https://discord.gg/Kx6PxSX">the discord community</a> (or <a href="https://groups.google.com/forum/#!forum/wren-lang">the mailing list</a>) and say,
&ldquo;Hi&rdquo;. There are no strangers to Wren, just friends we haven&rsquo;t met yet. </p> &ldquo;Hi&rdquo;. There are no strangers to Wren, just friends we haven&rsquo;t met yet.</p>
<h2>Growing the ecosystem <a href="#growing-the-ecosystem" name="growing-the-ecosystem" class="header-anchor">#</a></h2> <h2>Growing the ecosystem <a href="#growing-the-ecosystem" name="growing-the-ecosystem" class="header-anchor">#</a></h2>
<p>The simplest and often most helpful way to join the Wren party is to be a Wren <p>The simplest and often most helpful way to join the Wren party is to be a Wren
<em>user</em>. Create an application that embeds Wren. Write a library or a handy <em>user</em>. Create an application that embeds Wren. Write a library or a handy
utility in Wren. Add syntax highlighting support for Wren to your favorite text utility in Wren. Add syntax highlighting support for Wren to your favorite text
editor. Share that stuff and it will help the next Wren user to come along. </p> editor. Share that stuff and it will help the next Wren user to come along.</p>
<p>If you do any of the above, let us know by adding it to <a href="https://github.com/wren-lang/wren/wiki">the wiki</a>. We <p>If you do any of the above, let us know by adding it to <a href="https://github.com/wren-lang/wren/wiki">the wiki</a>. <br />
like to keep track of: </p> We like to keep track of:</p>
<ul> <ul>
<li><a href="https://github.com/wren-lang/wren/wiki/Applications">Applications</a> that host Wren as a scripting language. </li> <li><a href="https://github.com/wren-lang/wren/wiki/Applications">Applications</a> that host Wren as a scripting language.</li>
<li><a href="https://github.com/wren-lang/wren/wiki/Modules">Modules</a> written in Wren that others can use. </li> <li><a href="https://github.com/wren-lang/wren/wiki/Modules">Modules</a> written in Wren that others can use.</li>
<li><a href="https://github.com/wren-lang/wren/wiki/Language-Bindings">Language bindings</a> that let you interact with Wren from other programming <li><a href="https://github.com/wren-lang/wren/wiki/Language-Bindings">Language bindings</a> that let you interact with Wren from other
languages. </li> languages.</li>
<li>Other <a href="https://github.com/wren-lang/wren/wiki/Tools">tools and utilities</a> that make it easier to be a Wren programmer. </li> <li><a href="https://github.com/wren-lang/wren/wiki/Tools">Tools and utilities</a> that make it easier to be a Wren programmer.</li>
</ul> </ul>
<h2>Contributing to Wren <a href="#contributing-to-wren" name="contributing-to-wren" class="header-anchor">#</a></h2> <h2>Contributing to Wren <a href="#contributing-to-wren" name="contributing-to-wren" class="header-anchor">#</a></h2>
<p>You&rsquo;re also more than welcome to contribute to Wren itself, both the core VM and <p>You&rsquo;re also more than welcome to contribute to Wren itself, both the core VM and
the command-line interpreter. The source is developed <a href="https://github.com/wren-lang/wren">on GitHub</a>. Our the command-line interpreter. The source is developed <a href="https://github.com/wren-lang/">on GitHub</a>. Our
hope is that the codebase, tests, and <a href="https://github.com/wren-lang/wren/tree/master/doc/site">documentation</a> are easy to hope is that the codebase, tests, and <a href="https://github.com/wren-lang/wren/tree/master/doc/site">documentation</a> are easy to
understand and contribute to. If they aren&rsquo;t, that&rsquo;s a bug. </p> understand and contribute to. If they aren&rsquo;t, that&rsquo;s a bug.</p>
<p>You can learn how to build wren on the <a href="getting-started.html#building-wren">getting started page</a>.</p>
<h3>Finding something to hack on <a href="#finding-something-to-hack-on" name="finding-something-to-hack-on" class="header-anchor">#</a></h3> <h3>Finding something to hack on <a href="#finding-something-to-hack-on" name="finding-something-to-hack-on" class="header-anchor">#</a></h3>
<p>Between the <a href="https://github.com/wren-lang/wren/issues">issue tracker</a> and searching for <code>TODO</code> comments in the <p>Between the <a href="https://github.com/wren-lang/wren/issues">issue tracker</a> and searching for <code>TODO</code> comments in the
code, it&rsquo;s pretty easy to find something that needs doing, though we don&rsquo;t code, it&rsquo;s pretty easy to find something that needs doing, though we don&rsquo;t
always do a good job of writing everything down. </p> always do a good job of writing everything down.</p>
<p>If nothing there suits your fancy, new ideas are welcome as well! If you have an <p>If nothing there suits your fancy, new ideas are welcome as well! If you have an
idea for a significant change or addition, please file a <a href="https://github.com/wren-lang/wren/labels/proposal">proposal</a> to discuss idea for a significant change or addition, please file a <a href="https://github.com/wren-lang/wren/labels/proposal">proposal</a> to discuss
it before writing lots of code. Wren tries very <em>very</em> hard to be minimal which it before writing lots of code. Wren tries very <em>very</em> hard to be minimal which
means often having to say &ldquo;no&rdquo; to language additions, even really cool ones. </p> means often having to say &ldquo;no&rdquo; to language additions, even really cool ones.</p>
<h3>Hacking on docs <a href="#hacking-on-docs" name="hacking-on-docs" class="header-anchor">#</a></h3> <h3>Hacking on docs <a href="#hacking-on-docs" name="hacking-on-docs" class="header-anchor">#</a></h3>
<p>The <a href="/">documentation</a> is one of the easiest&mdash;and most <p>The <a href="/">documentation</a> is one of the easiest&mdash;and most
important!&mdash;parts of Wren to contribute to. The source for the site is important!&mdash;parts of Wren to contribute to. The source for the site is
written in <a href="http://daringfireball.net/projects/markdown/">Markdown</a> (and a little <a href="http://sass-lang.com/">SASS</a>) and lives under <code>doc/site</code>. A written in <a href="http://daringfireball.net/projects/markdown/">Markdown</a> and lives under <code>doc/site</code>. A
simple Python script, <code>util/generate_docs.py</code>, converts that to HTML and CSS. </p> simple Python 3 script, <code>util/generate_docs.py</code>, converts that to HTML and CSS.</p>
<p>The site uses <a href="http://pygments.org">Pygments</a> for syntax highlighting, with a custom lexer plug-in <pre><code>$ python util/generate_docs.py
for Wren. To install that, run: </p> </code></pre>
<div class="codehilite"><pre><span class="nv">$ </span><span class="nb">cd </span>util/pygments-lexer <p>This generates the site in <code>build/docs/</code>. You can run any simple static web
<span class="nv">$ </span>sudo python3 setup.py develop server from there. Python includes one:</p>
<span class="nv">$ </span><span class="nb">cd</span> ../.. <span class="c"># Back to the root Wren directory.</span> <pre><code>$ cd build/docs
</pre></div> $ python -m http.server
</code></pre>
<p>Running that script every time you change a line of Markdown can be slow,
<p>Now you can build the docs: </p> so there is also a file watching version that will automatically regenerate the
<div class="codehilite"><pre><span class="nv">$ </span>make docs docs when you edit a file:</p>
</pre></div> <pre><code>$ python util/generate_docs.py --watch
</code></pre>
<p>This generates the site in <code>build/docs/</code>. You can run any simple static web
server from there. Python includes one: </p>
<div class="codehilite"><pre><span class="nv">$ </span><span class="nb">cd </span>build/docs
<span class="nv">$ </span>python3 -m http.server
</pre></div>
<p>Running <code>make docs</code> is a drag every time you change a line of Markdown or SASS,
so there is also a file watching version that will automatically regenerate the
docs when you edit a file: </p>
<div class="codehilite"><pre><span class="nv">$ </span>make watchdocs
</pre></div>
<h3>Hacking on the VM <a href="#hacking-on-the-vm" name="hacking-on-the-vm" class="header-anchor">#</a></h3> <h3>Hacking on the VM <a href="#hacking-on-the-vm" name="hacking-on-the-vm" class="header-anchor">#</a></h3>
<p>The basic process is simple: </p> <p>The basic process is simple:</p>
<ol> <ol>
<li> <li>
<p><strong>Make sure you can build and run the tests locally.</strong> It&rsquo;s good to ensure <p><strong>Make sure you can build and run the tests locally.</strong> It&rsquo;s good to ensure
you&rsquo;re starting from a happy place before you poke at the code. Running the you&rsquo;re starting from a happy place before you poke at the code. Running the
tests is as simple as: </p> tests is as simple as <a href="getting-started.html#building-wren">building the vm project</a>,
<div class="codehilite"><pre><span class="nv">$ </span>make <span class="nb">test</span> which generates <code>bin/wren_test</code> and then running the following python 3 script:</p>
</pre></div> <pre><code>$ python util/test.py
</code></pre>
<p>If there are no failures, you&rsquo;re good to go.</p>
<p>If there are no failures, you&rsquo;re good to go. </p>
</li> </li>
<li> <li>
<p><strong><a href="https://help.github.com/articles/fork-a-repo/">Fork the repo</a> so you can change it locally.</strong> Please make your <p><strong><a href="https://help.github.com/articles/fork-a-repo/">Fork the repo</a> so you can change it locally.</strong> Please make your
changes in separate <a href="https://www.atlassian.com/git/tutorials/comparing-workflows/centralized-workflow">feature branches</a> to make things a little easier on changes in separate <a href="https://www.atlassian.com/git/tutorials/comparing-workflows/centralized-workflow">feature branches</a> to make things a little easier on
me. </p> me.</p>
</li> </li>
<li> <li>
<p><strong>Change the code.</strong> Please follow the style of the surrounding code. That <p><strong>Change the code.</strong> Please follow the style of the surrounding code. That
basically means <code>camelCase</code> names, <code>{</code> on the next line, keep within 80 basically means <code>camelCase</code> names, <code>{</code> on the next line, keep within 80
columns, and two spaces of indentation. If you see places where the existing columns, and two spaces of indentation. If you see places where the existing
code is inconsistent, let me know. </p> code is inconsistent, let us know.</p>
</li> </li>
<li> <li>
<p><strong>Write some tests for your new functionality.</strong> They live under <code>test/</code>. <p><strong>Write some tests for your new functionality.</strong> They live under <code>test/</code>.
Take a look at some existing tests to get an idea of how to define Take a look at some existing tests to get an idea of how to define
expectations. </p> expectations.</p>
</li> </li>
<li> <li>
<p><strong>Make sure the tests all pass, both the old ones and your new ones.</strong> </p> <p><strong>Make sure the tests all pass, both the old ones and your new ones.</strong></p>
</li> </li>
<li> <li>
<p><strong>Add your name and email to the <a href="https://github.com/wren-lang/wren/tree/master/AUTHORS">AUTHORS</a> file if you haven&rsquo;t already.</strong> </p> <p><strong>Add your name and email to the <a href="https://github.com/wren-lang/wren/tree/master/AUTHORS">AUTHORS</a> file if you haven&rsquo;t already.</strong></p>
</li> </li>
<li> <li>
<p><strong>Send a <a href="https://github.com/wren-lang/wren/pulls">pull request</a>.</strong> Pat yourself on the back for contributing to a <p><strong>Send a <a href="https://github.com/wren-lang/wren/pulls">pull request</a>.</strong> Pat yourself on the back for contributing to a
fun open source project! I&rsquo;ll take it from here and hopefully we&rsquo;ll get it fun open source project! I&rsquo;ll take it from here and hopefully we&rsquo;ll get it
landed smoothly. </p> landed smoothly.</p>
</li> </li>
</ol> </ol>
<h2>Getting help <a href="#getting-help" name="getting-help" class="header-anchor">#</a></h2> <h2>Getting help <a href="#getting-help" name="getting-help" class="header-anchor">#</a></h2>
<p>If at any point you have questions, feel free to <a href="https://github.com/wren-lang/wren/issues">file an issue</a> or ask <p>If at any point you have questions, feel free to <a href="https://github.com/wren-lang/wren/issues">file an issue</a> or ask
on the <a href="https://groups.google.com/forum/#!forum/wren-lang">mailing list</a>. If you&rsquo;re a Redditor, try the on the <a href="https://discord.gg/Kx6PxSX">discord community</a> (or the <a href="https://groups.google.com/forum/#!forum/wren-lang">mailing list</a>). If you&rsquo;re a Redditor, try the
<a href="https://www.reddit.com/r/wren_lang/">/r/wren_lang</a> subreddit. You can also email me directly (<code>robert</code> at <a href="https://www.reddit.com/r/wren_lang/">/r/wren_lang</a> subreddit. You can also email me directly (<code>robert</code> at
<code>stuffwithstuff.com</code>) if you want something less public. </p> <code>stuffwithstuff.com</code>) if you want something less public.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Control Flow &ndash; Wren</title> <title>Control Flow &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,226 +110,226 @@
</nav> </nav>
<main> <main>
<h2>Control Flow</h2> <h2>Control Flow</h2>
<p>Control flow is used to determine which chunks of code are executed and how many <p>Control flow is used to determine which chunks of code are executed and how many
times. <em>Branching</em> statements and expressions decide whether or not to execute times. <em>Branching</em> statements and expressions decide whether or not to execute
some code and <em>looping</em> ones execute something more than once. </p> some code and <em>looping</em> ones execute something more than once.</p>
<h2>Truth <a href="#truth" name="truth" class="header-anchor">#</a></h2> <h2>Truth <a href="#truth" name="truth" class="header-anchor">#</a></h2>
<p>All control flow is based on <em>deciding</em> whether or not to do something. This <p>All control flow is based on <em>deciding</em> whether or not to do something. This
decision depends on some expression&rsquo;s value. We take the entire universe of decision depends on some expression&rsquo;s value. We take the entire universe of
possible objects and divide them into two buckets: some we consider &ldquo;true&rdquo; and possible objects and divide them into two buckets: some we consider &ldquo;true&rdquo; and
the rest are &ldquo;false&rdquo;. If the expression results in a value in the true bucket, the rest are &ldquo;false&rdquo;. If the expression results in a value in the true bucket,
we do one thing. Otherwise, we do something else. </p> we do one thing. Otherwise, we do something else.</p>
<p>Obviously, the boolean <code>true</code> is in the &ldquo;true&rdquo; bucket and <code>false</code> is in <p>Obviously, the boolean <code>true</code> is in the &ldquo;true&rdquo; bucket and <code>false</code> is in
&ldquo;false&rdquo;, but what about values of other types? The choice is ultimately &ldquo;false&rdquo;, but what about values of other types? The choice is ultimately
arbitrary, and different languages have different rules. Wren&rsquo;s rules follow arbitrary, and different languages have different rules. Wren&rsquo;s rules follow
Ruby: </p> Ruby:</p>
<ul> <ul>
<li>The boolean value <code>false</code> is false. </li> <li>The boolean value <code>false</code> is false.</li>
<li>The null value <code>null</code> is false. </li> <li>The null value <code>null</code> is false.</li>
<li>Everything else is true. </li> <li>Everything else is true.</li>
</ul> </ul>
<p>This means <code>0</code>, empty strings, and empty collections are all considered &ldquo;true&rdquo; <p>This means <code>0</code>, empty strings, and empty collections are all considered &ldquo;true&rdquo;
values. </p> values.</p>
<h2>If statements <a href="#if-statements" name="if-statements" class="header-anchor">#</a></h2> <h2>If statements <a href="#if-statements" name="if-statements" class="header-anchor">#</a></h2>
<p>The simplest branching statement, <code>if</code> lets you conditionally skip a chunk of <p>The simplest branching statement, <code>if</code> lets you conditionally skip a chunk of
code. It looks like this: </p> code. It looks like this:</p>
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;go!&quot;</span><span class="p">)</span> <pre class="snippet">
</pre></div> if (ready) System.print("go!")
</pre>
<p>That evaluates the parenthesized expression after <code>if</code>. If it&rsquo;s true, then the
statement after the condition is evaluated. Otherwise it is skipped. Instead of
a statement, you can have a <a href="syntax.html#blocks">block</a>:</p>
<pre class="snippet">
if (ready) {
System.print("getSet")
System.print("go!")
}
</pre>
<p>That evaluates the parenthesized expression after <code>if</code>. If it&rsquo;s true, then the <p>You may also provide an <code>else</code> branch. It will be executed if the condition is
statement after the condition is evaluated. Otherwise it is skipped. Instead of false:</p>
a statement, you can have a <a href="syntax.html#blocks">block</a>: </p> <pre class="snippet">
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="p">{</span> if (ready) System.print("go!") else System.print("not ready!")
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;getSet&quot;</span><span class="p">)</span> </pre>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;go!&quot;</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
<p>You may also provide an <code>else</code> branch. It will be executed if the condition is
false: </p>
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;go!&quot;</span><span class="p">)</span> <span class="k">else</span> <span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;not ready!&quot;</span><span class="p">)</span>
</pre></div>
<p>And, of course, it can take a block too: </p>
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">ready</span><span class="p">)</span> <span class="p">{</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;go!&quot;</span><span class="p">)</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;not ready!&quot;</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
<p>And, of course, it can take a block too:</p>
<pre class="snippet">
if (ready) {
System.print("go!")
} else {
System.print("not ready!")
}
</pre>
<h2>Logical operators <a href="#logical-operators" name="logical-operators" class="header-anchor">#</a></h2> <h2>Logical operators <a href="#logical-operators" name="logical-operators" class="header-anchor">#</a></h2>
<p>Unlike most other <a href="method-calls.html#operators">operators</a> in Wren which are just a special syntax for <p>Unlike most other <a href="method-calls.html#operators">operators</a> in Wren which are just a special syntax for
<a href="method-calls.html">method calls</a>, the <code>&amp;&amp;</code> and <code>||</code> operators are special. This is because they <a href="method-calls.html">method calls</a>, the <code>&amp;&amp;</code> and <code>||</code> operators are special. This is because they
only conditionally evaluate right operand&mdash;they short-circuit. </p> only conditionally evaluate right operand&mdash;they short-circuit.</p>
<p>A <code>&amp;&amp;</code> (&ldquo;logical and&rdquo;) expression evaluates the left-hand argument. If it&rsquo;s <p>A <code>&amp;&amp;</code> (&ldquo;logical and&rdquo;) expression evaluates the left-hand argument. If it&rsquo;s
false, it returns that value. Otherwise it evaluates and returns the right-hand false, it returns that value. Otherwise it evaluates and returns the right-hand
argument. </p> argument.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="kc">false</span> <span class="o">&amp;&amp;</span> <span class="mi">1</span><span class="p">)</span> <span class="output">false</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="mi">2</span><span class="p">)</span> <span class="output">2</span> System.print(false && 1) //> false
</pre></div> System.print(1 && 2) //> 2
</pre>
<p>A <code>||</code> (&ldquo;logical or&rdquo;) expression is reversed. If the left-hand argument is
<em>true</em>, it&rsquo;s returned, otherwise the right-hand argument is evaluated and
returned: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="kc">false</span> <span class="o">||</span> <span class="mi">1</span><span class="p">)</span> <span class="output">1</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mi">1</span> <span class="o">||</span> <span class="mi">2</span><span class="p">)</span> <span class="output">1</span>
</pre></div>
<p>A <code>||</code> (&ldquo;logical or&rdquo;) expression is reversed. If the left-hand argument is
<em>true</em>, it&rsquo;s returned, otherwise the right-hand argument is evaluated and
returned:</p>
<pre class="snippet">
System.print(false || 1) //> 1
System.print(1 || 2) //> 1
</pre>
<h2>The conditional operator <code>?:</code> <a href="#the-conditional-operator-" name="the-conditional-operator-" class="header-anchor">#</a></h2> <h2>The conditional operator <code>?:</code> <a href="#the-conditional-operator-" name="the-conditional-operator-" class="header-anchor">#</a></h2>
<p>Also known as the &ldquo;ternary&rdquo; operator since it takes three arguments, Wren has <p>Also known as the &ldquo;ternary&rdquo; operator since it takes three arguments, Wren has
the little &ldquo;if statement in the form of an expression&rdquo; you know and love from C the little &ldquo;if statement in the form of an expression&rdquo; you know and love from C
and its brethren. </p> and its brethren.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mi">1</span> <span class="o">!=</span> <span class="mi">2</span> <span class="o">?</span> <span class="s">&quot;math is sane&quot;</span> <span class="o">:</span> <span class="s">&quot;math is not sane!&quot;</span><span class="p">)</span> <pre class="snippet">
</pre></div> System.print(1 != 2 ? "math is sane" : "math is not sane!")
</pre>
<p>It takes a condition expression, followed by <code>?</code>, followed by a then
<p>It takes a condition expression, followed by <code>?</code>, followed by a then expression, a <code>:</code>, then an else expression. Just like <code>if</code>, it evaluates the
expression, a <code>:</code>, then an else expression. Just like <code>if</code>, it evaluates the condition. If true, it evaluates and returns the then expression. Otherwise
condition. If true, it evaluates and returns the then expression. Otherwise it does the else expression.</p>
it does the else expression. </p>
<h2>While statements <a href="#while-statements" name="while-statements" class="header-anchor">#</a></h2> <h2>While statements <a href="#while-statements" name="while-statements" class="header-anchor">#</a></h2>
<p>It&rsquo;s hard to write a useful program without executing some chunk of code <p>It&rsquo;s hard to write a useful program without executing some chunk of code
repeatedly. To do that, you use looping statements. There are two in Wren, and repeatedly. To do that, you use looping statements. There are two in Wren, and
they should be familiar if you&rsquo;ve used other imperative languages. </p> they should be familiar if you&rsquo;ve used other imperative languages.</p>
<p>The simplest, a <code>while</code> statement executes a chunk of code as long as a <p>The simplest, a <code>while</code> statement executes a chunk of code as long as a
condition continues to hold. For example: </p> condition continues to hold. For example:</p>
<div class="codehilite"><pre><span class="c1">// Hailstone sequence.</span> <pre class="snippet">
<span class="k">var</span> <span class="err">n</span> <span class="o">=</span> <span class="mi">27</span> // Hailstone sequence.
<span class="k">while</span> <span class="p">(</span><span class="err">n</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> var n = 27
<span class="k">if</span> <span class="p">(</span><span class="err">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> while (n != 1) {
<span class="err">n</span> <span class="o">=</span> <span class="err">n</span> <span class="o">/</span> <span class="mi">2</span> if (n % 2 == 0) {
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span> n = n / 2
<span class="err">n</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">*</span> <span class="err">n</span> <span class="o">+</span> <span class="mi">1</span> } else {
<span class="p">}</span> n = 3 * n + 1
<span class="p">}</span> }
</pre></div> }
</pre>
<p>This evaluates the expression <code>n != 1</code>. If it is true, then it executes the
following body. After that, it loops back to the top, and evaluates the
condition again. It keeps doing this as long as the condition evaluates to
something true. </p>
<p>The condition for a while loop can be any expression, and must be surrounded by
parentheses. The body of the loop is usually a curly block but can also be a
single statement: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">n</span> <span class="o">=</span> <span class="mi">27</span>
<span class="k">while</span> <span class="p">(</span><span class="err">n</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="p">(</span><span class="err">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="err">n</span> <span class="o">=</span> <span class="err">n</span> <span class="o">/</span> <span class="mi">2</span> <span class="k">else</span> <span class="err">n</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">*</span> <span class="err">n</span> <span class="o">+</span> <span class="mi">1</span>
</pre></div>
<p>This evaluates the expression <code>n != 1</code>. If it is true, then it executes the
following body. After that, it loops back to the top, and evaluates the
condition again. It keeps doing this as long as the condition evaluates to
something true.</p>
<p>The condition for a while loop can be any expression, and must be surrounded by
parentheses. The body of the loop is usually a curly block but can also be a
single statement:</p>
<pre class="snippet">
var n = 27
while (n != 1) if (n % 2 == 0) n = n / 2 else n = 3 * n + 1
</pre>
<h2>For statements <a href="#for-statements" name="for-statements" class="header-anchor">#</a></h2> <h2>For statements <a href="#for-statements" name="for-statements" class="header-anchor">#</a></h2>
<p>While statements are useful when you want to loop indefinitely or according to <p>While statements are useful when you want to loop indefinitely or according to
some complex condition. But in most cases, you&rsquo;re looping through some complex condition. But in most cases, you&rsquo;re looping through
a <a href="lists.html">list</a>, a series of numbers, or some other &ldquo;sequence&rdquo; object. a <a href="lists.html">list</a>, a series of numbers, or some other &ldquo;sequence&rdquo; object.
That&rsquo;s what <code>for</code> is, uh, for. It looks like this: </p> That&rsquo;s what <code>for</code> is, uh, for. It looks like this:</p>
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="n">beatle</span> <span class="k">in</span> <span class="p">[</span><span class="s">&quot;george&quot;</span><span class="p">,</span> <span class="s">&quot;john&quot;</span><span class="p">,</span> <span class="s">&quot;paul&quot;</span><span class="p">,</span> <span class="s">&quot;ringo&quot;</span><span class="p">])</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">beatle</span><span class="p">)</span> for (beatle in ["george", "john", "paul", "ringo"]) {
<span class="p">}</span> System.print(beatle)
</pre></div> }
</pre>
<p>A <code>for</code> loop has three components:</p>
<p>A <code>for</code> loop has three components: </p>
<ol> <ol>
<li> <li>
<p>A <em>variable name</em> to bind. In the example, that&rsquo;s <code>beatle</code>. Wren will create <p>A <em>variable name</em> to bind. In the example, that&rsquo;s <code>beatle</code>. Wren will create
a new variable with that name whose scope is the body of the loop. </p> a new variable with that name whose scope is the body of the loop.</p>
</li> </li>
<li> <li>
<p>A <em>sequence expression</em>. This determines what you&rsquo;re looping over. It gets <p>A <em>sequence expression</em>. This determines what you&rsquo;re looping over. It gets
evaluated <em>once</em> before the body of the loop. In this case, it&rsquo;s a list evaluated <em>once</em> before the body of the loop. In this case, it&rsquo;s a list
literal, but it can be any expression. </p> literal, but it can be any expression.</p>
</li> </li>
<li> <li>
<p>A <em>body</em>. This is a curly block or a single statement. It gets executed once <p>A <em>body</em>. This is a curly block or a single statement. It gets executed once
for each iteration of the loop. </p> for each iteration of the loop.</p>
</li> </li>
</ol> </ol>
<h2>Break statements <a href="#break-statements" name="break-statements" class="header-anchor">#</a></h2> <h2>Break statements <a href="#break-statements" name="break-statements" class="header-anchor">#</a></h2>
<p>Sometimes, right in the middle of a loop body, you decide you want to bail out <p>Sometimes, right in the middle of a loop body, you decide you want to bail out
and stop. To do that, you can use a <code>break</code> statement. It&rsquo;s just the <code>break</code> and stop. To do that, you can use a <code>break</code> statement. It&rsquo;s just the <code>break</code>
keyword all by itself. That immediately exits out of the nearest enclosing keyword all by itself. That immediately exits out of the nearest enclosing
<code>while</code> or <code>for</code> loop. </p> <code>while</code> or <code>for</code> loop.</p>
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="err">i</span> <span class="k">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">])</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">i</span><span class="p">)</span> <span class="output">1</span> for (i in [1, 2, 3, 4]) {
<span class="k">if</span> <span class="p">(</span><span class="err">i</span> <span class="o">==</span> <span class="mi">3</span><span class="p">)</span> <span class="k">break</span> <span class="output">2</span> System.print(i) //> 1
<span class="p">}</span> <span class="output">3</span> if (i == 3) break //> 2
</pre></div> } //> 3
</pre>
<h2>Numeric ranges <a href="#numeric-ranges" name="numeric-ranges" class="header-anchor">#</a></h2> <h2>Numeric ranges <a href="#numeric-ranges" name="numeric-ranges" class="header-anchor">#</a></h2>
<p>Lists are one common use for <code>for</code> loops, but sometimes you want to walk over a <p>Lists are one common use for <code>for</code> loops, but sometimes you want to walk over a
sequence of numbers, or loop a number of times. For that, you can create a sequence of numbers, or loop a number of times. For that, you can create a
<a href="values.html#ranges">range</a>, like so: </p> <a href="values.html#ranges">range</a>, like so:</p>
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="err">i</span> <span class="k">in</span> <span class="mi">1</span><span class="o">..</span><span class="mi">100</span><span class="p">)</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">i</span><span class="p">)</span> for (i in 1..100) {
<span class="p">}</span> System.print(i)
</pre></div> }
</pre>
<p>This loops over the numbers from 1 to 100, including 100 itself. If you want to
leave off the last value, use three dots instead of two:</p>
<pre class="snippet">
for (i in 1...100) {
System.print(i)
}
</pre>
<p>This loops over the numbers from 1 to 100, including 100 itself. If you want to <p>This looks like some special &ldquo;range&rdquo; syntax in the <code>for</code> loop, but it&rsquo;s actually
leave off the last value, use three dots instead of two: </p> just a pair of operators. The <code>..</code> and <code>...</code> syntax are infix &ldquo;range&rdquo; operators.
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="err">i</span> <span class="k">in</span> <span class="mi">1</span><span class="o">...</span><span class="mi">100</span><span class="p">)</span> <span class="p">{</span> Like <a href="method-calls.html#operators">other operators</a>, they are special syntax for a regular method
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">i</span><span class="p">)</span> call. The number type implements them and returns a <a href="values.html#ranges">range object</a> that knows
<span class="p">}</span> how to iterate over a series of numbers.</p>
</pre></div>
<p>This looks like some special &ldquo;range&rdquo; syntax in the <code>for</code> loop, but it&rsquo;s actually
just a pair of operators. The <code>..</code> and <code>...</code> syntax are infix &ldquo;range&rdquo; operators.
Like <a href="method-calls.html#operators">other operators</a>, they are special syntax for a regular method
call. The number type implements them and returns a <a href="values.html#ranges">range object</a> that knows
how to iterate over a series of numbers. </p>
<h2>The iterator protocol <a href="#the-iterator-protocol" name="the-iterator-protocol" class="header-anchor">#</a></h2> <h2>The iterator protocol <a href="#the-iterator-protocol" name="the-iterator-protocol" class="header-anchor">#</a></h2>
<p>Lists and ranges cover the two most common kinds of loops, but you should also <p>Lists and ranges cover the two most common kinds of loops, but you should also
be able to define your own sequences. To enable that, the semantics of <code>for</code> be able to define your own sequences. To enable that, the semantics of <code>for</code>
are defined in terms of an &ldquo;iterator protocol&rdquo;. The loop itself doesn&rsquo;t know are defined in terms of an &ldquo;iterator protocol&rdquo;. The loop itself doesn&rsquo;t know
anything about lists or ranges, it just knows how to call two particular anything about lists or ranges, it just knows how to call two particular
methods on the object that resulted from evaluating the sequence expression. </p> methods on the object that resulted from evaluating the sequence expression.</p>
<p>When you write a loop like this: </p> <p>When you write a loop like this:</p>
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="err">i</span> <span class="k">in</span> <span class="mi">1</span><span class="o">..</span><span class="mi">100</span><span class="p">)</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">i</span><span class="p">)</span> for (i in 1..100) {
<span class="p">}</span> System.print(i)
</pre></div> }
</pre>
<p>Wren sees it something like this:</p>
<pre class="snippet">
var iter_ = null
var seq_ = 1..100
while (iter_ = seq_.iterate(iter_)) {
var i = seq_.iteratorValue(iter_)
System.print(i)
}
</pre>
<p>Wren sees it something like this: </p> <p>First, Wren evaluates the sequence expression and stores it in a hidden
<div class="codehilite"><pre><span class="k">var</span> <span class="n">iter_</span> <span class="o">=</span> <span class="kc">null</span> variable (written <code>seq_</code> in the example but in reality it doesn&rsquo;t have a name
<span class="k">var</span> <span class="n">seq_</span> <span class="o">=</span> <span class="mi">1</span><span class="o">..</span><span class="mi">100</span> you can use). It also creates a hidden &ldquo;iterator&rdquo; variable and initializes it
<span class="k">while</span> <span class="p">(</span><span class="n">iter_</span> <span class="o">=</span> <span class="n">seq_</span><span class="o">.</span><span class="n">iterate</span><span class="p">(</span><span class="n">iter_</span><span class="p">))</span> <span class="p">{</span> to <code>null</code>.</p>
<span class="k">var</span> <span class="err">i</span> <span class="o">=</span> <span class="n">seq_</span><span class="o">.</span><span class="n">iteratorValue</span><span class="p">(</span><span class="n">iter_</span><span class="p">)</span> <p>Each iteration, it calls <code>iterate()</code> on the sequence, passing in the current
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">i</span><span class="p">)</span> iterator value. (In the first iteration, it passes in <code>null</code>.) The sequence&rsquo;s
<span class="p">}</span> job is to take that iterator and advance it to the next element in the
</pre></div> sequence. (Or, in the case where the iterator is <code>null</code>, to advance it to the
<em>first</em> element). It then returns either the new iterator, or <code>false</code> to
indicate that there are no more elements.</p>
<p>First, Wren evaluates the sequence expression and stores it in a hidden <p>If <code>false</code> is returned, Wren exits out of the loop and we&rsquo;re done. If anything
variable (written <code>seq_</code> in the example but in reality it doesn&rsquo;t have a name else is returned, that means that we have advanced to a new valid element. To
you can use). It also creates a hidden &ldquo;iterator&rdquo; variable and initializes it get that, Wren then calls <code>iteratorValue()</code> on the sequence and passes in the
to <code>null</code>. </p> iterator value that it just got from calling <code>iterate()</code>. The sequence uses
<p>Each iteration, it calls <code>iterate()</code> on the sequence, passing in the current that to look up and return the appropriate element.</p>
iterator value. (In the first iteration, it passes in <code>null</code>.) The sequence&rsquo;s <p>The built-in <a href="lists.html">List</a> and <a href="values.html#ranges">Range</a> types implement
job is to take that iterator and advance it to the next element in the <code>iterate()</code> and <code>iteratorValue()</code> to walk over their respective sequences. You
sequence. (Or, in the case where the iterator is <code>null</code>, to advance it to the can implement the same methods in your classes to make your own types iterable.</p>
<em>first</em> element). It then returns either the new iterator, or <code>false</code> to <p><br><hr>
indicate that there are no more elements. </p> <a class="right" href="variables.html">Variables &rarr;</a>
<p>If <code>false</code> is returned, Wren exits out of the loop and we&rsquo;re done. If anything <a href="method-calls.html">&larr; Method Calls</a></p>
else is returned, that means that we have advanced to a new valid element. To
get that, Wren then calls <code>iteratorValue()</code> on the sequence and passes in the
iterator value that it just got from calling <code>iterate()</code>. The sequence uses
that to look up and return the appropriate element. </p>
<p>The built-in <a href="lists.html">List</a> and <a href="values.html#ranges">Range</a> types implement
<code>iterate()</code> and <code>iteratorValue()</code> to walk over their respective sequences. You
can implement the same methods in your classes to make your own types iterable. </p>
<p><br><hr>
<a class="right" href="variables.html">Variables &rarr;</a>
<a href="method-calls.html">&larr; Method Calls</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Calling C from Wren &ndash; Wren</title> <title>Calling C from Wren &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,6 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section> <section>
<h2>embedding</h2> <h2>embedding</h2>
<ul> <ul>
@ -63,121 +70,121 @@
</nav> </nav>
<main> <main>
<h1>Calling C from Wren</h1> <h1>Calling C from Wren</h1>
<p>When we are ensconced within the world of Wren, the external C world is <p>When we are ensconced within the world of Wren, the external C world is
&ldquo;foreign&rdquo; to us. There are two reasons we might want to bring some foreign &ldquo;foreign&rdquo; to us. There are two reasons we might want to bring some foreign
flavor into our VM: </p> flavor into our VM:</p>
<ul> <ul>
<li>We want to execute code written in C. </li> <li>We want to execute code written in C.</li>
<li>We want to store raw C data. </li> <li>We want to store raw C data.</li>
</ul> </ul>
<p>Since Wren is object-oriented, behavior lives in methods, so for the former we <p>Since Wren is object-oriented, behavior lives in methods, so for the former we
have <strong>foreign methods</strong>. Likewise, data lives in objects, so for the latter, we have <strong>foreign methods</strong>. Likewise, data lives in objects, so for the latter, we
define <strong>foreign classes</strong>. This page is about the first, foreign methods. The define <strong>foreign classes</strong>. This page is about the first, foreign methods. The
<a href="/embedding/storing-c-data.html">next page</a> covers foreign classes. </p> <a href="/embedding/storing-c-data.html">next page</a> covers foreign classes.</p>
<p>A foreign method looks to Wren like a regular method. It is defined on a Wren <p>A foreign method looks to Wren like a regular method. It is defined on a Wren
class, it has a name and signature, and calls to it are dynamically dispatched. class, it has a name and signature, and calls to it are dynamically dispatched.
The only difference is that the <em>body</em> of the method is written in C. </p> The only difference is that the <em>body</em> of the method is written in C.</p>
<p>A foreign method is declared in Wren like so: </p> <p>A foreign method is declared in Wren like so:</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Math</span> <span class="p">{</span> <pre class="snippet">
<span class="k">foreign</span> <span class="k">static</span> <span class="n">add</span><span class="p">(</span><span class="err">a</span><span class="p">,</span> <span class="err">b</span><span class="p">)</span> class Math {
<span class="p">}</span> foreign static add(a, b)
</pre></div> }
</pre>
<p>The <code>foreign</code> keyword tells Wren that the method <code>add()</code> is declared on <code>Math</code>,
<p>The <code>foreign</code> keyword tells Wren that the method <code>add()</code> is declared on <code>Math</code>, but implemented in C. Both static and instance methods can be foreign.</p>
but implemented in C. Both static and instance methods can be foreign. </p>
<h2>Binding Foreign Methods <a href="#binding-foreign-methods" name="binding-foreign-methods" class="header-anchor">#</a></h2> <h2>Binding Foreign Methods <a href="#binding-foreign-methods" name="binding-foreign-methods" class="header-anchor">#</a></h2>
<p>When you call a foreign method, Wren needs to figure out which C function to <p>When you call a foreign method, Wren needs to figure out which C function to
execute. This process is called <em>binding</em>. Binding is performed on-demand by the execute. This process is called <em>binding</em>. Binding is performed on-demand by the
VM. When a class that declares a foreign method is executed &ndash; when the <code>class</code> VM. When a class that declares a foreign method is executed &ndash; when the <code>class</code>
statement itself is evaluated &ndash; the VM asks the host application for the C statement itself is evaluated &ndash; the VM asks the host application for the C
function that should be used for the foreign method. </p> function that should be used for the foreign method.</p>
<p>It does this through the <code>bindForeignMethodFn</code> callback you give it when you <p>It does this through the <code>bindForeignMethodFn</code> callback you give it when you
first <a href="configuring-the-vm.html">configure the VM</a>. This callback isn&rsquo;t the foreign method itself. first <a href="configuring-the-vm.html">configure the VM</a>. This callback isn&rsquo;t the foreign method itself.
It&rsquo;s the binding function your app uses to <em>look up</em> foreign methods. </p> It&rsquo;s the binding function your app uses to <em>look up</em> foreign methods.</p>
<p>Its signature is: </p> <p>Its signature is:</p>
<div class="codehilite"><pre><span class="n">WrenForeignMethodFn</span> <span class="nf">bindForeignMethodFn</span><span class="p">(</span> <pre class="snippet" data-lang="c">
<span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> WrenForeignMethodFn bindForeignMethodFn(
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span> WrenVM* vm,
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">className</span><span class="p">,</span> const char* module,
<span class="kt">bool</span> <span class="n">isStatic</span><span class="p">,</span> const char* className,
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">signature</span><span class="p">);</span> bool isStatic,
</pre></div> const char* signature);
</pre>
<p>Every time a foreign method is first declared, the VM invokes this callback. It
passes in the module containing the class declaration, the name of the class
containing the method, the method&rsquo;s signature, and whether or not it&rsquo;s a static
method. In the above example, it would pass something like:</p>
<pre class="snippet" data-lang="c">
bindForeignMethodFn(vm, "main", "Math", true, "add(_,_)");
</pre>
<p>Every time a foreign method is first declared, the VM invokes this callback. It <p>When you configure the VM, you give it a C callback that looks up the
passes in the module containing the class declaration, the name of the class appropriate function for the given foreign method and returns a pointer to it.
containing the method, the method&rsquo;s signature, and whether or not it&rsquo;s a static Something like:</p>
method. In the above example, it would pass something like: </p> <pre class="snippet" data-lang="c">
<div class="codehilite"><pre><span class="n">bindForeignMethodFn</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="s">&quot;main&quot;</span><span class="p">,</span> <span class="s">&quot;Math&quot;</span><span class="p">,</span> <span class="nb">true</span><span class="p">,</span> <span class="s">&quot;add(_,_)&quot;</span><span class="p">);</span> WrenForeignMethodFn bindForeignMethod(
</pre></div> WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature)
{
if (strcmp(module, "main") == 0)
{
if (strcmp(className, "Math") == 0)
{
if (isStatic && strcmp(signature, "add(_,_)") == 0)
{
return mathAdd; // C function for Math.add(_,_).
}
// Other foreign methods on Math...
}
// Other classes in main...
}
// Other modules...
}
</pre>
<p>This implementation is pretty tedious, but you get the idea. Feel free to do
<p>When you configure the VM, you give it a C callback that looks up the something more clever here in your host application.</p>
appropriate function for the given foreign method and returns a pointer to it. <p>The important part is that it returns a pointer to a C function to use for that
Something like: </p> foreign method. Wren does this binding step <em>once</em> when the class definition is
<div class="codehilite"><pre><span class="n">WrenForeignMethodFn</span> <span class="nf">bindForeignMethod</span><span class="p">(</span> first executed. It then keeps the function pointer you return and associates it
<span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> with that method. This way, <em>calls</em> to the foreign method are fast.</p>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">className</span><span class="p">,</span>
<span class="kt">bool</span> <span class="n">isStatic</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">signature</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="s">&quot;main&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">className</span><span class="p">,</span> <span class="s">&quot;Math&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">isStatic</span> <span class="o">&amp;&amp;</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">signature</span><span class="p">,</span> <span class="s">&quot;add(_,_)&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">mathAdd</span><span class="p">;</span> <span class="c1">// C function for Math.add(_,_).</span>
<span class="p">}</span>
<span class="c1">// Other foreign methods on Math...</span>
<span class="p">}</span>
<span class="c1">// Other classes in main...</span>
<span class="p">}</span>
<span class="c1">// Other modules...</span>
<span class="p">}</span>
</pre></div>
<p>This implementation is pretty tedious, but you get the idea. Feel free to do
something more clever here in your host application. </p>
<p>The important part is that it returns a pointer to a C function to use for that
foreign method. Wren does this binding step <em>once</em> when the class definition is
first executed. It then keeps the function pointer you return and associates it
with that method. This way, <em>calls</em> to the foreign method are fast. </p>
<h2>Implementing a Foreign Method <a href="#implementing-a-foreign-method" name="implementing-a-foreign-method" class="header-anchor">#</a></h2> <h2>Implementing a Foreign Method <a href="#implementing-a-foreign-method" name="implementing-a-foreign-method" class="header-anchor">#</a></h2>
<p>All C functions for foreign methods have the same signature: </p> <p>All C functions for foreign methods have the same signature:</p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">foreignMethod</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> void foreignMethod(WrenVM* vm);
</pre>
<p>Arguments passed from Wren are not passed as C arguments, and the method&rsquo;s
return value is not a C return value. Instead &ndash; you guessed it &ndash; we go through
the <a href="/embedding/slots-and-handles.html">slot array</a>.</p>
<p>When a foreign method is called from Wren, the VM sets up the slot array with
the receiver and arguments to the call. As in calling Wren from C, the receiver
object is in slot zero, and arguments are in consecutive slots after that.</p>
<p>You use the slot API to read those arguments, and then perform whatever work you
want to in C. If you want the foreign method to return a value, place it in slot
zero. Like so:</p>
<pre class="snippet" data-lang="c">
void mathAdd(WrenVM* vm)
{
double a = wrenGetSlotDouble(vm, 1);
double b = wrenGetSlotDouble(vm, 2);
wrenSetSlotDouble(vm, 0, a + b);
}
</pre>
<p>Arguments passed from Wren are not passed as C arguments, and the method&rsquo;s <p>While your foreign method is executing, the VM is completely suspended. No other
return value is not a C return value. Instead &ndash; you guessed it &ndash; we go through fibers run until your foreign method returns. You should <em>not</em> try to resume the
the <a href="/embedding/slots-and-handles.html">slot array</a>. </p> VM from within a foreign method by calling <code>wrenCall()</code> or <code>wrenInterpret()</code>.
<p>When a foreign method is called from Wren, the VM sets up the slot array with The VM is not re-entrant.</p>
the receiver and arguments to the call. As in calling Wren from C, the receiver <p>This covers foreign behavior, but what about foreign <em>state</em>? For that, we need
object is in slot zero, and arguments are in consecutive slots after that. </p> a foreign <em>class</em>&hellip;</p>
<p>You use the slot API to read those arguments, and then perform whatever work you <p><a class="right" href="storing-c-data.html">Storing C Data &rarr;</a>
want to in C. If you want the foreign method to return a value, place it in slot <a href="calling-wren-from-c.html">&larr; Calling Wren from C</a></p>
zero. Like so: </p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">mathAdd</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">double</span> <span class="n">a</span> <span class="o">=</span> <span class="n">wrenGetSlotDouble</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="kt">double</span> <span class="n">b</span> <span class="o">=</span> <span class="n">wrenGetSlotDouble</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
<span class="n">wrenSetSlotDouble</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>While your foreign method is executing, the VM is completely suspended. No other
fibers run until your foreign method returns. You should <em>not</em> try to resume the
VM from within a foreign method by calling <code>wrenCall()</code> or <code>wrenInterpret()</code>.
The VM is not re-entrant. </p>
<p>This covers foreign behavior, but what about foreign <em>state</em>? For that, we need
a foreign <em>class</em>&hellip; </p>
<p><a class="right" href="storing-c-data.html">Storing C Data &rarr;</a>
<a href="calling-wren-from-c.html">&larr; Calling Wren from C</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Calling Wren from C &ndash; Wren</title> <title>Calling Wren from C &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,6 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section> <section>
<h2>embedding</h2> <h2>embedding</h2>
<ul> <ul>
@ -63,155 +70,155 @@
</nav> </nav>
<main> <main>
<h1>Calling Wren from C</h1> <h1>Calling Wren from C</h1>
<p>From C, we can tell Wren to do stuff by calling <code>wrenInterpret()</code>, but that&rsquo;s <p>From C, we can tell Wren to do stuff by calling <code>wrenInterpret()</code>, but that&rsquo;s
not always the ideal way to drive the VM. First of all, it&rsquo;s slow. It has to not always the ideal way to drive the VM. First of all, it&rsquo;s slow. It has to
parse and compile the string of source code you give it. Wren has a pretty fast parse and compile the string of source code you give it. Wren has a pretty fast
compiler, but that&rsquo;s still a good bit of work. </p> compiler, but that&rsquo;s still a good bit of work.</p>
<p>It&rsquo;s also not an effective way to communicate. You can&rsquo;t pass arguments to <p>It&rsquo;s also not an effective way to communicate. You can&rsquo;t pass arguments to
Wren&mdash;at least, not without doing something nasty like converting them to Wren&mdash;at least, not without doing something nasty like converting them to
literals in a string of source code&mdash;and you can&rsquo;t get a result value back. </p> literals in a string of source code&mdash;and you can&rsquo;t get a result value back.</p>
<p><code>wrenInterpret()</code> is great for loading code into the VM, but it&rsquo;s not the best <p><code>wrenInterpret()</code> is great for loading code into the VM, but it&rsquo;s not the best
way to execute code that&rsquo;s already been loaded. What we want to do is invoke way to execute code that&rsquo;s already been loaded. What we want to do is invoke
some already compiled chunk of code. Since Wren is an object-oriented language, some already compiled chunk of code. Since Wren is an object-oriented language,
&ldquo;chunk of code&rdquo; means a <a href="../method-calls.html">method</a>, not a <a href="../functions.html">function</a>. </p> &ldquo;chunk of code&rdquo; means a <a href="../method-calls.html">method</a>, not a <a href="../functions.html">function</a>.</p>
<p>The C API for doing this is <code>wrenCall()</code>. In order to invoke a Wren method from <p>The C API for doing this is <code>wrenCall()</code>. In order to invoke a Wren method from
C, we need a few things: </p> C, we need a few things:</p>
<ul> <ul>
<li> <li>
<p><strong>The method to call.</strong> Wren is dynamically typed, so this means we&rsquo;ll look it <p><strong>The method to call.</strong> Wren is dynamically typed, so this means we&rsquo;ll look it
up by name. Further, since Wren supports overloading by arity, we actually up by name. Further, since Wren supports overloading by arity, we actually
need its entire <a href="../method-calls.html#signature">signature</a>. </p> need its entire <a href="../method-calls.html#signature">signature</a>.</p>
</li> </li>
<li> <li>
<p><strong>The receiver object to invoke the method on.</strong> The receiver&rsquo;s class <p><strong>The receiver object to invoke the method on.</strong> The receiver&rsquo;s class
determines which method is actually called. </p> determines which method is actually called.</p>
</li> </li>
<li> <li>
<p><strong>The arguments to pass to the method.</strong> </p> <p><strong>The arguments to pass to the method.</strong></p>
</li> </li>
</ul> </ul>
<p>We&rsquo;ll tackle these one at a time. </p> <p>We&rsquo;ll tackle these one at a time.</p>
<h3>Getting a Method Handle <a href="#getting-a-method-handle" name="getting-a-method-handle" class="header-anchor">#</a></h3> <h3>Getting a Method Handle <a href="#getting-a-method-handle" name="getting-a-method-handle" class="header-anchor">#</a></h3>
<p>When you run a chunk of Wren code like this: </p> <p>When you run a chunk of Wren code like this:</p>
<div class="codehilite"><pre><span class="n">object</span><span class="o">.</span><span class="n">someMethod</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <pre class="snippet">
</pre></div> object.someMethod(1, 2, 3)
</pre>
<p>At runtime, the VM has to look up the class of <code>object</code> and find a method there
whose signature is <code>someMethod(_,_,_)</code>. This sounds like it&rsquo;s doing some string
manipulation&mdash;at the very least hashing the signature&mdash;every time a
method is called. That&rsquo;s how many dynamic languages work.</p>
<p>But, as you can imagine, that&rsquo;s pretty slow. So, instead, Wren does as much of
that work at compile time as it can. When it&rsquo;s compiling the above code to
bytecode, it takes that method signature a converts it to a <em>method symbol</em>, a
number that uniquely identifes that method. That&rsquo;s the only part of the process
that requires treating a signature as a string.</p>
<p>At runtime, the VM just looks for the method <em>symbol</em> in the receiver&rsquo;s class&rsquo;s
method table. In fact, the way it&rsquo;s implemented today, the symbol is simply the
array index into the table. That&rsquo;s <a href="../performance.html">why method calls are so fast</a> in Wren.</p>
<p>It would be a shame if calling a method from C didn&rsquo;t have that same speed
benefit. To achieve that, we split the process of calling a method into two
steps. First, we create a handle that represents a &ldquo;compiled&rdquo; method signature:</p>
<pre class="snippet" data-lang="c">
WrenHandle* wrenMakeCallHandle(WrenVM* vm, const char* signature);
</pre>
<p>At runtime, the VM has to look up the class of <code>object</code> and find a method there <p>That takes a method signature as a string and gives you back an opaque handle
whose signature is <code>someMethod(_,_,_)</code>. This sounds like it&rsquo;s doing some string that represents the compiled method symbol. Now you have a <em>reusable</em> handle
manipulation&mdash;at the very least hashing the signature&mdash;every time a that can be used to very quickly call a certain method given a receiver and some
method is called. That&rsquo;s how many dynamic languages work. </p> arguments.</p>
<p>But, as you can imagine, that&rsquo;s pretty slow. So, instead, Wren does as much of <p>This is just a regular WrenHandle, which means you can hold onto it as long as
that work at compile time as it can. When it&rsquo;s compiling the above code to you like. Typically, you&rsquo;d call this once outside of your application&rsquo;s
bytecode, it takes that method signature a converts it to a <em>method symbol</em>, a performance critical loops and reuse it as long as you need. It is us up to you
number that uniquely identifes that method. That&rsquo;s the only part of the process to release it when you no longer need it by calling <code>wrenReleaseHandle()</code>.</p>
that requires treating a signature as a string. </p>
<p>At runtime, the VM just looks for the method <em>symbol</em> in the receiver&rsquo;s class&rsquo;s
method table. In fact, the way it&rsquo;s implemented today, the symbol is simply the
array index into the table. That&rsquo;s <a href="../performance.html">why method calls are so fast</a> in Wren. </p>
<p>It would be a shame if calling a method from C didn&rsquo;t have that same speed
benefit. To achieve that, we split the process of calling a method into two
steps. First, we create a handle that represents a &ldquo;compiled&rdquo; method signature: </p>
<div class="codehilite"><pre><span class="n">WrenHandle</span><span class="o">*</span> <span class="nf">wrenMakeCallHandle</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">signature</span><span class="p">);</span>
</pre></div>
<p>That takes a method signature as a string and gives you back an opaque handle
that represents the compiled method symbol. Now you have a <em>reusable</em> handle
that can be used to very quickly call a certain method given a receiver and some
arguments. </p>
<p>This is just a regular WrenHandle, which means you can hold onto it as long as
you like. Typically, you&rsquo;d call this once outside of your application&rsquo;s
performance critical loops and reuse it as long as you need. It is us up to you
to release it when you no longer need it by calling <code>wrenReleaseHandle()</code>. </p>
<h2>Setting Up a Receiver <a href="#setting-up-a-receiver" name="setting-up-a-receiver" class="header-anchor">#</a></h2> <h2>Setting Up a Receiver <a href="#setting-up-a-receiver" name="setting-up-a-receiver" class="header-anchor">#</a></h2>
<p>OK, we have a method, but who are we calling it on? We need a receiver, and as <p>OK, we have a method, but who are we calling it on? We need a receiver, and as
you can probably guess after reading the <a href="slots-and-handles.html">last section</a>, we give that to Wren you can probably guess after reading the <a href="slots-and-handles.html">last section</a>, we give that to Wren
by storing it in a slot. In particular, <strong>the receiver for a method call goes in by storing it in a slot. In particular, <strong>the receiver for a method call goes in
slot zero.</strong> </p> slot zero.</strong></p>
<p>Any object you store in that slot can be used as a receiver. You could even call <p>Any object you store in that slot can be used as a receiver. You could even call
<code>+</code> on a number by storing a number in there if you felt like it. </p> <code>+</code> on a number by storing a number in there if you felt like it.</p>
<p>Needing a receiver to call some Wren code from C might feel strange. C is <p>Needing a receiver to call some Wren code from C might feel strange. C is
procedural, so it&rsquo;s natural to want to just invoke a bare <em>function</em> from Wren, procedural, so it&rsquo;s natural to want to just invoke a bare <em>function</em> from Wren,
but Wren isn&rsquo;t procedural. Instead, if you want to define some executable but Wren isn&rsquo;t procedural. Instead, if you want to define some executable
operation that isn&rsquo;t logically tied to a specific object, the natural way is to operation that isn&rsquo;t logically tied to a specific object, the natural way is to
define a static method on an appropriate class. </p> define a static method on an appropriate class.</p>
<p>For example, say we&rsquo;re making a game engine. From C, we want to tell the game <p>For example, say we&rsquo;re making a game engine. From C, we want to tell the game
engine to update all of the entities each frame. We&rsquo;ll keep track of the list of engine to update all of the entities each frame. We&rsquo;ll keep track of the list of
entities within Wren, so from C, there&rsquo;s no obvious object to call <code>update(_)</code> entities within Wren, so from C, there&rsquo;s no obvious object to call <code>update(_)</code>
on. Instead, we&rsquo;ll just make it a static method: </p> on. Instead, we&rsquo;ll just make it a static method:</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">GameEngine</span> <span class="p">{</span> <pre class="snippet">
<span class="k">static</span> <span class="n">update</span><span class="p">(</span><span class="n">elapsedTime</span><span class="p">)</span> <span class="p">{</span> class GameEngine {
<span class="c1">// ...</span> static update(elapsedTime) {
<span class="p">}</span> // ...
<span class="p">}</span> }
</pre></div> }
</pre>
<p>Often, when you call a Wren method from C, you&rsquo;ll be calling a static method.
But, even then, you need a receiver. Now, though, the receiver is the <em>class
itself</em>. Classes are first class objects in Wren, and when you define a named
class, you&rsquo;re really declaring a variable with the class&rsquo;s name and storing a
reference to the class object in it.</p>
<p>Assuming you declared that class at the top level, the C API <a href="slots-and-handles.html#looking-up-variables">gives you a way to
look it up</a>. We can get a handle to the above class like so:</p>
<pre class="snippet" data-lang="c">
// Load the class into slot 0.
wrenEnsureSlots(vm, 1);
wrenGetVariable(vm, "main", "GameEngine", 0);
</pre>
<p>Often, when you call a Wren method from C, you&rsquo;ll be calling a static method. <p>We could do this every time we call <code>update()</code>, but, again, that&rsquo;s kind of slow
But, even then, you need a receiver. Now, though, the receiver is the <em>class because we&rsquo;re looking up &ldquo;GameEngine&rdquo; by name each time. A faster solution is to
itself</em>. Classes are first class objects in Wren, and when you define a named create a handle to the class once and use it each time:</p>
class, you&rsquo;re really declaring a variable with the class&rsquo;s name and storing a <pre class="snippet" data-lang="c">
reference to the class object in it. </p> // Load the class into slot 0.
<p>Assuming you declared that class at the top level, the C API <a href="slots-and-handles.html#looking-up-variables">gives you a way to wrenEnsureSlots(vm, 1);
look it up</a>. We can get a handle to the above class like so: </p> wrenGetVariable(vm, "main", "GameEngine", 0);
<div class="codehilite"><pre><span class="c1">// Load the class into slot 0.</span> WrenHandle* gameEngineClass = wrenGetSlotHandle(vm, 0);
<span class="n">wrenEnsureSlots</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> </pre>
<span class="n">wrenGetVariable</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="s">&quot;main&quot;</span><span class="p">,</span> <span class="s">&quot;GameEngine&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</pre></div>
<p>Now, each time we want to call a method on GameEngine, we store that value back
in slot zero:</p>
<pre class="snippet" data-lang="c">
wrenSetSlotHandle(vm, 0, gameEngineClass);
</pre>
<p>We could do this every time we call <code>update()</code>, but, again, that&rsquo;s kind of slow <p>Just like we hoisted <code>wrenMakeCallHandle()</code> out of our performance critical
because we&rsquo;re looking up &ldquo;GameEngine&rdquo; by name each time. A faster solution is to loop, we can hoist the call to <code>wrenGetVariable()</code> out. Of course, if your code
create a handle to the class once and use it each time: </p> isn&rsquo;t performance critical, you don&rsquo;t have to do this.</p>
<div class="codehilite"><pre><span class="c1">// Load the class into slot 0.</span>
<span class="n">wrenEnsureSlots</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">wrenGetVariable</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="s">&quot;main&quot;</span><span class="p">,</span> <span class="s">&quot;GameEngine&quot;</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">WrenHandle</span><span class="o">*</span> <span class="n">gameEngineClass</span> <span class="o">=</span> <span class="n">wrenGetSlotHandle</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
</pre></div>
<p>Now, each time we want to call a method on GameEngine, we store that value back
in slot zero: </p>
<div class="codehilite"><pre><span class="n">wrenSetSlotHandle</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">gameEngineClass</span><span class="p">);</span>
</pre></div>
<p>Just like we hoisted <code>wrenMakeCallHandle()</code> out of our performance critical
loop, we can hoist the call to <code>wrenGetVariable()</code> out. Of course, if your code
isn&rsquo;t performance critical, you don&rsquo;t have to do this. </p>
<h2>Passing Arguments <a href="#passing-arguments" name="passing-arguments" class="header-anchor">#</a></h2> <h2>Passing Arguments <a href="#passing-arguments" name="passing-arguments" class="header-anchor">#</a></h2>
<p>We&rsquo;ve got a receiver in slot zero now, next we need to pass in any other <p>We&rsquo;ve got a receiver in slot zero now, next we need to pass in any other
arguments. In our GameEngine example, that&rsquo;s just the elapsed time. Method arguments. In our GameEngine example, that&rsquo;s just the elapsed time. Method
arguments go in consecutive slots after the receiver. So the elapsed time goes arguments go in consecutive slots after the receiver. So the elapsed time goes
into slot one. You can use any of the slot functions to set this up. For the into slot one. You can use any of the slot functions to set this up. For the
example, it&rsquo;s just: </p> example, it&rsquo;s just:</p>
<div class="codehilite"><pre><span class="n">wrenSetSlotDouble</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">elapsedTime</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> wrenSetSlotDouble(vm, 1, elapsedTime);
</pre>
<h2>Calling the Method <a href="#calling-the-method" name="calling-the-method" class="header-anchor">#</a></h2> <h2>Calling the Method <a href="#calling-the-method" name="calling-the-method" class="header-anchor">#</a></h2>
<p>We have all of the data in place, so all that&rsquo;s left is to pull the trigger and <p>We have all of the data in place, so all that&rsquo;s left is to pull the trigger and
tell the VM to start running some code: </p> tell the VM to start running some code:</p>
<div class="codehilite"><pre><span class="n">WrenInterpretResult</span> <span class="nf">wrenCall</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="n">WrenHandle</span><span class="o">*</span> <span class="n">method</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> WrenInterpretResult wrenCall(WrenVM* vm, WrenHandle* method);
</pre>
<p>It takes the method handle we created using <code>wrenMakeCallHandle()</code>. Now Wren
<p>It takes the method handle we created using <code>wrenMakeCallHandle()</code>. Now Wren starts running code. It looks up the method on the receiver, executes it and
starts running code. It looks up the method on the receiver, executes it and keeps running until either the method returns or a fiber <a href="../modules/core/fiber.html#fiber.suspend()">suspends</a>.</p>
keeps running until either the method returns or a fiber <a href="../modules/core/fiber.html#fiber.suspend()">suspends</a>. </p> <p><code>wrenCall()</code> returns the same WrenInterpretResult enum as <code>wrenInterpret()</code> to
<p><code>wrenCall()</code> returns the same WrenInterpretResult enum as <code>wrenInterpret()</code> to tell you if the method completed successfully or a runtime error occurred.
tell you if the method completed successfully or a runtime error occurred. (<code>wrenCall()</code> never returns <code>WREN_ERROR_COMPILE</code> since it doesn&rsquo;t compile
(<code>wrenCall()</code> never returns <code>WREN_ERROR_COMPILE</code> since it doesn&rsquo;t compile anything.)</p>
anything.) </p>
<h2>Getting the Return Value <a href="#getting-the-return-value" name="getting-the-return-value" class="header-anchor">#</a></h2> <h2>Getting the Return Value <a href="#getting-the-return-value" name="getting-the-return-value" class="header-anchor">#</a></h2>
<p>When <code>wrenCall()</code> returns, it leaves the slot array in place. In slot zero, you <p>When <code>wrenCall()</code> returns, it leaves the slot array in place. In slot zero, you
can find the method&rsquo;s return value, which you can access using any of the slot can find the method&rsquo;s return value, which you can access using any of the slot
reading functions. If you don&rsquo;t need the return value, you can ignore it. </p> reading functions. If you don&rsquo;t need the return value, you can ignore it.</p>
<p>This is how you drive Wren from C, but how do you put control in Wren&rsquo;s hands? <p>This is how you drive Wren from C, but how do you put control in Wren&rsquo;s hands?
For that, you&rsquo;ll need the next section&hellip; </p> For that, you&rsquo;ll need the next section&hellip;</p>
<p><a class="right" href="calling-c-from-wren.html">Calling C From Wren &rarr;</a> <p><a class="right" href="calling-c-from-wren.html">Calling C From Wren &rarr;</a>
<a href="slots-and-handles.html">&larr; Slots and Handles</a> </p> <a href="slots-and-handles.html">&larr; Slots and Handles</a></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Configuring the VM &ndash; Wren</title> <title>Configuring the VM &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,6 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section> <section>
<h2>embedding</h2> <h2>embedding</h2>
<ul> <ul>
@ -63,160 +70,160 @@
</nav> </nav>
<main> <main>
<h1>Configuring the VM</h1> <h1>Configuring the VM</h1>
<p>When you create a Wren VM, you tweak it by passing in a pointer to a <p>When you create a Wren VM, you tweak it by passing in a pointer to a
WrenConfiguration structure. Since Wren has no global state, you can configure WrenConfiguration structure. Since Wren has no global state, you can configure
each VM differently if your application happens to run multiple. </p> each VM differently if your application happens to run multiple.</p>
<p>The struct looks like: </p> <p>The struct looks like:</p>
<div class="codehilite"><pre><span class="k">typedef</span> <span class="k">struct</span> <pre class="snippet" data-lang="c">
<span class="p">{</span> typedef struct
<span class="n">WrenReallocateFn</span> <span class="n">reallocateFn</span><span class="p">;</span> {
<span class="n">WrenLoadModuleFn</span> <span class="n">loadModuleFn</span><span class="p">;</span> WrenReallocateFn reallocateFn;
<span class="n">WrenBindForeignMethodFn</span> <span class="n">bindForeignMethodFn</span><span class="p">;</span> WrenLoadModuleFn loadModuleFn;
<span class="n">WrenBindForeignClassFn</span> <span class="n">bindForeignClassFn</span><span class="p">;</span> WrenBindForeignMethodFn bindForeignMethodFn;
<span class="n">WrenWriteFn</span> <span class="n">writeFn</span><span class="p">;</span> WrenBindForeignClassFn bindForeignClassFn;
<span class="n">WrenErrorFn</span> <span class="n">errorFn</span><span class="p">;</span> WrenWriteFn writeFn;
<span class="kt">size_t</span> <span class="n">initialHeapSize</span><span class="p">;</span> WrenErrorFn errorFn;
<span class="kt">size_t</span> <span class="n">minHeapSize</span><span class="p">;</span> size_t initialHeapSize;
<span class="kt">int</span> <span class="n">heapGrowthPercent</span><span class="p">;</span> size_t minHeapSize;
<span class="p">}</span> <span class="n">WrenConfiguration</span><span class="p">;</span> int heapGrowthPercent;
</pre></div> } WrenConfiguration;
</pre>
<p>Most fields have useful defaults, which you can (and should) initialize by
calling:</p>
<pre class="snippet" data-lang="c">
wrenInitConfiguration(&configuration);
</pre>
<p>Most fields have useful defaults, which you can (and should) initialize by <p>Calling this ensures that your VM doesn&rsquo;t get uninitialized configuration when
calling: </p> new fields are added to WrenConfiguration. Here is what each field does, roughly
<div class="codehilite"><pre><span class="n">wrenInitConfiguration</span><span class="p">(</span><span class="o">&amp;</span><span class="n">configuration</span><span class="p">);</span> categorized:</p>
</pre></div>
<p>Calling this ensures that your VM doesn&rsquo;t get uninitialized configuration when
new fields are added to WrenConfiguration. Here is what each field does, roughly
categorized: </p>
<h2>Binding <a href="#binding" name="binding" class="header-anchor">#</a></h2> <h2>Binding <a href="#binding" name="binding" class="header-anchor">#</a></h2>
<p>The VM is isolated from the outside world. These callbacks let the VM request <p>The VM is isolated from the outside world. These callbacks let the VM request
access to imported code and foreign functionality. </p> access to imported code and foreign functionality.</p>
<h3><code>loadModuleFn</code> <a href="#loadmodulefn" name="loadmodulefn" class="header-anchor">#</a></h3> <h3><strong><code>loadModuleFn</code></strong> <a href="#loadmodulefn" name="loadmodulefn" class="header-anchor">#</a></h3>
<p>This is the callback Wren uses to load an imported module. The VM itself does <p>This is the callback Wren uses to load an imported module. The VM itself does
not know how to talk to the file system, so when an <code>import</code> statement is not know how to talk to the file system, so when an <code>import</code> statement is
executed, it relies on the host application to locate and read the source code executed, it relies on the host application to locate and read the source code
for a module. </p> for a module.</p>
<p>The signature of this function is: </p> <p>The signature of this function is:</p>
<div class="codehilite"><pre><span class="kt">char</span><span class="o">*</span> <span class="n">loadModule</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">)</span> <pre class="snippet" data-lang="c">
</pre></div> char* loadModule(WrenVM* vm, const char* name)
</pre>
<p>When a module is imported, Wren calls this and passes in the module&rsquo;s name. The
<p>When a module is imported, Wren calls this and passes in the module&rsquo;s name. The host should return the source code for that module. Memory for the source should
host should return the source code for that module. Memory for the source should be allocated using the same allocator that the VM uses for other allocation (see
be allocated using the same allocator that the VM uses for other allocation (see below). Wren will take ownership of the returned string and free it later.</p>
below). Wren will take ownership of the returned string and free it later. </p> <p>The module loader is only be called once for any given module name. Wren caches
<p>The module loader is only be called once for any given module name. Wren caches the result internally so subsequent imports of the same module use the
the result internally so subsequent imports of the same module use the previously loaded code.</p>
previously loaded code. </p> <p>If your host application isn&rsquo;t able to load a module with some name, it should
<p>If your host application isn&rsquo;t able to load a module with some name, it should return <code>NULL</code> and Wren will report that as a runtime error.</p>
return <code>NULL</code> and Wren will report that as a runtime error. </p> <p>If you don&rsquo;t use any <code>import</code> statements, you can leave this <code>NULL</code>.</p>
<p>If you don&rsquo;t use any <code>import</code> statements, you can leave this <code>NULL</code>. </p> <h3><strong><code>bindForeignMethodFn</code></strong> <a href="#bindforeignmethodfn" name="bindforeignmethodfn" class="header-anchor">#</a></h3>
<h3><code>bindForeignMethodFn</code> <a href="#bindforeignmethodfn" name="bindforeignmethodfn" class="header-anchor">#</a></h3> <p>The callback Wren uses to find a foreign method and bind it to a class. See
<p>The callback Wren uses to find a foreign method and bind it to a class. See <a href="/embedding/calling-c-from-wren.html">this page</a> for details. If your application defines no foreign
<a href="/embedding/calling-c-from-wren.html">this page</a> for details. If your application defines no foreign methods, you can leave this <code>NULL</code>.</p>
methods, you can leave this <code>NULL</code>. </p> <h3><strong><code>bindForeignClassFn</code></strong> <a href="#bindforeignclassfn" name="bindforeignclassfn" class="header-anchor">#</a></h3>
<h3><code>bindForeignClassFn</code> <a href="#bindforeignclassfn" name="bindforeignclassfn" class="header-anchor">#</a></h3> <p>The callback Wren uses to find a foreign class and get its foreign methods. See
<p>The callback Wren uses to find a foreign class and get its foreign methods. See <a href="/embedding/storing-c-data.html">this page</a> for details. If your application defines no foreign
<a href="/embedding/storing-c-data.html">this page</a> for details. If your application defines no foreign classes, you can leave this <code>NULL</code>.</p>
classes, you can leave this <code>NULL</code>. </p>
<h2>Diagnostics <a href="#diagnostics" name="diagnostics" class="header-anchor">#</a></h2> <h2>Diagnostics <a href="#diagnostics" name="diagnostics" class="header-anchor">#</a></h2>
<p>These let you wire up some minimal output so you can tell if your code is doing <p>These let you wire up some minimal output so you can tell if your code is doing
what you expect. </p> what you expect.</p>
<h3><code>writeFn</code> <a href="#writefn" name="writefn" class="header-anchor">#</a></h3> <h3><strong><code>writeFn</code></strong> <a href="#writefn" name="writefn" class="header-anchor">#</a></h3>
<p>This is the callback Wren uses to output text when <code>System.print()</code> or the other <p>This is the callback Wren uses to output text when <code>System.print()</code> or the other
related functions are called. This is the minimal connection the VM has with the related functions are called. This is the minimal connection the VM has with the
outside world and lets you do rudimentary &ldquo;printf debugging&rdquo;. Its signature is: </p> outside world and lets you do rudimentary &ldquo;printf debugging&rdquo;. Its signature is:</p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="n">write</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">text</span><span class="p">)</span> <pre class="snippet" data-lang="c">
</pre></div> void write(WrenVM* vm, const char* text)
</pre>
<p>Wren does <em>not</em> have a default implementation for this. It&rsquo;s up to you to wire
it up to <code>printf()</code> or some other way to show the text. If you leave it <code>NULL</code>,
calls to <code>System.print()</code> and others silently do nothing.</p>
<h3><strong><code>errorFn</code></strong> <a href="#errorfn" name="errorfn" class="header-anchor">#</a></h3>
<p>Wren uses this callback to report compile time and runtime errors. Its signature
is:</p>
<pre class="snippet" data-lang="c">
void error(
WrenVM* vm,
WrenErrorType type,
const char* module,
int line,
const char* message)
</pre>
<p>Wren does <em>not</em> have a default implementation for this. It&rsquo;s up to you to wire <p>The <code>type</code> parameter is one of:</p>
it up to <code>printf()</code> or some other way to show the text. If you leave it <code>NULL</code>, <pre class="snippet" data-lang="c">
calls to <code>System.print()</code> and others silently do nothing. </p> typedef enum
<h3><code>errorFn</code> <a href="#errorfn" name="errorfn" class="header-anchor">#</a></h3> {
<p>Wren uses this callback to report compile time and runtime errors. Its signature // A syntax or resolution error detected at compile time.
is: </p> WREN_ERROR_COMPILE,
<div class="codehilite"><pre><span class="kt">void</span> <span class="n">error</span><span class="p">(</span>
<span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span>
<span class="n">WrenErrorType</span> <span class="n">type</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span>
<span class="kt">int</span> <span class="n">line</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">message</span><span class="p">)</span>
</pre></div>
// The error message for a runtime error.
WREN_ERROR_RUNTIME,
<p>The <code>type</code> parameter is one of: </p> // One entry of a runtime error's stack trace.
<div class="codehilite"><pre><span class="k">typedef</span> <span class="k">enum</span> WREN_ERROR_STACK_TRACE
<span class="p">{</span> } WrenErrorType;
<span class="c1">// A syntax or resolution error detected at compile time.</span> </pre>
<span class="n">WREN_ERROR_COMPILE</span><span class="p">,</span>
<span class="c1">// The error message for a runtime error.</span> <p>When a compile error occurs, <code>errorFn</code> is called once with type
<span class="n">WREN_ERROR_RUNTIME</span><span class="p">,</span> <code>WREN_ERROR_COMPILE</code>, the name of the module and line where the error occurs,
and the error message.</p>
<span class="c1">// One entry of a runtime error&#39;s stack trace.</span> <p>Runtime errors include stack traces. To handle this, Wren first calls <code>errorFn</code>
<span class="n">WREN_ERROR_STACK_TRACE</span> with <code>WREN_ERROR_RUNTIME</code>, no module or line, and the runtime error&rsquo;s message.
<span class="p">}</span> <span class="n">WrenErrorType</span><span class="p">;</span> After that, it calls <code>errorFn</code> again using type <code>WREN_ERROR_STACK_TRACE</code>, once
</pre></div> for each line in the stack trace. Each of those calls has the module and line
where the method or function is defined and <code>message</code> is the name of the method
or function.</p>
<p>When a compile error occurs, <code>errorFn</code> is called once with type <p>If you leave this <code>NULL</code>, Wren does not report any errors.</p>
<code>WREN_ERROR_COMPILE</code>, the name of the module and line where the error occurs,
and the error message. </p>
<p>Runtime errors include stack traces. To handle this, Wren first calls <code>errorFn</code>
with <code>WREN_ERROR_RUNTIME</code>, no module or line, and the runtime error&rsquo;s message.
After that, it calls <code>errorFn</code> again using type <code>WREN_ERROR_STACK_TRACE</code>, once
for each line in the stack trace. Each of those calls has the module and line
where the method or function is defined and <code>message</code> is the name of the method
or function. </p>
<p>If you leave this <code>NULL</code>, Wren does not report any errors. </p>
<h2>Memory Management <a href="#memory-management" name="memory-management" class="header-anchor">#</a></h2> <h2>Memory Management <a href="#memory-management" name="memory-management" class="header-anchor">#</a></h2>
<p>These fields control how the VM allocates and manages memory. </p> <p>These fields control how the VM allocates and manages memory.</p>
<h3><code>reallocateFn</code> <a href="#reallocatefn" name="reallocatefn" class="header-anchor">#</a></h3> <h3><strong><code>reallocateFn</code></strong> <a href="#reallocatefn" name="reallocatefn" class="header-anchor">#</a></h3>
<p>This lets you provide a custom memory allocation function. Its signature is: </p> <p>This lets you provide a custom memory allocation function. Its signature is:</p>
<div class="codehilite"><pre><span class="kt">void</span><span class="o">*</span> <span class="n">reallocate</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">memory</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">newSize</span><span class="p">)</span> <pre class="snippet" data-lang="c">
</pre></div> void* reallocate(void* memory, size_t newSize)
</pre>
<p>Wren uses this one function to allocate, grow, shrink, and deallocate memory.
<p>Wren uses this one function to allocate, grow, shrink, and deallocate memory. When called, <code>memory</code> is the existing pointer to the block of memory if an
When called, <code>memory</code> is the existing pointer to the block of memory if an allocation is being changed or freed. If Wren is requesting new memory, then
allocation is being changed or freed. If Wren is requesting new memory, then <code>memory</code> is <code>NULL</code>.</p>
<code>memory</code> is <code>NULL</code>. </p> <p><code>newSize</code> is the number of bytes of memory being requested. If memory is being
<p><code>newSize</code> is the number of bytes of memory being requested. If memory is being freed, this is zero. Your callback should allocate the proper amount of memory
freed, this is zero. Your callback should allocate the proper amount of memory and return it.</p>
and return it. </p> <p>If you don&rsquo;t provide a custom allocator, the VM uses a default one that relies
<p>If you don&rsquo;t provide a custom allocator, the VM uses a default one that relies on <code>realloc</code> and <code>free</code>.</p>
on <code>realloc</code> and <code>free</code>. </p> <h3><strong><code>initialHeapSize</code></strong> <a href="#initialheapsize" name="initialheapsize" class="header-anchor">#</a></h3>
<h3><code>initialHeapSize</code> <a href="#initialheapsize" name="initialheapsize" class="header-anchor">#</a></h3> <p>This defines the total number of bytes of memory the VM will allocate before
<p>This defines the total number of bytes of memory the VM will allocate before triggering the first garbage collection. Setting this to a smaller number
triggering the first garbage collection. Setting this to a smaller number reduces the amount of memory Wren will have allocated at one time, but causes it
reduces the amount of memory Wren will have allocated at one time, but causes it to collect garbage more frequently.</p>
to collect garbage more frequently. </p> <p>If you set this to zero, Wren uses a default size of 10MB.</p>
<p>If you set this to zero, Wren uses a default size of 10MB. </p> <h3><strong><code>minHeapSize</code></strong> <a href="#minheapsize" name="minheapsize" class="header-anchor">#</a></h3>
<h3><code>minHeapSize</code> <a href="#minheapsize" name="minheapsize" class="header-anchor">#</a></h3> <p>After a garbage collection occurs, the threshold for the <em>next</em> collection is
<p>After a garbage collection occurs, the threshold for the <em>next</em> collection is determined based on the number of bytes remaining in use. This allows Wren to
determined based on the number of bytes remaining in use. This allows Wren to grow or shrink its memory usage automatically based on how much memory is
grow or shrink its memory usage automatically based on how much memory is actually needed.</p>
actually needed. </p> <p>This can be used to ensure that the heap does not get <em>too</em> small, which can
<p>This can be used to ensure that the heap does not get <em>too</em> small, which can in turn lead to a large number of collections afterwards as the heap grows
in turn lead to a large number of collections afterwards as the heap grows back to a usable size.</p>
back to a usable size. </p> <p>If zero, this defaults to 1MB.</p>
<p>If zero, this defaults to 1MB. </p> <h3><strong><code>heapGrowthPercent</code></strong> <a href="#heapgrowthpercent" name="heapgrowthpercent" class="header-anchor">#</a></h3>
<h3><code>heapGrowthPercent</code> <a href="#heapgrowthpercent" name="heapgrowthpercent" class="header-anchor">#</a></h3> <p>Wren tunes the rate of garbage collection based on how much memory is still in
<p>Wren tunes the rate of garbage collection based on how much memory is still in use after a collection. This number controls that. It determines the amount of
use after a collection. This number controls that. It determines the amount of additional memory Wren will use after a collection, as a percentage of the
additional memory Wren will use after a collection, as a percentage of the current heap size.</p>
current heap size. </p> <p>For example, say that this is 50. After a garbage collection, there are 400
<p>For example, say that this is 50. After a garbage collection, there are 400 bytes of memory still in use. That means the next collection will be triggered
bytes of memory still in use. That means the next collection will be triggered after a total of 600 bytes are allocated (including the 400 already in use.)</p>
after a total of 600 bytes are allocated (including the 400 already in use.) </p> <p>Setting this to a smaller number wastes less memory, but triggers more
<p>Setting this to a smaller number wastes less memory, but triggers more frequent garbage collections.</p>
frequent garbage collections. </p> <p>If set to zero, the VM uses a default of 50.</p>
<p>If set to zero, the VM uses a default of 50. </p> <p><a href="storing-c-data.html">&larr; Storing C Data</a></p>
<p><a href="storing-c-data.html">&larr; Storing C Data</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Embedding &ndash; Wren</title> <title>Embedding &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,6 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section> <section>
<h2>embedding</h2> <h2>embedding</h2>
<ul> <ul>
@ -63,153 +70,150 @@
</nav> </nav>
<main> <main>
<h1>Embedding</h1> <h1>Embedding</h1>
<p>Wren is designed to be a scripting language that lives inside a host <p>Wren is designed to be a scripting language that lives inside a host
application, so the embedding API is as important as any of its language application, so the embedding API is as important as any of its language
features. Designing this API well requires satisfying several constraints: </p> features. Designing this API well requires satisfying several constraints:</p>
<ol> <ol>
<li> <li>
<p><strong>Wren is dynamically typed, but C is not.</strong> A variable can hold a value of <p><strong>Wren is dynamically typed, but C is not.</strong> A variable can hold a value of
any type in Wren, but that&rsquo;s definitely not the case in C unless you define any type in Wren, but that&rsquo;s definitely not the case in C unless you define
some sort of variant type, which ultimately just kicks the problem down the some sort of variant type, which ultimately just kicks the problem down the
road. Eventually, we have to move data across the boundary between statically and dynamically typed code. </p> road. Eventually, we have to move data across the boundary between statically and dynamically typed code.</p>
</li> </li>
<li> <li>
<p><strong>Wren uses garbage collection, but C manages memory manually.</strong> GC adds a <p><strong>Wren uses garbage collection, but C manages memory manually.</strong> GC adds a
few constraints on the API. The VM must be able to find every Wren object few constraints on the API. The VM must be able to find every Wren object
that is still usable, even if that object is being referenced from native C that is still usable, even if that object is being referenced from native C
code. Otherwise, Wren could free an object that&rsquo;s still in use. </p> code. Otherwise, Wren could free an object that&rsquo;s still in use.</p>
<p>Also, we ideally don&rsquo;t want to let native C code see a bare pointer to a <p>Also, we ideally don&rsquo;t want to let native C code see a bare pointer to a
chunk of memory managed by Wren. Many garbage collection strategies involve chunk of memory managed by Wren. Many garbage collection strategies involve
<a href="https://en.wikipedia.org/wiki/Tracing_garbage_collection#Copying_vs._mark-and-sweep_vs._mark-and-don.27t-sweep">moving objects</a> in memory. If we allow C code to point directly to an <a href="https://en.wikipedia.org/wiki/Tracing_garbage_collection#Copying_vs._mark-and-sweep_vs._mark-and-don.27t-sweep">moving objects</a> in memory. If we allow C code to point directly to an
object, that pointer will be left dangling when the object moves. Wren&rsquo;s GC object, that pointer will be left dangling when the object moves. Wren&rsquo;s GC
doesn&rsquo;t move objects today, but we would like to keep that option for the doesn&rsquo;t move objects today, but we would like to keep that option for the
future. </p> future.</p>
</li> </li>
<li> <li>
<p><strong>The embedding API needs to be fast.</strong> Users may add layers of abstraction <p><strong>The embedding API needs to be fast.</strong> Users may add layers of abstraction
on top of the API to make it more pleasant to work with, but the base API on top of the API to make it more pleasant to work with, but the base API
defines the <em>maximum</em> performance you can get out of the system. It&rsquo;s the defines the <em>maximum</em> performance you can get out of the system. It&rsquo;s the
bottom of the stack, so there&rsquo;s no way for a user to optimize around it if bottom of the stack, so there&rsquo;s no way for a user to optimize around it if
it&rsquo;s too slow. There is no lower level alternative. </p> it&rsquo;s too slow. There is no lower level alternative.</p>
</li> </li>
<li> <li>
<p><strong>We want the API to be pleasant to use.</strong> This is the last constraint <p><strong>We want the API to be pleasant to use.</strong> This is the last constraint
because it&rsquo;s the softest. Of course, we want a beautiful, usable API. But we because it&rsquo;s the softest. Of course, we want a beautiful, usable API. But we
really <em>need</em> to handle the above, so we&rsquo;re willing to make things a bit more really <em>need</em> to handle the above, so we&rsquo;re willing to make things a bit more
of a chore to reach the first three goals. </p> of a chore to reach the first three goals.</p>
</li> </li>
</ol> </ol>
<p>Fortunately, we aren&rsquo;t the first people to tackle this. If you&rsquo;re familiar with <p>Fortunately, we aren&rsquo;t the first people to tackle this. If you&rsquo;re familiar with
<a href="https://www.lua.org/pil/24.html">Lua&rsquo;s C API</a>, you&rsquo;ll find Wren&rsquo;s similar. </p> <a href="https://www.lua.org/pil/24.html">Lua&rsquo;s C API</a>, you&rsquo;ll find Wren&rsquo;s similar.</p>
<h3>Performance and safety <a href="#performance-and-safety" name="performance-and-safety" class="header-anchor">#</a></h3> <h3>Performance and safety <a href="#performance-and-safety" name="performance-and-safety" class="header-anchor">#</a></h3>
<p>When code is safely snuggled within the confines of the VM, it&rsquo;s pretty safe. <p>When code is safely snuggled within the confines of the VM, it&rsquo;s pretty safe.
Method calls are dynamically checked and generate runtime errors which can be Method calls are dynamically checked and generate runtime errors which can be
caught and handled. The stack grows if it gets close to overflowing. In general, caught and handled. The stack grows if it gets close to overflowing. In general,
when you&rsquo;re within Wren code, it tries very hard to avoid crashing and burning. </p> when you&rsquo;re within Wren code, it tries very hard to avoid crashing and burning.</p>
<p>This is why you use a high level language after all&mdash;it&rsquo;s safer and more <p>This is why you use a high level language after all&mdash;it&rsquo;s safer and more
productive than C. C, meanwhile, really assumes you know what you&rsquo;re doing. You productive than C. C, meanwhile, really assumes you know what you&rsquo;re doing. You
can cast pointers in invalid ways, misinterpret bits, use memory after freeing can cast pointers in invalid ways, misinterpret bits, use memory after freeing
it, etc. What you get in return is blazing performance. Many of the reasons C is it, etc. What you get in return is blazing performance. Many of the reasons C is
fast are because it takes all the governors and guardrails off. </p> fast are because it takes all the governors and guardrails off.</p>
<p>Wren&rsquo;s embedding API defines the border between those worlds, and takes on some <p>Wren&rsquo;s embedding API defines the border between those worlds, and takes on some
of the characteristics of C. When you call any of the embedding API functions, of the characteristics of C. When you call any of the embedding API functions,
it assumes you are calling them correctly. If you invoke a Wren method from C it assumes you are calling them correctly. If you invoke a Wren method from C
that expects three arguments, it trusts that you gave it three arguments. </p> that expects three arguments, it trusts that you gave it three arguments.</p>
<p>In debug builds, Wren has assertions to check as many things as it can, but in <p>In debug builds, Wren has assertions to check as many things as it can, but in
release builds, Wren expects you to do the right thing. This means you need to release builds, Wren expects you to do the right thing. This means you need to
take care when using the embedding API, just like you do in all C code you take care when using the embedding API, just like you do in all C code you
write. In return, you get an API that is quite fast. </p> write. In return, you get an API that is quite fast.</p>
<h2>Including Wren <a href="#including-wren" name="including-wren" class="header-anchor">#</a></h2> <h2>Including Wren <a href="#including-wren" name="including-wren" class="header-anchor">#</a></h2>
<p>There are two (well, three) ways to get the Wren VM into your program: </p> <p>There are two (well, three) ways to get the Wren VM into your program:</p>
<ol> <ol>
<li> <li>
<p><strong>Link to the static or dynamic library.</strong> When you <a href="../getting-started.html">build Wren</a>, it <p><strong>Link to the static or dynamic library.</strong> When you <a href="../getting-started.html">build Wren</a>, it
generates both shared and static libraries in <code>lib</code> that you can link to. </p> generates both shared and static libraries in <code>lib</code> that you can link to.</p>
</li> </li>
<li> <li>
<p><strong>Include the source directly in your application.</strong> If you want to include <p><strong>Include the source directly in your application.</strong> If you want to include
the source directly in your program, you don&rsquo;t need to run any build steps. the source directly in your program, you don&rsquo;t need to run any build steps.
Just add the source files in <code>src/vm</code> to your project. They should compile Just add the source files in <code>src/vm</code> to your project. They should compile
cleanly as C99 or C++98 or anything later. </p> cleanly as C99 or C++98 or anything later.</p>
</li> </li>
</ol> </ol>
<p>In either case, you also want to add <code>src/include</code> to your include path so you <p>In either case, you also want to add <code>src/include</code> to your include path so you
can find the <a href="https://github.com/wren-lang/wren/blob/master/src/include/wren.h">public header for Wren</a>: </p> can find the <a href="https://github.com/wren-lang/wren/blob/master/src/include/wren.h">public header for Wren</a>:</p>
<div class="codehilite"><pre><span class="cp">#include &quot;wren.h&quot;</span> <pre class="snippet" data-lang="c">
</pre></div> #include "wren.h"
</pre>
<p>Wren depends only on the C standard library, so you don&rsquo;t usually need to link
to anything else. On some platforms (at least BSD and Linux) some of the math
functions in <code>math.h</code> are implemented in a separate library, <a href="https://en.wikipedia.org/wiki/C_mathematical_functions#libm">libm</a>, that you
have to explicitly link to. </p>
<p>If your program is in C++ but you are linking to the Wren library compiled as C,
this header handles the differences in calling conventions between C and C++: </p>
<div class="codehilite"><pre><span class="cp">#include &quot;wren.hpp&quot;</span>
</pre></div>
<p>Wren depends only on the C standard library, so you don&rsquo;t usually need to link
to anything else. On some platforms (at least BSD and Linux) some of the math
functions in <code>math.h</code> are implemented in a separate library, <a href="https://en.wikipedia.org/wiki/C_mathematical_functions#libm">libm</a>, that you
have to explicitly link to.</p>
<p>If your program is in C++ but you are linking to the Wren library compiled as C,
this header handles the differences in calling conventions between C and C++:</p>
<pre class="snippet" data-lang="c">
#include "wren.hpp"
</pre>
<h2>Creating a Wren VM <a href="#creating-a-wren-vm" name="creating-a-wren-vm" class="header-anchor">#</a></h2> <h2>Creating a Wren VM <a href="#creating-a-wren-vm" name="creating-a-wren-vm" class="header-anchor">#</a></h2>
<p>Once you&rsquo;ve integrated the code into your executable, you need to create a <p>Once you&rsquo;ve integrated the code into your executable, you need to create a
virtual machine. To do that, you create a WrenConfiguration: </p> virtual machine. To do that, you create a
<div class="codehilite"><pre><span class="n">WrenConfiguration</span> <span class="n">config</span><span class="p">;</span> WrenConfiguration config;
<span class="n">wrenInitConfiguration</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> wrenInitConfiguration(&amp;config);</p>
</pre></div> <p>This gives you a basic configuration that has reasonable defaults for
everything. If you don&rsquo;t need to tweak stuff, you can leave it at that. We&rsquo;ll
<a href="configuring-the-vm.html">learn more</a> about what you can configure later.</p>
<p>With this ready, you can create the VM:</p>
<pre class="snippet" data-lang="c">
WrenVM* vm = wrenNewVM(&config);
</pre>
<p>This allocates memory for a new VM and initializes it. The Wren C implementation
<p>This gives you a basic configuration that has reasonable defaults for has no global state, so every single bit of data Wren uses is bundled up inside
everything. If you don&rsquo;t need to tweak stuff, you can leave it at that. We&rsquo;ll a WrenVM. You can have multiple Wren VMs running independently of each other
<a href="configuring-the-vm.html">learn more</a> about what you can configure later. </p> without any problems, even concurrently on different threads.</p>
<p>With this ready, you can create the VM: </p> <p><code>wrenNewVM()</code> stores its own copy of the configuration, so after calling it, you
<div class="codehilite"><pre><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span> <span class="o">=</span> <span class="n">wrenNewVM</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> can discard the WrenConfiguration struct you filled in. Now you have a live
</pre></div> VM, waiting to run some code!</p>
<p>This allocates memory for a new VM and initializes it. The Wren C implementation
has no global state, so every single bit of data Wren uses is bundled up inside
a WrenVM. You can have multiple Wren VMs running independently of each other
without any problems, even concurrently on different threads. </p>
<p><code>wrenNewVM()</code> stores its own copy of the configuration, so after calling it, you
can discard the WrenConfiguration struct you filled in. Now you have a live
VM, waiting to run some code! </p>
<h2>Executing Wren code <a href="#executing-wren-code" name="executing-wren-code" class="header-anchor">#</a></h2> <h2>Executing Wren code <a href="#executing-wren-code" name="executing-wren-code" class="header-anchor">#</a></h2>
<p>You execute a string of Wren source code like so: </p> <p>You execute a string of Wren source code like so:</p>
<div class="codehilite"><pre><span class="n">WrenInterpretResult</span> <span class="n">result</span> <span class="o">=</span> <span class="n">wrenInterpret</span><span class="p">(</span> <pre class="snippet" data-lang="c">
<span class="n">vm</span><span class="p">,</span> WrenInterpretResult result = wrenInterpret(
<span class="s">&quot;my_module&quot;</span><span class="p">,</span> vm,
<span class="s">&quot;System.print(</span><span class="se">\&quot;</span><span class="s">I am running in a VM!</span><span class="se">\&quot;</span><span class="s">)&quot;</span><span class="p">);</span> "my_module",
</pre></div> "System.print(\"I am running in a VM!\")");
</pre>
<p>The string is a series of one or more statements separated by newlines. Wren
<p>The string is a series of one or more statements separated by newlines. Wren copies the string, so you can free it after calling this. When you call
copies the string, so you can free it after calling this. When you call <code>wrenInterpret()</code>, Wren first compiles your source to bytecode. If an error
<code>wrenInterpret()</code>, Wren first compiles your source to bytecode. If an error occurs, it returns immediately with <code>WREN_RESULT_COMPILE_ERROR</code>.</p>
occurs, it returns immediately with <code>WREN_RESULT_COMPILE_ERROR</code>. </p> <p>Otherwise, Wren spins up a new <a href="../concurrency.html">fiber</a> and executes the code in that. Your
<p>Otherwise, Wren spins up a new <a href="../concurrency.html">fiber</a> and executes the code in that. Your code can in turn spawn whatever other fibers it wants. It keeps running fibers
code can in turn spawn whatever other fibers it wants. It keeps running fibers until they all complete or one <a href="../modules/core/fiber.html#fiber.suspend()">suspends</a>.</p>
until they all complete or one <a href="../modules/core/fiber.html#fiber.suspend()">suspends</a>. </p> <p>If a <a href="../error-handling.html">runtime error</a> occurs (and another fiber doesn&rsquo;t handle it), Wren aborts
<p>If a <a href="../error-handling.html">runtime error</a> occurs (and another fiber doesn&rsquo;t handle it), Wren aborts fibers all the way back to the main one and returns <code>WREN_RESULT_RUNTIME_ERROR</code>.
fibers all the way back to the main one and returns <code>WREN_RESULT_RUNTIME_ERROR</code>. Otherwise, when the last fiber successfully returns, it returns
Otherwise, when the last fiber successfully returns, it returns <code>WREN_RESULT_SUCCESS</code>.</p>
<code>WREN_RESULT_SUCCESS</code>. </p> <p>All code passed to <code>wrenInterpret()</code> runs in a special &ldquo;main&rdquo; module. That way,
<p>All code passed to <code>wrenInterpret()</code> runs in a special &ldquo;main&rdquo; module. That way, top-level names defined in one call can be accessed in later ones. It&rsquo;s similar
top-level names defined in one call can be accessed in later ones. It&rsquo;s similar to a REPL session.</p>
to a REPL session. </p>
<h2>Shutting down a VM <a href="#shutting-down-a-vm" name="shutting-down-a-vm" class="header-anchor">#</a></h2> <h2>Shutting down a VM <a href="#shutting-down-a-vm" name="shutting-down-a-vm" class="header-anchor">#</a></h2>
<p>Once the party is over and you&rsquo;re ready to end your relationship with a VM, you <p>Once the party is over and you&rsquo;re ready to end your relationship with a VM, you
need to free any memory it allocated. You do that like so: </p> need to free any memory it allocated. You do that like so:</p>
<div class="codehilite"><pre><span class="n">wrenFreeVM</span><span class="p">(</span><span class="n">vm</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> wrenFreeVM(vm);
</pre>
<p>After calling that, you obviously cannot use the <code>WrenVM*</code> you passed to it
<p>After calling that, you obviously cannot use the <code>WrenVM*</code> you passed to it again. It&rsquo;s dead.</p>
again. It&rsquo;s dead. </p> <p>Note that Wren will yell at you if you still have any live <a href="slots-and-handles.html#handles">WrenHandle</a>
<p>Note that Wren will yell at you if you still have any live <a href="slots-and-handles.html#handles">WrenHandle</a> objects when you call this. This makes sure you haven&rsquo;t lost track of any of
objects when you call this. This makes sure you haven&rsquo;t lost track of any of them (which leaks memory) and you don&rsquo;t try to use any of them after the VM has
them (which leaks memory) and you don&rsquo;t try to use any of them after the VM has been freed.</p>
been freed. </p> <p>Next, we&rsquo;ll learn to make that VM do useful stuff&hellip;</p>
<p>Next, we&rsquo;ll learn to make that VM do useful stuff&hellip; </p> <p><a class="right" href="slots-and-handles.html">Slots and Handles &rarr;</a></p>
<p><a class="right" href="slots-and-handles.html">Slots and Handles &rarr;</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Slots and Handles &ndash; Wren</title> <title>Slots and Handles &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,6 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section> <section>
<h2>embedding</h2> <h2>embedding</h2>
<ul> <ul>
@ -63,228 +70,228 @@
</nav> </nav>
<main> <main>
<h1>Slots and Handles</h1> <h1>Slots and Handles</h1>
<p>With <code>wrenInterpret()</code>, we can execute code, but that code can&rsquo;t do anything <p>With <code>wrenInterpret()</code>, we can execute code, but that code can&rsquo;t do anything
particularly interesting. By default, the VM is isolated from the rest of the particularly interesting. By default, the VM is isolated from the rest of the
world, so pretty much all it can do is turn your laptop into a lap warmer. </p> world, so pretty much all it can do is turn your laptop into a lap warmer.</p>
<p>To make our Wren code <em>useful</em>, the VM needs to communicate with the outside <p>To make our Wren code <em>useful</em>, the VM needs to communicate with the outside
world. Wren uses a single unified set of functions for passing data into and out world. Wren uses a single unified set of functions for passing data into and out
of the VM. These functions are based on two fundamental concepts: <strong>slots</strong> and of the VM. These functions are based on two fundamental concepts: <strong>slots</strong> and
<strong>handles</strong>. </p> <strong>handles</strong>.</p>
<h2>The Slot Array <a href="#the-slot-array" name="the-slot-array" class="header-anchor">#</a></h2> <h2>The Slot Array <a href="#the-slot-array" name="the-slot-array" class="header-anchor">#</a></h2>
<p>When you want to send data to Wren, read data from it, or generally monkey <p>When you want to send data to Wren, read data from it, or generally monkey
around with Wren objects from C, you do so by going through an array of slots. around with Wren objects from C, you do so by going through an array of slots.
Think of it as a shared message board that both the VM and your C code leave Think of it as a shared message board that both the VM and your C code leave
notes on for the other side to process. </p> notes on for the other side to process.</p>
<p>The array is zero-based, and each slot can hold a value of any type. It is <p>The array is zero-based, and each slot can hold a value of any type. It is
dynamically sized, but it&rsquo;s your responsibility to ensure there are enough slots dynamically sized, but it&rsquo;s your responsibility to ensure there are enough slots
<em>before</em> you use them. You do this by calling: </p> <em>before</em> you use them. You do this by calling:</p>
<div class="codehilite"><pre><span class="n">wrenEnsureSlots</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slotCount</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> wrenEnsureSlots(WrenVM* vm, int slotCount);
</pre>
<p>This grows the slot array if needed to ensure that many slots are available. If
it&rsquo;s already big enough, this does nothing. You&rsquo;ll typically call this once
before populating the slots with data that you want to send to Wren.</p>
<pre class="snippet" data-lang="c">
wrenEnsureSlots(vm, 4);
// Can now use slots 0 through 3, inclusive.
</pre>
<p>This grows the slot array if needed to ensure that many slots are available. If <p>After you ensure an array of slots, you can only rely on them being there until
it&rsquo;s already big enough, this does nothing. You&rsquo;ll typically call this once you pass control back to Wren. That includes calling <code>wrenCall()</code> or
before populating the slots with data that you want to send to Wren. </p> <code>wrenInterpret()</code>, or returning from a <a href="calling-c-from-wren.html">foreign method</a>.</p>
<div class="codehilite"><pre><span class="n">wrenEnsureSlots</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">4</span><span class="p">);</span> <p>If you read or write from a slot that you haven&rsquo;t ensured is valid, Wren makes
<span class="c1">// Can now use slots 0 through 3, inclusive.</span> no guarantees about what will happen. I&rsquo;ve heard rumors of smoke and feathers
</pre></div> flying out of a user&rsquo;s computer.</p>
<p>If you want to see how big the slot array is, use:</p>
<pre class="snippet" data-lang="c">
int wrenGetSlotCount(WrenVM* vm);
</pre>
<p>It returns the number of slots in the array. Note that this may be higher than
<p>After you ensure an array of slots, you can only rely on them being there until the size you&rsquo;ve ensured. Wren reuses the memory for this array when possible,
you pass control back to Wren. That includes calling <code>wrenCall()</code> or so you may get one bigger than you need if it happened to be laying around.</p>
<code>wrenInterpret()</code>, or returning from a <a href="calling-c-from-wren.html">foreign method</a>. </p> <p>When Wren <a href="calling-c-from-wren.html">calls your C code</a> and passes data to you, it ensures there are
<p>If you read or write from a slot that you haven&rsquo;t ensured is valid, Wren makes enough slots for the objects it is sending you.</p>
no guarantees about what will happen. I&rsquo;ve heard rumors of smoke and feathers
flying out of a user&rsquo;s computer. </p>
<p>If you want to see how big the slot array is, use: </p>
<div class="codehilite"><pre><span class="kt">int</span> <span class="nf">wrenGetSlotCount</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">);</span>
</pre></div>
<p>It returns the number of slots in the array. Note that this may be higher than
the size you&rsquo;ve ensured. Wren reuses the memory for this array when possible,
so you may get one bigger than you need if it happened to be laying around. </p>
<p>When Wren <a href="calling-c-from-wren.html">calls your C code</a> and passes data to you, it ensures there are
enough slots for the objects it is sending you. </p>
<h3>Writing slots <a href="#writing-slots" name="writing-slots" class="header-anchor">#</a></h3> <h3>Writing slots <a href="#writing-slots" name="writing-slots" class="header-anchor">#</a></h3>
<p>Once you have some slots, you store data in them using a number of functions all <p>Once you have some slots, you store data in them using a number of functions all
named <code>wrenSetSlot&lt;type&gt;()</code> where <code>&lt;type&gt;</code> is the kind of data. We&rsquo;ll start with named <code>wrenSetSlot&lt;type&gt;()</code> where <code>&lt;type&gt;</code> is the kind of data. We&rsquo;ll start with
the simple ones: </p> the simple ones:</p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">wrenSetSlotBool</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">value</span><span class="p">);</span> <pre class="snippet" data-lang="c">
<span class="kt">void</span> <span class="nf">wrenSetSlotDouble</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">,</span> <span class="kt">double</span> <span class="n">value</span><span class="p">);</span> void wrenSetSlotBool(WrenVM* vm, int slot, bool value);
<span class="kt">void</span> <span class="nf">wrenSetSlotNull</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> void wrenSetSlotDouble(WrenVM* vm, int slot, double value);
</pre></div> void wrenSetSlotNull(WrenVM* vm, int slot);
</pre>
<p>Each of these takes a primitive C value and converts it to the corresponding
<a href="../values.html">Wren value</a>. (Since Wren&rsquo;s <a href="../values.html#numbers">native number type</a> <em>is</em> a double, there&rsquo;s not
really much <em>conversion</em> going on, but you get the idea.)</p>
<p>You can also pass string data to Wren:</p>
<pre class="snippet" data-lang="c">
void wrenSetSlotBytes(WrenVM* vm, int slot,
const char* bytes, size_t length);
<p>Each of these takes a primitive C value and converts it to the corresponding void wrenSetSlotString(WrenVM* vm, int slot,
<a href="../values.html">Wren value</a>. (Since Wren&rsquo;s <a href="../values.html#numbers">native number type</a> <em>is</em> a double, there&rsquo;s not const char* text);
really much <em>conversion</em> going on, but you get the idea.) </p> </pre>
<p>You can also pass string data to Wren: </p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">wrenSetSlotBytes</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">bytes</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">length</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">wrenSetSlotString</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">,</span> <p>Both of these copy the bytes into a new <a href="../values.html#strings">String</a> object managed by Wren&rsquo;s
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">text</span><span class="p">);</span> garbage collector, so you can free your copy of it after you call this. The
</pre></div> difference between the two is that <code>wrenSetSlotBytes()</code> takes an explicit
length. Since Wren strings may contain arbitrary byte values, including the null
byte, this lets you pass those in. It&rsquo;s also a little faster to use this for
<p>Both of these copy the bytes into a new <a href="../values.html#strings">String</a> object managed by Wren&rsquo;s regular strings if you happen to know the length. The latter calculates the
garbage collector, so you can free your copy of it after you call this. The length of the string using <code>strlen()</code>.</p>
difference between the two is that <code>wrenSetSlotBytes()</code> takes an explicit
length. Since Wren strings may contain arbitrary byte values, including the null
byte, this lets you pass those in. It&rsquo;s also a little faster to use this for
regular strings if you happen to know the length. The latter calculates the
length of the string using <code>strlen()</code>. </p>
<h3>Reading slots <a href="#reading-slots" name="reading-slots" class="header-anchor">#</a></h3> <h3>Reading slots <a href="#reading-slots" name="reading-slots" class="header-anchor">#</a></h3>
<p>You can, of course, also pull data out of slots. Here are the simple ones: </p> <p>You can, of course, also pull data out of slots. Here are the simple ones:</p>
<div class="codehilite"><pre><span class="kt">bool</span> <span class="nf">wrenGetSlotBool</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> <pre class="snippet" data-lang="c">
<span class="kt">double</span> <span class="nf">wrenGetSlotDouble</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> bool wrenGetSlotBool(WrenVM* vm, int slot);
</pre></div> double wrenGetSlotDouble(WrenVM* vm, int slot);
</pre>
<p>These take a Wren value of the corresponding type and convert it to its raw C
representation. For strings, we have:</p>
<pre class="snippet" data-lang="c">
const char* wrenGetSlotString(WrenVM* vm, int slot);
const char* wrenGetSlotBytes(WrenVM* vm, int slot,
int* length);
</pre>
<p>These take a Wren value of the corresponding type and convert it to its raw C <p>These return a pointer to the first byte of the string. If you want to know the
representation. For strings, we have: </p> length, the latter stores it in the variable pointed to by <code>length</code>. Both of
<div class="codehilite"><pre><span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="nf">wrenGetSlotString</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> these return a direct pointer to the bytes managed by Wren. You should not hold
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="nf">wrenGetSlotBytes</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">,</span> on to this pointer for long. Wren does not promise that it won&rsquo;t move or free
<span class="kt">int</span><span class="o">*</span> <span class="n">length</span><span class="p">);</span> the data.</p>
</pre></div> <p>With these functions, you are going from dynamically typed Wren data to
statically typed C. It&rsquo;s up to <em>you</em> to ensure that you read a value as the
correct type. If you read a number from a slot that currently holds a string,
you&rsquo;re gonna have a bad time.</p>
<p>Fortunately, you usually know what type of data you have in a slot. If not, you
can ask:</p>
<pre class="snippet" data-lang="c">
WrenType wrenGetSlotType(WrenVM* vm, int slot);
</pre>
<p>This returns an enum defining what type of value is in the slot. It only covers
<p>These return a pointer to the first byte of the string. If you want to know the the primitive values that are supported by the C API. Things like ranges and
length, the latter stores it in the variable pointed to by <code>length</code>. Both of instances of classes come back as <code>WREN_TYPE_UNKNOWN</code>. If you want to move that
these return a direct pointer to the bytes managed by Wren. You should not hold kind of data between Wren and C, you&rsquo;ll have to pull the object apart into
on to this pointer for long. Wren does not promise that it won&rsquo;t move or free simple primitive values first or use a <a href="storing-c-data.html">foreign class</a>.</p>
the data. </p>
<p>With these functions, you are going from dynamically typed Wren data to
statically typed C. It&rsquo;s up to <em>you</em> to ensure that you read a value as the
correct type. If you read a number from a slot that currently holds a string,
you&rsquo;re gonna have a bad time. </p>
<p>Fortunately, you usually know what type of data you have in a slot. If not, you
can ask: </p>
<div class="codehilite"><pre><span class="n">WrenType</span> <span class="nf">wrenGetSlotType</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span>
</pre></div>
<p>This returns an enum defining what type of value is in the slot. It only covers
the primitive values that are supported by the C API. Things like ranges and
instances of classes come back as <code>WREN_TYPE_UNKNOWN</code>. If you want to move that
kind of data between Wren and C, you&rsquo;ll have to pull the object apart into
simple primitive values first or use a <a href="storing-c-data.html">foreign class</a>. </p>
<h3>Looking up variables <a href="#looking-up-variables" name="looking-up-variables" class="header-anchor">#</a></h3> <h3>Looking up variables <a href="#looking-up-variables" name="looking-up-variables" class="header-anchor">#</a></h3>
<p>There are a few other utility functions that move data into and out of slots. <p>There are a few other utility functions that move data into and out of slots.
Here&rsquo;s the first: </p> Here&rsquo;s the first:</p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">wrenGetVariable</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span> <pre class="snippet" data-lang="c">
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> void wrenGetVariable(WrenVM* vm, const char* module,
</pre></div> const char* name, int slot);
</pre>
<p>This looks up a top level variable with the given name in the module with the
<p>This looks up a top level variable with the given name in the module with the given name and stores its value in the given slot. Note that classes are just
given name and stores its value in the given slot. Note that classes are just objects stored in variables too, so you can use this to look up a class by its
objects stored in variables too, so you can use this to look up a class by its name. Handy for calling static methods on it.</p>
name. Handy for calling static methods on it. </p> <p>Like any method that works with strings, this one is a bit slow. It has to hash
<p>Like any method that works with strings, this one is a bit slow. It has to hash the name and look it up in the module&rsquo;s string table. You might want to avoid
the name and look it up in the module&rsquo;s string table. You might want to avoid calling this in the middle of a hot loop where performance is critical. Instead,
calling this in the middle of a hot loop where performance is critical. Instead, it&rsquo;s faster to look up the variable once outside the loop and store a reference
it&rsquo;s faster to look up the variable once outside the loop and store a reference to the object using a <a href="#handles">handle</a>.</p>
to the object using a <a href="#handles">handle</a>. </p>
<h3>Working with lists <a href="#working-with-lists" name="working-with-lists" class="header-anchor">#</a></h3> <h3>Working with lists <a href="#working-with-lists" name="working-with-lists" class="header-anchor">#</a></h3>
<p>The slot array is fine for moving a fixed number of objects between Wren and <p>The slot array is fine for moving a fixed number of objects between Wren and
C, but sometimes you need to shuttle a larger or dynamically-sized ball of C, but sometimes you need to shuttle a larger or dynamically-sized ball of
stuff. <a href="../lists.html">List objects</a> work well for that, so the C API lets you work stuff. <a href="../lists.html">List objects</a> work well for that, so the C API lets you work
with them directly. </p> with them directly.</p>
<p>You can create a new empty list from C using: </p> <p>You can create a new empty list from C using:</p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">wrenSetSlotNewList</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> void wrenSetSlotNewList(WrenVM* vm, int slot);
</pre>
<p>It stores the resulting list in the given slot. If you have a list in a
slot&mdash;either one you created from C or from Wren&mdash;you can add elements
to it using:</p>
<pre class="snippet" data-lang="c">
void wrenInsertInList(WrenVM* vm, int listSlot, int index,
int elementSlot);
</pre>
<p>It stores the resulting list in the given slot. If you have a list in a <p>That&rsquo;s a lot of int parameters:</p>
slot&mdash;either one you created from C or from Wren&mdash;you can add elements
to it using: </p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">wrenInsertInList</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">listSlot</span><span class="p">,</span> <span class="kt">int</span> <span class="n">index</span><span class="p">,</span>
<span class="kt">int</span> <span class="n">elementSlot</span><span class="p">);</span>
</pre></div>
<p>That&rsquo;s a lot of int parameters: </p>
<ul> <ul>
<li> <li>
<p><code>listSlot</code> is the slot where the list object is stored. That&rsquo;s the list you&rsquo;ll <p><code>listSlot</code> is the slot where the list object is stored. That&rsquo;s the list you&rsquo;ll
be modifying. If you created the list from C, it will be the slot you passed be modifying. If you created the list from C, it will be the slot you passed
to <code>wrenSetSlotNewList()</code>. </p> to <code>wrenSetSlotNewList()</code>.</p>
</li> </li>
<li> <li>
<p><code>index</code> is the index within the list where you want to insert the element. <p><code>index</code> is the index within the list where you want to insert the element.
Just like from within Wren, you can use a negative number to count back from Just like from within Wren, you can use a negative number to count back from
the end, so <code>-1</code> appends to the list. </p> the end, so <code>-1</code> appends to the list.</p>
</li> </li>
<li> <li>
<p><code>elementSlot</code> identifies the slot where the value you want to insert in the <p><code>elementSlot</code> identifies the slot where the value you want to insert in the
list can be found. </p> list can be found.</p>
</li> </li>
</ul> </ul>
<p>This API means getting a value from C into a list is a two step operation. First <p>This API means getting a value from C into a list is a two step operation. First
you move the value into a slot, then you take it from the slot and insert it in you move the value into a slot, then you take it from the slot and insert it in
the list. This is kind of tedious, but it lets us use the same set of functions the list. This is kind of tedious, but it lets us use the same set of functions
for moving values into slots of each primitive type. Otherwise, we&rsquo;d need for moving values into slots of each primitive type. Otherwise, we&rsquo;d need
<code>wrenInsertInListDouble()</code>, <code>wrenInsertInListBool()</code>, etc. </p> <code>wrenInsertInListDouble()</code>, <code>wrenInsertInListBool()</code>, etc.</p>
<h2>Handles <a href="#handles" name="handles" class="header-anchor">#</a></h2> <h2>Handles <a href="#handles" name="handles" class="header-anchor">#</a></h2>
<p>Slots are pretty good for shuttling primitive data between C and Wren, but they <p>Slots are pretty good for shuttling primitive data between C and Wren, but they
have two limitations: </p> have two limitations:</p>
<ol> <ol>
<li> <li>
<p><strong>They are short-lived.</strong> As soon as you execute some more Wren code, the <p><strong>They are short-lived.</strong> As soon as you execute some more Wren code, the
slot array is invalidated. You can&rsquo;t use a slot to persistently keep track slot array is invalidated. You can&rsquo;t use a slot to persistently keep track
of some object. </p> of some object.</p>
</li> </li>
<li> <li>
<p><strong>They only support primitive types.</strong> A slot can hold a value of any type, <p><strong>They only support primitive types.</strong> A slot can hold a value of any type,
but the C API we&rsquo;ve seen so far doesn&rsquo;t let you <em>do</em> anything with values but the C API we&rsquo;ve seen so far doesn&rsquo;t let you <em>do</em> anything with values
that aren&rsquo;t simple primitive ones. If you want to grab a reference to, that aren&rsquo;t simple primitive ones. If you want to grab a reference to,
say, an instance of some class, how do you do it? </p> say, an instance of some class, how do you do it?</p>
</li> </li>
</ol> </ol>
<p>To address those, we have handles. A handle wraps a reference to an object of <p>To address those, we have handles. A handle wraps a reference to an object of
any kind&mdash;strings, numbers, instances of classes, collections, whatever. any kind&mdash;strings, numbers, instances of classes, collections, whatever.
You create a handle using this: </p> You create a handle using this:</p>
<div class="codehilite"><pre><span class="n">WrenHandle</span><span class="o">*</span> <span class="nf">wrenGetSlotHandle</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> WrenHandle* wrenGetSlotHandle(WrenVM* vm, int slot);
</pre>
<p>This takes the object stored in the given slot, creates a new WrenHandle to wrap
it, and returns a pointer to it back to you. You can send that wrapped object
back to Wren by calling:</p>
<pre class="snippet" data-lang="c">
void wrenSetSlotHandle(WrenVM* vm, int slot, WrenHandle* handle);
</pre>
<p>This takes the object stored in the given slot, creates a new WrenHandle to wrap <p>Note that this doesn&rsquo;t invalidate your WrenHandle. You can still keep using it.</p>
it, and returns a pointer to it back to you. You can send that wrapped object
back to Wren by calling: </p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">wrenSetSlotHandle</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">,</span> <span class="n">WrenHandle</span><span class="o">*</span> <span class="n">handle</span><span class="p">);</span>
</pre></div>
<p>Note that this doesn&rsquo;t invalidate your WrenHandle. You can still keep using it. </p>
<h3>Retaining and releasing handles <a href="#retaining-and-releasing-handles" name="retaining-and-releasing-handles" class="header-anchor">#</a></h3> <h3>Retaining and releasing handles <a href="#retaining-and-releasing-handles" name="retaining-and-releasing-handles" class="header-anchor">#</a></h3>
<p>A handle is an opaque wrapper around an object of any type, but just as <p>A handle is an opaque wrapper around an object of any type, but just as
important, it&rsquo;s a <em>persistent</em> one. When Wren gives you a pointer to a important, it&rsquo;s a <em>persistent</em> one. When Wren gives you a pointer to a
WrenHandle, it guarantees that that pointer remains valid. You can keep it WrenHandle, it guarantees that that pointer remains valid. You can keep it
around as long as you want. Even if a garbage collection occurs, Wren will around as long as you want. Even if a garbage collection occurs, Wren will
ensure the handle and the object it wraps are kept safely in memory. </p> ensure the handle and the object it wraps are kept safely in memory.</p>
<p>Internally, Wren keeps a list of all of the WrenHandles that have been created. <p>Internally, Wren keeps a list of all of the WrenHandles that have been created.
That way, during garbage collection, it can find them all and make sure their That way, during garbage collection, it can find them all and make sure their
objects aren&rsquo;t freed. But what if you don&rsquo;t want it to be kept around any more? objects aren&rsquo;t freed. But what if you don&rsquo;t want it to be kept around any more?
Since C relies on manual memory management, WrenHandle does too. When you are Since C relies on manual memory management, WrenHandle does too. When you are
done with one, you must explicitly release it by calling: </p> done with one, you must explicitly release it by calling:</p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">wrenReleaseHandle</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="n">WrenHandle</span><span class="o">*</span> <span class="n">handle</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> void wrenReleaseHandle(WrenVM* vm, WrenHandle* handle);
</pre>
<p>This does not immediately delete the wrapped object&mdash;after all, there may
<p>This does not immediately delete the wrapped object&mdash;after all, there may be other references to the same object in the program. It just invalidates the
be other references to the same object in the program. It just invalidates the WrenHandle wrapper itself. After you call this, you cannot use that pointer
WrenHandle wrapper itself. After you call this, you cannot use that pointer again.</p>
again. </p> <p>You must release every WrenHandle you&rsquo;ve created before shutting down the VM.
<p>You must release every WrenHandle you&rsquo;ve created before shutting down the VM. Wren warns you if you don&rsquo;t, since it implies you&rsquo;ve probably leaked a resource
Wren warns you if you don&rsquo;t, since it implies you&rsquo;ve probably leaked a resource somewhere.</p>
somewhere. </p> <p>Now we know how to pass values between Wren and C, but we don&rsquo;t know how to
<p>Now we know how to pass values between Wren and C, but we don&rsquo;t know how to actually <em>do</em> anything with them. Next, we&rsquo;ll learn how to use slots to pass
actually <em>do</em> anything with them. Next, we&rsquo;ll learn how to use slots to pass parameters to a Wren method from C&hellip;</p>
parameters to a Wren method from C&hellip; </p> <p><a class="right" href="calling-wren-from-c.html">Calling Wren from C &rarr;</a>
<p><a class="right" href="calling-wren-from-c.html">Calling Wren from C &rarr;</a> <a href="index.html">&larr; Introduction</a></p>
<a href="index.html">&larr; Introduction</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Storing C Data &ndash; Wren</title> <title>Storing C Data &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,6 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section> <section>
<h2>embedding</h2> <h2>embedding</h2>
<ul> <ul>
@ -63,339 +70,339 @@
</nav> </nav>
<main> <main>
<h1>Storing C Data</h1> <h1>Storing C Data</h1>
<p>An embedded language often needs to work with native data. You may want a <p>An embedded language often needs to work with native data. You may want a
pointer to some memory managed in the C heap, or maybe you want to store a chunk pointer to some memory managed in the C heap, or maybe you want to store a chunk
of data more efficiently than Wren&rsquo;s dynamism allows. You may want a Wren object of data more efficiently than Wren&rsquo;s dynamism allows. You may want a Wren object
that represents a native resource like a file handle or database connection. </p> that represents a native resource like a file handle or database connection.</p>
<p>For those cases, you can define a <strong>foreign class</strong>, a chimera whose state is <p>For those cases, you can define a <strong>foreign class</strong>, a chimera whose state is
half Wren and half C. It is a real Wren class with a name, constructor, and half Wren and half C. It is a real Wren class with a name, constructor, and
methods. You can define methods on it written in Wren, or <a href="http://localhost:8000/embedding/calling-c-from-wren.html">foreign methods</a> methods. You can define methods on it written in Wren, or <a href="http://localhost:8000/embedding/calling-c-from-wren.html">foreign methods</a>
written in C. It produces real Wren objects that you can pass around, do <code>is</code> written in C. It produces real Wren objects that you can pass around, do <code>is</code>
checks on, etc. But it also wraps a blob of raw memory that is opaque to Wren checks on, etc. But it also wraps a blob of raw memory that is opaque to Wren
but accessible from C. </p> but accessible from C.</p>
<h2>Defining a Foreign Class <a href="#defining-a-foreign-class" name="defining-a-foreign-class" class="header-anchor">#</a></h2> <h2>Defining a Foreign Class <a href="#defining-a-foreign-class" name="defining-a-foreign-class" class="header-anchor">#</a></h2>
<p>You define one like so: </p> <p>You define one like so:</p>
<div class="codehilite"><pre><span class="k">foreign</span> <span class="k">class</span> <span class="vg">Point</span> <span class="p">{</span> <pre class="snippet">
<span class="c1">// ...</span> foreign class Point {
<span class="p">}</span> // ...
</pre></div> }
</pre>
<p>The <code>foreign</code> keyword tells Wren to loop in the host application when it
constructs instances of the class. The host tells Wren how many bytes of extra
memory the foreign instance should contain and in return, Wren gives the host
the opportunity to initialize that data.</p>
<p>To talk to the host app, Wren needs a C function it can call when it constructs
an instance of the foreign class. This function is found through a binding
process similar to <a href="calling-c-from-wren.html#binding-foreign-methods">how foreign methods are bound</a>. When you <a href="configuring-the-vm.html">configure
the VM</a>, you set the <code>bindForeignClassFn</code> field in WrenConfiguration to point
to a C callback you define. Its signature must be:</p>
<pre class="snippet" data-lang="c">
WrenForeignClassMethods bindForeignClass(
WrenVM* vm, const char* module, const char* className);
</pre>
<p>The <code>foreign</code> keyword tells Wren to loop in the host application when it <p>Wren invokes this callback once when a foreign class declaration is executed.
constructs instances of the class. The host tells Wren how many bytes of extra Wren passes in the name of the module containing the foreign class, and the name
memory the foreign instance should contain and in return, Wren gives the host of the class being declared. The host&rsquo;s responsibility is to return one of these
the opportunity to initialize that data. </p> structs:</p>
<p>To talk to the host app, Wren needs a C function it can call when it constructs <pre class="snippet" data-lang="c">
an instance of the foreign class. This function is found through a binding typedef struct
process similar to <a href="calling-c-from-wren.html#binding-foreign-methods">how foreign methods are bound</a>. When you <a href="configuring-the-vm.html">configure {
the VM</a>, you set the <code>bindForeignClassFn</code> field in WrenConfiguration to point WrenForeignMethodFn allocate;
to a C callback you define. Its signature must be: </p> WrenFinalizerFn finalize;
<div class="codehilite"><pre><span class="n">WrenForeignClassMethods</span> <span class="nf">bindForeignClass</span><span class="p">(</span> } WrenForeignClassMethods;
<span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">className</span><span class="p">);</span> </pre>
</pre></div>
<p>Wren invokes this callback once when a foreign class declaration is executed.
Wren passes in the name of the module containing the foreign class, and the name
of the class being declared. The host&rsquo;s responsibility is to return one of these
structs: </p>
<div class="codehilite"><pre><span class="k">typedef</span> <span class="k">struct</span>
<span class="p">{</span>
<span class="n">WrenForeignMethodFn</span> <span class="n">allocate</span><span class="p">;</span>
<span class="n">WrenFinalizerFn</span> <span class="n">finalize</span><span class="p">;</span>
<span class="p">}</span> <span class="n">WrenForeignClassMethods</span><span class="p">;</span>
</pre></div>
<p>It&rsquo;s a pair of function pointers. The first, <code>allocate</code>, is called by Wren
whenever an instance of the foreign class is created. (We&rsquo;ll get to the optional
<code>finalize</code> callback later.) The allocation callback has the same signature as a
foreign method: </p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">allocate</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">);</span>
</pre></div>
<p>It&rsquo;s a pair of function pointers. The first, <code>allocate</code>, is called by Wren
whenever an instance of the foreign class is created. (We&rsquo;ll get to the optional
<code>finalize</code> callback later.) The allocation callback has the same signature as a
foreign method:</p>
<pre class="snippet" data-lang="c">
void allocate(WrenVM* vm);
</pre>
<h2>Initializing an Instance <a href="#initializing-an-instance" name="initializing-an-instance" class="header-anchor">#</a></h2> <h2>Initializing an Instance <a href="#initializing-an-instance" name="initializing-an-instance" class="header-anchor">#</a></h2>
<p>When you create an instance of a foreign class by calling one its <p>When you create an instance of a foreign class by calling one its
<a href="../classes.html#constructors">constructors</a>, Wren invokes the <code>allocate</code> callback you gave it when binding <a href="../classes.html#constructors">constructors</a>, Wren invokes the <code>allocate</code> callback you gave it when binding
the foreign class. Your primary responsibility in that callback is to tell Wren the foreign class. Your primary responsibility in that callback is to tell Wren
how many bytes of raw memory you need. You do that by calling: </p> how many bytes of raw memory you need. You do that by calling:</p>
<div class="codehilite"><pre><span class="kt">void</span><span class="o">*</span> <span class="nf">wrenSetSlotNewForeign</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <pre class="snippet" data-lang="c">
<span class="kt">int</span> <span class="n">slot</span><span class="p">,</span> <span class="kt">int</span> <span class="n">classSlot</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">size</span><span class="p">);</span> void* wrenSetSlotNewForeign(WrenVM* vm,
</pre></div> int slot, int classSlot, size_t size);
</pre>
<p>Like other <a href="slots-and-handles.html">slot manipulation functions</a>, it both reads from and writes to
<p>Like other <a href="slots-and-handles.html">slot manipulation functions</a>, it both reads from and writes to the slot array. It has a few parameters to make it more general purpose since it
the slot array. It has a few parameters to make it more general purpose since it can also be used in other foreign methods:</p>
can also be used in other foreign methods: </p>
<ul> <ul>
<li> <li>
<p>The <code>slot</code> parameter is the destination slot where the new foreign object <p>The <code>slot</code> parameter is the destination slot where the new foreign object
should be placed. When you&rsquo;re calling this in a foreign class&rsquo;s allocate should be placed. When you&rsquo;re calling this in a foreign class&rsquo;s allocate
callback, this should be 0. </p> callback, this should be 0.</p>
</li> </li>
<li> <li>
<p>The <code>classSlot</code> parameter is the slot where the foreign class being <p>The <code>classSlot</code> parameter is the slot where the foreign class being
constructed can be found. When the VM calls an allocate callback for a constructed can be found. When the VM calls an allocate callback for a
foreign class, the class itself is already in slot 0, so you&rsquo;ll pass 0 for foreign class, the class itself is already in slot 0, so you&rsquo;ll pass 0 for
this too. </p> this too.</p>
</li> </li>
<li> <li>
<p>Finally, the <code>size</code> parameter is the interesting one. Here, you pass in the <p>Finally, the <code>size</code> parameter is the interesting one. Here, you pass in the
number of extra raw bytes of data you want the foreign instance to store. number of extra raw bytes of data you want the foreign instance to store.
This is the memory you get to play with from C. </p> This is the memory you get to play with from C.</p>
</li> </li>
</ul> </ul>
<p>So, for example, if you wanted to create a foreign instance that contains eight <p>So, for example, if you wanted to create a foreign instance that contains eight
bytes of C data, you&rsquo;d call: </p> bytes of C data, you&rsquo;d call:</p>
<div class="codehilite"><pre><span class="kt">void</span><span class="o">*</span> <span class="n">data</span> <span class="o">=</span> <span class="n">wrenSetSlotNewForeign</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">8</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> void* data = wrenSetSlotNewForeign(vm, 0, 0, 8);
</pre>
<p>The value returned by <code>wrenSetSlotNewForeign()</code> is the raw pointer to the
<p>The value returned by <code>wrenSetSlotNewForeign()</code> is the raw pointer to the requested bytes. You can cast that to whatever C type makes sense (as long as it
requested bytes. You can cast that to whatever C type makes sense (as long as it fits within the requested number of bytes) and initialize it as you see fit.</p>
fits within the requested number of bytes) and initialize it as you see fit. </p> <p>Any parameters passed to the constructor are also available in subsequent slots
<p>Any parameters passed to the constructor are also available in subsequent slots in the slot array. That way you can initialize the foreign data based on values
in the slot array. That way you can initialize the foreign data based on values passed to the constructor from Wren.</p>
passed to the constructor from Wren. </p> <p>After the allocate callback returns, the class&rsquo;s constructor in Wren is run and
<p>After the allocate callback returns, the class&rsquo;s constructor in Wren is run and execution proceeds like normal. From here on out, within Wren, it appears you
execution proceeds like normal. From here on out, within Wren, it appears you have a normal instance of a class. It just happens to have some extra bytes
have a normal instance of a class. It just happens to have some extra bytes hiding inside it that can be accessed from foreign methods.</p>
hiding inside it that can be accessed from foreign methods. </p>
<h2>Accessing Foreign Data <a href="#accessing-foreign-data" name="accessing-foreign-data" class="header-anchor">#</a></h2> <h2>Accessing Foreign Data <a href="#accessing-foreign-data" name="accessing-foreign-data" class="header-anchor">#</a></h2>
<p>Typically, the way you make use of the data stored in an instance of a foreign <p>Typically, the way you make use of the data stored in an instance of a foreign
class is through other foreign methods. Those are usually defined on the same class is through other foreign methods. Those are usually defined on the same
foreign class, but can be defined on other classes as well. Wren doesn&rsquo;t care. </p> foreign class, but can be defined on other classes as well. Wren doesn&rsquo;t care.</p>
<p>Once you have a foreign instance in a slot, you can access the raw bytes it <p>Once you have a foreign instance in a slot, you can access the raw bytes it
stores by calling: </p> stores by calling:</p>
<div class="codehilite"><pre><span class="kt">void</span><span class="o">*</span> <span class="nf">wrenGetSlotForeign</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="kt">int</span> <span class="n">slot</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> void* wrenGetSlotForeign(WrenVM* vm, int slot);
</pre>
<p>You pass in the slot index containing the foreign object and it gives you back a
<p>You pass in the slot index containing the foreign object and it gives you back a pointer to the raw memory the object wraps. As usual, the C API doesn&rsquo;t do any
pointer to the raw memory the object wraps. As usual, the C API doesn&rsquo;t do any type or bounds checking, so it&rsquo;s on you to make sure the object in that slot
type or bounds checking, so it&rsquo;s on you to make sure the object in that slot actually <em>is</em> an instance of a foreign class and contains as much memory as you
actually <em>is</em> an instance of a foreign class and contains as much memory as you access.</p>
access. </p> <p>Given that void pointer, you can now freely read and modify the data it points
<p>Given that void pointer, you can now freely read and modify the data it points to. They&rsquo;re your bits, Wren just holds them for you.</p>
to. They&rsquo;re your bits, Wren just holds them for you. </p>
<h2>Freeing Resources <a href="#freeing-resources" name="freeing-resources" class="header-anchor">#</a></h2> <h2>Freeing Resources <a href="#freeing-resources" name="freeing-resources" class="header-anchor">#</a></h2>
<p>If your foreign instances are just holding memory and you&rsquo;re OK with Wren&rsquo;s <p>If your foreign instances are just holding memory and you&rsquo;re OK with Wren&rsquo;s
garbage collector managing the lifetime of that memory, then you&rsquo;re done. Wren garbage collector managing the lifetime of that memory, then you&rsquo;re done. Wren
will keep the bytes around as long as there is still a reference to them. When will keep the bytes around as long as there is still a reference to them. When
the instance is no longer reachable, eventually the garbage collector will do the instance is no longer reachable, eventually the garbage collector will do
its thing and free the memory. </p> its thing and free the memory.</p>
<p>But, often, your foreign data refers to some resource whose lifetime needs to <p>But, often, your foreign data refers to some resource whose lifetime needs to
be explicitly managed. For example, if you have a foreign object that wraps an be explicitly managed. For example, if you have a foreign object that wraps an
open file handle, you need to ensure that handle doesn&rsquo;t get left open when the open file handle, you need to ensure that handle doesn&rsquo;t get left open when the
GC frees the foreign instance. </p> GC frees the foreign instance.</p>
<p>Of course, you can (and usually should) add a method on your foreign class, like <p>Of course, you can (and usually should) add a method on your foreign class, like
<code>close()</code> so the user can explicitly release the resource managed by the object. <code>close()</code> so the user can explicitly release the resource managed by the object.
But if they forget to do that and the object is no longer reachable, you want to But if they forget to do that and the object is no longer reachable, you want to
make sure the resource isn&rsquo;t leaked. </p> make sure the resource isn&rsquo;t leaked.</p>
<p>To that end, you can also provide a <em>finalizer</em> function when binding the <p>To that end, you can also provide a <em>finalizer</em> function when binding the
foreign class. That&rsquo;s the other callback in the WrenForeignClassMethods struct. foreign class. That&rsquo;s the other callback in the WrenForeignClassMethods struct.
If you provide that callback, then Wren will invoke it when an instance of your If you provide that callback, then Wren will invoke it when an instance of your
foreign class is about to be freed by the garbage collector. This gives you one foreign class is about to be freed by the garbage collector. This gives you one
last chance to clean up the object&rsquo;s resources. </p> last chance to clean up the object&rsquo;s resources.</p>
<p>Because this is called during the middle of a garbage collection, you do not <p>Because this is called during the middle of a garbage collection, you do not
have unfettered access to the VM. It&rsquo;s not like a normal foreign method where have unfettered access to the VM. It&rsquo;s not like a normal foreign method where
you can monkey around with slots and other stuff. Doing that while the GC is you can monkey around with slots and other stuff. Doing that while the GC is
running could leave Wren in a weird state. </p> running could leave Wren in a weird state.</p>
<p>Instead, the finalize callback&rsquo;s signature is only: </p> <p>Instead, the finalize callback&rsquo;s signature is only:</p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">finalize</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">);</span> <pre class="snippet" data-lang="c">
</pre></div> void finalize(void* data);
</pre>
<p>Wren gives you the pointer to your foreign function&rsquo;s memory, and that&rsquo;s it. The
<p>Wren gives you the pointer to your foreign function&rsquo;s memory, and that&rsquo;s it. The <em>only</em> thing you should do inside a finalizer is release any external resources
<em>only</em> thing you should do inside a finalizer is release any external resources referenced by that memory.</p>
referenced by that memory. </p>
<h2>A Full Example <a href="#a-full-example" name="a-full-example" class="header-anchor">#</a></h2> <h2>A Full Example <a href="#a-full-example" name="a-full-example" class="header-anchor">#</a></h2>
<p>That&rsquo;s a lot to take in, so let&rsquo;s walk through a full example of a foreign class <p>That&rsquo;s a lot to take in, so let&rsquo;s walk through a full example of a foreign class
with a finalizer and a couple of methods. We&rsquo;ll do a File class that wraps the with a finalizer and a couple of methods. We&rsquo;ll do a File class that wraps the
C standard file API. </p> C standard file API.</p>
<p>In Wren, the class we want looks like this: </p> <p>In Wren, the class we want looks like this:</p>
<div class="codehilite"><pre><span class="k">foreign</span> <span class="k">class</span> <span class="vg">File</span> <span class="p">{</span> <pre class="snippet">
<span class="k">construct</span> <span class="n">create</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="p">{}</span> foreign class File {
construct create(path) {}
<span class="k">foreign</span> <span class="n">write</span><span class="p">(</span><span class="n">text</span><span class="p">)</span> foreign write(text)
<span class="k">foreign</span> <span class="n">close</span><span class="p">()</span> foreign close()
<span class="p">}</span> }
</pre></div> </pre>
<p>So you can create a new file given a path. Once you have one, you can write to
<p>So you can create a new file given a path. Once you have one, you can write to it and then explicitly close it if you want. We also need to make sure the file
it and then explicitly close it if you want. We also need to make sure the file gets closed if the user forgets to and the GC cleans up the object.</p>
gets closed if the user forgets to and the GC cleans up the object. </p>
<h3>Setting up the VM <a href="#setting-up-the-vm" name="setting-up-the-vm" class="header-anchor">#</a></h3> <h3>Setting up the VM <a href="#setting-up-the-vm" name="setting-up-the-vm" class="header-anchor">#</a></h3>
<p>Over in the host, first we&rsquo;ll set up the VM: </p> <p>Over in the host, first we&rsquo;ll set up the VM:</p>
<div class="codehilite"><pre><span class="cp">#include &quot;wren.h&quot;</span> <pre class="snippet" data-lang="c">
#include "wren.h"
<span class="kt">int</span> <span class="nf">main</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">argv</span><span class="p">[])</span> int main(int argc, const char* argv[])
<span class="p">{</span> {
<span class="n">WrenConfiguration</span> <span class="n">config</span><span class="p">;</span> WrenConfiguration config;
<span class="n">wrenInitConfiguration</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> wrenInitConfiguration(&config);
<span class="n">config</span><span class="p">.</span><span class="n">bindForeignClassFn</span> <span class="o">=</span> <span class="n">bindForeignClass</span><span class="p">;</span> config.bindForeignClassFn = bindForeignClass;
<span class="n">config</span><span class="p">.</span><span class="n">bindForeignMethodFn</span> <span class="o">=</span> <span class="n">bindForeignMethod</span><span class="p">;</span> config.bindForeignMethodFn = bindForeignMethod;
<span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span> <span class="o">=</span> <span class="n">wrenNewVM</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> WrenVM* vm = wrenNewVM(&config);
<span class="n">wrenInterpret</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="s">&quot;my_module&quot;</span><span class="p">,</span> <span class="s">&quot;some code...&quot;</span><span class="p">);</span> wrenInterpret(vm, "my_module", "some code...");
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
return 0;
}
</pre>
<h3>Binding the foreign class <a href="#binding-the-foreign-class" name="binding-the-foreign-class" class="header-anchor">#</a></h3> <h3>Binding the foreign class <a href="#binding-the-foreign-class" name="binding-the-foreign-class" class="header-anchor">#</a></h3>
<p>We give the VM two callbacks. The first is for wiring up the foreign class <p>We give the VM two callbacks. The first is for wiring up the foreign class
itself: </p> itself:</p>
<div class="codehilite"><pre><span class="n">WrenForeignClassMethods</span> <span class="nf">bindForeignClass</span><span class="p">(</span> <pre class="snippet" data-lang="c">
<span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">className</span><span class="p">)</span> WrenForeignClassMethods bindForeignClass(
<span class="p">{</span> WrenVM* vm, const char* module, const char* className)
<span class="n">WrenForeignClassMethods</span> <span class="n">methods</span><span class="p">;</span> {
WrenForeignClassMethods methods;
<span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">className</span><span class="p">,</span> <span class="s">&quot;File&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> if (strcmp(className, "File") == 0)
<span class="p">{</span> {
<span class="n">methods</span><span class="o">-&gt;</span><span class="n">allocate</span> <span class="o">=</span> <span class="n">fileAllocate</span><span class="p">;</span> methods.allocate = fileAllocate;
<span class="n">methods</span><span class="o">-&gt;</span><span class="n">finalize</span> <span class="o">=</span> <span class="n">fileFinalize</span><span class="p">;</span> methods.finalize = fileFinalize;
<span class="p">}</span> }
<span class="k">else</span> else
<span class="p">{</span> {
<span class="c1">// Unknown class.</span> // Unknown class.
<span class="n">methods</span><span class="o">-&gt;</span><span class="n">allocate</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> methods.allocate = NULL;
<span class="n">methods</span><span class="o">-&gt;</span><span class="n">finalize</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span> methods.finalize = NULL;
<span class="p">}</span> }
<span class="k">return</span> <span class="n">methods</span><span class="p">;</span> return methods;
<span class="p">}</span> }
</pre></div> </pre>
<p>When our binding callback is invoked for the File class, we return the allocate
and finalize functions the VM should call. Allocation looks like:</p>
<pre class="snippet" data-lang="c">
#include &lt;stdio.h>
#include "wren.h"
<p>When our binding callback is invoked for the File class, we return the allocate void fileAllocate(WrenVM* vm)
and finalize functions the VM should call. Allocation looks like: </p> {
<div class="codehilite"><pre><span class="cp">#include &lt;stdio.h&gt; </span> FILE** file = (FILE**)wrenSetSlotNewForeign(vm,
<span class="cp">#include &quot;wren.h&quot;</span> 0, 0, sizeof(FILE*));
const char* path = wrenGetSlotString(vm, 1);
*file = fopen(path, "w");
}
</pre>
<span class="kt">void</span> <span class="nf">fileAllocate</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">)</span> <p>First we create the instance by calling <code>wrenSetSlotNewForeign()</code>. We tell it to
<span class="p">{</span> add enough extra bytes to store a <code>FILE*</code> in it, which is C&rsquo;s representation of
<span class="kt">FILE</span><span class="o">**</span> <span class="n">file</span> <span class="o">=</span> <span class="p">(</span><span class="kt">FILE</span><span class="o">**</span><span class="p">)</span><span class="n">wrenSetSlotNewForeign</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> a file handle. We&rsquo;re given back a pointer to the bytes. Since the file handle is
<span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">FILE</span><span class="o">*</span><span class="p">));</span> itself a pointer, we end up with a double indirection, hence the <code>FILE**</code>. In
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">path</span> <span class="o">=</span> <span class="n">wrenGetSlotString</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> most cases, you&rsquo;ll just have a single <code>*</code>.</p>
<span class="o">*</span><span class="n">file</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s">&quot;w&quot;</span><span class="p">);</span> <p>We also pull the file path from the slot array. Then we tell C to create a new
<span class="p">}</span> file at that path. That gives us back a new file handle &ndash; a <code>FILE*</code> &ndash; and we
</pre></div> store that back into the foreign instance using <code>*file</code>. Now we have a foreign
object that wraps an open file handle.</p>
<p>The finalizer simply casts the foreign instance&rsquo;s data back to the proper type
and closes the file:</p>
<pre class="snippet" data-lang="c">
void fileFinalize(void* data)
{
closeFile((FILE**) data);
}
</pre>
<p>It uses this little utility function:</p>
<pre class="snippet" data-lang="c">
static void closeFile(FILE** file)
{
// Already closed.
if (*file == NULL) return;
<p>First we create the instance by calling <code>wrenSetSlotNewForeign()</code>. We tell it to fclose(*file);
add enough extra bytes to store a <code>FILE*</code> in it, which is C&rsquo;s representation of *file = NULL;
a file handle. We&rsquo;re given back a pointer to the bytes. Since the file handle is }
itself a pointer, we end up with a double indirection, hence the <code>FILE**</code>. In </pre>
most cases, you&rsquo;ll just have a single <code>*</code>. </p>
<p>We also pull the file path from the slot array. Then we tell C to create a new
file at that path. That gives us back a new file handle &ndash; a <code>FILE*</code> &ndash; and we
store that back into the foreign instance using <code>*file</code>. Now we have a foreign
object that wraps an open file handle. </p>
<p>The finalizer simply casts the foreign instance&rsquo;s data back to the proper type
and closes the file: </p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">fileFinalize</span><span class="p">(</span><span class="kt">void</span><span class="o">*</span> <span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">closeFile</span><span class="p">((</span><span class="kt">FILE</span><span class="o">**</span><span class="p">)</span> <span class="n">data</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>This closes the file (if it&rsquo;s not already closed) and also nulls out the file
<p>It uses this little utility function: </p> handle so that we don&rsquo;t try to use the file after it&rsquo;s been closed.</p>
<div class="codehilite"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">closeFile</span><span class="p">(</span><span class="kt">FILE</span><span class="o">**</span> <span class="n">file</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Already closed.</span>
<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">file</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> <span class="k">return</span><span class="p">;</span>
<span class="n">fclose</span><span class="p">(</span><span class="o">*</span><span class="n">file</span><span class="p">);</span>
<span class="o">*</span><span class="n">file</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
<p>This closes the file (if it&rsquo;s not already closed) and also nulls out the file
handle so that we don&rsquo;t try to use the file after it&rsquo;s been closed. </p>
<h3>Binding the foreign methods <a href="#binding-the-foreign-methods" name="binding-the-foreign-methods" class="header-anchor">#</a></h3> <h3>Binding the foreign methods <a href="#binding-the-foreign-methods" name="binding-the-foreign-methods" class="header-anchor">#</a></h3>
<p>That&rsquo;s the foreign <em>class</em> part. Now we have a couple of foreign <em>methods</em> to <p>That&rsquo;s the foreign <em>class</em> part. Now we have a couple of foreign <em>methods</em> to
handle. The host tells the VM how to find them by giving Wren a pointer to this handle. The host tells the VM how to find them by giving Wren a pointer to this
function: </p> function:</p>
<div class="codehilite"><pre><span class="n">WrenForeignMethodFn</span> <span class="nf">bindForeignMethod</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">module</span><span class="p">,</span> <pre class="snippet" data-lang="c">
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">className</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">isStatic</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">signature</span><span class="p">)</span> WrenForeignMethodFn bindForeignMethod(WrenVM* vm, const char* module,
<span class="p">{</span> const char* className, bool isStatic, const char* signature)
<span class="k">if</span> <span class="p">(</span><span class="n">strcmp</span><span class="p">(</span><span class="n">className</span><span class="p">,</span> <span class="s">&quot;File&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> {
<span class="p">{</span> if (strcmp(className, "File") == 0)
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">isStatic</span> <span class="o">&amp;&amp;</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">signature</span><span class="p">,</span> <span class="s">&quot;write(_)&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> {
<span class="p">{</span> if (!isStatic && strcmp(signature, "write(_)") == 0)
<span class="k">return</span> <span class="n">fileWrite</span><span class="p">;</span> {
<span class="p">}</span> return fileWrite;
}
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">isStatic</span> <span class="o">&amp;&amp;</span> <span class="n">strcmp</span><span class="p">(</span><span class="n">signature</span><span class="p">,</span> <span class="s">&quot;close()&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> if (!isStatic && strcmp(signature, "close()") == 0)
<span class="p">{</span> {
<span class="k">return</span> <span class="n">fileClose</span><span class="p">;</span> return fileClose;
<span class="p">}</span> }
<span class="p">}</span> }
<span class="c1">// Unknown method.</span> // Unknown method.
<span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span> return NULL;
<span class="p">}</span> }
</pre></div> </pre>
<p>When Wren calls this, we look at the class and method name to figure out which
method it&rsquo;s binding, and then return a pointer to the appropriate function. The
foreign method for writing to the file is:</p>
<pre class="snippet" data-lang="c">
void fileWrite(WrenVM* vm)
{
FILE** file = (FILE**)wrenGetSlotForeign(vm, 0);
<p>When Wren calls this, we look at the class and method name to figure out which // Make sure the file is still open.
method it&rsquo;s binding, and then return a pointer to the appropriate function. The if (*file == NULL)
foreign method for writing to the file is: </p> {
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">fileWrite</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">)</span> wrenSetSlotString(vm, 0, "Cannot write to a closed file.");
<span class="p">{</span> wrenAbortFiber(vm, 0);
<span class="kt">FILE</span><span class="o">**</span> <span class="n">file</span> <span class="o">=</span> <span class="p">(</span><span class="kt">FILE</span><span class="o">**</span><span class="p">)</span><span class="n">wrenGetSlotForeign</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span> return;
}
<span class="c1">// Make sure the file is still open.</span> const char* text = wrenGetSlotString(vm, 1);
<span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">file</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span> fwrite(text, sizeof(char), strlen(text), *file);
<span class="p">{</span> }
<span class="n">wrenSetSlotString</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s">&quot;Cannot write to a closed file.&quot;</span><span class="p">);</span> </pre>
<span class="n">wrenAbortFiber</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">text</span> <span class="o">=</span> <span class="n">wrenGetSlotString</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span> <p>We use <code>wrenGetSlotForeign()</code> to pull the foreign data out of the slot array.
<span class="n">fwrite</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span><span class="p">),</span> <span class="n">strlen</span><span class="p">(</span><span class="n">text</span><span class="p">),</span> <span class="o">*</span><span class="n">file</span><span class="p">);</span> Since this method is called on the file itself, the foreign object is in slot
<span class="p">}</span> zero. We take the resulting pointer and cast it to a pointer of the proper type.
</pre></div> Again, because our foreign data is <em>itself</em> a pointer, we get a pointer to a
pointer.</p>
<p>We do a little sanity checking to make sure the user isn&rsquo;t writing to a file
they already closed. If not, we call <code>fwrite()</code> to write to the file.</p>
<p>The other method is <code>close()</code> to let them explicitly close the file:</p>
<pre class="snippet" data-lang="c">
void fileClose(WrenVM* vm)
{
FILE** file = (FILE**)wrenGetSlotForeign(vm, 0);
closeFile(file);
}
</pre>
<p>It uses the same helper we defined above. And that&rsquo;s it, a complete foreign
class with a finalizer and a couple of foreign methods. In Wren, you can use it
like so:</p>
<pre class="snippet">
var file = File.create("some/path.txt")
file.write("some text")
file.close()
</pre>
<p>We use <code>wrenGetSlotForeign()</code> to pull the foreign data out of the slot array. <p>Pretty neat, right? The resulting class looks and feels like a normal Wren
Since this method is called on the file itself, the foreign object is in slot class, but it has the functionality and much of the performance of native C
zero. We take the resulting pointer and cast it to a pointer of the proper type. code.</p>
Again, because our foreign data is <em>itself</em> a pointer, we get a pointer to a <p><a class="right" href="configuring-the-vm.html">Configuring the VM &rarr;</a>
pointer. </p> <a href="calling-c-from-wren.html">&larr; Calling C from Wren</a></p>
<p>We do a little sanity checking to make sure the user isn&rsquo;t writing to a file
they already closed. If not, we call <code>fwrite()</code> to write to the file. </p>
<p>The other method is <code>close()</code> to let them explicitly close the file: </p>
<div class="codehilite"><pre><span class="kt">void</span> <span class="nf">fileClose</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">FILE</span><span class="o">**</span> <span class="n">file</span> <span class="o">=</span> <span class="p">(</span><span class="kt">FILE</span><span class="o">**</span><span class="p">)</span><span class="n">wrenGetSlotForeign</span><span class="p">(</span><span class="n">vm</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="n">closeFile</span><span class="p">(</span><span class="n">file</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
<p>It uses the same helper we defined above. And that&rsquo;s it, a complete foreign
class with a finalizer and a couple of foreign methods. In Wren, you can use it
like so: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">file</span> <span class="o">=</span> <span class="vg">File</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="s">&quot;some/path.txt&quot;</span><span class="p">)</span>
<span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot;some text&quot;</span><span class="p">)</span>
<span class="n">file</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
<p>Pretty neat, right? The resulting class looks and feels like a normal Wren
class, but it has the functionality and much of the performance of native C
code. </p>
<p><a class="right" href="configuring-the-vm.html">Configuring the VM &rarr;</a>
<a href="calling-c-from-wren.html">&larr; Calling C from Wren</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Error Handling &ndash; Wren</title> <title>Error Handling &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,154 +110,142 @@
</nav> </nav>
<main> <main>
<h2>Error Handling</h2> <h2>Error Handling</h2>
<p>Errors come in a few fun flavors. </p> <p>Errors come in a few fun flavors.</p>
<h2>Syntax errors <a href="#syntax-errors" name="syntax-errors" class="header-anchor">#</a></h2> <h2>Syntax errors <a href="#syntax-errors" name="syntax-errors" class="header-anchor">#</a></h2>
<p>The first errors you&rsquo;re likely to run into are syntax errors. These include <p>The first errors you&rsquo;re likely to run into are syntax errors. These include
simple bugs where your code doesn&rsquo;t follow the language&rsquo;s grammar, like: </p> simple bugs where your code doesn&rsquo;t follow the language&rsquo;s grammar, like:</p>
<div class="codehilite"><pre><span class="mi">1</span> <span class="o">+</span> <span class="o">*</span> <span class="mi">2</span> <pre class="snippet">
</pre></div> 1 + * 2
</pre>
<p>Wren detects these errors as soon as it tries to read your code. When it hits
one, you get a friendly error message, like:</p>
<pre><code>[main line 1] Error on '*': Unexpected token for expression.
</code></pre>
<p>Some slightly more &ldquo;semantic&rdquo; errors fall into this bucket too. Things like
using a variable that hasn&rsquo;t been defined, or declaring two variables with the
same name in the same scope. So if you do:</p>
<pre class="snippet">
var a = "once"
var a = "twice"
</pre>
<p>Wren detects these errors as soon as it tries to read your code. When it hits <p>Wren tells you:</p>
one, you get a friendly error message, like: </p> <pre><code>[main line 2] Error on 'a': Top-level variable is already defined.
<div class="codehilite"><pre>[main line 1] Error on &#39;*&#39;: Unexpected token for expression. </code></pre>
</pre></div> <p>Note that it does this before it executes <em>any</em> code. Unlike some other
scripting languages, Wren tries to help you find your errors as soon as
possible when it can.</p>
<p>Some slightly more &ldquo;semantic&rdquo; errors fall into this bucket too. Things like <p>If it starts running your code, you can be sure you don&rsquo;t have any errors
using a variable that hasn&rsquo;t been defined, or declaring two variables with the related to syntax or variable scope.</p>
same name in the same scope. So if you do: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="s">&quot;once&quot;</span>
<span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="s">&quot;twice&quot;</span>
</pre></div>
<p>Wren tells you: </p>
<div class="codehilite"><pre>[main line 2] Error on &#39;a&#39;: Top-level variable is already defined.
</pre></div>
<p>Note that it does this before it executes <em>any</em> code. Unlike some other
scripting languages, Wren tries to help you find your errors as soon as
possible when it can. </p>
<p>If it starts running your code, you can be sure you don&rsquo;t have any errors
related to syntax or variable scope. </p>
<h2>Runtime errors <a href="#runtime-errors" name="runtime-errors" class="header-anchor">#</a></h2> <h2>Runtime errors <a href="#runtime-errors" name="runtime-errors" class="header-anchor">#</a></h2>
<p>Alas, just fixing all of the &ldquo;compile-time&rdquo; errors doesn&rsquo;t mean your code does <p>Alas, just fixing all of the &ldquo;compile-time&rdquo; errors doesn&rsquo;t mean your code does
what you want. Your program may still have errors that can&rsquo;t be detected what you want. Your program may still have errors that can&rsquo;t be detected
statically. Since they can&rsquo;t be found until your code is run, they&rsquo;re called statically. Since they can&rsquo;t be found until your code is run, they&rsquo;re called
&ldquo;runtime&rdquo; errors. </p> &ldquo;runtime&rdquo; errors.</p>
<p>Most runtime errors come from the VM itself. They arise from code trying to <p>Most runtime errors come from the VM itself. They arise from code trying to
perform an operation that the VM can&rsquo;t do. The most common error is a &ldquo;method perform an operation that the VM can&rsquo;t do. The most common error is a &ldquo;method
not found&rdquo; one. If you call a method on an object and its class (and all of its not found&rdquo; one. If you call a method on an object and its class (and all of its
superclasses) don&rsquo;t define that method, there&rsquo;s nothing Wren can do: </p> superclasses) don&rsquo;t define that method, there&rsquo;s nothing Wren can do:</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Foo</span> <span class="p">{</span> <pre class="snippet">
<span class="k">construct</span> <span class="n">new</span><span class="p">()</span> <span class="p">{}</span> class Foo {
<span class="p">}</span> construct new() {}
}
<span class="k">var</span> <span class="n">foo</span> <span class="o">=</span> <span class="vg">Foo</span><span class="o">.</span><span class="n">new</span><span class="p">()</span> var foo = Foo.new()
<span class="n">foo</span><span class="o">.</span><span class="n">someRandomMethod</span> foo.someRandomMethod
</pre></div> </pre>
<p>If you run this, Wren will print:</p>
<pre><code>Foo does not implement method 'someRandomMethod'.
</code></pre>
<p>Then it stops executing code. Unlike some other languages, Wren doesn&rsquo;t keep
plugging away after a runtime error has occurred. A runtime error implies
there&rsquo;s a bug in your code and it wants to draw your attention to it. To help
you out, it prints a stack trace showing where in the code the error occurred,
and all of the method calls that led to it.</p>
<p>Another common runtime error is passing an argument of the wrong type to a
method. For example, lists are indexed using a number. If you try to pass some
other type, it&rsquo;s an error:</p>
<pre class="snippet">
var list = ["a", "b", "c"]
list["1"]
</pre>
<p>If you run this, Wren will print: </p> <p>This exits with:</p>
<div class="codehilite"><pre>Foo does not implement method &#39;someRandomMethod&#39;. <pre><code>Subscript must be a number or a range.
</pre></div>
<p>Then it stops executing code. Unlike some other languages, Wren doesn&rsquo;t keep
plugging away after a runtime error has occurred. A runtime error implies
there&rsquo;s a bug in your code and it wants to draw your attention to it. To help
you out, it prints a stack trace showing where in the code the error occurred,
and all of the method calls that led to it. </p>
<p>Another common runtime error is passing an argument of the wrong type to a
method. For example, lists are indexed using a number. If you try to pass some
other type, it&rsquo;s an error: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span>
<span class="n">list</span><span class="p">[</span><span class="s">&quot;1&quot;</span><span class="p">]</span>
</pre></div>
<p>This exits with: </p>
<div class="codehilite"><pre>Subscript must be a number or a range.
[main line 2] in (script) [main line 2] in (script)
</pre></div> </code></pre>
<p>These are the two most common kinds of runtime errors, but there are others.
Stuff like out of bounds errors on lists, calling a function with the wrong
<p>These are the two most common kinds of runtime errors, but there are others. number of arguments, etc.</p>
Stuff like out of bounds errors on lists, calling a function with the wrong
number of arguments, etc. </p>
<h2>Handling runtime errors <a href="#handling-runtime-errors" name="handling-runtime-errors" class="header-anchor">#</a></h2> <h2>Handling runtime errors <a href="#handling-runtime-errors" name="handling-runtime-errors" class="header-anchor">#</a></h2>
<p>Most of the time, runtime errors indicate a bug in your code and the best <p>Most of the time, runtime errors indicate a bug in your code and the best
solution is to fix the bug. However, sometimes it&rsquo;s useful to be able to handle solution is to fix the bug. However, sometimes it&rsquo;s useful to be able to handle
them at, uh, runtime. </p> them at, uh, runtime.</p>
<p>To keep the language simpler, Wren does not have exception handling. Instead, it <p>To keep the language simpler, Wren does not have exception handling. Instead, it
takes advantage of <a href="concurrency.html">fibers</a> for handling errors. When a runtime error occurs, takes advantage of <a href="concurrency.html">fibers</a> for handling errors. When a runtime error occurs,
the current fiber is aborted. Normally, Wren will also abort any fibers that the current fiber is aborted. Normally, Wren will also abort any fibers that
invoked that one, all the way to the main fiber, and then exit the VM. </p> invoked that one, all the way to the main fiber, and then exit the VM.</p>
<p>However, you can run a fiber using the <code>try</code> method. If a runtime error occurs <p>However, you can run a fiber using the <code>try</code> method. If a runtime error occurs
in the called fiber, the error is captured and the <code>try</code> method returns the in the called fiber, the error is captured and the <code>try</code> method returns the
error message as a string. </p> error message as a string.</p>
<p>For example, if you run this program: </p> <p>For example, if you run this program:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="mi">123</span><span class="o">.</span><span class="n">badMethod</span> var fiber = Fiber.new {
<span class="p">}</span> 123.badMethod
}
<span class="k">var</span> <span class="n">error</span> <span class="o">=</span> <span class="n">fiber</span><span class="o">.</span><span class="n">try</span><span class="p">()</span> var error = fiber.try()
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Caught error: &quot;</span> <span class="o">+</span> <span class="n">error</span><span class="p">)</span> System.print("Caught error: " + error)
</pre></div> </pre>
<p>It prints:</p>
<pre><code>Caught error: Num does not implement method 'badMethod'.
</code></pre>
<p>The called fiber can no longer be used, but any other fibers can proceed as
usual. When a fiber has been aborted because of a runtime error, you can also
get the error from the fiber object. Continuing the above example:</p>
<pre class="snippet">
System.print(fiber.error)
</pre>
<p>It prints: </p> <p>This also prints:</p>
<div class="codehilite"><pre>Caught error: Num does not implement method &#39;badMethod&#39;. <pre><code>Num does not implement method 'badMethod'.
</pre></div> </code></pre>
<p>If you have a chain of fiber calls and a runtime error occurs, it will walk the
chain looking for a <code>try</code> call, so this can also be used to capture runtime
<p>The called fiber can no longer be used, but any other fibers can proceed as errors generated in fibers that are invoked by the one you called <code>try</code> on.</p>
usual. When a fiber has been aborted because of a runtime error, you can also
get the error from the fiber object. Continuing the above example: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">fiber</span><span class="o">.</span><span class="n">error</span><span class="p">)</span>
</pre></div>
<p>This also prints: </p>
<div class="codehilite"><pre>Num does not implement method &#39;badMethod&#39;.
</pre></div>
<p>If you have a chain of fiber calls and a runtime error occurs, it will walk the
chain looking for a <code>try</code> call, so this can also be used to capture runtime
errors generated in fibers that are invoked by the one you called <code>try</code> on. </p>
<h2>Creating runtime errors <a href="#creating-runtime-errors" name="creating-runtime-errors" class="header-anchor">#</a></h2> <h2>Creating runtime errors <a href="#creating-runtime-errors" name="creating-runtime-errors" class="header-anchor">#</a></h2>
<p>Most runtime errors come from within the Wren VM, but you may want to be able <p>Most runtime errors come from within the Wren VM, but you may want to be able
to cause your own runtime errors to occur. This can be done by calling the to cause your own runtime errors to occur. This can be done by calling the
<code>abort()</code> static method on <code>Fiber</code>: </p> <code>abort()</code> static method on <code>Fiber</code>:</p>
<div class="codehilite"><pre><span class="vg">Fiber</span><span class="o">.</span><span class="n">abort</span><span class="p">(</span><span class="s">&quot;Something bad happened&quot;</span><span class="p">)</span> <pre class="snippet">
</pre></div> Fiber.abort("Something bad happened")
</pre>
<p>You must pass in an error message, and it must be a string.</p>
<p>You must pass in an error message, and it must be a string. </p> <p>If the provided message is <code>null</code>, no runtime error is raised.</p>
<p>If the provided message is <code>null</code>, no runtime error is raised. </p>
<h2>Failures <a href="#failures" name="failures" class="header-anchor">#</a></h2> <h2>Failures <a href="#failures" name="failures" class="header-anchor">#</a></h2>
<p>The last flavor of errors is the highest-level one. All of the above errors <p>The last flavor of errors is the highest-level one. All of the above errors
indicate <em>bugs</em>&mdash;places where the code itself is incorrect. But some indicate <em>bugs</em>&mdash;places where the code itself is incorrect. But some
errors indicate that the code simply couldn&rsquo;t accomplish its task for errors indicate that the code simply couldn&rsquo;t accomplish its task for
unforeseeable reasons. We&rsquo;ll call these &ldquo;failures&rdquo;. </p> unforeseeable reasons. We&rsquo;ll call these &ldquo;failures&rdquo;.</p>
<p>Consider a program that reads in a string of input from the user and parses it <p>Consider a program that reads in a string of input from the user and parses it
to a number. Many strings are not valid numbers, so this parsing can fail. The to a number. Many strings are not valid numbers, so this parsing can fail. The
only way the program could prevent that failure is by validating the string only way the program could prevent that failure is by validating the string
before its parsed, but validating that a string is a number is pretty much the before its parsed, but validating that a string is a number is pretty much the
same thing as parsing it. </p> same thing as parsing it.</p>
<p>For cases like this where failure can occur and the program <em>will</em> want to <p>For cases like this where failure can occur and the program <em>will</em> want to
handle it, fibers and <code>try()</code> are too coarse-grained to work with. Instead, handle it, fibers and <code>try()</code> are too coarse-grained to work with. Instead,
these operations will indicate failure by <em>returning</em> some sort of error these operations will indicate failure by <em>returning</em> some sort of error
indication. </p> indication.</p>
<p>For example, a method for parsing a number could return a number on success and <p>For example, a method for parsing a number could return a number on success and
<code>null</code> to indicate parsing failed. Since Wren is dynamically typed, it&rsquo;s easy <code>null</code> to indicate parsing failed. Since Wren is dynamically typed, it&rsquo;s easy
and natural for a method to return different types of values. </p> and natural for a method to return different types of values.</p>
<p><br><hr> <p><br><hr>
<a class="right" href="modularity.html">Modularity &rarr;</a> <a class="right" href="modularity.html">Modularity &rarr;</a>
<a href="concurrency.html">&larr; Concurrency</a> </p> <a href="concurrency.html">&larr; Concurrency</a></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Functions &ndash; Wren</title> <title>Functions &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,160 +110,160 @@
</nav> </nav>
<main> <main>
<h2>Functions</h2> <h2>Functions</h2>
<p>No self-respecting language today can get by without functions&mdash;first <p>No self-respecting language today can get by without functions&mdash;first
class little bundles of code. Since Wren is object-oriented, most of your code class little bundles of code. Since Wren is object-oriented, most of your code
will live in methods on classes, but free-floating functions are still will live in methods on classes, but free-floating functions are still
eminently handy. </p> eminently handy.</p>
<p>Functions are objects like everything else in Wren, instances of the <code>Fn</code> <p>Functions are objects like everything else in Wren, instances of the <code>Fn</code>
class. </p> class.</p>
<h2>Block arguments <a href="#block-arguments" name="block-arguments" class="header-anchor">#</a></h2> <h2>Block arguments <a href="#block-arguments" name="block-arguments" class="header-anchor">#</a></h2>
<p>Most of the time you create a function just to pass it to some method. For <p>Most of the time you create a function just to pass it to some method. For
example, if you want to filter a <a href="lists.html">list</a> by some criteria, you&rsquo;ll example, if you want to filter a <a href="lists.html">list</a> by some criteria, you&rsquo;ll
call its <code>where</code> method, passing in a function that defines the predicate call its <code>where</code> method, passing in a function that defines the predicate
you&rsquo;re filtering on. </p> you&rsquo;re filtering on.</p>
<p>Since that&rsquo;s the most common usage pattern, Wren&rsquo;s syntax optimizes for that. <p>Since that&rsquo;s the most common usage pattern, Wren&rsquo;s syntax optimizes for that.
Taking a page from Ruby, a function is created by passing a <em>block argument</em> to Taking a page from Ruby, a function is created by passing a <em>block argument</em> to
a method. At its simplest, it looks like this: </p> a method. At its simplest, it looks like this:</p>
<div class="codehilite"><pre><span class="n">blondie</span><span class="o">.</span><span class="n">callMe</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;This is the body!&quot;</span><span class="p">)</span> blondie.callMe {
<span class="p">}</span> System.print("This is the body!")
</pre></div> }
</pre>
<p>Here we&rsquo;re invoking the <code>callMe</code> method on <code>blondie</code>. We&rsquo;re passing one
argument, a function whose body is the
following <a href="syntax.html#blocks">block</a>&mdash;everything between that pair of
curly braces.</p>
<p>Methods that take a block argument receive it as a normal parameter. <code>callMe</code>
could be defined like so:</p>
<pre class="snippet">
class Blondie {
callMe(fn) {
// Call it...
}
}
<p>Here we&rsquo;re invoking the <code>callMe</code> method on <code>blondie</code>. We&rsquo;re passing one var blondie = Blondie.new()
argument, a function whose body is the </pre>
following <a href="syntax.html#blocks">block</a>&mdash;everything between that pair of
curly braces. </p>
<p>Methods that take a block argument receive it as a normal parameter. <code>callMe</code>
could be defined like so: </p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Blondie</span> <span class="p">{</span>
<span class="n">callMe</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Call it...</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">var</span> <span class="n">blondie</span> <span class="o">=</span> <span class="vg">Blondie</span><span class="o">.</span><span class="n">new</span><span class="p">()</span> <p>A method can take other arguments in addition to the block. They appear before
</pre></div> the block just like a regular argument list. For example:</p>
<pre class="snippet">
blondie.callMeAt(867, 5309) {
System.print("This is the body!")
}
</pre>
<p>Of course, you don&rsquo;t <em>have</em> to use a block argument to pass a function to a
method. If you already have a function object, you can pass it like a regular
argument:</p>
<pre class="snippet">
var someFn = // Get a function...
blondie.callMe(someFn)
</pre>
<p>A method can take other arguments in addition to the block. They appear before <p>Block arguments are purely sugar for creating a function and passing it in one
the block just like a regular argument list. For example: </p> little blob of syntax. There are some times when you want to create a function
<div class="codehilite"><pre><span class="n">blondie</span><span class="o">.</span><span class="n">callMeAt</span><span class="p">(</span><span class="mi">867</span><span class="p">,</span> <span class="mi">5309</span><span class="p">)</span> <span class="p">{</span> but <em>don&rsquo;t</em> need to pass it to a method. For that, you can call the <code>Fn</code>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;This is the body!&quot;</span><span class="p">)</span> class&rsquo;s constructor:</p>
<span class="p">}</span> <pre class="snippet">
</pre></div> var someFn = Fn.new {
System.print("Hi!")
}
</pre>
<p>As you can see it takes a block argument too! All the constructor does it
<p>Of course, you don&rsquo;t <em>have</em> to use a block argument to pass a function to a return that, so this exists purely as a convenience method for you.</p>
method. If you already have a function object, you can pass it like a regular
argument: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">someFn</span> <span class="o">=</span> <span class="c1">// Get a function...</span>
<span class="n">blondie</span><span class="o">.</span><span class="n">callMe</span><span class="p">(</span><span class="n">someFn</span><span class="p">)</span>
</pre></div>
<p>Block arguments are purely sugar for creating a function and passing it in one
little blob of syntax. There are some times when you want to create a function
but <em>don&rsquo;t</em> need to pass it to a method. For that, you can call the <code>Fn</code>
class&rsquo;s constructor: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">someFn</span> <span class="o">=</span> <span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Hi!&quot;</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
<p>As you can see it takes a block argument too! All the constructor does it
return that, so this exists purely as a convenience method for you. </p>
<h2>Calling functions <a href="#calling-functions" name="calling-functions" class="header-anchor">#</a></h2> <h2>Calling functions <a href="#calling-functions" name="calling-functions" class="header-anchor">#</a></h2>
<p>Once you have a function, how do you invoke it? Like everything in Wren, you do <p>Once you have a function, how do you invoke it? Like everything in Wren, you do
so by calling a method on it: </p> so by calling a method on it:</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Blondie</span> <span class="p">{</span> <pre class="snippet">
<span class="n">callMe</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span> <span class="p">{</span> class Blondie {
<span class="n">fn</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> callMe(fn) {
<span class="p">}</span> fn.call()
<span class="p">}</span> }
</pre></div> }
</pre>
<p>Functions expose a <code>call()</code> method that executes the body of the function. This
method is dynamically-dispatched like any other, so you can define your own
&ldquo;function-like&rdquo; classes and pass them to methods that expect &ldquo;real&rdquo; functions.</p>
<pre class="snippet">
class FakeFn {
call() {
System.print("I'm feeling functional!")
}
}
<p>Functions expose a <code>call()</code> method that executes the body of the function. This blondie.callMe(FakeFn.new())
method is dynamically-dispatched like any other, so you can define your own </pre>
&ldquo;function-like&rdquo; classes and pass them to methods that expect &ldquo;real&rdquo; functions. </p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">FakeFn</span> <span class="p">{</span>
<span class="n">call</span><span class="p">()</span> <span class="p">{</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;I&#39;m feeling functional!&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="n">blondie</span><span class="o">.</span><span class="n">callMe</span><span class="p">(</span><span class="vg">FakeFn</span><span class="o">.</span><span class="n">new</span><span class="p">())</span>
</pre></div>
<h2>Function parameters <a href="#function-parameters" name="function-parameters" class="header-anchor">#</a></h2> <h2>Function parameters <a href="#function-parameters" name="function-parameters" class="header-anchor">#</a></h2>
<p>Of course, functions aren&rsquo;t very useful if you can&rsquo;t pass values to them. The <p>Of course, functions aren&rsquo;t very useful if you can&rsquo;t pass values to them. The
functions that we&rsquo;ve seen so far take no arguments. To change that, you can functions that we&rsquo;ve seen so far take no arguments. To change that, you can
provide a parameter list surrounded by <code>|</code> immediately after the opening brace provide a parameter list surrounded by <code>|</code> immediately after the opening brace
of the body, like so: </p> of the body, like so:</p>
<div class="codehilite"><pre><span class="n">blondie</span><span class="o">.</span><span class="n">callMe</span> <span class="p">{</span><span class="o">|</span><span class="n">first</span><span class="p">,</span> <span class="n">last</span><span class="o">|</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Hi, &quot;</span> <span class="o">+</span> <span class="n">first</span> <span class="o">+</span> <span class="s">&quot; &quot;</span> <span class="o">+</span> <span class="n">last</span> <span class="o">+</span> <span class="s">&quot;!&quot;</span><span class="p">)</span> blondie.callMe {|first, last|
<span class="p">}</span> System.print("Hi, " + first + " " + last + "!")
</pre></div> }
</pre>
<p>Here we&rsquo;re passing a function to <code>callMe</code> that takes two parameters, <code>first</code> and
<code>last</code>. They are passed to the function when it&rsquo;s called:</p>
<pre class="snippet">
class Blondie {
callMe(fn) {
fn.call("Debbie", "Harry")
}
}
</pre>
<p>Here we&rsquo;re passing a function to <code>callMe</code> that takes two parameters, <code>first</code> and <p>It&rsquo;s an error to call a function with fewer arguments than its parameter list
<code>last</code>. They are passed to the function when it&rsquo;s called: </p> expects. If you pass too <em>many</em> arguments, the extras are ignored.</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Blondie</span> <span class="p">{</span>
<span class="n">callMe</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fn</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;Debbie&quot;</span><span class="p">,</span> <span class="s">&quot;Harry&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>It&rsquo;s an error to call a function with fewer arguments than its parameter list
expects. If you pass too <em>many</em> arguments, the extras are ignored. </p>
<h2>Returning values <a href="#returning-values" name="returning-values" class="header-anchor">#</a></h2> <h2>Returning values <a href="#returning-values" name="returning-values" class="header-anchor">#</a></h2>
<p>The body of a function is a <a href="syntax.html#blocks">block</a>. If it is a single <p>The body of a function is a <a href="syntax.html#blocks">block</a>. If it is a single
expression&mdash;more precisely if there is no newline after the <code>{</code> or expression&mdash;more precisely if there is no newline after the <code>{</code> or
parameter list&mdash;then the function implicitly returns the value of the parameter list&mdash;then the function implicitly returns the value of the
expression. </p> expression.</p>
<p>Otherwise, the body returns <code>null</code> by default. You can explicitly return a <p>Otherwise, the body returns <code>null</code> by default. You can explicitly return a
value using a <code>return</code> statement. In other words, these two functions do the value using a <code>return</code> statement. In other words, these two functions do the
same thing: </p> same thing:</p>
<div class="codehilite"><pre><span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <span class="s">&quot;return value&quot;</span> <span class="p">}</span> <pre class="snippet">
Fn.new { "return value" }
<span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span>
<span class="k">return</span> <span class="s">&quot;return value&quot;</span>
<span class="p">}</span>
</pre></div>
Fn.new {
return "return value"
}
</pre>
<h2>Closures <a href="#closures" name="closures" class="header-anchor">#</a></h2> <h2>Closures <a href="#closures" name="closures" class="header-anchor">#</a></h2>
<p>As you expect, functions are closures&mdash;they can access variables defined <p>As you expect, functions are closures&mdash;they can access variables defined
outside of their scope. They will hold onto closed-over variables even after outside of their scope. They will hold onto closed-over variables even after
leaving the scope where the function is defined: </p> leaving the scope where the function is defined:</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Counter</span> <span class="p">{</span> <pre class="snippet">
<span class="k">static</span> <span class="n">create</span><span class="p">()</span> <span class="p">{</span> class Counter {
<span class="k">var</span> <span class="err">i</span> <span class="o">=</span> <span class="mi">0</span> static create() {
<span class="k">return</span> <span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <span class="err">i</span> <span class="o">=</span> <span class="err">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="p">}</span> var i = 0
<span class="p">}</span> return Fn.new { i = i + 1 }
<span class="p">}</span> }
</pre></div> }
</pre>
<p>Here, the <code>create</code> method returns the function created on its second line. That
function references a variable <code>i</code> declared outside of the function. Even after
the function is returned from <code>create</code>, it is still able to read and assign
to<code>i</code>:</p>
<pre class="snippet">
var counter = Counter.create()
System.print(counter.call()) //> 1
System.print(counter.call()) //> 2
System.print(counter.call()) //> 3
</pre>
<p>Here, the <code>create</code> method returns the function created on its second line. That <p><br><hr>
function references a variable <code>i</code> declared outside of the function. Even after <a class="right" href="classes.html">Classes &rarr;</a>
the function is returned from <code>create</code>, it is still able to read and assign <a href="variables.html">&larr; Variables</a></p>
to<code>i</code>: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">counter</span> <span class="o">=</span> <span class="vg">Counter</span><span class="o">.</span><span class="n">create</span><span class="p">()</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">counter</span><span class="o">.</span><span class="n">call</span><span class="p">())</span> <span class="output">1</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">counter</span><span class="o">.</span><span class="n">call</span><span class="p">())</span> <span class="output">2</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">counter</span><span class="o">.</span><span class="n">call</span><span class="p">())</span> <span class="output">3</span>
</pre></div>
<p><br><hr>
<a class="right" href="classes.html">Classes &rarr;</a>
<a href="variables.html">&larr; Variables</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Getting Started &ndash; Wren</title> <title>Getting Started &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,100 +110,66 @@
</nav> </nav>
<main> <main>
<h2>Getting Started</h2> <h2>Getting Started</h2>
<p>Getting Wren running on your machine is straightforward. Tiny C programs with <h2>Trying out the language <a href="#trying-out-the-language" name="trying-out-the-language" class="header-anchor">#</a></h2>
few dependencies are nice that way. &ldquo;Wren&rdquo; encompasses two separate artifacts: </p> <p>If you&rsquo;d like to try Wren, you have a few options.</p>
<ul> <ul>
<li> <li><strong>In your browser.</strong> You can try Wren <strong><a href="./try/">right here</a></strong>!</li>
<p><strong>The virtual machine.</strong> This is the core chunk of C that executes Wren <li><strong>On your computer.</strong> The <a href="cli">Wren CLI</a> project is a downloadable executable
source code. It is just a library, not a standalone application. It&rsquo;s to run scripts with access to file io and more. See the <a href="cli">Wren CLI docs</a>.</li>
designed to be <a href="embedding">embedded</a> in a larger host application. It has no <li><strong>Embedded in your code.</strong> See how to <a href="#embed-the-vm">build and embed Wren</a> below. <br />
dependencies beyond the C standard library. You can use it as a static And then read the <a href="embedding">embedding guide</a>!</li>
library, shared library, or simply compile the source into your app. </p>
</li>
<li>
<p><strong>The command line executable.</strong> Wren also ships with a CLI wrapper around
the VM. This gives you a way to run Wren code from the command-line, and
also includes modules for talking to the operating system&mdash;file IO,
networking, stuff like that. It depends on <a href="http://libuv.org/">libuv</a> for that
functionality. </p>
</li>
</ul> </ul>
<p>If you&rsquo;re on a Unix or Mac and you can rock a command line, it&rsquo;s just: </p> <p>Once you have somewhere to explore, it&rsquo;s time to <a href="syntax.html">learn the
<div class="codehilite"><pre><span class="nv">$ </span>git clone https://github.com/wren-lang/wren.git language</a>.</p>
<span class="nv">$ </span><span class="nb">cd </span>wren <hr />
<span class="nv">$ </span>make <h2>Embed the VM <a href="#embed-the-vm" name="embed-the-vm" class="header-anchor">#</a></h2>
<span class="nv">$ </span>./wren <p><strong>The Wren Virtual Machine</strong> is the core of the language that executes Wren
</pre></div> source code. It is just a library, not a standalone application. It&rsquo;s
designed to be <a href="embedding">embedded</a> in a larger host application.</p>
<p>It has no dependencies beyond the C standard library.
<p>This builds both the VM and the CLI. The release build of the CLI goes right You can use it as a static library, shared library, or simply compile the source into your app.</p>
into the repo&rsquo;s top level directory. Binaries for other configurations are built <h3>Building Wren <a href="#building-wren" name="building-wren" class="header-anchor">#</a></h3>
to <code>bin/</code>. Static and shared libraries for embedding Wren get built in <code>lib/</code>. </p> <p>To build the Wren library, we look inside the <code>projects/</code> folder.
<p>For Mac users, there is also an XCode project under <code>util/xcode</code>. For In here you&rsquo;ll find ready to go projects for <code>Visual Studio</code>, <code>XCode</code> and tools like <code>make</code>.</p>
Windows brethren, <code>util/vs2017</code> contains a Visual Studio solution. Note
that these may not have the exact same build settings as the makefile. The
makefile is the &ldquo;official&rdquo; way to compile Wren. </p>
<p>If you only want to build the VM, you can do: </p>
<div class="codehilite"><pre><span class="nv">$ </span>make vm
</pre></div>
<p>This compiles the VM to static and shared libraries. </p>
<h2>Interactive mode <a href="#interactive-mode" name="interactive-mode" class="header-anchor">#</a></h2>
<p>If you just run <code>wren</code> without any arguments, it starts the interpreter in
interactive mode. You can type in a line of code, and it immediately executes
it. Here&rsquo;s something to try: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Hello, world!&quot;</span><span class="p">)</span>
</pre></div>
<p>Or a little more exciting: </p>
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="err">i</span> <span class="k">in</span> <span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">)</span> <span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Counting up </span><span class="si">%(</span><span class="err">i</span><span class="si">)</span><span class="s">&quot;</span><span class="p">)</span>
</pre></div>
<p>You can exit the interpreter using good old Ctrl-C or Ctrl-D, or just throw
your computer to the ground and storm off. </p>
<h2>Running scripts <a href="#running-scripts" name="running-scripts" class="header-anchor">#</a></h2>
<p>The standalone interpreter can also load scripts from files and run them. Just
pass the name of the script to <code>wren</code>. Create a file named &ldquo;my_script.wren&rdquo; in
your favorite text editor and paste this into it: </p>
<div class="codehilite"><pre><span class="k">for</span> <span class="p">(</span><span class="n">yPixel</span> <span class="k">in</span> <span class="mi">0</span><span class="o">...</span><span class="mi">24</span><span class="p">)</span> <span class="p">{</span>
<span class="k">var</span> <span class="err">y</span> <span class="o">=</span> <span class="n">yPixel</span> <span class="o">/</span> <span class="mi">12</span> <span class="o">-</span> <span class="mi">1</span>
<span class="k">for</span> <span class="p">(</span><span class="n">xPixel</span> <span class="k">in</span> <span class="mi">0</span><span class="o">...</span><span class="mi">80</span><span class="p">)</span> <span class="p">{</span>
<span class="k">var</span> <span class="err">x</span> <span class="o">=</span> <span class="n">xPixel</span> <span class="o">/</span> <span class="mi">30</span> <span class="o">-</span> <span class="mi">2</span>
<span class="k">var</span> <span class="n">x0</span> <span class="o">=</span> <span class="err">x</span>
<span class="k">var</span> <span class="n">y0</span> <span class="o">=</span> <span class="err">y</span>
<span class="k">var</span> <span class="n">iter</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="p">(</span><span class="n">iter</span> <span class="o">&lt;</span> <span class="mi">11</span> <span class="o">&amp;&amp;</span> <span class="n">x0</span> <span class="o">*</span> <span class="n">x0</span> <span class="o">+</span> <span class="n">y0</span> <span class="o">*</span> <span class="n">y0</span> <span class="o">&lt;=</span> <span class="mi">4</span><span class="p">)</span> <span class="p">{</span>
<span class="k">var</span> <span class="n">x1</span> <span class="o">=</span> <span class="p">(</span><span class="n">x0</span> <span class="o">*</span> <span class="n">x0</span><span class="p">)</span> <span class="o">-</span> <span class="p">(</span><span class="n">y0</span> <span class="o">*</span> <span class="n">y0</span><span class="p">)</span> <span class="o">+</span> <span class="err">x</span>
<span class="k">var</span> <span class="n">y1</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">x0</span> <span class="o">*</span> <span class="n">y0</span> <span class="o">+</span> <span class="err">y</span>
<span class="n">x0</span> <span class="o">=</span> <span class="n">x1</span>
<span class="n">y0</span> <span class="o">=</span> <span class="n">y1</span>
<span class="n">iter</span> <span class="o">=</span> <span class="n">iter</span> <span class="o">+</span> <span class="mi">1</span>
<span class="p">}</span>
<span class="vg">System</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&quot; .-:;+=xX$&amp; &quot;</span><span class="p">[</span><span class="n">iter</span><span class="p">])</span>
<span class="p">}</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
<p>Now run: </p>
<div class="codehilite"><pre><span class="nv">$ </span>./wren my_script.wren
</pre></div>
<p>Neat, right? You&rsquo;re a Wren programmer now! The next step is to <a href="syntax.html">learn the
language</a>. If you run into bugs, or have ideas or questions, any of
the following work: </p>
<ul> <ul>
<li><strong>Ask on the <a href="https://groups.google.com/forum/#!forum/wren-lang">Wren mailing list</a>.</strong> </li> <li><strong>Windows</strong> Open <code>wren.sln</code> inside <code>projects/vs2019/</code> (or <code>vs2017</code>), hit build.</li>
<li>Tell me on twitter at <a href="https://twitter.com/intent/user?screen_name=munificentbob">@munificentbob</a>. </li> <li><strong>Mac</strong> Open <code>wren.xcworkspace</code> inside <code>projects/xcode/</code>, hit build.</li>
<li><a href="https://github.com/wren-lang/wren/issues">File a ticket</a> at <a href="https://github.com/wren-lang/wren">the GitHub repo</a>. </li> <li><strong>Linux</strong> Run <code>make</code> inside of <code>projects/make/</code>.</li>
<li>Send a pull request. </li> </ul>
<li>Email me at <a href="mailto:robert@stuffwithstuff.com"><code>robert@stuffwithstuff.com</code></a>. </li> <p>In each case, <strong>there will be library files generated into the root <code>lib/</code> folder</strong>. <br />
These are what you&rsquo;ll link into your project, based on your needs.</p>
<ul>
<li><strong>Static Linking</strong> <code>wren.lib</code> on Windows, <code>libwren.a</code> elsewhere.</li>
<li><strong>Dynamic Linking</strong> <code>wren.dll</code> on Windows, <code>libwren.so</code> on Linux, and <code>libwren.dylib</code> on Mac.</li>
</ul>
<p><small>
Note that the default build will also generate <code>wren_test</code> inside of <code>bin/</code>, <br />
a binary that is used to run the language tests. It can execute simple scripts.
</small></p>
<p><strong>Other platforms</strong> <br />
If your platform isn&rsquo;t explicitly supported,
it is recommended that you include the Wren source
in your project for a portable experience.</p>
<h3>Including the code in your project <a href="#including-the-code-in-your-project" name="including-the-code-in-your-project" class="header-anchor">#</a></h3>
<p><strong>all source files</strong> <br />
The alternative to building via the provided projects is to include the wren source code in your project.
Since it has no dependencies this is simple, all the code in <code>src/</code> comes along. There&rsquo;s a readme in <code>src/</code> for details.</p>
<p><strong>&rsquo;amalgamated&rsquo; build</strong> <br />
If you want an even simpler way, there&rsquo;s an &lsquo;amalgamated&rsquo; build (often called <code>blob</code>, or <code>unity</code> builds.).
This is <em>all of the wren source code in one file</em>.</p>
<p>This file can be generated by running <code>python3 util/generate_amalgamation.py</code>, and the generated output will be in <code>build/wren.c</code>.
Include <code>build/wren.c</code> and <code>src/include/wren.h</code> in your project code and you&rsquo;re good to go.
<small>Ideally later we can automate generating this and include it in the repo.</small></p>
<hr />
<p>If you run into bugs, or have ideas or questions, any of
the following work:</p>
<ul>
<li>Join the <a href="https://discord.gg/Kx6PxSX">discord community</a>.</li>
<li>Ask on the <a href="https://groups.google.com/forum/#!forum/wren-lang">Wren mailing list</a> (which is pretty quiet).</li>
<li>Tell us on twitter at <a href="https://twitter.com/intent/user?screen_name=munificentbob">@munificentbob</a> or <a href="https://twitter.com/intent/user?screen_name=ruby0x1">@ruby0x1</a>.</li>
<li><a href="https://github.com/wren-lang/wren/issues">File a ticket</a> at <a href="https://github.com/wren-lang/wren">the GitHub repo</a>.</li>
<li>The CLI also has <a href="https://github.com/wren-lang/wren-cli/issues">tickets</a> and a <a href="https://github.com/wren-lang/wren-cli">GitHub repo</a> too.</li>
<li>Pull requests are welcome.</li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title> &ndash; Wren</title> <title> &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -100,56 +112,56 @@
<h2></h2> <h2></h2>
<h2>Wren is a small, fast, class-based concurrent scripting language <a href="#wren-is-a-small,-fast,-class-based-concurrent-scripting-language" name="wren-is-a-small,-fast,-class-based-concurrent-scripting-language" class="header-anchor">#</a></h2> <h2>Wren is a small, fast, class-based concurrent scripting language <a href="#wren-is-a-small,-fast,-class-based-concurrent-scripting-language" name="wren-is-a-small,-fast,-class-based-concurrent-scripting-language" class="header-anchor">#</a></h2>
<hr /> <hr />
<p>Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in <p>Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in
a familiar, modern <a href="syntax.html">syntax</a>. </p> a familiar, modern <a href="syntax.html">syntax</a>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Hello, world!&quot;</span><span class="p">)</span> <pre class="snippet">
System.print("Hello, world!")
<span class="k">class</span> <span class="vg">Wren</span> <span class="p">{</span> class Wren {
<span class="n">flyTo</span><span class="p">(</span><span class="n">city</span><span class="p">)</span> <span class="p">{</span> flyTo(city) {
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Flying to </span><span class="si">%(</span><span class="n">city</span><span class="si">)</span><span class="s">&quot;</span><span class="p">)</span> System.print("Flying to %(city)")
<span class="p">}</span> }
<span class="p">}</span> }
<span class="k">var</span> <span class="n">adjectives</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> var adjectives = Fiber.new {
<span class="p">[</span><span class="s">&quot;small&quot;</span><span class="p">,</span> <span class="s">&quot;clean&quot;</span><span class="p">,</span> <span class="s">&quot;fast&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span><span class="o">|</span><span class="n">word</span><span class="o">|</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">(</span><span class="n">word</span><span class="p">)</span> <span class="p">}</span> ["small", "clean", "fast"].each {|word| Fiber.yield(word) }
<span class="p">}</span> }
<span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">adjectives</span><span class="o">.</span><span class="n">isDone</span><span class="p">)</span> <span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">adjectives</span><span class="o">.</span><span class="n">call</span><span class="p">())</span>
</pre></div>
while (!adjectives.isDone) System.print(adjectives.call())
</pre>
<ul> <ul>
<li> <li>
<p><strong>Wren is small.</strong> The VM implementation is under <a href="https://github.com/wren-lang/wren/tree/master/src">4,000 semicolons</a>. <p><strong>Wren is small.</strong> The VM implementation is under <a href="https://github.com/wren-lang/wren/tree/master/src">4,000 semicolons</a>.
You can skim the whole thing in an afternoon. It&rsquo;s <em>small</em>, but not You can skim the whole thing in an afternoon. It&rsquo;s <em>small</em>, but not
<em>dense</em>. It is readable and <a href="https://github.com/wren-lang/wren/blob/46c1ba92492e9257aba6418403161072d640cb29/src/wren_value.h#L378-L433">lovingly-commented</a>. </p> <em>dense</em>. It is readable and <a href="https://github.com/wren-lang/wren/blob/46c1ba92492e9257aba6418403161072d640cb29/src/wren_value.h#L378-L433">lovingly-commented</a>.</p>
</li> </li>
<li> <li>
<p><strong>Wren is fast.</strong> A fast single-pass compiler to tight bytecode, and a <p><strong>Wren is fast.</strong> A fast single-pass compiler to tight bytecode, and a
compact object representation help Wren <a href="performance.html">compete with other dynamic compact object representation help Wren <a href="performance.html">compete with other dynamic
languages</a>. </p> languages</a>.</p>
</li> </li>
<li> <li>
<p><strong>Wren is class-based.</strong> There are lots of scripting languages out there, <p><strong>Wren is class-based.</strong> There are lots of scripting languages out there,
but many have unusual or non-existent object models. Wren places but many have unusual or non-existent object models. Wren places
<a href="classes.html">classes</a> front and center. </p> <a href="classes.html">classes</a> front and center.</p>
</li> </li>
<li> <li>
<p><strong>Wren is concurrent.</strong> Lightweight <a href="concurrency.html">fibers</a> are core to the execution <p><strong>Wren is concurrent.</strong> Lightweight <a href="concurrency.html">fibers</a> are core to the execution
model and let you organize your program into an army of communicating model and let you organize your program into a flock of communicating
coroutines. </p> coroutines.</p>
</li> </li>
<li> <li>
<p><strong>Wren is a scripting language.</strong> Wren is intended for embedding in <p><strong>Wren is a scripting language.</strong> Wren is intended for embedding in
applications. It has no dependencies, a small standard library, applications. It has no dependencies, a small standard library,
and <a href="embedding">an easy-to-use C API</a>. It compiles cleanly as C99, C++98 and <a href="embedding">an easy-to-use C API</a>. It compiles cleanly as C99, C++98
or anything later. </p> or anything later.</p>
</li> </li>
</ul> </ul>
<hr /> <hr />
<p>If you like the sound of this, <a href="getting-started.html">let&rsquo;s get started</a>. You can even try <p>You can try it <a href="try">in your browser</a>! <br />
it <a href="http://ppvk.github.io/wren-nest/">in your browser</a>! Excited? Well, come on and <a href="contributing.html">get If you like the sound of this, <a href="getting-started.html">let&rsquo;s get started</a>. <br />
involved</a>! </p> Excited? You&rsquo;re also welcome to <a href="contributing.html">get involved</a>!</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Lists &ndash; Wren</title> <title>Lists &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,120 +110,120 @@
</nav> </nav>
<main> <main>
<h2>Lists</h2> <h2>Lists</h2>
<p>A list is a compound object that holds a collection of elements identified by <p>A list is a compound object that holds a collection of elements identified by
integer index. You can create a list by placing a sequence of comma-separated integer index. You can create a list by placing a sequence of comma-separated
expressions inside square brackets: </p> expressions inside square brackets:</p>
<div class="codehilite"><pre><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s">&quot;banana&quot;</span><span class="p">,</span> <span class="kc">true</span><span class="p">]</span> <pre class="snippet">
</pre></div> [1, "banana", true]
</pre>
<p>Here, we&rsquo;ve created a list of three elements. Notice that the elements don&rsquo;t
<p>Here, we&rsquo;ve created a list of three elements. Notice that the elements don&rsquo;t have to be the same type.</p>
have to be the same type. </p>
<h2>Accessing elements <a href="#accessing-elements" name="accessing-elements" class="header-anchor">#</a></h2> <h2>Accessing elements <a href="#accessing-elements" name="accessing-elements" class="header-anchor">#</a></h2>
<p>You can access an element from a list by calling the <a href="method-calls.html#subscripts">subscript <p>You can access an element from a list by calling the <a href="method-calls.html#subscripts">subscript
operator</a> on it with the index of the operator</a> on it with the index of the
element you want. Like most languages, indexes start at zero: </p> element you want. Like most languages, indexes start at zero:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">hirsute</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;sideburns&quot;</span><span class="p">,</span> <span class="s">&quot;porkchops&quot;</span><span class="p">,</span> <span class="s">&quot;&#39;stache&quot;</span><span class="p">,</span> <span class="s">&quot;goatee&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="output">sideburns</span> var hirsute = ["sideburns", "porkchops", "'stache", "goatee"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="output">porkchops</span> System.print(hirsute[0]) //> sideburns
</pre></div> System.print(hirsute[1]) //> porkchops
</pre>
<p>Negative indices counts backwards from the end:</p>
<pre class="snippet">
System.print(hirsute[-1]) //> goatee
System.print(hirsute[-2]) //> 'stache
</pre>
<p>Negative indices counts backwards from the end: </p> <p>It&rsquo;s a runtime error to pass an index outside of the bounds of the list. If you
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="output">goatee</span> don&rsquo;t know what those bounds are, you can find out using count:</p>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">])</span> <span class="output">&#39;stache</span> <pre class="snippet">
</pre></div> System.print(hirsute.count) //> 4
</pre>
<p>It&rsquo;s a runtime error to pass an index outside of the bounds of the list. If you
don&rsquo;t know what those bounds are, you can find out using count: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="o">.</span><span class="n">count</span><span class="p">)</span> <span class="output">4</span>
</pre></div>
<h2>Slices and ranges <a href="#slices-and-ranges" name="slices-and-ranges" class="header-anchor">#</a></h2> <h2>Slices and ranges <a href="#slices-and-ranges" name="slices-and-ranges" class="header-anchor">#</a></h2>
<p>Sometimes you want to copy a chunk of elements from a list. You can do that by <p>Sometimes you want to copy a chunk of elements from a list. You can do that by
passing a <a href="values.html#ranges">range</a> to the subscript operator, like so: </p> passing a <a href="values.html#ranges">range</a> to the subscript operator, like so:</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="mi">2</span><span class="p">])</span> <span class="output">[porkchops, &#39;stache]</span> <pre class="snippet">
</pre></div> System.print(hirsute[1..2]) //> [porkchops, 'stache]
</pre>
<p>This returns a new list containing the elements of the original list whose
indices are within the given range. Both inclusive and exclusive ranges work
and do what you expect. </p>
<p>Negative bounds also work like they do when passing a single number, so to copy
a list, you can just do: </p>
<div class="codehilite"><pre><span class="n">hirsute</span><span class="p">[</span><span class="mi">0</span><span class="o">..-</span><span class="mi">1</span><span class="p">]</span>
</pre></div>
<p>This returns a new list containing the elements of the original list whose
indices are within the given range. Both inclusive and exclusive ranges work
and do what you expect.</p>
<p>Negative bounds also work like they do when passing a single number, so to copy
a list, you can just do:</p>
<pre class="snippet">
hirsute[0..-1]
</pre>
<h2>Adding elements <a href="#adding-elements" name="adding-elements" class="header-anchor">#</a></h2> <h2>Adding elements <a href="#adding-elements" name="adding-elements" class="header-anchor">#</a></h2>
<p>Lists are <em>mutable</em>, meaning their contents can be changed. You can swap out an <p>Lists are <em>mutable</em>, meaning their contents can be changed. You can swap out an
existing element in the list using the subscript setter: </p> existing element in the list using the subscript setter:</p>
<div class="codehilite"><pre><span class="n">hirsute</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;muttonchops&quot;</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="output">muttonchops</span> hirsute[1] = "muttonchops"
</pre></div> System.print(hirsute[1]) //> muttonchops
</pre>
<p>It&rsquo;s an error to set an element that&rsquo;s out of bounds. To grow a list, you can
use <code>add</code> to append a single item to the end:</p>
<pre class="snippet">
hirsute.add("goatee")
System.print(hirsute.count) //> 5
</pre>
<p>It&rsquo;s an error to set an element that&rsquo;s out of bounds. To grow a list, you can <p>You can insert a new element at a specific position using <code>insert</code>:</p>
use <code>add</code> to append a single item to the end: </p> <pre class="snippet">
<div class="codehilite"><pre><span class="n">hirsute</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s">&quot;goatee&quot;</span><span class="p">)</span> hirsute.insert(2, "soul patch")
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="o">.</span><span class="n">count</span><span class="p">)</span> <span class="output">5</span> </pre>
</pre></div>
<p>You can insert a new element at a specific position using <code>insert</code>: </p>
<div class="codehilite"><pre><span class="n">hirsute</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s">&quot;soul patch&quot;</span><span class="p">)</span>
</pre></div>
<p>The first argument is the index to insert at, and the second is the value to
insert. All elements following the inserted one will be pushed down to
make room for it. </p>
<p>It&rsquo;s valid to &ldquo;insert&rdquo; after the last element in the list, but only <em>right</em>
after it. Like other methods, you can use a negative index to count from the
back. Doing so counts back from the size of the list <em>after</em> it&rsquo;s grown by one: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">letters</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span>
<span class="n">letters</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">)</span> <span class="c1">// OK: inserts at end.</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">letters</span><span class="p">)</span> <span class="output">[a, b, c, d]</span>
<span class="n">letters</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="s">&quot;e&quot;</span><span class="p">)</span> <span class="c1">// Counts back from size after insert.</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">letters</span><span class="p">)</span> <span class="output">[a, b, c, e, d]</span>
</pre></div>
<p>The first argument is the index to insert at, and the second is the value to
insert. All elements following the inserted one will be pushed down to
make room for it.</p>
<p>It&rsquo;s valid to &ldquo;insert&rdquo; after the last element in the list, but only <em>right</em>
after it. Like other methods, you can use a negative index to count from the
back. Doing so counts back from the size of the list <em>after</em> it&rsquo;s grown by one:</p>
<pre class="snippet">
var letters = ["a", "b", "c"]
letters.insert(3, "d") // OK: inserts at end.
System.print(letters) //> [a, b, c, d]
letters.insert(-2, "e") // Counts back from size after insert.
System.print(letters) //> [a, b, c, e, d]
</pre>
<h2>Adding lists together <a href="#adding-lists-together" name="adding-lists-together" class="header-anchor">#</a></h2> <h2>Adding lists together <a href="#adding-lists-together" name="adding-lists-together" class="header-anchor">#</a></h2>
<p>Lists have the ability to be added together via the <code>+</code> operator. This is often known as concatenation. </p> <p>Lists have the ability to be added together via the <code>+</code> operator. This is often known as concatenation.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">letters</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="k">var</span> <span class="n">other</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;d&quot;</span><span class="p">,</span> <span class="s">&quot;e&quot;</span><span class="p">,</span> <span class="s">&quot;f&quot;</span><span class="p">]</span> var letters = ["a", "b", "c"]
<span class="k">var</span> <span class="n">combined</span> <span class="o">=</span> <span class="n">letters</span> <span class="o">+</span> <span class="n">other</span> var other = ["d", "e", "f"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">combined</span><span class="p">)</span> <span class="output">[a, b, c, d, e, f]</span> var combined = letters + other
</pre></div> System.print(combined) //> [a, b, c, d, e, f]
</pre>
<h2>Removing elements <a href="#removing-elements" name="removing-elements" class="header-anchor">#</a></h2> <h2>Removing elements <a href="#removing-elements" name="removing-elements" class="header-anchor">#</a></h2>
<p>The opposite of <code>insert</code> is <code>removeAt</code>. It removes a single element from a <p>The opposite of <code>insert</code> is <code>removeAt</code>. It removes a single element from a
given position in the list. All following items are shifted up to fill in the given position in the list. All following items are shifted up to fill in the
gap: </p> gap:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">letters</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="n">letters</span><span class="o">.</span><span class="n">removeAt</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> var letters = ["a", "b", "c", "d"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">letters</span><span class="p">)</span> <span class="output">[a, c, d]</span> letters.removeAt(1)
</pre></div> System.print(letters) //> [a, c, d]
</pre>
<p>The <code>removeAt</code> method returns the removed item:</p>
<pre class="snippet">
System.print(letters.removeAt(1)) //> c
</pre>
<p>The <code>removeAt</code> method returns the removed item: </p> <p>If you want to remove everything from the list, you can clear it:</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">letters</span><span class="o">.</span><span class="n">removeAt</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="output">c</span> <pre class="snippet">
</pre></div> hirsute.clear()
System.print(hirsute) //> []
</pre>
<p><br><hr>
<p>If you want to remove everything from the list, you can clear it: </p> <a class="right" href="maps.html">Maps &rarr;</a>
<div class="codehilite"><pre><span class="n">hirsute</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span> <a href="values.html">&larr; Values</a></p>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">hirsute</span><span class="p">)</span> <span class="output">[]</span>
</pre></div>
<p><br><hr>
<a class="right" href="maps.html">Maps &rarr;</a>
<a href="values.html">&larr; Values</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

210
maps.html
View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Maps &ndash; Wren</title> <title>Maps &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,117 +110,117 @@
</nav> </nav>
<main> <main>
<h2>Maps</h2> <h2>Maps</h2>
<p>A map is an <em>associative</em> collection. It holds a set of entries, each of which <p>A map is an <em>associative</em> collection. It holds a set of entries, each of which
maps a <em>key</em> to a <em>value</em>. The same data structure has a variety of names in maps a <em>key</em> to a <em>value</em>. The same data structure has a variety of names in
other languages: hash table, dictionary, association, table, etc. </p> other languages: hash table, dictionary, association, table, etc.</p>
<p>You can create a map by placing a series of comma-separated entries inside <p>You can create a map by placing a series of comma-separated entries inside
curly braces. Each entry is a key and a value separated by a colon: </p> curly braces. Each entry is a key and a value separated by a colon:</p>
<div class="codehilite"><pre><span class="p">{</span> <pre class="snippet">
<span class="s">&quot;George&quot;</span><span class="o">:</span> <span class="s">&quot;Harrison&quot;</span><span class="p">,</span> {
<span class="s">&quot;John&quot;</span><span class="o">:</span> <span class="s">&quot;Lennon&quot;</span><span class="p">,</span> "George": "Harrison",
<span class="s">&quot;Paul&quot;</span><span class="o">:</span> <span class="s">&quot;McCartney&quot;</span><span class="p">,</span> "John": "Lennon",
<span class="s">&quot;Ringo&quot;</span><span class="o">:</span> <span class="s">&quot;Starr&quot;</span> "Paul": "McCartney",
<span class="p">}</span> "Ringo": "Starr"
</pre></div> }
</pre>
<p>This creates a map that associates the first name of each Beatle with his last
<p>This creates a map that associates the first name of each Beatle with his last name. Syntactically, in a map literal, keys can be any literal, a variable
name. Syntactically, in a map literal, keys can be any literal, a variable name, or a parenthesized expression. Values can be any expression. Here, we&rsquo;re
name, or a parenthesized expression. Values can be any expression. Here, we&rsquo;re using string literals for both keys and values.</p>
using string literals for both keys and values. </p> <p><em>Semantically</em>, values can be any object, and multiple keys may map to the same
<p><em>Semantically</em>, values can be any object, and multiple keys may map to the same value. Keys have a few limitations. They must be one of the immutable built-in
value. Keys have a few limitations. They must be one of the immutable built-in <a href="values.html">value types</a> in Wren. That means a number, string, range, bool, or <code>null</code>.
<a href="values.html">value types</a> in Wren. That means a number, string, range, bool, or <code>null</code>. You can also use a <a href="classes.html">class object</a> as a key.</p>
You can also use a <a href="classes.html">class object</a> as a key. </p> <p>The reason for this limitation&mdash;and the reason maps are called &ldquo;<em>hash</em>
<p>The reason for this limitation&mdash;and the reason maps are called &ldquo;<em>hash</em> tables&rdquo; in other languages&mdash;is that each key is used to generate a numeric
tables&rdquo; in other languages&mdash;is that each key is used to generate a numeric <em>hash code</em>. This lets a map locate the value associated with a key in constant
<em>hash code</em>. This lets a map locate the value associated with a key in constant time, even in very large maps. Since Wren only knows how to hash certain
time, even in very large maps. Since Wren only knows how to hash certain built-in types, only those can be used as keys.</p>
built-in types, only those can be used as keys. </p>
<h2>Adding entries <a href="#adding-entries" name="adding-entries" class="header-anchor">#</a></h2> <h2>Adding entries <a href="#adding-entries" name="adding-entries" class="header-anchor">#</a></h2>
<p>You add new key-value pairs to the map using the <a href="method-calls.html#subscripts">subscript operator</a>: </p> <p>You add new key-value pairs to the map using the <a href="method-calls.html#subscripts">subscript operator</a>:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">capitals</span> <span class="o">=</span> <span class="p">{}</span> <pre class="snippet">
<span class="n">capitals</span><span class="p">[</span><span class="s">&quot;Georgia&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;Atlanta&quot;</span> var capitals = {}
<span class="n">capitals</span><span class="p">[</span><span class="s">&quot;Idaho&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;Boise&quot;</span> capitals["Georgia"] = "Atlanta"
<span class="n">capitals</span><span class="p">[</span><span class="s">&quot;Maine&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;Augusta&quot;</span> capitals["Idaho"] = "Boise"
</pre></div> capitals["Maine"] = "Augusta"
</pre>
<p>If the key isn&rsquo;t already present, this adds it and associates it with the given
<p>If the key isn&rsquo;t already present, this adds it and associates it with the given value. If the key is already there, this just replaces its value.</p>
value. If the key is already there, this just replaces its value. </p>
<h2>Looking up values <a href="#looking-up-values" name="looking-up-values" class="header-anchor">#</a></h2> <h2>Looking up values <a href="#looking-up-values" name="looking-up-values" class="header-anchor">#</a></h2>
<p>To find the value associated with some key, again you use your friend the <p>To find the value associated with some key, again you use your friend the
subscript operator: </p> subscript operator:</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">capitals</span><span class="p">[</span><span class="s">&quot;Idaho&quot;</span><span class="p">])</span> <span class="output">Boise</span> <pre class="snippet">
</pre></div> System.print(capitals["Idaho"]) //> Boise
</pre>
<p>If the key is present, this returns its value. Otherwise, it returns <code>null</code>. Of
course, <code>null</code> itself can also be used as a value, so seeing <code>null</code> here
doesn&rsquo;t necessarily mean the key wasn&rsquo;t found.</p>
<p>To tell definitively if a key exists, you can call <code>containsKey()</code>:</p>
<pre class="snippet">
var belief = {"nihilism": null}
<p>If the key is present, this returns its value. Otherwise, it returns <code>null</code>. Of System.print(belief["nihilism"]) //> null (though key exists)
course, <code>null</code> itself can also be used as a value, so seeing <code>null</code> here System.print(belief["solipsism"]) //> null
doesn&rsquo;t necessarily mean the key wasn&rsquo;t found. </p> System.print(belief.containsKey("nihilism")) //> true
<p>To tell definitively if a key exists, you can call <code>containsKey()</code>: </p> System.print(belief.containsKey("solipsism")) //> false
<div class="codehilite"><pre><span class="k">var</span> <span class="n">belief</span> <span class="o">=</span> <span class="p">{</span><span class="s">&quot;nihilism&quot;</span><span class="o">:</span> <span class="kc">null</span><span class="p">}</span> </pre>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">belief</span><span class="p">[</span><span class="s">&quot;nihilism&quot;</span><span class="p">])</span> <span class="output">null (though key exists)</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">belief</span><span class="p">[</span><span class="s">&quot;solipsism&quot;</span><span class="p">])</span> <span class="output">null</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">belief</span><span class="o">.</span><span class="n">containsKey</span><span class="p">(</span><span class="s">&quot;nihilism&quot;</span><span class="p">))</span> <span class="output">true</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">belief</span><span class="o">.</span><span class="n">containsKey</span><span class="p">(</span><span class="s">&quot;solipsism&quot;</span><span class="p">))</span> <span class="output">false</span>
</pre></div>
<p>You can see how many entries a map contains using <code>count</code>: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">capitals</span><span class="o">.</span><span class="n">count</span><span class="p">)</span> <span class="output">3</span>
</pre></div>
<p>You can see how many entries a map contains using <code>count</code>:</p>
<pre class="snippet">
System.print(capitals.count) //> 3
</pre>
<h2>Removing entries <a href="#removing-entries" name="removing-entries" class="header-anchor">#</a></h2> <h2>Removing entries <a href="#removing-entries" name="removing-entries" class="header-anchor">#</a></h2>
<p>To remove an entry from a map, call <code>remove()</code> and pass in the key for the <p>To remove an entry from a map, call <code>remove()</code> and pass in the key for the
entry you want to delete: </p> entry you want to delete:</p>
<div class="codehilite"><pre><span class="n">capitals</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s">&quot;Maine&quot;</span><span class="p">)</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">capitals</span><span class="o">.</span><span class="n">containsKey</span><span class="p">(</span><span class="s">&quot;Maine&quot;</span><span class="p">))</span> <span class="output">false</span> capitals.remove("Maine")
</pre></div> System.print(capitals.containsKey("Maine")) //> false
</pre>
<p>If the key was found, this returns the value that was associated with it:</p>
<pre class="snippet">
System.print(capitals.remove("Georgia")) //> Atlanta
</pre>
<p>If the key was found, this returns the value that was associated with it: </p> <p>If the key wasn&rsquo;t in the map to begin with, <code>remove()</code> just returns <code>null</code>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">capitals</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s">&quot;Georgia&quot;</span><span class="p">))</span> <span class="output">Atlanta</span> <p>If you want to remove <em>everything</em> from the map, like with <a href="lists.html">lists</a>, you call
</pre></div> <code>clear()</code>:</p>
<pre class="snippet">
capitals.clear()
<p>If the key wasn&rsquo;t in the map to begin with, <code>remove()</code> just returns <code>null</code>. </p> System.print(capitals.count) //> 0
<p>If you want to remove <em>everything</em> from the map, like with <a href="lists.html">lists</a>, you call </pre>
<code>clear()</code>: </p>
<div class="codehilite"><pre><span class="n">capitals</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">capitals</span><span class="o">.</span><span class="n">count</span><span class="p">)</span> <span class="output">0</span>
</pre></div>
<h2>Iterating over the contents <a href="#iterating-over-the-contents" name="iterating-over-the-contents" class="header-anchor">#</a></h2> <h2>Iterating over the contents <a href="#iterating-over-the-contents" name="iterating-over-the-contents" class="header-anchor">#</a></h2>
<p>The subscript operator works well for finding values when you know the key <p>The subscript operator works well for finding values when you know the key
you&rsquo;re looking for, but sometimes you want to see everything that&rsquo;s in the map. you&rsquo;re looking for, but sometimes you want to see everything that&rsquo;s in the map.
For that, map exposes two methods: <code>keys</code> and <code>values</code>. </p> For that, map exposes two methods: <code>keys</code> and <code>values</code>.</p>
<p>The first returns a <a href="modules/core/sequence.html">Sequence</a> that <a href="control-flow.html#the-iterator-protocol">iterates</a> over all of the keys in the <p>The first returns a <a href="modules/core/sequence.html">Sequence</a> that <a href="control-flow.html#the-iterator-protocol">iterates</a> over all of the keys in the
map, and the second returns one that iterates over the values. </p> map, and the second returns one that iterates over the values.</p>
<p>If you want to see all of the key-value pairs in a map, the easiest way is to <p>If you want to see all of the key-value pairs in a map, the easiest way is to
iterate over the keys and use each to look up its value: </p> iterate over the keys and use each to look up its value:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">birds</span> <span class="o">=</span> <span class="p">{</span> <pre class="snippet">
<span class="s">&quot;Arizona&quot;</span><span class="o">:</span> <span class="s">&quot;Cactus wren&quot;</span><span class="p">,</span> var birds = {
<span class="s">&quot;Hawaii&quot;</span><span class="o">:</span> <span class="s">&quot;Nēnē&quot;</span><span class="p">,</span> "Arizona": "Cactus wren",
<span class="s">&quot;Ohio&quot;</span><span class="o">:</span> <span class="s">&quot;Northern Cardinal&quot;</span> "Hawaii": "Nēnē",
<span class="p">}</span> "Ohio": "Northern Cardinal"
}
<span class="k">for</span> <span class="p">(</span><span class="n">state</span> <span class="k">in</span> <span class="n">birds</span><span class="o">.</span><span class="n">keys</span><span class="p">)</span> <span class="p">{</span> for (state in birds.keys) {
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;The state bird of &quot;</span> <span class="o">+</span> <span class="n">state</span> <span class="o">+</span> <span class="s">&quot; is &quot;</span> <span class="o">+</span> <span class="n">birds</span><span class="p">[</span><span class="n">state</span><span class="p">])</span> System.print("The state bird of " + state + " is " + birds[state])
<span class="p">}</span> }
</pre></div> </pre>
<p>This program prints the three states and their birds. However, the <em>order</em>
<p>This program prints the three states and their birds. However, the <em>order</em> that they are printed isn&rsquo;t defined. Wren makes no promises about what order
that they are printed isn&rsquo;t defined. Wren makes no promises about what order keys and values are iterated in when you use these methods. All it promises is
keys and values are iterated in when you use these methods. All it promises is that every entry will appear exactly once.</p>
that every entry will appear exactly once. </p> <p><br><hr>
<p><br><hr> <a class="right" href="method-calls.html">Method Calls &rarr;</a>
<a class="right" href="method-calls.html">Method Calls &rarr;</a> <a href="lists.html">&larr; Lists</a></p>
<a href="lists.html">&larr; Lists</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Method Calls &ndash; Wren</title> <title>Method Calls &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,167 +110,165 @@
</nav> </nav>
<main> <main>
<h2>Method Calls</h2> <h2>Method Calls</h2>
<p>Wren is deeply object oriented, so most code consists of invoking methods on <p>Wren is deeply object oriented, so most code consists of invoking methods on
objects, usually something like this: </p> objects, usually something like this:</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Heyoo!&quot;</span><span class="p">)</span> <span class="output">Heyoo!</span> <pre class="snippet">
</pre></div> System.print("Heyoo!") //> Heyoo!
</pre>
<p>You have a <em>receiver</em> expression (here <code>System</code>) followed by a <code>.</code>, then a name
(<code>print</code>) and an argument list in parentheses (<code>("Heyoo!")</code>). Multiple arguments
are separated by commas:</p>
<pre class="snippet">
list.insert(3, "item")
</pre>
<p>You have a <em>receiver</em> expression (here <code>System</code>) followed by a <code>.</code>, then a name <p>The argument list can also be empty:</p>
(<code>print</code>) and an argument list in parentheses (<code>("Heyoo!")</code>). Multiple arguments <pre class="snippet">
are separated by commas: </p> list.clear()
<div class="codehilite"><pre><span class="n">list</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s">&quot;item&quot;</span><span class="p">)</span> </pre>
</pre></div>
<p>The VM executes a method call like so:</p>
<p>The argument list can also be empty: </p>
<div class="codehilite"><pre><span class="n">list</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</pre></div>
<p>The VM executes a method call like so: </p>
<ol> <ol>
<li>Evaluate the receiver and arguments from left to right. </li> <li>Evaluate the receiver and arguments from left to right.</li>
<li>Look up the method on the receiver&rsquo;s <a href="classes.html">class</a>. </li> <li>Look up the method on the receiver&rsquo;s <a href="classes.html">class</a>.</li>
<li>Invoke it, passing in the argument values. </li> <li>Invoke it, passing in the argument values.</li>
</ol> </ol>
<h2>Signature <a href="#signature" name="signature" class="header-anchor">#</a></h2> <h2>Signature <a href="#signature" name="signature" class="header-anchor">#</a></h2>
<p>Unlike most other dynamically-typed languages, in Wren a class can have multiple <p>Unlike most other dynamically-typed languages, in Wren a class can have multiple
methods with the same <em>name</em>, as long as they have different <em>signatures</em>. The methods with the same <em>name</em>, as long as they have different <em>signatures</em>. The
signature includes the method&rsquo;s name along with the number of arguments it signature includes the method&rsquo;s name along with the number of arguments it
takes. In technical terms, this means you can <em>overload by arity</em>. </p> takes. In technical terms, this means you can <em>overload by arity</em>.</p>
<p>For example, the <a href="modules/random/random.html">Random</a> class has two methods for getting a random integer. <p>For example, the <a href="modules/random/random.html">Random</a> class has two methods for getting a random integer.
One takes a minimum and maximum value and returns a value in that range. The One takes a minimum and maximum value and returns a value in that range. The
other only takes a maximum value and uses 0 as the minimum: </p> other only takes a maximum value and uses 0 as the minimum:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">()</span> <pre class="snippet">
<span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> var random = Random.new()
<span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> random.int(3, 10)
</pre></div> random.int(4)
</pre>
<p>In a language like Python or JavaScript, these would both call a single <code>int()</code>
<p>In a language like Python or JavaScript, these would both call a single <code>int()</code> method, which has some kind of &ldquo;optional&rdquo; parameter. The body of the method
method, which has some kind of &ldquo;optional&rdquo; parameter. The body of the method figures out how many arguments were passed and uses control flow to handle the
figures out how many arguments were passed and uses control flow to handle the two different behaviors. That means first parameter represents &ldquo;max unless
two different behaviors. That means first parameter represents &ldquo;max unless another parameter was passed, in which case it&rsquo;s min&rdquo;. Kind of gross.</p>
another parameter was passed, in which case it&rsquo;s min&rdquo;. Kind of gross. </p> <p>In Wren, these are calls to two entirely separate methods, <code>int(_,_)</code> and
<p>In Wren, these are calls to two entirely separate methods, <code>int(_,_)</code> and <code>int(_)</code>. This makes it easier to define &ldquo;overloads&rdquo; like this since you don&rsquo;t
<code>int(_)</code>. This makes it easier to define &ldquo;overloads&rdquo; like this since you don&rsquo;t need optional parameters or any kind of control flow to handle the different
need optional parameters or any kind of control flow to handle the different cases.</p>
cases. </p> <p>It&rsquo;s also faster to execute. Since we know how many arguments are passed at
<p>It&rsquo;s also faster to execute. Since we know how many arguments are passed at compile time, we can compile this to directly call the right method and avoid
compile time, we can compile this to directly call the right method and avoid any &ldquo;if I got two arguments do this&hellip;&rdquo; runtime work.</p>
any &ldquo;if I got two arguments do this&hellip;&rdquo; runtime work. </p>
<h2>Getters <a href="#getters" name="getters" class="header-anchor">#</a></h2> <h2>Getters <a href="#getters" name="getters" class="header-anchor">#</a></h2>
<p>Some methods exist to expose a stored or computed property of an object. These <p>Some methods exist to expose a stored or computed property of an object. These
are <em>getters</em> and have no parentheses: </p> are <em>getters</em> and have no parentheses:</p>
<div class="codehilite"><pre><span class="s">&quot;string&quot;</span><span class="o">.</span><span class="n">count</span> <span class="output">6</span> <pre class="snippet">
<span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">)</span><span class="o">.</span><span class="n">min</span> <span class="output">1</span> "string".count //> 6
<span class="mf">1.23</span><span class="o">.</span><span class="n">sin</span> <span class="output">0.9424888019317</span> (1..10).min //> 1
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">isEmpty</span> <span class="output">false</span> 1.23.sin //> 0.9424888019317
</pre></div> [1, 2, 3].isEmpty //> false
</pre>
<p>A getter is <em>not</em> the same as a method with an empty argument list. The <code>()</code> is
part of the signature, so <code>count</code> and <code>count()</code> have different signatures.
Unlike Ruby&rsquo;s optional parentheses, Wren wants to make sure you call a getter
like a getter and a <code>()</code> method like a <code>()</code> method. These don&rsquo;t work:</p>
<pre class="snippet">
"string".count()
[1, 2, 3].clear
</pre>
<p>A getter is <em>not</em> the same as a method with an empty argument list. The <code>()</code> is <p>If you&rsquo;re defining some member that doesn&rsquo;t need any parameters, you need to
part of the signature, so <code>count</code> and <code>count()</code> have different signatures. decide if it should be a getter or a method with an empty <code>()</code> parameter list.
Unlike Ruby&rsquo;s optional parentheses, Wren wants to make sure you call a getter The general guidelines are:</p>
like a getter and a <code>()</code> method like a <code>()</code> method. These don&rsquo;t work: </p>
<div class="codehilite"><pre><span class="s">&quot;string&quot;</span><span class="o">.</span><span class="n">count</span><span class="p">()</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">clear</span>
</pre></div>
<p>If you&rsquo;re defining some member that doesn&rsquo;t need any parameters, you need to
decide if it should be a getter or a method with an empty <code>()</code> parameter list.
The general guidelines are: </p>
<ul> <ul>
<li> <li>If it modifies the object or has some other side effect, make it a method:</li>
<p>If it modifies the object or has some other side effect, make it a method: </p> </ul>
<div class="codehilite"><pre><span class="n">list</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span> <pre class="snippet">
</pre></div> list.clear()
</pre>
<ul>
<li>If the method supports multiple arities, make the zero-parameter case a <code>()</code>
method to be consistent with the other versions:</li>
</ul>
<pre class="snippet">
Fiber.yield()
Fiber.yield("value")
</pre>
</li> <ul>
<li> <li>Otherwise, it can probably be a getter.</li>
<p>If the method supports multiple arities, make the zero-parameter case a <code>()</code>
method to be consistent with the other versions: </p>
<div class="codehilite"><pre><span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">()</span>
<span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">(</span><span class="s">&quot;value&quot;</span><span class="p">)</span>
</pre></div>
</li>
<li>
<p>Otherwise, it can probably be a getter. </p>
</li>
</ul> </ul>
<h2>Setters <a href="#setters" name="setters" class="header-anchor">#</a></h2> <h2>Setters <a href="#setters" name="setters" class="header-anchor">#</a></h2>
<p>A getter lets an object expose a public &ldquo;property&rdquo; that you can <em>read</em>. <p>A getter lets an object expose a public &ldquo;property&rdquo; that you can <em>read</em>.
Likewise, a <em>setter</em> lets you write to a property: </p> Likewise, a <em>setter</em> lets you write to a property:</p>
<div class="codehilite"><pre><span class="n">person</span><span class="o">.</span><span class="n">height</span> <span class="o">=</span> <span class="mi">74</span> <span class="c1">// Grew up!</span> <pre class="snippet">
</pre></div> person.height = 74 // Grew up!
</pre>
<p>Despite the <code>=</code>, this is just another syntax for a method call. From the
<p>Despite the <code>=</code>, this is just another syntax for a method call. From the language&rsquo;s perspective, the above line is just a call to the <code>height=(_)</code>
language&rsquo;s perspective, the above line is just a call to the <code>height=(_)</code> method on <code>person</code>, passing in <code>74</code>.</p>
method on <code>person</code>, passing in <code>74</code>. </p> <p>Since the <code>=(_)</code> is in the setter&rsquo;s signature, an object can have both a getter
<p>Since the <code>=(_)</code> is in the setter&rsquo;s signature, an object can have both a getter and setter with the same name without a collision. Defining both lets you
and setter with the same name without a collision. Defining both lets you provide a read/write property.</p>
provide a read/write property. </p>
<h2>Operators <a href="#operators" name="operators" class="header-anchor">#</a></h2> <h2>Operators <a href="#operators" name="operators" class="header-anchor">#</a></h2>
<p>Wren has most of the same operators you know and love with the same precedence <p>Wren has most of the same operators you know and love with the same precedence
and associativity. We have three prefix operators: </p> and associativity. We have three prefix operators:</p>
<div class="codehilite"><pre><span class="o">!</span> <span class="o">~</span> <span class="o">-</span> <pre class="snippet">
</pre></div> ! ~ -
</pre>
<p>They are just method calls on their operand without any other arguments. An
expression like <code>!possible</code> means &ldquo;call the <code>!</code> method on <code>possible</code>&ldquo;.</p>
<p>We also have a slew of infix operators&mdash;they have operands on both sides.
They are:</p>
<pre class="snippet">
* / % + - .. ... << >> < <= > >= == != & ^ | is
</pre>
<p>They are just method calls on their operand without any other arguments. An <p>Like prefix operators, they are all funny ways of writing method calls. The left
expression like <code>!possible</code> means &ldquo;call the <code>!</code> method on <code>possible</code>&ldquo;. </p> operand is the receiver, and the right operand gets passed to it. So <code>a + b</code> is
<p>We also have a slew of infix operators&mdash;they have operands on both sides. semantically interpreted as &ldquo;invoke the <code>+(_)</code> method on <code>a</code>, passing it <code>b</code>&ldquo;.</p>
They are: </p> <p>Note that <code>-</code> is both a prefix and an infix operator. Since they have different
<div class="codehilite"><pre><span class="o">*</span> <span class="o">/</span> <span class="o">%</span> <span class="o">+</span> <span class="o">-</span> <span class="o">..</span> <span class="o">...</span> <span class="o">&lt;&lt;</span> <span class="o">&gt;&gt;</span> <span class="o">&lt;</span> <span class="o">&lt;=</span> <span class="o">&gt;</span> <span class="o">&gt;=</span> <span class="o">==</span> <span class="o">!=</span> <span class="o">&amp;</span> <span class="o">^</span> <span class="o">|</span> <span class="k">is</span> signatures (<code>-</code> and <code>-(_)</code>), there&rsquo;s no ambiguity between them.</p>
</pre></div> <p>Most of these are probably familiar already. The <code>..</code> and <code>...</code> operators are
&ldquo;range&rdquo; operators. The number type implements those to create <a href="values.html#ranges">range</a>
objects, but they are method calls like other operators.</p>
<p>Like prefix operators, they are all funny ways of writing method calls. The left <p>The <code>is</code> keyword is a &ldquo;type test&rdquo; operator. The base <a href="modules/core/object.html">Object</a> class implements
operand is the receiver, and the right operand gets passed to it. So <code>a + b</code> is it to tell if an object is an instance of a given class. You&rsquo;ll rarely need to,
semantically interpreted as &ldquo;invoke the <code>+(_)</code> method on <code>a</code>, passing it <code>b</code>&ldquo;. </p> but you can override <code>is</code> in your own classes. That can be useful for things
<p>Note that <code>-</code> is both a prefix and an infix operator. Since they have different like mocks or proxies where you want an object to masquerade as a certain class.</p>
signatures (<code>-</code> and <code>-(_)</code>), there&rsquo;s no ambiguity between them. </p>
<p>Most of these are probably familiar already. The <code>..</code> and <code>...</code> operators are
&ldquo;range&rdquo; operators. The number type implements those to create <a href="values.html#ranges">range</a>
objects, but they are method calls like other operators. </p>
<p>The <code>is</code> keyword is a &ldquo;type test&rdquo; operator. The base <a href="modules/core/object.html">Object</a> class implements
it to tell if an object is an instance of a given class. You&rsquo;ll rarely need to,
but you can override <code>is</code> in your own classes. That can be useful for things
like mocks or proxies where you want an object to masquerade as a certain class. </p>
<h2>Subscripts <a href="#subscripts" name="subscripts" class="header-anchor">#</a></h2> <h2>Subscripts <a href="#subscripts" name="subscripts" class="header-anchor">#</a></h2>
<p>Another familiar syntax from math class is <em>subscripting</em> using square brackets <p>Another familiar syntax from math class is <em>subscripting</em> using square brackets
(<code>[]</code>). It&rsquo;s handy for working with collection-like objects. For example: </p> (<code>[]</code>). It&rsquo;s handy for working with collection-like objects. For example:</p>
<div class="codehilite"><pre><span class="n">list</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1">// Get the first item in a list.</span> <pre class="snippet">
<span class="n">map</span><span class="p">[</span><span class="s">&quot;key&quot;</span><span class="p">]</span> <span class="c1">// Get the value associated with &quot;key&quot;.</span> list[0] // Get the first item in a list.
</pre></div> map["key"] // Get the value associated with "key".
</pre>
<p>You know the refrain by now. In Wren, these are method calls. In the above
examples, the signature is <code>[_]</code>. Subscript operators may also take multiple
arguments, which is useful for things like multi-dimensional arrays:</p>
<pre class="snippet">
matrix[3, 5]
</pre>
<p>You know the refrain by now. In Wren, these are method calls. In the above <p>These examples are subscript &ldquo;getters&rdquo;, and there are also
examples, the signature is <code>[_]</code>. Subscript operators may also take multiple corresponding <em>subscript setters</em>:</p>
arguments, which is useful for things like multi-dimensional arrays: </p> <pre class="snippet">
<div class="codehilite"><pre><span class="n">matrix</span><span class="p">[</span><span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span> list[0] = "item"
</pre></div> map["key"] = "value"
</pre>
<p>These are equivalent to method calls whose signature is <code>[_]=(_)</code> and whose
<p>These examples are subscript &ldquo;getters&rdquo;, and there are also arguments are both the subscript (or subscripts) and the value on the right-hand
corresponding <em>subscript setters</em>: </p> side.</p>
<div class="codehilite"><pre><span class="n">list</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;item&quot;</span> <p><br><hr>
<span class="n">map</span><span class="p">[</span><span class="s">&quot;key&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;value&quot;</span> <a class="right" href="control-flow.html">Control Flow &rarr;</a>
</pre></div> <a href="maps.html">&larr; Maps</a></p>
<p>These are equivalent to method calls whose signature is <code>[_]=(_)</code> and whose
arguments are both the subscript (or subscripts) and the value on the right-hand
side. </p>
<p><br><hr>
<a class="right" href="control-flow.html">Control Flow &rarr;</a>
<a href="maps.html">&larr; Maps</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Modularity &ndash; Wren</title> <title>Modularity &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,267 +110,263 @@
</nav> </nav>
<main> <main>
<h2>Modularity</h2> <h2>Modularity</h2>
<p>Once you start writing programs that are more than little toys, you quickly run <p>Once you start writing programs that are more than little toys, you quickly run
into two problems: </p> into two problems:</p>
<ol> <ol>
<li> <li>
<p>You want to break them down into multiple smaller files to make it easier to <p>You want to break them down into multiple smaller files to make it easier to
find your way around them. </p> find your way around them.</p>
</li> </li>
<li> <li>
<p>You want to reuse pieces of them across different programs. </p> <p>You want to reuse pieces of them across different programs.</p>
</li> </li>
</ol> </ol>
<p>To address those, Wren has a simple module system. A file containing Wren code <p>To address those, Wren has a simple module system. A file containing Wren code
defines a <em>module</em>. A module can use the code defined in another module by defines a <em>module</em>. A module can use the code defined in another module by
<em>importing</em> it. You can break big programs into smaller modules that you <em>importing</em> it. You can break big programs into smaller modules that you
import, and you can reuse code by having multiple programs share the use of a import, and you can reuse code by having multiple programs share the use of a
single module. </p> single module.</p>
<p>Wren does not have a single global scope. Instead, each module has its own <p>Wren does not have a single global scope. Instead, each module has its own
top-level scope independent of all other modules. This means, for example, that top-level scope independent of all other modules. This means, for example, that
two modules can define a top-level variable with the same name without causing two modules can define a top-level variable with the same name without causing
a name collision. Each module is, well, modular. </p> a name collision. Each module is, well, modular.</p>
<h2>Importing, briefly <a href="#importing,-briefly" name="importing,-briefly" class="header-anchor">#</a></h2> <h2>Importing, briefly <a href="#importing,-briefly" name="importing,-briefly" class="header-anchor">#</a></h2>
<p>When you run Wren and give it a file name to execute, the contents of that file <p>When you run Wren and give it a file name to execute, the contents of that file
define the &ldquo;main&rdquo; module that execution starts at. To load and execute other define the &ldquo;main&rdquo; module that execution starts at. To load and execute other
modules, you use an import statement: </p> modules, you use an import statement:</p>
<div class="codehilite"><pre><span class="k">import</span> <span class="s">&quot;beverages&quot;</span> <span class="k">for</span> <span class="vg">Coffee</span><span class="p">,</span> <span class="vg">Tea</span> <pre class="snippet">
</pre></div> import "beverages" for Coffee, Tea
</pre>
<p>This finds a module named &ldquo;beverages&rdquo; and executes its source code. Then, it
looks up two top-level variables, <code>Coffee</code> and <code>Tea</code> in <em>that</em> module and
creates new variables in <em>this</em> module with their values.</p>
<p>This statement can appear anywhere a variable declaration is allowed, even
inside blocks:</p>
<pre class="snippet">
if (thirsty) {
import "beverages" for Coffee, Tea
}
</pre>
<p>This finds a module named &ldquo;beverages&rdquo; and executes its source code. Then, it <p>If you want to load a module, but not bind any variables from it, you can omit
looks up two top-level variables, <code>Coffee</code> and <code>Tea</code> in <em>that</em> module and the <code>for</code> clause:</p>
creates new variables in <em>this</em> module with their values. </p> <pre class="snippet">
<p>This statement can appear anywhere a variable declaration is allowed, even import "some_imperative_code"
inside blocks: </p> </pre>
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">thirsty</span><span class="p">)</span> <span class="p">{</span>
<span class="k">import</span> <span class="s">&quot;beverages&quot;</span> <span class="k">for</span> <span class="vg">Coffee</span><span class="p">,</span> <span class="vg">Tea</span>
<span class="p">}</span>
</pre></div>
<p>That&rsquo;s the basic idea. Now let&rsquo;s break it down into each of the steps it
<p>If you want to load a module, but not bind any variables from it, you can omit performs:</p>
the <code>for</code> clause: </p>
<div class="codehilite"><pre><span class="k">import</span> <span class="s">&quot;some_imperative_code&quot;</span>
</pre></div>
<p>That&rsquo;s the basic idea. Now let&rsquo;s break it down into each of the steps it
performs: </p>
<ol> <ol>
<li>Locate the source code for the module. </li> <li>Locate the source code for the module.</li>
<li>Execute the imported module&rsquo;s code. </li> <li>Execute the imported module&rsquo;s code.</li>
<li>Bind new variables in the importing module to values defined in the imported <li>Bind new variables in the importing module to values defined in the imported
module. </li> module.</li>
</ol> </ol>
<p>We&rsquo;ll go through each step: </p> <p>We&rsquo;ll go through each step:</p>
<h2>Locating a module <a href="#locating-a-module" name="locating-a-module" class="header-anchor">#</a></h2> <h2>Locating a module <a href="#locating-a-module" name="locating-a-module" class="header-anchor">#</a></h2>
<p>The first thing you need to do to import a module is actually <em>find</em> the code <p>The first thing you need to do to import a module is actually <em>find</em> the code
for it. The import specifies a <em>name</em>&mdash;some arbitrary string that is used for it. The import specifies a <em>name</em>&mdash;some arbitrary string that is used
to uniquely identify the module. The embedding application controls how that to uniquely identify the module. The embedding application controls how that
string is used to locate a blob of source code. </p> string is used to locate a blob of source code.</p>
<p>When the host application creates a new Wren VM, it provides a module loader <p>When the host application creates a new Wren VM, it provides a module loader
function: </p> function:</p>
<div class="codehilite"><pre><span class="n">WrenConfiguration</span> <span class="n">config</span><span class="p">;</span> <pre class="snippet" data-lang="c">
<span class="n">config</span><span class="p">.</span><span class="n">loadModuleFn</span> <span class="o">=</span> <span class="n">loadModule</span><span class="p">;</span> WrenConfiguration config;
config.loadModuleFn = loadModule;
<span class="c1">// Other configuration...</span> // Other configuration...
<span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span> <span class="o">=</span> <span class="n">wrenNewVM</span><span class="p">(</span><span class="o">&amp;</span><span class="n">config</span><span class="p">);</span> WrenVM* vm = wrenNewVM(&config);
</pre></div> </pre>
<p>That function has this signature:</p>
<pre class="snippet" data-lang="c">
char* WrenLoadModuleFn(WrenVM* vm, const char* name);
</pre>
<p>That function has this signature: </p> <p>Whenever a module is imported, the VM calls this and passes it the name of the
<div class="codehilite"><pre><span class="kt">char</span><span class="o">*</span> <span class="nf">WrenLoadModuleFn</span><span class="p">(</span><span class="n">WrenVM</span><span class="o">*</span> <span class="n">vm</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span><span class="o">*</span> <span class="n">name</span><span class="p">);</span> module. The embedder is expected to return the source code contents of the
</pre></div> module. When you embed Wren in your app, you can handle this however you want:
reach out to the file system, look inside resources bundled into your app,
whatever.</p>
<p>Whenever a module is imported, the VM calls this and passes it the name of the <p>You can return <code>NULL</code> from this function to indicate that a module couldn&rsquo;t be
module. The embedder is expected to return the source code contents of the found. When you do this, Wren will report it as a runtime error.</p>
module. When you embed Wren in your app, you can handle this however you want:
reach out to the file system, look inside resources bundled into your app,
whatever. </p>
<p>You can return <code>NULL</code> from this function to indicate that a module couldn&rsquo;t be
found. When you do this, Wren will report it as a runtime error. </p>
<h3>The command-line loader <a href="#the-command-line-loader" name="the-command-line-loader" class="header-anchor">#</a></h3> <h3>The command-line loader <a href="#the-command-line-loader" name="the-command-line-loader" class="header-anchor">#</a></h3>
<p>The default little command-line VM that comes with Wren has a very simple <p>The <a href="getting-started.html#using-the-wren-cli">Wren CLI command-line tool</a> has a very simple
lookup process. It appends the module name and &ldquo;.wren&rdquo; to the directory where lookup process. It appends the module name and &ldquo;.wren&rdquo; to the directory where
the main module was loaded and looks for that file. So, let&rsquo;s say you run: </p> the main module was loaded and looks for that file. So, let&rsquo;s say you run:</p>
<div class="codehilite"><pre><span class="nv">$ </span>wren /code/my_program.wren <pre><code>$ wren code/my_program.wren
</pre></div> </code></pre>
<p>And that main module has:</p>
<pre class="snippet">
import "some/module"
</pre>
<p>Then the command-line VM will try to find <code>/code/some/module.wren</code>. By
<p>And that main module has: </p> convention, forward slashes should be used as path separators, even on Windows,
<div class="codehilite"><pre><span class="k">import</span> <span class="s">&quot;some/module&quot;</span> to help ensure your scripts are platform-independent. (Forward slashes are a
</pre></div> valid separator on Windows, but backslashes are not valid on other OSes.)</p>
<p>Then the command-line VM will try to find <code>/code/some/module.wren</code>. By
convention, forward slashes should be used as path separators, even on Windows,
to help ensure your scripts are platform-independent. (Forward slashes are a
valid separator on Windows, but backslashes are not valid on other OSes.) </p>
<h2>Executing the module <a href="#executing-the-module" name="executing-the-module" class="header-anchor">#</a></h2> <h2>Executing the module <a href="#executing-the-module" name="executing-the-module" class="header-anchor">#</a></h2>
<p>Once we have the source code for a module, we need to run it. First, the VM <p>Once we have the source code for a module, we need to run it. First, the VM
takes the <a href="concurrency.html">fiber</a> that is executing the <code>import</code> statement in the importing takes the <a href="concurrency.html">fiber</a> that is executing the <code>import</code> statement in the importing
module and pauses it. </p> module and pauses it.</p>
<p>Then it creates a new module object&mdash;a new fresh top-level scope, <p>Then it creates a new module object&mdash;a new fresh top-level scope,
basically&mdash;and a new fiber. It executes the new module&rsquo;s code in that basically&mdash;and a new fiber. It executes the new module&rsquo;s code in that
fiber and scope. The module can run whatever imperative code it wants and fiber and scope. The module can run whatever imperative code it wants and
define whatever top-level variables it wants. </p> define whatever top-level variables it wants.</p>
<p>When the module&rsquo;s code is done being executed and its fiber completes, the <p>When the module&rsquo;s code is done being executed and its fiber completes, the
suspended fiber for the importing module is resumed. This suspending and suspended fiber for the importing module is resumed. This suspending and
resuming is recursive. So, if &ldquo;a&rdquo; imports &ldquo;b&rdquo; which imports &ldquo;c&rdquo;, both &ldquo;a&rdquo; and resuming is recursive. So, if &ldquo;a&rdquo; imports &ldquo;b&rdquo; which imports &ldquo;c&rdquo;, both &ldquo;a&rdquo; and
&ldquo;b&rdquo; will be suspended while &ldquo;c&rdquo; is running. When &ldquo;c&rdquo; is done, &ldquo;b&rdquo; is resumed. &ldquo;b&rdquo; will be suspended while &ldquo;c&rdquo; is running. When &ldquo;c&rdquo; is done, &ldquo;b&rdquo; is resumed.
Then, when &ldquo;b&rdquo; completes, &ldquo;a&rdquo; is resumed. </p> Then, when &ldquo;b&rdquo; completes, &ldquo;a&rdquo; is resumed.</p>
<p>Think of it like traversing the tree of imports, one node at a time. At any <p>Think of it like traversing the tree of imports, one node at a time. At any
given point in time, only one module&rsquo;s code is running. </p> given point in time, only one module&rsquo;s code is running.</p>
<h2>Binding variables <a href="#binding-variables" name="binding-variables" class="header-anchor">#</a></h2> <h2>Binding variables <a href="#binding-variables" name="binding-variables" class="header-anchor">#</a></h2>
<p>Once the module is done executing, the last step is to actually <em>import</em> some <p>Once the module is done executing, the last step is to actually <em>import</em> some
data from it. Any module can define &ldquo;top-level&rdquo; <a href="variables.html">variables</a>. data from it. Any module can define &ldquo;top-level&rdquo; <a href="variables.html">variables</a>.
These are simply variables declared outside of any These are simply variables declared outside of any
<a href="classes.html#methods">method</a> or <a href="functions.html">function</a>. </p> <a href="classes.html#methods">method</a> or <a href="functions.html">function</a>.</p>
<p>These are visible to anything inside the module, but they can also be <p>These are visible to anything inside the module, but they can also be
<em>exported</em> and used by other modules. When Wren executes an import like: </p> <em>exported</em> and used by other modules. When Wren executes an import like:</p>
<div class="codehilite"><pre><span class="k">import</span> <span class="s">&quot;beverages&quot;</span> <span class="k">for</span> <span class="vg">Coffee</span><span class="p">,</span> <span class="vg">Tea</span> <pre class="snippet">
</pre></div> import "beverages" for Coffee, Tea
</pre>
<p>First it runs the &ldquo;beverages&rdquo; module. Then it goes through each of the variable
<p>First it runs the &ldquo;beverages&rdquo; module. Then it goes through each of the variable names in the <code>for</code> clause. For each one, it looks for a top-level variable with
names in the <code>for</code> clause. For each one, it looks for a top-level variable with that name in the imported module. If a variable with that name can&rsquo;t be found
that name in the imported module. If a variable with that name can&rsquo;t be found in the imported module, it&rsquo;s a runtime error.</p>
in the imported module, it&rsquo;s a runtime error. </p> <p>Otherwise, it gets the current value of the variable and defines a new variable
<p>Otherwise, it gets the current value of the variable and defines a new variable in the importing module with the same name and value. It&rsquo;s worth noting that
in the importing module with the same name and value. It&rsquo;s worth noting that the importing module gets its <em>own</em> variable whose value is a snapshot of the
the importing module gets its <em>own</em> variable whose value is a snapshot of the value of the imported variable at the time it was imported. If either module
value of the imported variable at the time it was imported. If either module later assigns to that variable, the other won&rsquo;t see it. It&rsquo;s not a &ldquo;live&rdquo;
later assigns to that variable, the other won&rsquo;t see it. It&rsquo;s not a &ldquo;live&rdquo; connection.</p>
connection. </p> <p>In practice, most top-level variables are only assigned once anyway, so this
<p>In practice, most top-level variables are only assigned once anyway, so this rarely makes a difference.</p>
rarely makes a difference. </p>
<h2>Shared imports <a href="#shared-imports" name="shared-imports" class="header-anchor">#</a></h2> <h2>Shared imports <a href="#shared-imports" name="shared-imports" class="header-anchor">#</a></h2>
<p>Earlier, I described a program&rsquo;s set of modules as a tree. Of course, it&rsquo;s only <p>Earlier, I described a program&rsquo;s set of modules as a tree. Of course, it&rsquo;s only
a <em>tree</em> of modules if there are no <em>shared imports</em>. But consider a program a <em>tree</em> of modules if there are no <em>shared imports</em>. But consider a program
like: </p> like:</p>
<div class="codehilite"><pre><span class="c1">// main.wren</span> <pre class="snippet">
<span class="k">import</span> <span class="s">&quot;a&quot;</span> // main.wren
<span class="k">import</span> <span class="s">&quot;b&quot;</span> import "a"
import "b"
<span class="c1">// a.wren</span> // a.wren
<span class="k">import</span> <span class="s">&quot;shared&quot;</span> import "shared"
<span class="c1">// b.wren</span> // b.wren
<span class="k">import</span> <span class="s">&quot;shared&quot;</span> import "shared"
<span class="c1">// shared.wren</span> // shared.wren
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Shared!&quot;</span><span class="p">)</span> System.print("Shared!")
</pre></div> </pre>
<p>Here, &ldquo;a&rdquo; and &ldquo;b&rdquo; both want to use &ldquo;shared&rdquo;. If &ldquo;shared&rdquo; defines some top-level
<p>Here, &ldquo;a&rdquo; and &ldquo;b&rdquo; both want to use &ldquo;shared&rdquo;. If &ldquo;shared&rdquo; defines some top-level state, we only want a single copy of that in memory. To handle this, a module&rsquo;s
state, we only want a single copy of that in memory. To handle this, a module&rsquo;s code is only executed the <em>first</em> time it is loaded. After that, importing the
code is only executed the <em>first</em> time it is loaded. After that, importing the module again just looks up the previously loaded module.</p>
module again just looks up the previously loaded module. </p> <p>Internally, Wren maintains a map of every module it has previously loaded. When
<p>Internally, Wren maintains a map of every module it has previously loaded. When a module is imported, Wren looks for it in that map first before it calls out
a module is imported, Wren looks for it in that map first before it calls out to the embedder for its source.</p>
to the embedder for its source. </p> <p>In other words, in that list of steps above, there&rsquo;s an implicit zeroth step:
<p>In other words, in that list of steps above, there&rsquo;s an implicit zeroth step: &ldquo;See if we already loaded the module and reuse it if we did&rdquo;. That means the
&ldquo;See if we already loaded the module and reuse it if we did&rdquo;. That means the above program only prints &ldquo;Shared!&rdquo; once.</p>
above program only prints &ldquo;Shared!&rdquo; once. </p>
<h2>Cyclic imports <a href="#cyclic-imports" name="cyclic-imports" class="header-anchor">#</a></h2> <h2>Cyclic imports <a href="#cyclic-imports" name="cyclic-imports" class="header-anchor">#</a></h2>
<p>You can even have cycles in your imports, provided you&rsquo;re a bit careful with <p>You can even have cycles in your imports, provided you&rsquo;re a bit careful with
them. The loading process, in detail, is: </p> them. The loading process, in detail, is:</p>
<ol> <ol>
<li>See if we have already created a module with the given name. </li> <li>See if we have already created a module with the given name.</li>
<li>If so, use it. </li> <li>If so, use it.</li>
<li>Otherwise, create a new module with the name and store it in the module <li>Otherwise, create a new module with the name and store it in the module
registry. </li> registry.</li>
<li>Create a fiber for it and execute its code. </li> <li>Create a fiber for it and execute its code.</li>
</ol> </ol>
<p>Note the order of the last two steps. When a module is loaded, it is added to <p>Note the order of the last two steps. When a module is loaded, it is added to
the registry <em>before</em> it is executed. This means if an import for that same the registry <em>before</em> it is executed. This means if an import for that same
module is reached while the module itself or one of its imports is executing, module is reached while the module itself or one of its imports is executing,
it will be found in the registry and the cycle is short-circuited. </p> it will be found in the registry and the cycle is short-circuited.</p>
<p>For example: </p> <p>For example:</p>
<div class="codehilite"><pre><span class="c1">// main.wren</span> <pre class="snippet">
<span class="k">import</span> <span class="s">&quot;a&quot;</span> // main.wren
import "a"
<span class="c1">// a.wren</span> // a.wren
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;start a&quot;</span><span class="p">)</span> System.print("start a")
<span class="k">import</span> <span class="s">&quot;b&quot;</span> import "b"
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;end a&quot;</span><span class="p">)</span> System.print("end a")
<span class="c1">// b.wren</span> // b.wren
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;start b&quot;</span><span class="p">)</span> System.print("start b")
<span class="k">import</span> <span class="s">&quot;a&quot;</span> import "a"
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;end b&quot;</span><span class="p">)</span> System.print("end b")
</pre></div> </pre>
<p>This program runs successfully and prints:</p>
<p>This program runs successfully and prints: </p> <pre><code>start a
<div class="codehilite"><pre>start a start b
start b end b
end b
end a end a
</pre></div> </code></pre>
<p>Where you have to be careful is binding variables. Consider:</p>
<pre class="snippet">
// main.wren
import "a"
// a.wren
import "b" for B
var A = "a variable"
<p>Where you have to be careful is binding variables. Consider: </p> // b.wren
<div class="codehilite"><pre><span class="c1">// main.wren</span> import "a" for A
<span class="k">import</span> <span class="s">&quot;a&quot;</span> var B = "b variable"
</pre>
<span class="c1">// a.wren</span> <p>The import of &ldquo;a&rdquo; in b.wren will fail here. If you trace the execution, you
<span class="k">import</span> <span class="s">&quot;b&quot;</span> <span class="k">for</span> <span class="err">B</span> get:</p>
<span class="k">var</span> <span class="err">A</span> <span class="o">=</span> <span class="s">&quot;a variable&quot;</span>
<span class="c1">// b.wren</span>
<span class="k">import</span> <span class="s">&quot;a&quot;</span> <span class="k">for</span> <span class="err">A</span>
<span class="k">var</span> <span class="err">B</span> <span class="o">=</span> <span class="s">&quot;b variable&quot;</span>
</pre></div>
<p>The import of &ldquo;a&rdquo; in b.wren will fail here. If you trace the execution, you
get: </p>
<ol> <ol>
<li>Execute <code>import "a"</code> in &ldquo;main.wren&rdquo;. That suspends &ldquo;main.wren&rdquo;. </li> <li>Execute <code>import "a"</code> in &ldquo;main.wren&rdquo;. That suspends &ldquo;main.wren&rdquo;.</li>
<li>Execute <code>import "b"</code> in &ldquo;a.wren&rdquo;. That suspends &ldquo;a.wren&rdquo;. </li> <li>Execute <code>import "b"</code> in &ldquo;a.wren&rdquo;. That suspends &ldquo;a.wren&rdquo;.</li>
<li>Execute <code>import "a"</code> in &ldquo;b.wren&rdquo;. Since &ldquo;a&rdquo; is already in the module map, <li>Execute <code>import "a"</code> in &ldquo;b.wren&rdquo;. Since &ldquo;a&rdquo; is already in the module map,
this does <em>not</em> suspend it. </li> this does <em>not</em> suspend it.</li>
</ol> </ol>
<p>Instead, we look for a variable named <code>A</code> in that module. But it hasn&rsquo;t been <p>Instead, we look for a variable named <code>A</code> in that module. But it hasn&rsquo;t been
defined yet since &ldquo;a.wren&rdquo; is still sitting on the <code>import "b" for B</code> line defined yet since &ldquo;a.wren&rdquo; is still sitting on the <code>import "b" for B</code> line
before the declaration. To get this to work, you would need to move the before the declaration. To get this to work, you would need to move the
variable declaration above the import: </p> variable declaration above the import:</p>
<div class="codehilite"><pre><span class="c1">// main.wren</span> <pre class="snippet">
<span class="k">import</span> <span class="s">&quot;a&quot;</span> // main.wren
import "a"
<span class="c1">// a.wren</span> // a.wren
<span class="k">var</span> <span class="err">A</span> <span class="o">=</span> <span class="s">&quot;a variable&quot;</span> var A = "a variable"
<span class="k">import</span> <span class="s">&quot;b&quot;</span> <span class="k">for</span> <span class="err">B</span> import "b" for B
<span class="c1">// b.wren</span> // b.wren
<span class="k">import</span> <span class="s">&quot;a&quot;</span> <span class="k">for</span> <span class="err">A</span> import "a" for A
<span class="k">var</span> <span class="err">B</span> <span class="o">=</span> <span class="s">&quot;b variable&quot;</span> var B = "b variable"
</pre></div> </pre>
<p>Now when we run it, we get:</p>
<p>Now when we run it, we get: </p>
<ol> <ol>
<li>Execute <code>import "a"</code> in &ldquo;main.wren&rdquo;. That suspends &ldquo;main.wren&rdquo;. </li> <li>Execute <code>import "a"</code> in &ldquo;main.wren&rdquo;. That suspends &ldquo;main.wren&rdquo;.</li>
<li>Define <code>A</code> in &ldquo;a.wren&rdquo;. </li> <li>Define <code>A</code> in &ldquo;a.wren&rdquo;.</li>
<li>Execute <code>import "b"</code> in &ldquo;a.wren&rdquo;. That suspends &ldquo;a.wren&rdquo;. </li> <li>Execute <code>import "b"</code> in &ldquo;a.wren&rdquo;. That suspends &ldquo;a.wren&rdquo;.</li>
<li>Execute <code>import "a"</code> in &ldquo;b.wren&rdquo;. Since &ldquo;a&rdquo; is already in the module map, <li>Execute <code>import "a"</code> in &ldquo;b.wren&rdquo;. Since &ldquo;a&rdquo; is already in the module map,
this does <em>not</em> suspend it. It looks up <code>A</code>, which has already been defined, this does <em>not</em> suspend it. It looks up <code>A</code>, which has already been defined,
and binds it. </li> and binds it.</li>
<li>Define <code>B</code> in &ldquo;b.wren&rdquo;. </li> <li>Define <code>B</code> in &ldquo;b.wren&rdquo;.</li>
<li>Complete &ldquo;b.wren&rdquo;. </li> <li>Complete &ldquo;b.wren&rdquo;.</li>
<li>Look up <code>B</code> in &ldquo;b.wren&rdquo; and bind it in &ldquo;a.wren&rdquo;. </li> <li>Look up <code>B</code> in &ldquo;b.wren&rdquo; and bind it in &ldquo;a.wren&rdquo;.</li>
<li>Resume &ldquo;a.wren&rdquo;. </li> <li>Resume &ldquo;a.wren&rdquo;.</li>
</ol> </ol>
<p>This sounds super hairy, but that&rsquo;s because cyclic dependencies are hairy in <p>This sounds super hairy, but that&rsquo;s because cyclic dependencies are hairy in
general. The key point here is that Wren <em>can</em> handle them in the rare cases general. The key point here is that Wren <em>can</em> handle them in the rare cases
where you need them. </p> where you need them.</p>
<p><br><hr> <p><br><hr>
<a href="error-handling.html">&larr; Error Handling</a> </p> <a href="error-handling.html">&larr; Error Handling</a></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Bool Class &ndash; Wren</title> <title>Bool Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,17 +82,17 @@
</nav> </nav>
<main> <main>
<h1>Bool Class</h1> <h1>Bool Class</h1>
<p>Boolean <a href="../../values.html">values</a>. There are two instances, <code>true</code> and <code>false</code>. </p> <p>Boolean <a href="../../values.html">values</a>. There are two instances, <code>true</code> and <code>false</code>.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>!</strong> operator <a href="#-operator" name="-operator" class="header-anchor">#</a></h3> <h3><strong>!</strong> operator <a href="#-operator" name="-operator" class="header-anchor">#</a></h3>
<p>Returns the logical complement of the value. </p> <p>Returns the logical complement of the value.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="o">!</span><span class="kc">true</span><span class="p">)</span> <span class="output">false</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="o">!</span><span class="kc">false</span><span class="p">)</span> <span class="output">true</span> System.print(!true) //> false
</pre></div> System.print(!false) //> true
</pre>
<h3>toString <a href="#tostring" name="tostring" class="header-anchor">#</a></h3> <h3>toString <a href="#tostring" name="tostring" class="header-anchor">#</a></h3>
<p>The string representation of the value, either <code>"true"</code> or <code>"false"</code>. </p> <p>The string representation of the value, either <code>"true"</code> or <code>"false"</code>.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Class Class &ndash; Wren</title> <title>Class Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,27 +82,28 @@
</nav> </nav>
<main> <main>
<h1>Class Class</h1> <h1>Class Class</h1>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>name</strong> <a href="#name" name="name" class="header-anchor">#</a></h3> <h3><strong>name</strong> <a href="#name" name="name" class="header-anchor">#</a></h3>
<p>The name of the class. </p> <p>The name of the class.</p>
<h3><strong>supertype</strong> <a href="#supertype" name="supertype" class="header-anchor">#</a></h3> <h3><strong>supertype</strong> <a href="#supertype" name="supertype" class="header-anchor">#</a></h3>
<p>The superclass of this class. </p> <p>The superclass of this class.</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Crustacean</span> <span class="p">{}</span> <pre class="snippet">
<span class="k">class</span> <span class="vg">Crab</span> <span class="k">is</span> <span class="vg">Crustacean</span> <span class="p">{}</span> class Crustacean {}
class Crab is Crustacean {}
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Crab</span><span class="o">.</span><span class="n">supertype</span><span class="p">)</span> <span class="output">Crustacean</span> System.print(Crab.supertype) //> Crustacean
</pre></div> </pre>
<p>A class with no explicit superclass implicitly inherits Object:</p>
<pre class="snippet">
System.print(Crustacean.supertype) //> Object
</pre>
<p>A class with no explicit superclass implicitly inherits Object: </p> <p>Object forms the root of the class hierarchy and has no supertype:</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Crustacean</span><span class="o">.</span><span class="n">supertype</span><span class="p">)</span> <span class="output">Object</span> <pre class="snippet">
</pre></div> System.print(Object.supertype) //> null
</pre>
<p>Object forms the root of the class hierarchy and has no supertype: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Object</span><span class="o">.</span><span class="n">supertype</span><span class="p">)</span> <span class="output">null</span>
</pre></div>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Fiber Class &ndash; Wren</title> <title>Fiber Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,148 +82,148 @@
</nav> </nav>
<main> <main>
<h1>Fiber Class</h1> <h1>Fiber Class</h1>
<p>A lightweight coroutine. <a href="../../concurrency.html">Here</a> is a gentle introduction. </p> <p>A lightweight coroutine. <a href="../../concurrency.html">Here</a> is a gentle introduction.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>Fiber.<strong>abort</strong>(message) <a href="#fiber.abort(message)" name="fiber.abort(message)" class="header-anchor">#</a></h3> <h3>Fiber.<strong>abort</strong>(message) <a href="#fiber.abort(message)" name="fiber.abort(message)" class="header-anchor">#</a></h3>
<p>Raises a runtime error with the provided message: </p> <p>Raises a runtime error with the provided message:</p>
<div class="codehilite"><pre><span class="vg">Fiber</span><span class="o">.</span><span class="n">abort</span><span class="p">(</span><span class="s">&quot;Something bad happened.&quot;</span><span class="p">)</span> <pre class="snippet">
</pre></div> Fiber.abort("Something bad happened.")
</pre>
<p>If the message is <code>null</code>, does nothing.</p>
<p>If the message is <code>null</code>, does nothing. </p>
<h3>Fiber.<strong>current</strong> <a href="#fiber.current" name="fiber.current" class="header-anchor">#</a></h3> <h3>Fiber.<strong>current</strong> <a href="#fiber.current" name="fiber.current" class="header-anchor">#</a></h3>
<p>The currently executing fiber. </p> <p>The currently executing fiber.</p>
<h3>Fiber.<strong>new</strong>(function) <a href="#fiber.new(function)" name="fiber.new(function)" class="header-anchor">#</a></h3> <h3>Fiber.<strong>new</strong>(function) <a href="#fiber.new(function)" name="fiber.new(function)" class="header-anchor">#</a></h3>
<p>Creates a new fiber that executes <code>function</code> in a separate coroutine when the <p>Creates a new fiber that executes <code>function</code> in a separate coroutine when the
fiber is run. Does not immediately start running the fiber. </p> fiber is run. Does not immediately start running the fiber.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;I won&#39;t get printed&quot;</span><span class="p">)</span> var fiber = Fiber.new {
<span class="p">}</span> System.print("I won't get printed")
</pre></div> }
</pre>
<p><code>function</code> must be a function (an actual <a href="fn.html">Fn</a> instance, not just an object
<p><code>function</code> must be a function (an actual <a href="fn.html">Fn</a> instance, not just an object with a <code>call()</code> method) and it may only take zero or one parameters.</p>
with a <code>call()</code> method) and it may only take zero or one parameters. </p>
<h3>Fiber.<strong>suspend</strong>() <a href="#fiber.suspend()" name="fiber.suspend()" class="header-anchor">#</a></h3> <h3>Fiber.<strong>suspend</strong>() <a href="#fiber.suspend()" name="fiber.suspend()" class="header-anchor">#</a></h3>
<p>Pauses the current fiber, and stops the interpreter. Control returns to the <p>Pauses the current fiber, and stops the interpreter. Control returns to the
host application. </p> host application.</p>
<p>Typically, you store a reference to the fiber using <code>Fiber.current</code> before <p>Typically, you store a reference to the fiber using <code>Fiber.current</code> before
calling this. The fiber can be resumed later by calling or transferring to that calling this. The fiber can be resumed later by calling or transferring to that
reference. If there are no references to it, it is eventually garbage collected. </p> reference. If there are no references to it, it is eventually garbage collected.</p>
<p>Much like <code>yield()</code>, returns the value passed to <code>call()</code> or <code>transfer()</code> when <p>Much like <code>yield()</code>, returns the value passed to <code>call()</code> or <code>transfer()</code> when
the fiber is resumed. </p> the fiber is resumed.</p>
<h3>Fiber.<strong>yield</strong>() <a href="#fiber.yield()" name="fiber.yield()" class="header-anchor">#</a></h3> <h3>Fiber.<strong>yield</strong>() <a href="#fiber.yield()" name="fiber.yield()" class="header-anchor">#</a></h3>
<p>Pauses the current fiber and transfers control to the parent fiber. &ldquo;Parent&rdquo; <p>Pauses the current fiber and transfers control to the parent fiber. &ldquo;Parent&rdquo;
here means the last fiber that was started using <code>call</code> and not <code>transfer</code>. </p> here means the last fiber that was started using <code>call</code> and not <code>transfer</code>.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Before yield&quot;</span><span class="p">)</span> var fiber = Fiber.new {
<span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">()</span> System.print("Before yield")
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;After yield&quot;</span><span class="p">)</span> Fiber.yield()
<span class="p">}</span> System.print("After yield")
}
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> <span class="output">Before yield</span> fiber.call() //> Before yield
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;After call&quot;</span><span class="p">)</span> <span class="output">After call</span> System.print("After call") //> After call
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> <span class="output">After yield</span> fiber.call() //> After yield
</pre></div> </pre>
<p>When resumed, the parent fiber&rsquo;s <code>call()</code> method returns <code>null</code>.</p>
<p>If a yielded fiber is resumed by calling <code>call()</code> or <code>transfer()</code> with an
argument, <code>yield()</code> returns that value.</p>
<pre class="snippet">
var fiber = Fiber.new {
System.print(Fiber.yield()) //> value
}
<p>When resumed, the parent fiber&rsquo;s <code>call()</code> method returns <code>null</code>. </p> fiber.call() // Run until the first yield.
<p>If a yielded fiber is resumed by calling <code>call()</code> or <code>transfer()</code> with an fiber.call("value") // Resume the fiber.
argument, <code>yield()</code> returns that value. </p> </pre>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">())</span> <span class="output">value</span>
<span class="p">}</span>
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span> <span class="c1">// Run until the first yield.</span>
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;value&quot;</span><span class="p">)</span> <span class="c1">// Resume the fiber.</span>
</pre></div>
<p>If it was resumed by calling <code>call()</code> or <code>transfer()</code> with no argument, it
returns <code>null</code>. </p>
<p>If there is no parent fiber to return to, this exits the interpreter. This can
be useful to pause execution until the host application wants to resume it
later. </p>
<div class="codehilite"><pre><span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">()</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;this does not get reached&quot;</span><span class="p">)</span>
</pre></div>
<p>If it was resumed by calling <code>call()</code> or <code>transfer()</code> with no argument, it
returns <code>null</code>.</p>
<p>If there is no parent fiber to return to, this exits the interpreter. This can
be useful to pause execution until the host application wants to resume it
later.</p>
<pre class="snippet">
Fiber.yield()
System.print("this does not get reached")
</pre>
<h3>Fiber.<strong>yield</strong>(value) <a href="#fiber.yield(value)" name="fiber.yield(value)" class="header-anchor">#</a></h3> <h3>Fiber.<strong>yield</strong>(value) <a href="#fiber.yield(value)" name="fiber.yield(value)" class="header-anchor">#</a></h3>
<p>Similar to <code>Fiber.yield</code> but provides a value to return to the parent fiber&rsquo;s <p>Similar to <code>Fiber.yield</code> but provides a value to return to the parent fiber&rsquo;s
<code>call</code>. </p> <code>call</code>.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">(</span><span class="s">&quot;value&quot;</span><span class="p">)</span> var fiber = Fiber.new {
<span class="p">}</span> Fiber.yield("value")
}
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">())</span> <span class="output">value</span>
</pre></div>
System.print(fiber.call()) //> value
</pre>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>call</strong>() <a href="#call()" name="call()" class="header-anchor">#</a></h3> <h3><strong>call</strong>() <a href="#call()" name="call()" class="header-anchor">#</a></h3>
<p>Starts or resumes the fiber if it is in a paused state. Equivalent to: </p> <p>Starts or resumes the fiber if it is in a paused state. Equivalent to:</p>
<div class="codehilite"><pre><span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="kc">null</span><span class="p">)</span> <pre class="snippet">
</pre></div> fiber.call(null)
</pre>
<h3><strong>call</strong>(value) <a href="#call(value)" name="call(value)" class="header-anchor">#</a></h3> <h3><strong>call</strong>(value) <a href="#call(value)" name="call(value)" class="header-anchor">#</a></h3>
<p>Start or resumes the fiber if it is in a paused state. If the fiber is being <p>Start or resumes the fiber if it is in a paused state. If the fiber is being
started for the first time, and its function takes a parameter, <code>value</code> is started for the first time, and its function takes a parameter, <code>value</code> is
passed to it. </p> passed to it.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span><span class="o">|</span><span class="n">param</span><span class="o">|</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">param</span><span class="p">)</span> <span class="output">begin</span> var fiber = Fiber.new {|param|
<span class="p">}</span> System.print(param) //> begin
}
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;begin&quot;</span><span class="p">)</span> fiber.call("begin")
</pre></div> </pre>
<p>If the fiber is being resumed, <code>value</code> becomes the returned value of the fiber&rsquo;s
call to <code>yield</code>.</p>
<pre class="snippet">
var fiber = Fiber.new {
System.print(Fiber.yield()) //> resume
}
<p>If the fiber is being resumed, <code>value</code> becomes the returned value of the fiber&rsquo;s fiber.call()
call to <code>yield</code>. </p> fiber.call("resume")
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> </pre>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Fiber</span><span class="o">.</span><span class="n">yield</span><span class="p">())</span> <span class="output">resume</span>
<span class="p">}</span>
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">()</span>
<span class="n">fiber</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;resume&quot;</span><span class="p">)</span>
</pre></div>
<h3><strong>error</strong> <a href="#error" name="error" class="header-anchor">#</a></h3> <h3><strong>error</strong> <a href="#error" name="error" class="header-anchor">#</a></h3>
<p>The error message that was passed when aborting the fiber, or <code>null</code> if the <p>The error message that was passed when aborting the fiber, or <code>null</code> if the
fiber has not been aborted. </p> fiber has not been aborted.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="mi">123</span><span class="o">.</span><span class="n">badMethod</span> var fiber = Fiber.new {
<span class="p">}</span> 123.badMethod
}
<span class="n">fiber</span><span class="o">.</span><span class="n">try</span><span class="p">()</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">fiber</span><span class="o">.</span><span class="n">error</span><span class="p">)</span> <span class="output">Num does not implement method &#39;badMethod&#39;.</span>
</pre></div>
fiber.try()
System.print(fiber.error) //> Num does not implement method 'badMethod'.
</pre>
<h3><strong>isDone</strong> <a href="#isdone" name="isdone" class="header-anchor">#</a></h3> <h3><strong>isDone</strong> <a href="#isdone" name="isdone" class="header-anchor">#</a></h3>
<p>Whether the fiber&rsquo;s main function has completed and the fiber can no longer be <p>Whether the fiber&rsquo;s main function has completed and the fiber can no longer be
run. This returns <code>false</code> if the fiber is currently running or has yielded. </p> run. This returns <code>false</code> if the fiber is currently running or has yielded.</p>
<h3><strong>try</strong>() <a href="#try()" name="try()" class="header-anchor">#</a></h3> <h3><strong>try</strong>() <a href="#try()" name="try()" class="header-anchor">#</a></h3>
<p>Tries to run the fiber. If a runtime error occurs <p>Tries to run the fiber. If a runtime error occurs
in the called fiber, the error is captured and is returned as a string. </p> in the called fiber, the error is captured and is returned as a string.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fiber</span> <span class="o">=</span> <span class="vg">Fiber</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="mi">123</span><span class="o">.</span><span class="n">badMethod</span> var fiber = Fiber.new {
<span class="p">}</span> 123.badMethod
}
<span class="k">var</span> <span class="n">error</span> <span class="o">=</span> <span class="n">fiber</span><span class="o">.</span><span class="n">try</span><span class="p">()</span> var error = fiber.try()
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Caught error: &quot;</span> <span class="o">+</span> <span class="n">error</span><span class="p">)</span> System.print("Caught error: " + error)
</pre></div> </pre>
<p>If the called fiber raises an error, it can no longer be used.</p>
<p>If the called fiber raises an error, it can no longer be used. </p>
<h3><strong>transfer</strong>() <a href="#transfer()" name="transfer()" class="header-anchor">#</a></h3> <h3><strong>transfer</strong>() <a href="#transfer()" name="transfer()" class="header-anchor">#</a></h3>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<h3><strong>transfer</strong>(value) <a href="#transfer(value)" name="transfer(value)" class="header-anchor">#</a></h3> <h3><strong>transfer</strong>(value) <a href="#transfer(value)" name="transfer(value)" class="header-anchor">#</a></h3>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<h3><strong>transferError</strong>(error) <a href="#transfererror(error)" name="transfererror(error)" class="header-anchor">#</a></h3> <h3><strong>transferError</strong>(error) <a href="#transfererror(error)" name="transfererror(error)" class="header-anchor">#</a></h3>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Fn Class &ndash; Wren</title> <title>Fn Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,42 +82,42 @@
</nav> </nav>
<main> <main>
<h1>Fn Class</h1> <h1>Fn Class</h1>
<p>A first class function&mdash;an object that wraps an executable chunk of code. <p>A first class function&mdash;an object that wraps an executable chunk of code.
<a href="../../functions.html">Here</a> is a friendly introduction. </p> <a href="../../functions.html">Here</a> is a friendly introduction.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>Fn.<strong>new</strong>(function) <a href="#fn.new(function)" name="fn.new(function)" class="header-anchor">#</a></h3> <h3>Fn.<strong>new</strong>(function) <a href="#fn.new(function)" name="fn.new(function)" class="header-anchor">#</a></h3>
<p>Creates a new function from&hellip; <code>function</code>. Of course, <code>function</code> is already a <p>Creates a new function from&hellip; <code>function</code>. Of course, <code>function</code> is already a
function, so this really just returns the argument. It exists mainly to let you function, so this really just returns the argument. It exists mainly to let you
create a &ldquo;bare&rdquo; function when you don&rsquo;t want to immediately pass it as a <a href="../functions.html#block-arguments">block create a &ldquo;bare&rdquo; function when you don&rsquo;t want to immediately pass it as a <a href="../functions.html#block-arguments">block
argument</a> to some other method. </p> argument</a> to some other method.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fn</span> <span class="o">=</span> <span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;The body&quot;</span><span class="p">)</span> var fn = Fn.new {
<span class="p">}</span> System.print("The body")
</pre></div> }
</pre>
<p>It is a runtime error if <code>function</code> is not a function.</p>
<p>It is a runtime error if <code>function</code> is not a function. </p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>arity</strong> <a href="#arity" name="arity" class="header-anchor">#</a></h3> <h3><strong>arity</strong> <a href="#arity" name="arity" class="header-anchor">#</a></h3>
<p>The number of arguments the function requires. </p> <p>The number of arguments the function requires.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{}</span><span class="o">.</span><span class="n">arity</span><span class="p">)</span> <span class="output">0</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span><span class="o">|</span><span class="err">a</span><span class="p">,</span> <span class="err">b</span><span class="p">,</span> <span class="err">c</span><span class="o">|</span> <span class="err">a</span> <span class="p">}</span><span class="o">.</span><span class="n">arity</span><span class="p">)</span> <span class="output">3</span> System.print(Fn.new {}.arity) //> 0
</pre></div> System.print(Fn.new {|a, b, c| a }.arity) //> 3
</pre>
<h3><strong>call</strong>(args&hellip;) <a href="#call(args...)" name="call(args...)" class="header-anchor">#</a></h3> <h3><strong>call</strong>(args&hellip;) <a href="#call(args...)" name="call(args...)" class="header-anchor">#</a></h3>
<p>Invokes the function with the given arguments. </p> <p>Invokes the function with the given arguments.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">fn</span> <span class="o">=</span> <span class="vg">Fn</span><span class="o">.</span><span class="n">new</span> <span class="p">{</span> <span class="o">|</span><span class="n">arg</span><span class="o">|</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="output">Hello world</span> var fn = Fn.new { |arg|
<span class="p">}</span> System.print(arg) //> Hello world
}
<span class="n">fn</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="s">&quot;Hello world&quot;</span><span class="p">)</span> fn.call("Hello world")
</pre></div> </pre>
<p>It is a runtime error if the number of arguments given is less than the arity
<p>It is a runtime error if the number of arguments given is less than the arity of the function. If more arguments are given than the function&rsquo;s arity they are
of the function. If more arguments are given than the function&rsquo;s arity they are ignored.</p>
ignored. </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -2,7 +2,10 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Module "core" &ndash; Wren</title> <title> &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -79,27 +81,10 @@
</table> </table>
</nav> </nav>
<main> <main>
<h1>Module "core"</h1> <h1></h1>
<p>Because Wren is designed for <a href="../../embedding-api.html">embedding in applications</a>, its core <script type="text/javascript">
module is minimal and is focused on working with objects within Wren. For window.location = '../'
stuff like file IO, graphics, etc., it is up to the host application to provide </script>
interfaces for this. </p>
<p>All Wren source files automatically have access to the following classes: </p>
<ul>
<li><a href="bool.html">Bool</a> </li>
<li><a href="class.html">Class</a> </li>
<li><a href="fiber.html">Fiber</a> </li>
<li><a href="fn.html">Fn</a> </li>
<li><a href="list.html">List</a> </li>
<li><a href="map.html">Map</a> </li>
<li><a href="null.html">Null</a> </li>
<li><a href="num.html">Num</a> </li>
<li><a href="object.html">Object</a> </li>
<li><a href="range.html">Range</a> </li>
<li><a href="sequence.html">Sequence</a> </li>
<li><a href="string.html">String</a> </li>
<li><a href="system.html">System</a> </li>
</ul>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>List Class &ndash; Wren</title> <title>List Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,95 +82,96 @@
</nav> </nav>
<main> <main>
<h1>List Class</h1> <h1>List Class</h1>
<p>Extends <a href="sequence.html">Sequence</a>. </p> <p>Extends <a href="sequence.html">Sequence</a>.</p>
<p>An indexable contiguous collection of elements. More details <a href="../../lists.html">here</a>. </p> <p>An indexable contiguous collection of elements. More details <a href="../../lists.html">here</a>.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>List.<strong>filled</strong>(size, element) <a href="#list.filled(size,-element)" name="list.filled(size,-element)" class="header-anchor">#</a></h3> <h3>List.<strong>filled</strong>(size, element) <a href="#list.filled(size,-element)" name="list.filled(size,-element)" class="header-anchor">#</a></h3>
<p>Creates a new list with <code>size</code> elements, all set to <code>element</code>. </p> <p>Creates a new list with <code>size</code> elements, all set to <code>element</code>.</p>
<p>It is a runtime error if <code>size</code> is not a nonnegative integer. </p> <p>It is a runtime error if <code>size</code> is not a nonnegative integer.</p>
<h3>List.<strong>new</strong>() <a href="#list.new()" name="list.new()" class="header-anchor">#</a></h3> <h3>List.<strong>new</strong>() <a href="#list.new()" name="list.new()" class="header-anchor">#</a></h3>
<p>Creates a new empty list. Equivalent to <code>[]</code>. </p> <p>Creates a new empty list. Equivalent to <code>[]</code>.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>add</strong>(item) <a href="#add(item)" name="add(item)" class="header-anchor">#</a></h3> <h3><strong>add</strong>(item) <a href="#add(item)" name="add(item)" class="header-anchor">#</a></h3>
<p>Appends <code>item</code> to the end of the list. </p> <p>Appends <code>item</code> to the end of the list.</p>
<h3><strong>clear</strong>() <a href="#clear()" name="clear()" class="header-anchor">#</a></h3> <h3><strong>clear</strong>() <a href="#clear()" name="clear()" class="header-anchor">#</a></h3>
<p>Removes all elements from the list. </p> <p>Removes all elements from the list.</p>
<h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3> <h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3>
<p>The number of elements in the list. </p> <p>The number of elements in the list.</p>
<h3><strong>insert</strong>(index, item) <a href="#insert(index,-item)" name="insert(index,-item)" class="header-anchor">#</a></h3> <h3><strong>insert</strong>(index, item) <a href="#insert(index,-item)" name="insert(index,-item)" class="header-anchor">#</a></h3>
<p>Inserts the <code>item</code> at <code>index</code> in the list. </p> <p>Inserts the <code>item</code> at <code>index</code> in the list.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="n">list</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">&quot;e&quot;</span><span class="p">)</span> var list = ["a", "b", "c", "d"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">list</span><span class="p">)</span> <span class="output">[a, e, b, c, d]</span> list.insert(1, "e")
</pre></div> System.print(list) //> [a, e, b, c, d]
</pre>
<p>The <code>index</code> may be one past the last index in the list to append an element.</p>
<pre class="snippet">
var list = ["a", "b", "c"]
list.insert(3, "d")
System.print(list) //> [a, b, c, d]
</pre>
<p>The <code>index</code> may be one past the last index in the list to append an element. </p> <p>If <code>index</code> is negative, it counts backwards from the end of the list. It bases this on the length of the list <em>after</em> inserted the element, so that <code>-1</code> will append the element, not insert it before the last element.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="n">list</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">)</span> var list = ["a", "b"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">list</span><span class="p">)</span> <span class="output">[a, b, c, d]</span> list.insert(-1, "d")
</pre></div> list.insert(-2, "c")
System.print(list) //> [a, b, c, d]
</pre>
<p>Returns the inserted item.</p>
<pre class="snippet">
System.print(["a", "c"].insert(1, "b")) //> b
</pre>
<p>If <code>index</code> is negative, it counts backwards from the end of the list. It bases this on the length of the list <em>after</em> inserted the element, so that <code>-1</code> will append the element, not insert it before the last element. </p> <p>It is a runtime error if the index is not an integer or is out of bounds.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">]</span>
<span class="n">list</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">)</span>
<span class="n">list</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">)</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">list</span><span class="p">)</span> <span class="output">[a, b, c, d]</span>
</pre></div>
<p>Returns the inserted item. </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">))</span> <span class="output">b</span>
</pre></div>
<p>It is a runtime error if the index is not an integer or is out of bounds. </p>
<h3><strong>iterate</strong>(iterator), <strong>iteratorValue</strong>(iterator) <a href="#iterate(iterator),-iteratorvalue(iterator)" name="iterate(iterator),-iteratorvalue(iterator)" class="header-anchor">#</a></h3> <h3><strong>iterate</strong>(iterator), <strong>iteratorValue</strong>(iterator) <a href="#iterate(iterator),-iteratorvalue(iterator)" name="iterate(iterator),-iteratorvalue(iterator)" class="header-anchor">#</a></h3>
<p>Implements the <a href="../../control-flow.html#the-iterator-protocol">iterator protocol</a> for iterating over the elements in the <p>Implements the <a href="../../control-flow.html#the-iterator-protocol">iterator protocol</a> for iterating over the elements in the
list. </p> list.</p>
<h3><strong>removeAt</strong>(index) <a href="#removeat(index)" name="removeat(index)" class="header-anchor">#</a></h3> <h3><strong>removeAt</strong>(index) <a href="#removeat(index)" name="removeat(index)" class="header-anchor">#</a></h3>
<p>Removes the element at <code>index</code>. If <code>index</code> is negative, it counts backwards <p>Removes the element at <code>index</code>. If <code>index</code> is negative, it counts backwards
from the end of the list where <code>-1</code> is the last element. All trailing elements from the end of the list where <code>-1</code> is the last element. All trailing elements
are shifted up to fill in where the removed element was. </p> are shifted up to fill in where the removed element was.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="n">list</span><span class="o">.</span><span class="n">removeAt</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> var list = ["a", "b", "c", "d"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">list</span><span class="p">)</span> <span class="output">[a, c, d]</span> list.removeAt(1)
</pre></div> System.print(list) //> [a, c, d]
</pre>
<p>Returns the removed item.</p>
<pre class="snippet">
System.print(["a", "b", "c"].removeAt(1)) //> b
</pre>
<p>Returns the removed item. </p> <p>It is a runtime error if the index is not an integer or is out of bounds.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">removeAt</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="output">b</span>
</pre></div>
<p>It is a runtime error if the index is not an integer or is out of bounds. </p>
<h3><strong>[</strong>index<strong>]</strong> operator <a href="#[index]-operator" name="[index]-operator" class="header-anchor">#</a></h3> <h3><strong>[</strong>index<strong>]</strong> operator <a href="#[index]-operator" name="[index]-operator" class="header-anchor">#</a></h3>
<p>Gets the element at <code>index</code>. If <code>index</code> is negative, it counts backwards from <p>Gets the element at <code>index</code>. If <code>index</code> is negative, it counts backwards from
the end of the list where <code>-1</code> is the last element. </p> the end of the list where <code>-1</code> is the last element.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">list</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="output">b</span> var list = ["a", "b", "c"]
</pre></div> System.print(list[1]) //> b
</pre>
<p>It is a runtime error if the index is not an integer or is out of bounds.</p>
<p>It is a runtime error if the index is not an integer or is out of bounds. </p>
<h3><strong>[</strong>index<strong>]=</strong>(item) operator <a href="#[index]=(item)-operator" name="[index]=(item)-operator" class="header-anchor">#</a></h3> <h3><strong>[</strong>index<strong>]=</strong>(item) operator <a href="#[index]=(item)-operator" name="[index]=(item)-operator" class="header-anchor">#</a></h3>
<p>Replaces the element at <code>index</code> with <code>item</code>. If <code>index</code> is negative, it counts <p>Replaces the element at <code>index</code> with <code>item</code>. If <code>index</code> is negative, it counts
backwards from the end of the list where <code>-1</code> is the last element. </p> backwards from the end of the list where <code>-1</code> is the last element.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="n">list</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;new&quot;</span> var list = ["a", "b", "c"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">list</span><span class="p">)</span> <span class="output">[a, new, c]</span> list[1] = "new"
</pre></div> System.print(list) //> [a, new, c]
</pre>
<p>It is a runtime error if the index is not an integer or is out of bounds.</p>
<p>It is a runtime error if the index is not an integer or is out of bounds. </p>
<h2><strong>+</strong>(other) operator <a href="#+(other)-operator" name="+(other)-operator" class="header-anchor">#</a></h2> <h2><strong>+</strong>(other) operator <a href="#+(other)-operator" name="+(other)-operator" class="header-anchor">#</a></h2>
<p>Appends a list to the end of the list (concatenation). <code>other</code> must be a <code>List</code>. </p> <p>Appends a list to the end of the list (concatenation). <code>other</code> must be a <code>List</code>.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">letters</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">]</span> <pre class="snippet">
<span class="k">var</span> <span class="n">other</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;d&quot;</span><span class="p">,</span> <span class="s">&quot;e&quot;</span><span class="p">,</span> <span class="s">&quot;f&quot;</span><span class="p">]</span> var letters = ["a", "b", "c"]
<span class="k">var</span> <span class="n">combined</span> <span class="o">=</span> <span class="n">letters</span> <span class="o">+</span> <span class="n">other</span> var other = ["d", "e", "f"]
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">combined</span><span class="p">)</span> <span class="output">[a, b, c, d, e, f]</span> var combined = letters + other
</pre></div> System.print(combined) //> [a, b, c, d, e, f]
</pre>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Map Class &ndash; Wren</title> <title>Map Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,42 +82,42 @@
</nav> </nav>
<main> <main>
<h1>Map Class</h1> <h1>Map Class</h1>
<p>An associative collection that maps keys to values. More details <a href="../../maps.html">here</a>. </p> <p>An associative collection that maps keys to values. More details <a href="../../maps.html">here</a>.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>clear</strong>() <a href="#clear()" name="clear()" class="header-anchor">#</a></h3> <h3><strong>clear</strong>() <a href="#clear()" name="clear()" class="header-anchor">#</a></h3>
<p>Removes all entries from the map. </p> <p>Removes all entries from the map.</p>
<h3><strong>containsKey</strong>(key) <a href="#containskey(key)" name="containskey(key)" class="header-anchor">#</a></h3> <h3><strong>containsKey</strong>(key) <a href="#containskey(key)" name="containskey(key)" class="header-anchor">#</a></h3>
<p>Returns <code>true</code> if the map contains <code>key</code> or <code>false</code> otherwise. </p> <p>Returns <code>true</code> if the map contains <code>key</code> or <code>false</code> otherwise.</p>
<h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3> <h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3>
<p>The number of entries in the map. </p> <p>The number of entries in the map.</p>
<h3><strong>keys</strong> <a href="#keys" name="keys" class="header-anchor">#</a></h3> <h3><strong>keys</strong> <a href="#keys" name="keys" class="header-anchor">#</a></h3>
<p>A <a href="sequence.html">Sequence</a> that can be used to iterate over the keys in the <p>A <a href="sequence.html">Sequence</a> that can be used to iterate over the keys in the
map. Note that iteration order is undefined. All keys will be iterated over, map. Note that iteration order is undefined. All keys will be iterated over,
but may be in any order, and may even change between invocations of Wren. </p> but may be in any order, and may even change between invocations of Wren.</p>
<h3><strong>remove</strong>(key) <a href="#remove(key)" name="remove(key)" class="header-anchor">#</a></h3> <h3><strong>remove</strong>(key) <a href="#remove(key)" name="remove(key)" class="header-anchor">#</a></h3>
<p>Removes <code>key</code> and the value associated with it from the map. Returns the value. </p> <p>Removes <code>key</code> and the value associated with it from the map. Returns the value.</p>
<p>If the key was not present, returns <code>null</code>. </p> <p>If the key was not present, returns <code>null</code>.</p>
<h3><strong>values</strong> <a href="#values" name="values" class="header-anchor">#</a></h3> <h3><strong>values</strong> <a href="#values" name="values" class="header-anchor">#</a></h3>
<p>A <a href="sequence.html">Sequence</a> that can be used to iterate over the values in the <p>A <a href="sequence.html">Sequence</a> that can be used to iterate over the values in the
map. Note that iteration order is undefined. All values will be iterated over, map. Note that iteration order is undefined. All values will be iterated over,
but may be in any order, and may even change between invocations of Wren. </p> but may be in any order, and may even change between invocations of Wren.</p>
<p>If multiple keys are associated with the same value, the value will appear <p>If multiple keys are associated with the same value, the value will appear
multiple times in the sequence. </p> multiple times in the sequence.</p>
<h3><strong>[</strong>key<strong>]</strong> operator <a href="#[key]-operator" name="[key]-operator" class="header-anchor">#</a></h3> <h3><strong>[</strong>key<strong>]</strong> operator <a href="#[key]-operator" name="[key]-operator" class="header-anchor">#</a></h3>
<p>Gets the value associated with <code>key</code> in the map. If <code>key</code> is not present in the <p>Gets the value associated with <code>key</code> in the map. If <code>key</code> is not present in the
map, returns <code>null</code>. </p> map, returns <code>null</code>.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">map</span> <span class="o">=</span> <span class="p">{</span><span class="s">&quot;george&quot;</span><span class="o">:</span> <span class="s">&quot;harrison&quot;</span><span class="p">,</span> <span class="s">&quot;ringo&quot;</span><span class="o">:</span> <span class="s">&quot;starr&quot;</span><span class="p">}</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">map</span><span class="p">[</span><span class="s">&quot;ringo&quot;</span><span class="p">])</span> <span class="output">starr</span> var map = {"george": "harrison", "ringo": "starr"}
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">map</span><span class="p">[</span><span class="s">&quot;pete&quot;</span><span class="p">])</span> <span class="output">null</span> System.print(map["ringo"]) //> starr
</pre></div> System.print(map["pete"]) //> null
</pre>
<h3><strong>[</strong>key<strong>]=</strong>(value) operator <a href="#[key]=(value)-operator" name="[key]=(value)-operator" class="header-anchor">#</a></h3> <h3><strong>[</strong>key<strong>]=</strong>(value) operator <a href="#[key]=(value)-operator" name="[key]=(value)-operator" class="header-anchor">#</a></h3>
<p>Associates <code>value</code> with <code>key</code> in the map. If <code>key</code> was already in the map, this <p>Associates <code>value</code> with <code>key</code> in the map. If <code>key</code> was already in the map, this
replaces the previous association. </p> replaces the previous association.</p>
<p>It is a runtime error if the key is not a <a href="bool.html">Bool</a>, <p>It is a runtime error if the key is not a <a href="bool.html">Bool</a>,
<a href="class.html">Class</a>, <a href="null.html">Null</a>, <a href="num.html">Num</a>, <a href="range.html">Range</a>, <a href="class.html">Class</a>, <a href="null.html">Null</a>, <a href="num.html">Num</a>, <a href="range.html">Range</a>,
or <a href="string.html">String</a>. </p> or <a href="string.html">String</a>.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Null Class &ndash; Wren</title> <title>Null Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -82,9 +84,10 @@
<h1>Null Class</h1> <h1>Null Class</h1>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>!</strong> operator <a href="#-operator" name="-operator" class="header-anchor">#</a></h3> <h3><strong>!</strong> operator <a href="#-operator" name="-operator" class="header-anchor">#</a></h3>
<p>Returns <code>true</code>, since <code>null</code> is considered <a href="../control-flow.html#truth">false</a>. </p> <p>Returns <code>true</code>, since <code>null</code> is considered <a href="../control-flow.html#truth">false</a>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="o">!</span><span class="kc">null</span><span class="p">)</span> <span class="output">true</span> <pre class="snippet">
</pre></div> System.print(!null) //> true
</pre>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Num Class &ndash; Wren</title> <title>Num Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -82,134 +84,137 @@
<h1>Num Class</h1> <h1>Num Class</h1>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>Num.<strong>fromString</strong>(value) <a href="#num.fromstring(value)" name="num.fromstring(value)" class="header-anchor">#</a></h3> <h3>Num.<strong>fromString</strong>(value) <a href="#num.fromstring(value)" name="num.fromstring(value)" class="header-anchor">#</a></h3>
<p>Attempts to parse <code>value</code> as a decimal literal and return it as an instance of <p>Attempts to parse <code>value</code> as a decimal literal and return it as an instance of
<code>Num</code>. If the number cannot be parsed <code>null</code> will be returned. </p> <code>Num</code>. If the number cannot be parsed <code>null</code> will be returned.</p>
<p>It is a runtime error if <code>value</code> is not a string. </p> <p>It is a runtime error if <code>value</code> is not a string.</p>
<h3>Num.<strong>pi</strong> <a href="#num.pi" name="num.pi" class="header-anchor">#</a></h3> <h3>Num.<strong>pi</strong> <a href="#num.pi" name="num.pi" class="header-anchor">#</a></h3>
<p>The value of &pi;. </p> <p>The value of &pi;.</p>
<h3>Num.<strong>largest</strong> <a href="#num.largest" name="num.largest" class="header-anchor">#</a></h3> <h3>Num.<strong>largest</strong> <a href="#num.largest" name="num.largest" class="header-anchor">#</a></h3>
<p>The largest representable numeric value. </p> <p>The largest representable numeric value.</p>
<h3>Num.<strong>smallest</strong> <a href="#num.smallest" name="num.smallest" class="header-anchor">#</a></h3> <h3>Num.<strong>smallest</strong> <a href="#num.smallest" name="num.smallest" class="header-anchor">#</a></h3>
<p>The smallest positive representable numeric value. </p> <p>The smallest positive representable numeric value.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>abs</strong> <a href="#abs" name="abs" class="header-anchor">#</a></h3> <h3><strong>abs</strong> <a href="#abs" name="abs" class="header-anchor">#</a></h3>
<p>The absolute value of the number. </p> <p>The absolute value of the number.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span> <span class="p">(</span><span class="o">-</span><span class="mi">123</span><span class="p">)</span><span class="o">.</span><span class="n">abs</span> <span class="p">)</span> <span class="output">123</span> <pre class="snippet">
</pre></div> System.print( (-123).abs ) //> 123
</pre>
<h3><strong>acos</strong> <a href="#acos" name="acos" class="header-anchor">#</a></h3> <h3><strong>acos</strong> <a href="#acos" name="acos" class="header-anchor">#</a></h3>
<p>The arc cosine of the number. </p> <p>The arc cosine of the number.</p>
<h3><strong>asin</strong> <a href="#asin" name="asin" class="header-anchor">#</a></h3> <h3><strong>asin</strong> <a href="#asin" name="asin" class="header-anchor">#</a></h3>
<p>The arc sine of the number. </p> <p>The arc sine of the number.</p>
<h3><strong>atan</strong> <a href="#atan" name="atan" class="header-anchor">#</a></h3> <h3><strong>atan</strong> <a href="#atan" name="atan" class="header-anchor">#</a></h3>
<p>The arc tangent of the number. </p> <p>The arc tangent of the number.</p>
<h3><strong>atan</strong>(x) <a href="#atan(x)" name="atan(x)" class="header-anchor">#</a></h3> <h3><strong>atan</strong>(x) <a href="#atan(x)" name="atan(x)" class="header-anchor">#</a></h3>
<p>The arc tangent of the number when divided by <code>x</code>, using the signs of the two <p>The arc tangent of the number when divided by <code>x</code>, using the signs of the two
numbers to determine the quadrant of the result. </p> numbers to determine the quadrant of the result.</p>
<h3><strong>ceil</strong> <a href="#ceil" name="ceil" class="header-anchor">#</a></h3> <h3><strong>ceil</strong> <a href="#ceil" name="ceil" class="header-anchor">#</a></h3>
<p>Rounds the number up to the nearest integer. </p> <p>Rounds the number up to the nearest integer.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mf">1.5</span><span class="o">.</span><span class="n">ceil</span><span class="p">)</span> <span class="output">2</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="o">-</span><span class="mf">3.2</span><span class="p">)</span><span class="o">.</span><span class="n">ceil</span><span class="p">)</span> <span class="output">-3</span> System.print(1.5.ceil) //> 2
</pre></div> System.print((-3.2).ceil) //> -3
</pre>
<h3><strong>cos</strong> <a href="#cos" name="cos" class="header-anchor">#</a></h3> <h3><strong>cos</strong> <a href="#cos" name="cos" class="header-anchor">#</a></h3>
<p>The cosine of the number. </p> <p>The cosine of the number.</p>
<h3><strong>floor</strong> <a href="#floor" name="floor" class="header-anchor">#</a></h3> <h3><strong>floor</strong> <a href="#floor" name="floor" class="header-anchor">#</a></h3>
<p>Rounds the number down to the nearest integer. </p> <p>Rounds the number down to the nearest integer.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mf">1.5</span><span class="o">.</span><span class="n">floor</span><span class="p">)</span> <span class="output">1</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="o">-</span><span class="mf">3.2</span><span class="p">)</span><span class="o">.</span><span class="n">floor</span><span class="p">)</span> <span class="output">-4</span> System.print(1.5.floor) //> 1
</pre></div> System.print((-3.2).floor) //> -4
</pre>
<h3><strong>isInfinity</strong> <a href="#isinfinity" name="isinfinity" class="header-anchor">#</a></h3> <h3><strong>isInfinity</strong> <a href="#isinfinity" name="isinfinity" class="header-anchor">#</a></h3>
<p>Whether the number is positive or negative infinity or not. </p> <p>Whether the number is positive or negative infinity or not.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mi">99999</span><span class="o">.</span><span class="n">isInfinity</span><span class="p">)</span> <span class="output">false</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">1</span><span class="o">/</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">isInfinity</span><span class="p">)</span> <span class="output">true</span> System.print(99999.isInfinity) //> false
</pre></div> System.print((1/0).isInfinity) //> true
</pre>
<h3><strong>isInteger</strong> <a href="#isinteger" name="isinteger" class="header-anchor">#</a></h3> <h3><strong>isInteger</strong> <a href="#isinteger" name="isinteger" class="header-anchor">#</a></h3>
<p>Whether the number is an integer or has some fractional component. </p> <p>Whether the number is an integer or has some fractional component.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mi">2</span><span class="o">.</span><span class="n">isInteger</span><span class="p">)</span> <span class="output">true</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mf">2.3</span><span class="o">.</span><span class="n">isInteger</span><span class="p">)</span> <span class="output">false</span> System.print(2.isInteger) //> true
</pre></div> System.print(2.3.isInteger) //> false
</pre>
<h3><strong>isNan</strong> <a href="#isnan" name="isnan" class="header-anchor">#</a></h3> <h3><strong>isNan</strong> <a href="#isnan" name="isnan" class="header-anchor">#</a></h3>
<p>Whether the number is <a href="http://en.wikipedia.org/wiki/NaN">not a number</a>. This is <p>Whether the number is <a href="http://en.wikipedia.org/wiki/NaN">not a number</a>. This is
<code>false</code> for normal number values and infinities, and <code>true</code> for the result of <code>false</code> for normal number values and infinities, and <code>true</code> for the result of
<code>0/0</code>, the square root of a negative number, etc. </p> <code>0/0</code>, the square root of a negative number, etc.</p>
<h3><strong>log</strong> <a href="#log" name="log" class="header-anchor">#</a></h3> <h3><strong>log</strong> <a href="#log" name="log" class="header-anchor">#</a></h3>
<p>The natural logarithm of the number. </p> <p>The natural logarithm of the number.</p>
<h3><strong>pow</strong>(power) <a href="#pow(power)" name="pow(power)" class="header-anchor">#</a></h3> <h3><strong>pow</strong>(power) <a href="#pow(power)" name="pow(power)" class="header-anchor">#</a></h3>
<p>Raises this number (the base) to <code>power</code>. Returns <code>nan</code> if the base is negative. </p> <p>Raises this number (the base) to <code>power</code>. Returns <code>nan</code> if the base is negative.</p>
<h3><strong>round</strong> <a href="#round" name="round" class="header-anchor">#</a></h3> <h3><strong>round</strong> <a href="#round" name="round" class="header-anchor">#</a></h3>
<p>Rounds the number to the nearest integer. </p> <p>Rounds the number to the nearest integer.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mf">1.5</span><span class="o">.</span><span class="n">round</span><span class="p">)</span> <span class="output">2</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="o">-</span><span class="mf">3.2</span><span class="p">)</span><span class="o">.</span><span class="n">round</span><span class="p">)</span> <span class="output">-3</span> System.print(1.5.round) //> 2
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="o">-</span><span class="mf">3.7</span><span class="p">)</span><span class="o">.</span><span class="n">round</span><span class="p">)</span> <span class="output">-4</span> System.print((-3.2).round) //> -3
</pre></div> System.print((-3.7).round) //> -4
</pre>
<h3><strong>sign</strong> <a href="#sign" name="sign" class="header-anchor">#</a></h3>
<p>The sign of the number, expressed as a -1, 1 or 0, for negative and positive numbers, and zero.</p>
<h3><strong>sin</strong> <a href="#sin" name="sin" class="header-anchor">#</a></h3> <h3><strong>sin</strong> <a href="#sin" name="sin" class="header-anchor">#</a></h3>
<p>The sine of the number. </p> <p>The sine of the number.</p>
<h3><strong>sqrt</strong> <a href="#sqrt" name="sqrt" class="header-anchor">#</a></h3> <h3><strong>sqrt</strong> <a href="#sqrt" name="sqrt" class="header-anchor">#</a></h3>
<p>The square root of the number. Returns <code>nan</code> if the number is negative. </p> <p>The square root of the number. Returns <code>nan</code> if the number is negative.</p>
<h3><strong>tan</strong> <a href="#tan" name="tan" class="header-anchor">#</a></h3> <h3><strong>tan</strong> <a href="#tan" name="tan" class="header-anchor">#</a></h3>
<p>The tangent of the number. </p> <p>The tangent of the number.</p>
<h3><strong>-</strong> operator <a href="#--operator" name="--operator" class="header-anchor">#</a></h3> <h3><strong>-</strong> operator <a href="#--operator" name="--operator" class="header-anchor">#</a></h3>
<p>Negates the number. </p> <p>Negates the number.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="mi">123</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="o">-</span><span class="err">a</span><span class="p">)</span> <span class="output">-123</span> var a = 123
</pre></div> System.print(-a) //> -123
</pre>
<h3><strong>-</strong>(other), <strong>+</strong>(other), <strong>/</strong>(other), <strong>*</strong>(other) operators <a href="#-(other),-+(other),-(other),-\(other)-operators" name="-(other),-+(other),-(other),-\(other)-operators" class="header-anchor">#</a></h3> <h3><strong>-</strong>(other), <strong>+</strong>(other), <strong>/</strong>(other), <strong>*</strong>(other) operators <a href="#-(other),-+(other),-(other),-\(other)-operators" name="-(other),-+(other),-(other),-\(other)-operators" class="header-anchor">#</a></h3>
<p>The usual arithmetic operators you know and love. All of them do 64-bit <p>The usual arithmetic operators you know and love. All of them do 64-bit
floating point arithmetic. It is a runtime error if the right-hand operand is floating point arithmetic. It is a runtime error if the right-hand operand is
not a number. Wren doesn&rsquo;t roll with implicit conversions. </p> not a number. Wren doesn&rsquo;t roll with implicit conversions.</p>
<h3><strong>%</strong>(denominator) operator <a href="#%(denominator)-operator" name="%(denominator)-operator" class="header-anchor">#</a></h3> <h3><strong>%</strong>(denominator) operator <a href="#%(denominator)-operator" name="%(denominator)-operator" class="header-anchor">#</a></h3>
<p>Also known as mod or modulus. <p>Also known as mod or modulus. <br />
The floating-point remainder of this number divided by <code>denominator</code>. </p> The floating-point remainder of this number divided by <code>denominator</code>. </p>
<p>The returned value has the same sign as <code>this</code> (internally calls <code>fmod</code> from C). </p> <p>The returned value has the same sign as <code>this</code> (internally calls <code>fmod</code> from C).</p>
<p>It is a runtime error if <code>denominator</code> is not a number. </p> <p>It is a runtime error if <code>denominator</code> is not a number.</p>
<h3><strong>&lt;</strong>(other), <strong>&gt;</strong>(other), <strong>&lt;=</strong>(other), <strong>&gt;=</strong>(other) operators <a href="#&lt;(other),-&gt;(other),-&lt;=(other),-&gt;=(other)-operators" name="&lt;(other),-&gt;(other),-&lt;=(other),-&gt;=(other)-operators" class="header-anchor">#</a></h3> <h3><strong>&lt;</strong>(other), <strong>&gt;</strong>(other), <strong>&lt;=</strong>(other), <strong>&gt;=</strong>(other) operators <a href="#&lt;(other),-&gt;(other),-&lt;=(other),-&gt;=(other)-operators" name="&lt;(other),-&gt;(other),-&lt;=(other),-&gt;=(other)-operators" class="header-anchor">#</a></h3>
<p>Compares this and <code>other</code>, returning <code>true</code> or <code>false</code> based on how the numbers <p>Compares this and <code>other</code>, returning <code>true</code> or <code>false</code> based on how the numbers
are ordered. It is a runtime error if <code>other</code> is not a number. </p> are ordered. It is a runtime error if <code>other</code> is not a number.</p>
<h3><strong>~</strong> operator <a href="#~-operator" name="~-operator" class="header-anchor">#</a></h3> <h3><strong>~</strong> operator <a href="#~-operator" name="~-operator" class="header-anchor">#</a></h3>
<p>Performs <em>bitwise</em> negation on the number. The number is first converted to a <p>Performs <em>bitwise</em> negation on the number. The number is first converted to a
32-bit unsigned value, which will truncate any floating point value. The bits 32-bit unsigned value, which will truncate any floating point value. The bits
of the result of that are then negated, yielding the result. </p> of the result of that are then negated, yielding the result.</p>
<h3><strong>&amp;</strong>(other) operator <a href="#&(other)-operator" name="&(other)-operator" class="header-anchor">#</a></h3> <h3><strong>&amp;</strong>(other) operator <a href="#&(other)-operator" name="&(other)-operator" class="header-anchor">#</a></h3>
<p>Performs bitwise and on the number. Both numbers are first converted to 32-bit <p>Performs bitwise and on the number. Both numbers are first converted to 32-bit
unsigned values. The result is then a 32-bit unsigned number where each bit is unsigned values. The result is then a 32-bit unsigned number where each bit is
<code>true</code> only where the corresponding bits of both inputs were <code>true</code>. </p> <code>true</code> only where the corresponding bits of both inputs were <code>true</code>.</p>
<p>It is a runtime error if <code>other</code> is not a number. </p> <p>It is a runtime error if <code>other</code> is not a number.</p>
<h3><strong>|</strong>(other) operator <a href="#|(other)-operator" name="|(other)-operator" class="header-anchor">#</a></h3> <h3><strong>|</strong>(other) operator <a href="#|(other)-operator" name="|(other)-operator" class="header-anchor">#</a></h3>
<p>Performs bitwise or on the number. Both numbers are first converted to 32-bit <p>Performs bitwise or on the number. Both numbers are first converted to 32-bit
unsigned values. The result is then a 32-bit unsigned number where each bit is unsigned values. The result is then a 32-bit unsigned number where each bit is
<code>true</code> only where the corresponding bits of one or both inputs were <code>true</code>. </p> <code>true</code> only where the corresponding bits of one or both inputs were <code>true</code>.</p>
<p>It is a runtime error if <code>other</code> is not a number. </p> <p>It is a runtime error if <code>other</code> is not a number.</p>
<h3><strong>..</strong>(other) operator <a href="#..(other)-operator" name="..(other)-operator" class="header-anchor">#</a></h3> <h3><strong>..</strong>(other) operator <a href="#..(other)-operator" name="..(other)-operator" class="header-anchor">#</a></h3>
<p>Creates a <a href="range.html">Range</a> representing a consecutive range of numbers <p>Creates a <a href="range.html">Range</a> representing a consecutive range of numbers
from the beginning number to the ending number. </p> from the beginning number to the ending number.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">range</span> <span class="o">=</span> <span class="mf">1.2</span><span class="o">..</span><span class="mf">3.4</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">range</span><span class="o">.</span><span class="n">min</span><span class="p">)</span> <span class="output">1.2</span> var range = 1.2..3.4
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">range</span><span class="o">.</span><span class="n">max</span><span class="p">)</span> <span class="output">3.4</span> System.print(range.min) //> 1.2
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">range</span><span class="o">.</span><span class="n">isInclusive</span><span class="p">)</span> <span class="output">true</span> System.print(range.max) //> 3.4
</pre></div> System.print(range.isInclusive) //> true
</pre>
<h3><strong>&hellip;</strong>(other) operator <a href="#...(other)-operator" name="...(other)-operator" class="header-anchor">#</a></h3> <h3><strong>&hellip;</strong>(other) operator <a href="#...(other)-operator" name="...(other)-operator" class="header-anchor">#</a></h3>
<p>Creates a <a href="range.html">Range</a> representing a consecutive range of numbers <p>Creates a <a href="range.html">Range</a> representing a consecutive range of numbers
from the beginning number to the ending number not including the ending number. </p> from the beginning number to the ending number not including the ending number.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">range</span> <span class="o">=</span> <span class="mf">1.2</span><span class="o">...</span><span class="mf">3.4</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">range</span><span class="o">.</span><span class="n">min</span><span class="p">)</span> <span class="output">1.2</span> var range = 1.2...3.4
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">range</span><span class="o">.</span><span class="n">max</span><span class="p">)</span> <span class="output">3.4</span> System.print(range.min) //> 1.2
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">range</span><span class="o">.</span><span class="n">isInclusive</span><span class="p">)</span> <span class="output">false</span> System.print(range.max) //> 3.4
</pre></div> System.print(range.isInclusive) //> false
</pre>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Object Class &ndash; Wren</title> <title>Object Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -82,36 +84,36 @@
<h1>Object Class</h1> <h1>Object Class</h1>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3><strong>same</strong>(obj1, obj2) <a href="#same(obj1,-obj2)" name="same(obj1,-obj2)" class="header-anchor">#</a></h3> <h3><strong>same</strong>(obj1, obj2) <a href="#same(obj1,-obj2)" name="same(obj1,-obj2)" class="header-anchor">#</a></h3>
<p>Returns <code>true</code> if <em>obj1</em> and <em>obj2</em> are the same. For <a href="../values.html">value <p>Returns <code>true</code> if <em>obj1</em> and <em>obj2</em> are the same. For <a href="../values.html">value
types</a>, this returns <code>true</code> if the objects have equivalent types</a>, this returns <code>true</code> if the objects have equivalent
state. In other words, numbers, strings, booleans, and ranges compare by value. </p> state. In other words, numbers, strings, booleans, and ranges compare by value.</p>
<p>For all other objects, this returns <code>true</code> only if <em>obj1</em> and <em>obj2</em> refer to <p>For all other objects, this returns <code>true</code> only if <em>obj1</em> and <em>obj2</em> refer to
the exact same object in memory. </p> the exact same object in memory.</p>
<p>This is similar to the built in <code>==</code> operator in Object except that this cannot <p>This is similar to the built in <code>==</code> operator in Object except that this cannot
be overriden. It allows you to reliably access the built-in equality semantics be overriden. It allows you to reliably access the built-in equality semantics
even on user-defined classes. </p> even on user-defined classes.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>!</strong> operator <a href="#-operator" name="-operator" class="header-anchor">#</a></h3> <h3><strong>!</strong> operator <a href="#-operator" name="-operator" class="header-anchor">#</a></h3>
<p>Returns <code>false</code>, since most objects are considered <a href="control-flow.html#truth">true</a>. </p> <p>Returns <code>false</code>, since most objects are considered <a href="control-flow.html#truth">true</a>.</p>
<h3><strong>==</strong>(other) and <strong>!=</strong>(other) operators <a href="#==(other)-and-=(other)-operators" name="==(other)-and-=(other)-operators" class="header-anchor">#</a></h3> <h3><strong>==</strong>(other) and <strong>!=</strong>(other) operators <a href="#==(other)-and-=(other)-operators" name="==(other)-and-=(other)-operators" class="header-anchor">#</a></h3>
<p>Compares two objects using built-in equality. This compares <a href="../values.html">value <p>Compares two objects using built-in equality. This compares <a href="../values.html">value
types</a> by value, and all other objects are compared by types</a> by value, and all other objects are compared by
identity&mdash;two objects are equal only if they are the exact same object. </p> identity&mdash;two objects are equal only if they are the exact same object.</p>
<h3><strong>is</strong>(class) operator <a href="#is(class)-operator" name="is(class)-operator" class="header-anchor">#</a></h3> <h3><strong>is</strong>(class) operator <a href="#is(class)-operator" name="is(class)-operator" class="header-anchor">#</a></h3>
<p>Returns <code>true</code> if this object&rsquo;s class or one of its superclasses is <code>class</code>. </p> <p>Returns <code>true</code> if this object&rsquo;s class or one of its superclasses is <code>class</code>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="mi">123</span> <span class="k">is</span> <span class="vg">Num</span><span class="p">)</span> <span class="output">true</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;s&quot;</span> <span class="k">is</span> <span class="vg">Num</span><span class="p">)</span> <span class="output">false</span> System.print(123 is Num) //> true
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="kc">null</span> <span class="k">is</span> <span class="vg">String</span><span class="p">)</span> <span class="output">false</span> System.print("s" is Num) //> false
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([]</span> <span class="k">is</span> <span class="vg">List</span><span class="p">)</span> <span class="output">true</span> System.print(null is String) //> false
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([]</span> <span class="k">is</span> <span class="vg">Sequence</span><span class="p">)</span> <span class="output">true</span> System.print([] is List) //> true
</pre></div> System.print([] is Sequence) //> true
</pre>
<p>It is a runtime error if <code>class</code> is not a <a href="class.html">Class</a>.</p>
<p>It is a runtime error if <code>class</code> is not a <a href="class.html">Class</a>. </p>
<h3><strong>toString</strong> <a href="#tostring" name="tostring" class="header-anchor">#</a></h3> <h3><strong>toString</strong> <a href="#tostring" name="tostring" class="header-anchor">#</a></h3>
<p>A default string representation of the object. </p> <p>A default string representation of the object.</p>
<h3><strong>type</strong> <a href="#type" name="type" class="header-anchor">#</a></h3> <h3><strong>type</strong> <a href="#type" name="type" class="header-anchor">#</a></h3>
<p>The <a href="class.html">Class</a> of the object. </p> <p>The <a href="class.html">Class</a> of the object.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Range Class &ndash; Wren</title> <title>Range Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,52 +82,52 @@
</nav> </nav>
<main> <main>
<h1>Range Class</h1> <h1>Range Class</h1>
<p>A range defines a bounded range of values from a starting point to a possibly <p>A range defines a bounded range of values from a starting point to a possibly
exclusive endpoint. <a href="../../values.html#ranges">Here</a> is a friendly introduction. </p> exclusive endpoint. <a href="../../values.html#ranges">Here</a> is a friendly introduction.</p>
<p>Extends <a href="sequence.html">Sequence</a>. </p> <p>Extends <a href="sequence.html">Sequence</a>.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>from</strong> <a href="#from" name="from" class="header-anchor">#</a></h3> <h3><strong>from</strong> <a href="#from" name="from" class="header-anchor">#</a></h3>
<p>The starting point of the range. A range may be backwards, so this can be <p>The starting point of the range. A range may be backwards, so this can be
greater than [to]. </p> greater than [to].</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">3</span><span class="o">..</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">from</span><span class="p">)</span> <span class="output">3</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">4</span><span class="o">..</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">from</span><span class="p">)</span> <span class="output">4</span> System.print((3..5).from) //> 3
</pre></div> System.print((4..2).from) //> 4
</pre>
<h3><strong>to</strong> <a href="#to" name="to" class="header-anchor">#</a></h3> <h3><strong>to</strong> <a href="#to" name="to" class="header-anchor">#</a></h3>
<p>The endpoint of the range. If the range is inclusive, this value is included, <p>The endpoint of the range. If the range is inclusive, this value is included,
otherwise it is not. </p> otherwise it is not.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">3</span><span class="o">..</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">to</span><span class="p">)</span> <span class="output">5</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">4</span><span class="o">..</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">to</span><span class="p">)</span> <span class="output">2</span> System.print((3..5).to) //> 5
</pre></div> System.print((4..2).to) //> 2
</pre>
<h3><strong>min</strong> <a href="#min" name="min" class="header-anchor">#</a></h3> <h3><strong>min</strong> <a href="#min" name="min" class="header-anchor">#</a></h3>
<p>The minimum bound of the range. Returns either <code>from</code>, or <code>to</code>, whichever is <p>The minimum bound of the range. Returns either <code>from</code>, or <code>to</code>, whichever is
lower. </p> lower.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">3</span><span class="o">..</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">min</span><span class="p">)</span> <span class="output">3</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">4</span><span class="o">..</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">min</span><span class="p">)</span> <span class="output">2</span> System.print((3..5).min) //> 3
</pre></div> System.print((4..2).min) //> 2
</pre>
<h3><strong>max</strong> <a href="#max" name="max" class="header-anchor">#</a></h3> <h3><strong>max</strong> <a href="#max" name="max" class="header-anchor">#</a></h3>
<p>The maximum bound of the range. Returns either <code>from</code>, or <code>to</code>, whichever is <p>The maximum bound of the range. Returns either <code>from</code>, or <code>to</code>, whichever is
greater. </p> greater.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">3</span><span class="o">..</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">max</span><span class="p">)</span> <span class="output">5</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">4</span><span class="o">..</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">max</span><span class="p">)</span> <span class="output">4</span> System.print((3..5).max) //> 5
</pre></div> System.print((4..2).max) //> 4
</pre>
<h3><strong>isInclusive</strong> <a href="#isinclusive" name="isinclusive" class="header-anchor">#</a></h3> <h3><strong>isInclusive</strong> <a href="#isinclusive" name="isinclusive" class="header-anchor">#</a></h3>
<p>Whether or not the range includes <code>to</code>. (<code>from</code> is always included.) </p> <p>Whether or not the range includes <code>to</code>. (<code>from</code> is always included.)</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">3</span><span class="o">..</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">isInclusive</span><span class="p">)</span> <span class="output">true</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">3</span><span class="o">...</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">isInclusive</span><span class="p">)</span> <span class="output">false</span> System.print((3..5).isInclusive) //> true
</pre></div> System.print((3...5).isInclusive) //> false
</pre>
<h3><strong>iterate</strong>(iterator), <strong>iteratorValue</strong>(iterator) <a href="#iterate(iterator),-iteratorvalue(iterator)" name="iterate(iterator),-iteratorvalue(iterator)" class="header-anchor">#</a></h3> <h3><strong>iterate</strong>(iterator), <strong>iteratorValue</strong>(iterator) <a href="#iterate(iterator),-iteratorvalue(iterator)" name="iterate(iterator),-iteratorvalue(iterator)" class="header-anchor">#</a></h3>
<p>Iterates over the range. Starts at <code>from</code> and increments by one towards <code>to</code> <p>Iterates over the range. Starts at <code>from</code> and increments by one towards <code>to</code>
until the endpoint is reached. </p> until the endpoint is reached.</p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Sequence Class &ndash; Wren</title> <title>Sequence Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,142 +82,143 @@
</nav> </nav>
<main> <main>
<h1>Sequence Class</h1> <h1>Sequence Class</h1>
<p>An abstract base class for any iterable object. Any class that implements the <p>An abstract base class for any iterable object. Any class that implements the
core <a href="../../control-flow.html#the-iterator-protocol">iterator protocol</a> can extend this to get a number of helpful methods. </p> core <a href="../../control-flow.html#the-iterator-protocol">iterator protocol</a> can extend this to get a number of helpful methods.</p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>all</strong>(predicate) <a href="#all(predicate)" name="all(predicate)" class="header-anchor">#</a></h3> <h3><strong>all</strong>(predicate) <a href="#all(predicate)" name="all(predicate)" class="header-anchor">#</a></h3>
<p>Tests whether all the elements in the sequence pass the <code>predicate</code>. </p> <p>Tests whether all the elements in the sequence pass the <code>predicate</code>.</p>
<p>Iterates over the sequence, passing each element to the function <code>predicate</code>. <p>Iterates over the sequence, passing each element to the function <code>predicate</code>.
If it returns something <a href="../control-flow.html#truth">false</a>, stops iterating If it returns something <a href="../control-flow.html#truth">false</a>, stops iterating
and returns the value. Otherwise, returns <code>true</code>. </p> and returns the value. Otherwise, returns <code>true</code>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">all</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">})</span> <span class="output">false</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">all</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">})</span> <span class="output">true</span> System.print([1, 2, 3].all {|n| n > 2}) //> false
</pre></div> System.print([1, 2, 3].all {|n| n < 4}) //> true
</pre>
<h3><strong>any</strong>(predicate) <a href="#any(predicate)" name="any(predicate)" class="header-anchor">#</a></h3> <h3><strong>any</strong>(predicate) <a href="#any(predicate)" name="any(predicate)" class="header-anchor">#</a></h3>
<p>Tests whether any element in the sequence passes the <code>predicate</code>. </p> <p>Tests whether any element in the sequence passes the <code>predicate</code>.</p>
<p>Iterates over the sequence, passing each element to the function <code>predicate</code>. <p>Iterates over the sequence, passing each element to the function <code>predicate</code>.
If it returns something <a href="../../control-flow.html#truth">true</a>, stops iterating and If it returns something <a href="../../control-flow.html#truth">true</a>, stops iterating and
returns that value. Otherwise, returns <code>false</code>. </p> returns that value. Otherwise, returns <code>false</code>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">any</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="p">})</span> <span class="output">false</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">any</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">})</span> <span class="output">true</span> System.print([1, 2, 3].any {|n| n < 1}) //> false
</pre></div> System.print([1, 2, 3].any {|n| n > 2}) //> true
</pre>
<h3><strong>contains</strong>(element) <a href="#contains(element)" name="contains(element)" class="header-anchor">#</a></h3> <h3><strong>contains</strong>(element) <a href="#contains(element)" name="contains(element)" class="header-anchor">#</a></h3>
<p>Returns whether the sequence contains any element equal to the given element. </p> <p>Returns whether the sequence contains any element equal to the given element.</p>
<h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3> <h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3>
<p>The number of elements in the sequence. </p> <p>The number of elements in the sequence.</p>
<p>Unless a more efficient override is available, this will iterate over the <p>Unless a more efficient override is available, this will iterate over the
sequence in order to determine how many elements it contains. </p> sequence in order to determine how many elements it contains.</p>
<h3><strong>count</strong>(predicate) <a href="#count(predicate)" name="count(predicate)" class="header-anchor">#</a></h3> <h3><strong>count</strong>(predicate) <a href="#count(predicate)" name="count(predicate)" class="header-anchor">#</a></h3>
<p>Returns the number of elements in the sequence that pass the <code>predicate</code>. </p> <p>Returns the number of elements in the sequence that pass the <code>predicate</code>.</p>
<p>Iterates over the sequence, passing each element to the function <code>predicate</code> <p>Iterates over the sequence, passing each element to the function <code>predicate</code>
and counting the number of times the returned value evaluates to <code>true</code>. </p> and counting the number of times the returned value evaluates to <code>true</code>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">count</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">})</span> <span class="output">1</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">count</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">&lt;</span> <span class="mi">4</span><span class="p">})</span> <span class="output">3</span> System.print([1, 2, 3].count {|n| n > 2}) //> 1
</pre></div> System.print([1, 2, 3].count {|n| n < 4}) //> 3
</pre>
<h3><strong>each</strong>(function) <a href="#each(function)" name="each(function)" class="header-anchor">#</a></h3> <h3><strong>each</strong>(function) <a href="#each(function)" name="each(function)" class="header-anchor">#</a></h3>
<p>Iterates over the sequence, passing each element to the given <code>function</code>. </p> <p>Iterates over the sequence, passing each element to the given <code>function</code>.</p>
<div class="codehilite"><pre><span class="p">[</span><span class="s">&quot;one&quot;</span><span class="p">,</span> <span class="s">&quot;two&quot;</span><span class="p">,</span> <span class="s">&quot;three&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">each</span> <span class="p">{</span><span class="o">|</span><span class="n">word</span><span class="o">|</span> <span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">word</span><span class="p">)</span> <span class="p">}</span> <pre class="snippet">
</pre></div> ["one", "two", "three"].each {|word| System.print(word) }
</pre>
<h3><strong>isEmpty</strong> <a href="#isempty" name="isempty" class="header-anchor">#</a></h3> <h3><strong>isEmpty</strong> <a href="#isempty" name="isempty" class="header-anchor">#</a></h3>
<p>Returns whether the sequence contains any elements. </p> <p>Returns whether the sequence contains any elements.</p>
<p>This can be more efficient that <code>count == 0</code> because this does not iterate over <p>This can be more efficient that <code>count == 0</code> because this does not iterate over
the entire sequence. </p> the entire sequence.</p>
<h3><strong>join</strong>(separator) <a href="#join(separator)" name="join(separator)" class="header-anchor">#</a></h3> <h3><strong>join</strong>(separator) <a href="#join(separator)" name="join(separator)" class="header-anchor">#</a></h3>
<p>Converts every element in the sequence to a string and then joins the results <p>Converts every element in the sequence to a string and then joins the results
together into a single string, each separated by <code>separator</code>. </p> together into a single string, each separated by <code>separator</code>.</p>
<p>It is a runtime error if <code>separator</code> is not a string. </p> <p>It is a runtime error if <code>separator</code> is not a string.</p>
<h3><strong>join</strong>() <a href="#join()" name="join()" class="header-anchor">#</a></h3> <h3><strong>join</strong>() <a href="#join()" name="join()" class="header-anchor">#</a></h3>
<p>Converts every element in the sequence to a string and then joins the results <p>Converts every element in the sequence to a string and then joins the results
together into a single string. </p> together into a single string.</p>
<h3><strong>map</strong>(transformation) <a href="#map(transformation)" name="map(transformation)" class="header-anchor">#</a></h3> <h3><strong>map</strong>(transformation) <a href="#map(transformation)" name="map(transformation)" class="header-anchor">#</a></h3>
<p>Creates a new sequence that applies the <code>transformation</code> to each element in the <p>Creates a new sequence that applies the <code>transformation</code> to each element in the
original sequence while it is iterated. </p> original sequence while it is iterated.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">doubles</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">*</span> <span class="mi">2</span> <span class="p">}</span> <pre class="snippet">
<span class="k">for</span> <span class="p">(</span><span class="err">n</span> <span class="k">in</span> <span class="n">doubles</span><span class="p">)</span> <span class="p">{</span> var doubles = [1, 2, 3].map {|n| n * 2 }
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">n</span><span class="p">)</span> <span class="output">2</span> for (n in doubles) {
<span class="output">4</span> System.print(n) //> 2
<span class="output">6</span> //> 4
<span class="p">}</span> //> 6
</pre></div> }
</pre>
<p>The returned sequence is <em>lazy</em>. It only applies the mapping when you iterate
over the sequence, and it does so by holding a reference to the original
sequence. </p>
<p>This means you can use <code>map(_)</code> for things like infinite sequences or sequences
that have side effects when you iterate over them. But it also means that
changes to the original sequence will be reflected in the mapped sequence. </p>
<p>To force eager evaluation, just call <code>.toList</code> on the result. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="k">var</span> <span class="n">doubles</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">*</span> <span class="mi">2</span> <span class="p">}</span><span class="o">.</span><span class="n">toList</span>
<span class="n">numbers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">doubles</span><span class="p">)</span> <span class="output">[2, 4, 6]</span>
</pre></div>
<p>The returned sequence is <em>lazy</em>. It only applies the mapping when you iterate
over the sequence, and it does so by holding a reference to the original
sequence.</p>
<p>This means you can use <code>map(_)</code> for things like infinite sequences or sequences
that have side effects when you iterate over them. But it also means that
changes to the original sequence will be reflected in the mapped sequence.</p>
<p>To force eager evaluation, just call <code>.toList</code> on the result.</p>
<pre class="snippet">
var numbers = [1, 2, 3]
var doubles = numbers.map {|n| n * 2 }.toList
numbers.add(4)
System.print(doubles) //> [2, 4, 6]
</pre>
<h3><strong>reduce</strong>(function) <a href="#reduce(function)" name="reduce(function)" class="header-anchor">#</a></h3> <h3><strong>reduce</strong>(function) <a href="#reduce(function)" name="reduce(function)" class="header-anchor">#</a></h3>
<p>Reduces the sequence down to a single value. <code>function</code> is a function that <p>Reduces the sequence down to a single value. <code>function</code> is a function that
takes two arguments, the accumulator and sequence item and returns the new takes two arguments, the accumulator and sequence item and returns the new
accumulator value. The accumulator is initialized from the first item in the accumulator value. The accumulator is initialized from the first item in the
sequence. Then, the function is invoked on each remaining item in the sequence, sequence. Then, the function is invoked on each remaining item in the sequence,
iteratively updating the accumulator. </p> iteratively updating the accumulator.</p>
<p>It is a runtime error to call this on an empty sequence. </p> <p>It is a runtime error to call this on an empty sequence.</p>
<h3><strong>reduce</strong>(seed, function) <a href="#reduce(seed,-function)" name="reduce(seed,-function)" class="header-anchor">#</a></h3> <h3><strong>reduce</strong>(seed, function) <a href="#reduce(seed,-function)" name="reduce(seed,-function)" class="header-anchor">#</a></h3>
<p>Similar to above, but uses <code>seed</code> for the initial value of the accumulator. If <p>Similar to above, but uses <code>seed</code> for the initial value of the accumulator. If
the sequence is empty, returns <code>seed</code>. </p> the sequence is empty, returns <code>seed</code>.</p>
<h3><strong>skip</strong>(count) <a href="#skip(count)" name="skip(count)" class="header-anchor">#</a></h3> <h3><strong>skip</strong>(count) <a href="#skip(count)" name="skip(count)" class="header-anchor">#</a></h3>
<p>Creates a new sequence that skips the first <code>count</code> elements of the original <p>Creates a new sequence that skips the first <code>count</code> elements of the original
sequence. </p> sequence.</p>
<p>The returned sequence is <em>lazy</em>. The first <code>count</code> elements are only skipped <p>The returned sequence is <em>lazy</em>. The first <code>count</code> elements are only skipped
once you start to iterate the returned sequence. Changes to the original once you start to iterate the returned sequence. Changes to the original
sequence will be reflected in the filtered sequence. </p> sequence will be reflected in the filtered sequence.</p>
<h3><strong>take</strong>(count) <a href="#take(count)" name="take(count)" class="header-anchor">#</a></h3> <h3><strong>take</strong>(count) <a href="#take(count)" name="take(count)" class="header-anchor">#</a></h3>
<p>Creates a new sequence that iterates only the first <code>count</code> elements of the <p>Creates a new sequence that iterates only the first <code>count</code> elements of the
original sequence. </p> original sequence.</p>
<p>The returned sequence is <em>lazy</em>. Changes to the original sequence will be <p>The returned sequence is <em>lazy</em>. Changes to the original sequence will be
reflected in the filtered sequence. </p> reflected in the filtered sequence.</p>
<h3><strong>toList</strong> <a href="#tolist" name="tolist" class="header-anchor">#</a></h3> <h3><strong>toList</strong> <a href="#tolist" name="tolist" class="header-anchor">#</a></h3>
<p>Creates a <a href="list.html">list</a> containing all the elements in the sequence. </p> <p>Creates a <a href="list.html">list</a> containing all the elements in the sequence.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">((</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">toList</span><span class="p">)</span> <span class="output">[1, 2, 3]</span> <pre class="snippet">
</pre></div> System.print((1..3).toList) //> [1, 2, 3]
</pre>
<p>If the sequence is already a list, this creates a copy of it.</p>
<p>If the sequence is already a list, this creates a copy of it. </p>
<h3><strong>where</strong>(predicate) <a href="#where(predicate)" name="where(predicate)" class="header-anchor">#</a></h3> <h3><strong>where</strong>(predicate) <a href="#where(predicate)" name="where(predicate)" class="header-anchor">#</a></h3>
<p>Creates a new sequence containing only the elements from the original sequence <p>Creates a new sequence containing only the elements from the original sequence
that pass the <code>predicate</code>. </p> that pass the <code>predicate</code>.</p>
<p>During iteration, each element in the original sequence is passed to the <p>During iteration, each element in the original sequence is passed to the
function <code>predicate</code>. If it returns <code>false</code>, the element is skipped. </p> function <code>predicate</code>. If it returns <code>false</code>, the element is skipped.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">odds</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">6</span><span class="p">)</span><span class="o">.</span><span class="n">where</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">}</span> <pre class="snippet">
<span class="k">for</span> <span class="p">(</span><span class="err">n</span> <span class="k">in</span> <span class="n">odds</span><span class="p">)</span> <span class="p">{</span> var odds = (1..6).where {|n| n % 2 == 1 }
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">n</span><span class="p">)</span> <span class="output">1</span> for (n in odds) {
<span class="output">3</span> System.print(n) //> 1
<span class="output">5</span> //> 3
<span class="p">}</span> //> 5
</pre></div> }
</pre>
<p>The returned sequence is <em>lazy</em>. It only applies the filtering when you iterate
<p>The returned sequence is <em>lazy</em>. It only applies the filtering when you iterate over the sequence, and it does so by holding a reference to the original
over the sequence, and it does so by holding a reference to the original sequence.</p>
sequence. </p> <p>This means you can use <code>where(_)</code> for things like infinite sequences or
<p>This means you can use <code>where(_)</code> for things like infinite sequences or sequences that have side effects when you iterate over them. But it also means
sequences that have side effects when you iterate over them. But it also means that changes to the original sequence will be reflected in the filtered
that changes to the original sequence will be reflected in the filtered sequence.</p>
sequence. </p> <p>To force eager evaluation, just call <code>.toList</code> on the result.</p>
<p>To force eager evaluation, just call <code>.toList</code> on the result. </p> <pre class="snippet">
<div class="codehilite"><pre><span class="k">var</span> <span class="n">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">]</span> var numbers = [1, 2, 3, 4, 5, 6]
<span class="k">var</span> <span class="n">odds</span> <span class="o">=</span> <span class="n">numbers</span><span class="o">.</span><span class="n">where</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">1</span> <span class="p">}</span><span class="o">.</span><span class="n">toList</span> var odds = numbers.where {|n| n % 2 == 1 }.toList
<span class="n">numbers</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span> numbers.add(7)
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">odds</span><span class="p">)</span> <span class="output">[1, 3, 5]</span> System.print(odds) //> [1, 3, 5]
</pre></div> </pre>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>String Class &ndash; Wren</title> <title>String Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,212 +82,212 @@
</nav> </nav>
<main> <main>
<h1>String Class</h1> <h1>String Class</h1>
<p>A string is an immutable array of bytes. Strings usually store text, in which <p>A string is an immutable array of bytes. Strings usually store text, in which
case the bytes are the UTF-8 encoding of the text&rsquo;s code points. But you can put case the bytes are the UTF-8 encoding of the text&rsquo;s code points. But you can put
any kind of byte values in there you want, including null bytes or invalid any kind of byte values in there you want, including null bytes or invalid
UTF-8. </p> UTF-8.</p>
<p>There are a few ways to think of a string: </p> <p>There are a few ways to think of a string:</p>
<ul> <ul>
<li> <li>
<p>As a searchable chunk of text composed of a sequence of textual code points. </p> <p>As a searchable chunk of text composed of a sequence of textual code points.</p>
</li> </li>
<li> <li>
<p>As an iterable sequence of code point numbers. </p> <p>As an iterable sequence of code point numbers.</p>
</li> </li>
<li> <li>
<p>As a flat array of directly indexable bytes. </p> <p>As a flat array of directly indexable bytes.</p>
</li> </li>
</ul> </ul>
<p>All of those are useful for some problems, so the string API supports all three. <p>All of those are useful for some problems, so the string API supports all three.
The first one is the most common, so that&rsquo;s what methods directly on the string The first one is the most common, so that&rsquo;s what methods directly on the string
class cater to. </p> class cater to.</p>
<p>In UTF-8, a single Unicode code point&mdash;very roughly a single <p>In UTF-8, a single Unicode code point&mdash;very roughly a single
&ldquo;character&rdquo;&mdash;may encode to one or more bytes. This means you can&rsquo;t &ldquo;character&rdquo;&mdash;may encode to one or more bytes. This means you can&rsquo;t
efficiently index by code point. There&rsquo;s no way to jump directly to, say, the efficiently index by code point. There&rsquo;s no way to jump directly to, say, the
fifth code point in a string without walking the string from the beginning and fifth code point in a string without walking the string from the beginning and
counting them as you go. </p> counting them as you go.</p>
<p>Because counting code points is relatively slow, the indexes passed to string <p>Because counting code points is relatively slow, the indexes passed to string
methods are <em>byte</em> offsets, not <em>code point</em> offsets. When you do: </p> methods are <em>byte</em> offsets, not <em>code point</em> offsets. When you do:</p>
<div class="codehilite"><pre><span class="n">someString</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <pre class="snippet">
</pre></div> someString[3]
</pre>
<p>That means &ldquo;get the code point starting at <em>byte</em> three&rdquo;, not &ldquo;get the third
code point in the string&rdquo;. This sounds scary, but keep in mind that the methods
on strings <em>return</em> byte indexes too. So, for example, this does what you want:</p>
<pre class="snippet">
var metalBand = "Fäcëhämmër"
var hPosition = metalBand.indexOf("h")
System.print(metalBand[hPosition]) //> h
</pre>
<p>That means &ldquo;get the code point starting at <em>byte</em> three&rdquo;, not &ldquo;get the third <p>If you want to work with a string as a sequence numeric code points, call the
code point in the string&rdquo;. This sounds scary, but keep in mind that the methods <code>codePoints</code> getter. It returns a <a href="sequence.html">Sequence</a> that decodes UTF-8
on strings <em>return</em> byte indexes too. So, for example, this does what you want: </p> and iterates over the code points, returning each as a number.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">metalBand</span> <span class="o">=</span> <span class="s">&quot;Fäcëhämmër&quot;</span> <p>If you want to get at the raw bytes, call <code>bytes</code>. This returns a Sequence that
<span class="k">var</span> <span class="n">hPosition</span> <span class="o">=</span> <span class="n">metalBand</span><span class="o">.</span><span class="n">indexOf</span><span class="p">(</span><span class="s">&quot;h&quot;</span><span class="p">)</span> ignores any UTF-8 encoding and works directly at the byte level.</p>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">metalBand</span><span class="p">[</span><span class="n">hPosition</span><span class="p">])</span> <span class="output">h</span>
</pre></div>
<p>If you want to work with a string as a sequence numeric code points, call the
<code>codePoints</code> getter. It returns a <a href="sequence.html">Sequence</a> that decodes UTF-8
and iterates over the code points, returning each as a number. </p>
<p>If you want to get at the raw bytes, call <code>bytes</code>. This returns a Sequence that
ignores any UTF-8 encoding and works directly at the byte level. </p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>String.<strong>fromCodePoint</strong>(codePoint) <a href="#string.fromcodepoint(codepoint)" name="string.fromcodepoint(codepoint)" class="header-anchor">#</a></h3> <h3>String.<strong>fromCodePoint</strong>(codePoint) <a href="#string.fromcodepoint(codepoint)" name="string.fromcodepoint(codepoint)" class="header-anchor">#</a></h3>
<p>Creates a new string containing the UTF-8 encoding of <code>codePoint</code>. </p> <p>Creates a new string containing the UTF-8 encoding of <code>codePoint</code>.</p>
<div class="codehilite"><pre><span class="vg">String</span><span class="o">.</span><span class="n">fromCodePoint</span><span class="p">(</span><span class="mi">8225</span><span class="p">)</span> <span class="output"></span> <pre class="snippet">
</pre></div> String.fromCodePoint(8225) //> ‡
</pre>
<p>It is a runtime error if <code>codePoint</code> is not an integer between <code>0</code> and
<p>It is a runtime error if <code>codePoint</code> is not an integer between <code>0</code> and <code>0x10ffff</code>, inclusive.</p>
<code>0x10ffff</code>, inclusive. </p>
<h3>String.<strong>fromByte</strong>(byte) <a href="#string.frombyte(byte)" name="string.frombyte(byte)" class="header-anchor">#</a></h3> <h3>String.<strong>fromByte</strong>(byte) <a href="#string.frombyte(byte)" name="string.frombyte(byte)" class="header-anchor">#</a></h3>
<p>Creates a new string containing the single byte <code>byte</code>. </p> <p>Creates a new string containing the single byte <code>byte</code>.</p>
<div class="codehilite"><pre><span class="vg">String</span><span class="o">.</span><span class="n">fromByte</span><span class="p">(</span><span class="mi">255</span><span class="p">)</span> <span class="output"><EFBFBD></span> <pre class="snippet">
</pre></div> String.fromByte(255) //> <20>
</pre>
<p>It is a runtime error if <code>byte</code> is not an integer between <code>0</code> and <code>0xff</code>, inclusive.</p>
<p>It is a runtime error if <code>byte</code> is not an integer between <code>0</code> and <code>0xff</code>, inclusive. </p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>bytes</strong> <a href="#bytes" name="bytes" class="header-anchor">#</a></h3> <h3><strong>bytes</strong> <a href="#bytes" name="bytes" class="header-anchor">#</a></h3>
<p>Gets a <a href="sequence.html"><code>Sequence</code></a> that can be used to access the raw bytes of <p>Gets a <a href="sequence.html"><code>Sequence</code></a> that can be used to access the raw bytes of
the string and ignore any UTF-8 encoding. In addition to the normal sequence the string and ignore any UTF-8 encoding. In addition to the normal sequence
methods, the returned object also has a subscript operator that can be used to methods, the returned object also has a subscript operator that can be used to
directly index bytes. </p> directly index bytes.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;hello&quot;</span><span class="o">.</span><span class="n">bytes</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="output">101 (for &quot;e&quot;)</span> <pre class="snippet">
</pre></div> System.print("hello".bytes[1]) //> 101 (for "e")
</pre>
<p>The <code>count</code> method on the returned sequence returns the number of bytes in the
<p>The <code>count</code> method on the returned sequence returns the number of bytes in the string. Unlike <code>count</code> on the string itself, it does not have to iterate over
string. Unlike <code>count</code> on the string itself, it does not have to iterate over the string, and runs in constant time instead.</p>
the string, and runs in constant time instead. </p>
<h3><strong>codePoints</strong> <a href="#codepoints" name="codepoints" class="header-anchor">#</a></h3> <h3><strong>codePoints</strong> <a href="#codepoints" name="codepoints" class="header-anchor">#</a></h3>
<p>Gets a <a href="sequence.html"><code>Sequence</code></a> that can be used to access the UTF-8 decode <p>Gets a <a href="sequence.html"><code>Sequence</code></a> that can be used to access the UTF-8 decode
code points of the string <em>as numbers</em>. Iteration and subscripting work similar code points of the string <em>as numbers</em>. Iteration and subscripting work similar
to the string itself. The difference is that instead of returning to the string itself. The difference is that instead of returning
single-character strings, this returns the numeric code point values. </p> single-character strings, this returns the numeric code point values.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">string</span> <span class="o">=</span> <span class="s">&quot;(ᵔᴥᵔ)&quot;</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">string</span><span class="o">.</span><span class="n">codePoints</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="output">40 (for &quot;(&quot;)</span> var string = "(ᵔᴥᵔ)"
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">string</span><span class="o">.</span><span class="n">codePoints</span><span class="p">[</span><span class="mi">4</span><span class="p">])</span> <span class="output">7461 (for &quot;&quot;)</span> System.print(string.codePoints[0]) //> 40 (for "(")
</pre></div> System.print(string.codePoints[4]) //> 7461 (for "ᴥ")
</pre>
<p>If the byte at <code>index</code> does not begin a valid UTF-8 sequence, or the end of the
string is reached before the sequence is complete, returns <code>-1</code>. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">string</span> <span class="o">=</span> <span class="s">&quot;(ᵔᴥᵔ)&quot;</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">string</span><span class="o">.</span><span class="n">codePoints</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="output">-1 (in the middle of &quot;&quot;)</span>
</pre></div>
<p>If the byte at <code>index</code> does not begin a valid UTF-8 sequence, or the end of the
string is reached before the sequence is complete, returns <code>-1</code>.</p>
<pre class="snippet">
var string = "(ᵔᴥᵔ)"
System.print(string.codePoints[2]) //> -1 (in the middle of "ᵔ")
</pre>
<h3><strong>contains</strong>(other) <a href="#contains(other)" name="contains(other)" class="header-anchor">#</a></h3> <h3><strong>contains</strong>(other) <a href="#contains(other)" name="contains(other)" class="header-anchor">#</a></h3>
<p>Checks if <code>other</code> is a substring of the string. </p> <p>Checks if <code>other</code> is a substring of the string.</p>
<p>It is a runtime error if <code>other</code> is not a string. </p> <p>It is a runtime error if <code>other</code> is not a string.</p>
<h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3> <h3><strong>count</strong> <a href="#count" name="count" class="header-anchor">#</a></h3>
<p>Returns the number of code points in the string. Since UTF-8 is a <p>Returns the number of code points in the string. Since UTF-8 is a
variable-length encoding, this requires iterating over the entire string, which variable-length encoding, this requires iterating over the entire string, which
is relatively slow. </p> is relatively slow.</p>
<p>If the string contains bytes that are invalid UTF-8, each byte adds one to the <p>If the string contains bytes that are invalid UTF-8, each byte adds one to the
count as well. </p> count as well.</p>
<h3><strong>endsWith</strong>(suffix) <a href="#endswith(suffix)" name="endswith(suffix)" class="header-anchor">#</a></h3> <h3><strong>endsWith</strong>(suffix) <a href="#endswith(suffix)" name="endswith(suffix)" class="header-anchor">#</a></h3>
<p>Checks if the string ends with <code>suffix</code>. </p> <p>Checks if the string ends with <code>suffix</code>.</p>
<p>It is a runtime error if <code>suffix</code> is not a string. </p> <p>It is a runtime error if <code>suffix</code> is not a string.</p>
<h3><strong>indexOf</strong>(search) <a href="#indexof(search)" name="indexof(search)" class="header-anchor">#</a></h3> <h3><strong>indexOf</strong>(search) <a href="#indexof(search)" name="indexof(search)" class="header-anchor">#</a></h3>
<p>Returns the index of the first byte matching <code>search</code> in the string or <code>-1</code> if <p>Returns the index of the first byte matching <code>search</code> in the string or <code>-1</code> if
<code>search</code> was not found. </p> <code>search</code> was not found.</p>
<p>It is a runtime error if <code>search</code> is not a string. </p> <p>It is a runtime error if <code>search</code> is not a string.</p>
<h3><strong>indexOf</strong>(search, start) <a href="#indexof(search,-start)" name="indexof(search,-start)" class="header-anchor">#</a></h3> <h3><strong>indexOf</strong>(search, start) <a href="#indexof(search,-start)" name="indexof(search,-start)" class="header-anchor">#</a></h3>
<p>Returns the index of the first byte matching <code>search</code> in the string or <code>-1</code> if <p>Returns the index of the first byte matching <code>search</code> in the string or <code>-1</code> if
<code>search</code> was not found, starting a byte offset <code>start</code>. The start can be <code>search</code> was not found, starting a byte offset <code>start</code>. The start can be
negative to count backwards from the end of the string. </p> negative to count backwards from the end of the string.</p>
<p>It is a runtime error if <code>search</code> is not a string or <code>start</code> is not an integer <p>It is a runtime error if <code>search</code> is not a string or <code>start</code> is not an integer
index within the string&rsquo;s byte length. </p> index within the string&rsquo;s byte length.</p>
<h3><strong>iterate</strong>(iterator), <strong>iteratorValue</strong>(iterator) <a href="#iterate(iterator),-iteratorvalue(iterator)" name="iterate(iterator),-iteratorvalue(iterator)" class="header-anchor">#</a></h3> <h3><strong>iterate</strong>(iterator), <strong>iteratorValue</strong>(iterator) <a href="#iterate(iterator),-iteratorvalue(iterator)" name="iterate(iterator),-iteratorvalue(iterator)" class="header-anchor">#</a></h3>
<p>Implements the <a href="../../control-flow.html#the-iterator-protocol">iterator protocol</a> for iterating over the <em>code points</em> in the <p>Implements the <a href="../../control-flow.html#the-iterator-protocol">iterator protocol</a> for iterating over the <em>code points</em> in the
string: </p> string:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">codePoints</span> <span class="o">=</span> <span class="p">[]</span> <pre class="snippet">
<span class="k">for</span> <span class="p">(</span><span class="err">c</span> <span class="k">in</span> <span class="s">&quot;(ᵔᴥᵔ)&quot;</span><span class="p">)</span> <span class="p">{</span> var codePoints = []
<span class="n">codePoints</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="err">c</span><span class="p">)</span> for (c in "(ᵔᴥᵔ)") {
<span class="p">}</span> codePoints.add(c)
}
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">codePoints</span><span class="p">)</span> <span class="output">[(, ᵔ, ᴥ, ᵔ, )]</span> System.print(codePoints) //> [(, ᵔ, ᴥ, ᵔ, )]
</pre></div> </pre>
<p>If the string contains any bytes that are not valid UTF-8, this iterates over
<p>If the string contains any bytes that are not valid UTF-8, this iterates over those too, one byte at a time.</p>
those too, one byte at a time. </p>
<h3><strong>replace</strong>(old, swap) <a href="#replace(old,-swap)" name="replace(old,-swap)" class="header-anchor">#</a></h3> <h3><strong>replace</strong>(old, swap) <a href="#replace(old,-swap)" name="replace(old,-swap)" class="header-anchor">#</a></h3>
<p>Returns a new string with all occurrences of <code>old</code> replaced with <code>swap</code>. </p> <p>Returns a new string with all occurrences of <code>old</code> replaced with <code>swap</code>.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">string</span> <span class="o">=</span> <span class="s">&quot;abc abc abc&quot;</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">string</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="p">,</span> <span class="s">&quot;&quot;</span><span class="p">))</span> <span class="output">abcabcabc</span> var string = "abc abc abc"
</pre></div> System.print(string.replace(" ", "")) //> abcabcabc
</pre>
<h3><strong>split</strong>(separator) <a href="#split(separator)" name="split(separator)" class="header-anchor">#</a></h3> <h3><strong>split</strong>(separator) <a href="#split(separator)" name="split(separator)" class="header-anchor">#</a></h3>
<p>Returns a list of one or more strings separated by <code>separator</code>. </p> <p>Returns a list of one or more strings separated by <code>separator</code>.</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">string</span> <span class="o">=</span> <span class="s">&quot;abc abc abc&quot;</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">string</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="p">))</span> <span class="output">[abc, abc, abc]</span> var string = "abc abc abc"
</pre></div> System.print(string.split(" ")) //> [abc, abc, abc]
</pre>
<p>It is a runtime error if <code>separator</code> is not a string or is an empty string.</p>
<p>It is a runtime error if <code>separator</code> is not a string or is an empty string. </p>
<h3><strong>startsWith</strong>(prefix) <a href="#startswith(prefix)" name="startswith(prefix)" class="header-anchor">#</a></h3> <h3><strong>startsWith</strong>(prefix) <a href="#startswith(prefix)" name="startswith(prefix)" class="header-anchor">#</a></h3>
<p>Checks if the string starts with <code>prefix</code>. </p> <p>Checks if the string starts with <code>prefix</code>.</p>
<p>It is a runtime error if <code>prefix</code> is not a string. </p> <p>It is a runtime error if <code>prefix</code> is not a string.</p>
<h3><strong>trim</strong>() <a href="#trim()" name="trim()" class="header-anchor">#</a></h3> <h3><strong>trim</strong>() <a href="#trim()" name="trim()" class="header-anchor">#</a></h3>
<p>Returns a new string with whitespace removed from the beginning and end of this <p>Returns a new string with whitespace removed from the beginning and end of this
string. &ldquo;Whitespace&rdquo; is space, tab, carriage return, and line feed characters. </p> string. &ldquo;Whitespace&rdquo; is space, tab, carriage return, and line feed characters.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot; </span><span class="se">\n</span><span class="s">stuff</span><span class="se">\r\t</span><span class="s">&quot;</span><span class="o">.</span><span class="n">trim</span><span class="p">())</span> <span class="output">stuff</span> <pre class="snippet">
</pre></div> System.print(" \nstuff\r\t".trim()) //> stuff
</pre>
<h3><strong>trim</strong>(chars) <a href="#trim(chars)" name="trim(chars)" class="header-anchor">#</a></h3> <h3><strong>trim</strong>(chars) <a href="#trim(chars)" name="trim(chars)" class="header-anchor">#</a></h3>
<p>Returns a new string with all code points in <code>chars</code> removed from the beginning <p>Returns a new string with all code points in <code>chars</code> removed from the beginning
and end of this string. </p> and end of this string.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;ᵔᴥᵔᴥᵔbearᵔᴥᴥᵔᵔ&quot;</span><span class="o">.</span><span class="n">trim</span><span class="p">(</span><span class="s">&quot;ᵔᴥ&quot;</span><span class="p">))</span> <span class="output">bear</span> <pre class="snippet">
</pre></div> System.print("ᵔᴥᵔᴥᵔbearᵔᴥᴥᵔᵔ".trim("ᵔᴥ")) //> bear
</pre>
<h3><strong>trimEnd</strong>() <a href="#trimend()" name="trimend()" class="header-anchor">#</a></h3> <h3><strong>trimEnd</strong>() <a href="#trimend()" name="trimend()" class="header-anchor">#</a></h3>
<p>Like <code>trim()</code> but only removes from the end of the string. </p> <p>Like <code>trim()</code> but only removes from the end of the string.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot; </span><span class="se">\n</span><span class="s">stuff</span><span class="se">\r\t</span><span class="s">&quot;</span><span class="o">.</span><span class="n">trimEnd</span><span class="p">())</span> <span class="output">&quot; \nstuff&quot;</span> <pre class="snippet">
</pre></div> System.print(" \nstuff\r\t".trimEnd()) //> " \nstuff"
</pre>
<h3><strong>trimEnd</strong>(chars) <a href="#trimend(chars)" name="trimend(chars)" class="header-anchor">#</a></h3> <h3><strong>trimEnd</strong>(chars) <a href="#trimend(chars)" name="trimend(chars)" class="header-anchor">#</a></h3>
<p>Like <code>trim()</code> but only removes from the end of the string. </p> <p>Like <code>trim()</code> but only removes from the end of the string.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;ᵔᴥᵔᴥᵔbearᵔᴥᴥᵔᵔ&quot;</span><span class="o">.</span><span class="n">trimEnd</span><span class="p">(</span><span class="s">&quot;ᵔᴥ&quot;</span><span class="p">))</span> <span class="output">ᵔᴥᵔᴥᵔbear</span> <pre class="snippet">
</pre></div> System.print("ᵔᴥᵔᴥᵔbearᵔᴥᴥᵔᵔ".trimEnd("ᵔᴥ")) //> ᵔᴥᵔᴥᵔbear
</pre>
<h3><strong>trimStart</strong>() <a href="#trimstart()" name="trimstart()" class="header-anchor">#</a></h3> <h3><strong>trimStart</strong>() <a href="#trimstart()" name="trimstart()" class="header-anchor">#</a></h3>
<p>Like <code>trim()</code> but only removes from the beginning of the string. </p> <p>Like <code>trim()</code> but only removes from the beginning of the string.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot; </span><span class="se">\n</span><span class="s">stuff</span><span class="se">\r\t</span><span class="s">&quot;</span><span class="o">.</span><span class="n">trimStart</span><span class="p">())</span> <span class="output">&quot;stuff\r\t&quot;</span> <pre class="snippet">
</pre></div> System.print(" \nstuff\r\t".trimStart()) //> "stuff\r\t"
</pre>
<h3><strong>trimStart</strong>(chars) <a href="#trimstart(chars)" name="trimstart(chars)" class="header-anchor">#</a></h3> <h3><strong>trimStart</strong>(chars) <a href="#trimstart(chars)" name="trimstart(chars)" class="header-anchor">#</a></h3>
<p>Like <code>trim()</code> but only removes from the beginning of the string. </p> <p>Like <code>trim()</code> but only removes from the beginning of the string.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;ᵔᴥᵔᴥᵔbearᵔᴥᴥᵔᵔ&quot;</span><span class="o">.</span><span class="n">trimStart</span><span class="p">(</span><span class="s">&quot;ᵔᴥ&quot;</span><span class="p">))</span> <span class="output">bearᵔᴥᴥᵔᵔ</span> <pre class="snippet">
</pre></div> System.print("ᵔᴥᵔᴥᵔbearᵔᴥᴥᵔᵔ".trimStart("ᵔᴥ")) //> bearᵔᴥᴥᵔᵔ
</pre>
<h3><strong>+</strong>(other) operator <a href="#+(other)-operator" name="+(other)-operator" class="header-anchor">#</a></h3> <h3><strong>+</strong>(other) operator <a href="#+(other)-operator" name="+(other)-operator" class="header-anchor">#</a></h3>
<p>Returns a new string that concatenates this string and <code>other</code>. </p> <p>Returns a new string that concatenates this string and <code>other</code>.</p>
<p>It is a runtime error if <code>other</code> is not a string. </p> <p>It is a runtime error if <code>other</code> is not a string.</p>
<h3><strong>==</strong>(other) operator <a href="#==(other)-operator" name="==(other)-operator" class="header-anchor">#</a></h3> <h3><strong>==</strong>(other) operator <a href="#==(other)-operator" name="==(other)-operator" class="header-anchor">#</a></h3>
<p>Checks if the string is equal to <code>other</code>. </p> <p>Checks if the string is equal to <code>other</code>.</p>
<h3><strong>!=</strong>(other) operator <a href="#=(other)-operator" name="=(other)-operator" class="header-anchor">#</a></h3> <h3><strong>!=</strong>(other) operator <a href="#=(other)-operator" name="=(other)-operator" class="header-anchor">#</a></h3>
<p>Check if the string is not equal to <code>other</code>. </p> <p>Check if the string is not equal to <code>other</code>.</p>
<h3><strong>[</strong>index<strong>]</strong> operator <a href="#[index]-operator" name="[index]-operator" class="header-anchor">#</a></h3> <h3><strong>[</strong>index<strong>]</strong> operator <a href="#[index]-operator" name="[index]-operator" class="header-anchor">#</a></h3>
<p>Returns a string containing the code point starting at byte <code>index</code>. </p> <p>Returns a string containing the code point starting at byte <code>index</code>.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;ʕ•ᴥ•ʔ&quot;</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="output"></span> <pre class="snippet">
</pre></div> System.print("ʕ•ᴥ•ʔ"[5]) //> ᴥ
</pre>
<p>Since <code>ʕ</code> is two bytes in UTF-8 and <code></code> is three, the fifth byte points to the
bear&rsquo;s nose.</p>
<p>If <code>index</code> points into the middle of a UTF-8 sequence or at otherwise invalid
UTF-8, this returns a one-byte string containing the byte at that index:</p>
<pre class="snippet">
System.print("I ♥ NY"[3]) //> (one-byte string [153])
</pre>
<p>Since <code>ʕ</code> is two bytes in UTF-8 and <code></code> is three, the fifth byte points to the <p>It is a runtime error if <code>index</code> is greater than the number of bytes in the
bear&rsquo;s nose. </p> string.</p>
<p>If <code>index</code> points into the middle of a UTF-8 sequence or at otherwise invalid
UTF-8, this returns a one-byte string containing the byte at that index: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;I ♥ NY&quot;</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span> <span class="output">(one-byte string [153])</span>
</pre></div>
<p>It is a runtime error if <code>index</code> is greater than the number of bytes in the
string. </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>System Class &ndash; Wren</title> <title>System Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,9 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">core</a></li>
</ul> </ul>
<section> <section>
<h2>core classes</h2> <h2>core classes</h2>
@ -80,40 +82,40 @@
</nav> </nav>
<main> <main>
<h1>System Class</h1> <h1>System Class</h1>
<p>The System class is a grab-bag of functionality exposed by the VM, mostly for <p>The System class is a grab-bag of functionality exposed by the VM, mostly for
use during development or debugging. </p> use during development or debugging.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2> <h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>System.<strong>clock</strong> <a href="#system.clock" name="system.clock" class="header-anchor">#</a></h3> <h3>System.<strong>clock</strong> <a href="#system.clock" name="system.clock" class="header-anchor">#</a></h3>
<p>Returns the number of seconds (including fractional seconds) since the program <p>Returns the number of seconds (including fractional seconds) since the program
was started. This is usually used for benchmarking. </p> was started. This is usually used for benchmarking.</p>
<h3>System.<strong>gc</strong>() <a href="#system.gc()" name="system.gc()" class="header-anchor">#</a></h3> <h3>System.<strong>gc</strong>() <a href="#system.gc()" name="system.gc()" class="header-anchor">#</a></h3>
<p>Requests that the VM perform an immediate garbage collection to free unused <p>Requests that the VM perform an immediate garbage collection to free unused
memory. </p> memory.</p>
<h3>System.<strong>print</strong>() <a href="#system.print()" name="system.print()" class="header-anchor">#</a></h3> <h3>System.<strong>print</strong>() <a href="#system.print()" name="system.print()" class="header-anchor">#</a></h3>
<p>Prints a single newline to the console. </p> <p>Prints a single newline to the console.</p>
<h3>System.<strong>print</strong>(object) <a href="#system.print(object)" name="system.print(object)" class="header-anchor">#</a></h3> <h3>System.<strong>print</strong>(object) <a href="#system.print(object)" name="system.print(object)" class="header-anchor">#</a></h3>
<p>Prints <code>object</code> to the console followed by a newline. If not already a string, <p>Prints <code>object</code> to the console followed by a newline. If not already a string,
the object is converted to a string by calling <code>toString</code> on it. </p> the object is converted to a string by calling <code>toString</code> on it.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;I like bananas&quot;</span><span class="p">)</span> <span class="output">I like bananas</span> <pre class="snippet">
</pre></div> System.print("I like bananas") //> I like bananas
</pre>
<h3>System.<strong>printAll</strong>(sequence) <a href="#system.printall(sequence)" name="system.printall(sequence)" class="header-anchor">#</a></h3> <h3>System.<strong>printAll</strong>(sequence) <a href="#system.printall(sequence)" name="system.printall(sequence)" class="header-anchor">#</a></h3>
<p>Iterates over <code>sequence</code> and prints each element, then prints a single newline <p>Iterates over <code>sequence</code> and prints each element, then prints a single newline
at the end. Each element is converted to a string by calling <code>toString</code> on it. </p> at the end. Each element is converted to a string by calling <code>toString</code> on it.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">printAll</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">],</span> <span class="mi">4</span><span class="p">])</span> <span class="output">1[2, 3]4</span> <pre class="snippet">
</pre></div> System.printAll([1, [2, 3], 4]) //> 1[2, 3]4
</pre>
<h3>System.<strong>write</strong>(object) <a href="#system.write(object)" name="system.write(object)" class="header-anchor">#</a></h3> <h3>System.<strong>write</strong>(object) <a href="#system.write(object)" name="system.write(object)" class="header-anchor">#</a></h3>
<p>Prints a single value to the console, but does not print a newline character <p>Prints a single value to the console, but does not print a newline character
afterwards. Converts the value to a string by calling <code>toString</code> on it. </p> afterwards. Converts the value to a string by calling <code>toString</code> on it.</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="mi">4</span> <span class="o">+</span> <span class="mi">5</span><span class="p">)</span> <span class="output">9</span> <pre class="snippet">
</pre></div> System.write(4 + 5) //> 9
</pre>
<p>In the above example, the result of <code>4 + 5</code> is printed, and then the prompt is
<p>In the above example, the result of <code>4 + 5</code> is printed, and then the prompt is printed on the same line because no newline character was printed afterwards.</p>
printed on the same line because no newline character was printed afterwards. </p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Modules &ndash; Wren</title> <title>Modules &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" /> <link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,11 +23,26 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../wren.svg" class="logo"></a> <a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Wren</a></li>
</ul>
<section> <section>
<h2>core</h2> <h2>core classes</h2>
<ul> <ul>
<li><a href="core">core</a></li> <li><a href="core/bool.html">Bool</a></li>
<li><a href="core/class.html">Class</a></li>
<li><a href="core/fiber.html">Fiber</a></li>
<li><a href="core/fn.html">Fn</a></li>
<li><a href="core/list.html">List</a></li>
<li><a href="core/map.html">Map</a></li>
<li><a href="core/null.html">Null</a></li>
<li><a href="core/num.html">Num</a></li>
<li><a href="core/object.html">Object</a></li>
<li><a href="core/range.html">Range</a></li>
<li><a href="core/sequence.html">Sequence</a></li>
<li><a href="core/string.html">String</a></li>
<li><a href="core/system.html">System</a></li>
</ul> </ul>
</section> </section>
<section> <section>
@ -34,27 +52,29 @@
<li><a href="random">random</a></li> <li><a href="random">random</a></li>
</ul> </ul>
</section> </section>
<section>
<h2>cli</h2>
<ul>
<li><a href="io">io</a></li>
<li><a href="os">os</a></li>
<li><a href="scheduler">scheduler</a></li>
<li><a href="timer">timer</a></li>
</ul>
</section>
</nav> </nav>
<nav class="small"> <nav class="small">
<table> <table>
<tr> <tr>
<td><h2>core</h2></td> <td><h2>core classes</h2></td>
<td><h2>optional</h2></td> <td><h2>optional</h2></td>
<td><h2>cli</h2></td>
</tr> </tr>
<tr> <tr>
<td> <td>
<ul> <ul>
<li><a href="core">core</a></li> <li><a href="core/bool.html">Bool</a></li>
<li><a href="core/class.html">Class</a></li>
<li><a href="core/fiber.html">Fiber</a></li>
<li><a href="core/fn.html">Fn</a></li>
<li><a href="core/list.html">List</a></li>
<li><a href="core/map.html">Map</a></li>
<li><a href="core/null.html">Null</a></li>
<li><a href="core/num.html">Num</a></li>
<li><a href="core/object.html">Object</a></li>
<li><a href="core/range.html">Range</a></li>
<li><a href="core/sequence.html">Sequence</a></li>
<li><a href="core/string.html">String</a></li>
<li><a href="core/system.html">System</a></li>
</ul> </ul>
</td> </td>
<td> <td>
@ -63,54 +83,31 @@
<li><a href="random">random</a></li> <li><a href="random">random</a></li>
</ul> </ul>
</td> </td>
<td>
<ul>
<li><a href="io">io</a></li>
<li><a href="os">os</a></li>
<li><a href="scheduler">scheduler</a></li>
<li><a href="timer">timer</a></li>
</ul>
</td>
</tr> </tr>
</table> </table>
</nav> </nav>
<main> <main>
<h1>Modules</h1> <h1>Modules</h1>
<p>Because Wren can be used both as an embedded scripting language, and as a <p>Wren comes with two kinds of modules, the core module (built-in),
general purpose programming language run from the command line, the definition and a few optional modules that the host embedding Wren can enable.</p>
of a &ldquo;built-in&rdquo; module is a little complicated. They are organized into three <h2>Core module <a href="#core-module" name="core-module" class="header-anchor">#</a></h2>
categories: </p> <p>The core module is built directly into the VM and is implicitly
<h2>Core <a href="#core" name="core" class="header-anchor">#</a></h2> imported by every other module. You don&rsquo;t need to <code>import</code> anything to use it.
<p>There is one core module. It is built directly into the VM and is implicitly It contains objects and types for the language itself like <a href="core/num.html">numbers</a> and <a href="core/string.html">strings</a>.</p>
imported by every other module. It contains the classes for the objects built <p>Because Wren is designed for [embedding in applications][embedding], its core
directly into the language itself: <a href="core/num.html">numbers</a>, <a href="core/string.html">strings</a>, etc. </p> module is minimal and is focused on working with objects within Wren. For
<p>The core module is always available and can&rsquo;t be removed. </p> stuff like file IO, graphics, etc., it is up to the host application to provide
interfaces for this.</p>
<h2>Optional modules <a href="#optional-modules" name="optional-modules" class="header-anchor">#</a></h2>
<p>Optional modules are available in the Wren project, but whether they are included is up to the host.
They are written in Wren and C, with no external dependencies, so including them in
your application is as easy as a simple compile flag.</p>
<p>Since they aren&rsquo;t <em>needed</em> by the VM itself to function, you can
disable some or all of them, so check if your host has them available.</p>
<p>So far there are a few optional modules:</p>
<ul> <ul>
<li><a href="core">core</a> </li> <li><a href="meta">meta docs</a></li>
</ul> <li><a href="random">random docs</a></li>
<h2>Optional <a href="#optional" name="optional" class="header-anchor">#</a></h2>
<p>Optional modules are available in the command line Wren interpreter. When you
embed Wren in your own host application, you can also include them too. They are
written in Wren and C, but have no external dependencies, so including them in
your application doesn&rsquo;t force you to bring in any other third-party code. </p>
<p>At the same time, they aren&rsquo;t <em>needed</em> by the VM itself to function, so you can
disable some or all of them if you want to keep your app as small and
constrained as possible. </p>
<p>There are a couple of optional modules: </p>
<ul>
<li><a href="meta">meta</a> </li>
<li><a href="random">random</a> </li>
</ul>
<h2>CLI <a href="#cli" name="cli" class="header-anchor">#</a></h2>
<p>The CLI modules are only available in the standalone command-line Wren
interpreter. They are deeply tied to <a href="http://libuv.org">libuv</a>, each other, and other internals
of the command-line app, so can&rsquo;t be separated out and pulled into host
applications that want to embed Wren. </p>
<ul>
<li><a href="io">io</a> </li>
<li><a href="os">os</a> </li>
<li><a href="scheduler">scheduler</a> </li>
<li><a href="timer">timer</a> </li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Module "meta" &ndash; Wren</title> <title>Module "meta" &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">meta</a></li> <li><a href="./">meta module</a></li>
</ul> </ul>
<section> <section>
<h2>meta classes</h2> <h2>meta classes</h2>
@ -56,9 +59,9 @@
</nav> </nav>
<main> <main>
<h1>Module "meta"</h1> <h1>Module "meta"</h1>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<ul> <ul>
<li><a href="meta.html">Meta</a> </li> <li><a href="meta.html">Meta</a></li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Meta Class &ndash; Wren</title> <title>Meta Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">meta</a></li> <li><a href="./">meta module</a></li>
</ul> </ul>
<section> <section>
<h2>meta classes</h2> <h2>meta classes</h2>
@ -56,9 +59,9 @@
</nav> </nav>
<main> <main>
<h1>Meta Class</h1> <h1>Meta Class</h1>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> <h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<p><strong>TODO</strong> </p> <p><strong>TODO</strong></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Module "random" &ndash; Wren</title> <title>Module "random" &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">random</a></li> <li><a href="./">random module</a></li>
</ul> </ul>
<section> <section>
<h2>random classes</h2> <h2>random classes</h2>
@ -56,12 +59,12 @@
</nav> </nav>
<main> <main>
<h1>Module "random"</h1> <h1>Module "random"</h1>
<p>This module provides a simple, fast pseudo-random number generator. </p> <p>This module provides a simple, fast pseudo-random number generator.</p>
<p>It is an optional module. You can omit it from your application by setting the <p>It is an optional module. You can omit it from your application by setting the
preprocessor constant <code>WREN_OPT_RANDOM</code> to <code>0</code>. </p> preprocessor constant <code>WREN_OPT_RANDOM</code> to <code>0</code>.</p>
<p>It contains a single class: </p> <p>It contains a single class:</p>
<ul> <ul>
<li><a href="random.html">Random</a> </li> <li><a href="random.html">Random</a></li>
</ul> </ul>
</main> </main>
</div> </div>

View File

@ -3,6 +3,9 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Random Class &ndash; Wren</title> <title>Random Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" /> <link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -20,10 +23,10 @@
</header> </header>
<div class="page"> <div class="page">
<nav class="big"> <nav class="big">
<a href="./"><img src="../../wren.svg" class="logo"></a> <a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul> <ul>
<li><a href="../">Modules</a></li> <li><a href="../">Back to Modules</a></li>
<li><a href="./">random</a></li> <li><a href="./">random module</a></li>
</ul> </ul>
<section> <section>
<h2>random classes</h2> <h2>random classes</h2>
@ -56,109 +59,136 @@
</nav> </nav>
<main> <main>
<h1>Random Class</h1> <h1>Random Class</h1>
<p>A simple, fast pseudo-random number generator. Internally, it uses the <a href="https://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear">well <p>A simple, fast pseudo-random number generator. Internally, it uses the <a href="https://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear">well
equidistributed long-period linear PRNG</a> (WELL512a). </p> equidistributed long-period linear PRNG</a> (WELL512a).</p>
<p>Each instance of the class generates a sequence of randomly distributed numbers <p>Each instance of the class generates a sequence of randomly distributed numbers
based on the internal state of the object. The state is initialized from a based on the internal state of the object. The state is initialized from a
<em>seed</em>. Two instances with the same seed generate the exact same sequence of <em>seed</em>. Two instances with the same seed generate the exact same sequence of
numbers. </p> numbers.</p>
<p>It must be imported from the <a href="../">random</a> module: </p> <p>It must be imported from the [random][] module:</p>
<div class="codehilite"><pre><span class="k">import</span> <span class="s">&quot;random&quot;</span> <span class="k">for</span> <span class="vg">Random</span> <pre class="snippet">
</pre></div> import "random" for Random
[random]: ../
<h2>Constructors <a href="#constructors" name="constructors" class="header-anchor">#</a></h2> ##Constructors <a href="#constructors" name="constructors" class="header-anchor">#</a>
<h3>Random.<strong>new</strong>() <a href="#random.new()" name="random.new()" class="header-anchor">#</a></h3>
<p>Creates a new generator whose state is seeded based on the current time. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">()</span>
</pre></div>
###Random.**new**() <a href="#random.new()" name="random.new()" class="header-anchor">#</a>
<h3>Random.<strong>new</strong>(seed) <a href="#random.new(seed)" name="random.new(seed)" class="header-anchor">#</a></h3> Creates a new generator whose state is seeded based on the current time.
<p>Creates a new generator initialized with [seed]. The seed can either be a
number, or a non-empty sequence of numbers. If the sequnce has more than 16
elements, only the first 16 are used. If it has fewer, the elements are cycled
to generate 16 seed values. </p>
<div class="codehilite"><pre><span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">12345</span><span class="p">)</span>
<span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;appleseed&quot;</span><span class="o">.</span><span class="n">codePoints</span><span class="p">)</span>
</pre></div>
<pre class="snippet">
var random = Random.new()
</pre>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2> ###Random.**new**(seed) <a href="#random.new(seed)" name="random.new(seed)" class="header-anchor">#</a>
<h3><strong>float</strong>() <a href="#float()" name="float()" class="header-anchor">#</a></h3>
<p>Returns a floating point value between 0.0 and 1.0, including 0.0, but excluding
1.0. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">12345</span><span class="p">)</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">())</span> <span class="output">0.53178795980617</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">())</span> <span class="output">0.20180515043262</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">())</span> <span class="output">0.43371948658705</span>
</pre></div>
Creates a new generator initialized with [seed]. The seed can either be a
number, or a non-empty sequence of numbers. If the sequnce has more than 16
elements, only the first 16 are used. If it has fewer, the elements are cycled
to generate 16 seed values.
<h3><strong>float</strong>(end) <a href="#float(end)" name="float(end)" class="header-anchor">#</a></h3> <pre class="snippet">
<p>Returns a floating point value between 0.0 and <code>end</code>, including 0.0 but Random.new(12345)
excluding <code>end</code>. </p> Random.new("appleseed".codePoints)
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">12345</span><span class="p">)</span> </pre>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span> <span class="output">0</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">(</span><span class="mi">100</span><span class="p">))</span> <span class="output">20.180515043262</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">(</span><span class="o">-</span><span class="mi">100</span><span class="p">))</span> <span class="output">-43.371948658705</span>
</pre></div>
##Methods <a href="#methods" name="methods" class="header-anchor">#</a>
<h3><strong>float</strong>(start, end) <a href="#float(start,-end)" name="float(start,-end)" class="header-anchor">#</a></h3> ###**float**() <a href="#float()" name="float()" class="header-anchor">#</a>
<p>Returns a floating point value between <code>start</code> and <code>end</code>, including <code>start</code> but
excluding <code>end</code>. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">12345</span><span class="p">)</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span> <span class="output">3.5317879598062</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">(</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span> <span class="output">-5.9638969913476</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">float</span><span class="p">(</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span> <span class="output">-1.3976830804777</span>
</pre></div>
Returns a floating point value between 0.0 and 1.0, including 0.0, but excluding
1.0.
<h3><strong>int</strong>(end) <a href="#int(end)" name="int(end)" class="header-anchor">#</a></h3> <pre class="snippet">
<p>Returns an integer between 0 and <code>end</code>, including 0 but excluding <code>end</code>. </p> var random = Random.new(12345)
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">12345</span><span class="p">)</span> System.print(random.float()) //> 0.53178795980617
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="output">0</span> System.print(random.float()) //> 0.20180515043262
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span> <span class="output">2</span> System.print(random.float()) //> 0.43371948658705
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="o">-</span><span class="mi">50</span><span class="p">))</span> <span class="output">-22</span> </pre>
</pre></div>
###**float**(end) <a href="#float(end)" name="float(end)" class="header-anchor">#</a>
<h3><strong>int</strong>(start, end) <a href="#int(start,-end)" name="int(start,-end)" class="header-anchor">#</a></h3> Returns a floating point value between 0.0 and `end`, including 0.0 but
<p>Returns an integer between <code>start</code> and <code>end</code>, including <code>start</code> but excluding excluding `end`.
<code>end</code>. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">12345</span><span class="p">)</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span> <span class="output">3</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="o">-</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span> <span class="output">-6</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">int</span><span class="p">(</span><span class="o">-</span><span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span> <span class="output">-2</span>
</pre></div>
<pre class="snippet">
var random = Random.new(12345)
System.print(random.float(0)) //> 0
System.print(random.float(100)) //> 20.180515043262
System.print(random.float(-100)) //> -43.371948658705
</pre>
<h3><strong>sample</strong>(list) <a href="#sample(list)" name="sample(list)" class="header-anchor">#</a></h3> ###**float**(start, end) <a href="#float(start,-end)" name="float(start,-end)" class="header-anchor">#</a>
<p>Selects a random element from <code>list</code>. </p>
<h3><strong>sample</strong>(list, count) <a href="#sample(list,-count)" name="sample(list,-count)" class="header-anchor">#</a></h3>
<p>Samples <code>count</code> randomly chosen unique elements from <code>list</code>. </p>
<p>This uses &ldquo;random without replacement&rdquo; sampling&mdash;no index in the list will
be selected more than once. </p>
<p>Returns a new list of the selected elements. </p>
<p>It is an error if <code>count</code> is greater than the number of elements in the list. </p>
<h3><strong>shuffle</strong>(list) <a href="#shuffle(list)" name="shuffle(list)" class="header-anchor">#</a></h3>
<p>Randomly shuffles the elements in <code>list</code>. The items are randomly re-ordered in
place. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">random</span> <span class="o">=</span> <span class="vg">Random</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">12345</span><span class="p">)</span>
<span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">5</span><span class="p">)</span><span class="o">.</span><span class="n">toList</span>
<span class="n">random</span><span class="o">.</span><span class="n">shuffle</span><span class="p">(</span><span class="n">list</span><span class="p">)</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">list</span><span class="p">)</span> <span class="output">[3, 2, 4, 1, 5]</span>
</pre></div>
Returns a floating point value between `start` and `end`, including `start` but
excluding `end`.
<p>Uses the Fisher-Yates algorithm to ensure that all permutations are chosen <pre class="snippet">
with equal probability. </p> var random = Random.new(12345)
<p>Keep in mind that a list with even a modestly large number of elements has an System.print(random.float(3, 4)) //> 3.5317879598062
astronomically large number of permutations. For example, there are about 10^74 System.print(random.float(-10, 10)) //> -5.9638969913476
ways a deck of 56 cards can be shuffled. The random number generator&rsquo;s internal System.print(random.float(-4, 2)) //> -1.3976830804777
state is not that large, which means there are many permutations it will never </pre>
generate. </p>
###**int**(end) <a href="#int(end)" name="int(end)" class="header-anchor">#</a>
Returns an integer between 0 and `end`, including 0 but excluding `end`.
<pre class="snippet">
var random = Random.new(12345)
System.print(random.int(1)) //> 0
System.print(random.int(10)) //> 2
System.print(random.int(-50)) //> -22
</pre>
###**int**(start, end) <a href="#int(start,-end)" name="int(start,-end)" class="header-anchor">#</a>
Returns an integer between `start` and `end`, including `start` but excluding
`end`.
<pre class="snippet">
var random = Random.new(12345)
System.print(random.int(3, 4)) //> 3
System.print(random.int(-10, 10)) //> -6
System.print(random.int(-4, 2)) //> -2
</pre>
###**sample**(list) <a href="#sample(list)" name="sample(list)" class="header-anchor">#</a>
Selects a random element from `list`.
###**sample**(list, count) <a href="#sample(list,-count)" name="sample(list,-count)" class="header-anchor">#</a>
Samples `count` randomly chosen unique elements from `list`.
This uses "random without replacement" sampling&mdash;no index in the list will
be selected more than once.
Returns a new list of the selected elements.
It is an error if `count` is greater than the number of elements in the list.
###**shuffle**(list) <a href="#shuffle(list)" name="shuffle(list)" class="header-anchor">#</a>
Randomly shuffles the elements in `list`. The items are randomly re-ordered in
place.
<pre class="snippet">
var random = Random.new(12345)
var list = (1..5).toList
random.shuffle(list)
System.print(list) //> [3, 2, 4, 1, 5]
</pre>
Uses the Fisher-Yates algorithm to ensure that all permutations are chosen
with equal probability.
Keep in mind that a list with even a modestly large number of elements has an
astronomically large number of permutations. For example, there are about 10^74
ways a deck of 56 cards can be shuffled. The random number generator's internal
state is not that large, which means there are many permutations it will never
generate.
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Performance &ndash; Wren</title> <title>Performance &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,215 +110,222 @@
</nav> </nav>
<main> <main>
<h2>Performance</h2> <h2>Performance</h2>
<p>Even though most benchmarks aren&rsquo;t worth the pixels they&rsquo;re printed on, people <p>Even though most benchmarks aren&rsquo;t worth the pixels they&rsquo;re printed on, people
seem to like them, so here&rsquo;s a few: </p> seem to like them, so here&rsquo;s a few:</p>
<h3>Method Call</h3> <h3>Method Call</h3>
<p><table class="chart"> <table class="chart">
<tr> <tr>
<th>wren</th><td><div class="chart-bar wren" style="width: 14%;">0.12s&nbsp;</div></td> <th>wren</th><td><div class="chart-bar wren" style="width: 14%;">0.12s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>luajit (-joff)</th><td><div class="chart-bar" style="width: 18%;">0.16s&nbsp;</div></td> <th>luajit (-joff)</th><td><div class="chart-bar" style="width: 18%;">0.16s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>ruby</th><td><div class="chart-bar" style="width: 23%;">0.20s&nbsp;</div></td> <th>ruby</th><td><div class="chart-bar" style="width: 23%;">0.20s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>lua</th><td><div class="chart-bar" style="width: 41%;">0.35s&nbsp;</div></td> <th>lua</th><td><div class="chart-bar" style="width: 41%;">0.35s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>python3</th><td><div class="chart-bar" style="width: 91%;">0.78s&nbsp;</div></td> <th>python3</th><td><div class="chart-bar" style="width: 91%;">0.78s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>python</th><td><div class="chart-bar" style="width: 100%;">0.85s&nbsp;</div></td> <th>python</th><td><div class="chart-bar" style="width: 100%;">0.85s&nbsp;</div></td>
</tr> </tr>
</table> </table>
<h3>DeltaBlue</h3>
<table class="chart"> <h3>DeltaBlue</h3>
<tr>
<th>wren</th><td><div class="chart-bar wren" style="width: 22%;">0.13s&nbsp;</div></td> <table class="chart">
</tr> <tr>
<tr> <th>wren</th><td><div class="chart-bar wren" style="width: 22%;">0.13s&nbsp;</div></td>
<th>python3</th><td><div class="chart-bar" style="width: 83%;">0.48s&nbsp;</div></td> </tr>
</tr> <tr>
<tr> <th>python3</th><td><div class="chart-bar" style="width: 83%;">0.48s&nbsp;</div></td>
<th>python</th><td><div class="chart-bar" style="width: 100%;">0.57s&nbsp;</div></td> </tr>
</tr> <tr>
</table> <th>python</th><td><div class="chart-bar" style="width: 100%;">0.57s&nbsp;</div></td>
<h3>Binary Trees</h3> </tr>
<table class="chart"> </table>
<tr>
<th>luajit (-joff)</th><td><div class="chart-bar" style="width: 20%;">0.11s&nbsp;</div></td> <h3>Binary Trees</h3>
</tr>
<tr> <table class="chart">
<th>wren</th><td><div class="chart-bar wren" style="width: 41%;">0.22s&nbsp;</div></td> <tr>
</tr> <th>luajit (-joff)</th><td><div class="chart-bar" style="width: 20%;">0.11s&nbsp;</div></td>
<tr> </tr>
<th>ruby</th><td><div class="chart-bar" style="width: 46%;">0.24s&nbsp;</div></td> <tr>
</tr> <th>wren</th><td><div class="chart-bar wren" style="width: 41%;">0.22s&nbsp;</div></td>
<tr> </tr>
<th>python</th><td><div class="chart-bar" style="width: 71%;">0.37s&nbsp;</div></td> <tr>
</tr> <th>ruby</th><td><div class="chart-bar" style="width: 46%;">0.24s&nbsp;</div></td>
<tr> </tr>
<th>python3</th><td><div class="chart-bar" style="width: 73%;">0.38s&nbsp;</div></td> <tr>
</tr> <th>python</th><td><div class="chart-bar" style="width: 71%;">0.37s&nbsp;</div></td>
<tr> </tr>
<th>lua</th><td><div class="chart-bar" style="width: 100%;">0.52s&nbsp;</div></td> <tr>
</tr> <th>python3</th><td><div class="chart-bar" style="width: 73%;">0.38s&nbsp;</div></td>
</table> </tr>
<h3>Recursive Fibonacci</h3> <tr>
<table class="chart"> <th>lua</th><td><div class="chart-bar" style="width: 100%;">0.52s&nbsp;</div></td>
<tr> </tr>
<th>luajit (-joff)</th><td><div class="chart-bar" style="width: 17%;">0.10s&nbsp;</div></td> </table>
</tr>
<tr> <h3>Recursive Fibonacci</h3>
<th>wren</th><td><div class="chart-bar wren" style="width: 35%;">0.20s&nbsp;</div></td>
</tr> <table class="chart">
<tr> <tr>
<th>ruby</th><td><div class="chart-bar" style="width: 39%;">0.22s&nbsp;</div></td> <th>luajit (-joff)</th><td><div class="chart-bar" style="width: 17%;">0.10s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>lua</th><td><div class="chart-bar" style="width: 49%;">0.28s&nbsp;</div></td> <th>wren</th><td><div class="chart-bar wren" style="width: 35%;">0.20s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>python</th><td><div class="chart-bar" style="width: 90%;">0.51s&nbsp;</div></td> <th>ruby</th><td><div class="chart-bar" style="width: 39%;">0.22s&nbsp;</div></td>
</tr> </tr>
<tr> <tr>
<th>python3</th><td><div class="chart-bar" style="width: 100%;">0.57s&nbsp;</div></td> <th>lua</th><td><div class="chart-bar" style="width: 49%;">0.28s&nbsp;</div></td>
</tr> </tr>
</table> </p> <tr>
<p><strong>Shorter bars are better.</strong> Each benchmark is run ten times and the best time <th>python</th><td><div class="chart-bar" style="width: 90%;">0.51s&nbsp;</div></td>
is kept. It only measures the time taken to execute the benchmarked code </tr>
itself, not interpreter startup. </p> <tr>
<p>These were run on my MacBook Pro 2.3 GHz Intel Core i7 with 16 GB of 1,600 MHz <th>python3</th><td><div class="chart-bar" style="width: 100%;">0.57s&nbsp;</div></td>
DDR3 RAM. Tested against Lua 5.2.3, LuaJIT 2.0.2, Python 2.7.5, Python 3.3.4, </tr>
ruby 2.0.0p247. LuaJIT is run with the JIT <em>disabled</em> (i.e. in bytecode </table>
interpreter mode) since I want to support platforms where JIT-compilation is
disallowed. LuaJIT with the JIT enabled is <em>much</em> faster than all of the other <p><strong>Shorter bars are better.</strong> Each benchmark is run ten times and the best time
languages benchmarked, including Wren, because Mike Pall is a robot from the is kept. It only measures the time taken to execute the benchmarked code
future. </p> itself, not interpreter startup.</p>
<p>The benchmark harness and programs are <p>These were run on my MacBook Pro 2.3 GHz Intel Core i7 with 16 GB of 1,600 MHz
DDR3 RAM. Tested against Lua 5.2.3, LuaJIT 2.0.2, Python 2.7.5, Python 3.3.4,
ruby 2.0.0p247. LuaJIT is run with the JIT <em>disabled</em> (i.e. in bytecode
interpreter mode) since I want to support platforms where JIT-compilation is
disallowed. LuaJIT with the JIT enabled is <em>much</em> faster than all of the other
languages benchmarked, including Wren, because Mike Pall is a robot from the
future.</p>
<p>The benchmark harness and programs are
<a href="https://github.com/wren-lang/wren/tree/master/test/benchmark">here</a>.</p> <a href="https://github.com/wren-lang/wren/tree/master/test/benchmark">here</a>.</p>
<h2>Why is Wren fast? <a href="#why-is-wren-fast" name="why-is-wren-fast" class="header-anchor">#</a></h2> <h2>Why is Wren fast? <a href="#why-is-wren-fast" name="why-is-wren-fast" class="header-anchor">#</a></h2>
<p>Languages come in four rough performance buckets, from slowest to fastest: </p> <p>Languages come in four rough performance buckets, from slowest to fastest:</p>
<ol> <ol>
<li> <li>
<p>Tree-walk interpreters: Ruby 1.8.7 and earlier, Io, that <p>Tree-walk interpreters: Ruby 1.8.7 and earlier, Io, that
interpreter you wrote for a class in college. </p> interpreter you wrote for a class in college.</p>
</li> </li>
<li> <li>
<p>Bytecode interpreters: CPython, <p>Bytecode interpreters: CPython,
Ruby 1.9 and later, Lua, early JavaScript VMs. </p> Ruby 1.9 and later, Lua, early JavaScript VMs.</p>
</li> </li>
<li> <li>
<p>JIT compiled dynamically typed languages: Modern JavaScript VMs, <p>JIT compiled dynamically typed languages: Modern JavaScript VMs,
LuaJIT, PyPy, some Lisp/Scheme implementations. </p> LuaJIT, PyPy, some Lisp/Scheme implementations.</p>
</li> </li>
<li> <li>
<p>Statically typed languages: C, C++, Java, C#, Haskell, etc. </p> <p>Statically typed languages: C, C++, Java, C#, Haskell, etc.</p>
</li> </li>
</ol> </ol>
<p>Most languages in the first bucket aren&rsquo;t suitable for production use. (Servers <p>Most languages in the first bucket aren&rsquo;t suitable for production use. (Servers
are one exception, because you can throw more hardware at a slow language are one exception, because you can throw more hardware at a slow language
there.) Languages in the second bucket are fast enough for many use cases, even there.) Languages in the second bucket are fast enough for many use cases, even
on client hardware, as the success of the listed languages shows. Languages in on client hardware, as the success of the listed languages shows. Languages in
the third bucket are quite fast, but their implementations are breathtakingly the third bucket are quite fast, but their implementations are breathtakingly
complex, often rivaling that of compilers for statically-typed languages. </p> complex, often rivaling that of compilers for statically-typed languages.</p>
<p>Wren is in the second bucket. If you want a simple implementation that&rsquo;s fast <p>Wren is in the second bucket. If you want a simple implementation that&rsquo;s fast
enough for real use, this is the sweet spot. In addition, Wren has a few tricks enough for real use, this is the sweet spot. In addition, Wren has a few tricks
up its sleeve: </p> up its sleeve:</p>
<h3>A compact value representation <a href="#a-compact-value-representation" name="a-compact-value-representation" class="header-anchor">#</a></h3> <h3>A compact value representation <a href="#a-compact-value-representation" name="a-compact-value-representation" class="header-anchor">#</a></h3>
<p>A core piece of a dynamic language implementation is the data structure used <p>A core piece of a dynamic language implementation is the data structure used
for variables. It needs to be able to store (or reference) a value of any type, for variables. It needs to be able to store (or reference) a value of any type,
while also being as compact as possible. Wren uses a technique called <em><a href="http://wingolog.org/archives/2011/05/18/value-representation-in-javascript-implementations">NaN while also being as compact as possible. Wren uses a technique called <em><a href="http://wingolog.org/archives/2011/05/18/value-representation-in-javascript-implementations">NaN
tagging</a></em> for this. </p> tagging</a></em> for this.</p>
<p>All values are stored internally in Wren as small, eight-byte double-precision <p>All values are stored internally in Wren as small, eight-byte double-precision
floats. Since that is also Wren&rsquo;s number type, in order to do arithmetic, no floats. Since that is also Wren&rsquo;s number type, in order to do arithmetic, no
conversion is needed before the &ldquo;raw&rdquo; number can be accessed: a value holding a conversion is needed before the &ldquo;raw&rdquo; number can be accessed: a value holding a
number <em>is</em> a valid double. This keeps arithmetic fast. </p> number <em>is</em> a valid double. This keeps arithmetic fast.</p>
<p>To store values of other types, it turns out there&rsquo;s a ton of unused bits in a <p>To store values of other types, it turns out there&rsquo;s a ton of unused bits in a
NaN double. You can stuff a pointer for heap-allocated objects, with room left NaN double. You can stuff a pointer for heap-allocated objects, with room left
over for special values like <code>true</code>, <code>false</code>, and <code>null</code>. This means numbers, over for special values like <code>true</code>, <code>false</code>, and <code>null</code>. This means numbers,
bools, and null are unboxed. It also means an entire value is only eight bytes, bools, and null are unboxed. It also means an entire value is only eight bytes,
the native word size on 64-bit machines. Smaller = faster when you take into the native word size on 64-bit machines. Smaller = faster when you take into
account CPU caching and the cost of passing values around. </p> account CPU caching and the cost of passing values around.</p>
<h3>Fixed object layout <a href="#fixed-object-layout" name="fixed-object-layout" class="header-anchor">#</a></h3> <h3>Fixed object layout <a href="#fixed-object-layout" name="fixed-object-layout" class="header-anchor">#</a></h3>
<p>Most dynamic languages treat objects as loose bags of named properties. You can <p>Most dynamic languages treat objects as loose bags of named properties. You can
freely add and remove properties from an object after you&rsquo;ve created it. freely add and remove properties from an object after you&rsquo;ve created it.
Languages like Lua and JavaScript don&rsquo;t even have a well-defined concept of a Languages like Lua and JavaScript don&rsquo;t even have a well-defined concept of a
&ldquo;type&rdquo; of object. </p> &ldquo;type&rdquo; of object.</p>
<p>Wren is strictly class-based. Every object is an instance of a class. Classes <p>Wren is strictly class-based. Every object is an instance of a class. Classes
in turn have a well-defined declarative syntax, and cannot be imperatively in turn have a well-defined declarative syntax, and cannot be imperatively
modified. In addition, fields in Wren are private to the class&mdash;they can modified. In addition, fields in Wren are private to the class&mdash;they can
only be accessed from methods defined directly on that class. </p> only be accessed from methods defined directly on that class.</p>
<p>Put all of that together and it means you can determine at <em>compile</em> time <p>Put all of that together and it means you can determine at <em>compile</em> time
exactly how many fields an object has and what they are. In other languages, exactly how many fields an object has and what they are. In other languages,
when you create an object, you allocate some initial memory for it, but that when you create an object, you allocate some initial memory for it, but that
may have to be reallocated multiple times as fields are added and the object may have to be reallocated multiple times as fields are added and the object
grows. Wren just does a single allocation up front for exactly the right number grows. Wren just does a single allocation up front for exactly the right number
of fields. </p> of fields.</p>
<p>Likewise, when you access a field in other languages, the interpreter has to <p>Likewise, when you access a field in other languages, the interpreter has to
look it up by name in a hash table in the object, and then maybe walk its look it up by name in a hash table in the object, and then maybe walk its
inheritance chain if it can&rsquo;t find it. It must do this every time since fields inheritance chain if it can&rsquo;t find it. It must do this every time since fields
may be added freely. In Wren, field access is just accessing a slot in the may be added freely. In Wren, field access is just accessing a slot in the
instance by an offset known at compile time: it&rsquo;s just adding a few pointers. </p> instance by an offset known at compile time: it&rsquo;s just adding a few pointers.</p>
<h3>Copy-down inheritance <a href="#copy-down-inheritance" name="copy-down-inheritance" class="header-anchor">#</a></h3> <h3>Copy-down inheritance <a href="#copy-down-inheritance" name="copy-down-inheritance" class="header-anchor">#</a></h3>
<p>When you call a method on an object, the method must be located. It could be <p>When you call a method on an object, the method must be located. It could be
defined directly on the object&rsquo;s class, or it may be inheriting it from some defined directly on the object&rsquo;s class, or it may be inheriting it from some
superclass. This means that in the worst case, you may have to walk the superclass. This means that in the worst case, you may have to walk the
inheritance chain to find it. </p> inheritance chain to find it.</p>
<p>Advanced implementations do very smart things to optimize this, but it&rsquo;s made <p>Advanced implementations do very smart things to optimize this, but it&rsquo;s made
more difficult by the mutable nature of the underlying language: if you can add more difficult by the mutable nature of the underlying language: if you can add
new methods to existing classes freely or change the inheritance hierarchy, the new methods to existing classes freely or change the inheritance hierarchy, the
lookup for a given method may actually change over time. You have to check for lookup for a given method may actually change over time. You have to check for
that which costs CPU cycles. </p> that which costs CPU cycles.</p>
<p>Wren&rsquo;s inheritance hierarchy is static and fixed at class definition time. This <p>Wren&rsquo;s inheritance hierarchy is static and fixed at class definition time. This
means that we can copy down all inherited methods in the subclass when it&rsquo;s means that we can copy down all inherited methods in the subclass when it&rsquo;s
created since we know those will never change. Method dispatch then just created since we know those will never change. Method dispatch then just
requires locating the method in the class of the receiver. </p> requires locating the method in the class of the receiver.</p>
<h3>Method signatures <a href="#method-signatures" name="method-signatures" class="header-anchor">#</a></h3> <h3>Method signatures <a href="#method-signatures" name="method-signatures" class="header-anchor">#</a></h3>
<p>Wren supports overloading by arity using its concept of <a href="method-calls.html#signature">signatures</a>. This makes <p>Wren supports overloading by arity using its concept of <a href="method-calls.html#signature">signatures</a>. This makes
the language more expressive, but also faster. When a method is called, we look the language more expressive, but also faster. When a method is called, we look
it up on the receiver&rsquo;s class. If we succeed in finding it, we also know it has it up on the receiver&rsquo;s class. If we succeed in finding it, we also know it has
the right number of parameters. </p> the right number of parameters.</p>
<p>This lets Wren avoid the extra checking most languages need to do at runtime to <p>This lets Wren avoid the extra checking most languages need to do at runtime to
handle too few or too many arguments being passed to a method. In Wren, it&rsquo;s not handle too few or too many arguments being passed to a method. In Wren, it&rsquo;s not
<em>syntactically</em> possible to call a method with the wrong number of arguments. </p> <em>syntactically</em> possible to call a method with the wrong number of arguments.</p>
<h3>Computed gotos <a href="#computed-gotos" name="computed-gotos" class="header-anchor">#</a></h3> <h3>Computed gotos <a href="#computed-gotos" name="computed-gotos" class="header-anchor">#</a></h3>
<p>On compilers that support it, Wren&rsquo;s core bytecode interpreter loop uses <p>On compilers that support it, Wren&rsquo;s core bytecode interpreter loop uses
something called <a href="http://eli.thegreenplace.net/2012/07/12/computed-goto-for-efficient-dispatch-tables/"><em>computed gotos</em></a>. The hot core of a bytecode something called <a href="http://eli.thegreenplace.net/2012/07/12/computed-goto-for-efficient-dispatch-tables/"><em>computed gotos</em></a>. The hot core of a bytecode
interpreter is effectively a giant <code>switch</code> on the instruction being executed. </p> interpreter is effectively a giant <code>switch</code> on the instruction being executed.</p>
<p>Doing that using an actual <code>switch</code> confounds the CPU&rsquo;s <a href="http://en.wikipedia.org/wiki/Branch_predictor">branch <p>Doing that using an actual <code>switch</code> confounds the CPU&rsquo;s <a href="http://en.wikipedia.org/wiki/Branch_predictor">branch
predictor</a>&mdash;there is basically a single branch point for the entire predictor</a>&mdash;there is basically a single branch point for the entire
interpreter. That quickly saturates the predictor and it just gets confused and interpreter. That quickly saturates the predictor and it just gets confused and
fails to predict anything, which leads to more CPU stalls and pipeline flushes. </p> fails to predict anything, which leads to more CPU stalls and pipeline flushes.</p>
<p>Using computed gotos gives you a separate branch point at the end of each <p>Using computed gotos gives you a separate branch point at the end of each
instruction. Each gets its own branch prediction, which often succeeds since instruction. Each gets its own branch prediction, which often succeeds since
some instruction pairs are more common than others. In my rough testing, this some instruction pairs are more common than others. In my rough testing, this
makes a 5-10% performance difference. </p> makes a 5-10% performance difference.</p>
<h3>A single-pass compiler <a href="#a-single-pass-compiler" name="a-single-pass-compiler" class="header-anchor">#</a></h3> <h3>A single-pass compiler <a href="#a-single-pass-compiler" name="a-single-pass-compiler" class="header-anchor">#</a></h3>
<p>Compile time is a relatively small component of a language&rsquo;s performance: code <p>Compile time is a relatively small component of a language&rsquo;s performance: code
only has to be compiled once but a given line of code may be run many times. only has to be compiled once but a given line of code may be run many times.
However, fast compilation helps with <em>startup</em> speed&mdash;the time it takes to However, fast compilation helps with <em>startup</em> speed&mdash;the time it takes to
get anything up and running. For that, Wren&rsquo;s compiler is quite fast. </p> get anything up and running. For that, Wren&rsquo;s compiler is quite fast.</p>
<p>It&rsquo;s modeled after Lua&rsquo;s compiler. Instead of tokenizing and then parsing to <p>It&rsquo;s modeled after Lua&rsquo;s compiler. Instead of tokenizing and then parsing to
create a bunch of AST structures which are then consumed and deallocated by create a bunch of AST structures which are then consumed and deallocated by
later phases, it emits code directly during parsing. This means it does minimal later phases, it emits code directly during parsing. This means it does minimal
memory allocation during a parse and has very little overhead. </p> memory allocation during a parse and has very little overhead.</p>
<h2>Why don&rsquo;t other languages do this? <a href="#why-don't-other-languages-do-this" name="why-don't-other-languages-do-this" class="header-anchor">#</a></h2> <h2>Why don&rsquo;t other languages do this? <a href="#why-don't-other-languages-do-this" name="why-don't-other-languages-do-this" class="header-anchor">#</a></h2>
<p>Most of Wren&rsquo;s performance comes from language design decisions. While it&rsquo;s <p>Most of Wren&rsquo;s performance comes from language design decisions. While it&rsquo;s
dynamically <em>typed</em> and <em>dispatched</em>, classes are relatively statically dynamically <em>typed</em> and <em>dispatched</em>, classes are relatively statically
<em>defined</em>. That makes a lot of things much easier. Other languages have a much <em>defined</em>. That makes a lot of things much easier. Other languages have a much
more mutable object model, and cannot change that without breaking lots of more mutable object model, and cannot change that without breaking lots of
existing code. </p> existing code.</p>
<p>Wren&rsquo;s closest sibling, by far, is Lua. Lua is more dynamic than Wren which <p>Wren&rsquo;s closest sibling, by far, is Lua. Lua is more dynamic than Wren which
makes its job harder. Lua also tries very hard to be compatible across a wide makes its job harder. Lua also tries very hard to be compatible across a wide
range of hardware and compilers. If you have a C89 compiler for it, odds are range of hardware and compilers. If you have a C89 compiler for it, odds are
very good that you can run Lua on it. </p> very good that you can run Lua on it.</p>
<p>Wren cares about compatibility, but it requires C99 or C++98 and IEEE double <p>Wren cares about compatibility, but it requires C99 or C++98 and IEEE double
precision floats. That may exclude some edge case hardware, but makes things precision floats. That may exclude some edge case hardware, but makes things
like NaN tagging, computed gotos, and some other tricks possible. </p> like NaN tagging, computed gotos, and some other tricks possible.</p>
<script src="script.js"></script> <script src="script.js"></script>
</main> </main>
</div> </div>

142
prism.css Normal file
View File

@ -0,0 +1,142 @@
/* PrismJS 1.20.0
https://prismjs.com/download.html#themes=prism&languages=clike+c+lua */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.token.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

6
prism.js Normal file

File diff suppressed because one or more lines are too long

250
qa.html
View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Q & A &ndash; Wren</title> <title>Q & A &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -99,142 +111,146 @@
<main> <main>
<h2>Q & A</h2> <h2>Q & A</h2>
<h2>Why did you create Wren? <a href="#why-did-you-create-wren" name="why-did-you-create-wren" class="header-anchor">#</a></h2> <h2>Why did you create Wren? <a href="#why-did-you-create-wren" name="why-did-you-create-wren" class="header-anchor">#</a></h2>
<p>Other creative endeavors aren&rsquo;t immediately met with existential crises, but <p>Other creative endeavors aren&rsquo;t immediately met with existential crises, but
for some reason programmers don&rsquo;t seem to like new languages. Here&rsquo;s the niche for some reason programmers don&rsquo;t seem to like new languages. Here&rsquo;s the niche
I&rsquo;m trying to fill: </p> I&rsquo;m trying to fill:</p>
<p>There are a few scripting languages used for embedding in applications. Lua is <p>There are a few scripting languages used for embedding in applications. Lua is
the main one. TCL used to be. There&rsquo;s also Guile, increasingly JavaScript, and the main one. TCL used to be. There&rsquo;s also Guile, increasingly JavaScript, and
some applications embed Python. I&rsquo;m an ex-game developer, so when I think some applications embed Python. I&rsquo;m an ex-game developer, so when I think
&ldquo;scripting&rdquo;, I tend to think &ldquo;game scripting&rdquo;. </p> &ldquo;scripting&rdquo;, I tend to think &ldquo;game scripting&rdquo;.</p>
<p>Lua is nice: it&rsquo;s small, simple, and fast. But&mdash;and I don&rsquo;t mean this as a <p>Lua is nice: it&rsquo;s small, simple, and fast. But&mdash;and I don&rsquo;t mean this as a
criticism&mdash;it&rsquo;s also weird if you&rsquo;re used to languages like C++ and Java. criticism&mdash;it&rsquo;s also weird if you&rsquo;re used to languages like C++ and Java.
The syntax is different. The semantics, especially the object model are The syntax is different. The semantics, especially the object model are
unusual. Anyone can get used to 1-based indexing, but things like metatables unusual. Anyone can get used to 1-based indexing, but things like metatables
really show that objects were bolted onto Lua after the fact. </p> really show that objects were bolted onto Lua after the fact.</p>
<p>I think there&rsquo;s room for a language as simple as Lua, but that feels natural to <p>I think there&rsquo;s room for a language as simple as Lua, but that feels natural to
someone with an OOP background. Wren is my attempt at that. </p> someone with an OOP background. Wren is my attempt at that.</p>
<h2>Why classes? <a href="#why-classes" name="why-classes" class="header-anchor">#</a></h2> <h2>Why classes? <a href="#why-classes" name="why-classes" class="header-anchor">#</a></h2>
<p>Thanks to JavaScript&rsquo;s popularity, lots of people are discovering prototypes <p>Thanks to JavaScript&rsquo;s popularity, lots of people are discovering prototypes
right now, and the paradigm is experiencing a popularity boom. I think right now, and the paradigm is experiencing a popularity boom. I think
prototypes are interesting, but after <a href="http://finch.stuffwithstuff.com/">several years playing with them</a>, prototypes are interesting, but after <a href="http://finch.stuffwithstuff.com/">several years playing with them</a>,
I concluded (like many people on the original Self project that invented I concluded (like many people on the original Self project that invented
prototypes) that classes are more usable. </p> prototypes) that classes are more usable.</p>
<p>Here&rsquo;s an example of that kind of object-oriented programming in Lua: </p> <p>Here&rsquo;s an example of that kind of object-oriented programming in Lua:</p>
<div class="codehilite"><pre><span class="n">Account</span> <span class="o">=</span> <span class="p">{}</span> <pre class="snippet">
<span class="n">Account</span><span class="p">.</span><span class="n">__index</span> <span class="o">=</span> <span class="n">Account</span> -- account.lua
<span class="k">function</span> <span class="nc">Account</span><span class="p">.</span><span class="nf">create</span><span class="p">(</span><span class="n">balance</span><span class="p">)</span> Account = {}
<span class="kd">local</span> <span class="n">acnt</span> <span class="o">=</span> <span class="p">{}</span> <span class="c1">-- our new object </span> Account.__index = Account
<span class="nb">setmetatable</span><span class="p">(</span><span class="n">acnt</span><span class="p">,</span><span class="n">Account</span><span class="p">)</span> <span class="c1">-- make Account handle lookup </span>
<span class="n">acnt</span><span class="p">.</span><span class="n">balance</span> <span class="o">=</span> <span class="n">balance</span> <span class="c1">-- initialize our object </span>
<span class="k">return</span> <span class="n">acnt</span>
<span class="k">end</span>
<span class="k">function</span> <span class="nf">Account</span><span class="p">:</span><span class="n">withdraw</span><span class="p">(</span><span class="n">amount</span><span class="p">)</span> function Account.create(balance)
<span class="n">self</span><span class="p">.</span><span class="n">balance</span> <span class="o">=</span> <span class="n">self</span><span class="p">.</span><span class="n">balance</span> <span class="o">-</span> <span class="n">amount</span> local acnt = {} -- our new object
<span class="k">end</span> setmetatable(acnt,Account) -- make Account handle lookup
acnt.balance = balance -- initialize our object
return acnt
end
<span class="c1">-- create and use an Account </span> function Account:withdraw(amount)
<span class="n">account</span> <span class="o">=</span> <span class="n">Account</span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span> self.balance = self.balance - amount
<span class="n">account</span><span class="p">:</span><span class="n">withdraw</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span> end
</pre></div>
-- create and use an Account
account = Account.create(1000)
account:withdraw(100)
</pre>
<p>Here&rsquo;s the same example in Wren: </p> <p>Here&rsquo;s the same example in Wren:</p>
<div class="codehilite"><pre><span class="k">class</span> <span class="vg">Account</span> <span class="p">{</span> <pre class="snippet">
<span class="k">construct</span> <span class="n">new</span><span class="p">(</span><span class="n">balance</span><span class="p">)</span> <span class="p">{</span> <span class="vi">_balance</span> <span class="o">=</span> <span class="n">balance</span> <span class="p">}</span> //account.wren
<span class="n">withdraw</span><span class="p">(</span><span class="n">amount</span><span class="p">)</span> <span class="p">{</span> <span class="vi">_balance</span> <span class="o">=</span> <span class="vi">_balance</span> <span class="o">-</span> <span class="n">amount</span> <span class="p">}</span>
<span class="p">}</span>
<span class="c1">// create and use an Account</span> class Account {
<span class="k">var</span> <span class="n">account</span> <span class="o">=</span> <span class="vg">Account</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span> construct new(balance) { _balance = balance }
<span class="n">account</span><span class="o">.</span><span class="n">withdraw</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span> withdraw(amount) { _balance = _balance - amount }
</pre></div> }
// create and use an Account
var account = Account.new(1000)
account.withdraw(100)
</pre>
<p>Classes have a reputation for complexity because most of the widely used <p>Classes have a reputation for complexity because most of the widely used
languages with them are quite complex: C++, Java, C#, Ruby, and Python. I hope languages with them are quite complex: C++, Java, C#, Ruby, and Python. I hope
to show with Wren that it is those languages that are complex, and not classes to show with Wren that it is those languages that are complex, and not classes
themselves. </p> themselves.</p>
<p>Smalltalk, the language that inspired most of those languages, is famously <p>Smalltalk, the language that inspired most of those languages, is famously
simple. Its syntax <a href="http://www.jarober.com/blog/blogView?showComments=true&amp;title=Readability+is+Key&amp;entry=3506312690">fits on an index card</a>. My aim is to keep Wren that simple. Its syntax <a href="http://www.jarober.com/blog/blogView?showComments=true&amp;title=Readability+is+Key&amp;entry=3506312690">fits on an index card</a>. My aim is to keep Wren that
minimal while still having the expressive power of <a href="classes.html">classes</a>. </p> minimal while still having the expressive power of <a href="classes.html">classes</a>.</p>
<h2>Why compile to bytecode? <a href="#why-compile-to-bytecode" name="why-compile-to-bytecode" class="header-anchor">#</a></h2> <h2>Why compile to bytecode? <a href="#why-compile-to-bytecode" name="why-compile-to-bytecode" class="header-anchor">#</a></h2>
<p>The <a href="performance.html">performance page</a> has more details, but the short answer <p>The <a href="performance.html">performance page</a> has more details, but the short answer
is that bytecode is a nice trade-off between performance and simplicity. Also: </p> is that bytecode is a nice trade-off between performance and simplicity. Also:</p>
<ul> <ul>
<li> <li>
<p>Many devices like iPhones and game consoles don&rsquo;t allow executing code <p>Many devices like iPhones and game consoles don&rsquo;t allow executing code
generated at runtime, which rules out just-in-time compilation. </p> generated at runtime, which rules out just-in-time compilation.</p>
</li> </li>
<li> <li>
<p>I think <a href="concurrency.html">fibers</a> are a really powerful tool, and implementing them is <p>I think <a href="concurrency.html">fibers</a> are a really powerful tool, and implementing them is
straightforward in a bytecode VM that doesn&rsquo;t use the native stack. </p> straightforward in a bytecode VM that doesn&rsquo;t use the native stack.</p>
</li> </li>
</ul> </ul>
<h2>Why is the VM stack-based instead of register-based? <a href="#why-is-the-vm-stack-based-instead-of-register-based" name="why-is-the-vm-stack-based-instead-of-register-based" class="header-anchor">#</a></h2> <h2>Why is the VM stack-based instead of register-based? <a href="#why-is-the-vm-stack-based-instead-of-register-based" name="why-is-the-vm-stack-based-instead-of-register-based" class="header-anchor">#</a></h2>
<p>Bytecode VMs come in two flavors. Stack-based VMs have short (usually one byte) <p>Bytecode VMs come in two flavors. Stack-based VMs have short (usually one byte)
instructions whose operands are implicitly understood to be at the top of the instructions whose operands are implicitly understood to be at the top of the
stack. That means you often have a couple of instructions to push some stuff on stack. That means you often have a couple of instructions to push some stuff on
the stack and then an instruction to do something. </p> the stack and then an instruction to do something.</p>
<p>Register-based VMs have big instructions (usually 32 bits) that contain both an <p>Register-based VMs have big instructions (usually 32 bits) that contain both an
opcode and a couple of numbers indicating where in the stack the operands can opcode and a couple of numbers indicating where in the stack the operands can
be found. This is cool because it means, that, for example, this Lua statement: </p> be found. This is cool because it means, that, for example, this Lua statement:</p>
<div class="codehilite"><pre><span class="n">a</span> <span class="o">=</span> <span class="n">b</span> <span class="o">+</span> <span class="n">c</span> <pre class="snippet">
</pre></div> a = b + c
</pre>
<p>Can be a single bytecode instruction. In a stack-based language, it would be
<p>Can be a single bytecode instruction. In a stack-based language, it would be four&mdash;push <code>b</code>, push <code>c</code>, add, store <code>a</code>. (Though note that in both cases
four&mdash;push <code>b</code>, push <code>c</code>, add, store <code>a</code>. (Though note that in both cases you&rsquo;ve got 32 total bits of code.)</p>
you&rsquo;ve got 32 total bits of code.) </p> <p>Lua used to be stack-based and switched to register-based and got a speed
<p>Lua used to be stack-based and switched to register-based and got a speed boost. Why not use registers for Wren?</p>
boost. Why not use registers for Wren? </p> <p>I&rsquo;ve implemented a <a href="http://finch.stuffwithstuff.com/">register-based VM
<p>I&rsquo;ve implemented a <a href="http://finch.stuffwithstuff.com/">register-based VM
before</a>. I think it&rsquo;s a cool model, but I before</a>. I think it&rsquo;s a cool model, but I
don&rsquo;t think it would bring much benefit for Wren. It&rsquo;s more effort to compile, don&rsquo;t think it would bring much benefit for Wren. It&rsquo;s more effort to compile,
and I&rsquo;m trying to keep Wren&rsquo;s implementation as simple as possible. </p> and I&rsquo;m trying to keep Wren&rsquo;s implementation as simple as possible.</p>
<p>In return for that complexity, you can generate fewer instructions. However, I <p>In return for that complexity, you can generate fewer instructions. However, I
don&rsquo;t think Wren would be able to take advantage of that. Wren doesn&rsquo;t don&rsquo;t think Wren would be able to take advantage of that. Wren doesn&rsquo;t
currently have any dedicated instructions for arithmetic. Operators are just currently have any dedicated instructions for arithmetic. Operators are just
regular method calls and can call user-defined procedures. </p> regular method calls and can call user-defined procedures.</p>
<p>The calling convention for methods requires all of their parameters to be at <p>The calling convention for methods requires all of their parameters to be at
the top of the caller&rsquo;s stack so that they can become bottom of the callee&rsquo;s the top of the caller&rsquo;s stack so that they can become bottom of the callee&rsquo;s
stack frame window. To call <code>+</code> in Wren, we still have to push the arguments on stack frame window. To call <code>+</code> in Wren, we still have to push the arguments on
top of the stack. Likewise, the method calling convention places the return top of the stack. Likewise, the method calling convention places the return
value where the first argument was, so we&rsquo;d have to move it back down to the value where the first argument was, so we&rsquo;d have to move it back down to the
destination slot after the call. </p> destination slot after the call.</p>
<p>It may be worth having dedicated instructions for arithmetic that special case <p>It may be worth having dedicated instructions for arithmetic that special case
the built-in types before falling back to user-defined operator methods (which the built-in types before falling back to user-defined operator methods (which
I assume is what Lua does since they added operator overloading late in the I assume is what Lua does since they added operator overloading late in the
language&rsquo;s development). If that happens, it may be possible to switch to language&rsquo;s development). If that happens, it may be possible to switch to
register-based. </p> register-based.</p>
<p>But I&rsquo;m not convinced it would be an actual performance win. A lot of details <p>But I&rsquo;m not convinced it would be an actual performance win. A lot of details
of the language affect whether a register-based VM is better. For example, of the language affect whether a register-based VM is better. For example,
assignments are statements in Lua but expressions in Wren, which would make assignments are statements in Lua but expressions in Wren, which would make
them harder to compile to efficient register-based code. </p> them harder to compile to efficient register-based code.</p>
<h2>What about your other languages? <a href="#what-about-your-other-languages" name="what-about-your-other-languages" class="header-anchor">#</a></h2> <h2>What about your other languages? <a href="#what-about-your-other-languages" name="what-about-your-other-languages" class="header-anchor">#</a></h2>
<p>This is a strange question if you don&rsquo;t happen to know <a href="http://journal.stuffwithstuff.com">who I am</a>. In the <p>This is a strange question if you don&rsquo;t happen to know <a href="http://journal.stuffwithstuff.com">who I am</a>. In the
past, I&rsquo;ve hacked on and blogged about a couple of other hobby languages like past, I&rsquo;ve hacked on and blogged about a couple of other hobby languages like
<a href="http://finch.stuffwithstuff.com/">Finch</a> and <a href="http://magpie-lang.org/">Magpie</a>. </p> <a href="http://finch.stuffwithstuff.com/">Finch</a> and <a href="http://magpie-lang.org/">Magpie</a>.</p>
<p>I started Finch to learn more about implementing an interpreter and also about <p>I started Finch to learn more about implementing an interpreter and also about
the prototype paradigm. I learned a ton about both. Critically, I learned that the prototype paradigm. I learned a ton about both. Critically, I learned that
I really prefer classes over prototypes. I started retrofitting classes into I really prefer classes over prototypes. I started retrofitting classes into
Finch but realized it was too big of a change, and thus Wren was born. </p> Finch but realized it was too big of a change, and thus Wren was born.</p>
<p>Wren is a replacement for Finch to me. I gave it a new name mainly so that I <p>Wren is a replacement for Finch to me. I gave it a new name mainly so that I
can keep Finch around in case other people want to take it and do something can keep Finch around in case other people want to take it and do something
with it. I don&rsquo;t have any intention to work on it anymore. </p> with it. I don&rsquo;t have any intention to work on it anymore.</p>
<p>Magpie is a trickier one. I really like the ideas behind Magpie. It&rsquo;s the <p>Magpie is a trickier one. I really like the ideas behind Magpie. It&rsquo;s the
general-purpose language I wish I had much of the time. I love pattern matching general-purpose language I wish I had much of the time. I love pattern matching
and multiple dispatch. I like how it integrates the event-based IO of <a href="https://github.com/joyent/libuv">libuv</a> and multiple dispatch. I like how it integrates the event-based IO of <a href="https://github.com/joyent/libuv">libuv</a>
with the simplicity of fibers. </p> with the simplicity of fibers.</p>
<p>But it&rsquo;s also a much more challenging project. As a general-purpose language, <p>But it&rsquo;s also a much more challenging project. As a general-purpose language,
there&rsquo;s a ton of library work to do before Magpie is useful for anything. It there&rsquo;s a ton of library work to do before Magpie is useful for anything. It
has some unresolved GC issues. And I&rsquo;m frankly not skilled enough right now to has some unresolved GC issues. And I&rsquo;m frankly not skilled enough right now to
implement multiple dispatch efficiently. </p> implement multiple dispatch efficiently.</p>
<p>Meanwhile, since I started working on Magpie, <a href="http://julialang.org/">Julia</a> <p>Meanwhile, since I started working on Magpie, <a href="http://julialang.org/">Julia</a>
appeared and <a href="http://opendylan.org/">Dylan</a> <em>re</em>appeared. I created Magpie appeared and <a href="http://opendylan.org/">Dylan</a> <em>re</em>appeared. I created Magpie
partially to carry the torch of multiple dispatch, but others are starting to partially to carry the torch of multiple dispatch, but others are starting to
spread that light now. </p> spread that light now.</p>
</main> </main>
</div> </div>
<footer> <footer>

677
style.css
View File

@ -1,51 +1,91 @@
:root {
--header-h: 8em;
--header: "Sanchez", helvetica, arial, sans-serif;
--subheader: "Lato", helvetica, arial, sans-serif;
--code: "Source Code Pro", Menlo, Monaco, Consolas, monospace;
--body: "Source Sans Pro", georgia, serif;
--code-bg: hsl(210, 0%, 99%);
--dark: hsl(210, 10%, 25%);
--darker: hsl(210, 20%, 10%);
--light: hsl(0, 0%, 100%);
--code-color: hsl(210, 20%, 30%);
--text: #333333;
--gray-5: whitesmoke;
--gray-10: #ebebec;
--gray-20: #d7d8da;
--gray-30: #c3c5c7;
--gray-50: #9c9fa2;
--gray-60: #888c90;
--gray-80: #60666a;
--link: hsl(200, 60%, 50%);
--link-dark: hsl(210, 60%, 20%);
--link-hover: hsl(210, 100%, 80%);
--link: hsl(200, 60%, 50%);
--module-link-dark: hsl(160, 60%, 25%);
--module-link-hover: hsl(130, 70%, 70%);
--module-link: hsl(150, 70%, 40%);
}
* { * {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
box-sizing: border-box; } box-sizing: border-box;
}
body, code, h1, h2, h3, p, pre, html { body, code, h1, h2, h3, p, pre, html {
margin: 0; margin: 0;
padding: 0; } padding: 0;
}
html { html {
height: 100%; height: 100%;
min-height: 100%; } min-height: 100%;
}
body { body {
background: white; background-color: var(--light);
color: #333333; color: var(--text);
font: 16px/25px "Source Sans Pro", georgia, serif; font: 16px/25px var(--body);
height: 100%; height: 100%;
min-height: 100%; } min-height: 100%;
}
hr { hr {
display: block; display: block;
height: 1px; height: 1px;
border: 0; border: 0;
border-top: 1px solid whitesmoke; border-top: 1px solid var(--gray-5);
margin: 1em 0; margin: 1em 0;
padding: 0; } padding: 0;
}
blockquote { blockquote {
color: #9c9fa2; color: var(--gray-50);
margin: 0; margin: 0;
max-width: 24em; max-width: 24em;
margin-left: 0.5em; } margin-left: 0.5em;
}
date { date {
color: #60666a; } color: var(--gray-80);
}
.page { .page {
margin: 0 auto; margin: 0 auto;
width: 800px; width: 800px;
min-height: calc(100% - 16.75em); } min-height: calc(100% - 16.75em);
.page:after { }
content: ""; /* Clear contents.*/
display: table; .page::after {
clear: both; } content: "";
display: table;
clear: both;
}
.main-column, main { .main-column, main {
position: relative; position: relative;
width: 560px; } width: 560px;
}
.logo { .logo {
height: 7em; height: 7em;
@ -53,339 +93,482 @@ date {
margin: auto; margin: auto;
display: block; display: block;
left: -1em; left: -1em;
margin-bottom: 2em; } margin-bottom: 2em;
}
header { header {
background: white; background: var(--light);
border-bottom: solid 1px #ebebec; } border-bottom: solid 1px var(--gray-10);
header .page { }
height: 8em; }
header h1 { header h1 {
position: absolute; position: absolute;
left: -8px; left: -8px;
top: 1.51667em; top: calc((var(--header-h) / 3) - 1.15em);
padding: 0; padding: 0;
font: 400 48px "Sanchez", helvetica, arial, sans-serif; font-weight: 400;
letter-spacing: 2px; } font-size: 48px;
header h2 { font-family: "Sanchez", helvetica, arial, sans-serif;
position: absolute; letter-spacing: 2px;
left: 0; }
top: 8.5em;
padding: 0; header h2 {
font: 500 13px "Lato", helvetica, arial, sans-serif; position: absolute;
text-transform: uppercase; left: 0;
letter-spacing: 2px; top: calc(var(--header-h) + 0.5em);
color: #9c9fa2; } padding: 0;
header a { font: 500 13px var(--subheader);
color: #60666a; } text-transform: uppercase;
header a:hover { letter-spacing: 2px;
color: #99ccff; color: var(--gray-50);
/*text-shadow: 0 0 6px $link-glow;*/ } }
header a {
color: var(--gray-80);
}
header a:hover {
color: var(--link-hover);
}
header .page {
height: var(--header-h);
}
nav { nav {
float: right; float: right;
width: 160px; width: 160px;
margin-top: 2em; } margin-top: 2em;
nav h2 { }
color: #60666a;
font: 500 13px "Lato", helvetica, arial, sans-serif; nav h2 {
text-transform: uppercase; color: var(--gray-80);
letter-spacing: 2px; font: 500 13px var(--subheader);
margin: 0; } text-transform: uppercase;
nav ul { letter-spacing: 2px;
padding: 0; margin: 0;
margin: 6px 0 20px 0; } }
nav li {
font: 17px "Source Sans Pro", georgia, serif; nav ul {
color: #c3c5c7; padding: 0;
list-style-type: none; margin: 6px 0 20px 0;
margin: 0 0 4px 0; } }
nav li {
font: 17px var(--body);
color: var(--gray-30);
list-style-type: none;
margin: 0 0 4px 0;
}
nav.small { nav.small {
/*Only show the mobile navigation on small screens.*/
display: none; display: none;
float: none; float: none;
width: 100%; width: 100%;
padding: 16px 0 0 0; padding: 16px 0 0 0;
margin: 0; margin: 0;
background: #ebebec; } background: var(--gray-10);
nav.small table {
width: 100%; }
border-collapse: separate;
border-spacing: 16px 0; } nav.small div:not(table) { padding-left: 1em; }
nav.small h2 {
margin: 16px 0 0 0; nav.small table {
padding: 0 0 1px 0; width: 100%;
border-bottom: solid 1px #d7d8da; }
border-collapse: separate;
border-spacing: 16px 0;
}
nav.small h2 {
margin: 16px 0 0 0;
padding: 0 0 1px 0;
border-bottom: solid 1px var(--gray-20);
}
h1 { h1 {
padding-top: 30px; padding-top: 30px;
font: 500 36px/60px "Sanchez", helvetica, arial, sans-serif; font: 500 36px/60px var(--header);
color: #3399cc; } color: var(--link);
}
h2 { h2 {
font: 500 24px "Sanchez", helvetica, arial, sans-serif; font-weight: 500;
font-size: 24px;
font-family: var(--header);
margin: 24px 0 0 0; margin: 24px 0 0 0;
color: #3399cc; } color: var(--link);
h2 code { }
border: none;
background: inherit; h2 code {
color: inherit; border: none;
font-size: 24px; } background: inherit;
color: inherit;
font-size: 24px;
}
h3 { h3 {
font: 20px "Source Sans Pro", georgia, serif; font: 20px var(--body);
margin: 24px 0 0 0; margin: 24px 0 0 0;
color: #3399cc; } color: var(--link);
h3 code { }
border: none;
background: inherit; h3 code {
color: inherit; border: none;
font-size: 20px; } background: inherit;
color: inherit;
font-size: 20px;
}
a { a {
color: #3399cc; color: var(--link);
text-decoration: none; text-decoration: none;
transition: color 0.2s, text-shadow 0.2s; transition: color 0.2s, text-shadow 0.2s;
outline: none; } outline: none;
cursor: pointer;
}
main { main {
margin-top: 2em; margin-top: 2em;
float: left; } float: left;
main .intro { }
border-bottom: solid 1px #ebebec;
margin-bottom: -0.5em; } main .intro {
main h2 { border-bottom: solid 1px var(--gray-10);
display: block; margin-bottom: -0.5em;
position: relative; }
max-width: 16em; }
main h2 {
display: block;
position: relative;
max-width: 16em;
}
a:hover { a:hover {
color: #143352; } color: var(--link-dark);
}
.header-anchor { .header-anchor {
color: white; } color: var(--light);
}
h2:hover > .header-anchor, h2:hover > .header-anchor,
h3:hover > .header-anchor { h3:hover > .header-anchor {
color: #ebebec; } color: var(--gray-10);
}
h2:hover > .header-anchor:hover, h2:hover > .header-anchor:hover,
h3:hover > .header-anchor:hover { h3:hover > .header-anchor:hover {
color: #143352; } color: var(--link-dark);
}
p { p {
margin: 10px 0; } margin: 10px 0;
}
p + p { p + p {
margin-top: 20px; } margin-top: 20px;
}
code, pre { code, pre {
color: #3d4c5c; background-color: var(--code-bg) !important;
font: 13px "Source Code Pro", Menlo, Monaco, Consolas, monospace; color: var(--code-color) !important;
background: #fcfcfc; font-family: var(--code) !important;
border-radius: 2px; font-size: 13px !important;
border: solid 1px #dae2e7; } }
code { code {
padding: 1px 2px; white-space: pre;
white-space: nowrap; } }
pre { pre {
margin: 10px 0; border-radius: 2px;
line-height: 20px; border: solid 1px hsl(200, 20%, 88%);
padding: 10px;
overflow: auto; overflow: auto;
white-space: pre-wrap; } white-space: pre-wrap;
padding: 1em;
}
footer { footer {
margin-top: 4em; margin-top: 4em;
padding: 20px 0 40px 0; padding: 20px 0 40px 0;
font: 14px "Source Sans Pro", georgia, serif; font: 14px var(--body);
background: #394046; background: var(--dark);
color: #d7d8da; color: var(--gray-20);
border-top: solid 1px #14191f; border-top: solid 1px var(--darker);
text-align: center; text-align: center;
text-shadow: 0 1px 1px #14191f; } text-shadow: 0 1px 1px var(--darker);
footer a { }
color: #99ccff; }
footer a:hover { footer a {
color: #3399cc; } color: var(--link-hover);
}
footer a:hover {
color: var(--link);
}
.right { .right {
float: right; }
.codehilite pre span.c1, .codehilite pre span.cm {
color: #89929c; }
.codehilite pre span.k, .codehilite pre span.kd, .codehilite pre span.kc, .codehilite pre span.kt, .codehilite pre span.nb {
color: #269dd9; }
.codehilite pre span.vg {
color: #1b9898; }
.codehilite pre span.vi {
color: #59a112; }
.codehilite pre span.vc {
color: #29a33d; }
.codehilite pre span.nf {
color: #29a3a3; }
.codehilite pre span.m, .codehilite pre span.mi, .codehilite pre span.mf {
color: #80b34d; }
.codehilite pre span.s, .codehilite pre span.s2 {
color: #c2850a; }
.codehilite pre span.se {
color: #dab80b; }
.codehilite pre span.si {
color: #c2a30a;
background: #fef6e7; }
.codehilite pre span.o {
color: #4d90b3; }
.codehilite pre span.p {
color: #636f7c; }
.codehilite pre span.cp {
color: #9970c2; }
.codehilite pre span.output {
float: right; float: right;
color: #39ac73; } }
.codehilite pre span.output::before, .codehilite pre span.output::after {
color: #b3e6cc; }
.codehilite pre span.output::before {
content: "\276c "; }
.codehilite pre span.output::after {
content: ' \276d'; }
.codehilite pre span.error {
float: right;
color: #cc6677; }
.codehilite pre span.error::before {
color: #df9faa;
content: "Error: "; }
/* Have a different primary color for the module docs.*/
body.module header a { body.module header a {
color: #60666a; } color: var(--gray-80);
}
body.module header a:hover { body.module header a:hover {
color: #7de88f; } color: var(--module-link-hover);
}
body.module a { body.module a {
color: #1fad66; } color: var(--module-link);
}
body.module a:hover { body.module a:hover {
color: #19664d; } color: var(--module-link-dark);
}
body.module .header-anchor { body.module .header-anchor {
color: white; } color: var(--light);
body.module main h1, body.module main h2, body.module main h3 { }
color: #1fad66; }
body.module footer a {
color: var(--module-link-hover);
}
body.module footer a:hover {
color: var(--module-link);
}
body.module main h1 { color: var(--module-link); }
body.module main h2 { color: var(--module-link); }
body.module main h3 { color: var(--module-link); }
body.module main h2:hover > .header-anchor:hover, body.module main h2:hover > .header-anchor:hover,
body.module main h3:hover > .header-anchor:hover { body.module main h3:hover > .header-anchor:hover {
color: #19664d; } color: var(--module-link-dark);
body.module footer a { }
color: #7de88f; }
body.module footer a:hover { /* Try related stuff */
color: #1fad66; }
.buttons {
z-index: 2;
right: 0;
display: block;
position: absolute;
font-size: 1.3em;
letter-spacing: 0.05em;
margin-top: -1.25em;
}
.button {
margin-right: 0.25em;
display: inline-block;
text-align: right;
}
#examples {
margin-bottom: 1em;
}
#try-area {
margin-bottom: 1em;
}
#try-area p {
margin-left: 0.2em;
color: var(--gray-50);
font-size: 0.9em;
margin-bottom: -0.1em;
}
#try-output {
scrollbar-width: thin;
white-space: pre;
overflow-x: auto;
font-family: var(--code);
font-size: 1em;
line-height: 1.25em;
}
#try-result {
display: block;
margin-top: 1.4em;
position: absolute;
right: 0;
}
#try-result.error {
color: #c00;
font-weight: bold;
}
span.token.error {
color: #c00;
}
.codejar-linenumbers {
background-color: #f9f9f9 !important;
border-left: solid 1px hsl(200, 20%, 88%);
border-top: solid 1px hsl(200, 20%, 88%);
border-bottom: solid 1px hsl(200, 20%, 88%);
color: #d9d9d9 !important;
mix-blend-mode: normal !important;
width: 2.5em !important;
text-align: right !important;
padding-left: 0 !important;
padding-right: 0.5em !important;
}
#try-code {
scrollbar-width: thin;
border-radius: 0.01em;
border: solid 1px hsl(200, 20%, 88%);
font-family: 'Source Code Pro', monospace;
font-size: 14px;
font-weight: 400;
height: auto;
letter-spacing: normal;
line-height: 1.5em;
padding: 1em;
tab-size: 2;
}
table { table {
width: 100%; width: 100%;
border-collapse: collapse; } border-collapse: collapse;
table tr { }
margin: 0;
padding: 0;
vertical-align: top; }
table th, table td {
font-size: 14px;
line-height: 20px;
text-align: left; }
tr {
margin: 0;
padding: 0;
vertical-align: top;
}
th, td {
font-size: 14px;
line-height: 20px;
text-align: left;
}
/* Bar charts on the performance page.*/
table.chart { table.chart {
margin: 4px 0 0 0; margin: 4px 0 0 0;
padding: 5px 0 5px 25px; } padding: 5px 0 5px 25px;
table.chart td, table.chart th { }
line-height: 14px;
margin: 0;
padding: 1px 0; }
table.chart th {
font-size: 14px;
width: 100px; }
table.chart .chart-bar {
display: inline-block;
font: 13px "Source Sans Pro", georgia, serif;
color: white;
background: #3399cc;
border-bottom: solid 1px #143352;
text-align: right;
border-radius: 2px; }
table.chart .chart-bar.wren {
background: #1d5176;
border-bottom: solid 1px #143352; }
table.chart td, th {
line-height: 14px;
margin: 0;
padding: 1px 0;
}
table.chart th {
font-size: 14px;
width: 100px;
}
table.chart .chart-bar {
display: inline-block;
font: 13px var(--body);
color: var(--light);
background: var(--link);
border-bottom: solid 1px var(--link-dark);
text-align: right;
border-radius: 2px;
}
table.chart .chart-bar.wren {
background: #1d5176;
border-bottom: solid 1px var(--link-dark);
}
/* Precedence table on expressions page.*/
table.precedence th { table.precedence th {
font: 500 11px "Lato", helvetica, arial, sans-serif; font: 500 11px var(--subheader);
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 1px; letter-spacing: 1px;
color: #888c90; color: var(--gray-60);
padding: 6px 0; padding: 6px 0;
border-bottom: solid 1px #ebebec; } border-bottom: solid 1px var(--gray-10);
}
table.precedence td { table.precedence td {
padding: 3px 0; padding: 3px 0;
border-bottom: solid 1px #ebebec; } border-bottom: solid 1px var(--gray-10);
}
@media only screen and (max-width: 839px) { @media only screen and (max-width: 839px) {
.page { /* 36 pixel columns.*/
width: 720px; } .page { width: 720px; }
nav { width: 144px; }
.main-column, main { width: 504px; }
}
nav {
width: 144px; }
.main-column, main {
width: 504px; } }
@media only screen and (max-width: 759px) { @media only screen and (max-width: 759px) {
.page { /* 32 pixel columns.*/
width: 640px; } .page { width: 640px; }
nav { width: 128px; }
.main-column, main { width: 448px; }
}
nav {
width: 128px; }
.main-column, main {
width: 448px; } }
@media only screen and (max-width: 679px) { @media only screen and (max-width: 679px) {
.page { /* 28 pixel columns.*/
width: 560px; } .page { width: 560px; }
nav { width: 112px; }
nav { .main-column, main { width: 392px; }
width: 112px; }
.main-column, main {
width: 392px; }
header h2 { header h2 {
font-size: 12px; font-size: 12px;
letter-spacing: 1px; } } letter-spacing: 1px;
}
}
@media only screen and (max-width: 639px) { @media only screen and (max-width: 639px) {
.page { .page { width: 100%; }
width: 100%; } .buttons { margin-right: 1em; }
#try-result { margin-right: 1.5em; }
nav.big { /* Switch to the mobile navigation.*/
display: none; } nav.big { display: none; }
nav.small { display: block; }
nav.small { nav.small div:not(table) { padding-left: 1em; }
display: block; }
.main-column, main { .main-column, main {
padding: 0 20px; padding: 0 20px;
width: 100%; } width: 100%;
}
header h1 { header h1 {
position: relative; position: relative;
top: 10px; top: 10px;
left: 0; left: 0;
text-align: center; } text-align: center;
}
header h2 { header h2 {
position: relative; position: relative;
top: 0; top: 0;
right: 0; right: 0;
text-align: center; text-align: center;
font-size: 13px; font-size: 13px;
letter-spacing: 2px; } letter-spacing: 2px;
}
main { main {
float: none; float: none;
width: 100%; } width: 100%;
}
pre { pre {
font-size: 13px; } font-size: 13px;
}
footer { footer {
padding: 20px 20px 40px 20px; } } padding: 20px 20px 40px 20px;
}
}

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Syntax &ndash; Wren</title> <title>Syntax &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,256 +110,256 @@
</nav> </nav>
<main> <main>
<h2>Syntax</h2> <h2>Syntax</h2>
<p>Wren&rsquo;s syntax is designed to be familiar to people coming from C-like languages <p>Wren&rsquo;s syntax is designed to be familiar to people coming from C-like languages
while being a bit simpler and more streamlined. </p> while being a bit simpler and more streamlined.</p>
<p>Scripts are stored in plain text files with a <code>.wren</code> file extension. Wren does <p>Scripts are stored in plain text files with a <code>.wren</code> file extension. Wren does
not compile ahead of time: programs are run directly from source, from top to not compile ahead of time: programs are run directly from source, from top to
bottom like a typical scripting language. (Internally, programs are compiled to bottom like a typical scripting language. (Internally, programs are compiled to
bytecode for <a href="performance.html">efficiency</a>, but that&rsquo;s an implementation detail.) </p> bytecode for <a href="performance.html">efficiency</a>, but that&rsquo;s an implementation detail.)</p>
<h2>Comments <a href="#comments" name="comments" class="header-anchor">#</a></h2> <h2>Comments <a href="#comments" name="comments" class="header-anchor">#</a></h2>
<p>Line comments start with <code>//</code> and end at the end of the line:</p> <p>Line comments start with <code>//</code> and end at the end of the line:</p>
<div class="codehilite"><pre><span class="c1">// This is a comment.</span> <pre class="snippet">
</pre></div> // This is a comment.
</pre>
<p>Block comments start with <code>/*</code> and end with <code>*/</code>. They can span multiple lines:</p>
<pre class="snippet">
/* This
is
a
multi-line
comment. */
</pre>
<p>Block comments start with <code>/*</code> and end with <code>*/</code>. They can span multiple lines: </p> <p>Unlike C, block comments can nest in Wren:</p>
<div class="codehilite"><pre><span class="cm">/* This </span> <pre class="snippet">
<span class="cm"> is </span> /* This is /* a nested */ comment. */
<span class="cm"> a </span> </pre>
<span class="cm"> multi-line </span>
<span class="cm"> comment. */</span>
</pre></div>
<p>This is handy because it lets you easily comment out an entire block of code,
<p>Unlike C, block comments can nest in Wren: </p> even if the code already contains block comments.</p>
<div class="codehilite"><pre><span class="cm">/* This is /* a nested */ comment. */</span>
</pre></div>
<p>This is handy because it lets you easily comment out an entire block of code,
even if the code already contains block comments. </p>
<h2>Reserved words <a href="#reserved-words" name="reserved-words" class="header-anchor">#</a></h2> <h2>Reserved words <a href="#reserved-words" name="reserved-words" class="header-anchor">#</a></h2>
<p>One way to get a quick feel for a language&rsquo;s style is to see what words it <p>One way to get a quick feel for a language&rsquo;s style is to see what words it
reserves. Here&rsquo;s what Wren has: </p> reserves. Here&rsquo;s what Wren has:</p>
<div class="codehilite"><pre><span class="k">break</span> <span class="k">class</span> <span class="k">construct</span> <span class="k">else</span> <span class="kc">false</span> <span class="k">for</span> <span class="k">foreign</span> <span class="k">if</span> <span class="k">import</span> <pre class="snippet">
<span class="k">in</span> <span class="k">is</span> <span class="kc">null</span> <span class="k">return</span> <span class="k">static</span> <span class="k">super</span> <span class="nb">this</span> <span class="kc">true</span> <span class="k">var</span> <span class="k">while</span> break class construct else false for foreign if import
</pre></div> in is null return static super this true var while
</pre>
<h2>Identifiers <a href="#identifiers" name="identifiers" class="header-anchor">#</a></h2> <h2>Identifiers <a href="#identifiers" name="identifiers" class="header-anchor">#</a></h2>
<p>Naming rules are similar to other programming languages. Identifiers start with <p>Naming rules are similar to other programming languages. Identifiers start with
a letter or underscore and may contain letters, digits, and underscores. Case a letter or underscore and may contain letters, digits, and underscores. Case
is sensitive. </p> is sensitive.</p>
<div class="codehilite"><pre><span class="n">hi</span> <pre class="snippet">
<span class="n">camelCase</span> hi
<span class="vg">PascalCase</span> camelCase
<span class="vi">_under_score</span> PascalCase
<span class="n">abc123</span> _under_score
<span class="vg">ALL_CAPS</span> abc123
</pre></div> ALL_CAPS
</pre>
<p>Identifiers that start with underscore (<code>_</code>) are special in Wren. They are used
<p>Identifiers that start with underscore (<code>_</code>) are special in Wren. They are used to indicate <a href="classes.html#fields">fields</a> in classes.</p>
to indicate <a href="classes.html#fields">fields</a> in classes. </p>
<h2>Newlines <a href="#newlines" name="newlines" class="header-anchor">#</a></h2> <h2>Newlines <a href="#newlines" name="newlines" class="header-anchor">#</a></h2>
<p>Newlines (<code>\n</code>) are meaningful in Wren. They are used to separate statements: </p> <p>Newlines (<code>\n</code>) are meaningful in Wren. They are used to separate statements:</p>
<div class="codehilite"><pre><span class="c1">// Two statements:</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;hi&quot;</span><span class="p">)</span> <span class="c1">// Newline.</span> // Two statements:
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;bye&quot;</span><span class="p">)</span> System.print("hi") // Newline.
</pre></div> System.print("bye")
</pre>
<p>Sometimes, though, a statement doesn&rsquo;t fit on a single line and jamming a
newline in the middle would trip it up. To handle that, Wren has a very simple
rule: It ignores a newline following any token that can&rsquo;t end a statement.</p>
<pre class="snippet">
System.print( // Newline here is ignored.
"hi")
</pre>
<p>Sometimes, though, a statement doesn&rsquo;t fit on a single line and jamming a <p>In practice, this means you can put each statement on its own line and wrap
newline in the middle would trip it up. To handle that, Wren has a very simple them across lines as needed without too much trouble.</p>
rule: It ignores a newline following any token that can&rsquo;t end a statement. </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span> <span class="c1">// Newline here is ignored.</span>
<span class="s">&quot;hi&quot;</span><span class="p">)</span>
</pre></div>
<p>In practice, this means you can put each statement on its own line and wrap
them across lines as needed without too much trouble. </p>
<h2>Blocks <a href="#blocks" name="blocks" class="header-anchor">#</a></h2> <h2>Blocks <a href="#blocks" name="blocks" class="header-anchor">#</a></h2>
<p>Wren uses curly braces to define <em>blocks</em>. You can use a block anywhere a <p>Wren uses curly braces to define <em>blocks</em>. You can use a block anywhere a
statement is allowed, like in <a href="control-flow.html">control flow</a> statements. statement is allowed, like in <a href="control-flow.html">control flow</a> statements.
<a href="classes.html#methods">Method</a> and <a href="functions.html">function</a> bodies are also <a href="classes.html#methods">Method</a> and <a href="functions.html">function</a> bodies are also
blocks. For example, here we have a block for the then case, and a single blocks. For example, here we have a block for the then case, and a single
statement for the else: </p> statement for the else:</p>
<div class="codehilite"><pre><span class="k">if</span> <span class="p">(</span><span class="n">happy</span> <span class="o">&amp;&amp;</span> <span class="n">knowIt</span><span class="p">)</span> <span class="p">{</span> <pre class="snippet">
<span class="n">hands</span><span class="o">.</span><span class="n">clap</span><span class="p">()</span> if (happy && knowIt) {
<span class="p">}</span> <span class="k">else</span> <span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;sad&quot;</span><span class="p">)</span> hands.clap()
</pre></div> } else System.print("sad")
</pre>
<p>Blocks have two similar but not identical forms. Typically, blocks contain a
series of statements like:</p>
<pre class="snippet">
{
System.print("one")
System.print("two")
System.print("three")
}
</pre>
<p>Blocks have two similar but not identical forms. Typically, blocks contain a <p>Blocks of this form when used for method and function bodies automatically
series of statements like: </p> return <code>null</code> after the block has completed. If you want to return a different
<div class="codehilite"><pre><span class="p">{</span> value, you need an explicit <code>return</code> statement.</p>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;one&quot;</span><span class="p">)</span> <p>However, it&rsquo;s pretty common to have a method or function that just evaluates and
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;two&quot;</span><span class="p">)</span> returns the result of a single expression. Some other languages use <code>=&gt;</code> to
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;three&quot;</span><span class="p">)</span> define these. Wren uses:</p>
<span class="p">}</span> <pre class="snippet">
</pre></div> { "single expression" }
</pre>
<p>If there is no newline after the <code>{</code> (or after the parameter list in a
<a href="functions.html">function</a>), then the block may only contain a single
expression, and it automatically returns the result of it. It&rsquo;s exactly the same
as doing:</p>
<pre class="snippet">
{
return "single expression"
}
</pre>
<p>Blocks of this form when used for method and function bodies automatically <p>Statements are not allowed in this form (since they don&rsquo;t produce values), which
return <code>null</code> after the block has completed. If you want to return a different means nothing starting with <code>class</code>, <code>for</code>, <code>if</code>, <code>import</code>, <code>return</code>,
value, you need an explicit <code>return</code> statement. </p> <code>var</code>, or <code>while</code>. If you want a block that contains a single statement,
<p>However, it&rsquo;s pretty common to have a method or function that just evaluates and put a newline in there:</p>
returns the result of a single expression. Some other languages use <code>=&gt;</code> to <pre class="snippet">
define these. Wren uses: </p> {
<div class="codehilite"><pre><span class="p">{</span> <span class="s">&quot;single expression&quot;</span> <span class="p">}</span> if (happy) {
</pre></div> System.print("I'm feelin' it!")
}
}
<p>If there is no newline after the <code>{</code> (or after the parameter list in a </pre>
<a href="functions.html">function</a>), then the block may only contain a single
expression, and it automatically returns the result of it. It&rsquo;s exactly the same
as doing: </p>
<div class="codehilite"><pre><span class="p">{</span>
<span class="k">return</span> <span class="s">&quot;single expression&quot;</span>
<span class="p">}</span>
</pre></div>
<p>Statements are not allowed in this form (since they don&rsquo;t produce values), which
means nothing starting with <code>class</code>, <code>for</code>, <code>if</code>, <code>import</code>, <code>return</code>,
<code>var</code>, or <code>while</code>. If you want a block that contains a single statement,
put a newline in there: </p>
<div class="codehilite"><pre><span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="n">happy</span><span class="p">)</span> <span class="p">{</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;I&#39;m feelin&#39; it!&quot;</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
</pre></div>
<p>Using an initial newline after the <code>{</code> does feel a little weird or magical, but
newlines are already significant in Wren, so it&rsquo;s not totally crazy. The nice
thing about this syntax as opposed to something like <code>=&gt;</code> is that the <em>end</em> of
the block has an explicit delimiter. That helps when chaining: </p>
<div class="codehilite"><pre><span class="n">numbers</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">*</span> <span class="mi">2</span> <span class="p">}</span><span class="o">.</span><span class="n">where</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">&lt;</span> <span class="mi">100</span> <span class="p">}</span>
</pre></div>
<p>Using an initial newline after the <code>{</code> does feel a little weird or magical, but
newlines are already significant in Wren, so it&rsquo;s not totally crazy. The nice
thing about this syntax as opposed to something like <code>=&gt;</code> is that the <em>end</em> of
the block has an explicit delimiter. That helps when chaining:</p>
<pre class="snippet">
numbers.map {|n| n * 2 }.where {|n| n < 100 }
</pre>
<h2>Precedence and Associativity <a href="#precedence-and-associativity" name="precedence-and-associativity" class="header-anchor">#</a></h2> <h2>Precedence and Associativity <a href="#precedence-and-associativity" name="precedence-and-associativity" class="header-anchor">#</a></h2>
<p>We&rsquo;ll talk about Wren&rsquo;s different expression forms and what they mean in the <p>We&rsquo;ll talk about Wren&rsquo;s different expression forms and what they mean in the
next few pages. But if you want to see how they interact with each other next few pages. But if you want to see how they interact with each other
grammatically, here&rsquo;s the whole table. </p> grammatically, here&rsquo;s the whole table.</p>
<p>It shows which expressions have higher <em>precedence</em>&mdash;which ones bind more <p>It shows which expressions have higher <em>precedence</em>&mdash;which ones bind more
tightly than others&mdash;and their <em>associativity</em>&mdash;how a series of the tightly than others&mdash;and their <em>associativity</em>&mdash;how a series of the
same kind of expression is ordered. Wren mostly follows C, except that it fixes same kind of expression is ordered. Wren mostly follows C, except that it fixes
<a href="http://www.lysator.liu.se/c/dmr-on-or.html">the bitwise operator mistake</a>. The full precedence table, from <a href="http://www.lysator.liu.se/c/dmr-on-or.html">the bitwise operator mistake</a>. The full precedence table, from
tightest to loosest, is: </p> tightest to loosest, is:</p>
<table class="precedence"> <table class="precedence">
<tbody> <tbody>
<tr> <tr>
<th>Prec</th> <th>Prec</th>
<th>Operator</th> <th>Operator</th>
<th>Description</th> <th>Description</th>
<th>Associates</th> <th>Associates</th>
</tr> </tr>
<tr> <tr>
<td>1</td> <td>1</td>
<td><code>()</code> <code>[]</code> <code>.</code></td> <td><code>()</code> <code>[]</code> <code>.</code></td>
<td>Grouping, <a href="method-calls.html">Subscript, Method call</a></td> <td>Grouping, <a href="method-calls.html">Subscript, Method call</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>2</td> <td>2</td>
<td><code>-</code> <code>!</code> <code>~</code></td> <td><code>-</code> <code>!</code> <code>~</code></td>
<td><a href="method-calls.html#operators">Negate, Not, Complement</a></td> <td><a href="method-calls.html#operators">Negate, Not, Complement</a></td>
<td>Right</td> <td>Right</td>
</tr> </tr>
<tr> <tr>
<td>3</td> <td>3</td>
<td><code>*</code> <code>/</code> <code>%</code></td> <td><code>*</code> <code>/</code> <code>%</code></td>
<td><a href="method-calls.html#operators">Multiply, Divide, Modulo</a></td> <td><a href="method-calls.html#operators">Multiply, Divide, Modulo</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>4</td> <td>4</td>
<td><code>+</code> <code>-</code></td> <td><code>+</code> <code>-</code></td>
<td><a href="method-calls.html#operators">Add, Subtract</a></td> <td><a href="method-calls.html#operators">Add, Subtract</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>5</td> <td>5</td>
<td><code>..</code> <code>...</code></td> <td><code>..</code> <code>...</code></td>
<td><a href="method-calls.html#operators">Inclusive range, Exclusive range</a></td> <td><a href="method-calls.html#operators">Inclusive range, Exclusive range</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>6</td> <td>6</td>
<td><code>&lt;&lt;</code> <code>&gt;&gt;</code></td> <td><code>&lt;&lt;</code> <code>&gt;&gt;</code></td>
<td><a href="method-calls.html#operators">Left shift, Right shift</a></td> <td><a href="method-calls.html#operators">Left shift, Right shift</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>7</td> <td>7</td>
<td><code>&amp;</code></td> <td><code>&amp;</code></td>
<td><a href="method-calls.html#operators">Bitwise and</a></td> <td><a href="method-calls.html#operators">Bitwise and</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>8</td> <td>8</td>
<td><code>^</code></td> <td><code>^</code></td>
<td><a href="method-calls.html#operators">Bitwise xor</a></td> <td><a href="method-calls.html#operators">Bitwise xor</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>9</td> <td>9</td>
<td><code>|</code></td> <td><code>|</code></td>
<td><a href="method-calls.html#operators">Bitwise or</a></td> <td><a href="method-calls.html#operators">Bitwise or</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>10</td> <td>10</td>
<td><code>&lt;</code> <code>&lt;=</code> <code>&gt;</code> <code>&gt;=</code></td> <td><code>&lt;</code> <code>&lt;=</code> <code>&gt;</code> <code>&gt;=</code></td>
<td><a href="method-calls.html#operators">Comparison</a></td> <td><a href="method-calls.html#operators">Comparison</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>11</td> <td>11</td>
<td><code>is</code></td> <td><code>is</code></td>
<td><a href="method-calls.html#operators">Type test</a></td> <td><a href="method-calls.html#operators">Type test</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>12</td> <td>12</td>
<td><code>==</code> <code>!=</code></td> <td><code>==</code> <code>!=</code></td>
<td><a href="method-calls.html#operators">Equals, Not equal</a></td> <td><a href="method-calls.html#operators">Equals, Not equal</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>13</td> <td>13</td>
<td><code>&amp;&amp;</code></td> <td><code>&amp;&amp;</code></td>
<td><a href="control-flow.html#logical-operators">Logical and</a></td> <td><a href="control-flow.html#logical-operators">Logical and</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>14</td> <td>14</td>
<td><code>||</code></td> <td><code>||</code></td>
<td><a href="control-flow.html#logical-operators">Logical or</a></td> <td><a href="control-flow.html#logical-operators">Logical or</a></td>
<td>Left</td> <td>Left</td>
</tr> </tr>
<tr> <tr>
<td>15</td> <td>15</td>
<td><code>?:</code></td> <td><code>?:</code></td>
<td><a href="control-flow.html#the-conditional-operator-">Conditional</a></td> <td><a href="control-flow.html#the-conditional-operator-">Conditional</a></td>
<td>Right</td> <td>Right</td>
</tr> </tr>
<tr> <tr>
<td>16</td> <td>16</td>
<td><code>=</code></td> <td><code>=</code></td>
<td><a href="variables.html#assignment">Assignment</a>, <a href="method-calls.html#setters">Setter</a></td> <td><a href="variables.html#assignment">Assignment</a>, <a href="method-calls.html#setters">Setter</a></td>
<td>Right</td> <td>Right</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<p><br><hr> <p><br><hr>
<a class="right" href="values.html">Values &rarr;</a> <a class="right" href="values.html">Values &rarr;</a>
<a href="getting-started.html">&larr; Getting Started</a> </p> <a href="getting-started.html">&larr; Getting Started</a></p>
</main> </main>
</div> </div>
<footer> <footer>

175
try/index.html Normal file
View File

@ -0,0 +1,175 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Try Wren &ndash; Wren</title>
<script type="application/javascript" src="../prism.js" data-manual></script>
<script type="application/javascript" src="../codejar.js"></script>
<script type="application/javascript" src="../codejar-linenumbers.js"></script>
<script type="application/javascript" src="../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../prism.css" />
<link rel="stylesheet" type="text/css" href="../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top">
<header>
<div class="page">
<div class="main-column">
<h1><a href="../">wren</a></h1>
<h2>a classy little scripting language</h2>
</div>
</div>
</header>
<div class="page">
<nav class="big">
<a href="../"><img src="../wren.svg" class="logo"></a>
<ul>
<li><a href="../getting-started.html">Getting Started</a></li>
<li><a href="../contributing.html">Contributing</a></li>
<li><a href="../blog">Blog</a></li>
<li><a href="./">Try it!</a></li>
</ul>
<section>
<h2>guides</h2>
<ul>
<li><a href="../syntax.html">Syntax</a></li>
<li><a href="../values.html">Values</a></li>
<li><a href="../lists.html">Lists</a></li>
<li><a href="../maps.html">Maps</a></li>
<li><a href="../method-calls.html">Method Calls</a></li>
<li><a href="../control-flow.html">Control Flow</a></li>
<li><a href="../variables.html">Variables</a></li>
<li><a href="../functions.html">Functions</a></li>
<li><a href="../classes.html">Classes</a></li>
<li><a href="../concurrency.html">Concurrency</a></li>
<li><a href="../error-handling.html">Error Handling</a></li>
<li><a href="../modularity.html">Modularity</a></li>
</ul>
</section>
<section>
<h2>API docs</h2>
<ul>
<li><a href="../modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="../cli">Wren CLI</a></li>
<li><a href="../embedding">Embedding</a></li>
<li><a href="../performance.html">Performance</a></li>
<li><a href="../qa.html">Q &amp; A</a></li>
</ul>
</section>
</nav>
<nav class="small">
<table>
<tr>
<div><a href="../getting-started.html">Getting Started</a></div>
<div><a href="../contributing.html">Contributing</a></div>
<div><a href="../blog">Blog</a></div>
<div><a href="../try">Try it!</a></div>
</tr>
<tr>
<td colspan="2"><h2>guides</h2></td>
<td><h2>reference</h2></td>
</tr>
<tr>
<td>
<ul>
<li><a href="../syntax.html">Syntax</a></li>
<li><a href="../values.html">Values</a></li>
<li><a href="../lists.html">Lists</a></li>
<li><a href="../maps.html">Maps</a></li>
<li><a href="../method-calls.html">Method Calls</a></li>
<li><a href="../control-flow.html">Control Flow</a></li>
</ul>
</td>
<td>
<ul>
<li><a href="../variables.html">Variables</a></li>
<li><a href="../functions.html">Functions</a></li>
<li><a href="../classes.html">Classes</a></li>
<li><a href="../concurrency.html">Concurrency</a></li>
<li><a href="../error-handling.html">Error Handling</a></li>
<li><a href="../modularity.html">Modularity</a></li>
</ul>
</td>
<td>
<ul>
<li><a href="../modules">API/Modules</a></li>
<li><a href="../embedding">Embedding</a></li>
<li><a href="../performance.html">Performance</a></li>
<li><a href="../qa.html">Q &amp; A</a></li>
</ul>
</td>
</tr>
</table>
</nav>
<main>
<h2>Try Wren</h2>
<hr />
<div id="examples">
examples: &nbsp;
<a class="button" id="try-hello">hello</a>
<a class="button" id="try-loop">loop</a>
<a class="button" id="try-fractal">fractal</a>
</div>
<div id="try-area">
<p>enter code below</p>
<div class="buttons">
<a class="button" id="try-run">run</a>
</div>
<div id="try-code" class="language-lua">System.print("hello wren")</div>
<p id="try-result">no errors</p>
<p>code output</p>
<pre><div id="try-output">...</div></pre>
</div>
</main>
</div>
<footer>
<div class="page">
<div class="main-column">
<p>Wren lives
<a href="https://github.com/wren-lang/wren">on GitHub</a>
&mdash; Made with &#x2764; by
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
<a href="https://github.com/wren-lang/wren/blob/master/AUTHORS">friends</a>.
</p>
<div class="main-column">
</div>
</footer>
<script type='text/javascript'>
var Module = {
print: (function(text) {
console.log(text);
var element = document.getElementById('try-output');
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
element.innerText += text + "\n";
element.scrollTop = element.scrollHeight;
}),
printErr: function(text) {
console.warn(text);
var element = document.getElementById('try-output');
if(element.getAttribute('ready') === null) return;
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
element.innerHTML += `<span class="token error">${text}</span>\n`;
element.scrollTop = element.scrollHeight;
}
};
</script>
<script async type="text/javascript" src="../wren_try.js"></script>
</body>
</html>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Values &ndash; Wren</title> <title>Values &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,120 +110,120 @@
</nav> </nav>
<main> <main>
<h2>Values</h2> <h2>Values</h2>
<p>Values are the built-in atomic object types that all other objects are composed <p>Values are the built-in atomic object types that all other objects are composed
of. They can be created through <em>literals</em>, expressions that evaluate to a of. They can be created through <em>literals</em>, expressions that evaluate to a
value. All values are <em>immutable</em>&mdash;once created, they do not change. The value. All values are <em>immutable</em>&mdash;once created, they do not change. The
number <code>3</code> is always the number <code>3</code>. The string <code>"frozen"</code> can never have its number <code>3</code> is always the number <code>3</code>. The string <code>"frozen"</code> can never have its
character array modified in place. </p> character array modified in place.</p>
<h2>Booleans <a href="#booleans" name="booleans" class="header-anchor">#</a></h2> <h2>Booleans <a href="#booleans" name="booleans" class="header-anchor">#</a></h2>
<p>A boolean value represents truth or falsehood. There are two boolean literals, <p>A boolean value represents truth or falsehood. There are two boolean literals,
<code>true</code> and <code>false</code>. Their class is <a href="modules/core/bool.html">Bool</a>. </p> <code>true</code> and <code>false</code>. Their class is <a href="modules/core/bool.html">Bool</a>.</p>
<h2>Numbers <a href="#numbers" name="numbers" class="header-anchor">#</a></h2> <h2>Numbers <a href="#numbers" name="numbers" class="header-anchor">#</a></h2>
<p>Like other scripting languages, Wren has a single numeric type: <p>Like other scripting languages, Wren has a single numeric type:
double-precision floating point. Number literals look like you expect coming double-precision floating point. Number literals look like you expect coming
from other languages: </p> from other languages:</p>
<div class="codehilite"><pre><span class="mi">0</span> <pre class="snippet">
<span class="mi">1234</span> 0
<span class="o">-</span><span class="mi">5678</span> 1234
<span class="mf">3.14159</span> -5678
<span class="mf">1.0</span> 3.14159
<span class="o">-</span><span class="mf">12.34</span> 1.0
</pre></div> -12.34
</pre>
<p>Numbers are instances of the <a href="modules/core/num.html">Num</a> class.</p>
<p>Numbers are instances of the <a href="modules/core/num.html">Num</a> class. </p>
<h2>Strings <a href="#strings" name="strings" class="header-anchor">#</a></h2> <h2>Strings <a href="#strings" name="strings" class="header-anchor">#</a></h2>
<p>A string is an array of bytes. Typically, they store characters encoded in <p>A string is an array of bytes. Typically, they store characters encoded in
UTF-8, but you can put any byte values in there, even zero or invalid UTF-8 UTF-8, but you can put any byte values in there, even zero or invalid UTF-8
sequences. (You might have some trouble <em>printing</em> the latter to your terminal, sequences. (You might have some trouble <em>printing</em> the latter to your terminal,
though.) </p> though.)</p>
<p>String literals are surrounded in double quotes: </p> <p>String literals are surrounded in double quotes:</p>
<div class="codehilite"><pre><span class="s">&quot;hi there&quot;</span> <pre class="snippet">
</pre></div> "hi there"
</pre>
<p>A handful of escape characters are supported:</p>
<pre class="snippet">
"\0" // The NUL byte: 0.
"\"" // A double quote character.
"\\" // A backslash.
"\%" // A percent sign.
"\a" // Alarm beep. (Who uses this?)
"\b" // Backspace.
"\f" // Formfeed.
"\n" // Newline.
"\r" // Carriage return.
"\t" // Tab.
"\v" // Vertical tab.
</pre>
<p>A handful of escape characters are supported: </p> <p>A <code>\u</code> followed by four hex digits can be used to specify a Unicode code point:</p>
<div class="codehilite"><pre><span class="s">&quot;</span><span class="se">\0</span><span class="s">&quot;</span> <span class="c1">// The NUL byte: 0.</span> <pre class="snippet">
<span class="s">&quot;</span><span class="se">\&quot;</span><span class="s">&quot;</span> <span class="c1">// A double quote character.</span> System.print("\u0041\u0b83\u00DE") //> AஃÞ
<span class="s">&quot;</span><span class="se">\\</span><span class="s">&quot;</span> <span class="c1">// A backslash.</span> </pre>
<span class="s">&quot;</span><span class="se">\%</span><span class="s">&quot;</span> <span class="c1">// A percent sign.</span>
<span class="s">&quot;</span><span class="se">\a</span><span class="s">&quot;</span> <span class="c1">// Alarm beep. (Who uses this?)</span>
<span class="s">&quot;</span><span class="se">\b</span><span class="s">&quot;</span> <span class="c1">// Backspace.</span>
<span class="s">&quot;</span><span class="se">\f</span><span class="s">&quot;</span> <span class="c1">// Formfeed.</span>
<span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span> <span class="c1">// Newline.</span>
<span class="s">&quot;</span><span class="se">\r</span><span class="s">&quot;</span> <span class="c1">// Carriage return.</span>
<span class="s">&quot;</span><span class="se">\t</span><span class="s">&quot;</span> <span class="c1">// Tab.</span>
<span class="s">&quot;</span><span class="se">\v</span><span class="s">&quot;</span> <span class="c1">// Vertical tab.</span>
</pre></div>
<p>A capital <code>\U</code> followed by <em>eight</em> hex digits allows Unicode code points outside
of the basic multilingual plane, like all-important emoji:</p>
<pre class="snippet">
System.print("\U0001F64A\U0001F680") //> 🙊🚀
</pre>
<p>A <code>\u</code> followed by four hex digits can be used to specify a Unicode code point: </p> <p>A <code>\x</code> followed by two hex digits specifies a single unencoded byte:</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\u0041\u0b83\u00DE</span><span class="s">&quot;</span><span class="p">)</span> <span class="output">AஃÞ</span> <pre class="snippet">
</pre></div> System.print("\x48\x69\x2e") //> Hi.
</pre>
<p>Strings are instances of class <a href="modules/core/string.html">String</a>.</p>
<p>A capital <code>\U</code> followed by <em>eight</em> hex digits allows Unicode code points outside
of the basic multilingual plane, like all-important emoji: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\U0001F64A\U0001F680</span><span class="s">&quot;</span><span class="p">)</span> <span class="output">🙊🚀</span>
</pre></div>
<p>A <code>\x</code> followed by two hex digits specifies a single unencoded byte: </p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\x48\x69\x2e</span><span class="s">&quot;</span><span class="p">)</span> <span class="output">Hi.</span>
</pre></div>
<p>Strings are instances of class <a href="modules/core/string.html">String</a>. </p>
<h3>Interpolation <a href="#interpolation" name="interpolation" class="header-anchor">#</a></h3> <h3>Interpolation <a href="#interpolation" name="interpolation" class="header-anchor">#</a></h3>
<p>String literals also allow <em>interpolation</em>. If you have a percent sign (<code>%</code>) <p>String literals also allow <em>interpolation</em>. If you have a percent sign (<code>%</code>)
followed by a parenthesized expression, the expression is evaluated. The followed by a parenthesized expression, the expression is evaluated. The
resulting object&rsquo;s <code>toString</code> method is called and the result is inserted in the resulting object&rsquo;s <code>toString</code> method is called and the result is inserted in the
string: </p> string:</p>
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;Math </span><span class="si">%(</span><span class="mi">3</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">*</span> <span class="mi">5</span><span class="si">)</span><span class="s"> is fun!&quot;</span><span class="p">)</span> <span class="output">Math 23 is fun!</span> <pre class="snippet">
</pre></div> System.print("Math %(3 + 4 * 5) is fun!") //> Math 23 is fun!
</pre>
<p>Arbitrarily complex expressions are allowed inside the parentheses:</p>
<pre class="snippet">
System.print("wow %((1..3).map {|n| n * n}.join())") //> wow 149
</pre>
<p>Arbitrarily complex expressions are allowed inside the parentheses: </p> <p>An interpolated expression can even contain a string literal which in turn has
<div class="codehilite"><pre><span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="s">&quot;wow </span><span class="si">%(</span><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">)</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span><span class="o">|</span><span class="err">n</span><span class="o">|</span> <span class="err">n</span> <span class="o">*</span> <span class="err">n</span><span class="p">}</span><span class="o">.</span><span class="n">join</span><span class="p">()</span><span class="si">)</span><span class="s">&quot;</span><span class="p">)</span> <span class="output">wow 149</span> its own nested interpolations, but doing that gets unreadable pretty quickly.</p>
</pre></div>
<p>An interpolated expression can even contain a string literal which in turn has
its own nested interpolations, but doing that gets unreadable pretty quickly. </p>
<h2>Ranges <a href="#ranges" name="ranges" class="header-anchor">#</a></h2> <h2>Ranges <a href="#ranges" name="ranges" class="header-anchor">#</a></h2>
<p>A range is a little object that represents a consecutive range of numbers. They <p>A range is a little object that represents a consecutive range of numbers. They
don&rsquo;t have their own dedicated literal syntax. Instead, the number class don&rsquo;t have their own dedicated literal syntax. Instead, the number class
implements the <code>..</code> and <code>...</code> <a href="method-calls.html#operators">operators</a> to create them: </p> implements the <code>..</code> and <code>...</code> <a href="method-calls.html#operators">operators</a> to create them:</p>
<div class="codehilite"><pre><span class="mi">3</span><span class="o">..</span><span class="mi">8</span> <pre class="snippet">
</pre></div> 3..8
</pre>
<p>This creates a range from three to eight, including eight itself. If you want a
half-inclusive range, use <code>...</code>:</p>
<pre class="snippet">
4...6
</pre>
<p>This creates a range from three to eight, including eight itself. If you want a <p>This creates a range from four to six <em>not</em> including six itself. Ranges are
half-inclusive range, use <code>...</code>: </p> commonly used for <a href="control-flow.html#for-statements">iterating</a> over a
<div class="codehilite"><pre><span class="mi">4</span><span class="o">...</span><span class="mi">6</span> sequences of numbers, but are useful in other places too. You can pass them to
</pre></div> a <a href="lists.html">list</a>&lsquo;s subscript operator to return a subset of the list, for
example:</p>
<pre class="snippet">
var list = ["a", "b", "c", "d", "e"]
var slice = list[1..3]
System.print(slice) //> [b, c, d]
</pre>
<p>Their class is <a href="modules/core/range.html">Range</a>.</p>
<p>This creates a range from four to six <em>not</em> including six itself. Ranges are
commonly used for <a href="control-flow.html#for-statements">iterating</a> over a
sequences of numbers, but are useful in other places too. You can pass them to
a <a href="lists.html">list</a>&lsquo;s subscript operator to return a subset of the list, for
example: </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">list</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;a&quot;</span><span class="p">,</span> <span class="s">&quot;b&quot;</span><span class="p">,</span> <span class="s">&quot;c&quot;</span><span class="p">,</span> <span class="s">&quot;d&quot;</span><span class="p">,</span> <span class="s">&quot;e&quot;</span><span class="p">]</span>
<span class="k">var</span> <span class="n">slice</span> <span class="o">=</span> <span class="n">list</span><span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">]</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">slice</span><span class="p">)</span> <span class="output">[b, c, d]</span>
</pre></div>
<p>Their class is <a href="modules/core/range.html">Range</a>. </p>
<h2>Null <a href="#null" name="null" class="header-anchor">#</a></h2> <h2>Null <a href="#null" name="null" class="header-anchor">#</a></h2>
<p>Wren has a special value <code>null</code>, which is the only instance of the class <p>Wren has a special value <code>null</code>, which is the only instance of the class
<a href="modules/core/null.html">Null</a>. (Note the difference in case.) It functions a bit like <code>void</code> in some <a href="modules/core/null.html">Null</a>. (Note the difference in case.) It functions a bit like <code>void</code> in some
languages: it indicates the absence of a value. If you call a method that languages: it indicates the absence of a value. If you call a method that
doesn&rsquo;t return anything and get its returned value, you get <code>null</code> back. </p> doesn&rsquo;t return anything and get its returned value, you get <code>null</code> back.</p>
<p><br><hr> <p><br><hr>
<a class="right" href="lists.html">Lists &rarr;</a> <a class="right" href="lists.html">Lists &rarr;</a>
<a href="syntax.html">&larr; Syntax</a> </p> <a href="syntax.html">&larr; Syntax</a></p>
</main> </main>
</div> </div>
<footer> <footer>

View File

@ -3,6 +3,10 @@
<head> <head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Variables &ndash; Wren</title> <title>Variables &ndash; Wren</title>
<script type="application/javascript" src="prism.js" data-manual></script>
<script type="application/javascript" src="codejar.js"></script>
<script type="application/javascript" src="wren.js"></script>
<link rel="stylesheet" type="text/css" href="prism.css" />
<link rel="stylesheet" type="text/css" href="style.css" /> <link rel="stylesheet" type="text/css" href="style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'> <link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop <!-- Tell mobile browsers we're optimized for them and they don't need to crop
@ -14,7 +18,7 @@
<div class="page"> <div class="page">
<div class="main-column"> <div class="main-column">
<h1><a href="./">wren</a></h1> <h1><a href="./">wren</a></h1>
<h2>a classy little scripting language</h2> <h2>a classy little scripting language</h2>
</div> </div>
</div> </div>
</header> </header>
@ -25,6 +29,7 @@
<li><a href="getting-started.html">Getting Started</a></li> <li><a href="getting-started.html">Getting Started</a></li>
<li><a href="contributing.html">Contributing</a></li> <li><a href="contributing.html">Contributing</a></li>
<li><a href="blog">Blog</a></li> <li><a href="blog">Blog</a></li>
<li><a href="try">Try it!</a></li>
</ul> </ul>
<section> <section>
<h2>guides</h2> <h2>guides</h2>
@ -44,9 +49,15 @@
</ul> </ul>
</section> </section>
<section> <section>
<h2>reference</h2> <h2>API docs</h2>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">Modules</a></li>
</ul>
</section>
<section>
<h2>reference</h2>
<ul>
<li><a href="cli">Wren CLI</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -59,6 +70,7 @@
<div><a href="getting-started.html">Getting Started</a></div> <div><a href="getting-started.html">Getting Started</a></div>
<div><a href="contributing.html">Contributing</a></div> <div><a href="contributing.html">Contributing</a></div>
<div><a href="blog">Blog</a></div> <div><a href="blog">Blog</a></div>
<div><a href="try">Try it!</a></div>
</tr> </tr>
<tr> <tr>
<td colspan="2"><h2>guides</h2></td> <td colspan="2"><h2>guides</h2></td>
@ -87,7 +99,7 @@
</td> </td>
<td> <td>
<ul> <ul>
<li><a href="modules">Modules</a></li> <li><a href="modules">API/Modules</a></li>
<li><a href="embedding">Embedding</a></li> <li><a href="embedding">Embedding</a></li>
<li><a href="performance.html">Performance</a></li> <li><a href="performance.html">Performance</a></li>
<li><a href="qa.html">Q &amp; A</a></li> <li><a href="qa.html">Q &amp; A</a></li>
@ -98,74 +110,74 @@
</nav> </nav>
<main> <main>
<h2>Variables</h2> <h2>Variables</h2>
<p>Variables are named slots for storing values. You define a new variable in Wren <p>Variables are named slots for storing values. You define a new variable in Wren
using a <code>var</code> statement, like so: </p> using a <code>var</code> statement, like so:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span> <pre class="snippet">
</pre></div> var a = 1 + 2
</pre>
<p>This creates a new variable <code>a</code> in the current scope and initializes it with
the result of the expression following the <code>=</code>. Once a variable has been
defined, it can be accessed by name as you would expect. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="n">animal</span> <span class="o">=</span> <span class="s">&quot;Slow Loris&quot;</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">animal</span><span class="p">)</span> <span class="output">Slow Loris</span>
</pre></div>
<p>This creates a new variable <code>a</code> in the current scope and initializes it with
the result of the expression following the <code>=</code>. Once a variable has been
defined, it can be accessed by name as you would expect.</p>
<pre class="snippet">
var animal = "Slow Loris"
System.print(animal) //> Slow Loris
</pre>
<h2>Scope <a href="#scope" name="scope" class="header-anchor">#</a></h2> <h2>Scope <a href="#scope" name="scope" class="header-anchor">#</a></h2>
<p>Wren has true block scope: a variable exists from the point where it is defined <p>Wren has true block scope: a variable exists from the point where it is defined
until the end of the <a href="syntax.html#blocks">block</a> where that definition appears. </p> until the end of the <a href="syntax.html#blocks">block</a> where that definition appears.</p>
<div class="codehilite"><pre><span class="p">{</span> <pre class="snippet">
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">a</span><span class="p">)</span> <span class="error">&quot;a&quot; doesn&#39;t exist yet.</span> {
<span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="mi">123</span> System.print(a) //! "a" doesn't exist yet.
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">a</span><span class="p">)</span> <span class="output">123</span> var a = 123
<span class="p">}</span> System.print(a) //> 123
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">a</span><span class="p">)</span> <span class="error">&quot;a&quot; doesn&#39;t exist anymore.</span> }
</pre></div> System.print(a) //! "a" doesn't exist anymore.
</pre>
<p>Variables defined at the top level of a script are <em>top-level</em> and are visible
to the <a href="modules.html">module</a> system. All other variables are <em>local</em>.
Declaring a variable in an inner scope with the same name as an outer one is
called <em>shadowing</em> and is not an error (although it&rsquo;s not something you likely
intend to do much).</p>
<pre class="snippet">
var a = "outer"
{
var a = "inner"
System.print(a) //> inner
}
System.print(a) //> outer
</pre>
<p>Variables defined at the top level of a script are <em>top-level</em> and are visible <p>Declaring a variable with the same name in the <em>same</em> scope <em>is</em> an error.</p>
to the <a href="modules.html">module</a> system. All other variables are <em>local</em>. <pre class="snippet">
Declaring a variable in an inner scope with the same name as an outer one is var a = "hi"
called <em>shadowing</em> and is not an error (although it&rsquo;s not something you likely var a = "again" //! "a" is already declared.
intend to do much). </p> </pre>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="s">&quot;outer&quot;</span>
<span class="p">{</span>
<span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="s">&quot;inner&quot;</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">a</span><span class="p">)</span> <span class="output">inner</span>
<span class="p">}</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">a</span><span class="p">)</span> <span class="output">outer</span>
</pre></div>
<p>Declaring a variable with the same name in the <em>same</em> scope <em>is</em> an error. </p>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="s">&quot;hi&quot;</span>
<span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="s">&quot;again&quot;</span> <span class="error">&quot;a&quot; is already declared.</span>
</pre></div>
<h2>Assignment <a href="#assignment" name="assignment" class="header-anchor">#</a></h2> <h2>Assignment <a href="#assignment" name="assignment" class="header-anchor">#</a></h2>
<p>After a variable has been declared, you can assign to it using <code>=</code>: </p> <p>After a variable has been declared, you can assign to it using <code>=</code>:</p>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="mi">123</span> <pre class="snippet">
<span class="err">a</span> <span class="o">=</span> <span class="mi">234</span> var a = 123
</pre></div> a = 234
</pre>
<p>An assignment walks up the scope stack to find where the named variable is
declared. It&rsquo;s an error to assign to a variable that isn&rsquo;t defined. Wren
doesn&rsquo;t roll with implicit variable definition.</p>
<p>When used in a larger expression, an assignment expression evaluates to the
assigned value.</p>
<pre class="snippet">
var a = "before"
System.print(a = "after") //> after
</pre>
<p>An assignment walks up the scope stack to find where the named variable is <p>If the left-hand side is some more complex expression than a bare variable name,
declared. It&rsquo;s an error to assign to a variable that isn&rsquo;t defined. Wren then it isn&rsquo;t an assignment. Instead, it&rsquo;s calling a <a href="method-calls.html#setters">setter method</a>.</p>
doesn&rsquo;t roll with implicit variable definition. </p> <p><br><hr>
<p>When used in a larger expression, an assignment expression evaluates to the <a class="right" href="functions.html">Functions &rarr;</a>
assigned value. </p> <a href="control-flow.html">&larr; Control Flow</a></p>
<div class="codehilite"><pre><span class="k">var</span> <span class="err">a</span> <span class="o">=</span> <span class="s">&quot;before&quot;</span>
<span class="vg">System</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="err">a</span> <span class="o">=</span> <span class="s">&quot;after&quot;</span><span class="p">)</span> <span class="output">after</span>
</pre></div>
<p>If the left-hand side is some more complex expression than a bare variable name,
then it isn&rsquo;t an assignment. Instead, it&rsquo;s calling a <a href="method-calls.html#setters">setter method</a>. </p>
<p><br><hr>
<a class="right" href="functions.html">Functions &rarr;</a>
<a href="control-flow.html">&larr; Control Flow</a> </p>
</main> </main>
</div> </div>
<footer> <footer>

79
wren.js Normal file
View File

@ -0,0 +1,79 @@
window.onload = function() {
var blocks = document.querySelectorAll('pre.snippet')
blocks.forEach((element) => {
var lang = 'lua'
var input_lang = element.getAttribute('data-lang')
if(input_lang) lang = input_lang
var code = document.createElement('code');
code.setAttribute('class', ' language-'+lang);
code.innerHTML = element.innerHTML;
element.innerHTML = '';
element.append(code)
});
Prism.highlightAll();
var try_code = document.querySelector("#try-code")
if(try_code) {
var jar_options = { tab: ' '.repeat(2) }
var jar = CodeJar(try_code, withLineNumbers(Prism.highlightElement), jar_options)
var output = document.querySelector("#try-output")
var result = document.querySelector("#try-result")
Module.print = function(text) { output.innerText += text + "\n"; }
Module.printErr = function(text) { output.innerText += text + "\n"; }
var run = document.querySelector("#try-run")
var hello = document.querySelector("#try-hello")
var fractal = document.querySelector("#try-fractal")
var loop = document.querySelector("#try-loop")
var compile = Module.cwrap('wren_compile', 'number', ['string'])
var set_input = (content) => {
output.innerText = '...';
result.removeAttribute('class');
result.innerText = 'no errors';
jar.updateCode(content);
}
run.onclick = (e) => {
console.log("run")
output.setAttribute('ready', '');
output.innerText = '';
var res = compile(jar.toString())
var message = "no errors!"
result.removeAttribute('class');
if(res == 1) { //WREN_RESULT_COMPILE_ERROR
message = "Compile error!"
result.setAttribute('class', 'error');
} else if(res == 2) { //WREN_RESULT_RUNTIME_ERROR
message = "Runtime error!"
result.setAttribute('class', 'error');
}
result.innerText = message;
console.log(result);
}
hello.onclick = (e) => { set_input('System.print("hello wren")') }
loop.onclick = (e) => { set_input(`for (i in 1..10) System.print("Counting up %(i)")`); }
fractal.onclick = (e) => {
set_input(`for (yPixel in 0...24) {
var y = yPixel / 12 - 1
for (xPixel in 0...80) {
var x = xPixel / 30 - 2
var x0 = x
var y0 = y
var iter = 0
while (iter < 11 && x0 * x0 + y0 * y0 <= 4) {
var x1 = (x0 * x0) - (y0 * y0) + x
var y1 = 2 * x0 * y0 + y
x0 = x1
y0 = y1
iter = iter + 1
}
System.write(" .-:;+=xX$& "[iter])
}
System.print("")
}`);
} //fractal
} //if try_code
}

2582
wren_try.js Normal file

File diff suppressed because it is too large Load Diff

BIN
wren_try.wasm Normal file

Binary file not shown.