[PATCH] GNU Smalltalk/gnuplot bindings

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] GNU Smalltalk/gnuplot bindings

Paolo Bonzini
This is something I needed for other things.  It looks nice, so I'm
committing it.

It is based on the Squeak bindings from Igor Stasenko, but only a couple
of classes remain from his code.  Everything else has been heavily
refactored and rewritten.  Additional features include expressing
functions with Smalltalk blocks, using files as data sources, curve
fitting, and a lot of utility constructor methods.

(Note: despite being in RC mode, I have no problem committing new
packages as far as they don't interfere with the kernel.  If you have
any, just tell.)

Paolo

* looking for [hidden email]--2004b/smalltalk--devo--2.2--patch-638 to compare with
* comparing to [hidden email]--2004b/smalltalk--devo--2.2--patch-638
A/ packages/gnuplot
A  packages/gnuplot/2D.st
A  packages/gnuplot/Base.st
A  packages/gnuplot/ChangeLog
A  packages/gnuplot/Examples.st
A  packages/gnuplot/Expressions.st
A  packages/gnuplot/Terminals.st
A  packages/gnuplot/package.xml
M  configure.ac
M  NEWS

* modified files

--- orig/NEWS
+++ mod/NEWS
@@ -1085,6 +1085,8 @@ o   Database manager with MySQL driver
 
 o   Emacs Smalltalk mode back from the dead (thanks to David Forster)
 
+o   GNUPlot bindings
+
 o   GTK+ bindings support callbacks and GTK+ 2.x
 
 o   NetClientsBase is integrated in the base image.  FileStreams support


--- orig/configure.ac
+++ mod/configure.ac
@@ -315,6 +315,7 @@ GST_PACKAGE_ENABLE([Iconv], [iconv],
   [Makefile], [iconv.la])
 GST_PACKAGE_ENABLE([Java], [java])
 GST_PACKAGE_ENABLE([Digest], [digest], [], [], [Makefile], [digest.la])
+GST_PACKAGE_ENABLE([GNUPlot], [gnuplot])
 
 GST_PACKAGE_ENABLE([NCurses],
   [ncurses],



* added files

--- /dev/null
+++ mod/packages/gnuplot/2D.st
@@ -0,0 +1,599 @@
+"======================================================================
+|
+|   GNUPlot bindings, GPPlot and related classes
+|
+|
+ ======================================================================"
+
+"======================================================================
+|
+| Copyright 2007 Free Software Foundation, Inc.
+| Written by Paolo Bonzini.
+|
+| This file is part of GNU Smalltalk.
+|
+| GNU Smalltalk is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| GNU Smalltalk is distributed in the hope that it will be useful, but
+| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+| or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+| for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with GNU Smalltalk; see the file COPYING.  If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02110-1301, USA.  
+|
+ ======================================================================"
+
+GPAbstractPlot subclass: GPPlot [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a single ''plot'' command.'>
+
+    GPPlot class >> defaultParamsClass [
+        ^GPPlotParams
+    ]
+
+    function: exprBlock [
+ <category: 'building'>
+ | expr |
+ expr := exprBlock value: (GPVariableExpression on: $x).
+        ^self add: (GPFunctionSeries on: expr)
+    ]
+
+    lrSteps: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYSeries on: aDataSourceOrArray)
+ style: 'steps';
+ yourself)
+    ]
+
+    lrSteps: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self lrSteps: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    ulSteps: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYSeries on: aDataSourceOrArray)
+ style: 'fsteps';
+ yourself)
+    ]
+
+    ulSteps: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self ulSteps: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    centerSteps: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYSeries on: aDataSourceOrArray)
+ style: 'histeps';
+ yourself)
+    ]
+
+    centerSteps: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self centerSteps: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    dots: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYSeries on: aDataSourceOrArray)
+ style: 'dots';
+ yourself)
+    ]
+
+    dots: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self dots: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    points: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYSeries on: aDataSourceOrArray)
+ style: 'points';
+ yourself)
+    ]
+
+    points: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self points: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    impulses: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYSeries on: aDataSourceOrArray)
+ style: 'impulses';
+ yourself)
+    ]
+
+    impulses: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self impulses: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    vectors: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPVectorSeries on: aDataSourceOrArray)
+ style: 'vectors';
+ yourself)
+    ]
+
+    vectors: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self vectors: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    boxes: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPBoxSeries on: aDataSourceOrArray)
+ style: 'boxes';
+ yourself)
+    ]
+
+    boxes: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self boxes: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    xyErrorBoxes: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYErrorSeries on: aDataSourceOrArray)
+ style: 'xyerrorboxes';
+ yourself)
+    ]
+
+    xyErrorBoxes: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self xyErrorBoxes: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    xErrorBoxes: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXErrorBoxSeries on: aDataSourceOrArray)
+ style: 'xerrorboxes';
+ yourself)
+    ]
+
+    xErrorBoxes: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self xErrorBoxes: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    errorBoxes: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPErrorBoxSeries on: aDataSourceOrArray)
+ style: 'yerrorboxes';
+ yourself)
+    ]
+
+    errorBoxes: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self errorBoxes: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    candleSticks: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPFinancialDataSeries on: aDataSourceOrArray)
+ style: 'candlesticks';
+ yourself)
+    ]
+
+    candleSticks: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self candleSticks: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    financeBars: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPFinancialDataSeries on: aDataSourceOrArray)
+ style: 'financebars';
+ yourself)
+    ]
+
+    financeBars: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self financeBars: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    lines: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYSeries on: aDataSourceOrArray)
+ style: 'lines';
+ yourself)
+    ]
+
+    lines: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self lines: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    xyErrorBars: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXYErrorSeries on: aDataSourceOrArray)
+ style: 'xyerrorbars';
+ yourself)
+    ]
+
+    xyErrorBars: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self xyErrorBars: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    xErrorBars: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPXErrorSeries on: aDataSourceOrArray)
+ style: 'xerrorbars';
+ yourself)
+    ]
+
+    xErrorBars: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self xErrorBars: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+
+    errorBars: aDataSourceOrArray [
+ <category: 'building'>
+ ^self add: ((GPErrorSeries on: aDataSourceOrArray)
+ style: 'errorbars';
+ yourself)
+    ]
+
+    errorBars: aDataSourceOrArray with: aBlock [
+ <category: 'building'>
+ | series |
+ series := self errorBars: aDataSourceOrArray.
+ aBlock value: series.
+ ^series
+    ]
+]
+
+GPObject subclass: GPPlotParams [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define parameters for a ''plot'' command.'>
+
+]
+
+GPDataSeries subclass: GPXYSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for (x,y) values.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1 }
+    ]
+
+    data: expr [
+ self columns: { expr asGPExpression }
+    ]
+
+    x: xExpr y: yExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression  }
+    ]
+]
+
+GPXYSeries subclass: GPBoxSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for (x,y) values
+optionally specifying a box width.'>
+
+    x: xExpr y: yExpr width: widthExpr [
+ self columns: { xExpr asGPExpression. yExpr asGPExpression.
+ widthExpr asGPExpression }
+    ]
+]
+
+GPDataSeries subclass: GPErrorSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for (x,y) values
+with a (vertical) error bar.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1. GPColumnRef column: 2.
+ GPColumnRef column: 3 }
+    ]
+
+    x: xExpr y: yExpr error: errExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ errExpr asGPExpression }
+    ]
+
+    x: xExpr min: minExpr max: maxExpr [
+ | y err min max |
+ min := minExpr asGPExpression.
+        max := maxExpr asGPExpression.
+ y := (min + max) / 2.
+ err := (max - min) / 2.
+ self columns: { xExpr asGPExpression.  y. err }
+    ]
+
+    x: xExpr y: yExpr min: minExpr max: maxExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ minExpr asGPExpression.
+ maxExpr asGPExpression }
+    ]
+]
+
+GPErrorSeries subclass: GPErrorBoxSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for (x,y) values
+with an adjustable width and a (vertical) error bar.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1. GPColumnRef column: 2.
+ GPColumnRef column: 3 }
+    ]
+
+    x: xExpr y: yExpr error: errExpr width: widthExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ errExpr asGPExpression.
+ widthExpr asGPExpression }
+    ]
+
+    x: xExpr min: minExpr max: maxExpr width: widthExpr [
+ | y err min max |
+ min := minExpr asGPExpression.
+        max := maxExpr asGPExpression.
+ y := (min + max) / 2.
+ err := (max - min) / 2.
+ self columns: { xExpr asGPExpression.  y. err.
+ widthExpr asGPExpression }
+    ]
+
+    x: xExpr y: yExpr min: minExpr max: maxExpr width: widthExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ minExpr asGPExpression.
+ maxExpr asGPExpression.
+ widthExpr asGPExpression }
+    ]
+]
+
+GPDataSeries subclass: GPXErrorSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for (x,y) values
+with an horizontal error bar.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1. GPColumnRef column: 2.
+ GPColumnRef column: 3 }
+    ]
+
+    x: xExpr error: errExpr y: yExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ errExpr asGPExpression }
+    ]
+
+    min: minExpr max: maxExpr y: yExpr [
+ | x err min max |
+ min := minExpr asGPExpression.
+        max := maxExpr asGPExpression.
+ x := (min + max) / 2.
+ err := (max - min) / 2.
+ self columns: { x. yExpr asGPExpression. err }
+    ]
+
+    x: xExpr min: minExpr max: maxExpr y: yExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ minExpr asGPExpression.
+ maxExpr asGPExpression }
+    ]
+]
+
+GPXErrorSeries subclass: GPXErrorBoxSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for (x,y) values
+with an adjustable width and an horizontal error bar.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1. GPColumnRef column: 2.
+ GPColumnRef column: 3 }
+    ]
+
+    x: xExpr error: errExpr y: yExpr width: widthExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ errExpr asGPExpression.
+ widthExpr asGPExpression }
+    ]
+
+    min: minExpr max: maxExpr y: yExpr width: widthExpr [
+ | x err min max |
+ min := minExpr asGPExpression.
+        max := maxExpr asGPExpression.
+ x := (min + max) / 2.
+ err := (max - min) / 2.
+ self columns: { x. yExpr asGPExpression. err.
+ widthExpr asGPExpression }
+    ]
+
+    x: xExpr min: minExpr max: maxExpr y: yExpr width: widthExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ minExpr asGPExpression.
+ maxExpr asGPExpression.
+ widthExpr asGPExpression }
+    ]
+]
+
+GPDataSeries subclass: GPXYErrorSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for (x,y) values
+with 2D error bars.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1. GPColumnRef column: 2.
+ GPColumnRef column: 3. GPColumnRef column: 4 }
+    ]
+
+    x: xExpr error: xErrExpr y: yExpr error: yErrExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ xErrExpr asGPExpression.
+ yErrExpr asGPExpression }
+    ]
+
+    xMin: xMinExpr max: xMaxExpr yMin: yMinExpr max: yMaxExpr [
+ | x y xErr yErr xMin yMin xMax yMax |
+ xMin := xMinExpr asGPExpression.
+        xMax := xMaxExpr asGPExpression.
+ x := (xMin + xMax) / 2.
+ xErr := (xMax - xMin) / 2.
+ yMin := yMinExpr asGPExpression.
+        yMax := yMaxExpr asGPExpression.
+ y := (yMin + yMax) / 2.
+ yErr := (yMax - yMin) / 2.
+ self columns: { x. y. xErr. yErr }
+    ]
+
+    x: xExpr min: xMinExpr max: xMaxExpr y: yExpr min: yMinExpr max: yMaxExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ xMinExpr asGPExpression.
+ xMaxExpr asGPExpression.
+ yMinExpr asGPExpression.
+ yMaxExpr asGPExpression }
+    ]
+]
+
+GPDataSeries subclass: GPVectorSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for vector fields.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1. GPColumnRef column: 2.
+ GPColumnRef column: 3. GPColumnRef column: 4 }
+    ]
+
+    x: xExpr dx: dxExpr y: yExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ dxExpr asGPExpression.
+ 0 asGPExpression }
+    ]
+
+    x: xExpr y: yExpr dx: dxExpr dy: dyExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ dxExpr asGPExpression.
+ dyExpr asGPExpression }
+    ]
+
+    x: xExpr dx: dxExpr y: yExpr dy: dyExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ dxExpr asGPExpression.
+ dyExpr asGPExpression }
+    ]
+
+    x1: x1Expr x2: x2Expr y: yExpr [
+ | x1 |
+ x1 := x1Expr asGPExpression.
+ self columns: { x1.  yExpr asGPExpression.
+ x2Expr asGPExpression - x1.
+ 0 asGPExpression }
+    ]
+
+    x: xExpr y: yExpr dy: dyExpr [
+ self columns: { xExpr asGPExpression.
+ yExpr asGPExpression.
+ 0 asGPExpression.
+ dyExpr asGPExpression }
+    ]
+
+    x: xExpr y1: y1Expr y2: y2Expr [
+ | y1 |
+ y1 := y1Expr asGPExpression.
+ self columns: { xExpr asGPExpression.  y1.
+ 0 asGPExpression.
+ y2Expr asGPExpression - y1 }
+    ]
+
+    x1: x1Expr x2: x2Expr y1: y1Expr y2: y2Expr [
+ | x1 y1 |
+ x1 := x1Expr asGPExpression.
+ y1 := y1Expr asGPExpression.
+ self columns: { x1.  y1.
+ x2Expr asGPExpression - x1.
+ y2Expr asGPExpression - y1 }
+    ]
+]
+
+GPDataSeries subclass: GPFinancialDataSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a data series for
+low/high/open/close values.'>
+
+    initialize [
+ self columns: { GPColumnRef column: 1. GPColumnRef column: 2.
+ GPColumnRef column: 3. GPColumnRef column: 4.
+ GPColumnRef column: 5 }
+    ]
+
+    x: xExpr open: openExpr low: lowExpr high: highExpr close: closeExpr [
+ self columns: { xExpr asGPExpression.
+ openExpr asGPExpression.
+ lowExpr asGPExpression.
+ highExpr asGPExpression.
+ closeExpr asGPExpression }
+    ]
+
+]
+


--- /dev/null
+++ mod/packages/gnuplot/Base.st
@@ -0,0 +1,771 @@
+"======================================================================
+|
+|   GNUPlot bindings base classes
+|
+|
+ ======================================================================"
+
+"======================================================================
+|
+| Copyright 2007 Free Software Foundation, Inc.
+| Written by Paolo Bonzini.
+|
+| This file is part of GNU Smalltalk.
+|
+| GNU Smalltalk is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| GNU Smalltalk is distributed in the hope that it will be useful, but
+| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+| or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+| for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with GNU Smalltalk; see the file COPYING.  If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02110-1301, USA.  
+|
+ ======================================================================"
+
+"The GPSeriesParams class is Copyright (c) 2007 Igor Stasenko
+ and licensed under the X11 license.
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the `Software'), to deal in the Software without
+    restriction, including without limitation the rights to use,
+    copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following
+    conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED `AS IS', WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS IN THE SOFTWARE."
+
+Object subclass: GPObject [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used to define aspects of a plot.'>
+
+    GPObject class >> new [
+ <category: 'instance creation'>
+        ^super new initialize
+    ]
+
+    asString [
+ <category: 'printing'>
+ ^self displayString
+    ]
+
+    initialize [
+ <category: 'instance creation'>
+    ]
+
+    displayOn: aStream [
+ <category: 'printing'>
+    ]
+
+    printOn: aStream [
+ <category: 'printing'>
+ self class printOn: aStream.
+ aStream nextPut: $(.
+ self displayOn: aStream.
+ aStream nextPut: $)
+    ]
+]
+
+GPObject subclass: GNUPlot [
+    | commands terminal |
+    
+    <category: 'GNUPlot'>
+    <comment: 'I am the main class to interact with GNU plot.
+ See GNUPlotExamples for usage examples'>
+
+    CommandPath := nil.
+
+    GNUPlot class >> commandPath [
+ <category: 'executing'>
+ ^CommandPath ifNil: [ self defaultCommandPath ]
+    ]
+
+    GNUPlot class >> commandPath: aString [
+ <category: 'executing'>
+ CommandPath := aString
+    ]
+
+    GNUPlot class >> defaultCommandPath [
+ <category: 'executing'>
+ ^(Smalltalk hostSystem indexOfSubCollection: '-mingw' ifAbsent: [ 0 ]) > 0
+    ifTrue: [ 'pgnuplot.exe -' ]
+    ifFalse: [ 'gnuplot' ]
+    ]
+
+    GNUPlot class >> newPipe: dir [
+ <category: 'executing'>
+ ^FileStream popen: self commandPath dir: dir
+    ]
+
+    initialize [
+ <category: 'initialize-release'>
+ commands := OrderedCollection new
+    ]
+
+    output: aFileName [
+ <category: 'commands'>
+ self terminal isInteractive ifTrue: [ self terminal: GPPngTerminal new ].
+ self terminal output: aFileName
+    ]
+
+    execute [
+ ^self terminal display: self
+    ]
+
+    plot [
+ "Adding a plot command and returning GPPlot instance ready for accepting parameters"
+
+ <category: 'commands'>
+ ^commands add: GPPlot new
+    ]
+
+    displayOn: aStream [
+ <category: 'converting'>
+ commands do:
+ [:each |
+ each isString
+    ifTrue: [aStream nextPutAll: each]
+    ifFalse: [each displayOn: aStream]]
+    separatedBy: [aStream nl]
+    ]
+
+    terminal [
+ <category: 'accessing'>
+ ^terminal ifNil: [ terminal := GPInteractiveTerminal new ].
+    ]
+
+    terminal: aGPTerminal [
+ <category: 'commands'>
+ terminal := aGPTerminal
+    ]
+]
+
+GPObject subclass: GPSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used to define a plotted function or data set.'>
+
+    | params |
+    GPSeries class [
+ | defaultParams |
+ defaultParamsClass [
+    ^GPSeriesParams
+ ]
+
+ defaultParams [
+            ^defaultParams ifNil: [ defaultParams := self defaultParamsClass new ]
+ ]
+    ]
+
+    defaultTitle [
+ self subclassResponsibility
+    ]
+
+    params [
+ ^params ifNil: [ params := self class defaultParams copy ].
+    ]
+
+    printDataOn: aStream [
+ <category: 'printing'>
+    ]
+
+    displayOn: aStream [
+ <category: 'printing'>
+ | theParameters |
+ theParameters := params ifNil: [ self class defaultParams ].
+ theParameters displayOn: aStream for: self
+    ]
+
+    displayPrologOn: aStream into: defs [
+    ]
+]
+
+GPObject subclass: GPSeriesParams [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used to customize the appearance of a plotted
+function or data set.'>
+
+    | x2 y2 title params |
+    
+    <category: 'GNUPlot'>
+    <comment: nil>
+
+    y2 [
+ <category: 'axes'>
+ ^y2 ifNil: [ false ]
+    ]
+
+    y2: aBoolean [
+ <category: 'axes'>
+ y2 := aBoolean
+    ]
+
+    x2 [
+ <category: 'axes'>
+ ^x2 ifNil: [ false ]
+    ]
+
+    x2: aBoolean [
+ <category: 'axes'>
+ x2 := aBoolean
+    ]
+
+    initialize [
+ <category: 'initialize-release'>
+ params := Dictionary new
+    ]
+
+    lineColor: aColorSpec [
+ "aColorSpec has one of the following forms:
+ rgbcolor 'colorname'
+ rgbcolor '#RRGGBB'
+ rgbcolor variable
+ palette frac <val> # <val> runs from 0 to 1
+ palette cb <value> # <val> lies within cbrange
+ palette z
+
+ 'rgb variable' requires an additional column in the using specifier, and is only available in 3D plotting
+ mode (splot). The extra column is interpreted as a 24-bit packed RGB triple. These are most easily
+ specified in a data file as hexidecimal values (see above).
+
+ Example:
+ rgb(r,g,b) = 65536 * int(r) + 256 * int(g) + int(b)
+ splot 'data' using 1:2:3:(rgb($1,$2,$3)) with points lc rgb variable
+
+ The color palette is a linear gradient of colors that smoothly maps a single numerical value onto a
+ particular color. Two such mappings are always in effect. palette frac maps a fractional value between
+ 0 and 1 onto the full range of the color palette. palette cb maps the range of the color axis onto the
+ same palette. See set cbrange. See also set colorbox. You can use either of these
+ to select a constant color from the current palette.
+ 'palette z' maps the z value of each plot segment or plot element into the cbrange mapping of the
+ palette. This allows smoothly-varying color along a 3d line or surface. This option applies only to 3D
+ plots (splot).
+ "
+
+ <category: 'styles'>
+ "FIXME"
+ params at: #linecolor
+    put: aColorSpec "(aColorSpec isColor
+    ifTrue: ['rgbcolor ''' , aColorSpec asHTMLColor , '''']
+    ifFalse: [aColorSpec])"
+    ]
+
+    lineStyle: aNumber [
+ "Tells plot to use previously defined line style (via set style line <number> ... command )"
+
+ <category: 'styles'>
+ params at: #linestyle put: aNumber
+    ]
+
+    lineType: aNumber [
+ "If you wish to choose the line or point type for a single plot, <line type> and <point type> may be
+ specified. These are positive integer constants (or expressions) that specify the line type and point type
+ to be used for the plot."
+
+ <category: 'styles'>
+ params at: #linetype put: aNumber
+    ]
+
+    lineWidth: aParam [
+ "You may also scale the line width and point size for a plot by using <line width> and <point size>,
+ which are specified relative to the default values for each terminal. The pointsize may also be altered
+ globally — see set pointsize (p. 111) for details. But note that both <point size> as set here and
+ as set by set pointsize multiply the default point size — their effects are not cumulative. That is, set
+ pointsize 2; plot x w p ps 3 will use points three times default size, not six."
+
+ <category: 'styles'>
+ params at: #linewidth put: aParam
+    ]
+
+    notitle [
+ "The line title and sample can be omitted from the key by using the keyword notitle"
+
+ <category: 'title'>
+ title := 'notitle'
+    ]
+
+    pointSize: aParam [
+ "You may also scale the line width and point size for a plot by using <line width> and <point size>,
+ which are specified relative to the default values for each terminal. The pointsize may also be altered
+ globally — see set pointsize (p. 111) for details. But note that both <point size> as set here and
+ as set by set pointsize multiply the default point size — their effects are not cumulative. That is, set
+ pointsize 2; plot x w p ps 3 will use points three times default size, not six.
+
+ It is also possible to specify pointsize variable either as part of a line style or for an individual plot.
+ In this case one extra column of input is required, i.e. 3 columns for a 2D plot and 4 columns for a 3D
+ splot. The size of each individual point is determined by multiplying the global pointsize by the value
+ read from the data file."
+
+ <category: 'styles'>
+ params at: #pointsize put: aParam
+    ]
+
+    pointType: aNumber [
+ "If you wish to choose the line or point type for a single plot, <line type> and <point type> may be
+ specified. These are positive integer constants (or expressions) that specify the line type and point type
+ to be used for the plot."
+
+ <category: 'styles'>
+ params at: #pointtype put: aNumber
+    ]
+
+    axes [
+ | axes |
+ axes := 'axes x1y1' copy.
+ self x2 ifTrue: [ axes at: 7 put: $2 ].
+ self y2 ifTrue: [ axes at: 9 put: $2 ].
+ ^axes
+    ]
+
+    titleFor: aSeries [
+ title notNil ifTrue: [ ^title ].
+ ^aSeries defaultTitle
+    ifNil: [ 'notitle' ]
+    ifNotNil: [ :defaultTitle | 'title ''%1''' % { defaultTitle } ]
+    ]
+
+    displayOn: aStream [
+ ^self displayOn: aStream for: nil
+    ]
+
+    displayOn: aStream for: aSeries [
+ "#axes #title #with comes first, then rest"
+
+ <category: 'converting'>
+ | d |
+ d := OrderedCollection new.
+ (self x2 or: [ self y2 ])
+    ifTrue: [ aStream space; nextPutAll: self axes ].
+ (title notNil or: [ aSeries notNil ])
+    ifTrue: [ aStream space; nextPutAll: (self titleFor: aSeries) ].
+ params keysAndValuesDo:
+ [:key :val |
+ aStream
+    space; nextPutAll: key;
+    space; nextPutAll: val]
+    ]
+
+    title: aTitle [
+ "A line title for each function and data set appears in the key, accompanied by a sample of the line and/or
+ symbol used to represent it.
+
+ If key autotitles is set (which is the default) and neither title nor notitle are specified the line title is
+ the function name or the file name as it appears on the plot command. If it is a file name, any datafile
+ modifiers specified will be included in the default title.
+ "
+
+ "sig: using single quotes to prevent backslash conversion"
+
+ <category: 'title'>
+ title := 'title ''%1''' % { aTitle asString }
+    ]
+]
+
+GPSeries subclass: GPFunctionSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used to define a plotted function.'>
+
+    | expression range |
+    GPFunctionSeries class >> on: expr [
+ <category: 'instance creation'>
+ ^self new expression: expr
+    ]
+
+    defaultTitle [
+ ^String streamContents: [ :str | expression displayAsOperandOn: str ]
+    ]
+
+    expression [
+ <category: 'accessing'>
+ ^expression
+    ]
+
+    expression: expr [
+ <category: 'private - initialization'>
+ expression := expr asGPExpression
+    ]
+
+    from: a to: b [
+ <category: 'accessing'>
+ range := { a. b }
+    ]
+
+    from [
+ ^range ifNotNil: [ :r | r first ]
+    ]
+
+    to [
+ ^range ifNotNil: [ :r | r second ]
+    ]
+
+    displayOn: aStream [
+ range isNil ifFalse: [
+    aStream
+ nextPut: $[;
+ display: range first;
+ nextPut: $:;
+ display: range second;
+ nextPut: $];
+ space ].
+ expression displayOn: aStream.
+ super displayOn: aStream
+    ]
+
+    displayPrologOn: aStream into: defs [
+ expression displayPrologOn: aStream into: defs
+    ]
+]
+
+GPSeries subclass: GPDataSeries [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used to define a plotted data set.'>
+
+    | columns dataSource style |
+    "GPDataSeries >> defaultParamsClass [
+ ^GPDataSeriesParams
+    ]"
+
+    GPDataSeries class >> on: aDataSource [
+ <category: 'instance creation'>
+ ^self new dataSource: aDataSource asGPDataSource
+    ]
+
+    columns [
+ <category: 'accessing'>
+ ^columns
+    ]
+
+    columns: anArray [
+ <category: 'private - initialization'>
+ columns := anArray
+    ]
+
+    dataSource [
+ <category: 'accessing'>
+ ^dataSource
+    ]
+
+    dataSource: aDataSource [
+ <category: 'private - initialization'>
+ dataSource := aDataSource
+    ]
+
+    defaultTitle [
+ ^dataSource defaultTitle
+    ]
+
+    style: aString [
+ <category: 'private - initialization'>
+ style := aString
+    ]
+
+    displayOn: aStream [
+ dataSource displayOn: aStream.
+ aStream nextPutAll: ' using '.
+ columns
+    do: [ :each | each displayOn: aStream ]
+    separatedBy: [ aStream nextPut: $: ].
+ aStream nextPutAll: ' with '; nextPutAll: style; space.
+ super displayOn: aStream.
+    ]
+
+    printDataOn: aStream [
+ dataSource printDataOn: aStream.
+ aStream nl.
+    ]
+
+    displayPrologOn: aStream into: defs [
+ columns do: [ :each | each displayPrologOn: aStream into: defs ]
+    ]
+]
+
+GPObject subclass: GPDataSource [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used to define the source of a plotted data set.'>
+
+    defaultTitle [
+ self subclassResponsibility
+    ]
+
+    printDataOn: aStream [
+ <category: 'printing'>
+ "Do nothing by default"
+    ]
+]
+
+GPDataSource subclass: GPFileDataSource [
+    <category: 'GNUPlot'>
+    <comment: 'My instances allow to use a file as the source of a plot.'>
+
+    | fileName |
+    GPFileDataSource class >> on: aString [
+ <category: 'instance creation'>
+ ^self new fileName: aString
+    ]
+
+    defaultTitle [
+ ^fileName
+    ]
+
+    fileName [
+ <category: 'accessing'>
+ ^fileName
+    ]
+
+    fileName: aString [
+ <category: 'private - initialization'>
+ fileName := aString
+    ]
+
+    displayOn: aStream [
+ fileName printOn: aStream
+    ]
+]
+
+File extend [
+    asGPDataSource [
+ ^GNUPlot.GPDataSource on: self name
+    ]
+]
+
+GPDataSource subclass: GPSmalltalkDataSource [
+    <category: 'GNUPlot'>
+    <comment: 'My instances allow to use an object, typically a collection,
+as the source of a plot.'>
+
+    | data |
+    GPSmalltalkDataSource class >> on: aString [
+ <category: 'instance creation'>
+ ^self new data: aString
+    ]
+
+    data [
+ <category: 'accessing'>
+ ^data
+    ]
+
+    data: aString [
+ <category: 'private - initialization'>
+ data := aString
+    ]
+
+    defaultTitle [
+ ^nil
+    ]
+
+    displayOn: aStream [
+ '''-''' displayOn: aStream
+    ]
+
+    printData: coll on: aStream separatedBy: aBlock [
+ coll
+    do: [:each |
+                each isNumber
+                    ifTrue: [each printOn: aStream]
+                    ifFalse: [self printData: each on: aStream separatedBy: [aStream space]]]
+            separatedBy: aBlock.
+    ]
+
+    printDataOn: aStream [
+ self printData: data on: aStream separatedBy: [aStream nl].
+        aStream
+            nl;
+            nextPut: $e
+    ]
+
+    Object >> asGPDataSource [
+ ^GNUPlot.GPSmalltalkDataSource on: self
+    ]
+
+    asGPDataSource [
+ ^self
+    ]
+]
+
+GPObject subclass: GPAbstractPlot [
+    <category: 'GNUPlot'>
+    <comment: 'My instance is used to define a single ''plot'' command.'>
+
+    | series params |
+    GPAbstractPlot class >> defaultParamsClass [
+ self subclassResponsibility
+    ]
+
+    params [
+        <category: 'accessing'>
+        ^params ifNil: [ params := self class defaultParamsClass new ].
+    ]
+
+    params: aGPPlotParams [
+        <category: 'accessing'>
+        params := aGPPlotParams.
+    ]
+
+    add: aSeries [
+        <category: 'building'>
+        series isNil ifTrue: [ series := OrderedCollection new ].
+        ^series add: aSeries
+    ]
+
+    function: exprBlock [
+        <category: 'building'>
+        self subclassResponsibility
+    ]
+
+    function: exprBlock with: aBlock [
+        <category: 'building'>
+        | series |
+        series := self function: exprBlock.
+        aBlock value: series.
+        ^series
+    ]
+
+    displayPrologOn: aStream into: defs [
+        params isNil ifFalse: [ params displayOn: aStream ].
+        series do: [:d | d displayPrologOn: aStream into: defs ].
+    ]
+
+    displayOn: aStream [
+        <category: 'printing'>
+ | defs |
+        aStream nextPutAll: 'reset'; nl.
+ defs := Set new.
+        self displayPrologOn: aStream into: defs.
+        aStream nextPutAll: 'plot '.
+        series do: [:d | d displayOn: aStream]
+            separatedBy: [aStream nextPutAll: ' , '].
+        aStream nl.
+        series do: [:d | d printDataOn: aStream]
+            separatedBy: [aStream nl].
+    ]
+]
+GPObject subclass: GPTerminal [
+    
+    <category: 'GNUPlot'>
+    <comment: 'My instances describe an abstract GNU Plot terminal
+(corresponding to the ''set terminal'' command).'>
+
+    displayOn: aStream [
+ <category: 'printing'>
+ aStream
+    nextPutAll: 'set terminal ';
+    nextPutAll: self name;
+    nextPut: Character space.
+ self printOptionsOn: aStream.
+ aStream nl.
+    ]
+
+    printOptionsOn: aStream [
+ <category: 'printing'>
+    ]
+
+    name [
+ "Return a string identifying terminal type"
+
+ <category: 'printing'>
+ self subclassResponsibility
+    ]
+
+    display: aGNUPlot [
+ <category: 'executing'>
+ self subclassResponsibility
+    ]
+
+    display: aGNUPlot on: aStream [
+ <category: 'executing'>
+ ^aStream
+    display: self; nl;
+    display: aGNUPlot;
+    yourself
+    ]
+
+    isInteractive [
+ <category: 'testing'>
+ self subclassResponsibility
+    ]
+]
+
+
+GPTerminal subclass: GPInteractiveTerminal [
+    
+    <category: 'GNUPlot'>
+    <comment: 'My instances describe an abstract GNU Plot terminal
+that plots data on the display.'>
+
+    display: aGNUPlot [
+ <category: 'executing'>
+ | pipe |
+ pipe := GNUPlot newPipe: FileStream write.
+ self display: aGNUPlot on: pipe.
+ pipe close
+    ]
+
+    display: aGNUPlot on: aStream [
+ <category: 'executing'>
+ ^aStream display: aGNUPlot; yourself
+    ]
+
+    isInteractive [
+ <category: 'testing'>
+ ^true
+    ]
+]
+
+GPTerminal subclass: GPFileTerminal [
+    
+    <category: 'GNUPlot'>
+    <comment: 'My instances describe an abstract GNU Plot terminal
+that saves plots to a file.'>
+
+    | output |
+
+    output [
+ <category: 'accessing'>
+ ^output
+    ]
+
+    output: aFileName [
+ <category: 'accessing'>
+ output := aFileName
+    ]
+
+    displayOn: aStream [
+ <category: 'printing'>
+ super displayOn: aStream.
+ aStream
+    nextPutAll: 'set output ';
+    print: (self output ifNil: [ '-' ])
+    ]
+
+    display: aGNUPlot [
+ <category: 'executing'>
+ | pipe |
+ pipe := GNUPlot newPipe: FileStream readWrite.
+ self display: aGNUPlot on: pipe.
+ ^pipe shutdown; contents
+    ]
+
+    isInteractive [
+ <category: 'testing'>
+ ^false
+    ]
+]
+
+


