diff --git a/funcs.go b/funcs.go index 2704ebe..8502e34 100644 --- a/funcs.go +++ b/funcs.go @@ -1,7 +1,9 @@ package main import ( + "fmt" "html/template" + "math" "path" "reflect" "strings" @@ -13,6 +15,7 @@ import ( func (s *Site) funcs() map[string]interface{} { return map[string]interface{}{ "exec": executeString, + "math": func() _math { return _math{} }, "path": func() _path { return _path{} }, "partial": s.templates.ExecutePartial, "reverse": reverse, @@ -26,6 +29,279 @@ func (s *Site) funcs() map[string]interface{} { } } +type _math struct{} + +func (_math) Add(a, b interface{}) interface{} { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + return a + b + case float64: + return float64(a) + b + } + case float64: + switch b := get64(b).(type) { + case int64: + return a + float64(b) + case float64: + return a + b + } + } + panic("unreachable") +} + +func (_math) Sub(a, b interface{}) interface{} { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + return a - b + case float64: + return float64(a) - b + } + case float64: + switch b := get64(b).(type) { + case int64: + return a - float64(b) + case float64: + return a - b + } + } + panic("unreachable") +} + +func (_math) Mul(a, b interface{}) interface{} { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + return a * b + case float64: + return float64(a) * b + } + case float64: + switch b := get64(b).(type) { + case int64: + return a * float64(b) + case float64: + return a * b + } + } + panic("unreachable") +} + +func (_math) Div(a, b interface{}) float64 { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + return float64(a) / float64(b) + case float64: + return float64(a) / b + } + case float64: + switch b := get64(b).(type) { + case int64: + return a / float64(b) + case float64: + return a / b + } + } + panic("unreachable") +} + +func (_math) Mod(a, b interface{}) int64 { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + return a % b + case float64: + return int64(math.Mod(float64(a), b)) + } + case float64: + switch b := get64(b).(type) { + case int64: + return int64(math.Mod(a, float64(b))) + case float64: + return int64(math.Mod(a, b)) + } + } + panic("unreachable") +} + +func (_math) Ceil(a interface{}) int64 { + switch a := get64(a).(type) { + case int64: + return a + case float64: + return int64(math.Ceil(a)) + } + panic("unreachable") +} + +func (_math) Floor(a interface{}) int64 { + switch a := get64(a).(type) { + case int64: + return a + case float64: + return int64(math.Floor(a)) + } + panic("unreachable") +} + +func (_math) Log(a interface{}) float64 { + switch a := get64(a).(type) { + case int64: + return math.Log(float64(a)) + case float64: + return math.Log(a) + } + panic("unreachable") +} + +func (_math) Max(a, b interface{}) interface{} { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + if a >= b { + return a + } else { + return b + } + case float64: + if float64(a) >= b { + return float64(a) + } else { + return b + } + } + case float64: + switch b := get64(b).(type) { + case int64: + if a >= float64(b) { + return a + } else { + return float64(b) + } + case float64: + if a >= b { + return a + } else { + return b + } + } + } + panic("unreachable") +} + +func (_math) Min(a, b interface{}) interface{} { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + if a <= b { + return a + } else { + return b + } + case float64: + if float64(a) <= b { + return float64(a) + } else { + return b + } + } + case float64: + switch b := get64(b).(type) { + case int64: + if a <= float64(b) { + return a + } else { + return float64(b) + } + case float64: + if a <= b { + return a + } else { + return b + } + } + } + panic("unreachable") +} + +func (_math) Pow(a, b interface{}) float64 { + switch a := get64(a).(type) { + case int64: + switch b := get64(b).(type) { + case int64: + return math.Pow(float64(a), float64(b)) + case float64: + return math.Pow(float64(a), b) + } + case float64: + switch b := get64(b).(type) { + case int64: + return math.Pow(a, float64(b)) + case float64: + return math.Pow(a, b) + } + } + panic("unreachable") +} + +func (_math) Round(a interface{}) int64 { + switch a := get64(a).(type) { + case int64: + return a + case float64: + return int64(math.Round(a)) + } + panic("unreachable") +} + +func (_math) Sqrt(a interface{}) float64 { + switch a := get64(a).(type) { + case int64: + return math.Sqrt(float64(a)) + case float64: + return math.Sqrt(a) + } + panic("unreachable") +} + +func get64(x interface{}) interface{} { + switch x := x.(type) { + case uint8: + return int64(x) + case int8: + return int64(x) + case uint16: + return int64(x) + case int16: + return int64(x) + case uint32: + return int64(x) + case int32: + return int64(x) + case uint64: + return int64(x) + case int64: + return int64(x) + case int: + return int64(x) + case float32: + return float64(x) + case float64: + return float64(x) + default: + panic(fmt.Errorf("unexpected type %T", x)) + } +} + type _path struct{} func (_path) Base(s string) string { return path.Base(s) }