Version 0 of Notes on TIP 309 - expose expression parsing

Updated 2012-12-13 07:45:44 by arjen

Arjen Markus (13 december 2012) Several years back I wrote TIP 309, in pursuit of a method to manipulate arithmetic expressions. The idea: go beyond ordinary arithmetic and make it possible to use complex numbers in the same way as real numbers or to implement (basic) symbolic manipulation.

The start of the Tcl novem development is an opportunity to look at it again. Here is a simple program that shows how this can actually be used (it uses a mock-up version of the proposed command, of course):

# example.tcl --
#     Example of using the proposed command s-expr
#

# s-expr --
#     Mock up version of the proposed command
#
# Arguments:
#     expression     An - in principle - arbitrary arithmetic expression
#
# Result:
#     A prefix version of the expression.
#     In this mock-up just "+ $x $y"
#
proc s-expr {expression} {
    return [list {+ $x $y} x y]
}

# complex --
#     Namespace defining complex number operations
#
namespace eval ::complex {
    variable expressions
}

# number --
#     Construct a complex number
#
# Arguments:
#     real        Real part
#     imaginary   Imaginary part
#
proc ::complex::number {real imaginary} {
    return [list $real $imaginary]
}

# + --
#     Complex addition
#
# Arguments:
#     z1       First argument
#     z2       Second argument
#
# Result:
#     Complex sum of the two arguments
#
proc ::complex::+ {z1 z2} {

    lassign $z1 x1 y1
    lassign $z2 x2 y2

    return [list [expr {$x1+$x2}] [expr {$y1+$y2}]]
}

# cexpr -- 
#     Evaluate complex arithmetic expressions
#
# Arguments:
#     expression     Arbitrary arithmetic expression
#
# Result:
#     Value of the expression
#
proc ::complex::cexpr {expression} {
    variable expressions
        
    #
    # Construct a new procedure if the expression has not been handled before
    #

    if { ![info exists expressions($expression)] } {
        set parsed [s-expr $expression]

        set prefix [lindex $parsed 0]
        set vars   [lrange $parsed 1 end]

        set expressions($expression) 1

        set upvars {}
        foreach var $vars {
            append upvars "upvar 2 $var $var\n"
        }

        proc $expression {} "$upvars$prefix"
     }

     $expression
}

# main --
#     Test this example
#
set x [::complex::number 0 1]
set y [::complex::number 1 0]

puts "Sum of i and 1: "
puts [::complex::cexpr {$x + $y}] 

As you can see: the [cexpr] command behaves (superficially) in the same way as the [expr] command, but takes complex numbers in stead of ordinary reals.

My second example - automatic differentiation as a simple form of symbolic manipulation - is on its way.