[PATCH] prototype patch to fix mutate.st

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] prototype patch to fix mutate.st

Paolo Bonzini
This fixes one of the blockers for the release.  Basically:

- CompiledMethods remembers if they were old or new syntax

- #compile: only accepts methods with the new syntax

- #recompile is added to CompiledMethod

- a new #methodFormattedSourceString method was added which is used to
recompile old-syntax methods (and is only provided when Parser is
loaded, so old-syntax methods can only be recompiled if Parser is loaded)

- the C and STInST parsers was adapted to mark old-syntax methods
appropriately

- #parserClass was moved from Behavior to CompiledMethod.  While it is
all fine that different Behaviors have different Compilers, if we want
any tool to reason on the source code it *must* be standard Smalltalk
syntax.  Stephen's recent Presource examples show how far you can go
while remaining within those boundaries.  Even parsing could be done
using a syntax like this:

  term [
      <parse: #rule>
      factor save, ((#+ | #-) save, factor save) sequence
          -> [ :op1 :ops |
                ops inject: op1 into: [ :result :op |
                    result perform: op first with: op second ].
  ]

  factor [
      <parse: #rule>
      primary save,
      ((#* | (#/ -> #//) save, primary save) sequence
          -> [ :op1 :ops |
                ops inject: op1 into: [ :result :op |
                    result perform: op first with: op second ].
  ]

  primary [
      <parse: #rule>
      number save
      | #'(', term save, #')'
      -> [ :value | value ].

      identifier
      -> [ :name | vars at: name ].
  ]


Needs more testing, but unless someone screams that they don't like it
and suggest a better way, this will be committed.

Paolo

2007-10-14  Paolo Bonzini  <[hidden email]>
 
        * kernel/Behavior.st: Move recompilation methods to CompiledMethod.
        Move #instanceVariableNames: and related methods from ClassDescription.
        Change #updateInstanceVars:shape: to
        #updateInstanceVars:numInherited:shape:.
        * kernel/Builtins.st: Promote #instanceVariableNames: to Behavior.
        * kernel/CStruct.st: Compile methods as new syntax.
        * kernel/ClassDesc.st: Remove #instanceVariableNames: and related
        methods.
        * kernel/CompildMeth.st: Add #methodFormattedSourceString,
        #isOldSyntax, #noteOldSyntax, #recompile, #recompileNotifying:.
        Support recompiling methods from both syntaxes.
        * kernel/Metaclass.st: Change #updateInstanceVars:shape: to
        #updateInstanceVars:numInherited:shape:.
        * kernel/UndefObject.st: Add #instSize for polymorphism.

        * tests/mutate.st: Add new tests on class extension.
        * tests/mutate.ok: Update test results.

2007-10-14  Paolo Bonzini  <[hidden email]>

        * libgst/comp.c: Add brackets to source code of #methodsFor:.  
        Set isOldSyntax bit of the CompiledMethod header.
        * libgst/comp.h: Add isOldSyntax bit.
        * libgst/gst-parse.c: Parse isolated methods with new syntax.
        * libgst/tree.c: Add isOldSyntax argument to _gst_make_method.
        * libgst/tree.h: Likewise, and add it to AST.

packages/stinst/compiler:
2007-10-14  Paolo Bonzini  <[hidden email]>

        * StartCompiler.st: Remove #parserClass from Behavior.

packages/stinst/parser:
2007-10-14  Paolo Bonzini  <[hidden email]>

        * Exporter.st: Add #methodFormattedSourceString and use it.
        Add #parserClass.
        * GSTParser.st: Support adding more instance variables to a class.
        * RBParser.st: Add RBBracketedMethodParser.
        * SIFParser.st: Send #noteOldSyntax to compiled methods.
        * STFileParser.st: Return compiled methods from #compile:.  Add
        #resolveClass:.  Send #noteOldSyntax to compiled methods.
        * STLoader.st: Return compiled methods from #compile:.
        * STLoaderObjs.st: Add dummy #noteOldSyntax method to LoadedMethod.



* looking for [hidden email]--2004b/smalltalk--devo--2.2--patch-606 to compare with
* comparing to [hidden email]--2004b/smalltalk--devo--2.2--patch-606
M  packages/stinst/parser/STFileParser.st
M  packages/stinst/parser/Exporter.st
M  tests/testsuite.at
M  tests/testsuite
M  packages/stinst/compiler/ChangeLog
M  packages/stinst/parser/SIFParser.st
M  packages/stinst/parser/GSTParser.st
M  ChangeLog
M  packages/stinst/parser/ChangeLog
M  NEWS
M  packages/stinst/parser/RBParser.st
M  packages/stinst/parser/STLoader.st
M  packages/stinst/parser/STLoaderObjs.st
M  packages/stinst/compiler/StartCompiler.st
M  kernel/Behavior.st
M  kernel/Builtins.st
M  kernel/CStruct.st
M  kernel/ClassDesc.st
M  kernel/CompildMeth.st
M  kernel/Metaclass.st
M  kernel/UndefObject.st
M  libgst/ChangeLog
M  libgst/gst-parse.c
M  libgst/comp.c
M  libgst/comp.h
M  libgst/tree.c
M  libgst/tree.h
M  tests/mutate.ok
M  tests/mutate.st

* modified files

--- orig/NEWS
+++ mod/NEWS
@@ -66,6 +66,12 @@ o   The #writeStream method was moved do
 o   The database access library has been replaced by a new DBI-like library,
     contributed by Mike Anderson.
 
+o   In general, GNU Smalltalk is able to load files with the old syntax.
+    In some cases, however, it will be necessary to either convert them
+    using the gst-convert tool, or load the Parser package before them.
+    This is the case if you get a "not yet implemented" error while loading
+    the files.
+
 
 Packages improvements:
 


--- orig/kernel/Behavior.st
+++ mod/kernel/Behavior.st
@@ -54,7 +54,10 @@ method dictionary, and iterating over th
     ifTrue: [{symbol}]
     ifFalse: [instanceVariables copyWith: symbol].
  duplicated := self superclass allInstVarNames includes: symbol.
- self updateInstanceVars: newInstanceVariables shape: self shape.
+ self
+    updateInstanceVars: newInstanceVariables
+    numInherited: self superclass instSize
+    shape: self shape.
  duplicated ifTrue: [self compileAll].
  self compileAllSubclasses
     ]
@@ -73,12 +76,58 @@ method dictionary, and iterating over th
     copyReplaceFrom: index
     to: index
     with: #().
- self updateInstanceVars: newInstanceVariables shape: self shape.
+ self
+    updateInstanceVars: newInstanceVariables
+    numInherited: self superclass instSize
+    shape: self shape.
  self
     compileAll;
     compileAllSubclasses
     ]
 
+    instanceVariableNames: instVarNames [
+        "Set the instance variables for the receiver to be those
+         in instVarNames"
+
+        <category: 'instance variables'>
+        | variableArray oldInstVarNames |
+        variableArray := self parseInstanceVariableString: instVarNames.
+        variableArray := self subclassInstVarNames, variableArray.
+        oldInstVarNames := self allInstVarNames.
+
+        "If instance variables change, update  instance variables and
+         instance spec of the class and all its subclasses"
+        variableArray = oldInstVarNames ifTrue: [^self].
+        self
+    updateInstanceVars: variableArray
+    numInherited: self superclass instSize
+    shape: self shape.
+
+        "If no variable has been removed, no need to recompile"
+        (oldInstVarNames allSatisfy: [:each | variableArray includes: each])
+            ifTrue: [^self].
+        Transcript
+            nextPutAll: 'Recompiling classes...';
+            nl.
+        self compileAll.
+        self compileAllSubclasses
+    ]
+
+    parseInstanceVariableString: variableString [
+        <category: 'parsing class declarations'>
+        | variableArray |
+        variableArray := self parseVariableString: variableString.
+        ^variableArray collect: [:each | each asSymbol]
+    ]
+
+    parseVariableString: aString [
+        <category: 'parsing class declarations'>
+        | tokens |
+        tokens := aString subStrings asArray.
+        tokens do: [:token | self validateIdentifier: token].
+        ^tokens
+    ]
+
     createGetMethod: what default: value [
  "Create a method accessing the variable `what', with a default value
  of `value', using lazy initialization"
@@ -261,21 +310,7 @@ method dictionary, and iterating over th
  the new CompiledMethod if everything's ok."
 
  <category: 'method dictionary'>
- | source category ok |
- ok :=
- [source := self sourceCodeAt: selector.
- category := (self compiledMethodAt: selector) methodCategory.
- true]
- on: Error
- do: [:ex | ex return: false].
- ok ifFalse: [^nil].
- RegressionTesting
-    ifFalse:
- [Transcript
-    nextPutAll: 'Recompiling selector: ';
-    print: selector asSymbol;
-    nl].
- ^self compile: source classified: category
+ (self compiledMethodAt: selector) recompile.
     ]
 
     recompile: selector notifying: aNotifier [
@@ -284,24 +319,7 @@ method dictionary, and iterating over th
  compilation"
 
  <category: 'method dictionary'>
- | source category ok |
- ok :=
- [source := self sourceCodeAt: selector.
- category := (self compiledMethodAt: selector) methodCategory.
- true]
- on: Error
- do: [:ex | ex return: false].
- ok ifFalse: [^nil].
- RegressionTesting
-    ifFalse:
- [Transcript
-    nextPutAll: 'Recompiling selector: ';
-    print: selector asSymbol;
-    nl].
- ^self
-    compile: source
-    classified: category
-    notifying: aNotifier
+ (self compiledMethodAt: selector) recompileNotifying: aNotifier.
     ]
 
     decompile: selector [
@@ -364,7 +382,7 @@ method dictionary, and iterating over th
     nextPutAll: 'Recompiling class: ';
     print: self;
     nl].
- self methodDictionary keysDo: [:selector | self recompile: selector]]
+ self methodDictionary do: [:method | method recompile]]
     ]
 
     compileAll: aNotifier [
@@ -380,8 +398,7 @@ method dictionary, and iterating over th
     nextPutAll: 'Recompiling class: ';
     print: self;
     nl].
- self methodDictionary
-    keysDo: [:selector | self recompile: selector notifying: aNotifier]]
+ self methodDictionary do: [:method | method recompileNotifying: aNotifier]]
     ]
 
     evalString: aString to: anObject [
@@ -994,8 +1011,11 @@ method dictionary, and iterating over th
  [realShape := CSymbols.CLongSize = 4 ifTrue: [#uint] ifFalse: [#uint64]].
  shape = #inherit ifTrue: [realShape := self superclass shape].
  self shape == realShape ifTrue: [^false].
- realShape isNil
-    ifTrue: [^self updateInstanceVars: self allInstVarNames shape: nil].
+ realShape isNil ifTrue: [
+            self
+        updateInstanceVars: self allInstVarNames
+        numInherited: self superclass instSize
+        shape: nil ].
  self isVariable
     ifTrue:
  [SystemExceptions.MutationError
@@ -1317,15 +1337,13 @@ method dictionary, and iterating over th
  ^true
     ]
 
-    updateInstanceVars: variableArray shape: shape [
+    updateInstanceVars: variableArray numInherited: numInherited shape: shape [
  "Update instance variables and instance spec of the class and all
  its subclasses"
 
  <category: 'private'>
  | instVarMap startOfInstanceVars endOfInstanceVars newInstanceVars oldInstVars oldClass instances |
- startOfInstanceVars := self superclass isNil
-    ifTrue: [1]
-    ifFalse: [self superclass instSize + 1].
+ startOfInstanceVars := numInherited + 1.
  endOfInstanceVars := self instSize.
  newInstanceVars := variableArray copyFrom: startOfInstanceVars
     to: variableArray size.


--- orig/kernel/Builtins.st
+++ mod/kernel/Builtins.st
@@ -171,14 +171,14 @@ Class extend [
 ]
     
 ClassDescription extend [
-    instanceVariableNames: ivn [
-    ]
-
     import: aString [
     ]
 ]
     
 Behavior extend [
+    instanceVariableNames: ivn [
+    ]
+
     shape: aSymbol [
     ]
 ]


--- orig/kernel/CStruct.st
+++ mod/kernel/CStruct.st
@@ -130,7 +130,7 @@ CObject subclass: CCompound [
  maxAlignment := self superclass alignof.
  inspStr := WriteStream on: (String new: 8).
  inspStr
-    nextPutAll: 'inspectSelectorList';
+    nextPutAll: 'inspectSelectorList [';
     nl;
     nextPutAll: '    ^#('.
 
@@ -148,14 +148,18 @@ CObject subclass: CCompound [
  str := WriteStream on: (String new: 20).
  str
     nextPutAll: name;
+    nextPutAll: ' [';
     nl;
     nextPutAll: '    ^self at: ';
     print: offset;
     nextPutAll: ' type: ';
-    store: type.
+    store: type;
+    nl;
+    nextPut: $].
  self compile: str classified: 'accessing'.
  offset := offset + type sizeof].
- self compile: inspStr contents , ')' classified: 'debugging'.
+ inspStr nextPut: $); nl; nextPut: $].
+ self compile: inspStr contents classified: 'debugging'.
  self compileSize: offset align: maxAlignment
     ]
 
@@ -164,10 +168,12 @@ CObject subclass: CCompound [
 
  <category: 'subclass creation'>
  | sizeofMethod alignofMethod |
- sizeofMethod := 'sizeof
-    ^' , (size alignTo: alignment) printString.
- alignofMethod := 'alignof
-    ^' , alignment printString.
+ sizeofMethod := 'sizeof [
+    ^' , (size alignTo: alignment) printString, '
+]'.
+ alignofMethod := 'alignof [
+    ^' , alignment printString, '
+]'.
  self compile: sizeofMethod classified: 'accessing'.
  self class compile: sizeofMethod classified: 'accessing'.
  self compile: alignofMethod classified: 'accessing'.


--- orig/kernel/ClassDesc.st
+++ mod/kernel/ClassDesc.st
@@ -386,45 +386,5 @@ files.'>
  <category: 'parsing class declarations'>
  self addSharedPool: aDictionary
     ]
-
-    instanceVariableNames: instVarNames [
- "Set the instance variables for the receiver to be those
- in instVarNames"
-
- <category: 'parsing class declarations'>
- | variableArray variableString oldInstVarNames |
- variableArray := self parseInstanceVariableString: instVarNames.
- variableArray := self subclassInstVarNames , variableArray.
- oldInstVarNames := self allInstVarNames.
-
- "If instance variables change, update  instance variables and
- instance spec of the class and all its subclasses"
- variableArray = oldInstVarNames ifTrue: [^self].
- self updateInstanceVars: variableArray shape: self shape.
-
- "If no variable has been removed, no need to recompile"
- (oldInstVarNames allSatisfy: [:each | variableArray includes: each])
-    ifTrue: [^self].
- Transcript
-    nextPutAll: 'Recompiling classes...';
-    nl.
- self compileAll.
- self compileAllSubclasses
-    ]
-
-    parseInstanceVariableString: variableString [
- <category: 'parsing class declarations'>
- | variableArray |
- variableArray := self parseVariableString: variableString.
- ^variableArray collect: [:each | each asSymbol]
-    ]
-
-    parseVariableString: aString [
- <category: 'parsing class declarations'>
- | tokens |
- tokens := aString subStrings asArray.
- tokens do: [:token | self validateIdentifier: token].
- ^tokens
-    ]
 ]
 


--- orig/kernel/CompildMeth.st
+++ mod/kernel/CompildMeth.st
@@ -121,6 +121,13 @@ instances.'>
     ifFalse: [descriptor sourceCode]
     ]
 
+    methodFormattedSourceString [
+ "Answer the method source code as a string"
+
+ <category: 'basic'>
+ self notYetImplemented
+    ]
+
     methodSourceString [
  "Answer the method source code as a string"
 
@@ -248,7 +255,23 @@ instances.'>
  "Answer the primitive called by the receiver"
 
  <category: 'accessing'>
- ^(header bitShift: -17) bitAnd: 1023
+ ^(header bitShift: -17) bitAnd: 511
+    ]
+
+    isOldSyntax [
+ "Answer whether the method was written with the old (chunk-format)
+ syntax"
+
+ <category: 'accessing'>
+ ^((header bitShift: -26) bitAnd: 1) == 1
+    ]
+
+    noteOldSyntax [
+ "Remember that the method is written with the old (chunk-format)
+         syntax"
+
+        <category: 'accessing'>
+ header := header bitOr: (1 bitShift: 26)
     ]
 
     allLiterals [
@@ -301,6 +324,56 @@ instances.'>
     ifFalse: [anObject perform: self withArguments: args]
     ]
 
+    recompile [
+ "Recompile the method in the scope of the class where it leaves."
+
+ <category: 'compiling'>
+        | source category ok |
+        ok :=
+                [source := self isOldSyntax
+ ifTrue: [ self methodFormattedSourceString ]
+ ifFalse: [ self methodSourceString ].
+                category := self methodCategory.
+                true]
+                        on: Error
+                        do: [:ex | ex return: false].
+        ok ifFalse: [^nil].
+        RegressionTesting
+            ifFalse:
+                [Transcript
+                    nextPutAll: 'Recompiling selector: ';
+                    print: self selector asSymbol;
+                    nl].
+        ^self methodClass compile: source classified: category
+    ]
+
+    recompileNotifying: aNotifier [
+ "Recompile the method in the scope of the class where it leaves,
+ notifying errors to aNotifier by sending it #error:."
+
+ <category: 'compiling'>
+        | source category ok |
+        ok :=
+                [source := self isOldSyntax
+ ifTrue: [ self methodFormattedSourceString ]
+ ifFalse: [ self methodSourceString ].
+                category := self methodCategory.
+                true]
+                        on: Error
+                        do: [:ex | ex return: false].
+        ok ifFalse: [^nil].
+        RegressionTesting
+            ifFalse:
+                [Transcript
+                    nextPutAll: 'Recompiling selector: ';
+                    print: self selector asSymbol;
+                    nl].
+        ^self methodClass
+    compile: source
+    classified: category
+    notifying: aNotifier
+    ]
+
     isAnnotated [
  "If the receiver has any attributes, answer true."
 


--- orig/kernel/Metaclass.st
+++ mod/kernel/Metaclass.st
@@ -276,7 +276,10 @@ it should be...the Smalltalk metaclass s
     | needToRecompileMetaclasses) | (aClass shape ~~ realShape)
     ifTrue:
  [aClass instanceCount > 0 ifTrue: [ObjectMemory globalGarbageCollect].
- aClass updateInstanceVars: variableArray shape: realShape].
+ aClass
+    updateInstanceVars: variableArray
+    numInherited: superclass instSize
+    shape: realShape].
 
  "Now add/remove pool dictionaries.  FIXME: They may affect name binding,
  so we should probably recompile everything if they change."
@@ -299,8 +302,11 @@ it should be...the Smalltalk metaclass s
 
  self superclass allInstVarNames ~= superclass class allInstVarNames
     ifTrue:
- [aClass class updateInstanceVars: superclass class allInstVarNames
-    , aClass class instVarNames
+ [aClass class
+    updateInstanceVars:
+ superclass class allInstVarNames,
+ aClass class instVarNames
+    numInherited: superclass class instSize
     shape: aClass class shape].
 
  "Fix references between classes..."


--- orig/kernel/UndefObject.st
+++ mod/kernel/UndefObject.st
@@ -257,6 +257,11 @@ instance, which is the object "nil".'>
     yourself
     ]
 
+    instSize [
+ <category: 'class polymorphism'>
+ ^0
+    ]
+
     methodDictionary [
  <category: 'class polymorphism'>
  ^nil


--- orig/libgst/comp.c
+++ mod/libgst/comp.c
@@ -472,12 +472,12 @@ _gst_install_initial_methods (void)
   install_method (termination_method);
 
   methodsForString = "\
-methodsFor: aCategoryString \
+methodsFor: aCategoryString [\
     \"Calling this method prepares the parser to receive methods \
       to be compiled and installed in the receiver's method dictionary. \
       The methods are put in the category identified by the parameter.\" \
     <primitive: VMpr_Behavior_methodsFor> \
-";
+]";
   _gst_set_compilation_class (_gst_behavior_class);
   _gst_set_compilation_category (_gst_string_new ("compiling methods"));
   _gst_push_smalltalk_string (_gst_string_new (methodsForString));
@@ -662,7 +662,7 @@ _gst_execute_statements (tree_node temps
   methodOOP =
     _gst_compile_method (_gst_make_method (&statements->location, &loc,
    messagePattern, temps, NULL,
-   statements),
+   statements, false),
  true, false);
 
   SET_CLASS_ENVIRONMENT (_gst_undefined_object_class,
@@ -793,6 +793,7 @@ _gst_compile_method (tree_node method,
   int primitiveIndex;
   int stack_depth;
   inc_ptr incPtr;
+  gst_compiled_method compiledMethod;
 
   dup_message_receiver = false;
   literal_vec_curr = literal_vec;
@@ -900,6 +901,9 @@ _gst_compile_method (tree_node method,
  _gst_this_category,
  method->location.file_offset,
  method->v_method.endPos);
+
+      compiledMethod = (gst_compiled_method) OOP_TO_OBJ (methodOOP);
+      compiledMethod->header.isOldSyntax = method->v_method.isOldSyntax;
       INC_ADD_OOP (methodOOP);
 
       if (install)
@@ -2689,6 +2693,7 @@ _gst_make_new_method (int primitiveIndex
   inc_ptr incPtr;
 
   maximumStackDepth += numArgs + numTemps;
+  memset (&header, 0, sizeof (method_header));
 
   incPtr = INC_SAVE_POINTER ();
   if (primitiveIndex)
@@ -2867,6 +2872,8 @@ _gst_block_new (int numArgs,
   maximumStackDepth++; /* just to be sure */
 
   numByteCodes = _gst_bytecode_length (bytecodes);
+
+  memset (&header, 0, sizeof (header));
   header.numArgs = numArgs;
   header.numTemps = numTemps;
   header.depth = maximumStackDepth;


--- orig/libgst/comp.h
+++ mod/libgst/comp.h
@@ -88,7 +88,7 @@
 #define MTH_DEPTH_BITS 6
 #define MTH_TEMPS_BITS 6
 #define MTH_ARGS_BITS 5
-#define MTH_PRIM_BITS 10
+#define MTH_PRIM_BITS 9
 #define MTH_FLAG_BITS 3
 
 #define MTH_NORMAL 0
@@ -108,8 +108,8 @@ typedef struct method_header
 #endif
   unsigned :1; /* sign - must be 0 */
   unsigned headerFlag:MTH_FLAG_BITS; /* prim _gst_self, etc.  */
-  unsigned primitiveIndex:MTH_PRIM_BITS; /* index of primitve,
-   or 0 */
+  unsigned isOldSyntax:1;
+  unsigned primitiveIndex:MTH_PRIM_BITS; /* index of primitive, or 0 */
   unsigned numTemps:MTH_TEMPS_BITS;
   unsigned stack_depth:MTH_DEPTH_BITS;
   unsigned numArgs:MTH_ARGS_BITS;
@@ -121,6 +121,7 @@ typedef struct method_header
   unsigned numTemps:MTH_TEMPS_BITS;
   unsigned primitiveIndex:MTH_PRIM_BITS; /* index of primitve,
    or 0 */
+  unsigned isOldSyntax:1;
   unsigned headerFlag:MTH_FLAG_BITS; /* prim _gst_self, etc.  */
   unsigned :1; /* sign - must be 0 */
 #if SIZEOF_OOP == 8


--- orig/libgst/gst-parse.c
+++ mod/libgst/gst-parse.c
@@ -314,7 +314,7 @@ _gst_parse_method ()
   p.state = PARSE_METHOD;
   lex_init (&p);
   if (setjmp (p.recover) == 0)
-    parse_method (&p, EOF);
+    parse_method (&p, ']');
   else
     _gst_had_error = false;
 
@@ -1021,7 +1021,14 @@ parse_instance_variables (gst_parser *p,
     {
       gst_behavior class = (gst_behavior) OOP_TO_OBJ (classOOP);
       OOP *instVars = OOP_TO_OBJ (class->instanceVariables)->data;
-      int n = NUM_INDEXABLE_FIELDS (class->instanceVariables);
+      int n = CLASS_FIXED_FIELDS (classOOP);
+      OOP superclassOOP = SUPERCLASS (classOOP);
+      if (!IS_NIL (superclassOOP))
+ {
+  int superclassVars = CLASS_FIXED_FIELDS (superclassOOP);
+  instVars += superclassVars;
+  n -= superclassVars;
+ }
       for (; n--; instVars++)
  {
   char *s = _gst_to_cstring (*instVars);
@@ -1088,7 +1095,8 @@ parse_method (gst_parser *p, int at_end)
     current_pos.file_offset++;
 
   method = _gst_make_method (&pat->location, &current_pos,
-     pat, temps, attrs, stmts);
+     pat, temps, attrs, stmts,
+     at_end != ']');
 
   if (!_gst_had_error && !_gst_skip_compilation)
     {


--- orig/libgst/tree.c
+++ mod/libgst/tree.c
@@ -124,7 +124,8 @@ _gst_make_method (YYLTYPE *location,
   tree_node selectorExpr,
   tree_node temporaries,
   tree_node attributes,
-  tree_node statements)
+  tree_node statements,
+  int isOldSyntax)
 {
   tree_node result;
 
@@ -134,6 +135,7 @@ _gst_make_method (YYLTYPE *location,
   result->v_method.temporaries = temporaries;
   result->v_method.attributes = attributes;
   result->v_method.statements = statements;
+  result->v_method.isOldSyntax = isOldSyntax;
   return (result);
 }
 
@@ -707,6 +709,11 @@ print_method_node (tree_node node,
   indent (level);
   printf ("statements: ");
   _gst_print_tree (node->v_method.statements, level + 12);
+  indent (level);
+  if (node->v_method.isOldSyntax)
+    printf ("old syntax\n");
+  else
+    printf ("new syntax\n");
 }
 
 static void


--- orig/libgst/tree.h
+++ mod/libgst/tree.h
@@ -181,6 +181,7 @@ typedef struct method_node
   tree_node attributes;
   tree_node statements;
   int64_t endPos;
+  mst_Boolean isOldSyntax;
 }
 method_node;
 
@@ -230,7 +231,8 @@ extern tree_node _gst_make_method (YYLTY
    tree_node selectorExpr,
    tree_node temporaries,
    tree_node attributes,
-   tree_node statements)
+   tree_node statements,
+   int isOldSyntax)
   ATTRIBUTE_HIDDEN;
 
 /* Create an expr_node to be passed to _gst_make_method for a unary


--- orig/packages/stinst/compiler/StartCompiler.st
+++ mod/packages/stinst/compiler/StartCompiler.st
@@ -112,7 +112,6 @@ hidden from other objects trying to work
     ]
 ]
 
-
 
 STParsingDriver subclass: STEvaluationDriver [
     | curCategory curClass curCompilerClass evalFor lastResult method |
@@ -264,8 +263,7 @@ RBParser extend [
 Behavior extend [
 
     compilerClass [
- "This method is present for symmetry with #parserClass.  It
- specifies the class that will be used to compile the parse
+ "Return the class that will be used to compile the parse
  nodes into bytecodes."
 
  <category: 'compiling'>
@@ -287,14 +285,6 @@ Behavior extend [
  ^STInST.GSTFileInParser
     ]
 
-    parserClass [
- "Answer the class to be used by my method-compiling methods to
- parse methods for delivery to my #compilerClass."
-
- <category: 'compiling'>
- ^STInST.RBParser
-    ]
-
 ]
 
 




--- orig/packages/stinst/parser/Exporter.st
+++ mod/packages/stinst/parser/Exporter.st
@@ -294,9 +294,7 @@ FileOutExporter subclass: FormattingExpo
                         outClass asMetaclass ]
                     ifFalse: [ outClass ].
                     
- source := STInST.RBFormatter new
-      initialIndent: 1;
-                      format: (class parseNodeAt: selector).
+ source := (class compiledMethodAt: selector) methodFormattedSourceString.
         outStream nextPutAll: source; nl.
     ]
 ]
@@ -308,11 +306,28 @@ Behavior extend [
 ]
 
 CompiledMethod extend [
+    methodFormattedSourceString [
+        "Answer the method source code as a string"
+
+        <category: 'compiling'>
+ ^STInST.RBFormatter new
+      initialIndent: 1;
+                      format: self methodParseNode.
+    ]
+
     methodParseNode [
- ^STInST.RBParser
+        <category: 'compiling'>
+ ^self parserClass
             parseMethod: self methodSourceString
             category: self methodCategory
     ]
+
+    parserClass [
+        <category: 'compiling'>
+ ^self isOldSyntax
+    ifTrue: [ STInST.RBParser ]
+    ifFalse: [ STInST.RBBracketedMethodParser ]
+    ]
 ]
 
 Class extend [
@@ -341,3 +356,26 @@ ClassDescription extend [
         STInST.FileOutExporter fileOutCategory: category of: self to: aFileStream
     ]
 ]
+
+RBParser subclass: RBBracketedMethodParser [
+    skipToken: tokenValue [
+        (currentToken value = tokenValue)
+            ifTrue: [self step. ^true]
+            ifFalse: [^false]
+    ]
+
+    skipExpectedToken: tokenValue [
+        (self skipToken: tokenValue)
+            ifFalse: [self parserError: ('expected ' , tokenValue asSymbol)]
+    ]
+
+    parseMethodInto: methodNode [
+        <category: 'private-parsing'>
+        self skipExpectedToken: $[.
+ super parseMethodInto: methodNode.
+        self skipExpectedToken: $].
+        ^methodNode
+    ]
+]
+
+


--- orig/packages/stinst/parser/GSTParser.st
+++ mod/packages/stinst/parser/GSTParser.st
@@ -307,15 +307,19 @@ STInST.STFileInParser subclass: GSTFileI
     parseInstanceVariables: node add: addThem [
         | vars |
             
- "FIXME: support adding more instance variables."
- addThem ifTrue: [ self notYetImplemented ].
-        vars := (node arguments at: 1) name.
+ vars := addThem
+    ifTrue: [
+        (self resolveClass: class) instVarNames
+    fold: [ :a :b | a, ' ', b ] ]
+    ifFalse: [ '' ].
+
+        vars := vars, ' ', (node arguments at: 1) name.
         [currentToken isIdentifier]
             whileTrue: [vars := vars , ' ' , currentToken value.
         
                         self step ].      
+
         self skipExpectedToken: #|.
-        
         self evaluateMessageOn: class
              selector: #instanceVariableNames:
              argument: vars.


--- orig/packages/stinst/parser/RBParser.st
+++ mod/packages/stinst/parser/RBParser.st
@@ -1420,6 +1420,33 @@ Stream subclass: RBScanner [
     ]
 ]
 
+
+
+RBParser subclass: RBBracketedMethodParser [
+
+    <category: 'Refactory-Parser'>
+    <comment: 'A subclass of RBParser that discards a pair of brackets around
+methods.'>
+
+    skipToken: tokenValue [
+        (currentToken value = tokenValue)
+            ifTrue: [self step. ^true]
+            ifFalse: [^false]
+    ]
+
+    skipExpectedToken: tokenValue [
+        (self skipToken: tokenValue)
+            ifFalse: [self parserError: ('expected ' , tokenValue asSymbol)]
+    ]
+
+    parseMethodInto: methodNode [
+        <category: 'private-parsing'>
+        self skipExpectedToken: $[.
+       super parseMethodInto: methodNode.
+        self skipExpectedToken: $].
+        ^methodNode
+    ]
+]
 
 
 Eval [


--- orig/packages/stinst/parser/SIFParser.st
+++ mod/packages/stinst/parser/SIFParser.st
@@ -39,7 +39,9 @@ STFileInParser subclass: #SIFFileInParse
 
 parseMethodDefinitionList
     "Methods are defined one by one in SIF."
-    self compile: self parseMethodFromFile.
+    | method |
+    method := self compile: self parseMethodFromFile.
+    method isNil ifFalse: [ method noteOldSyntax ].
     self endMethodList
 ! !
 


--- orig/packages/stinst/parser/STFileParser.st
+++ mod/packages/stinst/parser/STFileParser.st
@@ -89,7 +89,7 @@ RBParser subclass: STFileParser [
 
     compile: node [
  <category: 'overridable - parsing file-ins'>
- driver compile: node
+ ^driver compile: node
     ]
 
     endMethodList [
@@ -97,6 +97,12 @@ RBParser subclass: STFileParser [
  driver endMethodList
     ]
 
+    resolveClass: node [
+ <category: 'overridable - parsing file-ins'>
+ self evaluate: node.
+ ^self result
+    ]
+
     evaluate: node [
  "This should be overridden because its result affects the parsing
  process: true means 'start parsing methods', false means 'keep
@@ -240,7 +246,7 @@ Object subclass: STParsingDriver [
  "do nothing by default"
 
  <category: 'overridable - parsing file-ins'>
-
+ ^nil
     ]
 
     endMethodList [
@@ -326,9 +332,13 @@ STFileParser subclass: STFileInParser [
  method definitions, followed by a bang"
 
  <category: 'private-parsing'>
+ | method |
+
  self step. "gobble doit terminating bang"
  [scanner atEnd or: [currentToken isSpecial and: [currentToken value == $!]]]
-    whileFalse: [self compile: self parseMethodFromFile].
+    whileFalse: [
+ method := self compile: self parseMethodFromFile.
+ method isNil ifFalse: [method noteOldSyntax]].
  scanner stripSeparators.
  self step.
  self endMethodList


--- orig/packages/stinst/parser/STLoader.st
+++ mod/packages/stinst/parser/STLoader.st
@@ -248,7 +248,7 @@ defineMethod: node
 !
 
 compile: node
-    self defineMethod: node.
+    ^self defineMethod: node
 ! !
 
 !STClassLoader methodsFor: 'evaluating statements'!


--- orig/packages/stinst/parser/STLoaderObjs.st
+++ mod/packages/stinst/parser/STLoaderObjs.st
@@ -1148,7 +1148,12 @@ methodSourceString
 
 !LoadedMethod methodsFor: 'empty stubs'!
 
+noteOldSyntax
+    "Do nothing"
+!
+
 discardTranslation
+    "Do nothing"
 ! !
 
 !PseudoNamespace methodsFor: 'abstract'!


--- orig/tests/mutate.ok
+++ mod/tests/mutate.ok
@@ -92,7 +92,20 @@ Execution begins...
 returned value is Association new "<0>"
 
 Execution begins...
-returned value is CompiledMethod new: 2 "<0>"
+returned value is CompiledMethod new: 4 "<0>"
 
 Execution begins...
 returned value is true
+Recompiling classes...
+
+Execution begins...
+(#a #b #c )
+returned value is Array new: 3 "<0>"
+
+Execution begins...
+(#a #d #b #c )
+returned value is Array new: 4 "<0>"
+
+Execution begins...
+(#a #d )
+returned value is Array new: 2 "<0>"


--- orig/tests/mutate.st
+++ mod/tests/mutate.st
@@ -123,3 +123,11 @@ Eval [ (C shape -> C classPool keys asAr
 
 Eval [ C class compile: 'foo [ ^MutationError ]' ]
 Eval [ C foo == SystemExceptions.MutationError ]
+
+Object subclass: Foo [ | a | ]
+Foo subclass: Bar [ | xyz | ]
+Foo subclass: Bar [ | b | | c | ]
+Eval [ Bar allInstVarNames printNl ]
+Foo extend [ | d | ]
+Eval [ Bar allInstVarNames printNl ]
+Eval [ Foo allInstVarNames printNl ]


--- orig/tests/testsuite.at
+++ mod/tests/testsuite.at
@@ -42,7 +42,7 @@ AT_DIFF_TEST([geometry.st])
 AT_DIFF_TEST([cobjects.st])
 AT_DIFF_TEST([compiler.st])
 AT_DIFF_TEST([fileext.st])
-AT_DIFF_TEST([mutate.st], [AT_XFAIL_IF(:)])
+AT_DIFF_TEST([mutate.st])
 AT_DIFF_TEST([untrusted.st])
 AT_DIFF_TEST([getopt.st])
 AT_DIFF_TEST([quit.st])




_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] prototype patch to fix mutate.st

Paolo Bonzini-2
Applied (together with some more fixes to the browser) as patch-611.

Paolo



_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk