Planet Squeak

blogs about Squeak, Pharo, Croquet and family
planet squeak - planet squeak es - planet squeak jp - planet croquet - planet squeak code - planet smalltalk

January 23, 2020

Pierce Ng

Embedding Pharo in Pascal HOWTO - Linux

Pharo headless VM

First, build the Pharo headless VM, following the instructions in its README. When done, the VM files are in build/vm.

Pharo application image

Next, prepare the Pharo application image. Basically, start from a fresh Pharo 8.0 image and load the EmbeddedSupport code from Pablo's repository. The following snippet works, assuming you have cloned Pablo's repository locally; adjust the gitlocal path in the snippet, of course.

Metacello new
    baseline: 'EmbeddedSupport';
    repository: 'gitlocal:///home/pierce/src/st/pharo-vm-embedded-example/smalltalk-src';
    load.

NoChangesLog install.
NoPharoFilesOpener install.
PharoCommandLineHandler forcePreferencesOmission: true.

SmalltalkImage current snapshot: true andQuit: true

Windows resource

Then, embed the Pharo application image into a Windows resource file.

Here's a simplified version of resources.rc. This assumes you have named the image to be embedded Pharo.image.

300 RCDATA "Pharo.image"

Building a Windows resource file on Linux requires windres. On Ubuntu, this program is part of the package binutils-mingw-w64-x86-64.

Place the application Pharo.image and resources.rc in the same directory. Then,

% /usr/bin/x86_64-w64-mingw32-windres -i resources.rc -o resources.res
% ls -l
total 113488
-rw-r--r-- 2 pierce pierce 58098672 Jan 23 14:10 Pharo.image
-rw-r--r-- 2 pierce pierce       25 Jan 23 14:01 resources.rc
-rw-r--r-- 2 pierce pierce 58098736 Jan 23 14:10 resources.res

The output resources.res is the compiled resources file.

Pascal host program

Finally we are ready to build the Pascal host program. Move resources.res to this repository's embedded-cli directory. Also create a link to libPharoVMCore.so or make a copy of it. The directory's content is now as follows:

% ls -l
total 58736
-rwxr-xr-x 2 pierce pierce  3344760 Jan 23 09:26 libPharoVMCore.so*
-rw-r--r-- 2 pierce pierce 58098736 Jan 23 14:10 resources.res
-rw-r--r-- 4 pierce pierce     1945 Jan 23 12:55 runPharoEmbedded.pas
-rw-r--r-- 4 pierce pierce     3824 Jan 23 12:54 ulibEmbeddedImage.pas
-rw-r--r-- 5 pierce pierce     1045 Jan 22 15:42 ulibPharoVM.pas

At the start of runPharoEmbedded.pas, the line {$R resources.res} is the Pascal compiler directive to incorporate resources.res into the executable that is being built:

program runPharoEmbedded;

{$mode objfpc}{$H+}
{$R resources.res} { <= compiler directive to incorporate resources.res }
{$linklib m}

