refactoring a bit, defined accumulator struct

added subtraction and multiplication
master
Jordan Orelli 12 years ago
parent 39286ce998
commit ac8430076a

@ -0,0 +1,64 @@
package main
import (
"fmt"
"reflect"
)
type accumulator struct {
name string
floatFn func(float64, float64) float64
intFn func(int64, int64) int64
acc int64
accf float64
floating bool
}
func (a *accumulator) total(vals ...interface{}) (interface{}, error) {
if len(vals) == 0 {
return int64(0), nil
}
switch v := vals[0].(type) {
case int64:
a.acc = v
case float64:
a.floating = true
a.accf = v
default:
return nil, fmt.Errorf("%v is not defined for %v", a.name, reflect.TypeOf(v))
}
if len(vals) == 1 {
if a.floating {
return a.accf, nil
} else {
return a.acc, nil
}
}
for _, raw := range vals[1:] {
switch v := raw.(type) {
case int64:
if a.floating {
a.accf = a.floatFn(a.accf, float64(v))
break
}
a.acc = a.intFn(a.acc, v)
case float64:
if !a.floating {
a.floating = true
a.accf = a.floatFn(a.accf, float64(a.acc))
}
a.accf = a.floatFn(a.accf, v)
default:
return nil, fmt.Errorf("%v is not defined for %v", a.name, reflect.TypeOf(v))
}
}
if a.floating {
return a.accf, nil
} else {
return a.acc, nil
}
panic("not reached")
}

@ -1,40 +1,42 @@
package main package main
import (
"fmt"
"reflect"
)
type proc func(...interface{}) (interface{}, error) type proc func(...interface{}) (interface{}, error)
func addition(vals ...interface{}) (interface{}, error) { func addition(vals ...interface{}) (interface{}, error) {
addFloats := false a := accumulator{
var accf float64 name: "addition",
var acc int64 floatFn: func(left, right float64) float64 {
return left + right
for _, raw := range vals { },
switch v := raw.(type) { intFn: func(left, right int64) int64 {
case int64: return left + right
if addFloats { },
accf += float64(v)
} else {
acc += v
} }
case float64: return a.total(vals...)
if !addFloats {
addFloats = true
accf += float64(acc)
} }
accf += v
default: func subtraction(vals ...interface{}) (interface{}, error) {
return nil, fmt.Errorf("addition is not defined for %v", reflect.TypeOf(v)) a := accumulator{
name: "subtraction",
floatFn: func(left, right float64) float64 {
return left - right
},
intFn: func(left, right int64) int64 {
return left - right
},
} }
return a.total(vals...)
} }
if addFloats { func multiplication(vals ...interface{}) (interface{}, error) {
return accf, nil a := accumulator{
} else { name: "multiplication",
return acc, nil floatFn: func(left, right float64) float64 {
return left * right
},
intFn: func(left, right int64) int64 {
return left * right
},
} }
panic("not reached") return a.total(vals...)
} }

@ -17,10 +17,12 @@ type sexp []interface{}
type symbol string type symbol string
var universe = environment{ var universe = environment{
"int": 5, "int": int64(5),
"float": 3.14, "float": float64(3.14),
"string": "Jordan", "string": "Jordan",
"+": proc(addition), "+": proc(addition),
"-": proc(subtraction),
"*": proc(multiplication),
} }
// parses the string lexeme into a value that can be eval'd // parses the string lexeme into a value that can be eval'd

Loading…
Cancel
Save