view compiler.js @ 20:bf03c9f0dd55

Initial work on proper property support
author Mike Pavone <pavone@retrodev.com>
date Sun, 25 Mar 2012 16:52:11 -0700
parents 59e83296e331
children 068d63627b16
line wrap: on
line source

function indent(str)
{
	return str.split('\n').join('\n\t');
}

function osymbols(parent)
{
	this.parent = parent;
	this.names = {};
	this.lastname = null;
}
osymbols.prototype.find = function(name) {
	if (name in this.names) {
		if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
			return {
				type: 'foreign',
				def: this.names[name]
			};
		}
		return {
			type: 'self',
			def: this.names[name],
		};
	} else if(this.parent) {
		var ret = this.parent.find(name);
		if (ret) {
			if(ret.type == 'self') {
				ret.type = 'parent';
				ret.depth = 1;
			} else if(ret.type == 'parent') {
				ret.depth++;
			}
		}
		return ret;
	}
	return null;
};
osymbols.prototype.defineMsg = function(name, def) {
	this.lastname = name;
	this.names[name] = def;
}
osymbols.prototype.parentObject = function() {
	if (!this.parent) {
		return 'null';
	}
	return 'this';
}

function lsymbols(parent)
{
	this.parent = parent;
	this.names = {};
	this.lastname = null;
	this.needsSelfVar = false;
}
lsymbols.prototype.find = function(name) {
	if (name in this.names) {
		if (this.names[name] instanceof funcall && this.names[name].name == 'foreign:') {
			return {
				type: 'foreign',
				def: this.names[name]
			};
		}
		return {
			type: 'local',
			def: this.names[name]
		};
	} else if(this.parent) {
		var ret = this.parent.find(name);
		if (ret && ret.type == 'local') {
			ret.type = 'upvar';
		}
		return ret;
	}
	return null;
};
lsymbols.prototype.defineVar = function(name, def) {
	this.lastname = name;
	this.names[name] = def;
};
lsymbols.prototype.selfVar = function() {
	if (this.parent && this.parent instanceof lsymbols) {
		this.parent.needsSelf();
		return 'self';
	} else {
		return 'this';
	}
};
lsymbols.prototype.needsSelf = function() {
	if (this.parent && this.parent instanceof lsymbols) {
		this.parent.needsSelf();
	} else {
		this.needsSelfVar = true;
	}
};

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.populateSymbols = function(symbols, isReceiver) {
	this.left.populateSymbols(symbols);
	this.right.populateSymbols(symbols);
};

symbol.prototype.populateSymbols = function(symbols) {
	this.symbols = symbols;
}

intlit.prototype.populateSymbols = function(symbols) {
}

floatlit.prototype.populateSymbols = function(symbols) {
}

strlit.prototype.populateSymbols = function(symbols) {
}

funcall.prototype.populateSymbols = function(symbols) {
	if(this.name == 'q:') { console.log('populateSymbols', this); }
	if (this.name == 'foreign:') {
		if ((this.args[0] instanceof lambda) || (this.args[0] instanceof object) || (this.args[0] instanceof symbol)) {
			return;
		} else {
			throw new Error("Unexpected AST type for foreign:");
		}
	}
	this.symbols = symbols;
	for (var i in this.args) {
		this.args[i].populateSymbols(symbols);
	}
	if (this.receiver) {
		this.receiver.populateSymbols(symbols);
	}
}

object.prototype.populateSymbols = function(symbols) {
	symbols = new osymbols(symbols);
	for (var i in this.messages) {
		this.messages[i].populateSymbolsObject(symbols);
	}
	this.symbols = symbols;
}

lambda.prototype.populateSymbols = 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].populateSymbols(symbols);
	}
	for (var i in exprs) {
		exprs[i].populateSymbols(symbols);
	}
	this.symbols = symbols;
};

assignment.prototype.populateSymbols = function(symbols) {
	var existing = symbols.find(this.symbol.name);
	if (!existing) {
		symbols.defineVar(this.symbol.name, this.expression);
	}
	this.symbol.populateSymbols(symbols);
	this.expression.populateSymbols(symbols);
	this.symbols = symbols;
};
assignment.prototype.populateSymbolsObject = function(symbols) {
	console.log('populateSymbolsObject for assignment to ' + this.symbol.name)
	symbols.defineMsg(this.symbol.name, this.expression);
	if (!(this.expression instanceof lambda)) {
		symbols.defineMsg(this.symbol.name + '!', new setter(null));
	}
	this.symbol.populateSymbols(symbols);
	this.expression.populateSymbols(symbols);
	this.symbols = symbols;
};

function setter(fun)
{
	this.fun = fun;
}

function getter(fun)
{
	this.fun = fun;
}