jslinted functions

This commit is contained in:
Danny Yoo 2011-08-07 23:55:56 -04:00
parent 2be2c72754
commit e147f3d6bb

View File

@ -1,9 +1,14 @@
/*jslint unparam: true, sub: true, vars: true, white: true, plusplus: true, maxerr: 50, indent: 4 */
// Procedures
// For historical reasons, this module is called 'functions' instead of 'procedures'.
// This may change soon.
(function(baselib) {
/*global plt*/
(function (baselib) {
'use strict';
var exports = {};
baselib.functions = exports;
@ -16,195 +21,8 @@
// coerseToJavaScript: racket function -> JavaScript function
// Given a closure or primitive, produces an
// asynchronous JavaScript function.
// The function will run on the provided MACHINE.
//
// It assumes that it must begin its own trampoline.
var asJavaScriptFunction = function(v, MACHINE) {
MACHINE = MACHINE || plt.runtime.currentMachine;
if (isPrimitiveProcedure(v)) {
return coersePrimitiveToJavaScript(v, MACHINE);
} else if (isClosure(v)) {
return coerseClosureToJavaScript(v, MACHINE);
} else {
plt.baselib.exceptions.raise(MACHINE,
plt.baselib.exceptions.makeExnFail(
plt.baselib.format.format(
"Not a procedure: ~e",
v)));
}
};
var coersePrimitiveToJavaScript = function(v, MACHINE) {
return function(succ, fail) {
try {
succ = succ || function(){};
fail = fail || function(){};
var oldArgcount = MACHINE.argcount;
MACHINE.argcount = arguments.length - 2;
for (var i = 0; i < arguments.length - 2; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
if (! plt.baselib.arity.isArityMatching(v.racketArity, MACHINE.argcount)) {
fail(new Error(plt.baselib.format.format(
"arity mismatch: expected ~s arguments, but received ~s",
[v.racketArity, MACHINE.argcount])));
return;
}
var result = v(MACHINE);
MACHINE.argcount = oldArgcount;
for (var i = 0; i < arguments.length - 2; i++) {
MACHINE.env.pop();
}
succ(result);
} catch (e) {
fail(e);
}
}
};
var coerseClosureToJavaScript = function(v, MACHINE) {
var f = function(succ, fail) {
succ = succ || function(){};
fail = fail || function(){};
if (! plt.baselib.arity.isArityMatching(v.racketArity, arguments.length - 2)) {
fail(new Error(
plt.baselib.format.format(
"arity mismatch: expected ~s argument(s) but received ~s",
[v.racketArity, arguments.length - 2])));
return;
}
var oldVal = MACHINE.val;
var oldArgcount = MACHINE.argcount;
var oldProc = MACHINE.proc;
var oldErrorHandler = MACHINE.params['currentErrorHandler'];
var afterGoodInvoke = function(MACHINE) {
plt.runtime.PAUSE(
function(restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValue = MACHINE.val;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
succ(returnValue);
});
};
afterGoodInvoke.multipleValueReturn = function(MACHINE) {
plt.runtime.PAUSE(
function(restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValues = [MACHINE.val];
for (var i = 0; i < MACHINE.argcount - 1; i++) {
returnValues.push(MACHINE.env.pop());
}
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
succ.apply(null, returnValues);
});
};
MACHINE.control.push(
new plt.baselib.frames.CallFrame(afterGoodInvoke, null));
MACHINE.argcount = arguments.length - 2;
for (var i = 0; i < arguments.length - 2; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
MACHINE.proc = v;
MACHINE.params['currentErrorHandler'] = function(MACHINE, e) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
fail(e);
};
MACHINE.trampoline(v.label);
};
return f;
};
// internallCallDuringPause: call a Racket procedure and get its results.
// The use assumes the machine is in a running-but-paused state.
var internalCallDuringPause = function(MACHINE, proc, success, fail) {
if (! plt.baselib.arity.isArityMatching(proc.racketArity, arguments.length - 4)) {
return fail(plt.baselib.exceptions.makeExnFailContractArity("arity mismatch"));
}
if (isPrimitiveProcedure(proc)) {
var oldArgcount = MACHINE.argcount;
MACHINE.argcount = arguments.length - 4;
for (var i = 0; i < arguments.length - 4; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
var result = proc(MACHINE);
for (var i = 0; i < arguments.length - 4; i++) {
MACHINE.env.pop();
}
success(result);
} else if (isClosure(proc)) {
var oldVal = MACHINE.val;
var oldArgcount = MACHINE.argcount;
var oldProc = MACHINE.proc;
var oldErrorHandler = MACHINE.params['currentErrorHandler'];
var afterGoodInvoke = function(MACHINE) {
plt.runtime.PAUSE(function(restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValue = MACHINE.val;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
success(returnValue);
});
};
afterGoodInvoke.multipleValueReturn = function(MACHINE) {
plt.runtime.PAUSE(function(restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValues = [MACHINE.val];
for (var i = 0; i < MACHINE.argcount - 1; i++) {
returnValues.push(MACHINE.env.pop());
}
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
success.apply(null, returnValues);
});
};
MACHINE.control.push(
new plt.baselib.frames.CallFrame(afterGoodInvoke, null));
MACHINE.argcount = arguments.length - 4;
for (var i = 0; i < arguments.length - 4; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
MACHINE.proc = proc;
MACHINE.params['currentErrorHandler'] = function(MACHINE, e) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
fail(e);
};
MACHINE.trampoline(proc.label);
} else {
fail(plt.baselib.exceptions.makeExnFail(
plt.baselib.format.format(
"Not a procedure: ~e",
proc)));
}
var isPrimitiveProcedure = function (x) {
return typeof (x) === 'function';
};
@ -221,15 +39,14 @@
// A closure consists of its free variables as well as a label
// into its text segment.
var Closure = function(label, arity, closedVals, displayName) {
this.label = label; // (MACHINE -> void)
this.racketArity = arity; // number
this.closedVals = closedVals; // arrayof number
this.displayName = displayName; // string
var Closure = function (label, arity, closedVals, displayName) {
this.label = label; // (MACHINE -> void)
this.racketArity = arity; // number
this.closedVals = closedVals; // arrayof number
this.displayName = displayName; // string
};
// Finalize the return from a closure. This is a helper function
// for those who implement Closures by hand.
//
@ -243,28 +60,237 @@
//
// I'd personally love for this to be a macro and avoid the
// extra function call here.
var finalizeClosureCall = function(MACHINE) {
var finalizeClosureCall = function (MACHINE) {
MACHINE.callsBeforeTrampoline--;
var i, returnArgs = [].slice.call(arguments, 1);
// clear out stack space
// TODO: replace with a splice.
MACHINE.env.length = MACHINE.env.length - MACHINE.argcount;
MACHINE.env.length = MACHINE.env.length - MACHINE.argcount;
if (returnArgs.length === 1) {
MACHINE.val = returnArgs[0];
return MACHINE.control.pop().label(MACHINE);
return MACHINE.control.pop().label(MACHINE);
} else if (returnArgs.length === 0) {
MACHINE.argcount = 0;
return MACHINE.control.pop().label.multipleValueReturn(MACHINE);
return MACHINE.control.pop().label.multipleValueReturn(MACHINE);
} else {
MACHINE.argcount = returnArgs.length;
MACHINE.val = returnArgs.shift();
// TODO: replace with a splice.
for(i = 0; i < MACHINE.argcount - 1; i++) {
for (i = 0; i < MACHINE.argcount - 1; i++) {
MACHINE.env.push(returnArgs.pop());
}
return MACHINE.control.pop().label.multipleValueReturn(MACHINE);
return MACHINE.control.pop().label.multipleValueReturn(MACHINE);
}
};
var isClosure = function (x) {
return x instanceof Closure;
};
var isProcedure = function (x) {
return (typeof (x) === 'function' ||
x instanceof Closure);
};
var coersePrimitiveToJavaScript = function (v, MACHINE) {
return function (succ, fail) {
try {
succ = succ || function () {};
fail = fail || function () {};
var oldArgcount = MACHINE.argcount, i;
MACHINE.argcount = arguments.length - 2;
for (i = 0; i < arguments.length - 2; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
if (!(baselib.arity.isArityMatching(v.racketArity, MACHINE.argcount))) {
fail(new Error(baselib.format.format("arity mismatch: expected ~s arguments, but received ~s",
[v.racketArity, MACHINE.argcount])));
return;
}
var result = v(MACHINE);
MACHINE.argcount = oldArgcount;
for (i = 0; i < arguments.length - 2; i++) {
MACHINE.env.pop();
}
succ(result);
} catch (e) {
fail(e);
}
};
};
var coerseClosureToJavaScript = function (v, MACHINE) {
var f = function (succ, fail) {
succ = succ || function () {};
fail = fail || function () {};
if (!(baselib.arity.isArityMatching(v.racketArity, arguments.length - 2))) {
fail(new Error(
baselib.format.format(
"arity mismatch: expected ~s argument(s) but received ~s",
[v.racketArity, arguments.length - 2])));
return;
}
var oldVal = MACHINE.val;
var oldArgcount = MACHINE.argcount;
var oldProc = MACHINE.proc;
var oldErrorHandler = MACHINE.params['currentErrorHandler'];
var afterGoodInvoke = function (MACHINE) {
plt.runtime.PAUSE(
function (restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValue = MACHINE.val;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
succ(returnValue);
});
};
afterGoodInvoke.multipleValueReturn = function (MACHINE) {
plt.runtime.PAUSE(
function (restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValues = [MACHINE.val], i;
for (i = 0; i < MACHINE.argcount - 1; i++) {
returnValues.push(MACHINE.env.pop());
}
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
succ.apply(null, returnValues);
});
};
MACHINE.control.push(
new baselib.frames.CallFrame(afterGoodInvoke, null));
MACHINE.argcount = arguments.length - 2;
var i;
for (i = 0; i < arguments.length - 2; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
MACHINE.proc = v;
MACHINE.params['currentErrorHandler'] = function (MACHINE, e) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
fail(e);
};
MACHINE.trampoline(v.label);
};
return f;
};
// coerseToJavaScript: racket function -> JavaScript function
// Given a closure or primitive, produces an
// asynchronous JavaScript function.
// The function will run on the provided MACHINE.
//
// It assumes that it must begin its own trampoline.
var asJavaScriptFunction = function (v, MACHINE) {
MACHINE = MACHINE || plt.runtime.currentMachine;
if (isPrimitiveProcedure(v)) {
return coersePrimitiveToJavaScript(v, MACHINE);
} else if (isClosure(v)) {
return coerseClosureToJavaScript(v, MACHINE);
} else {
baselib.exceptions.raise(MACHINE,
baselib.exceptions.makeExnFail(
baselib.format.format(
"Not a procedure: ~e",
v)));
}
};
// internallCallDuringPause: call a Racket procedure and get its results.
// The use assumes the machine is in a running-but-paused state.
var internalCallDuringPause = function (MACHINE, proc, success, fail) {
var i;
var oldArgcount, oldVal, oldProc, oldErrorHandler;
if (! baselib.arity.isArityMatching(proc.racketArity, arguments.length - 4)) {
return fail(baselib.exceptions.makeExnFailContractArity("arity mismatch"));
}
if (isPrimitiveProcedure(proc)) {
oldArgcount = MACHINE.argcount;
MACHINE.argcount = arguments.length - 4;
for (i = 0; i < arguments.length - 4; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
var result = proc(MACHINE);
for (i = 0; i < arguments.length - 4; i++) {
MACHINE.env.pop();
}
success(result);
} else if (isClosure(proc)) {
oldVal = MACHINE.val;
oldArgcount = MACHINE.argcount;
oldProc = MACHINE.proc;
oldErrorHandler = MACHINE.params['currentErrorHandler'];
var afterGoodInvoke = function (MACHINE) {
plt.runtime.PAUSE(function (restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValue = MACHINE.val;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
success(returnValue);
});
};
afterGoodInvoke.multipleValueReturn = function (MACHINE) {
plt.runtime.PAUSE(function (restart) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
var returnValues = [MACHINE.val];
var i;
for (i = 0; i < MACHINE.argcount - 1; i++) {
returnValues.push(MACHINE.env.pop());
}
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
success.apply(null, returnValues);
});
};
MACHINE.control.push(
new baselib.frames.CallFrame(afterGoodInvoke, null));
MACHINE.argcount = arguments.length - 4;
for (i = 0; i < arguments.length - 4; i++) {
MACHINE.env.push(arguments[arguments.length - 1 - i]);
}
MACHINE.proc = proc;
MACHINE.params['currentErrorHandler'] = function (MACHINE, e) {
MACHINE.params['currentErrorHandler'] = oldErrorHandler;
MACHINE.val = oldVal;
MACHINE.argcount = oldArgcount;
MACHINE.proc = oldProc;
fail(e);
};
MACHINE.trampoline(proc.label);
} else {
fail(baselib.exceptions.makeExnFail(
baselib.format.format(
"Not a procedure: ~e",
proc)));
}
};
@ -273,13 +299,18 @@
var makePrimitiveProcedure = function(name, arity, f) {
var makePrimitiveProcedure = function (name, arity, f) {
f.racketArity = arity;
f.displayName = name;
return f;
};
var makeClosure = function(name, arity, f, closureArgs) {
var makeClosure = function (name, arity, f, closureArgs) {
if (! closureArgs) { closureArgs = []; }
return new Closure(f,
arity,
@ -290,28 +321,15 @@
var isPrimitiveProcedure = function(x) {
return typeof(x) === 'function';
};
var isClosure = function(x) {
return x instanceof Closure;
};
var isProcedure = function(x) {
return (typeof(x) === 'function' ||
x instanceof Closure);
};
var renameProcedure = function(f, name) {
var renameProcedure = function (f, name) {
if (isPrimitiveProcedure(f)) {
return makePrimitiveProcedure(
name,
f.racketArity,
function() {
function () {
return f.apply(null, arguments);
});
} else {
@ -346,4 +364,4 @@
exports.asJavaScriptFunction = asJavaScriptFunction;
})(this['plt'].baselib);
}(this.plt.baselib));