Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

186 lines (160 sloc) 6.107 kb
{spawn, exec} = require \child_process
# ANSI Terminal Colors.
bold = '\33[0;1m'
red = '\33[0;31m'
green = '\33[0;32m'
reset = '\33[0m'
tint = (text, color ? green) -> color + text + reset
# Run our node/coco interpreter.
run = (args) ->
proc = spawn \bin/coco args
proc.stderr.on \data say
proc .on \exit -> process.exit it if it
slobber = (path, code) ->
spit path, code
say '* ' + path
minify = ->
{parser, uglify} = require \uglify-js
ast = parser.parse it
ast = uglify.ast_mangle ast
ast = uglify.ast_squeeze ast
uglify.gen_code ast
option \prefix 'set the installation prefix for `install`' \DIR
task \install 'install Coco into /usr/local (or --prefix)' (options) ->
base = options.prefix or \/usr/local
lib = "#base/lib/coco"
bin = "#base/bin"
nlib = \~/.node_libraries
e, stdout, stderr <- exec """
echo Installing Coco to #lib
mkdir -p #lib #bin #nlib
cp -rf lib LICENSE README.md package.json #lib
ln -sfv #lib/lib/command.js #bin/coco
ln -sfv #lib/lib/coke.js #bin/coke
ln -sfnv #lib/lib #nlib/coco
"""replace /\n/g \&&
say stdout.trim! if stdout
say if e then stderr.trim! else tint \done
docs = <[ doc.co lang-co.co ]>
task \build 'build lib/ from src/' ->
ext = /\.co$/; webs = docs.concat \mode-coco.co
sources = for file of dir \src
\src/ + file if ext.test file and file not of webs
run [\-bco \lib]concat sources
task \build:full 'build twice and run tests' ->
exec 'bin/coke build && bin/coke build && bin/coke test'
, (err, stdout, stderr) ->
say stdout.trim! if stdout
say stderr.trim! if stderr
throw err if err
task \build:parser 'build lib/parser.js from lib/grammar.js' ->
spit \lib/parser.js,
require(\./lib/grammar)generate!
.replace /^[^]+?var (?=parser = {)/ \exports.
.replace /\ncase \d+:\nbreak;/g ''
.replace /return parser;[^]+/ ''
.replace /(:[^]+?break;)(?=\ncase \d+\1)/g \:
.replace /(:return .+)\nbreak;/g \$1
task \build:doc 'build doc/' ->
<- docs.forEach
name = it.slice 0 -3; js = require(\./lib/coco)compile slurp \src/ + it
fs.writeFile "doc/#name.raw.js" js
slobber "doc/#name.js" minify js
task \build:browser 'build extras/' ->
Coco = require \./lib/coco
js = Coco.compile slurp \src/mode-coco.co
fs.writeFile \extras/mode-coco.raw.js js
slobber \extras/mode-coco.js minify js
co = ''
for name of <[ lexer ast coco ]>
code = slurp("src/#name.co")replace /\n/g '\n '
co += "let exports = require'./#name' = {}\n#code\n"
fs.writeFile \extras/coco.raw.js js = """
this.Coco = function(){
function require(path){ return require[path] }
var exports = require['./parser'] = {}; #{ slurp \lib/parser.js }
#{ Coco.compile co, {+bare} }
return require['./coco']
}()
this.window && function(){\n#{ slurp \lib/browser.js }\n}()
this.WSH && function(){\n#{ slurp \lib/wsh.js }\n}()
this.Coco
"""
slobber \extras/coco.js """
// Coco #{Coco.VERSION}
// Copyright 2011, Jeremy Ashkenas + Satoshi Murakami
// Released under the MIT License
http://satyr.github.com/coco
#{ minify js };
"""
invoke \test:browser
coreSources = -> "src/#src.co" for src of <[ coco grammar lexer ast ]>
task \bench 'quick benchmark of compilation time' ->
Coco = require \./lib/coco
co = coreSources!map(-> slurp it)join \\n
fmt = -> "#bold#{ " #it"slice -4 }#reset ms"
total = nc = 0
now = Date.now!
time = -> total += ms = -(now - now := Date.now!); fmt ms
tokens = Coco.lex co
msg = "Lex #{time!} (#{tokens.length} tokens)\n"
Coco.tokens.rewrite tokens
msg += "Rewrite #{time!} (#{tokens.length} tokens)\n"
tree = Coco.ast tokens
msg += "Parse #{time!} (%s nodes)\n"
js = tree.compileRoot {+bare}
msg += "Compile #{time!} (#{js.length} chars)\n" +
"TOTAL #{ fmt total }"
tree.traverseChildren (-> ++nc; void), true
console.log msg, nc
task \loc 'count the lines of main compiler code' ->
count = 0; line = /^[^\n\S]*[^#\s]/mg
++count while line.test code for code of coreSources!map -> slurp it
console.log count
task \test 'run test/' -> runTests require \./lib/coco
task \test:browser 'run test/ against extras/coco.js' ->
runTests (new new Function slurp \extras/coco.js)Coco
task \test:json 'test JSON {de,}serialization' ->
{ast} = require \./lib/coco
json = ast slurp \src/ast.co .stringify!
code = ast.parse json .compileRoot {+bare}
exec 'diff -u lib/ast.js -' (e, out) -> say e || out.trim! || tint \ok
.stdin.end code
function runTests global.Coco
startTime = Date.now!
passedTests = failedTests = 0
for name, func in require \assert then let
global[name] = -> func ...; ++passedTests
global <<<
eq: strictEqual
throws: (msg, fun) ->
try do fun catch return eq e?message, msg
ok false "should throw: #msg"
process.on \exit ->
time = ((Date.now! - startTime) / 1e3)toFixed 2
message = "passed #passedTests tests in #time seconds"
say if failedTests
then tint "failed #failedTests and #message" red
else tint message
dir(\test)forEach (file) ->
return unless /\.co$/i.test file
code = slurp filename = path.join \test file
try Coco.run code, {filename} catch
++failedTests
return say e unless stk = e?stack
msg = e.message or ''+ /^[^]+?(?=\n at )/exec stk
if m = /^(AssertionError:) "(.+)" (===) "(.+)"$/exec msg
m[i] = tint m[i]replace(/\\n/g \\n), bold for i of [2 4]
msg = m.slice(1)join \\n
[, row, col]? = //#filename:(\d+):(\d+)\)?$//m.exec stk
if row and col
say tint "#msg\n#{red}at #filename:#{row--}:#{col--}" red
code = Coco.compile code, {+bare}
else if /\bon line (\d+)\b/exec msg
say tint msg, red
row = that.1 - 1
col = 0
else return say stk
{(row): line} = lines = code.split \\n
lines[row] = line.slice(0 col) + tint line.slice(col), bold
say lines.slice(row-8 >? 0, row+9)join \\n
Jump to Line
Something went wrong with that request. Please try again.