'From Squeak5.3beta of 21 January 2020 [latest update: #19329] on 22 January 2020 at 1:01:35 pm'!

!CompilationCue commentStamp: 'ct 1/19/2020 14:08' 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 optionally, 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>

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
!

FillInTheBlankMorph subclass: #FillInTheCodeBlankMorph
	instanceVariableNames: 'compilationCue noPattern'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-Windows'!

!CompilationCue methodsFor: 'initialization' stamp: 'ct 1/19/2020 14:46'!
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 ].
	self flag: #duplication "ct: Use #source: instead".
	context := aContext.
	receiver := recObject.
	class := aClass.
	environment := anEnvironment.
	requestor := reqObject! !

!CompilationCue methodsFor: 'initialization' stamp: 'ct 1/19/2020 14:45'!
source: aTextOrString

	source := ((aTextOrString isKindOf: PositionableStream)
		ifTrue: [ aTextOrString ]
		ifFalse: [ ReadStream on: aTextOrString asString ]).! !


!Compiler methodsFor: 'public access' stamp: 'ct 1/22/2020 12:58'!
compiledMethodForCue: aCue noPattern: aBoolean ifFail: failBlock

	| methodNode method |
	methodNode := self
		compileCue: aCue
		noPattern: aBoolean
		ifFail: [^failBlock value].
	method := self interactive
		ifTrue: [ methodNode generateWithTempNames ] 
		ifFalse: [ methodNode generate ].
	^method! !


!Debugger methodsFor: 'code pane menu' stamp: 'ct 1/22/2020 12:09'!
runUntil
	"Step until an expression evaluates to other than false, reporting an error if it doesn't evaluate to true.
	 Remember the expression in an inst var.  If shift is pressed when the expression is supplied, don't update the UI.
	 If shift is pressed while stepping, stop stepping.  Using a user interrupt to break out would be more natural
	 but Squeak currently doesn't provide a UserInterrupt expection.  It should do."
	| receiver context untilMethod updateUI breakOnShift lastUpdate |
	context := self selectedContext.
	receiver := context receiver.
	untilMethod := Project uiManager
					requestCode: 'run until expression is true (shift now to disable ui update; shift later to break):' translated
					cue: (CompilationCue source: '' context: context class: receiver class environment: receiver environment requestor: nil)
					initialAnswer: (untilExpression ifNil: ['"boolean expression"']).
	untilMethod ifNil: [^ self].
	updateUI := breakOnShift := Sensor shiftPressed not.
	untilExpression := untilMethod getSource readStream upTo: Character cr; upToEnd.
	
	lastUpdate := Time millisecondClockValue.
	Cursor execute showWhile:
		[[self selectedContext == context
		  and: [context willReturn not
		  and: [(untilMethod valueWithReceiver: receiver arguments: {context}) not]]] whileTrue:
			[interruptedProcess completeStep: self selectedContext.
			 self selectedContext == context ifTrue:
				[self resetContext: interruptedProcess stepToSendOrReturn changeContents: false].
			 Time millisecondClockValue - lastUpdate > 50 ifTrue:
				[updateUI ifTrue:
					[self changed: #contentsSelection.
					 Project current world displayWorldSafely].
				 breakOnShift
					ifTrue: [Sensor shiftPressed ifTrue:
								[self changed: #contentsSelection.
								 self updateInspectors.
								 ^self]]
					ifFalse: [Sensor shiftPressed ifFalse: [breakOnShift := true]].
				 lastUpdate := Time millisecondClockValue]]].
	self changed: #contentsSelection.
	self updateInspectors.! !

!Debugger methodsFor: 'context stack menu' stamp: 'ct 1/22/2020 12:38'!
returnValue
	"Force a return of a given value to the previous context!!"

	| previous selectedContext expression value |
	contextStackIndex = 0 ifTrue: [^Beeper beep].
	selectedContext := self selectedContext.
	expression := Project uiManager
		requestCode: 'Enter expression for return value:' translated
		cue: (CompilationCue source: '' context: selectedContext class: selectedContext receiver class requestor: nil).
	expression ifNil: [^ self].
	value := expression valueWithReceiver: selectedContext receiver arguments: {selectedContext}.
	previous := selectedContext sender.
	self resetContext: previous.
	interruptedProcess popTo: previous value: value! !


!FillInTheBlankMorph methodsFor: 'accessing' stamp: 'ct 1/20/2020 19:23'!
defaultAnswer

	^ ''! !

!FillInTheBlankMorph methodsFor: 'accessing' stamp: 'mt 7/13/2016 20:41'!
response: aText
	"Sent when text pane accepts."

	result := aText asString.
	self delete.
! !

