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