약간 이상한 예제동작

http://trans.onionmixer.net/mediawiki/index.php?title=SqueakByExample:6.5

이 부분을 진행하려고 상단에 있는 예제부터 입력시켜보고있는데….
희한하게 에러가 안나네요?….
(에러가 나야 디버거를 돌리고 검수를 하는데…T.T)

일단.. String 클래스에 시키는대로 method를 추가했습니다.

그리고 메소드를 저장하려고 하니 이런 에러가 나네요?

20130312_method_1

오호.. 이놈봐라? 해당되는 클래스가 없나보구나.. 라고 생각하고 그걸 다음과같이 처리했습니다.

20130312_method_2

물론 추천하는것중에 대략 비슷해보이는 FileDirectoryWrapper 클래스로 처리하기는 했는데….

workspace에 시킨대로 readme.txt 를 입력하고 mouse로 drag한다음

1. Print it > nil
2. Do it > 반응없음

이라는 결과가 나오네요.

Pharo 2.0에서 테스트해보고있습니다만….
뭔가….. spec이 바껴서 이런증상이 일어나는건지….
애매…합니다…-.-;

================================================

결국 해프닝으로 끝났습니다.

원문에서도 ‘readme.txt’ suffix 라고 이 부분만 font가 틀렸는데
번역문만을 보고 부주의하게 보고 말았네요.
번역본이 넘어온건 “readme.txt”의 접미사를 입력하고…라고 되어있어서
접미사를 .txt라고 생각하고 큰따옴표를 단순히 영문에 대한 강조구문이라고 생각했습니다….-.-;

정확한 해법(?)을 알려주신 한주영님 감사합니다.
Pharo 2.0에서도 전혀 이상없어요…T.T

SystemOrganization 딕셔너리에 대한 심화학습

이렇게 제목을 적으면 뭐 있을거같지만…없어요…-.-;

SystemOrganization 딕셔너리는 Smalltalk에서 Class들과 package등에 대한 구조를 담고있다고 합니다.

아 궁금하네요?

Inspect It 해봤죠.

SystemOrganization inspect
SystemOrganization inspect

 

어머? 뭔가 디게 많네요?……………………

http://trans.onionmixer.net/mediawiki/index.php?title=SqueakByExample:5.7#.EB.8B.A4.EB.A5.B8_.EC.9C.A0.EC.9A.A9.ED.95.9C_.EC.A0.84.EC.97.AD_.EB.B3.80.EC.88.98.EB.93.A4

이 부분을 보면 Magnitude가 어느 Collection에 속해있는지를 찾는법이 나옵니다.

아.. 궁금하네요 어떻게 찾는지?

 

SystemOrganization의 클래스를 찾으면 SystemOrganizer가 나오구요

여기서 method인 categoryOfElement: 를 찾으니깐 없네요? 그럼 누군가는 가지고 있겠죠… 자 그럼 부모클래스로 가보죠.

오호.. Categorizer 라는 클래스가 나오고 이 클래스의 셀렉터중에 categoryOfElement: 가 있습니다.

categoryOfElement: element
"Answer the category associated with the argument, element."

| index |
  index := self numberOfCategoryOfElement: element.
  index = 0
  ifTrue: [^nil]
  ifFalse: [^categoryArray at: index]

대략 이정도의 의미를 알 수가 있군요.

뭐.. 그럭저럭… 가지고 있는 categoryArray라는 인스턴스변수배역에서 관련된 값을 끄집어내는거같습니다.

변수를 본다고 제가 알 수 있는건 아니니.. 이쯤에서 pass욤 😀

객체의 실행과 전달되는 메소드의 처리과정을 살펴보기

이전에 올렸던 내용을 좀 더 떼어내서 살펴보겠습니다.
(원래는 메세지 전달에 대한 궁금증 뿐이었습니다만.. 이건 심화학습정도 되겠네요)

이 문제와 관련되어 메일링 리스트에서 왔다갔다한 내용은 다음과 같습니다

