added full complement of bitwise operators

This commit is contained in:
Jeremy Ashkenas
2009-12-19 22:55:58 -05:00
parent 9ba1ffde21
commit 93bdfcb72a
8 changed files with 143 additions and 8 deletions

View File

@@ -17,8 +17,16 @@ end
desc "Build the documentation page" desc "Build the documentation page"
task :doc do task :doc do
rendered = ERB.new(File.read('documentation/index.html.erb')).result(binding) source = 'documentation/index.html.erb'
File.open('index.html', 'w+') {|f| f.write(rendered) } loop do
mtime = File.stat(source).mtime
if !@mtime || mtime > @mtime
rendered = ERB.new(File.read(source)).result(binding)
File.open('index.html', 'w+') {|f| f.write(rendered) }
end
@mtime = mtime
sleep 1
end
end end
namespace :gem do namespace :gem do

6
TODO
View File

@@ -7,10 +7,12 @@ TODO:
* Figure out a generic way to transform statements into expressions, and * Figure out a generic way to transform statements into expressions, and
use it recursively for returns and assigns on whiles, fors, ifs, etc. use it recursively for returns and assigns on whiles, fors, ifs, etc.
* If we manage to get array comprehensions working ... object comprehensions?
* Create the documentation page. (amy, idle) * Create the documentation page. (amy, idle)
uv -c . -s coffeescript -t amy --no-lines examples/code.cs > code.html uv -c . -s coffeescript -t amy --no-lines examples/code.cs > code.html
* Object comprehensions would be easy to add to array comprehensions -- if
we knew that the variable in question is, indeed, an object. Check for
length? Special syntax to tag it?
* Is it possible to close blocks (functions, ifs, trys) without an explicit * Is it possible to close blocks (functions, ifs, trys) without an explicit
block delimiter or significant whitespace? block delimiter or significant whitespace?

View File

@@ -0,0 +1,59 @@
body {
font-size: 16px;
line-height: 24px;
background: #f0f0e5;
color: #252519;
font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
}
div.container {
width: 720px;
margin: 50px 0 50px 50px;
}
p {
width: 550px;
}
#documentation p {
margin-bottom: 4px;
}
a, a:visited {
padding: 0 2px;
text-decoration: none;
background: #dadaba;
color: #252519;
}
a:active, a:hover {
color: #000;
background: #f0c095;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 40px;
}
b.header {
font-size: 18px;
}
span.alias {
font-size: 14px;
font-style: italic;
margin-left: 20px;
}
table, tr, td {
margin: 0; padding: 0;
}
td {
padding: 2px 12px 2px 0;
}
code, pre, tt {
font-family: Monaco, Consolas, "Lucida Console", monospace;
font-size: 12px;
line-height: 18px;
color: #555529;
}
code {
margin-left: 20px;
}
pre {
font-size: 12px;
padding: 2px 0 2px 12px;
border-left: 6px solid #aaaa99;
margin: 0px 0 30px;
}

View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>CoffeeScript</title>
<link rel="stylesheet" type="text/css" href="documentation/css/docs.css" />
</head>
<body>
<div class="container">
<h1>CoffeeScript</h1>
<p>
CoffeeScript is a little language that compiles into JavaScript. Think
of it as JavaScript's simpleminded kid brother &mdash; the same genes,
the same accent, but another kind of way of doing things.
</p>
</div>
</body>
</html>

23
index.html Normal file
View File

@@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>CoffeeScript</title>
<link rel="stylesheet" type="text/css" href="documentation/css/docs.css" />
</head>
<body>
<div class="container">
<h1>CoffeeScript</h1>
<p>
CoffeeScript is a little language that compiles into JavaScript. Think
of it as JavaScript's simpleminded kid brother &mdash; the same genes,
the same accent, but another kind of way of doing things.
</p>
</div>
</body>
</html>

View File

