mirror of
https://github.com/samsonjs/elisp.js.git
synced 2026-04-05 11:05:50 +00:00
133 lines
3.6 KiB
JavaScript
133 lines
3.6 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.
|
|
|
|
|
|
/****************************************************************
|
|
**** Primitives ************************************************
|
|
****************************************************************/
|
|
|
|
EL.PrimitiveVariables = [
|
|
['t', {
|
|
type: 'variable',
|
|
value: ['symbol', 't'],
|
|
docstring: "true"
|
|
}],
|
|
['nil', {
|
|
type: 'variable',
|
|
value: ['symbol', 'nil'],
|
|
docstring: "nil"
|
|
}]
|
|
];
|
|
|
|
// 'this' is bound to the EL.Evaluator object
|
|
EL.PrimitiveFunctions = [
|
|
['symbol-name', {
|
|
type: 'primitive',
|
|
name: 'symbol-name',
|
|
params: ['symbol'],
|
|
body: function(symbol) { return EL.string(EL.val(symbol)); },
|
|
docstring: "Return a symbol's name, a string."
|
|
}],
|
|
|
|
['string-match', {
|
|
type: 'primitive',
|
|
name: 'string-match',
|
|
params: ['regex', 'string', '&optional', 'start'],
|
|
body: function(regex, string, start) {
|
|
var index = start ? EL.val(start) : 0,
|
|
s = EL.val(string).substring(index),
|
|
match = s.match(new RegExp(EL.val(regex))),
|
|
found = match ? EL.number(s.indexOf(match[0])) : EL.nil;
|
|
return found;
|
|
},
|
|
docstring: "Return the index of the char matching regex in string, beginning from start if available."
|
|
}],
|
|
|
|
['+', {
|
|
type: 'primitive',
|
|
name: '+',
|
|
params: [/* ... */],
|
|
body: function() {
|
|
var args = EL.Util.shallowCopy(arguments),
|
|
initial = EL.inferType(args),
|
|
type = initial[0];
|
|
return EL.Util.reduce(function(sum, n) {
|
|
return [type, EL.val(sum) + EL.val(n)];
|
|
}, initial, args);
|
|
},
|
|
docstring: "add two numbers"
|
|
}],
|
|
['-', {
|
|
type: 'primitive',
|
|
name: '-',
|
|
params: [/* ... */],
|
|
body: function() {
|
|
return EL.Util.foldr(function(diff, n) {
|
|
return EL.number(EL.val(diff) - EL.val(n));
|
|
}, EL.number(0), EL.Util.shallowCopy(arguments));
|
|
},
|
|
docstring: "subtract two numbers"
|
|
}],
|
|
['*', {
|
|
type: 'primitive',
|
|
name: '*',
|
|
params: [/* ... */],
|
|
body: function() {
|
|
return EL.Util.reduce(function(prod, n) {
|
|
return EL.number(EL.val(prod) * EL.val(n));
|
|
}, EL.number(1), EL.Util.shallowCopy(arguments));
|
|
},
|
|
docstring: "multiply two numbers"
|
|
}],
|
|
['/', {
|
|
type: 'primitive',
|
|
name: '/',
|
|
params: [/* ... */],
|
|
body: function() {
|
|
return EL.Util.foldr(function(quot, n) {
|
|
return EL.number(EL.val(quot) / EL.val(n));
|
|
}, EL.number(1), EL.Util.shallowCopy(arguments));
|
|
},
|
|
docstring: "divide two numbers"
|
|
}],
|
|
['print', {
|
|
type: 'primitive',
|
|
name: 'print',
|
|
params: ['x'],
|
|
body: function(x, tostring) {
|
|
var buffer = "",
|
|
tag = EL.tag(x);
|
|
function p(s) {
|
|
if (tostring) buffer += s;
|
|
else print(s);
|
|
}
|
|
if (tag == 'number' || tag == 'symbol' || tag == 'string') {
|
|
p(EL.val(x));
|
|
}
|
|
else if (tag == 'lambda') {
|
|
var fn = EL.val(x);
|
|
p('(lambda ' + fn.name + ' (' + fn.params + ')\n');
|
|
p(fn.body); // TODO lisp pretty print
|
|
p(')');
|
|
}
|
|
else if (tag == 'list') {
|
|
var recurse = arguments.callee; // far easier to remember than Y
|
|
print('(', El.val(x).map(function(e){return (recurse(e, true) + ' ');}), ")");
|
|
}
|
|
else {
|
|
print('unknown type: ' + x);
|
|
}
|
|
return EL.nil;
|
|
},
|
|
docstring: "print an expression"
|
|
}]
|
|
];
|
|
|
|
|
|
/****************************************************************
|
|
****************************************************************/
|