2
0
Эх сурвалжийг харах

Merge pull request #182 from bmx-ng/bcc_overload

BCC overload support
Brucey 9 жил өмнө
parent
commit
eee5a2482c
9 өөрчлөгдсөн 1943 нэмэгдсэн , 477 устгасан
  1. 7 0
      config.bmx
  2. 402 100
      ctranslator.bmx
  3. 570 133
      decl.bmx
  4. 252 56
      expr.bmx
  5. 6 1
      iparser.bmx
  6. 8 0
      options.bmx
  7. 109 81
      parser.bmx
  8. 170 27
      translator.bmx
  9. 419 79
      type.bmx

+ 7 - 0
config.bmx

@@ -63,6 +63,13 @@ Function Err( err$ )
 	Throw "Compile Error: "+err + "~n" + _errInfo + "~n"
 End Function
 
+Function Warn( err$ )
+	'If DEBUGSTOP_ON_ERROR Then
+	'	DebugStop ' useful for debugging!
+	'End If
+	Print "Compile Warning: "+err + "~n" + _errInfo + "~n"
+End Function
+
 Function FormatError:String(path:String, line:Int, char:Int)
 	Return "[" + path + ";" + line + ";" + char + "]"
 End Function

+ 402 - 100
ctranslator.bmx

@@ -378,7 +378,7 @@ Type TCTranslator Extends TTranslator
 'If decl.ident="ToHex" DebugStop
 
 		Local t$
-		If objParam And decl.IsMethod() And ((Not decl.IsExtern()) Or (decl.IsExtern() And TClassDecl(decl.scope) And Not TClassDecl(decl.scope).IsStruct())) Then
+		If objParam And (decl.IsMethod() Or decl.isCtor()) And ((Not decl.IsExtern()) Or (decl.IsExtern() And TClassDecl(decl.scope) And Not TClassDecl(decl.scope).IsStruct())) Then
 			t:+ objParam
 		End If
 		For Local i:Int=0 Until decl.argDecls.Length
@@ -426,7 +426,7 @@ Type TCTranslator Extends TTranslator
 										Local obj:String = Bra("struct " + scope.munged + "_obj*")
 										Local class:String = "o->clas"
 				
-										t:+ class + "->fn_" + fdecl.ident
+										t:+ class + "->f_" + fdecl.ident + MangleMethod(fdecl)
 									Else
 										t:+ fdecl.munged
 									End If
@@ -754,7 +754,7 @@ t:+"NULLNULLNULL"
 				Local scope:TScopeDecl = _env.ClassScope()
 				Local obj:String = Bra("struct " + scope.munged + "_obj*")
 				Local class:String = "o->clas"
-				Return class + "->fn_" + decl.ident
+				Return class + "->f_" + decl.ident + MangleMethod(TFuncDecl(decl))
 			Else
 				Return decl.munged
 			End If
@@ -800,6 +800,7 @@ t:+"NULLNULLNULL"
 	End Method
 
 	Method TransField$( decl:TFieldDecl,lhs:TExpr )
+
 		If lhs Then
 			Return TransFieldRef(decl, TransSubExpr( lhs ), lhs.exprType)
 		Else
@@ -814,7 +815,7 @@ t:+"NULLNULLNULL"
 	End Method
 
 	Method TransFunc$( decl:TFuncDecl,args:TExpr[],lhs:TExpr, sup:Int = False, scope:TScopeDecl = Null )
-'If decl.ident = "GetClassName" DebugStop
+'If decl.ident = "eventfilter" DebugStop
 		' for calling the super class method instead
 		Local tSuper:String
 		If sup Then
@@ -855,19 +856,20 @@ t:+"NULLNULLNULL"
 							End If
 							Err "TODO extern types not allowed methods"
 						Else
-							If cdecl.IsInterface() And reserved_methods.Find("," + decl.IdentLower() + ",") = -1 Then
+
+							If cdecl.IsInterface() And Not equalsBuiltInFunc(cdecl, decl) Then
 								Local ifc:String = Bra("(struct " + cdecl.munged + "_methods*)" + Bra("bbObjectInterface(" + TransSubExpr( lhs ) + ", " + "&" + cdecl.munged + "_ifc)"))
-								Return ifc + "->" + TransFuncPrefix(cdecl, decl) + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
+								Return ifc + "->" + TransFuncPrefix(cdecl, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, TransSubExpr( lhs ) )
 							Else
 								Local class:String = Bra(TransSubExpr( lhs )) + "->clas" + tSuper
-								Return class + "->" + TransFuncPrefix(cdecl, decl) + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
+								Return class + "->" + TransFuncPrefix(cdecl, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, TransSubExpr( lhs ) )
 							End If
 						End If
 					End If
 				Else If TNewObjectExpr(lhs) Then
 					Local cdecl:TClassDecl = TNewObjectExpr(lhs).classDecl
 					Local class:String = cdecl.munged
-					Return class + "." + TransFuncPrefix(cdecl, decl) + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
+					Return class + "." + TransFuncPrefix(cdecl, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, TransSubExpr( lhs ) )
 				Else If TCastExpr(lhs) Then
 					Local cdecl:TClassDecl = TObjectType(TCastExpr(lhs).ty).classDecl
 					Local obj:String = Bra(TransObject(cdecl))
@@ -879,12 +881,12 @@ t:+"NULLNULLNULL"
 							EmitDebugNullObjectError(TransSubExpr( lhs ))
 						End If
 
-						If cdecl.IsInterface() And reserved_methods.Find("," + decl.IdentLower() + ",") = -1 Then
+						If cdecl.IsInterface() And Not equalsBuiltInFunc(cdecl, decl) Then
 							Local ifc:String = Bra("(struct " + cdecl.munged + "_methods*)" + Bra("bbObjectInterface(" + obj + TransSubExpr( lhs ) + ", " + "&" + cdecl.munged + "_ifc)"))
-							Return ifc + "->" + TransFuncPrefix(cdecl, decl) + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
+							Return ifc + "->" + TransFuncPrefix(cdecl, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, TransSubExpr( lhs ) )
 						Else
 							Local class:String = Bra("(" + obj + TransSubExpr( lhs ) + ")->clas" + tSuper)
-							Return class + "->" + TransFuncPrefix(cdecl, decl) + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
+							Return class + "->" + TransFuncPrefix(cdecl, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, TransSubExpr( lhs ) )
 						End If
 					End If
 				Else If TMemberVarExpr(lhs) Then
@@ -905,7 +907,7 @@ t:+"NULLNULLNULL"
 
 						Local class:String = Bra("(" + obj + TransSubExpr( lhs ) + ")->clas" + tSuper)
 						'Local class:String = TransFuncClass(cdecl)
-						Return class + "->" + TransFuncPrefix(cdecl, decl) + decl.ident+TransArgs( args,decl, TransSubExpr( lhs ) )
+						Return class + "->" + TransFuncPrefix(cdecl, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, TransSubExpr( lhs ) )
 					End If
 				Else If TInvokeExpr(lhs) Then
 					' create a local variable of the inner invocation
@@ -918,7 +920,7 @@ t:+"NULLNULLNULL"
 
 					Local obj:String = Bra(TransObject(decl.scope))
 					Local class:String = Bra("(" + obj + lvar +")->clas" + tSuper)
-					Return class + "->" + TransFuncPrefix(decl.scope, decl)+ decl.ident+TransArgs( args,decl, lvar )
+					Return class + "->" + TransFuncPrefix(decl.scope, decl)+ FuncDeclMangleIdent(decl)+TransArgs( args,decl, lvar )
 
 					'Local obj:String = Bra("struct " + decl.scope.munged + "_obj*")
 					'Local class:String = Bra("(" + obj + TransSubExpr( lhs ) +")->clas" + tSuper)
@@ -941,7 +943,7 @@ t:+"NULLNULLNULL"
 						End If
 	
 						Local obj:String = lvar + "->clas" + tSuper
-						Return obj + "->" + TransFuncPrefix(decl.scope, decl)+ decl.ident+TransArgs( args,decl, lvar )
+						Return obj + "->" + TransFuncPrefix(decl.scope, decl)+ FuncDeclMangleIdent(decl)+TransArgs( args,decl, lvar )
 					End If
 
 				Else If TIndexExpr(lhs) Then
@@ -956,7 +958,7 @@ t:+"NULLNULLNULL"
 					'Local class:String = Bra("(" + obj + loc +")->clas" + tSuper)
 					'Local class:String = Bra("&" + decl.scope.munged)
 					Local class:String = Bra(loc + "->clas" + tSuper)
-					Return class + "->" + TransFuncPrefix(decl.scope, decl) + decl.ident+TransArgs( args,decl, loc )
+					Return class + "->" + TransFuncPrefix(decl.scope, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, loc )
 				Else
 					InternalErr
 				End If
@@ -989,7 +991,7 @@ t:+"NULLNULLNULL"
 				'Local obj:String = Bra("struct " + scope.munged + "_obj*")
 				'Local class:String = Bra("(" + obj + "o)->clas" + tSuper)
 				'Local class:String = Bra("&" + decl.scope.munged)
-				Return class + "->" + TransFuncPrefix(scope, decl) + decl.ident+TransArgs( args,decl, "o" )
+				Return class + "->" + TransFuncPrefix(scope, decl) + FuncDeclMangleIdent(decl)+TransArgs( args,decl, "o" )
 			Else
 				' Null test
 				If opt_debug Then
@@ -1030,13 +1032,14 @@ t:+"NULLNULLNULL"
 
 	Method TransFuncPrefix:String(decl:TScopeDecl, fdecl:TFuncDecl)
 		Local ident:String = fdecl.ident
-		If Not decl Or decl.ident = "Object" Or ident = "ToString" Or ident = "Compare" Or ident = "SendMessage" Then
+
+		If Not decl Or decl.ident = "Object" Or equalsBuiltInFunc(fdecl.ClassScope(), fdecl)
 			Return ""
 		Else
 			If fdecl.IsMethod() Then
-				Return "md_"
+				Return "m_"
 			Else
-				Return "fn_"
+				Return "f_"
 			End If
 		End If
 	End Method
@@ -1249,13 +1252,34 @@ t:+"NULLNULLNULL"
 	Method TransNewObjectExpr$( expr:TNewObjectExpr )
 		Local t$
 
-		If expr.instanceExpr Then
-			t = "bbObjectNew(" + Bra(expr.instanceExpr.Trans()) + "->clas)"
+		If Not expr.ctor.argDecls Or expr.ctor.argDecls.length = 0 Then
+			If expr.instanceExpr Then
+				t = "bbObjectNew(" + Bra(expr.instanceExpr.Trans()) + "->clas)"
+			Else
+				If ClassHasObjectField(expr.classDecl) Then
+					t = "bbObjectNew(&" + expr.classDecl.actual.munged + ")"
+				Else
+					t = "bbObjectAtomicNew(&" + expr.classDecl.actual.munged + ")"
+				End If
+			End If
 		Else
-			If ClassHasObjectField(expr.classDecl) Then
-				t = "bbObjectNew(&" + expr.classDecl.actual.munged + ")"
+
+			Local ctorMunged:String
+			
+			If expr.classDecl = expr.ctor.scope Then
+				ctorMunged = expr.ctor.munged
 			Else
-				t = "bbObjectAtomicNew(&" + expr.classDecl.actual.munged + ")"
+				ctorMunged = expr.classDecl.actual.munged + "_" + expr.ctor.ident + MangleMethod(expr.ctor)
+			End If
+
+			If expr.instanceExpr Then
+				t = "_" + ctorMunged + "_ObjectNew" + TransArgs( expr.args,expr.ctor, Bra(expr.instanceExpr.Trans()) + "->clas" )
+			Else
+				If ClassHasObjectField(expr.classDecl) Then
+					t = "_" + ctorMunged + "_ObjectNew" + TransArgs( expr.args,expr.ctor, "&" + expr.classDecl.actual.munged )
+				Else
+					t = "_" + ctorMunged + "_ObjectNew" + TransArgs( expr.args,expr.ctor, "&" + expr.classDecl.actual.munged)
+				End If
 			End If
 		End If
 		'Local t$="(new "+expr.classDecl.actual.munged+")"
@@ -2278,11 +2302,11 @@ End Rem
 		Local pre:String
 
 		If decl.IsMethod() Then
-			id :+ "_md"
-			pre = "md_"
+			id :+ "_m"
+			pre = "m_"
 		Else
-			id :+ "_fn"
-			pre = "fn_"
+			id :+ "_f"
+			pre = "f_"
 		End If
 
 		Local bk:String = ";"
@@ -2291,7 +2315,7 @@ End Rem
 		'	pre = "extern "
 		'End If
 'DebugLog "id = " + id
-		Emit id + " " + pre + odecl.ident + ";"
+		Emit id + " " + pre + FuncDeclMangleIdent(odecl) + ";"
 
 '		If Not proto Or (proto And Not odecl.IsExtern()) Then
 Rem
@@ -2321,6 +2345,24 @@ End Rem
 		'PopMungScope
 		EndLocalScope
 	End Method
+	
+	Method FuncDeclMangleIdent:String(fdecl:TFuncDecl)
+
+		If (Not fdecl.ClassScope()) Or equalsBuiltInFunc(fdecl.classScope(), fdecl) Then
+			Return fdecl.ident
+		End If	
+	
+		If Not fdecl.mangled Then
+			fdecl.mangled = fdecl.ident + MangleMethod(fdecl)
+		End If
+
+		Return fdecl.mangled		
+'		If fdecl.olIndex Then
+'			Return fdecl.ident + fdecl.olIndex
+'		Else
+'			Return fdecl.ident
+'		End If
+	End Method
 
 	Method EmitClassFuncProto( decl:TFuncDecl)
 		'PushMungScope
@@ -2377,9 +2419,9 @@ End Rem
 		Local pre:String = "typedef "
 		Local api:String
 		If decl.IsMethod() Then
-			id :+ "_md"
+			id :+ "_m"
 		Else
-			id :+ "_fn"
+			id :+ "_f"
 		End If
 		
 		If decl.attrs & DECL_API_WIN32 Then
@@ -2436,7 +2478,7 @@ End Rem
 
 	Method EmitFuncDecl( decl:TFuncDecl, proto:Int = False, classFunc:Int = False )
 		'If Not proto And decl.IsAbstract() Return
-		
+
 		Local tmpDebug:Int = opt_debug
 		If decl.isNoDebug() Then
 			opt_debug = False
@@ -2655,7 +2697,7 @@ End Rem
 
 	Method BBClassClassFuncProtoBuildList( classDecl:TClassDecl, list:TList )
 
-		Local reserved:String = ",New,Delete,ToString,Compare,SendMessage,_reserved1_,_reserved2_,_reserved3_,".ToLower()
+		'Local reserved:String = ",New,Delete,ToString,Compare,SendMessage,_reserved1_,_reserved2_,_reserved3_,".ToLower()
 
 		If classDecl.superClass Then
 			BBClassClassFuncProtoBuildList(classDecl.superClass, list)
