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 }
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 }
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} }