浏览代码

Merge remote-tracking branch 'origin/master' into bcc_gen

woollybah 8 年之前
父节点
当前提交
739b05c826

+ 1 - 1
COPYING.md

@@ -1,4 +1,4 @@
-Copyright (c) 2013-2015 Bruce A Henderson
+Copyright (c) 2013-2017 Bruce A Henderson
 
 This software is provided 'as-is', without any express or implied
 warranty. In no event will the authors be held liable for any damages

+ 3 - 0
TODO.md

@@ -1,5 +1,8 @@
 #TODO
 
+## Access Modifiers
+Allowing use of Private/Public for Type members.
+
 ##Documentation
 Need some user-friendly documentation for installing and configuration.
 Details for each platform, notes on cross-compilation, etc.

+ 1 - 1
base.configmap.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Ronny Otto
+' Copyright (c) 2013-2017 Ronny Otto
 ' 
 ' This software is provided 'as-is', without any express or implied
 ' warranty. In no event will the authors be held liable for any damages

+ 2 - 2
base.stringhelper.bmx

@@ -1,5 +1,5 @@
-' Copyright (c) 2014-2016 Bruce A Henderson
-' Copyright (c) 2014-2016 Ronny Otto
+' Copyright (c) 2014-2017 Bruce A Henderson
+' Copyright (c) 2014-2017 Ronny Otto
 '
 ' This software is provided 'as-is', without any express or implied
 ' warranty. In no event will the authors be held liable for any damages

+ 1 - 1
bcc.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '

+ 14 - 1
config.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -47,6 +47,9 @@ Global OBJECT_BASE_OFFSET:Int = 8
 ' 4 bytes on 32-bit, 8 bytes on 64-bit
 Global POINTER_SIZE:Int = 4
 
+Global _symbols$[]=[ "..","[]",":*",":/",":+",":-",":|",":&",":~~",":shr",":shl",":sar",":mod"]
+Global _symbols_map$[]=[ "..","[]","*=","/=","+=","-=","|=","&=","^=",">>=", "<<=",">>=","%=" ]
+
 Function PushErr( errInfo$ )
 	_errStack.AddLast _errInfo
 	_errInfo=errInfo
@@ -114,6 +117,16 @@ Function IsStandardFunc:Int(func:String)
 	Return funcs.Find(func) > 0
 End Function
 
+Function mapSymbol:String(sym:String)
+	For Local i:Int = 0 Until _symbols.length
+		If sym = _symbols[i] Then
+			Return _symbols_map[i]
+		End If
+	Next
+	Return sym
+End Function
+
+
 'enquote depending on ENV_LANG
 '
 Function LangEnquote$( str$ )

文件差异内容过多而无法显示
+ 484 - 101
ctranslator.bmx


+ 306 - 76
decl.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -36,9 +36,11 @@ Const DECL_ARG:Int=         $800000
 Const DECL_INITONLY:Int=   $1000000
 
 Const DECL_NODEBUG:Int=    $2000000
+Const DECL_PROTECTED:Int=  $4000000
 
-Const DECL_API_WIN32:Int= $10000000
-Const DECL_API_OS:Int=DECL_API_WIN32
+Const DECL_API_CDECL:Int=   $00000000
+Const DECL_API_STDCALL:Int= $10000000
+Const DECL_API_DEFAULT:Int= DECL_API_CDECL
 
 Const CLASS_INTERFACE:Int=  $001000
 Const CLASS_THROWABLE:Int=  $002000
@@ -50,6 +52,10 @@ Const SCOPE_CLASS_HEIRARCHY:Int = 2
 Const SCOPE_MODULE:Int = 3
 Const SCOPE_ALL:Int = 4
 
+'Const CALL_CONV_CDECL:Int = 0
+'Const CALL_CONV_STDCALL:Int = 1
+'Const CALL_CONV_DEFAULT:Int = CALL_CONV_CDECL
+
 Global _env:TScopeDecl
 Global _envStack:TList=New TList
 
@@ -139,9 +145,21 @@ Type TDecl
 		Return (attrs & DECL_EXTERN)<>0
 	End Method
 	
+	Method IsFinal:Int()
+		Return (attrs & DECL_FINAL)<>0
+	End Method
+
 	Method IsPrivate:Int()
 		Return (attrs & DECL_PRIVATE)<>0
 	End Method
+
+	Method IsProtected:Int()
+		Return (attrs & DECL_PROTECTED)<>0
+	End Method
+	
+	Method IsPublic:Int()
+		Return Not (IsPrivate() Or IsProtected())
+	End Method
 	
 	Method IsAbstract:Int()
 		Return (attrs & DECL_ABSTRACT)<>0
@@ -188,7 +206,11 @@ Type TDecl
 	
 	Method AssertAccess()
 		If Not CheckAccess()
-			Err ToString() +" is private."
+			If IsPrivate() Then
+				Err ToString() +" is private."
+			Else
+				Err ToString() +" is protected."
+			End If
 		EndIf
 	End Method
 
@@ -311,15 +333,22 @@ Type TValDecl Extends TDecl
 	End Method
 	
 	Method OnSemant()
-
+	
 		If declTy
+
+			Local at:TType = TArrayType(declTy)
+			
+			While TArrayType(at)
+				at = TArrayType(at).elemType
+			Wend
+		
 			' ensure to set the scope for a function pointer array before semanting
-			If TArrayType(declTy) And TFunctionPtrType(TArrayType(declTy).elemType) Then
-				If Not TFunctionPtrType(TArrayType(declTy).elemType).func.scope Then
+			If TFunctionPtrType(at) Then
+				If Not TFunctionPtrType(at).func.scope Then
 					If scope Then
-						TFunctionPtrType(TArrayType(declTy).elemType).func.scope = scope
+						TFunctionPtrType(at).func.scope = scope
 					Else
-						TFunctionPtrType(TArrayType(declTy).elemType).func.scope = _env
+						TFunctionPtrType(at).func.scope = _env
 					End If
 				End If
 			End If
@@ -365,46 +394,82 @@ Type TValDecl Extends TDecl
 			If declInit Then
 				If TFunctionPtrType(ty) Then
 					
-					' the default munged function value as defined in the interface
+					Local expr:TExpr
+					
 					If TInvokeExpr(declInit) Then
-						init = declInit.Copy()
+						expr = declInit.Copy()
 					Else If TConstExpr(declInit) Then
-						init = declInit.Copy().Semant()
+						expr = declInit.Copy().Semant()
+					Else If TFuncCallExpr(declInit) Then
+						expr=declInit.Copy().Semant()
+					Else If TNullExpr(declInit) Then
+						expr = declInit
 					Else
-						Local expr:TExpr
-						
-						If TFuncCallExpr(declInit) Then
-							expr=declInit.Copy().Semant()
-						Else If TNullExpr(declInit) Then
-							expr = declInit
-						Else
-							Local argExpr:TExpr[] = New TExpr[0]
-
-							For Local arg:TArgDecl = EachIn TFunctionPtrType(ty).func.argDecls
-								Local ldecl:TLocalDecl = New TLocalDecl.Create(arg.ident, arg.declTy, Null, 0)
-								ldecl.Semant()
-								Local aexp:TVarExpr = New TVarExpr.Create(ldecl)
-								'Local aexp:TIdentTypeExpr = New TIdentTypeExpr.Create(arg.declTy)
-								aexp.Semant()
-								argExpr :+ [aexp]
-							Next
+						' declInit can only be an expression, never a statement
+						' this means that any function call in there is required to have parentheses, and will
+						' thus appear in the form of a TFuncCallExpr
+						' as such, trying SemantFunc in the Else branch seems pointless and will in fact wrongly
+						' interpret function pointers (as TIdentExpr, TIndexExpr, possibly others?) as calls
+						Rem
+						Local argExpr:TExpr[] = New TExpr[0]
+
+						For Local arg:TArgDecl = EachIn TFunctionPtrType(ty).func.argDecls
+							Local ldecl:TLocalDecl = New TLocalDecl.Create(arg.ident, arg.declTy, Null, 0)
+							ldecl.Semant()
+							Local aexp:TVarExpr = New TVarExpr.Create(ldecl)
+							'Local aexp:TIdentTypeExpr = New TIdentTypeExpr.Create(arg.declTy)
+							aexp.Semant()
+							argExpr :+ [aexp]
+						Next
 
-							expr=declInit.Copy().SemantFunc(argExpr, False, False)
-							If Not expr Then
-								expr = declInit.Copy().Semant()
-							End If
+						expr=declInit.Copy().SemantFunc(argExpr, False, False)
+						If Not expr Then
+							expr = declInit.Copy().Semant()
 						End If
+						End Rem
 						
-						If expr.exprType.EqualsType( ty ) Then
-							init = expr
-						Else
-							init = New TCastExpr.Create( ty,expr,CAST_EXPLICIT ).Semant()
-						End If
+						expr = declInit.Copy().Semant()
+					End If
+					
+					If expr.exprType.EqualsType( ty ) Then
+						init = expr
+					Else
+						init = New TCastExpr.Create( ty,expr,CAST_EXPLICIT ).Semant()
 					End If
 					
 					
 				Else
+					If TArrayExpr(declInit) And TArrayType(ty) And TNumericType(TArrayType(ty).elemType) Then
+						TArrayExpr(declInit).toType = TArrayType(ty).elemType
+					End If
+				
 					init=declInit.Copy().SemantAndCast(ty)
+					
+					' check if struct has been initialised
+					If TObjectType(ty) And TObjectType(ty).classDecl.IsStruct() Then
+					
+						' new not used
+						If TConstExpr(init) And Not TConstExpr(init).value Then
+							
+							Local found:Int = False
+							' struct contains any objects?
+							For Local fld:TFieldDecl = EachIn TObjectType(ty).classDecl._decls
+								If Not fld.IsSemanted() Then
+									fld.Semant()
+								End If
+							
+								If TObjectType(fld.ty) Or TStringType(fld.ty) Or TArrayType(fld.ty) Then
+									found = True
+									Exit
+								End If
+							Next
+						
+							' we need to initialise object fields, so we'll call the default constructor
+							If found Then
+								init = New TNewObjectExpr.Create(ty, Null).Semant()
+							End If
+						End If
+					End If
 				End If
 			End If
 		Else If declInit
@@ -478,18 +543,20 @@ End Type
 Type TLocalDecl Extends TVarDecl
 
 	Field done:Int
+	Field volatile:Int = True
 
-	Method Create:TLocalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0, generated:Int = False )
+	Method Create:TLocalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0, generated:Int = False, volatile:Int = True )
 		Self.ident=ident
 		Self.declTy=ty
 		Self.declInit=init
 		Self.attrs=attrs
 		Self.generated=generated
+		Self.volatile=volatile
 		Return Self
 	End Method
 	
 	Method OnCopy:TDecl(deep:Int = True)
-		Return New TLocalDecl.Create( ident,ty,CopyInit(),attrs, generated )
+		Return New TLocalDecl.Create( ident,ty,CopyInit(),attrs, generated, volatile )
 	End Method
 
 	Method GetDeclPrefix:String()
@@ -506,12 +573,13 @@ Type TArgDecl Extends TLocalDecl
 
 	Field castTo:String
 	
-	Method Create:TArgDecl( ident$,ty:TType,init:TExpr,attrs:Int=0, generated:Int = False )
+	Method Create:TArgDecl( ident$,ty:TType,init:TExpr,attrs:Int=0, generated:Int = False, volatile:Int = True )
 		Self.ident=ident
 		Self.declTy=ty
 		Self.declInit=init
 		Self.attrs=attrs
 		Self.generated=generated
+		Self.volatile=volatile
 		Return Self
 	End Method
 	
@@ -524,7 +592,7 @@ Type TArgDecl Extends TLocalDecl
 	End Method
 	
 	Method OnCopy:TDecl(deep:Int = True)
-		Local d:TArgDecl = New TArgDecl.Create( ident,ty,CopyInit(),attrs,generated )
+		Local d:TArgDecl = New TArgDecl.Create( ident,ty,CopyInit(),attrs,generated,volatile )
 		d.ty = d.declTy
 		d.init = d.declInit
 		Return d
@@ -573,6 +641,20 @@ Type TGlobalDecl Extends TVarDecl
 		Return inst
 	End Method
 
+	Method CheckAccess:Int()
+		Local cd:TClassDecl = ClassScope()
+		If cd Then
+			If IsPrivate() And cd<>_env.ClassScope() Return False
+			If IsProtected() Then
+				Local ec:TClassDecl = _env.ClassScope()
+				If Not ec Return False
+				If Not ec.ExtendsClass(cd) Return False
+			End If
+			Return True
+		End If
+		Return Super.CheckAccess()
+	End Method
+
 End Type
 
 Type TFieldDecl Extends TVarDecl
@@ -605,7 +687,17 @@ Type TFieldDecl Extends TVarDecl
 		inst.declInit=declInit
 		Return inst
 	End Method
-	
+
+	Method CheckAccess:Int()
+		If IsPrivate() And ClassScope()<>_env.ClassScope() Return False
+		If IsProtected() And ClassScope() Then
+			Local ec:TClassDecl = _env.ClassScope()
+			If Not ec Return False
+			If Not ec.ExtendsClass(ClassScope()) Return False
+		End If
+		Return True
+	End Method
+
 End Type
 
 Type TAliasDecl Extends TDecl
@@ -790,7 +882,7 @@ Type TScopeDecl Extends TDecl
 		If TFuncDeclList(decl) Then
 			For Local fdecl:TFuncDecl = EachIn TFuncDeclList(decl)
 
-				If Not fdecl.IsSemanted() Then
+				If Not fdecl.IsSemanted() And Not fdecl.IsSemanting() Then
 					fdecl.Semant
 				End If
 				
@@ -840,6 +932,27 @@ Type TScopeDecl Extends TDecl
 					declList.AddLast(decl)
 				End If
 			End If
+
+			' if scope is an interface, also check implemented/extended interfaces?
+			If TClassDecl(tscope) And TClassDecl(tscope).IsInterface() Then
+				If TClassDecl(tscope).implments Then
+					For Local idecl:TScopeDecl = EachIn TClassDecl(tscope).implments
+						Local decl:Object=idecl.GetDeclList( ident, declList, maxSearchDepth )
+						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
+					Next
+				End If 
+			End If
+			
 			tscope=tscope.scope
 			
 			If TClassDecl(tscope) And maxSearchDepth < SCOPE_CLASS_HEIRARCHY Then
@@ -1034,6 +1147,9 @@ End Rem
 					' 
 				Else If Not bestMatch.IsMethod() And func.IsMethod() Then
 					bestMatch = func
+				Else If (bestMatch.scope <> func.scope) And (TClassDecl(bestMatch.scope).ExtendsClass(TClassDecl(func.scope))) Then
+					' match is in different level of class hierarchy
+					Exit
 				Else
 					' a tie?
 					Err "Unable to determine overload to use: "+ bestMatch.ToString()+" or "+func.ToString()+"."
@@ -1091,7 +1207,9 @@ End Rem
 '		If Not funcs Then Return Null
 		
 		For Local func:TDecl = EachIn funcs
-			func.Semant()
+			If Not func.IsSemanting() Then
+				func.Semant()
+			End If
 		Next
 		
 		'Local f:TDecl = TDecl(findDecl(ident))
@@ -1189,20 +1307,23 @@ End Rem
 				
 				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
-				
+
+				If argExprs.Length>argDecls.Length
+					exact = False
+					Continue
+				End If
+
 				For Local i:Int=0 Until argDecls.Length
 	
 					If i<argExprs.Length And argExprs[i]
