Skip to content

Commit

Permalink
hoisted catchee (jashkenas/coffeescript#2422)
Browse files Browse the repository at this point in the history
  • Loading branch information
satyr committed Jul 24, 2012
1 parent 547bb66 commit 070edd1
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 58 deletions.
21 changes: 14 additions & 7 deletions lib/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -2814,7 +2814,7 @@ exports.Try = Try = (function(superclass){
var prototype = extend$(Try, superclass).prototype, constructor = Try;
function Try(attempt, thrown, recovery, ensure){
this.attempt = attempt;
this.thrown = thrown != null ? thrown : 'e$';
this.thrown = thrown;
this.recovery = recovery;
this.ensure = ensure;
}
Expand All @@ -2839,15 +2839,22 @@ exports.Try = Try = (function(superclass){
return this;
};
prototype.compileNode = function(o){
var code, v;
var code, that;
o.indent += TAB;
code = "try " + this.compileBlock(o, this.attempt);
code = 'try ' + this.compileBlock(o, this.attempt);
if (this.recovery || !this.ensure) {
o.scope.check(v = this.thrown || 'e') || o.scope.add(v, 'catch');
code += " catch (" + v + ") " + this.compileBlock(o, this.recovery);
code += ' catch (e$) {';
if (this.recovery) {
code += '\n' + o.indent + o.scope.declare(this.thrown || 'e', this) + ' = e$;';
if (that = this.recovery.compile(o)) {
code += '\n' + that;
}
code += '\n' + this.tab;
}
code += '}';
}
if (this.ensure) {
code += " finally " + this.compileBlock(o, this.ensure);
if (that = this.ensure) {
code += ' finally ' + this.compileBlock(o, that);
}
return code;
};
Expand Down
4 changes: 3 additions & 1 deletion lib/browser.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
var type, sink, i$, ref$, len$, script, that;
Coco.stab = function(code, callback, filename, error){
var e;
try {
Coco.run(code, {
filename: filename
});
} catch (e) {
} catch (e$) {
e = e$;
error = e;
}
return callback(error);
Expand Down
5 changes: 3 additions & 2 deletions lib/coco.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ parser.lexer = {
};
exports.VERSION = '0.7.7b';
exports.compile = function(code, options){
var that;
var e, that;
try {
return parser.parse(lexer.lex(code)).compileRoot(options);
} catch (e) {
} catch (e$) {
e = e$;
if (that = options != null ? options.filename : void 8) {
e.message += "\nat " + that;
}
Expand Down
13 changes: 8 additions & 5 deletions lib/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ function compileScript(filename, input, base){
} else {
writeJS(filename, t.output, base);
}
} catch (e) {
} catch (e$) {
e = e$;
if (e != null) {
if (Coco.listeners('failure').length) {
Coco.emit('failure', e, t);
Expand Down Expand Up @@ -308,10 +309,11 @@ function repl(){
global.exports = exports;
global.require = require;
server = (ref$ = clone$(require('repl').REPLServer.prototype), ref$.context = global, ref$.commands = [], ref$.useGlobal = true, ref$.useColors = process.env.NODE_DISABLE_COLORS, ref$.eval = function(code, arg$, arg1$, cb){
var res, err;
var res, e, err;
try {
res = vm.runInThisContext(code, 'repl');
} catch (e) {
} catch (e$) {
e = e$;
err = e;
}
cb(err, res);
Expand All @@ -329,7 +331,7 @@ function repl(){
});
rl.on('close', bind$(process, 'exit'));
rl.on('line', function(it){
var _;
var e, _;
if (0 < cont && cont < 3) {
code += it + '\n';
this.output.write(repeatString$('.', prompt.length) + '. ');
Expand All @@ -354,7 +356,8 @@ function repl(){
say(_);
}
}
} catch (e) {
} catch (e$) {
e = e$;
say(e);
}
reset();
Expand Down
2 changes: 1 addition & 1 deletion lib/grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ bnf = {
OptComma: [o(''), o(',')],
Lines: [
o('', function(){
return Block();
return L(Block());
}), o('Line', function(){
return Block($1);
}), o('Lines NEWLINE Line', function(){
Expand Down
9 changes: 6 additions & 3 deletions lib/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ exports.tokenize = function(code, o){
};
exports.dent = 0;
exports.doID = function(code, index){
var match, input, id, last, ref$, tag, that;
var match, input, id, e, last, ref$, tag, that;
input = (match = (ID.lastIndex = index, ID).exec(code))[0];
if (!input) {
return 0;
Expand All @@ -95,7 +95,8 @@ exports.doID = function(code, index){
if (NONASCII.test(id)) {
try {
Function("var " + id);
} catch (e) {
} catch (e$) {
e = e$;
this.carp("invalid identifier \"" + id + "\"");
}
}
Expand Down Expand Up @@ -860,9 +861,11 @@ exports.strnum = function(it){
this.token('STRNUM', it, this.adi() || this.last[0] === 'DOT');
};
exports.regex = function(body, flag){
var e;
try {
RegExp(body);
} catch (e) {
} catch (e$) {
e = e$;
this.carp(e.message);
}
if (flag === '$') {
Expand Down
10 changes: 6 additions & 4 deletions lib/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module.exports = function(Coco){
fs = require('fs');
path = require('path');
Coco.run = function(code, options, js){
var filename, main, dirname, ref$;
var filename, main, dirname, ref$, e;
if (options != null) {
filename = options.filename;
}
Expand All @@ -19,20 +19,22 @@ module.exports = function(Coco){
js || (code = Coco.compile(code, (ref$ = {}, import$(ref$, options), ref$.bare = true, ref$)));
try {
return main._compile(code, filename);
} catch (e) {
} catch (e$) {
e = e$;
throw hackTrace(e, code, filename);
}
};
importAll$(Coco, require('events').EventEmitter.prototype);
require.extensions['.co'] = function(module, filename){
var js;
var js, e;
js = Coco.compile(fs.readFileSync(filename, 'utf8'), {
filename: filename,
bare: true
});
try {
return module._compile(js, filename);
} catch (e) {
} catch (e$) {
e = e$;
throw hackTrace(e, js, filename);
}
};
Expand Down
2 changes: 1 addition & 1 deletion lib/parser.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions src/ast.co
Original file line number Diff line number Diff line change
Expand Up @@ -1719,7 +1719,7 @@ class exports.For extends While
#### Try
# Classic `try`-`catch`-`finally` block with optional `catch`.
class exports.Try extends Node
(@attempt, @thrown ? \e$, @recovery, @ensure) ->
(@attempt, @thrown, @recovery, @ensure) ->

children: <[ attempt recovery ensure ]>

Expand All @@ -1738,12 +1738,16 @@ class exports.Try extends Node

compileNode: (o) ->
o.indent += TAB
code = "try #{@compileBlock o, @attempt}"
code = 'try ' + @compileBlock o, @attempt
if @recovery or not @ensure
o.scope.check(v = @thrown or \e) or o.scope.add v, \catch
code += " catch (#v) #{ @compileBlock o, @recovery }"
if @ensure
code += " finally #{ @compileBlock o, @ensure }"
code += ' catch (e$) {'
if @recovery
code += \\n + o.indent +
o.scope.declare(@thrown or \e, this) + ' = e$;'
code += \\n + that if @recovery.compile o
code += \\n + @tab
code += \}
code += ' finally ' + @compileBlock o, that if @ensure
code

#### Switch
Expand Down
2 changes: 1 addition & 1 deletion src/grammar.co
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ bnf =

# A list of lines, separated by newlines or semicolons.
Lines:
o '' -> Block!
o '' -> L Block!
o \Line -> Block $1
o 'Lines NEWLINE Line' -> $1.add $3
o 'Lines NEWLINE'
Expand Down
12 changes: 12 additions & 0 deletions test/operator.co
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,18 @@ eq(+ +1, - -1)
eq -1, - --[2]0


### `throw`
throws 'up' -> throw Error 'up'

# from anywhere.
try [throw 0] catch
eq e, 0

# `null` when empty.
try throw catch
eq e, null


### `do`
eq '', do do do -> -> -> do String
eq 1, do -> 1
Expand Down
61 changes: 34 additions & 27 deletions test/try.co
Original file line number Diff line number Diff line change
@@ -1,25 +1,42 @@
# Basic exception throwing.
throws 'up', -> throw Error 'up'
n = 1
try
n *= 2
throw \error
n *= 3
catch error
n *= 5
finally
n *= 7
eq n, 70

# Hoist `catch`ee.
eq error, \error

# Basic try/catch.
eq 5, try throw 'error' catch err err.length

eq 2, try
throw 'up'
catch e
e.length
# Allow one-liners.
try x = 0 catch _ ok false finally ++x
eq x, 1

eq 1, try
throw o = i: 0
catch e
++e.i
finally
++o.i
eq o.i, 2

# Declare `e` by default.
try throw 0 catch
eq e, 0


# Return results.
eq 1 let
try 1
finally 2

eq 2 let
try throw 1
catch 2
finally 3

eq 3 try 3

# try/catch with empty clauses still compiles.

# Tolerate empty blocks.
try

try catch
Expand All @@ -36,16 +53,6 @@ finally
#!nothing


# Nested implicit indentations
# Tolerate nested implicit blocks.
eq 1, do -> try 1
eq 2, do -> try do -> throw 1 catch do -> 2 finally


# Empty `throw`
try throw
catch
eq null e


# `throw` from anywhere
eq 0, try [throw 0] catch then e

0 comments on commit 070edd1

Please sign in to comment.