123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- package glisp
- import (
- "errors"
- )
- type IntegerOp int
- const (
- ShiftLeft IntegerOp = iota
- ShiftRightArith
- ShiftRightLog
- Modulo
- BitAnd
- BitOr
- BitXor
- )
- var WrongType error = errors.New("operands have invalid type")
- func IntegerDo(op IntegerOp, a, b Sexp) (Sexp, error) {
- var ia SexpInt
- var ib SexpInt
- switch i := a.(type) {
- case SexpInt:
- ia = i
- case SexpChar:
- ia = SexpInt(i)
- default:
- return SexpNull, WrongType
- }
- switch i := b.(type) {
- case SexpInt:
- ib = i
- case SexpChar:
- ib = SexpInt(i)
- default:
- return SexpNull, WrongType
- }
- switch op {
- case ShiftLeft:
- return ia << uint(ib), nil
- case ShiftRightArith:
- return ia >> uint(ib), nil
- case ShiftRightLog:
- return SexpInt(uint(ia) >> uint(ib)), nil
- case Modulo:
- return ia % ib, nil
- case BitAnd:
- return ia & ib, nil
- case BitOr:
- return ia | ib, nil
- case BitXor:
- return ia ^ ib, nil
- }
- return SexpNull, errors.New("unrecognized shift operation")
- }
- type NumericOp int
- const (
- Add NumericOp = iota
- Sub
- Mult
- Div
- )
- func NumericFloatDo(op NumericOp, a, b SexpFloat) Sexp {
- switch op {
- case Add:
- return a + b
- case Sub:
- return a - b
- case Mult:
- return a * b
- case Div:
- return a / b
- }
- return SexpNull
- }
- func NumericIntDo(op NumericOp, a, b SexpInt) Sexp {
- switch op {
- case Add:
- return a + b
- case Sub:
- return a - b
- case Mult:
- return a * b
- case Div:
- if a%b == 0 {
- return a / b
- } else {
- return SexpFloat(a) / SexpFloat(b)
- }
- }
- return SexpNull
- }
- func NumericMatchFloat(op NumericOp, a SexpFloat, b Sexp) (Sexp, error) {
- var fb SexpFloat
- switch tb := b.(type) {
- case SexpFloat:
- fb = tb
- case SexpInt:
- fb = SexpFloat(tb)
- case SexpChar:
- fb = SexpFloat(tb)
- default:
- return SexpNull, WrongType
- }
- return NumericFloatDo(op, a, fb), nil
- }
- func NumericMatchInt(op NumericOp, a SexpInt, b Sexp) (Sexp, error) {
- switch tb := b.(type) {
- case SexpFloat:
- return NumericFloatDo(op, SexpFloat(a), tb), nil
- case SexpInt:
- return NumericIntDo(op, a, tb), nil
- case SexpChar:
- return NumericIntDo(op, a, SexpInt(tb)), nil
- }
- return SexpNull, WrongType
- }
- func NumericMatchChar(op NumericOp, a SexpChar, b Sexp) (Sexp, error) {
- var res Sexp
- switch tb := b.(type) {
- case SexpFloat:
- res = NumericFloatDo(op, SexpFloat(a), tb)
- case SexpInt:
- res = NumericIntDo(op, SexpInt(a), tb)
- case SexpChar:
- res = NumericIntDo(op, SexpInt(a), SexpInt(tb))
- default:
- return SexpNull, WrongType
- }
- switch tres := res.(type) {
- case SexpFloat:
- return tres, nil
- case SexpInt:
- return SexpChar(tres), nil
- }
- return SexpNull, errors.New("unexpected result")
- }
- func NumericDo(op NumericOp, a, b Sexp) (Sexp, error) {
- switch ta := a.(type) {
- case SexpFloat:
- return NumericMatchFloat(op, ta, b)
- case SexpInt:
- return NumericMatchInt(op, ta, b)
- case SexpChar:
- return NumericMatchChar(op, ta, b)
- }
- return SexpNull, WrongType
- }
|