@@ -1430,10 +1551,11 @@ Const FUNC_METHOD:Int=   $0001			'mutually exclusive with ctor
 Const FUNC_CTOR:Int=     $0002
 Const FUNC_PROPERTY:Int= $0004
 Const FUNC_DTOR:Int=     $0008
-Const FUNC_PTR:Int=      $0100
 Const FUNC_BUILTIN:Int = $0080
+Const FUNC_PTR:Int=      $0100
 Const FUNC_INIT:Int =    $0200
 Const FUNC_NESTED:Int =  $0400
+Const FUNC_OPERATOR:Int= $0800
 
 'Fix! A func is NOT a block/scope!
 '
@@ -1475,7 +1597,7 @@ Type TFuncDecl Extends TBlockDecl
 		For Local i:Int=0 Until args.Length
 			args[i]=TArgDecl( args[i].Copy() )
 		Next
-		Local t:TFuncDecl=New TFuncDecl.CreateF( ident,retType,args,attrs )
+		Local t:TFuncDecl=New TFuncDecl.CreateF( ident,retType,args,attrs)
 		If deep Then
 			For Local stmt:TStmt=EachIn stmts
 				t.AddStmt stmt.Copy( t )
@@ -1565,6 +1687,10 @@ Type TFuncDecl Extends TBlockDecl
 		Return (attrs & FUNC_METHOD)<>0
 	End Method
 	
+	Method IsAnyMethod:Int()
+		Return IsMethod() Or IsCtor() Or IsDtor() 
+	End Method
+	
 	Method IsStatic:Int()
 		Return (attrs & (FUNC_METHOD|FUNC_CTOR))=0
 	End Method
@@ -1573,26 +1699,40 @@ Type TFuncDecl Extends TBlockDecl
 		Return (attrs & FUNC_PROPERTY)<>0
 	End Method
 	
-	Method EqualsArgs:Int( decl:TFuncDecl )
+	Method EqualsArgs:Int( decl:TFuncDecl ) ' careful, this is not commutative!
 		If argDecls.Length<>decl.argDecls.Length Return False
 		For Local i:Int=0 Until argDecls.Length
-			If Not argDecls[i].ty.EqualsType( decl.argDecls[i].ty ) Return False
+			' objects can be subclasses as well as the same.
+			If TObjectType(decl.argDecls[i].ty) Then
+				If Not decl.argDecls[i].ty.EqualsType( argDecls[i].ty ) And Not decl.argDecls[i].ty.ExtendsType( argDecls[i].ty ) Return False
+			Else
+				If Not decl.argDecls[i].ty.EqualsType( argDecls[i].ty ) Return False
+			End If
 		Next
 		Return True
 	End Method
 
-	Method EqualsFunc:Int( decl:TFuncDecl )
+	Method EqualsFunc:Int( decl:TFuncDecl ) ' careful, this is not commutative!
 		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 )
+			' matching args?
+			If EqualsArgs( decl ) Then
+				' matching return type?
+				If TObjectType(retType) Or TArrayType(retType) Or TStringType(retType) Then
+					Return retType.EqualsType( decl.retType ) Or retType.ExtendsType( decl.retType )' Or decl.retType.EqualsType( retType )) And EqualsArgs( decl )
+				Else
+					Return retType.EqualsType( decl.retType )
+				End If
+			End If
 		End If
+		Return False
 	End Method
 
 	Method OnSemant()
 
 		Local strictVoidToInt:Int = False
-		
+
 		'semant ret type
 		If Not retTypeExpr Then
 			If Not retType Then ' may have previously been set (if this is a function pointer)
@@ -1607,6 +1747,21 @@ Type TFuncDecl Extends TBlockDecl
 				End If
 			End If
 		Else
+			' pass the scope into the function ptr
+			Local retTypeExpr_:TType = retTypeExpr
+			While TArrayType(retTypeExpr_) ' look into array types, since the element type might be function ptr
+				retTypeExpr_ = TArrayType(retTypeExpr_).elemType
+			Wend
+			If TFunctionPtrType(retTypeExpr_) Then
+				If Not TFunctionPtrType(retTypeExpr_).func.scope Then
+					If scope Then
+						TFunctionPtrType(retTypeExpr_).func.scope = scope
+					Else
+						TFunctionPtrType(retTypeExpr_).func.scope = _env
+					End If
+				End If
+			End If
+		
 			retType=retTypeExpr.Semant()
 			
 			' for Strict code, a void return type becomes Int
@@ -1704,12 +1859,41 @@ Type TFuncDecl Extends TBlockDecl
 
 						If EqualsFunc( decl ) And Not voidReturnTypeFail
 
-							If Not retType.EqualsType( decl.retType ) And retType.ExtendsType( decl.retType ) Then
-								returnTypeSubclassed = True
+							' check we aren't attempting to assign weaker access modifiers
+							If (IsProtected() And decl.IsPublic()) Or (IsPrivate() And (decl.IsProtected() Or decl.IsPublic())) Then
+							
+								Local p:String
+								If IsProtected() Then
+									p = "Protected"
+								Else
+									p = "Private"
+								End If
+								
+								Local dp:String
+								If decl.IsPublic() Then
+									dp = "Public"
+								Else
+									dp = "Protected"
+								End If
+							
+								Err ToString() + " clashes with " + decl.ToString() + ". Attempt to assign weaker access privileges ('" + p + "'), was '" + dp + "'."
+							
+							End If
+						
+							If TObjectType(retType) And TObjectType(decl.retType ) Then
+								If Not retType.EqualsType( decl.retType ) And retType.ExtendsType( decl.retType ) Then
+									returnTypeSubclassed = True
+								End If
 							End If
 							
 							overrides=TFuncDecl( decl.actual )
 						Else
+							' method overloading?
+							If Not EqualsArgs(decl) Then
+								found = False
+								Continue
+							End If
+							
 							'prepare a more detailed error message
 							If (Not retType.EqualsType( decl.retType ) Or Not retType.ExtendsType( decl.retType )) Or (decl.retType And Not decl.retType.EqualsType( retType )) Or voidReturnTypeFail
 								errorDetails :+ "Return type is ~q"+retType.ToString()+"~q, expected ~q"+decl.retType.ToString()+"~q. "
@@ -1720,11 +1904,7 @@ Type TFuncDecl Extends TBlockDecl
 								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
+
 							Local argCount:Int = Min(argDecls.Length, decl.argDecls.Length)
 							If argCount > 0
 								For Local i:Int=0 Until argCount
@@ -1740,6 +1920,7 @@ Type TFuncDecl Extends TBlockDecl
 				Next
 				If found
 					If Not overrides Err "Overriding method does not match any overridden method. (Detail: " + errorDetails+")"
+					If overrides.IsFinal() Err "Final methods cannot be overridden."
 					' for overrides, make the ident match that of the superclass
 					ident = overrides.ident
 					
@@ -1766,7 +1947,21 @@ Type TFuncDecl Extends TBlockDecl
 		
 		Super.OnSemant()
 	End Method
-	
+
+	Method CheckAccess:Int()
+		Local cd:TClassDecl = ClassScope()
+		If cd Then
+			If IsPrivate() And cd<>_env.ClassScope() Return False
+			If IsProtected() Then
+				Local ec:TClassDecl = _env.ClassScope()
+				If Not ec Return False
+				If Not ec.ExtendsClass(cd) Return False
+			End If
+			Return True
+		End If
+		Return Super.CheckAccess()
+	End Method
+
 End Type
 
 Type TNewDecl Extends TFuncDecl
@@ -1794,7 +1989,7 @@ Type TClassDecl Extends TScopeDecl
 
 	Field lastOffset:Int
 
-	Field args:TClassDecl[]
+	Field args:String[]
 	Field superTy:TIdentType
 	Field impltys:TIdentType[]
 
@@ -1808,10 +2003,11 @@ Type TClassDecl Extends TScopeDecl
 	Field instArgs:TType[]
 
 	Field objectType:TObjectType '"canned" objectType
+	Field globInit:Int
 
 	'Global nullObjectClass:TClassDecl=New TNullDecl.Create( "{NULL}",Null,Null,Null,DECL_ABSTRACT|DECL_EXTERN )
 	
-	Method Create:TClassDecl( ident$,args:TClassDecl[],superTy:TIdentType,impls:TIdentType[],attrs:Int )
+	Method Create:TClassDecl( ident$,args:String[],superTy:TIdentType,impls:TIdentType[],attrs:Int )
 		Self.ident=ident
 		Self.args=args
 		Self.superTy=superTy
@@ -1845,7 +2041,7 @@ Type TClassDecl Extends TScopeDecl
 	Method ToTypeString:String()
 		Return ident
 	End Method
-Rem	
+Rem
 	Method GenClassInstance:TClassDecl( instArgs:TClassDecl[] )
 		If Not IsSemanted() InternalErr
 		
@@ -1904,7 +2100,6 @@ Rem
 		Return inst
 	End Method
 End Rem
-
 	Method GenClassInstance:TClassDecl( instArgs:TType[] )
 
 		If instanceof InternalErr
@@ -1959,10 +2154,6 @@ End Rem
 		Return (attrs & CLASS_INTERFACE)<>0
 	End Method
 
-	Method IsFinal:Int()
-		Return (attrs & DECL_FINAL)<>0
-	End Method
-
 	Method IsThrowable:Int()
 		Return (attrs & CLASS_THROWABLE)<>0
 	End Method
@@ -2087,6 +2278,7 @@ End Rem
 	End Method
 	
 	Method GetAllFuncDecls:TFuncDecl[](funcs:TFuncDecl[] = Null, includeSuper:Int = True)
+
 		If Not funcs Then
 			funcs = New TFuncDecl[0]
 		End If
@@ -2108,6 +2300,10 @@ End Rem
 				' found a match - we are overriding it
 				If func.IdentLower() = funcs[i].IdentLower() And func.EqualsArgs(funcs[i]) Then
 					matched = True
+					' but don't override if we are an interface and the function is implemented
+					If IsInterface() And Not funcs[i].ClassScope().IsInterface() Then
+						Exit
+					End If
 					' set this to our own func
 					funcs[i] = func
 					Exit
@@ -2468,11 +2664,10 @@ End Rem
 						
 						While cdecl And Not found
 							For Local decl2:TFuncDecl=EachIn cdecl.SemantedMethods( decl.ident )
-								If decl.EqualsFunc( decl2 )
-									If decl2.munged And Not iface.IsExtern()
-										Err "Extern methods cannot be used to implement interface methods."
-									EndIf
+								' equals (or extends - for object types)
+								If decl2.EqualsFunc( decl )
 									found=True
+									Exit
 								EndIf
 							Next
 						
@@ -2485,12 +2680,47 @@ End Rem
 					Next
 				Next
 			End If
+		Else
+			' check for compatible overloads, etc.
+
+			Local impls:TList=New TList
+
+			CheckInterface(Self, impls)
+			
 		EndIf
 		
 		PopErr
 		
 	End Method
 	
+	Method CheckInterface(cdecl:TClassDecl, impls:TList)
+		While cdecl
+		
+			For Local decl:TFuncDecl=EachIn cdecl.SemantedMethods()
+				Local found:Int
+				For Local decl2:TFuncDecl=EachIn impls
+					If decl.IdentLower() = decl2.IdentLower()
+						If Not decl2.EqualsFunc( decl )
+							Err "Cannot mix incompatible method signatures." + decl2.ToString() + " vs " + decl.ToString() + "."
+						Else
+							found = True
+						End If
+					EndIf
+				Next
+				If Not found Then
+					impls.AddLast decl
+				End If
+				'EndIf
+			Next
+			
+			For Local idecl:TClassDecl = EachIn cdecl.implments
+				CheckInterface(idecl, impls)
+			Next
+
+			cdecl=cdecl.superClass
+		Wend
+	End Method
+	
 	Method GetFieldOffset(decl:TFieldDecl)
 		
 		Local ty:TType = decl.declTy

+ 316 - 54
expr.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -171,6 +171,12 @@ Type TExpr
 					End If
 				End If
 
+				' re-test auto array for compatible consts.
+				If TArrayExpr(args[i]) And TArrayType(funcDecl.argDecls[i].ty) And TNumericType(TArrayType(funcDecl.argDecls[i].ty).elemType) Then
+					TArrayExpr(args[i]).toType = TArrayType(funcDecl.argDecls[i].ty).elemType
+					args[i].exprType = Null
+					args[i].Semant()
+				End If
 				args[i]=args[i].Cast( funcDecl.argDecls[i].ty )
 			Else If funcDecl.argDecls[i].init
 				If i = args.length Then
@@ -186,14 +192,6 @@ Type TExpr
 	End Method
 
 	Method BalanceTypes:TType( lhs:TType,rhs:TType )
-'DebugStop
-		'If lhs._flags & TType.T_VAR Then
-		'	lhs = TType.MapVarPointerToPrim(lhs)
-		'End If
-
-		'If rhs._flags & TType.T_VAR Then
-		'	rhs = TType.MapVarPointerToPrim(rhs)
-		'End If
 
 		If TStringType( lhs ) Or TStringType( rhs ) Then
 			If TObjectType(lhs) Or TObjectType(rhs) Then
@@ -211,16 +209,22 @@ Type TExpr
 			If IsPointerType( lhs, 0, TType.T_POINTER ) Return lhs
 			If IsPointerType( rhs, 0, TType.T_POINTER ) Return rhs
 		End If
+		If TDouble128Type( lhs ) Or TDouble128Type( rhs ) Return New TDouble128Type
+		If TFloat128Type( lhs ) Or TFloat128Type( rhs ) Return New TFloat128Type
+		If TFloat64Type( lhs ) Or TFloat64Type( rhs ) Return New TFloat64Type
 		If TDoubleType( lhs ) Or TDoubleType( rhs ) Return New TDoubleType
 		If TFloatType( lhs ) Or TFloatType( rhs ) Return New TFloatType
 		If TFunctionPtrType( lhs ) Or TFunctionPtrType( rhs ) Then
 			If TFunctionPtrType( lhs ) Return lhs
 			If TFunctionPtrType( rhs ) Return rhs
 		End If
+		If TInt128Type( lhs ) Or TInt128Type( rhs ) Return New TInt128Type
 		If TULongType( lhs ) Or TULongType( rhs ) Return New TULongType
 		If TSizeTType( lhs ) Or TSizeTType( rhs ) Return New TSizeTType
+		If TWParamType( lhs ) Or TWParamType( rhs ) Return New TWParamType
 		If TLongType( lhs ) And TUIntType( rhs ) Return New TULongType
 		If TUIntType( lhs ) And TLongType( rhs ) Return New TULongType
+		If TLParamType( lhs ) Or TLParamType( rhs ) Return New TLParamType
 		If TLongType( lhs ) Or TLongType( rhs ) Return New TLongType
 		If TUIntType( lhs ) Or TUIntType( rhs ) Return New TUIntType
 		If TIntType( lhs ) Or TIntType( rhs ) Return New TIntType
@@ -352,7 +356,6 @@ Type TConstExpr Extends TExpr
 	Field typeSpecific:Int
 
 	Method Create:TConstExpr( ty:TType,value$ )
-
 		originalValue = value
 		
 		If TNumericType( ty ) And IsPointerType(ty, 0, TType.T_POINTER) Then
@@ -365,7 +368,7 @@ Type TConstExpr Extends TExpr
 			Return Self
 		End If
 		
-		If TIntType( ty ) Or TShortType( ty ) Or TByteType( ty ) Or TLongType( ty ) Or TUIntType( ty ) Or TULongType( ty )
+		If TIntType( ty ) Or TShortType( ty ) Or TByteType( ty ) Or TLongType( ty ) Or TUIntType( ty ) Or TULongType( ty ) Or TWParamType(ty) Or TLParamType(ty)
 			Local radix:Int
 			If value.StartsWith( "%" )
 				radix=1
