The Inbox: Compiler-eem.421.mcz

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

The Inbox: Compiler-eem.421.mcz

commits-2
A new version of Compiler was added to project The Inbox:
http://source.squeak.org/inbox/Compiler-eem.421.mcz

==================== Summary ====================

Name: Compiler-eem.421
Author: eem
Time: 25 March 2020, 9:00:37.328826 pm
UUID: 7bacb14a-f088-4fca-aa94-35dae28aa8e8
Ancestors: Compiler-nice.420

A suggested implementation of writable results from doits.  This scheme is careful to only make read-only collection literals that the compiler makes read-only, not e.g. numeric literals (which should always be read-only) or objects the evaluation makes read-only.

=============== Diff against Compiler-nice.420 ===============

Item was changed:
  Object subclass: #CompilationCue
+ instanceVariableNames: 'source context receiver class environment requestor writableCollectionLiterals'
- instanceVariableNames: 'source context receiver class environment requestor'
  classVariableNames: ''
  poolDictionaries: ''
  category: 'Compiler-Kernel'!
 
+ !CompilationCue commentStamp: 'eem 3/25/2020 20:52' prior: 0!
- !CompilationCue commentStamp: 'eem 3/30/2017 17:32' prior: 0!
  A CompilationCue is a helper class holding enough context for evaluating/compiling Smalltalk code.
 
  That is mainly the source code, and the source code editor to interact with if the Compiler is used interactively.
  But that is also any additional information necessary to resolve variable names.
 
  When compiling a method, the Compiler typically need to know the target class in which to install the method.
 
  When evaluating an expression, the Compiler also needs a receiver (for accessing the value of its instance variables), its class (for resolving instance/class variable names), and optionnally a context of execution when debugging a method (for accessing values of temporaries and parameters).
 
  Instance Variables
+ class: <Behavior>
+ context: <Context | nil>
+ environment: <Environment | nil>
+ receiver: <Object>
+ requestor: <TextEditor | nil>
+ source: <Stream>
+ writableCollectionLiterals: <Boolean>
- class: <Behavior>
- context: <Context | nil>
- environment: <Environment | nil>
- receiver: <Object>
- requestor: <TextEditor | nil>
- source: <Stream>
 
  class
  - the target class in which to install the compiled method;
   this enables to resolve the instance variable names, class variable names and shared pool variable names.
   When evaluating, this should be the receiver class
 
  context
  - the context introspected when evaluating the code: this is typically for accessing parameters and temporary variables when debugging
 
  environment
  - the environment in which to resolve global variable names
 
  receiver
  - the receiver into which to evaluate the code: this is typically for accessing instance variables in an inspector
 
  requestor
  - typically the text editor containing the source code being compiled/evaluated. This enables the Compiler to interact in case of syntax error.
 
  source
  - a ReadStream on the source code to be compiled
+
+ writableCollectionLiterals
+ - if true then the compiler should answer writable collection literals in an evaluation; by default all literals are read-only
  !

Item was changed:
  ----- Method: CompilationCue class>>source:context:class:environment:requestor: (in category 'instance creation') -----
  source: aTextOrStream context: aContext class: aClass environment: anEnvironment requestor: reqObject
  ^ self basicNew
  initializeWithSource: aTextOrStream
  context: aContext
  receiver: (aContext ifNotNil: [aContext receiver])
  class: aClass
  environment: anEnvironment
+ requestor: reqObject
+ writableCollectionLiterals: false!
- requestor: reqObject!

Item was changed:
  ----- Method: CompilationCue class>>source:context:receiver:class:environment:requestor: (in category 'instance creation') -----
  source: aTextOrStream context: aContext receiver: recObject class: aClass environment: anEnvironment requestor: reqObject
  ^ self basicNew
  initializeWithSource: aTextOrStream
  context: aContext
  receiver: recObject
  class: aClass
  environment: anEnvironment
+ requestor: reqObject
+ writableCollectionLiterals: false!
- requestor: reqObject!