@@ -2671,12 +2713,14 @@ End Rem
 				If Not fdecl.IsSemanted()
 					fdecl.Semant()
 				End If
-				If reserved.Find("," + fdecl.IdentLower() + ",") = -1 Then
+
+				If Not equalsBuiltInFunc(classDecl, fdecl) And Not equalsTorFunc(classDecl, fdecl) Then
 				
 					Local ignore:Int
 					Local link:TLink=list._head._succ
 					While link<>list._head
-						If fdecl.ident = TFuncDecl(link._value).ident Then
+						Local ofdecl:TFuncDecl = TFuncDecl(link._value)
+						If fdecl.ident = ofdecl.ident And fdecl.EqualsArgs(ofdecl) Then
 							If fdecl.overrides Then
 								If fdecl.returnTypeSubclassed Then
 									link._value = fdecl
@@ -2723,7 +2767,9 @@ End Rem
 			superid=classDecl.superClass.actual.munged
 		End If
 
-		Emit "void _" + classid + "_New" + Bra(TransObject(classdecl) + " o") + ";"
+		'Emit "void _" + classid + "_New" + Bra(TransObject(classdecl) + " o") + ";"
+		
+		EmitClassDeclNewListProto(classDecl)
 		
 		If classHierarchyHasFunction(classDecl, "Delete") Then
 			Emit "void _" + classid + "_Delete" + Bra(TransObject(classdecl) + " o") + ";"
@@ -2741,7 +2787,7 @@ End Rem
 			Emit "BBOBJECT _" + classid + "_SendMessage(" + TransObject(classdecl) + " o, BBOBJECT message, BBOBJECT source);"
 		End If
 
-		Local reserved:String = ",New,Delete,ToString,Compare,SendMessage,_reserved1_,_reserved2_,_reserved3_,".ToLower()
+		'Local reserved:String = ",New,Delete,ToString,Compare,SendMessage,_reserved1_,_reserved2_,_reserved3_,".ToLower()
 
 		classDecl.SemantParts()
 
@@ -2752,7 +2798,7 @@ End Rem
 			Local fdecl:TFuncDecl =TFuncDecl( decl )
 			If fdecl
 
-				If reserved.Find("," + fdecl.IdentLower() + ",") = -1 Then
+				If Not equalsBuiltInFunc(classDecl, fdecl) And Not equalsTorFunc(classDecl, fdecl) Then
 					EmitClassFuncProto( fdecl )
 					Continue
 				End If
@@ -2924,11 +2970,14 @@ End Rem
 		End If
 
 	End Method
-	
+
 	Method classHasFunction:Int(classDecl:TClassDecl, func:String)
 		Local f:String = func.ToLower()
 		For Local decl:TFuncDecl = EachIn classDecl.Decls()
-			If decl.IdentLower() = f Then
+			If Not decl.IsSemanted() Then
+				decl.Semant
+			End If
+			If decl.IdentLower() = f And equalsBuiltInFunc(classDecl.superClass, decl) Then
 				Return True
 			End If
 		Next
@@ -2978,7 +3027,7 @@ End Rem
 			Emit "{"
 			Emit "BBDEBUGDECL_CONST,"
 			Emit Enquote(decl.ident) + ","
-			Emit Enquote(TransDebugScopeType(decl.ty) + TransDebugMetaData(decl.metadata)) + ","
+			Emit Enquote(TransDebugScopeType(decl.ty) + TransDebugMetaData(decl.metadata.metadataString)) + ","
 			
 			_appInstance.mapStringConsts(decl.value)
 			
@@ -2999,7 +3048,7 @@ End Rem
 			Emit "{"
 			Emit "BBDEBUGDECL_FIELD,"
 			Emit Enquote(decl.ident) + ","
-			Emit Enquote(TransDebugScopeType(decl.ty) + TransDebugMetaData(decl.metadata)) + ","
+			Emit Enquote(TransDebugScopeType(decl.ty) + TransDebugMetaData(decl.metadata.metadataString)) + ","
 
 			Local offset:String = ".field_offset=offsetof" + Bra("struct " + classDecl.munged + "_obj," + decl.munged)
 '			If WORD_SIZE = 8 Then
@@ -3058,10 +3107,10 @@ End Rem
 				s:+ TransDebugScopeType(decl.retType)
 			End If
 
-			s:+ TransDebugMetaData(decl.metadata)
+			s:+ TransDebugMetaData(decl.metadata.metadataString)
 
 			Emit Enquote(s) + ","
-			If decl.IsMethod() Then
+			If decl.IsMethod() Or decl.IsCTor() Then 
 				Emit "&_" + decl.munged
 			Else
 				Emit "&" + decl.munged
@@ -3070,7 +3119,7 @@ End Rem
 	End Method
 
 	Method BBClassClassFuncsDebugScopeBuildList(classDecl:TClassDecl, list:TList)
-		Local reserved:String = ",New,Delete,ToString,Compare,SendMessage,_reserved1_,_reserved2_,_reserved3_,".ToLower()
+		'Local reserved:String = ",New,Delete,ToString,Compare,SendMessage,_reserved1_,_reserved2_,_reserved3_,".ToLower()
 
 		For Local decl:TDecl=EachIn classDecl.GetAllFuncDecls(Null, False)
 			Local fdecl:TFuncDecl =TFuncDecl( decl )
@@ -3081,7 +3130,8 @@ End Rem
 				If Not classDecl.IsInterface() And fdecl.IsAbstract() Then
 					Continue
 				End If
-				If reserved.Find("," + fdecl.IdentLower() + ",") = -1 Then
+
+				If Not equalsBuiltInFunc(classDecl, fdecl) Then
 				
 					Local ignore:Int
 					Local link:TLink=list._head._succ
@@ -3164,7 +3214,6 @@ End Rem
 	End Method
 
 	Method CountBBClassClassFuncsDebugScope(classDecl:TClassDecl, count:Int Var)
-		Local reserved:String = ",New,Delete,ToString,Compare,SendMessage,_reserved1_,_reserved2_,_reserved3_,".ToLower()
 
 		For Local decl:TDecl=EachIn classDecl.GetAllFuncDecls(Null, False)
 			Local fdecl:TFuncDecl =TFuncDecl( decl )
@@ -3172,7 +3221,8 @@ End Rem
 				If Not classDecl.IsInterface() And fdecl.IsAbstract() Then
 					Continue
 				End If
-				If reserved.Find("," + fdecl.IdentLower() + ",") = -1 Then
+
+				If Not equalsBuiltInFunc(classDecl, fdecl) Then
 					count :+ 1
 				End If
 			End If
@@ -3245,7 +3295,7 @@ End Rem
 		Local superid$=classDecl.superClass.actual.munged
 
 		' process nested functions for new
-		Local decl:TFuncDecl = classDecl.FindFuncDecl("new")
+		Local decl:TFuncDecl = classDecl.FindFuncDecl("new",,,,,,SCOPE_CLASS_HEIRARCHY)
 		If decl And decl.scope = classDecl Then ' only our own New method, not any from superclasses
 			decl.Semant
 			' emit nested protos
@@ -3259,10 +3309,10 @@ End Rem
 			Next
 		End If
 
-		EmitClassDeclNew(classDecl)
+		EmitClassDeclNewList(classDecl)
 		
 		' process nested functions for delete
-		decl = classDecl.FindFuncDecl("delete")
+		decl = classDecl.FindFuncDecl("delete",,,,,,SCOPE_CLASS_HEIRARCHY)
 		If decl Then
 			decl.Semant
 			' emit nested protos
@@ -3358,7 +3408,7 @@ End Rem
 		Else
 			Emit "BBDEBUGSCOPE_USERTYPE,"
 		End If
-		Emit EnQuote(classDecl.ident + TransDebugMetaData(classDecl.metadata)) + ","
+		Emit EnQuote(classDecl.ident + TransDebugMetaData(classDecl.metadata.metadataString)) + ","
 
 		Emit "{"
 		
@@ -3409,7 +3459,7 @@ End Rem
 						
 							For Local f:TFuncDecl = EachIn fdecls
 								Mungdecl f
-								If f.ident = func.ident Then
+								If f.ident = func.ident And func.EqualsFunc(f) Then
 									Emit "_" + f.munged + ","
 									Exit
 								End If
@@ -3518,10 +3568,10 @@ End Rem
 		' methods/funcs
 		'reserved = "New,Delete,ToString,ObjectCompare,SendMessage".ToLower()
 
-		
 		'For Local decl:TFuncDecl = EachIn classDecl.Decls()
 		For Local decl:TFuncDecl = EachIn fdecls
-			If reserved.Find("," + decl.IdentLower() + ",") = -1 Then
+
+			If Not equalsBuiltInFunc(classDecl, decl) And Not equalsTorFunc(classDecl, decl) Then
 
 				MungDecl decl
 
@@ -3544,68 +3594,321 @@ End Rem
 
 	End Method
 
-	Method EmitClassDeclNew( classDecl:TClassDecl )
+	Method EmitClassDeclNew( classDecl:TClassDecl, fdecl:TFuncDecl )
 		Local classid$=classDecl.munged
 		Local superid$=classDecl.superClass.actual.munged
+'Emit "// EmitClassDeclNew for " + classDecl.ident
+		Local t:String = "void _" 
+		
+		If fdecl.argDecls.Length Then
+			If classDecl = fdecl.scope Then
+				t :+ fdecl.munged
+			Else
+				t :+ classDecl.munged + "_" + fdecl.ident + MangleMethod(fdecl)
+			End If
+		Else
+			t :+ classid + "_New"
+		End If
+		
+		'Find decl we override
+		Local odecl:TFuncDecl=fdecl
+		While odecl.overrides
+			odecl=odecl.overrides
+		Wend
 
-		' New
-'		If opt_issuperstrict Then
-			Emit "void _" + classid + "_New" + Bra(TransObject(classdecl) + " o") + " {"
-'		Else
-'			Emit "int _" + classid + "_New" + Bra(TransObject(classdecl) + " o") + " {"
-'		End If
+		Local args:String = TransObject(classdecl) + " o"
 
-		If classDecl.superClass.ident = "Object" Then
-			Emit "bbObjectCtor(o);"
+		For Local i:Int=0 Until fdecl.argDecls.Length
+			Local arg:TArgDecl=fdecl.argDecls[i]
+			Local oarg:TArgDecl=odecl.argDecls[i]
+			MungDecl arg, True
+			If args args:+","
+			If Not TFunctionPtrType(oarg.ty) Then
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )+" "+arg.munged
+				Else
+					args:+ oarg.castTo + " " + arg.munged
+				End If
+			Else
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )
+				Else
+					args:+ oarg.castTo
+				End If
+			End If
+			If arg.ty.EqualsType( oarg.ty ) Continue
+		Next
+		
+		Emit t + Bra(args) + " {"
+		
+		Local newDecl:TNewDecl = TNewDecl(fdecl)
+		
+		' calling constructor?
+		If newDecl And newDecl.chainedCtor Then
+			mungdecl newDecl.chainedCtor.ctor
+			
+			Emit "_" + newDecl.chainedCtor.ctor.ClassScope().munged + "_" + newDecl.chainedCtor.ctor.ident + MangleMethod(newDecl.chainedCtor.ctor) + TransArgs(newDecl.chainedCtor.args, newDecl.chainedCtor.ctor, "o") + ";"
 		Else
-			Emit "_" + superid + "_New(o);"
+			If classDecl.superClass.ident = "Object" Then
+				Emit "bbObjectCtor(o);"
+			Else
+				Emit "_" + superid + "_New(o);"
+			End If
 		End If
 
 		Emit "o->clas = (BBClass*)&" + classid + ";"
 
-		' field initialisation
-		For Local decl:TFieldDecl=EachIn classDecl.Decls()
-			Local fld:String
-
-			' ((int*)((char*)o + 5))[0] =
-			fld :+ TransFieldRef(decl, "o")
+		' only initialise fields if we are not chaining to a local (in our class) constructor.
+		' this prevents fields being re-initialised through the call-chain.
+		If Not newDecl.chainedCtor Or (newDecl.chainedCtor And classDecl <> newDecl.chainedCtor.ctor.scope) Then
 
-			If decl.init Then
-				If TObjectType(decl.ty) And TObjectType(decl.ty).classdecl.IsExtern() And TObjectType(decl.ty).classdecl.IsStruct() Then
-					' skip for uninitialised extern type
-					If Not isPointerType(decl.ty) And TConstExpr(decl.init) And Not TConstExpr(decl.init).value Then
-						Continue
+			' field initialisation
+			For Local decl:TFieldDecl=EachIn classDecl.Decls()
+			
+				Local fld:String
+	
+				' ((int*)((char*)o + 5))[0] =
+				fld :+ TransFieldRef(decl, "o")
+	
+				If decl.init Then
+					If TObjectType(decl.ty) And TObjectType(decl.ty).classdecl.IsExtern() And TObjectType(decl.ty).classdecl.IsStruct() Then
+						' skip for uninitialised extern type
+						If Not isPointerType(decl.ty) And TConstExpr(decl.init) And Not TConstExpr(decl.init).value Then
+							Continue
+						End If
+					End If
+	
+					' initial value
+					fld :+ "= " + decl.init.Trans() + ";";
+				Else
+					If TNumericType(decl.ty) Or TObjectType(decl.ty) Or IsPointerType(decl.ty, 0, TType.T_POINTER) Then
+						fld :+ "= 0;"
+					Else If TFunctionPtrType(decl.ty) Then
+						fld :+ "= &brl_blitz_NullFunctionError;"
+					Else If TStringType(decl.ty) Then
+						fld :+ "= &bbEmptyString;"
+					Else If TArrayType(decl.ty) Then
+						fld :+ "= &bbEmptyArray;"
 					End If
 				End If
