Browse Source

Merge remote-tracking branch 'gokr/master'

Nicolas Petton 13 years ago
parent
commit
2016dd1e56

+ 72 - 16
bin/jtalkc

@@ -7,22 +7,26 @@ JTALK=`dirname ${0}`/..
 
 function usage {
 	cat <<ENDOFHELP
-Usage: $0 [-N|D] [-K|C] [-m class] [-M file] [-i] [-I file] file1 [file2 ...] [Program]
+Usage: $0 [-N|D] [-K|C] [-o] [-O] [-m class] [-M file] [-i] [-I file] file1 [file2 ...] [Program]
 
-   Will compile Jtalk files in a variety of ways.
+   Will compile Jtalk files - either separately or into a runnable complete program.
    Files listed will be handled using these rules:
 
-     *.js files are concatenated as is. If not found we look in $JTALK/js
+   *.js
+     Files are concatenated in listed order. If not found we look in $JTALK/js
 
-     *.st files are compiled into .js files. If not found we look in $JTALK/st.
-     Each file is currently considered to be a fileout of a single class
-     category of the same name as the file.
+   *.st
+     Files are compiled into .js files before concatenated. If not found we look
+     in $JTALK/st.
 
-   If no Program is specified only each given .st file will be compiled into a .js file.
-   Otherwise a Program.js file is linked together based on the given options described below:
+     NOTE: Each file is currently considered to be a fileout of a single class
+     category of the same name as the file!
+
+   If no Program is specified each given .st file will be compiled into a .js file.
+   Otherwise a <Program>.js file is linked together based on the options:
 
   -N or -D
-     Compile for Node.js or D8 (V8 shell). Defaults to "-Kim Main" so boot.js and Kernel.js
+     Compile for Node.js or D8 (V8 shell). Implies "-K -i -m Main" so boot.js and Kernel.js
      are added first and init.js is added last with a call to Main class>>main.
 
   -K
@@ -31,6 +35,18 @@ Usage: $0 [-N|D] [-K|C] [-m class] [-M file] [-i] [-I file] file1 [file2 ...] [P
   -C
      Add libraries to get minimal JTalk Compiler running.
 
+  -o
+     Optimize each js file using the Google closure compiler. Using ~/compiler.jar    
+
+  -O
+     Optimize <Program>.js using the Google closure compiler. Using ~/compiler.jar
+
+  -l libray1,library2
+     Load listed libraries (no spaces) in Compiler before compiling.
+
+  -L
+     Loads all libraries in directory js in Compiler before compiling.
+
   -i
      Add library standard initializer $JTALK/js/init.js
 
@@ -75,6 +91,7 @@ fi
 BOOT="$JTALK/js/boot.js"
 KERNEL="$BOOT $JTALK/js/Kernel.js"
 COMPILER="$KERNEL $JTALK/js/Parser.js $JTALK/js/Compiler.js"
+CANVAS="$COMPILER $JTALK/js/Canvas.js"
 
 # Predefined initializer
 INITIALIZER="$JTALK/js/init.js"
@@ -85,10 +102,10 @@ INIT=
 MAIN=
 MAINFILE=
 BASE=$KERNEL
-OURCOMPILER="$COMPILER $JTALK/js/init.js $JTALK/nodejs/nodecompile.js"
+LOAD=
 
 # Read options and shift them away
-while getopts "NDKCiI:M:m:h?" o; do
+while getopts "NDKCoOl:LiI:M:m:h?" o; do
 case "$o" in
    N) ENV=NODE
       BASE=$KERNEL
@@ -100,6 +117,12 @@ case "$o" in
       MAIN=Main;;
    K) BASE=$KERNEL;;
    C) BASE=$COMPILER;;
