Browse Source

- Added Widget>>alert:
- Check for parse error before compiling (class browser and workspace)
- added convenience methods in Compiler for parsing source

Nicolas Petton 14 years ago
parent
commit
e2e8ff82ff
6 changed files with 89 additions and 15 deletions
  1. 12 0
      js/canvas.js
  2. 28 4
      js/compiler.js
  3. 21 6
      js/ide.js
  4. 4 0
      st/canvas.st
  5. 10 2
      st/compiler.st
  6. 14 3
      st/ide.st

+ 12 - 0
js/canvas.js

@@ -770,6 +770,18 @@ return self;},
 source: unescape('appendToJQuery%3A%20aJQuery%0A%20%20%20%20self%20render.%0A%20%20%20%20aJQuery%20append%3A%20self%20root%20asJQuery%0A')}),
 smalltalk.Widget);
 
+smalltalk.addMethod(
+'_alert_',
+smalltalk.method({
+selector: 'alert:',
+category: 'actions',
+fn: function (aString){
+var self=this;
+(function(){alert(aString)})();
+return self;},
+source: unescape('alert%3A%20aString%0A%20%20%20%20%7B%27alert%28aString%29%27%7D%0A')}),
+smalltalk.Widget);
+
 smalltalk.addMethod(
 '_confirm_',
 smalltalk.method({

+ 28 - 4
js/compiler.js

@@ -846,9 +846,9 @@ category: 'compiling',
 fn: function (aString){
 var self=this;
 self._currentClass_(smalltalk.DoIt);
-return self._compile_(unescape("doIt%20%5E%5B").__comma(aString).__comma(unescape("%5D%20value")));
+return self._compileNode_(self._parseExpression_(aString));
 return self;},
-source: unescape('compileExpression%3A%20aString%0A%09self%20currentClass%3A%20DoIt.%0A%09%5Eself%20compile%3A%20%27doIt%20%5E%5B%27%2C%20aString%2C%20%27%5D%20value%27%0A')}),
+source: unescape('compileExpression%3A%20aString%0A%09self%20currentClass%3A%20DoIt.%0A%09%5Eself%20compileNode%3A%20%28self%20parseExpression%3A%20aString%29%0A')}),
 smalltalk.Compiler);
 
 smalltalk.addMethod(
@@ -870,9 +870,9 @@ selector: 'compile:',
 category: 'compiling',
 fn: function (aString){
 var self=this;
-return self._compileNode_(self._parser()._parse_(aString._readStream()));
+return self._compileNode_(self._parse_(aString));
 return self;},
-source: unescape('compile%3A%20aString%0A%09%5Eself%20compileNode%3A%20%28self%20parser%20parse%3A%20aString%20readStream%29%0A')}),
+source: unescape('compile%3A%20aString%0A%09%5Eself%20compileNode%3A%20%28self%20parse%3A%20aString%29%0A')}),
 smalltalk.Compiler);
 
 smalltalk.addMethod(
@@ -1086,6 +1086,30 @@ return self;},
 source: unescape('visitJSStatementNode%3A%20aNode%0A%09stream%20nextPutAll%3A%20%27%28function%28%29%7B%27.%0A%09stream%20nextPutAll%3A%20%28aNode%20source%20value%20replace%3A%20%27%27%27%27%27%27%20with%3A%20%27%27%27%27%29.%0A%09stream%20nextPutAll%3A%20%27%7D%29%28%29%27%0A')}),
 smalltalk.Compiler);
 
