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