+   o) CLOSURE=true
+      CLOSUREPARTS=true;;
+   O) CLOSURE=true
+      CLOSUREFULL=true;;
+   l) LOAD=$OPTARG;;
+   L) LOAD="$JTALK/*.js";;
    I) INIT=$INITIALIZER;;
    i) INIT=$OPTARG;;
    M) MAINFILE=$OPTARG;;
@@ -110,6 +133,24 @@ case "$o" in
 done
 shift $(($OPTIND - 1))
 
+# Check for Closure compiler and Java
+if [ ! -z $CLOSURE ]; then
+  java > /dev/null
+  if [ $? -eq 0 ]; then 
+    if [ ! -f ~/compiler.jar ]; then
+      echo "Can not find Closure compiler at ~/compiler.jar"
+      exit 1
+    fi
+  else
+   echo "java is not installed and is needed for -O or -o (Closure compiler)."
+   exit 1
+  fi
+fi
+
+# Define our Compiler
+# We need to add extra listed libraries in $LOAD not already in $CANVAS
+OURCOMPILER="$CANVAS $JTALK/js/init.js $JTALK/nodejs/nodecompile.js"
+
 # Combine supplied libraries
 LIBS="$BASE $ADDONS"
 
@@ -182,6 +223,18 @@ do
   fi 
 done
 
+if [ ! -z $CLOSUREPARTS ]; then
+  echo "Compiling all js files using Google closure compiler."
+
+  ALLJSFILES="$COMPILED $LIBS"
+  for FILE in $ALLJSFILES
+  do
+    mv $FILE $FILE.original
+    java -jar ~/compiler.jar --js $FILE.original --js_output_file $FILE
+    rm $FILE.original
+  done
+fi
+
 
 if [ -z $PROGRAM ]; then
   echo "Done."
@@ -234,9 +287,12 @@ echo "Writing $PROGRAM.js ..."
 cat $LIBS $COMPILED $INIT $MAIN > $PROGRAM.js
 echo "Done."
 
-# Optionally run Program and give all args left to it
-if [ -n "$RUN" ]; then
-  echo "Running program"
-  echo "---------------"
-  node $PROGRAM.js $@
+
+if [ ! -z $CLOSUREFULL ]; then
+  echo "Compiling $PROGRAM.js file using Google closure compiler."
+  mv $PROGRAM.js $PROGRAM.js.original
+  java -jar ~/compiler.jar --js $PROGRAM.js.original --js_output_file $PROGRAM.js
+  rm $PROGRAM.js.original
+  echo "Done."
 fi
+

+ 1 - 0
ide.html

@@ -18,6 +18,7 @@
     <script type="text/javascript" src="./js/IDE.js"></script>
     <script type="text/javascript" src="./js/SUnit.js"></script>
     <script type="text/javascript" src="./js/Examples.js"></script>
+    <script type="text/javascript" src="./js/Benchfib.js"></script>
     <script type="text/javascript" src="./js/init.js"></script>
     <link rel="stylesheet" type="text/css" href="./css/jtalk.css">
     <link rel="stylesheet" type="text/css" href="./css/sunit.css">

+ 81 - 0
js/Benchfib.js

