// EvalUnary evaluates a unary operator. func (c *Context) EvalUnary(op string, right value.Value) value.Value { right = right.Eval(c) fn := c.UnaryFn[op] if fn == nil { return value.Unary(c, op, right) } if fn.Body == nil { value.Errorf("unary %q undefined", op) } c.push() defer c.pop() c.assignLocal(fn.Right, right) var v value.Value for _, e := range fn.Body { v = e.Eval(c) } if v == nil { value.Errorf("no value returned by %q", op) } return v }
// put writes to out a version of the value that will recreate it when parsed. func put(out io.Writer, val value.Value) { switch val := val.(type) { case value.Char: fmt.Fprintf(out, "%q", rune(val)) case value.Int: fmt.Fprintf(out, "%d", int(val)) case value.BigInt: fmt.Fprintf(out, "%d", val.Int) case value.BigRat: fmt.Fprintf(out, "%d/%d", val.Num(), val.Denom()) case value.BigFloat: // TODO The actual value might not have the same prec as // the configuration, so we might not get this right // Probably not important but it would be nice to fix it. if val.Sign() == 0 || val.IsInf() { // These have prec 0 and are easy. // They shouldn't appear anyway, but be safe. fmt.Fprintf(out, "%g", val) return } digits := int(float64(val.Prec()) * 0.301029995664) // 10 log 2. fmt.Fprintf(out, "%.*g", digits, val.Float) case value.Vector: if val.AllChars() { fmt.Fprintf(out, "%q", val) return } for i, v := range val { if i > 0 { fmt.Fprint(out, " ") } put(out, v) } case value.Matrix: put(out, val.Shape()) fmt.Fprint(out, " rho ") put(out, val.Data()) default: value.Errorf("internal error: can't save type %T", val) } }