| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716 |
- // Copyright 2022 The Gc Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package gc // modernc.org/gc/v3
- import (
- "go/constant"
- "math"
- )
- var (
- _ Expression = (*BasicLitNode)(nil)
- _ Expression = (*BinaryExpressionNode)(nil)
- _ Expression = (*CompositeLitNode)(nil)
- _ Expression = (*ConversionNode)(nil)
- _ Expression = (*FunctionLitNode)(nil)
- _ Expression = (*KeyedElementNode)(nil)
- _ Expression = (*LiteralValueNode)(nil)
- _ Expression = (*MethodExprNode)(nil)
- _ Expression = (*OperandNameNode)(nil)
- _ Expression = (*OperandNode)(nil)
- _ Expression = (*OperandQualifiedNameNode)(nil)
- _ Expression = (*ParenthesizedExpressionNode)(nil)
- _ Expression = (*PrimaryExprNode)(nil)
- _ Expression = (*UnaryExprNode)(nil)
- _ Expression = (*ValueExpression)(nil)
- falseVal = constant.MakeBool(false)
- trueVal = constant.MakeBool(true)
- unknown = constant.MakeUnknown()
- )
- func known(v constant.Value) bool { return v != nil && v.Kind() != constant.Unknown }
- type valueCache struct {
- v constant.Value
- }
- func (n *valueCache) Value() constant.Value {
- if n.v != nil {
- return n.v
- }
- return unknown
- }
- func (n *valueCache) setValue(v constant.Value) constant.Value {
- n.v = v
- return v
- }
- type valuer interface {
- Value() constant.Value
- }
- type Expression interface {
- Node
- checkExpr(c *ctx) Expression
- clone() Expression
- typer
- valuer
- }
- type ValueExpression struct {
- Node
- typeCache
- valueCache
- }
- func (n *ValueExpression) checkExpr(c *ctx) Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *ValueExpression) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *BasicLitNode) Type() Type {
- switch n.Ch() {
- case CHAR:
- return n.ctx.int32
- case INT:
- return n.ctx.untypedInt
- case FLOAT:
- return n.ctx.untypedFloat
- case STRING:
- return n.ctx.untypedString
- default:
- panic(todo("%v: %T %s %v", n.Position(), n, n.Source(false), n.Ch()))
- }
- }
- func (n *BasicLitNode) Value() constant.Value {
- return constant.MakeFromLiteral(n.Src(), n.Ch(), 0)
- }
- func (n *BasicLitNode) checkExpr(c *ctx) Expression {
- n.ctx = c
- if !known(n.Value()) {
- c.err(n, "invalid literal: %s", n.Source(false))
- }
- return n
- }
- func (n *BasicLitNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandNameNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandNameNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandNameNode) checkExpr(c *ctx) Expression {
- in, named := n.LexicalScope().lookup(n.Name)
- switch x := named.n.(type) {
- case *ConstSpecNode:
- switch in.kind {
- case UniverseScope:
- switch n.Name.Src() {
- case "iota":
- if c.iota < 0 {
- panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
- }
- r := &ValueExpression{Node: x}
- r.t = c.untypedInt
- r.v = constant.MakeInt64(c.iota)
- return r
- default:
- panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
- }
- default:
- return x.Expression
- }
- default:
- panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
- }
- }
- func (n *OperandNameNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *ParenthesizedExpressionNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *ParenthesizedExpressionNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *ParenthesizedExpressionNode) checkExpr(c *ctx) Expression {
- return n.Expression.checkExpr(c)
- }
- func (n *ParenthesizedExpressionNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *LiteralValueNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *LiteralValueNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *LiteralValueNode) checkExpr(c *ctx) Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *LiteralValueNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *KeyedElementNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *KeyedElementNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *KeyedElementNode) checkExpr(c *ctx) Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *KeyedElementNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *CompositeLitNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *CompositeLitNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *CompositeLitNode) checkExpr(c *ctx) Expression {
- if n == nil {
- return nil
- }
- if !n.enter(c, n) {
- return n
- }
- t := n.setType(c.checkType(n.LiteralType))
- n.LiteralValue.check(c, t)
- return n
- }
- func (n *CompositeLitNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *LiteralValueNode) check(c *ctx, t Type) {
- if n == nil {
- return
- }
- switch t.Kind() {
- case Array:
- n.checkArray(c, t.(*ArrayTypeNode))
- default:
- panic(todo("%v: %T %s %v", n.Position(), n, n.Source(false), t.Kind()))
- }
- }
- func (n *LiteralValueNode) checkArray(c *ctx, t *ArrayTypeNode) {
- panic(todo("%v: %T %s %s", n.Position(), n, t, n.Source(false)))
- }
- func (n *FunctionLitNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *FunctionLitNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *FunctionLitNode) checkExpr(c *ctx) Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *FunctionLitNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandNode) checkExpr(c *ctx) Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandQualifiedNameNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandQualifiedNameNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandQualifiedNameNode) checkExpr(c *ctx) Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *OperandQualifiedNameNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *ConversionNode) Type() Type {
- return n.TypeNode
- }
- func (n *ConversionNode) checkExpr(c *ctx) Expression {
- t := n.TypeNode.check(c)
- n.Expression = n.Expression.checkExpr(c)
- v := n.Expression.Value()
- n.v = c.convertValue(n.Expression, v, t)
- return n
- }
- func (n *ConversionNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *MethodExprNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *MethodExprNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *MethodExprNode) checkExpr(c *ctx) Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *MethodExprNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *PrimaryExprNode) Type() Type {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *PrimaryExprNode) Value() constant.Value {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *PrimaryExprNode) checkExpr(c *ctx) Expression {
- switch x := n.PrimaryExpr.(type) {
- case *OperandNameNode:
- _, named := x.LexicalScope().lookup(x.Name)
- switch y := named.n.(type) {
- case *TypeDefNode:
- switch z := n.Postfix.(type) {
- case *ArgumentsNode:
- cnv := &ConversionNode{
- TypeNode: &TypeNameNode{
- Name: x.Name,
- lexicalScoper: x.lexicalScoper,
- },
- LPAREN: z.LPAREN,
- Expression: z.Expression,
- RPAREN: z.RPAREN,
- }
- return cnv.checkExpr(c)
- default:
- panic(todo("%v: %T %s", n.Position(), z, n.Source(false)))
- }
- default:
- panic(todo("%v: %T %s", n.Position(), y, n.Source(false)))
- }
- default:
- panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
- }
- n.PrimaryExpr = n.PrimaryExpr.checkExpr(c)
- switch x := n.Postfix.(type) {
- default:
- panic(todo("%v: %T %s", n.Position(), x, n.Source(false)))
- }
- }
- func (n *PrimaryExprNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *BinaryExpressionNode) checkExpr(c *ctx) (r Expression) {
- if n == nil {
- return nil
- }
- if n.typeCache.Type() != Invalid {
- return n
- }
- n.LHS = n.LHS.checkExpr(c)
- n.RHS = n.RHS.checkExpr(c)
- lv := n.LHS.Value()
- lt := n.LHS.Type()
- rv := n.RHS.Value()
- rt := n.RHS.Type()
- defer func() {
- if known(lv) && known(rv) && r != nil && !known(r.Value()) {
- c.err(n.Op, "operation value not determined: %v %s %v", lv, n.Op.Src(), rv)
- }
- }()
- switch n.Op.Ch() {
- case SHL, SHR:
- var u uint64
- var uOk bool
- n.t = lt
- // The right operand in a shift expression must have integer type or be an
- // untyped constant representable by a value of type uint.
- switch {
- case isIntegerType(rt):
- // ok
- case known(rv):
- if isAnyArithmeticType(rt) {
- rv = c.convertValue(n.RHS, rv, c.cfg.uint)
- if known(rv) {
- u, uOk = constant.Uint64Val(rv)
- }
- break
- }
- c.err(n.Op, "TODO %v", n.Op.Src())
- return n
- default:
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- return n
- }
- // If the left operand of a non-constant shift expression is an untyped
- // constant, it is first implicitly converted to the type it would assume if
- // the shift expression were replaced by its left operand alone.
- switch {
- case known(lv) && !known(rv):
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- // c.err(n.Op, "TODO %v", n.Op.Ch.str())
- // return n
- case known(lv) && known(rv):
- if !uOk {
- panic(todo(""))
- }
- n.t = lt
- n.v = constant.Shift(lv, n.Op.Ch(), uint(u))
- default:
- trc("", known(lv), known(rv), u, uOk)
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- // n.t = lt
- // n.v = constant.BinaryOp(lv, n.Op.Ch(), rv)
- }
- case ADD, SUB, MUL, QUO, REM:
- if !isAnyArithmeticType(lt) || !isAnyArithmeticType(rt) {
- c.err(n.Op, "TODO %v %v", lt, rt)
- break
- }
- // For other binary operators, the operand types must be identical unless the
- // operation involves shifts or untyped constants.
- //
- // Except for shift operations, if one operand is an untyped constant and the
- // other operand is not, the constant is implicitly converted to the type of
- // the other operand.
- switch {
- case isAnyUntypedType(lt) && isAnyUntypedType(rt):
- n.v = constant.BinaryOp(lv, n.Op.Ch(), rv)
- switch n.v.Kind() {
- case constant.Int:
- n.t = c.untypedInt
- case constant.Float:
- n.t = c.untypedFloat
- default:
- c.err(n.Op, "TODO %v %v %q %v %v -> %v %v", lv, lt, n.Op.Src(), rv, rt, n.v, n.v.Kind())
- }
- case isAnyUntypedType(lt) && !isAnyUntypedType(rt):
- c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
- case !isAnyUntypedType(lt) && isAnyUntypedType(rt):
- c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
- default: // case !isAnyUntypedType(lt) && !isAnyUntypedType(rt):
- c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
- }
- default:
- c.err(n.Op, "TODO %v %v %q %v %v", lv, lt, n.Op.Src(), rv, rt)
- }
- return n
- }
- func (n *BinaryExpressionNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (n *UnaryExprNode) checkExpr(c *ctx) Expression {
- if n == nil {
- return nil
- }
- if n.typeCache.Type() != Invalid {
- return n
- }
- n.UnaryExpr = n.UnaryExpr.checkExpr(c)
- v := n.UnaryExpr.Value()
- t := n.UnaryExpr.Type()
- switch n.Op.Ch() {
- default:
- trc("", v, t)
- panic(todo("%v: %T %s", n.Op.Position(), n, n.Source(false)))
- }
- }
- func (n *UnaryExprNode) clone() Expression {
- panic(todo("%v: %T %s", n.Position(), n, n.Source(false)))
- }
- func (c *ctx) convertValue(n Node, v constant.Value, to Type) (r constant.Value) {
- if !known(v) {
- return unknown
- }
- switch to.Kind() {
- case
- Complex128,
- Complex64,
- Function,
- Interface,
- Map,
- Pointer,
- Slice,
- String,
- Struct,
- Tuple,
- UnsafePointer,
- UntypedBool,
- UntypedComplex,
- UntypedFloat,
- UntypedInt,
- UntypedNil,
- UntypedRune,
- UntypedString:
- c.err(n, "TODO %v -> %v", v, to)
- case Int:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- i64, ok := constant.Int64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- switch c.cfg.goarch {
- case "386", "arm":
- if i64 < math.MinInt32 || i64 > math.MaxInt32 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- }
- return w
- case Int8:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- i64, ok := constant.Int64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- if i64 < math.MinInt8 || i64 > math.MaxInt8 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Int16:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- i64, ok := constant.Int64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- if i64 < math.MinInt16 || i64 > math.MaxInt16 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Int32:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- i64, ok := constant.Int64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- if i64 < math.MinInt32 || i64 > math.MaxInt32 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Int64:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- if _, ok := constant.Int64Val(w); !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Uint, Uintptr:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- u64, ok := constant.Uint64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- switch c.cfg.goarch {
- case "386", "arm":
- if u64 > math.MaxUint32 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- }
- return w
- case Uint8:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- u64, ok := constant.Uint64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- if u64 > math.MaxUint8 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Uint16:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- u64, ok := constant.Uint64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- if u64 > math.MaxUint16 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Uint32:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- u64, ok := constant.Uint64Val(w)
- if !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- if u64 > math.MaxUint32 {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Uint64:
- w := constant.ToInt(v)
- if !known(w) {
- c.err(n, "cannot convert %s to %s", v, to)
- return unknown
- }
- if _, ok := constant.Uint64Val(w); !ok {
- c.err(n, "value %s overflows %s", v, to)
- return unknown
- }
- return w
- case Float32, Float64:
- return constant.ToFloat(v)
- case Bool:
- if v.Kind() == constant.Bool {
- return v
- }
- }
- return unknown
- }
|