@@ -0,0 +1,81 @@
+smalltalk.addClass('Benchfib', smalltalk.Object, [], 'Benchfib');
+
+smalltalk.addMethod(
+'_main',
+smalltalk.method({
+selector: 'main',
+category: 'not yet classified',
+fn: function (){
+var self=this;
+var result=nil;
+result=smalltalk.send((0), "_tinyBenchmarks", []);
+console.log('0 tinyBenchmarks => ' + result);;
+return self;},
+source: unescape('main%0A%0A%09%7C%20result%20%7C%0A%09result%20%3A%3D%200%20tinyBenchmarks.%0A%09%7B%27console.log%28%27%270%20tinyBenchmarks%20%3D%3E%20%27%27%20+%20result%29%3B%27%7D'),
+messageSends: ["tinyBenchmarks"],
+referencedClasses: []
+}),
+smalltalk.Benchfib.klass);
+
+
+smalltalk.addMethod(
+'_benchFib',
+smalltalk.method({
+selector: 'benchFib',
+category: '*Benchfib',
+fn: function (){
+var self=this;
+return smalltalk.send(smalltalk.send(self, "__lt", [(2)]), "_ifTrue_ifFalse_", [(function(){return (1);}), (function(){return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(self, "__minus", [(1)]), "_benchFib", []), "__plus", [smalltalk.send(smalltalk.send(self, "__minus", [(2)]), "_benchFib", [])]), "__plus", [(1)]);})]);
+return self;},
+source: unescape('benchFib%0A%09%22Handy%20send-heavy%20benchmark%22%0A%09%22%28result%20//%20seconds%20to%20run%29%20%3D%20approx%20calls%20per%20second%22%0A%09%22%20%7C%20r%20t%20%7C%0A%09%20%20t%20%3A%3D%20Time%20millisecondsToRun%3A%20%5Br%20%3A%3D%2026%20benchFib%5D.%0A%09%20%20%28r%20*%201000%29%20//%20t%22%0A%09%22138000%20on%20a%20Mac%208100/100%22%0A%09%5E%20self%20%3C%202%0A%09%09ifTrue%3A%20%5B1%5D%20%0A%09%09ifFalse%3A%20%5B%28self-1%29%20benchFib%20+%20%28self-2%29%20benchFib%20+%201%5D'),
+messageSends: ["ifTrue:ifFalse:", unescape("%3C"), unescape("+"), "benchFib", unescape("-")],
+referencedClasses: []
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+'_benchmark',
+smalltalk.method({
+selector: 'benchmark',
+category: '*Benchfib',
+fn: function (){
+var self=this;
+var size=nil;
+var flags=nil;
+var prime=nil;
+var k=nil;
+var count=nil;
+size=(8190);
+smalltalk.send((1), "_to_do_", [self, (function(iter){count=(0);flags=smalltalk.send(smalltalk.Array, "_new", []);smalltalk.send(size, "_timesRepeat_", [(function(){return smalltalk.send(flags, "_add_", [true]);})]);return smalltalk.send((1), "_to_do_", [size, (function(i){return smalltalk.send(smalltalk.send(flags, "_at_", [i]), "_ifTrue_", [(function(){prime=smalltalk.send(i, "__plus", [(1)]);k=smalltalk.send(i, "__plus", [prime]);smalltalk.send((function(){return smalltalk.send(k, "__lt_eq", [size]);}), "_whileTrue_", [(function(){smalltalk.send(flags, "_at_put_", [k, false]);return k=smalltalk.send(k, "__plus", [prime]);})]);return count=smalltalk.send(count, "__plus", [(1)]);})]);})]);})]);
+return count;
+return self;},
+source: unescape('benchmark%20%20%22Handy%20bytecode-heavy%20benchmark%22%0A%09%22%28500000%20//%20time%20to%20run%29%20%3D%20approx%20bytecodes%20per%20second%22%0A%09%225000000%20//%20%28Time%20millisecondsToRun%3A%20%5B10%20benchmark%5D%29%20*%201000%22%0A%09%223059000%20on%20a%20Mac%208100/100%22%0A%20%20%20%20%7C%20size%20flags%20prime%20k%20count%20%7C%0A%20%20%20%20size%20%3A%3D%208190.%0A%20%20%20%201%20to%3A%20self%20do%3A%0A%20%20%20%20%20%20%20%20%5B%3Aiter%20%7C%0A%20%20%20%20%20%20%20%20count%20%3A%3D%200.%0A%20%20%20%20%20%20%20%20flags%20%3A%3D%20Array%20new.%0A%20%20%20%20%20%20%20%20size%20timesRepeat%3A%20%5B%20flags%20add%3A%20true%5D.%0A%20%20%20%20%20%20%20%201%20to%3A%20size%20do%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%3Ai%20%7C%20%28flags%20at%3A%20i%29%20ifTrue%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bprime%20%3A%3D%20i+1.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20k%20%3A%3D%20i%20+%20prime.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bk%20%3C%3D%20size%5D%20whileTrue%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bflags%20at%3A%20k%20put%3A%20false.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20k%20%3A%3D%20k%20+%20prime%5D.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20count%20%3A%3D%20count%20+%201%5D%5D%5D.%0A%20%20%20%20%5E%20count'),
+messageSends: ["to:do:", "new", "timesRepeat:", "add:", "ifTrue:", "at:", unescape("+"), "whileTrue:", unescape("%3C%3D"), "at:put:"],
+referencedClasses: [smalltalk.Array]
+}),
+smalltalk.Number);
+
+smalltalk.addMethod(
+'_tinyBenchmarks',
+smalltalk.method({
+selector: 'tinyBenchmarks',
+category: '*Benchfib',
+fn: function (){
+var self=this;
+var t1=nil;
+var t2=nil;
+var r=nil;
+var n1=nil;
+var n2=nil;
+n1=(1);
+smalltalk.send((function(){t1=smalltalk.send(smalltalk.Date, "_millisecondsToRun_", [(function(){return smalltalk.send(n1, "_benchmark", []);})]);return smalltalk.send(t1, "__lt", [(1000)]);}), "_whileTrue_", [(function(){return n1=smalltalk.send(n1, "__star", [(2)]);})]);
+n2=(28);
+smalltalk.send((function(){t2=smalltalk.send(smalltalk.Date, "_millisecondsToRun_", [(function(){return r=smalltalk.send(n2, "_benchFib", []);})]);return smalltalk.send(t2, "__lt", [(1000)]);}), "_whileTrue_", [(function(){return n2=smalltalk.send(n2, "__plus", [(1)]);})]);
+return smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(smalltalk.send(n1, "__star", [(500000)]), "__star", [(1000)]), "__slash", [t1]), "_printString", []), "__comma", [unescape("%20bytecodes/sec%3B%20")]), "__comma", [smalltalk.send(smalltalk.send(smalltalk.send(r, "__star", [(1000)]), "__slash", [t2]), "_printString", [])]), "__comma", [unescape("%20sends/sec")]);
+return self;},
+source: unescape('tinyBenchmarks%0A%09%22Report%20the%20results%20of%20running%20the%20two%20tiny%20Squeak%20benchmarks.%0A%09ar%209/10/1999%3A%20Adjusted%20to%20run%20at%20least%201%20sec%20to%20get%20more%20stable%20results%22%0A%09%220%20tinyBenchmarks%22%0A%09%22On%20a%20292%20MHz%20G3%20Mac%3A%2022727272%20bytecodes/sec%3B%20984169%20sends/sec%22%0A%09%22On%20a%20400%20MHz%20PII/Win98%3A%20%2018028169%20bytecodes/sec%3B%201081272%20sends/sec%22%0A%09%7C%20t1%20t2%20r%20n1%20n2%20%7C%0A%09n1%20%3A%3D%201.%0A%09%5Bt1%20%3A%3D%20Date%20millisecondsToRun%3A%20%5Bn1%20benchmark%5D.%0A%09t1%20%3C%201000%5D%20whileTrue%3A%5Bn1%20%3A%3D%20n1%20*%202%5D.%20%22Note%3A%20%23benchmark%27s%20runtime%20is%20about%20O%28n%29%22%0A%0A%09n2%20%3A%3D%2028.%0A%09%5Bt2%20%3A%3D%20Date%20millisecondsToRun%3A%20%5Br%20%3A%3D%20n2%20benchFib%5D.%0A%09t2%20%3C%201000%5D%20whileTrue%3A%5Bn2%20%3A%3D%20n2%20+%201%5D.%20%0A%09%22Note%3A%20%23benchFib%27s%20runtime%20is%20about%20O%28k%5En%29%2C%0A%09%09where%20k%20is%20the%20golden%20number%20%3D%20%281%20+%205%20sqrt%29%20/%202%20%3D%201.618....%22%0A%0A%09%5E%20%28%28n1%20*%20500000%20*%201000%29%20/%20t1%29%20printString%2C%20%27%20bytecodes/sec%3B%20%27%2C%0A%09%20%20%28%28r%20*%201000%29%20/%20t2%29%20printString%2C%20%27%20sends/sec%27'),
+messageSends: ["whileTrue:", "millisecondsToRun:", "benchmark", unescape("%3C"), unescape("*"), "benchFib", unescape("+"), unescape("%2C"), "printString", unescape("/")],
+referencedClasses: [smalltalk.Date]
+}),
+smalltalk.Number);
+