@@ -401,7 +404,43 @@ Type TConstExpr Extends TExpr
 				Else If TByteType( ty ) Then
 					value = String.FromLong(Byte(value.ToLong()))
 				Else
-					value = String.FromLong(value.ToLong())
+					Local buf:Byte[64]
+					Local b:Int
+					Local v:String = value.Trim()
+					Local leading0:Int = True
+					If v Then
+						Local i:Int
+						If v[0] = Asc("+") Then
+							i = 1
+						Else If v[0] = Asc("-") Then
+							i = 1
+							buf[b] = Asc("-")
+							b:+ 1
+						End If
+						
+						While i < value.Length
+							If Not IsDigit(v[i]) Then
+								Exit
+							End If
+							If leading0 And v[i] = Asc("0") Then
+								i :+ 1
+								Continue
+							End If
+							leading0 = False
+							buf[b] = v[i]
+							
+							b :+ 1
+							i :+ 1
+						Wend
+						
+						If leading0 Then
+							value = "0"
+						Else
+							value = String.FromBytes(buf, b)
+						End If
+					Else
+						value = "0"
+					End If
 				End If
 			EndIf
 
@@ -470,7 +509,7 @@ Type TConstExpr Extends TExpr
 			Local val:Long = value.ToLong()
 			
 			If val < 0 Then
-				If TByteType(ty) Or TShortType(ty) Or TUIntType(ty) Or TULongType(ty) Or TSizeTType(ty) Then
+				If TByteType(ty) Or TShortType(ty) Or TUIntType(ty) Or TULongType(ty) Or TSizeTType(ty) Or TInt128Type(ty) Or TWParamType(ty) Then
 					Return False
 				End If
 			Else
@@ -480,13 +519,13 @@ Type TConstExpr Extends TExpr
 					End If
 				End If
 
-				If TUIntType(ty) Or (TSizeTType(ty) And WORD_SIZE = 4) Then
+				If TUIntType(ty) Or ((TSizeTType(ty) Or TWParamType(ty)) And WORD_SIZE = 4) Then
 					If val > 4294967296:Long Then
 						Return False
 					End If
 				End If
 				
-				If TULongType(ty) Or (TSizeTType(ty) And WORD_SIZE = 8) Then
+				If TULongType(ty) Or ((TSizeTType(ty) Or TWParamType(ty)) And WORD_SIZE = 8) Then
 					If value.length > 20 Then
 						Return False
 					Else If value.length = 20 Then
@@ -509,13 +548,13 @@ Type TConstExpr Extends TExpr
 				End If
 			End If
 
-			If TIntType(ty) Then
+			If TIntType(ty) Or (TLParamType(ty) And WORD_SIZE = 4) Then
 				If value <> String.FromInt(Int(val)) Then
 					Return False
 				End If
 			End If
 
-			If TLongType(ty) Then
+			If TLongType(ty) Or (TLParamType(ty) And WORD_SIZE = 8) Then
 				If value <> String.FromLong(Long(val)) Then
 					Return False
 				End If
@@ -651,8 +690,15 @@ Type TInvokeExpr Extends TExpr
 		'	exprType=decl.retType
 		'End If
 
-		If ((isArg Or isRhs) And Not invokedWithBraces) And (args = Null Or args.length = 0) Then
-			' nothing to do here, as we are probably a function pointer. i.e. no braces and no 
+		'If ((isArg Or isRhs) And Not invokedWithBraces) And (args = Null Or args.length = 0) Then
+
+		' if the call was a statement (even one written without parentheses), then invokedWithBraces is true
+		' so no complicated checks are needed here; if invokedWithBraces is false, this is definitely not a call
+		If Not invokedWithBraces Then
+			' nothing to do here, as we are a function pointer. i.e. no braces
+			' and our expression type is a function ptr...
+			exprType = New TFunctionPtrType.Create(decl)
+			
 		Else
 			args=CastArgs( args,decl )
 		End If
@@ -773,16 +819,21 @@ Type TNewObjectExpr Extends TExpr
 		args=SemantArgs( args )
 
 		Local objTy:TObjectType=TObjectType( ty )
-		If Not objTy
+		Local clsTy:TClassType=TClassType( ty )
+		If Not objTy And Not clsTy
 			Err "Expression is not a class."
 		EndIf
 		
 		' 
-		If objTy.instance Then
+		If clsTy And clsTy.instance Then
 			instanceExpr = New TSelfExpr.Semant()
 		End If
 
-		classDecl=objTy.classDecl
+		If objTy Then
+			classDecl=objTy.classDecl
+		Else
+			classDecl=clsTy.classDecl
+		End If
 
 		If Not instanceExpr Then
 			If classDecl.IsInterface() Err "Cannot create instance of an interface."
@@ -814,7 +865,11 @@ Type TNewObjectExpr Extends TExpr
 
 		classDecl.attrs:|CLASS_INSTANCED
 
-		exprType=ty
+		If TClassType(ty) Then
+			exprType=New TObjectType.Create(TClassType(ty).classDecl)
+		Else
+			exprType=ty
+		End If
 		
 		If it Then
 			'Local parts:String[] = it.ident.ToLower().Split(".")
@@ -829,10 +884,10 @@ Type TNewObjectExpr Extends TExpr
 
 			Local expr:TExpr = Self
 			Local cdecl:TClassDecl = classDecl
-			Local eType:TType = objTy
+			Local eType:TType = ty
 			
 			Local errorDetails:String
-			
+
 			While i < parts.length
 				Local id:String = parts[i]
 				i :+ 1
@@ -1033,7 +1088,15 @@ Type TSelfExpr Extends TExpr
 		If Not scope Then
 			Err "'Self' can only be used within methods."
 		End If
-		exprType=New TObjectType.Create( scope )
+		
+		Local funcScope:TFuncDecl = _env.FuncScope()
+		If funcScope.IsAnyMethod() Then
+			exprType=New TObjectType.Create( scope )
+			TObjectType(exprType).instance = True
+		Else
+			exprType=New TClassType.Create( scope )
+		End If
+
 		Return Self
 	End Method
 
@@ -1119,12 +1182,16 @@ Type TCastExpr Extends TExpr
 					op="ToFloat"
 				Else If TStringType( ty )
 					op="ToString"
-				Else If IsPointerType( ty, TType.T_BYTE )
+				Else If IsPointerType(ty, 0, TType.T_POINTER)
 					exprType = ty
 					If flags = CAST_EXPLICIT Then
 						Return Self
 					Else
-						Return expr
+						If Not TObjectType( src ).classDecl.IsExtern() Then
+							Return Self
+						Else
+							Return expr
+						End If
 					End If
 				Else
 					InternalErr
@@ -1143,6 +1210,22 @@ Type TCastExpr Extends TExpr
 			End If
 			
 			If TNumericType(src) And (TNumericType(ty) Or TStringType(ty)) Then
+				' intrinsics can only cast between selves
+				If (TIntrinsicType(src) And TIntrinsicType(ty)=Null) Or (TIntrinsicType(ty) And TIntrinsicType(src)=Null) Then
+					If TFloat64Type(src) Or TFloat64Type(ty) Then
+						If (TFloat64Type(src) And (TLongType(ty) Or TULongType(ty))) Or (TFloat64Type(ty) And (TLongType(src) Or TULongType(src))) Then
+							' ok
+						Else
+							Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
+						End If
+					Else
+						Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
+					End If
+				Else If TIntrinsicType(src) And TIntrinsicType(ty) Then
+					If (TFloat64Type(src) And TFloat64Type(ty)=Null) Or (TFloat64Type(ty) And TFloat64Type(src)=Null) Then
+						Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
+					End If
+				End If
 				exprType = ty
 			End If
 			
@@ -1154,13 +1237,6 @@ Type TCastExpr Extends TExpr
 			If TFunctionPtrType(src) And IsPointerType(ty, 0, TType.T_POINTER) Then
 				exprType = ty
 			End If
-			
-			If TArrayType(ty) And TArrayType(src) Then
-				If TArrayType(ty).dims = TArrayType(src).dims Then
-					exprType = ty
-					Return Self
-				End If
-			End If
 
 		Else If TBoolType( ty )
 
@@ -1197,6 +1273,40 @@ Type TCastExpr Extends TExpr
 
 		EndIf
 
+
+		If TArrayType(ty) And TArrayType(src) Then
+			If TArrayType(ty).dims = TArrayType(src).dims Then
+				If TArrayExpr(expr) Then
+					Local last:TType
+					For Local e:TExpr = EachIn TArrayExpr(expr).exprs
+						If TNullType(e.exprType) Then
+							Err "Auto array element has no type"
+						End If
+
+						If TObjectType(TArrayType(ty).elemType) And TObjectType(TArrayType(ty).elemType).classDecl.ident = "Object" And (TStringType(e.exprType) Or TObjectType(e.exprType) Or TArrayType(e.exprType)) Then
+							' array takes generic objects, so we don't care if source elements are the same kinds.
+						Else
+							If last <> Null And Not last.EqualsType(e.exprType) Then
+								Err "Auto array elements must have identical types"
+							End If
+							If Not TArrayType(ty).elemType.EqualsType(e.exprType) Then
+								If (TObjectType(TArrayType(ty).elemType) = Null And TStringType(TArrayType(ty).elemType) = Null) Or (TObjectType(e.exprType) = Null And TStringType(e.exprType) = Null) Then
+									Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
+								Else If TStringType(e.exprType) = Null And Not TObjectType(e.exprType).ExtendsType(TObjectType(TArrayType(ty).elemType)) Then
+									Err "Unable to convert from "+src.ToString()+" to "+ty.ToString()+"."
+								End If
+							End If
+						End If
+						
+						last = e.exprType
+					Next
+				End If
+				
+				exprType = ty
+				Return Self
+			End If
+		End If
+
 		'If TStringType(src) And TStringVarPtrType(ty) Then
 		'	exprType = ty
 		'	Return Self
@@ -1212,17 +1322,19 @@ Type TCastExpr Extends TExpr
 			If Not TInvokeExpr(expr).invokedWithBraces Then
 				src = New TFunctionPtrType
 				TFunctionPtrType(src).func = TInvokeExpr(expr).decl
-			
+
 				' signatures should match
-				If TFunctionPtrType(ty).func.EqualsFunc(TInvokeExpr(expr).decl) Then
+				If TInvokeExpr(expr).decl.equalsFunc(TFunctionPtrType(ty).func)  Then
 					exprType = ty
 					Return expr
 				End If
 			Else
 				' return type should be function ptr?
-				' TODO
-				exprType = ty
-				Return expr
+				Local retType:TType = expr.exprType
+				If TFunctionPtrType(retType) And TFunctionPtrType(ty).func.EqualsFunc(TFunctionPtrType(retType).func) Then
+					exprType = retType
+					Return expr
+				End If
 			End If
 		End If
 
@@ -1306,6 +1418,15 @@ Type TCastExpr Extends TExpr
 			Else If TNumericType(src) And (src._flags & TType.T_VARPTR) Then
 				exprType = expr.exprType
 			Else If TArrayType(src) Then
+			
+				' for functions and index access, use a new local variable
+				If Not TVarExpr(expr) And Not TMemberVarExpr(expr) Then
+					Local tmp:TLocalDecl=New TLocalDecl.Create( "", expr.exprType, expr,, True )
+					tmp.Semant()
+					Local v:TVarExpr = New TVarExpr.Create( tmp )
+					expr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), v ).Semant()
+				End If
+			
 				If TNumericType(TArrayType(src).elemType) Then
 					exprType = TNumericType(TArrayType(src).elemType).ToPointer()
 					Return Self
@@ -1367,11 +1488,11 @@ Type TCastExpr Extends TExpr
 		Local val$=expr.Eval()
 		If Not val Return val
 		If TBoolType( exprType )
-			If TIntType( expr.exprType )
-				If Int( val ) Return "1"
+			If TIntegralType(expr.exprType)
+				If Long( val ) Return "1"
 				Return ""
-			Else If TFloatType( expr.exprType )
-				If Float( val ) Return "1"
+			Else If TDecimalType( expr.exprType )
+				If Double( val ) Return "1"
 				Return ""
 			Else If TStringType( expr.exprType )
 				If val.Length Return "1"
@@ -1397,10 +1518,22 @@ Type TCastExpr Extends TExpr
 			Return Long( val )
 		Else If TSizeTType( exprType )
 			Return Long( val )
+		Else If TInt128Type( exprType )
+			Return Long( val )
+		Else If TFloat128Type( exprType )
+			Return Float( val )
+		Else If TDouble128Type( exprType )
+			Return Float( val )
+		Else If TFloat64Type( exprType )
+			Return Float( val )
 		Else If TStringType( exprType )
 			Return String( val )
 		Else If TByteType( exprType )
 			Return Byte( val )
+		Else If TWParamType( exprType )
+			Return Long( val )
+		Else If TLParamType( exprType )
+			Return Long( val )
 		Else If TObjectType( exprType )
 			If TStringType( expr.exprType )
 				Return val
@@ -1520,11 +1653,39 @@ Type TBinaryMathExpr Extends TBinaryExpr
 		If exprType Return Self
 
 		lhs=lhs.Semant()
+
+		If TIdentExpr(rhs) Then
+			TIdentExpr(rhs).isRhs = True
+		End If
+
 		rhs=rhs.Semant()
+		
+		' operator overload?
+		If TObjectType(lhs.exprType) Then
+			Local args:TExpr[] = [rhs]
+			Try
+				Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
+				If decl Then
+					Return New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+				End If
+			Catch error:String
+				If error.StartsWith("Compile Error") Then
+					Throw error
+				Else
+					Err "Operator " + op + " cannot be used with Objects."
+				End If
+			End Try
+		End If
 
 		Select op
 		Case "&","~~","|","shl","shr"
-			If TDoubleType(lhs.exprType) Then
+			If TFloat128Type(lhs.exprType) Then
+				exprType=New TInt128Type
+			Else If TDouble128Type(lhs.exprType) Then
+				exprType=New TInt128Type
+			Else If TFloat64Type(lhs.exprType) Then
+				exprType=New TInt128Type
+			Else If TDoubleType(lhs.exprType) Then
 				exprType=New TLongType
 			Else If TFloatType(lhs.exprType) Then
 				exprType=New TIntType
@@ -1536,6 +1697,10 @@ Type TBinaryMathExpr Extends TBinaryExpr
 				exprType=New TULongType
 			Else If TSizeTType(lhs.exprType) Then
 				exprType=New TSizeTType
+			Else If TWParamType(lhs.exprType) Then
+				exprType=New TWParamType
+			Else If TLParamType(lhs.exprType) Then
+				exprType=New TLParamType
 			Else
 				exprType=New TIntType
 			End If
@@ -1597,7 +1762,7 @@ Type TBinaryMathExpr Extends TBinaryExpr
 			Case "~~" Return x ~ y
 			Case "|" Return x | y
 			End Select
-		Else If TLongType( exprType ) Or TSizeTType(exprType) Or TUIntType(exprType) Or TULongType(exprType)
+		Else If TLongType( exprType ) Or TSizeTType(exprType) Or TUIntType(exprType) Or TULongType(exprType) Or TInt128Type(exprType) Or TWParamType(exprType) Or TLParamType(exprType) 
 			Local x:Long=Long(lhs),y:Long=Long(rhs)
 			Select op
 			Case "^" Return x^y
@@ -1622,7 +1787,7 @@ Type TBinaryMathExpr Extends TBinaryExpr
 			Case "+" Return x + y
 			Case "-" Return x - y
 			End Select