+	
+				Emit fld
+			Next
+		
+		End If
+
+		'Local decl:TFuncDecl = classDecl.FindFuncDecl("new",,,,,,SCOPE_CLASS_LOCAL)
+		If fdecl And (fdecl.scope = classDecl Or fdecl.argDecls.Length) Then ' only our own New method, not any from superclasses
+			fdecl.Semant
+			If fdecl.munged <> "bbObjectCtor" Then
+				EmitLocalDeclarations(fdecl)
+				EmitBlock fdecl
+			End If
+		End If
+
+		'
+		Emit "}"
+	End Method
+
+	Method EmitClassDeclNewList( classDecl:TClassDecl )
+		Local classid$=classDecl.munged
+		Local superid$=classDecl.superClass.actual.munged
+'DebugStop
+'Emit "// EmitClassDeclNewListZZZZ"
+		Local newDecls:TFuncDeclList = TFuncDeclList(classdecl.FindDeclList("new", SCOPE_CLASS_LOCAL))
+		
+		For Local fdecl:TFuncDecl = EachIn newDecls
+		
+'Emit "// EmitClassDeclNewList"
+			EmitClassDeclNew(classDecl, fdecl)
+
+			' generate "objectNew" function if required
+			If fdecl.argDecls And fdecl.argDecls.length Then
+				EmitClassDeclNewInit(classDecl, fdecl)
+			End If
+		
+		Next
+
+	End Method
+
+	Method EmitClassDeclNewListProto( classDecl:TClassDecl )
+		Local classid$=classDecl.munged
+		Local superid$=classDecl.superClass.actual.munged
+
+		Local newDecls:TFuncDeclList = TFuncDeclList(classdecl.FindDeclList("new", SCOPE_CLASS_LOCAL))
+		
+		For Local fdecl:TFuncDecl = EachIn newDecls
+		
+			EmitClassDeclNewProto(classDecl, fdecl)
+		
+			' generate "objectNew" function if required
+			If fdecl.argDecls And fdecl.argDecls.length Then
+				EmitClassDeclObjectNewProto(classDecl, fdecl)
+			End If
+		
+		Next
+
+	End Method
+	
+	Method EmitClassDeclNewInit(classDecl:TClassDecl, fdecl:TFuncDecl)
+
+		Local funcMunged:String
+		
+		If classDecl = fdecl.scope Then
+			funcMunged = fdecl.munged
+		Else
+			funcMunged = classDecl.munged + "_" + fdecl.ident + MangleMethod(fdecl)
+		End If
+
+		Local t:String = TransObject(classdecl) + " _" + funcMunged + "_ObjectNew"
+
+		'Find decl we override
+		Local odecl:TFuncDecl=fdecl
+		While odecl.overrides
+			odecl=odecl.overrides
+		Wend
+
+		Local args:String = "BBClass * clas"
 
-				' initial value
-				fld :+ "= " + decl.init.Trans() + ";";
+		For Local i:Int=0 Until fdecl.argDecls.Length
+			Local arg:TArgDecl=fdecl.argDecls[i]
+			Local oarg:TArgDecl=odecl.argDecls[i]
+			MungDecl arg, True
+			If args args:+","
+			If Not TFunctionPtrType(oarg.ty) Then
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )+" "+arg.munged
+				Else
+					args:+ oarg.castTo + " " + arg.munged
+				End If
 			Else
-				If TNumericType(decl.ty) Or TObjectType(decl.ty) Or IsPointerType(decl.ty, 0, TType.T_POINTER) Then
-					fld :+ "= 0;"
-				Else If TFunctionPtrType(decl.ty) Then
-					fld :+ "= &brl_blitz_NullFunctionError;"
-				Else If TStringType(decl.ty) Then
-					fld :+ "= &bbEmptyString;"
-				Else If TArrayType(decl.ty) Then
-					fld :+ "= &bbEmptyArray;"
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )
+				Else
+					args:+ oarg.castTo
 				End If
 			End If
+			If arg.ty.EqualsType( oarg.ty ) Continue
+		Next
+		
+		Emit t + Bra(args) + " {"
+
+		t = TransObject(classdecl) + " o = "
 
-			Emit fld
+		If ClassHasObjectField(classDecl) Then
+			t :+ "bbObjectNewNC"
+		Else
+			t :+ "bbObjectAtomicNewNC"
+		End If
+		
+		Emit t + "(clas);"
+		
+		t = "_" + funcMunged + "(o"
+		
+		For Local i:Int=0 Until fdecl.argDecls.Length
+			Local arg:TArgDecl=fdecl.argDecls[i]
+			t :+ ", " + arg.munged
 		Next
+		
+		Emit t + ");"
+		
+		Emit "return o;"
+		
+		Emit "}"
+		
+	End Method
 
-		Local decl:TFuncDecl = classDecl.FindFuncDecl("new")
-		If decl And decl.scope = classDecl Then ' only our own New method, not any from superclasses
-			decl.Semant
-			If decl.munged <> "bbObjectCtor" Then
-				EmitLocalDeclarations(decl)
-				EmitBlock decl
+	Method EmitClassDeclNewProto( classDecl:TClassDecl, fdecl:TFuncDecl )
+		Local classid$=classDecl.munged
+		Local superid$=classDecl.superClass.actual.munged
+'Emit "// EmitClassDeclNew for " + classDecl.ident
+		Local t:String = "void _" 
+		
+		If fdecl.argDecls.Length Then
+			If classDecl = fdecl.scope Then
+				t :+ fdecl.munged
+			Else
+				t :+ classDecl.munged + "_" + fdecl.ident + MangleMethod(fdecl)
+			End If
+		Else
+			t :+ classid + "_New"
+		End If
+		
+		'Find decl we override
+		Local odecl:TFuncDecl=fdecl
+		While odecl.overrides
+			odecl=odecl.overrides
+		Wend
+
+		Local args:String = TransObject(classdecl) + " o"
+
+		For Local i:Int=0 Until fdecl.argDecls.Length
+			Local arg:TArgDecl=fdecl.argDecls[i]
+			Local oarg:TArgDecl=odecl.argDecls[i]
+			MungDecl arg, True
+			If args args:+","
+			If Not TFunctionPtrType(oarg.ty) Then
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )+" "+arg.munged
+				Else
+					args:+ oarg.castTo + " " + arg.munged
+				End If
+			Else
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )
+				Else
+					args:+ oarg.castTo
+				End If
 			End If
+			If arg.ty.EqualsType( oarg.ty ) Continue
+		Next
+		
+		Emit t + Bra(args) + ";"
+	End Method
+	
+	Method EmitClassDeclObjectNewProto(classDecl:TClassDecl, fdecl:TFuncDecl)
+
+		Local t:String = TransObject(classdecl) + " _"
+		
+		If classDecl = fdecl.scope Then
+			t :+ fdecl.munged
+		Else
+			t :+ classDecl.munged + "_" + fdecl.ident + MangleMethod(fdecl)
 		End If
+		
+		t:+ "_ObjectNew"
+			
+		'Find decl we override
+		Local odecl:TFuncDecl=fdecl
+		While odecl.overrides
+			odecl=odecl.overrides
+		Wend
+
+		Local args:String = "BBClass * clas"
+
+		For Local i:Int=0 Until fdecl.argDecls.Length
+			Local arg:TArgDecl=fdecl.argDecls[i]
+			Local oarg:TArgDecl=odecl.argDecls[i]
+			MungDecl arg, True
+			If args args:+","
+			If Not TFunctionPtrType(oarg.ty) Then
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )+" "+arg.munged
+				Else
+					args:+ oarg.castTo + " " + arg.munged
+				End If
+			Else
+				If Not odecl.castTo Then
+					args:+TransType( oarg.ty, arg.munged )
+				Else
+					args:+ oarg.castTo
+				End If
+			End If
+			If arg.ty.EqualsType( oarg.ty ) Continue
+		Next
+		
+		Emit t + Bra(args) + ";"
 
-		'
-		Emit "}"
 	End Method
 
 	Method EmitClassDeclDelete( classDecl:TClassDecl )
@@ -3619,7 +3922,7 @@ End Rem
 '			Emit "int _" + classid + "_Delete" + Bra(TransObject(classdecl) + " o") + " {"
 '		End If
 
-		Local decl:TFuncDecl = classDecl.FindFuncDecl("delete")
+		Local decl:TFuncDecl = classDecl.FindFuncDecl("delete",,,,,,SCOPE_CLASS_HEIRARCHY)
 		If decl Then
 			decl.Semant
 			EmitLocalDeclarations(decl)
@@ -3768,7 +4071,7 @@ End Rem
 		Local func:String
 
 		' method / function
-		If funcDecl.IsMethod() Then
+		If funcDecl.IsMethod() Or funcDecl.IsCTor() Then
 			func :+ "-"
 		Else
 			func :+ "+"
@@ -3973,13 +4276,11 @@ End Rem
 				Emit "-Delete()=" + Enquote("_" + classDecl.munged + "_Delete")
 			End If
 
-			Local reserved:String = ",New,Delete,_reserved1_,_reserved2_,_reserved3_,".ToLower()
-
 			For Local decl:TDecl=EachIn classDecl.Decls()
 
 				Local fdecl:TFuncDecl=TFuncDecl( decl )
 				If fdecl
-					If reserved.Find("," + fdecl.IdentLower() + ",") = -1 Then
+					If Not equalsIfcBuiltInFunc(classDecl, fdecl) Then
 						EmitIfcClassFuncDecl fdecl
 					End If
 					Continue
@@ -4188,6 +4489,7 @@ End Rem
 '			Emit prefix + decl.munged+";"
 
 			'PushMungScope
+			funcMungs = New TMap
 			BeginLocalScope
 
 			For Local decl:TDecl=EachIn cdecl.Semanted()

+ 570 - 133
decl.bmx

@@ -44,6 +44,12 @@ Const CLASS_INTERFACE:Int=  $001000
 Const CLASS_THROWABLE:Int=  $002000
 Const CLASS_STRUCT:Int=     $004000
 
+Const SCOPE_FUNC:Int = 0
+Const SCOPE_CLASS_LOCAL:Int = 1
+Const SCOPE_CLASS_HEIRARCHY:Int = 2
+Const SCOPE_MODULE:Int = 3
+Const SCOPE_ALL:Int = 4
+
 Global _env:TScopeDecl
 Global _envStack:TList=New TList
 
@@ -61,6 +67,36 @@ Function PopEnv()
 End Function
 
 Type TFuncDeclList Extends TList
+	Field ident:String
+	Field _identLower:String
+	
+	Method IdentLower:String()
+		If Not _identLower Then
+			_identLower = ident.ToLower()
+		End If
+		Return _identLower
+	End Method
+End Type
+
+Type TMetadata
+
+	Field metadataString:String
+
+	' key/value pairs
+	Field meta:TMap
+
+	Method InsertMeta(key:String, value:String)
+		If Not meta Then
+			meta = New TMap
+		End If
+		
+		meta.Insert(key, value)
+	End Method
+
+	Method HasMeta:Int(key:String)
+		Return meta And meta.Contains(key.ToLower())
+	End Method
+	
 End Type
 
 Type TDecl
@@ -70,7 +106,7 @@ Type TDecl
 	Field actual:TDecl
 	Field scope:TScopeDecl
 	Field attrs:Int
-	Field metadata:String
+	Field metadata:TMetadata = New TMetadata
 	
 	Field declImported:Int = False
 	Field generated:Int
@@ -667,20 +703,21 @@ Type TScopeDecl Extends TDecl
 		'Local _decls:TMap
 		Local tdecl_:Object=declsMap.ValueForKey( decl.IdentLower() )
 		
-		'If TFuncDecl( decl )
-		'	Local funcs:TFuncDeclList=TFuncDeclList( tdecl_ )
-		'	If funcs Or Not tdecl_
-		'		If Not funcs
-		'			funcs=New TFuncDeclList
-		'			declsMap.Insert ident.ToLower(),funcs
-		'		EndIf
-		'		funcs.AddLast TFuncDecl( decl )
-		'	Else
-		'		Err "Duplicate identifier '"+ident+"'."
-		'	EndIf
-		'Else
-		If Not tdecl_
-'DebugLog "Adding " + decl.ident
+		If TFuncDecl( decl )
+			Local funcs:TFuncDeclList=TFuncDeclList( tdecl_ )
+			If funcs Or Not tdecl_
+				If Not funcs
+					funcs=New TFuncDeclList
+					funcs.ident = decl.IdentLower()
+					declsMap.Insert decl.IdentLower(),funcs
+				EndIf
+
+				funcs.AddLast TFuncDecl( decl )
+				Return
+			Else
+				Err "Duplicate identifier '"+decl.ident+"'."
+			EndIf
+		Else If Not tdecl_
 			declsMap.Insert decl.IdentLower(),decl
 		Else
 			Err "Duplicate identifier '"+decl.ident+"'."
@@ -726,11 +763,88 @@ Type TScopeDecl Extends TDecl
 		
 		Local tscope:TScopeDecl=Self
 		While tscope
-			Local decl:TDecl=TDecl(tscope.GetDecl( ident ))
+			Local decl:Object=tscope.GetDecl( ident )
 			If decl Return decl
 			tscope=tscope.scope
 		Wend
 	End Method
+	
+	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+
+		Local decl:Object=Object(declsMap.ValueForKey( ident ))
+
+		If Not decl Return Null
+
+		If TFuncDeclList(decl) Then
+			For Local fdecl:TFuncDecl = EachIn TFuncDeclList(decl)
+
+				If Not fdecl.IsSemanted() Then
+					fdecl.Semant
+				End If
+				
+				Local found:Int
+				For Local func:TFuncDecl = EachIn declList
+					If func.equalsFunc(fdecl) Then
+						found = True
+						Exit
+'Else
+'Print func.ToString() + "  didn't match  " + fdecl.ToString()
+					End If
+				Next
+				
+				If Not found Then
+					declList.AddLast(fdecl)
+				End If
+			Next
+			
+			Return declList
+		End If		
+		
+		Return decl
+		
+	End Method
+	
+	' returns a list of all matching named decls in scope
+	Method FindDeclList:Object(ident:String, override:Int = False, declList:TFuncDeclList = Null, maxSearchDepth:Int = SCOPE_ALL )
+	
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+	
+		If Not override And _env<>Self Return GetDeclList( ident, declList, maxSearchDepth )
+		
+		Local tscope:TScopeDecl=Self
+		While tscope
+			Local decl:Object=tscope.GetDeclList( ident, declList, maxSearchDepth )
+			'If decl And (Not TFuncDeclList(decl) And declList.IsEmpty()) Return decl
+			If decl Then
+				If TFuncDeclList(decl) Then
+					If TFuncDeclList(decl) <> declList Then
+						For Local d:TDecl = EachIn TFuncDeclList(decl)
+							declList.AddLast(d)
+						Next
+					End If
+				Else
+					declList.AddLast(decl)
+				End If
+			End If
+			tscope=tscope.scope
+			
+			If TClassDecl(tscope) And maxSearchDepth < SCOPE_CLASS_HEIRARCHY Then
+				Exit
+			Else If TModuleDecl(tscope) And maxSearchDepth < SCOPE_ALL Then
+				Exit
+			End If
+		Wend
+		
+		Return declList
+	End Method
+
+	
 
 '	Method FindDecl:Object( ident$, static:Int = False )
 '		Local decl:Object=GetDecl( ident )
@@ -845,67 +959,27 @@ End Rem
 		Return decl
 	End Method
 	
