Browse Source

Made some semi-major/scary leanups to generics+overloading.

Mark Sibly 8 năm trước cách đây
mục cha
commit
90efe9035b
5 tập tin đã thay đổi với 152 bổ sung120 xóa
  1. 1 1
      src/mx2cc/alias.monkey2
  2. 1 3
      src/mx2cc/class.monkey2
  3. 42 22
      src/mx2cc/func.monkey2
  4. 45 90
      src/mx2cc/overload.monkey2
  5. 63 4
      src/mx2cc/type.monkey2

+ 1 - 1
src/mx2cc/alias.monkey2

@@ -10,7 +10,7 @@ Class AliasDecl Extends Decl
 	
 		Local types:=New Type[genArgs.Length]
 		For Local i:=0 Until types.Length
-			types[i]=New GenArgType( i,genArgs[i],Null,Null )
+			types[i]=New GenArgType( i,genArgs[i] )',Null,Null )
 		Next
 		
 		Return New AliasType( Self,scope,types,Null )

+ 1 - 3
src/mx2cc/class.monkey2

@@ -11,7 +11,7 @@ Class ClassDecl Extends Decl
 	
 		Local types:=New Type[genArgs.Length]
 		For Local i:=0 Until types.Length
-			types[i]=New GenArgType( i,genArgs[i],Null,Null )
+			types[i]=New GenArgType( i,genArgs[i] )',Null,Null )
 		Next
 		
 		Return New ClassType( Self,scope,types,Null )
@@ -432,8 +432,6 @@ Class ClassType Extends Type
 
 		If types.Length<>Self.types.Length Throw New SemantEx( "Wrong number of generic type parameters" )
 
-'		If AnyTypeGeneric( types ) Return Self
-
 		If Not instances instances=New Stack<ClassType>
 	
 		For Local inst:=Eachin instances

+ 42 - 22
src/mx2cc/func.monkey2

@@ -15,7 +15,7 @@ Class FuncDecl Extends Decl
 	
 		Local types:=New Type[genArgs.Length]
 		For Local i:=0 Until types.Length
-			types[i]=New GenArgType( i,genArgs[i],Null,Null )
+			types[i]=New GenArgType( i,genArgs[i] )',Null,Null )
 		Next
 		
 		Return New FuncValue( Self,scope,types,Null )
@@ -112,9 +112,7 @@ Class FuncValue Extends Value
 	End
 	
 	Property IsGeneric:Bool()
-		If Not ftype SemantError( "FuncValue.IsGeneric()" )
-		
-		Return ftype.IsGeneric Or (types And Not instanceOf)
+		Return types And Not instanceOf
 	End
 	
 	Property IsCtor:Bool()
@@ -339,7 +337,6 @@ Class FuncValue Extends Value
 	End
 	
 	Method GenInstance:Value( types:Type[] ) Override
-	
 		If AnyTypeGeneric( types ) SemantError( "FuncValue.GenInstance()" )
 		
 		If Not IsGeneric Return Super.GenInstance( types )
@@ -457,8 +454,7 @@ Class FuncValue Extends Value
 	End
 	
 	Method TryGenInstance:FuncValue( types:Type[] )
-	
-'		If AnyTypeGeneric( types ) Print "TryGenInstance:"+fdecl.ident+"<"+Join( types )+">"
+		If AnyTypeGeneric( types ) SemantError( "FuncValue.GenInstance()" )
 
 		If types.Length<>Self.types.Length Return Null
 		
@@ -532,11 +528,16 @@ Class FuncListValue Extends Value
 	End
 	
 	Method ToString:String() Override
+	
+		Return flistType.ToString()
 
 		Local args:=Join( flistType.types )
 		If args args="<"+args+">"
 		
-		Return flistType.flist.ident+args+"(...)"
+'		Return flistType.flist.ident+args+"(...)"
+		
+		Local funcs:=Join( flistType.funcs.ToArray() )
+		Return flistType.flist.ident+args+"["+funcs+"]"
 	End
 	
 	Method GenInstance:Value( types:Type[] ) Override
@@ -569,18 +570,17 @@ Class FuncListValue Extends Value
 	End
 	
 	Method UpCast:Value( type:Type ) Override
+		DebugAssert( Not type.IsGeneric )
 	
 		If type.Equals( Type.VariantType ) Return New UpCastValue( Type.VariantType,ToRValue() )
 	
 		Local ftype:=TCast<FuncType>( type )
 		If Not ftype Throw New UpCastEx( Self,type )
 		
