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