resin 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. data/amber/bin/amberc +10 -350
  2. data/amber/js/Benchfib.deploy.js +80 -89
  3. data/amber/js/Benchfib.js +80 -89
  4. data/amber/js/Canvas.deploy.js +558 -545
  5. data/amber/js/Canvas.js +563 -545
  6. data/amber/js/Compiler-AST.deploy.js +431 -243
  7. data/amber/js/Compiler-AST.js +487 -244
  8. data/amber/js/Compiler-Core.deploy.js +201 -1045
  9. data/amber/js/Compiler-Core.js +208 -1207
  10. data/amber/js/Compiler-Exceptions.deploy.js +37 -18
  11. data/amber/js/Compiler-Exceptions.js +42 -18
  12. data/amber/js/Compiler-IR.deploy.js +1071 -774
  13. data/amber/js/Compiler-IR.js +1194 -848
  14. data/amber/js/Compiler-Inlining.deploy.js +395 -373
  15. data/amber/js/Compiler-Inlining.js +395 -373
  16. data/amber/js/Compiler-Interpreter.deploy.js +1202 -0
  17. data/amber/js/Compiler-Interpreter.js +1631 -0
  18. data/amber/js/Compiler-Semantic.deploy.js +695 -600
  19. data/amber/js/Compiler-Semantic.js +721 -611
  20. data/amber/js/Compiler-Tests.deploy.js +699 -376
  21. data/amber/js/Compiler-Tests.js +834 -381
  22. data/amber/js/Compiler.deploy.js +8563 -1805
  23. data/amber/js/Compiler.js +11476 -2633
  24. data/amber/js/Examples.deploy.js +29 -29
  25. data/amber/js/Examples.js +29 -29
  26. data/amber/js/IDE.deploy.js +3292 -2649
  27. data/amber/js/IDE.js +3318 -2710
  28. data/amber/js/Importer-Exporter.deploy.js +393 -349
  29. data/amber/js/Importer-Exporter.js +398 -354
  30. data/amber/js/Kernel-Announcements.deploy.js +53 -44
  31. data/amber/js/Kernel-Announcements.js +55 -44
  32. data/amber/js/Kernel-Classes.deploy.js +566 -368
  33. data/amber/js/Kernel-Classes.js +660 -402
  34. data/amber/js/Kernel-Collections.deploy.js +1149 -1098
  35. data/amber/js/Kernel-Collections.js +1183 -1116
  36. data/amber/js/Kernel-Exceptions.deploy.js +173 -75
  37. data/amber/js/Kernel-Exceptions.js +215 -77
  38. data/amber/js/Kernel-Methods.deploy.js +530 -313
  39. data/amber/js/Kernel-Methods.js +632 -338
  40. data/amber/js/Kernel-Objects.deploy.js +1734 -1577
  41. data/amber/js/Kernel-Objects.js +1867 -1654
  42. data/amber/js/Kernel-Tests.deploy.js +1416 -973
  43. data/amber/js/Kernel-Tests.js +1495 -981
  44. data/amber/js/Kernel-Transcript.deploy.js +23 -24
  45. data/amber/js/Kernel-Transcript.js +25 -26
  46. data/amber/js/SUnit-Tests.deploy.js +402 -0
  47. data/amber/js/SUnit-Tests.js +518 -0
  48. data/amber/js/SUnit.deploy.js +535 -237
  49. data/amber/js/SUnit.js +634 -246
  50. data/amber/js/amber.js +90 -53
  51. data/amber/js/boot.js +441 -255
  52. data/amber/js/init.js +1 -3
  53. data/amber/js/lib/CodeMirror/codemirror.css +3 -0
  54. data/amber/js/lib/CodeMirror/codemirror.js +104 -55
  55. data/amber/js/lib/peg-0.7.0.min.js +9 -0
  56. data/amber/js/parser.js +1504 -802
  57. data/amber/js/parser.pegjs +170 -165
  58. data/amber/st/Canvas.st +6 -0
  59. data/amber/st/Compiler-AST.st +54 -3
  60. data/amber/st/Compiler-Core.st +6 -551
  61. data/amber/st/Compiler-Exceptions.st +4 -0
  62. data/amber/st/Compiler-IR.st +205 -87
  63. data/amber/st/Compiler-Interpreter.st +597 -0
  64. data/amber/st/Compiler-Semantic.st +46 -21
  65. data/amber/st/Compiler-Tests.st +254 -7
  66. data/amber/st/Compiler.st +3172 -1541
  67. data/amber/st/IDE.st +57 -93
  68. data/amber/st/Importer-Exporter.st +4 -7
  69. data/amber/st/Kernel-Announcements.st +8 -0
  70. data/amber/st/Kernel-Classes.st +149 -40
  71. data/amber/st/Kernel-Collections.st +43 -32
  72. data/amber/st/Kernel-Exceptions.st +70 -1
  73. data/amber/st/Kernel-Methods.st +165 -27
  74. data/amber/st/Kernel-Objects.st +215 -140
  75. data/amber/st/Kernel-Tests.st +195 -10
  76. data/amber/st/Kernel-Transcript.st +1 -3
  77. data/amber/st/SUnit-Tests.st +186 -0
  78. data/amber/st/SUnit.st +186 -14
  79. data/bin/resin +6 -0
  80. data/lib/resin/cli.rb +19 -0
  81. metadata +41 -25
  82. data/amber/js/lib/peg-0.6.2.min.js +0 -2
  83. data/bin/resin-compile +0 -6
  84. data/bin/runresin +0 -12