+smalltalk.addMethod(
+'_parse_',
+smalltalk.method({
+selector: 'parse:',
+category: 'compiling',
+fn: function (aString){
+var self=this;
+return self._parser()._parse_(aString._readStream());
+return self;},
+source: unescape('parse%3A%20aString%0A%20%20%20%20%5Eself%20parser%20parse%3A%20aString%20readStream%0A')}),
+smalltalk.Compiler);
+
+smalltalk.addMethod(
+'_parseExpression_',
+smalltalk.method({
+selector: 'parseExpression:',
+category: 'compiling',
+fn: function (aString){
+var self=this;
+return self._parse_(unescape("doIt%20%5E%5B").__comma(aString).__comma(unescape("%5D%20value")));
+return self;},
+source: unescape('parseExpression%3A%20aString%0A%20%20%20%20%5Eself%20parse%3A%20%27doIt%20%5E%5B%27%2C%20aString%2C%20%27%5D%20value%27%0A')}),
+smalltalk.Compiler);
+
 
 
 smalltalk.addClass('DoIt', smalltalk.Object, [], 'Compiler');

+ 21 - 6
js/ide.js

@@ -497,9 +497,15 @@ selector: 'eval:',
 category: 'actions',
 fn: function (aString){
 var self=this;
-return smalltalk.Compiler._new()._loadExpression_(aString);
-return self;},
-source: unescape('eval%3A%20aString%0A%20%20%20%20%5ECompiler%20new%20loadExpression%3A%20aString%0A')}),
+try{var compiler=nil;
+var node=nil;
+compiler=smalltalk.Compiler._new();
+node=compiler._parseExpression_(aString);
+node._isParseFailure()._ifTrue_((function(){return (function(){throw({name: 'stReturn', selector: '_eval_', fn: function(){return self._alert_(node._reason().__comma(unescape("%2C%20position%3A%20")).__comma(node._position()))}})})();}));
+(function(){throw({name: 'stReturn', selector: '_eval_', fn: function(){return compiler._loadExpression_(aString)}})})();
+return self;
+} catch(e) {if(e.name === 'stReturn' && e.selector === '_eval_'){return e.fn()} throw(e)}},
+source: unescape('eval%3A%20aString%0A%20%20%20%20%7C%20compiler%20node%20%7C%0A%20%20%20%20compiler%20%3A%3D%20Compiler%20new.%0A%20%20%20%20node%20%3A%3D%20compiler%20parseExpression%3A%20aString.%0A%20%20%20%20node%20isParseFailure%20ifTrue%3A%20%5B%0A%09%5Eself%20alert%3A%20node%20reason%2C%20%27%2C%20position%3A%20%27%2C%20node%20position%5D.%0A%20%20%20%20%5Ecompiler%20loadExpression%3A%20aString%0A')}),
 smalltalk.Workspace);
 
 smalltalk.addMethod(
@@ -981,14 +987,23 @@ selector: 'compileMethodDefinitionFor:',
 category: 'actions',
 fn: function (aClass){
 var self=this;
+try{var compiler=nil;
 var method=nil;
-method=smalltalk.Compiler._new()._load_forClass_(self['@sourceTextarea']._asJQuery()._val(),self['@selectedClass']);
+var source=nil;
+var node=nil;
+source=self['@sourceTextarea']._asJQuery()._val();
+compiler=smalltalk.Compiler._new();
+node=compiler._parse_(source);
+node._isParseFailure()._ifTrue_((function(){return (function(){throw({name: 'stReturn', selector: '_compileMethodDefinitionFor_', fn: function(){return self._alert_("PARSE ERROR: ".__comma(node._reason()).__comma(unescape("%2C%20position%3A%20")).__comma(node._position()._asString()))}})})();}));
+compiler._currentClass_(self['@selectedClass']);
+method=compiler._eval_(compiler._compileNode_(node));
 method._category_(self['@selectedProtocol']);
 aClass._addCompiledMethod_(method);
 self._updateMethodsList();
 self._selectMethod_(method);
-return self;},
-source: unescape('compileMethodDefinitionFor%3A%20aClass%0A%20%20%20%20%7C%20method%20%7C%0A%20%20%20%20method%20%3A%3D%20Compiler%20new%20load%3A%20sourceTextarea%20asJQuery%20val%20forClass%3A%20selectedClass.%0A%20%20%20%20method%20category%3A%20selectedProtocol.%0A%20%20%20%20aClass%20addCompiledMethod%3A%20method.%0A%20%20%20%20self%20updateMethodsList.%0A%20%20%20%20self%20selectMethod%3A%20method%0A')}),
+return self;
+} catch(e) {if(e.name === 'stReturn' && e.selector === '_compileMethodDefinitionFor_'){return e.fn()} throw(e)}},
+source: unescape('compileMethodDefinitionFor%3A%20aClass%0A%20%20%20%20%7C%20compiler%20method%20source%20node%20%7C%0A%20%20%20%20source%20%3A%3D%20sourceTextarea%20asJQuery%20val.%0A%20%20%20%20compiler%20%3A%3D%20Compiler%20new.%0A%20%20%20%20node%20%3A%3D%20compiler%20parse%3A%20source.%0A%20%20%20%20node%20isParseFailure%20ifTrue%3A%20%5B%0A%09%5Eself%20alert%3A%20%27PARSE%20ERROR%3A%20%27%2C%20node%20reason%2C%20%27%2C%20position%3A%20%27%2C%20node%20position%20asString%5D.%0A%20%20%20%20compiler%20currentClass%3A%20selectedClass.%0A%20%20%20%20method%20%3A%3D%20compiler%20eval%3A%20%28compiler%20compileNode%3A%20node%29.%0A%20%20%20%20method%20category%3A%20selectedProtocol.%0A%20%20%20%20aClass%20addCompiledMethod%3A%20method.%0A%20%20%20%20self%20updateMethodsList.%0A%20%20%20%20self%20selectMethod%3A%20method%0A')}),
 smalltalk.Browser);
 
 smalltalk.addMethod(

+ 4 - 0
st/canvas.st

@@ -309,6 +309,10 @@ appendToJQuery: aJQuery
 
 !Widget methodsFor: 'actions'!
 
+alert: aString
+    {'alert(aString)'}
+!
+
 confirm: aString
     ^{'return window.confirm(aString)'}
 !

+ 10 - 2
st/compiler.st

@@ -409,8 +409,16 @@ parser
 
 !Compiler methodsFor: 'compiling'!
 
+parse: aString
+    ^self parser parse: aString readStream
+!
+
+parseExpression: aString
+    ^self parse: 'doIt ^[', aString, '] value'
+!
+
 compile: aString
-	^self compileNode: (self parser parse: aString readStream)
+	^self compileNode: (self parse: aString)
 !
 
 compile: aString forClass: aClass
@@ -420,7 +428,7 @@ compile: aString forClass: aClass
 
 compileExpression: aString
 	self currentClass: DoIt.
-	^self compile: 'doIt ^[', aString, '] value'
+	^self compileNode: (self parseExpression: aString)
 !
 
 compileNode: aNode

+ 14 - 3
st/ide.st

@@ -286,7 +286,12 @@ print: aString
 !
 
 eval: aString
-    ^Compiler new loadExpression: aString
+    | compiler node |
+    compiler := Compiler new.
+    node := compiler parseExpression: aString.
+    node isParseFailure ifTrue: [
+	^self alert: node reason, ', position: ', node position].
+    ^compiler loadExpression: aString
 ! !
 
 !Workspace methodsFor: 'rendering'!
@@ -589,8 +594,14 @@ compileMethodDefinition
 !
 
 compileMethodDefinitionFor: aClass
-    | method |
-    method := Compiler new load: sourceTextarea asJQuery val forClass: selectedClass.
+    | compiler method source node |
+    source := sourceTextarea asJQuery val.
+    compiler := Compiler new.
+    node := compiler parse: source.
+    node isParseFailure ifTrue: [
+	^self alert: 'PARSE ERROR: ', node reason, ', position: ', node position asString].
+    compiler currentClass: selectedClass.
+    method := compiler eval: (compiler compileNode: node).
     method category: selectedProtocol.
     aClass addCompiledMethod: method.
     self updateMethodsList.