Showing posts with label smalltalk. Show all posts
Showing posts with label smalltalk. Show all posts

Sunday, October 18, 2015

Using traits to reuse code in Pharo

While working on a small Tetris-like clone in Pharo, I found an opportunity to reuse some code.

It's common for Tetris implementations to show a small preview of the tetrimino that comes next. Here's how it looks:

I wanted to create a separate Morphic component to show this preview. But I didn't want to duplicate the code required to paint the tetriminos. Sharing this code will allow me to have just one place to change the way tetriminos look. Also I didn't want to create a base class on top of both the game and the preview Morphs.

While reading about Pharo and Squeak I found that it supports Traits. The Pharo collaborActive book provides a nice explanation of how to use traits. Here's a quick definition from this document:

... traits are just groups of methods that can be reused in different classes.

This is exactly what I needed for reusing the tetrimino matrix drawing code. The following code shows the code defined in the game matrix Morph component.

drawOn: canvas
   "Draws the current game state"
   |rows columns currentValue rectangle currentColor cellWidth cellHeight|

   rows := gameState size x.
   columns := gameState size y.

   super drawOn: canvas.

   cellWidth :=   ((self width) / columns) asFloat truncated.
   cellHeight :=   ((self height) / rows) asFloat truncated.
   1 to: rows do: [ :row |
      1 to: columns do: [ :column|
         currentValue := gameState at: row at: column .
         currentValue ~= 0 ifTrue: [
                 currentColor := (colors at: currentValue).
                 rectangle := Rectangle left: (self bounds left)



                 canvas frameAndFillRectangle: rectangle
                                 fillColor:  currentColor
                                 borderWidth:  1
                                 borderColor: (Color white).
                  ]
          ]
       ].

Moving this code to a trait implies that I have to pass all instance state variables as an argument of the draw method.

The definition of the trait looks like this:

Trait named: #TTetriminoDrawing
    uses: {}
    category: 'TryTrix'

And the definition of the method inside this trait looks like this:

drawGameStateOn: canvas 
      width: areaWidth height: areaHeight 
      columns: columns rows: rows 
      morphBounds: morphBounds
      matrix: contentMatrix
      colors:  colorPalette
   "Draw the contents of the specified matrix on the given canvas"
   |cellWidth cellHeight currentValue currentColor rectangle|
      cellWidth :=   (areaWidth / columns) asFloat truncated.
   cellHeight :=   (areaHeight / rows) asFloat truncated.
   1 to: rows do: [ :row |
      1 to: columns do: [ :column|
         currentValue := contentMatrix at: row at: column .
         currentValue ~= 0 ifTrue: [ 
            currentColor := (colorPalette at: currentValue).
            rectangle := Rectangle left: (morphBounds left) + ((column - 1)*cellWidth) 
                                    right: (morphBounds left) + ((column - 1)*cellWidth) + cellWidth
                                    top: (morphBounds top) + ((row - 1)*cellHeight )
                                    bottom: (morphBounds top) + ((row - 1)*cellHeight ) + cellHeight.
            canvas frameAndFillRectangle: rectangle
                  fillColor:  currentColor
                  borderWidth:  1
                  borderColor: (Color white).
             ]
          ]
       ].

Now I can use this trait inside each morph definition:

Morph subclass: #TryTrixMorph
    uses: TTetriminoDrawing
    instanceVariableNames: 'gameState colors eventHandlers'
    classVariableNames: ''
    category: 'TryTrix'


Morph subclass: #TetriminoPreview
    uses: TTetriminoDrawing
    instanceVariableNames: 'matrix'
    classVariableNames: ''
    category: 'TryTrix'

This code can be found in here.

Tuesday, September 15, 2015

A small Tetris-like Morphic component in Pharo

As part of my exploration of Pharo, I wanted to create a small basic/naive/incomplete implementation of a Tetris-like game as a Morphic component. Here's an example of the current state of the code:

Implementation

The (still incomplete) implementation is very simple. It uses a matrix to represent the game state. When we want to paint the current game state, we examine the matrix and paint a small rectangle for each of the occupied positions.

drawOn: canvas
   "Draws the current game state"
   |rows columns currentValue rectangle currentColor cellWidth cellHeight|

   rows := gameState size x.
   columns := gameState size y.
   
   super drawOn: canvas.
   
   cellWidth :=   ((self width) / columns) asFloat truncated.
   cellHeight :=   ((self height) / rows) asFloat truncated.
   1 to: rows do: [ :row |
      1 to: columns do: [ :column|
         currentValue := gameState at: row at: column .
         currentValue ~= 0 ifTrue: [ 
            currentColor := (colors at: currentValue).
            rectangle := Rectangle left: (self bounds left) + ((column - 1)*cellWidth) 
                                   right: (self bounds left) + ((column - 1)*cellWidth) + cellWidth
                                   top: (self bounds top) + ((row - 1)*cellHeight )
                                   bottom: (self bounds top) + ((row - 1)*cellHeight ) + cellHeight.
            canvas frameAndFillRectangle: rectangle
                  fillColor:  currentColor
                  borderWidth:  1
                  borderColor: (Color white).
             ]
          ]
       ].

Each Tetrimino is also represented as a small matrix.

Here's the definition for the 'J' and 'S' tetriminos:


   kind = #J ifTrue: [ 
      resultTetrimino := 
         Tetrimino 
            create: gameMatrix 
            tetriminoMatrix: 
               (Matrix rows: 2 
                  columns: 3 
                  contents: { 1. 1. 1.
                              0. 0. 1. })  
            colorIndex: 5.
      ].

...

   kind = #S ifTrue: [ 
      resultTetrimino := 
         Tetrimino 
            create: gameMatrix 
            tetriminoMatrix: 
               (Matrix rows: 2 
                  columns: 3 
                  contents: { 0. 1. 1.
                              1. 1. 0. })  
            colorIndex: 3.
      ].

The implementation is still incomplete, I hope that future posts will show more progress.

The source code can be found here: http://www.github.com/ldfallas/TryTrix .

Friday, August 28, 2015

Glider Gun

Just a quick look at the Gosper's Glider Gun pattern.

This is running on Pharo using this program https://github.com/ldfallas/GameOfLife

Sunday, August 23, 2015

Game Of Life and Pharo

For me, watching executions of the Conway's Game of Life is hypnotizing. It is interesting how a small set of simple rules creates such complex and beautiful patterns.

Creating a naive version of the Game of Life is a small programming task, which is ideal for learning a new programming language. I used it to create a small example in Pharo which is a Smalltalk based language. For its implementation I also used the Morphic UI environment.

Game of life Morph executing

The program is written as a Morph, which is the name of an object on the screen. Here's the definition:

Morph subclass: #GameOfLifeMorph
        instanceVariableNames: 'columns rows content mouseInteraction nextGrid'
        classVariableNames: ''
        category: 'GameOfLife'

Drawing the matrix with the contents of the game is very simple:

drawing
drawOn: canvas
     "Draws the game of life widget with the current state"
     | cellWidth cellHeight rectangle  cellColor cellValue|
      
     cellWidth :=   (self width) / columns.
     cellHeight :=   (self height) / rows.
     1 to: rows do: [ :row |
          1 to: columns do: [ :column |
                 cellValue := (content at: row at: column).
                 cellColor := cellValue = 1 ifTrue: [ Color black ] ifFalse: [ Color white  ].
                 rectangle := Rectangle left: (self bounds left) + ((column - 1)*cellWidth) 
                                        right: (self bounds left) + ((column - 1)*cellWidth) + cellWidth
                                        top: (self bounds top) + ((row - 1)*cellHeight )
                                         bottom: (self bounds top) + ((row - 1)*cellHeight ) + cellHeight.
         
                 cellValue = 1 ifTrue: [canvas fillRectangle:  rectangle color:  cellColor]
                               ifFalse: [canvas frameAndFillRectangle: rectangle 
                                                   fillColor:  (Color white) 
                                                   borderWidth: 1 
                                                   borderColor: (Color black)].
             ]
       ].
       ^self.

The implementation of the animation part of the program was created using the step and stepTime methods.

stepping and presenter
step
      "Verifies the rules of the Game Of Life"
      | tmp |
      
      1 to: rows do:  [ :row | 
          1 to: columns do:  [ :column |
              nextGrid at: row at: column put: (self getNextGenerationFor: row column: column).
          ]
      ].
      tmp := content.
      content := nextGrid.
      nextGrid := tmp.
      self changed.

The following method shows how to get the next generation for a given (row, column) individual.

This method is going to check for the game of life rules.

game of life rules
getNextGenerationFor: row column: column
      "Verifies the Game Of Life rules"
      |topLeft top topRight left right bottomLeft bottomRight bottom neighbors|

      topLeft :=  self getCellValue: (row - 1) column: (column - 1).
      top := self getCellValue: (row - 1) column: column.
      left := self getCellValue: row column: (column - 1).
      right := self getCellValue: row column: (column + 1).
      topRight := self getCellValue: (row - 1) column: (column + 1).
      bottomRight := self getCellValue: (row + 1) column: (column + 1).
      bottom := self getCellValue: (row + 1) column: column.
      bottomLeft := self getCellValue: (row + 1) column: (column - 1).
   
      neighbors := topLeft + top + left + right + topRight + bottomRight + bottom  + bottomLeft.

      ^ ((content at: row at: column) = 1) 
             ifTrue: [ (neighbors < 2 | (neighbors > 3)) ifTrue: [ 0 ] ifFalse: [ 1 ]  ] 
             ifFalse: [ (neighbors = 3) ifTrue: [ 1 ] ifFalse: [ 0 ] ].

The last statement verifies the rules:

  • A live cell with less than two neighbors dies in the next generation
  • A live cell with two or three neighbors survives to the next generation
  • A live cell with more than three neighbors dies
  • A dead cell with three neighbors becomes alive in the next generation

To open this Morph into the Pharo environment we can evaluate:

|m|
m := GameOfLifeMorph rows: 30 columns: 30.
m width: 300 ;height: 300 ; openInWorld.
m stopStepping.
m enableMouseInteraction . 

To start the execution we can evaluate:


GameOfLifeMorph allInstances last startStepping.

Programming in Pharo is a very interesting experience. This mainly because the development environment is really integrated with the program you are developing. Something that called my attention is how you can define missing code while debugging and without stopping the debugging session.

The code for this experiment can be found here: http://github.com/ldfallas/GameOfLife

Monday, August 10, 2015

Starting with Pharo and external source control

Here's a series of steps I'm following for using Git to store the source code of some Pharo experiments I'm working on.

I'm starting learning about Pharo. The information on this post is based on the nice Pharo and Github using Sourcetree video and an introduction to Monticello.

Configuring a repository

We can start by creating a repository that is located in the filesystem. To define configure this repository we open the "Monticello Browser" from the "World" menu and press the "+Repository" button.

We are going to select the filetree:// repository type. This is useful to store the code in separate files.

When this option is selected the UI will prompt us for the folder where the code will be stored. We are going to specify a directory where we executed the git init command . Other source control systems could be used to manage this directory since it will contain the source code as text files.

Creating a package

Now we're going to define a package where we will the create the code to be stored in source control. To define the package we open the "Monticello Browser" from the "World" menu and press the "+Package" button.

Now we can create a class inside this package. We are going to define the GameOfLifeMorph class to be in the GameOfLife category.

We are going to add a method to the GameOfLifeMorph class.

After adding these elements we can save the changes to the GameOfLife package. We can review the changes before saving by pressing the Changes button on the "Monticello" browser.

This option opens the following screen to review the changes before saving.

After reviewing the changes we can save the changes to the file system using the Save button in the "Monticello Browser" window. Now we can go to the command line to directory we selected when creating the repository and execute a git status command.

~/devel/pharo/GameOfLife$ git add .filetree GameOfLife.package/
~/devel/pharo/GameOfLife$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

        new file:   .filetree
        new file:   GameOfLife.package/.filetree
        new file:   GameOfLife.package/GameOfLifeMorph.class/README.md
        new file:   GameOfLife.package/GameOfLifeMorph.class/instance/initWithRows.columns..st
        new file:   GameOfLife.package/GameOfLifeMorph.class/methodProperties.json
        new file:   GameOfLife.package/GameOfLifeMorph.class/properties.json
        new file:   GameOfLife.package/monticello.meta/categories.st
        new file:   GameOfLife.package/monticello.meta/initializers.st
        new file:   GameOfLife.package/monticello.meta/package
        new file:   GameOfLife.package/monticello.meta/version
        new file:   GameOfLife.package/properties.json

~/devel/pharo/GameOfLife$ git commit -m "First commit"

Sunday, June 21, 2009

Using libcurl with Newspeak FFI (continued)

The previous post presented a small low level interface to libcurl using the Newspeak programming language. In this post I'm going to show the HttpServiceClient class, which was created to give a simple interface to the LibCurlHelper class.

The definition for class looks like this:


Newsqueak2
'LangexplrExperiments'

class HttpServiceClient usingLib: platform withCurlPath: curlLibraryPath = (
"This class is used to access services provided by the HTTP protocol"
|
LibCurlHelper = platform LibCurlHelper.
ByteString = platform ByteString.
platform = platform.
Transcript = platform Transcript .
private curlLibraryPath = curlLibraryPath .
|
)
(

class HttpRequestResult curlErrorCode: curlErrorCode httpResponse: httpResponse data: data= (
...
)
(
...
)

createNewCurlInstance = (
...
)

get: url <String> ^ <HttpRequestResult> = (
...
)

get: url <String> withHeaders: headers <Array> ^ <HttpRequestResult> = (
...
)

private isHttpsUrl: url <String> ^ <Boolean> = (
...
)

postForm: formData <Dictionary> to: url <String> ^ <HttpRequestResult> = (
...
)

) : (
...
)


The get:, get: withHeaders: and postForm: to: methods provide the functionally to do very simple GET and POST requests.

The HttpRequestResult encapsulates the result of calling these methods which has the result of calling libcurl, the HTTP response code and the text of the requested data if successful.

The code for the GET methods looks like this:

get: url <String> ^ <HttpRequestResult> = (
| curl data tmpBuffer bufferLength response|
^ get: url withHeaders: {}.
)


get: url <String> withHeaders: headers <Array> ^ <HttpRequestResult> = (
| curl data tmpBuffer bufferLength curlCallResult response|
data:: ''.
curl:: createNewCurlInstance.
curl writeCallback:
[:args :result|
bufferLength:: ((args datasize) * (args nmemb)).
tmpBuffer:: ByteString new: bufferLength.
args data copyInto: tmpBuffer
from: 1 to: bufferLength
in: (args data) startingAt: 1.
data:: data,tmpBuffer.
result returnInteger: bufferLength.
].

headers size > 0 ifTrue: [curl headers: headers].

(isHttpsUrl: url)
ifTrue: [curl noSslVerification.].
curl url: url.

curlCallResult:: curl performOperation.

response:: curl responseCode.
curl cleanup.
^HttpRequestResult
curlErrorCode: curlCallResult
httpResponse: response
data: data.
)


The code for the POST operation looks like this:


postForm: formData <Dictionary> to: url = (
| curl data tmpBuffer bufferLength curlFormData response curlCallResult|
data:: ''.
curl:: createNewCurlInstance.

curl post: formData.
curl writeCallback:
[:args :result|
bufferLength:: ((args datasize) * (args nmemb)).
tmpBuffer:: ByteString new: bufferLength.
args data copyInto: tmpBuffer
from: 1 to: bufferLength
in: (args data) startingAt: 1.
data:: data,tmpBuffer.
result returnInteger: bufferLength.
].

(isHttpsUrl: url)
ifTrue: [curl noSslVerification.].

curl url: url.
curlCallResult: curl performOperation.

response:: curl responseCode.
curl cleanup.
^HttpRequestResult
curlErrorCode: curlCallResult
httpResponse: response
data: data.
)


Code for this post can be found here.

Saturday, June 13, 2009

Using libcurl with Newspeak FFI

In this post I'm going to show a little example of using libcurl from the Newspeak programming language .

Newspeak FFI



Newspeak provides a nice mechanism to call C code. This mechanism is described in
Newspeak Foreign Function Interface User Guide document. The AlienDemo example provided with the Newspeak prototype has some nice small examples of the FFI.

The experiment presented in this post was created using the Newspeak prototype from February 2009. Due to some limitations of this release, this code only works with the Windows version of the prototype.

libcurl



libcurl is a C library that provides client access to several networking protocols with a common interface. For this post I'm going to implement a wrapper for very small subset of the functionality provided by libcurl in order to perform simple HTTP/HTTPS GET and POST requests .

The simple.c example shows how to do a simple GET request.


int main(void)
{
CURL *curl;
CURLcode res;

curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}


The LibCurlHelper class



A class named LibCurlHelper will be used to encapsulate calls to libcurl. As you will notice the interface of this class is pretty low level. For future posts I'll try to create a better interface using more Newspeak features.