@@ -19,7 +19,7 @@ amber = (function() {
19
19
  var spec;
20
20
  var jsToLoad = [];
21
21
  var loadJS;
22
- var nocache = '';
22
+ var nocache = '';
23
23
 
24
24
  that.toggleIDE = function() {
25
25
  if ($('#amber').length == 0) {
@@ -30,7 +30,7 @@ amber = (function() {
30
30
  smalltalk.TabManager._current()._open();
31
31
  }
32
32
  return false;
33
- }
33
+ };
34
34
 
35
35
  that.load = function(obj) {
36
36
  spec = obj || {};
@@ -56,9 +56,9 @@ amber = (function() {
56
56
  }
57
57
 
58
58
  loadDependencies();
59
- addJSToLoad('lib/es5-shim-2.0.2/es5-shim.min.js');
60
- addJSToLoad('lib/es5-shim-2.0.2/es5-sham.min.js');
61
- addJSToLoad('boot.js');
59
+ addJSToLoad('js/lib/es5-shim-2.0.2/es5-shim.min.js');
60
+ addJSToLoad('js/lib/es5-shim-2.0.2/es5-sham.min.js');
61
+ addJSToLoad('js/boot.js');
62
62
 
63
63
  if (deploy) {
64
64
  loadPackages([
@@ -92,56 +92,90 @@ amber = (function() {
92
92
  'Compiler-Semantic',
93
93
  'Compiler-IR',
94
94
  'Compiler-Inlining',
95
+ 'Compiler-Interpreter',
95
96
  'Compiler-Tests',
96
97
  'parser',
97
98
  'IDE',
98
99
  'Examples',
99
100
  'Benchfib',
100
- 'Kernel-Tests'
101
+ 'Kernel-Tests',
102
+ 'SUnit-Tests'
101
103
  ]);
102
104
  }
103
105
 
104
106
  var additionalFiles = spec.packages || spec.files;
107
+ var commitPathForInit = null;
105
108
  if (additionalFiles) {
106
- loadPackages(additionalFiles, spec.prefix, spec.packageHome);
109
+ commitPathForInit = loadPackages(additionalFiles, spec.prefix, spec.packageHome);
107
110
  }
108
111
 
109
112
  // Be sure to setup & initialize smalltalk classes
110
- addJSToLoad('init.js');
111
- initializeSmalltalk();
113
+ addJSToLoad('js/init.js');
114
+ initializeSmalltalk(commitPathForInit);
112
115
  };
113
116
 
114
117
  function loadPackages(names, prefix, urlHome){
115
- var name, url;
116
- var prefix = prefix || 'js';
117
- var urlHome = urlHome || home;
118
+ var name;
119
+ prefix = prefix || 'js';
120
+ urlHome = urlHome || home;
118
121
 
119
122
  for (var i=0; i < names.length; i++) {
120
123
  name = names[i].split(/\.js$/)[0];
121
124
  addJSToLoad(name + '.js', prefix, urlHome);
122
125
  }
123
- };
126
+
127
+ return {
128
+ js: urlHome+prefix,
129
+ st: urlHome+'st'
130
+ };
131
+ }
124
132
 
125
133
  function addJSToLoad(name, prefix, urlHome) {
126
- var urlHome = urlHome || home;
134
+ urlHome = urlHome || home;
127
135
  jsToLoad.push(buildJSURL(name, prefix, urlHome));
128
- };
136
+ }
137
+
138
+ function resolve(base, path) {
139
+ if (/(^|:)\/\//.test(path)) {
140
+ // path: [http:]//foo.com/bar/; base: whatever/
141
+ // -> http://foo.com/bar/
142
+ return path;
143
+ }
144
+ if (!/^\//.test(path)) {
145
+ // path: relative/; base: whatever/
146
+ // -> whatever/relative/
147
+ return base + path;
148
+ }
149
+ var match = base.match(/^(([^:/]*:|^)\/\/[^/]*)/);
150
+ if (match) {
151
+ // path: /absolute/; base: [http:]//foo.com/whatever/
152
+ // -> [http:]//foo.com/absolute/
153
+ return match[1] + path;
154
+ }
155
+ // path: /absolute/; base: whatever/path/
156
+ // -> /absolute/
157
+ return path;
158
+ }
129
159
 
130
160
  function buildJSURL(name, prefix, urlHome) {
131
- var prefix = prefix || 'js';
132
- var name = name;
133
- var urlHome = urlHome || home;
161
+ prefix = prefix || '';
162
+ urlHome = urlHome || home;
163
+
164
+ var parts = name.match(/^(.*\/)([^/]*)$/);
165
+ if (parts) {
166
+ name = parts[2];
167
+ urlHome = resolve(urlHome, parts[1]);
168
+ }
134
169
 
135
170
  if (!deploy) {
136
171
  name = name + nocache;
137
172
  }
138
173
 
139
174
  return urlHome + prefix + '/' + name;
140
- };
175
+ }
141
176
 
142
177
  function loadCSS(name, prefix) {
143
- var prefix = prefix || 'css';
144
- var name = name;
178
+ prefix = prefix || 'css';
145
179
  if (!deploy) {
146
180
  name = name + nocache;
147
181
  }
@@ -153,39 +187,43 @@ amber = (function() {
153
187
  link.setAttribute("type", "text/css");
154
188
  link.setAttribute("href", url);
155
189
  document.getElementsByTagName("head")[0].appendChild(link);
156
- };
190
+ }
157
191
 
158
192
  function loadDependencies() {
159
193
  if (typeof jQuery == 'undefined') {
160
- writeScriptTag(buildJSURL('lib/jQuery/jquery-1.8.2.min.js'));
194
+ writeScriptTag(buildJSURL('js/lib/jQuery/jquery-1.8.2.min.js'));
161
195
  }
162
196
 
163
197
  if ((typeof jQuery == 'undefined') || (typeof jQuery.ui == 'undefined')) {
164
- writeScriptTag(buildJSURL('lib/jQuery/jquery-ui-1.8.16.custom.min.js'));
198
+ writeScriptTag(buildJSURL('js/lib/jQuery/jquery-ui-1.8.16.custom.min.js'));
165
199
  }
166
- };
200
+ }
167
201
 
168
202
  function loadIDEDependencies() {
169
- addJSToLoad('lib/jQuery/jquery.textarea.js');
170
- addJSToLoad('lib/CodeMirror/codemirror.js');
171
- addJSToLoad('lib/CodeMirror/smalltalk.js');
203
+ addJSToLoad('js/lib/jQuery/jquery.textarea.js');
204
+ addJSToLoad('js/lib/CodeMirror/codemirror.js');
205
+ addJSToLoad('js/lib/CodeMirror/smalltalk.js');
172
206
  loadCSS('lib/CodeMirror/codemirror.css', 'js');
173
207
  loadCSS('lib/CodeMirror/amber.css', 'js');
174
- };
208
+ }
175
209
 
176
210
  // This will be called after JS files have been loaded
177
- function initializeSmalltalk() {
211
+ function initializeSmalltalk(commitPath) {
178
212
  window.smalltalkReady = function() {
213
+ if (commitPath) {
214
+ smalltalk['@@commitPath'] = commitPath;
215
+ smalltalk.Package._commitPathsFromLoader();
216
+ }
179
217
  if (spec.ready) {
180
218
  spec.ready();
181
- };
182
- evaluateSmalltalkScripts();
219
+ }
220
+ evaluateSmalltalkScripts();
183
221
  };
184
222
 
185
- loadAllJS();
186
- };
223
+ loadAllJS();
224
+ }
187
225
 
188
- /*
226
+ /*
189
227
  * When loaded using AJAX, scripts order not guaranteed.
190
228
  * Load JS in the order they have been added using addJSToLoad().
191
229
  * If loaded, will use jQuery's getScript instead of adding a script element
@@ -196,7 +234,7 @@ amber = (function() {
196
234
  loadJS = loadJSViaJQuery;
197
235
  }
198
236
  loadNextJS();
199
- };
237
+ }
200
238
 
201
239
  function loadNextJS() {
202
240
  loadJS(jsToLoad[0], function(){
@@ -205,37 +243,36 @@ amber = (function() {
205
243
  loadNextJS();
206
244
  }
207
245
  });
208
- };
246
+ }
209
247
 
210
248
  function loadJSViaScriptTag(url, callback) {
211
249
  writeScriptTag(url);
212
250
  callback();
213
- };
251
+ }
214
252
 
215
253
  function loadJSViaJQuery(url, callback) {
216
254
  $.ajax({
217
255
  dataType: "script",
218
- url: jsToLoad[0],
256
+ url: url,
219
257
  cache: deploy,
220
258
  success: callback
221
259
  });
222
- };
260
+ }
223
261
 
224
262
  function writeScriptTag(src) {
225
263
  var scriptString = '<script src="' + src + '" type="text/javascript"></script>';
226
264
  document.write(scriptString);
227
- };
265
+ }
266
+
267
+ function evaluateSmalltalkScripts() {
268
+ jQuery(document).ready(function() {
269
+ jQuery('script[type="text/smalltalk"]').each(function(i, elt) {
270
+ smalltalk.Compiler._new()._evaluateExpression_(jQuery(elt).html());
271
+ });
272
+ })
273
+ }
228
274
 
229
- function evaluateSmalltalkScripts() {
230
- jQuery(document).ready(function() {
231
- jQuery('script[type="text/smalltalk"]').each(function(i, elt) {
232
- smalltalk.send(
233
- smalltalk.send(smalltalk.Compiler, '_new'),
234
- '_evaluateExpression_',
235
- [jQuery(elt).html()])
236
- });
237
- })
238
- };
275
+ var localPackages;
239
276
 
240
277
  function populateLocalPackages(){
241
278
  var localStorageRE = /^smalltalk\.packages\.(.*)$/;
@@ -252,14 +289,14 @@ amber = (function() {
252
289
  }
253
290
 
254
291
  return localPackages;
255
- };
292
+ }
256
293
 
257
294
  function clearLocalPackages() {
258
295
  for (var name in localPackages) {
259
296
  log('Removing ' + name + ' from local storage');
260
297
  localStorage.removeItem('smalltalk.packages.' + name);
261
298
  }
262
- };
299
+ }
263
300
 
264
301
  function log(string) {
265
302
  if (debug) {
@@ -13,29 +13,29 @@
13
13
  | Amber is released under the MIT license
14
14
  |
15
15
  | Permission is hereby granted, free of charge, to any person obtaining
16
- | a copy of this software and associated documentation files (the
17
- | 'Software'), to deal in the Software without restriction, including
18
- | without limitation the rights to use, copy, modify, merge, publish,
19
- | distribute, sublicense, and/or sell copies of the Software, and to
20
- | permit persons to whom the Software is furnished to do so, subject to
16
+ | a copy of this software and associated documentation files (the
17
+ | 'Software'), to deal in the Software without restriction, including
18
+ | without limitation the rights to use, copy, modify, merge, publish,
19
+ | distribute, sublicense, and/or sell copies of the Software, and to
20
+ | permit persons to whom the Software is furnished to do so, subject to
21
21
  | the following conditions:
22
22
  |
23
- | The above copyright notice and this permission notice shall be
23
+ | The above copyright notice and this permission notice shall be
24
24
  | included in all copies or substantial portions of the Software.
25
25
  |
26
- | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
27
- | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28
- | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
29
- | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
30
- | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31
- | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32
- | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
27
+ | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28
+ | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
29
+ | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
30
+ | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31
+ | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32
+ | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
33
  |
34
34
  ==================================================================== */
35
35
 
36
36
  /* Make sure that console is defined */
37
37
 
38
- if (typeof console === "undefined") {
38
+ if(typeof console === "undefined") {
39
39
  this.console = {
40
40
  log: function() {},
41
41
  warn: function() {},
@@ -45,51 +45,61 @@ if (typeof console === "undefined") {
45
45
  };
46
46
  }
47
47
 
48
- /* Smalltalk constructors definition */
48
+ /* Array extensions */
49
49
 
50
- function SmalltalkObject(){};
51
- function SmalltalkBehavior(){};
52
- function SmalltalkClass(){};
53
- function SmalltalkPackage(){};
54
- function SmalltalkMetaclass(){
55
- this.meta = true;
50
+ Array.prototype.addElement = function(el) {
51
+ if(typeof el === 'undefined') { return; }
52
+ if(this.indexOf(el) == -1) {
53
+ this.push(el);
54
+ }
56
55
  };
57
- function SmalltalkMethod(){};
58
- function SmalltalkNil(){};
59
56
 
60
- function SmalltalkSymbol(string){
61
- this.value = string;
57
+ Array.prototype.removeElement = function(el) {
58
+ var i = this.indexOf(el);
59
+ if (i !== -1) { this.splice(i, 1); }
62
60
  };
63
61
 
62
+
63
+ /* Smalltalk constructors definition */
64
+
65
+ function SmalltalkObject() {}
66
+ function SmalltalkBehavior() {}
67
+ function SmalltalkClass() {}
68
+ function SmalltalkMetaclass() {
69
+ this.meta = true;
70
+ }
71
+ function SmalltalkPackage() {}
72
+ function SmalltalkMethod() {}
73
+ function SmalltalkNil() {}
74
+ function SmalltalkSymbol(string) {
75
+ this.value = string;
76
+ }
64
77
  function SmalltalkOrganizer() {
65
78
  this.elements = [];
66
- };
79
+ }
67
80
 
68
- SmalltalkOrganizer.prototype.addElement = function(el) {
69
- if(typeof el === 'undefined' || el === nil) {
70
- return false;
71
- }
72
- if(this.elements.indexOf(el) == -1) {
73
- this.elements.push(el);
74
- }
75
- };
81
+ function inherits(child, parent) {
82
+ child.prototype = Object.create(parent.prototype, {
83
+ constructor: { value: child,
84
+ enumerable: false, configurable: true, writable: true }
85
+ });
86
+ }
76
87
 
77
- SmalltalkOrganizer.prototype.removeElement = function(el) {
78
- for(var i=0; i<this.elements.length; i++) {
79
- if(this.elements[i] == el) {
80
- this.elements.splice(i, 1);
81
- break;
82
- }
83
- }
84
- };
88
+ inherits(SmalltalkBehavior, SmalltalkObject);
89
+ inherits(SmalltalkClass, SmalltalkBehavior);
90
+ inherits(SmalltalkMetaclass, SmalltalkBehavior);
91
+ inherits(SmalltalkNil, SmalltalkObject);
92
+ inherits(SmalltalkMethod, SmalltalkObject);
93
+ inherits(SmalltalkPackage, SmalltalkObject);
94
+ inherits(SmalltalkOrganizer, SmalltalkObject);
85
95
 
86
96
 
87
- function Smalltalk(){
97
+ function Smalltalk() {
88
98
 
89
99
  var st = this;
90
100
 
91
101
  /* This is the current call context object. While it is publicly available,
92
- Use smalltalk.getThisContext() instead which will answer a safe copy of
102
+ Use smalltalk.getThisContext() instead which will answer a safe copy of
93
103
  the current context */
94
104
 
95
105
  st.thisContext = undefined;
@@ -97,26 +107,69 @@ function Smalltalk(){
97
107
  /* List of all reserved words in JavaScript. They may not be used as variables
98
108
  in Smalltalk. */
99
109
 
100
- st.reservedWords = ['break', 'case', 'catch', 'char', 'class', 'continue', 'debugger',
101
- 'default', 'delete', 'do', 'else', 'finally', 'for', 'function',
102
- 'if', 'in', 'instanceof', 'new', 'private', 'protected',
103
- 'public', 'return', 'static', 'switch', 'this', 'throw',
104
- 'try', 'typeof', 'var', 'void', 'while', 'with', 'yield'];
110
+ // list of reserved JavaScript keywords as of
111
+ // http://es5.github.com/#x7.6.1.1
112
+ // and
113
+ // http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.6.1
114
+ st.reservedWords = ['break', 'case', 'catch', 'continue', 'debugger',
115
+ 'default', 'delete', 'do', 'else', 'finally', 'for', 'function',
116
+ 'if', 'in', 'instanceof', 'new', 'return', 'switch', 'this', 'throw',
117
+ 'try', 'typeof', 'var', 'void', 'while', 'with',
118
+ // ES5: future use: http://es5.github.com/#x7.6.1.2
119
+ 'class', 'const', 'enum', 'export', 'extends', 'import', 'super',
120
+ // ES5: future use in strict mode
121
+ 'implements', 'interface', 'let', 'package', 'private', 'protected',
122
+ 'public', 'static', 'yield'];
123
+
124
+ var initialized = false;
125
+
126
+ /* Smalltalk classes */
127
+
128
+ var classes = [];
129
+ var wrappedClasses = [];
130
+
131
+ /* Method not implemented handlers */
132
+
133
+ var dnu = {
134
+ methods: [],
135
+ selectors: [],
136
+
137
+ get: function (string) {
138
+ var index = this.selectors.indexOf(string);
139
+ if(index !== -1) {
140
+ return this.methods[index];
141
+ }
142
+ this.selectors.push(string);
143
+ var selector = st.selector(string);
144
+ var method = {jsSelector: selector, fn: this.createHandler(selector)};
145
+ this.methods.push(method);
146
+ return method;
147
+ },
148
+
149
+ /* Dnu handler method */
150
+
151
+ createHandler: function (selector) {
152
+ return function () {
153
+ var args = Array.prototype.slice.call(arguments);
154
+ return messageNotUnderstood(this, selector, args);
155
+ };
156
+ }
157
+ };
105
158
 
106
159
  /* The symbol table ensures symbol unicity */
107
160
 
108
- symbolTable = {};
161
+ var symbolTable = {};
109
162
  st.symbolFor = function(string) {
110
163
  if(symbolTable[string] === undefined) {
111
164
  symbolTable[string] = new SmalltalkSymbol(string);
112
- };
165
+ }
113
166
 
114
167
  return symbolTable[string];
115
168
  };
116
169
 
117
170
  /* Unique ID number generator */
118
171
 
119
- oid = 0;
172
+ var oid = 0;
120
173
  st.nextId = function() {
121
174
  oid += 1;
122
175
  return oid;
@@ -134,18 +187,22 @@ function Smalltalk(){
134
187
  that.organization = new SmalltalkOrganizer();
135
188
  that.properties = spec.properties || {};
136
189
  return that;
137
- };
190
+ }
138
191
 
139
- /* Smalltalk class creation. A class is an instance of an automatically
192
+ /* Smalltalk class creation. A class is an instance of an automatically
140
193
  created metaclass object. Newly created classes (not their metaclass)
141
194
  should be added to the smalltalk object, see smalltalk.addClass().
142
195
  Superclass linking is *not* handled here, see smalltalk.init() */
143
196
 
144
197
  function klass(spec) {
145
- var spec = spec || {};
146
- var meta = metaclass();
147
- var that = setupClass(meta.instanceClass, spec);
148
- that.className = spec.className;
198
+ spec = spec || {};
199
+ var meta = metaclass(spec);
200
+ var that = meta.instanceClass;
201
+ that.fn = spec.fn || function() {};
202
+ setupClass(that, spec);
203
+
204
+ that.className = spec.className;
205
+ that.wrapped = spec.wrapped || false;
149
206
  meta.className = spec.className + ' class';
150
207
  if(spec.superclass) {
151
208
  that.superclass = spec.superclass;
@@ -153,29 +210,36 @@ function Smalltalk(){
153
210
  }
154
211
  return that;
155
212
  }
156
-
157
- function metaclass() {
158
- var meta = setupClass(new SmalltalkMetaclass(), {})
159
- meta.instanceClass = new meta.fn;
160
- return meta;
213
+
214
+ function metaclass(spec) {
215
+ spec = spec || {};
216
+ var that = new SmalltalkMetaclass();
217
+ inherits(
218
+ that.fn = function() {},
219
+ spec.superclass ? spec.superclass.klass.fn : SmalltalkClass
220
+ );
221
+ that.instanceClass = new that.fn();
222
+ setupClass(that);
223
+ return that;
161
224
  }
162
-
163
- function setupClass(that, spec) {
164
- that.fn = spec.fn || function(){};
165
- that.iVarNames = spec.iVarNames || [];
166
- Object.defineProperty(that, "toString", {
167
- value: function() { return 'Smalltalk ' + this.className; },
168
- configurable: true // no writable - in par with ES6 methods
225
+
226
+ function setupClass(klass, spec) {
227
+ spec = spec || {};
228
+ klass.iVarNames = spec.iVarNames || [];
229
+ klass.pkg = spec.pkg;
230
+
231
+ Object.defineProperty(klass, "toString", {
232
+ value: function() { return 'Smalltalk ' + this.className; },
233
+ enumerable:false, configurable: true, writable: false
169
234
  });
170
- that.organization = new SmalltalkOrganizer();
171
- that.pkg = spec.pkg;
172
- Object.defineProperties(that.fn.prototype, {
173
- methods: { value: {}, enumerable: false, configurable: true, writable: true },
174
- inheritedMethods: { value: {}, enumerable: false, configurable: true, writable: true },
175
- klass: { value: that, enumerable: false, configurable: true, writable: true }
235
+
236
+ klass.organization = new SmalltalkOrganizer();
237
+ Object.defineProperty(klass, "methods", {
238
+ value: {},
239
+ enumerable: false, configurable: true, writable: true
176
240
  });
177
- return that;
178
- };
241
+ wireKlass(klass);
242
+ }
179
243
 
180
244
  /* Smalltalk method object. To add a method to a class,
181
245
  use smalltalk.addMethod() */
@@ -193,9 +257,9 @@ function Smalltalk(){
193
257
  return that;
194
258
  };
195
259
 
196
- /* Initialize a class in its class hierarchy. Handle both class and
260
+ /* Initialize a class in its class hierarchy. Handle both classes and
197
261
  metaclasses. */
198
-
262
+
199
263
  st.init = function(klass) {
200
264
  st.initClass(klass);
201
265
  if(klass.klass && !klass.meta) {
@@ -203,71 +267,102 @@ function Smalltalk(){
203
267
  }
204
268
  };
205
269
 
206
- st.initClass = function(klass) {
207
- var subclasses = st.subclasses(klass);
208
- var methods, prototype = klass.fn.prototype;
270
+ st.initClass = function(klass) {
271
+ if(klass.wrapped) {
272
+ copySuperclass(klass);
273
+ }
274
+ else {
275
+ installSuperclass(klass);
276
+ }
277
+
278
+ if(klass === st.Object || klass.wrapped) {
279
+ installDnuHandlers(klass);
280
+ }
281
+ };
282
+
283
+ function wireKlass(klass) {
284
+ Object.defineProperty(klass.fn.prototype, "klass", {
285
+ value: klass,
286
+ enumerable: false, configurable: true, writable: true
287
+ });
288
+ }
289
+
290
+ function installSuperclass(klass) {
291
+ // only if the klass has not been initialized yet.
292
+ if(klass.fn.prototype._yourself) { return; }
209
293
 
210
294
  if(klass.superclass && klass.superclass !== nil) {
211
- methods = st.methods(klass.superclass);
212
-
213
- //Methods linking
214
- for(var keys = Object.keys(methods), i=0; i<keys.length; i++) {
215
- var key = keys[i];
216
- if(!prototype.methods[key]) {
217
- prototype.inheritedMethods[key] = methods[key];
218
- Object.defineProperty(prototype, methods[key].jsSelector, {
219
- value: methods[key].fn, configurable: true, writable: true
220
- });
221
- }
295
+ inherits(klass.fn, klass.superclass.fn);
296
+ wireKlass(klass);
297
+ reinstallMethods(klass);
298
+ }
299
+ }
300
+
301
+ function copySuperclass(klass, superclass) {
302
+ for (superclass = superclass || klass.superclass;
303
+ superclass && superclass !== nil;
304
+ superclass = superclass.superclass) {
305
+ for (var keys = Object.keys(superclass.methods), i = 0; i < keys.length; i++) {
306
+ installMethodIfAbsent(superclass.methods[keys[i]], klass);
222
307
  }
223
308
  }
309
+ }
224
310
 
225
- for(var i=0; i<subclasses.length; i++) {
226
- st.initClass(subclasses[i]);
311
+ function installMethod(method, klass) {
312
+ Object.defineProperty(klass.fn.prototype, method.jsSelector, {
313
+ value: method.fn,
314
+ enumerable: false, configurable: true, writable: true
315
+ });
316
+ }
317
+
318
+ function installMethodIfAbsent(method, klass) {
319
+ if(!klass.fn.prototype[method.jsSelector]) {
320
+ installMethod(method, klass);
227
321
  }
228
- };
322
+ }
323
+
324
+ function reinstallMethods(klass) {
325
+ for(var keys = Object.keys(klass.methods), i=0; i<keys.length; i++) {
326
+ installMethod(klass.methods[keys[i]], klass);
327
+ }
328
+ }
229
329
 
330
+ function installDnuHandlers(klass) {
331
+ var m = dnu.methods;
332
+ for(var i=0; i<m.length; i++) {
333
+ installMethodIfAbsent(m[i], klass);
334
+ }
335
+ }
336
+
337
+ function installNewDnuHandler(newHandler) {
338
+ installMethodIfAbsent(newHandler, st.Object);
339
+ for(var i = 0; i < wrappedClasses.length; i++) {
340
+ installMethodIfAbsent(newHandler, wrappedClasses[i]);
341
+ }
342
+ }
230
343
 
231
344
  /* Answer all registered Packages as Array */
345
+ // TODO: Remove this hack
232
346
 
233
347
  st.packages.all = function() {
234
348
  var packages = [];
235
349
  for(var i in st.packages) {
236
- if (!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
350
+ if(!st.packages.hasOwnProperty(i) || typeof(st.packages[i]) === "function") continue;
237
351
  packages.push(st.packages[i]);
238
352
  }
239
353
  return packages
240
354
  };
241
355
 
242
356
  /* Answer all registered Smalltalk classes */
357
+ //TODO: remove the function and make smalltalk.classes an array
243
358
 
244
359
  st.classes = function() {
245
- var classes = [], names = Object.keys(st), l = names.length;
246
- for (var i=0; i<l; i++) {
247
- var name = names[i];
248
- if (name.search(/^[A-Z]/) !== -1) {
249
- classes.push(st[name]);
250
- }
251
- }
252
360
  return classes;
253
361
  };
254
362
 
255
-
256
- /* Answer all methods (included inherited ones) of klass. */
257
-
258
- st.methods = function(klass) {
259
- var methods = {};
260
- inheritedMethods = klass.fn.prototype.inheritedMethods;
261
- for(var i=0, keys=Object.keys(inheritedMethods); i<keys.length; i++) {
262
- methods[keys[i]] = inheritedMethods[keys[i]];
263
- }
264
- var inheritedMethods = klass.fn.prototype.methods;
265
- for(var i=0, keys=Object.keys(inheritedMethods); i<keys.length; i++) {
266
- methods[keys[i]] = inheritedMethods[keys[i]];
267
- }
268
- return methods;
269
- };
270
-
363
+ st.wrappedClasses = function() {
364
+ return wrappedClasses;
365
+ };
271
366
 
272
367
  /* Answer the direct subclasses of klass. */
273
368
 
@@ -291,23 +386,32 @@ function Smalltalk(){
291
386
  return subclasses;
292
387
  };
293
388
 
294
- /* Create a new class wrapping a JavaScript constructor, and add it to the
389
+ /* Create a new class wrapping a JavaScript constructor, and add it to the
295
390
  global smalltalk object. Package is lazily created if it does not exist with given name. */
296
391
 
297
- st.wrapClassName = function(className, pkgName, fn, superclass) {
392
+ st.wrapClassName = function(className, pkgName, fn, superclass, wrapped) {
393
+ if(wrapped !== false) {
394
+ wrapped = true;
395
+ }
298
396
  var pkg = st.addPackage(pkgName);
299
397
  st[className] = klass({
300
- className: className,
398
+ className: className,
301
399
  superclass: superclass,
302
- pkg: pkg,
303
- fn: fn
400
+ pkg: pkg,
401
+ fn: fn,
402
+ wrapped: wrapped
304
403
  });
404
+
405
+ classes.addElement(st[className]);
406
+ if(wrapped) {wrappedClasses.addElement(st[className])}
407
+ pkg.organization.elements.addElement(st[className]);
305
408
  };
306
409
 
307
410
  /* Create an alias for an existing class */
411
+
308
412
  st.alias = function(klass, alias) {
309
413
  st[alias] = klass;
310
- }
414
+ };
311
415
 
312
416
  /* Add a package to the smalltalk.packages object, creating a new one if needed.
313
417
  If pkgName is null or empty we return nil, which is an allowed package for a class.
@@ -323,7 +427,7 @@ function Smalltalk(){
323
427
  } else {
324
428
  if(properties) {
325
429
  st.packages[pkgName].properties = properties;
326
- }
430
+ }
327
431
  }
328
432
  return st.packages[pkgName];
329
433
  };
@@ -333,104 +437,125 @@ function Smalltalk(){
333
437
 
334
438
  st.addClass = function(className, superclass, iVarNames, pkgName) {
335
439
  var pkg = st.addPackage(pkgName);
336
- if(st[className]) {
440
+ if (superclass == nil) { superclass = null; }
441
+ if(st[className] && st[className].superclass == superclass) {
337
442
  st[className].superclass = superclass;
338
443
  st[className].iVarNames = iVarNames;
339
444
  st[className].pkg = pkg || st[className].pkg;
340
445
  } else {
446
+ if(st[className]) {
447
+ st.removeClass(st[className]);
448
+ }
341
449
  st[className] = klass({
342
- className: className,
450
+ className: className,
343
451
  superclass: superclass,
344
452
  pkg: pkg,
345
453
  iVarNames: iVarNames
346
454
  });
347
455
  }
348
456
 
349
- pkg.organization.addElement(st[className]);
457
+ classes.addElement(st[className]);
458
+ pkg.organization.elements.addElement(st[className]);
350
459
  };
351
460
 
352
461
  st.removeClass = function(klass) {
353
- klass.pkg.organization.removeElement(klass);
462
+ klass.pkg.organization.elements.removeElement(klass);
463
+ classes.removeElement(klass);
354
464
  delete st[klass.className];
355
465
  };
356
466
 
357
467
  /* Add/remove a method to/from a class */
358
468
 
359
469
  st.addMethod = function(jsSelector, method, klass) {
360
- Object.defineProperty(klass.fn.prototype, jsSelector, {
361
- value: method.fn, configurable: true, writable: true
362
- });
363
- klass.fn.prototype.methods[method.selector] = method;
364
- method.methodClass = klass;
365
470
  method.jsSelector = jsSelector;
471
+ installMethod(method, klass);
472
+ klass.methods[method.selector] = method;
473
+ method.methodClass = klass;
366
474
 
367
- klass.organization.addElement(method.category);
475
+ klass.organization.elements.addElement(method.category);
476
+
477
+ for(var i=0; i<method.messageSends.length; i++) {
478
+ var dnuHandler = dnu.get(method.messageSends[i]);
479
+ if(initialized) {
480
+ installNewDnuHandler(dnuHandler);
481
+ }
482
+ }
368
483
  };
369
484
 
370
485
  st.removeMethod = function(method) {
371
486
  var protocol = method.category;
372
487
  var klass = method.methodClass;
373
- var methods = klass.fn.prototype.methods;
374
488
 
375
- delete klass.fn.prototype[method.selector._asSelector()];
376
- delete methods[method.selector];
489
+ delete klass.fn.prototype[st.selector(method.selector)];
490
+ delete klass.methods[method.selector];
377
491
 
378
- var selectors = Object.keys(methods);
492
+ var selectors = Object.keys(klass.methods);
379
493
  var shouldDeleteProtocol = true;
380
- for(var i= 0, l = selectors.length; i<l; i++) {
381
- if(methods[selectors[i]].category === protocol) {
494
+
495
+ for(var i = 0, l = selectors.length; i<l; i++) {
496
+ if(klass.methods[selectors[i]].category === protocol) {
382
497
  shouldDeleteProtocol = false;
383
498
  break;
384
499
  };
385
500
  };
386
501
  if(shouldDeleteProtocol) {
387
- klass.organization.removeElement(protocol)
502
+ klass.organization.elements.removeElement(protocol)
388
503
  };
389
504
  };
390
505
 
391
506
  /* Handles unhandled errors during message sends */
507
+ // simply send the message and handle #dnu:
392
508
 
393
509
  st.send = function(receiver, selector, args, klass) {
394
- if(st.thisContext) {
395
- return withContextSend(receiver, selector, args, klass);
396
- } else {
397
- try {return withContextSend(receiver, selector, args, klass)}
398
- catch(error) {
399
- // Reset the context stack in any case
400
- st.thisContext = undefined;
401
- if(error.smalltalkError) {
402
- handleError(error);
403
- } else {
404
- throw(error);
405
- }
406
- }
407
- }
408
- };
409
-
410
- function withContextSend(receiver, selector, args, klass) {
411
- var call, method;
510
+ var method;
412
511
  if(receiver == null) {
413
512
  receiver = nil;
414
513
  }
415
514
  method = klass ? klass.fn.prototype[selector] : receiver.klass && receiver[selector];
416
515
  if(method) {
417
- var context = pushContext(receiver, selector, method, args);
418
- call = method.apply(receiver, args);
419
- popContext(context);
420
- return call;
516
+ return method.apply(receiver, args);
421
517
  } else {
422
518
  return messageNotUnderstood(receiver, selector, args);
423
519
  }
520
+ }
521
+
522
+ st.withContext = function(worker, setup) {
523
+ if(st.thisContext) {
524
+ st.thisContext.pc++;
525
+ return inContext(worker, setup);
526
+ } else {
527
+ try {return inContext(worker, setup)}
528
+ catch(error) {
529
+ if(error.smalltalkError) {
530
+ handleError(error);
531
+ } else {
532
+ var errorWrapper = st.JavaScriptException._on_(error);
533
+ try {errorWrapper._signal()} catch(ex) {}
534
+ errorWrapper._context_(st.getThisContext());
535
+ handleError(errorWrapper);
536
+ }
537
+ // Reset the context stack in any case
538
+ st.thisContext = undefined;
539
+ // Throw the exception anyway, as we want to stop
540
+ // the execution to avoid infinite loops
541
+ throw error;
542
+ }
543
+ }
424
544
  };
425
545
 
426
- /* Handles Smalltalk errors. Triggers the registered ErrorHandler
546
+ function inContext(worker, setup) {
547
+ var context = pushContext(setup);
548
+ var result = worker(context);
549
+ popContext(context);
550
+ return result;
551
+ }
552
+
553
+ /* Handles Smalltalk errors. Triggers the registered ErrorHandler
427
554
  (See the Smalltalk class ErrorHandler and its subclasses */
428
555
 
429
556
  function handleError(error) {
430
- if(!error.cc) {
431
- smalltalk.ErrorHandler._current()._handleError_(error);
432
- }
433
- };
557
+ st.ErrorHandler._current()._handleError_(error);
558
+ }
434
559
 
435
560
  /* Handles #dnu: *and* JavaScript method calls.
436
561
  if the receiver has no klass, we consider it a JS object (outside of the
@@ -442,21 +567,21 @@ function Smalltalk(){
442
567
  return callJavaScriptMethod(receiver, selector, args);
443
568
  }
444
569
 
445
- /* Handles not understood messages. Also see the Amber counter-part
570
+ /* Handles not understood messages. Also see the Amber counter-part
446
571
  Object>>doesNotUnderstand: */
447
572
 
448
573
  return receiver._doesNotUnderstand_(
449
- st.Message._new()
574
+ st.Message._new()
450
575
  ._selector_(st.convertSelector(selector))
451
576
  ._arguments_(args)
452
- );
453
- };
577
+ );
578
+ }
454
579
 
455
580
  /* Call a method of a JS object, or answer a property if it exists.
456
581
  Else try wrapping a JSObjectProxy around the receiver.
457
582
 
458
583
  If the object property is a function, then call it, except if it starts with
459
- an uppercase character (we probably want to answer the function itself in this
584
+ an uppercase character (we probably want to answer the function itself in this
460
585
  case and send it #new from Amber).
461
586
 
462
587
  Converts keyword-based selectors by using the first
@@ -480,42 +605,47 @@ function Smalltalk(){
480
605
  }
481
606
 
482
607
  return st.send(st.JSObjectProxy._on_(receiver), selector, args);
483
- };
484
-
485
-
486
- /* Reuse one old context stored in oldContext */
487
-
488
- st.oldContext = null;
489
-
608
+ }
490
609
 
491
610
  /* Handle thisContext pseudo variable */
492
611
 
493
612
  st.getThisContext = function() {
494
- if(st.thisContext) {
495
- return st.thisContext.copy();
496
- }
613
+ if(st.thisContext) {
614
+ st.thisContext.init();
615
+ return st.thisContext;
616
+ } else {
617
+ return nil;
618
+ }
497
619
  };
498
620
 
499
- function pushContext(receiver, selector, method, temps) {
500
- var c = st.oldContext, tc = st.thisContext;
501
- if (!c) {
502
- return st.thisContext = new SmalltalkMethodContext(receiver, selector, method, temps, tc);
503
- }
504
- st.oldContext = null;
505
- c.homeContext = tc;
506
- c.pc = 1;
507
- c.receiver = receiver;
508
- c.selector = selector;
509
- c.method = method;
510
- c.temps = temps || {};
511
- return st.thisContext = c;
512
- };
621
+ function pushContext(setup) {
622
+ return st.thisContext = new SmalltalkMethodContext(smalltalk.thisContext, setup);
623
+ }
513
624
 
514
625
  function popContext(context) {
515
626
  st.thisContext = context.homeContext;
516
- context.homeContext = undefined;
517
- st.oldContext = context;
518
- };
627
+ }
628
+
629
+ /* Convert a Smalltalk selector into a JS selector */
630
+
631
+ st.selector = function(string) {
632
+ var selector = '_' + string;
633
+ selector = selector.replace(/:/g, '_');
634
+ selector = selector.replace(/[\&]/g, '_and');
635
+ selector = selector.replace(/[\|]/g, '_or');
636
+ selector = selector.replace(/[+]/g, '_plus');
637
+ selector = selector.replace(/-/g, '_minus');
638
+ selector = selector.replace(/[*]/g ,'_star');
639
+ selector = selector.replace(/[\/]/g ,'_slash');
640
+ selector = selector.replace(/[\\]/g ,'_backslash');
641
+ selector = selector.replace(/[\~]/g ,'_tild');
642
+ selector = selector.replace(/>/g ,'_gt');
643
+ selector = selector.replace(/</g ,'_lt');
644
+ selector = selector.replace(/=/g ,'_eq');
645
+ selector = selector.replace(/,/g ,'_comma');
646
+ selector = selector.replace(/[@]/g ,'_at');
647
+ return selector
648
+ };
519
649
 
520
650
  /* Convert a string to a valid smalltalk selector.
521
651
  if you modify the following functions, also change String>>asSelector
@@ -531,21 +661,25 @@ function Smalltalk(){
531
661
 
532
662
  function convertKeywordSelector(selector) {
533
663
  return selector.replace(/^_/, '').replace(/_/g, ':');
534
- };
664
+ }
535
665
 
536
666
  function convertBinarySelector(selector) {
537
667
  return selector
538
668
  .replace(/^_/, '')
539
- .replace(/_plus/, '+')
540
- .replace(/_minus/, '-')
541
- .replace(/_star/, '*')
542
- .replace(/_slash/, '/')
543
- .replace(/_gt/, '>')
544
- .replace(/_lt/, '<')
545
- .replace(/_eq/, '=')
546
- .replace(/_comma/, ',')
547
- .replace(/_at/, '@')
548
- };
669
+ .replace(/_and/g, '&')
670
+ .replace(/_or/g, '|')
671
+ .replace(/_plus/g, '+')
672
+ .replace(/_minus/g, '-')
673
+ .replace(/_star/g, '*')
674
+ .replace(/_slash/g, '/')
675
+ .replace(/_backslash/g, '\\')
676
+ .replace(/_tild/g, '~')
677
+ .replace(/_gt/g, '>')
678
+ .replace(/_lt/g, '<')
679
+ .replace(/_eq/g, '=')
680
+ .replace(/_comma/g, ',')
681
+ .replace(/_at/g, '@')
682
+ }
549
683
 
550
684
  /* Converts a JavaScript object to valid Smalltalk Object */
551
685
  st.readJSObject = function(js) {
@@ -554,12 +688,12 @@ function Smalltalk(){
554
688
  var readArray = (js.constructor === Array);
555
689
 
556
690
  if(readObject) {
557
- object = smalltalk.Dictionary._new();
691
+ object = st.Dictionary._new();
558
692
  }
559
693
  for(var i in js) {
560
694
  if(readObject) {
561
695
  object._at_put_(i, st.readJSObject(js[i]));
562
- }
696
+ }
563
697
  if(readArray) {
564
698
  object[i] = st.readJSObject(js[i]);
565
699
  }
@@ -568,35 +702,76 @@ function Smalltalk(){
568
702
  };
569
703
 
570
704
  /* Boolean assertion */
571
- st.assert = function(boolean) {
572
- if ((undefined !== boolean) && (boolean.klass === smalltalk.Boolean)) {
573
- return boolean;
705
+ st.assert = function(shouldBeBoolean) {
706
+ if ((undefined !== shouldBeBoolean) && (shouldBeBoolean.klass === smalltalk.Boolean)) {
707
+ return shouldBeBoolean == true;
574
708
  } else {
575
- smalltalk.NonBooleanReceiver._new()._object_(boolean)._signal();
709
+ smalltalk.NonBooleanReceiver._new()._object_(shouldBeBoolean)._signal();
576
710
  }
577
- }
578
- };
711
+ };
579
712
 
580
- function SmalltalkMethodContext(receiver, selector, method, temps, home) {
581
- this.receiver = receiver;
582
- this.selector = selector;
583
- this.method = method;
584
- this.temps = temps || {};
713
+ /* Smalltalk initialization. Called on page load */
714
+
715
+ st.initialize = function() {
716
+ if(initialized) { return; }
717
+
718
+ classes.forEach(function(klass) {
719
+ st.init(klass);
720
+ });
721
+ classes.forEach(function(klass) {
722
+ klass._initialize();
723
+ });
724
+
725
+ initialized = true;
726
+ };
727
+ }
728
+
729
+ inherits(Smalltalk, SmalltalkObject);
730
+
731
+ function SmalltalkMethodContext(home, setup) {
585
732
  this.homeContext = home;
733
+ this.setup = setup || function() {};
734
+ this.pc = 0;
735
+ }
736
+
737
+ // Fallbacks
738
+ SmalltalkMethodContext.prototype.locals = {};
739
+ SmalltalkMethodContext.prototype.receiver = null;
740
+ SmalltalkMethodContext.prototype.selector = null;
741
+ SmalltalkMethodContext.prototype.lookupClass = null;
742
+
743
+ inherits(SmalltalkMethodContext, SmalltalkObject);
744
+
745
+ SmalltalkMethodContext.prototype.fill = function(receiver, selector, locals, lookupClass) {
746
+ this.receiver = receiver;
747
+ this.selector = selector;
748
+ this.locals = locals || {};
749
+ this.lookupClass = lookupClass;
586
750
  };
587
751
 
588
- SmalltalkMethodContext.prototype.copy = function() {
752
+ SmalltalkMethodContext.prototype.fillBlock = function(locals, ctx) {
753
+ this.locals = locals || {};
754
+ this.methodContext = ctx;
755
+ };
756
+
757
+ SmalltalkMethodContext.prototype.init = function() {
589
758
  var home = this.homeContext;
590
- if(home) {home = home.copy()}
591
- return new SmalltalkMethodContext(
592
- this.receiver,
593
- this.selector,
594
- this.method,
595
- this.temps,
596
- home
597
- );
759
+ if(home) {home = home.init()}
760
+
761
+ this.setup(this);
762
+ };
763
+
764
+ SmalltalkMethodContext.prototype.method = function() {
765
+ var method;
766
+ var lookup = this.lookupClass || this.receiver.klass;
767
+ while(!method && lookup) {
768
+ method = lookup.methods[smalltalk.convertSelector(this.selector)];
769
+ lookup = lookup.superclass
770
+ }
771
+ return method;
598
772
  };
599
773
 
774
+ // TODO: this is just wrong :)
600
775
  SmalltalkMethodContext.prototype.resume = function() {
601
776
  //Brutally set the receiver as thisContext, then re-enter the function
602
777
  smalltalk.thisContext = this;
@@ -612,39 +787,50 @@ if(this.jQuery) {
612
787
  this.jQuery.allowJavaScriptCalls = true;
613
788
  }
614
789
 
615
- /****************************************************************************************/
790
+ /*
791
+ * Answer the smalltalk representation of o.
792
+ * Used in message sends
793
+ */
794
+
795
+ var _st = function(o) {
796
+ if(o == null) {return nil}
797
+ if(o.klass) {return o}
798
+ return smalltalk.JSObjectProxy._on_(o);
799
+ };
616
800
 
617
801
 
618
- /* Base classes wrapping. If you edit this part, do not forget to set the superclass of the
619
- object metaclass to Class after the definition of Object */
802
+ /***************************************** BOOTSTRAP ******************************************/
620
803
 
621
- smalltalk.wrapClassName("Object", "Kernel", SmalltalkObject);
622
- smalltalk.wrapClassName("Smalltalk", "Kernel", Smalltalk, smalltalk.Object);
623
- smalltalk.wrapClassName("Package", "Kernel", SmalltalkPackage, smalltalk.Object);
624
- smalltalk.wrapClassName("Behavior", "Kernel", SmalltalkBehavior, smalltalk.Object);
625
- smalltalk.wrapClassName("Class", "Kernel", SmalltalkClass, smalltalk.Behavior);
626
- smalltalk.wrapClassName("Metaclass", "Kernel", SmalltalkMetaclass, smalltalk.Behavior);
627
- smalltalk.wrapClassName("CompiledMethod", "Kernel", SmalltalkMethod, smalltalk.Object);
628
- smalltalk.wrapClassName("Organizer", "Kernel-Objects", SmalltalkOrganizer, smalltalk.Object);
804
+ smalltalk.wrapClassName("Object", "Kernel-Objects", SmalltalkObject, undefined, false);
805
+ smalltalk.wrapClassName("Behavior", "Kernel-Classes", SmalltalkBehavior, smalltalk.Object, false);
806
+ smalltalk.wrapClassName("Metaclass", "Kernel-Classes", SmalltalkMetaclass, smalltalk.Behavior, false);
807
+ smalltalk.wrapClassName("Class", "Kernel-Classes", SmalltalkClass, smalltalk.Behavior, false);
629
808
 
630
809
  smalltalk.Object.klass.superclass = smalltalk.Class;
631
810
 
811
+
812
+ smalltalk.wrapClassName("Smalltalk", "Kernel-Objects", Smalltalk, smalltalk.Object, false);
813
+ smalltalk.wrapClassName("Package", "Kernel-Objects", SmalltalkPackage, smalltalk.Object, false);
814
+ smalltalk.wrapClassName("CompiledMethod", "Kernel-Methods", SmalltalkMethod, smalltalk.Object, false);
815
+ smalltalk.wrapClassName("Organizer", "Kernel-Objects", SmalltalkOrganizer, smalltalk.Object, false);
816
+
817
+
632
818
  smalltalk.wrapClassName("Number", "Kernel", Number, smalltalk.Object);
633
819
  smalltalk.wrapClassName("BlockClosure", "Kernel", Function, smalltalk.Object);
634
820
  smalltalk.wrapClassName("Boolean", "Kernel", Boolean, smalltalk.Object);
635
821
  smalltalk.wrapClassName("Date", "Kernel", Date, smalltalk.Object);
636
- smalltalk.wrapClassName("UndefinedObject", "Kernel", SmalltalkNil, smalltalk.Object);
822
+ smalltalk.wrapClassName("UndefinedObject", "Kernel", SmalltalkNil, smalltalk.Object, false);
637
823
 
638
- smalltalk.wrapClassName("Collection", "Kernel", null, smalltalk.Object);
639
- smalltalk.wrapClassName("SequenceableCollection", "Kernel", null, smalltalk.Collection);
640
- smalltalk.wrapClassName("CharacterArray", "Kernel", null, smalltalk.SequenceableCollection);
824
+ smalltalk.addClass("Collection", smalltalk.Object, null, "Kernel");
825
+ smalltalk.addClass("SequenceableCollection", smalltalk.Collection, null, "Kernel");
826
+ smalltalk.addClass("CharacterArray", smalltalk.SequenceableCollection, null, "Kernel");
641
827
  smalltalk.wrapClassName("String", "Kernel", String, smalltalk.CharacterArray);
642
- smalltalk.wrapClassName("Symbol", "Kernel", SmalltalkSymbol, smalltalk.CharacterArray);
828
+ smalltalk.wrapClassName("Symbol", "Kernel", SmalltalkSymbol, smalltalk.CharacterArray, false);
643
829
  smalltalk.wrapClassName("Array", "Kernel", Array, smalltalk.SequenceableCollection);
644
- smalltalk.wrapClassName("RegularExpression", "Kernel", RegExp, smalltalk.String);
830
+ smalltalk.wrapClassName("RegularExpression", "Kernel", RegExp, smalltalk.Object);
645
831
 
646
832
  smalltalk.wrapClassName("Error", "Kernel", Error, smalltalk.Object);
647
- smalltalk.wrapClassName("MethodContext", "Kernel", SmalltalkMethodContext, smalltalk.Object);
833
+ smalltalk.wrapClassName("MethodContext", "Kernel", SmalltalkMethodContext, smalltalk.Object, false);
648
834
 
649
835
  /* Alias definitions */
650
836