+ 2 - 6
nodejs/README

@@ -2,13 +2,9 @@ JTalk + Node.js = Awesomeness
 =============================
 These are some experiments of using JTalk together with Node.js:
 
-jtalkc          - a bash script for compiling JTalk programs.
-nodecompile.js  - Node.js javascript code for compiling .st files, used by jtalkc.
-
 hello           - Hello world example with a simple Makefile.
+benchfib        - Port of tinybenchmarks from Squeak.
 trivialserver   - A slightly larger example.
 trivialserver2  - A variation on trivialserver that tries to do more in JTalk.
 
-You will need "node" in your path to try examples.
-
-
+You will need "node" in your path to try all the above.

+ 1 - 3
nodejs/benchfib/Benchfib.st

@@ -6,9 +6,7 @@ Object subclass: #Benchfib
 
 main
 
-	| result |
-	result := 0 tinyBenchmarks.
-	{'console.log(''0 tinyBenchmarks => '' + result);'}
+	console log: '0 tinyBenchmarks => ', 0 tinyBenchmarks
 ! !
 
 !Number methodsFor: '*Benchfib'!

+ 2 - 2
nodejs/benchfib/Makefile

@@ -1,8 +1,8 @@
 Program.js: Benchfib.st
-	../jtalkc -N -m Benchfib Benchfib.st Program
+	../../bin/jtalkc -N -m Benchfib Benchfib.st Program
 
 run: Program.js
 	./benchfib
 
 clean:
-	rm Program.js Benchfib.js
+	rm Program.js* Benchfib.js

+ 1 - 1
nodejs/hello/Hello.st

@@ -5,7 +5,7 @@ Object subclass: #Hello
 !Hello class methodsFor: 'main'!
 
 main
-	{'console.log(smalltalk.Hello._new()._hello());'}
+	console log: Hello new hello
 ! ! 
 
 !Hello methodsFor: 'printing'!

+ 1 - 1
nodejs/hello/Makefile

@@ -1,5 +1,5 @@
 Program.js: Hello.st
-	../jtalkc -N -m Hello Hello.st Program
+	../../bin/jtalkc -N -m Hello Hello.st Program
 
 run: Program.js
 	./hello

+ 3 - 7
nodejs/hello/README

@@ -1,17 +1,13 @@
-Trivial Node.js example in JTalk:
+Trivial Node.js example in JTalk that also uses the Google Closure compiler
+if ~/compiler.jar is present.
 
 Hello.st - source code.
 hello    - trivial bash script to run resulting program.
-main.js  - small "doit" to actually run code. Will be added by ntalkc.
 Makefile - trivial makefile, read it.
 
-Hello.js - produced when you run make. Contains JTalk + Hello.st + main.js
+Hello.js - produced when you run make. Contains JTalk + Hello.st + a main call
 
 To play, do this:
 
-make run
-
-...or:
-
 make
 ./hello

+ 2 - 2
nodejs/trivialserver/Makefile

