
# fileIn("s8/library/scripting/ScriptCompiler.st")
smalltalk.addClass("ScriptCompiler",smalltalk.Compiler,["cache"],"ScriptCompiler")

smalltalk.addClass("CompiledScript",smalltalk.CompiledMethod,["args","script","source"],"ScriptCompiler")

smalltalk.bind(smalltalk.CompiledScript,"args",0
,smalltalk.__f__("""(self):
	#CompiledScript>>#args
	return getattr(self,"@args",nil) 
""","CompiledScript_args")
,"accessing","""args
		" Return the args of the receiver. "
	
		^args""",nil)

smalltalk.bind(smalltalk.CompiledScript,"args:",0
,smalltalk.__f__("""(self,anObject):
	#CompiledScript>>#args:
	smalltalk.basic_at_put(self,"@args",anObject) 
	return self 
""","CompiledScript_args_")
,"accessing","""args: anObject
		" Set the args of the receiver. "
	
		args := anObject""",nil)

smalltalk.bind(smalltalk.CompiledScript,"script",0
,smalltalk.__f__("""(self):
	#CompiledScript>>#script
	return getattr(self,"@script",nil) 
""","CompiledScript_script")
,"accessing","""script
		" Return the script of the receiver. "
	
		^script""",nil)

smalltalk.bind(smalltalk.CompiledScript,"script:",0
,smalltalk.__f__("""(self,anObject):
	#CompiledScript>>#script:
	smalltalk.basic_at_put(self,"@script",anObject) 
	return self 
""","CompiledScript_script_")
,"accessing","""script: anObject
		" Set the script of the receiver. "
	
		script := anObject""",nil)

smalltalk.bind(smalltalk.CompiledScript,"source",0
,smalltalk.__f__("""(self):
	#CompiledScript>>#source
	return getattr(self,"@source",nil) 
""","CompiledScript_source")
,"accessing","""source
		" Return the source of the receiver. "
	
		^source""",nil)

smalltalk.bind(smalltalk.CompiledScript,"source:",0
,smalltalk.__f__("""(self,anObject):
	#CompiledScript>>#source:
	smalltalk.basic_at_put(self,"@source",anObject) 
	return self 
""","CompiledScript_source_")
,"accessing","""source: anObject
		" Set the source of the receiver. "
	
		source := anObject""",nil)

smalltalk.bind(smalltalk.ScriptCompiler.__class__,"constructEventsTriggered",0
,smalltalk.__f__("""(self):
	#ScriptCompiler class>>#constructEventsTriggered
	return smalltalk.object_comma_(smalltalk.newArray(["needsScriptFor:","codeGenerated:","eval:"]),smalltalk.superReceiver(smalltalk.ScriptCompiler.__class__,self).constructEventsTriggered()) 
""","ScriptCompiler_class_constructEventsTriggered")
,"events","""constructEventsTriggered
	" Private - Return the events managed by instances of the receiver. "

	^#(	#needsScriptFor:
		#codeGenerated:
		#eval:
	) ,super constructEventsTriggered""",nil)

smalltalk.bind(smalltalk.ScriptCompiler.__class__,"install",0
,smalltalk.__f__("""(self):
	#ScriptCompiler class>>#install
	self.install_(self._gt_gt(smalltalk.String("scriptCompilerSupport"))) 
	return self 
""","ScriptCompiler_class_install")
,"installation","""install
	" Install the receiver as default Compiler support.
	Note that effect of changing the compiler is inmediate.
	DO NOT install if you don't know what you are doing.
	"

	self install: self >> #scriptCompilerSupport """,nil)

smalltalk.bind(smalltalk.ScriptCompiler.__class__,"isInstalled",0
,smalltalk.__f__("""(self):
	#ScriptCompiler class>>#isInstalled
	return smalltalk.isObject_equalTo_(self._gt_gt(smalltalk.String("scriptCompilerSupport")).fn(),smalltalk.Smalltalk._gt_gt(smalltalk.String("compilerSupport")).fn()) 
""","ScriptCompiler_class_isInstalled")
,"testing","""isInstalled
	" Returns true if the receiver is installed as default Compiler support. "

	^(self >> #scriptCompilerSupport) fn = (Smalltalk >> #compilerSupport) fn """,nil)

