Esempio n. 1
0
func buildBinaryOpExpr(b *builder, expr *tast.OpExpr) *ref {
	op := expr.Op.Lit
	A := b.buildExpr(expr.A)
	atyp := A.Type()
	if types.IsBasic(atyp, types.Bool) && (op == "&&" || op == "||") {
		switch op {
		case "&&":
			return buildLogicAnd(b, A, expr.B)
		case "||":
			return buildLogicOr(b, A, expr.B)
		}
		panic("unreachable")
	}

	B := b.buildExpr(expr.B)
	btyp := B.Type()
	if types.IsConst(atyp) && types.IsConst(btyp) {
		return binaryOpConst(b, op, A, B)
	}

	if op == ">>" || op == "<<" {
		ret := b.newTemp(atyp)
		buildShift(b, ret, A, B, op)
		return ret
	}

	if ok, t := types.SameBasic(atyp, btyp); ok {
		switch t {
		case types.Int, types.Int8:
			return binaryOpInt(b, op, A, B, t)
		case types.Uint, types.Uint8:
			return binaryOpUint(b, op, A, B, t)
		case types.Bool:
			return binaryOpBool(b, op, A, B)
		}
		panic("bug")
	}

	if types.IsNil(atyp) && types.IsNil(btyp) {
		return binaryOpNil(b, op, A, B)
	} else if types.BothPointer(atyp, btyp) {
		return binaryOpPtr(b, op, A, B)
	} else if types.BothFuncPointer(atyp, btyp) {
		return binaryOpPtr(b, op, A, B)
	} else if types.BothSlice(atyp, btyp) {
		return binaryOpSlice(b, op, A, B)
	}
	panic("bug")
}
Esempio n. 2
0
File: op.go Progetto: 272489711/e8vm
func buildUnaryOpExpr(b *builder, expr *ast.OpExpr) tast.Expr {
	opTok := expr.Op
	op := opTok.Lit
	opPos := opTok.Pos

	B := b.buildExpr(expr.B)
	if B == nil {
		return nil
	}
	bref := B.R()
	if !bref.IsSingle() {
		b.Errorf(opPos, "%q on %s", op, bref)
		return nil
	}

	btyp := bref.T
	if op == "&" {
		return refAddress(b, opTok, B)
	} else if types.IsConst(btyp) {
		return unaryOpConst(b, opTok, B)
	} else if types.IsInteger(btyp) {
		return unaryOpInt(b, opTok, B)
	} else if types.IsBasic(btyp, types.Bool) {
		return unaryOpBool(b, opTok, B)
	}

	b.Errorf(opPos, "invalid unary operator %q", op)
	return nil
}
Esempio n. 3
0
func buildUnaryOpExpr(b *builder, expr *tast.OpExpr) *ref {
	op := expr.Op.Lit
	B := b.buildExpr(expr.B)
	btyp := B.Type()
	if op == "&" {
		ret := b.newTemp(&types.Pointer{btyp})
		b.b.Arith(ret.IR(), nil, op, B.IR())
		return ret
	} else if types.IsConst(btyp) {
		panic("bug")
	} else if types.IsInteger(btyp) {
		return unaryOpInt(b, op, B)
	} else if types.IsBasic(btyp, types.Bool) {
		return unaryOpBool(b, op, B)
	}
	panic("bug")
}
Esempio n. 4
0
func buildConstDecl(b *builder, d *ast.ConstDecl) *tast.Define {
	if d.Type != nil {
		b.Errorf(ast.ExprPos(d.Type), "typed const not implemented yet")
		return nil
	}

	right := buildConstExprList(b, d.Exprs)
	if right == nil {
		return nil
	}

	nright := right.R().Len()
	idents := d.Idents.Idents
	nleft := len(idents)
	if nleft != nright {
		b.Errorf(d.Eq.Pos, "%d values for %d identifiers",
			nright, nleft,
		)
		return nil
	}

	var syms []*sym8.Symbol
	for i, ident := range idents {
		t := right.R().At(i).Type()
		if !types.IsConst(t) {
			b.Errorf(ast.ExprPos(d.Exprs.Exprs[i]), "not a const")
			return nil
		}

		sym := declareConst(b, ident, t)
		if sym == nil {
			return nil
		}
		syms = append(syms, sym)
	}

	return &tast.Define{syms, right}
}
Esempio n. 5
0
File: op.go Progetto: 272489711/e8vm
func buildBinaryOpExpr(b *builder, expr *ast.OpExpr) tast.Expr {
	opTok := expr.Op
	op := opTok.Lit
	opPos := opTok.Pos

	A := b.buildExpr(expr.A)
	if A == nil {
		return nil
	}
	aref := A.R()
	if !aref.IsSingle() {
		b.Errorf(opPos, "%q on %s", op, aref)
		return nil
	}
	atyp := aref.T

	B := b.buildExpr(expr.B)
	if B == nil {
		return nil
	}
	bref := B.R()
	if !bref.IsSingle() {
		b.Errorf(opPos, "%q on %s", op, bref)
		return nil
	}
	btyp := bref.T

	if types.IsConst(atyp) && types.IsConst(btyp) {
		return binaryOpConst(b, opTok, A, B)
	}

	if op == ">>" || op == "<<" {
		if v, ok := types.NumConst(btyp); ok {
			B = constCast(b, opPos, v, B, types.Uint)
			if B == nil {
				return nil
			}
			btyp = types.Uint
		}

		if v, ok := types.NumConst(atyp); ok {
			A = constCast(b, opPos, v, A, types.Int)
			if A == nil {
				return nil
			}
			atyp = types.Int
		}

		if !canShift(b, atyp, btyp, opPos, op) {
			return nil
		}

		r := tast.NewRef(atyp)
		return &tast.OpExpr{A, opTok, B, r}
	}

	if v, ok := types.NumConst(atyp); ok {
		A = constCast(b, opPos, v, A, btyp)
		if A == nil {
			return nil
		}
		atyp = btyp
	} else if c, ok := atyp.(*types.Const); ok {
		atyp = c.Type
	}

	if v, ok := types.NumConst(btyp); ok {
		B = constCast(b, opPos, v, B, atyp)
		if B == nil {
			return nil
		}
		btyp = atyp
	} else if c, ok := btyp.(*types.Const); ok {
		btyp = c.Type
	}

	if ok, t := types.SameBasic(atyp, btyp); ok {
		switch t {
		case types.Int, types.Int8, types.Uint, types.Uint8:
			return binaryOpInt(b, opTok, A, B, t)
		case types.Bool:
			return binaryOpBool(b, opTok, A, B)
		case types.Float32:
			b.Errorf(opPos, "floating point operations not implemented")
			return nil
		}
	}

	if types.IsNil(atyp) && types.IsNil(btyp) {
		return binaryOpNil(b, opTok, A, B)
	} else if types.BothPointer(atyp, btyp) {
		return binaryOpPtr(b, opTok, A, B)
	} else if types.BothFuncPointer(atyp, btyp) {
		return binaryOpPtr(b, opTok, A, B)
	} else if types.BothSlice(atyp, btyp) {
		return binaryOpSlice(b, opTok, A, B)
	}

	b.Errorf(opPos, "invalid operation of %s %s %s", atyp, op, btyp)
	if types.IsInteger(atyp) && types.IsInteger(btyp) {
		switch op {
		case "+", "-", "*", "&", "|", "^", "%", "/",
			"==", "!=", ">", "<", ">=", "<=":
			b.Errorf(
				opPos,
				"operation %s needs the same type on both sides",
				op,
			)
		}
	}
	return nil
}
Esempio n. 6
0
func (r *ref) IsConst() bool {
	return r.IsSingle() && types.IsConst(r.Type())
}