-		Else If TDoubleType( exprType )
+		Else If TDoubleType( exprType ) Or TFloat128Type(exprType) Or TDouble128Type(exprType) Or TFloat64Type(exprType)
 			Local x:Double=Double(lhs),y:Double=Double(rhs)
 			Select op
 			Case "^" Return x^y
@@ -1666,6 +1831,20 @@ Type TBinaryCompareExpr Extends TBinaryExpr
 		lhs=lhs.Semant()
 		rhs=rhs.Semant()
 
+		' operator overload?
+		If TObjectType(lhs.exprType) Then
+			Local args:TExpr[] = [rhs]
+			Try
+				Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
+				If decl Then
+					Return New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+				End If
+			Catch error:String
+				' no overload, continue...
+			End Try
+		End If
+
+
 		ty=BalanceTypes( lhs.exprType,rhs.exprType )
 
 		lhs=lhs.Cast( ty )
@@ -1698,7 +1877,7 @@ Type TBinaryCompareExpr Extends TBinaryExpr
 			Case ">"  r=(lhs> rhs)
 			Case ">=", "=>" r=(lhs>=rhs)
 			End Select
-		Else If TLongType( ty ) Or TSizeTType( ty ) Or TUIntType( ty ) Or TULongType( ty )
+		Else If TLongType( ty ) Or TSizeTType( ty ) Or TUIntType( ty ) Or TULongType( ty ) Or TInt128Type(ty) Or TWParamType(ty) Or TLParamType(ty)
 			Local lhs:Long=Long( Self.lhs.Eval() )
 			Local rhs:Long=Long( Self.rhs.Eval() )
 			Select op
@@ -1720,7 +1899,7 @@ Type TBinaryCompareExpr Extends TBinaryExpr
 			Case ">"  r=(lhs> rhs)
 			Case ">=", "=>" r=(lhs>=rhs)
 			End Select
-		Else If TDoubleType( ty )
+		Else If TDoubleType( ty ) Or TFloat128Type(ty) Or TDouble128Type(ty) Or TFloat64Type(ty)
 			Local lhs:Double=Double( Self.lhs.Eval() )
 			Local rhs:Double=Double( Self.rhs.Eval() )
 			Select op
@@ -1812,14 +1991,18 @@ Type TIndexExpr Extends TExpr
 
 		' for functions and index access, use a new local variable
 		If Not TVarExpr(expr) And Not TMemberVarExpr(expr) Then
-			Local tmp:TLocalDecl=New TLocalDecl.Create( "", expr.exprType, expr,, True )
+			Local tmp:TLocalDecl=New TLocalDecl.Create( "", TType.MapVarPointerToPointerType(expr.exprType.Copy()), expr,, True )
 			tmp.Semant()
 			Local v:TVarExpr = New TVarExpr.Create( tmp )
 			expr = New TStmtExpr.Create( New TDeclStmt.Create( tmp ), v ).Semant()
 		End If
 
 		For Local i:Int = 0 Until index.length
-			index[i]=index[i].SemantAndCast( New TUIntType, True )
+			If Not(TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)) Then
+				index[i]=index[i].SemantAndCast( New TUIntType, True )
+			Else
+				index[i]=index[i].Semant()
+			End If
 		Next
 
 		If TStringType( expr.exprType )
@@ -1865,6 +2048,8 @@ Type TIndexExpr Extends TExpr
 		Else If TNumericType(expr.exprType) And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
 			exprType=TType.MapPointerToPrim(TNumericType(expr.exprType))
 			'exprType=TType.intType
+		Else If TObjectType(expr.exprType) And TObjectType(expr.exprType).classDecl.IsStruct() And IsPointerType( expr.exprType, 0 , TType.T_POINTER | TType.T_VARPTR)' And Not TFunctionPtrType( expr.exprType )
+			exprType = expr.exprType
 		Else
 			Err "Only strings, arrays and pointers may be indexed."
 		EndIf
@@ -1958,6 +2143,8 @@ End Type
 
 Type TArrayExpr Extends TExpr
 	Field exprs:TExpr[]
+	
+	Field toType:TType
 
 	Method Create:TArrayExpr( exprs:TExpr[] )
 		Self.exprs=exprs
@@ -1965,12 +2152,17 @@ Type TArrayExpr Extends TExpr
 	End Method
 
 	Method Copy:TExpr()
-		Return New TArrayExpr.Create( CopyArgs(exprs) )
+		Local expr:TArrayExpr = New TArrayExpr.Create( CopyArgs(exprs) )
+		expr.toType = toType
+		Return expr
 	End Method
 
 	Method Semant:TExpr()
 		If exprType Return Self
 
+		If TIdentExpr(exprs[0]) Then
+			TIdentExpr(exprs[0]).isRhs = True
+		End If
 		exprs[0]=exprs[0].Semant()
 		Local ty:TType=exprs[0].exprType
 		' convert from varptr to ptr if required
@@ -1985,6 +2177,9 @@ Type TArrayExpr Extends TExpr
 			TFunctionPtrType(ty).func = TInvokeExpr(exprs[0]).decl
 
 			For Local i:Int=1 Until exprs.Length
+				If TIdentExpr(exprs[1]) Then
+					TIdentExpr(exprs[1]).isRhs = True
+				End If
 				exprs[i]=exprs[i].Semant()
 				
 				If TInvokeExpr(exprs[i]) And Not TInvokeExpr(exprs[i]).invokedWithBraces
@@ -2006,11 +2201,42 @@ Type TArrayExpr Extends TExpr
 			Next
 		End If
 
+		Local comp:Int = True
+		Local last:TType
 		For Local i:Int=0 Until exprs.Length
-			exprs[i]=exprs[i].Cast( ty )
+
+			Local expr:TExpr = exprs[i]
+
+			' don't cast null types
+			If TNullType(expr.exprType) <> Null Then
+				Err "Auto array element has no type"
+			End If
+
+			Local ety:TType = expr.exprType
+			If TBoolType(ety) Then
+				ety = New TIntType
+			End If
+			
+			If last <> Null And Not last.EqualsType(ety) Then
+				If (Not TConstExpr(expr) And Not IsNumericType(ety)) Or (TConstExpr(expr) And IsNumericType(ety) And Not TConstExpr(expr).CompatibleWithType(ty)) Then
+					Err "Auto array elements must have identical types : Index " + i
+				End If
+			End If
+			
+			If toType And TConstExpr(expr) And Not TConstExpr(expr).CompatibleWithType(toType) Then
+				comp = False
+			End If
+		
+			last = ety
+			
+			exprs[i]=expr.Cast( ty )
 		Next
 
-		exprType=New TArrayType.Create( ty )
+		If comp And toType Then
+			exprType=New TArrayType.Create( toType )
+		Else
+			exprType=New TArrayType.Create( ty )
+		End If
 		Return Self
 	End Method
 
@@ -2578,6 +2804,12 @@ Type TAbsExpr Extends TBuiltinExpr
 		expr=expr.Semant()
 
 		If TNumericType(expr.exprType) Or TBoolType(expr.exprType) Then
+
+			If TInt128Type(expr.exprType) Err "'Abs' does not support Int128 type. Use specific intrinsic function instead."
+			If TFloat64Type(expr.exprType) Err "'Abs' does not support Float64 type. Use specific intrinsic function instead."
+			If TFloat128Type(expr.exprType) Err "'Abs' does not support Float128 type. Use specific intrinsic function instead."
+			If TDouble128Type(expr.exprType) Err "'Abs' does not support Double128 type. Use specific intrinsic function instead."
+
 			If TIntType(expr.exprType) Or TByteType(expr.exprType) Or TShortType(expr.exprType) Then
 				exprType=New TIntType
 			Else
@@ -2665,6 +2897,11 @@ Type TSgnExpr Extends TBuiltinExpr
 		If Not TNumericType(expr.exprType) Then
 			Err "Subexpression for 'Sgn' must be of numeric type"
 		End If
+
+		If TInt128Type(expr.exprType) Err "'Sgn' does not support Int128 type. Use specific intrinsic function instead."
+		If TFloat64Type(expr.exprType) Err "'Sgn' does not support Float64 type. Use specific intrinsic function instead."
+		If TFloat128Type(expr.exprType) Err "'Sgn' does not support Float128 type. Use specific intrinsic function instead."
+		If TDouble128Type(expr.exprType) Err "'Sgn' does not support Double128 type. Use specific intrinsic function instead."
 		
 		exprType=expr.exprType
 		Return Self
@@ -2696,6 +2933,11 @@ Type TMinExpr Extends TBuiltinExpr
 
 		expr=expr.Semant()
 		expr2=expr2.Semant()
+		
+		If TInt128Type(expr.exprType) Or TInt128Type(expr2.exprType) Err "'Min' does not support Int128 type. Use specific intrinsic function instead."
+		If TFloat64Type(expr.exprType) Or TFloat64Type(expr2.exprType) Err "'Min' does not support Float64 type. Use specific intrinsic function instead."
+		If TFloat128Type(expr.exprType) Or TFloat128Type(expr2.exprType) Err "'Min' does not support Float128 type. Use specific intrinsic function instead."
+		If TDouble128Type(expr.exprType) Or TDouble128Type(expr2.exprType) Err "'Min' does not support Double128 type. Use specific intrinsic function instead."
 
 		exprType=BalanceTypes(expr.exprType, expr2.exprType)
 		Return Self
@@ -2728,6 +2970,11 @@ Type TMaxExpr Extends TBuiltinExpr
 		expr=expr.Semant()
 		expr2=expr2.Semant()
 
+		If TInt128Type(expr.exprType) Or TInt128Type(expr2.exprType) Err "'Max' does not support Int128 type. Use specific intrinsic function instead."
+		If TFloat64Type(expr.exprType) Or TFloat64Type(expr2.exprType) Err "'Max' does not support Float64 type. Use specific intrinsic function instead."
+		If TFloat128Type(expr.exprType) Or TFloat128Type(expr2.exprType) Err "'Max' does not support Float128 type. Use specific intrinsic function instead."
+		If TDouble128Type(expr.exprType) Or TDouble128Type(expr2.exprType) Err "'Max' does not support Double128 type. Use specific intrinsic function instead."
+
 		exprType=BalanceTypes(expr.exprType, expr2.exprType)
 		Return Self
 	End Method
@@ -2838,6 +3085,21 @@ Type TFuncCallExpr Extends TExpr
 		End If
 	End Method
 
+	Method SemantFunc:TExpr( args:TExpr[] , throwError:Int = True, funcCall:Int = False )
+		' we are only likely to be called if a function returns and invokes a function pointer.
+
+		Local ex:TExpr = Semant()
+		
+		If TFunctionPtrType(ex.exprType) Then
+			exprType = TFunctionPtrType(ex.exprType).func.retType
+		End If
+		
+		Self.args = SemantArgs(args)
+		expr = ex
+		
+		Return Self
+	End Method
+
 	Method Trans$()
 		Return _trans.TransFuncCallExpr( Self )
 	End Method

+ 206 - 33
iparser.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 ' 
@@ -93,7 +93,11 @@ Type TIParser
 			
 			' import Object and String definitions
 			Local par:TIParser = New TIParser
-			par.ParseModuleImport(_mod, "brl.classes", modulepath("brl.blitz"), modulepath("brl.blitz") + "\blitz_classes.i")
+			If FileType(modulepath("brl.blitz") + "\blitz_classes." + opt_platform + ".i") Then
+				par.ParseModuleImport(_mod, "brl.classes", modulepath("brl.blitz"), modulepath("brl.blitz") + "\blitz_classes." + opt_platform + ".i")
+			Else
+				par.ParseModuleImport(_mod, "brl.classes", modulepath("brl.blitz"), modulepath("brl.blitz") + "\blitz_classes.i")
+			End If
 	
 			' set up built-in keywords
 			par = New TIParser
@@ -266,6 +270,9 @@ Type TIParser
 						Else If CParse("A")
 							class.attrs :| DECL_ABSTRACT
 
+						Else If CParse("S")
+							class.attrs :| CLASS_STRUCT
+
 						Else If CParse("AF")
 							class.attrs :| DECL_ABSTRACT | DECL_FINAL
 
@@ -274,8 +281,8 @@ Type TIParser
 							ApplyFunctionAttributes(class, DECL_EXTERN)
 
 						Else If CParse("EW")
-							class.attrs :| DECL_EXTERN | DECL_API_WIN32 
-							ApplyFunctionAttributes(class, DECL_EXTERN | DECL_API_WIN32)
+							class.attrs :| DECL_EXTERN | DECL_API_STDCALL
+							ApplyFunctionAttributes(class, DECL_EXTERN | DECL_API_STDCALL)
 						
 						Else If CParse("AI")
 							class.attrs :| CLASS_INTERFACE | DECL_ABSTRACT
@@ -286,14 +293,14 @@ Type TIParser
 							ApplyFunctionAttributes(class, DECL_EXTERN | DECL_ABSTRACT)
 
 						Else If CParse("EIW")
-							class.attrs :| DECL_EXTERN | CLASS_INTERFACE | DECL_API_WIN32
-							ApplyFunctionAttributes(class, DECL_EXTERN | DECL_ABSTRACT | DECL_API_WIN32)
+							class.attrs :| DECL_EXTERN | CLASS_INTERFACE | DECL_API_STDCALL
+							ApplyFunctionAttributes(class, DECL_EXTERN | DECL_ABSTRACT | DECL_API_STDCALL)
 
 						Else If CParse("ES")
 							class.attrs :| DECL_EXTERN | CLASS_STRUCT
 
 						Else If CParse("ESW")
-							class.attrs :| DECL_EXTERN | CLASS_STRUCT | DECL_API_WIN32 
+							class.attrs :| DECL_EXTERN | CLASS_STRUCT | DECL_API_STDCALL
 
 						End If
 'DebugStop
@@ -501,7 +508,7 @@ Type TIParser
 		'If toke Parse toke
 		
 		Local id$=ParseIdent()
-		Local args:TClassDecl[]
+		Local args:String[]
 		Local superTy:TIdentType
 		Local imps:TIdentType[]
 
@@ -722,7 +729,7 @@ Type TIParser
 		Return str
 	End Method
 
-	Method ParseFuncDecl:TFuncDecl( toke$,attrs:Int )
+	Method ParseFuncDecl:TFuncDecl( toke$,attrs:Int, returnType:TType = Null )
 		SetErr
 
 		'If toke Parse toke
@@ -730,31 +737,30 @@ Type TIParser
 		Local id$
 		Local ty:TType
 		Local meth:Int = attrs & FUNC_METHOD
-		
-		If attrs & FUNC_METHOD
-			If _toker._toke.tolower() = "new"
-'DebugStop
-				If attrs & DECL_EXTERN
-					Err "Extern classes cannot have constructors"
+
+		If Not returnType Then		
+			If attrs & FUNC_METHOD
+				If _toker._toke.tolower() = "new"
+					If attrs & DECL_EXTERN
+						Err "Extern classes cannot have constructors"
+					EndIf
+					id=_toker._toke
+					NextToke
+					attrs:|FUNC_CTOR
+					attrs:&~FUNC_METHOD
+					ty=ParseDeclType(attrs, True)
+				Else
+					If _toker._tokeType = TOKE_STRINGLIT Then
+						id = ParseStringLit()
+					Else
+						id=ParseIdent()
+					End If
+					ty=ParseDeclType(attrs, True)
 				EndIf
-				id=_toker._toke
-				NextToke
-				attrs:|FUNC_CTOR
-				attrs:&~FUNC_METHOD
-				ty=ParseDeclType(attrs, True)
 			Else
 				id=ParseIdent()
 				ty=ParseDeclType(attrs, True)
 			EndIf
