Exemplo n.º 1
0
func assign(b *builder, dest *ref, src *ref, op *lex8.Token) bool {
	ndest := dest.Len()
	nsrc := src.Len()
	if ndest != nsrc {
		b.Errorf(op.Pos, "cannot assign %s to %s",
			nsrc, ndest,
		)
		return false
	}

	for i, destType := range dest.typ {
		if !dest.ir[i].Addressable() {
			b.Errorf(op.Pos, "assigning to non-addressable")
			return false
		}

		srcType := src.typ[i]
		if !types.CanAssign(destType, srcType) {
			b.Errorf(op.Pos, "cannot assign %s to %s", src, dest)
			return false
		}
	}

	// perform the assignment
	for i, dest := range dest.ir {
		b.b.Assign(dest, src.ir[i])
	}

	return true
}
Exemplo n.º 2
0
func buildCallExpr(b *builder, expr *ast.CallExpr) *ref {
	f := b.buildExpr(expr.Func)
	if f == nil {
		return nil
	}

	pos := ast.ExprPos(expr.Func)

	if !f.IsSingle() {
		b.Errorf(pos, "expression list is not callable")
		return nil
	}

	funcType, ok := f.Type().(*types.Func) // the func sig in the builder
	if !ok {
		// not a function
		b.Errorf(pos, "function call on non-callable")
		return nil
	}

	args := buildExprList(b, expr.Args)
	if args == nil {
		return nil
	}

	if args.Len() != len(funcType.Args) {
		b.Errorf(ast.ExprPos(expr), "argument expects (%s), got (%s)",
			fmt8.Join(funcType.Args, ","), fmt8.Join(args.typ, ","),
		)
		return nil
	}

	// type check on parameters
	for i, argType := range args.typ {
		expect := funcType.Args[i].T
		if !types.CanAssign(expect, argType) {
			pos := ast.ExprPos(expr.Args.Exprs[i])
			b.Errorf(pos, "argument %d expects %s, got %s",
				i+1, expect, argType,
			)
		}
	}

	ret := new(ref)
	ret.typ = funcType.RetTypes
	for _, t := range funcType.RetTypes {
		ret.ir = append(ret.ir, b.f.NewTemp(t.Size(), types.IsByte(t)))
	}

	// call the func in IR
	b.b.Call(ret.ir, f.IR(), funcType.Sig, args.ir...)

	return ret
}
Exemplo n.º 3
0
func buildReturnStmt(b *builder, stmt *ast.ReturnStmt) {
	pos := stmt.Kw.Pos
	if stmt.Exprs == nil {
		println(b.fretNamed)
		if b.fretRef == nil || b.fretNamed {
			buildFuncExit(b)
		} else {
			b.Errorf(pos, "expects return %s", b.fretRef)
		}
	} else {
		if b.fretRef == nil {
			b.Errorf(pos, "function expects no return value")
			return
		}

		ref := buildExprList(b, stmt.Exprs)
		if ref == nil {
			return
		}

		nret := b.fretRef.Len()
		nsrc := ref.Len()
		if nret != nsrc {
			b.Errorf(pos, "expects (%s), returning (%s)", b.fretRef, ref)
			return
		}

		for i, t := range b.fretRef.typ {
			if !b.fretRef.ir[i].Addressable() {
				panic("bug")
			}

			srcType := ref.typ[i]
			if !types.CanAssign(t, srcType) {
				b.Errorf(pos, "expect (%s), returning (%s)", b.fretRef, ref)
				return
			}
		}

		for i, dest := range b.fretRef.ir {
			b.b.Assign(dest, ref.ir[i])
		}

		buildFuncExit(b)
	}
}