-		Local func:=flistType.FindOverload( ftype.retType,ftype.argTypes )
-		If Not func Throw New OverloadEx( Self,ftype.argTypes )
-		
-		If Not func.ftype.Equals( ftype ) Throw New UpCastEx( Self,type )
+		Local match:=flistType.FindFunc( ftype )
+		If Not match Throw New UpCastEx( Self,type )
 		
-		Return func.ToValue( instance )
+		Return match.ToValue( instance )
 	End
 	
 End
@@ -612,9 +612,20 @@ Class FuncListType Extends Type
 	End
 	
 	Method ToString:String() Override
+
 		Local str:=""
 		If types str="<"+Join( types )+">"
-		Return flist.ident+str+"(...)"
+		
+		If funcs.Length=1 Return flist.ident+str+":"+funcs[0].ftype.ToString()
+		
+		Local ftypes:=New Type[funcs.Length]
+		For Local i:=0 Until ftypes.Length
+			ftypes[i]=funcs[i].ftype
+		Next
+
+		Return flist.ident+str+"["+Join( ftypes )+"]" 
+	
+'		Return flist.ident+str+"(...)"
 	End
 	
 	Property Name:String() Override
@@ -630,22 +641,31 @@ Class FuncListType Extends Type
 		SemantError( "FuncListType.ToValue()" )
 		Return Null
 	End
-	
+
 	Method DistanceToType:Int( type:Type ) Override
-	
-		If type.Equals( Type.VariantType ) Return funcs.Length=1 ? MAX_DISTANCE Else -1
+		DebugAssert( Not type.IsGeneric )
 
 		Local ftype:=TCast<FuncType>( type )
 		If Not ftype Return -1
 		
-		Local func:=FindOverload( ftype.retType,ftype.argTypes )
-		If func Return func.ftype.DistanceToType( ftype )
-		
-		Return -1
+		Local match:=FindFunc( ftype )
+		Return match ? 0 Else -1
 	End
 	
+	Method FindFunc:FuncValue( ftype:FuncType )
+
+		Local match:FuncValue
+		
+		For Local func:=Eachin funcs
+			If Not func.ftype.Equals( ftype ) Continue
+			If match Return Null
+			match=func
+		Next
+		
+		Return match
+	End
+
 	Method FindOverload:FuncValue( ret:Type,args:Type[] )
-	
 		Return overload.FindOverload( funcs,ret,args )
 	End
 	

+ 45 - 90
src/mx2cc/overload.monkey2

@@ -3,7 +3,7 @@ Namespace mx2.overload
 
 Private
 
-Const debug:=False
+Const debug:=False'True
 
 Function dprint( txt:String )
 	Global tab:=""
@@ -12,80 +12,54 @@ Function dprint( txt:String )
 	If txt.EndsWith( "{" ) tab+="  "
 End
 
-Function IsCandidate:Bool( func:FuncValue,ret:Type,args:Type[],infered:Type[] )
+Function GenCandidate:FuncValue( func:FuncValue,ret:Type,args:Type[] )
 
 	Local ftype:=func.ftype
 	Local retType:=ftype.retType
 	Local argTypes:=ftype.argTypes
 	
-	If args.Length>argTypes.Length Return False
+	If args.Length>argTypes.Length Return Null
+	
+	Local infered:Type[]
+	If func.IsGeneric infered=New Type[func.types.Length]
 	
 	If ret
 		If retType.IsGeneric
 			retType=retType.InferType( ret,infered )
-			If Not retType Return False
-		Endif
-'		If Not retType.ExtendsType( ret ) Return False
-		If Not retType.Equals( ret ) Return False
-	#rem
-		If retType.IsGeneric
-			If Not retType.inferType( ret,infered ) return false
-		Else
-'			If Not retType.ExtendsType( ret ) Return False
-			If Not retType.Equals( ret ) Return False
+			If Not retType Return Null
 		Endif
-	#end
+		If Not retType.Equals( ret ) Return Null
 	Endif
 	
 	For Local i:=0 Until argTypes.Length
 	
 		If i>=args.Length Or Not args[i]
-		
 			Local pdecl:=func.pdecls[i]
-			
-			If Not pdecl.init Return False
-			
+			If Not pdecl.init Return Null
 			Continue
 		Endif
