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