-	Method FindFuncDecl:TFuncDecl( ident$,argExprs:TExpr[] = Null,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False )
-'DebugLog "FindFuncDecl : " + ident
-'If ident = "FixPath" Then DebugStop
-		'Local funcs:TFuncDeclList=TFuncDeclList( FindDecl( ident ) )
-		Local f:TDecl = TDecl(findDecl(ident))
-		If Not f Then Return Null
-		
-		Local func:TFuncDecl = TFuncDecl(f)
-		If Not func Then
-			If TVarDecl(f) Then
-				If Not f.IsSemanted() Then
-					f.Semant()
-				End If
-				If TFunctionPtrType(TVarDecl(f).ty) Then
-					func = TFunctionPtrType(TVarDecl(f).ty).func
-					If Not func.scope Then
-						func.scope = f.scope
-					End If
-					If Not func.ident Then
-						func.ident = f.ident
-					End If
-				End If
-			End If
-		End If
-		If Not func Return Null
+	Method FindBestMatchForArgs:TFuncDecl(argExprs:TExpr[], matches:TList)
 
-		If Not argExprs
-			argExprs = New TExpr[0]
-		End If
-	
-		func.Semant()
+		Local bestMatch:TFuncDecl = Null
+		Local totals:Int[] = New Int[matches.count()]
+		Local index:Int
 		
-		Local match:TFuncDecl,isexact:Int
-		Local _err$
-		Local errorDetails:String
+		For Local func:TFuncDecl = EachIn matches
 
-		While True
-			If Not func.CheckAccess() Exit
-			
 			Local argDecls:TArgDecl[]=func.argDecls
 			
-			If argExprs.Length>argDecls.Length Exit
-			
-			Local exact:Int=True
-			Local possible:Int=True
-			
-			' we found a matching name - this is probably the one we mean...
-			If isArg Then
-				match=func
-				Exit
-			End If
-			
 			For Local i:Int=0 Until argDecls.Length
-
+	
 				If i<argExprs.Length And argExprs[i]
 				
 					Local declTy:TType=argDecls[i].ty
 					Local exprTy:TType=argExprs[i].exprType
 
 					If TFunctionPtrType(declTy) And TInvokeExpr(argExprs[i]) Then
-						If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(argExprs[i]).decl) Continue
+						If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(argExprs[i]).decl) Then
+							Continue
+						End If
 					End If
 
 					' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
@@ -919,53 +993,300 @@ End Rem
 					
 					If exprTy.EqualsType( declTy ) Continue
 					
-					exact=False
+					' not an exact match. increase distance...
+					totals[index] :+ exprTy.DistanceToType(declTy)
 					
-					If Not explicit And exprTy.ExtendsType( declTy ) Continue
+				End If
+				
+			Next
+			
+			index :+ 1
 
-					' make a more helpful error message
-					errorDetails :+ "Argument #"+(i+1)+" is ~q" + exprTy.ToString()+"~q but declaration is ~q"+declTy.ToString()+"~q. "
+		Next
+		
+		Local tot:Int = -1
+		index = 0
+		Local i:Int
+		For Local func:TFuncDecl = EachIn matches
+			If tot = -1 Or totals[i] < tot Then
+				tot = totals[i]
+				bestMatch = func
+			Else If tot = totals[i] Then
+				' a tie?
+				Err "Unable to determine overload to use: "+ bestMatch.ToString()+" or "+func.ToString()+"."
+			End If
+			i :+ 1
+		Next
+		
+		Return bestMatch
+		
+	End Method
+	
+	Method FindFuncDecl:TFuncDecl( ident$,argExprs:TExpr[] = Null,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False, maxSearchDepth:Int )
+'DebugLog "FindFuncDecl : " + ident
+'If ident = "new" Then DebugStop
+		Local foundIdentMatch:Int
+		Local funcs:TFuncDeclList
 
-				Else If Not argDecls[i].init
+		' does ident exist?
+		Local f:Object = FindDeclList(ident, True,,maxSearchDepth)
+		If Not f Then Return Null
+		
+		funcs = TFuncDeclList( f )
+		Local fp:TFuncDecl
+		
+		' not a function list, test for a function ptr var
+		If Not funcs Or funcs.IsEmpty() Then
 
-					If (func.attrs & FUNC_PTR) Or isIdentExpr Then
-						exact=False
-						Exit
+			' we found a funcdecl
+			If TFuncDecl(f) Then
+				funcs = New TFuncDeclList
+				funcs.AddLast(f)
+			End If
+			
+			If TVarDecl(f) Then
+				If Not TVarDecl(f).IsSemanted() Then
+					TVarDecl(f).Semant()
+				End If
+				If TFunctionPtrType(TVarDecl(f).ty) Then
+					funcs = New TFuncDeclList
+					fp = TFunctionPtrType(TVarDecl(f).ty).func
+					If Not fp.scope Then
+						fp.scope = TVarDecl(f).scope
 					End If
+					If Not fp.ident Then
+						fp.ident = TVarDecl(f).ident
+					End If
+					funcs.AddLast fp
+				End If
+			End If
+		End If
+		' was neither... lets bug out
+		If Not funcs Return Null
+		
+'		If Not funcs Then Return Null
+		
+		For Local func:TDecl = EachIn funcs
+			func.Semant()
+		Next
+		
+		'Local f:TDecl = TDecl(findDecl(ident))
+		'If Not f Then Return Null
+		
+				
+			'Local func:TFuncDecl = TFuncDecl(f)
+'			If Not func Then
+'				If TVarDecl(f) Then
+'					If Not f.IsSemanted() Then
+'						f.Semant()
+'					End If
+'					If TFunctionPtrType(TVarDecl(f).ty) Then
+'						func = TFunctionPtrType(TVarDecl(f).ty).func
+'						If Not func.scope Then
+'							func.scope = f.scope
+'						End If
+'						If Not func.ident Then
+'							func.ident = f.ident
+'						End If
+'					End If
+'				End If
+'			End If
+'			If Not func Return Null
+	
+		If Not argExprs
+			argExprs = New TExpr[0]
+		End If
+	
+		'func.Semant()
+		
+		Local match:TFuncDecl,isexact:Int
+		Local _err$
+		Local errorDetails:String
+		Local matches:TList = New TList
+
+		Local noExtendString:Int = True
+		Local generateWarnings:Int = False
+
+		' double test for matches.
+		' * first time through we don't allow up-casting args to String
+		'    if we get a match on the first pass, we'll take it.
+		' * second iteration we allow up-casting numerics to string
+		' * third iteration is valid if opt_warnover is enabled
+		'    this will allow down-casting of numerics (eg. double->float)
+		'    warnings will be generated if this produces valid results.
+		' if after all that, there's no match, then we can fail it.
+		For Local n:Int = 0 Until 3
+		
+			If n > 1 Then
+				If Not opt_warnover Then
+					Continue
+				Else
+					generateWarnings = True
+				End If
+			End If
+		
+			errorDetails = ""
+		
+			If n Then
+				noExtendString = False
+			End If
 
-					' if this argument is missing and there isn't a default...
-					Err "Missing function parameter '" + argDecls[i].ident + "'"
+			For Local iDecl:TDecl = EachIn funcs
+			
+				Local func:TFuncDecl = TFuncDecl(iDecl)
+				
+				If Not func Then
+					If TVarDecl(iDecl) Then
+'						If Not TVarDecl(iDecl).IsSemanted() Then
+'							TVarDecl(f).Semant()
+'						End If
+						If TFunctionPtrType(TVarDecl(iDecl).ty) Then
+							'funcs = New TFuncDeclList
+							fp = TFunctionPtrType(TVarDecl(iDecl).ty).func
+							If Not fp.scope Then
+								fp.scope = TVarDecl(iDecl).scope
+							End If
+							If Not fp.ident Then
+								fp.ident = TVarDecl(iDecl).ident
+							End If
+							'funcs.AddLast fp
+							func = fp
+						End If
+					End If
+					
+					If Not func Then
+						Continue
+					End If
+				End If
+				
+	
+			'While True
+				If Not func.CheckAccess() Continue
+				
+				Local argDecls:TArgDecl[]=func.argDecls
+				
+				If argExprs.Length>argDecls.Length Continue
+				
+				Local exact:Int=True
+				Local possible:Int=True
+				
+				foundIdentMatch = True
+				
+				' we found a matching name - this is probably the one we mean...
+				If isArg Then
+					'match=func
+					matches.AddLast(func)
+					Exit
+				End If
+				
+				For Local i:Int=0 Until argDecls.Length
+	
+					If i<argExprs.Length And argExprs[i]
+					
+						Local declTy:TType=argDecls[i].ty
+						Local exprTy:TType=argExprs[i].exprType
+						
+						Local widensTest:Int = True
+						
+						' for numeric constants, allow them to be auto-cast unless
+						'If TConstExpr(argExprs[i]) And TNumericType(exprTy) And Not TConstExpr(argExprs[i]).typeSpecific Then
+						'	widensTest = False
+						'End If
+	
+						If TFunctionPtrType(declTy) And TInvokeExpr(argExprs[i]) Then
+							If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(argExprs[i]).decl) Continue
+						End If
+	
+						' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
+						If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(argExprs[i]) And TInvokeExpr(argExprs[i]).invokedWithBraces = 0 Then
+							Continue
+						End If
+						
+						If TFunctionPtrType(declTy) And IsPointerType(exprTy, TType.T_BYTE) Then
+							Continue
+						End If
+						
+						If exprTy.EqualsType( declTy ) Continue
+						
+						exact=False
+						
+						If Not generateWarnings Then
+							If Not explicit And exprTy.ExtendsType( declTy, noExtendString, widensTest ) Continue
+						Else
+							If Not explicit Then
+								' fails widen test
+								If Not exprTy.ExtendsType( declTy, noExtendString, True ) Then
+									' but passes non-widen test
+									If exprTy.ExtendsType( declTy, noExtendString, False ) Then
+										' generate a warning, and accept it
+										Warn "In call to " + func.ToString()+ ". Argument #"+(i+1)+" is ~q" + exprTy.ToString()+"~q but declaration is ~q"+declTy.ToString()+"~q. "
+										Continue
+									End If
+								Else
+									Continue
+								End If
+							End If
+						End If
+	
+						' make a more helpful error message
+						errorDetails :+ "Argument #"+(i+1)+" is ~q" + exprTy.ToString()+"~q but declaration is ~q"+declTy.ToString()+"~q. "
 
-				Else ' for case of argdecls having default args
-					exact=False
-					If Not explicit Exit
+					Else If Not argDecls[i].init
+	
+						If (func.attrs & FUNC_PTR) Or isIdentExpr Then
+							exact=False
+							Exit
+						End If
+	
+						' if this argument is missing and there isn't a default...
+						errorDetails :+  "Missing function parameter '" + argDecls[i].ident + "'"
+	
+					Else ' for case of argdecls having default args
+						exact=False
+						If Not explicit Exit
+					EndIf
+				
+					possible=False
+					Exit
+				Next
+				
+				If Not possible Continue
+				
+				If exact
+					If isexact
+						Err "Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
+					Else
+						_err=""
+						'match=func
+						matches.AddLast(func)
+						isexact=True
+						Exit
+					EndIf
+				Else
+					If Not isexact
+						'If match 
+						'	_err="Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
+						'Else
+							'match=func
+							matches.AddLast(func)
+						'EndIf
+					EndIf
 				EndIf
-			
-				possible=False
-				Exit
+				'Exit
 			Next
 			
-			If Not possible Exit
+			If Not matches.IsEmpty() Then
+				Exit
+			End If
 			
-			If exact
-				If isexact
-					Err "Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
-				Else
-					_err=""
-					match=func
-					isexact=True
-				EndIf
-			Else
-				If Not isexact
-					If match 
-						_err="Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
-					Else
-						match=func
-					EndIf
-				EndIf
-			EndIf
-			Exit
-		Wend
+		Next
+		
+		If matches.Count() = 1 Then
+			match = TFuncDecl(matches.First())
+		Else
+			' find best match
+			match = FindBestMatchForArgs(argExprs, matches)
+		End If
 		
 		If Not isexact
 			If _err Err _err
@@ -974,9 +1295,9 @@ End Rem
 
 		' last try... maybe we are trying to use it as a function pointer? (no args)
 		If Not match Then
-			If func And Not argExprs Then
-				match = func
-				match.maybeFunctionPtr = True
+			If argExprs Then
+				'match = func
+'				match.maybeFunctionPtr = True
 			End If
 		Else If Not argExprs Then
 			' if there are no args, the actual function may have none either... so we may still be trying to use it as a function pointer
@@ -989,10 +1310,18 @@ End Rem
 				If t t:+","
 				If argExprs[i] t:+argExprs[i].exprType.ToString()
 			Next
-			If throwOnNotMatched Then
-				Throw "Unable to find overload for "+ident+"("+t+"). " + errorDetails
+			If foundIdentMatch Then
+				If throwOnNotMatched Then
+					Throw "Unable to find overload for "+ident+"("+t+"). " + errorDetails
+				Else
+					Err "Unable to find overload for "+ident+"("+t+"). " + errorDetails
+				End If
 			Else
-				Err "Unable to find overload for "+ident+"("+t+"). " + errorDetails
+				If throwOnNotMatched Then
+					Throw "Identifier '" + ident + "' not found."
+				Else
+					Err "Identifier '" + ident + "' not found."
+				End If
 			End If
 		EndIf
 		
@@ -1000,7 +1329,7 @@ End Rem
 
 		Return match
 	End Method
-	
+
 	Method FindLoop:TStmt(ident:String = Null)
 
 		If TBlockDecl(Self) And TBlockDecl(Self).extra Then
@@ -1098,6 +1427,11 @@ Type TFuncDecl Extends TBlockDecl
 	
 	Field returnTypeSubclassed:Int
 	
+	Field mangled:String
+	Field noMangle:Int
+	
+	Field equalsBuiltIn:Int = -1
+	
 	Method CreateF:TFuncDecl( ident$,ty:TType,argDecls:TArgDecl[],attrs:Int )
 		Self.ident=ident
 		Self.retTypeExpr=ty
@@ -1129,6 +1463,8 @@ Type TFuncDecl Extends TBlockDecl
 		t.noCastGen = noCastGen
 		t.munged = munged
 		t.metadata = metadata
+		t.mangled = mangled
+		t.noMangle = noMangle
 		Return  t
 	End Method
 
@@ -1220,7 +1556,11 @@ Type TFuncDecl Extends TBlockDecl
 	End Method
 
 	Method EqualsFunc:Int( decl:TFuncDecl )
-		Return (retType.EqualsType( decl.retType ) Or retType.ExtendsType( decl.retType ) Or decl.retType.EqualsType( retType )) And EqualsArgs( decl )
+		If IsCtor() Then
+			Return EqualsArgs( decl )
+		Else
+			Return (retType.EqualsType( decl.retType ) Or retType.ExtendsType( decl.retType ) Or decl.retType.EqualsType( retType )) And EqualsArgs( decl )
+		End If
 	End Method
 
 	Method OnSemant()
