tc_resolve.mx raw
1 package main
2
3 // resolveTypeExpr resolves a type expression to a Type.
4 // This is the core of the type system - translating AST type nodes to Type values.
5 func (c *Checker) resolveTypeExpr(e Expr) Type {
6 if e == nil {
7 return nil
8 }
9 switch e := e.(type) {
10 case *Name:
11 return c.resolveTypeName(e)
12 case *SelectorExpr:
13 return c.resolveQualifiedTypeName(e)
14 case *Operation:
15 // *T (pointer)
16 if e.Y == nil && e.Op == Mul {
17 base := c.resolveTypeExpr(e.X)
18 if base == nil {
19 return nil
20 }
21 return NewPointer(base)
22 }
23 // ~T (approximation element in type constraints) - treat as T for B1
24 if e.Y == nil && e.Op == Tilde {
25 return c.resolveTypeExpr(e.X)
26 }
27 // T | U (union element in type constraints) - return first operand for B1
28 if e.Y != nil && e.Op == Or {
29 c.resolveTypeExpr(e.Y) // resolve both sides to catch undefined errors
30 return c.resolveTypeExpr(e.X)
31 }
32 case *SliceType:
33 elem := c.resolveTypeExpr(e.Elem)
34 if elem == nil {
35 return nil
36 }
37 return NewSlice(elem)
38 case *ArrayType:
39 elem := c.resolveTypeExpr(e.Elem)
40 if elem == nil {
41 return nil
42 }
43 if e.Len == nil {
44 // [...]T - length inferred from composite literal
45 return NewArray(elem, -1)
46 }
47 n := c.evalArrayLen(e.Len)
48 return NewArray(elem, n)
49 case *MapType:
50 key := c.resolveTypeExpr(e.Key)
51 val := c.resolveTypeExpr(e.Value)
52 if key == nil || val == nil {
53 return nil
54 }
55 return NewTCMap(key, val)
56 case *ChanType:
57 elem := c.resolveTypeExpr(e.Elem)
58 if elem == nil {
59 return nil
60 }
61 var dir TCChanDir
62 switch e.Dir {
63 case SendOnly:
64 dir = TCSendOnly
65 case RecvOnly:
66 dir = TCRecvOnly
67 default:
68 dir = TCSendRecv
69 }
70 return NewTCChan(dir, elem)
71 case *StructType:
72 return c.resolveStructType(e)
73 case *InterfaceType:
74 return c.resolveInterfaceType(e)
75 case *FuncType:
76 return c.resolveFuncType(e, nil)
77 case *IndexExpr:
78 // generic instantiation T[A, B, ...]
79 return c.resolveGenericInst(e)
80 case *DotsType:
81 // variadic element type (used in parameter lists, not standalone)
82 return c.resolveTypeExpr(e.Elem)
83 }
84 c.errorf(e.Pos(), "cannot resolve type expression")
85 return nil
86 }
87
88 func (c *Checker) resolveTypeName(e *Name) Type {
89 _, obj := c.lookupType(e.Value)
90 if obj == nil {
91 c.errorf(e.Pos(), "undefined: %s", e.Value)
92 return nil
93 }
94 if tn, ok := obj.(*TypeName); ok {
95 if c.info != nil {
96 c.info.Uses[e] = tn
97 }
98 return tn.typ
99 }
100 c.errorf(e.Pos(), "%s is not a type", e.Value)
101 return nil
102 }
103
104 func (c *Checker) resolveQualifiedTypeName(e *SelectorExpr) Type {
105 pkgName, ok := e.X.(*Name)
106 if !ok {
107 c.errorf(e.Pos(), "invalid type expression")
108 return nil
109 }
110 _, obj := c.lookup(pkgName.Value, c.pkg.scope)
111 if obj == nil {
112 c.errorf(e.Pos(), "undefined: %s", pkgName.Value)
113 return nil
114 }
115 pkgObj, ok := obj.(*PkgName)
116 if !ok {
117 c.errorf(e.Pos(), "%s is not a package", pkgName.Value)
118 return nil
119 }
120 imported := pkgObj.imported
121 if imported == nil {
122 return nil
123 }
124 typeObj := imported.scope.Lookup(e.Sel.Value)
125 if typeObj == nil {
126 c.errorf(e.Sel.Pos(), "undefined: %s.%s", pkgName.Value, e.Sel.Value)
127 return nil
128 }
129 if tn, ok := typeObj.(*TypeName); ok {
130 return tn.typ
131 }
132 c.errorf(e.Sel.Pos(), "%s.%s is not a type", pkgName.Value, e.Sel.Value)
133 return nil
134 }
135
136 func (c *Checker) resolveStructType(e *StructType) *TCStruct {
137 var fields []*TCVar
138 var tags []string
139 for i, f := range e.FieldList {
140 typ := c.resolveTypeExpr(f.Type)
141 if f.Name != nil {
142 fields = append(fields, NewTCField(c.pkg, f.Name.Value, typ, false))
143 } else {
144 // anonymous/embedded
145 name := typeBaseName(typ)
146 fields = append(fields, NewTCField(c.pkg, name, typ, true))
147 }
148 tag := ""
149 if i < len(e.TagList) && e.TagList[i] != nil {
150 tag = e.TagList[i].Value
151 }
152 tags = append(tags, tag)
153 }
154 return NewTCStruct(fields, tags)
155 }
156
157 func (c *Checker) resolveInterfaceType(e *InterfaceType) *TCInterface {
158 var methods []*IfaceMethod
159 var embeds []Type
160 for _, f := range e.MethodList {
161 if f.Name == nil {
162 // embedded type
163 typ := c.resolveTypeExpr(f.Type)
164 if typ != nil {
165 embeds = append(embeds, typ)
166 }
167 continue
168 }
169 ft, ok := f.Type.(*FuncType)
170 if !ok {
171 continue
172 }
173 sig := c.resolveFuncType(ft, nil)
174 if sig != nil {
175 methods = append(methods, &IfaceMethod{name: f.Name.Value, sig: sig})
176 }
177 }
178 iface := NewTCInterface(methods, embeds)
179 iface.Complete()
180 return iface
181 }
182
183 // resolveFuncType converts a FuncType AST node to a Signature.
184 // recv is optional (non-nil only for method declarations).
185 func (c *Checker) resolveFuncType(ft *FuncType, recv *Field) *Signature {
186 if ft == nil {
187 return nil
188 }
189 var recvVar *TCVar
190 if recv != nil {
191 recvTyp := c.resolveTypeExpr(recv.Type)
192 recvName := ""
193 if recv.Name != nil {
194 recvName = recv.Name.Value
195 }
196 recvVar = NewTCVar(c.pkg, recvName, recvTyp)
197 }
198
199 params := c.resolveFieldList(ft.ParamList)
200 results := c.resolveFieldList(ft.ResultList)
201
202 variadic := false
203 if len(ft.ParamList) > 0 {
204 last := ft.ParamList[len(ft.ParamList)-1]
205 if _, ok := last.Type.(*DotsType); ok {
206 variadic = true
207 // unwrap: the slice type is already resolved in resolveFieldList
208 }
209 }
210
211 return NewSignature(recvVar, params, results, variadic)
212 }
213
214 func (c *Checker) resolveFieldList(fields []*Field) *Tuple {
215 if len(fields) == 0 {
216 return nil
217 }
218 var vars []*TCVar
219 for _, f := range fields {
220 typ := c.resolveTypeExpr(f.Type)
221 name := ""
222 if f.Name != nil {
223 name = f.Name.Value
224 }
225 vars = append(vars, NewTCVar(c.pkg, name, typ))
226 }
227 return NewTuple(vars...)
228 }
229
230 func (c *Checker) resolveGenericInst(e *IndexExpr) Type {
231 // TODO: full generic instantiation
232 return c.resolveTypeExpr(e.X)
233 }
234
235 // typeBaseName returns the name of the base type for an anonymous field.
236 func typeBaseName(t Type) string {
237 if t == nil {
238 return ""
239 }
240 switch t := t.(type) {
241 case *Named:
242 if t.obj != nil {
243 return t.obj.name
244 }
245 case *Pointer:
246 return typeBaseName(t.base)
247 case *Basic:
248 return t.name
249 }
250 return ""
251 }
252