--- /dev/null
+++ mod/packages/gnuplot/ChangeLog
@@ -0,0 +1,7 @@
+2007-11-16  Paolo Bonzini  <[hidden email]>
+
+ * 2D.st: New.
+ * Base.st: New.
+ * Examples.st: New.
+ * Expressions.st: New.
+ * Terminals.st: New.


--- /dev/null
+++ mod/packages/gnuplot/Examples.st
@@ -0,0 +1,152 @@
+"======================================================================
+|
+|   GNUPlot bindings, examples
+|
+|
+ ======================================================================"
+
+"======================================================================
+|
+| Copyright 2007 Free Software Foundation, Inc.
+| Written by Paolo Bonzini.
+|
+| This file is part of GNU Smalltalk.
+|
+| GNU Smalltalk is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| GNU Smalltalk is distributed in the hope that it will be useful, but
+| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+| or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+| for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with GNU Smalltalk; see the file COPYING.  If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02110-1301, USA.  
+|
+ ======================================================================"
+
+GPObject subclass: GNUPlotExamples [
+    
+    <category: 'GNUPlot-Tests and examples'>
+    <comment: 'See class side for methods with examples'>
+
+    GNUPlotExamples class >> example1 [
+ | p |
+ p := GNUPlot new.
+ p plot
+    lines: #(1 2 3 4 5)
+    with: [:series | series params title: 'Title' ].
+ ^p asString
+    ]
+
+    GNUPlotExamples class >> example2 [
+ ^self example2On: nil
+    ]
+
+    GNUPlotExamples class >> example2On: file [
+ | p |
+ p := GNUPlot new.
+ file isNil ifFalse: [
+    p terminal: ((GPPngTerminal new)
+    size: 300 @ 300;
+    "colors: (GPTerminalColors new borders: Color darkGray); FIXME"
+    yourself).
+    p output: file
+ ].
+
+ p plot
+    lines: #(1 5 2 8 3)
+    with: [:series | series params title: 'Title' ].
+ Transcript display: p; nl.
+ p execute
+    ]
+
+    GNUPlotExamples class >> threePlots [
+ ^self threePlotsOn: nil
+    ]
+
+    GNUPlotExamples class >> threePlotsOn: file [
+ | p |
+ p := GNUPlot new.
+ file isNil ifFalse: [
+    p terminal: ((GPPngTerminal new)
+    transparent: true;
+    size: 300 @ 300;
+    "colors: (GPTerminalColors new borders: Color darkGray); FIXME"
+    yourself).
+    p output: file
+ ].
+
+ p plot
+    "first plot"
+    lines: #(1 5 2 8 3)
+    with: [:series | series params title: 'Zig-zag' ];
+
+    "second plot"
+    function: [ :x | x sin ];
+
+    "third plot, notice no title appears"
+    boxes: #(6 3 1 5 4).
+
+ Transcript display: p; nl.
+ p execute
+    ]
+
+    GNUPlotExamples class >> twoPlots [
+ ^self twoPlotsOn: nil
+    ]
+
+    GNUPlotExamples class >> twoPlotsOn: file [
+ | p |
+ p := GNUPlot new.
+ file isNil ifFalse: [
+    p terminal: ((GPPngTerminal new)
+    size: 300 @ 300;
+    "colors: (GPTerminalColors new borders: Color darkGray); FIXME"
+    yourself).
+    p output: file
+ ].
+
+ p plot
+    lines: #(1 5 2 8 3)
+    with: [:series | series params title: 'Zig-zag' ];
+
+    "second plot"
+    function: [ :x | x sin ].
+
+ Transcript display: p; nl.
+ p execute
+    ]
+
+    GNUPlotExamples class >> fit [
+ ^self fitOn: nil
+    ]
+
+    GNUPlotExamples class >> fitOn: file [
+ | p fit data |
+ p := GNUPlot new.
+ file isNil ifFalse: [
+    p terminal: ((GPPngTerminal new)
+    transparent: true;
+    size: 300 @ 300;
+    "colors: (GPTerminalColors new borders: Color darkGray); FIXME"
+    yourself).
+    p output: file
+ ].
+
+ data := #((0.1 0.2) (1 2) (2 1) (3 3) (4 2) (4.9 3.8)).
+
+ p plot
+    points: data with: [ :series |
+ series x: '$1' y: '$2' ];
+    function: [ :x |
+ x fit: data to: [ :a :b | a * x + b ] name: 'f' ].
+
+ Transcript display: p; nl.
+ p execute
+    ]
+]


