view jsbackend.js @ 17:7400bb42e0c9

Add direct file edit link support
author Mike Pavone <pavone@retrodev.com>
date Sun, 25 Mar 2012 15:31:10 -0700
parents 6e4851a204a5
children 132c7756860e
line wrap: on
line source

var mainModule;

function toobj(val)
{
	switch(typeof val)
	{
	case 'boolean':
		if(val) {
			return mainModule.strue;
		} else {
			return mainModule.sfalse;
		}
	case 'number':
		return mainModule.snumber(val);
	}
	throw new Error("can't make val into object");
}

function setP(o, p, val)
{
	o[p] = val;
	return o;
}

function getP(o, p)
{
	return o[p];
}

op.prototype.toJS = function(symbols, isReceiver) {
	var ret = '(' + this.left.toJS(symbols) +' '+ (this.op == '=' ? '==' : this.op) +' '+ this.right.toJS(symbols) + ')';
	if (isReceiver) {
		ret = 'toobj' + ret;
	}
	return ret;
};

symbol.prototype.toJS = function(symbols) {
	var name = this.cleanName();
	if (name == 'self') {
		return symbols.selfVar();
	}
	name = name.replace("_", "UN_").replace(":", "CN_").replace("!", "EX_").replace('?', 'QS_').replace('@', 'AT_');
	var reserved = {'true': true, 'false': true, 'this': true, 'if': true, 'else': true, 'NaN': true};
	if (name in reserved) {
		name = 's' + name;
	}
	return name;
}

intlit.prototype.toJS = function(symbols) {
	return this.val.toString();
}

floatlit.prototype.toJS = function(symbols) {
	return this.val.toString();
}

strlit.prototype.toJS = function(symbols) {
	return '"' + this.val.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n').replace('\r', '\\r') + '"';
}

funcall.prototype.toJS = function(symbols) {
	var name = this.name[this.name.length-1] == ':' ? this.name.substr(0, this.name.length-1) : this.name;
	if (name == 'foreign') {
		if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object)) {
			return null;
		} else if(this.args[0] instanceof symbol) {
			return this.args[0].name;
		} else {
			throw new Error("Unexpected AST type for foreign:");
		}
	}
	var args = this.args.slice(0, this.args.length);
	if (this.receiver) {
		args.splice(0, 0, this.receiver);
	}
	var funinfo = symbols.find(name);
	if (!funinfo) {
		var receiver = args[0];
		args.splice(0, 1);
		for (var i in args) {
			args[i] = args[i].toJS(symbols);
		}
		return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
	}
	switch(funinfo.type)
	{
	case 'self':
		if (args.length < funinfo.def.args.length || funinfo.def.args[0].name != 'self') {
			var receiver = new symbol('self');
		} else {
			var receiver = args[0];
			args.splice(0, 1);
		}
		for (var i in args) {
			args[i] = args[i].toJS(symbols);
		}
		return receiver.toJS(symbols, true) + '.' + (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
	case 'parent':
		var ret = 'this';
		for (var i = 0; i < funinfo.depth; ++i) {
			ret += '.parent';
		}
		for (var i in args) {
			args[i] = args[i].toJS(symbols);
		}
		ret += (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
		return ret;
	case 'local':
	case 'upvar':
	case 'foreign':
		for (var i in args) {
			args[i] = args[i].toJS(symbols);
		}
		return (new symbol(name)).toJS(symbols) + '(' + args.join(', ') + ')';
	}
}

object.prototype.toJS = function(symbols) {
	var messages = this.messages;
	symbols = new osymbols(symbols);
	var compiled = []
	for (var i in messages) {
		var js = messages[i].toJSObject(symbols);
		if (js) {
			compiled.push(indent(js));
		}
	}
	return '{\n\tparent: ' + symbols.parentObject() + ',\n\t' + compiled.join(',\n\t') + '\n}';
}

object.prototype.toJSModule = function() {
	return '(function () {\n\tvar module = ' + indent(this.toJS(null)) + ';\n\treturn module;\n})'
}

lambda.prototype.toJS = function(symbols) {
	var args = this.args ? this.args.slice(0, this.args.length) : [];
	if (args.length && args[0].cleanName() == 'self') {
		args.splice(0, 1);
	}
	var exprs = this.expressions;
	symbols = new lsymbols(symbols);
	for (var i in args) {
		symbols.defineVar(args[i].cleanName(), null);
		args[i] = args[i].toJS(symbols);
	}
	var compiled = []
	for (var i in exprs) {
		var js = exprs[i].toJS(symbols);
		if (js) {
			compiled.push(indent(js));
		}
	}
	exprs = compiled;
	if (exprs.length) {
		exprs[exprs.length-1] = 'return ' + exprs[exprs.length-1] + ';';
	}
	return 'function (' + args.join(', ') + ') {\n\t' + (symbols.needsSelfVar ? 'var self = this;\n\t' : '') + exprs.join(';\n\t') + '\n}'
};
lambda.prototype.toJSModule = lambda.prototype.toJS

assignment.prototype.toJS = function(symbols) {
	var existing = symbols.find(this.symbol.name);
	var prefix = '';
	if (!existing) {
		symbols.defineVar(this.symbol.name, this.expression);
		prefix =  'var ';
	} else {
		switch (existing.type)
		{
		case 'self':
			prefix = 'this.';
			break;
		case 'parent':
			prefix = 'this.';
			for (var i = 0; i < existing.depth; ++i) {
				prefix += 'parent.';
			}
			break;
		}
	}
	var val = this.expression.toJS(symbols);
	if (val === null) {
		return null;
	}
	return prefix + this.symbol.toJS(symbols) + ' = ' + val;
};
assignment.prototype.toJSObject = function(symbols) {
	symbols.defineMsg(this.symbol.name, this.expression);
	var val = this.expression.toJS(symbols);
	if (val === null) {
		return null;
	}
	return this.symbol.toJS(symbols) + ': ' + val;
};