@@ -1271,6 +1611,15 @@ Type TFuncDecl Extends TBlockDecl
 				If decl<>Self And EqualsArgs( decl )
 					Err "Duplicate declaration "+ToString()
 				EndIf
+				If noMangle Then
+					If decl<>Self Then
+						If decl.argDecls.Length = 0 Then
+							Err "You cannot apply NoMangle to the function, as another function with no arguments exists."
+						Else If decl.NoMangle Then
+							Err "Another function is already declared with NoMangle."
+						End If
+					End If
+				End If
 			Next
 		End If
 		
@@ -1341,8 +1690,12 @@ Type TFuncDecl Extends TBlockDecl
 								If voidReturnTypeFail Then
 									errorDetails :+ "You may have Strict type overriding SuperStrict type. "
 								End If
+							Else
+								found = False
+								Continue
 							End If
-
+' TODO REMOVE
+' the following doesn't apply when supporting overloading, as we can have methods of the same name with different args length/types
 							If argDecls.Length <> decl.argDecls.Length
 								errorDetails :+ "Argument count differs. Got " + argDecls.Length +", expected " + decl.argDecls.Length + " arguments."
 							End If
@@ -1390,6 +1743,15 @@ Type TFuncDecl Extends TBlockDecl
 	
 End Type
 
+Type TNewDecl Extends TFuncDecl
+
+	Field chainedCtor:TNewExpr
+	
+	
+
+End Type
+
+
 'Const CLASS_INTERFACE:Int=1
 'Const CLASS_TEMPLATEARG:Int=2
 'Const CLASS_TEMPLATEINST:Int=4
@@ -1611,8 +1973,44 @@ End Rem
 	Method GetDecl2:Object( ident$ )
 		Return Super.GetDecl( ident )
 	End Method
+
+	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+	
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+	
+		Local cdecl:TClassDecl=Self
+		While cdecl
+			Local decl:Object=cdecl.GetDeclList2( ident, declList, maxSearchDepth )
+			'If decl And (Not TFuncDeclList(decl) And declList.IsEmpty()) Return decl
+			If decl Then
+				declList.AddLast(decl)
+			End If
+
+			cdecl=cdecl.superClass
+			
+			If maxSearchDepth < SCOPE_CLASS_HEIRARCHY Then
+				Exit
+			End If
+		Wend
+
+		Return declList
+	End Method
+	
+	'needs this 'coz you can't go blah.Super.GetDecl()...
+	Method GetDeclList2:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+		Return Super.GetDeclList( ident, declList, maxSearchDepth )
+	End Method
+	
+	Method FindFuncDecl:TFuncDecl( ident$,args:TExpr[] = Null ,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False, maxSearchDepth:Int )
+	
+		' try the super first...
+		Local funcDecl:TFuncDecl = Super.FindFuncDecl(ident, args, explicit, isArg, isIdentExpr, throwOnNotMatched, maxSearchDepth)
+		If funcDecl Then
+			Return funcDecl
+		End If
 	
-	Method FindFuncDecl:TFuncDecl( ident$,args:TExpr[] = Null ,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False )
 	
 		If args = Null Then
 			args = New TExpr[0]
@@ -1659,7 +2057,7 @@ End Rem
 	End Method
 	
 	Method FindFuncDecl2:TFuncDecl( ident$,args:TExpr[],explicit:Int, isIdentExpr:Int = False )
-		Return Super.FindFuncDecl( ident,args,explicit,,isIdentExpr )
+		Return Super.FindFuncDecl( ident,args,explicit,,isIdentExpr,0,0 )
 	End Method
 	
 	Method GetAllFuncDecls:TFuncDecl[](funcs:TFuncDecl[] = Null, includeSuper:Int = True)
@@ -1673,23 +2071,8 @@ End Rem
 
 		' interface methods
 		For Local iface:TClassDecl=EachIn implmentsAll
-			For Local func:TFuncDecl=EachIn iface._decls
-				Local matched:Int = False
-
-				For Local i:Int = 0 Until funcs.length
-					' found a match - we are overriding it
-					If func.IdentLower() = funcs[i].IdentLower() Then
-						matched = True
-						Exit
-					End If
-				Next
-				
-				If Not matched Then
-					funcs :+ [func]
-				End If
-			Next
+			funcs = iface.GetAllFuncDecls(funcs)
 		Next
-
 		
 		For Local func:TFuncDecl = EachIn _decls
 		
@@ -1697,7 +2080,7 @@ End Rem
 			
 			For Local i:Int = 0 Until funcs.length
 				' found a match - we are overriding it
-				If func.IdentLower() = funcs[i].IdentLower() Then
+				If func.IdentLower() = funcs[i].IdentLower() And func.EqualsArgs(funcs[i]) Then
 					matched = True
 					' set this to our own func
 					funcs[i] = func
@@ -1752,7 +2135,7 @@ End Rem
 			' dont count any that are already in the funcs list
 			For Local i:Int = 0 Until funcs.length
 				' found a match - we are overriding it
-				If func.IdentLower() = funcs[i].IdentLower() Then
+				If func.IdentLower() = funcs[i].IdentLower() And func.EqualsArgs(funcs[i]) Then
 					matched = True
 					' set this to our own func
 					'funcs[i] = func
@@ -2315,7 +2698,7 @@ Type TModuleDecl Extends TScopeDecl
 	End Method
 	
 	Method GetDecl:Object( ident$ )
-'DebugLog "GetDecl (" + ident + ") : " + filepath
+
 		Local todo:TList=New TList'<TModuleDecl>
 		Local done:TMap=New TMap'<TModuleDecl>
 		
@@ -2363,8 +2746,62 @@ Type TModuleDecl Extends TScopeDecl
 		Return Super.GetDecl( ident )
 	End Method
 
+
+	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+	
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+
+		Local todo:TList=New TList'<TModuleDecl>
+		Local done:TMap=New TMap'<TModuleDecl>
+		
+		todo.AddLast Self
+		done.Insert filepath,Self
+		
+		Local decl:Object,declmod$
+		
+		While Not todo.IsEmpty()
+	
+			Local mdecl:TModuleDecl=TModuleDecl(todo.RemoveLast())
+			Local tdecl_:Object=mdecl.GetDeclList2( ident, declList, maxSearchDepth )
+			
+			If tdecl_ And tdecl_<>decl
+				If mdecl=Self Return tdecl_
+				If decl
+					Err "Duplicate identifier '"+ident+"' found in module '"+declmod+"' and module '"+mdecl.ident+"'."
+				EndIf
+				decl=tdecl_
+				declmod=mdecl.ident
+			EndIf
+			
+			'If Not _env Exit
+			
+			Local imps:TUnorderedMap=mdecl.imported
+			'If mdecl<>_env.ModuleScope() imps=mdecl.pubImported
+
+			For Local mdecl2:TModuleDecl=EachIn imps.Values()
+				If Not done.Contains( mdecl2.filepath )
+					todo.AddLast mdecl2
+					done.Insert mdecl2.filepath,mdecl2
+				EndIf
+				
+				If ident = mdecl2.ident
+					Return mdecl2
+				End If
+			Next
+
+		Wend
+		
+		Return decl
+	End Method
+	
+	Method GetDeclList2:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+		Return Super.GetDeclList( ident, declList, maxSearchDepth )
+	End Method
+
 	Method OnSemant()
-		Local decl:TFuncDecl = FindFuncDecl( "__localmain" )
+		Local decl:TFuncDecl = FindFuncDecl( "__localmain", ,,,,,SCOPE_MODULE )
 		If decl Then
 			decl.Semant
 		End If
@@ -2460,7 +2897,7 @@ Type TAppDecl Extends TScopeDecl
 
 		mainModule.Semant
 
-		mainFunc=mainModule.FindFuncDecl( "__localmain" )
+		mainFunc=mainModule.FindFuncDecl( "__localmain",,,,,,SCOPE_MODULE )
 		
 		
 		' FIXME

+ 252 - 56
expr.bmx

@@ -348,6 +348,7 @@ Type TConstExpr Extends TExpr
 	Field ty:TType
 	Field value$
 	Field originalValue$
+	Field typeSpecific:Int
 
 	Method Create:TConstExpr( ty:TType,value$ )
 
@@ -414,11 +415,15 @@ Type TConstExpr Extends TExpr
 	End Method
 	
 	Method UpdateType(ty:TType)
+		typeSpecific = True
 		Create(ty, originalValue)
 	End Method
 
 	Method Copy:TExpr()
-		Return New TConstExpr.Create( ty,value )
+		Local e:TConstExpr = New TConstExpr.Create( ty,value )
+		e.originalValue = originalValue
+		e.typeSpecific = typeSpecific
+		Return e
 	End Method
 
 	Method ToString$()
@@ -686,7 +691,7 @@ Type TNewObjectExpr Extends TExpr
 		If exprType Return Self
 
 		Local it:TIdentType = TIdentType(ty)
-		Local iArgs:TExpr[] = CopyArgs(args)
+		Local iArgs:TExpr[] = SemantArgs(CopyArgs(args))
 
 		ty=ty.Semant(True)
 		If Not ty Then
@@ -720,14 +725,25 @@ Type TNewObjectExpr Extends TExpr
 		'If classDecl.IsTemplateArg() Err "Cannot create instance of a generic argument."
 		If classDecl.args And Not classDecl.instanceof Err "Cannot create instance of a generic class."
 
+		Local parts:String[]
+		If it Then
+			parts = it.ident.ToLower().Split(".")
+		End If
+
 		If classDecl.IsExtern()
 			Err "Cannot create instance of an extern type"
 			'If args Err "No suitable constructor found for class "+classDecl.ToString()+"."
-'		Else
-'DebugStop
-'			ctor=classDecl.FindFuncDecl( "new",args )
-'			If Not ctor	Err "No suitable constructor found for class "+classDecl.ToString()+"."
-'			args=CastArgs( args,ctor )
+		Else
+			' if the New Type doesn't have extra idents (like a create method), then don't use the args in the search.
+			' otherwise, the args are for the constructor.
+			If Not parts Or parts.length = 1 Then
+				ctor=classDecl.FindFuncDecl( "new",args,,,,,SCOPE_CLASS_HEIRARCHY )
+				If Not ctor	Err "No suitable constructor found for class "+classDecl.ToString()+"."
+				args=CastArgs( args,ctor )
+			Else
+				ctor=classDecl.FindFuncDecl( "new",,,,,,SCOPE_CLASS_HEIRARCHY )
+				If Not ctor	Err "No suitable constructor found for class "+classDecl.ToString()+"."
+			End If
 		EndIf
 
 		classDecl.attrs:|CLASS_INSTANCED
@@ -735,8 +751,8 @@ Type TNewObjectExpr Extends TExpr
 		exprType=ty
 		
 		If it Then
-			Local parts:String[] = it.ident.ToLower().Split(".")
-			
+			'Local parts:String[] = it.ident.ToLower().Split(".")
+
 			Local i:Int = 0
 			
 			While i < parts.length And parts[i] <> classDecl.IdentLower() And parts[i] <> "self"
@@ -749,12 +765,26 @@ Type TNewObjectExpr Extends TExpr
 			Local cdecl:TClassDecl = classDecl
 			Local eType:TType = objTy
 			
+			Local errorDetails:String
+			
 			While i < parts.length
 				Local id:String = parts[i]
 				i :+ 1
 				
 				' find member function.method
-				Local fdecl:TFuncDecl = cdecl.FindFuncDecl(id, iArgs)
+				Local fdecl:TFuncDecl
+				Try
+					fdecl = cdecl.FindFuncDecl(id, iArgs,,,,True,SCOPE_CLASS_HEIRARCHY)
+				Catch errorMessage:String
+					If errorMessage.StartsWith("Compile Error") Then
+						Throw errorMessage
+					Else
+						' couldn't find an exact match, look elsewhere
+						If errorMessage.StartsWith("Unable") Then
+							errorDetails = errorMessage
+						End If
+					End If
+				End Try
 				If fdecl Then
 					expr = New TInvokeMemberExpr.Create( expr,fdecl, iArgs ).Semant()
 					eType = expr.exprType
@@ -766,25 +796,32 @@ Type TNewObjectExpr Extends TExpr
 					End If
 					Continue
 				End If
+				
 				' find other member decl (field, etc)
-				Local decl:TVarDecl = TVarDecl(cdecl.GetDecl(id))
-				If decl Then
-					Local tmp:TLocalDecl=New TLocalDecl.Create( "", eType, expr,, True )
-					Local varExpr:TExpr = New TMemberVarExpr.Create(New TVarExpr.Create( tmp ), decl).Semant()
-					expr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), varExpr ).Semant()
-					eType = decl.ty
-					If TObjectType(eType) Then
-						cdecl = TObjectType(expr.exprType).classdecl
-					End If
-					If TArrayType(eType) Or TStringType(eType) Then
-						cdecl = eType.GetClass()
+				If Not errorDetails Then
+					Local decl:TVarDecl = TVarDecl(cdecl.GetDecl(id))
+					If decl Then
+						Local tmp:TLocalDecl=New TLocalDecl.Create( "", eType, expr,, True )
+						Local varExpr:TExpr = New TMemberVarExpr.Create(New TVarExpr.Create( tmp ), decl).Semant()
+						expr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), varExpr ).Semant()
+						eType = decl.ty
+						If TObjectType(eType) Then
+							cdecl = TObjectType(expr.exprType).classdecl
+						End If
+						If TArrayType(eType) Or TStringType(eType) Then
+							cdecl = eType.GetClass()
+						End If
+						Continue
 					End If
-					Continue
-				End If
-				
+				End If	
+
 				' didn't match member or function??
 				' probably an error...
-				Err "Identifier '" + id + "' not found."
+				If errorDetails Then
+					Err errorDetails
+				Else
+					Err "Identifier '" + id + "' not found."
+				End If
 			Wend
 			
 			Return expr
@@ -880,8 +917,19 @@ Type TInvokeSuperExpr Extends TExpr
 		If Not superClass Err "Type has no super class."
 		
 		args=SemantArgs( args )
-		origFuncDecl=classScope.FindFuncDecl(IdentLower(),args)
-		funcDecl=superClass.FindFuncDecl( IdentLower(),args )
+		Try
+			' get the local version of the method from local class scope
+			origFuncDecl=classScope.FindFuncDecl(IdentLower(),args,,,,True,SCOPE_CLASS_LOCAL)
+		Catch errorMessage:String
+			If errorMessage.StartsWith("Compile Error") Then
+				Throw errorMessage
+			Else
+				' if there isn't one, we'll just use a Super version of it anyway as a reference.
+				origFuncDecl=classScope.FindFuncDecl(IdentLower(),args,,,,,SCOPE_CLASS_HEIRARCHY)
+			End If
+		End Try
+
+		funcDecl=superClass.FindFuncDecl( IdentLower(),args,,,,,SCOPE_CLASS_HEIRARCHY )
 
 		If Not funcDecl Err "Can't find superclass method '"+ident+"'."
 
