diff --git a/core/cast.go b/core/cast.go new file mode 100644 index 0000000..23a39d2 --- /dev/null +++ b/core/cast.go @@ -0,0 +1,81 @@ +package core + +import ( + "github.com/mediocregopher/ginger/types" +) + +func Int(e types.Elem) int { + return e.(types.GoType).V.(int) +} + +func Int8(e types.Elem) int8 { + return e.(types.GoType).V.(int8) +} + +func Int16(e types.Elem) int16 { + return e.(types.GoType).V.(int16) +} + +func Int32(e types.Elem) int32 { + return e.(types.GoType).V.(int32) +} + +func Int64(e types.Elem) int64 { + return e.(types.GoType).V.(int64) +} + +func Uint(e types.Elem) uint { + return e.(types.GoType).V.(uint) +} + +func Uint8(e types.Elem) uint8 { + return e.(types.GoType).V.(uint8) +} + +func Uint16(e types.Elem) uint16 { + return e.(types.GoType).V.(uint16) +} + +func Uint32(e types.Elem) uint32 { + return e.(types.GoType).V.(uint32) +} + +func Uint64(e types.Elem) uint64 { + return e.(types.GoType).V.(uint64) +} + +func Float32(e types.Elem) float32 { + return e.(types.GoType).V.(float32) +} + +func Float64(e types.Elem) float64 { + return e.(types.GoType).V.(float64) +} + +func Complex64(e types.Elem) complex64 { + return e.(types.GoType).V.(complex64) +} + +func Complex128(e types.Elem) complex128 { + return e.(types.GoType).V.(complex128) +} + +func Bool(e types.Elem) bool { + return e.(types.GoType).V.(bool) +} + +func Byte(e types.Elem) byte { + return e.(types.GoType).V.(byte) +} + +func Rune(e types.Elem) rune { + return e.(types.GoType).V.(rune) +} + +func String(e types.Elem) string { + return e.(types.GoType).V.(string) +} + +func Error(e types.Elem) error { + return e.(types.GoType).V.(error) +} diff --git a/core/math.go b/core/math.go new file mode 100644 index 0000000..4c5c0f4 --- /dev/null +++ b/core/math.go @@ -0,0 +1,138 @@ +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) +} + +func plusInt(a, b types.Elem) types.Elem { + return types.GoType{Int(a) + Int(b)} +} + +func plusInt8(a, b types.Elem) types.Elem { + return types.GoType{Int8(a) + Int8(b)} +} + +func plusInt16(a, b types.Elem) types.Elem { + return types.GoType{Int16(a) + Int16(b)} +} + +func plusInt32(a, b types.Elem) types.Elem { + return types.GoType{Int32(a) + Int32(b)} +} + +func plusInt64(a, b types.Elem) types.Elem { + return types.GoType{Int64(a) + Int64(b)} +} + +func plusUint(a, b types.Elem) types.Elem { + return types.GoType{Uint(a) + Uint(b)} +} + +func plusUint8(a, b types.Elem) types.Elem { + return types.GoType{Uint8(a) + Uint8(b)} +} + +func plusUint16(a, b types.Elem) types.Elem { + return types.GoType{Uint16(a) + Uint16(b)} +} + +func plusUint32(a, b types.Elem) types.Elem { + return types.GoType{Uint32(a) + Uint32(b)} +} + +func plusUint64(a, b types.Elem) types.Elem { + return types.GoType{Uint64(a) + Uint64(b)} +} + +func plusFloat32(a, b types.Elem) types.Elem { + return types.GoType{Float32(a) + Float32(b)} +} + +func plusFloat64(a, b types.Elem) types.Elem { + return types.GoType{Float64(a) + Float64(b)} +} + +func plusComplex64(a, b types.Elem) types.Elem { + return types.GoType{Complex64(a) + Complex64(b)} +} + +func plusComplex128(a, b types.Elem) types.Elem { + return types.GoType{Complex128(a) + Complex128(b)} +} + +func plusString(a, b types.Elem) types.Elem { + return types.GoType{String(a) + String(b)} +} + +func Plus(s seq.Seq) types.Elem { + if seq.Empty(s) { + return types.GoType{0} + } + + first, _, _ := s.FirstRest() + var fn mathReduceFn + var zero types.Elem + switch first.(types.GoType).V.(type) { + case int: + fn = plusInt + zero = types.GoType{int(0)} + case int8: + fn = plusInt8 + zero = types.GoType{int8(0)} + case int16: + fn = plusInt16 + zero = types.GoType{int16(0)} + case int32: + fn = plusInt32 + zero = types.GoType{int32(0)} + case int64: + fn = plusInt64 + zero = types.GoType{int64(0)} + case uint: + fn = plusInt + zero = types.GoType{uint(0)} + case uint8: + fn = plusInt8 + zero = types.GoType{uint8(0)} + case uint16: + fn = plusInt16 + zero = types.GoType{uint16(0)} + case uint32: + fn = plusInt32 + zero = types.GoType{uint32(0)} + case uint64: + fn = plusInt64 + zero = types.GoType{uint64(0)} + case float32: + fn = plusFloat32 + zero = types.GoType{float32(0)} + case float64: + fn = plusFloat64 + zero = types.GoType{float64(0)} + case complex64: + fn = plusComplex64 + zero = types.GoType{complex64(0)} + case complex128: + fn = plusComplex128 + zero = types.GoType{complex128(0)} + case string: + fn = plusString + zero = types.GoType{string(0)} + default: + panic(fmt.Sprintf("$#v cannot have plus called on it", first)) + } + + return mathReduce(fn, zero, s) +} diff --git a/eval/eval_test.go b/eval/eval_test.go index 7888689..bc8d075 100644 --- a/eval/eval_test.go +++ b/eval/eval_test.go @@ -3,9 +3,9 @@ package eval import ( . "testing" + "github.com/mediocregopher/ginger/core" "github.com/mediocregopher/ginger/macros/pkgctx" "github.com/mediocregopher/ginger/parse" - "github.com/mediocregopher/ginger/seq" "github.com/mediocregopher/ginger/types" ) @@ -13,27 +13,18 @@ import ( // something down before I kept thinking about it, so I would know what would // work -func shittyPlus(s seq.Seq) types.Elem { - fn := func(acc, el types.Elem) (types.Elem, bool) { - i := acc.(types.GoType).V.(int) + el.(types.GoType).V.(int) - return types.GoType{i}, false - } - - return seq.Reduce(fn, types.GoType{0}, s) -} - func TestShittyPlus(t *T) { p := &pkgctx.PkgCtx{ CallMap: map[string]interface{}{ - "shittyPlus": Evaler(shittyPlus), + "Plus": Evaler(core.Plus), }, } m := map[string]types.Elem{ - "(: shittyPlus)": types.GoType{0}, - "(: shittyPlus 1 2 3)": types.GoType{6}, - `(: shittyPlus 1 2 3 - (: shittyPlus 1 2 3))`: types.GoType{12}, + "(: Plus)": types.GoType{0}, + "(: Plus 1 2 3)": types.GoType{6}, + `(: Plus 1 2 3 + (: Plus 1 2 3))`: types.GoType{12}, } for input, output := range m {