Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

174 lines (148 sloc) 5.703 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 \node [\bin/coco]concat args
proc.stderr.on \data say
proc .on \exit -> process.exit it if it
shell = (command) ->
err, sout, serr <- exec command
process.stdout.write sout if sout
process.stderr.write serr if serr
console.log err if err
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
task \install 'install Coco via npm' -> shell 'npm install -g .'
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' ->
shell 'bin/coke build && bin/coke build && bin/coke test'
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 2012, 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"
compileThrows: !(msg, lno, code) ->
throws "#msg on line #lno" !-> Coco.compile code
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.