@@ -1015,7 +1063,7 @@ Type TCastExpr Extends TExpr
 				Else
 					InternalErr
 				EndIf
-				Local fdecl:TFuncDecl=src.GetClass().FindFuncDecl( op )
+				Local fdecl:TFuncDecl=src.GetClass().FindFuncDecl( op,,,,,,SCOPE_ALL )
 				expr=New TInvokeMemberExpr.Create( expr,fdecl ).Semant()
 
 			EndIf
@@ -2079,19 +2127,12 @@ Type TIdentExpr Extends TExpr
 		Return scope
 	End Method
 
-	Method IdentErr( )
-		If scope
-			Local close$
-			For Local decl:TDecl=EachIn scope.Decls()
-				If IdentLower()=decl.IdentLower()
-					close=decl.ident
-				EndIf
-			Next
-			If close And ident<>close Then
-				Err "Identifier '"+ident+"' not found - perhaps you meant '"+close+"'?"
-			EndIf
-		EndIf
-		Err "Identifier '"+ident+"' not found."
+	Method IdentErr( errorDetails:String = Null )
+		If errorDetails Then
+			Err errorDetails
+		Else
+			Err "Identifier '"+ident+"' not found."
+		End If
 	End Method
 
 	Method IdentNotFound()
@@ -2153,7 +2194,7 @@ Type TIdentExpr Extends TExpr
 
 		If op And op<>"="
 
-			Local fdecl:TFuncDecl=scope.FindFuncDecl( IdentLower() )
+			Local fdecl:TFuncDecl=scope.FindFuncDecl( IdentLower(),,,,,,SCOPE_ALL )
 			If Not fdecl IdentErr
 
 			If _env.ModuleScope().IsStrict() And Not fdecl.IsProperty() Err "Identifier '"+ident+"' cannot be used in this way."
@@ -2183,7 +2224,15 @@ Type TIdentExpr Extends TExpr
 		Local args:TExpr[]
 		If rhs args=[rhs]
 
-		Local fdecl:TFuncDecl=scope.FindFuncDecl( IdentLower(),args, , isArg, True )
+		Local fdecl:TFuncDecl
+		
+		Try
+			fdecl=scope.FindFuncDecl( IdentLower(),args, , isArg, True,True,SCOPE_ALL )
+		Catch errorMessage:String
+			If errorMessage.StartsWith("Compile Error") Then
+				Throw errorMessage
+			End If
+		End Try
 
 		If fdecl
 			If _env.ModuleScope().IsStrict() And Not fdecl.IsProperty() And Not isArg And Not fdecl.maybeFunctionPtr Err "Identifier '"+ident+"' cannot be used in this way."
@@ -2230,15 +2279,37 @@ Type TIdentExpr Extends TExpr
 
 		_Semant
 
+		Local errorDetails:String
+		Local nearestScopeError:String
+
 		'Local scope:TScopeDecl=IdentScope()
+		Local initialScope:Int = SCOPE_ALL
+		If scope And TClassDecl(scope) Then
+			initialScope = SCOPE_CLASS_HEIRARCHY
+		End If
+		
 		Local fdecl:TFuncDecl
 		Try
-			fdecl=scope.FindFuncDecl( IdentLower(),args,,,,True )
+			fdecl=scope.FindFuncDecl( IdentLower(),args,,,,True,initialScope )
+'			Local decl:Object=scope.FindFuncDecl( IdentLower(),args,,,,True,SCOPE_ALL )
+'			If decl Then
+'				If TFuncDecl(decl) Then
+'					fdecl = TFuncDecl(decl)
+'				Else If TFuncDeclList(decl) Then
+'					If Not TFuncDeclList(decl).IsEmpty() Then
+'						fdecl = TFuncDecl(TFuncDeclList(decl).First())
+'					End If
+'				End If
+'			End If
 		Catch errorMessage:String
 			If errorMessage.StartsWith("Compile Error") Then
 				Throw errorMessage
 			Else
 				' couldn't find an exact match, look elsewhere
+				errorDetails = errorMessage
+				If errorMessage.StartsWith("Unable") Then
+					nearestScopeError = errorDetails
+				End If
 			End If
 		End Try
 
@@ -2251,17 +2322,63 @@ Type TIdentExpr Extends TExpr
 			
 			' if fdecl was a method, this would be the Type's scope (ie. file/module)
 			If scope2.scope Then
-				fdecl = scope2.scope.FindFuncDecl( IdentLower(),args )
+				fdecl = scope2.scope.FindFuncDecl( IdentLower(),args,,,,,SCOPE_CLASS_HEIRARCHY )
+			End If
+		Else If static And Not fdecl And Not fixedScope Then
+			If _env.classScope() Then
+				' try searching from our class scope
+				'fdecl = _env.classScope().FindFuncDecl( IdentLower(),args )
+
+				If Not fdecl Then				
+					' try searching from our class parent scope
+					Try
+						fdecl = _env.classScope().scope.FindFuncDecl( IdentLower(),args,,,,True,SCOPE_ALL )
+					Catch errorMessage:String
+						If errorMessage.StartsWith("Compile Error") Then
+							Throw errorMessage
+						Else
+							' couldn't find an exact match, look elsewhere
+							errorDetails = errorMessage
+							If Not nearestScopeError And errorDetails.StartsWith("Unable") Then
+								nearestScopeError = errorDetails
+							End If
+						End If
+					End Try
+				End If
+			Else If _env.ModuleScope() Then ' bah
+				' finally, try searching from our module scope
+				Try
+					fdecl = _env.ModuleScope().FindFuncDecl( IdentLower(),args,,,,True,SCOPE_ALL )
+				Catch errorMessage:String
+					If errorMessage.StartsWith("Compile Error") Then
+						Throw errorMessage
+					Else
+						' couldn't find an exact match, look elsewhere
+						errorDetails = errorMessage
+						If Not nearestScopeError And errorDetails.StartsWith("Unable") Then
+							nearestScopeError = errorDetails
+						End If
+					End If
+				End Try
 			End If
-		Else If static And Not fdecl And _env.classScope() Then
-			' try searching from our class parent scope
-			fdecl = _env.classScope().scope.FindFuncDecl( IdentLower(),args )
 		End If
 
 		' couldn't find it? try a global search
-		If Not fdecl Then
+		If Not fdecl And Not fixedScope Then
 			For Local mdecl:TModuleDecl = EachIn _appInstance.globalImports.Values()
-				fdecl=mdecl.FindFuncDecl( IdentLower(), args )
+				Try
+					fdecl=mdecl.FindFuncDecl( IdentLower(), args,,,,True,SCOPE_ALL )
+				Catch errorMessage:String
+					If errorMessage.StartsWith("Compile Error") Then
+						Throw errorMessage
+					Else
+						' couldn't find an exact match, look elsewhere
+						errorDetails = errorMessage
+						If Not nearestScopeError And errorDetails.StartsWith("Unable") Then
+							nearestScopeError = errorDetails
+						End If
+					End If
+				End Try
 				If fdecl Exit
 			Next
 		End If
@@ -2290,7 +2407,13 @@ Type TIdentExpr Extends TExpr
 			Err "Illegal number of arguments for type conversion"
 		End If
 
-		If throwError IdentErr
+		If throwError Then
+			If nearestScopeError Then
+				IdentErr(nearestScopeError)
+			Else
+				IdentErr(errorDetails)
+			End If
+		End If
 	End Method
 
 	Method SemantScope:TScopeDecl()
@@ -2378,16 +2501,19 @@ Type TAbsExpr Extends TBuiltinExpr
 	End Method
 
 	Method Semant:TExpr()
+
 		If exprType Return Self
 
 		expr=expr.Semant()
 
-		If TIntType(expr.exprType) Or TByteType(expr.exprType) Or TShortType(expr.exprType) Then
-			exprType=New TIntType
-		Else If TLongType(expr.exprType) Then
-			exprType=New TLongType
+		If TNumericType(expr.exprType) Or TBoolType(expr.exprType) Then
+			If TIntType(expr.exprType) Or TByteType(expr.exprType) Or TShortType(expr.exprType) Then
+				exprType=New TIntType
+			Else
+				exprType=expr.exprType
+			End If
 		Else
-			exprType=New TDoubleType
+			Err "Subexpression for 'Abs' must be of numeric type"
 		End If
 
 		Return Self
@@ -2464,6 +2590,11 @@ Type TSgnExpr Extends TBuiltinExpr
 		End If
 		
 		expr = expr.Semant()
+		
+		If Not TNumericType(expr.exprType) Then
+			Err "Subexpression for 'Sgn' must be of numeric type"
+		End If
+		
 		exprType=expr.exprType
 		Return Self
 	End Method
@@ -2667,6 +2798,71 @@ Type TScopeExpr Extends TExpr
 	End Method
 End Type
 
+Type TNewExpr Extends TExpr
+	Field isSuper:Int
+	Field args:TExpr[]
+	Field ctor:TFuncDecl
+
+	Method Create:TNewExpr( args:TExpr[]=Null, isSuper:Int = False )
+		If args Then
+			Self.args=args
+		Else
+			Self.args = New TExpr[0]
+		End If
+		Self.isSuper = isSuper
+		Return Self
+	End Method
+
+	Method Semant:TExpr()
+
+		Local fdecl:TFuncDecl = _env.FuncScope()
+		If Not fdecl Or TNewDecl(fdecl) = Null Or Not _env.ClassScope() Then
+			Err "Call to constructor not valid in this context."
+		End If
+	
+		' must be first statement of New() method
+		Local stmt:TStmt = TStmt(fdecl.stmts.First())
+		
+		If TExprStmt(stmt) = Null Or TExprStmt(stmt).expr <> Self Then
+			Err "Call to constructor must be first statement in New()."
+		End If
+	
+		args=SemantArgs( args )
+		
+		' validate called constructor
+		Try
+			Local cDecl:TClassDecl = _env.ClassScope()
+			If isSuper Then
+				cDecl = cDecl.superClass
+			End If
+			ctor = cDecl.FindFuncDecl("new",args,,,,True,SCOPE_CLASS_HEIRARCHY )
+		Catch errorMessage:String
+			If errorMessage.StartsWith("Compile Error") Then
+				Throw errorMessage
+			Else
+				Err errorMessage
+			End If
+		End Try
+		
+		' TODO : expand to full recursive test
+		If ctor = fdecl Then
+			Err "Recursive constructor invocation."
+		End If
+		
+		ctor.Semant
+		
+		' attach to ctor
+		TNewDecl(fdecl).chainedCtor = Self
+		
+		Return Self
+	End Method
+
+	Method Trans$()
+		'Return _trans.TransFuncCallExpr( Self )
+	End Method
+
+End Type
+
 Type TNullExpr Extends TExpr
 
 	Method Create:TNullExpr(ty:TType)

+ 6 - 1
iparser.bmx

@@ -855,7 +855,12 @@ Type TIParser
 			EndIf
 		Forever
 		
-		Local funcDecl:TFuncDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
+		Local funcDecl:TFuncDecl
+		If attrs & FUNC_CTOR Then
+			funcDecl = New TNewDecl.CreateF( id,ty,args,attrs )
+		Else
+			funcDecl = New TFuncDecl.CreateF( id,ty,args,attrs )
+		End If
 		
 		funcDecl.retType = ty
 		

+ 8 - 0
options.bmx

@@ -97,6 +97,10 @@ Global opt_gdbdebug:Int = False
 '    upgrade strict subclass method/function return types to match superstrict superclass.
 '    default is to auto-upgrade. Set flag if you want to throw an error - because of mismatch. (strict is Int, superstrict is Void).
 Global opt_strictupgrade:Int = True
+' overload warnings
+'    generate warnings (and accept) instead of errors for calling methods with arguments that need to be cast down.
+'    May cause issues using overloaded methods.
+Global opt_warnover:Int = False
 
 Global opt_filepath:String
 
@@ -188,6 +192,8 @@ Function ParseArgs:String[](args:String[])
 				opt_framework = args[count]
 			Case "d"
 				opt_gdbdebug=True
+			Case "w"
+				opt_warnover=True
 		End Select
 	
 		count:+ 1
@@ -214,6 +220,8 @@ Function DefaultOptions()
 	opt_arch = "x64"
 ?arm
 	opt_arch = "arm"
+?arm64
+	opt_arch = "arm64"
 ?armeabi
 	opt_arch = "armeabi"
 ?armeabiv7a

+ 109 - 81
parser.bmx

@@ -901,77 +901,82 @@ Type TParser
 		Case "."
 			expr=New TScopeExpr.Create( _module )
 		Case "new"
-'DebugStop
 			NextToke
-			Local ty:TType=ParseType()
-
-			While CParse("ptr")
-				ty = TType.MapToPointerType(ty)
-			Wend
-
-			If _toke = "[" Or _toke = "[]" Then
-				Local depth:Int = 0
-				Local ln:TExpr[]
-				Local tmpTy:TType = ty.Copy()
-
-				Repeat
-					Local dims:Int = 1
-					
-					If CParse("[]") Then
-						tmpTy=New TArrayType.Create( tmpTy )
-						depth :+ 1
-						Continue
-					End If
-
-					' looking for an array with expression					
-					If Not ln Then
-						Parse "["
-					Else
-						If Not CParse("[") Then
-							Exit
+			
+			If _toke = "(" Then
+				' call constructor
+				expr=New TNewExpr.Create( ParseArgs(stmt) )
+			Else
+				Local ty:TType=ParseType()
+	
+				While CParse("ptr")
+					ty = TType.MapToPointerType(ty)
+				Wend
+	
+				If _toke = "[" Or _toke = "[]" Then
+					Local depth:Int = 0
+					Local ln:TExpr[]
+					Local tmpTy:TType = ty.Copy()
+	
+					Repeat
+						Local dims:Int = 1
+						
+						If CParse("[]") Then
+							tmpTy=New TArrayType.Create( tmpTy )
+							depth :+ 1
+							Continue
+						End If
+	
+						' looking for an array with expression					
+						If Not ln Then
+							Parse "["
 						Else
-							Err "Unexpected '[' after array size declaration"
+							If Not CParse("[") Then
+								Exit
+							Else
+								Err "Unexpected '[' after array size declaration"
+							End If
 						End If
-					End If
-
-					Repeat
-						If CParse(",") Then
+	
+						Repeat
+							If CParse(",") Then
+								dims :+ 1
+								Continue
+							End If
+							If CParse("]") Exit
+							ln = ln + [ParseExpr()]
+							If CParse("]") Exit
+							Parse(",")
 							dims :+ 1
-							Continue
+						Forever
+	
+						If Not ln Then
+							tmpTy=New TArrayType.Create( tmpTy, dims )
 						End If
