Пример #1
0
func buildString(b *builder, op *lex8.Token) tast.Expr {
	v, e := strconv.Unquote(op.Lit)
	if e != nil {
		b.Errorf(op.Pos, "invalid string: %s", e)
		return nil
	}
	ref := tast.NewConstRef(types.String, v)
	return &tast.Const{ref}
}
Пример #2
0
func buildChar(b *builder, op *lex8.Token) tast.Expr {
	v, e := strconv.Unquote(op.Lit)
	if e != nil {
		b.Errorf(op.Pos, "invalid char: %s", e)
		return nil
	} else if len(v) != 1 {
		b.Errorf(op.Pos, "invalid char in quote: %q", v)
		return nil
	}
	ref := tast.NewConstRef(types.Int8, int64(v[0]))
	return &tast.Const{ref}
}
Пример #3
0
func buildInt(b *builder, op *lex8.Token) tast.Expr {
	ret, e := strconv.ParseInt(op.Lit, 0, 64)
	if e != nil {
		b.Errorf(op.Pos, "invalid integer: %s", e)
		return nil
	}

	if ret < math.MinInt32 {
		b.Errorf(op.Pos, "integer too small to fit in 32-bit")
		return nil
	} else if ret > math.MaxUint32 {
		b.Errorf(op.Pos, "integer too large to fit in 32-bit")
		return nil
	}

	ref := tast.NewConstRef(types.NewNumber(ret), ret)
	return &tast.Const{ref}
}
Пример #4
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}
}