스몰토크는 메소드 단위로 컴파일됩니다. 웍스페이스에서 선택해서 DoIt을 한다고 해도
해당 텍스트를 마치 메소드인냥 컴파일한다음 실행합니다. 
실행하는 메소드는 ProtoObject>>withArg:excute: 인가 그렇고
두번째 인자가 컴파일된 메소드입니다. 컴파일 결과는 스택기반 가상기계용 바이트코드구요.
=============================================
그럼 좀 구체적으로 질문을 드려도 될까요?

Transcript show: 'a'가 compile된다면

ProtoObject withArg:'Transcript show: 'a''
이런식으로 된다는 의미인건가요?
compile이 끝나면 vm위의 메모리에 바이트코드 형태로 존재하게 될거라는건
예상이 되는데....
실제로 어떻게 동작되는지 조금 궁금합니다.
=============================================
Transcript show: 가 어떤식의 VM 머신코드로 컴파일 되는지는 다음처럼 해보면 알 수 있습니다.

"Transcript 가 ThreadSafeTranscript의 인스턴스이므로.."

(ThreadSafeTranscript >> #show:) symbolic. 
"print it 해보세요."

관련해서 더 자세한 내용은 다음 페이지를 참고해보면 도움이 되겠네요.

Introduction to Smalltalk bytecodes

어? 그럼 이떤식으로 메세지가 compile되는지도 알 수 있다는거여?
일단 까라면 까야하는법 PrintIt을 해봤습니다. 그랬더니…

'21 <70> self
22 <88> dup
23 <10> pushTemp: 0
24  send: print:
25 <87> pop
26  send: endEntry
27 <87> pop
28 <78> returnSelf
'

이런결과를 workspace에서 볼 수 있네요.
……………………………
뭔가 죽이는데요? 저 내용 자체가 Smalltalk VM에서 인식하는 수준의 lowlevel이라는건데…
또 다른 방법이 있는거같습니다.
이번에는 한주영님이 알려주신 내용을 보겠습니다.

Transcript show: 'a'를 선택해서 Debug it 해보시면
SmalltalkEditor 클래스의 다음 메소드에서 멈춰있습니다.

debug: aCompiledMethod receiver: anObject in: evalContext

여기, aCompiledMethod 가 UndefinedObject>>#DoIt 메소드이며
실제로는 CompiledMethod 인스턴스(CompiledMethod는 ByteArray를 상속)입니다.
아마 임시로 생성된 메소드라고 보시면 될것 같아요.
receiver(anObject)는 nil 입니다.

DoIt 메소드의 몸체가 바로 "Transcript show: 'a'"입니다.
DoIt 이라는 CompiledMethod는 다음과 같이 바이트코드를 가지고 있습니다.

25 <41> pushLit: Transcript
26 <22> pushConstant: 'a'
27  send: show:
28 <7C> returnTop

메모리 상에 35바이트를 차지하네요.

debug:receiver:in: 에서 다음과 같이 호출합니다.

   aCompiledMethod
                       valueWithReceiver: anObject
                       arguments: (evalContext ifNil: [ #() ] ifNotNil: [ { evalContext } ])

valueWithReceiver: aReceiver arguments: anArray
  ^ aReceiver withArgs: anArray executeMethod: self

aReceiver는 nil이지만 withArgs:executeMethod:를 호출하는데에는 아무 문제가 없죠 ^^

#Transcript 심볼을 푸시
'a' 상수를 푸시
#show: 심볼을 'send'
그리고 리턴이네요..

'send'를 처리하고나면 결과값이 stack top에 저장되어 있을 거고요.

실제 본인이 디버깅 해가면서 추적하는 방법을 통째로 알려주셨습니다.
사실 방법이야 여러가지가 있겠습니다만…
중요한건 실시간으로 컴파일되는 바이트코드를 결과물로 봐가면서 디버깅을 할 수 있고
그걸로 내부 구조를 좀 더 볼 수 있다는게 중요한거같네요.

아직 이 내용을 제대로 다 숙지하지는 못했습니다만…..
좀 더 코드를 두들겨보고 스스로 결론을 낼 수 있는 단계가 오면
최종과정으로 한번 더 글을 쓰도록 하겠습니다 😀