-						If CParse("]") Exit
-						ln = ln + [ParseExpr()]
-						If CParse("]") Exit
-						Parse(",")
-						dims :+ 1
 					Forever
-
-					If Not ln Then
-						tmpTy=New TArrayType.Create( tmpTy, dims )
+	
+					If ln Then
+						ty = tmpTy
 					End If
-				Forever
-
-				If ln Then
-					ty = tmpTy
-				End If
-
-'				Repeat
-					'If CParse( "[" )
-'					Repeat
-'						ln = ln + [ParseExpr()]
-'						If CParse("]") Exit
-'						Parse ","
-'					Forever
-					'Parse "]"
-'					ty = ParseArrayType(ty)
-'				Forever
-				'While CParse( "[]" )
-				'	ty=New TArrayType.Create( ty)
-				'Wend
-				expr=New TNewArrayExpr.Create( ty,ln )
-			Else
-				expr=New TNewObjectExpr.Create( ty,ParseArgs( stmt ) )
-			EndIf
+	
+	'				Repeat
+						'If CParse( "[" )
+	'					Repeat
+	'						ln = ln + [ParseExpr()]
+	'						If CParse("]") Exit
+	'						Parse ","
+	'					Forever
+						'Parse "]"
+	'					ty = ParseArrayType(ty)
+	'				Forever
+					'While CParse( "[]" )
+					'	ty=New TArrayType.Create( ty)
+					'Wend
+					expr=New TNewArrayExpr.Create( ty,ln )
+				Else
+					expr=New TNewObjectExpr.Create( ty,ParseArgs( stmt ) )
+				EndIf
+			End If
 		Case "null"
 			NextToke
 			expr = New TNullExpr.Create(TType.nullObjectType)
@@ -2197,7 +2202,7 @@ End Rem
 
 					expr=New TFuncCallExpr.Create( expr,ParseArgs( True ) )
 
-				Else If TFuncCallExpr( expr) Or TInvokeSuperExpr( expr ) Or TNewObjectExpr( expr )
+				Else If TFuncCallExpr( expr) Or TInvokeSuperExpr( expr ) Or TNewObjectExpr( expr ) Or TNewExpr(expr)
 
 				Else
 					Err "Expression cannot be used as a statement."
@@ -2443,14 +2448,15 @@ End Rem
 
 	'should return a specific "metadata object" ?
 	' metadata is in the form : {key key=value key="value"}
-	Method ParseMetaData:String()
-		Local metaDataString:String = ""
+	Method ParseMetaData:TMetadata()
+		Local meta:TMetadata = New TMetadata
+
 		SkipEols
 
 		Repeat
 			
-			If metaDataString Then
-				metaDataString :+ " "
+			If meta.metadataString Then
+				meta.metadataString :+ " "
 			End If
 			
 			Select _tokeType
@@ -2465,11 +2471,13 @@ End Rem
 			End Select
 			
 			'append current token to metaDataString
-			metaDataString :+ _toke
+			Local key:String = _toke
+			meta.metadataString :+ key
 
 			'read next token
 			NextToke()
 
+			Local value:String
 			' got a value
 			If CParse("=") Then
 				
@@ -2477,14 +2485,18 @@ End Rem
 					Err "Meta data must be literal constant"
 				End If
 				
-				metaDataString :+ "=" + _toke
+				value = _toke
+				meta.metadataString :+ "=" + value
 
 				'read next token
 				NextToke()
 			Else
-				metaDataString :+ "=1"	
+				value = "1"
+				meta.metadataString :+ "=1"	
 			End If
 			
+			meta.InsertMeta(key.ToLower(), value)
+			
 			'reached end of meta data declaration
 			If _toke="}" Then Exit
 		Forever
@@ -2493,7 +2505,7 @@ End Rem
 		NextToke()
 
 		'parse this into something
-		Return metaDataString
+		Return meta
 	End Method
 
 
@@ -2505,7 +2517,8 @@ End Rem
 		Local id$
 		Local ty:TType
 		Local meth:Int = attrs & FUNC_METHOD
-		Local meta:String
+		Local meta:TMetadata
+		Local noMangle:Int
 
 		If attrs & FUNC_METHOD
 			If _toke="new"
@@ -2513,7 +2526,7 @@ End Rem
 				If attrs & DECL_EXTERN
 					Err "Extern classes cannot have constructors"
 				EndIf
-				id=_toke
+				id="New"
 				NextToke
 				attrs:|FUNC_CTOR
 				attrs:&~FUNC_METHOD
@@ -2610,6 +2623,14 @@ End Rem
 				'meta data for functions/methods
 				'print "meta for func/meth: "+id+ " -> "+ParseMetaData()
 				meta = ParseMetaData()
+				
+				If meta.HasMeta("nomangle") Then
+					If attrs & FUNC_METHOD Then
+						Err "Only functions can specify NoMangle"
+					Else
+						noMangle = True
+					End If
+				End If
 			Else If _tokeType=TOKE_STRINGLIT
 				' "win32", etc
 				' TODO ? something with this??
@@ -2622,7 +2643,13 @@ End Rem
 			EndIf
 		Forever
 
-		Local funcDecl:TFuncDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
+		Local funcDecl:TFuncDecl
+		If attrs & FUNC_CTOR Then
+			funcDecl=New TNewDecl.CreateF( id,ty,args,attrs )
+		Else
+			funcDecl=New TFuncDecl.CreateF( id,ty,args,attrs )
+			funcDecl.noMangle = noMangle
+		End If
 		If meta Then
 			funcDecl.metadata = meta
 		End If
@@ -2671,10 +2698,11 @@ End Rem
 			If CParse( "super" )
 				Parse "."
 				If _toke="new"
-					Local id$=_toke
+					Local id$="New"
 					NextToke
-					funcDecl.superCtor=New TInvokeSuperExpr.Create( id,ParseArgs( True ) )
-					funcDecl.AddStmt New TExprStmt.Create( funcDecl.superCtor )
+					'funcDecl.superCtor=New TInvokeSuperExpr.Create( id,ParseArgs( True ) )
+					'funcDecl.AddStmt New TExprStmt.Create( funcDecl.superCtor )
+					funcDecl.AddStmt New TExprStmt.Create( New TNewExpr.Create(ParseArgs(True), True))
 				Else
 					Local id$=ParseIdent()
 					funcDecl.AddStmt New TExprStmt.Create( New TInvokeSuperExpr.Create( id,ParseArgs( True ) ) )
@@ -2716,7 +2744,7 @@ End Rem
 		Local args:TClassDecl[]
 		Local superTy:TIdentType
 		Local imps:TIdentType[]
-		Local meta:String
+		Local meta:TMetadata
 
 		'If (attrs & CLASS_INTERFACE) And (attrs & DECL_EXTERN)
 		'	Err "Interfaces cannot be extern."
@@ -3433,7 +3461,7 @@ End Rem
 		End If
 
 		Local mainFunc:TFuncDecl = New TFuncDecl.CreateF("__LocalMain", New TIntType,Null,0)
-'DebugStop
+
 		'_app.InsertDecl mainFunc
 		_module.insertDecl(mainFunc)
 		'Local mainBlock:TBlockDecl = New TBlockDecl.Create( _block )

+ 170 - 27
translator.bmx

@@ -49,8 +49,8 @@ Type TTranslator
 	Field loopTryStack:TStack = New TStack
 
 	Field mungedScopes:TMap=New TMap'<StringSet>
-'	Field funcMungs:=New StringMap<FuncDeclList>
-'	Field mungedFuncs:=New StringMap<FuncDecl>
+	'Field funcMungs:TFuncDeclList=New TFuncDeclList
+	'Field mungedFuncs:TMap=New Map
 	Field localScopeStack:TStack = New TStack
 	Field localScope:TStack = New TStack
 	Field ind:Int
@@ -156,41 +156,182 @@ Type TTranslator
 		Next
 	End Method
 
+	Method TransManglePointer$( ty:TType )
+		Local p:String
+		
+		If ty
+
+			If ty._flags & TType.T_VAR Then
+				p:+ "v"
+			End If
+
+			If ty._flags & TType.T_PTR Then
+				p:+ "p"
+			Else If ty._flags & TType.T_PTRPTR Then
+				p:+ "pp"
+			Else If ty._flags & TType.T_PTRPTRPTR Then
+				p:+ "ppp"
+			End If
+
+		End If
+		
+		Return p
+	End Method
+
+	Method TransMangleType:String(ty:TType)
+		Local p:String = TransManglePointer(ty)
+
+		If TVoidType( ty ) Return "v"
+		If TByteType( ty ) Return p + "b"
+		If TShortType( ty ) Return p + "s"
+		If TIntType( ty ) Return p + "i"
+		If TUIntType( ty ) Return p + "u"
+		If TFloatType( ty ) Return p + "f"
+		If TDoubleType( ty ) Return p + "d"
+		If TLongType( ty ) Return p + "l"
+		If TULongType( ty ) Return p + "y"
+		If TSizeTType( ty ) Return p + "z"
+		If TStringType( ty ) Return p + "S"
+		If TArrayType( ty ) Then
+			Return p + "a" + TransMangleType(TArrayType( ty ).elemType)
+		End If
+		If TObjectType( ty ) Then
+			If Not TObjectType( ty ).classdecl.IsExtern()
+				Return p + "T" + TObjectType( ty ).classDecl.ident
+			Else
+				If TObjectType( ty ).classdecl.IsInterface() Then
+					Return p + "I" + TObjectType(ty).classDecl.ident
+				ElseIf TObjectType( ty ).classdecl.IsStruct() Then
+					Return p + "R" + TObjectType(ty).classDecl.ident
+				Else
+					Return p + "E" + TObjectType(ty).classDecl.ident
+				End If
+			End If
+		End If
+		If TFunctionPtrType( ty ) Then
+			Local func:TFuncDecl = TFunctionPtrType( ty ).func
+			Local s:String = "F" + MangleMethodArgs(func)
+'			For Local i:Int = 0 Until func.argDecls.length
+'				s :+ TransMangleType(func.argDecls[i].ty)
+'			Next
+			Return s + "_" + TransMangleType(func.retType) + "_"
+		End If
+	End Method
+
+	Method MangleMethod:String(fdecl:TFuncDecl)
+		If fdecl.IsMethod() Or fdecl.IsCtor() Then
+			Return MangleMethodArgs(fdecl)
+		Else
+			Return MangleMethodRetType(fdecl) + MangleMethodArgs(fdecl)
+		End If
+	End Method
+	
+	Method MangleMethodRetType:String(fdecl:TFuncDecl)
+		If fdecl.retType Then
+			Return "_" + TransMangleType(fdecl.retType)
+		Else
+			Return "_v"
+		End If
+	End Method
+	
+	Method MangleMethodArgs:String(fdecl:TFuncDecl)
+		Local s:String
+		For Local arg:TArgDecl = EachIn fdecl.argDecls
+			If Not s Then
+				s = "_"
+			End If
+			s :+ TransMangleType(arg.ty)
+		Next
+		Return s
+	End Method
+
+	Method equalsTorFunc:Int(classDecl:TClassDecl, func:TFuncDecl)
+		If func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
+			Return True
+		End If
+		Return False
+	End Method
+
+	Method equalsBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
+		If func.equalsBuiltIn > -1 Then
+			Return func.equalsBuiltIn
+		End If
+	
+		If checked Or func.IdentLower() = "tostring" Or func.IdentLower() = "compare" Or func.IdentLower() = "sendmessage" Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
+			If classDecl.munged = "bbObjectClass" Then
+				For Local decl:TFuncDecl = EachIn classDecl.Decls()
+					If Not decl.IsSemanted() Then
+						decl.Semant
+					End If
+					If decl.IdentLower() = func.IdentLower() Then
+						Local res:Int = decl.EqualsFunc(func)
+						If res Then
+							func.equalsBuiltIn = True
+						End If
+						Return res
+					End If
+				Next
+			End If
+			If classDecl.superClass Then
+				Return equalsBuiltInFunc(classDecl.superClass, func, True)
+			End If
+		End If
+		func.equalsBuiltIn = False
+		Return False
+	End Method
+
+	Method equalsIfcBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
+		If checked Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
+			If classDecl.munged = "bbObjectClass" Then
+				For Local decl:TFuncDecl = EachIn classDecl.Decls()
+					If Not decl.IsSemanted() Then
+						decl.Semant
+					End If
+					If decl.IdentLower() = func.IdentLower() Then
+						Return decl.EqualsFunc(func)
+					End If
+				Next
+			End If
+			If classDecl.superClass Then
+				Return equalsIfcBuiltInFunc(classDecl.superClass, func, True)
+			End If
+		End If
+		Return False
+	End Method
+
 	Method MungFuncDecl( fdecl:TFuncDecl )
 
 		If fdecl.munged Return
 		
-		If fdecl.overrides
-			MungFuncDecl fdecl.overrides
-			fdecl.munged=fdecl.overrides.munged
-			Return
-		EndIf
-		
 		Local funcs:TFuncDeclList=TFuncDeclList(funcMungs.ValueForKey( fdecl.ident ))
 		If funcs
 			For Local tdecl:TFuncDecl=EachIn funcs
-				If fdecl.argDecls.Length=tdecl.argDecls.Length
-					Local match:Int=True
-					For Local i:Int=0 Until fdecl.argDecls.Length
-						Local ty:TType=TArgDecl( fdecl.argDecls[i].actual ).ty
-						Local ty2:TType=TArgDecl( tdecl.argDecls[i].actual ).ty
-						If ty.EqualsType( ty2 ) Continue
-						match=False
-						Exit
-					Next
-					If match
-						fdecl.munged=tdecl.munged
-						Return
-					EndIf
+				If fdecl.EqualsArgs( tdecl )
+					fdecl.munged=tdecl.munged
+					Return
 				EndIf
 			Next
 		Else
 			funcs=New TFuncDeclList
 			funcMungs.Insert fdecl.ident,funcs
 		EndIf
+
+		If fdecl.scope Then
+			fdecl.munged = fdecl.scope.munged + "_" + fdecl.ident
+			
+			If Not equalsBuiltInFunc(fdecl.classScope(), fdecl) And Not fdecl.noMangle Then
+				fdecl.munged :+ MangleMethod(fdecl)
+			End If
+			
+			' fields are lowercase with underscore prefix.
+			' a function pointer with FUNC_METHOD is a field function pointer.
+			'If TFieldDecl(fdecl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
+			'	munged = "_" + munged.ToLower()
+			'End If
+		Else
+			fdecl.munged="bb_"+fdecl.ident
+		End If
 		
-		fdecl.munged="bbm_"+fdecl.ident
-		If Not funcs.IsEmpty() fdecl.munged:+String(funcs.Count()+1)
 		funcs.AddLast fdecl
 	End Method
 	
@@ -208,10 +349,12 @@ Type TTranslator
 
 		Local fdecl:TFuncDecl=TFuncDecl( decl )
 		