@@ -1,5 +1,5 @@
-Program.js: TrivialServer.st main.js
-	../jtalkc -N -M main.js TrivialServer.st Program
+Program.js: TrivialServer.st
+	../../bin/jtalkc -N -m TrivialServer TrivialServer.st Program
 
 run: Program.js
 	./trivial

+ 0 - 18
nodejs/trivialserver/README

@@ -1,18 +0,0 @@
-Trivial Node.js example in JTalk:
-
-TrivialServer.st - source code.
-trivial          - trivial bash script to run resulting program.
-main.js          - small "doit" to actually run code. Will be added by ntalkc.
-Makefile         - trivial makefile, read it.
-
-TrivialServer.js - produced when you run make.
-Program.js       - Contains JTalk + TrivialServer.js + main.js
-
-To play, do this:
-
-make run
-
-...or:
-
-make
-./trivial

+ 21 - 4
nodejs/trivialserver/TrivialServer.st

@@ -9,15 +9,14 @@ initialize
 
 !TrivialServer methodsFor: 'processing'!
 process: aRequest
-
         | hostname httpVersion stream |
 	counter := counter + 1.
 
         "Calling a method in a js module"
-	hostname := {'os.hostname()'}.
+	hostname := os hostname.
 
         "Accessing a property of js HTTP request object"
-        httpVersion := {'aRequest.httpVersion'}.
+        httpVersion := aRequest httpVersion.
 
         stream := String new writeStream.
 	stream
@@ -25,9 +24,27 @@ process: aRequest
 		nextPutAll: '<p>OS hostname: ', hostname, '</p>';
 		nextPutAll: '<p>Number of requests: ', counter asString, '</p></html>'.
 	^stream contents
+!
+
+start
+        | block obj |
+        block := [:req :res |
+           {'res.writeHead(200, {''Content-Type'': ''text/html''});'}.
+           res end: (self process: req)].
+
+        (http createServer: block)
+                listen: #(1337 '127.0.0.1').
+        console log: 'TrivialServer running at http://127.0.0.1:1337/'
 ! !
 
+
 !TrivialServer class methodsFor: 'initialization'!
 initialize
-	{'os = require(''os'');'}
+        "We require these Node modules."
+
+	{'os = require(''os''), http = require(''http'');'}
+!
+
+main
+	self new start
 ! !

+ 0 - 9
nodejs/trivialserver/main.js

@@ -1,9 +0,0 @@
-var http = require('http');
-// Instantiate a JTalk object to process requests
-var server = smalltalk.TrivialServer._new();
-http.createServer(function (req, res) {
-  res.writeHead(200, {'Content-Type': 'text/html'});
-  // Let the JTalk object process it
-  res.end(server._process_(req));
-}).listen(1337, "127.0.0.1");
-console.log('TrivialServer running at http://127.0.0.1:1337/');

+ 0 - 8
nodejs/trivialserver2/Makefile

@@ -1,8 +0,0 @@
-Program.js: TrivialServer.st
-	../jtalkc -N -m TrivialServer TrivialServer.st Program
-
-run: Program.js
-	./trivial
-
-clean:
-	rm Program.js TrivialServer.js

+ 0 - 4
nodejs/trivialserver2/README

@@ -1,4 +0,0 @@
-Slight variation on ../trivialserver but this one tries to do more Node
-stuff from Smalltalk. Note that we can use a block as a function callback.
-It would be nice if we could improve more on JTalk's ability to call javascript
-code directly.

+ 0 - 49
nodejs/trivialserver2/TrivialServer.st

