/
copy.go
63 lines (56 loc) · 1.55 KB
/
copy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package sexpconv
import (
"go/types"
"magic_pkg/emacs/lisp"
"magic_pkg/emacs/rt"
"sexp"
"xtypes"
)
func (conv *converter) copyStruct(typ *types.Named, form sexp.Form) *sexp.StructLit {
structTyp := typ.Underlying().(*types.Struct)
vals := make([]sexp.Form, structTyp.NumFields())
for i := 0; i < structTyp.NumFields(); i++ {
vals[i] = conv.copyValue(&sexp.StructIndex{
Struct: form,
Index: i,
Typ: structTyp,
}, structTyp.Field(i).Type())
}
return &sexp.StructLit{Vals: vals, Typ: typ}
}
func (conv *converter) copyNamed(typ *types.Named, form sexp.Form) sexp.Form {
if xtypes.IsStruct(typ) && !isStructLit(form) {
return conv.copyStruct(typ, form)
}
// #FIXME: copy interface types?
return form
}
func (conv *converter) copyValueList(forms []sexp.Form, dstTyp types.Type) {
for i, form := range forms {
forms[i] = conv.copyValue(form, dstTyp)
}
}
func (conv *converter) copyValue(form sexp.Form, dstTyp types.Type) sexp.Form {
var res sexp.Form
typ := form.Type()
if xtypes.IsArray(typ) && !isArrayLit(form) {
res = sexp.NewLispCall(lisp.FnCopySequence, form) // Copy array.
} else if typ, ok := typ.(*types.Named); ok {
res = conv.copyNamed(typ, form)
} else {
res = form
}
if dstTyp != nil && types.IsInterface(dstTyp) {
dstTyp := dstTyp.(*types.Named)
if dstTyp.Obj().Pkg() == lisp.Package || types.Identical(typ, dstTyp) {
return res
}
itab := conv.itabEnv.Intern(xtypes.AsNamedType(typ), dstTyp)
return sexp.NewCall(
rt.FnMakeIface,
sexp.Var{Name: itab, Typ: lisp.TypObject},
res,
)
}
return res
}