Redesign site.

This commit is contained in:
Bob Nystrom
2014-04-14 21:23:46 -07:00
parent f03895b17e
commit 2567c4846e
24 changed files with 341 additions and 175 deletions

View File

@ -1,4 +1,5 @@
^title Branching
^category language
*Control flow* is used to determine which chunks of code are executed and how many times. Expressions and statements for deciding whether or not to execute some code are called *branching* and are covered here. To execute something more than once, you'll want [*looping*](looping.html).
@ -18,12 +19,12 @@ This means `0`, empty strings, and empty collections are all considered "true" v
The simplest branching statement, `if` lets you conditionally skip a chunk of code. It looks like this:
:::wren
:::dart
if (ready) IO.print("go!")
That evaluates the parenthesized expression after `if`. If it's true, then the statement after the condition is evaluated. Otherwise it is skipped. Instead of a statement, you can have a [block](syntax.html#blocks):
:::wren
:::dart
if (ready) {
IO.print("getSet")
IO.print("go!")
@ -31,11 +32,12 @@ That evaluates the parenthesized expression after `if`. If it's true, then the s
You may also provide an `else` branch. It will be executed if the condition is false:
:::wren
:::dart
if (ready) IO.print("go!") else IO.print("not ready!")
And, of course, it can take a block too:
:::dart
if (ready) {
IO.print("go!")
} else {
@ -48,13 +50,13 @@ The `&&` and `||` operators are lumped here under branching because they conditi
An `&&` ("logical and") expression evaluates the left-hand argument. If it's falsey, it returns that value. Otherwise it evaluates and returns the right-hand argument.
:::wren
:::dart
IO.print(false && 1) // false
IO.print(1 && 2) // 2
An `||` ("logical or") expression is reversed. If the left-hand argument is truthy, it's returned, otherwise the right-hand argument is evaluated and returned:
:::wren
:::dart
IO.print(false || 1) // 1
IO.print(1 || 2) // 1

View File

@ -1,4 +1,5 @@
^title Classes
^category types
Every value in Wren is an object, and every object is an instance of a class.
Even `true` and `false` are full-featured objects—instances of the `Bool` class.
@ -147,3 +148,5 @@ Constructors, however, initialize the instance *after* it has been created. They
## Superclass method calls
**TODO**
**TODO: this**

View File

@ -0,0 +1,4 @@
^title Contributing
^category reference
**TODO**

View File

@ -0,0 +1,4 @@
^title Core Libraries
^category reference
**TODO**

View File

@ -0,0 +1,4 @@
^title Embedding API
^category reference
**TODO**

View File

@ -1,3 +0,0 @@
^title Embedding
**TODO**

View File

@ -1,3 +1,4 @@
^title Error Handling
^category language
**TODO**

View File

@ -1,4 +1,5 @@
^title Fibers
^category types
Fibers are a key part of Wren. They form its execution model, its concurrency story and take the place of exceptions in [error handling](error-handling.html). A fiber represents a "thread" of computation.

View File

@ -1,4 +1,5 @@
^title Functions
^category types
No self-respecting language today can get by without functions—first 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 useful.
@ -41,6 +42,7 @@ Of course, you don't *have* to use a block argument to pass a function to a meth
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 *don't* need to pass it to a method. For that, you can call the `Fn` class's constructor:
:::dart
var someFn = new Fn {
IO.print("Hi!")
}

View File

@ -1,3 +0,0 @@
^title Getting Involved
**TODO**

View File

@ -21,6 +21,7 @@ The above instructions will drop you into Wren's standalone interpreter in inter
Or a little more exciting:
:::dart
for (i in 1..10) IO.print("Counting up ", i)
You can exit the interpreter using good old Ctrl-C or Ctrl-D, or just throw your computer to the ground and storm off.

View File

@ -1,13 +1,13 @@
^title Welcome
^title Welcome!
Wren is a *small, clean, fast, class-based scripting language.* Think Smalltalk
in a Lua-sized package.
:::java
:::dart
IO.print("Hello, world!")
class Wren {
adjectives = ["small", "clean", "fast"]
adjectives = ["sm\nall", "clean", "fast"]
languageType {
"scripting"
}

View File

@ -1,4 +1,5 @@
^title Lists
^category types
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 expressions inside square brackets:
@ -61,12 +62,14 @@ It's valid to "insert" after the last element in the list, but only *right* afte
The opposite of `insert` is `removeAt`. It removes a single element from a given position in the list. All following items are shifted up to fill in the gap:
:::dart
var letters = ["a", "b", "c"]
letters.removeAt(1)
IO.print(letters) // ["a", "c"]
If you want to remove everything from the list, you can clear it:
:::dart
hirsute.clear
IO.print(hirsute) // []

View File

@ -1,4 +1,5 @@
^title Looping
^category language
It'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 they should be familiar if you've used other imperative languages.

View File

@ -1,3 +1,4 @@
^title Maps
^category types
**TODO**

View File

@ -1,11 +1,12 @@
^title Method Calls
^category language
**TODO: Refactor `method-calls` and `classes` into using and creating classes.**
Wren is object-oriented, so most code consists of method calls. Most of them
look like so:
:::wren
:::dart
IO.print("hello")
items.add("another")
items.insert(1, "value")
@ -19,7 +20,7 @@ argument list in parentheses. Semantically, a method call works like this:
Methods that do not take any arguments leave off the `()`:
:::wren
:::dart
text.length
These are special "getters" or "accessors" in other languages. In Wren, they're
@ -34,6 +35,7 @@ other. In technical terms, this means you can overload by *arity*.
In normal human terms, it means you can overload by number of parameters. These
are calls to two different methods:
:::dart
items.add("one arg")
items.add("first", "second")
@ -45,7 +47,7 @@ implement separately.
Modifying a public property of some object looks like you expect:
:::wren
:::dart
point.x = 123
You can probably guess by now, but again this is just another special syntax
@ -60,7 +62,7 @@ just a special syntax for regular method calls.
Wren has a few prefix operators:
:::wren
:::dart
! ~ -
They are just method calls on the operand without any other arguments. An
@ -70,7 +72,7 @@ We have a few other operators to play with. The remaining ones are
infix—they have operators on either side. In order of increasing
precedence, they are:
:::wren
:::dart
== !=
< > <= >=
.. ...
@ -92,7 +94,7 @@ which can in turn be iterated over using a `for` [loop](looping.html).
Most languages use square brackets (`[]`) for working with collection-like
objects. For example:
:::wren
:::dart
list.add["item"]
map["key"] = "value"
@ -100,5 +102,5 @@ You know the refrain by now. In Wren, these are just method calls. Subscript
operators can also be overloaded by arity, which is useful for things like
multi-dimensional arrays:
:::wren
:::dart
table[3, 5] = "value"

View File

@ -1,4 +1,5 @@
^title Performance
^category reference
Languages come in four rough performance buckets, from slowest to fastest:
@ -8,17 +9,16 @@ Languages come in four rough performance buckets, from slowest to fastest:
2. Bytecode interpreters: CPython,
Ruby 1.9 and later, Lua, early JavaScript VMs.
3. JIT compilers for dynamically typed languages: Modern JavaScript VMs,
3. JIT compiled dynamically typed languages: Modern JavaScript VMs,
LuaJIT, PyPy, some Lisp/Scheme implementations.
4. Statically compiled statically typed languages: C, C++, Java, C#, Haskell,
etc.
4. Statically typed languages: C, C++, Java, C#, Haskell, etc.
Most languages in the first bucket aren't suitable for production use. (Servers 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 on client hardware, as the success of the listed languages shows. Languages in the third bucket are quite fast, but their implementations are breathtakingly complex, often rivaling that of compilers for statically-typed languages.
## Why is Wren fast?
Wren is in the second bucket. If you want to have a simple implementation but be fast enough for real use, that's the sweet spot. Within that bucket, Wren's performance is quite competitive despite being much younger and with a much smaller, simpler codebase. Wren has a few tricks up its sleeve:
Wren is in the second bucket. If you want a simple implementation that's fast enough for real use, this is the sweet spot. Despite being younger and having a smaller codebase, Wren's performance is quite competitive with other languages in that bucket. It has a few tricks up its sleeve:
### A compact value representation

View File

@ -1,4 +1,5 @@
^title Q & A
^category reference
## Why did you create Wren?
@ -37,7 +38,7 @@ Here's an example of that kind of object-oriented programming in Lua:
Here's the same example in Wren:
:::wren
:::dart
class Account {
new(balance) { _balance = balance }
withdraw(amount) { _balance = _balance - amount }

View File

@ -2,17 +2,40 @@ $header: "Dosis", helvetica, arial, sans-serif;
$body: "Source Sans Pro", georgia, serif;
$code: "Source Code Pro", Menlo, Monaco, Consolas, monospace;
$primary: hsl(30, 40%, 65%);
$link: hsl(195, 60%, 50%);
$link-hover: hsl(195, 100%, 30%);
$link-glow: hsla(195, 100%, 60%, 0.2);
$dark: hsl(200, 30%, 20%);
$light: hsl(30, 20%, 92%);
$gray-10: mix($dark, $light, 10%);
$gray-20: mix($dark, $light, 20%);
$gray-30: mix($dark, $light, 30%);
$gray-40: mix($dark, $light, 40%);
$gray-50: mix($dark, $light, 50%);
$gray-60: mix($dark, $light, 60%);
$gray-80: mix($dark, $light, 80%);
$secondary-hue: 195;
$text: hsl(30, 10%, 40%);
$light-gray: hsl(195, 10%, 80%);
$lighter-gray: hsl(195, 10%, 93%);
$code-color: hsl(30, 5%, 55%);
$code-bg: mix($light, #fff, 50%);
$blue: hsl(200, 60%, 50%);
$blue-hover: hsl(200, 100%, 80%);
$blue-dark: hsl(200, 80%, 30%);
$blue-glow: hsla(200, 100%, 50%, 0.4);
// TODO: Green is not currently used.
$green: hsl(100, 70%, 35%);
$green-light: hsl(100, 70%, 45%);
$green-hover: hsl(100, 80%, 70%);
$green-dark: hsl(100, 70%, 20%);
$green-glow: hsla(100, 70%, 50%, 0.5);
$gold: hsl(40, 70%, 50%);
$gold-hover: hsl(40, 70%, 80%);
$gold-dark: hsl(40, 80%, 30%);
$gold-glow: hsla(40, 70%, 50%, 0.4);
* {
-moz-box-sizing: border-box;
box-sizing: border-box;
}
@ -22,102 +45,43 @@ body, code, h1, h2, h3, p, pre, tt {
}
body {
color: #333;
background: #fff;
padding: 0 40px;
}
h1 {
font: 36px/40px $header;
margin: 50px 0 0 0;
}
h2 {
font: normal 24px $header;
margin: 24px 0 0 0;
}
h3 {
font: normal 20px $header;
margin: 24px 0 0 0;
}
h1, h2, h3 {
color: $primary;
outline: none;
}
a {
color: $link;
text-decoration: none;
transition: color 0.3s, text-shadow 0.3s;
}
.header-anchor {
display: none;
}
h2:hover > .header-anchor,
h3:hover > .header-anchor {
display: inline;
color: $lighter-gray;
}
a:hover,
h2:hover > .header-anchor:hover,
h3:hover > .header-anchor:hover {
color: $link-hover;
text-shadow: 0 0 6px $link-glow;
}
p, li {
background: $light;
color: hsl(40, 10%, 40%);
font: 17px/26px $body;
margin: 10px 0;
}
p + p {
margin-top: 20px;
}
code, pre {
color: hsl($secondary-hue, 20%, 40%);
font: 14px $code;
background: hsl($secondary-hue, 40%, 98%);
border-radius: 4px;
}
code {
padding: 1px 3px;
white-space: nowrap;
}
pre {
margin: 10px 0;
line-height: 20px;
padding: 10px;
// Scroll horizontally if not wide enough.
overflow: auto;
}
.page {
position: relative;
margin: 0 auto;
max-width: 840px;
width: 800px;
// Clear contents.
&:after {
content: "";
display: table;
clear: both;
}
}
.left-1 { float: left; width: 240px; }
.left-2 { float: left; width: 520px; }
.right-1 { float: right; width: 240px; }
.right-2 { float: right; width: 520px; }
header {
position: relative;
height: 100px;
border-bottom: solid 1px $lighter-gray;
.page {
height: 150px;
}
background: $dark;
h1 {
position: absolute;
left: 0;
bottom: 0;
padding: 0;
font: 64px $header;
font-weight: 300;
margin: 0;
letter-spacing: 2px;
}
@ -125,25 +89,68 @@ header {
position: absolute;
right: 0;
bottom: 11px;
color: $light-gray;
padding: 0;
font: 18px $header;
font-weight: 300;
letter-spacing: 1px;
color: hsl(200, 30%, 40%);
}
a {
color: $blue;
}
a:hover {
color: $blue-hover;
text-shadow: 0 0 6px $blue-glow;
}
ul {
position: absolute;
display: inline-block;
right: 0;
bottom: 8px;
margin: 0;
padding: 0;
}
li {
display: inline-block;
position: relative;
margin: 0 5px;
font: 18px $header;
font-weight: 300;
letter-spacing: 1px;
text-align: center;
}
}
main {
margin-left: 220px;
.header-bar {
height: 100px;
background: $gray-10;
border-top: solid 1px $gray-20;
border-bottom: solid 1px white;
h1 {
padding-top: 30px;
font: 48px/60px $header;
font-weight: 400;
color: $gray-60;
small {
font-size: 36px;
font-weight: 400;
color: $gray-40;
}
}
}
nav {
position: absolute;
left: 0;
width: 140px;
margin-top: 102px;
padding-top: 20px;
h2 {
color: $light-gray;
color: $gray-30;
font: normal 18px $header;
font-weight: 300;
margin: 0;
@ -163,31 +170,136 @@ nav {
}
}
.footer {
color: $light-gray;
h2 {
font: normal 24px $header;
margin: 24px 0 0 0;
color: $blue;
}
h3 {
font: normal 20px $header;
margin: 24px 0 0 0;
color: $blue;
}
a {
color: $blue;
text-decoration: none;
transition: color 0.2s, text-shadow 0.2s;
outline: none;
}
a:hover {
color: $blue-dark;
}
.header-anchor {
color: $light;
}
h2:hover > .header-anchor,
h3:hover > .header-anchor {
color: $gray-10;
}
h2:hover > .header-anchor:hover,
h3:hover > .header-anchor:hover {
color: $blue-dark;
}
p, li {
margin: 10px 0;
}
p + p {
margin-top: 20px;
}
code, pre {
color: $code-color;
font: 14px $code;
background: $code-bg;
border-radius: 4px;
border-bottom: solid 1px $gray-10;
border-top: solid 1px #fff;
}
code {
padding: 1px 3px;
white-space: nowrap;
}
pre {
margin: 10px 0;
line-height: 20px;
padding: 10px;
// Scroll horizontally if not wide enough.
overflow: auto;
}
footer {
margin-top: 20px;
padding: 20px 0 40px 0;
font: 14px $body;
text-align: center;
margin: 30px 0 40px 0;
background: hsl(40, 5%, 60%);
color: hsl(40, 15%, 85%);
}
// Syntax highlighting.
.codehilite pre span.c1 { color: hsl($secondary-hue, 20%, 65%); } /* line comment */
.codehilite pre span.cm { color: hsl($secondary-hue, 20%, 65%); } /* block comment */
.codehilite pre span.vg { color: #5d3a85; } /* global variable */
.codehilite pre span.vi { color: #784bab; } /* instance variable */
.codehilite pre span.k { color: hsl($secondary-hue, 100%, 40%); } /* keyword message */
.codehilite pre span.kd { color: hsl($secondary-hue, 100%, 40%); } /* keyword decl */
.codehilite pre span.p { color: #777; } /* punctuation ()[]{} */
.codehilite pre span.s { color: hsl(30, 40%, 55%); } /* string */
.codehilite pre span.s2 { color: hsl(30, 40%, 55%); } /* string escape */
.codehilite pre span.se { color: hsl(30, 90%, 45%); } /* string escape */
.codehilite pre span.nb { color: #30a138; } /* built-in name: self undefined */
.codehilite pre span.o { color: hsl($secondary-hue, 100%, 35%); } /* operator */
.codehilite pre span.nv { color: #24a36a; } /* argument name */
.codehilite pre span.ow { color: #30a186; } /* user-defined operator */
.codehilite pre span.mi { } /* number */
.codehilite pre span.n { } /* name */
.codehilite pre {
// Comments.
span.c1, span.cm { color: mix($code-color, $code-bg, 60%); }
// Keywords.
span.k, span.kd, span.kc { color: $blue; }
// Numbers.
span.m, span.mi { color: $green; }
// Strings.
span.s, span.s2 { color: $gold; }
span.se { color: mix($gold, $gold-dark, 50%); }
}
// Category colors.
body.reference {
a {
color: $gold;
}
a:hover {
color: $gold-dark;
}
header {
a:hover {
color: $gold-hover;
}
}
main {
h2, h3 {
color: $gold;
}
.header-anchor {
color: $light;
}
h2:hover > .header-anchor,
h3:hover > .header-anchor {
color: $gray-10;
}
h2:hover > .header-anchor:hover,
h3:hover > .header-anchor:hover {
color: $gold-dark;
}
}
}
/*
@media only screen and (max-width: 639px) {
// Shrink the window padding.
body {
@ -228,3 +340,4 @@ nav {
margin-left: 0;
}
}
*/

View File

@ -1,4 +1,5 @@
^title Syntax
^category language
Wren's syntax is designed to be familiar to people coming from C-like languages while being as simple and expressive as possible within that framework.
@ -33,6 +34,20 @@ Wren also has a few predefined identifiers:
:::dart
false null this true
## Names
Identifiers are similar to other programming languages. They start with a letter or underscore and may contain letters, digits, and underscores. Case is sensitive.
:::dart
hi
camelCase
PascalCase
_under_score
abc123
ALL_CAPS
Identifiers that start with underscore (`_`) are special in Wren. They are used to indicate fields in [classes](classes.html).
## Statement terminators
Officially, statements are terminated by a semicolon (`;`) like in other
@ -56,7 +71,7 @@ there, don't worry, you should be fine here.
## Blocks
Wren uses curly braces to define *blocks*. Things like [control flow](branching.html) allow block bodies. [Method](method-calls.html) and [function](functions.html) bodies are also blocks. For example:
Wren uses curly braces to define *blocks*. Things like [control flow](branching.html) and [looping](looping.html) allow block bodies. [Method](method-calls.html) and [function](functions.html) bodies are also blocks. For example:
:::dart
if (happy && knowIt) {
@ -65,6 +80,7 @@ Wren uses curly braces to define *blocks*. Things like [control flow](branching.
Here we have a block for the then case, and just a single expression for the else. Blocks have two similar but not identical forms. If a there is a newline after the opening `{`, then the body contains a series of statements:
:::dart
{
IO.print("one")
IO.print("two")
@ -73,26 +89,13 @@ Here we have a block for the then case, and just a single expression for the els
If there is no newline, the block may only contain a single expression:
:::dart
{ "this is fine" }
{ while (this) "is an error" }
These are useful when defining method and function bodies. A normal block body implicitly returns `null`. If you want your method or function to return something different, you need an explicit `return` statement. However, a single-expression block with no newline after the `{` implicitly returns the result of that expression. This is a nice convenience for short methods and functions that just evaluate and return an expression.
## Names
Identifiers are similar to other programming languages. They start with a letter or underscore and may contain letters, digits, and underscores. Case is sensitive.
:::dart
hi
camelCase
PascalCase
_under_score
abc123
ALL_CAPS
Identifiers that start with underscore (`_`) are special in Wren. They are used to indicate fields in [classes](classes.html).
**TODO: Move this somewhere else:*
**TODO: Move this somewhere else:**
## The `is` operator

View File

@ -10,17 +10,24 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top">
<!--
<a href="https://github.com/munificent/wren">
<img style="position: absolute; top: 0; right: 0; border: 0; z-index: 100;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub">
</a>-->
<div class="page">
<header>
<header>
<div class="page">
<h1><a href="index.html">wren</a></h1>
<h2>a classy little scripting language</h2>
</header>
<nav>
<h2>welcome</h2>
</div>
</header>
<div class="header-bar">
<div class="page">
<div class="{nav-col}">
<h1><small>{category}</small></h1>
</div>
<div class="{main-col}">
<h1>{title}</h1>
</div>
</div>
</div>
<div class="page">
<nav class="{nav-col}">
<ul>
<li><a href="getting-started.html">Getting Started</a></li>
</ul>
@ -42,19 +49,23 @@
<li><a href="lists.html">Lists</a></li>
<li><a href="maps.html">Maps</a></li>
</ul>
</ul>
<h2>other</h2>
<h2>reference</h2>
<ul>
<li><a href="qa.html">Q &amp; A</a></li>
<li><a href="core-libraries.html">Core Libraries</a></li>
<li><a href="embedding-api.html">Embedding API</a></li>
<li><a href="performance.html">Performance</a></li>
<li><a href="embedding.html">Embedding</a></li>
<li><a href="getting-involved.html">Getting Involved</a></li>
<li><a href="contributing.html">Contributing</a></li>
<li><a href="qa.html">Q &amp; A</a></li>
</ul>
</nav>
<main>
<h1>{title}</h1>
<main class="{main-col}">
{html}
<p class="footer">Wren lives <a href="https://github.com/munificent/wren">on GitHub</a> &mdash; Last modified on {mod} &mdash; By Bob Nystrom.</p>
</main>
</div>
<footer>
<div class="page">
<p>Wren lives <a href="https://github.com/munificent/wren">on GitHub</a> &mdash; Last modified on {mod} &mdash; By Bob Nystrom.</p>
</div>
</footer>
</body>
</html>

View File

@ -1,4 +1,5 @@
^title Values
^category types
Values are the built-in object types that all other objects are composed of.
They can be created through *literals*, expressions that evaluate to a value.
@ -52,6 +53,7 @@ This creates a range from three two eight, including eight itself. If you want a
This creates a range from four to six *not* including six itself. Ranges are commonly used for [looping](looping.html) over a sequences of numbers, but are useful in other places too. You can pass them to a [list](lists.html)'s subscript operator to return a subset of the list, for example:
:::dart
var list = ["a", "b", "c", "d", "e"]
var slice = list[1..3]
IO.print(slice) // ["b", "c", "d"]

View File

@ -1,4 +1,5 @@
^title Variables
^category language
Variables are named slots for storing values. You can define a new variable in
Wren using a `var` statement, like so:

View File

@ -30,6 +30,7 @@ def format_file(path, skip_up_to_date):
return
title = ""
category = ""
# Read the markdown file and preprocess it.
contents = ""
@ -45,6 +46,8 @@ def format_file(path, skip_up_to_date):
if command == "title":
title = args
elif command == "category":
category = args
else:
print "UNKNOWN COMMAND:", command, args
@ -67,7 +70,16 @@ def format_file(path, skip_up_to_date):
modified = datetime.fromtimestamp(os.path.getmtime(path))
mod_str = modified.strftime('%B %d, %Y')
fields = {'title': title, 'html': html, 'mod': mod_str}
nav_col = 'left-1'
main_col = 'right-2'
fields = {
'title': title,
'html': html,
'mod': mod_str,
'category': category,
'nav-col': nav_col,
'main-col': main_col
}
with open("doc/site/template.html") as f:
template = f.read()