Build the host program - the Pascal compiler is its own make system and knows to compile the necessary source files. (The Pascal compiler also knows how to invoke windres to compile resources.rc into resources.res when so configured. I've done that part by hand since this is a HOWTO.)

% fpc runPharoEmbedded.pas
Free Pascal Compiler version 3.0.4 [2018/10/29] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling runPharoEmbedded.pas
Compiling ulibPharoVM.pas
Compiling ulibEmbeddedImage.pas
Compiling resource runPharoEmbedded.or
Linking runPharoEmbedded
/usr/bin/ld: warning: link.res contains output sections; did you forget -T?
232 lines compiled, 0.4 sec

% ls -l runPharoEmbedded
-rwxr-xr-x 1 pierce pierce 58884328 Jan 23 14:22 runPharoEmbedded*

Much of the size of the executable is due to the embedded Pharo.image.

We'll run runPharoEmbedded in the headless VM build directory because Pharo's baked-in library lookup currently requires this. (More on this in a later post.) So move the program over.

% mv runPharoEmbedded ~/src/st/opensmalltalk-vm-pharo/build/vm
% cd ~/src/st/opensmalltalk-vm-pharo/build/vm
% ls -T 30
libB2DPlugin.so*             libgit2.so.0.25.1             libSDL2-2.0.so.0*      libssl.so*
libBitBltPlugin.so*          libgit2.so.25                 libSDL2-2.0.so.0.7.0*  libssl.so.1.0.0*
libcrypto.so.1.0.0*          libIA32ABI.so*                libSDL2.so*            libSurfacePlugin.so*
libDSAPrims.so*              libJPEGReaderPlugin.so*       libSecurityPlugin.so*  libTestLibrary.so*
libffi.so*                   libJPEGReadWriter2Plugin.so*  libSocketPlugin.so*    libUnixOSProcessPlugin.so*
libffi.so.7*                 libLargeIntegers.so*          libSqueakFFIPrims.so*  libUUIDPlugin.so*
libffi.so.7.1.0*             libLocalePlugin.so*           libSqueakSSL.so*       pharo*
libFileAttributesPlugin.so*  libMiscPrimitivePlugin.so*    libssh2.so*            runPharoEmbedded*
libFilePlugin.so*            libPharoVMCore.so*            libssh2.so.1*
libgit2.so                   libPThreadedPlugin.so*        libssh2.so.1.0.1*

Set up LD_LIBRARY_PATH. The first path segment is for the Pharo VM. The second is for libcairo2.so needed by the embedded Pharo.image - on Ubuntu, it lives in /usr/lib/x86_64-linux-gnu, which isn't in Pharo 8's current hardcoded lookup path. Then run the executable:

% export LD_LIBRARY_PATH=`pwd`:/usr/lib/x86_64-linux-gnu
% uname -a
Linux Otrus 4.15.0-74-generic #84-Ubuntu SMP Thu Dec 19 08:06:28 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
% ./runPharoEmbedded
lala

runPharoEmbedded

Ta da! "lala" is printed by Pharo.

by Pierce Ng at January 23, 2020 02:40 PM

Program in Objects

Extending the Smalltalk Syntax 2

by Leandro Caniglia
President of FAST (Fundación Argentina de Smalltalk)

Story 2: Supporting Pragmas

All Smalltalk dialects support pragmas. Here is one:

identityHash
  <primitive: Hash>
  ^0

However, not all of them support other types of pragmas, as Pharo does. So, let’s see what it would take to add support for them to our dialect.

Where to start? Here is the roadmap:

  1. Find the Smalltalk Parser in your system
  2. In the Smalltalk Parser find the place where primitives are parsed
  3. Modify the code that parses primitive declarations to recognize pragmas as well
  4. Find a place in the CompiledMethod to store the pragma annotation

Now let’s see some hints on how to accomplish the tasks above:

Task 1: Find the Smalltalk Parser


Look for selectors like parse, parse:, parseMethod:, parseLiteral:, etc. In some dialects the entry point to parsing services is the Compiler, so you can debug the initial steps required to compile any expression until you reach the parser. You can also check to see if there are implementors of parserClass.

Task 2: Find the parsing of primitive declarations


This is best accomplished by debugging the compilation of any method with a primitive declaration. Just create a primitive method and debug its compilation. After some few clicks you should get to the parser method that distinguishes it as primitive.

Task 3: Parse the pragma


For this task I would recommend starting simple. There will be time for further sophistication. In this case “simple” means: assume the pragma is just one token. Much like:

methodWithPragma
  <ourPragma>
  self doSomething; etc.

The existing code in the parser should complain if the token that comes after $< is not 'primitive:' (or friends). And this is precisely where we need to branch, save the token as our pragma and (in this first attempt) save it in the MethodNode. Note that there is no need to add a new ivar to MethodNode, we can save the token in the same ivar where primitives are held. After all, primitives are numbers while pragmas are not, so we will be able to distinguish between them.

Don’t forget to consume the closing $>, which should be the next token. Otherwise issue a parsing error.

Task 4: Save the pragma in the method


This step is actually not required as we could always resort to the AST for getting the pragma. One could argue that it would be too slow to parse the entire method every time we want to access its pragma, should it have any. However, since pragmas occur before any other statements, there is no need to build the entire AST. In fact, we would only need a service in the parser that will stop parsing right before the parsing of the method sentences starts.

However, if you insist on avoiding any parsing, when a new CompiledMethod is compiled, the MethodNode should somehow inject the pragma in it. One way to do this is to add the pragma as the first literal. A practice also known as stealing literals. However, if we steal the first literal, how are we going to tell whether this first literal is a pragma or not?

There might be several tricks for solving this. For instance, in most dialects 0 (the SmallInteger) is never saved in the literal frame. The reason is that there are special bytecodes to operate with it, so the constant 0 doesn’t need to go into the literal frame.

Therefore, we could add the pragma as the first literal, and then add 0 as the second. Thus, in order to check and retrieve the pragma of a method we would do the following:

CompiledMethod >> pragma
  literals := self literals.
  ^(literals size >= 2 and: [(literals at: 2) = 0])
    ifTrue: [literals at: 1]

Note that the method will answer with nil if it has no pragma.

Final words


To make sure that 0 doesn’t go to the literal frame in your dialect, evaluate the following:

CompiledMethod allInstances select: [:cm | cm literals includes: 0]

It should answer with an empty array. If not, you will need to find another trick (hint: add two 0s instead of one.)

The simple case I’ve depicted here is for adding support to unary pragmas. You might want to allow for binary and keyword pragmas as well. The idea is the same. Just keep reading more tokens in Task 3, until $> is reached. Take a look at how Pharo does this for inspiration, starting at RBParser >> parsePragma. Then adapt the idea to your case.

If you decide to add support for multiple pragmas, note that you will need to steal n + 1 literals rather than 2 as we did in Task 4. You only need to move the 0 right after the last injection in the literal frame.

by smalltalkrenaissance at January 23, 2020 11:45 AM

PharoWeekly

[ANN] SmalltalkCI now supports Pharo 9

Hi,
Just to let you know that smalltalkCI was updated to include Pharo 9, 32 and 64 bits as available versions to be used, and stable/alpha were updated to be Pharo 8 and Pharo 9.
Thanks Pablo Tesone & Fabio Niephaus for helping in getting this updates ready.
Regards,
Gabriel

by Stéphane Ducasse at January 23, 2020 07:54 AM

January 22, 2020

Pierce Ng

Cross Platform Embedded Pharo

Recently Pablo Tesone published an example of embedding a Pharo image as a Windows resource inside a program written in C.

Well, the excellent and, like Smalltalk, vastly underrated Free Pascal programming system has cross-platform support for handling Windows resources. With it, I have reimplemented Pablo's example: One source code building executables that run on Ubuntu 18.04 and MacOS Mojave. Not tested on Windows yet, but I'm sure it'll work there too. The three Pascal source files, including blank lines and comments, total 209 lines:

Repository on GH. More details to come.

by Pierce Ng at January 22, 2020 07:32 PM

PharoWeekly

[Ann] Pharo embedded in Pascal :)

Hi all,

Inspired by Pablo’s example, I’ve created a cross-platform
implemenation. Pablo’s example uses Pharo.image embedded as a Windows
resource. Well, the  excellent and, like Smalltalk, vastly underrated
Free Pascal has built-in cross platform support for Windows resources.
Basically I have implemented, in Pascal, FFI to libPharoVMCore and the
embedded image access routines for callback by libPharoVMCore, together
with a driver program to run the embedded Pharo.image.

Repository is here:

https://github.com/PierceNg/pharo-vm-embedded-pascal

More details to come in the repository.

Pierce

by Stéphane Ducasse at January 22, 2020 12:32 PM

January 21, 2020

PharoWeekly

[ann] Neat for Pharo

Today is the official release of the NEAT algorithm for Pharo
🙂

by Stéphane Ducasse at January 21, 2020 08:51 PM

Take the survey!

Hi all,
We would like to share with you a short survey about the automatic deprecation rewrites that have been around since Pharo 6.
It will be super useful for us to enhance the support for migrations.
We estimate it will take ~< 3 minutes to fill.
This survey is aimed at people both *using* Pharo, or writing libraries and frameworks for Pharo.
If you’re a library/framework maintainer and you know people using your library, would you mind share it with them?
Link to the survey: https://sondages.inria.fr/index.php/133442?lang=en
Thanks a lot!
Guille, in behalf of the Pharo consortium

by Stéphane Ducasse at January 21, 2020 08:13 PM

January 20, 2020

PharoWeekly

Setting up a Pharo project on Github

Hello,

I recorded myself setting up a Pharo project on Github this afternoon.