-		Else
-			id=ParseIdent()
-			ty=ParseDeclType(attrs, True)
-		EndIf
-
-		If attrs & FUNC_METHOD
-'DebugLog "Found Method :  " + id
-		Else
-'DebugLog "Found Function :  " + id
 		End If
 		
 		Local args:TArgDecl[]
@@ -833,18 +839,92 @@ Type TIParser
 			args=args[..nargs]
 		EndIf
 		Parse ")"
+		
+		If returnType Then
+			Return New TFuncDecl.CreateF(Null, returnType, args, 0)
+		End If
 
+		Local fdecl:TFuncDecl
+		' wait.. so everything until now was a function pointer return type, and we still have to process the function declaration...
+		If _toke = "(" Then
+			Local retTy:TType = New TFunctionPtrType
+			TFunctionPtrType(retTy).func = New TFuncDecl.CreateF("",ty,args,attrs )
+			TFunctionPtrType(retTy).func.attrs :| FUNC_PTR
+			fdecl = ParseFuncDecl("", attrs, retTy)
+			ty = retTy
+		End If
+		
 		Repeat		
 			If CParse( "F" )
 				attrs:|DECL_FINAL
 			Else If CParse( "FW" )
-				attrs:|DECL_FINAL | DECL_API_WIN32
+				attrs:|DECL_FINAL | DECL_API_STDCALL
+			Else If CParse( "FP" )
+				attrs:|DECL_FINAL|DECL_PRIVATE
+			Else If CParse( "FPW" )
+				attrs:|DECL_FINAL|DECL_PRIVATE | DECL_API_STDCALL
+			Else If CParse( "FR" )
+				attrs:|DECL_FINAL|DECL_PROTECTED
+			Else If CParse( "FRW" )
+				attrs:|DECL_FINAL|DECL_PROTECTED | DECL_API_STDCALL
 			Else If CParse( "A" )
 				attrs:|DECL_ABSTRACT
 			Else If CParse( "AW" )
-				attrs:|DECL_ABSTRACT | DECL_API_WIN32
+				attrs:|DECL_ABSTRACT | DECL_API_STDCALL
+			Else If CParse( "AP" )
+				attrs:|DECL_ABSTRACT|DECL_PRIVATE
+			Else If CParse( "APW" )
+				attrs:|DECL_ABSTRACT|DECL_PRIVATE | DECL_API_STDCALL
+			Else If CParse( "AR" )
+				attrs:|DECL_ABSTRACT|DECL_PROTECTED
+			Else If CParse( "ARW" )
+				attrs:|DECL_ABSTRACT|DECL_PROTECTED | DECL_API_STDCALL
 			Else If CParse( "W" )