!FillInTheBlankMorph methodsFor: 'initialization' stamp: 'ct 1/22/2020 12:13'!
createTextPaneAcceptOnCR: acceptBoolean 

	| text |
	text := PluggableTextMorph
			on: self
			text: #response
			accept: #response:
			readSelection: #selectionInterval
			menu: #codePaneMenu:shifted:.
	text
		showScrollBarsOnlyWhenNeeded;
		wantsFrameAdornments: false;
		hasUnacceptedEdits: true;
		acceptOnCR: acceptBoolean;
		setNameTo: 'textPane';
		layoutFrame: (LayoutFrame fractions: (0@0 corner: 1@1));
		hResizing: #spaceFill;
		vResizing: #spaceFill;
		scrollToTop.
	^ text! !

!FillInTheBlankMorph methodsFor: 'initialization' stamp: 'ct 1/22/2020 12:52'!
setQuery: queryString initialAnswer: initialAnswer answerExtent: answerExtent acceptOnCR: acceptBoolean 
	
	result := initialAnswer ifNil: [self defaultAnswer].
	done := false.

	self paneMorph removeAllMorphs.

	self title: 'Input Requested' translated.
	self message: queryString.
	
	textPane := self createTextPaneAcceptOnCR: acceptBoolean.
	self paneMorph addMorphBack: textPane.

	self paneMorph
		wantsPaneSplitters: true;
		addCornerGrips.
	self paneMorph grips do: [:ea | ea showHandle: true].
		
	self paneMorph extent: ((result asText asMorph extent + (20@10) max: answerExtent) min: 500@500).	
	self setDefaultParameters.! !


!FillInTheCodeBlankMorph methodsFor: 'accessing' stamp: 'ct 1/22/2020 11:38'!
defaultAnswer

	| code |
	code := 'self shouldBeImplemented'.
	noPattern ifTrue: [^ code].
	^ 'DoIt\	' withCRs , code! !

!FillInTheCodeBlankMorph methodsFor: 'accessing' stamp: 'ct 1/22/2020 11:31'!
response: aText

	compilationCue source: aText.
	result := Compiler new compiledMethodForCue: compilationCue noPattern: noPattern ifFail: [^ self].
	self delete.! !

!FillInTheCodeBlankMorph methodsFor: 'initialization' stamp: 'ct 1/22/2020 11:48'!
createTextPaneAcceptOnCR: acceptBoolean 

	| pane |
	pane := super createTextPaneAcceptOnCR: acceptBoolean.
	pane := pane becomeForward: (PluggableTextMorphPlus basicNew copyFrom: pane).
	pane useDefaultStyler.
	^ pane! !

!FillInTheCodeBlankMorph methodsFor: 'initialization' stamp: 'ct 1/22/2020 11:39'!
setCompilationCue: aCue

	compilationCue := (aCue copy
		requestor: self textPane;
		yourself).! !

!FillInTheCodeBlankMorph methodsFor: 'initialization' stamp: 'ct 1/22/2020 11:44'!
setQuery: queryString compilationCue: aCue noPattern: aBoolean initialAnswer: initialAnswer answerExtent: answerExtent

	noPattern := aBoolean.
	self setQuery: queryString initialAnswer: initialAnswer answerExtent: answerExtent acceptOnCR: aBoolean.
	self setCompilationCue: aCue.
	self textPane updateStyleNow.! !

!FillInTheCodeBlankMorph methodsFor: 'styling' stamp: 'ct 1/22/2020 11:45'!
aboutToStyle: aStyler requestor: aMorph

	aMorph = self textPane
		ifFalse: [^ super aboutToStyle: aStyler requestor: aMorph].
	
	aStyler
		parseAMethod: noPattern not;
		environment: compilationCue environment;
		classOrMetaClass: compilationCue getClass;
		context: compilationCue context.
	^ true! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:03'!
completionContext

	^ compilationCue context! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:01'!
completionController

	| controller |
	controller := self dependents 
		detect: [ :each | each isKindOf:  ECController ]
		ifNone: [ 
			"This is just the migration code from the old #actionMap hack."
			(self triggerEvent: #getCompletionController) ifNotNil: [ :theController |
				self addDependent: theController ] ].
	^controller ifNil: [ self initializeCompletionController ]! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:01'!
completionControllerClass
	
	^ ECPreferences useECompletionInsteadOfOCompletion
		ifFalse: [ OController ]
		ifTrue: [ ECController ]! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:02'!
createCompletionController

	^ self completionControllerClass model: self! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:02'!
guessTypeForName: aString

	^nil! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:02'!
initializeCompletionController

	^ self wantsAutocompletion
		ifTrue: [self addDependent: self createCompletionController]
		ifFalse: [nil]! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:02'!
selectedClassOrMetaClass

	^ compilationCue getClass! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:02'!