--- /dev/null
+++ mod/packages/gnuplot/Expressions.st
@@ -0,0 +1,481 @@
+"======================================================================
+|
+|   GNUPlot bindings, expression trees
+|
+|
+ ======================================================================"
+
+"======================================================================
+|
+| Copyright 2007 Free Software Foundation, Inc.
+| Written by Paolo Bonzini.
+|
+| This file is part of GNU Smalltalk.
+|
+| GNU Smalltalk is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| GNU Smalltalk is distributed in the hope that it will be useful, but
+| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+| or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+| for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with GNU Smalltalk; see the file COPYING.  If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02110-1301, USA.  
+|
+ ======================================================================"
+
+GPObject subclass: GPExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used to define plotted functions.'>
+
+    precedence [
+ self subclassResponsibility
+    ]
+
+    printOn: aStream [
+ <category: 'printing'>
+ self class printOn: aStream.
+ aStream nextPut: $(.
+ self displayAsOperandOn: aStream.
+ aStream nextPut: $)
+    ]
+
+    displayPrologOn: aStream into: defs [
+    ]
+
+    displayAsOperandOn: aStream [
+ <category: 'printing'>
+    ]
+
+    displayOn: aStream [
+ <category: 'printing'>
+ aStream nextPut: $(.
+ self displayAsOperandOn: aStream.
+ aStream nextPut: $).
+    ]
+
+    printOperand: aGPExpression on: aStream [
+ <category: 'printing'>
+ aGPExpression precedence < self precedence
+     ifTrue: [ aStream nextPut: $( ].
+ aGPExpression displayAsOperandOn: aStream.
+ aGPExpression precedence < self precedence
+     ifTrue: [ aStream nextPut: $) ]
+    ]
+
+    Object >> asGPExpression [
+ <category: 'conversion'>
+ ^GNUPlot.GPLiteralExpression on: self
+    ]
+
+    asGPExpression [
+ <category: 'conversion'>
+ ^self
+    ]
+
+    coerce: aNumber [
+ <category: 'mixed computation'>
+ ^aNumber asGPExpression
+    ]
+
+    generality [
+ <category: 'mixed computation'>
+ ^1000
+    ]
+
+    + expr [
+ <category: 'mixed computation'>
+ ^GPBinaryExpression new
+    op: #+ prec: -4 lhs: self rhs: expr asGPExpression;
+    yourself
+    ]
+
+    - expr [
+ <category: 'mixed computation'>
+ ^GPBinaryExpression new
+    op: #- prec: -4 lhs: self rhs: expr asGPExpression;
+    yourself
+    ]
+
+    * expr [
+ <category: 'mixed computation'>
+ ^GPBinaryExpression new
+    op: #* prec: -3 lhs: self rhs: expr asGPExpression;
+    yourself
+    ]
+
+    / expr [
+ <category: 'mixed computation'>
+ ^GPBinaryExpression new
+    op: #/ prec: -3 lhs: self rhs: expr asGPExpression;
+    yourself
+    ]
+
+    raisedTo: expr [
+ <category: 'mixed computation'>
+ ^GPBinaryExpression new
+    op: '**' prec: -1 lhs: self rhs: expr asGPExpression;
+    yourself
+    ]
+
+    raisedToInteger: expr [
+ <category: 'mixed computation'>
+ ^self raisedTo: expr
+    ]
+
+    bitInvert [
+ <category: 'mixed computation'>
+ ^GPUnaryOpExpression new
+    op: '~' expr: self
+    ]
+
+    negated [
+ <category: 'mixed computation'>
+ ^GPUnaryOpExpression new
+    op: #- expr: self
+    ]
+
+    squared [
+ <category: 'mixed computation'>
+ ^self raisedTo: 2
+    ]
+
+    abs [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'abs' expr: self
+    ]
+
+    sign [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'sgn' expr: self
+    ]
+
+    round [
+ <category: 'mixed computation'>
+ ^(self + 0.5) truncated
+    ]
+
+    truncated [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'int' expr: self
+    ]
+
+    ceiling [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'ceil' expr: self
+    ]
+
+    floor [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'floor' expr: self
+    ]
+
+    ln [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'log' expr: self
+    ]
+
+    log [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'log10' expr: self
+    ]
+
+    exp [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'exp' expr: self
+    ]
+
+    arcTanh [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'atanh' expr: self
+    ]
+
+    arcCosh [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'acosh' expr: self
+    ]
+
+    arcSinh [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'asinh' expr: self
+    ]
+
+    tanh [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'tanh' expr: self
+    ]
+
+    cosh [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'cosh' expr: self
+    ]
+
+    sinh [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'sinh' expr: self
+    ]
+
+    arcTan [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'atan' expr: self
+    ]
+
+    arcCos [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'acos' expr: self
+    ]
+
+    arcSin [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'asin' expr: self
+    ]
+
+    tan [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'tan' expr: self
+    ]
+
+    cos [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'cos' expr: self
+    ]
+
+    sin [
+ <category: 'mixed computation'>
+ ^GPFunctionExpression new
+    op: 'sin' expr: self
+    ]
+]
+
+GPExpression subclass: GPUnaryExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions.'>
+
+    | op expr |
+    displayAsOperandOn: aStream [
+ aStream nextPutAll: op.
+ self printOperand: expr on: aStream.
+    ]
+
+    displayPrologOn: aStream into: defs [
+ expr displayPrologOn: aStream into: defs
+    ]
+
+    op: operandSymbol expr: exprExpr [
+ op := operandSymbol.
+ expr := exprExpr
+    ]
+]
+
+GPUnaryExpression subclass: GPUnaryOpExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions.'>
+
+    precedence [
+ ^-2
+    ]
+]
+
+GPUnaryExpression subclass: GPFunctionExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions.'>
+
+    precedence [
+ ^1
+    ]
+]
+
+GPFunctionExpression subclass: GPFitExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions
+and represent functions fitted to a data source.'>
+
+    | source function expr params |
+    GPFunctionExpression class >>
+ name: aString source: aSource function: aBlock variable: expr [
+ ^self new
+    op: aString expr: expr;
+    source: aSource asGPDataSource function: aBlock;
+    yourself
+    ]
+
+    source: aSource function: aBlock [
+ "Use variables from A on as parameters"
+ params := (1 to: aBlock argumentCount) collect: [ :i |
+    GPVariableExpression on: (Character digitValue: i + 9) ].
+
+ function := aBlock valueWithArguments: params.
+ source := aSource
+    ]
+
+    displayPrologOn: aStream into: defs [
+ (defs includes: self) ifTrue: [ ^self ].
+ defs add: self.
+ super displayPrologOn: aStream into: defs.
+
+ "f(x)=a*x+b"
+ self displayAsOperandOn: aStream.
+ aStream
+     nextPut: $=;
+     display: function;
+     nl;
+     nextPutAll: 'fit '.
+
+ "fit f(x) 'filename' using 1:2 via A,B"
+ self displayAsOperandOn: aStream.
+ aStream
+    space;
+    display: source;
+    nextPutAll: ' using 1:2 via '.
+
+ params
+    do: [ :each | each displayAsOperandOn: aStream ]
+    separatedBy: [ aStream nextPut: $, ].
+
+ aStream nl.
+ source printDataOn: aStream.
+ aStream nl.
+    ]
+]
+
+GPExpression subclass: GPBinaryExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions.'>
+
+    | op prec lhs rhs |
+    precedence [
+ ^prec
+    ]
+
+    displayAsOperandOn: aStream [
+ self printOperand: lhs on: aStream.
+ aStream nextPutAll: op.
+ self printOperand: rhs on: aStream.
+    ]
+
+    displayPrologOn: aStream into: defs [
+ lhs displayPrologOn: aStream into: defs.
+ rhs displayPrologOn: aStream into: defs
+    ]
+
+    op: operandSymbol prec: precedence lhs: lhsExpr rhs: rhsExpr [
+ op := operandSymbol.
+ prec := precedence.
+ lhs := lhsExpr.
+ rhs := rhsExpr
+    ]
+]
+
+GPExpression subclass: GPPrimaryExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions.'>
+
+    precedence [
+ ^0
+    ]
+]
+
+GPPrimaryExpression subclass: GPColumnRef [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions
+and refer to columns of external data sets.'>
+
+    | column |
+    GPColumnRef class >> column: anInteger [
+ <category: 'instance creation'>
+ ^self new column: anInteger
+    ]
+
+    column [
+ <category: 'accessing'>
+ ^column
+    ]
+
+    column: aString [
+ <category: 'private - initialization'>
+ column := aString
+    ]
+
+    displayAsOperandOn: aStream [
+ <category: 'printing'>
+ aStream nextPut: $$.
+ column printOn: aStream
+    ]
+
+    displayOn: aStream [
+ <category: 'printing'>
+ column printOn: aStream
+    ]
+]
+
+GPPrimaryExpression subclass: GPLiteralExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions
+and usually refer to numeric values.'>
+
+    | object |
+    GPLiteralExpression class >> on: anObject [
+ <category: 'instance creation'>
+ ^self new object: anObject
+    ]
+
+    object [
+ <category: 'accessing'>
+ ^object
+    ]
+
+    object: aString [
+ <category: 'private - initialization'>
+ object := aString
+    ]
+
+    displayAsOperandOn: aStream [
+ <category: 'printing'>
+ object displayOn: aStream
+    ]
+]
+
+UndefinedObject extend [
+    asGPExpression [
+ ^GNUPlot.GPLiteralExpression on: '(1/0)'
+    ]
+]
+
+GPLiteralExpression subclass: GPVariableExpression [
+    <category: 'GNUPlot'>
+    <comment: 'My instances are used in the syntax tree of plotted functions
+and refer to independent variables.'>
+
+    fit: source to: aBlock name: aString [
+ ^GPFitExpression
+    name: aString
+    source: source asGPDataSource
+    function: aBlock
+    variable: self
+    ]
+]
+