-		'If fdecl And fdecl.IsMethod() 
-		'	MungFuncDecl( fdecl )
-		'	Return
-		'End If
+		' apply mangling to methods and New (ctors)
+		' but don't apply mangling to function pointers
+		If fdecl And fdecl.ClassScope() And Not (fdecl.attrs & FUNC_PTR)
+			MungFuncDecl( fdecl )
+			Return
+		End If
 		
 		Local id$=decl.ident,munged$
 		

+ 419 - 79
type.bmx

@@ -40,10 +40,18 @@ Type TType
 		Return False
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
 		Return EqualsType( ty )
 	End Method
 	
+	Method WidensToType:Int( ty:TType )
+		Return False
+	End Method
+	
+	Method DistanceToType:Int(ty:TType)
+		Return T_MAX_DISTANCE
+	End Method
+	
 	Method Semant:TType(option:Int = False)
 		Return Self
 	End Method
@@ -197,6 +205,7 @@ Type TType
 	Const T_UINT:Int        = $400
 	Const T_ULONG:Int       = $800
 
+	Const T_MAX_DISTANCE:Int = $FFFF
 
 	Method Copy:TType()
 		Local ty:TType = OnCopy()
@@ -337,7 +346,7 @@ Type TNullType Extends TType
 		Return False
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
 		Return True
 	End Method
 	
@@ -357,8 +366,12 @@ Type TBoolType Extends TType
 		Return TBoolType( ty )<>Null
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		Return TNumericType( ty )<>Null Or TBoolType( ty )<>Null Or TStringType( ty )<>Null
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or TBoolType( ty )<>Null Or (Not noExtendString And TStringType( ty )<>Null)
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		Return IsNumericType(ty)
 	End Method
 	
 	Method ToString$()
@@ -377,7 +390,6 @@ End Type
 
 Type TNumericType Extends TType
 
-
 	Method ToPointer:TType()
 		Local ty:TType = Copy()
 		Return MapToPointerType(ty)
@@ -392,14 +404,42 @@ Type TIntType Extends TNumericType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True,,,,SCOPE_CLASS_HEIRARCHY )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf
 		If _flags & T_VARPTR And (TIntType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TIntVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null)
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TIntType(ty)<>Null And (ty._flags & T_VAR)) Or TLongType(ty)<>Null Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null
+	End Method
+	
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TIntType(ty)<>Null Then
+			Return 0
+		End If
+		
+		If TLongType(ty)<>Null Then
+			Return 2
+		End If
+
+		If TFloatType(ty)<>Null Then
+			Return 4
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 6
+		End If
+		
+		Return T_MAX_DISTANCE
 	End Method
 	
 	Method OnCopy:TType()
@@ -423,14 +463,58 @@ Type TUIntType Extends TNumericType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf
 		If _flags & T_VARPTR And (TUIntType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TIntVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TIntVarPtrType( ty )<> Null
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TUIntType(ty)<>Null And (ty._flags & T_VAR)) Or TIntType(ty)<> Null Or TLongType(ty)<>Null Or TULongType(ty)<>Null Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If WORD_SIZE = 4 And TSizeTType(ty)<>Null Then
+			Return 0
+		End If
+		
+		If TUIntType(ty)<>Null Then
+			Return 0
+		End If
+
+		If TIntType(ty)<>Null Then
+			Return 1
+		End If
+		
+		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+			Return 2
+		End If
+		
+		If TULongType(ty)<>Null Then
+			Return 2
+		End If
+
+		If TLongType(ty)<>Null Then
+			Return 3
+		End If
+
+		If TFloatType(ty)<>Null Then
+			Return 4
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 6
+		End If
+		
+		Return T_MAX_DISTANCE
 	End Method
 	
 	Method OnCopy:TType()
@@ -454,14 +538,77 @@ Type TSizeTType Extends TNumericType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf
 		If _flags & T_VARPTR And (TSizeTType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TIntVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TIntVarPtrType( ty )<> Null
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		If WORD_SIZE = 4 Then
+			Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or ((TSizeTType(ty)<>Null Or TUIntType(ty)<>Null) And (ty._flags & T_VAR)) Or TIntType(ty)<>Null Or TUIntType(ty)<>Null Or TLongType(ty)<>Null Or TULongType(ty)<>Null Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null
+		Else
+			Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or ((TSizeTType(ty)<>Null Or TULongType(ty)<>Null) And (ty._flags & T_VAR)) Or TLongType(ty)<>Null Or TULongType(ty)<>Null Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null
+		End If
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TSizeTType(ty)<>Null Then
+			Return 0
+		End If
+
+		If WORD_SIZE = 4 Then
+			If TUIntType(ty)<>Null Then
+				Return 0
+			End If
+
+			If TIntType(ty)<>Null Then
+				Return 2
+			End If
+
+			If TULongType(ty)<>Null Then
+				Return 3
+			End If
+
+			If TLongType(ty)<>Null Then
+				Return 4
+			End If
+
+			If TFloatType(ty)<>Null Then
+				Return 5
+			End If
+	
+			If TDoubleType(ty)<>Null Then
+				Return 6
+			End If
+			
+		Else
+			If TULongType(ty)<>Null Then
+				Return 0
+			End If
+
+			If TLongType(ty)<>Null Then
+				Return 2
+			End If
+
+			If TFloatType(ty)<>Null Then
+				Return 4
+			End If
+	
+			If TDoubleType(ty)<>Null Then
+				Return 6
+			End If
+		End If
+	
+		Return T_MAX_DISTANCE
 	End Method
 	
 	Method OnCopy:TType()
@@ -485,16 +632,68 @@ Type TByteType Extends TNumericType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf
 		If (_flags & T_VARPTR) And (TByteType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TByteVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TByteVarPtrType( ty )<> Null
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TByteType(ty)<>Null And (ty._flags & T_VAR)) Or TShortType(ty)<>Null Or TIntType(ty)<>Null Or TUIntType(ty)<>Null Or TLongType(ty)<>Null Or TULongType(ty)<>Null Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null
 	End Method
 
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TByteType(ty)<>Null Then
+			Return 0
+		End If
+
+		If TShortType(ty)<>Null Then
+			Return 2
+		End If
+
+		If WORD_SIZE = 4 And TSizeTType(ty)<>Null Then
+			Return 4
+		End If
+		
+		If TUIntType(ty)<>Null Then
+			Return 4
+		End If
+
+		If TIntType(ty)<>Null Then
+			Return 5
+		End If
+		
+		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+			Return 6
+		End If
+		
+		If TULongType(ty)<>Null Then
+			Return 6
+		End If
+
+		If TLongType(ty)<>Null Then
+			Return 7
+		End If
+
+		If TFloatType(ty)<>Null Then
+			Return 8
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 10
+		End If
+		
+		Return T_MAX_DISTANCE
+	End Method
+	
 	Method OnCopy:TType()
 		Return New TByteType
 	End Method
@@ -516,16 +715,64 @@ Type TShortType Extends TNumericType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf
 		If _flags & T_VARPTR And (TShortType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TShortVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TShortVarPtrType( ty )<> Null
 	End Method
-	
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TShortType(ty)<>Null And (ty._flags & T_VAR)) Or TIntType(ty)<>Null Or TUIntType(ty)<>Null Or TLongType(ty)<>Null Or TULongType(ty)<>Null Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TShortType(ty)<>Null Then
+			Return 0
+		End If
+
+		If WORD_SIZE = 4 And TSizeTType(ty)<>Null Then
+			Return 2
+		End If
+		
+		If TUIntType(ty)<>Null Then
+			Return 2
+		End If
+
+		If TIntType(ty)<>Null Then
+			Return 3
+		End If
+		
+		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+			Return 4
+		End If
+
+		If TULongType(ty)<>Null Then
+			Return 4
+		End If
+
+		If TLongType(ty)<>Null Then
+			Return 5
+		End If
+
+		If TFloatType(ty)<>Null Then
+			Return 6
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 8
+		End If
+		
+		Return T_MAX_DISTANCE
+	End Method
+
 	Method OnCopy:TType()
 		Return New TShortType
 	End Method
@@ -547,14 +794,38 @@ Type TLongType Extends TNumericType ' BaH Long
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf
 		If _flags & T_VARPTR And (TLongType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TLongVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TLongVarPtrType( ty )<> Null
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TLongType(ty)<>Null And (ty._flags & T_VAR)) Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TLongType(ty)<>Null Then
+			Return 0
+		End If
+
+		If TFloatType(ty)<>Null Then
+			Return 2
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 4
+		End If
+		
+		Return T_MAX_DISTANCE
 	End Method
 	
 	Method OnCopy:TType()
@@ -573,16 +844,48 @@ Type TULongType Extends TNumericType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf
 		If _flags & T_VARPTR And (TULongType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TLongVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TLongVarPtrType( ty )<> Null
 	End Method
-	
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TULongType(ty)<>Null And (ty._flags & T_VAR)) Or TDoubleType(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TULongType(ty)<>Null Then
+			Return 0
+		End If
+
+		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+			Return 0
+		End If
+		
+		If TLongType(ty)<>Null Then
+			Return 1
+		End If
+
+		If TFloatType(ty)<>Null Then
+			Return 2
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 4
+		End If
+		
+		Return T_MAX_DISTANCE
+	End Method
+
 	Method OnCopy:TType()
 		Return New TULongType
 	End Method
@@ -602,14 +905,34 @@ Type TFloatType Extends TDecimalType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf	
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf	
 		If _flags & T_VARPTR And (TFloatType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TFloatVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TFloatVarPtrType( ty )<> Null
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TFloatType(ty)<>Null And (ty._flags & T_VAR)) Or TDoubleType(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TFloatType(ty)<>Null Then
+			Return 0
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 2
+		End If
+		
+		Return T_MAX_DISTANCE
 	End Method
 
 	Method OnCopy:TType()
@@ -633,14 +956,30 @@ Type TDoubleType Extends TDecimalType
 			(_flags & T_VARPTR And ty._flags & T_PTR) Or (ty._flags & T_VARPTR And _flags & T_PTR) Or (_flags & T_VAR))
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
-		If TObjectType( ty )
-			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
-			Return ctor And ctor.IsCtor()
-		EndIf	
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		'If TObjectType( ty )
+		'	Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
+		'	Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+		'	Return ctor And ctor.IsCtor()
+		'EndIf	
 		If _flags & T_VARPTR And (TDoubleType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return TNumericType( ty )<>Null Or TStringType( ty )<>Null 'Or TDoubleVarPtrType( ty )<> Null
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) 'Or TDoubleVarPtrType( ty )<> Null
+	End Method
+
+	Method WidensToType:Int( ty:TType )
+		Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or (TDoubleType(ty)<>Null And (ty._flags & T_VAR))
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
+			Return 0
+		End If
+
+		If TDoubleType(ty)<>Null Then
+			Return 0
+		End If
+		
+		Return T_MAX_DISTANCE
 	End Method
 
 	Method OnCopy:TType()
@@ -661,12 +1000,12 @@ Type TStringType Extends TType
 		Return TStringType( ty )<>Null And (_flags = ty._flags Or (_flags & T_VAR))
 	End Method
 
-	Method ExtendsType:Int( ty:TType )	
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )	
 		Return EqualsType( ty ) Or (TObjectType( ty ) And TObjectType( ty ).classDecl.ident="Object") Or (TStringType(ty) And (_flags & T_VAR)) ..
 			Or (TStringType(ty) And (ty._flags & T_VAR)) Or (TStringType(ty) And (ty._flags & T_CHAR_PTR)) Or (TStringType(ty) And (ty._flags & T_SHORT_PTR)) ..
 			Or IsPointerType(ty) Or (TStringType(ty) And (_flags & T_CHAR_PTR)) Or (TStringType(ty) And (_flags & T_SHORT_PTR))
 	End Method
-	
+
 	Method GetClass:TClassDecl()
 		If cdecl Return cdecl
 		
@@ -724,7 +1063,7 @@ Type TArrayType Extends TType
 		Return arrayType And elemType.EqualsType( arrayType.elemType ) And dims = arrayType.dims
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
 		Local arrayType:TArrayType=TArrayType( ty )
 		Return (arrayType And ( TVoidType( elemType ) Or elemType.EqualsType( arrayType.elemType ) Or elemType.ExtendsType( arrayType.elemType ) )) Or IsPointerType(ty, 0, TType.T_POINTER) <> Null Or (TObjectType( ty ) And TObjectType( ty ).classDecl.ident="Object")
 	End Method
@@ -771,7 +1110,7 @@ Type TObjectType Extends TType
 		Return TNullDecl(classDecl) <> Null Or (objty And (classDecl=objty.classDecl))' Or classDecl.ExtendsClass( objty.classDecl ))) 'Or TObjectVarPtrType(ty) <> Null
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
 		Local objty:TObjectType=TObjectType( ty )
 		If objty Return classDecl.ExtendsClass( objty.classDecl )
 		If IsPointerType( ty, T_BYTE ) Return True
@@ -829,7 +1168,7 @@ Type TIdentType Extends TType
 		InternalErr
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
 		InternalErr
 	End Method
 	
@@ -990,7 +1329,7 @@ Type TExternObjectType Extends TType
 		Return TNullDecl(classDecl) <> Null Or (objty And (classDecl=objty.classDecl Or classDecl.ExtendsClass( objty.classDecl ))) Or TObjectType(ty)
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
 		Local objty:TObjectType=TObjectType( ty )
 		If objty Return classDecl.ExtendsClass( objty.classDecl )
 		If IsPointerType( ty, T_BYTE ) Return True
@@ -1008,7 +1347,7 @@ Type TExternObjectType Extends TType
 		Else
 			Return False
 		EndIf
-		Local fdecl:TFuncDecl=GetClass().FindFuncDecl( op,Null,True )
+		Local fdecl:TFuncDecl=GetClass().FindFuncDecl( op,Null,True,,,,SCOPE_CLASS_HEIRARCHY )
 		Return fdecl And fdecl.IsMethod() And fdecl.retType.EqualsType( ty )
 	End Method
 	
@@ -1036,16 +1375,17 @@ Type TFunctionPtrType Extends TType
 		Return TFunctionPtrType( ty )<>Null
 	End Method
 	
-	Method ExtendsType:Int( ty:TType )
+	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
 		If TObjectType( ty )
 			Local expr:TExpr=New TConstExpr.Create( Self,"" ).Semant()
-			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True )
+			Local ctor:TFuncDecl=ty.GetClass().FindFuncDecl( "new",[expr],True,,,,SCOPE_CLASS_HEIRARCHY )
 			Return ctor And ctor.IsCtor()
 		EndIf
 		Return IsPointerType( ty, 0, T_POINTER )<>Null
 	End Method
 	
 	Method equalsDecl:Int(fdecl:TFuncDecl)
+
 		func.Semant
 		fdecl.Semant