Пример #1
0
func constCast(
	b *builder, pos *lex8.Pos, v int64, from tast.Expr, to types.T,
) tast.Expr {
	if types.IsInteger(to) && types.InRange(v, to) {
		return tast.NewCast(from, to)
	}
	b.Errorf(pos, "cannot cast %d to %s", v, to)
	return nil
}
Пример #2
0
func buildArrayType(b *builder, expr *ast.ArrayTypeExpr) types.T {
	t := buildType(b, expr.Type)
	if t == nil {
		return nil
	}

	if expr.Len == nil {
		// slice
		return &types.Slice{t}
	}

	// array
	n := b.buildConstExpr(expr.Len)
	if n == nil {
		return nil
	}

	ntype := n.R().T
	c, ok := ntype.(*types.Const)
	if !ok {
		// might be true, false, or other builtin consts
		b.Errorf(ast.ExprPos(expr), "array index is not a constant")
		return nil
	}

	if v, ok := types.NumConst(ntype); ok {
		if v < 0 {
			b.Errorf(ast.ExprPos(expr),
				"array index is negative: %d", c.Value,
			)
			return nil
		} else if !types.InRange(v, types.Int) {
			b.Errorf(ast.ExprPos(expr), "index out of range of int32")
			return nil
		}
		return &types.Array{T: t, N: int32(v)}
	}

	// TODO: support typed const
	b.Errorf(ast.ExprPos(expr), "typed const not implemented yet")
	return nil
}
Пример #3
0
func buildArrayLit(b *builder, lit *ast.ArrayLiteral) tast.Expr {
	hold := b.lhsSwap(false)
	defer b.lhsRestore(hold)

	if lit.Type.Len != nil {
		b.Errorf(
			ast.ExprPos(lit),
			"array literal with length not supported yet",
		)
		return nil
	}

	buf := new(bytes.Buffer)
	t := buildType(b, lit.Type.Type)
	if t == nil {
		return nil
	}

	if !types.IsInteger(t) {
		pos := ast.ExprPos(lit.Type.Type)
		b.Errorf(pos, "array literal must be integer type")
		return nil
	}
	bt := t.(types.Basic)

	if lit.Exprs != nil {
		for _, expr := range lit.Exprs.Exprs {
			n := b.buildConstExpr(expr)
			if n == nil {
				return nil
			}
			ntype := n.R().T
			if _, ok := ntype.(*types.Const); !ok {
				b.Errorf(ast.ExprPos(expr), "array literal not a constant")
				return nil
			}

			if v, ok := types.NumConst(ntype); ok {
				if !types.InRange(v, t) {
					b.Errorf(
						ast.ExprPos(expr),
						"constant out of range of %s",
						t,
					)
					return nil
				}

				switch bt {
				case types.Int, types.Uint:
					var bs [4]byte
					binary.LittleEndian.PutUint32(bs[:], uint32(v))
					buf.Write(bs[:])
				case types.Int8, types.Uint8:
					buf.Write([]byte{byte(v)})
				default:
					panic("not integer")
				}
			}
		}
	}

	ref := tast.NewConstRef(&types.Slice{bt}, buf.Bytes())
	return &tast.Const{ref}
}