OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [exp/] [types/] [const.go] - Rev 747

Compare with Previous | Blame | View Log

// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements operations on ideal constants.

package types

import (
        "go/token"
        "math/big"
        "strconv"
)

// TODO(gri) Consider changing the API so Const is an interface
//           and operations on consts don't have to type switch.

// A Const implements an ideal constant Value.
// The zero value z for a Const is not a valid constant value.
type Const struct {
        // representation of constant values:
        // ideal bool     ->  bool
        // ideal int      ->  *big.Int
        // ideal float    ->  *big.Rat
        // ideal complex  ->  cmplx
        // ideal string   ->  string
        val interface{}
}

// Representation of complex values.
type cmplx struct {
        re, im *big.Rat
}

func assert(cond bool) {
        if !cond {
                panic("go/types internal error: assertion failed")
        }
}

// MakeConst makes an ideal constant from a literal
// token and the corresponding literal string.
func MakeConst(tok token.Token, lit string) Const {
        switch tok {
        case token.INT:
                var x big.Int
                _, ok := x.SetString(lit, 0)
                assert(ok)
                return Const{&x}
        case token.FLOAT:
                var y big.Rat
                _, ok := y.SetString(lit)
                assert(ok)
                return Const{&y}
        case token.IMAG:
                assert(lit[len(lit)-1] == 'i')
                var im big.Rat
                _, ok := im.SetString(lit[0 : len(lit)-1])
                assert(ok)
                return Const{cmplx{big.NewRat(0, 1), &im}}
        case token.CHAR:
                assert(lit[0] == '\'' && lit[len(lit)-1] == '\'')
                code, _, _, err := strconv.UnquoteChar(lit[1:len(lit)-1], '\'')
                assert(err == nil)
                return Const{big.NewInt(int64(code))}
        case token.STRING:
                s, err := strconv.Unquote(lit)
                assert(err == nil)
                return Const{s}
        }
        panic("unreachable")
}

// MakeZero returns the zero constant for the given type.
func MakeZero(typ *Type) Const {
        // TODO(gri) fix this
        return Const{0}
}

// Match attempts to match the internal constant representations of x and y.
// If the attempt is successful, the result is the values of x and y,
// if necessary converted to have the same internal representation; otherwise
// the results are invalid.
func (x Const) Match(y Const) (u, v Const) {
        switch a := x.val.(type) {
        case bool:
                if _, ok := y.val.(bool); ok {
                        u, v = x, y
                }
        case *big.Int:
                switch y.val.(type) {
                case *big.Int:
                        u, v = x, y
                case *big.Rat:
                        var z big.Rat
                        z.SetInt(a)
                        u, v = Const{&z}, y
                case cmplx:
                        var z big.Rat
                        z.SetInt(a)
                        u, v = Const{cmplx{&z, big.NewRat(0, 1)}}, y
                }
        case *big.Rat:
                switch y.val.(type) {
                case *big.Int:
                        v, u = y.Match(x)
                case *big.Rat:
                        u, v = x, y
                case cmplx:
                        u, v = Const{cmplx{a, big.NewRat(0, 0)}}, y
                }
        case cmplx:
                switch y.val.(type) {
                case *big.Int, *big.Rat:
                        v, u = y.Match(x)
                case cmplx:
                        u, v = x, y
                }
        case string:
                if _, ok := y.val.(string); ok {
                        u, v = x, y
                }
        default:
                panic("unreachable")
        }
        return
}

// Convert attempts to convert the constant x to a given type.
// If the attempt is successful, the result is the new constant;
// otherwise the result is invalid.
func (x Const) Convert(typ *Type) Const {
        // TODO(gri) implement this
        switch x.val.(type) {
        case bool:
        case *big.Int:
        case *big.Rat:
        case cmplx:
        case string:
        }
        return x
}

func (x Const) String() string {
        switch x := x.val.(type) {
        case bool:
                if x {
                        return "true"
                }
                return "false"
        case *big.Int:
                return x.String()
        case *big.Rat:
                return x.FloatString(10) // 10 digits of precision after decimal point seems fine
        case cmplx:
                // TODO(gri) don't print 0 components
                return x.re.FloatString(10) + " + " + x.im.FloatString(10) + "i"
        case string:
                return x
        }
        panic("unreachable")
}

func (x Const) UnaryOp(op token.Token) Const {
        panic("unimplemented")
}

