View
41
Download
0
Category
Preview:
DESCRIPTION
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. Building Smalltalk. - PowerPoint PPT Presentation
Citation preview
Smalltalk in a .NET World
How to write a Smalltalk compiler without writing a VM
John Brantbrant@refactory.com
#Smalltalk
Open source Smalltalk compiler Complete Source Available Self hosting Compiles Smalltalk directly to .NET
executables and libraries
Building Smalltalk
Virtual Machine .NET Virtual Machine
Compiler RB parser
Class Library ANSI Standard
Development tools (debuggers, browsers, etc.)
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
Why .NET?(business reasons)
Backed by Microsoft Lots of existing code Allow Smalltalk to be used for
applications that “require .NET”
Why .NET?(personal reasons)
Build a Smalltalk compiler Make an experimental platform Learn .NET Unemployed
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 ?
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
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
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.
SmallIntegers
No support for tagged integers Real integer objects 10x slower than tagged integers
2r000010112r00000010
VW Tagged #Smalltalk
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
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
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[ ]
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
Primitive Example
identityHash ^Compiler primitive: [:codeGenerator | codeGenerator call: (System.Object getMethod: 'GetHashCode'); constructNewObject: codeGenerator smalltalk smallIntegerClass initializedConstructor] evaluate: self
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
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
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]
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
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)
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]]]
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)
#Smalltalk Development (Version 1)
Proof of concept VisualWorks program Compiled generated text file with ilasm
(.NET’s assembler) Not seamless
#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
#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
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
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
Recommended