mirror of
https://github.com/samsonjs/elisp.js.git
synced 2026-03-25 09:15:49 +00:00
113 lines
2.9 KiB
JavaScript
113 lines
2.9 KiB
JavaScript
////
|
|
// Emacs Lisp implementation in JavaScript.
|
|
//
|
|
// Copyright (c) 2009 Sami Samhuri - sami.samhuri@gmail.com
|
|
//
|
|
// Released under the terms of the MIT license. See the included file
|
|
// LICENSE.
|
|
|
|
// data types are simple tags
|
|
EL._defineTags = function() {
|
|
EL.tags = ['symbol', 'string', 'number', 'cons', 'lambda', 'regex'];
|
|
EL.tags.each = Array.prototype.each;
|
|
|
|
// define constructors for the primitive types (box values)
|
|
// e.g. EL.symbol('foo') => ['symbol', 'foo']
|
|
EL.tags.each(function(tag) {
|
|
// don't clobber custom constructors
|
|
if (EL[tag] === undefined) {
|
|
EL[tag] = function(value) {
|
|
return [tag, value];
|
|
};
|
|
}
|
|
// tag type tests
|
|
var isTag = function(expr) {
|
|
return (EL.tag(expr) == tag);
|
|
};
|
|
EL['is' + tag.camelize()] = isTag;
|
|
});
|
|
};
|
|
EL.initHook(EL._defineTags);
|
|
|
|
// shorthands to save my fingers
|
|
EL._defineConstants = function() {
|
|
EL.nil = EL.symbol('nil');
|
|
EL.t = EL.symbol('t');
|
|
};
|
|
EL.initHook(EL._defineConstants);
|
|
|
|
|
|
// retrieve the tag from a value
|
|
EL.tag = function(expr) {
|
|
EL.assert(function() { var f='tag'; return EL.typeOf(expr) == 'array'; }, expr);
|
|
return expr[0];
|
|
};
|
|
|
|
// unbox a value
|
|
EL.val = function(expr) {
|
|
EL.assert(function() { var f='val'; return EL.typeOf(expr) == 'array'; }, expr);
|
|
return expr[1];
|
|
};
|
|
|
|
EL.symbolName = function(symbol) {
|
|
// EL.Util.pp(symbol);
|
|
EL.assert(function(){ var f='symbolName'; return EL.isSymbol(symbol); }, symbol);
|
|
return EL.val(symbol);
|
|
};
|
|
|
|
EL.isNilSymbol = function(expr) {
|
|
return (EL.isSymbol(expr) && EL.symbolName(expr) == 'nil');
|
|
};
|
|
|
|
EL.isNil = function(expr) {
|
|
return EL.isNilSymbol(expr);
|
|
};
|
|
|
|
EL.list = function(exprs) {
|
|
var list = EL.nil,
|
|
i = exprs.length;
|
|
while (--i >= 0) {
|
|
list = EL.cons(exprs[i], list);
|
|
}
|
|
return list;
|
|
};
|
|
|
|
EL.isList = function(expr) {
|
|
return (EL.isNil(expr) || EL.isCons(expr));
|
|
};
|
|
|
|
EL.isAtom = function(expr) {
|
|
return !EL.isCons(expr);
|
|
};
|
|
|
|
EL.inferType = function(exprs) {
|
|
var type = 'number',
|
|
initial = 0,
|
|
i = exprs.length-1;
|
|
while(i >= 0) {
|
|
if (EL.isString(exprs[i--])) {
|
|
type = 'string';
|
|
initial = '';
|
|
break;
|
|
}
|
|
}
|
|
return EL[type](initial);
|
|
};
|
|
|
|
|
|
// special forms
|
|
|
|
EL.isSpecialForm = function(name, expr) {
|
|
var tag = EL.tag(expr),
|
|
car = EL.typeOf(expr) == 'array' && EL.val(expr)[0],
|
|
thisName = car && EL.symbolName(car);
|
|
return (tag == 'cons' && thisName == name);
|
|
};
|
|
|
|
EL.isQuote = function(expr){return EL.isSpecialForm('quote', expr);};
|
|
EL.isDefVar = function(expr){return EL.isSpecialForm('defvar', expr);};
|
|
EL.isDefFunc = function(expr){return EL.isSpecialForm('defun', expr);};
|
|
EL.isSet = function(expr){return EL.isSpecialForm('set', expr);};
|
|
EL.isSetq = function(expr){return EL.isSpecialForm('setq', expr);};
|
|
EL.isCond = function(expr){return EL.isSpecialForm('cond', expr);};
|
|
EL.isIf = function(expr){return EL.isSpecialForm('if', expr);};
|