Item was added:
+ ----- Method: CompilationCue class>>source:context:receiver:class:environment:requestor:writableCollectionLiterals: (in category 'instance creation') -----
+ source: aTextOrStream context: aContext receiver: recObject class: aClass environment: anEnvironment requestor: reqObject writableCollectionLiterals: writableCollectionLiteralsBool
+ ^ self basicNew
+ initializeWithSource: aTextOrStream
+ context: aContext
+ receiver: recObject
+ class: aClass
+ environment: anEnvironment
+ requestor: reqObject
+ writableCollectionLiterals: writableCollectionLiteralsBool!

Item was added:
+ ----- Method: CompilationCue class>>source:writableCollectionLiterals:environment: (in category 'instance creation') -----
+ source: aString writableCollectionLiterals: writableCollectionLiterals environment: anEnvironment
+ ^ self
+ source: aString
+ context: nil
+ receiver: nil
+ class: UndefinedObject
+ environment: anEnvironment
+ requestor: nil
+ writableCollectionLiterals: writableCollectionLiterals!

Item was removed:
- ----- Method: CompilationCue>>initializeWithSource:context:receiver:class:environment:requestor: (in category 'initialization') -----
- initializeWithSource: aTextOrString context: aContext receiver: recObject class: aClass environment: anEnvironment requestor: reqObject
- self initialize.
- source := (aTextOrString isKindOf: PositionableStream)
- ifTrue: [ aTextOrString ]
- ifFalse: [ ReadStream on: aTextOrString asString ].
- context := aContext.
- receiver := recObject.
- class := aClass.
- environment := anEnvironment.
- requestor := reqObject!

Item was added:
+ ----- Method: CompilationCue>>initializeWithSource:context:receiver:class:environment:requestor:writableCollectionLiterals: (in category 'initialization') -----
+ initializeWithSource: aTextOrString context: aContext receiver: recObject class: aClass environment: anEnvironment requestor: reqObject writableCollectionLiterals: writableCollectionLiteralsBool
+ self initialize.
+ source := aTextOrString isStream
+ ifTrue: [ aTextOrString ]
+ ifFalse: [ ReadStream on: aTextOrString asString ].
+ context := aContext.
+ receiver := recObject.
+ class := aClass.
+ environment := anEnvironment.
+ requestor := reqObject.
+ writableCollectionLiterals := writableCollectionLiteralsBool!

Item was added:
+ ----- Method: CompilationCue>>writableCollectionLiterals (in category 'accessing') -----
+ writableCollectionLiterals
+ ^writableCollectionLiterals!

Item was added:
+ ----- Method: Compiler class>>evaluate:writableCollectionLiterals:environment: (in category 'evaluating') -----
+ evaluate: aString writableCollectionLiterals: writableCollectionLiteralsBool environment: anEnvironment
+ ^  self new
+ evaluateCue: (CompilationCue
+ source: aString
+ writableCollectionLiterals: writableCollectionLiteralsBool
+ environment: anEnvironment)
+ ifFail: [^ nil]!

Item was changed:
  ----- Method: Compiler>>evaluateCue:ifFail: (in category 'private') -----
  evaluateCue: aCue ifFail: failBlock
  "Compiles the cue source into a parse tree, then generates code into
  a method. Finally, the compiled method is invoked from here via withArgs:executeMethod:, hence the system no longer creates Doit method
  litter on errors."
 
  | methodNode method value |
  methodNode := self compileCue: aCue noPattern: true ifFail: [^failBlock value].
 
  method := self interactive
  ifTrue: [methodNode generateWithTempNames]
  ifFalse: [methodNode generate].
 
  value := cue receiver
  withArgs: (cue context ifNil: [#()] ifNotNil: [{cue context}])
  executeMethod: method.
+ cue writableCollectionLiterals ifTrue:
+ [method allLiteralsDo:
+ [:lit| self makeCollectionLiteralWritable: lit]].
  ^ value
  !

Item was added:
+ ----- Method: Compiler>>makeCollectionLiteralWritable: (in category 'private') -----
+ makeCollectionLiteralWritable: lit
+ "By default all literals are read-only.  Usually this is exactly what we desire.
+ Sometimes this is inconvenient.  This method makes collection literals, and
+ only collection literals, writable, in response to the writableCollectionLiterals cue"
+ lit isCollection ifTrue:
+ [lit beWritableObject.
+ lit isArray ifTrue:
+ [lit do:
+ [:subLiteral| self makeCollectionLiteralWritable: subLiteral]]]!