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