-			
-		If argTypes[i].IsGeneric
 		
-			Local arg:=args[i]
-			
-			Local flist:=TCast<FuncListType>( arg )
-			If flist
-			
-				Local ftype:=TCast<FuncType>( argTypes[i] )
-				If Not ftype Return False
-				
-				Local func:=flist.FindOverload( Null,ftype.argTypes )
-				If Not func Return False
-				
-				arg=func.ftype
-			Endif
-			
-			If Not argTypes[i].InferType( arg,infered ) Return False
-			
-		Else
+		Local argType:=argTypes[i]
 		
-			If args[i].DistanceToType( argTypes[i] )<0 Return False
-
+		If argType.IsGeneric
+			argType=argType.InferType( args[i],infered )
+			If Not argType Return Null
 		Endif
-
+		
+		If args[i].DistanceToType( argType )<0 Return Null
 	Next
 	
+	If Not func.IsGeneric Return func
+	
 	For Local i:=0 Until infered.Length
-
-		If Not infered[i] Or infered[i]=Type.BadType Return False
+		If Not infered[i] Or infered[i]=Type.BadType Return Null
 	Next
 	
-	Return True
+	Return func.TryGenInstance( infered )
 End
 
 Function CanInfer:Bool( func:FuncValue,args:Type[] )
 
-	If Not func.IsGeneric SemantError( "overload.CanInfer()" )
-
 	Local ftype:=func.ftype
 	Local argTypes:=ftype.argTypes
 	
@@ -103,12 +77,12 @@ Function CanInfer:Bool( func:FuncValue,args:Type[] )
 End
 
 'return true if func is better than func2
+'
 Function IsBetter:Bool( func:FuncValue,func2:FuncValue,args:Type[] )
 
-	Local better:=False,exact:=True
+	Local better:=False,same:=True
 
 	For Local i:=0 Until args.Length
-	
 		If Not args[i] Continue
 	
 		Local dist1:=args[i].DistanceToType( func.ftype.argTypes[i] )
@@ -120,69 +94,62 @@ Function IsBetter:Bool( func:FuncValue,func2:FuncValue,args:Type[] )
 		
 		If dist1<dist2 better=True
 		
-		If dist1 exact=False
+		If dist1 same=False
 	Next
 	
 	If better Return True
-
-	'if exact match, prefer non-generic over generic		
-	'
-	If exact And Not func.instanceOf And func2.instanceOf Return True
 	
-	'If exact match, not better.
+	If Not same Return False
+	
+	'always prefer non-generic over generic
 	'
-	If exact Return False
+	If Not func.instanceOf And func2.instanceOf Return True
 	
-	'compare 2 generic func instances!
+	'compare 2 generic func instances
 	'		
 	If func.instanceOf And func2.instanceOf
-	
 		If CanInfer( func2.instanceOf,func.instanceOf.ftype.argTypes ) 
-		
 			If Not CanInfer( func.instanceOf,func2.instanceOf.ftype.argTypes ) 
-			
 				Return True
-
 			Endif
-			
 		Endif
-		
 	Endif
 
 	Return False
 End
 
-Function Linearize( types:Type[],func:FuncValue,funcs:Stack<FuncValue>,j:Int=0 )
+Function FindCandidates( func:FuncValue,candidates:Stack<FuncValue>,ret:Type,args:Type[],j:Int=0 )
 
-	For Local i:=j Until types.Length
+	For Local i:=j Until args.Length
 	
-		Local type:=types[i]
-	
-		Local flist:=TCast<FuncListType>( type )
+		Local flist:=TCast<FuncListType>( args[i] )
 		If Not flist Continue
 		
-		types=types.Slice( 0 )
+		args=args.Slice( 0 )
 		
 		For Local func2:=Eachin flist.funcs
-		
-			types[i]=func2.ftype
-			
-			Linearize( types,func,funcs,i+1 )
+			args[i]=func2.ftype
+			FindCandidates( func,candidates,ret,args,i+1 )
 		Next
 		
 		Return
-		
 	Next
 	
-	Local func2:=func.TryGenInstance( types )
-
-	If func2 funcs.Push( func2 )
+	func=GenCandidate( func,ret,args )
+	If Not func Or candidates.Contains( func ) Return
+	
+	candidates.Push( func )
 End
 
 Public
-
+	
 Function FindOverload:FuncValue( funcs:Stack<FuncValue>,ret:Type,args:Type[] )
 
