29
Smalltalk in a .NET World How to write a Smalltalk compiler without writing a VM John Brant [email protected]

Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant [email protected]

Embed Size (px)

Citation preview

Page 1: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Smalltalk in a .NET World

How to write a Smalltalk compiler without writing a VM

John [email protected]

Page 2: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

#Smalltalk

Open source Smalltalk compiler Complete Source Available Self hosting Compiles Smalltalk directly to .NET

executables and libraries

Page 3: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Building Smalltalk

Virtual Machine .NET Virtual Machine

Compiler RB parser

Class Library ANSI Standard

Development tools (debuggers, browsers, etc.)

Page 4: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

What’s .NET Anyway?

Common class library (collections, GUI, sockets, database, etc.)

Common virtual machine and byte code instruction set

Language isn’t supposed to matter

Page 5: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Why .NET?(business reasons)

Backed by Microsoft Lots of existing code Allow Smalltalk to be used for

applications that “require .NET”

Page 6: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Why .NET?(personal reasons)

Build a Smalltalk compiler Make an experimental platform Learn .NET Unemployed

Page 7: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Smalltalk vs. .NET

Smalltalk .NET

Strong, dynamic typing Strong, static typing

Tagged integers Primitive integer types

Blocks Delegates

Resumable Exceptions Non-resumable exceptions

become:, change classes ?

Page 8: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Smalltalk vs. .NET II

Smalltalk .NET

All methods are virtual Static, virtual, & non-virtual methods

Add/remove classes & methods

Add classes/methods (can’t remove or recompile)

? Structs & Enums

Page 9: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Dynamic Typing

Root super type Understands every message Sends #doesNotUnderstand:

Root

Object Proxy

printString ^self doesNotUnderstand: (Message selector: #printString arguments: #())

printString | stream | stream := WriteStream with: String new. self printOn: stream. ^stream contents

Page 10: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

null vs. nil

Special object for nil Class constructor initializes variables to

nil Method temporaries initialized to nil only

if they could be read before writtenmethod: aBoolean | temp one | aBoolean ifTrue: [temp := 5]. one := 1. ^temp + one

temp := nil.

Page 11: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

SmallIntegers

No support for tagged integers Real integer objects 10x slower than tagged integers

2r000010112r00000010

VW Tagged #Smalltalk

Page 12: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Blocks

Create class for each block Create object from block class at

runtime

method ^#(1) collect: [:each | each + 1]

method ^#(1) collect: (Method-Block new)

MonadicBlock subclass: Method-Block instanceVariableNames: ‘’ …

value: each ^each + 1

Page 13: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Block Variables

Variable references Copied values (method/block arguments) Active variables (temporaries)

method: arg | block temp | block := [temp + arg]. temp := 5. ^block value

methodarg

blocktemp

blockarg

temp

tempvalue

arg

5

Page 14: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Block Returns

Simulate using .NET exceptions 100x slower Tag object (integer)

method1 self method2: [^1]

method2: aBlock #(2) do: [:each | aBlock value. ^each]

method2

method1

do:

method2[ ]

method1[ ]

Page 15: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Primitives

Some actions aren’t representable (e.g., identityHash, +, etc.)

Primitive tag Only one per method

Compiler primitive: [] Used anywhere in method User can add new primitives Block code evaluated at compile time

Page 16: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Primitive Example

identityHash ^Compiler primitive: [:codeGenerator | codeGenerator call: (System.Object getMethod: 'GetHashCode'); constructNewObject: codeGenerator smalltalk smallIntegerClass initializedConstructor] evaluate: self

Page 17: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Optimized Messages

Certain messages aren’t sent (e.g., ifTrue:, whileTrue:, to:do:)

Can hard code in compiler Instead use macros and “Compiler

primitive: []” syntax

Page 18: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Macros

RB’s rewrite rules ``@node ifTrue: ``@block

Compiler primitive: [:codeGen :block | …] evaluate: ``@node uses: ``@block

Allows arbitrary optimizations (e.g., ifNil: isNil ifTrue:)

Copy source interval for debugger

Page 19: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Connecting with .NET

Over 2500 classes provided Seamless integration

| algorithm stream |algorithm := HashAlgorithm create: ‘MD5’.stream := FileStream read: ‘rb.im’.[algorithm computeHash: stream]

ensure: [stream close]

Page 20: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Connecting Smalltalk to .NET

Class references (Convert or System.Convert)

Typed Variables (System.Int32) Generic ObjectWrapper Messages for field, property, and

method access Constructors – #new* messages

Page 21: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Method arguments

First keyword for method name/rest can be anything

Arguments converted to .NET objects is-a tests for arguments

Overloaded methods left-to-right, specific-to-generic System.Console::Write(int/char/…/object)

Page 22: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Console Example

System.Console write: anObject

(anObject isKindOf: SmallInteger) ifTrue: [System.Console write: anObject integer] ifFalse: [(anObject isKindOf: Character) ifTrue: [System.Console write: anObject character] ifFalse: [(anObject isKindOf: String) ifTrue: [System.Console write: anObject string] ifFalse: [System.Console write: anObject]]]

Page 23: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Connecting .NET to Smalltalk

Events use add_EventName: / remove_EventName: methods

Delegates (#asDelegate:) Button new add_Click:

([:obj :args | …] asDelegate: EventHandler)

Exported Properties/Methods (specified by annotations)

Interfaces & subclasses (to do)

Page 24: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

#Smalltalk Development (Version 1)

Proof of concept VisualWorks program Compiled generated text file with ilasm

(.NET’s assembler) Not seamless

Page 25: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

#Smalltalk Development (Version 2)

Read .SIF files VisualWorks DLL connection to .NET Override qualified name lookup in VW

to use .NET DLL System.Int32 Parse: ‘1234’

System.Reflection.Emit generate .exe file directly

Page 26: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

#Smalltalk Development (Version 3)

Code based on Version 2 Self hosting Complete .exe compiler Compile three times (fixed point)

Old code compiling new code New code compiling new code Verify new code compiled new code valid

Page 27: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

BenchmarksDolphin #Smalltalk VA VW Squeak

add integers 36.06 2.62 576.97 576.97 14.07

add floats 64.76 75.48 2266.67 39.08 11.45

access strings 19.10 54.37 54.42 108.84 36.28

create objects 20.20 90.82 30.30 90.91 7.16

copy objects 29.91 37.35 74.77 74.77 14.11

perform selectors 28.96 16.12 37.65 161.35 8.07

evaluate blocks 6.80 30.91 61.88 42.67 2.17

generating fractonaccis 15.77 33.55 87.21 115.22 7.20

generating primes 42.22 43.15 140.38 181.13 *

generating strings 98.44 27.09 128.79 179.71 18.27

forming sets 20.19 13.25 48.63 216.11 21.14

sorting strings 36.65 49.36 856.50 70.59 28.65

Page 28: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Future work

IDE (GUI builders, Browsers, etc.) Add Subclassing/Interfaces Optimizations

Reusing intermediate numerical values (e.g., i + j + k)

Type inferencing – eliminating SmallIntegers (e.g., 1 to: 10 do: [:i | ])

Write programs

Page 29: Smalltalk in a.NET World How to write a Smalltalk compiler without writing a VM John Brant brant@refactory.com

Contact Information

#Smalltalk http://www.refactory.com/Software/SharpSmalltalk/

VisualWorks .NET DLL http://www.rileywhite.com/software/assemblyconnect.html

.NET http://www.microsoft.com/net/ http://www.go-mono.com/