Beispiel #1
0
func buildPkgConstDecl(b *builder, d *ast.ConstDecl) []*pkgConst {
	if d.Type != nil {
		b.Errorf(ast.ExprPos(d.Type), "typed const not implemented")
		return nil
	}

	nident := len(d.Idents.Idents)
	nexpr := len(d.Exprs.Exprs)
	if nident != nexpr {
		b.Errorf(d.Eq.Pos, "%d consts with %d expressions",
			nident, nexpr,
		)
		return nil
	}

	var ret []*pkgConst
	zero := types.NewNumber(0) // place holding the const
	for i, ident := range d.Idents.Idents {
		s := declareConst(b, ident, zero)
		if s == nil {
			return nil
		}

		expr := d.Exprs.Exprs[i]
		c := &pkgConst{
			sym:  s,
			tok:  ident,
			expr: expr,
			deps: symUse(expr),
		}
		ret = append(ret, c)
	}

	return ret
}
Beispiel #2
0
func unaryOpConst(b *builder, opTok *lex8.Token, B tast.Expr) tast.Expr {
	op := opTok.Lit
	bref := B.R()
	if !bref.IsSingle() {
		b.Errorf(opTok.Pos, "invalid operation: %q on %s", op, bref)
		return nil
	}

	v, ok := types.NumConst(bref.T)
	if !ok {
		// TODO: support type const
		b.Errorf(opTok.Pos, "typed const operation not implemented")
		return nil
	}

	switch op {
	case "+":
		return B // just shortcut this
	case "-":
		return &tast.Const{tast.NewRef(types.NewNumber(-v))}
	}

	b.Errorf(opTok.Pos, "invalid operation: %q on %s", op, B)
	return nil
}
Beispiel #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}
}
Beispiel #4
0
func binaryOpConst(b *builder, opTok *lex8.Token, A, B tast.Expr) tast.Expr {
	op := opTok.Lit
	aref := A.R()
	bref := B.R()
	if aref.List != nil || bref.List != nil {
		b.Errorf(opTok.Pos, "invalid %s %q %s", aref.T, op, bref.T)
		return nil
	}

	va, oka := types.NumConst(aref.T)
	vb, okb := types.NumConst(bref.T)
	if !(oka && okb) {
		b.Errorf(opTok.Pos, "non-numeric consts ops not implemented")
		return nil
	}

	r := func(v int64) tast.Expr {
		return &tast.Const{tast.NewRef(types.NewNumber(v))}
	}

	switch op {
	case "+":
		return r(va + vb)
	case "-":
		return r(va - vb)
	case "*":
		return r(va * vb)
	case "&":
		return r(va & vb)
	case "|":
		return r(va | vb)
	case "^":
		return r(va ^ vb)
	case "%":
		if vb == 0 {
			b.Errorf(opTok.Pos, "modular by zero")
			return nil
		}
		return r(va % vb)
	case "/":
		if vb == 0 {
			b.Errorf(opTok.Pos, "divide by zero")
			return nil
		}
		return r(va / vb)
	case "==", "!=", ">", "<", ">=", "<=":
		return &tast.OpExpr{A, opTok, B, tast.NewRef(types.Bool)}
	case "<<":
		if vb < 0 {
			b.Errorf(opTok.Pos, "shift with negative value", vb)
			return nil
		}
		return r(va << uint64(vb))
	case ">>":
		if vb < 0 {
			b.Errorf(opTok.Pos, "shift with negative value", vb)
			return nil
		}
		return r(va >> uint64(vb))
	}

	b.Errorf(opTok.Pos, "%q on consts", op)
	return nil
}