--- /dev/null
+++ mod/packages/gnuplot/Terminals.st
@@ -0,0 +1,174 @@
+"======================================================================
+|
+|   GNUPlot bindings, concrete terminal
+|
+|
+ ======================================================================"
+
+"======================================================================
+|
+| Copyright 2007 Free Software Foundation, Inc.
+| Written by Paolo Bonzini.
+|
+| This file is part of GNU Smalltalk.
+|
+| GNU Smalltalk is free software; you can redistribute it and/or modify
+| it under the terms of the GNU General Public License as published by
+| the Free Software Foundation; either version 2, or (at your option)
+| any later version.
+|
+| GNU Smalltalk is distributed in the hope that it will be useful, but
+| WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+| or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+| for more details.
+|
+| You should have received a copy of the GNU General Public License
+| along with GNU Smalltalk; see the file COPYING.  If not, write to the
+| Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+| 02110-1301, USA.  
+|
+ ======================================================================"
+
+
+"The GPPngTerminal class is Copyright (c) 2007 Igor Stasenko
+ and licensed under the X11 license.
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the `Software'), to deal in the Software without
+    restriction, including without limitation the rights to use,
+    copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following
+    conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED `AS IS', WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS IN THE SOFTWARE."
+
+GPFileTerminal subclass: GPPngTerminal [
+    <category: 'GNUPlot'>
+    <comment: 'My instances describe an abstract GNU Plot terminal
+that saves plots to a PNG file.'>
+
+    | transparent interlace trueColor rounded font size enhanced |
+    
+    enhanced [
+ <category: 'accessing'>
+ ^enhanced
+    ]
+
+    enhanced: aBoolean [
+ <category: 'accessing'>
+ enhanced := aBoolean
+    ]
+
+    font [
+ <category: 'accessing'>
+ ^font
+    ]
+
+    font: aSymbolOrString [
+ <category: 'accessing'>
+ font := aSymbolOrString
+    ]
+
+    initialize [
+ "Set default values"
+
+ <category: 'initialize-release'>
+ transparent := false.
+ interlace := false.
+ trueColor := true.
+ rounded := true.
+ font := #medium.
+ size := 800 @ 600.
+ enhanced := false.
+    ]
+
+    interlace [
+ <category: 'accessing'>
+ ^interlace
+    ]
+
+    interlace: aBoolean [
+ <category: 'accessing'>
+ interlace := aBoolean
+    ]
+
+    printOptionsOn: str [
+ <category: 'printing'>
+ transparent ifFalse: [str nextPutAll: 'no'].
+ str nextPutAll: 'transparent '.
+ interlace ifFalse: [str nextPutAll: 'no'].
+ str nextPutAll: 'interlace '.
+ trueColor ifFalse: [str nextPutAll: 'no'].
+ str
+    nextPutAll: 'truecolor ';
+    nextPutAll: (rounded ifTrue: ['rounded '] ifFalse: ['butt ']);
+    "font could be a one of: tiny | small | medium | large | giant , or font <face> {pointsize}"
+    nextPutAll: font;
+    nextPut: Character space;
+    nextPutAll: 'size ';
+    display: size x;
+    nextPut: $, ;
+    display: size y;
+    space.
+
+ enhanced ifFalse: [str nextPutAll: 'no'].
+ str nextPutAll: 'enhanced '.
+    ]
+
+    rounded [
+ <category: 'accessing'>
+ ^rounded
+    ]
+
+    rounded: aBoolean [
+ <category: 'accessing'>
+ rounded := aBoolean
+    ]
+
+    size [
+ <category: 'accessing'>
+ ^size
+    ]
+
+    size: aPoint [
+ <category: 'accessing'>
+ size := aPoint
+    ]
+
+    name [
+ <category: 'printing'>
+ ^'png'
+    ]
+
+    transparent [
+ <category: 'accessing'>
+ ^transparent
+    ]
+
+    transparent: aBoolean [
+ <category: 'accessing'>
+ transparent := aBoolean
+    ]
+
+    trueColor [
+ <category: 'accessing'>
+ ^trueColor
+    ]
+
+    trueColor: aBoolean [
+ <category: 'accessing'>
+ trueColor := aBoolean
+    ]
+]


--- /dev/null
+++ mod/packages/gnuplot/package.xml
@@ -0,0 +1,16 @@
+<package>
+  <name>GNUPlot</name>
+  <namespace>GNUPlot</namespace>
+
+  <filein>Base.st</filein>
+  <filein>Terminals.st</filein>
+  <filein>Expressions.st</filein>
+  <filein>2D.st</filein>
+  <filein>Examples.st</filein>
+
+  <file>Base.st</file>
+  <file>Terminals.st</file>
+  <file>Expressions.st</file>
+  <file>2D.st</file>
+  <file>Examples.st</file>
+</package>


_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk