Forráskód Böngészése

Fixed generation of nested functions. Fixes #281.

woollybah 8 éve
szülő
commit
296401d248
2 módosított fájl, 5403 hozzáadás és 5372 törlés
  1. 3552 3521
      decl.bmx
  2. 1851 1851
      translator.bmx

+ 3552 - 3521
decl.bmx

@@ -1,3521 +1,3552 @@
-' Copyright (c) 2013-2017 Bruce A Henderson
-'
-' Based on the public domain Monkey "trans" by Mark Sibly
-'
-' This software is provided 'as-is', without any express or implied
-' warranty. In no event will the authors be held liable for any damages
-' arising from the use of this software.
-'
-' Permission is granted to anyone to use this software for any purpose,
-' including commercial applications, and to alter it and redistribute it
-' freely, subject to the following restrictions:
-'
-'    1. The origin of this software must not be misrepresented; you must not
-'    claim that you wrote the original software. If you use this software
-'    in a product, an acknowledgment in the product documentation would be
-'    appreciated but is not required.
-'
-'    2. Altered source versions must be plainly marked as such, and must not be
-'    misrepresented as being the original software.
-'
-'    3. This notice may not be removed or altered from any source
-'    distribution.
-'
-
-Const DECL_EXTERN:Int=        $010000
-Const DECL_PRIVATE:Int=       $020000
-Const DECL_ABSTRACT:Int=      $040000
-Const DECL_FINAL:Int=         $080000
-
-Const DECL_SEMANTED:Int=      $100000
-Const DECL_SEMANTING:Int=     $200000
-Const DECL_CYCLIC:Int=       $8000000
-
-Const DECL_POINTER:Int=       $400000
-
-Const DECL_ARG:Int=           $800000
-Const DECL_INITONLY:Int=     $1000000
-
-Const DECL_NODEBUG:Int=      $2000000
-Const DECL_PROTECTED:Int=    $4000000
-
-Const DECL_API_CDECL:Int=   $00000000
-Const DECL_API_STDCALL:Int= $10000000
-Const DECL_API_DEFAULT:Int=DECL_API_CDECL
-
-Const CLASS_INTERFACE:Int=    $002000
-Const CLASS_THROWABLE:Int=    $004000
-Const CLASS_STRUCT:Int=       $008000
-Const CLASS_GENERIC:Int=      $001000
-
-Const SCOPE_FUNC:Int = 0
-Const SCOPE_CLASS_LOCAL:Int = 1
-Const SCOPE_CLASS_HEIRARCHY:Int = 2
-Const SCOPE_MODULE:Int = 3
-Const SCOPE_ALL:Int = 4
-
-'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
-
-Global _appInstance:TAppDecl
-
-Global _loopnest:Int
-
-Function PushEnv( env:TScopeDecl )
-	If _env _envStack.AddLast( _env )
-	_env=env
-End Function
-
-Function PopEnv()
-	_env=TScopeDecl( _envStack.RemoveLast() )
-End Function
-
-Type TFuncDeclList Extends TList
-	Field ident:String
-	Field _identLower:String
-	
-	Method IdentLower:String()
-		If Not _identLower Then
-			_identLower = ident.ToLower()
-		End If
-		Return _identLower
-	End Method
-End Type
-
-Type TMetadata
-
-	Field metadataString:String
-
-	' key/value pairs
-	Field meta:TMap
-
-	Method InsertMeta(key:String, value:String)
-		If Not meta Then
-			meta = New TMap
-		End If
-		
-		meta.Insert(key, value)
-	End Method
-
-	Method HasMeta:Int(key:String)
-		Return meta And meta.Contains(key.ToLower())
-	End Method
-	
-End Type
-
-Type TDecl
-	Field ident$
-	Field munged$
-	Field errInfo$
-	Field actual:TDecl
-	Field scope:TScopeDecl
-	Field attrs:Int
-	Field metadata:TMetadata = New TMetadata
-	
-	Field declImported:Int = False
-	Field generated:Int
-	
-	Field _identLower:String
-	
-	Method New()
-		errInfo=_errInfo
-		actual=Self
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True) Abstract
-	
-	Method IdentLower:String()
-		If Not _identLower Then
-			_identLower = ident.ToLower()
-		End If
-		Return _identLower
-	End Method
-	
-	Method ToString$()
-		If TClassDecl( scope ) Return scope.ToString()+"."+ident
-		Return ident
-	End Method
-	
-	Method ToTypeString:String()
-	End Method
-	
-	Method IsExtern:Int()
-		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
-	End Method
-	
-	Method IsSemanted:Int()
-		Return (attrs & DECL_SEMANTED)<>0
-	End Method
-	
-	Method IsSemanting:Int()
-		Return (attrs & DECL_SEMANTING)<>0
-	End Method
-	
-	Method IsNoDebug:Int()
-		Return (attrs & DECL_NODEBUG)<>0
-	End Method
-	
-	Method FuncScope:TFuncDecl()
-		If TFuncDecl( Self ) Return TFuncDecl( Self )
-		If scope Return scope.FuncScope()
-	End Method
-
-	Method ClassScope:TClassDecl()
-		If TClassDecl( Self ) Return TClassDecl( Self )
-		If scope Return scope.ClassScope()
-	End Method
-	
-	Method ModuleScope:TModuleDecl()
-		If TModuleDecl( Self ) Return TModuleDecl( Self )
-		' "app" is a module container
-		If TAppDecl( Self ) Return TAppDecl( Self).mainModule
-		If scope Return scope.ModuleScope()
-	End Method
-	
-	Method AppScope:TAppDecl()
-		If TAppDecl( Self ) Return TAppDecl( Self )
-		If scope Return scope.AppScope()
-	End Method
-	
-	Method CheckAccess:Int()
-		If IsPrivate() And ModuleScope()<>_env.ModuleScope() Return False
-		Return True
-	End Method
-	
-	Method AssertAccess()
-		If Not CheckAccess()
-			If IsPrivate() Then
-				Err ToString() +" is private."
-			Else
-				Err ToString() +" is protected."
-			End If
-		EndIf
-	End Method
-
-	Method Copy:TDecl(deep:Int = True)
-		Local t:TDecl=OnCopy(deep)
-		t.munged=munged
-		t.errInfo=errInfo
-		Return t
-	End Method
-
-	Method Semant()
-
-		If IsSemanted() Return
-
-		If IsSemanting() Then
-			If attrs & DECL_CYCLIC Then
-				Return
-			End If
-			Err "Cyclic declaration of '"+ident+"'."
-		End If
-		
-		If actual<>Self
-			actual.Semant
-		EndIf
-
-		PushErr errInfo
-		
-		If scope
-			PushEnv scope
-		EndIf
-		
-		attrs:|DECL_SEMANTING
-
-		'If ident And ClassScope() Print "Semanting "+ToString()
-
-		OnSemant
-		
-		attrs:&~DECL_SEMANTING
-
-		attrs:|DECL_SEMANTED
-
-		If scope 
-			'If Not IsExtern()
-			If TFuncDecl(Self) And attrs & FUNC_PTR
-				'DebugLog "**** " + ident
-			Else
-
-				scope._semanted.AddLast Self
-				
-				If TGlobalDecl( Self )
-					' FIXME
-					If AppScope() Then
-						AppScope().semantedGlobals.AddLast TGlobalDecl( Self )
-					End If
-				EndIf
-				
-				If TModuleDecl( scope )
-'DebugStop
-					' FIXME
-					Local app:TAppDecl = AppScope()
-					If app Then
-						app._semanted.AddLast Self
-					End If
-				EndIf
-			
-			EndIf
-			
-			If TValDecl(Self) And TValDecl(Self).deferInit Then
-				TValDecl(Self).SemantInit
-			End If
-
-			PopEnv
-		Else
-			If TValDecl(Self) And TValDecl(Self).deferInit Then
-				TValDecl(Self).SemantInit
-			End If
-		EndIf
-		
-		
-		PopErr
-	End Method
-	
-	Method InitInstance:TDecl( decl:TDecl )
-		decl.ident=ident
-		decl.munged=munged
-		decl.errInfo=errInfo
-		decl.actual=actual
-		decl.scope=Null
-		decl.attrs=attrs & ~(DECL_SEMANTED|DECL_SEMANTING)
-		Return decl
-	End Method
-	
-	Method GenInstance:TDecl()
-		InternalErr
-	End Method
-	
-	Method OnSemant() Abstract
-	
-	Method Clear()
-	End Method
-
-End Type
-
-Type TValDecl Extends TDecl
-	'pre-semant
-	Field declTy:TType
-	Field declInit:TExpr
-	'post-semant
-	Field ty:TType
-	Field init:TExpr
-	
-	Field deferInit:Int = False
-	
-	Method ToString$()
-		Local t$=Super.ToString()
-		If ty Return t+":"+ty.ToString()
-		If declTy Return t+":"+declTy.ToString()
-		Return t+":?"
-	End Method
-
-	Method ToTypeString:String()
-		If ty Return ty.ToString()
-		If declTy Return declTy.ToString()
-	End Method
-
-	Method CopyInit:TExpr()
-		If init Return init.Copy()
-	End Method
-	
-	Method OnSemant()
-'DebugStop	
-		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 TFunctionPtrType(at) Then
-				If Not TFunctionPtrType(at).func.scope Then
-					If scope Then
-						TFunctionPtrType(at).func.scope = scope
-					Else
-						TFunctionPtrType(at).func.scope = _env
-					End If
-				End If
-			End If
-
-			' pass the scope into the function ptr
-			If TFunctionPtrType(declTy) Then
-				If Not TFunctionPtrType(declTy).func.scope Then
-					If scope Then
-						TFunctionPtrType(declTy).func.scope = scope
-					Else
-						TFunctionPtrType(declTy).func.scope = _env
-					End If
-				End If
-			End If
-			
-			ty=declTy.Semant()
-
-			If Not deferInit Then
-				SemantInit()
-			End If
-			
-		Else If declInit
-			If Not deferInit Then
-				SemantInit()
-			End If
-		Else
-			InternalErr
-		EndIf
-		
-	End Method
-	
-	Method SemantInit()
-		' for field initialisation, create a stub New() method to use as current scope
-		' since fields are initialised in New(). Otherwise the scope would be "class", which is
-		' incorrect for processing field inits.
-		If TFieldDecl(Self) And declInit Then
-			Local newScope:TFuncDecl = New TFuncDecl.CreateF( "new", Null,Null,FUNC_METHOD )
-			newScope.scope = _env
-			PushEnv(newScope)
-		End If
-	
-		If declTy
-			If declInit Then
-				If TFunctionPtrType(ty) Then
-					
-					Local expr:TExpr
-					
-					If TInvokeExpr(declInit) Then
-						expr = declInit.Copy()
-					Else If TConstExpr(declInit) Then
-						expr = declInit.Copy().Semant()
-					Else If TFuncCallExpr(declInit) Then
-						expr=declInit.Copy().Semant()
-					Else If TNullExpr(declInit) Then
-						expr = declInit
-					Else
-						' 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
-						End Rem
-						
-						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
-			init=declInit.Copy().Semant()
-			ty=init.exprType
-		End If
-		
-		If init Then
-			If TVarExpr(init) And TVarExpr(init).decl = Self Then
-				Err "Identifier '" + TVarExpr(init).decl.ident + "' not found."
-			End If
-			
-			If TNewObjectExpr(init) And TVarExpr(TNewObjectExpr(init).instanceExpr) And TVarExpr(TNewObjectExpr(init).instanceExpr).decl = Self Then
-				Err "Identifier '" + Self.ident + "' not found."
-			End If
-		End If
-		
-		' remove the temporary scope
-		If TFieldDecl(Self) And declInit Then
-			PopEnv()
-		End If
-	End Method
-	
-	Method Clear()
-	End Method
-	
-End Type
-
-Type TConstDecl Extends TValDecl
-	Field value$
-	
-	Method Create:TConstDecl( ident$,ty:TType,init:TExpr,attrs:Int )
-		Self.ident=ident
-		Self.munged=ident
-		Self.declTy=ty
-		Self.declInit=init
-		Self.attrs=attrs
-		Return Self
-	End Method
-
-	Method GenInstance:TDecl()
-		Local inst:TConstDecl = New TConstDecl
-		InitInstance inst
-		inst.declTy=declTy
-		inst.declInit=declInit
-		Return inst
-	End Method
-
-	Method OnCopy:TDecl(deep:Int = True)
-		Return New TConstDecl.Create( ident,ty,CopyInit(), attrs )
-	End Method
-	
-	Method OnSemant()
-		Super.OnSemant()
-		'If Not IsExtern() value=init.Eval()
-		If init Then
-			value=init.Eval()
-			If TStringType(ty) And Not _appInstance.hasStringConst(value) Then
-				_appInstance.mapStringConsts(value)
-			End If
-		End If
-	End Method
-	
-	Method ToString$()
-		Return "Const "+Super.ToString()
-	End Method
-
-End Type
-
-Type TVarDecl Extends TValDecl
-
-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, 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)
-		Local decl:TLocalDecl = New TLocalDecl.Create( ident,declTy,declInit,attrs &~ DECL_SEMANTED, generated, volatile )
-		decl.scope = scope
-		decl.ty = ty
-		decl.init = init
-		Return decl
-	End Method
-
-	Method GetDeclPrefix:String()
-		Return "Local "
-	End Method
-	
-	Method ToString$()
-		Return GetDeclPrefix() + Super.ToString()
-	End Method
-
-	Method Clear()
-		done = False
-	End Method
-
-End Type
-
-Type TArgDecl Extends TLocalDecl
-
-	Field castTo:String
-	
-	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
-	
-	Method GenInstance:TDecl()
-		Local inst:TArgDecl=New TArgDecl
-		InitInstance inst
-		inst.declTy=declTy
-		inst.declInit=declInit
-		Return inst
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Local d:TArgDecl = New TArgDecl.Create( ident,declTy,declInit,attrs,generated,volatile )
-		d.ty = ty
-		d.init = init
-		Return d
-	End Method
-
-	Method GetDeclPrefix:String()
-		Return ""
-	End Method
-	
-	Method ToString$()
-		Return Super.ToString()
-	End Method
-	
-End Type
-
-Type TGlobalDecl Extends TVarDecl
-
-	Field inited:Int
-	Field funcGlobal:Int
-	
-	Method Create:TGlobalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0,funcGlobal:Int=False )
-		Self.deferInit = True
-		Self.ident=ident
-		Self.declTy=ty
-		Self.declInit=init
-		Self.attrs=attrs
-		Self.funcGlobal=funcGlobal
-		Return Self
-	End Method
-
-	Method OnCopy:TDecl(deep:Int = True)
-		Local g:TGlobalDecl = New TGlobalDecl.Create( ident,declTy,declInit,attrs,funcGlobal )
-		g.ty = ty
-		g.init = init
-		Return g
-	End Method
-	
-	Method ToString$()
-		Return "Global "+Super.ToString()
-	End Method
-
-	Method GenInstance:TDecl()
-'		PushErr errInfo
-'		Err "Global variables cannot be used inside generic classes."
-		Local inst:TGlobalDecl=New TGlobalDecl
-		InitInstance inst
-		inst.declTy=declTy
-		inst.declInit=declInit
-		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
-
-	' location offset in object variable data
-	Field offset:Int
-
-	Method Create:TFieldDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
-		Self.ident=ident
-		Self.declTy=ty
-		Self.declInit=init
-		Self.attrs=attrs
-		Return Self
-	End Method
-
-	Method OnCopy:TDecl(deep:Int = True)
-		Local f:TFieldDecl = New TFieldDecl.Create( ident,declTy,declInit,attrs )
-		f.ty = ty
-		f.init = init
-		f.metadata = metadata
-		Return f
-	End Method
-	
-	Method ToString$()
-		Return "Field "+Super.ToString()
-	End Method
-	
-	Method GenInstance:TDecl()
-		Local inst:TFieldDecl=New TFieldDecl
-		InitInstance inst
-		inst.declTy=declTy
-		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
-
-	Field decl:Object
-	
-	Method Create:TAliasDecl( ident$,decl:Object,attrs:Int=0 )
-		Self.ident=ident
-		Self.decl=decl
-		Self.attrs=attrs
-		Return Self
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Return New TAliasDecl.Create( ident,decl,attrs )
-	End Method
-	
-	Method OnSemant()
-	End Method
-	
-	Method Clear()
-	End Method
-	
-End Type
-
-Type TScopeDecl Extends TDecl
-
-'Private
-
-	Field _decls:TList=New TList'<TDecl>
-	Field _semanted:TList=New TList'<TDecl>
-
-	Field declsMap:TMap=New TMap'<Object>
-
-'Public
-
-	Method OnCopy:TDecl(deep:Int = True)
-		InternalErr
-	End Method
-
-	Method Decls:TList()
-		Return _decls
-	End Method
-	
-	Method Semanted:TList()
-		Return _semanted
-	End Method
-	
-	Method FuncDecls:TList( id$="" )
-		Local fdecls:TList=New TList
-		For Local decl:TDecl=EachIn _decls
-			If id And decl.ident<>id Continue
-			Local fdecl:TFuncDecl=TFuncDecl( decl )
-			If fdecl fdecls.AddLast fdecl
-		Next
-		Return fdecls
-	End Method
-	
-	Method MethodDecls:TList( id$="" )
-		Local fdecls:TList=New TList
-		For Local decl:TDecl=EachIn _decls
-			If id And decl.ident<>id Continue
-			Local fdecl:TFuncDecl=TFuncDecl( decl )
-			If fdecl And fdecl.IsMethod() fdecls.AddLast fdecl
-		Next
-		Return fdecls
-	End Method
-	
-	Method SemantedFuncs:TList( id$="" )
-		Local fdecls:TList=New TList
-		For Local decl:TDecl=EachIn _semanted
-			If id And decl.ident<>id Continue
-			Local fdecl:TFuncDecl=TFuncDecl( decl )
-			If fdecl fdecls.AddLast fdecl
-		Next
-		Return fdecls
-	End Method
-	
-	Method SemantedMethods:TList( id$="" )
-		Local fdecls:TList=New TList
-		For Local decl:TDecl=EachIn _decls
-			If id And decl.ident<>id Continue
-			Local fdecl:TFuncDecl=TFuncDecl( decl )
-			If fdecl And fdecl.IsMethod()
-				If Not fdecl.IsSemanted() Then
-					fdecl.Semant()
-				End If
-				fdecls.AddLast fdecl
-			End If
-		Next
-		Return fdecls
-	End Method
-	
-	Method InsertDecl( decl:TDecl, isCopy:Int = False )
-
-		If decl.scope And Not (decl.attrs & DECL_INITONLY) And Not isCopy InternalErr
-		
-		'Local ident$=decl.ident
-		If Not decl.ident Return
-		
-		If Not decl.scope Or isCopy Then
-			decl.scope=Self
-		End If
-		_decls.AddLast decl
-
-		'Local _decls:TMap
-		Local tdecl_:Object=declsMap.ValueForKey( decl.IdentLower() )
-		
-		If TFuncDecl( decl )
-			Local funcs:TFuncDeclList=TFuncDeclList( tdecl_ )
-			If funcs Or Not tdecl_
-				If Not funcs
-					funcs=New TFuncDeclList
-					funcs.ident = decl.IdentLower()
-					declsMap.Insert decl.IdentLower(),funcs
-				EndIf
-
-				funcs.AddLast TFuncDecl( decl )
-				Return
-			Else
-				Err "Duplicate identifier '"+decl.ident+"'."
-			EndIf
-		Else If Not tdecl_
-			declsMap.Insert decl.IdentLower(),decl
-		Else
-			Err "Duplicate identifier '"+decl.ident+"'."
-		EndIf
-
-	End Method
-
-	Method InsertDecls( _decls:TList )
-		For Local decl:TDecl=EachIn _decls
-			InsertDecl decl
-		Next
-	End Method
-	
-	'This is overridden by TClassDecl and TModuleDecl
-	Method GetDecl:Object( ident$ )
-'DebugLog "GetDecl (" + Self.ident + ") : " + ident
-		Local decl:Object=Object(declsMap.ValueForKey( ident ))
-
-		If Not decl Then
-			If Self.IdentLower() = ident Then
-				' name matches but we are a "module", but not a *real* module..
-				' .. so we can't be looking for ourself
-				If TModuleDecl(Self) And Self.ident.Find(".") = - 1 Then
-					decl = Null
-				Else
-					decl = Self
-				End If
-			End If
-		End If
-		
-		If Not decl Return Null
-		
-		Local adecl:TAliasDecl=TAliasDecl( decl )
-		If Not adecl Return decl
-		
-		If adecl.CheckAccess() Return adecl.decl
-	End Method
-	
-
-	Method FindDecl:Object( ident$, override:Int = False )
-	
-		If Not override And _env<>Self Return GetDecl( ident )
-		
-		Local tscope:TScopeDecl=Self
-		While tscope
-			Local decl:Object=tscope.GetDecl( ident )
-			If decl Return decl
-			tscope=tscope.scope
-		Wend
-	End Method
-	
-	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
-
-		If Not declList Then
-			declList = New TFuncDeclList
-		End If
-
-		Local decl:Object=Object(declsMap.ValueForKey( ident ))
-
-		If Not decl Return Null
-
-		If TFuncDeclList(decl) Then
-			For Local fdecl:TFuncDecl = EachIn TFuncDeclList(decl)
-
-				If Not fdecl.IsSemanted() And Not fdecl.IsSemanting() Then
-					fdecl.Semant
-				End If
-				
-				Local found:Int
-				For Local func:TFuncDecl = EachIn declList
-					If func.equalsFunc(fdecl) Then
-						found = True
-						Exit
-'Else
-'Print func.ToString() + "  didn't match  " + fdecl.ToString()
-					End If
-				Next
-				
-				If Not found Then
-					declList.AddLast(fdecl)
-				End If
-			Next
-			
-			Return declList
-		End If		
-		
-		Return decl
-		
-	End Method
-	
-	' returns a list of all matching named decls in scope
-	Method FindDeclList:Object(ident:String, override:Int = False, declList:TFuncDeclList = Null, maxSearchDepth:Int = SCOPE_ALL )
-	
-		If Not declList Then
-			declList = New TFuncDeclList
-		End If
-	
-		If Not override And _env<>Self Return GetDeclList( ident, declList, maxSearchDepth )
-		
-		Local tscope:TScopeDecl=Self
-		While tscope
-			Local decl:Object=tscope.GetDeclList( ident, declList, maxSearchDepth )
-			'If decl And (Not TFuncDeclList(decl) And declList.IsEmpty()) Return decl
-			If decl Then
-				If TFuncDeclList(decl) Then
-					If TFuncDeclList(decl) <> declList Then
-						For Local d:TDecl = EachIn TFuncDeclList(decl)
-							declList.AddLast(d)
-						Next
-					End If
-				Else
-					declList.AddLast(decl)
-				End If
-			End If
-
-			' if scope is an interface, also check implemented/extended interfaces?
-			If TClassDecl(tscope) Then'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
-				Exit
-			Else If TModuleDecl(tscope) And maxSearchDepth < SCOPE_ALL Then
-				Exit
-			End If
-		Wend
-		
-		Return declList
-	End Method
-
-	
-
-'	Method FindDecl:Object( ident$, static:Int = False )
-'		Local decl:Object=GetDecl( ident )
-'		
-'		If Not static Or Not decl Then
-'			If decl Return decl
-'		Else
-'			If Not TFieldDecl(decl) And Not (TFuncDecl(decl) And TFuncDecl(decl).IsMethod()) Then
-'				Return decl
-'			End If
-'		End If
-'		If scope Return scope.FindDecl( ident, static )
-'	End Method
-	
-	Method FindValDecl:TValDecl( ident$, static:Int = False )
-		Local decl:TValDecl=TValDecl( FindDecl( ident ) )
-		
-		' we found a field but we don't have access to it?
-		If TFieldDecl(decl) And static Then
-			' see if there's another decl with the same name elsewhere that we may...
-			' field's scope.scope will be a module.
-			If decl.scope And decl.scope.scope Then
-				Local vDecl:TValDecl = TValDecl( decl.scope.scope.FindDecl( ident, True ) )
-				If vDecl Then
-					decl = vDecl
-				End If
-			End If
-		End If
-		
-		If Not decl Then
-			' try scope search
-			decl = TValDecl( FindDecl( ident, True ) )
-			
-			If Not decl Then
-				' didn't find it? Maybe it is in module local scope?
-				' issue arises when a global initialises with a local variable in the module scope.
-				Local fdecl:Object = FindDecl("__localmain", True)
-				If fdecl Then
-					If TFuncDecl(fdecl) Then
-						decl = TValDecl( TFuncDecl(fdecl).FindDecl( ident ) )
-					Else If TFuncDeclList(fdecl) Then
-						For Local func:TFuncDecl = EachIn TFuncDeclList(fdecl)
-							func.Semant()
-							decl = TValDecl( func.FindDecl( ident ) )
-							If decl Then
-								Exit
-							End If
-						Next
-					End If
-					
-					' a local variable from module local scope can't be seen outside of module local scope...
-					If TLocalDecl(decl) And static Then
-						decl = Null
-					End If
-				End If
-			End If
-		End If
-		If Not decl Return Null
-		decl.AssertAccess
-		decl.Semant
-		Return decl
-	End Method
-
-	Method FindType:TType( ident$,args:TType[] )
-'DebugLog Self.ident + "::FindType::" + ident
-		Local decl:Object=(GetDecl( ident ))
-		If decl Then
-			If TModuleDecl(decl) Then
-				decl = TModuleDecl(decl).GetDecl(ident)
-			End If
-			Local ty:TType=TType(decl)
-			If ty
-				If args.Length Err "Wrong number of type arguments"
-				Return ty
-			EndIf
-			Local cdecl:TClassDecl=TClassDecl( decl )
-			If cdecl
-				cdecl.AssertAccess
-				If Not cdecl.instanceof Then
-					cdecl=cdecl.GenClassInstance( args )
-					cdecl.Semant
-				End If
-				Return cdecl.objectType
-			EndIf
-		EndIf
-		If scope Return scope.FindType( ident,args )
-	End Method
-	
-	Method FindScopeDecl:TScopeDecl( ident$ )
-		Local decl:TScopeDecl=TScopeDecl( FindDecl( ident ) )
-		If Not decl Return Null
-		decl.AssertAccess
-		decl.Semant
-		Return decl
-	End Method
-Rem	
-	Method FindClassDecl:TClassDecl( ident$,args:TClassDecl[] = Null )
-		Local decl:TClassDecl=TClassDecl( GetDecl( ident ) )
-		If Not args Then
-			args = New TClassDecl[0]
-		End If
-		If Not decl
-			If scope Return scope.FindClassDecl( ident,args )
-			Return Null
-		EndIf
-		decl.AssertAccess
-		decl.Semant
-		Return decl.GenClassInstance( args )
-	End Method
-End Rem	
-	Method FindModuleDecl:TModuleDecl( ident$ )
-'DebugStop
-		Local decl:TModuleDecl=TModuleDecl( GetDecl( ident ) )
-		If Not decl
-			If scope Return scope.FindModuleDecl( ident )
-			Return Null
-		EndIf
-		decl.AssertAccess
-		
-		' only semant on "real" module
-		If Not decl.declImported Then
-			decl.Semant
-		End If
-		Return decl
-	End Method
-	
-	Method FindBestMatchForArgs:TFuncDecl(argExprs:TExpr[], matches:TList)
-
-		Local bestMatch:TFuncDecl = Null
-		Local totals:Int[] = New Int[matches.count()]
-		Local index:Int
-		
-		For Local func:TFuncDecl = EachIn matches
-
-			Local argDecls:TArgDecl[]=func.argDecls
-			
-			For Local i:Int=0 Until argDecls.Length
-	
-				If i<argExprs.Length And argExprs[i]
-				
-					Local declTy:TType=argDecls[i].ty
-					Local exprTy:TType=argExprs[i].exprType
-
-					If TFunctionPtrType(declTy) And TInvokeExpr(argExprs[i]) Then
-						If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(argExprs[i]).decl) Then
-							Continue
-						End If
-					End If
-
-					' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
-					If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(argExprs[i]) And TInvokeExpr(argExprs[i]).invokedWithBraces = 0 Then
-						Continue
-					End If
-					
-					If TFunctionPtrType(declTy) And IsPointerType(exprTy, TType.T_BYTE) Then
-						Continue
-					End If
-					
-					If exprTy.EqualsType( declTy ) Continue
-					
-					' not an exact match. increase distance...
-					totals[index] :+ exprTy.DistanceToType(declTy)
-					
-				End If
-				
-			Next
-			
-			index :+ 1
-
-		Next
-		
-		Local tot:Int = -1
-		index = 0
-		Local i:Int
-		For Local func:TFuncDecl = EachIn matches
-			If tot = -1 Or totals[i] < tot Then
-				tot = totals[i]
-				bestMatch = func
-			Else If tot = totals[i] Then
-				If bestMatch.IsMethod() And Not func.IsMethod() Then
-					' 
-				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()+"."
-				End If
-			End If
-			i :+ 1
-		Next
-		
-		Return bestMatch
-		
-	End Method
-	
-	Method FindFuncDecl:TFuncDecl( ident$,argExprs:TExpr[] = Null,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False, maxSearchDepth:Int )
-'DebugLog "FindFuncDecl : " + ident
-'If ident = "new" Then DebugStop
-		Local foundIdentMatch:Int
-		Local funcs:TFuncDeclList
-
-		' does ident exist?
-		Local f:Object = FindDeclList(ident, True,,maxSearchDepth)
-		If Not f Then Return Null
-		
-		funcs = TFuncDeclList( f )
-		Local fp:TFuncDecl
-		
-		' not a function list, test for a function ptr var
-		If Not funcs Or funcs.IsEmpty() Then
-
-			' we found a funcdecl
-			If TFuncDecl(f) Then
-				funcs = New TFuncDeclList
-				funcs.AddLast(f)
-			End If
-			
-			If TVarDecl(f) Then
-				If Not TVarDecl(f).IsSemanted() Then
-					TVarDecl(f).Semant()
-				End If
-				If TFunctionPtrType(TVarDecl(f).ty) Then
-					funcs = New TFuncDeclList
-					fp = TFunctionPtrType(TVarDecl(f).ty).func
-					If Not fp.scope Then
-						fp.scope = TVarDecl(f).scope
-					End If
-					If Not fp.ident Then
-						fp.ident = TVarDecl(f).ident
-					End If
-					funcs.AddLast fp
-				End If
-			End If
-		End If
-		' was neither... lets bug out
-		If Not funcs Return Null
-		
-'		If Not funcs Then Return Null
-		
-		For Local func:TDecl = EachIn funcs
-			If Not func.IsSemanting() Then
-				func.Semant()
-			End If
-		Next
-		
-		'Local f:TDecl = TDecl(findDecl(ident))
-		'If Not f Then Return Null
-		
-				
-			'Local func:TFuncDecl = TFuncDecl(f)
-'			If Not func Then
-'				If TVarDecl(f) Then
-'					If Not f.IsSemanted() Then
-'						f.Semant()
-'					End If
-'					If TFunctionPtrType(TVarDecl(f).ty) Then
-'						func = TFunctionPtrType(TVarDecl(f).ty).func
-'						If Not func.scope Then
-'							func.scope = f.scope
-'						End If
-'						If Not func.ident Then
-'							func.ident = f.ident
-'						End If
-'					End If
-'				End If
-'			End If
-'			If Not func Return Null
-	
-		If Not argExprs
-			argExprs = New TExpr[0]
-		End If
-	
-		'func.Semant()
-		
-		Local match:TFuncDecl,isexact:Int
-		Local _err$
-		Local errorDetails:String
-		Local matches:TList = New TList
-
-		Local noExtendString:Int = True
-		Local generateWarnings:Int = False
-
-		' double test for matches.
-		' * first time through we don't allow up-casting args to String
-		'    if we get a match on the first pass, we'll take it.
-		' * second iteration we allow up-casting numerics to string
-		' * third iteration is valid if opt_warnover is enabled
-		'    this will allow down-casting of numerics (eg. double->float)
-		'    warnings will be generated if this produces valid results.
-		' if after all that, there's no match, then we can fail it.
-		For Local n:Int = 0 Until 3
-		
-			If n > 1 Then
-				If Not opt_warnover Then
-					Continue
-				Else
-					generateWarnings = True
-				End If
-			End If
-		
-			errorDetails = ""
-		
-			If n Then
-				noExtendString = False
-			End If
-
-			For Local iDecl:TDecl = EachIn funcs
-			
-				Local func:TFuncDecl = TFuncDecl(iDecl)
-				
-				If Not func Then
-					If TVarDecl(iDecl) Then
-'						If Not TVarDecl(iDecl).IsSemanted() Then
-'							TVarDecl(f).Semant()
-'						End If
-						If TFunctionPtrType(TVarDecl(iDecl).ty) Then
-							'funcs = New TFuncDeclList
-							fp = TFunctionPtrType(TVarDecl(iDecl).ty).func
-							If Not fp.scope Then
-								fp.scope = TVarDecl(iDecl).scope
-							End If
-							If Not fp.ident Then
-								fp.ident = TVarDecl(iDecl).ident
-							End If
-							'funcs.AddLast fp
-							func = fp
-						End If
-					End If
-					
-					If Not func Then
-						Continue
-					End If
-				End If
-				
-	
-			'While True
-				If Not func.CheckAccess() Continue
-				
-				Local argDecls:TArgDecl[]=func.argDecls
-				
-				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]
-					
-						Local arg:TExpr = argExprs[i]
-					
-						Local declTy:TType=argDecls[i].ty
-						Local exprTy:TType=arg.exprType
-						
-						Local widensTest:Int = True
-						
-						' for numeric constants, allow them to be auto-cast unless
-						If TConstExpr(arg) And IsNumericType(exprTy) And Not TConstExpr(arg).typeSpecific And TConstExpr(arg).CompatibleWithType(declTy) Then
-							widensTest = False
-						End If
-	
-						If TFunctionPtrType(declTy) And TInvokeExpr(arg) Then
-							If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(arg).decl) Continue
-						End If
-	
-						' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
-						If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(arg) And TInvokeExpr(arg).invokedWithBraces = 0 Then
-							Continue
-						End If
-						
-						If TFunctionPtrType(declTy) And IsPointerType(exprTy, TType.T_BYTE) Then
-							Continue
-						End If
-						
-						If exprTy.EqualsType( declTy ) Continue
-						
-						exact=False
-						
-						If Not generateWarnings Then
-							If Not explicit And exprTy.ExtendsType( declTy, noExtendString, widensTest ) Continue
-						Else
-							If Not explicit Then
-								' fails widen test
-								If Not exprTy.ExtendsType( declTy, noExtendString, True ) Then
-									' but passes non-widen test
-									If exprTy.ExtendsType( declTy, noExtendString, False ) Then
-										' generate a warning, and accept it
-										Warn "In call to " + func.ToString()+ ". Argument #"+(i+1)+" is ~q" + exprTy.ToString()+"~q but declaration is ~q"+declTy.ToString()+"~q. "
-										Continue
-									End If
-								Else
-									Continue
-								End If
-							End If
-						End If
-	
-						' make a more helpful error message
-						errorDetails :+ "Argument #"+(i+1)+" is ~q" + exprTy.ToString()+"~q but declaration is ~q"+declTy.ToString()+"~q. "
-
-					Else If Not argDecls[i].init
-	
-						If (func.attrs & FUNC_PTR) Or isIdentExpr Then
-							exact=False
-							Exit
-						End If
-	
-						' if this argument is missing and there isn't a default...
-						errorDetails :+  "Missing function parameter '" + argDecls[i].ident + "'"
-	
-					Else ' for case of argdecls having default args
-						exact=False
-						If Not explicit Exit
-					EndIf
-				
-					possible=False
-					Exit
-				Next
-				
-				If Not possible Continue
-				
-				If exact
-					If isexact
-						Err "Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
-					Else
-						_err=""
-						'match=func
-						matches.AddLast(func)
-						isexact=True
-						Exit
-					EndIf
-				Else
-					If Not isexact
-						'If match 
-						'	_err="Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
-						'Else
-							'match=func
-							matches.AddLast(func)
-						'EndIf
-					EndIf
-				EndIf
-				'Exit
-			Next
-			
-			If Not matches.IsEmpty() Then
-				Exit
-			End If
-			
-		Next
-		
-		If matches.Count() = 1 Then
-			match = TFuncDecl(matches.First())
-		Else
-			' find best match
-			match = FindBestMatchForArgs(argExprs, matches)
-		End If
-		
-		If Not isexact
-			If _err Err _err
-			If explicit Return Null
-		EndIf
-
-		' last try... maybe we are trying to use it as a function pointer? (no args)
-		If Not match Then
-			If argExprs Then
-				'match = func
-'				match.maybeFunctionPtr = True
-			End If
-		Else If Not argExprs Then
-			' if there are no args, the actual function may have none either... so we may still be trying to use it as a function pointer
-			match.maybeFunctionPtr = True
-		End If
-		
-		If Not match
-			Local t$
-			For Local i:Int=0 Until argExprs.Length
-				If t t:+","
-				If argExprs[i] t:+argExprs[i].exprType.ToString()
-			Next
-			If foundIdentMatch Then
-				If throwOnNotMatched Then
-					Throw "Unable to find overload for "+ident+"("+t+"). " + errorDetails
-				Else
-					Err "Unable to find overload for "+ident+"("+t+"). " + errorDetails
-				End If
-			Else
-				If throwOnNotMatched Then
-					Throw "Identifier '" + ident + "' not found."
-				Else
-					Err "Identifier '" + ident + "' not found."
-				End If
-			End If
-		EndIf
-		
-		match.AssertAccess
-
-		Return match
-	End Method
-
-	Method FindLoop:TStmt(ident:String = Null)
-
-		If TBlockDecl(Self) And TBlockDecl(Self).extra Then
-			Local loop:TLoopStmt = TLoopStmt(TBlockDecl(Self).extra)
-			If ident Then
-				If loop.loopLabel And loop.loopLabel.IdentLower() = ident Then
-					Return loop
-				End If
-			Else
-				Return loop
-			End If
-		End If
-
-		If TFuncDecl(scope) Or TModuleDecl(scope)
-			Return Null
-		End If
-		
-		If scope Return scope.FindLoop( ident )
-	End Method
-	
-	Method OnSemant()
-	End Method
-	
-	Method Clear()
-	End Method
-
-End Type
-
-Type TBlockDecl Extends TScopeDecl
-	Field stmts:TList=New TList
-	Field extra:Object
-	
-	Method Create:TBlockDecl( scope:TScopeDecl, generated:Int = False )
-		Self.scope=scope
-		Self.generated = generated
-		
-		attrs :| (scope.attrs & DECL_NODEBUG)
-		
-		Return Self
-	End Method
-	
-	Method AddStmt( stmt:TStmt )
-		stmts.AddLast stmt
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Local t:TBlockDecl=New TBlockDecl
-		t.scope = scope
-		If deep Then
-			For Local stmt:TStmt=EachIn stmts
-				t.AddStmt stmt.Copy( t )
-			Next
-		End If
-		t.extra = extra
-		t.generated = generated
-		Return t
-	End Method
-
-	Method OnSemant()
-		PushEnv Self
-		For Local stmt:TStmt=EachIn stmts
-			stmt.Semant
-		Next
-		PopEnv
-	End Method
-
-	Method CopyBlock:TBlockDecl( scope:TScopeDecl )
-		Local t:TBlockDecl=TBlockDecl( Copy() )
-		t.scope=scope
-		Return t
-	End Method
-
-	Method Clear()
-		For Local stmt:TStmt=EachIn stmts
-			stmt.Clear
-		Next
-	End Method
-
-End Type
-
-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_BUILTIN:Int = $0080
-Const FUNC_PTR:Int=      $0100
-Const FUNC_INIT:Int =    $0200
-Const FUNC_NESTED:Int =  $0400
-Const FUNC_OPERATOR:Int= $0800
-Const FUNC_FIELD:Int=    $1000
-
-'Fix! A func is NOT a block/scope!
-'
-Type TFuncDecl Extends TBlockDecl
-
-	Field retType:TType
-	Field retTypeExpr:TType
-	Field argDecls:TArgDecl[]
-
-	Field overrides:TFuncDecl
-	Field superCtor:TInvokeSuperExpr
-	
-	Field castTo:String
-	Field noCastGen:Int
-	
-	Field maybeFunctionPtr:Int
-	
-	Field returnTypeSubclassed:Int
-	
-	Field mangled:String
-	Field noMangle:Int
-	
-	Field equalsBuiltIn:Int = -1
-	
-	Method CreateF:TFuncDecl( ident$,ty:TType,argDecls:TArgDecl[],attrs:Int )
-		Self.ident=ident
-		Self.retTypeExpr=ty
-		If argDecls
-			Self.argDecls=argDecls
-		Else
-			Self.argDecls = New TArgDecl[0]
-		End If
-		Self.attrs=attrs
-		Return Self
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Local args:TArgDecl[]=argDecls[..]
-		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)
-		If deep Then
-			For Local stmt:TStmt=EachIn stmts
-				t.AddStmt stmt.Copy( t )
-			Next
-		End If
-		t.retType = retType
-		t.retTypeExpr = retTypeExpr
-		t.scope = scope
-		t.overrides = overrides
-		t.superCtor = superCtor
-		t.castTo = castTo
-		t.noCastGen = noCastGen
-		t.munged = munged
-		t.metadata = metadata
-		t.mangled = mangled
-		t.noMangle = noMangle
-		Return  t
-	End Method
-
-	Method GenInstance:TDecl()
-		Local inst:TFuncDecl=New TFuncDecl
-		InitInstance inst
-		inst.retTypeExpr=retTypeExpr
-		inst.argDecls=argDecls[..]
-		For Local i:Int=0 Until argDecls.Length
-			inst.argDecls[i]=TArgDecl( argDecls[i].GenInstance() )
-		Next
-		Return inst
-	End Method
-	
-	Method ToString$()
-		Local t$
-		For Local decl:TArgDecl=EachIn argDecls
-			If t t:+","
-			t:+decl.ToString()
-		Next
-		Local q$
-		If IsCtor()
-			q="Method "+Super.ToString()
-		Else
-			If IsMethod() q="Method " Else q="Function "
-			q:+Super.ToString()
-			If retType
-				If Not TVoidType(retType) Then
-					q:+":"+retType.ToString()
-				End If
-			Else If retTypeExpr 
-				q:+":"+retTypeExpr.ToString()
-			'Else
-			'	q:+":"+"?"
-			EndIf
-		EndIf
-		Return q+"("+t+")"
-	End Method
-
-	Method ToTypeString:String()
-		Local t$
-		For Local decl:TArgDecl=EachIn argDecls
-			If t t:+","
-			t:+decl.ToTypeString()
-		Next
-		Local q$
-		If Not IsCtor() Then
-			If retType
-				If Not TVoidType(retType) Then
-					q:+retType.ToString()
-				End If
-			Else If retTypeExpr 
-				q:+retTypeExpr.ToString()
-			EndIf
-		End If
-		Return q+"("+t+")"
-	End Method
-
-	Method IsBuiltIn:Int()
-		Return (attrs & FUNC_BUILTIN)<>0
-	End Method
-	
-	Method IsCtor:Int()
-		Return (attrs & FUNC_CTOR)<>0
-	End Method
-
-	Method IsDtor:Int()
-		Return (attrs & FUNC_DTOR)<>0
-	End Method
-
-	Method IsMethod:Int()
-		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
-	
-	Method IsProperty:Int()
-		Return (attrs & FUNC_PROPERTY)<>0
-	End Method
-
-	Method IsField:Int()
-		Return (attrs & FUNC_FIELD)<>0
-	End Method
-		
-	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
-			' 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 ) ' careful, this is not commutative!
-		If IsCtor() Then
-			Return EqualsArgs( decl )
-		Else
-			' 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
-
-		If isCtor() Or isDtor() Then
-			If ClassScope() And ClassScope().IsInterface() Then
-				Err ident + "() cannot be declared in an Interface."
-			End If
-		End If
-
-		'semant ret type
-		If Not retTypeExpr Then
-			If Not retType Then ' may have previously been set (if this is a function pointer)
-				retType = TType.voidType
-			Else If TIdentType(retType)
-				retType = retType.Semant()
-			Else
-				' for Strict code, a void return type becomes Int
-				If TVoidType(retType) And Not ModuleScope().IsSuperStrict() Then
-					strictVoidToInt = True
-					retType = New TIntType
-				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
-			If TVoidType(retType) And Not ModuleScope().IsSuperStrict() And Not IsDTor() Then
-				strictVoidToInt = True
-				retType = New TIntType
-			End If
-		End If
-		
-		If TArrayType( retType ) And Not retType.EqualsType( retType.ActualType() )
-'			Err "Return type cannot be an array of generic objects."
-		EndIf
-		
-		'semant args
-		For Local arg:TArgDecl=EachIn argDecls
-			InsertDecl arg
-			arg.Semant
-		Next
-
-		' if we are a function pointer declaration, we just want to semant the args here.
-		If attrs & FUNC_PTR Return
-
-		If actual<>Self Return
-		
-		'check for duplicate decl
-		If ident Then
-			For Local decl:TFuncDecl=EachIn scope.SemantedFuncs( ident )
-				If decl<>Self And EqualsArgs( decl ) And Not decl.IsCTOR()
-					Err "Duplicate declaration "+ToString()
-				EndIf
-				If noMangle Then
-					If decl<>Self Then
-						If decl.argDecls.Length = 0 Then
-							Err "You cannot apply NoMangle to the function, as another function with no arguments exists."
-						Else If decl.NoMangle Then
-							Err "Another function is already declared with NoMangle."
-						End If
-					End If
-				End If
-			Next
-		End If
-		
-		' any nested functions?
-		For Local fdecl:TFuncDecl = EachIn _decls
-			fdecl.Semant
-		Next
-		
-		'get cdecl, sclasss
-		Local cdecl:TClassDecl=ClassScope(),sclass:TClassDecl
-		If cdecl sclass=TClassDecl( cdecl.superClass )
-		
-		'prefix call to super ctor if necessary
-'		If IsCtor() And superCtor=Null And sclass
-'			If sclass.FindFuncDecl( "new", Null )
-'				superCtor=New TInvokeSuperExpr.Create( "new" )
-'				stmts.AddFirst New TExprStmt.Create( superCtor )
-'			EndIf
-'		EndIf
-		
-		'check we exactly match an override
-		If sclass 'And IsMethod()
-
-			While sclass
-				Local errorDetails:String = ""
-
-				Local found:Int
-				For Local decl:TFuncDecl=EachIn sclass.FuncDecls( )
-					
-					If decl.IdentLower() = IdentLower() Then
-
-						If IdentLower() = "new" Continue
-						If IdentLower() = "delete" Continue
-
-						found=True
-
-						If Not decl.IsSemanted() Then
-							decl.Semant
-						End If
-
-						' check void return type strictness, and fail if appropriate.
-						Local voidReturnTypeFail:Int = False
-						' super has void return type... so it is superstrict (or inherited from)
-						If TVoidType(decl.retType) And TIntType(retType) Then
-							' if we are only strict, we may fail on type mismatch
-							If Not ModuleScope().IsSuperStrict() Then
-								' we have the option of upgrading our return type to match superstrict parent
-								If opt_strictupgrade And strictVoidToInt Then
-									retType = TType.voidType
-								Else
-									' otherwise...
-									voidReturnTypeFail = True
-								End If
-							End If
-						End If
-
-						If EqualsFunc( decl ) And Not voidReturnTypeFail
-
-							' check we aren't attempting to assign weaker access modifiers
-							If (IsProtected() And decl.IsPublic()) Or (IsPrivate() And (decl.IsProtected() Or decl.IsPublic())) Then
-							
-								Err PrivilegeError(Self, decl)
-							
-							End If
-						
-							If (TObjectType(retType) And TObjectType(decl.retType )) Or (TArrayType(retType) And TArrayType(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. "
-								If voidReturnTypeFail Then
-									errorDetails :+ "You may have Strict type overriding SuperStrict type. "
-								End If
-							Else
-								found = False
-								Continue
-							End If
-
-							Local argCount:Int = Min(argDecls.Length, decl.argDecls.Length)
-							If argCount > 0
-								For Local i:Int=0 Until argCount
-									If Not argDecls[i].ty.EqualsType( decl.argDecls[i].ty )
-										errorDetails :+ "Argument #"+(i+1)+" is ~q" + argDecls[i].ty.ToString()+"~q, expected ~q"+decl.argDecls[i].ty.ToString()+"~q. "
-									End If
-								Next
-							EndIf
-							'remove last space
-							errorDetails = errorDetails.Trim()
-						EndIf
-					End If
-				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
-					
-					Exit
-				EndIf
-				sclass=sclass.superClass
-			Wend
-		EndIf
-
-		'append a return statement if necessary
-		If Not IsExtern() And Not TVoidType( retType ) And Not TReturnStmt( stmts.Last() )
-			If Not isCtor() And Not isDtor()
-				Local stmt:TReturnStmt
-
-				stmt=New TReturnStmt.Create( New TConstExpr.Create( retType,"" ) )
-				stmt.generated = True
-
-				stmt.errInfo=errInfo
-				stmts.AddLast stmt
-			End If
-		EndIf
-
-		attrs:|DECL_SEMANTED
-		
-		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
-
-	Function PrivilegeError:String(decl:TFuncDecl, decl2:TFuncDecl)
-		Local p:String
-		If decl.IsProtected() Then
-			p = "Protected"
-		Else
-			p = "Private"
-		End If
-		
-		Local dp:String
-		If decl2.IsPublic() Then
-			dp = "Public"
-		Else
-			dp = "Protected"
-		End If
-	
-		Return decl.ToString() + " clashes with " + decl2.ToString() + ". Attempt to assign weaker access privileges ('" + p + "'), was '" + dp + "'."
-	End Function
-	
-End Type
-
-Type TNewDecl Extends TFuncDecl
-
-	Field chainedCtor:TNewExpr
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Local args:TArgDecl[]=argDecls[..]
-		For Local i:Int=0 Until args.Length
-			args[i]=TArgDecl( args[i].Copy() )
-		Next
-		Local t:TNewDecl = TNewDecl(New TNewDecl.CreateF( ident,retType,args,attrs &~DECL_SEMANTED ))
-		If deep Then
-			For Local stmt:TStmt=EachIn stmts
-				t.AddStmt stmt.Copy(Null)
-			Next
-		End If
-		t.retType = retType
-		t.scope = scope
-		t.overrides = overrides
-		t.superCtor = superCtor
-		t.castTo = castTo
-		t.noCastGen = noCastGen
-		t.munged = munged
-		t.metadata = metadata
-		t.mangled = mangled
-		t.noMangle = noMangle
-		t.chainedCtor = chainedCtor
-
-		Return  t
-	End Method
-
-
-End Type
-
-
-'Const CLASS_INTERFACE:Int=1
-'Const CLASS_TEMPLATEARG:Int=2
-'Const CLASS_TEMPLATEINST:Int=4
-'Const CLASS_INSTANCED:Int=8		'class used in New?
-Const CLASS_INSTANCED:Int=1
-Const CLASS_EXTENDSOBJECT:Int=2
-Const CLASS_FINALIZED:Int=4
-
-Type TNullDecl Extends TClassDecl
-
-End Type
-
-Type TClassDecl Extends TScopeDecl
-
-	Field lastOffset:Int
-
-	Field args:TTemplateArg[]
-	Field superTy:TIdentType
-	Field impltys:TIdentType[]
-
-	Field superClass:TClassDecl
-	
-	Field implments:TClassDecl[]			'interfaces immediately implemented
-	Field implmentsAll:TClassDecl[]		'all interfaces implemented
-	
-	Field instanceof:TClassDecl			'for instances
-	Field instances:TList		'for actual (non-arg, non-instance)
-	Field instArgs:TType[]
-
-	Field objectType:TObjectType '"canned" objectType
-	Field globInit:Int
-	Field templateSource:TTemplateRecord
-
-	'Global nullObjectClass:TClassDecl=New TNullDecl.Create( "{NULL}",Null,Null,Null,DECL_ABSTRACT|DECL_EXTERN )
-	
-	Method Create:TClassDecl( ident$,args:TTemplateArg[],superTy:TIdentType,impls:TIdentType[],attrs:Int )
-		Self.ident=ident
-		Self.args=args
-		Self.superTy=superTy
-		Self.impltys=impls
-		Self.attrs=attrs
-		Self.objectType=New TObjectType.Create( Self )
-		If args
-			instances=New TList
-		EndIf
-		Return Self
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		InternalErr
-	End Method
-	
-	Method ToString$()
-		Local t$
-
-		If args Then
-			For Local i:Int=0 Until args.Length
-				If i Then
-					t :+ ","
-				End If
-				t:+args[i].ToString()
-			Next
-		ElseIf instargs
-			For Local i:Int=0 Until instargs.Length
-				If i Then
-					t :+ ","
-				End If
-				t :+ instargs[i].ToString()
-			Next
-		End If
-		If t t="<"+t+">"
-		Return ident+t
-	End Method
-
-	Method ToTypeString:String()
-		Return ToString()
-	End Method
-Rem
-	Method GenClassInstance:TClassDecl( instArgs:TClassDecl[] )
-		If Not IsSemanted() InternalErr
-		
-		'no args
-		If Not instArgs
-			If Not args Return Self
-			If instanceof Return Self
-			For Local inst:TClassDecl=EachIn instances
-				If _env.ClassScope()=inst Return inst
-			Next
-		EndIf
-		
-		'If Not instanceof And Not instArgs Return Self
-		
-		'check number of args
-		If instanceof Or args.Length<>instArgs.Length
-			Err "Wrong number of class arguments for "+ToString()
-		EndIf
-		
-		'look for existing instance
-		For Local inst:TClassDecl=EachIn instances
-			Local equal:Int=True
-			For Local i:Int=0 Until args.Length
-				If inst.args[i]=instArgs[i] Continue
-				equal=False
-				Exit
-			Next
-			If equal Return inst
-		Next
-		
-		Local inst:TClassDecl=New TClassDecl
-
-		InitInstance inst
-
-		inst.scope=scope
-		inst.attrs:|CLASS_TEMPLATEINST
-		inst.args=instArgs
-		inst.superTy=superTy
-		inst.instanceof=Self
-		instances.AddLast inst
-		
-		For Local i:Int=0 Until args.Length
-			inst.InsertDecl New TAliasDecl.Create( args[i].ident,instArgs[i] )
-		Next
-		
-		For Local decl:TDecl=EachIn _decls
-			If TClassDecl( decl ) Continue
-			inst.InsertDecl decl.GenInstance()
-		Next
-
-		'inst.Semant
-		'A bit cheeky...
-		inst.OnSemant
-		inst.attrs:|DECL_SEMANTED
-		
-		Return inst
-	End Method
-End Rem
-	Method GenClassInstance:TClassDecl( instArgs:TType[], declImported:Int = False )
-
-		If instanceof InternalErr
-		
-		'no args
-		If Not instArgs
-			If Not args Return Self
-			For Local inst:TClassDecl=EachIn instances
-				If _env.ClassScope()=inst Return inst
-			Next
-		EndIf
-		
-		'check number of args
-		If args.Length<>instArgs.Length
-			Err "Wrong number of type arguments for class "+ToString()
-		EndIf
-		
-		'look for existing instance
-		For Local inst:TClassDecl=EachIn instances
-			Local equal:Int=True
-			For Local i:Int=0 Until args.Length
-				If Not inst.instArgs[i].EqualsType( instArgs[i] )
-					equal=False
-					Exit
-				EndIf
-			Next
-			If equal Return inst
-		Next
-
-		Local inst:TClassDecl=New TClassDecl.Create( ident,Null,superTy,impltys, attrs )
-
-		inst.attrs:&~DECL_SEMANTED
-
-		inst.munged=munged
-		inst.errInfo=errInfo
-		inst.scope=scope
-		inst.instanceof=Self
-		inst.instArgs=instArgs
-		inst.templateSource = templateSource
-		instances.AddLast inst
-		
-		inst.declImported = declImported
-
-		For Local i:Int=0 Until args.Length
-		
-			' ensure parameter types are compatible
-			If args[i].superTy Then
-				args[i].superTy = args[i].superTy.Semant()
-				If Not instArgs[i].EqualsType(args[i].superTy) And Not instArgs[i].ExtendsType(args[i].superTy) Then
-					Err "Type parameter '" + instArgs[i].ToString() + "' is not within its bound; should extend '" + args[i].superTy.ToString() + "'"
-				End If
-			End If
-		
-			inst.InsertDecl New TAliasDecl.Create( args[i].ident,instArgs[i],0 )
-		Next
-
-		For Local decl:TDecl=EachIn _decls
-			inst.InsertDecl decl.Copy(), True
-		Next
-
-		If Not declImported Then
-			inst.scope = _env.ModuleScope()
-		End If
-
-		Return inst
-	End Method
-
-	Method IsInterface:Int()
-		Return (attrs & CLASS_INTERFACE)<>0
-	End Method
-
-	Method IsThrowable:Int()
-		Return (attrs & CLASS_THROWABLE)<>0
-	End Method
-
-	Method IsFinalized:Int()
-		Return (attrs & CLASS_FINALIZED)<>0
-	End Method
-	
-	Method IsStruct:Int()
-		Return (attrs & CLASS_STRUCT)<>0
-	End Method
-
-	Method ExtendsObject:Int()
-		Return (attrs & CLASS_EXTENDSOBJECT)<>0
-	End Method
-	
-	Method IsInstanced:Int()
-		Return (attrs & CLASS_INSTANCED)<>0
-	End Method
-	
-	Method GetDecl:Object( ident$ )
-	
-		Local cdecl:TClassDecl=Self
-		While cdecl
-			Local decl:Object=cdecl.GetDecl2( ident )
-			If decl Return decl
-			
-			cdecl=cdecl.superClass
-		Wend
-
-	End Method
-	
-	'needs this 'coz you can't go blah.Super.GetDecl()...
-	Method GetDecl2:Object( ident$ )
-		Return Super.GetDecl( ident )
-	End Method
-
-	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
-	
-		If Not declList Then
-			declList = New TFuncDeclList
-		End If
-	
-		Local cdecl:TClassDecl=Self
-		While cdecl
-			Local decl:Object=cdecl.GetDeclList2( ident, declList, maxSearchDepth )
-			'If decl And (Not TFuncDeclList(decl) And declList.IsEmpty()) Return decl
-			If decl Then
-				declList.AddLast(decl)
-			End If
-
-			cdecl=cdecl.superClass
-			
-			If maxSearchDepth < SCOPE_CLASS_HEIRARCHY Then
-				Exit
-			End If
-		Wend
-
-		Return declList
-	End Method
-	
-	'needs this 'coz you can't go blah.Super.GetDecl()...
-	Method GetDeclList2:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
-		Return Super.GetDeclList( ident, declList, maxSearchDepth )
-	End Method
-	
-	Method FindFuncDecl:TFuncDecl( ident$,args:TExpr[] = Null ,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False, maxSearchDepth:Int )
-	
-		' try the super first...
-		Local funcDecl:TFuncDecl = Super.FindFuncDecl(ident, args, explicit, isArg, isIdentExpr, throwOnNotMatched, maxSearchDepth)
-		If funcDecl Then
-			Return funcDecl
-		End If
-	
-	
-		If args = Null Then
-			args = New TExpr[0]
-		End If
-	
-		If Not IsInterface()
-			' try getdecl first&
-			Local decl:TFuncDecl = TFuncDecl(GetDecl(ident))
-			If decl Then
-				Return decl
-			End If
-			Return FindFuncDecl2( ident,args,explicit,isIdentExpr )
-		EndIf
-		
-		Local fdecl:TFuncDecl=FindFuncDecl2( ident,args,True )
-		
-		For Local iface:TClassDecl=EachIn implmentsAll
-			Local decl:TFuncDecl=iface.FindFuncDecl2( ident,args,True )
-			If Not decl Continue
-			
-			If fdecl
-				If fdecl.EqualsFunc( decl ) Continue
-				Err "Unable to determine overload to use: "+fdecl.ToString()+" or "+decl.ToString()+"."
-			EndIf
-			fdecl=decl
-		Next
-		
-		If fdecl Or explicit Return fdecl
-		
-		fdecl=FindFuncDecl2( ident,args,False )
-		
-		For Local iface:TClassDecl=EachIn implmentsAll
-			Local decl:TFuncDecl=iface.FindFuncDecl2( ident,args,False )
-			If Not decl Continue
-			
-			If fdecl
-				If fdecl.EqualsFunc( decl ) Continue
-				Err "Unable to determine overload to use: "+fdecl.ToString()+" or "+decl.ToString()+"."
-			EndIf
-			fdecl=decl
-		Next
-		
-		Return fdecl
-	End Method
-	
-	Method FindFuncDecl2:TFuncDecl( ident$,args:TExpr[],explicit:Int, isIdentExpr:Int = False )
-		Return Super.FindFuncDecl( ident,args,explicit,,isIdentExpr,0,0 )
-	End Method
-	
-	Method GetAllFuncDecls:TFuncDecl[](funcs:TFuncDecl[] = Null, includeSuper:Int = True)
-
-		If Not funcs Then
-			funcs = New TFuncDecl[0]
-		End If
-		
-		If superClass And includeSuper Then
-			funcs = superClass.GetAllFuncDecls(funcs)
-		End If
-
-		' interface methods
-		For Local iface:TClassDecl=EachIn implmentsAll
-			funcs = iface.GetAllFuncDecls(funcs)
-		Next
-		
-		For Local func:TFuncDecl = EachIn _decls
-		
-			Local matched:Int = False
-			
-			For Local i:Int = 0 Until funcs.length
-				' found a match - we are overriding it
-				If func.IdentLower() = funcs[i].IdentLower() 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
-				End If
-			Next
-			
-			If Not matched Then
-				funcs :+ [func]
-			End If
-		
-		Next
-		
-		Return funcs
-	End Method
-
-	' returns a list of original function decls (i.e. decls in the scope of their original declarations).
-	' this is useful for generating vtables for extern types
-	Method GetAllOriginalFuncDecls:TFuncDecl[](funcs:TFuncDecl[] = Null, includeSuper:Int = True)
-		If Not funcs Then
-			funcs = New TFuncDecl[0]
-		End If
-		
-		If superClass And includeSuper Then
-			funcs = superClass.GetAllOriginalFuncDecls(funcs, True)
-		End If
-
-		' interface methods
-		For Local iface:TClassDecl=EachIn implmentsAll
-			For Local func:TFuncDecl=EachIn iface._decls
-				Local matched:Int = False
-
-'				For Local i:Int = 0 Until funcs.length
-'					' found a match - we are overriding it
-'					If func.IdentLower() = funcs[i].IdentLower() Then
-'						matched = True
-'						Exit
-'					End If
-'				Next
-				
-				If Not matched Then
-					funcs :+ [func]
-				End If
-			Next
-		Next
-
-		
-		For Local func:TFuncDecl = EachIn _decls
-		
-			Local matched:Int = False
-			
-			' dont count any that are already in the funcs list
-			For Local i:Int = 0 Until funcs.length
-				' found a match - we are overriding it
-				If func.IdentLower() = funcs[i].IdentLower() And func.EqualsArgs(funcs[i]) Then
-					matched = True
-					' set this to our own func
-					'funcs[i] = func
-					Exit
-				End If
-			Next
-			
-			If Not matched Then
-				funcs :+ [func]
-			End If
-		
-		Next
-		
-		Return funcs
-	End Method
-
-	Method GetOriginalFuncDecl:TFuncDecl(fdecl:TFuncDecl)
-		If Not TClassDecl(Self) Then
-			Return fdecl
-		End If
-		
-		If superClass Then
-			Local decl:TFuncDecl = superClass.GetOriginalFuncDecl(fdecl)
-			If decl <> fdecl Then
-				Return decl
-			End If
-		End If
-		
-		For Local func:TFuncDecl = EachIn _decls
-		
-			If func.IdentLower() = fdecl.IdentLower() And func.EqualsArgs(fdecl) Then
-				Return func
-			End If
-		
-		Next
-		
-		Return fdecl
-	End Method
-
-	
-	Method ExtendsClass:Int( cdecl:TClassDecl )
-		'If Self=nullObjectClass Return True
-		
-'		If cdecl.IsTemplateArg()
-'			cdecl=TType.objectType.FindClass()
-'		EndIf
-		
-		Local tdecl_:TClassDecl=Self
-		While tdecl_
-			If tdecl_=cdecl Return True
-			If cdecl.IsInterface()
-				For Local iface:TClassDecl=EachIn tdecl_.implmentsAll
-					If iface=cdecl Return True
-				Next
-			EndIf
-			tdecl_=tdecl_.superClass
-		Wend
-		
-		Return False
-	End Method
-	
-	Method OnSemant()
-	
-		If args Then
-			Return
-		End If
-
-		PushEnv Self
-
-		'If Not IsTemplateInst()
-		'	For Local i:Int=0 Until args.Length
-		'		InsertDecl args[i]
-		'		args[i].Semant
-		'	Next
-		'EndIf
-
-		'Semant superclass		
-		If superTy
-			'superClass=superTy.FindClass()
-			superClass=superTy.SemantClass()
-			If superClass.IsInterface() Then
-				If Not IsExtern() Or Not superClass.IsExtern() Err superClass.ToString()+" is an interface, not a class."
-				If (IsExtern() And Not superClass.IsExtern()) Or (superClass.IsExtern() And Not IsExtern()) Err "Extern and non extern types cannot be mixed."
-			End If
-			If superClass.IsFinal() Err "Final types cannot be extended."
-		EndIf
-		
-		'Semant implemented interfaces
-		Local impls:TClassDecl[]=New TClassDecl[impltys.Length]
-		Local implsall:TStack=New TStack
-		For Local i:Int=0 Until impltys.Length
-			attrs :| DECL_CYCLIC
-			Local cdecl:TClassDecl=impltys[i].SemantClass()
-			attrs :~ DECL_CYCLIC
-			If Not cdecl.IsInterface()
-				Err cdecl.ToString()+" is a type, not an interface."
-			EndIf
-			For Local j:Int=0 Until i
-				If impls[j]=cdecl
-					Err "Duplicate interface "+cdecl.ToString()+"."
-				EndIf
-			Next
-			impls[i]=cdecl
-			implsall.Push cdecl
-			For Local tdecl_:TDecl=EachIn cdecl.implmentsAll
-				implsall.Push tdecl_
-			Next
-		Next
-		Local length:Int = implsall.Length()
-		implmentsAll=New TClassDecl[length]
-		For Local i:Int=0 Until length
-			implmentsAll[i]=TClassDecl(implsall.Get(length - i - 1))
-		Next
-		implments=impls
-
-		Rem
-		If IsInterface()
-			'add implemented methods to our methods
-			For Local iface:=EachIn implmentsAll
-				For Local decl:=EachIn iface.FuncDecls
-					InsertAlias decl.ident,decl
-				Next
-			Next
-		EndIf
-		EndRem
-				
-'		attrs|=DECL_SEMANTED
-		
-		PopEnv
-		
-		'If IsTemplateArg()
-		'	actual=TType.objectType.FindClass()
-		'	Return
-		'EndIf
-		
-		'If IsTemplateInst()
-		'	Return
-		'EndIf
-		
-		'Are we abstract?
-		If Not IsAbstract()
-			For Local decl:TDecl=EachIn _decls
-				Local fdecl:TFuncDecl=TFuncDecl( decl )
-				If fdecl And fdecl.IsAbstract()
-					attrs:|DECL_ABSTRACT
-					Exit
-				EndIf
-			Next
-		EndIf
-		
-		If Not lastOffset And superClass Then
-			lastOffset = superClass.LastOffset
-		End If
-
-		For Local decl:TFieldDecl=EachIn _decls
-			GetFieldOffset(decl)
-		Next
-
-		If Not IsExtern() And Not IsInterface()
-			Local fdecl:TFuncDecl
-			For Local decl:TFuncDecl=EachIn FuncDecls()
-				If Not decl.IsCtor() Continue
-				Local nargs:Int
-				For Local arg:TArgDecl=EachIn decl.argDecls
-					If Not arg.init nargs:+1
-				Next
-				If nargs Continue
-				fdecl=decl
-				Exit
-			Next
-			
-			
-			' Don't need default new?
-			'If Not fdecl
-			'	fdecl=New TFuncDecl.CreateF( "new",New TObjectType.Create( Self ),Null,FUNC_CTOR )
-			'	fdecl.AddStmt New TReturnStmt.Create( Null )
-			'	InsertDecl fdecl
-			'EndIf
-		EndIf
-
-		'NOTE: do this AFTER super semant so UpdateAttrs order is cool.
-
-		If AppScope() Then
-			AppScope().semantedClasses.AddLast Self
-		End If
-	End Method
-	
-	Method SemantParts()
-'		If IsSemanted() Return
-		
-'		Super.Semant()
-		If args Then
-			Return
-		End If
-		
-		For Local decl:TConstDecl = EachIn Decls()
-			decl.Semant()
-		Next
-
-		For Local decl:TGlobalDecl = EachIn Decls()
-			decl.Semant()
-		Next
-
-		' NOTE : we can't semant functions here as they cause cyclic errors.
-		For Local decl:TFuncDecl = EachIn Decls()
-			decl.Semant()
-		Next
-
-		For Local decl:TFieldDecl = EachIn Decls()
-			decl.Semant()
-		Next
-
-	End Method
-	
-	'Ok, this dodgy looking beast 'resurrects' methods that may not currently be alive, but override methods that ARE.
-	Method UpdateLiveMethods:Int()
-	
-		If IsInterface() Return 0
-
-		If Not superClass Return 0
-
-		Local n:Int
-		For Local decl:TFuncDecl=EachIn MethodDecls()
-			If decl.IsSemanted() Continue
-			
-			Local live:Int
-			Local unsem:TList=New TList'<TFuncDecl>
-			
-			unsem.AddLast decl
-			
-			Local sclass:TClassDecl=superClass
-			While sclass
-				For Local decl2:TFuncDecl=EachIn sclass.MethodDecls( decl.ident )
-					If decl2.IsSemanted()
-						live=True
-					Else
-						unsem.AddLast decl2
-						If decl2.IsExtern() live=True
-						If decl2.actual.IsSemanted() live=True
-					EndIf
-				Next
-				sclass=sclass.superClass
-			Wend
-			
-			If Not live
-				Local cdecl:TClassDecl=Self
-				While cdecl
-					For Local iface:TClassDecl=EachIn cdecl.implmentsAll
-						For Local decl2:TFuncDecl=EachIn iface.MethodDecls( decl.ident )
-							If decl2.IsSemanted()
-								live=True
-							Else
-								unsem.AddLast decl2
-								If decl2.IsExtern() live=True
-								If decl2.actual.IsSemanted() live=True
-							EndIf
-						Next
-					Next
-					cdecl=cdecl.superClass
-				Wend
-			EndIf
-			
-			If Not live Continue
-			
-			For Local decl:TDecl=EachIn unsem
-				decl.Semant
-				n:+1
-			Next
-		Next
-		
-		Return n
-	End Method
-	
-	Method FinalizeClass()
-	
-		SemantParts()
-
-		PushErr errInfo
-		
-		If Not IsInterface()
-			'
-			'check for duplicate fields! - BlitzMax supports fields with the same name in subclasses..
-			'
-			'For Local decl:TDecl=EachIn Semanted()
-			'	Local fdecl:TFieldDecl=TFieldDecl( decl )
-			'	If Not fdecl Continue
-			'	Local cdecl:TClassDecl=superClass
-			'	While cdecl
-			'		For Local decl:TDecl=EachIn cdecl.Semanted()
-			'			If decl.ident=fdecl.ident Err "Field '"+fdecl.ident+"' in class "+ToString()+" overrides existing declaration in class "+cdecl.ToString()
-			'		Next
-			'		cdecl=cdecl.superClass
-			'	Wend
-			'Next
-			'
-			'Check we implement all abstract methods!
-			'
-			If IsInstanced()
-				Local cdecl:TClassDecl=Self
-				Local impls:TList=New TList'<TFuncDecl>
-				While cdecl
-					For Local decl:TFuncDecl=EachIn cdecl.SemantedMethods()
-						If decl.IsAbstract()
-							Local found:Int
-							For Local decl2:TFuncDecl=EachIn impls
-								If decl.IdentLower() = decl2.IdentLower() And decl2.EqualsFunc( decl )
-									found=True
-									Exit
-								EndIf
-							Next
-							If Not found
-								Err "Can't create instance of type "+ToString()+" due to abstract method "+decl.ToString()+"."
-							EndIf
-						Else
-							impls.AddLast decl
-						EndIf
-					Next
-					cdecl=cdecl.superClass
-				Wend
-			EndIf
-			'
-			'Check we implement all interface methods!
-			'
-			If Not IsAbstract() Then
-
-				Local ints:TMap = GetInterfaces()
-
-				For Local iface:TClassDecl=EachIn ints.Values()
-				
-					If (Not IsExtern() And iface.IsExtern()) Or (IsExtern() And Not iface.IsExtern()) Then
-						Err "Cannot mix Extern and non Extern Types and Interfaces."
-					End If
-				
-					For Local decl:TFuncDecl=EachIn iface.SemantedMethods()
-						Local found:Int
-
-						Local cdecl:TClassDecl=Self
-						
-						While cdecl And Not found
-							For Local decl2:TFuncDecl=EachIn cdecl.SemantedMethods( decl.ident )
-								' equals (or extends - for object types)
-								If decl2.EqualsFunc( decl )
-									If Not decl2.IsPublic() Then
-										' error on function decl
-										PushErr decl2.errInfo
-										Err TFuncDecl.PrivilegeError(decl2, decl)
-									End If
-									found=True
-									Exit
-								EndIf
-							Next
-						
-							cdecl = cdecl.superClass
-						Wend
-
-						If Not found
-							Err decl.ToString() + " must be implemented by type " + ToString()
-						EndIf
-					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 decl2.argDecls.Length = decl.argDecls.Length And 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
-		
-		Local modifier:Int = POINTER_SIZE
-		
-		If TIntType(ty) Or TFloatType(ty) Or TUIntType(ty) Then
-			modifier = 4
-		Else If TShortType(ty) Then
-			modifier = 2
-		Else If TLongType(ty) Or TDoubleType(ty) Or TULongType(ty) Then
-			modifier = 8
-		Else If TByteType(ty) Then
-			modifier = 1
-		Else If TSizeTType(ty) Then
-			modifier = WORD_SIZE
-		End If
-
-		If modifier > 1 And lastOffset Mod modifier Then
-			lastOffset :+ modifier - (lastOffset Mod modifier)
-		End If
-		
-		decl.offset = lastOffset
-		
-		lastOffset :+ modifier
-	End Method
-	
-	Method ImplementsInterface:Int(ident:String)
-		ident = ident.ToLower()
-		For Local iface:TClassDecl = EachIn implmentsAll
-			If iface.IdentLower() = ident Then
-				Return True
-			End If
-		Next
-		Return False
-	End Method
-	
-	' returns a map of all interfaces implemented in this hierarchy
-	Method GetInterfaces:TMap(map:TMap = Null)
-		If Not map Then
-			map = New TMap
-		End If
-
-		For Local iface:TClassDecl=EachIn implmentsAll
-		
-			If iface.IsInterface() Then
-			
-				Local cdecl:TClassDecl = iface
-				While cdecl
-				
-					If cdecl.IsInterface() Then
-						If Not map.Contains(cdecl) Then
-							map.Insert(cdecl, cdecl)
-						End If
-					End If
-
-
-					cdecl=cdecl.superClass
-				Wend
-			
-			End If
-		Next
-
-		
-		If superClass Then
-			map = superClass.GetInterfaces(map)
-		End If
-		
-		Return map
-	End Method
-	
-	Method GetImplementedFuncs:TList(list:TList = Null)
-		If Not list Then
-			list = New TList
-		End If
-		
-		For Local idecl:TClassDecl = EachIn implmentsAll
-			idecl.GetImplementedFuncs(list)
-		Next
-		
-		For Local decl:TFuncDecl = EachIn SemantedMethods()
-			list.AddLast(decl)
-		Next
-
-		Return list
-	End Method
-	
-End Type
-
-Type TLoopLabelDecl Extends TDecl
-
-	Field realIdent:String
-
-	Method Create:TLoopLabelDecl( ident$, attrs:Int=0 )
-		Self.ident="#" + ident
-		Self.realIdent = ident
-		Self.attrs=attrs
-		Return Self
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Return New TLoopLabelDecl.Create( realIdent,attrs )
-	End Method
-	
-	Method OnSemant()
-	End Method
-	
-End Type
-
-Type TDataLabelDecl Extends TDecl
-
-	Field realIdent:String
-	Field index:Int
-
-	Method Create:TDataLabelDecl( ident$, attrs:Int=0 )
-		Self.ident="#" + ident
-		Self.realIdent = ident
-		Self.attrs=attrs
-		Return Self
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Return New TDataLabelDecl.Create( realIdent,attrs )
-	End Method
-	
-	Method OnSemant()
-	End Method
-	
-End Type
-
-Type TDefDataDecl Extends TDecl
-
-	Global count:Int
-
-	Field label:TDataLabelDecl
-	Field data:TExpr[]
-
-	Method Create:TDefDataDecl(data:TExpr[], label:TDataLabelDecl = Null, attrs:Int=0 )
-		Self.data=data
-		Self.label=label
-		Self.attrs=attrs
-		Return Self
-	End Method
-	
-	Method OnCopy:TDecl(deep:Int = True)
-		Return New TDefDataDecl.Create(TExpr.CopyArgs(data),TDataLabelDecl(label.Copy()),attrs)
-	End Method
-
-	Method OnSemant()
-		If data Then
-			If label Then
-				label.index = count
-			End If
-		
-			For Local i:Int = 0 Until data.length
-				data[i] = data[i].Semant()
-				If Not TConstExpr(data[i]) Then
-					Err "Data items must be numeric or strings"
-				Else
-					' todo : more type tests?
-				End If
-				count :+ 1
-			Next
-		Else
-			' err?
-		End If
-	End Method
-	
-End Type
-
-Const MODULE_STRICT:Int=1
-Const MODULE_SUPERSTRICT:Int=2
-Const MODULE_ACTUALMOD:Int=4
-
-Type TNamespaceDecl Extends TScopeDecl
-
-'	Field mods:TMap = New TMap
-
-	Method Create:TNamespaceDecl( ident$,munged$ )
-		Self.ident=ident
-		Self.munged=munged
-		Return Self
-	End Method
-
-'	Method GetDecl:Object( ident$ )
-'		Return mods.ValueForKey(ident.ToLower())
-'	End Method
-	
-End Type
-
-Type TModuleDecl Extends TScopeDecl
-
-	Field filepath$
-	Field relpath$
-	Field imported:TUnorderedMap=New TUnorderedMap'<TModuleDecl>		'Maps filepath to modules
-	Field pubImported:TUnorderedMap =New TUnorderedMap'<TModuleDecl>	'Ditto for publicly imported modules
-
-	Field pmod:TModuleDecl
-
-	Field fileImports:TList=New TList'StringList
-	
-	' cache of ModuleInfo lines
-	Field modInfo:TList = New TList
-
-	Field _getDeclTreeCache:TList
-	
-	Field _getDeclCache:TMap = New TMap
-	Field _getDeclListCache:TMap = New TMap
-
-	Method ToString$()
-		Return "Module "+munged
-	End Method
-	
-	Method Create:TModuleDecl( ident$,munged$,filepath$,attrs:Int )
-		Self.ident=ident
-		Self.munged=munged
-		Self.filepath=filepath
-		Self.attrs=attrs
-
-		If ident.Find(".") <> -1 And ident.find("/") = -1 And ident.find("\") = -1 Then
-			Local m:String = ident[..ident.Find(".")]
-			Local ns:TNamespaceDecl = TNamespaceDecl(_appInstance.GetDecl(m.ToLower()))
-			If Not ns Then
-				ns = New TNamespaceDecl.Create(m, m)
-				If _appInstance.mainModule Then
-					_appInstance.mainModule.InsertDecl(ns)
-				Else
-					' this must be the main module...
-					InsertDecl(ns)
-				End If
-			End If
-			ns.InsertDecl(Self)
-		End If
-
-		Return Self
-	End Method
-
-	Method UpdateFilePath(fp:String)
-		filepath = fp
-	End Method
-	
-	Method AddImport(imp:String, obj:Object)
-		imported.Insert(imp, obj)
-		FlushCaches()
-	End Method
-	
-	Method FlushCaches()
-		_getDeclTreeCache = Null
-		If TModuleDecl(pmod) Then
-			TModuleDecl(pmod).FlushCaches()
-		End If
-	End Method
-	
-	Method IsStrict:Int()
-		Return (attrs & MODULE_STRICT)<>0
-	End Method
-
-	Method IsSuperStrict:Int()
-		Return (attrs & MODULE_SUPERSTRICT)<>0
-	End Method
-	
-	Method IsActualModule:Int()
-		Return (attrs & MODULE_ACTUALMOD)<>0
-	End Method
-	
-	Method GetDecl:Object( ident$ )
-		' if we previously found it, return it from the cache
-		Local decl:Object = _getDeclCache.ValueForKey(ident)
-
-		If decl Then
-			Return decl
-		End If
-		
-		If _getDeclTreeCache Then
-		
-			Local declmod$
-		
-			For Local mdecl:TModuleDecl = EachIn _getDeclTreeCache
-
-				If ident = mdecl.ident
-					_getDeclCache.Insert(ident, mdecl)
-					Return mdecl
-				End If
-			
-				Local tdecl_:Object=mdecl.GetDecl2( ident )
-			
-				If tdecl_ And tdecl_<>decl
-					If mdecl=Self
-						_getDeclCache.Insert(ident, tdecl_)
-						Return tdecl_
-					End If
-					If decl
-						Err "Duplicate identifier '"+ident+"' found in module '"+declmod+"' and module '"+mdecl.ident+"'."
-					EndIf
-					decl=tdecl_
-					declmod=mdecl.ident
-				EndIf
-			Next
-		
-		Else
-		
-			_getDeclTreeCache = New TList
-	
-			Local todo:TList=New TList'<TModuleDecl>
-			'Local done:TIntMap=New TIntMap'<TModuleDecl>
-			Local done:TMap = New TMap
-			
-			todo.AddLast Self
-			'done.Insert _filePathId,Self
-			done.Insert filePath,Self
-			
-			Local declmod$
-			
-			While Not todo.IsEmpty()
-		
-				Local mdecl:TModuleDecl=TModuleDecl(todo.RemoveLast())
-				
-				_getDeclTreeCache.AddLast(mdecl)
-				
-				Local imps:TUnorderedMap=mdecl.imported
-	
-				For Local mdecl2:TModuleDecl=EachIn imps.Values()
-	
-					'If Not done.Contains( mdecl2._filePathId )
-					If Not done.Contains( mdecl2.filePath )
-						todo.AddLast mdecl2
-						'done.Insert mdecl2._filePathId,mdecl2
-						done.Insert mdecl2.filePath,mdecl2
-					EndIf
-					
-				Next
-	
-			Wend
-	
-			Return GetDecl(ident)
-	
-		End If
-			
-		' cache it for next time
-		_getDeclCache.Insert(ident, decl)
-		
-		Return decl
-	End Method
-	
-	Method GetDecl2:Object( ident$ )
-		Return Super.GetDecl( ident )
-	End Method
-
-
-	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
-
-		If Not declList Then
-			declList = New TFuncDeclList
-		End If
-
-		Local decl:Object,declmod$
-
-		If _getDeclTreeCache Then
-		
-'			Print "   Using Cache"
-			
-			Local declmod$
-		
-			For Local mdecl:TModuleDecl = EachIn _getDeclTreeCache
-			
-				If ident = mdecl.ident
-					'_getDeclCache.Insert(identId, mdecl)
-					Return mdecl
-				End If
-			
-				Local tdecl_:Object=mdecl.GetDeclList2( ident, declList, maxSearchDepth )
-			
-				If tdecl_ And tdecl_<>decl
-					If mdecl=Self
-						_getDeclCache.Insert(ident, tdecl_)
-						Return tdecl_
-					End If
-					If decl
-						Err "Duplicate identifier '"+ident+"' found in module '"+declmod+"' and module '"+mdecl.ident+"'."
-					EndIf
-					decl=tdecl_
-					declmod=mdecl.ident
-				EndIf
-			Next
-		
-		Else
-
-			_getDeclTreeCache = New TList
-	
-			Local todo:TList=New TList'<TModuleDecl>
-			Local done:TMap=New TMap'<TModuleDecl>
-			
-			todo.AddLast Self
-			done.Insert filepath,Self
-			
-			'Local decl:Object,declmod$
-			
-			While Not todo.IsEmpty()
-		
-				Local mdecl:TModuleDecl=TModuleDecl(todo.RemoveLast())
-				_getDeclTreeCache.AddLast(mdecl)
-				
-				Local imps:TUnorderedMap=mdecl.imported
-	
-				For Local mdecl2:TModuleDecl=EachIn imps.Values()
-					If Not done.Contains( mdecl2.filepath )
-						todo.AddLast mdecl2
-						done.Insert mdecl2.filepath,mdecl2
-					EndIf
-					
-				Next
-	
-			Wend
-		
-			Return GetDeclList( ident, declList, maxSearchDepth )
-		
-		End If
-		
-		Return decl
-	End Method
-	
-	Method GetDeclList2:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
-		Return Super.GetDeclList( ident, declList, maxSearchDepth )
-	End Method
-
-	Method OnSemant()
-		Local decl:TFuncDecl = FindFuncDecl( "__localmain", ,,,,,SCOPE_MODULE )
-		If decl Then
-			decl.Semant
-		End If
-	
-		For Local gdecl:TGlobalDecl=EachIn _decls
-			gdecl.Semant
-		Next
-
-		For Local cdecl:TClassDecl=EachIn _decls
-			If cdecl.args Then
-				For Local inst:TClassDecl = EachIn cdecl.instances
-					For Local idecl:TDecl = EachIn inst.Decls()
-						If TAliasDecl( idecl ) Continue
-						idecl.Semant()
-					Next
-				Next
-			Else
-				cdecl.Semant
-			End If
-		Next
-
-		For Local fdecl:TFuncDecl=EachIn _decls
-			fdecl.Semant
-		Next
-
-		For Local cdecl:TConstDecl=EachIn _decls
-			cdecl.Semant
-		Next
-	End Method
-
-End Type
-
-Type TAppDecl Extends TScopeDecl
-
-	Field imported:TUnorderedMap=New TUnorderedMap'<TModuleDecl>			'maps modpath->mdecl
-	
-	Field globalImports:TUnorderedMap = New TUnorderedMap
-	
-	Field mainModule:TModuleDecl
-	Field mainFunc:TFuncDecl	
-		
-	Field semantedClasses:TList=New TList'<TClassDecl>			'in-order (ie: base before derived) list of _semanted classes
-	Field semantedGlobals:TList=New TList'<TGlobalDecl>			'in-order (ie: dependancy sorted) list of _semanted globals
-
-	Field fileImports:TList=New TList'StringList
-	Field headers:TList = New TList
-	
-	Field stringConsts:TMap = New TMap
-	Field stringConstCount:Int
-	
-	Field incbins:TList = New TList
-	Field genIncBinHeader:Int = False
-	
-	Field dataDefs:TList = New TList
-	Field scopeDefs:TMap = New TMap
-	
-	Method GetPathPrefix:String()
-		If opt_buildtype = BUILDTYPE_MODULE Then
-			Local prefix:String
-			Local path:String[] = mainModule.filepath.split("/")
-			Local c:Int = 0
-			For Local dir:String = EachIn path
-				If c Then
-					prefix :+ dir.Replace(".mod", "") + "_"
-					c:- 1
-				End If
-				If dir = "mod" Then
-					c = 2
-				End If
-			Next
-		Else
-			Return "bb_"
-		End If
-	End Method
-	
-	Method InsertModule( mdecl:TModuleDecl )
-		mdecl.scope=Self
-		imported.Insert mdecl.filepath,mdecl
-		If Not mainModule
-			mainModule=mdecl
-		EndIf
-	End Method
-	
-	Method IsImported:Int(modpath:String)
-		Return globalImports.Contains(modpath)
-	End Method
-	
-	Method GetDecl:Object( ident$ )
-		Local obj:Object = Super.GetDecl(ident)
-		If Not obj And mainModule Then
-			Return mainModule.GetDecl(ident)
-		End If
-		Return obj
-	End Method
-
-	Method OnSemant()
-'DebugStop		
-		_env=Null
-		pushenv Self
-		
-		SemantDataDefs()	
-
-		mainModule.Semant
-
-		mainFunc=mainModule.FindFuncDecl( "__localmain",,,,,,SCOPE_MODULE )
-		
-		
-		' FIXME
-		If Not mainFunc Err "Function 'Main' not found."
-	
-		SemantDecls()
-
-		Repeat
-			Local more:Int
-			For Local cdecl:TClassDecl=EachIn semantedClasses
-				more:+cdecl.UpdateLiveMethods()
-			Next
-			If Not more Exit
-		Forever
-		
-		For Local cdecl:TClassDecl=EachIn semantedClasses
-			cdecl.FinalizeClass
-		Next
-	End Method
-	
-	Method SemantDataDefs()
-		TDefDataDecl.count = 0
-		
-		For Local decl:TDecl = EachIn dataDefs
-			decl.Semant
-		Next
-	End Method
-	
-	Method SemantDecls()
-		For Local decl:TDecl=EachIn mainModule._decls
-
-			decl.Semant
-			
-			' consts
-			Local cdecl:TConstDecl=TConstDecl( decl )
-			If cdecl
-				cdecl.Semant()
-				Continue
-			End If
-
-			' classes
-			Local tdecl:TClassDecl=TClassDecl( decl )
-			If tdecl
-				tdecl.Semant()
-				tdecl.SemantParts()
-				Continue
-			EndIf
-
-			' functions
-			Local fdecl:TFuncDecl=TFuncDecl( decl )
-			If fdecl And fdecl <> _appInstance.mainFunc Then
-				fdecl.Semant()
-				Continue
-			End If
-
-			' globals
-			Local gdecl:TGlobalDecl=TGlobalDecl( decl )
-			If gdecl
-				gdecl.Semant()
-				Continue
-			End If
-		Next
-
-	End Method
-	
-	Method hasStringConst:Int(value:String)
-		Return stringConsts.ValueForKey(value) <> Null
-	End Method
-	
-	Method mapStringConsts(value:String)
-		Local sc:TStringConst = TStringConst(stringConsts.ValueForKey(value))
-		
-		If Not sc Then
-			Local sc:TStringConst = New TStringConst
-			sc.count = 1
-		
-			If value Then
-				sc.id = "_s" + stringConstCount
-			Else
-				sc.id = "bbEmptyString"
-			End If
-
-			stringConsts.Insert(value, sc)
-
-			If value Then
-				stringConstCount:+ 1
-			End If
-		Else
-			sc.count :+ 1
-		End If
-	End Method
-	
-	Method removeStringConst(value:String)
-		If value Then
-			Local sc:TStringConst = TStringConst(stringConsts.ValueForKey(value))
-			If sc Then
-				If sc.count > 0 Then
-					sc.count :- 1
-					'stringConsts.Remove(value)
-				End If
-			End If
-		End If
-	End Method
-	
-	Method FindDataLabel:TDecl(ident:String)
-		For Local dd:TDefDataDecl = EachIn dataDefs
-			If dd.label And dd.label.ident.ToLower() = ident.ToLower() Then
-				Return dd
-			End If
-		Next
-	End Method
-	
-End Type
-
-Type TStringConst
-
-	Field id:String
-	Field count:Int
-
-End Type
+' Copyright (c) 2013-2017 Bruce A Henderson
+'
+' Based on the public domain Monkey "trans" by Mark Sibly
+'
+' This software is provided 'as-is', without any express or implied
+' warranty. In no event will the authors be held liable for any damages
+' arising from the use of this software.
+'
+' Permission is granted to anyone to use this software for any purpose,
+' including commercial applications, and to alter it and redistribute it
+' freely, subject to the following restrictions:
+'
+'    1. The origin of this software must not be misrepresented; you must not
+'    claim that you wrote the original software. If you use this software
+'    in a product, an acknowledgment in the product documentation would be
+'    appreciated but is not required.
+'
+'    2. Altered source versions must be plainly marked as such, and must not be
+'    misrepresented as being the original software.
+'
+'    3. This notice may not be removed or altered from any source
+'    distribution.
+'
+
+Const DECL_EXTERN:Int=        $010000
+Const DECL_PRIVATE:Int=       $020000
+Const DECL_ABSTRACT:Int=      $040000
+Const DECL_FINAL:Int=         $080000
+
+Const DECL_SEMANTED:Int=      $100000
+Const DECL_SEMANTING:Int=     $200000
+Const DECL_CYCLIC:Int=       $8000000
+
+Const DECL_POINTER:Int=       $400000
+
+Const DECL_ARG:Int=           $800000
+Const DECL_INITONLY:Int=     $1000000
+
+Const DECL_NODEBUG:Int=      $2000000
+Const DECL_PROTECTED:Int=    $4000000
+
+Const DECL_API_CDECL:Int=   $00000000
+Const DECL_API_STDCALL:Int= $10000000
+Const DECL_API_DEFAULT:Int=DECL_API_CDECL
+
+Const CLASS_INTERFACE:Int=    $002000
+Const CLASS_THROWABLE:Int=    $004000
+Const CLASS_STRUCT:Int=       $008000
+Const CLASS_GENERIC:Int=      $001000
+
+Const SCOPE_FUNC:Int = 0
+Const SCOPE_CLASS_LOCAL:Int = 1
+Const SCOPE_CLASS_HEIRARCHY:Int = 2
+Const SCOPE_MODULE:Int = 3
+Const SCOPE_ALL:Int = 4
+
+'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
+
+Global _appInstance:TAppDecl
+
+Global _loopnest:Int
+
+Function PushEnv( env:TScopeDecl )
+	If _env _envStack.AddLast( _env )
+	_env=env
+End Function
+
+Function PopEnv()
+	_env=TScopeDecl( _envStack.RemoveLast() )
+End Function
+
+Type TFuncDeclList Extends TList
+	Field ident:String
+	Field _identLower:String
+	
+	Method IdentLower:String()
+		If Not _identLower Then
+			_identLower = ident.ToLower()
+		End If
+		Return _identLower
+	End Method
+End Type
+
+Type TMetadata
+
+	Field metadataString:String
+
+	' key/value pairs
+	Field meta:TMap
+
+	Method InsertMeta(key:String, value:String)
+		If Not meta Then
+			meta = New TMap
+		End If
+		
+		meta.Insert(key, value)
+	End Method
+
+	Method HasMeta:Int(key:String)
+		Return meta And meta.Contains(key.ToLower())
+	End Method
+	
+End Type
+
+Type TDecl
+	Field ident$
+	Field munged$
+	Field errInfo$
+	Field actual:TDecl
+	Field scope:TScopeDecl
+	Field attrs:Int
+	Field metadata:TMetadata = New TMetadata
+	
+	Field declImported:Int = False
+	Field generated:Int
+	
+	Field _identLower:String
+	
+	Method New()
+		errInfo=_errInfo
+		actual=Self
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True) Abstract
+	
+	Method IdentLower:String()
+		If Not _identLower Then
+			_identLower = ident.ToLower()
+		End If
+		Return _identLower
+	End Method
+	
+	Method ToString$()
+		If TClassDecl( scope ) Return scope.ToString()+"."+ident
+		Return ident
+	End Method
+	
+	Method ToTypeString:String()
+	End Method
+	
+	Method IsExtern:Int()
+		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
+	End Method
+	
+	Method IsSemanted:Int()
+		Return (attrs & DECL_SEMANTED)<>0
+	End Method
+	
+	Method IsSemanting:Int()
+		Return (attrs & DECL_SEMANTING)<>0
+	End Method
+	
+	Method IsNoDebug:Int()
+		Return (attrs & DECL_NODEBUG)<>0
+	End Method
+	
+	Method FuncScope:TFuncDecl()
+		If TFuncDecl( Self ) Return TFuncDecl( Self )
+		If scope Return scope.FuncScope()
+	End Method
+
+	Method ClassScope:TClassDecl()
+		If TClassDecl( Self ) Return TClassDecl( Self )
+		If scope Return scope.ClassScope()
+	End Method
+	
+	Method ModuleScope:TModuleDecl()
+		If TModuleDecl( Self ) Return TModuleDecl( Self )
+		' "app" is a module container
+		If TAppDecl( Self ) Return TAppDecl( Self).mainModule
+		If scope Return scope.ModuleScope()
+	End Method
+	
+	Method AppScope:TAppDecl()
+		If TAppDecl( Self ) Return TAppDecl( Self )
+		If scope Return scope.AppScope()
+	End Method
+	
+	' find an owning scope of function, class or module
+	Method ParentScope:TScopeDecl()
+		Local _scope:TScopeDecl = scope.FuncScope()
+		If Not _scope Then
+			_scope = scope.ClassScope()
+		End If
+		
+		If Not _scope Then
+			_scope = scope.ModuleScope()
+		End If
+		
+		Return _scope
+	End Method
+	
+	Method CheckAccess:Int()
+		If IsPrivate() And ModuleScope()<>_env.ModuleScope() Return False
+		Return True
+	End Method
+	
+	Method AssertAccess()
+		If Not CheckAccess()
+			If IsPrivate() Then
+				Err ToString() +" is private."
+			Else
+				Err ToString() +" is protected."
+			End If
+		EndIf
+	End Method
+
+	Method Copy:TDecl(deep:Int = True)
+		Local t:TDecl=OnCopy(deep)
+		t.munged=munged
+		t.errInfo=errInfo
+		Return t
+	End Method
+
+	Method Semant()
+
+		If IsSemanted() Return
+
+		If IsSemanting() Then
+			If attrs & DECL_CYCLIC Then
+				Return
+			End If
+			Err "Cyclic declaration of '"+ident+"'."
+		End If
+		
+		If actual<>Self
+			actual.Semant
+		EndIf
+
+		PushErr errInfo
+		
+		If scope
+			PushEnv scope
+		EndIf
+		
+		attrs:|DECL_SEMANTING
+
+		'If ident And ClassScope() Print "Semanting "+ToString()
+
+		OnSemant
+		
+		attrs:&~DECL_SEMANTING
+
+		attrs:|DECL_SEMANTED
+
+		If scope 
+			'If Not IsExtern()
+			If TFuncDecl(Self) And attrs & FUNC_PTR
+				'DebugLog "**** " + ident
+			Else
+			
+				' a nested function needs to be scoped to another function, class or module.
+				If attrs & FUNC_NESTED Then
+					Local sc:TScopeDecl = ParentScope()
+					
+					' if our scope isn't one of the above, let it be so.
+					If sc <> scope Then
+						scope = Null
+						sc.InsertDecl(Self)
+					End If
+				End If
+			
+
+				scope._semanted.AddLast Self
+				
+				If TGlobalDecl( Self )
+					' FIXME
+					If AppScope() Then
+						AppScope().semantedGlobals.AddLast TGlobalDecl( Self )
+					End If
+				EndIf
+				
+				If TModuleDecl( scope )
+					' FIXME
+					Local app:TAppDecl = AppScope()
+					If app Then
+						app._semanted.AddLast Self
+					End If
+				EndIf
+			
+			EndIf
+			
+			If TValDecl(Self) And TValDecl(Self).deferInit Then
+				TValDecl(Self).SemantInit
+			End If
+
+			PopEnv
+		Else
+			If TValDecl(Self) And TValDecl(Self).deferInit Then
+				TValDecl(Self).SemantInit
+			End If
+		EndIf
+		
+		
+		PopErr
+	End Method
+	
+	Method InitInstance:TDecl( decl:TDecl )
+		decl.ident=ident
+		decl.munged=munged
+		decl.errInfo=errInfo
+		decl.actual=actual
+		decl.scope=Null
+		decl.attrs=attrs & ~(DECL_SEMANTED|DECL_SEMANTING)
+		Return decl
+	End Method
+	
+	Method GenInstance:TDecl()
+		InternalErr
+	End Method
+	
+	Method OnSemant() Abstract
+	
+	Method Clear()
+	End Method
+
+End Type
+
+Type TValDecl Extends TDecl
+	'pre-semant
+	Field declTy:TType
+	Field declInit:TExpr
+	'post-semant
+	Field ty:TType
+	Field init:TExpr
+	
+	Field deferInit:Int = False
+	
+	Method ToString$()
+		Local t$=Super.ToString()
+		If ty Return t+":"+ty.ToString()
+		If declTy Return t+":"+declTy.ToString()
+		Return t+":?"
+	End Method
+
+	Method ToTypeString:String()
+		If ty Return ty.ToString()
+		If declTy Return declTy.ToString()
+	End Method
+
+	Method CopyInit:TExpr()
+		If init Return init.Copy()
+	End Method
+	
+	Method OnSemant()
+'DebugStop	
+		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 TFunctionPtrType(at) Then
+				If Not TFunctionPtrType(at).func.scope Then
+					If scope Then
+						TFunctionPtrType(at).func.scope = scope
+					Else
+						TFunctionPtrType(at).func.scope = _env
+					End If
+				End If
+			End If
+
+			' pass the scope into the function ptr
+			If TFunctionPtrType(declTy) Then
+				If Not TFunctionPtrType(declTy).func.scope Then
+					If scope Then
+						TFunctionPtrType(declTy).func.scope = scope
+					Else
+						TFunctionPtrType(declTy).func.scope = _env
+					End If
+				End If
+			End If
+			
+			ty=declTy.Semant()
+
+			If Not deferInit Then
+				SemantInit()
+			End If
+			
+		Else If declInit
+			If Not deferInit Then
+				SemantInit()
+			End If
+		Else
+			InternalErr
+		EndIf
+		
+	End Method
+	
+	Method SemantInit()
+		' for field initialisation, create a stub New() method to use as current scope
+		' since fields are initialised in New(). Otherwise the scope would be "class", which is
+		' incorrect for processing field inits.
+		If TFieldDecl(Self) And declInit Then
+			Local newScope:TFuncDecl = New TFuncDecl.CreateF( "new", Null,Null,FUNC_METHOD )
+			newScope.scope = _env
+			PushEnv(newScope)
+		End If
+	
+		If declTy
+			If declInit Then
+				If TFunctionPtrType(ty) Then
+					
+					Local expr:TExpr
+					
+					If TInvokeExpr(declInit) Then
+						expr = declInit.Copy()
+					Else If TConstExpr(declInit) Then
+						expr = declInit.Copy().Semant()
+					Else If TFuncCallExpr(declInit) Then
+						expr=declInit.Copy().Semant()
+					Else If TNullExpr(declInit) Then
+						expr = declInit
+					Else
+						' 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
+						End Rem
+						
+						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
+			init=declInit.Copy().Semant()
+			ty=init.exprType
+		End If
+		
+		If init Then
+			If TVarExpr(init) And TVarExpr(init).decl = Self Then
+				Err "Identifier '" + TVarExpr(init).decl.ident + "' not found."
+			End If
+			
+			If TNewObjectExpr(init) And TVarExpr(TNewObjectExpr(init).instanceExpr) And TVarExpr(TNewObjectExpr(init).instanceExpr).decl = Self Then
+				Err "Identifier '" + Self.ident + "' not found."
+			End If
+		End If
+		
+		' remove the temporary scope
+		If TFieldDecl(Self) And declInit Then
+			PopEnv()
+		End If
+	End Method
+	
+	Method Clear()
+	End Method
+	
+End Type
+
+Type TConstDecl Extends TValDecl
+	Field value$
+	
+	Method Create:TConstDecl( ident$,ty:TType,init:TExpr,attrs:Int )
+		Self.ident=ident
+		Self.munged=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Return Self
+	End Method
+
+	Method GenInstance:TDecl()
+		Local inst:TConstDecl = New TConstDecl
+		InitInstance inst
+		inst.declTy=declTy
+		inst.declInit=declInit
+		Return inst
+	End Method
+
+	Method OnCopy:TDecl(deep:Int = True)
+		Return New TConstDecl.Create( ident,ty,CopyInit(), attrs )
+	End Method
+	
+	Method OnSemant()
+		Super.OnSemant()
+		'If Not IsExtern() value=init.Eval()
+		If init Then
+			value=init.Eval()
+			If TStringType(ty) And Not _appInstance.hasStringConst(value) Then
+				_appInstance.mapStringConsts(value)
+			End If
+		End If
+	End Method
+	
+	Method ToString$()
+		Return "Const "+Super.ToString()
+	End Method
+
+End Type
+
+Type TVarDecl Extends TValDecl
+
+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, 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)
+		Local decl:TLocalDecl = New TLocalDecl.Create( ident,declTy,declInit,attrs &~ DECL_SEMANTED, generated, volatile )
+		decl.scope = scope
+		decl.ty = ty
+		decl.init = init
+		Return decl
+	End Method
+
+	Method GetDeclPrefix:String()
+		Return "Local "
+	End Method
+	
+	Method ToString$()
+		Return GetDeclPrefix() + Super.ToString()
+	End Method
+
+	Method Clear()
+		done = False
+	End Method
+
+End Type
+
+Type TArgDecl Extends TLocalDecl
+
+	Field castTo:String
+	
+	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
+	
+	Method GenInstance:TDecl()
+		Local inst:TArgDecl=New TArgDecl
+		InitInstance inst
+		inst.declTy=declTy
+		inst.declInit=declInit
+		Return inst
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Local d:TArgDecl = New TArgDecl.Create( ident,declTy,declInit,attrs,generated,volatile )
+		d.ty = ty
+		d.init = init
+		Return d
+	End Method
+
+	Method GetDeclPrefix:String()
+		Return ""
+	End Method
+	
+	Method ToString$()
+		Return Super.ToString()
+	End Method
+	
+End Type
+
+Type TGlobalDecl Extends TVarDecl
+
+	Field inited:Int
+	Field funcGlobal:Int
+	
+	Method Create:TGlobalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0,funcGlobal:Int=False )
+		Self.deferInit = True
+		Self.ident=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Self.funcGlobal=funcGlobal
+		Return Self
+	End Method
+
+	Method OnCopy:TDecl(deep:Int = True)
+		Local g:TGlobalDecl = New TGlobalDecl.Create( ident,declTy,declInit,attrs,funcGlobal )
+		g.ty = ty
+		g.init = init
+		Return g
+	End Method
+	
+	Method ToString$()
+		Return "Global "+Super.ToString()
+	End Method
+
+	Method GenInstance:TDecl()
+'		PushErr errInfo
+'		Err "Global variables cannot be used inside generic classes."
+		Local inst:TGlobalDecl=New TGlobalDecl
+		InitInstance inst
+		inst.declTy=declTy
+		inst.declInit=declInit
+		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
+
+	' location offset in object variable data
+	Field offset:Int
+
+	Method Create:TFieldDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
+		Self.ident=ident
+		Self.declTy=ty
+		Self.declInit=init
+		Self.attrs=attrs
+		Return Self
+	End Method
+
+	Method OnCopy:TDecl(deep:Int = True)
+		Local f:TFieldDecl = New TFieldDecl.Create( ident,declTy,declInit,attrs )
+		f.ty = ty
+		f.init = init
+		f.metadata = metadata
+		Return f
+	End Method
+	
+	Method ToString$()
+		Return "Field "+Super.ToString()
+	End Method
+	
+	Method GenInstance:TDecl()
+		Local inst:TFieldDecl=New TFieldDecl
+		InitInstance inst
+		inst.declTy=declTy
+		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
+
+	Field decl:Object
+	
+	Method Create:TAliasDecl( ident$,decl:Object,attrs:Int=0 )
+		Self.ident=ident
+		Self.decl=decl
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Return New TAliasDecl.Create( ident,decl,attrs )
+	End Method
+	
+	Method OnSemant()
+	End Method
+	
+	Method Clear()
+	End Method
+	
+End Type
+
+Type TScopeDecl Extends TDecl
+
+'Private
+
+	Field _decls:TList=New TList'<TDecl>
+	Field _semanted:TList=New TList'<TDecl>
+
+	Field declsMap:TMap=New TMap'<Object>
+
+'Public
+
+	Method OnCopy:TDecl(deep:Int = True)
+		InternalErr
+	End Method
+
+	Method Decls:TList()
+		Return _decls
+	End Method
+	
+	Method Semanted:TList()
+		Return _semanted
+	End Method
+	
+	Method FuncDecls:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _decls
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl fdecls.AddLast fdecl
+		Next
+		Return fdecls
+	End Method
+	
+	Method MethodDecls:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _decls
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl And fdecl.IsMethod() fdecls.AddLast fdecl
+		Next
+		Return fdecls
+	End Method
+	
+	Method SemantedFuncs:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _semanted
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl fdecls.AddLast fdecl
+		Next
+		Return fdecls
+	End Method
+	
+	Method SemantedMethods:TList( id$="" )
+		Local fdecls:TList=New TList
+		For Local decl:TDecl=EachIn _decls
+			If id And decl.ident<>id Continue
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl And fdecl.IsMethod()
+				If Not fdecl.IsSemanted() Then
+					fdecl.Semant()
+				End If
+				fdecls.AddLast fdecl
+			End If
+		Next
+		Return fdecls
+	End Method
+	
+	Method InsertDecl( decl:TDecl, isCopy:Int = False )
+
+		If decl.scope And Not (decl.attrs & DECL_INITONLY) And Not isCopy InternalErr
+		
+		'Local ident$=decl.ident
+		If Not decl.ident Return
+		
+		If Not decl.scope Or isCopy Then
+			decl.scope=Self
+		End If
+		_decls.AddLast decl
+
+		'Local _decls:TMap
+		Local tdecl_:Object=declsMap.ValueForKey( decl.IdentLower() )
+		
+		If TFuncDecl( decl )
+			Local funcs:TFuncDeclList=TFuncDeclList( tdecl_ )
+			If funcs Or Not tdecl_
+				If Not funcs
+					funcs=New TFuncDeclList
+					funcs.ident = decl.IdentLower()
+					declsMap.Insert decl.IdentLower(),funcs
+				EndIf
+
+				funcs.AddLast TFuncDecl( decl )
+				Return
+			Else
+				Err "Duplicate identifier '"+decl.ident+"'."
+			EndIf
+		Else If Not tdecl_
+			declsMap.Insert decl.IdentLower(),decl
+		Else
+			Err "Duplicate identifier '"+decl.ident+"'."
+		EndIf
+
+	End Method
+
+	Method InsertDecls( _decls:TList )
+		For Local decl:TDecl=EachIn _decls
+			InsertDecl decl
+		Next
+	End Method
+	
+	'This is overridden by TClassDecl and TModuleDecl
+	Method GetDecl:Object( ident$ )
+'DebugLog "GetDecl (" + Self.ident + ") : " + ident
+		Local decl:Object=Object(declsMap.ValueForKey( ident ))
+
+		If Not decl Then
+			If Self.IdentLower() = ident Then
+				' name matches but we are a "module", but not a *real* module..
+				' .. so we can't be looking for ourself
+				If TModuleDecl(Self) And Self.ident.Find(".") = - 1 Then
+					decl = Null
+				Else
+					decl = Self
+				End If
+			End If
+		End If
+		
+		If Not decl Return Null
+		
+		Local adecl:TAliasDecl=TAliasDecl( decl )
+		If Not adecl Return decl
+		
+		If adecl.CheckAccess() Return adecl.decl
+	End Method
+	
+
+	Method FindDecl:Object( ident$, override:Int = False )
+	
+		If Not override And _env<>Self Return GetDecl( ident )
+		
+		Local tscope:TScopeDecl=Self
+		While tscope
+			Local decl:Object=tscope.GetDecl( ident )
+			If decl Return decl
+			tscope=tscope.scope
+		Wend
+	End Method
+	
+	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+
+		Local decl:Object=Object(declsMap.ValueForKey( ident ))
+
+		If Not decl Return Null
+
+		If TFuncDeclList(decl) Then
+			For Local fdecl:TFuncDecl = EachIn TFuncDeclList(decl)
+
+				If Not fdecl.IsSemanted() And Not fdecl.IsSemanting() Then
+					fdecl.Semant
+				End If
+				
+				Local found:Int
+				For Local func:TFuncDecl = EachIn declList
+					If func.equalsFunc(fdecl) Then
+						found = True
+						Exit
+'Else
+'Print func.ToString() + "  didn't match  " + fdecl.ToString()
+					End If
+				Next
+				
+				If Not found Then
+					declList.AddLast(fdecl)
+				End If
+			Next
+			
+			Return declList
+		End If		
+		
+		Return decl
+		
+	End Method
+	
+	' returns a list of all matching named decls in scope
+	Method FindDeclList:Object(ident:String, override:Int = False, declList:TFuncDeclList = Null, maxSearchDepth:Int = SCOPE_ALL )
+	
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+	
+		If Not override And _env<>Self Return GetDeclList( ident, declList, maxSearchDepth )
+		
+		Local tscope:TScopeDecl=Self
+		While tscope
+			Local decl:Object=tscope.GetDeclList( ident, declList, maxSearchDepth )
+			'If decl And (Not TFuncDeclList(decl) And declList.IsEmpty()) Return decl
+			If decl Then
+				If TFuncDeclList(decl) Then
+					If TFuncDeclList(decl) <> declList Then
+						For Local d:TDecl = EachIn TFuncDeclList(decl)
+							declList.AddLast(d)
+						Next
+					End If
+				Else
+					declList.AddLast(decl)
+				End If
+			End If
+
+			' if scope is an interface, also check implemented/extended interfaces?
+			If TClassDecl(tscope) Then'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
+				Exit
+			Else If TModuleDecl(tscope) And maxSearchDepth < SCOPE_ALL Then
+				Exit
+			End If
+		Wend
+		
+		Return declList
+	End Method
+
+	
+
+'	Method FindDecl:Object( ident$, static:Int = False )
+'		Local decl:Object=GetDecl( ident )
+'		
+'		If Not static Or Not decl Then
+'			If decl Return decl
+'		Else
+'			If Not TFieldDecl(decl) And Not (TFuncDecl(decl) And TFuncDecl(decl).IsMethod()) Then
+'				Return decl
+'			End If
+'		End If
+'		If scope Return scope.FindDecl( ident, static )
+'	End Method
+	
+	Method FindValDecl:TValDecl( ident$, static:Int = False )
+		Local decl:TValDecl=TValDecl( FindDecl( ident ) )
+		
+		' we found a field but we don't have access to it?
+		If TFieldDecl(decl) And static Then
+			' see if there's another decl with the same name elsewhere that we may...
+			' field's scope.scope will be a module.
+			If decl.scope And decl.scope.scope Then
+				Local vDecl:TValDecl = TValDecl( decl.scope.scope.FindDecl( ident, True ) )
+				If vDecl Then
+					decl = vDecl
+				End If
+			End If
+		End If
+		
+		If Not decl Then
+			' try scope search
+			decl = TValDecl( FindDecl( ident, True ) )
+			
+			If Not decl Then
+				' didn't find it? Maybe it is in module local scope?
+				' issue arises when a global initialises with a local variable in the module scope.
+				Local fdecl:Object = FindDecl("__localmain", True)
+				If fdecl Then
+					If TFuncDecl(fdecl) Then
+						decl = TValDecl( TFuncDecl(fdecl).FindDecl( ident ) )
+					Else If TFuncDeclList(fdecl) Then
+						For Local func:TFuncDecl = EachIn TFuncDeclList(fdecl)
+							func.Semant()
+							decl = TValDecl( func.FindDecl( ident ) )
+							If decl Then
+								Exit
+							End If
+						Next
+					End If
+					
+					' a local variable from module local scope can't be seen outside of module local scope...
+					If TLocalDecl(decl) And static Then
+						decl = Null
+					End If
+				End If
+			End If
+		End If
+		If Not decl Return Null
+		decl.AssertAccess
+		decl.Semant
+		Return decl
+	End Method
+
+	Method FindType:TType( ident$,args:TType[] )
+'DebugLog Self.ident + "::FindType::" + ident
+		Local decl:Object=(GetDecl( ident ))
+		If decl Then
+			If TModuleDecl(decl) Then
+				decl = TModuleDecl(decl).GetDecl(ident)
+			End If
+			Local ty:TType=TType(decl)
+			If ty
+				If args.Length Err "Wrong number of type arguments"
+				Return ty
+			EndIf
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If cdecl
+				cdecl.AssertAccess
+				If Not cdecl.instanceof Then
+					cdecl=cdecl.GenClassInstance( args )
+					cdecl.Semant
+				End If
+				Return cdecl.objectType
+			EndIf
+		EndIf
+		If scope Return scope.FindType( ident,args )
+	End Method
+	
+	Method FindScopeDecl:TScopeDecl( ident$ )
+		Local decl:TScopeDecl=TScopeDecl( FindDecl( ident ) )
+		If Not decl Return Null
+		decl.AssertAccess
+		decl.Semant
+		Return decl
+	End Method
+Rem	
+	Method FindClassDecl:TClassDecl( ident$,args:TClassDecl[] = Null )
+		Local decl:TClassDecl=TClassDecl( GetDecl( ident ) )
+		If Not args Then
+			args = New TClassDecl[0]
+		End If
+		If Not decl
+			If scope Return scope.FindClassDecl( ident,args )
+			Return Null
+		EndIf
+		decl.AssertAccess
+		decl.Semant
+		Return decl.GenClassInstance( args )
+	End Method
+End Rem	
+	Method FindModuleDecl:TModuleDecl( ident$ )
+'DebugStop
+		Local decl:TModuleDecl=TModuleDecl( GetDecl( ident ) )
+		If Not decl
+			If scope Return scope.FindModuleDecl( ident )
+			Return Null
+		EndIf
+		decl.AssertAccess
+		
+		' only semant on "real" module
+		If Not decl.declImported Then
+			decl.Semant
+		End If
+		Return decl
+	End Method
+	
+	Method FindBestMatchForArgs:TFuncDecl(argExprs:TExpr[], matches:TList)
+
+		Local bestMatch:TFuncDecl = Null
+		Local totals:Int[] = New Int[matches.count()]
+		Local index:Int
+		
+		For Local func:TFuncDecl = EachIn matches
+
+			Local argDecls:TArgDecl[]=func.argDecls
+			
+			For Local i:Int=0 Until argDecls.Length
+	
+				If i<argExprs.Length And argExprs[i]
+				
+					Local declTy:TType=argDecls[i].ty
+					Local exprTy:TType=argExprs[i].exprType
+
+					If TFunctionPtrType(declTy) And TInvokeExpr(argExprs[i]) Then
+						If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(argExprs[i]).decl) Then
+							Continue
+						End If
+					End If
+
+					' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
+					If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(argExprs[i]) And TInvokeExpr(argExprs[i]).invokedWithBraces = 0 Then
+						Continue
+					End If
+					
+					If TFunctionPtrType(declTy) And IsPointerType(exprTy, TType.T_BYTE) Then
+						Continue
+					End If
+					
+					If exprTy.EqualsType( declTy ) Continue
+					
+					' not an exact match. increase distance...
+					totals[index] :+ exprTy.DistanceToType(declTy)
+					
+				End If
+				
+			Next
+			
+			index :+ 1
+
+		Next
+		
+		Local tot:Int = -1
+		index = 0
+		Local i:Int
+		For Local func:TFuncDecl = EachIn matches
+			If tot = -1 Or totals[i] < tot Then
+				tot = totals[i]
+				bestMatch = func
+			Else If tot = totals[i] Then
+				If bestMatch.IsMethod() And Not func.IsMethod() Then
+					' 
+				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()+"."
+				End If
+			End If
+			i :+ 1
+		Next
+		
+		Return bestMatch
+		
+	End Method
+	
+	Method FindFuncDecl:TFuncDecl( ident$,argExprs:TExpr[] = Null,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False, maxSearchDepth:Int )
+'DebugLog "FindFuncDecl : " + ident
+'If ident = "new" Then DebugStop
+		Local foundIdentMatch:Int
+		Local funcs:TFuncDeclList
+
+		' does ident exist?
+		Local f:Object = FindDeclList(ident, True,,maxSearchDepth)
+		If Not f Then Return Null
+		
+		funcs = TFuncDeclList( f )
+		Local fp:TFuncDecl
+		
+		' not a function list, test for a function ptr var
+		If Not funcs Or funcs.IsEmpty() Then
+
+			' we found a funcdecl
+			If TFuncDecl(f) Then
+				funcs = New TFuncDeclList
+				funcs.AddLast(f)
+			End If
+			
+			If TVarDecl(f) Then
+				If Not TVarDecl(f).IsSemanted() Then
+					TVarDecl(f).Semant()
+				End If
+				If TFunctionPtrType(TVarDecl(f).ty) Then
+					funcs = New TFuncDeclList
+					fp = TFunctionPtrType(TVarDecl(f).ty).func
+					If Not fp.scope Then
+						fp.scope = TVarDecl(f).scope
+					End If
+					If Not fp.ident Then
+						fp.ident = TVarDecl(f).ident
+					End If
+					funcs.AddLast fp
+				End If
+			End If
+		End If
+		' was neither... lets bug out
+		If Not funcs Return Null
+		
+'		If Not funcs Then Return Null
+		
+		For Local func:TDecl = EachIn funcs
+			If Not func.IsSemanting() Then
+				func.Semant()
+			End If
+		Next
+		
+		'Local f:TDecl = TDecl(findDecl(ident))
+		'If Not f Then Return Null
+		
+				
+			'Local func:TFuncDecl = TFuncDecl(f)
+'			If Not func Then
+'				If TVarDecl(f) Then
+'					If Not f.IsSemanted() Then
+'						f.Semant()
+'					End If
+'					If TFunctionPtrType(TVarDecl(f).ty) Then
+'						func = TFunctionPtrType(TVarDecl(f).ty).func
+'						If Not func.scope Then
+'							func.scope = f.scope
+'						End If
+'						If Not func.ident Then
+'							func.ident = f.ident
+'						End If
+'					End If
+'				End If
+'			End If
+'			If Not func Return Null
+	
+		If Not argExprs
+			argExprs = New TExpr[0]
+		End If
+	
+		'func.Semant()
+		
+		Local match:TFuncDecl,isexact:Int
+		Local _err$
+		Local errorDetails:String
+		Local matches:TList = New TList
+
+		Local noExtendString:Int = True
+		Local generateWarnings:Int = False
+
+		' double test for matches.
+		' * first time through we don't allow up-casting args to String
+		'    if we get a match on the first pass, we'll take it.
+		' * second iteration we allow up-casting numerics to string
+		' * third iteration is valid if opt_warnover is enabled
+		'    this will allow down-casting of numerics (eg. double->float)
+		'    warnings will be generated if this produces valid results.
+		' if after all that, there's no match, then we can fail it.
+		For Local n:Int = 0 Until 3
+		
+			If n > 1 Then
+				If Not opt_warnover Then
+					Continue
+				Else
+					generateWarnings = True
+				End If
+			End If
+		
+			errorDetails = ""
+		
+			If n Then
+				noExtendString = False
+			End If
+
+			For Local iDecl:TDecl = EachIn funcs
+			
+				Local func:TFuncDecl = TFuncDecl(iDecl)
+				
+				If Not func Then
+					If TVarDecl(iDecl) Then
+'						If Not TVarDecl(iDecl).IsSemanted() Then
+'							TVarDecl(f).Semant()
+'						End If
+						If TFunctionPtrType(TVarDecl(iDecl).ty) Then
+							'funcs = New TFuncDeclList
+							fp = TFunctionPtrType(TVarDecl(iDecl).ty).func
+							If Not fp.scope Then
+								fp.scope = TVarDecl(iDecl).scope
+							End If
+							If Not fp.ident Then
+								fp.ident = TVarDecl(iDecl).ident
+							End If
+							'funcs.AddLast fp
+							func = fp
+						End If
+					End If
+					
+					If Not func Then
+						Continue
+					End If
+				End If
+				
+	
+			'While True
+				If Not func.CheckAccess() Continue
+				
+				Local argDecls:TArgDecl[]=func.argDecls
+				
+				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]
+					
+						Local arg:TExpr = argExprs[i]
+					
+						Local declTy:TType=argDecls[i].ty
+						Local exprTy:TType=arg.exprType
+						
+						Local widensTest:Int = True
+						
+						' for numeric constants, allow them to be auto-cast unless
+						If TConstExpr(arg) And IsNumericType(exprTy) And Not TConstExpr(arg).typeSpecific And TConstExpr(arg).CompatibleWithType(declTy) Then
+							widensTest = False
+						End If
+	
+						If TFunctionPtrType(declTy) And TInvokeExpr(arg) Then
+							If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(arg).decl) Continue
+						End If
+	
+						' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
+						If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(arg) And TInvokeExpr(arg).invokedWithBraces = 0 Then
+							Continue
+						End If
+						
+						If TFunctionPtrType(declTy) And IsPointerType(exprTy, TType.T_BYTE) Then
+							Continue
+						End If
+						
+						If exprTy.EqualsType( declTy ) Continue
+						
+						exact=False
+						
+						If Not generateWarnings Then
+							If Not explicit And exprTy.ExtendsType( declTy, noExtendString, widensTest ) Continue
+						Else
+							If Not explicit Then
+								' fails widen test
+								If Not exprTy.ExtendsType( declTy, noExtendString, True ) Then
+									' but passes non-widen test
+									If exprTy.ExtendsType( declTy, noExtendString, False ) Then
+										' generate a warning, and accept it
+										Warn "In call to " + func.ToString()+ ". Argument #"+(i+1)+" is ~q" + exprTy.ToString()+"~q but declaration is ~q"+declTy.ToString()+"~q. "
+										Continue
+									End If
+								Else
+									Continue
+								End If
+							End If
+						End If
+	
+						' make a more helpful error message
+						errorDetails :+ "Argument #"+(i+1)+" is ~q" + exprTy.ToString()+"~q but declaration is ~q"+declTy.ToString()+"~q. "
+
+					Else If Not argDecls[i].init
+	
+						If (func.attrs & FUNC_PTR) Or isIdentExpr Then
+							exact=False
+							Exit
+						End If
+	
+						' if this argument is missing and there isn't a default...
+						errorDetails :+  "Missing function parameter '" + argDecls[i].ident + "'"
+	
+					Else ' for case of argdecls having default args
+						exact=False
+						If Not explicit Exit
+					EndIf
+				
+					possible=False
+					Exit
+				Next
+				
+				If Not possible Continue
+				
+				If exact
+					If isexact
+						Err "Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
+					Else
+						_err=""
+						'match=func
+						matches.AddLast(func)
+						isexact=True
+						Exit
+					EndIf
+				Else
+					If Not isexact
+						'If match 
+						'	_err="Unable to determine overload to use: "+match.ToString()+" or "+func.ToString()+"."
+						'Else
+							'match=func
+							matches.AddLast(func)
+						'EndIf
+					EndIf
+				EndIf
+				'Exit
+			Next
+			
+			If Not matches.IsEmpty() Then
+				Exit
+			End If
+			
+		Next
+		
+		If matches.Count() = 1 Then
+			match = TFuncDecl(matches.First())
+		Else
+			' find best match
+			match = FindBestMatchForArgs(argExprs, matches)
+		End If
+		
+		If Not isexact
+			If _err Err _err
+			If explicit Return Null
+		EndIf
+
+		' last try... maybe we are trying to use it as a function pointer? (no args)
+		If Not match Then
+			If argExprs Then
+				'match = func
+'				match.maybeFunctionPtr = True
+			End If
+		Else If Not argExprs Then
+			' if there are no args, the actual function may have none either... so we may still be trying to use it as a function pointer
+			match.maybeFunctionPtr = True
+		End If
+		
+		If Not match
+			Local t$
+			For Local i:Int=0 Until argExprs.Length
+				If t t:+","
+				If argExprs[i] t:+argExprs[i].exprType.ToString()
+			Next
+			If foundIdentMatch Then
+				If throwOnNotMatched Then
+					Throw "Unable to find overload for "+ident+"("+t+"). " + errorDetails
+				Else
+					Err "Unable to find overload for "+ident+"("+t+"). " + errorDetails
+				End If
+			Else
+				If throwOnNotMatched Then
+					Throw "Identifier '" + ident + "' not found."
+				Else
+					Err "Identifier '" + ident + "' not found."
+				End If
+			End If
+		EndIf
+		
+		match.AssertAccess
+
+		Return match
+	End Method
+
+	Method FindLoop:TStmt(ident:String = Null)
+
+		If TBlockDecl(Self) And TBlockDecl(Self).extra Then
+			Local loop:TLoopStmt = TLoopStmt(TBlockDecl(Self).extra)
+			If ident Then
+				If loop.loopLabel And loop.loopLabel.IdentLower() = ident Then
+					Return loop
+				End If
+			Else
+				Return loop
+			End If
+		End If
+
+		If TFuncDecl(scope) Or TModuleDecl(scope)
+			Return Null
+		End If
+		
+		If scope Return scope.FindLoop( ident )
+	End Method
+	
+	Method OnSemant()
+	End Method
+	
+	Method Clear()
+	End Method
+
+End Type
+
+Type TBlockDecl Extends TScopeDecl
+	Field stmts:TList=New TList
+	Field extra:Object
+	
+	Method Create:TBlockDecl( scope:TScopeDecl, generated:Int = False )
+		Self.scope=scope
+		Self.generated = generated
+		
+		attrs :| (scope.attrs & DECL_NODEBUG)
+		
+		Return Self
+	End Method
+	
+	Method AddStmt( stmt:TStmt )
+		stmts.AddLast stmt
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Local t:TBlockDecl=New TBlockDecl
+		t.scope = scope
+		If deep Then
+			For Local stmt:TStmt=EachIn stmts
+				t.AddStmt stmt.Copy( t )
+			Next
+		End If
+		t.extra = extra
+		t.generated = generated
+		Return t
+	End Method
+
+	Method OnSemant()
+		PushEnv Self
+		
+		' any nested functions?
+		For Local fdecl:TFuncDecl = EachIn _decls
+			fdecl.Semant
+		Next
+		
+		For Local stmt:TStmt=EachIn stmts
+			stmt.Semant
+		Next
+		PopEnv
+	End Method
+
+	Method CopyBlock:TBlockDecl( scope:TScopeDecl )
+		Local t:TBlockDecl=TBlockDecl( Copy() )
+		t.scope=scope
+		Return t
+	End Method
+
+	Method Clear()
+		For Local stmt:TStmt=EachIn stmts
+			stmt.Clear
+		Next
+	End Method
+
+End Type
+
+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_BUILTIN:Int = $0080
+Const FUNC_PTR:Int=      $0100
+Const FUNC_INIT:Int =    $0200
+Const FUNC_NESTED:Int =  $0400
+Const FUNC_OPERATOR:Int= $0800
+Const FUNC_FIELD:Int=    $1000
+
+'Fix! A func is NOT a block/scope!
+'
+Type TFuncDecl Extends TBlockDecl
+
+	Field retType:TType
+	Field retTypeExpr:TType
+	Field argDecls:TArgDecl[]
+
+	Field overrides:TFuncDecl
+	Field superCtor:TInvokeSuperExpr
+	
+	Field castTo:String
+	Field noCastGen:Int
+	
+	Field maybeFunctionPtr:Int
+	
+	Field returnTypeSubclassed:Int
+	
+	Field mangled:String
+	Field noMangle:Int
+	
+	Field equalsBuiltIn:Int = -1
+	
+	Method CreateF:TFuncDecl( ident$,ty:TType,argDecls:TArgDecl[],attrs:Int )
+		Self.ident=ident
+		Self.retTypeExpr=ty
+		If argDecls
+			Self.argDecls=argDecls
+		Else
+			Self.argDecls = New TArgDecl[0]
+		End If
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Local args:TArgDecl[]=argDecls[..]
+		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)
+		If deep Then
+			For Local stmt:TStmt=EachIn stmts
+				t.AddStmt stmt.Copy( t )
+			Next
+		End If
+		t.retType = retType
+		t.retTypeExpr = retTypeExpr
+		t.scope = scope
+		t.overrides = overrides
+		t.superCtor = superCtor
+		t.castTo = castTo
+		t.noCastGen = noCastGen
+		t.munged = munged
+		t.metadata = metadata
+		t.mangled = mangled
+		t.noMangle = noMangle
+		Return  t
+	End Method
+
+	Method GenInstance:TDecl()
+		Local inst:TFuncDecl=New TFuncDecl
+		InitInstance inst
+		inst.retTypeExpr=retTypeExpr
+		inst.argDecls=argDecls[..]
+		For Local i:Int=0 Until argDecls.Length
+			inst.argDecls[i]=TArgDecl( argDecls[i].GenInstance() )
+		Next
+		Return inst
+	End Method
+	
+	Method ToString$()
+		Local t$
+		For Local decl:TArgDecl=EachIn argDecls
+			If t t:+","
+			t:+decl.ToString()
+		Next
+		Local q$
+		If IsCtor()
+			q="Method "+Super.ToString()
+		Else
+			If IsMethod() q="Method " Else q="Function "
+			q:+Super.ToString()
+			If retType
+				If Not TVoidType(retType) Then
+					q:+":"+retType.ToString()
+				End If
+			Else If retTypeExpr 
+				q:+":"+retTypeExpr.ToString()
+			'Else
+			'	q:+":"+"?"
+			EndIf
+		EndIf
+		Return q+"("+t+")"
+	End Method
+
+	Method ToTypeString:String()
+		Local t$
+		For Local decl:TArgDecl=EachIn argDecls
+			If t t:+","
+			t:+decl.ToTypeString()
+		Next
+		Local q$
+		If Not IsCtor() Then
+			If retType
+				If Not TVoidType(retType) Then
+					q:+retType.ToString()
+				End If
+			Else If retTypeExpr 
+				q:+retTypeExpr.ToString()
+			EndIf
+		End If
+		Return q+"("+t+")"
+	End Method
+
+	Method IsBuiltIn:Int()
+		Return (attrs & FUNC_BUILTIN)<>0
+	End Method
+	
+	Method IsCtor:Int()
+		Return (attrs & FUNC_CTOR)<>0
+	End Method
+
+	Method IsDtor:Int()
+		Return (attrs & FUNC_DTOR)<>0
+	End Method
+
+	Method IsMethod:Int()
+		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
+	
+	Method IsProperty:Int()
+		Return (attrs & FUNC_PROPERTY)<>0
+	End Method
+
+	Method IsField:Int()
+		Return (attrs & FUNC_FIELD)<>0
+	End Method
+		
+	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
+			' 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 ) ' careful, this is not commutative!
+		If IsCtor() Then
+			Return EqualsArgs( decl )
+		Else
+			' 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
+
+		If isCtor() Or isDtor() Then
+			If ClassScope() And ClassScope().IsInterface() Then
+				Err ident + "() cannot be declared in an Interface."
+			End If
+		End If
+
+		'semant ret type
+		If Not retTypeExpr Then
+			If Not retType Then ' may have previously been set (if this is a function pointer)
+				retType = TType.voidType
+			Else If TIdentType(retType)
+				retType = retType.Semant()
+			Else
+				' for Strict code, a void return type becomes Int
+				If TVoidType(retType) And Not ModuleScope().IsSuperStrict() Then
+					strictVoidToInt = True
+					retType = New TIntType
+				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
+			If TVoidType(retType) And Not ModuleScope().IsSuperStrict() And Not IsDTor() Then
+				strictVoidToInt = True
+				retType = New TIntType
+			End If
+		End If
+		
+		If TArrayType( retType ) And Not retType.EqualsType( retType.ActualType() )
+'			Err "Return type cannot be an array of generic objects."
+		EndIf
+		
+		'semant args
+		For Local arg:TArgDecl=EachIn argDecls
+			InsertDecl arg
+			arg.Semant
+		Next
+
+		' if we are a function pointer declaration, we just want to semant the args here.
+		If attrs & FUNC_PTR Return
+
+		If actual<>Self Return
+		
+		'check for duplicate decl
+		If ident Then
+			For Local decl:TFuncDecl=EachIn scope.SemantedFuncs( ident )
+				If decl<>Self And EqualsArgs( decl ) And Not decl.IsCTOR()
+					Err "Duplicate declaration "+ToString()
+				EndIf
+				If noMangle Then
+					If decl<>Self Then
+						If decl.argDecls.Length = 0 Then
+							Err "You cannot apply NoMangle to the function, as another function with no arguments exists."
+						Else If decl.NoMangle Then
+							Err "Another function is already declared with NoMangle."
+						End If
+					End If
+				End If
+			Next
+		End If
+		
+		' any nested functions?
+		For Local fdecl:TFuncDecl = EachIn _decls
+			fdecl.Semant
+		Next
+		
+		'get cdecl, sclasss
+		Local cdecl:TClassDecl=ClassScope(),sclass:TClassDecl
+		If cdecl sclass=TClassDecl( cdecl.superClass )
+		
+		'prefix call to super ctor if necessary
+'		If IsCtor() And superCtor=Null And sclass
+'			If sclass.FindFuncDecl( "new", Null )
+'				superCtor=New TInvokeSuperExpr.Create( "new" )
+'				stmts.AddFirst New TExprStmt.Create( superCtor )
+'			EndIf
+'		EndIf
+		
+		'check we exactly match an override
+		If sclass 'And IsMethod()
+
+			While sclass
+				Local errorDetails:String = ""
+
+				Local found:Int
+				For Local decl:TFuncDecl=EachIn sclass.FuncDecls( )
+					
+					If decl.IdentLower() = IdentLower() Then
+
+						If IdentLower() = "new" Continue
+						If IdentLower() = "delete" Continue
+
+						found=True
+
+						If Not decl.IsSemanted() Then
+							decl.Semant
+						End If
+
+						' check void return type strictness, and fail if appropriate.
+						Local voidReturnTypeFail:Int = False
+						' super has void return type... so it is superstrict (or inherited from)
+						If TVoidType(decl.retType) And TIntType(retType) Then
+							' if we are only strict, we may fail on type mismatch
+							If Not ModuleScope().IsSuperStrict() Then
+								' we have the option of upgrading our return type to match superstrict parent
+								If opt_strictupgrade And strictVoidToInt Then
+									retType = TType.voidType
+								Else
+									' otherwise...
+									voidReturnTypeFail = True
+								End If
+							End If
+						End If
+
+						If EqualsFunc( decl ) And Not voidReturnTypeFail
+
+							' check we aren't attempting to assign weaker access modifiers
+							If (IsProtected() And decl.IsPublic()) Or (IsPrivate() And (decl.IsProtected() Or decl.IsPublic())) Then
+							
+								Err PrivilegeError(Self, decl)
+							
+							End If
+						
+							If (TObjectType(retType) And TObjectType(decl.retType )) Or (TArrayType(retType) And TArrayType(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. "
+								If voidReturnTypeFail Then
+									errorDetails :+ "You may have Strict type overriding SuperStrict type. "
+								End If
+							Else
+								found = False
+								Continue
+							End If
+
+							Local argCount:Int = Min(argDecls.Length, decl.argDecls.Length)
+							If argCount > 0
+								For Local i:Int=0 Until argCount
+									If Not argDecls[i].ty.EqualsType( decl.argDecls[i].ty )
+										errorDetails :+ "Argument #"+(i+1)+" is ~q" + argDecls[i].ty.ToString()+"~q, expected ~q"+decl.argDecls[i].ty.ToString()+"~q. "
+									End If
+								Next
+							EndIf
+							'remove last space
+							errorDetails = errorDetails.Trim()
+						EndIf
+					End If
+				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
+					
+					Exit
+				EndIf
+				sclass=sclass.superClass
+			Wend
+		EndIf
+
+		'append a return statement if necessary
+		If Not IsExtern() And Not TVoidType( retType ) And Not TReturnStmt( stmts.Last() )
+			If Not isCtor() And Not isDtor()
+				Local stmt:TReturnStmt
+
+				stmt=New TReturnStmt.Create( New TConstExpr.Create( retType,"" ) )
+				stmt.generated = True
+
+				stmt.errInfo=errInfo
+				stmts.AddLast stmt
+			End If
+		EndIf
+
+		attrs:|DECL_SEMANTED
+		
+		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
+
+	Function PrivilegeError:String(decl:TFuncDecl, decl2:TFuncDecl)
+		Local p:String
+		If decl.IsProtected() Then
+			p = "Protected"
+		Else
+			p = "Private"
+		End If
+		
+		Local dp:String
+		If decl2.IsPublic() Then
+			dp = "Public"
+		Else
+			dp = "Protected"
+		End If
+	
+		Return decl.ToString() + " clashes with " + decl2.ToString() + ". Attempt to assign weaker access privileges ('" + p + "'), was '" + dp + "'."
+	End Function
+	
+End Type
+
+Type TNewDecl Extends TFuncDecl
+
+	Field chainedCtor:TNewExpr
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Local args:TArgDecl[]=argDecls[..]
+		For Local i:Int=0 Until args.Length
+			args[i]=TArgDecl( args[i].Copy() )
+		Next
+		Local t:TNewDecl = TNewDecl(New TNewDecl.CreateF( ident,retType,args,attrs &~DECL_SEMANTED ))
+		If deep Then
+			For Local stmt:TStmt=EachIn stmts
+				t.AddStmt stmt.Copy(Null)
+			Next
+		End If
+		t.retType = retType
+		t.scope = scope
+		t.overrides = overrides
+		t.superCtor = superCtor
+		t.castTo = castTo
+		t.noCastGen = noCastGen
+		t.munged = munged
+		t.metadata = metadata
+		t.mangled = mangled
+		t.noMangle = noMangle
+		t.chainedCtor = chainedCtor
+
+		Return  t
+	End Method
+
+
+End Type
+
+
+'Const CLASS_INTERFACE:Int=1
+'Const CLASS_TEMPLATEARG:Int=2
+'Const CLASS_TEMPLATEINST:Int=4
+'Const CLASS_INSTANCED:Int=8		'class used in New?
+Const CLASS_INSTANCED:Int=1
+Const CLASS_EXTENDSOBJECT:Int=2
+Const CLASS_FINALIZED:Int=4
+
+Type TNullDecl Extends TClassDecl
+
+End Type
+
+Type TClassDecl Extends TScopeDecl
+
+	Field lastOffset:Int
+
+	Field args:TTemplateArg[]
+	Field superTy:TIdentType
+	Field impltys:TIdentType[]
+
+	Field superClass:TClassDecl
+	
+	Field implments:TClassDecl[]			'interfaces immediately implemented
+	Field implmentsAll:TClassDecl[]		'all interfaces implemented
+	
+	Field instanceof:TClassDecl			'for instances
+	Field instances:TList		'for actual (non-arg, non-instance)
+	Field instArgs:TType[]
+
+	Field objectType:TObjectType '"canned" objectType
+	Field globInit:Int
+	Field templateSource:TTemplateRecord
+
+	'Global nullObjectClass:TClassDecl=New TNullDecl.Create( "{NULL}",Null,Null,Null,DECL_ABSTRACT|DECL_EXTERN )
+	
+	Method Create:TClassDecl( ident$,args:TTemplateArg[],superTy:TIdentType,impls:TIdentType[],attrs:Int )
+		Self.ident=ident
+		Self.args=args
+		Self.superTy=superTy
+		Self.impltys=impls
+		Self.attrs=attrs
+		Self.objectType=New TObjectType.Create( Self )
+		If args
+			instances=New TList
+		EndIf
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		InternalErr
+	End Method
+	
+	Method ToString$()
+		Local t$
+
+		If args Then
+			For Local i:Int=0 Until args.Length
+				If i Then
+					t :+ ","
+				End If
+				t:+args[i].ToString()
+			Next
+		ElseIf instargs
+			For Local i:Int=0 Until instargs.Length
+				If i Then
+					t :+ ","
+				End If
+				t :+ instargs[i].ToString()
+			Next
+		End If
+		If t t="<"+t+">"
+		Return ident+t
+	End Method
+
+	Method ToTypeString:String()
+		Return ToString()
+	End Method
+Rem
+	Method GenClassInstance:TClassDecl( instArgs:TClassDecl[] )
+		If Not IsSemanted() InternalErr
+		
+		'no args
+		If Not instArgs
+			If Not args Return Self
+			If instanceof Return Self
+			For Local inst:TClassDecl=EachIn instances
+				If _env.ClassScope()=inst Return inst
+			Next
+		EndIf
+		
+		'If Not instanceof And Not instArgs Return Self
+		
+		'check number of args
+		If instanceof Or args.Length<>instArgs.Length
+			Err "Wrong number of class arguments for "+ToString()
+		EndIf
+		
+		'look for existing instance
+		For Local inst:TClassDecl=EachIn instances
+			Local equal:Int=True
+			For Local i:Int=0 Until args.Length
+				If inst.args[i]=instArgs[i] Continue
+				equal=False
+				Exit
+			Next
+			If equal Return inst
+		Next
+		
+		Local inst:TClassDecl=New TClassDecl
+
+		InitInstance inst
+
+		inst.scope=scope
+		inst.attrs:|CLASS_TEMPLATEINST
+		inst.args=instArgs
+		inst.superTy=superTy
+		inst.instanceof=Self
+		instances.AddLast inst
+		
+		For Local i:Int=0 Until args.Length
+			inst.InsertDecl New TAliasDecl.Create( args[i].ident,instArgs[i] )
+		Next
+		
+		For Local decl:TDecl=EachIn _decls
+			If TClassDecl( decl ) Continue
+			inst.InsertDecl decl.GenInstance()
+		Next
+
+		'inst.Semant
+		'A bit cheeky...
+		inst.OnSemant
+		inst.attrs:|DECL_SEMANTED
+		
+		Return inst
+	End Method
+End Rem
+	Method GenClassInstance:TClassDecl( instArgs:TType[], declImported:Int = False )
+
+		If instanceof InternalErr
+		
+		'no args
+		If Not instArgs
+			If Not args Return Self
+			For Local inst:TClassDecl=EachIn instances
+				If _env.ClassScope()=inst Return inst
+			Next
+		EndIf
+		
+		'check number of args
+		If args.Length<>instArgs.Length
+			Err "Wrong number of type arguments for class "+ToString()
+		EndIf
+		
+		'look for existing instance
+		For Local inst:TClassDecl=EachIn instances
+			Local equal:Int=True
+			For Local i:Int=0 Until args.Length
+				If Not inst.instArgs[i].EqualsType( instArgs[i] )
+					equal=False
+					Exit
+				EndIf
+			Next
+			If equal Return inst
+		Next
+
+		Local inst:TClassDecl=New TClassDecl.Create( ident,Null,superTy,impltys, attrs )
+
+		inst.attrs:&~DECL_SEMANTED
+
+		inst.munged=munged
+		inst.errInfo=errInfo
+		inst.scope=scope
+		inst.instanceof=Self
+		inst.instArgs=instArgs
+		inst.templateSource = templateSource
+		instances.AddLast inst
+		
+		inst.declImported = declImported
+
+		For Local i:Int=0 Until args.Length
+		
+			' ensure parameter types are compatible
+			If args[i].superTy Then
+				args[i].superTy = args[i].superTy.Semant()
+				If Not instArgs[i].EqualsType(args[i].superTy) And Not instArgs[i].ExtendsType(args[i].superTy) Then
+					Err "Type parameter '" + instArgs[i].ToString() + "' is not within its bound; should extend '" + args[i].superTy.ToString() + "'"
+				End If
+			End If
+		
+			inst.InsertDecl New TAliasDecl.Create( args[i].ident,instArgs[i],0 )
+		Next
+
+		For Local decl:TDecl=EachIn _decls
+			inst.InsertDecl decl.Copy(), True
+		Next
+
+		If Not declImported Then
+			inst.scope = _env.ModuleScope()
+		End If
+
+		Return inst
+	End Method
+
+	Method IsInterface:Int()
+		Return (attrs & CLASS_INTERFACE)<>0
+	End Method
+
+	Method IsThrowable:Int()
+		Return (attrs & CLASS_THROWABLE)<>0
+	End Method
+
+	Method IsFinalized:Int()
+		Return (attrs & CLASS_FINALIZED)<>0
+	End Method
+	
+	Method IsStruct:Int()
+		Return (attrs & CLASS_STRUCT)<>0
+	End Method
+
+	Method ExtendsObject:Int()
+		Return (attrs & CLASS_EXTENDSOBJECT)<>0
+	End Method
+	
+	Method IsInstanced:Int()
+		Return (attrs & CLASS_INSTANCED)<>0
+	End Method
+	
+	Method GetDecl:Object( ident$ )
+	
+		Local cdecl:TClassDecl=Self
+		While cdecl
+			Local decl:Object=cdecl.GetDecl2( ident )
+			If decl Return decl
+			
+			cdecl=cdecl.superClass
+		Wend
+
+	End Method
+	
+	'needs this 'coz you can't go blah.Super.GetDecl()...
+	Method GetDecl2:Object( ident$ )
+		Return Super.GetDecl( ident )
+	End Method
+
+	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+	
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+	
+		Local cdecl:TClassDecl=Self
+		While cdecl
+			Local decl:Object=cdecl.GetDeclList2( ident, declList, maxSearchDepth )
+			'If decl And (Not TFuncDeclList(decl) And declList.IsEmpty()) Return decl
+			If decl Then
+				declList.AddLast(decl)
+			End If
+
+			cdecl=cdecl.superClass
+			
+			If maxSearchDepth < SCOPE_CLASS_HEIRARCHY Then
+				Exit
+			End If
+		Wend
+
+		Return declList
+	End Method
+	
+	'needs this 'coz you can't go blah.Super.GetDecl()...
+	Method GetDeclList2:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+		Return Super.GetDeclList( ident, declList, maxSearchDepth )
+	End Method
+	
+	Method FindFuncDecl:TFuncDecl( ident$,args:TExpr[] = Null ,explicit:Int=False, isArg:Int = False, isIdentExpr:Int = False, throwOnNotMatched:Int = False, maxSearchDepth:Int )
+	
+		' try the super first...
+		Local funcDecl:TFuncDecl = Super.FindFuncDecl(ident, args, explicit, isArg, isIdentExpr, throwOnNotMatched, maxSearchDepth)
+		If funcDecl Then
+			Return funcDecl
+		End If
+	
+	
+		If args = Null Then
+			args = New TExpr[0]
+		End If
+	
+		If Not IsInterface()
+			' try getdecl first&
+			Local decl:TFuncDecl = TFuncDecl(GetDecl(ident))
+			If decl Then
+				Return decl
+			End If
+			Return FindFuncDecl2( ident,args,explicit,isIdentExpr )
+		EndIf
+		
+		Local fdecl:TFuncDecl=FindFuncDecl2( ident,args,True )
+		
+		For Local iface:TClassDecl=EachIn implmentsAll
+			Local decl:TFuncDecl=iface.FindFuncDecl2( ident,args,True )
+			If Not decl Continue
+			
+			If fdecl
+				If fdecl.EqualsFunc( decl ) Continue
+				Err "Unable to determine overload to use: "+fdecl.ToString()+" or "+decl.ToString()+"."
+			EndIf
+			fdecl=decl
+		Next
+		
+		If fdecl Or explicit Return fdecl
+		
+		fdecl=FindFuncDecl2( ident,args,False )
+		
+		For Local iface:TClassDecl=EachIn implmentsAll
+			Local decl:TFuncDecl=iface.FindFuncDecl2( ident,args,False )
+			If Not decl Continue
+			
+			If fdecl
+				If fdecl.EqualsFunc( decl ) Continue
+				Err "Unable to determine overload to use: "+fdecl.ToString()+" or "+decl.ToString()+"."
+			EndIf
+			fdecl=decl
+		Next
+		
+		Return fdecl
+	End Method
+	
+	Method FindFuncDecl2:TFuncDecl( ident$,args:TExpr[],explicit:Int, isIdentExpr:Int = False )
+		Return Super.FindFuncDecl( ident,args,explicit,,isIdentExpr,0,0 )
+	End Method
+	
+	Method GetAllFuncDecls:TFuncDecl[](funcs:TFuncDecl[] = Null, includeSuper:Int = True)
+
+		If Not funcs Then
+			funcs = New TFuncDecl[0]
+		End If
+		
+		If superClass And includeSuper Then
+			funcs = superClass.GetAllFuncDecls(funcs)
+		End If
+
+		' interface methods
+		For Local iface:TClassDecl=EachIn implmentsAll
+			funcs = iface.GetAllFuncDecls(funcs)
+		Next
+		
+		For Local func:TFuncDecl = EachIn _decls
+		
+			Local matched:Int = False
+			
+			For Local i:Int = 0 Until funcs.length
+				' found a match - we are overriding it
+				If func.IdentLower() = funcs[i].IdentLower() 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
+				End If
+			Next
+			
+			If Not matched Then
+				funcs :+ [func]
+			End If
+		
+		Next
+		
+		Return funcs
+	End Method
+
+	' returns a list of original function decls (i.e. decls in the scope of their original declarations).
+	' this is useful for generating vtables for extern types
+	Method GetAllOriginalFuncDecls:TFuncDecl[](funcs:TFuncDecl[] = Null, includeSuper:Int = True)
+		If Not funcs Then
+			funcs = New TFuncDecl[0]
+		End If
+		
+		If superClass And includeSuper Then
+			funcs = superClass.GetAllOriginalFuncDecls(funcs, True)
+		End If
+
+		' interface methods
+		For Local iface:TClassDecl=EachIn implmentsAll
+			For Local func:TFuncDecl=EachIn iface._decls
+				Local matched:Int = False
+
+'				For Local i:Int = 0 Until funcs.length
+'					' found a match - we are overriding it
+'					If func.IdentLower() = funcs[i].IdentLower() Then
+'						matched = True
+'						Exit
+'					End If
+'				Next
+				
+				If Not matched Then
+					funcs :+ [func]
+				End If
+			Next
+		Next
+
+		
+		For Local func:TFuncDecl = EachIn _decls
+		
+			Local matched:Int = False
+			
+			' dont count any that are already in the funcs list
+			For Local i:Int = 0 Until funcs.length
+				' found a match - we are overriding it
+				If func.IdentLower() = funcs[i].IdentLower() And func.EqualsArgs(funcs[i]) Then
+					matched = True
+					' set this to our own func
+					'funcs[i] = func
+					Exit
+				End If
+			Next
+			
+			If Not matched Then
+				funcs :+ [func]
+			End If
+		
+		Next
+		
+		Return funcs
+	End Method
+
+	Method GetOriginalFuncDecl:TFuncDecl(fdecl:TFuncDecl)
+		If Not TClassDecl(Self) Then
+			Return fdecl
+		End If
+		
+		If superClass Then
+			Local decl:TFuncDecl = superClass.GetOriginalFuncDecl(fdecl)
+			If decl <> fdecl Then
+				Return decl
+			End If
+		End If
+		
+		For Local func:TFuncDecl = EachIn _decls
+		
+			If func.IdentLower() = fdecl.IdentLower() And func.EqualsArgs(fdecl) Then
+				Return func
+			End If
+		
+		Next
+		
+		Return fdecl
+	End Method
+
+	
+	Method ExtendsClass:Int( cdecl:TClassDecl )
+		'If Self=nullObjectClass Return True
+		
+'		If cdecl.IsTemplateArg()
+'			cdecl=TType.objectType.FindClass()
+'		EndIf
+		
+		Local tdecl_:TClassDecl=Self
+		While tdecl_
+			If tdecl_=cdecl Return True
+			If cdecl.IsInterface()
+				For Local iface:TClassDecl=EachIn tdecl_.implmentsAll
+					If iface=cdecl Return True
+				Next
+			EndIf
+			tdecl_=tdecl_.superClass
+		Wend
+		
+		Return False
+	End Method
+	
+	Method OnSemant()
+	
+		If args Then
+			Return
+		End If
+
+		PushEnv Self
+
+		'If Not IsTemplateInst()
+		'	For Local i:Int=0 Until args.Length
+		'		InsertDecl args[i]
+		'		args[i].Semant
+		'	Next
+		'EndIf
+
+		'Semant superclass		
+		If superTy
+			'superClass=superTy.FindClass()
+			superClass=superTy.SemantClass()
+			If superClass.IsInterface() Then
+				If Not IsExtern() Or Not superClass.IsExtern() Err superClass.ToString()+" is an interface, not a class."
+				If (IsExtern() And Not superClass.IsExtern()) Or (superClass.IsExtern() And Not IsExtern()) Err "Extern and non extern types cannot be mixed."
+			End If
+			If superClass.IsFinal() Err "Final types cannot be extended."
+		EndIf
+		
+		'Semant implemented interfaces
+		Local impls:TClassDecl[]=New TClassDecl[impltys.Length]
+		Local implsall:TStack=New TStack
+		For Local i:Int=0 Until impltys.Length
+			attrs :| DECL_CYCLIC
+			Local cdecl:TClassDecl=impltys[i].SemantClass()
+			attrs :~ DECL_CYCLIC
+			If Not cdecl.IsInterface()
+				Err cdecl.ToString()+" is a type, not an interface."
+			EndIf
+			For Local j:Int=0 Until i
+				If impls[j]=cdecl
+					Err "Duplicate interface "+cdecl.ToString()+"."
+				EndIf
+			Next
+			impls[i]=cdecl
+			implsall.Push cdecl
+			For Local tdecl_:TDecl=EachIn cdecl.implmentsAll
+				implsall.Push tdecl_
+			Next
+		Next
+		Local length:Int = implsall.Length()
+		implmentsAll=New TClassDecl[length]
+		For Local i:Int=0 Until length
+			implmentsAll[i]=TClassDecl(implsall.Get(length - i - 1))
+		Next
+		implments=impls
+
+		Rem
+		If IsInterface()
+			'add implemented methods to our methods
+			For Local iface:=EachIn implmentsAll
+				For Local decl:=EachIn iface.FuncDecls
+					InsertAlias decl.ident,decl
+				Next
+			Next
+		EndIf
+		EndRem
+				
+'		attrs|=DECL_SEMANTED
+		
+		PopEnv
+		
+		'If IsTemplateArg()
+		'	actual=TType.objectType.FindClass()
+		'	Return
+		'EndIf
+		
+		'If IsTemplateInst()
+		'	Return
+		'EndIf
+		
+		'Are we abstract?
+		If Not IsAbstract()
+			For Local decl:TDecl=EachIn _decls
+				Local fdecl:TFuncDecl=TFuncDecl( decl )
+				If fdecl And fdecl.IsAbstract()
+					attrs:|DECL_ABSTRACT
+					Exit
+				EndIf
+			Next
+		EndIf
+		
+		If Not lastOffset And superClass Then
+			lastOffset = superClass.LastOffset
+		End If
+
+		For Local decl:TFieldDecl=EachIn _decls
+			GetFieldOffset(decl)
+		Next
+
+		If Not IsExtern() And Not IsInterface()
+			Local fdecl:TFuncDecl
+			For Local decl:TFuncDecl=EachIn FuncDecls()
+				If Not decl.IsCtor() Continue
+				Local nargs:Int
+				For Local arg:TArgDecl=EachIn decl.argDecls
+					If Not arg.init nargs:+1
+				Next
+				If nargs Continue
+				fdecl=decl
+				Exit
+			Next
+			
+			
+			' Don't need default new?
+			'If Not fdecl
+			'	fdecl=New TFuncDecl.CreateF( "new",New TObjectType.Create( Self ),Null,FUNC_CTOR )
+			'	fdecl.AddStmt New TReturnStmt.Create( Null )
+			'	InsertDecl fdecl
+			'EndIf
+		EndIf
+
+		'NOTE: do this AFTER super semant so UpdateAttrs order is cool.
+
+		If AppScope() Then
+			AppScope().semantedClasses.AddLast Self
+		End If
+	End Method
+	
+	Method SemantParts()
+'		If IsSemanted() Return
+		
+'		Super.Semant()
+		If args Then
+			Return
+		End If
+		
+		For Local decl:TConstDecl = EachIn Decls()
+			decl.Semant()
+		Next
+
+		For Local decl:TGlobalDecl = EachIn Decls()
+			decl.Semant()
+		Next
+
+		' NOTE : we can't semant functions here as they cause cyclic errors.
+		For Local decl:TFuncDecl = EachIn Decls()
+			decl.Semant()
+		Next
+
+		For Local decl:TFieldDecl = EachIn Decls()
+			decl.Semant()
+		Next
+
+	End Method
+	
+	'Ok, this dodgy looking beast 'resurrects' methods that may not currently be alive, but override methods that ARE.
+	Method UpdateLiveMethods:Int()
+	
+		If IsInterface() Return 0
+
+		If Not superClass Return 0
+
+		Local n:Int
+		For Local decl:TFuncDecl=EachIn MethodDecls()
+			If decl.IsSemanted() Continue
+			
+			Local live:Int
+			Local unsem:TList=New TList'<TFuncDecl>
+			
+			unsem.AddLast decl
+			
+			Local sclass:TClassDecl=superClass
+			While sclass
+				For Local decl2:TFuncDecl=EachIn sclass.MethodDecls( decl.ident )
+					If decl2.IsSemanted()
+						live=True
+					Else
+						unsem.AddLast decl2
+						If decl2.IsExtern() live=True
+						If decl2.actual.IsSemanted() live=True
+					EndIf
+				Next
+				sclass=sclass.superClass
+			Wend
+			
+			If Not live
+				Local cdecl:TClassDecl=Self
+				While cdecl
+					For Local iface:TClassDecl=EachIn cdecl.implmentsAll
+						For Local decl2:TFuncDecl=EachIn iface.MethodDecls( decl.ident )
+							If decl2.IsSemanted()
+								live=True
+							Else
+								unsem.AddLast decl2
+								If decl2.IsExtern() live=True
+								If decl2.actual.IsSemanted() live=True
+							EndIf
+						Next
+					Next
+					cdecl=cdecl.superClass
+				Wend
+			EndIf
+			
+			If Not live Continue
+			
+			For Local decl:TDecl=EachIn unsem
+				decl.Semant
+				n:+1
+			Next
+		Next
+		
+		Return n
+	End Method
+	
+	Method FinalizeClass()
+	
+		SemantParts()
+
+		PushErr errInfo
+		
+		If Not IsInterface()
+			'
+			'check for duplicate fields! - BlitzMax supports fields with the same name in subclasses..
+			'
+			'For Local decl:TDecl=EachIn Semanted()
+			'	Local fdecl:TFieldDecl=TFieldDecl( decl )
+			'	If Not fdecl Continue
+			'	Local cdecl:TClassDecl=superClass
+			'	While cdecl
+			'		For Local decl:TDecl=EachIn cdecl.Semanted()
+			'			If decl.ident=fdecl.ident Err "Field '"+fdecl.ident+"' in class "+ToString()+" overrides existing declaration in class "+cdecl.ToString()
+			'		Next
+			'		cdecl=cdecl.superClass
+			'	Wend
+			'Next
+			'
+			'Check we implement all abstract methods!
+			'
+			If IsInstanced()
+				Local cdecl:TClassDecl=Self
+				Local impls:TList=New TList'<TFuncDecl>
+				While cdecl
+					For Local decl:TFuncDecl=EachIn cdecl.SemantedMethods()
+						If decl.IsAbstract()
+							Local found:Int
+							For Local decl2:TFuncDecl=EachIn impls
+								If decl.IdentLower() = decl2.IdentLower() And decl2.EqualsFunc( decl )
+									found=True
+									Exit
+								EndIf
+							Next
+							If Not found
+								Err "Can't create instance of type "+ToString()+" due to abstract method "+decl.ToString()+"."
+							EndIf
+						Else
+							impls.AddLast decl
+						EndIf
+					Next
+					cdecl=cdecl.superClass
+				Wend
+			EndIf
+			'
+			'Check we implement all interface methods!
+			'
+			If Not IsAbstract() Then
+
+				Local ints:TMap = GetInterfaces()
+
+				For Local iface:TClassDecl=EachIn ints.Values()
+				
+					If (Not IsExtern() And iface.IsExtern()) Or (IsExtern() And Not iface.IsExtern()) Then
+						Err "Cannot mix Extern and non Extern Types and Interfaces."
+					End If
+				
+					For Local decl:TFuncDecl=EachIn iface.SemantedMethods()
+						Local found:Int
+
+						Local cdecl:TClassDecl=Self
+						
+						While cdecl And Not found
+							For Local decl2:TFuncDecl=EachIn cdecl.SemantedMethods( decl.ident )
+								' equals (or extends - for object types)
+								If decl2.EqualsFunc( decl )
+									If Not decl2.IsPublic() Then
+										' error on function decl
+										PushErr decl2.errInfo
+										Err TFuncDecl.PrivilegeError(decl2, decl)
+									End If
+									found=True
+									Exit
+								EndIf
+							Next
+						
+							cdecl = cdecl.superClass
+						Wend
+
+						If Not found
+							Err decl.ToString() + " must be implemented by type " + ToString()
+						EndIf
+					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 decl2.argDecls.Length = decl.argDecls.Length And 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
+		
+		Local modifier:Int = POINTER_SIZE
+		
+		If TIntType(ty) Or TFloatType(ty) Or TUIntType(ty) Then
+			modifier = 4
+		Else If TShortType(ty) Then
+			modifier = 2
+		Else If TLongType(ty) Or TDoubleType(ty) Or TULongType(ty) Then
+			modifier = 8
+		Else If TByteType(ty) Then
+			modifier = 1
+		Else If TSizeTType(ty) Then
+			modifier = WORD_SIZE
+		End If
+
+		If modifier > 1 And lastOffset Mod modifier Then
+			lastOffset :+ modifier - (lastOffset Mod modifier)
+		End If
+		
+		decl.offset = lastOffset
+		
+		lastOffset :+ modifier
+	End Method
+	
+	Method ImplementsInterface:Int(ident:String)
+		ident = ident.ToLower()
+		For Local iface:TClassDecl = EachIn implmentsAll
+			If iface.IdentLower() = ident Then
+				Return True
+			End If
+		Next
+		Return False
+	End Method
+	
+	' returns a map of all interfaces implemented in this hierarchy
+	Method GetInterfaces:TMap(map:TMap = Null)
+		If Not map Then
+			map = New TMap
+		End If
+
+		For Local iface:TClassDecl=EachIn implmentsAll
+		
+			If iface.IsInterface() Then
+			
+				Local cdecl:TClassDecl = iface
+				While cdecl
+				
+					If cdecl.IsInterface() Then
+						If Not map.Contains(cdecl) Then
+							map.Insert(cdecl, cdecl)
+						End If
+					End If
+
+
+					cdecl=cdecl.superClass
+				Wend
+			
+			End If
+		Next
+
+		
+		If superClass Then
+			map = superClass.GetInterfaces(map)
+		End If
+		
+		Return map
+	End Method
+	
+	Method GetImplementedFuncs:TList(list:TList = Null)
+		If Not list Then
+			list = New TList
+		End If
+		
+		For Local idecl:TClassDecl = EachIn implmentsAll
+			idecl.GetImplementedFuncs(list)
+		Next
+		
+		For Local decl:TFuncDecl = EachIn SemantedMethods()
+			list.AddLast(decl)
+		Next
+
+		Return list
+	End Method
+	
+End Type
+
+Type TLoopLabelDecl Extends TDecl
+
+	Field realIdent:String
+
+	Method Create:TLoopLabelDecl( ident$, attrs:Int=0 )
+		Self.ident="#" + ident
+		Self.realIdent = ident
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Return New TLoopLabelDecl.Create( realIdent,attrs )
+	End Method
+	
+	Method OnSemant()
+	End Method
+	
+End Type
+
+Type TDataLabelDecl Extends TDecl
+
+	Field realIdent:String
+	Field index:Int
+
+	Method Create:TDataLabelDecl( ident$, attrs:Int=0 )
+		Self.ident="#" + ident
+		Self.realIdent = ident
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Return New TDataLabelDecl.Create( realIdent,attrs )
+	End Method
+	
+	Method OnSemant()
+	End Method
+	
+End Type
+
+Type TDefDataDecl Extends TDecl
+
+	Global count:Int
+
+	Field label:TDataLabelDecl
+	Field data:TExpr[]
+
+	Method Create:TDefDataDecl(data:TExpr[], label:TDataLabelDecl = Null, attrs:Int=0 )
+		Self.data=data
+		Self.label=label
+		Self.attrs=attrs
+		Return Self
+	End Method
+	
+	Method OnCopy:TDecl(deep:Int = True)
+		Return New TDefDataDecl.Create(TExpr.CopyArgs(data),TDataLabelDecl(label.Copy()),attrs)
+	End Method
+
+	Method OnSemant()
+		If data Then
+			If label Then
+				label.index = count
+			End If
+		
+			For Local i:Int = 0 Until data.length
+				data[i] = data[i].Semant()
+				If Not TConstExpr(data[i]) Then
+					Err "Data items must be numeric or strings"
+				Else
+					' todo : more type tests?
+				End If
+				count :+ 1
+			Next
+		Else
+			' err?
+		End If
+	End Method
+	
+End Type
+
+Const MODULE_STRICT:Int=1
+Const MODULE_SUPERSTRICT:Int=2
+Const MODULE_ACTUALMOD:Int=4
+
+Type TNamespaceDecl Extends TScopeDecl
+
+'	Field mods:TMap = New TMap
+
+	Method Create:TNamespaceDecl( ident$,munged$ )
+		Self.ident=ident
+		Self.munged=munged
+		Return Self
+	End Method
+
+'	Method GetDecl:Object( ident$ )
+'		Return mods.ValueForKey(ident.ToLower())
+'	End Method
+	
+End Type
+
+Type TModuleDecl Extends TScopeDecl
+
+	Field filepath$
+	Field relpath$
+	Field imported:TUnorderedMap=New TUnorderedMap'<TModuleDecl>		'Maps filepath to modules
+	Field pubImported:TUnorderedMap =New TUnorderedMap'<TModuleDecl>	'Ditto for publicly imported modules
+
+	Field pmod:TModuleDecl
+
+	Field fileImports:TList=New TList'StringList
+	
+	' cache of ModuleInfo lines
+	Field modInfo:TList = New TList
+
+	Field _getDeclTreeCache:TList
+	
+	Field _getDeclCache:TMap = New TMap
+	Field _getDeclListCache:TMap = New TMap
+
+	Method ToString$()
+		Return "Module "+munged
+	End Method
+	
+	Method Create:TModuleDecl( ident$,munged$,filepath$,attrs:Int )
+		Self.ident=ident
+		Self.munged=munged
+		Self.filepath=filepath
+		Self.attrs=attrs
+
+		If ident.Find(".") <> -1 And ident.find("/") = -1 And ident.find("\") = -1 Then
+			Local m:String = ident[..ident.Find(".")]
+			Local ns:TNamespaceDecl = TNamespaceDecl(_appInstance.GetDecl(m.ToLower()))
+			If Not ns Then
+				ns = New TNamespaceDecl.Create(m, m)
+				If _appInstance.mainModule Then
+					_appInstance.mainModule.InsertDecl(ns)
+				Else
+					' this must be the main module...
+					InsertDecl(ns)
+				End If
+			End If
+			ns.InsertDecl(Self)
+		End If
+
+		Return Self
+	End Method
+
+	Method UpdateFilePath(fp:String)
+		filepath = fp
+	End Method
+	
+	Method AddImport(imp:String, obj:Object)
+		imported.Insert(imp, obj)
+		FlushCaches()
+	End Method
+	
+	Method FlushCaches()
+		_getDeclTreeCache = Null
+		If TModuleDecl(pmod) Then
+			TModuleDecl(pmod).FlushCaches()
+		End If
+	End Method
+	
+	Method IsStrict:Int()
+		Return (attrs & MODULE_STRICT)<>0
+	End Method
+
+	Method IsSuperStrict:Int()
+		Return (attrs & MODULE_SUPERSTRICT)<>0
+	End Method
+	
+	Method IsActualModule:Int()
+		Return (attrs & MODULE_ACTUALMOD)<>0
+	End Method
+	
+	Method GetDecl:Object( ident$ )
+		' if we previously found it, return it from the cache
+		Local decl:Object = _getDeclCache.ValueForKey(ident)
+
+		If decl Then
+			Return decl
+		End If
+		
+		If _getDeclTreeCache Then
+		
+			Local declmod$
+		
+			For Local mdecl:TModuleDecl = EachIn _getDeclTreeCache
+
+				If ident = mdecl.ident
+					_getDeclCache.Insert(ident, mdecl)
+					Return mdecl
+				End If
+			
+				Local tdecl_:Object=mdecl.GetDecl2( ident )
+			
+				If tdecl_ And tdecl_<>decl
+					If mdecl=Self
+						_getDeclCache.Insert(ident, tdecl_)
+						Return tdecl_
+					End If
+					If decl
+						Err "Duplicate identifier '"+ident+"' found in module '"+declmod+"' and module '"+mdecl.ident+"'."
+					EndIf
+					decl=tdecl_
+					declmod=mdecl.ident
+				EndIf
+			Next
+		
+		Else
+		
+			_getDeclTreeCache = New TList
+	
+			Local todo:TList=New TList'<TModuleDecl>
+			'Local done:TIntMap=New TIntMap'<TModuleDecl>
+			Local done:TMap = New TMap
+			
+			todo.AddLast Self
+			'done.Insert _filePathId,Self
+			done.Insert filePath,Self
+			
+			Local declmod$
+			
+			While Not todo.IsEmpty()
+		
+				Local mdecl:TModuleDecl=TModuleDecl(todo.RemoveLast())
+				
+				_getDeclTreeCache.AddLast(mdecl)
+				
+				Local imps:TUnorderedMap=mdecl.imported
+	
+				For Local mdecl2:TModuleDecl=EachIn imps.Values()
+	
+					'If Not done.Contains( mdecl2._filePathId )
+					If Not done.Contains( mdecl2.filePath )
+						todo.AddLast mdecl2
+						'done.Insert mdecl2._filePathId,mdecl2
+						done.Insert mdecl2.filePath,mdecl2
+					EndIf
+					
+				Next
+	
+			Wend
+	
+			Return GetDecl(ident)
+	
+		End If
+			
+		' cache it for next time
+		_getDeclCache.Insert(ident, decl)
+		
+		Return decl
+	End Method
+	
+	Method GetDecl2:Object( ident$ )
+		Return Super.GetDecl( ident )
+	End Method
+
+
+	Method GetDeclList:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+
+		If Not declList Then
+			declList = New TFuncDeclList
+		End If
+
+		Local decl:Object,declmod$
+
+		If _getDeclTreeCache Then
+		
+'			Print "   Using Cache"
+			
+			Local declmod$
+		
+			For Local mdecl:TModuleDecl = EachIn _getDeclTreeCache
+			
+				If ident = mdecl.ident
+					'_getDeclCache.Insert(identId, mdecl)
+					Return mdecl
+				End If
+			
+				Local tdecl_:Object=mdecl.GetDeclList2( ident, declList, maxSearchDepth )
+			
+				If tdecl_ And tdecl_<>decl
+					If mdecl=Self
+						_getDeclCache.Insert(ident, tdecl_)
+						Return tdecl_
+					End If
+					If decl
+						Err "Duplicate identifier '"+ident+"' found in module '"+declmod+"' and module '"+mdecl.ident+"'."
+					EndIf
+					decl=tdecl_
+					declmod=mdecl.ident
+				EndIf
+			Next
+		
+		Else
+
+			_getDeclTreeCache = New TList
+	
+			Local todo:TList=New TList'<TModuleDecl>
+			Local done:TMap=New TMap'<TModuleDecl>
+			
+			todo.AddLast Self
+			done.Insert filepath,Self
+			
+			'Local decl:Object,declmod$
+			
+			While Not todo.IsEmpty()
+		
+				Local mdecl:TModuleDecl=TModuleDecl(todo.RemoveLast())
+				_getDeclTreeCache.AddLast(mdecl)
+				
+				Local imps:TUnorderedMap=mdecl.imported
+	
+				For Local mdecl2:TModuleDecl=EachIn imps.Values()
+					If Not done.Contains( mdecl2.filepath )
+						todo.AddLast mdecl2
+						done.Insert mdecl2.filepath,mdecl2
+					EndIf
+					
+				Next
+	
+			Wend
+		
+			Return GetDeclList( ident, declList, maxSearchDepth )
+		
+		End If
+		
+		Return decl
+	End Method
+	
+	Method GetDeclList2:Object( ident$, declList:TFuncDeclList = Null, maxSearchDepth:Int )
+		Return Super.GetDeclList( ident, declList, maxSearchDepth )
+	End Method
+
+	Method OnSemant()
+		Local decl:TFuncDecl = FindFuncDecl( "__localmain", ,,,,,SCOPE_MODULE )
+		If decl Then
+			decl.Semant
+		End If
+	
+		For Local gdecl:TGlobalDecl=EachIn _decls
+			gdecl.Semant
+		Next
+
+		For Local cdecl:TClassDecl=EachIn _decls
+			If cdecl.args Then
+				For Local inst:TClassDecl = EachIn cdecl.instances
+					For Local idecl:TDecl = EachIn inst.Decls()
+						If TAliasDecl( idecl ) Continue
+						idecl.Semant()
+					Next
+				Next
+			Else
+				cdecl.Semant
+			End If
+		Next
+
+		For Local fdecl:TFuncDecl=EachIn _decls
+			fdecl.Semant
+		Next
+
+		For Local cdecl:TConstDecl=EachIn _decls
+			cdecl.Semant
+		Next
+	End Method
+
+End Type
+
+Type TAppDecl Extends TScopeDecl
+
+	Field imported:TUnorderedMap=New TUnorderedMap'<TModuleDecl>			'maps modpath->mdecl
+	
+	Field globalImports:TUnorderedMap = New TUnorderedMap
+	
+	Field mainModule:TModuleDecl
+	Field mainFunc:TFuncDecl	
+		
+	Field semantedClasses:TList=New TList'<TClassDecl>			'in-order (ie: base before derived) list of _semanted classes
+	Field semantedGlobals:TList=New TList'<TGlobalDecl>			'in-order (ie: dependancy sorted) list of _semanted globals
+
+	Field fileImports:TList=New TList'StringList
+	Field headers:TList = New TList
+	
+	Field stringConsts:TMap = New TMap
+	Field stringConstCount:Int
+	
+	Field incbins:TList = New TList
+	Field genIncBinHeader:Int = False
+	
+	Field dataDefs:TList = New TList
+	Field scopeDefs:TMap = New TMap
+	
+	Method GetPathPrefix:String()
+		If opt_buildtype = BUILDTYPE_MODULE Then
+			Local prefix:String
+			Local path:String[] = mainModule.filepath.split("/")
+			Local c:Int = 0
+			For Local dir:String = EachIn path
+				If c Then
+					prefix :+ dir.Replace(".mod", "") + "_"
+					c:- 1
+				End If
+				If dir = "mod" Then
+					c = 2
+				End If
+			Next
+		Else
+			Return "bb_"
+		End If
+	End Method
+	
+	Method InsertModule( mdecl:TModuleDecl )
+		mdecl.scope=Self
+		imported.Insert mdecl.filepath,mdecl
+		If Not mainModule
+			mainModule=mdecl
+		EndIf
+	End Method
+	
+	Method IsImported:Int(modpath:String)
+		Return globalImports.Contains(modpath)
+	End Method
+	
+	Method GetDecl:Object( ident$ )
+		Local obj:Object = Super.GetDecl(ident)
+		If Not obj And mainModule Then
+			Return mainModule.GetDecl(ident)
+		End If
+		Return obj
+	End Method
+
+	Method OnSemant()
+'DebugStop		
+		_env=Null
+		pushenv Self
+		
+		SemantDataDefs()	
+
+		mainModule.Semant
+
+		mainFunc=mainModule.FindFuncDecl( "__localmain",,,,,,SCOPE_MODULE )
+		
+		
+		' FIXME
+		If Not mainFunc Err "Function 'Main' not found."
+	
+		SemantDecls()
+
+		Repeat
+			Local more:Int
+			For Local cdecl:TClassDecl=EachIn semantedClasses
+				more:+cdecl.UpdateLiveMethods()
+			Next
+			If Not more Exit
+		Forever
+		
+		For Local cdecl:TClassDecl=EachIn semantedClasses
+			cdecl.FinalizeClass
+		Next
+	End Method
+	
+	Method SemantDataDefs()
+		TDefDataDecl.count = 0
+		
+		For Local decl:TDecl = EachIn dataDefs
+			decl.Semant
+		Next
+	End Method
+	
+	Method SemantDecls()
+		For Local decl:TDecl=EachIn mainModule._decls
+
+			decl.Semant
+			
+			' consts
+			Local cdecl:TConstDecl=TConstDecl( decl )
+			If cdecl
+				cdecl.Semant()
+				Continue
+			End If
+
+			' classes
+			Local tdecl:TClassDecl=TClassDecl( decl )
+			If tdecl
+				tdecl.Semant()
+				tdecl.SemantParts()
+				Continue
+			EndIf
+
+			' functions
+			Local fdecl:TFuncDecl=TFuncDecl( decl )
+			If fdecl And fdecl <> _appInstance.mainFunc Then
+				fdecl.Semant()
+				Continue
+			End If
+
+			' globals
+			Local gdecl:TGlobalDecl=TGlobalDecl( decl )
+			If gdecl
+				gdecl.Semant()
+				Continue
+			End If
+		Next
+
+	End Method
+	
+	Method hasStringConst:Int(value:String)
+		Return stringConsts.ValueForKey(value) <> Null
+	End Method
+	
+	Method mapStringConsts(value:String)
+		Local sc:TStringConst = TStringConst(stringConsts.ValueForKey(value))
+		
+		If Not sc Then
+			Local sc:TStringConst = New TStringConst
+			sc.count = 1
+		
+			If value Then
+				sc.id = "_s" + stringConstCount
+			Else
+				sc.id = "bbEmptyString"
+			End If
+
+			stringConsts.Insert(value, sc)
+
+			If value Then
+				stringConstCount:+ 1
+			End If
+		Else
+			sc.count :+ 1
+		End If
+	End Method
+	
+	Method removeStringConst(value:String)
+		If value Then
+			Local sc:TStringConst = TStringConst(stringConsts.ValueForKey(value))
+			If sc Then
+				If sc.count > 0 Then
+					sc.count :- 1
+					'stringConsts.Remove(value)
+				End If
+			End If
+		End If
+	End Method
+	
+	Method FindDataLabel:TDecl(ident:String)
+		For Local dd:TDefDataDecl = EachIn dataDefs
+			If dd.label And dd.label.ident.ToLower() = ident.ToLower() Then
+				Return dd
+			End If
+		Next
+	End Method
+	
+End Type
+
+Type TStringConst
+
+	Field id:String
+	Field count:Int
+
+End Type

+ 1851 - 1851
translator.bmx

@@ -1,1851 +1,1851 @@
-' Copyright (c) 2013-2017 Bruce A Henderson
-'
-' Based on the public domain Monkey "trans" by Mark Sibly
-'
-' This software is provided 'as-is', without any express or implied
-' warranty. In no event will the authors be held liable for any damages
-' arising from the use of this software.
-'
-' Permission is granted to anyone to use this software for any purpose,
-' including commercial applications, and to alter it and redistribute it
-' freely, subject to the following restrictions:
-'
-'    1. The origin of this software must not be misrepresented; you must not
-'    claim that you wrote the original software. If you use this software
-'    in a product, an acknowledgment in the product documentation would be
-'    appreciated but is not required.
-'
-'    2. Altered source versions must be plainly marked as such, and must not be
-'    misrepresented as being the original software.
-'
-'    3. This notice may not be removed or altered from any source
-'    distribution.
-'
-
-Global _trans:TTranslator
-
-Type TTranslator
-
-	Field _app:TAppDecl
-
-	Field outputFiles:TMap = New TMap
-
-	Field indent$
-	Field LINES:TStringList'=New TStringList
-	Field unreachable:Int,broken:Int
-	
-	Field contLabelId:Int
-	Field exitLabelId:Int
-	
-	'Munging needs a big cleanup!
-	
-	Field mungScope:TMap=New TMap'<TDecl>
-	Field mungStack:TStack=New TStack'< StringMap<TDecl> >
-	Field funcMungs:TMap=New TMap'<FuncDeclList>
-	Field customVarStack:TStack = New TStack
-	Field varStack:TStack = New TStack
-
-	Field tryStack:TStack = New TStack
-	Field loopTryStack:TStack = New TStack
-
-	Field mungedScopes:TMap=New TMap'<StringSet>
-	'Field funcMungs:TFuncDeclList=New TFuncDeclList
-	'Field mungedFuncs:TMap=New Map
-	Field localScopeStack:TStack = New TStack
-	Field localScope:TStack = New TStack
-	Field ind:Int
-	Field debugOut:String
-	
-	Field processingReturnStatement:Int
-
-	Method PushVarScope()
-		varStack.Push customVarStack
-		customVarStack = New TStack
-	End Method
-	
-	Method PopVarScope()
-		customVarStack=TStack(varStack.Pop())
-	End Method
-	
-	Method PushLoopLocalStack(stmt:Object)
-		ind :+ 1
-		If DEBUG Then
-			Emit "// --> STACK = " + ind
-		End If
-		localScope.Push stmt
-	End Method
-
-	Method PopLoopLocalStack()
-		If DEBUG Then
-			Emit "// <-- STACK = " + ind
-		End If
-		ind :- 1
-		If ind < 0 Then
-			InternalErr
-		End If
-		localScope.Pop
-	End Method
-
-	Method LoopLocalScopeDepth:Int(findStmt:TStmt)
-		Local count:Int = 0
-
-		For Local stmt:Object = EachIn localScope
-			If TBlockDecl(stmt) = Null Then
-				If findStmt And TTryBreakCheck(stmt) And findStmt <> TTryBreakCheck(stmt).stmt Then
-					Continue
-				End If
-				Exit
-			End If
-
-			count :+ 1
-		Next
-		
-		Return count
-	End Method
-
-	Method GetTopLocalLoop:TTryBreakCheck(findStmt:TStmt)
-		For Local tbc:TTryBreakCheck = EachIn localScope
-			If findStmt And findStmt <> tbc.stmt Then
-				Continue
-			End If
-			Return tbc
-		Next
-	End Method
-
-	Method PushLoopTryStack(stmt:Object)
-		If loopTryStack.Length() = 0 Then
-			' Try statements can only be applied here to loops
-			If TTryStmt(stmt) = Null Then
-				loopTryStack.Push stmt
-			End If
-		Else
-			loopTryStack.Push stmt
-		End If
-	End Method
-
-	Method PopLoopTryStack()
-		loopTryStack.Pop
-	End Method
-	
-	Method LoopTryDepth:Int(findStmt:TStmt)
-		Local count:Int = 0
-		
-		For Local stmt:Object = EachIn loopTryStack
-			If TTryStmt(stmt) = Null Then
-				If findStmt And findStmt <> stmt Then
-					Continue
-				End If
-				
-				Exit
-			End If
-
-			count :+ 1
-		Next
-		
-		Return count
-	End Method
-
-	Method GetTopLoop:TTryBreakCheck(findStmt:TStmt)
-		For Local tbc:TTryBreakCheck = EachIn loopTryStack
-			If findStmt And findStmt <> tbc.stmt Then
-				Continue
-			End If
-			Return tbc
-		Next
-	End Method
-
-	Method TransManglePointer$( ty:TType )
-		Local p:String
-		
-		If ty
-
-			If ty._flags & TType.T_VAR Then
-				p:+ "v"
-			End If
-
-			If ty._flags & TType.T_PTR Then
-				p:+ "p"
-			Else If ty._flags & TType.T_PTRPTR Then
-				p:+ "pp"
-			Else If ty._flags & TType.T_PTRPTRPTR Then
-				p:+ "ppp"
-			End If
-
-		End If
-		
-		Return p
-	End Method
-
-	Method TransMangleType:String(ty:TType)
-		Local p:String = TransManglePointer(ty)
-
-		If TVoidType( ty ) Return "v"
-		If TByteType( ty ) Return p + "b"
-		If TShortType( ty ) Return p + "s"
-		If TIntType( ty ) Return p + "i"
-		If TUIntType( ty ) Return p + "u"
-		If TFloatType( ty ) Return p + "f"
-		If TDoubleType( ty ) Return p + "d"
-		If TLongType( ty ) Return p + "l"
-		If TULongType( ty ) Return p + "y"
-		If TSizeTType( ty ) Return p + "z"
-		If 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
-		If TObjectType( ty ) Then
-			If Not TObjectType( ty ).classdecl.IsExtern()
-				Return p + "T" + TObjectType( ty ).classDecl.ident
-			Else
-				If TObjectType( ty ).classdecl.IsInterface() Then
-					Return p + "I" + TObjectType(ty).classDecl.ident
-				ElseIf TObjectType( ty ).classdecl.IsStruct() Then
-					Return p + "R" + TObjectType(ty).classDecl.ident
-				Else
-					Return p + "E" + TObjectType(ty).classDecl.ident
-				End If
-			End If
-		End If
-		If TFunctionPtrType( ty ) Then
-			Local func:TFuncDecl = TFunctionPtrType( ty ).func
-			Local s:String = "F" + MangleMethodArgs(func)
-'			For Local i:Int = 0 Until func.argDecls.length
-'				s :+ TransMangleType(func.argDecls[i].ty)
-'			Next
-			Return s + "_" + TransMangleType(func.retType) + "_"
-		End If
-		
-		Err "Unsupported type for name mangling : " + ty.ToString()
-	End Method
-
-	Method MangleMethod:String(fdecl:TFuncDecl)
-		If (fdecl.IsMethod() And Not fdecl.ClassScope().IsStruct())Or fdecl.IsCtor() Then
-			Return MangleMethodArgs(fdecl)
-		Else
-			Return MangleMethodRetType(fdecl) + MangleMethodArgs(fdecl)
-		End If
-	End Method
-	
-	Method MangleMethodRetType:String(fdecl:TFuncDecl)
-		If fdecl.retType Then
-			Return "_" + TransMangleType(fdecl.retType)
-		Else
-			Return "_v"
-		End If
-	End Method
-	
-	Method MangleMethodArgs:String(fdecl:TFuncDecl)
-		Local s:String
-		For Local arg:TArgDecl = EachIn fdecl.argDecls
-			If Not s Then
-				s = "_"
-			End If
-			s :+ TransMangleType(arg.ty)
-		Next
-		Return s
-	End Method
-
-	Method equalsTorFunc:Int(classDecl:TClassDecl, func:TFuncDecl)
-		If func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
-			Return True
-		End If
-		Return False
-	End Method
-
-	Method equalsBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
-		If func.equalsBuiltIn > -1 Then
-			Return func.equalsBuiltIn
-		End If
-	
-		If checked Or func.IdentLower() = "tostring" Or func.IdentLower() = "compare" Or func.IdentLower() = "sendmessage" Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
-			If classDecl.munged = "bbObjectClass" Then
-				For Local decl:TFuncDecl = EachIn classDecl.Decls()
-					If Not decl.IsSemanted() Then
-						decl.Semant
-					End If
-					If decl.IdentLower() = func.IdentLower() Then
-						Local res:Int = decl.EqualsFunc(func)
-						If res Then
-							func.equalsBuiltIn = True
-						End If
-						Return res
-					End If
-				Next
-			End If
-			If classDecl.superClass Then
-				Return equalsBuiltInFunc(classDecl.superClass, func, True)
-			End If
-		End If
-		func.equalsBuiltIn = False
-		Return False
-	End Method
-
-	Method equalsIfcBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
-		If checked Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
-			If classDecl.munged = "bbObjectClass" Then
-				For Local decl:TFuncDecl = EachIn classDecl.Decls()
-					If Not decl.IsSemanted() Then
-						decl.Semant
-					End If
-					If decl.IdentLower() = func.IdentLower() Then
-						Return decl.EqualsFunc(func)
-					End If
-				Next
-			End If
-			If classDecl.superClass Then
-				Return equalsIfcBuiltInFunc(classDecl.superClass, func, True)
-			End If
-		End If
-		Return False
-	End Method
-
-	Method MungFuncDecl( fdecl:TFuncDecl )
-
-		If fdecl.munged Return
-		
-		Local funcs:TFuncDeclList=TFuncDeclList(funcMungs.ValueForKey( fdecl.ident ))
-		If funcs
-			For Local tdecl:TFuncDecl=EachIn funcs
-				If fdecl.EqualsArgs( tdecl ) And fdecl.scope = tdecl.scope
-					fdecl.munged=tdecl.munged
-					Return
-				EndIf
-			Next
-		Else
-			funcs=New TFuncDeclList
-			funcMungs.Insert fdecl.ident,funcs
-		EndIf
-
-		If fdecl.scope Then
-			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)
-			End If
-			
-			' fields are lowercase with underscore prefix.
-			' a function pointer with FUNC_METHOD is a field function pointer.
-			'If TFieldDecl(fdecl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
-			'	munged = "_" + munged.ToLower()
-			'End If
-		Else
-			fdecl.munged="bb_"+fdecl.ident
-		End If
-		
-		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
-			' ensure function args get into local scope correctly.
-			If addIfNotInScope Then
-				If Not mungScope.Contains( decl.munged ) Then
-					mungScope.Insert(decl.munged, decl)
-				End If
-			End If
-			Return
-		End If
-
-		Local fdecl:TFuncDecl=TFuncDecl( decl )
-		
-		' apply mangling to methods and New (ctors)
-		' but don't apply mangling to function pointers
-		If fdecl And fdecl.ClassScope() And Not (fdecl.attrs & FUNC_PTR)
-			MungFuncDecl( fdecl )
-			Return
-		End If
-		
-		Local id$=decl.ident,munged$
-		
-		'this lot just makes output a bit more readable...
-'		Select ENV_LANG
-'		Case "js"
-'			If TModuleDecl( decl.scope ) Or TGlobalDecl( decl ) Or (fdecl And Not fdecl.IsMethod())
-'				munged=decl.ModuleScope().munged+"_"+id
-'			EndIf
-'		Case "as"
-'			If TModuleDecl( decl.scope )
-'				munged=decl.ModuleScope().munged+"_"+id
-'			EndIf
-'		Case "cs"
-'			If TClassDecl( decl )
-'				munged=decl.ModuleScope().munged+"_"+id
-'			EndIf
-'		Case "java"
-'			If TClassDecl( decl )
-'				munged=decl.ModuleScope().munged+"_"+id
-'			EndIf
-'		Case "cpp"
-			If TModuleDecl( decl.scope )
-				munged=decl.ModuleScope().munged+"_"+id
-				
-				If TClassDecl(decl) And TClassDecl(decl).instArgs Then
-					For Local ty:TType = EachIn TClassDecl(decl).instArgs
-						munged :+ TransMangleType(ty)
-					Next
-				End If
-			EndIf
-
-			If TModuleDecl( decl )
-				munged=decl.ModuleScope().munged+"_"+id
-			EndIf
-
-'		End Select
-'DebugStop
-
-		If Not munged
-			If TLocalDecl( decl )
-				munged="bbt_"+id
-			Else
-				If decl.scope Then
-					munged = decl.scope.munged + "_" + id
-					
-					If TClassDecl(decl) And TClassDecl(decl).instArgs Then
-						For Local ty:TType = EachIn TClassDecl(decl).instArgs
-							munged :+ TransMangleType(ty)
-						Next
-					End If
-					
-					' fields are lowercase with underscore prefix.
-					' a function pointer with FUNC_METHOD is a field function pointer.
-					If TFieldDecl(decl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
-						munged = "_" + munged.ToLower()
-					End If
-				Else
-					munged="bb_"+id
-				End If
-			EndIf
-		EndIf
-
-		'sanitize non-mung-able characters
-		munged = TStringHelper.Sanitize(munged)
-
-
-		'add an increasing number to identifier if already used  
-		If mungScope.Contains( munged )
-			Local i:Int=1
-			Repeat
-				i:+1
-			Until Not mungScope.Contains( munged + i )
-			munged :+ i
-		EndIf
-
-		mungScope.Insert(munged, decl)
-		decl.munged=munged
-		
-		' a function pointers' real function is stored in "func" - need to set its munged to match the parent.
-		If TValDecl(decl) Then
-			If TFunctionPtrType(TValDecl(decl).ty) Then
-				TFunctionPtrType(TValDecl(decl).ty).func.munged = munged
-			End If
-		End If
-		
-	End Method
-
-Rem
-	Method MungDecl( decl:TDecl )
-
-		If decl.munged Return
-
-		Local fdecl:TFuncDecl=TFuncDecl( decl )
-		If fdecl And fdecl.IsMethod() Then
-'			DebugStop
-			MungFuncDecl( fdecl )
-			Return
-		End If
-		
-		Local id:String=decl.ident,munged$,scope$
-		
-		If TLocalDecl( decl )
-			scope="$"
-			munged="t_"+id
-		Else If TClassDecl( decl )
-			scope=""
-			munged="c_"+id
-		Else If TModuleDecl( decl )
-			scope=""
-			munged="bb_"+id
-		Else If TClassDecl( decl.scope )
-			scope=decl.scope.munged
-			munged="m_"+id
-		Else If TModuleDecl( decl.scope )
-			'If ENV_LANG="cs" Or ENV_LANG="java"
-			'	scope=decl.scope.munged
-			'	munged="g_"+id
-			'Else
-				scope=""
-				munged=decl.scope.munged+"_"+id
-			'EndIf
-		Else
-			InternalErr
-		EndIf
-		
-		Local set:TMap=TMap(mungedScopes.ValueForKey( scope ))
-		If set
-			If set.Contains( munged.ToLower() )
-				Local id:Int=1
-				Repeat
-					id :+ 1
-					Local t$=munged+id
-					If set.Contains( t.ToLower() ) Continue
-					munged=t
-					Exit
-				Forever
-			End If
-		Else
-			If scope="$"
-				Print "OOPS2"
-				InternalErr
-			EndIf
-			set=New TMap
-			mungedScopes.Insert scope,set
-		End If
-		set.Insert munged.ToLower(), ""
-		decl.munged=munged
-	End Method
-End Rem
-
-
-
-	
-	Method Bra$( str$ )
-		If str.StartsWith( "(" ) And str.EndsWith( ")" )
-			Local n:Int=1
-			For Local i:Int=1 Until str.Length-1
-				Select str[i..i+1]
-				Case "("
-					n:+1
-				Case ")"
-					n:-1
-					If Not n Return "("+str+")"
-				End Select
-			Next
-			If n=1 Return str
-'			If str.FindLast("(")<str.Find(")") Return str
-		EndIf
-		Return "("+str+")"
-	End Method
-	
-	'Utility C/C++ style...
-	Method Enquote$( str$ )
-		Return LangEnquote( str )
-	End Method
-	
-	Method EscapeChars:String(str:String)
-		If str Then
-			Local found:Int = False
-			For Local i:Int = 0 Until str.length
-				If str[i] > 127 Then
-					found = True
-					Exit
-				End If
-			Next
-			
-			If Not found Then
-				Return str
-			End If
-		
-			Local s:String
-			
-			For Local i:Int = 0 Until str.length
-				Local char:Int = str[i]
-				
-				If char < 128 Then
-					s :+ Chr(char)
-				Else
-					s :+ "~~" + char + "~~"
-				End If
-			Next
-			
-			Return s
-		End If
-	End Method
-
-	Method TransUnaryOp$( op$ )
-		Select op
-		Case "+" Return "+"
-		Case "-" Return "-"
-		Case "~~" Return op
-		Case "not" Return "!"
-		End Select
-		InternalErr
-	End Method
-	
-	Method TransBinaryOp$( op$,rhs$ )
-'DebugLog "TransBinaryOp '" + op + "' : '" + rhs + "'"
-op = mapSymbol(op)
-		Select op
-		Case "+","-"
-			If rhs.StartsWith( op ) Return op+" "
-			Return op
-		Case "*","/" Return op
-		Case "shl" Return "<<"
-		Case "shr" Return ">>"
-		Case "sar" Return ">>"
-		Case "mod" Return " % "
-		Case "and" Return " && "
-		Case "or" Return " || "
-		Case "=" Return "=="
-		Case "<>" Return "!="
-		Case "<","<=",">",">=" Return op
-		Case "=<" Return "<="
-		Case "=>" Return ">="
-		Case "&","|" Return op
-		Case "~~" Return "^"
-		Case "<<", ">>" Return Op
-		Case "%" Return Op
-		End Select
-		InternalErr
-	End Method
-	
-	Method TransAssignOp$( op$ )
-op = mapSymbol(op)
-		Select op
-		Case ":mod" Return "%="
-		Case ":shl" Return "<<="
-		Case ":shr" Return ">>="
-		Case ":sar" Return ">>="
-		End Select
-		Return op
-	End Method
-	
-	Method ExprPri:Int( expr:TExpr )
-		'
-		'1=primary,
-		'2=postfix
-		'3=prefix
-		'
-		If TNewObjectExpr( expr )
-			Return 3
-		Else If TUnaryExpr( expr )
-			Select TUnaryExpr( expr ).op
-			Case "+","-","~~","not" Return 3
-			End Select
-			InternalErr
-		Else If TBinaryExpr( expr )
-			Select TBinaryExpr( expr ).op
-			Case "^" Return 4
-			Case "*","/","mod","%" Return 5
-			Case "+","-" Return 6
-			Case "shl","shr", "sar","<<", ">>" Return 7
-			Case "<","<=",">",">=", "=<", "=>" Return 8
-			Case "=","<>" Return 9
-			Case "&" Return 10
-			Case "~~" Return 11
-			Case "|" Return 12
-			Case "and" Return 13
-			Case "or" Return 14
-			End Select
-			InternalErr
-		EndIf
-		Return 2
-	End Method
-	
-	Method TransSubExpr$( expr:TExpr,pri:Int=2 )
-		Local t_expr$=expr.Trans()
-		'If expr.exprType._flags & TTYPE.T_VAR Then
-		'	t_expr = Bra("*" + t_expr)
-		'End If
-		If ExprPri( expr )>pri t_expr=Bra( t_expr )
-		Return t_expr
-	End Method
-	
-	Method TransExprNS$( expr:TExpr )
-		If TVarExpr( expr ) Return expr.Trans()
-		If TConstExpr( expr ) Return expr.Trans()
-		Return CreateLocal( expr )
-	End Method
-	
-	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, init )+";"
-
-		EmitGDBDebug(_errInfo)
-		
-		Return tmp.munged
-	End Method
-
-	'***** Utility *****
-
-	Method TransLocalDecl$( decl:TLocalDecl,init:TExpr, declare:Int = False, outputInit:Int = True ) Abstract
-
-	Method TransGlobalDecl$( gdecl:TGlobalDecl ) Abstract
-	
-	Method EmitPushErr()
-	End Method
-	
-	Method EmitSetErr( errInfo$ )
-	End Method
-	
-	Method EmitPopErr()
-	End Method
-	
-	'***** Declarations *****
-	
-	Method TransGlobal$( decl:TGlobalDecl ) Abstract
-	
-	Method TransField$( decl:TFieldDecl,lhs:TExpr ) Abstract
-	
-	Method TransFunc$( decl:TFuncDecl,args:TExpr[],lhs:TExpr, sup:Int = False, scope:TScopeDecl = Null ) Abstract
-	
-	Method TransSuperFunc$( decl:TFuncDecl,args:TExpr[], scope:TScopeDecl ) Abstract
-	
-	
-	'***** Expressions *****
-	
-	Method TransConstExpr$( expr:TConstExpr ) Abstract
-	
-	Method TransNewObjectExpr$( expr:TNewObjectExpr ) Abstract
-	
-	Method TransNewArrayExpr$( expr:TNewArrayExpr ) Abstract
-	
-	Method TransSelfExpr$( expr:TSelfExpr ) Abstract
-	
-	Method TransCastExpr$( expr:TCastExpr ) Abstract
-	
-	Method TransUnaryExpr$( expr:TUnaryExpr ) Abstract
-	
-	Method TransBinaryExpr$( expr:TBinaryExpr ) Abstract
-	
-	Method TransIndexExpr$( expr:TIndexExpr ) Abstract
-	
-	Method TransSliceExpr$( expr:TSliceExpr ) Abstract
-	
-	Method TransArrayExpr$( expr:TArrayExpr ) Abstract
-	
-	Method TransArraySizeExpr$ ( expr:TArraySizeExpr ) Abstract
-	
-	Method TransIntrinsicExpr$( decl:TDecl,expr:TExpr,args:TExpr[]=Null ) Abstract
-	
-	Method TransArgs$( args:TExpr[],decl:TFuncDecl, objParam:String = Null ) Abstract
-
-	Method EmitDebugEnterScope(block:TBlockDecl) Abstract
-	
-	Method EmitLocalDeclarations(decl:TScopeDecl, v:TValDecl = Null) Abstract
-	
-	Method TransType$( ty:TType, ident:String, fpReturnTypeFunctionArgs:String = Null, fpReturnTypeClassFunc:Int = False) Abstract
-	
-	Method BeginLocalScope()
-		mungStack.Push mungScope
-		mungScope:TMap=New TMap'<TDecl>
-'		mungedScopes.Insert "$",New TMap
-		
-		If opt_debug Then
-			localScopeStack.Push localScope
-			localScope = New TStack
-		End If
-	End Method
-	
-	Method EndLocalScope()
-		mungScope=TMap(mungStack.Pop())
-'		mungedScopes.Insert "$",Null
-
-		If opt_debug Then
-			localScope = TStack(localScopeStack.Pop())
-		End If
-	End Method
-
-Rem	
-	Method MungMethodDecl( fdecl:TFuncDecl )
-
-		If fdecl.munged Return
-		
-		If fdecl.overrides
-			MungMethodDecl fdecl.overrides
-			fdecl.munged=fdecl.overrides.munged
-			Return
-		EndIf
-		
-		Local funcs:=funcMungs.Get( fdecl.ident )
-		If funcs
-			For Local tdecl:=EachIn funcs
-				If fdecl.EqualsArgs( tdecl )
-					fdecl.munged=tdecl.munged
-					Return
-				EndIf
-			Next
-		Else
-			funcs=New FuncDeclList
-			funcMungs.Set fdecl.ident,funcs
-		EndIf
-		
-		Local id:=fdecl.ident
-		If mungedFuncs.Contains( id )
-			Local n:=1
-			Repeat
-				n+=1
-				id=fdecl.ident+String(n)
-			Until Not mungedFuncs.Contains( id )
-		EndIf
-		
-		mungedFuncs.Set id,fdecl
-		fdecl.munged="p_"+id
-		funcs.AddLast fdecl
-	End
-End Rem	
-	'***** Simple statements *****
-	
-	'Expressions
-	Method TransStmtExpr$( expr:TStmtExpr )
-		Local t$=expr.stmt.Trans()
-		If t Emit t+";"
-		Return expr.expr.Trans()
-	End Method
-	
-	Method TransTemplateCast$( ty:TType,src:TType,expr$ )
-		Return expr
-	End Method
-	
-	Method TransVarExpr$( expr:TVarExpr )
-		Local decl:TVarDecl=TVarDecl( expr.decl.actual )
-
-		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null )
-		
-		If TLocalDecl( decl ) Then
-			If decl.ty._flags & TType.T_VAR Then
-				Return "*" + decl.munged
-			Else
-				Return decl.munged
-			End If
-		End If
-		
-		If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),Null )
-		
-		If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
-		
-		InternalErr
-	End Method
-	
-	Method TransMemberVarExpr$( expr:TMemberVarExpr )
-		Local decl:TVarDecl=TVarDecl( expr.decl.actual )
-		
-		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr )
-		
-		If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),expr.expr )
-
-		If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
-
-		InternalErr
-	End Method
-	
-	Method TransInvokeExpr$( expr:TInvokeExpr )
-		Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
-'If decl.ident = "OnDebugStop" DebugStop	
-		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 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 )
-		
-		If processingReturnStatement = 1 Then
-			If decl Then
-				processingReturnStatement :+ 1
-				Return CreateLocal(expr)
-			End If
-		Else
-			If decl Return TransFunc( TFuncDecl(decl),expr.args,Null )
-		End If
-		
-		InternalErr
-	End Method
-	
-	Method TransInvokeMemberExpr$( expr:TInvokeMemberExpr )
-		Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
-
-		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr,expr.args )
-		
-		If processingReturnStatement = 1 Then
-			If decl Then
-				processingReturnStatement :+ 1
-				Return CreateLocal(expr)
-			End If
-		Else
-			If decl Return TransFunc( TFuncDecl(decl),expr.args,expr.expr )	
-		End If
-		
-		InternalErr
-	End Method
-	
-	Method TransInvokeSuperExpr$( expr:TInvokeSuperExpr )
-		Local decl:TFuncDecl=TFuncDecl( expr.origFuncDecl.actual ),t$
-
-		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr )
-		
-		If processingReturnStatement = 1 Then
-			If decl Then
-				processingReturnStatement :+ 1
-				Return CreateLocal(expr)
-			End If
-		Else
-			If decl Return TransSuperFunc( TFuncDecl( expr.funcDecl ),expr.args, expr.classScope )
-		End If
-		
-		InternalErr
-	End Method
-	
-	Method TransFuncCallExpr:String( expr:TFuncCallExpr )
-
-		If TIndexExpr(expr.expr) And TArrayType(TIndexExpr(expr.expr).expr.exprType) And TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType) Then
-			Local decl:TDecl = TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType).func.actual
-			decl.Semant()
-			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
-	
-	Method TransExprStmt$( stmt:TExprStmt )
-		Return stmt.expr.TransStmt()
-	End Method
-	
-	Method TransAssignStmt$( stmt:TAssignStmt )
-		If stmt.rhs Return stmt.lhs.TransVar()+TransAssignOp(stmt.op)+stmt.rhs.Trans()
-		Return stmt.lhs.Trans()
-	End Method
-	
-	Method TransReturnStmt$( stmt:TReturnStmt )
-
-		Local t$="return"
-		unreachable=True
-		If stmt.expr Then
-
-			If TObjectType(stmt.expr.exprType) And TNullDecl(TObjectType(stmt.expr.exprType).classDecl) Then
-				If IsPointerType(stmt.fRetType, 0, TType.T_POINTER) Or IsNumericType(stmt.fRetType) Then
-					t:+ " 0"
-				End If
-				If TStringType(stmt.fRetType) Then
-					t:+ " &bbEmptyString"
-				End If
-				If TArrayType(stmt.fRetType) Then
-					t:+ " &bbEmptyArray"
-				End If
-
-			Else
-				
-				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
-						t:+" " + s
-					End If
-				End If
-			End If
-			
-		End If
-
-		FreeVarsIfRequired()
-		
-		' if this is a Delete() method, we need to call the dtor first
-		Local funcScope:TFuncDecl = _env.FuncScope()
-		If funcScope And funcScope.IdentLower() = "delete" Then
-			Local classScope:TClassDecl = funcScope.ClassScope()
-			If classScope Then
-				EmitClassDeclDeleteDtor(classScope)
-			End If
-		End If
-		
-		Return t
-	End Method
-	
-	Method NextExitId:Int(bc:TTryBreakCheck)
-		If Not bc.exitId Then
-			exitLabelId :+ 1
-			bc.exitId = exitLabelId
-		End If
-		
-		Return bc.exitId
-	End Method
-
-	Method NextContId:Int(bc:TTryBreakCheck)
-		If Not bc.contId Then
-			contLabelId :+ 1
-			bc.contId = contLabelId
-		End If
-		
-		Return bc.contId
-	End Method
-
-	Method TransContinueStmt$( stmt:TContinueStmt )
-		unreachable=True
-
-		Local contLoop:TStmt
-		' if we are continuing with a loop label, we'll need to find it in the stack
-		If stmt.label And TLoopLabelExpr(stmt.label) Then
-			contLoop = TLoopLabelExpr(stmt.label).loop
-		End If
-		' get count of Try statements in the stack in this loop
-		Local count:Int = LoopTryDepth(contLoop)
-		If count > 0 Then
-			Local bc:TTryBreakCheck = GetTopLoop(contLoop)
-			If bc Then
-				NextContId(bc)
-				For Local i:Int = 0 Until count
-					Emit "bbExLeave();"
-					If opt_debug Then
-						Emit "bbOnDebugPopExState();"
-					End If
-				Next
-				Emit "goto " + TransLabelCont(bc, False)
-			Else
-				InternalErr
-			End If
-		Else
-		 	' For debug builds, we need to rollback the local scope stack correctly
-			count = 0
-			
-			If opt_debug And TLoopStmt(contLoop) And Not TLoopStmt(contLoop).block.IsNoDebug() Then
-				count = LoopLocalScopeDepth(contLoop)
-			End If
-			
-			If count > 0 Then
-				Local bc:TTryBreakCheck = GetTopLocalLoop(contLoop)
-				If bc Then
-					NextContId(bc)
-					For Local i:Int = 0 Until count
-						Emit "bbOnDebugLeaveScope();"
-					Next
-					Emit "goto " + TransLabelCont(bc, False)
-				Else
-					InternalErr
-				End If
-			Else
-
-				If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
-					count = LoopLocalScopeDepth(Null)
-				End If
-				For Local i:Int = 0 Until count
-					Emit "bbOnDebugLeaveScope();"
-				Next
-
-				' No Try statements in the stack here..
-				If stmt.label And TLoopLabelExpr(stmt.label) Then
-					Emit "goto " + TransLoopLabelCont(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
-				Else
-					Return "continue"
-				End If
-			End If
-		End If
-	End Method
-	
-	Method TransBreakStmt$( stmt:TBreakStmt )
-		unreachable=True
-		broken:+1
-
-		Local brkLoop:TStmt
-		' if we are exiting with a loop label, we'll need to find it in the stack
-		If stmt.label And TLoopLabelExpr(stmt.label) Then
-			brkLoop = TLoopLabelExpr(stmt.label).loop
-		End If
-		' get count of Try statements in the stack in this loop
-		Local count:Int = LoopTryDepth(brkLoop)
-		If count > 0 Then
-			Local bc:TTryBreakCheck = GetTopLoop(brkLoop)
-			If bc Then
-				NextExitId(bc)
-				For Local i:Int = 0 Until count
-					Emit "bbExLeave();"
-					If opt_debug Then
-						Emit "bbOnDebugPopExState();"
-					End If
-				Next
-				Emit "goto " + TransLabelExit(bc, False)
-			Else
-				InternalErr
-			End If
-		Else
-		 	' For debug builds, we need to rollback the local scope stack correctly
-			count = 0
-			
-			If opt_debug And TLoopStmt(brkLoop) And Not TLoopStmt(brkLoop).block.IsNoDebug() Then
-				count = LoopLocalScopeDepth(brkLoop)
-			End If
-			
-			If count > 0 Then
-				Local bc:TTryBreakCheck = GetTopLocalLoop(brkLoop)
-				If bc Then
-					NextExitId(bc)
-					For Local i:Int = 0 Until count
-						Emit "bbOnDebugLeaveScope();"
-					Next
-					Emit "goto " + TransLabelExit(bc, False)
-				Else
-					InternalErr
-				End If
-			Else
-
-				If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
-					count = LoopLocalScopeDepth(Null)
-				End If
-				For Local i:Int = 0 Until count
-					Emit "bbOnDebugLeaveScope();"
-				Next
-				
-				' No Try statements in the stack here..
-				If stmt.label And TLoopLabelExpr(stmt.label) Then
-					Emit "goto " + TransLoopLabelExit(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
-				Else
-					Return "break"
-				End If
-			End If
-		End If
-	End Method
-	
-	Method TransTryStmt$( stmt:TTryStmt )
-	End Method
-	
-	Method EmitTryStack() Abstract
-
-	Method TransThrowStmt$( stmt:TThrowStmt )
-	End Method
-	
-
-	Method TransBuiltinExpr$( expr:TBuiltinExpr )
-		If TMinExpr(expr) Return TransMinExpr(TMinExpr(expr))
-		If TMaxExpr(expr) Return TransMaxExpr(TMaxExpr(expr))
-		If TAbsExpr(expr) Return TransAbsExpr(TAbsExpr(expr))
-		If TAscExpr(expr) Return TransAscExpr(TAscExpr(expr))
-		If TChrExpr(expr) Return TransChrExpr(TChrExpr(expr))
-		If TSgnExpr(expr) Return TransSgnExpr(TSgnExpr(expr))
-		If TLenExpr(expr) Return TransLenExpr(TLenExpr(expr))
-		If TSizeOfExpr(expr) Return TransSizeOfExpr(TSizeOfExpr(expr))
-		Err "TODO : TransBuiltinExpr()"
-	End Method
-	
-	Method TransMinExpr:String(expr:TMinExpr)
-	End Method
-
-	Method TransMaxExpr:String(expr:TMaxExpr)
-	End Method
-
-	Method TransAbsExpr:String(expr:TAbsExpr)
-	End Method
-
-	Method TransAscExpr:String(expr:TAscExpr)
-	End Method
-
-	Method TransChrExpr:String(expr:TChrExpr)
-	End Method
-
-	Method TransSgnExpr:String(expr:TSgnExpr)
-	End Method
-
-	Method TransLenExpr:String(expr:TLenExpr)
-	End Method
-
-	Method TransSizeOfExpr:String(expr:TSizeOfExpr)
-	End Method
-	
-	Method TransIdentTypeExpr:String(expr:TIdentTypeExpr) Abstract
-	
-	Method TransLabelCont:String(bc:TTryBreakCheck, jmp:Int = True)
-		If jmp Then
-			Return "_contjmp" + bc.contId + ": ;"
-		Else
-			Return "_contjmp" + bc.contId + ";"
-		End If
-	End Method
-	
-	Method TransLabelExit:String(bc:TTryBreakCheck, jmp:Int = True)
-		If jmp Then
-			Return "_exitjmp" + bc.exitId + ": ;"
-		Else
-			Return "_exitjmp" + bc.exitId + ";"
-		End If
-	End Method
-
-	Method TransLoopLabelCont:String(id:String, jmp:Int = True)
-		If jmp Then
-			Return "_loopcont_" + id.ToLower() + ": ;"
-		Else
-			Return "_loopcont_" + id.ToLower() + ";"
-		End If
-	End Method
-
-	Method TransLoopLabelExit:String(id:String, jmp:Int = True)
-		If jmp Then
-			Return "_loopexit_" + id.ToLower() + ": ;"
-		Else
-			Return "_loopexit_" + id.ToLower() + ";"
-		End If
-	End Method
-
-	'***** Block statements - all very C like! *****
-	
-	Method Emit( t$, useIndent:Int = True )
-		If Not t Return
-		If useIndent
-			If t.StartsWith( "}" )
-				indent=indent[..indent.Length-1]
-			EndIf
-		End If
-		LINES.AddLast indent+t
-		'code+=indent+t+"~n"
-		If useIndent
-			If t.EndsWith( "{" )
-				indent:+"~t"
-			EndIf
-		End If
-	End Method
-	
-	Method JoinLines$( file:String )
-		Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
-		
-		Local code$=_lines.Join( "~n" )
-		_lines.Clear
-		Return code
-	End Method
-	
-	'returns unreachable status!
-	Method EmitBlock:Int( block:TBlockDecl )
-		Local stmtCount:Int
-'DebugStop
-		'If ENV_CONFIG="debug"
-		'	If TFuncDecl( block ) EmitPushErr
-		'EndIf
-
-
-		PushEnv block
-		
-		' enter scope
-		If opt_debug And Not block.IsNoDebug() And Not block.generated Then
-			PushLoopLocalStack(block)
-			EmitDebugEnterScope(block)
-		End If
-
-		For Local stmt:TStmt=EachIn block.stmts
-		
-			_errInfo=stmt.errInfo
-			
-			If unreachable
-				' Statements following cannot be reached - maybe we have Returned, etc
-				' So don't process any more for this block - they won't be generated now!
-				Exit
-			EndIf
-
-Rem
-			If ENV_CONFIG="debug"
-				Local rs:TReturnStmt=TReturnStmt( stmt )
-				If rs
-					If rs.expr
-						EmitSetErr stmt.errInfo
-						Local t_expr$=TransExprNS( rs.expr )
-						EmitPopErr
-						Emit "return "+t_expr+";"
-					Else
-						EmitPopErr
-						Emit "return;"
-					EndIf
-					unreachable=True
-					Continue
-				EndIf
-				EmitSetErr stmt.errInfo
-			EndIf
-End Rem
-			If opt_debug And Not block.IsNoDebug() Then
-				' only for user-made code
-				If Not stmt.generated Then
-					EmitDebugStmtErrInfo(stmt.errInfo, stmtCount)
-					stmtCount :+ 1
-				End If
-			
-			End If
-
-			EmitGDBDebug(stmt)
-			
-			If TReturnStmt(stmt) And Not tryStack.IsEmpty() Then
-				processingReturnStatement = True
-			End If
-			
-			Local t$=stmt.Trans()
-			
-			processingReturnStatement = False
-			
-			If opt_debug And Not block.IsNoDebug() Then
-				If TReturnStmt(stmt) Then
-					For Local b:TBlockDecl = EachIn localScope
-						Emit "bbOnDebugLeaveScope();"
-					Next
-				End If
-			End If
-
-			If TReturnStmt(stmt) Then
-				EmitTryStack()
-			End If
-			
-			If t Emit t+";"
-
-			If DEBUG And debugOut Then
-				Emit debugOut
-				debugOut = Null
-			End If
-			
-			Local v:String = String(customVarStack.Pop())
-			While v
-				Emit "bbMemFree" + Bra(v) + ";"
-				v = String(customVarStack.Pop())
-			Wend
-			
-		Next
-
-		If opt_debug And Not block.IsNoDebug() And Not block.generated Then
-			PopLoopLocalStack()
-			If Not unreachable Then
-				Emit "bbOnDebugLeaveScope();"
-			End If
-		End If
-
-		Local r:Int=unreachable
-		unreachable=False
-		PopEnv
-		Return r
-	End Method
-	
-	Method TransDeclStmt$( stmt:TDeclStmt, declare:Int = False )
-		Local decl:TLocalDecl=TLocalDecl( stmt.decl )
-		If decl
-			MungDecl decl
-			' only generate local declarations once.
-			If decl.generated Then
-				If Not decl.done Then
-					decl.done = True
-				Else
-					Return ""
-				End If
-			End If
-			Return TransLocalDecl( decl,decl.init, decl.generated Or declare )
-		EndIf
-		Local cdecl:TConstDecl=TConstDecl( stmt.decl )
-		If cdecl
-			Return Null
-		EndIf
-		Local gdecl:TGlobalDecl=TGlobalDecl( stmt.decl )
-		If gdecl Then
-			MungDecl gdecl
-			If gdecl.inited Return Null
-			Return TransGlobalDecl( gdecl )
-		End If
-		InternalErr
-	End Method
-	
-	Method TransIfStmt$( stmt:TIfStmt )
-		If TConstExpr( stmt.expr )
-			If TConstExpr( stmt.expr ).value
-				Emit "{"
-				EmitLocalDeclarations(stmt.thenBlock)
-				If EmitBlock( stmt.thenBlock ) unreachable=True
-				Emit "}"
-			Else If stmt.elseBlock.stmts.First()
-				Emit "{"
-				EmitLocalDeclarations(stmt.elseBlock)
-				If EmitBlock( stmt.elseBlock ) unreachable=True
-				Emit "}"
-			EndIf
-		Else If stmt.elseBlock.stmts.First()
-			Emit "if"+Bra( stmt.expr.Trans() )+"{"
-			EmitLocalDeclarations(stmt.thenBlock)
-			FreeVarsIfRequired(False)
-			PushVarScope
-			Local unr:Int=EmitBlock( stmt.thenBlock )
-			PopVarScope
-			Emit "}else{"
-			EmitLocalDeclarations(stmt.elseBlock)
-			FreeVarsIfRequired
-			Local unr2:Int=EmitBlock( stmt.elseBlock )
-			Emit "}"
-			If unr And unr2 unreachable=True
-		Else
-
-'			Emit "if"+ Bra(TransCondition(stmt.expr)) + "{"
-'			If TVarExpr(stmt.expr) Then
-'				If TObjectType(TVarExpr(stmt.expr).exprType) Then
-'					Emit "if"+Bra( stmt.expr.Trans() + "!= &bbNullObject") + "{"
-'				Else If TStringType(TVarExpr(stmt.expr).exprType)  Then
-'					Emit "if"+Bra( stmt.expr.Trans() + "!= &bbEmptyString") + "{"
-'				Else
-'					Emit "if"+Bra( stmt.expr.Trans() )+"{"
-'				End If
-'			Else
-				Emit "if"+Bra( stmt.expr.Trans() )+"{"
-				FreeVarsIfRequired(False)
-'			End If
-			EmitLocalDeclarations(stmt.thenBlock)
-			PushVarScope
-			Local unr:Int=EmitBlock( stmt.thenBlock )
-			PopVarScope
-			Emit "}"
-			FreeVarsIfRequired
-		EndIf
-	End Method
-	
-	Method FreeVarsIfRequired(removeFromStack:Int = True)
-		If removeFromStack
-			Local v:String = String(customVarStack.Pop())
-			While v
-				Emit "bbMemFree" + Bra(v) + ";"
-				v = String(customVarStack.Pop())
-			Wend
-		Else
-			For Local v:String = EachIn customVarStack
-				Emit "bbMemFree" + Bra(v) + ";"
-			Next
-		End If
-	End Method
-	
-'	Method TransCondition:String(expr:TExpr)
-'		If TVarExpr(expr) Then
-'			If TObjectType(TVarExpr(expr).exprType) Then
-'				Return Bra( expr.Trans() + "!= &bbNullObject")
-'			Else If TStringType(TVarExpr(expr).exprType)  Then
-'				Return Bra( expr.Trans() + "!= &bbEmptyString")
-'			Else
-'				Return Bra( expr.Trans() )
-'			End If
-'		Else
-'			Return Bra( expr.Trans() )
-'		End If
-'	End Method
-	
-	Method TransWhileStmt$( stmt:TWhileStmt )
-		Local nbroken:Int=broken
-
-		Emit "while"+Bra( stmt.expr.Trans() )+"{"
-		
-		Local check:TTryBreakCheck = New TTryBreakCheck
-		check.stmt = stmt
-		PushLoopTryStack(check)
-		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
-			PushLoopLocalStack(check)
-		End If
-		EmitLocalDeclarations(stmt.block)
-		Local unr:Int=EmitBlock( stmt.block )
-		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
-			PopLoopLocalStack
-		End If
-		PopLoopTryStack
-		
-		If check.contId Then
-			Emit TransLabelCont(check)
-		End If
-
-		If stmt.loopLabel Then
-			Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
-		End If
-		
-		Emit "}"
-
-		If check.exitId Then
-			Emit TransLabelExit(check)
-		End If
-
-		If stmt.loopLabel Then
-			Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
-		End If
-		
-		If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
-		broken=nbroken
-	End Method
-
-	Method TransRepeatStmt$( stmt:TRepeatStmt )
-		Local nbroken:Int=broken
-
-		SetOutputTemp()
-
-		Emit "do{"
-		
-		Local check:TTryBreakCheck = New TTryBreakCheck
-		check.stmt = stmt
-		PushLoopTryStack(check)
-		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
-			PushLoopLocalStack(check)
-		End If
-		EmitLocalDeclarations(stmt.block)
-		Local unr:Int=EmitBlock( stmt.block )
-		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
-			PopLoopLocalStack
-		End If
-		PopLoopTryStack
-
-		If check.contId Then
-			Emit TransLabelCont(check)
-		End If
-
-		If stmt.loopLabel Then
-			Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
-		End If
-		
-		SetOutput("source")
-
-		Local s:String = "}while(!"+Bra( stmt.expr.Trans() )+");"
-		
-		SetOutputTemp(True)
-		
-		Emit s
-
-		If check.exitId Then
-			Emit TransLabelExit(check)
-		End If
-
-		If stmt.loopLabel Then
-			Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
-		End If
-
-		If broken=nbroken And TConstExpr( stmt.expr ) And Not TConstExpr( stmt.expr ).value unreachable=True
-		broken=nbroken
-	End Method
-
-	Method TransForStmt$( stmt:TForStmt )
-		Local nbroken:Int=broken
-
-		Local init$
-
-		Local decl:Int
-		Local vdecl:TValDecl
-		If TDeclStmt(stmt.init) Then
-			decl = True
-			Emit "{"
-			Emit TransDeclStmt(TDeclStmt(stmt.init), True) + ";"
-			init = TDeclStmt(stmt.init).decl.munged
-			vdecl = TValDecl(TDeclStmt(stmt.init).decl)
-		Else
-			init=stmt.init.Trans()
-		End If
-		Local expr$=stmt.expr.Trans()
-		Local incr$=stmt.incr.Trans()
-
-		Emit "for("+init+";"+expr+";"+incr+"){"
-
-		Local check:TTryBreakCheck = New TTryBreakCheck
-		check.stmt = stmt
-		PushLoopTryStack(check)
-		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
-			PushLoopLocalStack(check)
-		End If
-		EmitLocalDeclarations(stmt.block, vdecl)
-		Local unr:Int=EmitBlock( stmt.block )
-		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
-			PopLoopLocalStack
-		End If
-		PopLoopTryStack
-		
-		If check.contId Then
-			Emit TransLabelCont(check)
-		End If
-
-		If stmt.loopLabel Then
-			Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
-		End If
-		
-		Emit "}"
-		
-		If decl Then
-			Emit "}"
-		End If
-
-		If check.exitId Then
-			Emit TransLabelExit(check)
-		End If
-
-		If stmt.loopLabel Then
-			Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
-		End If
-		
-		If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
-		broken=nbroken
-	End Method
-
-	Method TransAssertStmt$( stmt:TAssertStmt ) Abstract
-
-	Method TransEndStmt$( stmt:TEndStmt ) Abstract
-
-	Method TransReleaseStmt$( stmt:TReleaseStmt ) Abstract
-
-	Method TransRestoreDataStmt$( stmt:TRestoreDataStmt ) Abstract
-
-	Method TransReadDataStmt$( stmt:TReadDataStmt ) Abstract
-	
-	Method TransNativeStmt$( stmt:TNativeStmt) Abstract
-
-	'module
-	Method TransApp( app:TAppDecl ) Abstract
-
-Rem	
-	Method MungOverrides( cdecl:TClassDecl )
-		For Local decl:=Eachin cdecl.Semanted
-			Local fdecl:=TFuncDecl( decl )
-			If fdecl And fdecl.overrides
-				If Not fdecl.overrides.munged InternalErr
-				fdecl.munged=fdecl.overrides.munged
-				mungScope.Insert fdecl.munged,fdecl
-			Endif
-		Next
-	End
-End Rem
-	
-	Method PostProcess$( source$ ) 
-		Return source
-	End Method
-	
-	Method SetOutput( file:String )
-		Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
-		
-		If Not _lines Then
-			_lines = New TStringList
-			outputFiles.Insert(file, _lines)
-		End If
-		
-		LINES = _lines
-		
-	End Method
-
-	Method SetOutputTemp( fin:Int = False )
-		Global tmpLevel:Int = 0
-	
-		If Not fin Then
-			tmpLevel :+ 1
-
-			Local _lines:TStringList = New TStringList
-			outputFiles.Insert("tmp" + tmpLevel, _lines)
-	
-			LINES = _lines
-		Else
-			Local _lines:TStringList = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
-			
-			tmpLevel :- 1
-		
-			If Not tmpLevel Then
-				SetOutput("source")
-			Else
-				LINES = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
-			End If
-			
-			If _lines Then
-				For Local line:String = EachIn _lines
-					LINES.AddLast(line)
-				Next
-			End If
-			
-		End If
-	End Method
-
-	Method DebugPrint(text:String, func:String = Null, trans:Int = False)
-		Global count:Int
-		Global lastFunc:String
-		
-		If func Then
-			lastFunc = func
-		End If
-		
-		Local s:String = "fprintf(stderr," + "~q" + lastFunc + " : " + count + " :: " + text + "\n~q)" + ";fflush(stderr);"
-		
-		If trans Then
-			debugOut :+ indent + s + "~n"
-		Else
-			Emit s
-		End If
-		count :+ 1
-	End Method
-	
-	Method DebugString(s:String, func:String = Null, trans:Int = False)
-		' bbNullObject test
-		If trans Then
-			debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
-		Else
-			Emit "if (" + s + "==&bbNullObject) {"
-		End If
-		DebugPrint("Invalid Null String : " + s, func, trans)
-		If trans Then
-			debugOut :+ indent + "}~n"
-		Else
-			Emit "}"
-		End If
-	End Method
-
-	Method DebugArray(s:String, func:String = Null, trans:Int = False)
-		' bbNullObject test
-		If trans Then
-			debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
-		Else
-			Emit "if (" + s + "==&bbNullObject) {"
-		End If
-		DebugPrint("Invalid Null Array : " + s, func, trans)
-		If trans Then
-			debugOut :+ indent + "}~n"
-		Else
-			Emit "}"
-		End If
-	End Method
-
-	Method DebugObject(ty:TType, id:String, func:String = Null, trans:Int = False)
-		If TObjectType(ty) Or TStringType(ty) Or TArrayType(ty) Then
-			' null test
-			If trans Then
-				debugOut :+ indent + "if (" + id + "==NULL) {~n"
-			Else
-				Emit "if (" + id + "==NULL) {"
-			End If
-			DebugPrint("Null Pointer : " + id, func, trans)
-			If trans Then
-				If ABORT_ON_NULL Then
-					debugOut :+ indent + "abort();~n"
-				End If
-				debugOut :+ indent + "}~n"
-			Else
-				If ABORT_ON_NULL Then
-					Emit "abort();~n"
-				End If
-				Emit "}"
-			End If
-		End If
-		
-		If TStringType(ty) Then
-			DebugString(id, func, trans)
-		Else If TArrayType(ty) Then
-			DebugArray(id, func, trans)
-		End If
-	End Method
-	
-	Method EmitDebugStmtErrInfo(info:String, count:Int)
-		' extract from info
-		info = info[1..info.length-1]
-		Local infoArray:String[] = info.Split(";")
-
-		Local dbg:String = "struct BBDebugStm __stmt_" + count + " = {"
-		dbg :+ Enquote(infoArray[0]) + ", "
-		dbg :+ infoArray[1] + ", "
-		dbg :+ infoArray[2] + "};"
-		Emit dbg
-		Emit "bbOnDebugEnterStm(&__stmt_" + count + ");" 
-	End Method
-	
-	Method EmitGDBDebug(obj:Object)
-		If opt_gdbdebug Then
-			If TStmt(obj) Then
-				Local stmt:TStmt = TStmt(obj)
-				Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
-				If Not stmt.generated Then
-					Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
-				End If
-			Else If TDecl(obj) Then
-				Local decl:TDecl = TDecl(obj)
-				Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
-				Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
-			Else If String(obj) Then
-				Local errInfo:String = String(obj)
-				Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
-				Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
-			End If
-		End If
-	End Method
-	
-	Method EmitClassDeclDeleteDtor( classDecl:TClassDecl )
-	End Method
-	
-End Type
-
-Type TTryBreakCheck
-
-	Field contId:Int
-	Field exitId:Int
-
-	Field stmt:TStmt
-	
-End Type
+' Copyright (c) 2013-2017 Bruce A Henderson
+'
+' Based on the public domain Monkey "trans" by Mark Sibly
+'
+' This software is provided 'as-is', without any express or implied
+' warranty. In no event will the authors be held liable for any damages
+' arising from the use of this software.
+'
+' Permission is granted to anyone to use this software for any purpose,
+' including commercial applications, and to alter it and redistribute it
+' freely, subject to the following restrictions:
+'
+'    1. The origin of this software must not be misrepresented; you must not
+'    claim that you wrote the original software. If you use this software
+'    in a product, an acknowledgment in the product documentation would be
+'    appreciated but is not required.
+'
+'    2. Altered source versions must be plainly marked as such, and must not be
+'    misrepresented as being the original software.
+'
+'    3. This notice may not be removed or altered from any source
+'    distribution.
+'
+
+Global _trans:TTranslator
+
+Type TTranslator
+
+	Field _app:TAppDecl
+
+	Field outputFiles:TMap = New TMap
+
+	Field indent$
+	Field LINES:TStringList'=New TStringList
+	Field unreachable:Int,broken:Int
+	
+	Field contLabelId:Int
+	Field exitLabelId:Int
+	
+	'Munging needs a big cleanup!
+	
+	Field mungScope:TMap=New TMap'<TDecl>
+	Field mungStack:TStack=New TStack'< StringMap<TDecl> >
+	Field funcMungs:TMap=New TMap'<FuncDeclList>
+	Field customVarStack:TStack = New TStack
+	Field varStack:TStack = New TStack
+
+	Field tryStack:TStack = New TStack
+	Field loopTryStack:TStack = New TStack
+
+	Field mungedScopes:TMap=New TMap'<StringSet>
+	'Field funcMungs:TFuncDeclList=New TFuncDeclList
+	'Field mungedFuncs:TMap=New Map
+	Field localScopeStack:TStack = New TStack
+	Field localScope:TStack = New TStack
+	Field ind:Int
+	Field debugOut:String
+	
+	Field processingReturnStatement:Int
+
+	Method PushVarScope()
+		varStack.Push customVarStack
+		customVarStack = New TStack
+	End Method
+	
+	Method PopVarScope()
+		customVarStack=TStack(varStack.Pop())
+	End Method
+	
+	Method PushLoopLocalStack(stmt:Object)
+		ind :+ 1
+		If DEBUG Then
+			Emit "// --> STACK = " + ind
+		End If
+		localScope.Push stmt
+	End Method
+
+	Method PopLoopLocalStack()
+		If DEBUG Then
+			Emit "// <-- STACK = " + ind
+		End If
+		ind :- 1
+		If ind < 0 Then
+			InternalErr
+		End If
+		localScope.Pop
+	End Method
+
+	Method LoopLocalScopeDepth:Int(findStmt:TStmt)
+		Local count:Int = 0
+
+		For Local stmt:Object = EachIn localScope
+			If TBlockDecl(stmt) = Null Then
+				If findStmt And TTryBreakCheck(stmt) And findStmt <> TTryBreakCheck(stmt).stmt Then
+					Continue
+				End If
+				Exit
+			End If
+
+			count :+ 1
+		Next
+		
+		Return count
+	End Method
+
+	Method GetTopLocalLoop:TTryBreakCheck(findStmt:TStmt)
+		For Local tbc:TTryBreakCheck = EachIn localScope
+			If findStmt And findStmt <> tbc.stmt Then
+				Continue
+			End If
+			Return tbc
+		Next
+	End Method
+
+	Method PushLoopTryStack(stmt:Object)
+		If loopTryStack.Length() = 0 Then
+			' Try statements can only be applied here to loops
+			If TTryStmt(stmt) = Null Then
+				loopTryStack.Push stmt
+			End If
+		Else
+			loopTryStack.Push stmt
+		End If
+	End Method
+
+	Method PopLoopTryStack()
+		loopTryStack.Pop
+	End Method
+	
+	Method LoopTryDepth:Int(findStmt:TStmt)
+		Local count:Int = 0
+		
+		For Local stmt:Object = EachIn loopTryStack
+			If TTryStmt(stmt) = Null Then
+				If findStmt And findStmt <> stmt Then
+					Continue
+				End If
+				
+				Exit
+			End If
+
+			count :+ 1
+		Next
+		
+		Return count
+	End Method
+
+	Method GetTopLoop:TTryBreakCheck(findStmt:TStmt)
+		For Local tbc:TTryBreakCheck = EachIn loopTryStack
+			If findStmt And findStmt <> tbc.stmt Then
+				Continue
+			End If
+			Return tbc
+		Next
+	End Method
+
+	Method TransManglePointer$( ty:TType )
+		Local p:String
+		
+		If ty
+
+			If ty._flags & TType.T_VAR Then
+				p:+ "v"
+			End If
+
+			If ty._flags & TType.T_PTR Then
+				p:+ "p"
+			Else If ty._flags & TType.T_PTRPTR Then
+				p:+ "pp"
+			Else If ty._flags & TType.T_PTRPTRPTR Then
+				p:+ "ppp"
+			End If
+
+		End If
+		
+		Return p
+	End Method
+
+	Method TransMangleType:String(ty:TType)
+		Local p:String = TransManglePointer(ty)
+
+		If TVoidType( ty ) Return "v"
+		If TByteType( ty ) Return p + "b"
+		If TShortType( ty ) Return p + "s"
+		If TIntType( ty ) Return p + "i"
+		If TUIntType( ty ) Return p + "u"
+		If TFloatType( ty ) Return p + "f"
+		If TDoubleType( ty ) Return p + "d"
+		If TLongType( ty ) Return p + "l"
+		If TULongType( ty ) Return p + "y"
+		If TSizeTType( ty ) Return p + "z"
+		If 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
+		If TObjectType( ty ) Then
+			If Not TObjectType( ty ).classdecl.IsExtern()
+				Return p + "T" + TObjectType( ty ).classDecl.ident
+			Else
+				If TObjectType( ty ).classdecl.IsInterface() Then
+					Return p + "I" + TObjectType(ty).classDecl.ident
+				ElseIf TObjectType( ty ).classdecl.IsStruct() Then
+					Return p + "R" + TObjectType(ty).classDecl.ident
+				Else
+					Return p + "E" + TObjectType(ty).classDecl.ident
+				End If
+			End If
+		End If
+		If TFunctionPtrType( ty ) Then
+			Local func:TFuncDecl = TFunctionPtrType( ty ).func
+			Local s:String = "F" + MangleMethodArgs(func)
+'			For Local i:Int = 0 Until func.argDecls.length
+'				s :+ TransMangleType(func.argDecls[i].ty)
+'			Next
+			Return s + "_" + TransMangleType(func.retType) + "_"
+		End If
+		
+		Err "Unsupported type for name mangling : " + ty.ToString()
+	End Method
+
+	Method MangleMethod:String(fdecl:TFuncDecl)
+		If (fdecl.IsMethod() And Not fdecl.ClassScope().IsStruct())Or fdecl.IsCtor() Then
+			Return MangleMethodArgs(fdecl)
+		Else
+			Return MangleMethodRetType(fdecl) + MangleMethodArgs(fdecl)
+		End If
+	End Method
+	
+	Method MangleMethodRetType:String(fdecl:TFuncDecl)
+		If fdecl.retType Then
+			Return "_" + TransMangleType(fdecl.retType)
+		Else
+			Return "_v"
+		End If
+	End Method
+	
+	Method MangleMethodArgs:String(fdecl:TFuncDecl)
+		Local s:String
+		For Local arg:TArgDecl = EachIn fdecl.argDecls
+			If Not s Then
+				s = "_"
+			End If
+			s :+ TransMangleType(arg.ty)
+		Next
+		Return s
+	End Method
+
+	Method equalsTorFunc:Int(classDecl:TClassDecl, func:TFuncDecl)
+		If func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
+			Return True
+		End If
+		Return False
+	End Method
+
+	Method equalsBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
+		If func.equalsBuiltIn > -1 Then
+			Return func.equalsBuiltIn
+		End If
+	
+		If checked Or func.IdentLower() = "tostring" Or func.IdentLower() = "compare" Or func.IdentLower() = "sendmessage" Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
+			If classDecl.munged = "bbObjectClass" Then
+				For Local decl:TFuncDecl = EachIn classDecl.Decls()
+					If Not decl.IsSemanted() Then
+						decl.Semant
+					End If
+					If decl.IdentLower() = func.IdentLower() Then
+						Local res:Int = decl.EqualsFunc(func)
+						If res Then
+							func.equalsBuiltIn = True
+						End If
+						Return res
+					End If
+				Next
+			End If
+			If classDecl.superClass Then
+				Return equalsBuiltInFunc(classDecl.superClass, func, True)
+			End If
+		End If
+		func.equalsBuiltIn = False
+		Return False
+	End Method
+
+	Method equalsIfcBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
+		If checked Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
+			If classDecl.munged = "bbObjectClass" Then
+				For Local decl:TFuncDecl = EachIn classDecl.Decls()
+					If Not decl.IsSemanted() Then
+						decl.Semant
+					End If
+					If decl.IdentLower() = func.IdentLower() Then
+						Return decl.EqualsFunc(func)
+					End If
+				Next
+			End If
+			If classDecl.superClass Then
+				Return equalsIfcBuiltInFunc(classDecl.superClass, func, True)
+			End If
+		End If
+		Return False
+	End Method
+
+	Method MungFuncDecl( fdecl:TFuncDecl )
+
+		If fdecl.munged Return
+		
+		Local funcs:TFuncDeclList=TFuncDeclList(funcMungs.ValueForKey( fdecl.ident ))
+		If funcs
+			For Local tdecl:TFuncDecl=EachIn funcs
+				If fdecl.EqualsArgs( tdecl ) And fdecl.scope = tdecl.scope
+					fdecl.munged=tdecl.munged
+					Return
+				EndIf
+			Next
+		Else
+			funcs=New TFuncDeclList
+			funcMungs.Insert fdecl.ident,funcs
+		EndIf
+
+		If fdecl.scope Then
+			Local id:String = fdecl.ident
+
+			If fdecl.attrs & FUNC_OPERATOR Then
+				id = MungSymbol(id)
+			End If
+			
+			fdecl.munged = fdecl.ParentScope().munged + "_" + id
+			
+			If Not equalsBuiltInFunc(fdecl.classScope(), fdecl) And Not fdecl.noMangle Then
+				fdecl.munged :+ MangleMethod(fdecl)
+			End If
+			
+			' fields are lowercase with underscore prefix.
+			' a function pointer with FUNC_METHOD is a field function pointer.
+			'If TFieldDecl(fdecl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
+			'	munged = "_" + munged.ToLower()
+			'End If
+		Else
+			fdecl.munged="bb_"+fdecl.ident
+		End If
+		
+		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
+			' ensure function args get into local scope correctly.
+			If addIfNotInScope Then
+				If Not mungScope.Contains( decl.munged ) Then
+					mungScope.Insert(decl.munged, decl)
+				End If
+			End If
+			Return
+		End If
+
+		Local fdecl:TFuncDecl=TFuncDecl( decl )
+		
+		' apply mangling to methods and New (ctors)
+		' but don't apply mangling to function pointers
+		If fdecl And fdecl.ClassScope() And Not (fdecl.attrs & FUNC_PTR)
+			MungFuncDecl( fdecl )
+			Return
+		End If
+		
+		Local id$=decl.ident,munged$
+		
+		'this lot just makes output a bit more readable...
+'		Select ENV_LANG
+'		Case "js"
+'			If TModuleDecl( decl.scope ) Or TGlobalDecl( decl ) Or (fdecl And Not fdecl.IsMethod())
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "as"
+'			If TModuleDecl( decl.scope )
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "cs"
+'			If TClassDecl( decl )
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "java"
+'			If TClassDecl( decl )
+'				munged=decl.ModuleScope().munged+"_"+id
+'			EndIf
+'		Case "cpp"
+			If TModuleDecl( decl.scope )
+				munged=decl.ModuleScope().munged+"_"+id
+				
+				If TClassDecl(decl) And TClassDecl(decl).instArgs Then
+					For Local ty:TType = EachIn TClassDecl(decl).instArgs
+						munged :+ TransMangleType(ty)
+					Next
+				End If
+			EndIf
+
+			If TModuleDecl( decl )
+				munged=decl.ModuleScope().munged+"_"+id
+			EndIf
+
+'		End Select
+'DebugStop
+
+		If Not munged
+			If TLocalDecl( decl )
+				munged="bbt_"+id
+			Else
+				If decl.scope Then
+					munged = decl.scope.munged + "_" + id
+					
+					If TClassDecl(decl) And TClassDecl(decl).instArgs Then
+						For Local ty:TType = EachIn TClassDecl(decl).instArgs
+							munged :+ TransMangleType(ty)
+						Next
+					End If
+					
+					' fields are lowercase with underscore prefix.
+					' a function pointer with FUNC_METHOD is a field function pointer.
+					If TFieldDecl(decl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
+						munged = "_" + munged.ToLower()
+					End If
+				Else
+					munged="bb_"+id
+				End If
+			EndIf
+		EndIf
+
+		'sanitize non-mung-able characters
+		munged = TStringHelper.Sanitize(munged)
+
+
+		'add an increasing number to identifier if already used  
+		If mungScope.Contains( munged )
+			Local i:Int=1
+			Repeat
+				i:+1
+			Until Not mungScope.Contains( munged + i )
+			munged :+ i
+		EndIf
+
+		mungScope.Insert(munged, decl)
+		decl.munged=munged
+		
+		' a function pointers' real function is stored in "func" - need to set its munged to match the parent.
+		If TValDecl(decl) Then
+			If TFunctionPtrType(TValDecl(decl).ty) Then
+				TFunctionPtrType(TValDecl(decl).ty).func.munged = munged
+			End If
+		End If
+		
+	End Method
+
+Rem
+	Method MungDecl( decl:TDecl )
+
+		If decl.munged Return
+
+		Local fdecl:TFuncDecl=TFuncDecl( decl )
+		If fdecl And fdecl.IsMethod() Then
+'			DebugStop
+			MungFuncDecl( fdecl )
+			Return
+		End If
+		
+		Local id:String=decl.ident,munged$,scope$
+		
+		If TLocalDecl( decl )
+			scope="$"
+			munged="t_"+id
+		Else If TClassDecl( decl )
+			scope=""
+			munged="c_"+id
+		Else If TModuleDecl( decl )
+			scope=""
+			munged="bb_"+id
+		Else If TClassDecl( decl.scope )
+			scope=decl.scope.munged
+			munged="m_"+id
+		Else If TModuleDecl( decl.scope )
+			'If ENV_LANG="cs" Or ENV_LANG="java"
+			'	scope=decl.scope.munged
+			'	munged="g_"+id
+			'Else
+				scope=""
+				munged=decl.scope.munged+"_"+id
+			'EndIf
+		Else
+			InternalErr
+		EndIf
+		
+		Local set:TMap=TMap(mungedScopes.ValueForKey( scope ))
+		If set
+			If set.Contains( munged.ToLower() )
+				Local id:Int=1
+				Repeat
+					id :+ 1
+					Local t$=munged+id
+					If set.Contains( t.ToLower() ) Continue
+					munged=t
+					Exit
+				Forever
+			End If
+		Else
+			If scope="$"
+				Print "OOPS2"
+				InternalErr
+			EndIf
+			set=New TMap
+			mungedScopes.Insert scope,set
+		End If
+		set.Insert munged.ToLower(), ""
+		decl.munged=munged
+	End Method
+End Rem
+
+
+
+	
+	Method Bra$( str$ )
+		If str.StartsWith( "(" ) And str.EndsWith( ")" )
+			Local n:Int=1
+			For Local i:Int=1 Until str.Length-1
+				Select str[i..i+1]
+				Case "("
+					n:+1
+				Case ")"
+					n:-1
+					If Not n Return "("+str+")"
+				End Select
+			Next
+			If n=1 Return str
+'			If str.FindLast("(")<str.Find(")") Return str
+		EndIf
+		Return "("+str+")"
+	End Method
+	
+	'Utility C/C++ style...
+	Method Enquote$( str$ )
+		Return LangEnquote( str )
+	End Method
+	
+	Method EscapeChars:String(str:String)
+		If str Then
+			Local found:Int = False
+			For Local i:Int = 0 Until str.length
+				If str[i] > 127 Then
+					found = True
+					Exit
+				End If
+			Next
+			
+			If Not found Then
+				Return str
+			End If
+		
+			Local s:String
+			
+			For Local i:Int = 0 Until str.length
+				Local char:Int = str[i]
+				
+				If char < 128 Then
+					s :+ Chr(char)
+				Else
+					s :+ "~~" + char + "~~"
+				End If
+			Next
+			
+			Return s
+		End If
+	End Method
+
+	Method TransUnaryOp$( op$ )
+		Select op
+		Case "+" Return "+"
+		Case "-" Return "-"
+		Case "~~" Return op
+		Case "not" Return "!"
+		End Select
+		InternalErr
+	End Method
+	
+	Method TransBinaryOp$( op$,rhs$ )
+'DebugLog "TransBinaryOp '" + op + "' : '" + rhs + "'"
+op = mapSymbol(op)
+		Select op
+		Case "+","-"
+			If rhs.StartsWith( op ) Return op+" "
+			Return op
+		Case "*","/" Return op
+		Case "shl" Return "<<"
+		Case "shr" Return ">>"
+		Case "sar" Return ">>"
+		Case "mod" Return " % "
+		Case "and" Return " && "
+		Case "or" Return " || "
+		Case "=" Return "=="
+		Case "<>" Return "!="
+		Case "<","<=",">",">=" Return op
+		Case "=<" Return "<="
+		Case "=>" Return ">="
+		Case "&","|" Return op
+		Case "~~" Return "^"
+		Case "<<", ">>" Return Op
+		Case "%" Return Op
+		End Select
+		InternalErr
+	End Method
+	
+	Method TransAssignOp$( op$ )
+op = mapSymbol(op)
+		Select op
+		Case ":mod" Return "%="
+		Case ":shl" Return "<<="
+		Case ":shr" Return ">>="
+		Case ":sar" Return ">>="
+		End Select
+		Return op
+	End Method
+	
+	Method ExprPri:Int( expr:TExpr )
+		'
+		'1=primary,
+		'2=postfix
+		'3=prefix
+		'
+		If TNewObjectExpr( expr )
+			Return 3
+		Else If TUnaryExpr( expr )
+			Select TUnaryExpr( expr ).op
+			Case "+","-","~~","not" Return 3
+			End Select
+			InternalErr
+		Else If TBinaryExpr( expr )
+			Select TBinaryExpr( expr ).op
+			Case "^" Return 4
+			Case "*","/","mod","%" Return 5
+			Case "+","-" Return 6
+			Case "shl","shr", "sar","<<", ">>" Return 7
+			Case "<","<=",">",">=", "=<", "=>" Return 8
+			Case "=","<>" Return 9
+			Case "&" Return 10
+			Case "~~" Return 11
+			Case "|" Return 12
+			Case "and" Return 13
+			Case "or" Return 14
+			End Select
+			InternalErr
+		EndIf
+		Return 2
+	End Method
+	
+	Method TransSubExpr$( expr:TExpr,pri:Int=2 )
+		Local t_expr$=expr.Trans()
+		'If expr.exprType._flags & TTYPE.T_VAR Then
+		'	t_expr = Bra("*" + t_expr)
+		'End If
+		If ExprPri( expr )>pri t_expr=Bra( t_expr )
+		Return t_expr
+	End Method
+	
+	Method TransExprNS$( expr:TExpr )
+		If TVarExpr( expr ) Return expr.Trans()
+		If TConstExpr( expr ) Return expr.Trans()
+		Return CreateLocal( expr )
+	End Method
+	
+	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, init )+";"
+
+		EmitGDBDebug(_errInfo)
+		
+		Return tmp.munged
+	End Method
+
+	'***** Utility *****
+
+	Method TransLocalDecl$( decl:TLocalDecl,init:TExpr, declare:Int = False, outputInit:Int = True ) Abstract
+
+	Method TransGlobalDecl$( gdecl:TGlobalDecl ) Abstract
+	
+	Method EmitPushErr()
+	End Method
+	
+	Method EmitSetErr( errInfo$ )
+	End Method
+	
+	Method EmitPopErr()
+	End Method
+	
+	'***** Declarations *****
+	
+	Method TransGlobal$( decl:TGlobalDecl ) Abstract
+	
+	Method TransField$( decl:TFieldDecl,lhs:TExpr ) Abstract
+	
+	Method TransFunc$( decl:TFuncDecl,args:TExpr[],lhs:TExpr, sup:Int = False, scope:TScopeDecl = Null ) Abstract
+	
+	Method TransSuperFunc$( decl:TFuncDecl,args:TExpr[], scope:TScopeDecl ) Abstract
+	
+	
+	'***** Expressions *****
+	
+	Method TransConstExpr$( expr:TConstExpr ) Abstract
+	
+	Method TransNewObjectExpr$( expr:TNewObjectExpr ) Abstract
+	
+	Method TransNewArrayExpr$( expr:TNewArrayExpr ) Abstract
+	
+	Method TransSelfExpr$( expr:TSelfExpr ) Abstract
+	
+	Method TransCastExpr$( expr:TCastExpr ) Abstract
+	
+	Method TransUnaryExpr$( expr:TUnaryExpr ) Abstract
+	
+	Method TransBinaryExpr$( expr:TBinaryExpr ) Abstract
+	
+	Method TransIndexExpr$( expr:TIndexExpr ) Abstract
+	
+	Method TransSliceExpr$( expr:TSliceExpr ) Abstract
+	
+	Method TransArrayExpr$( expr:TArrayExpr ) Abstract
+	
+	Method TransArraySizeExpr$ ( expr:TArraySizeExpr ) Abstract
+	
+	Method TransIntrinsicExpr$( decl:TDecl,expr:TExpr,args:TExpr[]=Null ) Abstract
+	
+	Method TransArgs$( args:TExpr[],decl:TFuncDecl, objParam:String = Null ) Abstract
+
+	Method EmitDebugEnterScope(block:TBlockDecl) Abstract
+	
+	Method EmitLocalDeclarations(decl:TScopeDecl, v:TValDecl = Null) Abstract
+	
+	Method TransType$( ty:TType, ident:String, fpReturnTypeFunctionArgs:String = Null, fpReturnTypeClassFunc:Int = False) Abstract
+
+	Method BeginLocalScope()
+		mungStack.Push mungScope
+		mungScope:TMap=New TMap'<TDecl>
+'		mungedScopes.Insert "$",New TMap
+		
+		If opt_debug Then
+			localScopeStack.Push localScope
+			localScope = New TStack
+		End If
+	End Method
+	
+	Method EndLocalScope()
+		mungScope=TMap(mungStack.Pop())
+'		mungedScopes.Insert "$",Null
+
+		If opt_debug Then
+			localScope = TStack(localScopeStack.Pop())
+		End If
+	End Method
+
+Rem	
+	Method MungMethodDecl( fdecl:TFuncDecl )
+
+		If fdecl.munged Return
+		
+		If fdecl.overrides
+			MungMethodDecl fdecl.overrides
+			fdecl.munged=fdecl.overrides.munged
+			Return
+		EndIf
+		
+		Local funcs:=funcMungs.Get( fdecl.ident )
+		If funcs
+			For Local tdecl:=EachIn funcs
+				If fdecl.EqualsArgs( tdecl )
+					fdecl.munged=tdecl.munged
+					Return
+				EndIf
+			Next
+		Else
+			funcs=New FuncDeclList
+			funcMungs.Set fdecl.ident,funcs
+		EndIf
+		
+		Local id:=fdecl.ident
+		If mungedFuncs.Contains( id )
+			Local n:=1
+			Repeat
+				n+=1
+				id=fdecl.ident+String(n)
+			Until Not mungedFuncs.Contains( id )
+		EndIf
+		
+		mungedFuncs.Set id,fdecl
+		fdecl.munged="p_"+id
+		funcs.AddLast fdecl
+	End
+End Rem	
+	'***** Simple statements *****
+	
+	'Expressions
+	Method TransStmtExpr$( expr:TStmtExpr )
+		Local t$=expr.stmt.Trans()
+		If t Emit t+";"
+		Return expr.expr.Trans()
+	End Method
+	
+	Method TransTemplateCast$( ty:TType,src:TType,expr$ )
+		Return expr
+	End Method
+	
+	Method TransVarExpr$( expr:TVarExpr )
+		Local decl:TVarDecl=TVarDecl( expr.decl.actual )
+
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null )
+		
+		If TLocalDecl( decl ) Then
+			If decl.ty._flags & TType.T_VAR Then
+				Return "*" + decl.munged
+			Else
+				Return decl.munged
+			End If
+		End If
+		
+		If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),Null )
+		
+		If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
+		
+		InternalErr
+	End Method
+	
+	Method TransMemberVarExpr$( expr:TMemberVarExpr )
+		Local decl:TVarDecl=TVarDecl( expr.decl.actual )
+		
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr )
+		
+		If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),expr.expr )
+
+		If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
+
+		InternalErr
+	End Method
+	
+	Method TransInvokeExpr$( expr:TInvokeExpr )
+		Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
+'If decl.ident = "OnDebugStop" DebugStop	
+		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 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 )
+		
+		If processingReturnStatement = 1 Then
+			If decl Then
+				processingReturnStatement :+ 1
+				Return CreateLocal(expr)
+			End If
+		Else
+			If decl Return TransFunc( TFuncDecl(decl),expr.args,Null )
+		End If
+		
+		InternalErr
+	End Method
+	
+	Method TransInvokeMemberExpr$( expr:TInvokeMemberExpr )
+		Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
+
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr,expr.args )
+		
+		If processingReturnStatement = 1 Then
+			If decl Then
+				processingReturnStatement :+ 1
+				Return CreateLocal(expr)
+			End If
+		Else
+			If decl Return TransFunc( TFuncDecl(decl),expr.args,expr.expr )	
+		End If
+		
+		InternalErr
+	End Method
+	
+	Method TransInvokeSuperExpr$( expr:TInvokeSuperExpr )
+		Local decl:TFuncDecl=TFuncDecl( expr.origFuncDecl.actual ),t$
+
+		If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr )
+		
+		If processingReturnStatement = 1 Then
+			If decl Then
+				processingReturnStatement :+ 1
+				Return CreateLocal(expr)
+			End If
+		Else
+			If decl Return TransSuperFunc( TFuncDecl( expr.funcDecl ),expr.args, expr.classScope )
+		End If
+		
+		InternalErr
+	End Method
+	
+	Method TransFuncCallExpr:String( expr:TFuncCallExpr )
+
+		If TIndexExpr(expr.expr) And TArrayType(TIndexExpr(expr.expr).expr.exprType) And TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType) Then
+			Local decl:TDecl = TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType).func.actual
+			decl.Semant()
+			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
+	
+	Method TransExprStmt$( stmt:TExprStmt )
+		Return stmt.expr.TransStmt()
+	End Method
+	
+	Method TransAssignStmt$( stmt:TAssignStmt )
+		If stmt.rhs Return stmt.lhs.TransVar()+TransAssignOp(stmt.op)+stmt.rhs.Trans()
+		Return stmt.lhs.Trans()
+	End Method
+	
+	Method TransReturnStmt$( stmt:TReturnStmt )
+
+		Local t$="return"
+		unreachable=True
+		If stmt.expr Then
+
+			If TObjectType(stmt.expr.exprType) And TNullDecl(TObjectType(stmt.expr.exprType).classDecl) Then
+				If IsPointerType(stmt.fRetType, 0, TType.T_POINTER) Or IsNumericType(stmt.fRetType) Then
+					t:+ " 0"
+				End If
+				If TStringType(stmt.fRetType) Then
+					t:+ " &bbEmptyString"
+				End If
+				If TArrayType(stmt.fRetType) Then
+					t:+ " &bbEmptyArray"
+				End If
+
+			Else
+				
+				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
+						t:+" " + s
+					End If
+				End If
+			End If
+			
+		End If
+
+		FreeVarsIfRequired()
+		
+		' if this is a Delete() method, we need to call the dtor first
+		Local funcScope:TFuncDecl = _env.FuncScope()
+		If funcScope And funcScope.IdentLower() = "delete" Then
+			Local classScope:TClassDecl = funcScope.ClassScope()
+			If classScope Then
+				EmitClassDeclDeleteDtor(classScope)
+			End If
+		End If
+		
+		Return t
+	End Method
+	
+	Method NextExitId:Int(bc:TTryBreakCheck)
+		If Not bc.exitId Then
+			exitLabelId :+ 1
+			bc.exitId = exitLabelId
+		End If
+		
+		Return bc.exitId
+	End Method
+
+	Method NextContId:Int(bc:TTryBreakCheck)
+		If Not bc.contId Then
+			contLabelId :+ 1
+			bc.contId = contLabelId
+		End If
+		
+		Return bc.contId
+	End Method
+
+	Method TransContinueStmt$( stmt:TContinueStmt )
+		unreachable=True
+
+		Local contLoop:TStmt
+		' if we are continuing with a loop label, we'll need to find it in the stack
+		If stmt.label And TLoopLabelExpr(stmt.label) Then
+			contLoop = TLoopLabelExpr(stmt.label).loop
+		End If
+		' get count of Try statements in the stack in this loop
+		Local count:Int = LoopTryDepth(contLoop)
+		If count > 0 Then
+			Local bc:TTryBreakCheck = GetTopLoop(contLoop)
+			If bc Then
+				NextContId(bc)
+				For Local i:Int = 0 Until count
+					Emit "bbExLeave();"
+					If opt_debug Then
+						Emit "bbOnDebugPopExState();"
+					End If
+				Next
+				Emit "goto " + TransLabelCont(bc, False)
+			Else
+				InternalErr
+			End If
+		Else
+		 	' For debug builds, we need to rollback the local scope stack correctly
+			count = 0
+			
+			If opt_debug And TLoopStmt(contLoop) And Not TLoopStmt(contLoop).block.IsNoDebug() Then
+				count = LoopLocalScopeDepth(contLoop)
+			End If
+			
+			If count > 0 Then
+				Local bc:TTryBreakCheck = GetTopLocalLoop(contLoop)
+				If bc Then
+					NextContId(bc)
+					For Local i:Int = 0 Until count
+						Emit "bbOnDebugLeaveScope();"
+					Next
+					Emit "goto " + TransLabelCont(bc, False)
+				Else
+					InternalErr
+				End If
+			Else
+
+				If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
+					count = LoopLocalScopeDepth(Null)
+				End If
+				For Local i:Int = 0 Until count
+					Emit "bbOnDebugLeaveScope();"
+				Next
+
+				' No Try statements in the stack here..
+				If stmt.label And TLoopLabelExpr(stmt.label) Then
+					Emit "goto " + TransLoopLabelCont(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
+				Else
+					Return "continue"
+				End If
+			End If
+		End If
+	End Method
+	
+	Method TransBreakStmt$( stmt:TBreakStmt )
+		unreachable=True
+		broken:+1
+
+		Local brkLoop:TStmt
+		' if we are exiting with a loop label, we'll need to find it in the stack
+		If stmt.label And TLoopLabelExpr(stmt.label) Then
+			brkLoop = TLoopLabelExpr(stmt.label).loop
+		End If
+		' get count of Try statements in the stack in this loop
+		Local count:Int = LoopTryDepth(brkLoop)
+		If count > 0 Then
+			Local bc:TTryBreakCheck = GetTopLoop(brkLoop)
+			If bc Then
+				NextExitId(bc)
+				For Local i:Int = 0 Until count
+					Emit "bbExLeave();"
+					If opt_debug Then
+						Emit "bbOnDebugPopExState();"
+					End If
+				Next
+				Emit "goto " + TransLabelExit(bc, False)
+			Else
+				InternalErr
+			End If
+		Else
+		 	' For debug builds, we need to rollback the local scope stack correctly
+			count = 0
+			
+			If opt_debug And TLoopStmt(brkLoop) And Not TLoopStmt(brkLoop).block.IsNoDebug() Then
+				count = LoopLocalScopeDepth(brkLoop)
+			End If
+			
+			If count > 0 Then
+				Local bc:TTryBreakCheck = GetTopLocalLoop(brkLoop)
+				If bc Then
+					NextExitId(bc)
+					For Local i:Int = 0 Until count
+						Emit "bbOnDebugLeaveScope();"
+					Next
+					Emit "goto " + TransLabelExit(bc, False)
+				Else
+					InternalErr
+				End If
+			Else
+
+				If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
+					count = LoopLocalScopeDepth(Null)
+				End If
+				For Local i:Int = 0 Until count
+					Emit "bbOnDebugLeaveScope();"
+				Next
+				
+				' No Try statements in the stack here..
+				If stmt.label And TLoopLabelExpr(stmt.label) Then
+					Emit "goto " + TransLoopLabelExit(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
+				Else
+					Return "break"
+				End If
+			End If
+		End If
+	End Method
+	
+	Method TransTryStmt$( stmt:TTryStmt )
+	End Method
+	
+	Method EmitTryStack() Abstract
+
+	Method TransThrowStmt$( stmt:TThrowStmt )
+	End Method
+	
+
+	Method TransBuiltinExpr$( expr:TBuiltinExpr )
+		If TMinExpr(expr) Return TransMinExpr(TMinExpr(expr))
+		If TMaxExpr(expr) Return TransMaxExpr(TMaxExpr(expr))
+		If TAbsExpr(expr) Return TransAbsExpr(TAbsExpr(expr))
+		If TAscExpr(expr) Return TransAscExpr(TAscExpr(expr))
+		If TChrExpr(expr) Return TransChrExpr(TChrExpr(expr))
+		If TSgnExpr(expr) Return TransSgnExpr(TSgnExpr(expr))
+		If TLenExpr(expr) Return TransLenExpr(TLenExpr(expr))
+		If TSizeOfExpr(expr) Return TransSizeOfExpr(TSizeOfExpr(expr))
+		Err "TODO : TransBuiltinExpr()"
+	End Method
+	
+	Method TransMinExpr:String(expr:TMinExpr)
+	End Method
+
+	Method TransMaxExpr:String(expr:TMaxExpr)
+	End Method
+
+	Method TransAbsExpr:String(expr:TAbsExpr)
+	End Method
+
+	Method TransAscExpr:String(expr:TAscExpr)
+	End Method
+
+	Method TransChrExpr:String(expr:TChrExpr)
+	End Method
+
+	Method TransSgnExpr:String(expr:TSgnExpr)
+	End Method
+
+	Method TransLenExpr:String(expr:TLenExpr)
+	End Method
+
+	Method TransSizeOfExpr:String(expr:TSizeOfExpr)
+	End Method
+	
+	Method TransIdentTypeExpr:String(expr:TIdentTypeExpr) Abstract
+	
+	Method TransLabelCont:String(bc:TTryBreakCheck, jmp:Int = True)
+		If jmp Then
+			Return "_contjmp" + bc.contId + ": ;"
+		Else
+			Return "_contjmp" + bc.contId + ";"
+		End If
+	End Method
+	
+	Method TransLabelExit:String(bc:TTryBreakCheck, jmp:Int = True)
+		If jmp Then
+			Return "_exitjmp" + bc.exitId + ": ;"
+		Else
+			Return "_exitjmp" + bc.exitId + ";"
+		End If
+	End Method
+
+	Method TransLoopLabelCont:String(id:String, jmp:Int = True)
+		If jmp Then
+			Return "_loopcont_" + id.ToLower() + ": ;"
+		Else
+			Return "_loopcont_" + id.ToLower() + ";"
+		End If
+	End Method
+
+	Method TransLoopLabelExit:String(id:String, jmp:Int = True)
+		If jmp Then
+			Return "_loopexit_" + id.ToLower() + ": ;"
+		Else
+			Return "_loopexit_" + id.ToLower() + ";"
+		End If
+	End Method
+
+	'***** Block statements - all very C like! *****
+	
+	Method Emit( t$, useIndent:Int = True )
+		If Not t Return
+		If useIndent
+			If t.StartsWith( "}" )
+				indent=indent[..indent.Length-1]
+			EndIf
+		End If
+		LINES.AddLast indent+t
+		'code+=indent+t+"~n"
+		If useIndent
+			If t.EndsWith( "{" )
+				indent:+"~t"
+			EndIf
+		End If
+	End Method
+	
+	Method JoinLines$( file:String )
+		Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
+		
+		Local code$=_lines.Join( "~n" )
+		_lines.Clear
+		Return code
+	End Method
+	
+	'returns unreachable status!
+	Method EmitBlock:Int( block:TBlockDecl )
+		Local stmtCount:Int
+'DebugStop
+		'If ENV_CONFIG="debug"
+		'	If TFuncDecl( block ) EmitPushErr
+		'EndIf
+
+
+		PushEnv block
+		
+		' enter scope
+		If opt_debug And Not block.IsNoDebug() And Not block.generated Then
+			PushLoopLocalStack(block)
+			EmitDebugEnterScope(block)
+		End If
+
+		For Local stmt:TStmt=EachIn block.stmts
+		
+			_errInfo=stmt.errInfo
+			
+			If unreachable
+				' Statements following cannot be reached - maybe we have Returned, etc
+				' So don't process any more for this block - they won't be generated now!
+				Exit
+			EndIf
+
+Rem
+			If ENV_CONFIG="debug"
+				Local rs:TReturnStmt=TReturnStmt( stmt )
+				If rs
+					If rs.expr
+						EmitSetErr stmt.errInfo
+						Local t_expr$=TransExprNS( rs.expr )
+						EmitPopErr
+						Emit "return "+t_expr+";"
+					Else
+						EmitPopErr
+						Emit "return;"
+					EndIf
+					unreachable=True
+					Continue
+				EndIf
+				EmitSetErr stmt.errInfo
+			EndIf
+End Rem
+			If opt_debug And Not block.IsNoDebug() Then
+				' only for user-made code
+				If Not stmt.generated Then
+					EmitDebugStmtErrInfo(stmt.errInfo, stmtCount)
+					stmtCount :+ 1
+				End If
+			
+			End If
+
+			EmitGDBDebug(stmt)
+			
+			If TReturnStmt(stmt) And Not tryStack.IsEmpty() Then
+				processingReturnStatement = True
+			End If
+			
+			Local t$=stmt.Trans()
+			
+			processingReturnStatement = False
+			
+			If opt_debug And Not block.IsNoDebug() Then
+				If TReturnStmt(stmt) Then
+					For Local b:TBlockDecl = EachIn localScope
+						Emit "bbOnDebugLeaveScope();"
+					Next
+				End If
+			End If
+
+			If TReturnStmt(stmt) Then
+				EmitTryStack()
+			End If
+			
+			If t Emit t+";"
+
+			If DEBUG And debugOut Then
+				Emit debugOut
+				debugOut = Null
+			End If
+			
+			Local v:String = String(customVarStack.Pop())
+			While v
+				Emit "bbMemFree" + Bra(v) + ";"
+				v = String(customVarStack.Pop())
+			Wend
+			
+		Next
+
+		If opt_debug And Not block.IsNoDebug() And Not block.generated Then
+			PopLoopLocalStack()
+			If Not unreachable Then
+				Emit "bbOnDebugLeaveScope();"
+			End If
+		End If
+
+		Local r:Int=unreachable
+		unreachable=False
+		PopEnv
+		Return r
+	End Method
+	
+	Method TransDeclStmt$( stmt:TDeclStmt, declare:Int = False )
+		Local decl:TLocalDecl=TLocalDecl( stmt.decl )
+		If decl
+			MungDecl decl
+			' only generate local declarations once.
+			If decl.generated Then
+				If Not decl.done Then
+					decl.done = True
+				Else
+					Return ""
+				End If
+			End If
+			Return TransLocalDecl( decl,decl.init, decl.generated Or declare )
+		EndIf
+		Local cdecl:TConstDecl=TConstDecl( stmt.decl )
+		If cdecl
+			Return Null
+		EndIf
+		Local gdecl:TGlobalDecl=TGlobalDecl( stmt.decl )
+		If gdecl Then
+			MungDecl gdecl
+			If gdecl.inited Return Null
+			Return TransGlobalDecl( gdecl )
+		End If
+		InternalErr
+	End Method
+	
+	Method TransIfStmt$( stmt:TIfStmt )
+		If TConstExpr( stmt.expr )
+			If TConstExpr( stmt.expr ).value
+				Emit "{"
+				EmitLocalDeclarations(stmt.thenBlock)
+				If EmitBlock( stmt.thenBlock ) unreachable=True
+				Emit "}"
+			Else If stmt.elseBlock.stmts.First()
+				Emit "{"
+				EmitLocalDeclarations(stmt.elseBlock)
+				If EmitBlock( stmt.elseBlock ) unreachable=True
+				Emit "}"
+			EndIf
+		Else If stmt.elseBlock.stmts.First()
+			Emit "if"+Bra( stmt.expr.Trans() )+"{"
+			EmitLocalDeclarations(stmt.thenBlock)
+			FreeVarsIfRequired(False)
+			PushVarScope
+			Local unr:Int=EmitBlock( stmt.thenBlock )
+			PopVarScope
+			Emit "}else{"
+			EmitLocalDeclarations(stmt.elseBlock)
+			FreeVarsIfRequired
+			Local unr2:Int=EmitBlock( stmt.elseBlock )
+			Emit "}"
+			If unr And unr2 unreachable=True
+		Else
+
+'			Emit "if"+ Bra(TransCondition(stmt.expr)) + "{"
+'			If TVarExpr(stmt.expr) Then
+'				If TObjectType(TVarExpr(stmt.expr).exprType) Then
+'					Emit "if"+Bra( stmt.expr.Trans() + "!= &bbNullObject") + "{"
+'				Else If TStringType(TVarExpr(stmt.expr).exprType)  Then
+'					Emit "if"+Bra( stmt.expr.Trans() + "!= &bbEmptyString") + "{"
+'				Else
+'					Emit "if"+Bra( stmt.expr.Trans() )+"{"
+'				End If
+'			Else
+				Emit "if"+Bra( stmt.expr.Trans() )+"{"
+				FreeVarsIfRequired(False)
+'			End If
+			EmitLocalDeclarations(stmt.thenBlock)
+			PushVarScope
+			Local unr:Int=EmitBlock( stmt.thenBlock )
+			PopVarScope
+			Emit "}"
+			FreeVarsIfRequired
+		EndIf
+	End Method
+	
+	Method FreeVarsIfRequired(removeFromStack:Int = True)
+		If removeFromStack
+			Local v:String = String(customVarStack.Pop())
+			While v
+				Emit "bbMemFree" + Bra(v) + ";"
+				v = String(customVarStack.Pop())
+			Wend
+		Else
+			For Local v:String = EachIn customVarStack
+				Emit "bbMemFree" + Bra(v) + ";"
+			Next
+		End If
+	End Method
+	
+'	Method TransCondition:String(expr:TExpr)
+'		If TVarExpr(expr) Then
+'			If TObjectType(TVarExpr(expr).exprType) Then
+'				Return Bra( expr.Trans() + "!= &bbNullObject")
+'			Else If TStringType(TVarExpr(expr).exprType)  Then
+'				Return Bra( expr.Trans() + "!= &bbEmptyString")
+'			Else
+'				Return Bra( expr.Trans() )
+'			End If
+'		Else
+'			Return Bra( expr.Trans() )
+'		End If
+'	End Method
+	
+	Method TransWhileStmt$( stmt:TWhileStmt )
+		Local nbroken:Int=broken
+
+		Emit "while"+Bra( stmt.expr.Trans() )+"{"
+		
+		Local check:TTryBreakCheck = New TTryBreakCheck
+		check.stmt = stmt
+		PushLoopTryStack(check)
+		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
+			PushLoopLocalStack(check)
+		End If
+		EmitLocalDeclarations(stmt.block)
+		Local unr:Int=EmitBlock( stmt.block )
+		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
+			PopLoopLocalStack
+		End If
+		PopLoopTryStack
+		
+		If check.contId Then
+			Emit TransLabelCont(check)
+		End If
+
+		If stmt.loopLabel Then
+			Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
+		End If
+		
+		Emit "}"
+
+		If check.exitId Then
+			Emit TransLabelExit(check)
+		End If
+
+		If stmt.loopLabel Then
+			Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
+		End If
+		
+		If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
+		broken=nbroken
+	End Method
+
+	Method TransRepeatStmt$( stmt:TRepeatStmt )
+		Local nbroken:Int=broken
+
+		SetOutputTemp()
+
+		Emit "do{"
+		
+		Local check:TTryBreakCheck = New TTryBreakCheck
+		check.stmt = stmt
+		PushLoopTryStack(check)
+		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
+			PushLoopLocalStack(check)
+		End If
+		EmitLocalDeclarations(stmt.block)
+		Local unr:Int=EmitBlock( stmt.block )
+		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
+			PopLoopLocalStack
+		End If
+		PopLoopTryStack
+
+		If check.contId Then
+			Emit TransLabelCont(check)
+		End If
+
+		If stmt.loopLabel Then
+			Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
+		End If
+		
+		SetOutput("source")
+
+		Local s:String = "}while(!"+Bra( stmt.expr.Trans() )+");"
+		
+		SetOutputTemp(True)
+		
+		Emit s
+
+		If check.exitId Then
+			Emit TransLabelExit(check)
+		End If
+
+		If stmt.loopLabel Then
+			Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
+		End If
+
+		If broken=nbroken And TConstExpr( stmt.expr ) And Not TConstExpr( stmt.expr ).value unreachable=True
+		broken=nbroken
+	End Method
+
+	Method TransForStmt$( stmt:TForStmt )
+		Local nbroken:Int=broken
+
+		Local init$
+
+		Local decl:Int
+		Local vdecl:TValDecl
+		If TDeclStmt(stmt.init) Then
+			decl = True
+			Emit "{"
+			Emit TransDeclStmt(TDeclStmt(stmt.init), True) + ";"
+			init = TDeclStmt(stmt.init).decl.munged
+			vdecl = TValDecl(TDeclStmt(stmt.init).decl)
+		Else
+			init=stmt.init.Trans()
+		End If
+		Local expr$=stmt.expr.Trans()
+		Local incr$=stmt.incr.Trans()
+
+		Emit "for("+init+";"+expr+";"+incr+"){"
+
+		Local check:TTryBreakCheck = New TTryBreakCheck
+		check.stmt = stmt
+		PushLoopTryStack(check)
+		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
+			PushLoopLocalStack(check)
+		End If
+		EmitLocalDeclarations(stmt.block, vdecl)
+		Local unr:Int=EmitBlock( stmt.block )
+		If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
+			PopLoopLocalStack
+		End If
+		PopLoopTryStack
+		
+		If check.contId Then
+			Emit TransLabelCont(check)
+		End If
+
+		If stmt.loopLabel Then
+			Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
+		End If
+		
+		Emit "}"
+		
+		If decl Then
+			Emit "}"
+		End If
+
+		If check.exitId Then
+			Emit TransLabelExit(check)
+		End If
+
+		If stmt.loopLabel Then
+			Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
+		End If
+		
+		If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
+		broken=nbroken
+	End Method
+
+	Method TransAssertStmt$( stmt:TAssertStmt ) Abstract
+
+	Method TransEndStmt$( stmt:TEndStmt ) Abstract
+
+	Method TransReleaseStmt$( stmt:TReleaseStmt ) Abstract
+
+	Method TransRestoreDataStmt$( stmt:TRestoreDataStmt ) Abstract
+
+	Method TransReadDataStmt$( stmt:TReadDataStmt ) Abstract
+	
+	Method TransNativeStmt$( stmt:TNativeStmt) Abstract
+
+	'module
+	Method TransApp( app:TAppDecl ) Abstract
+
+Rem	
+	Method MungOverrides( cdecl:TClassDecl )
+		For Local decl:=Eachin cdecl.Semanted
+			Local fdecl:=TFuncDecl( decl )
+			If fdecl And fdecl.overrides
+				If Not fdecl.overrides.munged InternalErr
+				fdecl.munged=fdecl.overrides.munged
+				mungScope.Insert fdecl.munged,fdecl
+			Endif
+		Next
+	End
+End Rem
+	
+	Method PostProcess$( source$ ) 
+		Return source
+	End Method
+	
+	Method SetOutput( file:String )
+		Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
+		
+		If Not _lines Then
+			_lines = New TStringList
+			outputFiles.Insert(file, _lines)
+		End If
+		
+		LINES = _lines
+		
+	End Method
+
+	Method SetOutputTemp( fin:Int = False )
+		Global tmpLevel:Int = 0
+	
+		If Not fin Then
+			tmpLevel :+ 1
+
+			Local _lines:TStringList = New TStringList
+			outputFiles.Insert("tmp" + tmpLevel, _lines)
+	
+			LINES = _lines
+		Else
+			Local _lines:TStringList = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
+			
+			tmpLevel :- 1
+		
+			If Not tmpLevel Then
+				SetOutput("source")
+			Else
+				LINES = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
+			End If
+			
+			If _lines Then
+				For Local line:String = EachIn _lines
+					LINES.AddLast(line)
+				Next
+			End If
+			
+		End If
+	End Method
+
+	Method DebugPrint(text:String, func:String = Null, trans:Int = False)
+		Global count:Int
+		Global lastFunc:String
+		
+		If func Then
+			lastFunc = func
+		End If
+		
+		Local s:String = "fprintf(stderr," + "~q" + lastFunc + " : " + count + " :: " + text + "\n~q)" + ";fflush(stderr);"
+		
+		If trans Then
+			debugOut :+ indent + s + "~n"
+		Else
+			Emit s
+		End If
+		count :+ 1
+	End Method
+	
+	Method DebugString(s:String, func:String = Null, trans:Int = False)
+		' bbNullObject test
+		If trans Then
+			debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
+		Else
+			Emit "if (" + s + "==&bbNullObject) {"
+		End If
+		DebugPrint("Invalid Null String : " + s, func, trans)
+		If trans Then
+			debugOut :+ indent + "}~n"
+		Else
+			Emit "}"
+		End If
+	End Method
+
+	Method DebugArray(s:String, func:String = Null, trans:Int = False)
+		' bbNullObject test
+		If trans Then
+			debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
+		Else
+			Emit "if (" + s + "==&bbNullObject) {"
+		End If
+		DebugPrint("Invalid Null Array : " + s, func, trans)
+		If trans Then
+			debugOut :+ indent + "}~n"
+		Else
+			Emit "}"
+		End If
+	End Method
+
+	Method DebugObject(ty:TType, id:String, func:String = Null, trans:Int = False)
+		If TObjectType(ty) Or TStringType(ty) Or TArrayType(ty) Then
+			' null test
+			If trans Then
+				debugOut :+ indent + "if (" + id + "==NULL) {~n"
+			Else
+				Emit "if (" + id + "==NULL) {"
+			End If
+			DebugPrint("Null Pointer : " + id, func, trans)
+			If trans Then
+				If ABORT_ON_NULL Then
+					debugOut :+ indent + "abort();~n"
+				End If
+				debugOut :+ indent + "}~n"
+			Else
+				If ABORT_ON_NULL Then
+					Emit "abort();~n"
+				End If
+				Emit "}"
+			End If
+		End If
+		
+		If TStringType(ty) Then
+			DebugString(id, func, trans)
+		Else If TArrayType(ty) Then
+			DebugArray(id, func, trans)
+		End If
+	End Method
+	
+	Method EmitDebugStmtErrInfo(info:String, count:Int)
+		' extract from info
+		info = info[1..info.length-1]
+		Local infoArray:String[] = info.Split(";")
+
+		Local dbg:String = "struct BBDebugStm __stmt_" + count + " = {"
+		dbg :+ Enquote(infoArray[0]) + ", "
+		dbg :+ infoArray[1] + ", "
+		dbg :+ infoArray[2] + "};"
+		Emit dbg
+		Emit "bbOnDebugEnterStm(&__stmt_" + count + ");" 
+	End Method
+	
+	Method EmitGDBDebug(obj:Object)
+		If opt_gdbdebug Then
+			If TStmt(obj) Then
+				Local stmt:TStmt = TStmt(obj)
+				Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
+				If Not stmt.generated Then
+					Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
+				End If
+			Else If TDecl(obj) Then
+				Local decl:TDecl = TDecl(obj)
+				Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
+				Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
+			Else If String(obj) Then
+				Local errInfo:String = String(obj)
+				Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
+				Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
+			End If
+		End If
+	End Method
+	
+	Method EmitClassDeclDeleteDtor( classDecl:TClassDecl )
+	End Method
+	
+End Type
+
+Type TTryBreakCheck
+
+	Field contId:Int
+	Field exitId:Int
+
+	Field stmt:TStmt
+	
+End Type