360 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Smalltalk
		
	
	
	
	
	
			
		
		
	
	
			360 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Smalltalk
		
	
	
	
	
	
class Apex(nil)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
class(#limited) Error(Apex)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
pooldic Error.Code
 | 
						|
{
 | 
						|
	ENOERR     := error(0).
 | 
						|
	EGENERIC   := error(1).
 | 
						|
	ENOIMPL    := error(2).
 | 
						|
	ESYSERR    := error(3).
 | 
						|
	EINTERN    := error(4).
 | 
						|
	ESYSMEM    := error(5).
 | 
						|
	EOOMEM     := error(6).
 | 
						|
	EINVAL     := error(7).
 | 
						|
	ENOENT     := error(8).
 | 
						|
	EPERM      := error(12).
 | 
						|
	ERANGE     := error(20).
 | 
						|
(* add more items... *)
 | 
						|
}
 | 
						|
 | 
						|
(*pooldic Error.Code2 
 | 
						|
{
 | 
						|
	>> CAN I SUPPORT this kind of redefnition? as of now, it's not accepted because 
 | 
						|
	>> Error.Code2.EGENERIC is not a literal. Should i treate pooldic members as a constant
 | 
						|
	>> and treat it as if it's a literal like? then even if the defined value changes,
 | 
						|
	>> the definition here won't see the change... what is the best way to tackle this issue?
 | 
						|
 | 
						|
	EGENERIC := Error.Code2.EGENERIC.
 | 
						|
}*)
 | 
						|
 | 
						|
extend Apex
 | 
						|
{
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
	method(#dual) dump
 | 
						|
	{
 | 
						|
		<primitive: #_dump>
 | 
						|
	}
 | 
						|
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
	method(#dual) yourself { ^self }
 | 
						|
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## INSTANTIATION & INITIALIZATION
 | 
						|
	## -------------------------------------------------------
 | 
						|
	method(#class,#primitive,#lenient) _basicNew.
 | 
						|
	method(#class,#primitive,#lenient) _basicNew: size.
 | 
						|
 | 
						|
	method(#class,#primitive) basicNew.
 | 
						|
	method(#class,#primitive) basicNew: size.
 | 
						|
	(* the following definition is almost equivalent to the simpler definition
 | 
						|
	 *    method(#class,#primitive) basicNew: size.
 | 
						|
	 * found above.
 | 
						|
	 * in the following defintion, the primitiveFailed method is executed 
 | 
						|
	 * from the basicNew: context. but in the simpler definition, it is executed
 | 
						|
	 * in the context of the caller of the basicNew:. the context of the basicNew:
 | 
						|
	 * method is not even created
 | 
						|
	method(#class) basicNew: size
 | 
						|
	{
 | 
						|
		<primitive: #Apex__basicNew:>
 | 
						|
		self primitiveFailed(thisContext method)
 | 
						|
	}*)
 | 
						|
 | 
						|
	method(#class) new
 | 
						|
	{
 | 
						|
		| x |
 | 
						|
		x := self basicNew.
 | 
						|
		x initialize. ## TODO: assess if it's good to call 'initialize' from new
 | 
						|
		^x.
 | 
						|
	}
 | 
						|
 | 
						|
	method(#class) new: anInteger
 | 
						|
	{
 | 
						|
		| x |
 | 
						|
		x := self basicNew: anInteger.
 | 
						|
		x initialize. ## TODO: assess if it's good to call 'initialize' from new.
 | 
						|
		^x.
 | 
						|
	}
 | 
						|
 | 
						|
	method initialize
 | 
						|
	{
 | 
						|
		(* a subclass may override this method *)
 | 
						|
		^self.
 | 
						|
	}
 | 
						|
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
	##method(#dual,#primitive,#lenient) _shallowCopy.
 | 
						|
	##method(#dual,#primitive) shallowCopy.
 | 
						|
	
 | 
						|
	method(#dual) shallowCopy
 | 
						|
	{
 | 
						|
		<primitive: #_shallow_copy>
 | 
						|
		self primitiveFailed(thisContext method).
 | 
						|
	}
 | 
						|
 | 
						|
	
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
	method(#dual,#primitive,#lenient) _basicSize.
 | 
						|
	method(#dual,#primitive) basicSize.
 | 
						|
 | 
						|
	method(#dual) basicAt: index
 | 
						|
	{
 | 
						|
		| perr |
 | 
						|
		
 | 
						|
		<primitive: #_basic_at>
 | 
						|
 | 
						|
## TODO: create a common method that translate a primitive error to some standard exceptions of primitive failure.
 | 
						|
		perr := thisProcess primError.
 | 
						|
		if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) }
 | 
						|
		elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt }
 | 
						|
		else { self primitiveFailed }
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) basicAt: index put: anObject
 | 
						|
	{
 | 
						|
		| perr |
 | 
						|
		
 | 
						|
		<primitive: #_basic_at_put>
 | 
						|
 | 
						|
		perr := thisProcess primError.
 | 
						|
		if (perr == Error.Code.ERANGE) { self index: index outOfRange: (self basicSize) }
 | 
						|
		elsif (perr == Error.Code.EPERM) { self messageProhibited: #basicAt:put: }
 | 
						|
		else { self primitiveFailed }
 | 
						|
	}
 | 
						|
 | 
						|
	(* ------------------------------------------------------------------
 | 
						|
	 * HASHING
 | 
						|
	 * ------------------------------------------------------------------ *)
 | 
						|
	method(#dual) hash
 | 
						|
	{
 | 
						|
		<primitive: #_hash>
 | 
						|
		self subclassResponsibility: #hash
 | 
						|
	}
 | 
						|
 | 
						|
	(* ------------------------------------------------------------------
 | 
						|
	 * IDENTITY TEST
 | 
						|
	 * ------------------------------------------------------------------ *)
 | 
						|
 | 
						|
	method(#dual) == anObject
 | 
						|
	{
 | 
						|
		(* check if the receiver is identical to anObject.
 | 
						|
		 * this doesn't compare the contents *)
 | 
						|
		<primitive: #_identical>
 | 
						|
		self primitiveFailed.
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) ~~ anObject
 | 
						|
	{
 | 
						|
		<primitive: #_not_identical>
 | 
						|
		^(self == anObject) not.
 | 
						|
	}
 | 
						|
 | 
						|
	(* ------------------------------------------------------------------
 | 
						|
	 * EQUALITY TEST
 | 
						|
	 * ------------------------------------------------------------------ *)
 | 
						|
	method(#dual) = anObject
 | 
						|
	{
 | 
						|
		<primitive: #_equal>
 | 
						|
		self subclassResponsibility: #=
 | 
						|
	}
 | 
						|
	
 | 
						|
	method(#dual) ~= anObject
 | 
						|
	{
 | 
						|
		<primitive: #_not_equal>
 | 
						|
		^(self = anObject) not.
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	(* ------------------------------------------------------------------
 | 
						|
	 * COMMON QUERIES
 | 
						|
	 * ------------------------------------------------------------------ *)
 | 
						|
 | 
						|
	method(#dual,#primitive) class.
 | 
						|
	 
 | 
						|
	method(#dual) isNil
 | 
						|
	{
 | 
						|
		"^self == nil."
 | 
						|
		^false
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) notNil
 | 
						|
	{
 | 
						|
		"^(self == nil) not"
 | 
						|
		"^self ~= nil."
 | 
						|
		^true.
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) isError
 | 
						|
	{
 | 
						|
		^false
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) notError
 | 
						|
	{
 | 
						|
		^true
 | 
						|
	}
 | 
						|
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
 | 
						|
	method(#class) inheritsFrom: aClass
 | 
						|
	{
 | 
						|
		| c |
 | 
						|
		c := self superclass.
 | 
						|
		[c notNil] whileTrue: [
 | 
						|
			[ c == aClass ] ifTrue: [^true].
 | 
						|
			c := c superclass.
 | 
						|
		].
 | 
						|
		^false
 | 
						|
	}
 | 
						|
 | 
						|
	method(#class) isMemberOf: aClass
 | 
						|
	{
 | 
						|
		(* a class object is an instance of Class
 | 
						|
		 * but Class inherits from Apex. On the other hand,
 | 
						|
		 * most of ordinary classes are under Object again under Apex.
 | 
						|
		 * special consideration is required here. *)
 | 
						|
		^aClass == Class
 | 
						|
	}
 | 
						|
 | 
						|
	method(#class) isKindOf: aClass
 | 
						|
	{
 | 
						|
		^(self isMemberOf: aClass) or: [self inheritsFrom: aClass].
 | 
						|
	}
 | 
						|
 | 
						|
	method isMemberOf: aClass
 | 
						|
	{
 | 
						|
		^self class == aClass
 | 
						|
	}
 | 
						|
 | 
						|
	method isKindOf: aClass
 | 
						|
	{
 | 
						|
		^(self isMemberOf: aClass) or: [self class inheritsFrom: aClass].
 | 
						|
	}
 | 
						|
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
 | 
						|
	method(#dual) respondsTo: selector
 | 
						|
	{
 | 
						|
		<primitive: #_responds_to>
 | 
						|
		self primitiveFailed
 | 
						|
	}
 | 
						|
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
 | 
						|
	method(#dual,#variadic) perform(selector)
 | 
						|
	{
 | 
						|
		<primitive: #_perform>
 | 
						|
		self primitiveFailed
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) perform: selector
 | 
						|
	{
 | 
						|
		<primitive: #_perform>
 | 
						|
		self primitiveFailed
 | 
						|
	}
 | 
						|
	
 | 
						|
 | 
						|
	method(#dual) perform: selector with: arg1
 | 
						|
	{
 | 
						|
		<primitive: #_perform>
 | 
						|
		self primitiveFailed
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) perform: selector with: arg1 with: arg2
 | 
						|
	{
 | 
						|
		<primitive: #_perform>
 | 
						|
		self primitiveFailed
 | 
						|
	}
 | 
						|
 | 
						|
	method(#dual) perform: selector with: arg1 with: arg2 with: arg3
 | 
						|
	{
 | 
						|
		<primitive: #_perform>
 | 
						|
		self primitiveFailed
 | 
						|
	}
 | 
						|
 | 
						|
	## -------------------------------------------------------
 | 
						|
	## -------------------------------------------------------
 | 
						|
 | 
						|
	method exceptionizeError: trueOrFalse
 | 
						|
	{
 | 
						|
		<primitive: #_exceptionize_error>
 | 
						|
		self class cannotExceptionizeError
 | 
						|
	}
 | 
						|
 | 
						|
	(* ------------------------------------------------------------------
 | 
						|
	 * COMMON ERROR/EXCEPTION HANDLERS
 | 
						|
	 * ------------------------------------------------------------------ *)
 | 
						|
	method(#dual) error: msgText
 | 
						|
	{
 | 
						|
		(* TODO: implement this
 | 
						|
		  Error signal: msgText. *)
 | 
						|
		msgText dump.
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
class Object(Apex)
 | 
						|
{
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
class UndefinedObject(Apex)
 | 
						|
{
 | 
						|
	method isNil
 | 
						|
	{
 | 
						|
		^true
 | 
						|
	}
 | 
						|
 | 
						|
	method notNil
 | 
						|
	{
 | 
						|
		^false.
 | 
						|
	}
 | 
						|
 | 
						|
	method handleException: exception
 | 
						|
	{
 | 
						|
		('### EXCEPTION NOT HANDLED #### ' &  exception class name & ' - ' & exception messageText) dump.
 | 
						|
		## TODO: debug the current process???? "
 | 
						|
## TODO: ensure to execute ensure blocks as well....
 | 
						|
		####Processor activeProcess terminate.
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
extend Error
 | 
						|
{
 | 
						|
	(* ----------------------------
 | 
						|
	TODO: support nested pooldic/constant declaration...
 | 
						|
 | 
						|
	pooldic/const
 | 
						|
	{
 | 
						|
		NONE := error(0).
 | 
						|
		GENERIC := error(1).
 | 
						|
	}
 | 
						|
	-------------------------------- *)
 | 
						|
 | 
						|
	method isError
 | 
						|
	{
 | 
						|
		^true
 | 
						|
	}
 | 
						|
 | 
						|
	method notError
 | 
						|
	{
 | 
						|
		^false
 | 
						|
	}
 | 
						|
 | 
						|
	method(#primitive) asInteger.
 | 
						|
	method(#primitive) asCharacter.
 | 
						|
	method(#primitive) asString.
 | 
						|
}
 |