@@ -23,6 +23,7 @@ Usage:
def initialize def initialize
@mtimes = {} @mtimes = {}
parse_options parse_options
return eval_scriptlet if @options[:eval]
check_sources check_sources
@sources.each {|source| compile_javascript(source) } @sources.each {|source| compile_javascript(source) }
watch_coffee_scripts if @options[:watch] watch_coffee_scripts if @options[:watch]
@@ -88,6 +89,11 @@ Usage:
stdout.close and stderr.close stdout.close and stderr.close
end end
# Eval a little piece of CoffeeScript directly from the command line.
def eval_scriptlet
puts CoffeeScript.compile(@sources.join(' '))
end
# Print the tokens that the lexer generates from a source script. # Print the tokens that the lexer generates from a source script.
def tokens(source) def tokens(source)
puts Lexer.new.tokenize(File.read(source)).inspect puts Lexer.new.tokenize(File.read(source)).inspect
@@ -135,6 +141,9 @@ Usage:
opts.on('-l', '--lint', 'pipe the compiled JavaScript through JSLint') do |l| opts.on('-l', '--lint', 'pipe the compiled JavaScript through JSLint') do |l|
@options[:lint] = true @options[:lint] = true
end end
opts.on('-e', '--eval', 'eval a little scriptlet directly from the cli') do |e|
@options[:eval] = true
end
opts.on('-t', '--tokens', 'print the tokens that the lexer produces') do |t| opts.on('-t', '--tokens', 'print the tokens that the lexer produces') do |t|
@options[:tokens] = true @options[:tokens] = true
end end

View File

@@ -17,9 +17,11 @@ token JS
# Declare order of operations. # Declare order of operations.
prechigh prechigh
nonassoc UMINUS NOT '!' nonassoc UMINUS NOT '!' '~'
left '*' '/' '%' left '*' '/' '%'
left '+' '-' left '+' '-'
left '<<' '>>' '>>>'
left '&' '|' '^'
left '<=' '<' '>' '>=' left '<=' '<' '>' '>='
right '==' '!=' IS AINT right '==' '!=' IS AINT
left '&&' '||' AND OR left '&&' '||' AND OR
@@ -127,6 +129,7 @@ rule
'!' Expression { result = OpNode.new(val[0], val[1]) } '!' Expression { result = OpNode.new(val[0], val[1]) }
| '-' Expression = UMINUS { result = OpNode.new(val[0], val[1]) } | '-' Expression = UMINUS { result = OpNode.new(val[0], val[1]) }
| NOT Expression { result = OpNode.new(val[0], val[1]) } | NOT Expression { result = OpNode.new(val[0], val[1]) }
| '~' Expression { result = OpNode.new(val[0], val[1]) }
| Expression '*' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '*' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '/' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '/' Expression { result = OpNode.new(val[1], val[0], val[2]) }
@@ -135,6 +138,14 @@ rule
| Expression '+' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '+' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '-' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '-' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '<<' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '>>' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '>>>' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '&' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '|' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '^' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '<=' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '<=' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '<' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '<' Expression { result = OpNode.new(val[1], val[0], val[2]) }
| Expression '>' Expression { result = OpNode.new(val[1], val[0], val[2]) } | Expression '>' Expression { result = OpNode.new(val[1], val[0], val[2]) }

View File

@@ -68,8 +68,8 @@ module CoffeeScript
"(function(){\n#{compile(TAB, Scope.new)}\n})();" "(function(){\n#{compile(TAB, Scope.new)}\n})();"
end end
# The extra fancy is to handle pushing down returns recursively to the # The extra fancy is to handle pushing down returns and assignments
# final lines of inner statements (so as to make expressions out of them). # recursively to the final lines of inner statements.
def compile(indent='', scope=nil, opts={}) def compile(indent='', scope=nil, opts={})
return root_compile unless scope return root_compile unless scope
code = @expressions.map { |n| code = @expressions.map { |n|
@@ -171,7 +171,7 @@ module CoffeeScript
end end
end end
# A value, indexed or dotted into or vanilla. # A value, indexed or dotted into, or vanilla.
class ValueNode < Node class ValueNode < Node
attr_reader :literal, :properties, :last attr_reader :literal, :properties, :last