67 lines
1.5 KiB
Smarty
67 lines
1.5 KiB
Smarty
|
package core
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
|
||
|
"github.com/mediocregopher/ginger/seq"
|
||
|
"github.com/mediocregopher/ginger/types"
|
||
|
)
|
||
|
|
||
|
type mathReduceFn func(types.Elem, types.Elem) types.Elem
|
||
|
|
||
|
func mathReduce(fn mathReduceFn, zero types.Elem, s seq.Seq) types.Elem {
|
||
|
reduceFn := func(acc, el types.Elem) (types.Elem, bool) {
|
||
|
return fn(acc, el), false
|
||
|
}
|
||
|
return seq.Reduce(reduceFn, zero, s)
|
||
|
}
|
||
|
|
||
|
{{range .}}
|
||
|
{{$mathOp := .}}
|
||
|
{{range .OpTypes}}
|
||
|
func {{$mathOp.Private}}{{.CastFn}}(a, b types.Elem) types.Elem {
|
||
|
return types.GoType{ {{.CastFn}}(a) {{$mathOp.Op}} {{.CastFn}}(b) }
|
||
|
}
|
||
|
{{end}}
|
||
|
{{if $mathOp.IncludeString}}
|
||
|
func {{$mathOp.Private}}String(a, b types.Elem) types.Elem {
|
||
|
return types.GoType{ String(a) {{$mathOp.Op}} String(b) }
|
||
|
}
|
||
|
{{end}}
|
||
|
func {{$mathOp.Public}}(s seq.Seq) types.Elem {
|
||
|
var first, zero types.Elem
|
||
|
{{if (eq $mathOp.Unit "")}}
|
||
|
if seq.Empty(s) {
|
||
|
panic("{{$mathOp.Public}} cannot be called with no arguments")
|
||
|
}
|
||
|
zero, s, _ = s.FirstRest()
|
||
|
first = zero
|
||
|
{{else}}
|
||
|
if seq.Empty(s) {
|
||
|
return types.GoType{ {{$mathOp.Unit}} }
|
||
|
}
|
||
|
first, _, _ = s.FirstRest()
|
||
|
{{end}}
|
||
|
|
||
|
var fn mathReduceFn
|
||
|
switch first.(types.GoType).V.(type) {
|
||
|
{{range .OpTypes}}
|
||
|
case {{.Type}}:
|
||
|
fn = {{$mathOp.Private}}{{.CastFn}}
|
||
|
{{if (ne $mathOp.Unit "")}}
|
||
|
zero = types.GoType{ {{.Type}}({{$mathOp.Unit}}) }
|
||
|
{{end}}
|
||
|
{{end}}
|
||
|
{{if $mathOp.IncludeString}}
|
||
|
case string:
|
||
|
fn = {{$mathOp.Private}}String
|
||
|
zero = types.GoType{string("")}
|
||
|
{{end}}
|
||
|
default:
|
||
|
panic(fmt.Sprintf("$#v cannot have {{$mathOp.Public}} called on it", first))
|
||
|
}
|
||
|
|
||
|
return mathReduce(fn, zero, s)
|
||
|
}
|
||
|
{{end}}
|