https://www.youtube.com/watch?v=Wnt3OBhR18I

The video shows how to:

– Create git repository on Github, make Pharo be aware of it via Iceberg

– Set-up the CI

– Add CI badge and install script to your README (which we should all do systematically… 🙂 ).

This can be useful for newcomers.

Cheers,

Julien

by Stéphane Ducasse at January 20, 2020 09:23 PM

Program in Objects

Extending the Smalltalk Syntax

by Leandro Caniglia
President of FAST (Fundación Argentina de Smalltalk)

Story 1: Adding Squeak Braces

Does your dialect support Squeak Braces? To answer this question, try to evaluate the following expression:

{Date today. 3 + 4}

If you get an Array with the above two elements, today’s date and 7, it does. Otherwise, you would get a compilation error. In the latter case, you might be interested in extending the syntax of your dialect so to have what I call Squeak Braces.

Where to start? Here is the roadmap:

  1. Find the hierarchy of classes that model parse tree nodes.
  2. Add a new class for modeling brace arrays (let’s call it BraceNode or ArrayNode).
  3. Add an ivar to the class for holding the elements of the array (let’s call it elements).
  4. Add a method to the class for transforming the elements into a cascade node (see below).
  5. Add all other required methods that nodes need to implement, especially those that message nodes have.

Now let’s see some hints on how to accomplish the tasks above:

Task 1: Finding the AST hierarchy


The Abstract Syntax Tree (a.k.a. AST) is the object that models the decomposition of a piece of source code into its constituents. This typically includes nodes for both the whole method and also its parts: literals, blocks, variables, etc. Therefore I would start by trying to find a class that includes Literal or LiteralNode in its name. From this class, go to the top of the hierarchy and you will get the complete picture of the place where you will be working next.

Task 2: Adding the new class


It’s simple, just subclass from the root of the AST hierarchy a new class appropriately named, say, BraceNode.

Task 3: Adding the required ivars


For sure we will need an ivar to keep the elements of the array. So, add the elements ivar. We will likely add one more ivar later though.

Task 4: Transforming the node into a cascade node


The idea here is to add a new method, say asCascadeNode, whose job is to answer with the CascadeNode that results from the expression:

(Array with: n)
  at: 1 put: (elements at: 1);
  …;
  at: n put: (elements at: 2);
  yourself

where n is elements size. To do this, you need to find the CascadeNode in the AST hierarchy and become familiar with it so you can create one instance of it for the method to return.

Task 5: Add other required methods


Typically, AST nodes implement the acceptVisitor: message for supporting the Visitor pattern’s double dispatching mechanism. It’s implemenation is straightforward:

acceptVisitor: aVisitor
  aVisitor acceptBraceNode: self

You also need to find all visitors that you will need to enhance. To discover them look for implementors of visiting messages in the AST hierarchy such as visitCascadeNode:, etc. Writing each of the required implementor of visitCascadeNode: is also straightforward:

visitBraceNode: aBraceNode
  self visitCascadeNode: aBraceNode asCascadeNode

For other messages, take inspiration from the other nodes, especially, from CascadeNode.

Improvements


Once you have all of this complete and tested, you may want to improve your implementation a little bit. For instance, some occurrences of these Squeak Braces are just literals. One example would be:

{3. $a. {'hello' 'world'}}

This is actually equivalent to:

#(3. $a. #('hello' 'world'))

However, our implementation would work as well if we had written:

(Array new: 3)
  at: 1 put: 3;
  at: 2 put: $a;
  at: 3 put: (
    (Array new: 2)
      at: 1 put: 'hello';
      at: 2 put: 'world';
      yourself);
  yourself

which sends 9 messages instead of none! To avoid this waste, what we can do is to give literal arrays a special treatment. Here is how:

Task 6


At the top of the AST hierarchy, add the method isLiteral returning false (this might or might not be there already). Now repeat the same for LiteralNode except that this time answer with true.
Finally, add the isLiteral method to BraceNode on the lines of:

isLiteral
   ^elements conform: [:e | e isLiteral]

given that the elements of our BraceNode are themselves instances of AST nodes, this closes the circle.

Task 7


Next, add the asLiteralNode method to BraceNode on the lines of:

asLiteralNode
  ^LiteralNode new
    value: self literal;
    start: self start;
    stop: self stop

So, the only piece that is missing is the literal message. Here it is:

literal
  ^elements collect: [:e | e literal]

where

LiteralNode >> #literal
  ^self value

Task 8


Finally, modify your implementations of visitBraceNode: method like this:

visitBraceNode: aBraceNode
  aBraceNode isLiteral
    ifTrue: [self visitLiteralNode: aBraceNode asLiteralNode]
    ifFalse: [self visitCascadenode: aBraceNode asCascadNode]

Depending on the internals of your system, some additional tweaks might be required. Just make sure your testing coverage is high enough. I almost forgot! In Task 3, I said that we would likely add another ivar to BraceNode, remember? Well, I was thinking in a cache for the result of asCascadeNode or asLiteralNode, depending on the case. This will help to preserve the identity of the BraceNode substitute should the translation be required more than once. No need to do this in advance though. Just keep it in mind.

by smalltalkrenaissance at January 20, 2020 05:28 AM

January 19, 2020

Program in Objects

A Look Ahead to Programming Languages in 2020

Python and JavaScript are the two hottest programming languages today. However, they cannot remain on top forever. Eventually, they must fall out of favour, as all languages do. This is likely to happen within the next decade or so. What languages might come to replace them? Here’s my list of challengers…

Dart

Thanks to the Flutter framework and Google’s imprimatur, this language has quickly risen in popularity. It’s similar to the same driving force that made Ruby so popular: the Rails framework. And if Google’s Fuchsia takes off, Dart will be in the centre of it.

Key advantage: it’s a much better language than JavaScript.

Key disadvantage: it’s up against JavaScript and its deluded hordes.

Mandelbrot set sample:

class Complex {
  double _r,_i;
 
  Complex(this._r,this._i);
  double get r => _r;
  double get i => _i;
  String toString() => "($r,$i)";
 
  Complex operator +(Complex other) => new Complex(r+other.r,i+other.i);
  Complex operator *(Complex other) =>
      new Complex(r*other.r-i*other.i,r*other.i+other.r*i);
  double abs() => r*r+i*i;
}
 
void main() {
  double start_x=-1.5;
  double start_y=-1.0;
  double step_x=0.03;
  double step_y=0.1;
 
  for(int y=0;y<20;y++) {
    String line="";
    for(int x=0;x<70;x++) {
      Complex c=new Complex(start_x+step_x*x,start_y+step_y*y);
      Complex z=new Complex(0.0, 0.0);
      for(int i=0;i<100;i++) {
        z=z*(z)+c;
        if(z.abs()>2) {
          break;
        }
      }
      line+=z.abs()>2 ? " " : "*";
    }
    print(line);
  }
}

Elixir

Elixir is an Erlang-derivative with an improved syntax and the same, amazing support for concurrency. As a pure functional language, it has a good likelihood of elevating this paradigm into the mainstream.

Key advantage: it makes functional programming exceptionally easy. And it’s great for concurrency.

Key disadvantage: you need to understand the underlying OTP foundation which can be a daunting task.

Mandelbrot set sample:

defmodule Mandelbrot do
  def set do
    xsize = 59
    ysize = 21
    minIm = -1.0
    maxIm = 1.0
    minRe = -2.0
    maxRe = 1.0
    stepX = (maxRe - minRe) / xsize
    stepY = (maxIm - minIm) / ysize
    Enum.each(0..ysize, fn y ->
      im = minIm + stepY * y
      Enum.map(0..xsize, fn x ->
        re = minRe + stepX * x
        62 - loop(0, re, im, re, im, re*re+im*im)
      end) |> IO.puts
    end)
  end
 
  defp loop(n, _, _, _, _, _) when n>=30, do: n
  defp loop(n, _, _, _, _, v) when v>4.0, do: n-1
  defp loop(n, re, im, zr, zi, _) do
    a = zr * zr
    b = zi * zi
    loop(n+1, re, im, a-b+re, 2*zr*zi+im, a+b)
  end
end
 
Mandelbrot.set

Golang

Another Google-supported language, Golang has proven to be winner, thanks to its lightning-quick compilation speed, easy and efficient concurrency, and remarkable simplicity. The only thing missing is generics, and this feature is on the roadmap.

Key advantage: it’s super-simple, and great for concurrency.

Key disadvantage: it lacks generics (for now).

Mandelbrot set sample:

package main
 
import (
    "fmt"
    "image"
    "image/color"
    "image/draw"
    "image/png"
    "math/cmplx"
    "os"
)
 
const (
    maxEsc = 100
    rMin   = -2.
    rMax   = .5
    iMin   = -1.
    iMax   = 1.
    width  = 750
    red    = 230
    green  = 235
    blue   = 255
)
 
func mandelbrot(a complex128) float64 {
    i := 0
    for z := a; cmplx.Abs(z) < 2 && i < maxEsc; i++ {
        z = z*z + a
    }
    return float64(maxEsc-i) / maxEsc
}
 
func main() {
    scale := width / (rMax - rMin)
    height := int(scale * (iMax - iMin))
    bounds := image.Rect(0, 0, width, height)
    b := image.NewNRGBA(bounds)
    draw.Draw(b, bounds, image.NewUniform(color.Black), image.ZP, draw.Src)
    for x := 0; x < width; x++ {
        for y := 0; y < height; y++ {
            fEsc := mandelbrot(complex(
                float64(x)/scale+rMin,
                float64(y)/scale+iMin))
            b.Set(x, y, color.NRGBA{uint8(red * fEsc),
                uint8(green * fEsc), uint8(blue * fEsc), 255})
 
        }
    }
    f, err := os.Create("mandelbrot.png")
    if err != nil {
        fmt.Println(err)
        return
    }
    if err = png.Encode(f, b); err != nil {
        fmt.Println(err)
    }
    if err = f.Close(); err != nil {
        fmt.Println(err)
    }
}

Julia

Julia’s strength is its excellent support for mathematical computation. The math-friendly syntax is great for data scientists. If any language can overthrow Python, this one is definitely a contender.

Key advantage: it’s well-designed for scientists.

Key disadvantage: it’s up against Python, the king of data science.

Mandelbrot set sample:

using Images
 
@inline function hsv2rgb(h, s, v)
    const c = v * s
    const x = c * (1 - abs(((h/60) % 2) - 1))
    const m = v - c
 
    const r,g,b =
        if h < 60
            (c, x, 0)
        elseif h < 120
            (x, c, 0)
        elseif h < 180
            (0, c, x)
        elseif h < 240
            (0, x, c)
        elseif h < 300
            (x, 0, c)
        else
            (c, 0, x)
        end
 
    (r + m), (b + m), (g + m)
end
 
function mandelbrot()
 
    const w, h = 1000, 1000
 
    const zoom  = 0.5
    const moveX = 0
    const moveY = 0
 
    const img = Array{RGB{Float64}}(h, w)
    const maxIter = 30
 
    for x in 1:w
        for y in 1:h
            i = maxIter
            const c = Complex(
                (2*x - w) / (w * zoom) + moveX,
                (2*y - h) / (h * zoom) + moveY
            )
            z = c
            while abs(z) < 2 && (i -= 1) > 0
                z = z^2 + c
            end
            const r,g,b = hsv2rgb(i / maxIter * 360, 1, i / maxIter)
            img[y,x] = RGB{Float64}(r, g, b)
        end
    end
 
    save("mandelbrot_set.png", img)
end
 
mandelbrot()

Kotlin

Kotlin is the better Java. In fact, it’s practically a drop-in replacement for Java. Google have already made it a first-class language for Android development.

Key advantage: it’s a souped-up Java.

Key disadvantage: it’s a very large language, even compared to Java.

Mandelbrot set sample:

import java.awt.Graphics
import java.awt.image.BufferedImage
import javax.swing.JFrame
 
class Mandelbrot: JFrame("Mandelbrot Set") {
    companion object {
        private const val MAX_ITER = 570
        private const val ZOOM = 150.0
    }
 
    private val img: BufferedImage
 
    init {
        setBounds(100, 100, 800, 600)
        isResizable = false
        defaultCloseOperation = EXIT_ON_CLOSE
        img = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
        for (y in 0 until height) {
            for (x in 0 until width) {
                var zx = 0.0
                var zy = 0.0
                val cX = (x - 400) / ZOOM
                val cY = (y - 300) / ZOOM
                var iter = MAX_ITER
                while (zx * zx + zy * zy < 4.0 && iter > 0) {
                    val tmp = zx * zx - zy * zy + cX
                    zy = 2.0 * zx * zy + cY
                    zx = tmp
                    iter--
                }
                img.setRGB(x, y, iter or (iter shl 7))
            }
        }
    }
 
    override fun paint(g: Graphics) {
        g.drawImage(img, 0, 0, this)
    }
}
 
fun main(args: Array<String>) {
    Mandelbrot().isVisible = true
}

Lua

Key advantage: Lua is a small, simple, fast, embeddable, portable, and flexible language.

Key disadvantage: it has been overlooked for 26 years. What’s going to change now?

Mandelbrot set sample:

local maxIterations = 250
local minX, maxX, minY, maxY = -2.5, 2.5, -2.5, 2.5
local miX, mxX, miY, mxY
function remap( x, t1, t2, s1, s2 )
    local f = ( x - t1 ) / ( t2 - t1 )
    local g = f * ( s2 - s1 ) + s1
    return g;
end
function drawMandelbrot()
    local pts, a, as, za, b, bs, zb, cnt, clr = {}
    for j = 0, hei - 1 do
        for i = 0, wid - 1 do
            a = remap( i, 0, wid, minX, maxX )
            b = remap( j, 0, hei, minY, maxY )
            cnt = 0; za = a; zb = b
            while( cnt < maxIterations ) do
                as = a * a - b * b; bs = 2 * a * b
                a = za + as; b = zb + bs
                if math.abs( a ) + math.abs( b ) > 16 then break end
                cnt = cnt + 1
            end
            if cnt == maxIterations then clr = 0
            else clr = remap( cnt, 0, maxIterations, 0, 255 )
            end
            pts[1] = { i, j, clr, clr, 0, 255 }
            love.graphics.points( pts )
        end
    end
end
function startFractal()
    love.graphics.setCanvas( canvas ); love.graphics.clear()
    love.graphics.setColor( 255, 255, 255 )
    drawMandelbrot(); love.graphics.setCanvas()
end
function love.load()
    wid, hei = love.graphics.getWidth(), love.graphics.getHeight()
    canvas = love.graphics.newCanvas( wid, hei )
    startFractal()
end
function love.mousepressed( x, y, button, istouch )
    if button ==  1 then
        startDrag = true; miX = x; miY = y
    else
        minX = -2.5; maxX = 2.5; minY = minX; maxY = maxX
        startFractal()
        startDrag = false
    end
end
function love.mousereleased( x, y, button, istouch )
    if startDrag then
        local l
        if x > miX then mxX = x
        else l = x; mxX = miX; miX = l
        end
        if y > miY then mxY = y
        else l = y; mxY = miY; miY = l
        end
        miX = remap( miX, 0, wid, minX, maxX ) 
        mxX = remap( mxX, 0, wid, minX, maxX )
        miY = remap( miY, 0, hei, minY, maxY ) 
        mxY = remap( mxY, 0, hei, minY, maxY )
        minX = miX; maxX = mxX; minY = miY; maxY = mxY
        startFractal()
    end
end
function love.draw()
    love.graphics.draw( canvas )
end

Pharo

Pharo is a modern variant of Smalltalk, a remarkably productive object-oriented language. In fact, Smalltalk is the paragon of OOP and has inspired nearly every other OOP language on the planet. In the end, no language does OOP better than Smalltalk.

Pharo is also one of the simplest, most elegant languages in the world. You can actually learn the entire syntax of Smalltalk within 15 minutes!

Key advantage: it’s super-productive, like 5X more productive!

Key disadvantage: it requires a different programming mindset. People are afraid of change.

Fractal tree sample (based on Squeak):

Object subclass: #FractalTree
    instanceVariableNames: ''
    classVariableNames: ''
    poolDictionaries: ''
    category: 'RosettaCode'

"Methods for FractalTree class"

tree: aPoint length: aLength angle: anAngle
    | p a |
 
    (aLength > 10) ifTrue: [
        p := Pen new.
        p up.
        p goto: aPoint.
        p turn: anAngle.
        p down.
        5 timesRepeat: [
            p go: aLength / 5.
            p turn: 5.
        ].
        a := anAngle - 30.
        3 timesRepeat: [
            self tree: p location length: aLength * 0.7 angle: a.
            a := a + 30.
        ]
    ].
 
draw
    Display restoreAfter: [
        Display fillWhite.      
        self tree: 700@700 length: 200 angle: 0.
    ]

"Execute"

FractalTree new draw.

Rust

Rust has gained recognition for its memory safety feature: the borrow checker. This feature practically eliminates the entire class of memory-related programming errors. Rust promises much safer programming.

Key advantage: it helps make software much more reliable.

Key disadvantage: it’s tough to learn, and the borrow checker can be complicated to understand.

Mandelbrot set sample:

extern crate image;
extern crate num_complex;
 
use std::fs::File;
use num_complex::Complex;
 
fn main() {
    let max_iterations = 256u16;
    let img_side = 800u32;
    let cxmin = -2f32;
    let cxmax = 1f32;
    let cymin = -1.5f32;
    let cymax = 1.5f32;
    let scalex = (cxmax - cxmin) / img_side as f32;
    let scaley = (cymax - cymin) / img_side as f32;
 
    // Create a new ImgBuf
    let mut imgbuf = image::ImageBuffer::new(img_side, img_side);
 
    // Calculate for each pixel
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let cx = cxmin + x as f32 * scalex;
        let cy = cymin + y as f32 * scaley;
 
        let c = Complex::new(cx, cy);
        let mut z = Complex::new(0f32, 0f32);
 
        let mut i = 0;
        for t in 0..max_iterations {
            if z.norm() > 2.0 {
                break;
            }
            z = z * z + c;
            i = t;
        }
 
        *pixel = image::Luma([i as u8]);
    }
 
    // Save image
    let fout = &mut File::create("fractal.png").unwrap();
    image::ImageLuma8(imgbuf).save(fout, image::PNG).unwrap();
}

TypeScript

TypeScript is JavaScript…with benefits. It primarily adds static typing. Compatibility with JavaScript makes it a favourite of front-end web developers because they already know JavaScript and they hardly need to alter their workflow.

Key advantage: it’s JavaScript, so there’s no big change for JavaScript developers.

Key disadvantage: it’s still JavaScript, so you inherit all of its baggage.

Fractal tree sample:

// Set up canvas for drawing
var canvas: HTMLCanvasElement = document.createElement('canvas')
canvas.width = 600
canvas.height = 500
document.body.appendChild(canvas)
var ctx: CanvasRenderingContext2D = canvas.getContext('2d')
ctx.fillStyle = '#000'
ctx.lineWidth = 1
 
// constants
const degToRad: number = Math.PI / 180.0
const totalDepth: number = 9
 
/** Helper function that draws a line on the canvas */
function drawLine(x1: number, y1: number, x2: number, y2: number): void {
    ctx.moveTo(x1, y1)
    ctx.lineTo(x2, y2)
}
 
/** Draws a branch at the given point and angle and then calls itself twice */
function drawTree(x1: number, y1: number, angle: number, depth: number): void {
    if (depth !== 0) {
        let x2: number = x1 + (Math.cos(angle * degToRad) * depth * 10.0)
        let y2: number = y1 + (Math.sin(angle * degToRad) * depth * 10.0)
        drawLine(x1, y1, x2, y2)
        drawTree(x2, y2, angle - 20, depth - 1)
        drawTree(x2, y2, angle + 20, depth - 1)
    }
}
 
// actual drawing of tree
ctx.beginPath()
drawTree(300, 500, -90, totalDepth)
ctx.closePath()
ctx.stroke()

WebAssembly

WebAssembly is a dark horse. In the next decade or so, it could possibly spawn a number of languages that rise to the top. WebAssembly is only a compilation target, but there’s no reason it couldn’t spread far beyond the web domain. What WebAssembly-based language(s) could rise to the top? It’s anybody’s guess.

(Previously published at Hacker Noon.)

by smalltalkrenaissance at January 19, 2020 10:01 PM

PharoWeekly

[Ann] New stable VM available

The VM is available through zeroConf.
Doing for example:

wget -O – get.pharo.org/64/80+vmLatest | bash

Cheers,
Pablo

by Stéphane Ducasse at January 19, 2020 07:00 PM

[Ann] New version of Pharo with Style

Hello

I updated Pharo with Style to include more mistakes to learn from and discussion about object initialization.

If you have feedback, please send them.

S.

by Stéphane Ducasse at January 19, 2020 03:09 PM

Program in Objects

How is Smalltalk’s revival like the e-car’s revival?

It’s not a riddle. I’ll give you the answer.

There are several interesting parallels between the evolution of the electric car and the evolution of Smalltalk. Let’s look at e-cars first.

E-cars were pioneered in the 1830s. By 1900, they had reached their peak of popularity with a third of all cars manufactured in the United States being electric.

By 1920, the maturity and popularity of the internal combustion engine had made e-cars no longer viable. So e-cars faded away.

By the 1960s, however, rising gas prices and concerns over pollution caused people to re-examine the electric car. But it would be another three decades before the Toyota Prius made electric viable again, if only in the form of hybrids.

The big breakthrough for true e-cars came in 2006 with Elon Musk’s Tesla Roadster. Everybody wanted one.

And today, Tesla remains the e-car that everybody wants.

Now, let’s look at Smalltalk. Smalltalk was pioneered in the 1970s. (The first official language release was Smalltalk-80 in 1980.)