smalltalk.bind(smalltalk.ScriptCompiler.__class__,"uninstall",0
,smalltalk.__f__("""(self):
	#ScriptCompiler class>>#uninstall
	self.install_(self._gt_gt(smalltalk.String("s8CompilerSupport"))) 
	return self 
""","ScriptCompiler_class_uninstall")
,"installation","""uninstall
	" Install the default Compiler support. "

	self install: self >> #s8CompilerSupport """,nil)

smalltalk.bind(smalltalk.ScriptCompiler.__class__,"install:",0
,smalltalk.__f__("""(self,support):
	#ScriptCompiler class>>#install:
	__0__=smalltalk.newContext()
	def __blk1__(_s8_rec):
		_s8_rec.source_(__0__.code.contents()) 
		return _s8_rec.fn_(support.fn()) 
	__0__.selector=nil
	__0__.cm=nil
	__0__.code=nil
	__0__.src=nil
	__0__.selector=smalltalk.String("compilerSupport") 
	__0__.code=smalltalk.String("").writeStream() 
	__0__.src=support.source().stream() 
	__0__.src.nextLine() 
	if not smalltalk.b(__0__.src.atEnd()):
		def __blk2__(_s8_rec):
			_s8_rec.nextPutAll_(__0__.selector) 
			return _s8_rec.cr() 
		__blk2__(__0__.code) 
		__0__.code.nextPutAll_(__0__.src.upToEnd()) 
	 
	__0__.cm=smalltalk.Smalltalk._gt_gt(__0__.selector) 
	__blk1__(__0__.cm) 
	__0__.cm.classField().addCompiledMethod_(__0__.cm) 
	return self 
""","ScriptCompiler_class_install_")
,"private","""install: support
	" Private - Install the given compiler support as default Compiler. "

	| selector cm code src |
	selector := #compilerSupport.
	code := '' writeStream.
	src := support source stream.
	src nextLine.
	src atEnd ifFalse: [
		code nextPutAll: selector; cr.
		code nextPutAll: src upToEnd
	].

	cm := Smalltalk >> selector.
	cm source: code contents; fn: support fn.
	cm classField addCompiledMethod: cm """,nil)

smalltalk.bind(smalltalk.ScriptCompiler.__class__,"evaluationScript",0
,smalltalk.__f__("""(self):
	#ScriptCompiler class>>#evaluationScript
	return smalltalk.StepOverScript 
""","ScriptCompiler_class_evaluationScript")
,"private","""evaluationScript
	" Return the support for skipping method execution. "

	^StepOverScript """,nil)

smalltalk.bind(smalltalk.ScriptCompiler,"s8CompilerSupport",0
,smalltalk.__f__("""(self):
	#ScriptCompiler>>#s8CompilerSupport
	return smalltalk.Compiler 
""","ScriptCompiler_s8CompilerSupport")
,"installation","""s8CompilerSupport
	" Return the compiler support for the receiver. "

	^Compiler """,nil)

smalltalk.bind(smalltalk.ScriptCompiler,"scriptCompilerSupport",0
,smalltalk.__f__("""(self):
	#ScriptCompiler>>#scriptCompilerSupport
	return smalltalk.ScriptCompiler 
""","ScriptCompiler_scriptCompilerSupport")
,"installation","""scriptCompilerSupport
	" Return the compiler support for the receiver. "

	^ScriptCompiler """,nil)