+	If ret DebugAssert( Not ret.IsGeneric )
+	For Local arg:=Eachin args
+		If arg DebugAssert( Not arg.IsGeneric )
+	Next
+
 	If debug
 		dprint( "{" )
 		dprint( "Funcs:"+Join( funcs.ToArray() ) )
@@ -193,20 +160,9 @@ Function FindOverload:FuncValue( funcs:Stack<FuncValue>,ret:Type,args:Type[] )
 	Local candidates:=New Stack<FuncValue>
 	
 	For Local func:=Eachin funcs
-	
-		If Not func.IsGeneric
-		
-			If IsCandidate( func,ret,args,Null ) candidates.Push( func )
-			
-			Continue
-		Endif
-		
-		Local infered:=New Type[func.types.Length]
-		
-		If IsCandidate( func,ret,args,infered ) Linearize( infered,func,candidates )
-		
+		FindCandidates( func,candidates,ret,args )
 	Next
-	
+
 	If debug dprint( "Candidates:"+Join( candidates.ToArray() ) )
 	
 	Local best:FuncValue
@@ -242,4 +198,3 @@ Function FindOverload:FuncValue( funcs:Stack<FuncValue>,ret:Type,args:Type[] )
 	
 	Return best
 End
-

+ 63 - 4
src/mx2cc/type.monkey2

@@ -216,7 +216,7 @@ Class PrimType Extends Type
 	End
 	
 	Method ToString:String() Override
-		Return ctype.cdecl.ident'.Slice( 1 )	'slice off '@' prefix
+		Return ctype.Name'cdecl.ident'.Slice( 1 )	'slice off '@' prefix
 	End
 	
 	Property Name:String() Override
@@ -595,8 +595,6 @@ Class FuncType Extends Type
 '		If type.Equals( BoolType ) Return MAX_DISTANCE			'NO func->bool yet!
 		If type.Equals( VariantType ) Return MAX_DISTANCE
 		
-'		If type.Dealias Return MAX_DISTANCE
-		
 		Return -1
 	End
 	
@@ -604,9 +602,12 @@ Class FuncType Extends Type
 	
 		If Not IsGeneric Return Super.InferType( type,infered )
 		
+'		Local flist:=TCast<FuncListType>( type )
+'		If flist Return flist.FindInfered( Self,infered )
+		
 		Local ftype:=TCast<FuncType>( type )
 		If Not ftype Or argTypes.Length<>ftype.argTypes.Length Return Null
-		
+				
 		Local retType:=Self.retType.InferType( ftype.retType,infered )
 		If Not retType Return Null
 		
@@ -622,6 +623,7 @@ Class FuncType Extends Type
 	
 End
 
+#rem
 Class GenArgType Extends Type
 
 	Field index:int
@@ -687,6 +689,8 @@ Class GenArgType Extends Type
 	
 	Method InferType:Type( type:Type,infered:Type[] ) Override
 	
+		If TCast<FuncListType>( type ) Return Null
+	
 		If types
 		
 			Local ctype:=TCast<ClassType>( type )
@@ -724,6 +728,61 @@ Class GenArgType Extends Type
 		Return Null
 	End
 	
+End
+#end
+
+Class GenArgType Extends Type
+
+	Field index:int
+	Field ident:String
+	
+	Method New( index:Int,ident:String )
+		Self.index=index
+		Self.ident=ident
+		
+		flags|=TYPE_GENERIC
+	End
+	
+	Method ToString:String() Override
+	
+		Return ident+"?"
+	End
+	
+	Property Name:String() Override
+	
+		Return ident+"?"
+	End
+	
+	Property TypeId:String() Override
+	
+		SemantError( "GenArgType.TypeId()" )
+		Return ""
+	End
+	
+	Method Equals:Bool( type:Type ) Override
+	
+		If type=Self Return True
+		
+		Local gtype:=TCast<GenArgType>( type )
+		Return gtype And index=gtype.index And ident=gtype.ident
+	End
+	
+	Method InferType:Type( type:Type,infered:Type[] ) Override
+	
+		If TCast<FuncListType>( type ) Return Null
+	
+		If Not infered[index]
+			infered[index]=type
+			Return type
+		Endif
+		
+		If infered[index].Equals( type ) Return type
+		
+		infered[index]=Type.BadType
+		
+		Return Null
+	End
+	
 End
 
 Class VoidType Extends Type