wantsAutocompletion

	^ true! !

!FillInTheCodeBlankMorph methodsFor: '*Autocompletion' stamp: 'ct 1/19/2020 17:02'!
wantsToCloseAutocompletion

	^ self isInWorld not! !


!FillInTheCodeBlankMorph class methodsFor: 'instance creation' stamp: 'ct 1/22/2020 11:42'!
request: queryString cue: aCompilationCue initialAnswer: defaultAnswer inWorld: aWorld onCancelReturn: returnOnCancel

	^ self request: queryString cue: aCompilationCue noPattern: true initialAnswer: defaultAnswer inWorld: aWorld onCancelReturn: returnOnCancel! !

!FillInTheCodeBlankMorph class methodsFor: 'instance creation' stamp: 'ct 1/22/2020 11:42'!
request: queryString cue: aCompilationCue noPattern: noPattern initialAnswer: defaultAnswer centerAt: aPoint inWorld: aWorld onCancelReturn: returnOnCancel answerExtent: answerExtent

	| aFillInTheBlankMorph |
	aFillInTheBlankMorph := self new
		setQuery: queryString
		compilationCue: aCompilationCue
		noPattern: noPattern
		initialAnswer: defaultAnswer
		answerExtent: answerExtent.

	aFillInTheBlankMorph createAcceptButton
		action: [aFillInTheBlankMorph textPane accept].
	aFillInTheBlankMorph createCancelButton
		action: [aFillInTheBlankMorph closeDialog: returnOnCancel].
		
	aFillInTheBlankMorph preferredPosition: aPoint.
	^ aFillInTheBlankMorph getUserResponse
! !

!FillInTheCodeBlankMorph class methodsFor: 'instance creation' stamp: 'ct 1/22/2020 11:42'!
request: queryString cue: aCompilationCue noPattern: noPattern initialAnswer: defaultAnswer inWorld: aWorld onCancelReturn: returnOnCancel

	^ self request: queryString cue: aCompilationCue noPattern: noPattern initialAnswer: defaultAnswer centerAt: ActiveHand cursorPoint
		inWorld: aWorld onCancelReturn: returnOnCancel 
		answerExtent: self defaultAnswerExtent! !


!MessageSet methodsFor: 'filtering' stamp: 'ct 1/22/2020 12:11'!
filterToMessagesThat
	"Allow the user to type in a block which will be"

	| reply |
	reply := UIManager default
		requestCode: 'Enter message filter' translated
		cue: (CompilationCue class: nil class)
		noPattern: false
		initialAnswer: 'matches: aClass selector: aSelector
	^ self shouldBeImplemented'.
	reply ifNil: [^ self].
	self filterFrom: [:class :selector |
		reply valueWithReceiver: nil arguments: {class. selector}]
! !


!UIManager methodsFor: 'ui requests - text' stamp: 'ct 1/22/2020 11:43'!
requestCode: queryString

	^ self requestCode: queryString cue: (CompilationCue class: Object)! !

!UIManager methodsFor: 'ui requests - text' stamp: 'ct 1/22/2020 11:41'!
requestCode: queryString cue: aCompilationCue

	^ self requestCode: queryString cue: aCompilationCue initialAnswer: nil! !

!UIManager methodsFor: 'ui requests - text' stamp: 'ct 1/22/2020 11:40'!
requestCode: queryString cue: aCompilationCue initialAnswer: defaultAnswer

	^ self requestCode: queryString cue: aCompilationCue noPattern: true initialAnswer: defaultAnswer! !

!UIManager methodsFor: 'ui requests - text' stamp: 'ct 1/22/2020 11:41'!
requestCode: queryString cue: aCompilationCue noPattern: noPattern

	^ self requestCode: queryString cue: aCompilationCue noPattern: noPattern initialAnswer: nil! !

!UIManager methodsFor: 'ui requests - text' stamp: 'ct 1/22/2020 11:40'!
requestCode: queryString cue: aCompilationCue noPattern: noPattern initialAnswer: defaultAnswer

	^ self multiLineRequest: queryString initialAnswer: defaultAnswer! !


!MorphicUIManager methodsFor: 'ui requests' stamp: 'ct 1/22/2020 11:42'!
requestCode: queryString cue: aCompilationCue noPattern: noPattern initialAnswer: defaultAnswer

	self askForProvidedAnswerTo: queryString ifSupplied: [:answer | 
		^ answer = #default
				ifTrue: [defaultAnswer]
				ifFalse: [answer]].
	
	^ FillInTheCodeBlankMorph 
		request: queryString 
		cue: aCompilationCue
		noPattern: noPattern
		initialAnswer: defaultAnswer 
		inWorld: self currentWorld
		onCancelReturn: nil! !