smalltalk.bind(smalltalk.ScriptCompiler,"cache",0
,smalltalk.__f__("""(self):
	#ScriptCompiler>>#cache
	if smalltalk.b(smalltalk.isNil_(getattr(self,"@cache",nil))):
		smalltalk.basic_at_put(self,"@cache",smalltalk.PoolDictionary.new()) 
	 
	return getattr(self,"@cache",nil) 
""","ScriptCompiler_cache")
,"accessing","""cache
	" Private - Returns the internal cache. "

	cache isNil ifTrue: [ cache := PoolDictionary new ].
	^cache""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"scriptFor:",0
,smalltalk.__f__("""(self,smalltalkExpression):
	_s8Ret_=smalltalk.newContext()
	try:
		#ScriptCompiler>>#scriptFor:
		__0__=smalltalk.newContext()
		def __blk1__(ex):
			return smalltalk.raise_result_(_s8Ret_,self.error_(ex.description())) 
		__0__.result=nil
		__0__.result=smalltalk.ScriptParser.for_(self.currentClass()).parse_onError_(smalltalkExpression,smalltalk.blk(__blk1__,1)) 
		smalltalk.raise_result_(_s8Ret_,__0__.result) 
	except Exception as __ex:
		if smalltalk.exception_at(__ex,_s8Ret_):
			return smalltalk.exceptionResult_(__ex)
		raise __ex
	
""","ScriptCompiler_scriptFor_")
,"private","""scriptFor: smalltalkExpression
	" Private - Return the script result of parsing expression to be evaluated. "

	| result |
	result := (ScriptParser for: self currentClass)
		parse: smalltalkExpression onError: [:ex|
			^self error: ex description
		].
	^result""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"isSourcecode:",0
,smalltalk.__f__("""(self,string):
	_s8Ret_=smalltalk.newContext()
	try:
		#ScriptCompiler>>#isSourcecode:
		__0__=smalltalk.newContext()
		def __blk1__():
			return __0__.input.atEnd() 
		__0__.input=nil
		__0__.input=string.stream() 
		while not smalltalk.b(smalltalk.blk(__blk1__,0)()):
			def __blk2__():
				return smalltalk.raise_result_(_s8Ret_,smalltalk.false) 
			smalltalk.if_true_false_(__0__.input.upTo_(smalltalk.String.crlf()).includes_(smalltalk.String.lf()),smalltalk.blk(__blk2__,0),nil) 
		 
		smalltalk.raise_result_(_s8Ret_,smalltalk.true) 
	except Exception as __ex:
		if smalltalk.exception_at(__ex,_s8Ret_):
			return smalltalk.exceptionResult_(__ex)
		raise __ex
	
""","ScriptCompiler_isSourcecode_")
,"private","""isSourcecode: string
	" Private - Returns true if a string is formated as sourcecode. "

	| input |
	input := string stream.
	[input atEnd] whileFalse: [
		((input upTo: String crlf) includes: String lf) ifTrue: [ ^false ]
	].
	^true""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"sourcecode:",0
,smalltalk.__f__("""(self,string):
	#ScriptCompiler>>#sourcecode:
	__0__=smalltalk.newContext()
	def __blk1__():
		return __0__.input.atEnd() 
	__0__.input=nil
	__0__.output=nil
	if smalltalk.b(self.isSourcecode_(string)):
		return string 
	 
	__0__.input=string.stream() 
	__0__.output=smalltalk.String("").writeStream() 
	while not smalltalk.b(smalltalk.blk(__blk1__,0)()):
		def __blk2__():
			return __0__.output.cr() 
		__0__.output.nextPutAll_(__0__.input.nextLine()) 
		smalltalk.if_true_false_(__0__.input.atEnd(),nil,smalltalk.blk(__blk2__,0)) 
	 
	return __0__.output.contents() 
""","ScriptCompiler_sourcecode_")
,"private","""sourcecode: string
	" Private - Returns a string formated as sourcecode. "

	| input output |
	(self isSourcecode: string) ifTrue: [ ^string ].
	input := string stream.
	output := '' writeStream.
	[input atEnd] whileFalse: [
		output nextPutAll: input nextLine.
		input atEnd ifFalse: [ output cr ]
	].
	^output contents""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"scriptForMethod:onError:",0
,smalltalk.__f__("""(self,source,aBlock):
	_s8Ret_=smalltalk.newContext()
	try:
		#ScriptCompiler>>#scriptForMethod:onError:
		__0__=smalltalk.newContext()
		def __blk1__(ex):
			return smalltalk.raise_result_(_s8Ret_,aBlock.value_(ex)) 
		__0__.method=nil
		__0__.method=smalltalk.CompiledScript.new() 
		__0__.method.classField_(self.currentClass()) 
		smalltalk.ScriptParser.for_(self.currentClass()).parse_method_onError_(self.sourcecode_(source),__0__.method,smalltalk.blk(__blk1__,1)) 
		smalltalk.raise_result_(_s8Ret_,__0__.method) 
	except Exception as __ex:
		if smalltalk.exception_at(__ex,_s8Ret_):
			return smalltalk.exceptionResult_(__ex)
		raise __ex
	
""","ScriptCompiler_scriptForMethod_onError_")
,"scripting","""scriptForMethod: source onError: aBlock
	" Return the compiled script for method with source code or the result of evaluating aBlock with error. "

	| method |
	method := CompiledScript new.
	method classField: self currentClass.
	(ScriptParser for: self currentClass)
		parse: (self sourcecode: source) method: method
		onError: [:ex| ^aBlock value: ex ].
	^method""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"scriptForMethod:",0
,smalltalk.__f__("""(self,source):
	#ScriptCompiler>>#scriptForMethod:
	def __blk1__():
		return nil 
	return self.scriptForMethod_onError_(source,smalltalk.blk(__blk1__,0)) 
""","ScriptCompiler_scriptForMethod_")
,"scripting","""scriptForMethod: source
	" Return the compiled script for method with source code (or nil). "

	^self scriptForMethod: source onError: [ nil ]""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"evaluate:in:to:",0
,smalltalk.__f__("""(self,smalltalkExpression,aClass,aReceiver):
	#ScriptCompiler>>#evaluate:in:to:
	self.currentClass_(aClass) 
	return self.scriptFor_(smalltalkExpression).evaluate_(aReceiver) 
""","ScriptCompiler_evaluate_in_to_")
,"evaluation","""evaluate: smalltalkExpression in: aClass to: aReceiver
	" Return the result of evaluating the smalltalk expression with aReceiver. "

	self currentClass: aClass.
	^(self scriptFor: smalltalkExpression)
		evaluate: aReceiver""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"compile:",0
,smalltalk.__f__("""(self,aString):
	#ScriptCompiler>>#compile:
	__0__=smalltalk.newContext()
	__0__.code=nil
	__0__.code=smalltalk.superReceiver(smalltalk.ScriptCompiler,self).compile_(aString) 
	self.cache().at_put_(smalltalk.String("code"),__0__.code) 
	self.triggerEvent_with_(smalltalk.String("codeGenerated:"),__0__.code) 
	return __0__.code 
""","ScriptCompiler_compile_")
,"private","""compile: aString
	" Return the native code result of compiling aString for currentClass. "

	| code |
	code := super compile: aString.
	self cache at: #code put: code.
	self triggerEvent: #codeGenerated: with: code.
	^code""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"basicEval:",0
,smalltalk.__f__("""(self,expression):
	_s8Ret_=smalltalk.newContext()
	try:
		#ScriptCompiler>>#basicEval:
		__0__=smalltalk.newContext()
		def __blk1__():
			return smalltalk.superReceiver(smalltalk.ScriptCompiler,self).eval_(expression) 
		def __blk2__():
			return smalltalk.raise_result_(_s8Ret_,__0__.default.value()) 
		def __blk3__():
			return smalltalk.raise_result_(_s8Ret_,__0__.default.value()) 
		__0__.default=nil
		__0__.script=nil
		__0__.code=nil
		__0__.default=smalltalk.blk(__blk1__,0) 
		__0__.script=self.cache().at_ifAbsent_(smalltalk.String("compiledScript"),smalltalk.blk(__blk2__,0)) 
		__0__.code=self.cache().at_ifAbsent_(smalltalk.String("code"),smalltalk.blk(__blk3__,0)) 
		if smalltalk.b(smalltalk.isObject_equalTo_(__0__.code,expression)):
			smalltalk.raise_result_(_s8Ret_,__0__.script) 
		 
		smalltalk.raise_result_(_s8Ret_,__0__.default.value()) 
	except Exception as __ex:
		if smalltalk.exception_at(__ex,_s8Ret_):
			return smalltalk.exceptionResult_(__ex)
		raise __ex
	
""","ScriptCompiler_basicEval_")
,"evaluation","""basicEval: expression
	" Private - Return the result of evaluating a native expression in global context.
	Note that we do NOT evaluate the code in case we parsed to a compiled script.
	"

	| default script code |
	default := [ super eval: expression ].
	script := self cache at: #compiledScript ifAbsent: [ ^default value ].
	code := self cache at: #code ifAbsent: [ ^default value ].
	code = expression ifTrue: [ ^script ].
	^default value""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"eval:",0
,smalltalk.__f__("""(self,nativeExpression):
	#ScriptCompiler>>#eval:
	def __blk1__():
		return self.basicEval_(nativeExpression) 
	return self.triggerEvent_with_ifNotHandled_(smalltalk.String("eval:"),nativeExpression,smalltalk.blk(__blk1__,0)) 
""","ScriptCompiler_eval_")
,"evaluation","""eval: nativeExpression
	" Return the result of evaluating a native expression in global context. "

	^self	triggerEvent: #eval: with: nativeExpression
		ifNotHandled: [ self basicEval: nativeExpression ]""",nil)

smalltalk.bind(smalltalk.ScriptCompiler,"parseMethod:",0
,smalltalk.__f__("""(self,aString):
	#ScriptCompiler>>#parseMethod:
	__0__=smalltalk.newContext()
	def __blk1__():
		return self.scriptForMethod_(aString) 
	__0__.script=nil
	__0__.script=self.triggerEvent_with_ifNotHandled_(smalltalk.String("needsScriptFor:"),aString,smalltalk.blk(__blk1__,0)) 
	if smalltalk.b(smalltalk.notNil_(__0__.script)):
		self.cache().at_put_(smalltalk.String("compiledScript"),__0__.script) 
	 
	return smalltalk.superReceiver(smalltalk.ScriptCompiler,self).parseMethod_(aString) 
""","ScriptCompiler_parseMethod_")
,"parsing","""parseMethod: aString
	" Return the result of parsing aString as a method source code. "

	| script |
	script := self
		triggerEvent: #needsScriptFor: with: aString
		ifNotHandled: [ self scriptForMethod: aString ].
	script notNil ifTrue: [ self cache at: #compiledScript put: script ].
	^super parseMethod: aString""",nil)

smalltalk.bind(smalltalk.CompiledScript,"fn",0
,smalltalk.__f__("""(self):
	#CompiledScript>>#fn
	__0__=smalltalk.newContext()
	__0__.fn=nil
	__0__.fn=smalltalk.superReceiver(smalltalk.CompiledScript,self).fn() 
	if smalltalk.b(smalltalk.isNil_(__0__.fn)):
		__0__.fn=getattr(self,"@script",nil).nativeImplementationFor_(self) 
		self.fn_(__0__.fn) 
	 
	return __0__.fn 
""","CompiledScript_fn")
,"accessing","""fn
	" Return the native implementation of the receiver. "

	| fn |
	fn := super fn.
	fn isNil ifTrue: [
		fn := script nativeImplementationFor: self.
		self fn: fn.
	].
	^fn """,nil)

smalltalk.bind(smalltalk.CompiledScript,"exportFor:on:",0
,smalltalk.__f__("""(self,anExporter,aStream):
	#CompiledScript>>#exportFor:on:
	__0__=smalltalk.newContext()
	__0__.encoder=nil
	__0__.cls=nil
	__0__.nClassName=nil
	if smalltalk.b(smalltalk.isNil_(self.compiledSource())):
		return smalltalk.false 
	 
	__0__.cls=self.classField() 
	__0__.encoder=anExporter.encoderFor_(__0__.cls) 
	return __0__.encoder.export_method_on_(__0__.cls,self,aStream) 
""","CompiledScript_exportFor_on_")
,"export","""exportFor: anExporter on: aStream
	" Export the native representation of the receiver on to aStream. "

	| encoder cls nClassName |
self compiledSource isNil ifTrue: ["NIY" ^false ].
	cls := self classField.
	encoder := anExporter encoderFor: cls.
"ToDo - encode to recompile on first run, with native source equivalent to:
	[ self recompile. #{this} basicPerform: self selector withArguments: #{arguments} ]
"	^encoder export: cls method: self on: aStream """,nil)
