forked from Mirror/wren
Start hacking on web site.
This commit is contained in:
3
doc/site/classes.markdown
Normal file
3
doc/site/classes.markdown
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
^title Classes
|
||||||
|
|
||||||
|
**TODO**
|
||||||
32
doc/site/index.markdown
Normal file
32
doc/site/index.markdown
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
^title Welcome
|
||||||
|
|
||||||
|
Wren is a *small, clean, fast, class-based scripting language.* Think Smalltalk
|
||||||
|
in a Lua-sized package.
|
||||||
|
|
||||||
|
:::java
|
||||||
|
io.write("Hello, world!")
|
||||||
|
|
||||||
|
class Wren {
|
||||||
|
adjectives = ["small", "clean", "fast"]
|
||||||
|
languageType {
|
||||||
|
"scripting"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* **Wren is small.** The codebase stays under 5,000 semicolons to keep the
|
||||||
|
language and libraries small enough to fit in your head. You can skim the
|
||||||
|
whole thing in one sitting.
|
||||||
|
|
||||||
|
* **Wren is clean.** The codebase is *small*, but not *dense*. It is readable
|
||||||
|
and lovingly-commented. It's written in warning-free standard C99.
|
||||||
|
|
||||||
|
* **Wren is fast.** Wren has a fast single-pass compiler, tight bytecode, and
|
||||||
|
a compact object representation.
|
||||||
|
|
||||||
|
* **Wren is class-based.** There are lots of scripting languages out there,
|
||||||
|
but many have unusual or non-existent object models. Wren places
|
||||||
|
classes front and center.
|
||||||
|
|
||||||
|
* **Wren is a scripting language.** Wren is intended for embedding in
|
||||||
|
applications. It has no dependencies, a small standard library,
|
||||||
|
and an easy-to-use C API.
|
||||||
152
doc/site/style.css
Normal file
152
doc/site/style.css
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
body, code, h1, h2, h3, p, pre, tt {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font: 36px "Sanchez", helvetica, arial, sans-serif;
|
||||||
|
margin: 30px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font: normal 24px "Sanchez", helvetica, arial, sans-serif;
|
||||||
|
margin: 24px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font: normal 18px "Sanchez", helvetica, arial, sans-serif;
|
||||||
|
margin: 24px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
color: hsl(195, 90%, 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: hsl(195, 80%, 40%);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: hsl(195, 70%, 40%);
|
||||||
|
}
|
||||||
|
|
||||||
|
p, li {
|
||||||
|
font: 17px/26px "Source Sans Pro", georgia, serif;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p + p {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code, pre, tt {
|
||||||
|
color: hsl(195, 20%, 40%);
|
||||||
|
font: 14px "Source Code Pro", Menlo, Monaco, Consolas, monospace;
|
||||||
|
background: hsl(195, 20%, 95%);
|
||||||
|
border-bottom: solid 2px hsl(195, 30%, 91%);
|
||||||
|
}
|
||||||
|
|
||||||
|
code, pre {
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
padding: 1px 3px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 12px 0;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background: hsl(195, 50%, 20%);
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
border-bottom: solid 2px hsl(330, 100%, 50%);
|
||||||
|
box-shadow: 0 10px 30px -10px hsl(195, 55%, 10%) inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 640px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 {
|
||||||
|
float: left;
|
||||||
|
font: 36px "Sanchez", helvetica, arial, sans-serif;
|
||||||
|
color: #fff;
|
||||||
|
padding-top: 25px;
|
||||||
|
margin: 0;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 a {
|
||||||
|
color: #fff;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header a:hover {
|
||||||
|
color: hsl(330, 100%, 50%);
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header h1 small {
|
||||||
|
font: 16px "Source Code Pro", helvetica, arial, sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
color: hsl(195, 50%, 50%);
|
||||||
|
letter-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header ul {
|
||||||
|
float: right;
|
||||||
|
margin: 0;
|
||||||
|
padding: 44px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header li {
|
||||||
|
display: inline;
|
||||||
|
font: 17px "Source Sans Pro", helvetica, arial, sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header li a {
|
||||||
|
color: hsl(195, 40%, 80%);
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
color: #888;
|
||||||
|
font: italic 14px "Source Sans Pro", georgia, serif;
|
||||||
|
text-align: center;
|
||||||
|
margin: 30px 0 40px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* syntax highlighting */
|
||||||
|
|
||||||
|
.codehilite pre span.c1 { color: hsl(195, 10%, 60%); } /* line comment */
|
||||||
|
.codehilite pre span.cm { color: hsl(195, 10%, 60%); } /* block comment */
|
||||||
|
.codehilite pre span.vg { color: #5d3a85; } /* global variable */
|
||||||
|
.codehilite pre span.vi { color: #784bab; } /* instance variable */
|
||||||
|
.codehilite pre span.k { color: hsl(195, 80%, 40%); } /* keyword message */
|
||||||
|
.codehilite pre span.p { color: #777; } /* punctuation ()[]{} */
|
||||||
|
.codehilite pre span.s { color: hsl(40, 90%, 45%); } /* string */
|
||||||
|
.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(195, 100%, 35%); } /* operator */
|
||||||
|
.codehilite pre span.kd { color: hsl(195, 100%, 45%); } /* keyword decl */
|
||||||
|
.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 */
|
||||||
106
doc/site/syntax.markdown
Normal file
106
doc/site/syntax.markdown
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
^title Syntax
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
Line comments start with `//` and end at the end of the line:
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
// This is a comment.
|
||||||
|
|
||||||
|
Block comments start with `/*` and end with `*/`. They can span multiple lines or be within a single one. Unlike C, block comments can nest in Wren:
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
/* This is /* a nested */ comment. */
|
||||||
|
|
||||||
|
## Literals
|
||||||
|
|
||||||
|
Wren currently supports a few atomic types: booleans, numbers, strings, and the null type. Numbers are double-precision floating point values, and strings are text. Wren doesn't support a lot of fancy formats for them yet, just the basic:
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
0
|
||||||
|
1234
|
||||||
|
-432.1
|
||||||
|
"a string"
|
||||||
|
"another string"
|
||||||
|
"supported escapes: \" \n \\"
|
||||||
|
|
||||||
|
Wren also has a couple of special values:
|
||||||
|
|
||||||
|
* `null` indicates the absence of a value.
|
||||||
|
* `this` inside a method refers to the method's receiver.
|
||||||
|
* `true` and `false` are boolean values.
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
Variables are named references to values. Naming rules mostly follow C. They start with a letter and can contain letters, digits, and underscores (`_`). Some examples:
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
foo
|
||||||
|
Bar
|
||||||
|
bestFriends4eva
|
||||||
|
under_score
|
||||||
|
|
||||||
|
Variables can be declared using `var`:
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
var pie = "pumpkin"
|
||||||
|
|
||||||
|
**TODO: Scoping**
|
||||||
|
|
||||||
|
## Method calls
|
||||||
|
|
||||||
|
Wren is a deeply object-oriented language, so most code consists of method calls. They look pretty familiar:
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
io.write("hello")
|
||||||
|
items.add("another")
|
||||||
|
items.insert(1, "value")
|
||||||
|
|
||||||
|
You have a *receiver* on the left, followed by a `.`, then a name and an argument list in parentheses. Semantically, a method call works like this:
|
||||||
|
|
||||||
|
1. Look up the class of the receiver.
|
||||||
|
2. Look up the method on it by name.
|
||||||
|
3. Invoke the method.
|
||||||
|
|
||||||
|
Methods that do not take any arguments leave off the `()`:
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
text.length
|
||||||
|
|
||||||
|
These are special "getters" or "accessors" in other languages. In Wren, they're just methods. Unlike most dynamic languages, the number of arguments to a method is part of its *name*. In technical terms, this means you can overload by *arity*. Basically, it means that these are calls to two different methods:
|
||||||
|
|
||||||
|
items.add("one arg")
|
||||||
|
items.add("first", "second")
|
||||||
|
|
||||||
|
## Operators
|
||||||
|
|
||||||
|
Wren has mostly the same operators you know and love from C, with the same precedence and associativity. These operators are prefix (they come before their operand):
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
! ~ -
|
||||||
|
|
||||||
|
Semantically, they are just method calls on their operand. When you see `!possible`, it's effectively the same as `possible.!` (though Wren does *not* allow that syntax).
|
||||||
|
|
||||||
|
These operators are infix (they have operands on either side):
|
||||||
|
|
||||||
|
:::wren
|
||||||
|
=
|
||||||
|
|| &&
|
||||||
|
is
|
||||||
|
== !=
|
||||||
|
< > <= >=
|
||||||
|
| &
|
||||||
|
+ -
|
||||||
|
* / %
|
||||||
|
|
||||||
|
The `is` operator is used for type tests. The left operand is an object and the right operand is a class. It evaluates to `true` if the object is an instance of the class (or one of its subclasses).
|
||||||
|
|
||||||
|
The `||` and `&&` are logical operators. Like in C, they are basically flow-control constructs. A `||` expression will only evaluate the right operand if the left-hand side evaluates to something non-false-y. Likewise, `&&` only evaluates the right operand if the left evaluates to something false-y.
|
||||||
|
|
||||||
|
In Wren, the only false value is the boolean value `false`. Everything else is considered "true".
|
||||||
|
|
||||||
|
All other infix operators are just syntactic sugar for method calls. The left operand is the receiver, and the right is passed to it as an argument. So `a + b` is semantically `a.+(b)`. The built-in types implement these methods to do what you (hopefully) expect.
|
||||||
|
|
||||||
|
**TODO: assignment, functions, lists, maps, flow control, whitespace and newlines**
|
||||||
92
make_docs
Executable file
92
make_docs
Executable file
@ -0,0 +1,92 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import markdown
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# from finch import FinchLexer
|
||||||
|
|
||||||
|
TEMPLATE = """
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
|
||||||
|
<title>wren {title}</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Sanchez:400|Source+Sans+Pro:300,400,700,400italic,700italic|Source+Code+Pro:300,400' rel='stylesheet' type='text/css'>
|
||||||
|
</head>
|
||||||
|
<body id="top">
|
||||||
|
<a href="https://github.com/munificent/wren">
|
||||||
|
<img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub">
|
||||||
|
</a>
|
||||||
|
<div class="header">
|
||||||
|
<div class="column">
|
||||||
|
<h1><a href="index.html">wren</a> <small>a scripting language</small></h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="index.html">welcome</a></li>
|
||||||
|
<li><a href="syntax.html">syntax</a></li>
|
||||||
|
<li><a href="classes.html">classes</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<h1>{title}</h1>
|
||||||
|
{html}
|
||||||
|
<p class="footer">Last modified on {mod}. By Bob Nystrom.</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
|
def format_file(path):
|
||||||
|
basename = os.path.basename(path)
|
||||||
|
basename = basename.split('.')[0]
|
||||||
|
|
||||||
|
title = ""
|
||||||
|
|
||||||
|
# Read the markdown file and preprocess it.
|
||||||
|
contents = ""
|
||||||
|
with open(path, "r") as input:
|
||||||
|
# Read each line, preprocessing the special codes.
|
||||||
|
for line in input:
|
||||||
|
stripped = line.lstrip()
|
||||||
|
indentation = line[:len(line) - len(stripped)]
|
||||||
|
|
||||||
|
if stripped.startswith("^"):
|
||||||
|
command,_,args = stripped.rstrip("\n").lstrip("^").partition(" ")
|
||||||
|
args = args.strip()
|
||||||
|
|
||||||
|
if command == "title":
|
||||||
|
title = args
|
||||||
|
else:
|
||||||
|
print "UNKNOWN COMMAND:", command, args
|
||||||
|
|
||||||
|
else:
|
||||||
|
contents = contents + line
|
||||||
|
|
||||||
|
html = markdown.markdown(contents, ['def_list', 'codehilite'])
|
||||||
|
|
||||||
|
modified = datetime.fromtimestamp(os.path.getmtime(path))
|
||||||
|
mod_str = modified.strftime('%B %d, %Y')
|
||||||
|
|
||||||
|
fields = {'title': title, 'html': html, 'mod': mod_str}
|
||||||
|
|
||||||
|
# Write the html output.
|
||||||
|
with open("build/site/" + basename + ".html", 'w') as out:
|
||||||
|
out.write(TEMPLATE.format(**fields))
|
||||||
|
|
||||||
|
print "converted", basename
|
||||||
|
|
||||||
|
# Clean the output directory.
|
||||||
|
if os.path.exists("build/site"):
|
||||||
|
shutil.rmtree("build/site")
|
||||||
|
os.mkdir("build/site")
|
||||||
|
|
||||||
|
# Process each markdown file.
|
||||||
|
for f in glob.iglob("doc/site/*.markdown"):
|
||||||
|
format_file(f)
|
||||||
|
|
||||||
|
# Copy the CSS file.
|
||||||
|
shutil.copyfile("doc/site/style.css", "build/site/style.css")
|
||||||
Reference in New Issue
Block a user