class LibCurlHelper usingLib: platform = (
"This class wraps an implementation of the libcurl library"
|
Transcript = platform Transcript.
Alien = platform Alien.
UnsafeAlien = platform UnsafeAlien.
Callback = platform Callback.
CurlWriteCallback = platform CurlWriteCallbackNs1.
CurlDebugCallback = platform CurlDebugCallback.
ByteString = platform ByteString.
OrderedCollection = platform OrderedCollection.
...
public libcurlPath = ''.
public errorBuffer = ''.
protected CURL_OPT_URL = 10002.
protected CURLOPT_WRITEFUNCTION = 20011.
...

internalDebugCallback = nil.
internalWriteCallback = nil.
formPostData = nil.
private curlInstance = nil.
private aliensToRelease = nil.


CURLFORM_NOTHING = 0 .
CURLFORM_COPYNAME = 1 .
CURLFORM_PTRNAME = 2.
...


libcurl uses a lot of constaints prefixed with "CURL" this class contains definitions for some of them.

Initialization



The initializeCurl method calls the curl_easy_init (as in the simple.c example shown above) and stores the returned pointer in a slot called curlInstance which will be used in further calls.


initializeCurl = (
|curl|
ensureLibrariesLoaded .
(Alien lookup: 'curl_easy_init' inLibrary: curlLibName )
primFFICallResult: (curl:: Alien new: 4).
curlInstance: curl.
)


The ensureLibrariesLoaded and methods.


curlLibName = (
^libcurlPath, 'libcurl.dll'
)
ensureLibrariesLoaded = (
Alien ensureLoaded: libcurlPath, 'libidn-11.dll'.
Alien ensureLoaded: libcurlPath, 'libeay32.dll'.
Alien ensureLoaded: libcurlPath, 'libssl32.dll'.
Alien ensureLoaded: curlLibName.
)


Setting the URL



In order to set the URL for the request we need to call the curl_easy_setopt function with the CURL_OPT_URL with the URL string.

The code looks like this:


url: url <String> = (
|result|
(Alien lookup: 'curl_easy_setopt' inLibrary: curlLibName )
primFFICallResult: (result:: Alien new:4)
withArguments: { curlInstance.
CURL_OPT_URL.
(addAlienToRelease: (url asAlien)) pointer. }.
^result.
)


The addAlienToRelease: method was added to in order to keep track of resources allocated in the C heap that need to be manually released when not needed. The asAlien method of the String class creates a resource of this kind.

The implementation of this method looks like this:


addAlienToRelease: anAlien = (
aliensToRelease isNil ifTrue: [ aliensToRelease:: OrderedCollection new. ].
aliensToRelease add: anAlien.
^anAlien.
)


Setting the write callback



Callback functions are used by libcurl to process the data coming from the network. The Newspeak FFI provides a nice way to add this kind of callbacks.


writeCallback: callback <Block>= (
|result|
internalWriteCallback:: Callback
block: callback
argsClass: CurlWriteCallback.

(Alien lookup: 'curl_easy_setopt' inLibrary: curlLibName )
primFFICallResult: (result:: Alien new: 4)
withArguments: { curlInstance.
CURLOPT_WRITEFUNCTION.
internalWriteCallback thunk. }.

^result.
)



The writeCallback: method sets the block in callback as the libcurl write callback. In order to do this it creates an instance of the Callback class with the block and the arguments class. An instance of this class is used to create a function pointer which is passed to the curl_easy_setopt function.

The "arguments class" is defined using the NS1 Newspeak syntax as follows:


Newsqueak1
'LangexplrExperiments'
CurlWriteCallbackNs1 = Alien (
"Class used to represent arguments of the LibCurl write function."
'as yet unclassified'
data = (
^Alien forPointer: (self unsignedLongAt: 1)
)
datasize = (
^(self unsignedLongAt: 5)
)
nmemb = (
^(self unsignedLongAt: 9)
)
writerData = (
^Alien forPointer: (self unsignedLongAt: 13)
)
) : (
'as yet unclassified'
dataSize = (
^16
))



An instance of this class is used to represent the arguments of a callback call. An example of the use of this function is presented below.

Performing the request



The curl_easy_perform function is used to start the operation. The following code shows the call to this function:


performOperation = (
|r|
(Alien lookup: 'curl_easy_perform' inLibrary: curlLibName )
primFFICallResult: (r:: Alien new: 4)
withArguments: { curlInstance. }.
^r signedLongAt: 1.
)


Cleanup



Finally the following method is used to release the resources allocated by libcurl.


cleanup = (
(Alien lookup: 'curl_easy_cleanup' inLibrary: curlLibName )
primFFICallResult: nil
withArguments: { curlInstance } .

aliensToRelease do: [:anAlien | anAlien free ].
)


Example of using the library



As mentioned above, the LibCurlHelper class provides a low level interface to libcurl, something needs to be created to encapsulate this functionality.

The following method shows a method that preforms a simple GET request and returns the downloaded data as a string.


class HttpServiceClient usingLib: platform withCurlPath: curlLibraryPath = (
"This class is used to access services provided by the HTTP protocol"
|
LibCurlHelper = platform LibCurlHelper.
ByteString = platform ByteString.
platform = platform.
Transcript = platform Transcript .
private curlLibraryPath = curlLibraryPath .
|
)

(
simpleGet: url ^ = (
| curl data tmpBuffer bufferLength response|
curl:: (LibCurlHelper usingLib: platform).
curl libcurlPath: curlLibraryPath .
curl initializeCurl.

data:: ''.
curl:: createNewCurlInstance.

curl writeCallback:
[:args :result|
bufferLength:: ((args datasize) * (args nmemb)).
tmpBuffer:: ByteString new: bufferLength.
args data copyInto: tmpBuffer
from: 1 to: bufferLength
in: (args data) startingAt: 1.
data:: data,tmpBuffer.
result returnInteger: bufferLength.
].
curl url: url.
curl performOperation.
curl cleanup.
^data
)
)


Notice that here the callback function modifies a local variable every time the data arrives. Also notice that args is an instance of CurlWriteCallbackNs1.

Final words


The experiment of using libcurl from Newspeak was a nice way to learn about its foreign function interface. Having access to libcurl access to useful things such as HTTPS requests.

There's already a nice Squeak wrapper for libcurl called CurlPlugin .

Code for this post can be found here.

Tuesday, April 14, 2009

Writing a small Twitter client with Newspeak and Hopscotch

In this post I'm going to show a small Twitter client written using the Newspeak programming language and the Hopscotch framework.

As part of the process of exploring the Newspeak language here I'm going to focus on the Hopscotch UI framework. It will be used to present information from the Twitter REST API which is very easy to use.

The Hopscotch framework and IDE is described in the "Hopscotch: Towards User Interface Composition" paper by Vassili Bykov.

Code for this program was created using the Newspeak prototype from 2009-02-27.

The program



Here's a screenshot of the program:

screenshot fo the twitter client

The program is not a complete client, it just allows to post a new twit and to read the current time line of a the user.

The code from the previous post "Parsing JSON with Newspeak" is used to access the data provided by the Twitter services.


The code



The following screenshot shows the definition of the TwitterGUI class



The following nested classes provide the functionality for the client:

  1. TwitterClient: A class for using the Twitter REST API
  2. TwitPresenter,TwitSubject: The UI piece and information for a single twit
  3. TwitterMainPresenter,TwitterMainSubject: The UI piece and information for a the complete client


As described in the Hopscotch paper a pair of elements is required to create a UI piece. A subject which contains the information being presented and the presenter which defines the UI that shows it.

In the case of a single twit the data is transmitted from the service as a JSON document.

The following code shows an example of the JSON response of a single twit from the Twitter REST API:


[{"in_reply_to_screen_name":null,
"user":{
"description":"Father, husband, friend, developer and late night programming language enthusiast.",
"statuses_count":318,
"utc_offset":-21600,
"profile_background_tile":false,
"profile_background_color":"6E8182",
"following":null,
"profile_text_color":"000000",
"url":"http:\/\/langexplr.blogspot.com",
"name":"Luis Diego Fallas",
"protected":false,
"profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/133285952\/ldnach_normal.png",
"notifications":null,
"profile_link_color":"0000ff",
"profile_background_image_url":"http:\/\/static.twitter.com\/images\/themes\/theme1\/bg.gif",
"created_at":"Mon Jul 28 13:51:55 +0000 2008",
"screen_name":"ldfallas",
"profile_sidebar_fill_color":"e0ff92",
"followers_count":45,
"time_zone":"Central America",
"location":"Costa Rica",
"id":15631932,
"favourites_count":9,
"friends_count":43,
"profile_sidebar_border_color":"87bc44"},
"text":"Experimenting with Hopscotch in Newspeak",
"truncated":false,
"in_reply_to_status_id":null,
"created_at":"Tue Apr 07 14:21:57 +0000 2009",
"in_reply_to_user_id":null,
"id":1469769323,
"favorited":false,
"source":"web"}
...]


A TwitSubject represents one of these pieces of information.


class TwitSubject withTwit: twit images: images= Subject (
"Describe the class in this comment."
|
theTwit = twit.
theImages = images.
|
)
(
createPresenter = (
^TwitPresenter new subject: self.
)
)


The definition of the TwitPresenter looks like this:


class TwitPresenter = Presenter (
"Presenter for a single twit."
|
|
)
(
definition = (
^(padded:( column: {

(row: { link: (subject theTwit user screen_name) action: [] . }) color: ( Color veryVeryLightGray).
row: { image: (subject theImages at: (subject theTwit user profile_image_url)) .
blank: 4.
elastic: twitBody}.

}) with: {3. 3. 2. 2.}) .
)
...
)


The following screenshot shows an example of the previous definition.

Single twit

A special treatment need to be applied to the message since we want to be able to click on links or twitter user id's (not supported right now). The definition of twitBody shows this.


twitBody = (
| text result |
text: subject theTwit text.
((string: text contains: '@') or: [string: text contains: 'http'] )
ifTrue: [ result:: flow: ((text subStrings: {Character space}) collect: [:t | componentFor: t])]
ifFalse: [ result:: textDisplay: text ].
^result
)

componentFor: s = (
|result|
(s includesSubString: '@')
ifTrue: [ result:: link: s action: [] ]
ifFalse: [
(string: s contains: 'http')
ifTrue: [ result:: link: s action: [openLink: s] ]
ifFalse:[ result:: label: s]
].
^result.
)

openLink:url = (
OSProcess command: (browser , ' ' , url).
)


What these methods do is to break the string of the message into words separated by spaces. If a word is an URL or and '@' character a link is created if not a 'label' is created . For the future this code needs to be improved with a better technique to identify urls.

The following code shows the definition of TwitterMainSubject:


class TwitterMainSubject user: userName password: pswd = Subject (
"Main subject."
|

user = userName.
password = pswd.
data
images = Dictionary new.
twitterClient = TwitterClient user: userName password:pswd.

|
)
createPresenter ^ = (
data:: twitterClient getFriendsTimeline.
^TwitterMainPresenter new subject: self
)

twits = (
data:: twitterClient getFriendsTimeline.
^data collect: [:t | TwitSubject withTwit: t images: imagesDictionary].
)

updateStatus: statusText = (
twitterClient updateStatus: statusText.
)
...


This class receives the used and password of the Twitter account. The TwitterClient class provides the access to the Twitter services.

Here's the definition of the TwitterMainPresenter class.


class TwitterMainPresenter = Presenter (
"Presenter for the main section of the GUI client."
|
editor
twitsHolder
charCountHolder

|
)
(

definition ^ <Fragment> = (
^column: {
row: { label: 'What are you doing?'.} .
row: { elastic:twitEditor.} .
row: { getCharCountHolder.
filler.
button: 'Update' action:[updateStatus: (editor editedText asString)].
blank: 5.
button: 'Refresh' action:[twitsHolder refresh].
blank: 5.
}.
row: {
blank: 5.
elastic:: getTwitsHolder
}}
))


The getTwitsHolder method create an instance of an HolderComposer object that allows the content to be recalculated using the refresh method. Here's the definition:


getTwitsHolder = (
twitsHolder:: holder: [ list:: subject twits collect: [ :i | i presenter ] ].
^twitsHolder.
)


Notice also that here we are requesting the list of twits to the subject, which calls the web service again getting new content.

Final words



The experience of using the Newspeak and the Hopscotch framework to create this program was very nice.

One thing that I need to find out is how to prevent the application from blocking when requesting the data from the services.

Code for this post can be found here.

Thursday, April 2, 2009

Parsing JSON with Newspeak

In this post I'm going to show a JSON parser written using the Newspeak parser combinator library.

Newspeak



Newspeak is a new programmming language. From its webpage http://newspeaklanguage.org/:


Newspeak is a new programming language in the tradition of Self and Smalltalk. Newspeak is highly dynamic and reflective - but designed to support modularity and security. It supports both object-oriented and functional programming.


In The Newspeak Programming Platform the authors give a nice introduction to the language and platform.

The first time I heard about Newspeak was by watching the Lang.NET 2008 symposium presentation video by Gilad Braha (available here). In this video, a nice parser combinator library is presented . This parser combinator library is described in the Executable Grammars in Newspeak paper by Gilad Bracha.

Code in this post was written using the Newspeak prototype released February 27 2009.

JSON



In order to learn about the language and platform I decided to create a little parser for JSON (Javascript Object Notation).

JSON is a simple data-interchange format defined in http://www.json.org/ .An example of it:


[{ "name": "Wiston Smith",
"description" :"Protagonist"},
{ "name": "Julia",
"description" :"Lover"},
{ "name": "O Brien",
"description" :"Goverment agent"}]


Parser structure



The parser is defined as a single class with a couple of nested classes. The following image shows the definition of JSON Parser in the Newspeak environment.

definition of the JSONParser class

As described in the "Modularity" section of the The Newspeak Programming Platform paper, top-level classes (in this case JSONParser) doesn't have access to its surrounding scope, it only has access to its own or inherited definitions. This is the reason why the JSONParser has the following definitions:


class JSONParser withParserLib: parserLibrary usingLib: platform = (
"Experiment for JSON parser based on the description from http://www.json.org/fatfree.html "
|
ExecutableGrammar = parserLibrary ExecutableGrammar.
CharParser = parserLibrary CharParser.
PredicateTokenParser = parserLibrary PredicateTokenParser.
Dictionary = platform Dictionary.
OrderedCollection = platform OrderedCollection.
Number = platform Number.
|
)
...


The "withParserLib: parserLibrary usingLib: platform" part defines parameters for the construction of JSONParser. These parameters are used to 'import' classes defined elsewhere.

The following code shows a way to create an instance of the JSONParser class:

|platform parser|
platform:: Platform new.
parser = (JSONParser withParserLib: (BlocklessCombinatorialParsing usingLib: platform) usingLib: platform).
...


The JSONParser nested classes are the following:

  1. CharExceptForParser which is a parser that accepts any character except for the one specified (this is for internal use)
  2. JSONGrammar The definition of the JSON grammar
  3. JSONGrammarWithAST which defines the way the AST is created
  4. JSONObject which is used in the representation of the JSON AST



Grammar



The following code shows the JSON grammar defined using the parsing combinators:


class JSONGrammar = ExecutableGrammar (
"Experiment for JSON grammar based on the description from http://www.json.org/fatfree.html "
|
doubleQuote = (char: $").
backslash = (char: $\).
str = doubleQuote,((backslash, ( char: $" )) |
(backslash, ( char: $/ )) |
(backslash, backslash) |
(backslash, ( char: $r )) |
(backslash, ( char: $n )) |
(backslash, ( char: $t )) |
(charExceptFor: $")) star, doubleQuote.
string = tokenFor: str.

negSign = (char: $-).
plusSign = (char: $+).
digit = (charBetween: $0 and: $9).
dot = (char: $. ) .
num = negSign opt, digit, digit star, dot opt,digit star, ((char: $e) | (char: $E)) opt, (plusSign | negSign) opt,digit star.
number = tokenFor: num.

leftbrace = tokenFromChar: ${.
rightbrace =tokenFromChar: $}.
colon = tokenFromChar: $:.
comma = tokenFromChar: $,.
definition = string,colon,value.
obj = leftbrace, (definition starSeparatedBy: comma),rightbrace.
object = tokenFor: obj.

leftbracket = tokenFromChar: $[.
rightbracket = tokenFromChar: $].
arr = leftbracket, (value starSeparatedBy: comma), rightbracket.
array = tokenFor: arr.

ttrue = tokenFromSymbol: #true.
tfalse = tokenFromSymbol: #false.
null = tokenFromSymbol: #null.

value = string | number | object | array | ttrue | tfalse | null.

|
)
...




For more information on the how this library works, check the Executable Grammars in Newspeak paper.


AST construction



We need to define a way to represent the tree structure(AST) parsed by JSONGrammar. As described in the "Executable Grammars is Newspeak" paper, one of the nice things about Newspeak is that we don't have the modify the grammar definition to add AST construction code. We can do that by inheriting from the original grammar:


class JSONGrammarWithAST = JSONGrammar(
"Parses a JSON File and generates and Ast"
|

|
)
('as yet unclassified'
array = (
^super array wrapper: [:a | (a token at: 2) ].
)


null = (
^ super null wrapper: [:o | nil].
)

number = (
^super number wrapper: [:o | Number readFrom: (flattenCharCollectionToString: (o token)) ].
)

object = (
^super object wrapper:
[:obj | JSONObject withContent:
(Dictionary newFrom: ((obj token at: 2) collect: [:e | (e at: 1) -> (e at: 3)]))].
)

parse: input = (
^super value parse: input.
)

string = (
^super string wrapper:
[:t | flattenCollectedString: (t token at: 2)].
)

tfalse = (
^super tfalse wrapper: [:o | false].
)

ttrue = (
^super ttrue wrapper: [:o | true].
)

...
)


As shown here (omitting some method definitions) the arrays are converted to Ordered collections, the numbers,strings,booleans to its equivalents and JSON objects to instances of JSONObject(described below).

JSONObject



In order to make it easy to use a JSON object in Newspeak the JSONParser class was defined:


class JSONObject withContent: dContent = (
"Instances of this class represent JSON objects."
|
content = dContent.
|
)
('as yet unclassified'
doesNotUnderstand: message = (
| fieldName |
fieldName:: message selector string.
(fieldName beginsWith: 'json_')
ifTrue: [fieldName:: fieldName allButFirst: 5].
^content at: fieldName ifAbsent: [nil].
)

)


This class receives a Dicionary as parameter. This dictionary contains all the name/value pairs of the JSON object definition. We create a definition of the doesNotUnderstand method which as in Smalltalk is called when a message sent to an object doesn't have a explicit way to respond it. We take the name of the message being called and check it against the dictionary.

If the message is prefixed by 'json_', the string after it is used as the key in the dictionary. This is defined this way because JSONObject has definitions inherited from Object (such as 'name').


...
| parsed |
parsed:: parserWithAST
parse: (streamFromString: '[{ "name": "Wiston Smith",
"description" :"Protagonist"},
{ "name": "Julia",
"description" :"Lover"},
{ "name": "O Brien",
"description" :"Goverment agent"}]'
).
assert:[((parsed at: 2) description) = 'Lover'].
assert:[((parsed at: 3) json_name) = 'O Brien'].




In the following post I'm going to use this parser to explore the GUI library provided with Newspeak.

Code for this post can be found here.

Monday, February 4, 2008

Handling a call to a missing method in different languages, Part 1

This is the first of a two-part series of posts about the way different languages allow you to handle a call to method that doesn't exist. I'll try to implement a little example with each of these languages. For this part I'm going to show Ruby, Smalltalk, Groovy and Boo.

The doesNotUnderstand message


Although this feature is called by many names, the origin may be the doesNotUnderstand message of Smalltalk. From its Wikipedia entry:


When an object is sent a message that it does not implement, the virtual machine sends the object the doesNotUnderstand: message with a reification of the message as an argument. The message (another object, an instance of Message) contains the selector of the message and an Array of its arguments...


This mecanism could be used for many tasks, from debugging to creating proxies. A nice reflection on this is The Best of method_missing and also in the reflection section of Smalltalk Wikipedia entry.

One of the most interesting uses is in the implementation of Ruby on Rails's ActiveRecord. In Under the hood: ActiveRecord::Base.find there's a nice description on how the find_... method is implemented using method_missing.


The example


For these posts I'm going to implement a little example of two classes that provides access to a CSV file by using this mecanism. For example given that we have the following file called "cars.csv" (taken from here):


Year,Make,Model
1997,Ford,E350
2000,Mercury,Cougar


and another called "scores.csv"


Name,Age,Score
Luis,31,1.8
John,35,1.9
Paul,25,1.6


For simplicity we assume that not double quotes are used.

Given that the first row are the headers, we can use this class to have access to the data of each record using the name of the header as if it was a member of the class. For example:


cs = CsvFile.new("cars.csv")
ps = CsvFile.new("scores.csv")

cs.each do|c|
puts c.Model
end

ps.each do|p|
puts p.Name
end


The basic strategy to create the example is to create two classes CsvFile and CsvFileEntry. One to represent the file and the other to represent each entry.

In general, the contents of the file will be loaded as an list of lists. The headers will be loading in a dictionary associated with its position.


The languages


For these posts I tried to find programming languages that have direct support for this feature. For most of these programming languages, the presented snippet is my first program in it, so please let me know if I missed something.

Ruby

In Ruby the method_missing method provides this functionality.

The method signature is the following:


obj.method_missing( aSymbol [, *args ] ) -> anObject


In our little example the:


class CsvFileEntry
def initialize(headers,content)
@headers = headers
@content = content
end
def method_missing(method_name,*args)
if (@headers.has_key? method_name.to_s) then
return @content[@headers[method_name.to_s]]
else
raise "Method not found #{method_name}"
end
end
end


Implementation for the CsvFile class is the following(without the file loading code):


class CsvFile
attr_reader :headers
attr_reader :content
def initialize(filename)
@filename = filename
@headers = Hash.new
@content = []
...
end

def entries
return content.collect {|c| CsvFileEntry.new(@headers,c)}
end
end


In the implementation of method_missing, the method_name argument is converted to string and used to lookup the name of the requested field. The headers instance variable contains a Hash with the positions of each header and the contents variable contains the contents of the entry.

Now we can use these classes as follows:


f = CsvFile.new("testfile.csv")
cars = CsvFile.new("cars.csv")

f.entries.each { |e| puts "#{e.Name} #{e.Age}" }

f.entries.each do |e|
puts e.Name
end

print "-------\n"

cars.entries.each do |c|
puts c.Model
puts c.Year
end


Smalltalk

As described above, in Smalltalk we have to implement the doesNotUnderstand method. This method receives a an instance of the Message class . This class contains information about the requested method and arguments.

The implementation of the CsvFileEntry class looks like this:


Object subclass: #CsvFileEntry
instanceVariableNames: 'headers contents'
classVariableNames: ''
poolDictionaries: ''
category: 'Langexplr-Classes'!


doesNotUnderstand: aMessage
| index |
^(headers includesKey: aMessage selector)
ifTrue:
[index := headers at: (aMessage selector).
contents at: index.]
ifFalse: [super doesNotUnderstand: aMessage].



initializeWith: theContents headers: theHeaders
headers := theHeaders.
contents := theContents.
^self.


The implementation of the CsvFile class(without the file loading code) looks like this:


Object subclass: #CsvFile
instanceVariableNames: 'fileName contents headers'
classVariableNames: ''
poolDictionaries: ''
category: 'Langexplr-Classes'


getContents
^contents.


getEntries
^(contents collect:[:e | (CsvFileEntry new) initializeWith: e headers: headers ]).

initializeWithFileName: aFileName
...
^ self.


An example of a use of these classes is the following:


scores := CsvFile new initializeWithFileName: 'testfile.csv'.

cars := CsvFile new initializeWithFileName: 'cars.csv'.

cars getEntries do:
[:entry|
Transcript show: (entry Model)].

scores getEntries do:
[:entry|
Transcript show: (entry Name)] .


Groovy

Groovy provides this feature for methods and properties. A description of this mecanism can be found in Using methodMissing and propertyMissing
. A nice example of a use of this mecanism is the GORM's Domain Class Querying.

In Groovy we need to implement the def propertyMissing(String name) method or the def methodMissing(String name,args) to handle a property or method access. The following CsvFileEntry implementation uses overrides both methods to provide property access and getter method(getXXXXX) access.


public class CsvFileEntry {
private HashMap headers;
private String[] contents;

CsvFileEntry(HashMap headers,String[] contents) {
this.headers = headers;
this.contents = contents;
}
def propertyMissing(String name) {
if (headers[name] != null) {
return this.contents[this.headers[name]];
} else {
throw new RuntimeException("Property not found ${name}");
}
}
def methodMissing(String name,args) {
def getterNameResult = name =~ /get(.*$)/;
if (getterNameResult.matches() &&
headers[getterNameResult.group(1)] != null) {
return this.contents[this.headers[getterNameResult.group(1)]];
} else {
throw new RuntimeException("Method not found ${name}");
}
}
}


The implementation for the CsvFile class is the following(without the file loading part):


span class="srckeyw">public class CsvFile {
def HashMap headers;
def contents;

CsvFile(String fileName) {
...
}

def entries() {
def result = []
for ( c in contents) {
result.add(new CsvFileEntry(headers,c));
}
return result
}
}


A use of this code looks like this:


def scores = new CsvFile("testfile.csv")
def cars = new CsvFile("cars.csv")


for ( e in scores.entries() ) {
println("${e.Name} --> ${e.getAge()}")
}

for ( c in cars.entries()) {
println(c.getModel());
println(c.Year)
}


Boo

In Boo this functionality is available by implementing the IQuackFu interface. A nice explanation of this feature is available from: If it walks like a duck and it quacks like a duck . Also Dynamic Inheritance - fun with IQuackFu provides more information . A very nice example called XmlObject.boo (available from Boo source distribution) shows how IQuackFu is used to easy the access to Xml trees.

The IQuackFu interface contains the following members:

  • def QuackInvoke(name as string, args as (object)) as object: for method calls

  • def QuackGet(name as string) as object: for property access

  • def QuackSet(name as string, value) as object: for property assignment




Since Boo allowed handling both method and property access I created two ways to access the data: by using the name of the header as a property or a call to a method called GetXXXXX.

The CsvFileEntry implementation is the following:


class CsvEntry(IQuackFu):
content as (string)
headers as Hash
public virtual def constructor(aContent as (string),aHeaders as Hash):
content = aContent
headers = aHeaders

def QuackInvoke(name as string, args as (object)) as object:
r = /Get(?<name>.*$)/.Match(name)

if (r.Success and headers.ContainsKey(r.Groups["name"].Value)):
index = headers[r.Groups["name"].Value]
return content[index]
else:
raise InvalidOperationException("Method ${name} not found")


def QuackSet(name as string, value) as object:
pass

def QuackGet(name as string) as object:
if(headers.ContainsKey(name)):
index = headers[name]
return content[index]
else:
raise InvalidOperationException("Property ${name} not found")


The CsvFile implementation (without the file loading part) :


class CsvFile():
headers = {}
content = []
public virtual def constructor(fileName as string):
...

public def Entries():
for e as (string) in content:
yield CsvEntry(e,headers)



A use of this class:


csvF = CsvFile("testfile.csv")
cars = CsvFile("cars.csv")


for e in csvF.Entries():
print e.Name


for c in cars.Entries():
print c.GetModel()



Code for this post can be found here.

For the next post the Python, Objective-C, Haxe, ActionScript and Perl examples will be presented.

Tuesday, January 29, 2008

First Smalltalk experiences

Experimenting with a new programming language is always a nice experience. While preparing some snippets for a future post, I took some time to learn a little bit about Smalltalk. In this post I'm going to show a couple of this that caught my attention about the environment.

There's a lot of tutorials that available. The ones I use: Smalltalk Overview, Basic Aspects of Squeak and the Smalltalk-80 Programming Language, Objects, Classes, and Constructors, Smalltalk Style and Smalltalk collections. The Smalltalk implementation I downloaded was Squeak.

As a friend of mine once told me, one (of the many) nice things about Smalltalk is the way it handles the source code. No explicit files are used to store the code. It seems that the source of program and the IDE you are working on is part of the running program itself(!).

The System Browser is a key part of the Smalltalk environment. There you can explore existing class definitions and add or modify classes.



Another interesting element of the environment is a section called Workspace, where you can write some code to test the functionality you just implemented. For example I implemented a class that loads the contents of a CSV file. Here I'm creating an instance of this class, and I'm going to inspect its contents.



By calling the inspect method the inspect window let you explore the members of the instance.




Another interesting thing is that the environment itself helps you to write a correct program. For example in the definition of the following method I forgot to the declare the headers instance field. When trying to save the modifications the environment tells me that the headers variable is not declared and ask me if I want it to be declared as a local variable or as a instance variable.



The environment also inform you when a local variable is not used. For example when trying to save the following code:



The environment tells me:




This "live" programming environment is pretty nice. It seems that the Smalltalk environment was/is a strong inspiration for IDEs for other languages.