-				attrs:|DECL_API_WIN32
+				attrs:| DECL_API_STDCALL
+			Else If CParse( "O" )
+				attrs:|FUNC_OPERATOR
+			Else If CParse( "OW" )
+				attrs:|FUNC_OPERATOR | DECL_API_STDCALL
+			Else If CParse( "OP" )
+				attrs:|FUNC_OPERATOR|DECL_PRIVATE
+			Else If CParse( "OPW" )
+				attrs:|FUNC_OPERATOR|DECL_PRIVATE | DECL_API_STDCALL
+			Else If CParse( "OR" )
+				attrs:|FUNC_OPERATOR|DECL_PROTECTED
+			Else If CParse( "ORW" )
+				attrs:|FUNC_OPERATOR|DECL_PROTECTED | DECL_API_STDCALL
+			Else If CParse( "P" )
+				attrs:|DECL_PRIVATE
+			Else If CParse( "PW" )
+				attrs:|DECL_PRIVATE | DECL_API_STDCALL
+			Else If CParse( "R" )
+				attrs:|DECL_PROTECTED
+			Else If CParse( "RW" )
+				attrs:|DECL_PROTECTED | DECL_API_STDCALL
+			Else If CParse( "FO" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR
+			Else If CParse( "FOW" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR | DECL_API_STDCALL
+			Else If CParse( "FOP" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR|DECL_PRIVATE
+			Else If CParse( "FOPW" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR|DECL_PRIVATE | DECL_API_STDCALL
+			Else If CParse( "FOR" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR|DECL_PROTECTED
+			Else If CParse( "FORW" )
+				attrs:|DECL_FINAL|FUNC_OPERATOR|DECL_PROTECTED | DECL_API_STDCALL
+			Else If CParse( "AO" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR
+			Else If CParse( "AOW" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR | DECL_API_STDCALL
+			Else If CParse( "AOP" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR|DECL_PRIVATE
+			Else If CParse( "AOPW" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR|DECL_PRIVATE | DECL_API_STDCALL
+			Else If CParse( "AOR" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR|DECL_PROTECTED
+			Else If CParse( "AORW" )
+				attrs:|DECL_ABSTRACT|FUNC_OPERATOR|DECL_PROTECTED | DECL_API_STDCALL
 			'Else If CParse( "property" )
 			'	If attrs & FUNC_METHOD
 			'		attrs:|FUNC_PROPERTY
@@ -860,7 +940,12 @@ Type TIParser
 		If attrs & FUNC_CTOR Then
 			funcDecl = New TNewDecl.CreateF( id,ty,args,attrs )
 		Else
-			funcDecl = New TFuncDecl.CreateF( id,ty,args,attrs )
+			If fdecl Then
+				funcDecl = fdecl
+				funcDecl.ident = id
+			Else
+				funcDecl = New TFuncDecl.CreateF( id,ty,args,attrs )
+			End If
 		End If
 		
 		funcDecl.retType = ty
@@ -897,6 +982,11 @@ Type TIParser
 		If CParse(":") Then
 			' ret type
 			Local rt$=_toker._toke
+
+			If CParse("unsigned") Then
+				rt :+ " " + _toker._toke
+			End If
+
 			NextToke
 			If CParse("*") Then
 				rt:+ "*"
@@ -1029,6 +1119,15 @@ Type TIParser
 					Wend
 
 				End If
+				
+				If CParse("`") Then
+					If CParse("`") Then
+						attrs :| DECL_PROTECTED
+					Else
+						attrs :| DECL_PRIVATE
+					End If
+				End If
+				
 
 Rem
 			If CParse( "=" )
@@ -1192,6 +1291,12 @@ End Rem
 				ty = New TLongType
 			ElseIf CParse("z") Then
 				ty = New TSizetType
+			ElseIf CParse("j") Then
+				ty = New TInt128Type
+			ElseIf CParse("w") Then
+				ty = New TWParamType
+			ElseIf CParse("x") Then
+				ty = New TLParamType
 			End If
 			
 			If CParse("&") And Not (attrs & DECL_FIELD) Then
@@ -1253,6 +1358,14 @@ End Rem
 		Case "!"
 			NextToke
 			ty=New TDoubleType
+			
+			If CParse("k") Then
+				ty = New TFloat128Type
+			Else If CParse("m") Then
+				ty = New TDouble128Type
+			Else If CParse("h") Then
+				ty = New TFloat64Type
+			End If
 
 			If CParse("&")  And Not (attrs & DECL_FIELD) Then
 				attrs :| DECL_GLOBAL
@@ -1460,6 +1573,66 @@ End Rem
 			Wend
 			Return ty
 		End If
+		If CParse( "int128" )
+			Local ty:TType = New TInt128Type
+			While CParse("ptr")
+				ty = TType.MapToPointerType(ty)
+			Wend
+			While CParse( "*" )
+				ty = TType.MapToPointerType(ty)
+			Wend
+			Return ty
+		End If
+		If CParse( "float64" )
+			Local ty:TType = New TFloat64Type
+			While CParse("ptr")
+				ty = TType.MapToPointerType(ty)
+			Wend
+			While CParse( "*" )
+				ty = TType.MapToPointerType(ty)
+			Wend
+			Return ty
+		End If
+		If CParse( "float128" )
+			Local ty:TType = New TFloat128Type
+			While CParse("ptr")
+				ty = TType.MapToPointerType(ty)
+			Wend
+			While CParse( "*" )
+				ty = TType.MapToPointerType(ty)
+			Wend
+			Return ty
+		End If
+		If CParse( "double128" )
+			Local ty:TType = New TDouble128Type
+			While CParse("ptr")
+				ty = TType.MapToPointerType(ty)
+			Wend
+			While CParse( "*" )
+				ty = TType.MapToPointerType(ty)
+			Wend
+			Return ty
+		End If
+		If CParse( "wparam" )
+			Local ty:TType = New TWParamType
+			While CParse("ptr")
+				ty = TType.MapToPointerType(ty)
+			Wend
+			While CParse( "*" )
+				ty = TType.MapToPointerType(ty)
+			Wend
+			Return ty
+		End If
+		If CParse( "lparam" )
+			Local ty:TType = New TLParamType
+			While CParse("ptr")
+				ty = TType.MapToPointerType(ty)
+			Wend
+			While CParse( "*" )
+				ty = TType.MapToPointerType(ty)
+			Wend
+			Return ty
+		End If
 		Return ParseIdentType()
 	End Method
 	

+ 7 - 2
options.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -25,7 +25,7 @@ SuperStrict
 
 Import "base.configmap.bmx"
 
-Const version:String = "0.77"
+Const version:String = "0.88"
 
 Const BUILDTYPE_APP:Int = 0
 Const BUILDTYPE_MODULE:Int = 1
@@ -101,6 +101,9 @@ Global opt_strictupgrade:Int = True
 '    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
+' musl libc support
+'    
+Global opt_musl:Int = False
 
 Global opt_filepath:String
 
@@ -194,6 +197,8 @@ Function ParseArgs:String[](args:String[])
 				opt_gdbdebug=True
 			Case "w"
 				opt_warnover=True
+			Case "musl"
+				opt_musl=True
 		End Select
 	
 		count:+ 1

文件差异内容过多而无法显示
+ 440 - 266
parser.bmx


+ 55 - 6
stmt.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -124,22 +124,49 @@ Type TAssignStmt Extends TStmt
 						rhs=rhs.Cast( lhs.exprType )
 						splitOp = False
 						
-					Case "*=","/=","+=","-="
+					Case ":*",":/",":+",":-"
 					
 						If TNumericType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ) Then
 							splitOp = False
 						End If
+						
+						If TObjectType(lhs.exprType) Then
+							Local args:TExpr[] = [rhs]
+							Try
+								Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,True,SCOPE_CLASS_HEIRARCHY))
+								If decl Then
+									lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+									rhs = Null
+									Return
+								End If
+							Catch error:String
+								Err "Operator " + op + " cannot be used with Objects."
+							End Try
+						End If
 					
-					Case "&=","|=","^=","<<=",">>=","%="
+					Case ":&",":|",":^",":shl",":shr",":mod"
 					
-						If TIntType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ) Then
+						If (TIntType( lhs.exprType ) And lhs.exprType.EqualsType( rhs.exprType ))  Or TObjectType(lhs.exprType) Then
 							splitOp = False
 						End If
-				
+
+						If TObjectType(lhs.exprType) Then
+							Local args:TExpr[] = [rhs]
+							Try
+								Local decl:TFuncDecl = TFuncDecl(TObjectType(lhs.exprType).classDecl.FindFuncDecl(op, args,,,,,SCOPE_CLASS_HEIRARCHY))
+								If decl Then
+									lhs = New TInvokeMemberExpr.Create( lhs, decl, args ).Semant()
+									rhs = Null
+									Return
+								End If
+							Catch error:String
+								Err "Operator " + op + " cannot be used with Objects."
+							End Try
+						End If
 				End Select
 				
 				If splitOp Then
-					rhs = New TBinaryMathExpr.Create(op[..op.length - 1], lhs, rhs).Semant().Cast(lhs.exprType)
+					rhs = New TBinaryMathExpr.Create(op[1..], lhs, rhs).Semant().Cast(lhs.exprType)
 					op = "="
 				End If
 				
@@ -192,6 +219,9 @@ Type TReturnStmt Extends TStmt
 	Method OnSemant()
 		Local fdecl:TFuncDecl=_env.FuncScope()
 		If expr
+			If TIdentExpr(expr) Then
+				TIdentExpr(expr).isRhs = True
+			End If
 			If fdecl.IsCtor() Err "Constructors may not return a value."
 			If TVoidType( fdecl.retType ) Then
 				Local errorText:String = "Function can not return a value."
@@ -688,3 +718,22 @@ Type TRestoreDataStmt Extends TStmt
 	
 End Type
 
+Type TNativeStmt Extends TStmt
+	Field raw:String
+	
+	Method Create:TNativeStmt( raw:String )
+		Self.raw = raw
+		Return Self
+	End Method
+
+	Method OnCopy:TStmt( scope:TScopeDecl )
+		Return New TNativeStmt.Create( raw )
+	End Method
+		
+	Method OnSemant()
+	End Method
+
+	Method Trans$()
+		Return _trans.TransNativeStmt( Self )
+	End Method
+End Type

+ 1 - 1
stringbuffer_common.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2016 Bruce A Henderson
+' Copyright (c) 2016-2017 Bruce A Henderson
 ' 
 ' Permission is hereby granted, free of charge, to any person obtaining a copy
 ' of this software and associated documentation files (the "Software"), to deal

+ 1 - 1
stringbuffer_core.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2016 Bruce A Henderson
+' Copyright (c) 2016-2017 Bruce A Henderson
 ' 
 ' Permission is hereby granted, free of charge, to any person obtaining a copy
 ' of this software and associated documentation files (the "Software"), to deal

+ 1 - 1
stringbuffer_glue.c

@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2016 Bruce A Henderson
+  Copyright (c) 2016-2017 Bruce A Henderson
  
   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal

+ 17 - 0
tests/framework/language/function_02.bmx

@@ -0,0 +1,17 @@
+'Test for nested functions
+'Source: https://github.com/bmx-ng/bcc/issues/255
+'Author: HurryStarfish
+SuperStrict
+Framework BRL.StandardIO
+
+Type T
+	Function F1()
+		Function G()
+		End Function
+	End Function
+	
+	Function F2()
+		Function G()
+		End Function
+	End Function
+End Type

+ 25 - 0
tests/framework/language/function_03.bmx

@@ -0,0 +1,25 @@
+'Test for nested functions
+'Source: https://github.com/bmx-ng/bcc/issues/251
+'Author: HurryStarfish
+SuperStrict
+Framework BRL.Blitz
+
+Function F()
+	G
+	Function G()
+		F
+	End Function
+End Function
+
+
+
+Function F2()
+	G2
+	Function G2()
+		H2
+	End Function
+End Function
+
+Function H2()
+	F2
+End Function

+ 22 - 0
tests/framework/language/inheritance_03.extend.overridereturn.bmx

@@ -0,0 +1,22 @@
+SuperStrict
+Framework Brl.StandardIO
+
+Type TBase
+	Field child:TBase
+
+	Method MyChildren:TBase[](param:Int, param2:String)
+		Return [child]
+	End Method
+End Type
+	
+
+Type TExtend Extends TBase
+	Method MyChildren:TExtend[](param:Int, param2:String)
+		Local children:TBase[] = Super.MyChildren(param, param2)
+		Local result:TExtend[]
+		For Local e:TExtend = EachIn children
+			result :+ [e]
+		Next
+		Return result
+	End Method
+End Type

+ 11 - 0
tests/framework/language/label_01.bmx

@@ -0,0 +1,11 @@
+'Test for nested functions
+'Source: https://github.com/bmx-ng/bcc/issues/236
+'Author: HurryStarfish
+SuperStrict
+Framework BRL.StandardIO
+
+#Loop
+For Local a:Int = EachIn [1, 2, 3]
+	If a = 2 Then Exit Loop
+	Print a
+Next

+ 4 - 0
tests/framework/language/metadata_01.bmx

@@ -1,6 +1,7 @@
 Rem
 	This test checks:
 	- if you can define "metadata" {meta="bla"}
+	- if you use an "empty" meta tag
 End Rem
 SuperStrict
 Framework BRL.StandardIO
@@ -12,4 +13,7 @@ Type TMyClass {typemetadata="available"}
 
 	Function myfunc:int() {funcmetadata="available"}
 	End Function
+
+	Function emptyfunc:int() {}
+	End Function
 End Type

+ 9 - 0
tests/framework/language/pointer_02.bmx

@@ -0,0 +1,9 @@
+'Test for negative array indices
+'Source: https://github.com/bmx-ng/bcc/issues/248
+'Author: HurryStarfish
+SuperStrict
+Framework BRL.StandardIO
+
+Local a:Int[] = [7,8,9]
+Local p:Int Ptr = Varptr a[1]
+Print p[-1]

+ 1 - 0
tests/framework/language/pointer_02.res

@@ -0,0 +1 @@
+7

+ 85 - 40
toker.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -38,29 +38,19 @@ Const TOKE_STRINGLITEX:Int=7
 Const TOKE_SYMBOL:Int=8
 Const TOKE_LINECOMMENT:Int=9
 Const TOKE_LONGLIT:Int=10
+Const TOKE_NATIVE:Int=11
 
 '***** Tokenizer *****
 Type TToker
 
-	Const _keywords$=";"+ ..
-	"strict;superstrict;"+ ..
-	"public;private;"+ ..
-	"short;int;float;double;long;string;object;ptr;var;varptr;mod;continue;exit;"+ ..
-	"include;import;module;extern;framework;"+ ..
-	"new;self;super;eachin;true;false;null;not;"+ ..
-	"extends;abstract;select;case;default;"+ ..
-	"const;local;global;field;method;function;type;"+ ..
-	"and;or;shl;shr;sar;end;if;then;else;elseif;endif;while;wend;repeat;until;forever;"+ ..
-	"for;to;step;next;return;"+ ..
-	"alias;rem;endrem;throw;assert;try;catch;nodebug;incbin;"+ ..
-	"endselect;endmethod;endfunction;endtype;endextern;endtry;endwhile;pi;release;defdata;readdata;restoredata;" + ..
-	"interface;endinterface;implements;"+ ..
-	"size_t;uint;ulong;struct;endstruct;"
-
-	Global _symbols$[]=[ "..","[]",":*",":/",":+",":-",":|",":&",":~~",":shr",":shl",":sar",":mod" ]
-	Global _symbols_map$[]=[ "..","[]","*=","/=","+=","-=","|=","&=","^=",">>=", "<<=",">>=","%=" ]
-	'Global _symbols$[]=[ "..","[]",":=",":*",":/",":+",":-",":|",":&",":~~" ]
-	'Global _symbols_map$[]=[ "..","[]",":=","*=","/=","+=","-=","|=","&=","~~=" ]
+	Const __keywords$="strict,superstrict,public,private,protected,short,int,float,double,long,string,object,ptr,var,varptr," + ..
+		"mod,continue,exit,include,import,module,extern,framework,new,self,super,eachin,true,false," + ..
+		"null,not,extends,abstract,select,case,default,const,local,global,field,method,function,type," + ..
+		"and,or,shl,shr,sar,end,if,then,else,elseif,endif,while,wend,repeat,until,forever,for,to,step," + ..
+		"next,return,alias,rem,endrem,throw,assert,try,catch,nodebug,incbin,endselect,endmethod," + ..
+		"endfunction,endtype,endextern,endtry,endwhile,pi,release,defdata,readdata,restoredata,interface," + ..
+		"endinterface,implements,size_t,uint,ulong,struct,endstruct,operator"
+	Global _keywords:TMap
 
 	Field _path$
 	Field _line:Int
@@ -83,9 +73,19 @@ Type TToker
 		_tokePos=0
 		_lines = source.split("~n")
 		_preprocess = preprocess
+		If Not _keywords Then
+			initKeywords()
+		End If
 		Return Self
 	End Method
 	
+	Method initKeywords()
+		_keywords = New TMap
+		For Local k:String = EachIn __keywords.Split(",")
+			_keywords.Insert(k, "")
+		Next
+	End Method
+	
 	Method rollback(pos:Int, toketype:Int = -1)
 		_tokePos = pos
 		If toketype >= 0
@@ -147,7 +147,7 @@ Type TToker
 			Wend
 			_toke=_source[start.._tokePos]
 			_tokeLower = _toke.ToLower()
-			If _keywords.Contains( ";"+_tokeLower+";" )
+			If _keywords.Contains( _tokeLower )
 				_tokeType=TOKE_KEYWORD
 
 				If Not _lookingForEndRem And _tokeLower = "rem" Then
@@ -169,10 +169,12 @@ Type TToker
 					_tokePos:+1
 				Wend
 			EndIf
-			If TSTR().ToLower()="e"
+			Local _tstr:String = TSTR()
+			If _tstr="e" Or _tstr="E" Then
 				_tokeType=TOKE_FLOATLIT
 				_tokePos:+1
-				If TSTR()="+" Or TSTR()="-" _tokePos:+1
+				_tstr = TSTR()
+				If _tstr="+" Or _tstr="-" _tokePos:+1
 				While IsDigit( TCHR() )
 					_tokePos:+1
 				Wend
@@ -194,39 +196,59 @@ Type TToker
 			Wend
 		Else If str="~q"
 			_tokeType=TOKE_STRINGLIT
-			While TSTR() And TSTR()<>"~q"
+			Local _tstr:String = TSTR()
+			While _tstr And _tstr<>"~q"
 				' Strings can't cross line boundries
-				If TSTR()="~n" Then
+				If _tstr="~n" Then
 					_tokePos:-1
 					Exit
 				End If
 				_tokePos:+1
+				_tstr = TSTR()
 			Wend
 			If _tokePos<_source.Length _tokePos:+1 Else _tokeType=TOKE_STRINGLITEX
 		Else If str="'"
-			_tokeType=TOKE_LINECOMMENT
-			
-			SkipToEOL()
-
-			' completely ignore line comments
-			If TSTR()="~n" Then
-				start = _tokePos
-				If _tokePos<_source.Length
+			Local _tstr:String = TSTR()
+			If _tstr="!" Then
+		
+				_tokeType=TOKE_NATIVE
+				
+				While _tstr 
+					If _tstr="~n" Then
+						_tokePos:-1
+						Exit
+					End If
 					_tokePos:+1
+					_tstr = TSTR()
+				Wend
+		
+			Else
+				_tokeType=TOKE_LINECOMMENT
+				
+				SkipToEOL()
+	
+				' completely ignore line comments
+				If TSTR()="~n" Then
+					start = _tokePos
+					If _tokePos<_source.Length
+						_tokePos:+1
+					End If
+					_line:+1
+					_tokeType=TOKE_SYMBOL
 				End If
-				_line:+1
-				_tokeType=TOKE_SYMBOL
 			End If
-
 		Else If str="." And TSTR()="." Then
 			Local pos:Int = _tokePos
 			Local isValidTilEOL:Int = True
 			_tokePos:+1
-			While TSTR() And TSTR()<>"~n"
+			
+			Local _tstr:String = TSTR()
+			While _tstr And _tstr<>"~n"
 				If Not IsSpace(TCHR()) Then
 					isValidTilEOL = False
 				End If
 				_tokePos:+1
+				_tstr = TSTR()
 			Wend
 			
 			If Not isValidTilEOL Or _preprocess Then
@@ -239,7 +261,6 @@ Type TToker
 				_line:+1
 				_tokeType=TOKE_SPACE
 			End If
-			
 		Else
 
 			_tokeType=TOKE_SYMBOL
@@ -348,12 +369,36 @@ Type TToker
 'Private
 
 	Method TCHR:Int( i:Int=0 )
-		If _tokePos+i<_source.Length Return _source[_tokePos+i]
+		If _lastIndex <> _tokePos+i Then
+			_lastIndex = _tokePos+i
+			If _lastIndex < _source.Length Then
+				_lastTCHR = _source[_lastIndex]
+				_lastTSTR = Chr( _lastTCHR )
+			Else
+				_lastTCHR = 0
+				_lastTSTR = ""
+			End If
+		End If
+		Return _lastTCHR
 	End Method
 	
+	Field _lastIndex:Int = -1
+	Field _lastTCHR:Int
+	
 	Method TSTR$( i:Int=0 )
-		If _tokePos+i<_source.Length Return Chr( _source[_tokePos+i] )
+		If _lastIndex <> _tokePos+i Then
+			_lastIndex = _tokePos+i
+			If _lastIndex < _source.Length Then
+				_lastTCHR = _source[_lastIndex]
+				_lastTSTR = Chr( _lastTCHR )
+			Else
+				_lastTCHR = 0
+				_lastTSTR = ""
+			End If
+		End If
+		Return _lastTSTR
 	End Method
 	
+	Field _lastTSTR:String
 	
 End Type

+ 1 - 1
transform.c

@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016 Bruce A Henderson
+/* Copyright (c) 2014-2017 Bruce A Henderson
 
   This software is provided 'as-is', without any express or implied
   warranty. In no event will the authors be held liable for any damages

+ 119 - 36
translator.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -58,8 +58,6 @@ Type TTranslator
 	
 	Field processingReturnStatement:Int
 
-	Field _inBinary:Int
-
 	Method PushVarScope()
 		varStack.Push customVarStack
 		customVarStack = New TStack
@@ -191,7 +189,13 @@ Type TTranslator
 		If TLongType( ty ) Return p + "l"
 		If TULongType( ty ) Return p + "y"
 		If TSizeTType( ty ) Return p + "z"
+		If TFloat64Type( ty ) Return p + "h"
+		If TFloat128Type( ty ) Return p + "k"
+		If TInt128Type( ty ) Return p + "j"
+		If TDouble128Type( ty ) Return p + "m"
 		If TStringType( ty ) Return p + "S"
+		If TWParamType( ty ) Return p + "W"
+		If TLParamType( ty ) Return p + "L"
 		If TArrayType( ty ) Then
 			Return p + "a" + TransMangleType(TArrayType( ty ).elemType)
 		End If
@@ -216,10 +220,12 @@ Type TTranslator
 '			Next
 			Return s + "_" + TransMangleType(func.retType) + "_"
 		End If
+		
+		Err "Unsupported type for name mangling : " + ty.ToString()
 	End Method
 
 	Method MangleMethod:String(fdecl:TFuncDecl)
-		If fdecl.IsMethod() Or fdecl.IsCtor() Then
+		If (fdecl.IsMethod() And Not fdecl.ClassScope().IsStruct())Or fdecl.IsCtor() Then
 			Return MangleMethodArgs(fdecl)
 		Else
 			Return MangleMethodRetType(fdecl) + MangleMethodArgs(fdecl)
@@ -306,7 +312,7 @@ Type TTranslator
 		Local funcs:TFuncDeclList=TFuncDeclList(funcMungs.ValueForKey( fdecl.ident ))
 		If funcs
 			For Local tdecl:TFuncDecl=EachIn funcs
-				If fdecl.EqualsArgs( tdecl )
+				If fdecl.EqualsArgs( tdecl ) And fdecl.scope = tdecl.scope
 					fdecl.munged=tdecl.munged
 					Return
 				EndIf
@@ -317,7 +323,13 @@ Type TTranslator
 		EndIf
 
 		If fdecl.scope Then
-			fdecl.munged = fdecl.scope.munged + "_" + fdecl.ident
+			Local id:String = fdecl.ident
+
+			If fdecl.attrs & FUNC_OPERATOR Then
+				id = MungSymbol(id)
+			End If
+			
+			fdecl.munged = fdecl.scope.munged + "_" + id
 			
 			If Not equalsBuiltInFunc(fdecl.classScope(), fdecl) And Not fdecl.noMangle Then
 				fdecl.munged :+ MangleMethod(fdecl)
@@ -335,6 +347,58 @@ Type TTranslator
 		funcs.AddLast fdecl
 	End Method
 	
+	Method MungSymbol:String(sym:String)
+		Select sym
+			Case "*"
+				Return "_mul"
+			Case "/"
+				Return "_div"
+			Case "+"
+				Return "_add"
+			Case "-"
+				Return "_sub"
+			Case "&"
+				Return "_and"
+			Case "|"
+				Return "_or"
+			Case "~~"
+				Return "_xor"
+			Case ":*"
+				Return "_muleq"
+			Case ":/"
+				Return "_diveq"
+			Case ":+"
+				Return "_addeq"
+			Case ":-"
+				Return "_subeq"
+			Case ":&"
+				Return "_andeq"
+			Case ":|"
+				Return "_oreq"
+			Case ":~~"
+				Return "_xoreq"
+			Case "<"
+				Return "_lt"
+			Case "<="
+				Return "_le"
+			Case ">"
+				Return "_gt"
+			Case ">="
+				Return "_ge"
+			Case "="
+				Return "_eq"
+			Case "<>"
+				Return "_ne"
+			Case "mod"
+				Return "_mod"
+			Case "shl"
+				Return "_shl"
+			Case "shr"
+				Return "_shr"
+		End Select
+		Return "?? unknown symbol ?? : " + sym
+	End Method
+	
 	Method MungDecl( decl:TDecl, addIfNotInScope:Int = False )
 
 		If decl.munged Then
@@ -562,6 +626,7 @@ End Rem
 	
 	Method TransBinaryOp$( op$,rhs$ )
 'DebugLog "TransBinaryOp '" + op + "' : '" + rhs + "'"
+op = mapSymbol(op)
 		Select op
 		Case "+","-"
 			If rhs.StartsWith( op ) Return op+" "
@@ -587,11 +652,12 @@ End Rem
 	End Method
 	
 	Method TransAssignOp$( op$ )
+op = mapSymbol(op)
 		Select op
-		Case "mod=" Return "%="
-		Case "shl=" Return "<<="
-		Case "shr=" Return ">>="
-		Case "sar=" Return ">>="
+		Case ":mod" Return "%="
+		Case ":shl" Return "<<="
+		Case ":shr" Return ">>="
+		Case ":sar" Return ">>="
 		End Select
 		Return op
 	End Method
@@ -643,10 +709,10 @@ End Rem
 		Return CreateLocal( expr )
 	End Method
 	
-	Method CreateLocal$( expr:TExpr )
-		Local tmp:TLocalDecl=New TLocalDecl.Create( "",expr.exprType,expr, True )
+	Method CreateLocal$( expr:TExpr, init:Int = True, vol:Int = True )
+		Local tmp:TLocalDecl=New TLocalDecl.Create( "",expr.exprType,expr, True, , vol )
 		MungDecl tmp
-		Emit TransLocalDecl( tmp,expr, True )+";"
+		Emit TransLocalDecl( tmp,expr, True, init )+";"
 
 		EmitGDBDebug(_errInfo)
 		
@@ -655,7 +721,7 @@ End Rem
 
 	'***** Utility *****
 
-	Method TransLocalDecl$( decl:TLocalDecl,init:TExpr, declare:Int = False ) Abstract
+	Method TransLocalDecl$( decl:TLocalDecl,init:TExpr, declare:Int = False, outputInit:Int = True ) Abstract
 
 	Method TransGlobalDecl$( gdecl:TGlobalDecl ) Abstract
 	
@@ -711,7 +777,7 @@ End Rem
 	
 	Method EmitLocalDeclarations(decl:TScopeDecl, v:TValDecl = Null) Abstract
 	
-	Method TransType$( ty:TType, ident:String) Abstract
+	Method TransType$( ty:TType, ident:String, fpReturnTypeFunctionArgs:String = Null, fpReturnTypeClassFunc:Int = False) Abstract
 	
 	Method BeginLocalScope()
 		mungStack.Push mungScope
@@ -811,6 +877,8 @@ End Rem
 		
 		If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),expr.expr )
 
+		If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
+
 		InternalErr
 	End Method
 	
@@ -820,12 +888,16 @@ End Rem
 		If Not decl.munged Then
 			MungDecl decl
 		End If
-
-		If (decl.attrs & FUNC_PTR) And (decl.attrs & FUNC_INIT) And Not expr.InvokedWithBraces Return decl.munged
 		
-		If ((decl.attrs & FUNC_PTR) Or (expr.decl.attrs & FUNC_PTR)) And Not expr.InvokedWithBraces Return decl.munged
+		'If (decl.attrs & FUNC_PTR) And (decl.attrs & FUNC_INIT) And Not expr.InvokedWithBraces Return decl.munged
+		
+		'If ((decl.attrs & FUNC_PTR) Or (expr.decl.attrs & FUNC_PTR)) And Not expr.InvokedWithBraces Return decl.munged
 		
-		If Not expr.InvokedWithBraces And expr.IsRhs And Not expr.args Return decl.munged
+		'If Not expr.InvokedWithBraces And expr.IsRhs Return decl.munged
+		
+		' if the call was a statement (even one written without parentheses), then invokedWithBraces is true
+		' so no complicated checks are needed here; if invokedWithBraces is false, this is definitely not a call
+		If Not expr.InvokedWithBraces Then Return decl.munged
 		
 		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null,expr.args )
 		
@@ -883,6 +955,14 @@ End Rem
 			expr.args=expr.CastArgs( expr.args,TFuncDecl(decl) )
 			Return expr.expr.Trans() + TransArgs(expr.args, TFuncDecl(decl))
 		End If
+
+		' hmmm, complicated - a function returning and invoking a function pointer...		
+		If TInvokeExpr(expr.expr) And TFunctionPtrType(TInvokeExpr(expr.expr).exprType) Then
+			Local decl:TDecl = TFunctionPtrType(TInvokeExpr(expr.expr).exprType).func.actual
+			decl.Semant()
+			expr.args=expr.CastArgs( expr.args,TFuncDecl(decl) )
+			Return expr.expr.Trans() + TransArgs(expr.args, TFuncDecl(decl))
+		End If
 		
 		InternalErr
 	End Method
@@ -915,19 +995,26 @@ End Rem
 
 			Else
 				
-				Local s:String = stmt.expr.Trans()
-				
-				' we have some temp variables that need to be freed before we can return
-				' put the results into a new variable, and return that.
-				If customVarStack.Count() > 0 Then
-					If Not TFunctionPtrType( stmt.expr.exprType ) Then
-						Emit TransType(stmt.expr.exprType, "rt_") + " rt_ = " + s + ";"
+				If TSelfExpr(stmt.expr) And TObjectType(TSelfExpr(stmt.expr).exprType).classDecl And TObjectType(TSelfExpr(stmt.expr).exprType).classDecl.IsStruct() Then
+					t :+ Bra("*" + stmt.expr.Trans())
+				Else If TObjectType(stmt.expr.exprType) And TObjectType(stmt.expr.exprType).classDecl.IsStruct() And TConstExpr(stmt.expr) And Not TConstExpr(stmt.expr).value Then
+					Local lvar:String = CreateLocal(stmt.expr)
+					t :+ " " + lvar
+				Else
+					Local s:String = stmt.expr.Trans()
+					
+					' we have some temp variables that need to be freed before we can return
+					' put the results into a new variable, and return that.
+					If customVarStack.Count() > 0 Then
+						If Not TFunctionPtrType( stmt.expr.exprType ) Then
+							Emit TransType(stmt.expr.exprType, "rt_") + " rt_ = " + s + ";"
+						Else
+							Emit TransType(stmt.expr.exprType, "rt_") + " = " + s + ";"
+						End If
+						t:+ " rt_"
 					Else
-						Emit TransType(stmt.expr.exprType, "rt_") + " = " + s + ";"
+						t:+" " + s
 					End If
-					t:+ " rt_"
-				Else
-					t:+" " + s
 				End If
 			End If
 			
@@ -1341,9 +1428,7 @@ End Rem
 				Emit "}"
 			EndIf
 		Else If stmt.elseBlock.stmts.First()
-			_inBinary :+ 1
 			Emit "if"+Bra( stmt.expr.Trans() )+"{"
-			_inBinary :- 1
 			EmitLocalDeclarations(stmt.thenBlock)
 			FreeVarsIfRequired(False)
 			PushVarScope
@@ -1367,10 +1452,8 @@ End Rem
 '					Emit "if"+Bra( stmt.expr.Trans() )+"{"
 '				End If
 '			Else
-			_inBinary :+ 1
 				Emit "if"+Bra( stmt.expr.Trans() )+"{"
 				FreeVarsIfRequired(False)
-			_inBinary :- 1
 '			End If
 			EmitLocalDeclarations(stmt.thenBlock)
 			PushVarScope
@@ -1412,9 +1495,7 @@ End Rem
 	Method TransWhileStmt$( stmt:TWhileStmt )
 		Local nbroken:Int=broken
 
-		_inBinary :+ 1
 		Emit "while"+Bra( stmt.expr.Trans() )+"{"
-		_inBinary :- 1
 		
 		Local check:TTryBreakCheck = New TTryBreakCheck
 		check.stmt = stmt
@@ -1568,6 +1649,8 @@ End Rem
 	Method TransRestoreDataStmt$( stmt:TRestoreDataStmt ) Abstract
 
 	Method TransReadDataStmt$( stmt:TReadDataStmt ) Abstract
+	
+	Method TransNativeStmt$( stmt:TNativeStmt) Abstract
 
 	'module
 	Method TransApp( app:TAppDecl ) Abstract

+ 646 - 71
type.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2016 Bruce A Henderson
+' Copyright (c) 2013-2017 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -192,18 +192,24 @@ Type TType
 
 	Const T_POINTER:Int = T_PTR | T_PTRPTR | T_PTRPTRPTR
 
-	Const T_BYTE:Int        = $001
-	Const T_SHORT:Int       = $002
-	Const T_INT:Int         = $004
-	Const T_LONG:Int        = $008
-	Const T_FLOAT:Int       = $010
-	Const T_DOUBLE:Int      = $020
-	Const T_STRING:Int      = $040
-	Const T_ARRAY:Int       = $080
-	Const T_FUNCTIONPTR:Int = $100
-	Const T_SIZET:Int       = $200
-	Const T_UINT:Int        = $400
-	Const T_ULONG:Int       = $800
+	Const T_BYTE:Int        =  $001
+	Const T_SHORT:Int       =  $002
+	Const T_INT:Int         =  $004
+	Const T_LONG:Int        =  $008
+	Const T_FLOAT:Int       =  $010
+	Const T_DOUBLE:Int      =  $020
+	Const T_STRING:Int      =  $040
+	Const T_ARRAY:Int       =  $080
+	Const T_FUNCTIONPTR:Int =  $100
+	Const T_SIZET:Int       =  $200
+	Const T_UINT:Int        =  $400
+	Const T_ULONG:Int       =  $800
+	Const T_FLOAT64:Int     = $1000
+	Const T_INT128:Int      = $2000
+	Const T_FLOAT128:Int    = $4000
+	Const T_DOUBLE128:Int   = $8000
+	Const T_LPARAM:Int      =$10000
+	Const T_WPARAM:Int      =$20000
 
 	Const T_MAX_DISTANCE:Int = $FFFF
 
@@ -248,12 +254,22 @@ Function NewType:TType(kind:Int = 0)
 			ty = New TUIntType
 		Case TType.T_LONG
 			ty = New TLongType
+		Case TType.T_ULONG
+			ty = New TULongType
 		Case TType.T_SIZET
 			ty = New TSizeTType
+		Case TType.T_INT128
+			ty = New TInt128Type
 		Case TType.T_FLOAT
 			ty = New TFloatType
 		Case TType.T_DOUBLE
 			ty = New TDoubleType
+		Case TType.T_FLOAT64
+			ty = New TFloat64Type
+		Case TType.T_FLOAT128
+			ty = New TFloat128Type
+		Case TType.T_DOUBLE128
+			ty = New TDouble128Type
 		Case TType.T_STRING
 			ty = New TStringType
 		Case TType.T_ARRAY
@@ -303,12 +319,22 @@ Function IsType:Int(ty:TType, kind:Int)
 			Return TUIntType(ty) <> Null
 		Case TType.T_LONG
 			Return TLongType(ty) <> Null
+		Case TType.T_ULONG
+			Return TULongType(ty) <> Null
 		Case TType.T_SIZET
 			Return TSizeTType(ty) <> Null
+		Case TType.T_INT128
+			Return TInt128Type(ty) <> Null
 		Case TType.T_FLOAT
 			Return TFloatType(ty) <> Null
 		Case TType.T_DOUBLE
 			Return TDoubleType(ty) <> Null
+		Case TType.T_FLOAT64
+			Return TFloat64Type(ty) <> Null
+		Case TType.T_FLOAT128
+			Return TFloat128Type(ty) <> Null
+		Case TType.T_DOUBLE128
+			Return TDouble128Type(ty) <> Null
 		Case TType.T_STRING
 			Return TStringType(ty) <> Null
 		Case TType.T_ARRAY
@@ -397,7 +423,10 @@ Type TNumericType Extends TType
 	
 End Type
 
-Type TIntType Extends TNumericType
+Type TIntegralType Extends TNumericType
+End Type
+
+Type TIntType Extends TIntegralType
 	
 	Method EqualsType:Int( ty:TType )
 		Return TIntType( ty )<>Null And (_flags = ty._flags Or ..
@@ -411,26 +440,38 @@ Type TIntType Extends TNumericType
 		'	Return ctor And ctor.IsCtor()
 		'EndIf
 		If _flags & T_VARPTR And (TIntType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null)
+		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And TStringType( ty )<>Null) Or (WORD_SIZE=4 And TLParamType(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
+		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 Or (WORD_SIZE=8 And TLParamType(ty)<>Null)
 	End Method
 	
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TIntType(ty)<>Null Then
 			Return 0
 		End If
 		
+		If WORD_SIZE = 4 And TLParamType(ty)<>Null Then
+			Return 0
+		End If
+		
 		If TLongType(ty)<>Null Then
 			Return 2
 		End If
 
+		If WORD_SIZE = 8 And TLParamType(ty)<>Null Then
+			Return 2
+		End If
+		
 		If TFloatType(ty)<>Null Then
 			Return 4
 		End If
@@ -456,7 +497,7 @@ Type TIntType Extends TNumericType
 
 End Type
 
-Type TUIntType Extends TNumericType
+Type TUIntType Extends TIntegralType
 	
 	Method EqualsType:Int( ty:TType )
 		Return TUIntType( ty )<>Null And (_flags = ty._flags Or ..
@@ -470,19 +511,23 @@ Type TUIntType Extends TNumericType
 		'	Return ctor And ctor.IsCtor()
 		'EndIf
 		If _flags & T_VARPTR And (TUIntType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And 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 (WORD_SIZE=4 And (TSizeTType(ty)<>Null Or TWParamType(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
+		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 Or (WORD_SIZE=8 And TWParamType(ty)<>Null)
 	End Method
 
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
-		If WORD_SIZE = 4 And TSizeTType(ty)<>Null Then
+		If WORD_SIZE = 4 And (TSizeTType(ty)<>Null Or TWParamType(ty)<>Null) Then
 			Return 0
 		End If
 		
@@ -494,7 +539,7 @@ Type TUIntType Extends TNumericType
 			Return 1
 		End If
 		
-		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+		If WORD_SIZE = 8 And (TSizeTType(ty)<>Null Or TWParamType(ty)<>Null) Then
 			Return 2
 		End If
 		
@@ -531,7 +576,7 @@ Type TUIntType Extends TNumericType
 
 End Type
 
-Type TSizeTType Extends TNumericType
+Type TSizeTType Extends TIntegralType
 	
 	Method EqualsType:Int( ty:TType )
 		Return TSizeTType( ty )<>Null And (_flags = ty._flags Or ..
@@ -545,26 +590,34 @@ Type TSizeTType Extends TNumericType
 		'	Return ctor And ctor.IsCtor()
 		'EndIf
 		If _flags & T_VARPTR And (TSizeTType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
-		Return (widensTest And WidensToType(ty)) Or (Not widensTest And TNumericType( ty )<>Null) Or (Not noExtendString And 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 (WORD_SIZE=4 And TUIntType(ty)<>Null) Or (WORD_SIZE=8 And TULongType(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
+			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 Or TWParamType(ty)<>Null Or TLParamType(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
+			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 Or TFloat64Type(ty)<>Null Or TWParamType(ty)<>Null Or TLParamType(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
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TSizeTType(ty)<>Null Then
 			Return 0
 		End If
 
+		If TWParamType(ty)<>Null Then
+			Return 0
+		End If
+
 		If WORD_SIZE = 4 Then
 			If TUIntType(ty)<>Null Then
 				Return 0
@@ -573,6 +626,10 @@ Type TSizeTType Extends TNumericType
 			If TIntType(ty)<>Null Then
 				Return 2
 			End If
+			
+			If TLParamType(ty)<>Null Then
+				Return 2
+			End If
 
 			If TULongType(ty)<>Null Then
 				Return 3
@@ -599,6 +656,10 @@ Type TSizeTType Extends TNumericType
 				Return 2
 			End If
 
+			If TLParamType(ty)<>Null Then
+				Return 2
+			End If
+
 			If TFloatType(ty)<>Null Then
 				Return 4
 			End If
@@ -606,6 +667,11 @@ Type TSizeTType Extends TNumericType
 			If TDoubleType(ty)<>Null Then
 				Return 6
 			End If
+
+			If TFloat64Type(ty)<>Null Then
+				Return 8
+			End If
+
 		End If
 	
 		Return T_MAX_DISTANCE
@@ -625,7 +691,7 @@ Type TSizeTType Extends TNumericType
 
 End Type
 
-Type TByteType Extends TNumericType
+Type TByteType Extends TIntegralType
 	
 	Method EqualsType:Int( ty:TType )
 		Return TByteType( ty )<>Null And (_flags = ty._flags Or ..
@@ -643,12 +709,16 @@ Type TByteType Extends TNumericType
 	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
+		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 Or TWParamType(ty)<>Null Or TLParamType(ty)<>Null
 	End Method
 
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TByteType(ty)<>Null Then
@@ -659,7 +729,7 @@ Type TByteType Extends TNumericType
 			Return 2
 		End If
 
-		If WORD_SIZE = 4 And TSizeTType(ty)<>Null Then
+		If WORD_SIZE = 4 And (TSizeTType(ty)<>Null Or TWParamType(ty)<>Null) Then
 			Return 4
 		End If
 		
@@ -670,8 +740,12 @@ Type TByteType Extends TNumericType
 		If TIntType(ty)<>Null Then
 			Return 5
 		End If
+
+		If WORD_SIZE = 4 And TLParamType(ty)<>Null Then
+			Return 5
+		End If
 		
-		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+		If WORD_SIZE = 8 And (TSizeTType(ty)<>Null Or TWParamType(ty)<>Null) Then
 			Return 6
 		End If
 		
@@ -683,6 +757,10 @@ Type TByteType Extends TNumericType
 			Return 7
 		End If
 
+		If WORD_SIZE = 8 And TLParamType(ty)<>Null Then
+			Return 7
+		End If
+
 		If TFloatType(ty)<>Null Then
 			Return 8
 		End If
@@ -708,7 +786,7 @@ Type TByteType Extends TNumericType
 
 End Type
 
-Type TShortType Extends TNumericType
+Type TShortType Extends TIntegralType
 
 	Method EqualsType:Int( ty:TType )
 		Return TShortType( ty )<>Null And (_flags = ty._flags Or ..
@@ -726,19 +804,23 @@ Type TShortType Extends TNumericType
 	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
+		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 Or TWParamType(ty)<>Null Or TLParamType(ty)<>Null
 	End Method
 
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TShortType(ty)<>Null Then
 			Return 0
 		End If
 
-		If WORD_SIZE = 4 And TSizeTType(ty)<>Null Then
+		If WORD_SIZE = 4 And (TSizeTType(ty)<>Null Or TWParamType(ty)<>Null) Then
 			Return 2
 		End If
 		
@@ -749,8 +831,12 @@ Type TShortType Extends TNumericType
 		If TIntType(ty)<>Null Then
 			Return 3
 		End If
+
+		If WORD_SIZE = 4 And TLParamType(ty)<>Null Then
+			Return 3
+		End If
 		
-		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+		If WORD_SIZE = 8 And (TSizeTType(ty)<>Null Or TWParamType(ty)<>Null) Then
 			Return 4
 		End If
 
@@ -762,6 +848,10 @@ Type TShortType Extends TNumericType
 			Return 5
 		End If
 
+		If WORD_SIZE = 8 And TLParamType(ty)<>Null Then
+			Return 5
+		End If
+
 		If TFloatType(ty)<>Null Then
 			Return 6
 		End If
@@ -787,7 +877,7 @@ Type TShortType Extends TNumericType
 
 End Type
 
-Type TLongType Extends TNumericType ' BaH Long
+Type TLongType Extends TIntegralType ' BaH Long
 	
 	Method EqualsType:Int( ty:TType )
 		Return TLongType( ty )<>Null And (_flags = ty._flags Or ..
@@ -805,17 +895,25 @@ Type TLongType Extends TNumericType ' BaH Long
 	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
+		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 Or TFloat64Type(ty)<>Null
 	End Method
 
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TLongType(ty)<>Null Then
 			Return 0
 		End If
+		
+		If WORD_SIZE = 8 And TLParamType(ty)<>Null Then
+			Return 0
+		End If
 
 		If TFloatType(ty)<>Null Then
 			Return 2
@@ -824,6 +922,10 @@ Type TLongType Extends TNumericType ' BaH Long
 		If TDoubleType(ty)<>Null Then
 			Return 4
 		End If
+
+		If TFloat64Type(ty)<>Null Then
+			Return 6
+		End If
 		
 		Return T_MAX_DISTANCE
 	End Method
@@ -837,7 +939,7 @@ Type TLongType Extends TNumericType ' BaH Long
 	End Method
 End Type
 
-Type TULongType Extends TNumericType
+Type TULongType Extends TIntegralType
 	
 	Method EqualsType:Int( ty:TType )
 		Return TULongType( ty )<>Null And (_flags = ty._flags Or ..
@@ -855,19 +957,23 @@ Type TULongType Extends TNumericType
 	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
+		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 Or TFloat64Type(ty)<>Null
 	End Method
 
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TULongType(ty)<>Null Then
 			Return 0
 		End If
 
-		If WORD_SIZE = 8 And TSizeTType(ty)<>Null Then
+		If WORD_SIZE = 8 And (TSizeTType(ty)<>Null Or TWParamType(ty)<>Null) Then
 			Return 0
 		End If
 		
@@ -882,7 +988,11 @@ Type TULongType Extends TNumericType
 		If TDoubleType(ty)<>Null Then
 			Return 4
 		End If
-		
+
+		If TFloat64Type(ty)<>Null Then
+			Return 6
+		End If
+
 		Return T_MAX_DISTANCE
 	End Method
 
@@ -920,8 +1030,12 @@ Type TFloatType Extends TDecimalType
 	End Method
 
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TFloatType(ty)<>Null Then
@@ -971,8 +1085,12 @@ Type TDoubleType Extends TDecimalType
 	End Method
 
 	Method DistanceToType:Int(ty:TType)
-		If (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Then
-			Return 0
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
 		End If
 
 		If TDoubleType(ty)<>Null Then
@@ -992,6 +1110,220 @@ Type TDoubleType Extends TDecimalType
 
 End Type
 
+Type TIntrinsicType Extends TNumericType
+End Type
+
+Type TInt128Type Extends TIntrinsicType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TInt128Type( ty )<>Null And (_flags = ty._flags Or ..
+			(_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, 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 (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 (TInt128Type(ty)<>Null And (ty._flags & T_VAR)) Or TFloat128Type(ty)<>Null Or TDouble128Type(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
+		End If
+
+		If TInt128Type(ty)<>Null Then
+			Return 0
+		End If
+
+		If TFloat128Type(ty)<>Null Then
+			Return 2
+		End If
+
+		If TDouble128Type(ty)<>Null Then
+			Return 4
+		End If
+		
+		Return T_MAX_DISTANCE
+	End Method
+	
+	Method OnCopy:TType()
+		Return New TInt128Type
+	End Method
+
+	Method ToString$()
+		Return "Int128" + ToStringParts()
+	End Method
+End Type
+
+Type TFloat64Type Extends TIntrinsicType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TFloat64Type( ty )<>Null And (_flags = ty._flags Or ..
+			(_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, 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 (TFloat64Type(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
+		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 (TFloat64Type(ty)<>Null And (ty._flags & T_VAR))
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
+		End If
+
+		If TFloat64Type(ty)<>Null Then
+			Return 0
+		End If
+		
+		Return T_MAX_DISTANCE
+	End Method
+
+	Method OnCopy:TType()
+		Return New TFloat64Type
+	End Method
+
+	Method ToString$()
+		Return "Float64" + ToStringParts()
+	End Method
+
+End Type
+
+Type TFloat128Type Extends TIntrinsicType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TFloat128Type( ty )<>Null And (_flags = ty._flags Or ..
+			(_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, 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 (TFloat128Type(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
+		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 (TFloat128Type(ty)<>Null And (ty._flags & T_VAR)) Or TInt128Type(ty)<>Null Or TDouble128Type(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
+		End If
+
+		If TFloat128Type(ty)<>Null Then
+			Return 0
+		End If
+
+		If TDouble128Type(ty)<>Null Then
+			Return 2
+		End If
+		
+		If TInt128Type(ty)<>Null Then
+			Return 4
+		End If
+	
+		Return T_MAX_DISTANCE
+	End Method
+
+	Method OnCopy:TType()
+		Return New TFloat128Type
+	End Method
+
+	Method ToString$()
+		Return "Float128" + ToStringParts()
+	End Method
+
+End Type
+
+Type TDouble128Type Extends TIntrinsicType
+	
+	Method EqualsType:Int( ty:TType )
+		Return TDouble128Type( ty )<>Null And (_flags = ty._flags Or ..
+			(_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, 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 (TDouble128Type(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
+		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 (TDouble128Type(ty)<>Null And (ty._flags & T_VAR)) Or TInt128Type(ty)<>Null Or TFloat128Type(ty)<>Null
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
+		End If
+
+		If TDouble128Type(ty)<>Null Then
+			Return 0
+		End If
+
+		If TFloat128Type(ty)<>Null Then
+			Return 2
+		End If
+
+		If TInt128Type(ty)<>Null Then
+			Return 4
+		End If
+		
+		Return T_MAX_DISTANCE
+	End Method
+
+	Method OnCopy:TType()
+		Return New TDouble128Type
+	End Method
+
+	Method ToString$()
+		Return "Double128" + ToStringParts()
+	End Method
+
+End Type
+
 Type TStringType Extends TType
 
 	Field cdecl:TClassDecl
@@ -1065,7 +1397,7 @@ Type TArrayType Extends 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")
+		Return (arrayType And dims = arrayType.dims And ( TVoidType( elemType ) Or (TObjectType(elemType) And 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
 	
 	Method Semant:TType(option:Int = False)
@@ -1111,6 +1443,7 @@ Type TObjectType Extends TType
 	End Method
 	
 	Method ExtendsType:Int( ty:TType, noExtendString:Int = False, widensTest:Int = False )
+		If classDecl.IsStruct() Return False
 		Local objty:TObjectType=TObjectType( ty )
 		If objty Return classDecl.ExtendsClass( objty.classDecl )
 		If IsPointerType( ty, T_BYTE ) Return True
@@ -1133,6 +1466,33 @@ Type TObjectType Extends TType
 
 End Type
 
+Type TClassType Extends TType
+
+	Field classDecl:TClassDecl
+	Field instance:Int
+	
+	Method Create:TClassType( classDecl:TClassDecl )
+		Self.classDecl=classDecl
+		Return Self
+	End Method
+
+	Method GetClass:TClassDecl()
+		Return classDecl
+	End Method
+
+	Method OnCopy:TType()
+		Local ty:TClassType = New TClassType
+		ty.classDecl = classDecl
+		ty.instance = instance
+		Return ty
+	End Method
+
+	Method ToString:String()
+		Return "Type"
+	End Method
+	
+End Type
+
 Type TIdentType Extends TType
 	Field ident$
 	Field args:TType[]
@@ -1192,18 +1552,18 @@ Type TIdentType Extends TType
 		
 		If i=-1
 			tyid=ident.ToLower()
-			
+
 			If tyid = "self" Then
 				' find owning class
 				Local scope:TClassDecl = _env.ClassScope()
 				If scope Then
 					tyid = scope.ident
-					ty = New TObjectType.Create(scope)
+					ty = New TClassType.Create(scope)
 					
 					' test for method scope - self is already an instance
 					Local funcScope:TFuncDecl = _env.FuncScope()
-					If funcScope.IsMethod() Then
-						TObjectType(ty).instance = True
+					If funcScope.IsAnyMethod() Then
+						TClassType(ty).instance = True
 					End If
 				Else
 					Err "'Self' can only be used within methods."
@@ -1233,12 +1593,12 @@ Type TIdentType Extends TType
 				Local scope:TClassDecl = _env.ClassScope()
 				If scope Then
 					tyid = scope.ident
-					ty = New TObjectType.Create(scope)
+					ty = New TClassType.Create(scope)
 					
 					' test for method scope - self is already an instance
 					Local funcScope:TFuncDecl = _env.FuncScope()
-					If funcScope.IsMethod() Then
-						TObjectType(ty).instance = True
+					If funcScope.IsAnyMethod() Then
+						TClassType(ty).instance = True
 					End If
 				Else
 					Err "'Self' can only be used within methods."
@@ -1279,6 +1639,10 @@ Type TIdentType Extends TType
 		End If
 
 		If (_flags & T_POINTER) And TObjectType(ty) Then
+			' FIXME #200
+			'If Not TObjectType(ty).classDecl.IsExtern() Then
+			'	Err "Invalid Pointer type."
+			'End If
 			ty = New TObjectType.Create(TObjectType(ty).classDecl)
 			ty._flags :| (_flags & T_POINTER)
 		End If
@@ -1369,17 +1733,36 @@ End Type
 Type TFunctionPtrType Extends TType
 
 	Field func:TFuncDecl
+	
+	Method Create:TFunctionPtrType(func:TFuncDecl)
+		Self.func = func
+		Return Self
+	End Method
 
 	Method EqualsType:Int( ty:TType )
-' TODO : compare function decl
-		Return TFunctionPtrType( ty )<>Null
+		If Not TFunctionPtrType(ty) Then Return False
+		' declared function pointer
+		Local tyfunc:TFuncDecl = TFunctionPtrType(ty).func
+		If Not tyfunc.retType.EqualsType(func.retType) Then Return False
+		If Not (tyfunc.argDecls.Length = func.argDecls.Length) Then Return False
+		For Local a:Int = 0 Until func.argDecls.Length
+			' does our arg equal declared arg?
+			If Not func.argDecls[a].ty.EqualsType(tyfunc.argDecls[a].ty) Then Return False
+		Next
+		Return True
 	End Method
 	
 	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()
+		If TFunctionPtrType( ty )
+			' declared function pointer
+			Local tyfunc:TFuncDecl = TFunctionPtrType(ty).func
+			If Not func.retType.ExtendsType(tyfunc.retType) Then Return False
+			If Not (func.argDecls.Length = tyfunc.argDecls.Length) Then Return False
+			For Local a:Int = 0 Until func.argDecls.Length
+				' does declared arg extend our arg?
+				If Not tyfunc.argDecls[a].ty.ExtendsType(func.argDecls[a].ty) Then Return False
+			Next
+			Return True
 		EndIf
 		Return IsPointerType( ty, 0, T_POINTER )<>Null
 	End Method
@@ -1434,3 +1817,195 @@ Type TVarPtrType Extends TType
 		Return New TVarPtrType
 	End Method
 End Type
+
+Type TParamType Extends TIntegralType
+End Type
+
+Type TWParamType Extends TParamType
+
+	Method EqualsType:Int( ty:TType )
+		Return TWParamType( ty )<>Null And (_flags = ty._flags Or ..
+			(_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, noExtendString:Int = False, widensTest:Int = False )
+		If _flags & T_VARPTR And (TWParamType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
+		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 ((TWParamType(ty)<>Null 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 ((TWParamType(ty)<>Null 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 Or TFloat64Type(ty)<>Null
+		End If
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
+		End If
+
+		If TWParamType(ty)<>Null 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
+
+			If TFloat64Type(ty)<>Null Then
+				Return 8
+			End If
+
+		End If
+	
+		Return T_MAX_DISTANCE
+	End Method
+	
+	Method OnCopy:TType()
+		Return New TWParamType
+	End Method
+
+	Method ToString$()
+		Return "WPARAM" + ToStringParts()
+	End Method
+
+	Method GetSize:Int()
+		Return WORD_SIZE
+	End Method
+
+End Type
+
+Type TLParamType Extends TParamType
+
+	Method EqualsType:Int( ty:TType )
+		Return TLParamType( ty )<>Null And (_flags = ty._flags Or ..
+			(_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, noExtendString:Int = False, widensTest:Int = False )
+		If _flags & T_VARPTR And (TLParamType(ty) <> Null Or IsPointerType(ty, 0, T_POINTER)) Return True
+		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 ((TIntType(ty)<>Null Or TLParamType(ty)<>Null) And (ty._flags & T_VAR)) Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null Or TFloat64Type(ty)<>Null
+		Else
+			Return (IsPointerType(ty, 0, T_POINTER) And IsPointerType(Self, 0, T_POINTER)) Or ((TLongType(ty)<>Null Or TLParamType(ty)<>Null) And (ty._flags & T_VAR)) Or TFloatType(ty)<>Null Or TDoubleType(ty)<>Null Or TFloat64Type(ty)<>Null
+		End If
+	End Method
+
+	Method DistanceToType:Int(ty:TType)
+		If IsPointerType(ty, 0, T_POINTER) Then
+			If IsPointerType(Self, 0, T_POINTER) Then
+				Return 0
+			Else
+				Return T_MAX_DISTANCE
+			End If
+		End If
+
+		If TLParamType(ty)<>Null Then
+			Return 0
+		End If
+
+		If WORD_SIZE = 4 Then
+		
+			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
+			
+		Else
+			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
+	
+			If TFloat64Type(ty)<>Null Then
+				Return 6
+			End If
+
+		End If
+	
+		Return T_MAX_DISTANCE
+	End Method
+	
+	Method OnCopy:TType()
+		Return New TLParamType
+	End Method
+
+	Method ToString$()
+		Return "LPARAM" + ToStringParts()
+	End Method
+
+	Method GetSize:Int()
+		Return WORD_SIZE
+	End Method
+
+End Type

部分文件因为文件数量过多而无法显示