@@ -1,49 +0,0 @@
-Object subclass: #TrivialServer
-        instanceVariableNames: 'counter'
-        category: 'TrivialServer'!
-
-!TrivialServer methodsFor: 'initializing'!
-initialize
-        counter := 0
-! !
-
-!TrivialServer methodsFor: 'processing'!
-process: aRequest
-        | hostname httpVersion stream |
-	counter := counter + 1.
-
-        "Calling a method in a js module"
-	hostname := {'os.hostname()'}.
-
-        "Accessing a property of js HTTP request object"
-        httpVersion := {'aRequest.httpVersion'}.
-
-        stream := String new writeStream.
-	stream
-		nextPutAll: '<html><p>Request HTTP version: ', httpVersion, '</p>';
-		nextPutAll: '<p>OS hostname: ', hostname, '</p>';
-		nextPutAll: '<p>Number of requests: ', counter asString, '</p></html>'.
-	^stream contents
-!
-
-start
-        | block |
-        block := [:req :res |
-           {'res.writeHead(200, {''Content-Type'': ''text/html''});'}.
-           {'res.end(self._process_(req));'}].
-
-        {'http.createServer(block).listen(1337, ''127.0.0.1'');'}.
-        {'console.log(''TrivialServer running at http://127.0.0.1:1337/'');'}
-! !
-
-
-!TrivialServer class methodsFor: 'initialization'!
-initialize
-        "We require these Node modules."
-
-	{'os = require(''os''), http = require(''http'');'}
-!
-
-main
-	self new start
-! !

+ 0 - 1
nodejs/trivialserver2/trivial

@@ -1 +0,0 @@
-node Program.js $@

+ 70 - 0
st/Benchfib.st

@@ -0,0 +1,70 @@
+Object subclass: #Benchfib
+	instanceVariableNames: ''
+	category: 'Benchfib'!
+
+!Benchfib class methodsFor: 'not yet classified'!
+
+main
+
+	| result |
+	result := 0 tinyBenchmarks.
+	{'console.log(''0 tinyBenchmarks => '' + result);'}
+! !
+
+!Number methodsFor: '*Benchfib'!
+
+benchFib
+	"Handy send-heavy benchmark"
+	"(result // seconds to run) = approx calls per second"
+	" | r t |
+	  t := Time millisecondsToRun: [r := 26 benchFib].
+	  (r * 1000) // t"
+	"138000 on a Mac 8100/100"
+	^ self < 2
+		ifTrue: [1] 
+		ifFalse: [(self-1) benchFib + (self-2) benchFib + 1]
+!
+
+benchmark  "Handy bytecode-heavy benchmark"
+	"(500000 // time to run) = approx bytecodes per second"
+	"5000000 // (Time millisecondsToRun: [10 benchmark]) * 1000"
+	"3059000 on a Mac 8100/100"
+    | size flags prime k count |
+    size := 8190.
+    1 to: self do:
+        [:iter |
+        count := 0.
+        flags := Array new.
+        size timesRepeat: [ flags add: true].
+        1 to: size do:
+            [:i | (flags at: i) ifTrue:
+                [prime := i+1.
+                k := i + prime.
+                [k <= size] whileTrue:
+                    [flags at: k put: false.
+                    k := k + prime].
+                count := count + 1]]].
+    ^ count
+!
+
+tinyBenchmarks
+	"Report the results of running the two tiny Squeak benchmarks.
+	ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results"
+	"0 tinyBenchmarks"
+	"On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec"
+	"On a 400 MHz PII/Win98:  18028169 bytecodes/sec; 1081272 sends/sec"
+	| t1 t2 r n1 n2 |
+	n1 := 1.
+	[t1 := Date millisecondsToRun: [n1 benchmark].
+	t1 < 1000] whileTrue:[n1 := n1 * 2]. "Note: #benchmark's runtime is about O(n)"
+
+	n2 := 28.
+	[t2 := Date millisecondsToRun: [r := n2 benchFib].
+	t2 < 1000] whileTrue:[n2 := n2 + 1]. 
+	"Note: #benchFib's runtime is about O(k^n),
+		where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...."
+
+	^ ((n1 * 500000 * 1000) / t1) printString, ' bytecodes/sec; ',
+	  ((r * 1000) / t2) printString, ' sends/sec'
+! !
+