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