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