whalesong/js-assembler/runtime-src/baselib-check.js
2011-09-19 14:02:00 -04:00

293 lines
9.0 KiB
JavaScript

/*jslint vars: true, white: true, plusplus: true, maxerr: 50, indent: 4 */
// Helper functions for argument checking.
(function (baselib) {
'use strict';
var exports = {};
baselib.check = exports;
var EMPTY = baselib.lists.EMPTY;
var isPair = baselib.lists.isPair;
var makeLowLevelEqHash = baselib.hashes.makeLowLevelEqHash;
//////////////////////////////////////////////////////////////////////
// testArgument: (X -> boolean) X number string string -> boolean
// Produces the argument value the predicate is true, and otherwise raises an error.
var testArgument = function (MACHINE,
expectedTypeName,
predicate,
val,
index,
callerName) {
if (predicate(val)) {
return val;
} else {
if (typeof(expectedTypeName) === 'function') {
expectedTypeName = expectedTypeName();
}
baselib.exceptions.raiseArgumentTypeError(MACHINE,
callerName,
expectedTypeName,
index,
val);
}
};
var makeCheckArgumentType = function (predicate, predicateName) {
return function (MACHINE, callerName, position) {
return testArgument(
MACHINE,
predicateName,
predicate,
MACHINE.e[MACHINE.e.length - 1 - position],
position,
callerName);
};
};
var makeCheckParameterizedArgumentType = function (parameterizedPredicate,
parameterizedPredicateName) {
return function (MACHINE, callerName, position) {
var args = [], i;
for (i = 3; i < arguments.length; i++) {
args.push(arguments[i]);
}
return testArgument(
MACHINE,
function () { return parameterizedPredicateName.apply(null, args); },
function (x) {
return parameterizedPredicate.apply(null, [x].concat(args));
},
MACHINE.e[MACHINE.e.length - 1 - position],
position,
callerName);
};
};
var makeCheckListofArgumentType = function (predicate, predicateName) {
var listPredicate = function (x) {
var seen = makeLowLevelEqHash();
while (true) {
if (x === EMPTY){
return true;
}
if (!isPair(x)) {
return false;
}
if(seen.containsKey(x)) {
// raise an error? we've got a cycle!
return false;
}
if (! predicate(x.first)) {
return false;
}
seen.put(x, true);
x = x.rest;
}
};
return function (MACHINE, callerName, position) {
return testArgument(
MACHINE,
'list of ' + predicateName,
listPredicate,
MACHINE.e[MACHINE.e.length - 1 - position],
position,
callerName);
};
};
var testArity = function (MACHINE, callerName, observed, minimum, maximum) {
if (observed < minimum || observed > maximum) {
baselib.exceptions.raise(
MACHINE,
baselib.exceptions.ExnFailContractArity.constructor(
callerName + ": expected at least " + minimum
+ " arguments "
+ " but received " + observed,
MACHINE.captureContinuationMarks()));
}
};
var checkOutputPort = makeCheckArgumentType(
baselib.ports.isOutputPort,
'output port');
var checkSymbol = makeCheckArgumentType(
baselib.symbols.isSymbol,
'symbol');
var checkString = makeCheckArgumentType(
baselib.strings.isString,
'string');
var checkSymbolOrString = makeCheckArgumentType(
function(x) { return (baselib.symbols.isSymbol(x) ||
baselib.strings.isString(x)); },
'symbol or string');
var checkMutableString = makeCheckArgumentType(
baselib.strings.isMutableString,
'mutable string');
var checkChar = makeCheckArgumentType(
baselib.chars.isChar,
'character');
var checkProcedure = makeCheckArgumentType(
baselib.functions.isProcedure,
'procedure');
var checkNumber = makeCheckArgumentType(
baselib.numbers.isNumber,
'number');
var checkReal = makeCheckArgumentType(
baselib.numbers.isReal,
'real');
var checkNatural = makeCheckArgumentType(
baselib.numbers.isNatural,
'natural');
var checkByte = makeCheckArgumentType(
baselib.numbers.isByte,
'byte');
var checkBytes = makeCheckArgumentType(
baselib.bytes.isBytes,
'bytes');
var checkNaturalInRange = makeCheckParameterizedArgumentType(
function (x, a, b) {
if (! baselib.numbers.isNatural(x)) { return false; }
return (baselib.numbers.lessThanOrEqual(a, x) &&
baselib.numbers.lessThan(x, b));
},
function (a, b) {
return baselib.format.format('natural between ~a and ~a', [a, b]);
});
var checkInteger = makeCheckArgumentType(
baselib.numbers.isInteger,
'integer');
var checkRational = makeCheckArgumentType(
baselib.numbers.isRational,
'rational');
var checkNonNegativeReal = makeCheckArgumentType(
baselib.numbers.isNonNegativeReal,
'non-negative real');
var checkPair = makeCheckArgumentType(
baselib.lists.isPair,
'pair');
var checkList = makeCheckArgumentType(
baselib.lists.isList,
'list');
var checkVector = makeCheckArgumentType(
baselib.vectors.isVector,
'vector');
var checkBoolean = makeCheckArgumentType(
function (x) { return x === true || x === false; },
'boolean');
var checkBox = makeCheckArgumentType(
baselib.boxes.isBox,
'box');
var checkMutableBox = makeCheckArgumentType(
baselib.boxes.isMutableBox,
'mutable box');
var checkInspector = makeCheckArgumentType(
baselib.inspectors.isInspector,
'inspector');
var checkPlaceholder = makeCheckArgumentType(
baselib.placeholders.isPlaceholder,
'placeholder');
var checkSrcloc = makeCheckArgumentType(
baselib.srclocs.isSrcloc,
'srcloc');
var checkContinuationMarkSet = makeCheckArgumentType(
baselib.contmarks.isContinuationMarkSet,
'continuation mark set');
var checkContinuationPromptTag = makeCheckArgumentType(
baselib.contmarks.isContinuationPromptTag,
'continuation prompt tag');
var checkExn = makeCheckArgumentType(
baselib.exceptions.isExn,
'exn');
//////////////////////////////////////////////////////////////////////
exports.testArgument = testArgument;
exports.testArity = testArity;
exports.makeCheckArgumentType = makeCheckArgumentType;
exports.makeCheckParameterizedArgumentType = makeCheckParameterizedArgumentType;
exports.makeCheckListofArgumentType = makeCheckListofArgumentType;
exports.checkOutputPort = checkOutputPort;
exports.checkSymbol = checkSymbol;
exports.checkString = checkString;
exports.checkSymbolOrString = checkSymbolOrString;
exports.checkMutableString = checkMutableString;
exports.checkChar = checkChar;
exports.checkProcedure = checkProcedure;
exports.checkNumber = checkNumber;
exports.checkReal = checkReal;
exports.checkNonNegativeReal = checkNonNegativeReal;
exports.checkNatural = checkNatural;
exports.checkNaturalInRange = checkNaturalInRange;
exports.checkByte = checkByte;
exports.checkBytes = checkBytes;
exports.checkInteger = checkInteger;
exports.checkRational = checkRational;
exports.checkPair = checkPair;
exports.checkList = checkList;
exports.checkVector = checkVector;
exports.checkBox = checkBox;
exports.checkMutableBox = checkMutableBox;
exports.checkInspector = checkInspector;
exports.checkByte = checkByte;
exports.checkBoolean = checkBoolean;
exports.checkPlaceholder = checkPlaceholder;
exports.checkSrcloc = checkSrcloc;
exports.checkContinuationMarkSet = checkContinuationMarkSet;
exports.checkContinuationPromptTag = checkContinuationPromptTag;
exports.checkExn = checkExn;
}(this.plt.baselib));