func (x Const) BinaryOp(op token.Token, y Const) Const {
        var z interface{}
        switch x := x.val.(type) {
        case bool:
                z = binaryBoolOp(x, op, y.val.(bool))
        case *big.Int:
                z = binaryIntOp(x, op, y.val.(*big.Int))
        case *big.Rat:
                z = binaryFloatOp(x, op, y.val.(*big.Rat))
        case cmplx:
                z = binaryCmplxOp(x, op, y.val.(cmplx))
        case string:
                z = binaryStringOp(x, op, y.val.(string))
        default:
                panic("unreachable")
        }
        return Const{z}
}

func binaryBoolOp(x bool, op token.Token, y bool) interface{} {
        switch op {
        case token.EQL:
                return x == y
        case token.NEQ:
                return x != y
        }
        panic("unreachable")
}

func binaryIntOp(x *big.Int, op token.Token, y *big.Int) interface{} {
        var z big.Int
        switch op {
        case token.ADD:
                return z.Add(x, y)
        case token.SUB:
                return z.Sub(x, y)
        case token.MUL:
                return z.Mul(x, y)
        case token.QUO:
                return z.Quo(x, y)
        case token.REM:
                return z.Rem(x, y)
        case token.AND:
                return z.And(x, y)
        case token.OR:
                return z.Or(x, y)
        case token.XOR:
                return z.Xor(x, y)
        case token.AND_NOT:
                return z.AndNot(x, y)
        case token.SHL:
                panic("unimplemented")
        case token.SHR:
                panic("unimplemented")
        case token.EQL:
                return x.Cmp(y) == 0
        case token.NEQ:
                return x.Cmp(y) != 0
        case token.LSS:
                return x.Cmp(y) < 0
        case token.LEQ:
                return x.Cmp(y) <= 0
        case token.GTR:
                return x.Cmp(y) > 0
        case token.GEQ:
                return x.Cmp(y) >= 0
        }
        panic("unreachable")
}

func binaryFloatOp(x *big.Rat, op token.Token, y *big.Rat) interface{} {
        var z big.Rat
        switch op {
        case token.ADD:
                return z.Add(x, y)
        case token.SUB:
                return z.Sub(x, y)
        case token.MUL:
                return z.Mul(x, y)
        case token.QUO:
                return z.Quo(x, y)
        case token.EQL:
                return x.Cmp(y) == 0
        case token.NEQ:
                return x.Cmp(y) != 0
        case token.LSS:
                return x.Cmp(y) < 0
        case token.LEQ:
                return x.Cmp(y) <= 0
        case token.GTR:
                return x.Cmp(y) > 0
        case token.GEQ:
                return x.Cmp(y) >= 0
        }
        panic("unreachable")
}

func binaryCmplxOp(x cmplx, op token.Token, y cmplx) interface{} {
        a, b := x.re, x.im
        c, d := y.re, y.im
        switch op {
        case token.ADD:
                // (a+c) + i(b+d)
                var re, im big.Rat
                re.Add(a, c)
                im.Add(b, d)
                return cmplx{&re, &im}
        case token.SUB:
                // (a-c) + i(b-d)
                var re, im big.Rat
                re.Sub(a, c)
                im.Sub(b, d)
                return cmplx{&re, &im}
        case token.MUL:
                // (ac-bd) + i(bc+ad)
                var ac, bd, bc, ad big.Rat
                ac.Mul(a, c)
                bd.Mul(b, d)
                bc.Mul(b, c)
                ad.Mul(a, d)
                var re, im big.Rat
                re.Sub(&ac, &bd)
                im.Add(&bc, &ad)
                return cmplx{&re, &im}
        case token.QUO:
                // (ac+bd)/s + i(bc-ad)/s, with s = cc + dd
                var ac, bd, bc, ad, s big.Rat
                ac.Mul(a, c)
                bd.Mul(b, d)
                bc.Mul(b, c)
                ad.Mul(a, d)
                s.Add(c.Mul(c, c), d.Mul(d, d))
                var re, im big.Rat
                re.Add(&ac, &bd)
                re.Quo(&re, &s)
                im.Sub(&bc, &ad)
                im.Quo(&im, &s)
                return cmplx{&re, &im}
        case token.EQL:
                return a.Cmp(c) == 0 && b.Cmp(d) == 0
        case token.NEQ:
                return a.Cmp(c) != 0 || b.Cmp(d) != 0
        }
        panic("unreachable")
}

func binaryStringOp(x string, op token.Token, y string) interface{} {
        switch op {
        case token.ADD:
                return x + y
        case token.EQL:
                return x == y
        case token.NEQ:
                return x != y
        case token.LSS:
                return x < y
        case token.LEQ:
                return x <= y
        case token.GTR:
                return x > y
        case token.GEQ:
                return x >= y
        }
        panic("unreachable")
}

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.