var window = this;
var nil;
+var lisp = {};
+
globalEval = eval; // Just an indirect eval
function pv (x) { return x==undefined? nil: x; }
}
}
+// Return a new Array of strings, each either length-1, or length-2 (a UTF-16 surrogate pair).
+function codepoints(string) {
+ return string.split(/(?![\udc00-\udfff])/);
+}
// Create and return a lisp string for the Javascript string STRING.
function make_lisp_string (string){
- var array = string.split("");
- array.type = 'character'
+ var array = codepoints(string);
+ array.stringp = 1
return array;
}
+function char_to_codepoint(ch) {
+ if (ch.length == 1) {
+ return ch.charCodeAt(0);
+ } else {
+ var xh = ch.charCodeAt(0) - 0xD800;
+ var xl = ch.charCodeAt(1) - 0xDC00;
+ return 0x10000 + (xh << 10) + (xl);
+ }
+}
+
+function char_from_codepoint(x) {
+ if (x <= 0xFFFF) {
+ return String.fromCharCode(x);
+ } else {
+ x -= 0x10000;
+ var xh = x >> 10;
+ var xl = x & 0x3FF;
+ return String.fromCharCode(0xD800 + xh) + String.fromCharCode(0xDC00 + xl);
+ }
+}
+
+// if a char (JS string) has the same number of codepoints after .toUpperCase(), return that, else the original.
+function safe_char_upcase(x) {
+ var xu = x.toUpperCase();
+ if (codepoints(xu).length == 1) {
+ return xu;
+ } else {
+ return x;
+ }
+}
+function safe_char_downcase(x) {
+ var xl = x.toLowerCase();
+ if (codepoints(xl).length == 1) {
+ return xl;
+ } else {
+ return x;
+ }
+}
+
function xstring(x){ return x.join(''); }
+function Symbol(name, package_name){
+ this.name = name;
+ if (package_name)
+ this['package'] = package_name;
+}
+
function lisp_to_js (x) {
- if (typeof x == 'object' && 'length' in x && x.type == 'character')
+ if (typeof x == 'object' && 'length' in x && x.stringp == 1)
return xstring(x);
else if (typeof x == 'function'){
// Trampoline calling the Lisp function
return (function(){
- return x.apply(this, [pv, arguments.length] + Array.prototype.slice.call(arguments));
- })
+ var args = Array.prototype.slice.call(arguments);
+ for (var i in args)
+ args[i] = js_to_lisp(args[i]);
+ return lisp_to_js(x.apply(this, [pv, arguments.length].concat(args)));
+ });
}
else return x;
}
else if (typeof x == 'function'){
// Trampoline calling the JS function
return (function(values, nargs){
- return x.apply(this, Array.prototype.slice.call(arguments, 2));
- })
+ var args = Array.prototype.slice.call(arguments, 2);
+ for (var i in args)
+ args[i] = lisp_to_js(args[i]);
+ return values(js_to_lisp(x.apply(this, args)));
+ });
} else return x;
}