cor-lang
Version:
The Language of the Web
206 lines (159 loc) • 4.32 kB
JavaScript
(function(cor){
var
Class = cor.Class,
yy = {},
hasProp = Object.prototype.hasOwnProperty;
function copyObj(from, to) {
var name;
to = to || {};
for (name in from) {
if (hasProp.call(from, name)) {
to[name] = from[name];
}
}
return to;
}
yy.Context = Class({
depth: null,
ownerNode: null,
ignoredVars: null,
usedVars: null,
localVars: null,
isCompiled: false,
parent: null,
init: function() {
this.usedVars = {};
this.ignoredVars = {'super': true};
this.localVars = {};
},
addUsedVar: function(name, value) {
//console.log('var - ' + name);
if (!hasProp.call(this.usedVars, name)) {
this.usedVars[name] = (typeof value === 'string' ? value : true);
}
},
addLocalVar: function(name, value) {
//console.log('var - ' + name);
this.localVars[name] = (typeof value === 'string' ? value : true);
this.addUsedVar(name, value);
},
ignoreVar: function(name) {
this.ignoredVars[name] = true;
},
isDeclaredLocal: function(name) {
var r = false;
if (hasProp.call(this.localVars, name)) {
r = true;
}
else if (this.parent){
r = this.parent.isDeclaredLocal(name);
}
else {
r = false;
}
return r;
},
compileVars: function() {
var
name,
stack = [],
usedVars = this.usedVars,
localVars = this.localVars,
ignoredVars = this.ignoredVars;
for (name in usedVars) {
if (! hasProp.call(usedVars, name)) {
continue;
}
if (! this.isDeclaredLocal(name)) {
this.addLocalVar(name, usedVars[name]);
}
if (hasProp.call(localVars, name) && ! hasProp.call(ignoredVars, name)) {
if (typeof localVars[name] === 'string') {
name += (' = ' + localVars[name]);
}
stack.push(name);
}
}
this.isCompiled = true;
return (stack.length > 0) ? 'var ' + stack.join(', ') + '; ': '';
},
generateVar: function(str, seed) {
seed = seed || 1;
var v = (str || 'var') + (seed++);
if (hasProp.call(this.usedVars, v)) {
return this.generateVar(str, seed);
}
this.addUsedVar(v);
return v;
},
});
yy.Environment = Class({
usesRuntime: false,
contexts: null,
errors: null,
exported: null,
classNodes: null,
currentCompilingClass: null,
currentCompilingMethod: null,
comments: null,
filename: '',
init: function(filename) {
this.filename = filename;
this.contexts = [];
this.errors = [];
this.exported = {};
this.classNodes = [];
this.comments = [];
// initialize the first context (module)
this.newContext();
},
addComment: function(node) {
this.comments.push(node);
},
getComments: function() {
return this.comments;
},
addExported: function(k, v) {
this.exported[k] = v || k;
},
getExported: function() {
return this.exported;
},
isExported: function(name) {
return this.exported && hasProp.call(this.exported, name);
},
registerClass: function(cls) {
this.classNodes.push(cls);
},
newContext: function(c) {
var pc = null;
if (!c) {
c = new yy.Context();
pc = this.context();
if (pc) {
c.parent = pc;
}
}
this.contexts.push(c);
c.depth = this.contexts.length - 1;
return c;
},
popContext: function() {
return this.contexts.pop();
},
context: function(n) {
if (isNaN(n) || n === null) {
n = this.contexts.length - 1;
}
else if (n <= 0) {
n = this.contexts.length + (n - 1);
}
return this.contexts[n];
},
error: function(e) {
this.errors.push(e);
throw e;
}
});
cor.yy = yy;
})(typeof cor === 'undefined' ? {} : cor);