Start hacking on web site.

This commit is contained in:
Bob Nystrom
2013-11-21 21:38:36 -08:00
parent 359481f260
commit d332eed048
5 changed files with 385 additions and 0 deletions

View File

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

32
doc/site/index.markdown Normal file
View 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
View 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
View 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
View 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")