Smalltalk had reached its peak of popularity in the early 1990s when it became the second most popular object-oriented language in the world (C++ was #1). Even IBM chose it as the centrepiece of their VisualAge enterprise initiative.

By 1995, that began to change. Sun Microsystems’ Java language burst onto the scene and sucked all the oxygen out of the room. Smalltalk was among the casualties.

By 2007, however, a modern variant of Smalltalk known as Pharo was birthed. It arrived at the right time because the world was suffering from low programmer productivity and a backlog of software applications begging to be written. The world was also suffering from a plethora of overly complex programming languages like C++, Java, C#, D, Groovy, and Scala. This group would be later joined by JavaScript, Kotlin, Rust, Swift, and TypeScript.

People are clamouring for fresh air. They want simpler languages. That’s one reason for the resurgence of Python (though calling Python a “simple” language is rather dubious).

It’s also why Golang took off, and why Dart, Elixir, Lua, and Nim are beloved.

Today, Pharo is a very exciting language. It has been innovating by leaps and bounds over the past decade. One of the most notable developments is the Glamorous Toolkit.

But Smalltalk is a family of languages, so we should also give a shout out to other great Smalltalk flavours such as GemStone/S from GemTalk Systems, VA Smalltalk from Instantiations, and VisualWorks from Cincom. Not to be overlooked are Amber (transpiles to JS), Cuis Smalltalk, Dolphin Smalltalk (optimized for Windows), GNU Smalltalk (for command line lovers), Hoot Smalltalk (JVM support), and Squeak.

Pharo is also extremely versatile which is well-explained in this article, “Smalltalk: It’s Not Your Grandparent’s Programming Language.”

Let me close by pointing out another interesting parallel. In the early years of the e-car, there were technical obstacles that limited its popularity. E-cars had a very limited range. They couldn’t compete with low-cost gas. They had limited horsepower.

In the early years of Smalltalk, it required expensive hardware to run on (processor and memory). It needed high-resolution graphical displays. It couldn’t compete with C/C++ and FORTRAN and BASIC and Pascal.

Today, both are experiencing a revival. E-cars are more economical than ever. Smalltalk can run on devices as small as the Raspberry Pi, and run well!

The epitome of the e-car is Tesla. It is the most aspirational electric car in the world.

The epitome of programming languages for productivity and ease of use is Pharo/Smalltalk. It, too, is aspirational. Is there a programmer alive who doesn’t want to write their applications quickly and easily, like in half the time? I don’t know about you, but I don’t want to work harder than I have to.

(Previously published at gitconnected.)

by smalltalkrenaissance at January 19, 2020 02:57 PM

Smalltalk: It’s Not Your Grandparent’s Programming Language

Smalltalk is old. Very old. Just like LISP is very old. Just like Forth is very old. Just like Erlang is very old. Just like Haskell is very old.

Let’s face it, any language created before 1995 is probably one that your parent, or even grandparent, used in their IT career. (I’m speaking to the current generation.)

Old programming languages are considered not cool. They’re not dope. Nobody wants to be like their grandparent.

This is a very unfortunate sentiment. It is couched in ignorance. It is myopic and parochial. The sentiment blinds you to wonderful opportunities.

You see, old languages are routinely updated for modern times. LISP can be found in Clojure (2007). Forth can be found in Factor (2003). Erlang can be found in Elixir (2011). And although Haskell is old, it is considered new, or at least a rediscovered treasure.

And so it is with Smalltalk. The language is timeless. It is as fresh today as it was 40 years ago (with the release of Smalltalk-80).

Smalltalk promises a productivity gain that is almost revolutionary, thanks to its unique and synergistic combination of simple, concise language, easily accessible live coding IDE, and a persistable system of live objects. Smalltalkers regularly claim a productivity gain of 5X.

Smalltalk is remarkably versatile. You can do back-end web with Seaside and Teapot frameworks. You can do front-end web with Amber and PharoJS transpiled languages. You can do mobile with Cordova/PhoneGap. You can do data science with PolyMath library, Roassal data visualization, and Moose data analytics platform. You can do machine learning with TensorFlow. You can do IoT with PharoThings. You can do robotics with PhaROS. You can do virtual reality. You can even script the Unreal game engine!

Roassal demonstration
virtual reality demonstration
Unreal game engine demonstration

This is all cutting-edge stuff. All of it was unimaginable 40 years ago. So let’s drop the grandparent attitude, shall we?

Maserati is your grandparent’s sports car. But who wouldn’t want to drive a modern Maserati?!

(Previously published at gitconnected.)

by smalltalkrenaissance at January 19, 2020 02:50 PM

Why Smalltalk is so easy to evangelize

Of all the programming languages in the world, Smalltalk is, by far, the easiest one to evangelize. Why is that?

First, Smalltalk has a wonderful historical legacy. It has contributed an enormous amount to the software industry, to computer science, and to programming language design. It pioneered the language virtual machine and JIT compilation. It created the world’s first modern IDE. It made live coding easily accessible. It introduced the MVC architectural pattern. It was largely responsible for TDD (test-driven development). It pioneered the development of object databases. It gave us the first refactoring browser. It was instrumental in developing GUI and WYSIWYG.

It influenced the design of Objective-C, Ruby, PHP, Perl, Python, Groovy, Scala, Dart, and other languages.

It popularized object-oriented programming (whereas Simula 67 academically introduced the concept of classes and objects). Remember the famous August 1981 cover of BYTE magazine?

Second, Alan Kay and his group at Xerox PARC are legendary. Alan Kay’s vision was extraordinary. His object-oriented philosophy was brilliant. It was far superior to the philosophy espoused by people like Bjarne Stroustrup.

Alan Kay on the early days of Smalltalk (jump to 2:18)

Third, Smalltalk has a wonderful track record. It actually achieved a significant measure of popularity in the 1980s and 1990s. It was adopted by IBM for their VisualAge enterprise initiative. It was used by many prominent customers, including the U.S. joint military, JP Morgan, Orient Overseas Container Lines, Desjardins, UBS, Texas Instruments, Telecom Argentina, BMW, and Siemens AG.

It has a very significant commercial vendor presence which enterprise companies appreciate. Look at Cincom (VisualWorks), Instantiations (VA Smalltalk), and GemTalk Systems (GemStone/S). It has significant corporate sponsorship from the Pharo Consortium.

Fourth, Smalltalk has statistical evidence (in the Namcook Analytics study by Capers Jones) to support the claim of enormous programmer productivity. This is consistent with much anecdotal evidence for the same claim.

Fifth, Smalltalk has a rich family of languages like Pharo, Squeak, Cuis Smalltalk, Dolphin Smalltalk (optimized for Windows), GNU Smalltalk (for command line lovers), Amber (transpiles to JS), Hoot Smalltalk (JVM support), VisualWorks, VA Smalltalk, and GemStone/S (high-performance object databases) that can satisfy a myriad of needs.

Moreover, Pharo is the fastest evolving and innovating Smalltalk in history! It has remade itself in just under a decade.

Sixth, Smalltalk makes object-oriented programming very easy, much easier than in C++, Java, C#, and others. Smalltalk is supremely simple and easy to learn. Its complete syntax fits on a post card. You can learn all of Smalltalk’s syntax within 15 minutes!

Seventh, Smalltalk is remarkably versatile. You can do back-end web with Seaside and Teapot frameworks. You can do front-end web with Amber and PharoJS transpiled languages. You can do mobile with Cordova/PhoneGap. You can do data science with PolyMath library, Roassal data visualization, and Moose data analytics platform. You can do machine learning with TensorFlow. You can do IoT with PharoThings. You can do robotics with PhaROS. You can do virtual reality. You can even script the Unreal game engine!

Roassal demonstration
virtual reality demonstration
Unreal game engine demonstration

In other words, Smalltalk provides a huge stockpile of ammunition. You can fire salvo after salvo after salvo.

What other language can be as easily evangelized? Clojure? Crystal? Dart? Elixir? Golang? Haskell? Julia? Kotlin? Nim? Racket? Rust? TypeScript? Nope. Not even close.

(Previously published at ITNEXT.)

by smalltalkrenaissance at January 19, 2020 02:40 PM

January 15, 2020

PharoWeekly

Characterizing Pharo code

Hello,

We have analyzed the source code of the 50 projects selected from the Pharo ecosystem and reported our findings in this document:

https://hal.inria.fr/hal-02440055v1

Perhaps, you will find it interesting.

Here are some fun facts that we have discovered:

Have a nice day, and let us know what you think.

We would be happy to receive your feedback.

Oleks

by Stéphane Ducasse at January 15, 2020 11:55 AM

January 14, 2020

Pierce Ng

More Secure Cookie Auto Login for TF-Login

I've implemented a more secure cookie-based auto-login in TF-Login 'password' branch to replace the existing simple and insecure cookie scheme.

To load, start with fresh Pharo 7 image:

"First load Seaside."
Metacello new 
    baseline: 'Seaside3'; 
    repository: 'github://SeasideSt/Seaside:v3.3.3/repository'; 
    load. 
    
"Then load TF-Login."
Metacello new 
    baseline: 'TFLogin'; 
    repository: 'github://PierceNg/TF-Login:password/src'; 
    load.

Start Test Runner to run TF-Login's tests. All 78 tests should pass. The class TLTest runs "scripted interactive" tests on the TLTester Seaside application. TLTest's testLoginLogout and testLoginThenAutomaticLogin methods exercise the cookie-based auto-login functionality.

Auto-login is also implemented in the TLTestApp demo Seaside application. Here's a screenshot of the cookie stored in Chromium upon logging into TLTestApp.

TF-Login cookie in Chromium

The original cookie-based auto-login stores username and the SHA1-hashed password in client cookies. This replacement implementation is based on Paragon Initiative's blog post on "remember me" cookies.

by Pierce Ng at January 14, 2020 11:11 PM

PharoWeekly

[Ann] VLC binding for Pharo

Hello there,

I just want to let you know that I’ve developed an FFI binding to VLC.
Since, version 2.1.1 you can use it on Windows, Linux, and OSX.
https://github.com/badetitou/Pharo-LibVLC

Thanks to the binding you can play easily sounds and videos from Pharo.

The next steps are:

Feel free to use the binding and tell me if you need help with it.

Benoît Verhaeghe

by Stéphane Ducasse at January 14, 2020 10:33 AM

January 13, 2020

PharoWeekly

[ann] Embedded image in Windows

Hi,
I have produced an example of using the headless VM to have an
embedded image in Windows. The example is hosted in Github
(https://github.com/tesonep/pharo-vm-embedded-example)

The example is a CMake project to generate a new small executable that
uses the VM as a library. Also, it shows how to perform the branding
of applications (I have used the same Pharo icon, but we can use
anything else).

In the example, I am opening one of the SDL2 examples, it opens a
window where we can draw in an Athens Canvas.

It requires a Cygwin environment, but if you are able to build the
headless VM you already have it!.

I will do other examples of the use case we are thinking for the headless VM!

Cheers,
Pablo


Pablo Tesone.
tesonep@gmail.com

by Stéphane Ducasse at January 13, 2020 05:09 PM

January 07, 2020

Torsten Bergmann

Smalltalk with the GraalVM

If you have followed Smalltalk history (or some of the posts in this blog) you might already know about the Strongtalk system.

It is a Smalltalk environment with optional static typing support. Strongtalk can make some compile time checks, and offer stronger type safety guarantees; this is the source of its name. It is non-commercial, though it was originally a commercial project developed by a small startup company named LongView Technologies (trading as Animorphic Systems). Strongtalk is freely available on http://www.strongtalk.org

Programmers of the Strongtalk VM were later responsible at Sun Microsystems to make Java running faster by implementing the so called Java HotSpot virtual machine.

The HotSpot VM (now owned by Oracle) was primarily a Java only virtual machine - thats why it is called "JVM".

But the work continued to provide a new polyglot virtual machine called "GraalVM" which is able to host and run other programming languages (like JavaScript, Python and even C) on a new single virtual machine too.

You can find more informations about GraalVM on https://www.graalvm.org

All this is based on a Graal compiler and Truffle language implementation framework as well as a language interop framework called Polyglot that allows Truffle languages to call each other.

Now the Software Architecture Group at HPI provides even a Smalltalk on the GraalVM which is primarily using Squeak as the hosted Smalltalk environment.

Using the Polyglot functionality of the GraalVM you can interoperate easily from Smalltalk with other languages of the GraalVM as it can be seen in this demo video:





by Torsten (noreply@blogger.com) at January 07, 2020 07:57 PM

Practical Agile AI with Pharo

Apress seems to have already a page on upcoming book "Practical Agile AI with Pharo" which will be available in 2020

by Torsten (noreply@blogger.com) at January 07, 2020 06:56 PM

Docker and Pharo

Pierce is playing with a minimal Docker image including Pharo.


I experimented with docker and Pharo too - some of my notes are here

by Torsten (noreply@blogger.com) at January 07, 2020 06:55 PM

Smalltalk / Web Camp Lake Constance

Nice summary report from Joachim about the Smalltalk / Web Camp Lake Constance test run - a meeting of some companies using Smalltalk for web development.

by Torsten (noreply@blogger.com) at January 07, 2020 06:50 PM

Cuis-Smalltalk-Chip8 in Cuis Smalltalk

A Chip 8 emulator (interpreter) written in Cuis Smalltalk:

       https://github.com/thiagoslino/Cuis-Smalltalk-Chip8

by Torsten (noreply@blogger.com) at January 07, 2020 06:47 PM

SQLite3 for Pharo updated and moved

In the past PierceNG and me were maintaining SQLite3 driver for Pharo. As in 2019 another Pharo community member (Julien Delplanque) contributed to the project it was better to align and move the project to a more community owned location.

So SQLite3 for Pharo was reworked to be fully standalone and it was moved to community owned "pharo-rdbms" location:

  https://github.com/pharo-rdbms/Pharo-SQLite3

Additional Docu and CI support was added with green builds for Pharo 6.1, Pharo 7 and Pharo 8.

The old locations were marked deprecated.


by Torsten (noreply@blogger.com) at January 07, 2020 06:43 PM

Pharo XML support packages moved to GitHub

In November 2019 some time was spend to move the XML Support for Pharo from old SmalltalkHub to a community managed location on GitHub:

     https://github.com/pharo-contributions

For the detailed packages this means


Fortunately there is a nice tool from Peter Uhnak called "git-migration" that helped a lot in this transition and preserved original commit history as much as possible. 

Additionally some more cleanups were applied and a continuous integration (CI) was established.

The move to GitHub should help to better maintain contributions to these projects and also verify that the XML support runs on newer Pharo versions.



by Torsten (noreply@blogger.com) at January 07, 2020 06:03 PM

MoreVMs 2020

In 2020 there is a workshop on Modern Language Runtimes, Ecosystems, and VMs in Portugal. Maybe the topic is interesting for you. Read more here.

by Torsten (noreply@blogger.com) at January 07, 2020 06:01 PM

Grouper for Pharo

Grouper is a nice package to group data in Pharo:

by Torsten (noreply@blogger.com) at January 07, 2020 04:51 PM

ReStore for Pharo

ReStore - an object relational database framework originally available for Dolphin Smalltalk was ported to Pharo.

Nice - I should give it a try.

by Torsten (noreply@blogger.com) at January 07, 2020 04:50 PM

Towards Machine Learning in Pharo: Visualizing Linear Regression

A nice medium article from Oleksandr Zaitsev on Machine Learning in Pharo. Note that he used the new Roassal 3 package for the visualizations.

by Torsten (noreply@blogger.com) at January 07, 2020 04:32 PM