forked from jcoglan/jsclass
-
Notifications
You must be signed in to change notification settings - Fork 0
/
compiler.js
95 lines (85 loc) · 3.11 KB
/
compiler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
JS.Compiler = {
queue: [],
compile: function(klass) {
var str = '';
this.queue.push(klass);
while (this.queue.length > 0)
str += new JS.ClassCompiler(this.queue.shift()).output();
return str;
},
stringify: function(object) {
switch (true) {
case (object === null):
return 'null';
case (object === undefined):
return 'undefined';
case (object.isA && object.isA(JS.Class)):
this.queue.push(object);
return null;
case (object instanceof Function):
return object.toString();
case (typeof object == 'number' || typeof object == 'boolean'):
return String(object);
case (typeof object == 'string'):
return '"' + object.replace(/"/g, "\\\"").replace(/\n/g, "\\n") + '"';
}
}
};
JS.ClassCompiler = new JS.Class({
initialize: function(klass) {
this._subject = klass;
this._className = JS.StackTrace.nameOf(klass);
},
output: function() {
return this.declaration() + this.classMethods() + this.instanceMethods();
},
declaration: function() {
var str = this._className + ' = ' + this._subject.toString() + ';\n';
if (this._subject.superclass != Object) str += this.subclass();
str += this._className + '.prototype.constructor = \n';
str += this._className + '.prototype.klass = ' + this._className + ';\n';
var superclass = this._subject.superclass;
superclass = (superclass == Object) ? 'Object' : JS.StackTrace.nameOf(superclass);
str += this._className + '.superclass = ' + superclass + ';\n';
str += this._className + '.subclasses = [];\n';
if (this._subject.superclass.subclasses instanceof Array)
str += superclass + '.subclasses.push(' + this._className + ');\n';
return str;
},
subclass: function() {
var superclass = JS.StackTrace.nameOf(this._subject.superclass);
return this._className + '.prototype = (function() {\n' +
' var bridge = function() {};\n' +
' bridge.prototype = ' + superclass + '.prototype;\n' +
' return new bridge;\n' +
'})();\n';
},
classMethods: function() {
var anc = this._subject.__eigen__().ancestors(),
methods = {},
str = '',
value, method;
for (var i = 0, n = anc.length; i < n; i++) {
if (anc[i] == JS.ObjectMethods || anc[i] == JS.Module || anc[i] == JS.Class) continue;
JS.extend(methods, anc[i].__mod__.__fns__);
}
for (method in methods) {
value = JS.Compiler.stringify(methods[method]);
if (!value) continue;
str += this._className + '.' + method + ' = ' + value + ';\n';
}
return str;
},
instanceMethods: function() {
var anc = this._subject.ancestors(), methods = {}, str = '', method;
for (var i = 0, n = anc.length; i < n; i++) {
if (anc[i] == JS.ObjectMethods) continue;
JS.extend(methods, anc[i].__mod__.__fns__);
}
for (method in methods) {
if (methods[method] == this._subject.superclass.prototype[method]) continue;
str += this._className + '.prototype.' + method + ' = ' + JS.Compiler.stringify(methods[method]) + ';\n';
}
return str;
}
});