Browse Source

Added simple finalizers to mx2cc.

Mark Sibly 8 years ago
parent
commit
50e986405c

+ 21 - 15
src/mx2cc/decl.monkey2

@@ -1,23 +1,25 @@
 
 
 Namespace mx2
 Namespace mx2
 
 
-Const DECL_PUBLIC:=		$000001
-Const DECL_PRIVATE:=	$000002
-Const DECL_PROTECTED:=	$000004
-Const DECL_INTERNAL:=	$000008
+Const DECL_PUBLIC:=			$000001
+Const DECL_PRIVATE:=		$000002
+Const DECL_PROTECTED:=		$000004
+Const DECL_INTERNAL:=		$000008
 
 
-Const DECL_VIRTUAL:=	$000100
-Const DECL_OVERRIDE:=	$000200
-Const DECL_ABSTRACT:=	$000400
-Const DECL_FINAL:=		$000800
-Const DECL_EXTERN:=		$001000
-Const DECL_EXTENSION:=	$002000
-Const DECL_DEFAULT:=	$004000
+Const DECL_VIRTUAL:=		$000100
+Const DECL_OVERRIDE:=		$000200
+Const DECL_ABSTRACT:=		$000400
+Const DECL_FINAL:=			$000800
+Const DECL_EXTERN:=			$001000
+Const DECL_EXTENSION:=		$002000
+Const DECL_DEFAULT:=		$004000
 
 
-Const DECL_GETTER:=		$010000
-Const DECL_SETTER:=		$020000
-Const DECL_OPERATOR:=	$040000
-Const DECL_IFACEMEMBER:=$080000
+Const DECL_GETTER:=			$010000
+Const DECL_SETTER:=			$020000
+Const DECL_OPERATOR:=		$040000
+Const DECL_IFACEMEMBER:=	$080000
+
+Const DECL_HASFINALIZER:=	$100000
 
 
 Const DECL_ACCESSMASK:=DECL_PUBLIC|DECL_PRIVATE|DECL_PROTECTED|DECL_INTERNAL
 Const DECL_ACCESSMASK:=DECL_PUBLIC|DECL_PRIVATE|DECL_PROTECTED|DECL_INTERNAL
 
 
@@ -92,6 +94,10 @@ Class Decl Extends PNode
 		Return (flags & DECL_DEFAULT)<>0
 		Return (flags & DECL_DEFAULT)<>0
 	End
 	End
 	
 	
+	Property HasFinalizer:Bool()
+		Return (flags & DECL_HASFINALIZER)<>0
+	End
+	
 	Method ToNode:SNode( scope:Scope ) Virtual
 	Method ToNode:SNode( scope:Scope ) Virtual
 		Return Null
 		Return Null
 	End
 	End

+ 1 - 1
src/mx2cc/mx2cc.monkey2

@@ -21,7 +21,7 @@ Using mx2..
 
 
 Global StartDir:String
 Global StartDir:String
 
 
-'Const TestArgs:="mx2cc makemods sdl2"
+'Const TestArgs:="mx2cc makemods -clean monkey"
 
 
 Const TestArgs:="mx2cc makeapp -target=desktop -apptype=console -run src/mx2cc/test.monkey2"
 Const TestArgs:="mx2cc makeapp -target=desktop -apptype=console -run src/mx2cc/test.monkey2"
 
 

+ 25 - 4
src/mx2cc/parser.monkey2

@@ -404,6 +404,10 @@ Class Parser
 		
 		
 		decl.members=ParseDecls( mflags,False )
 		decl.members=ParseDecls( mflags,False )
 		
 		
+		For Local mdecl:=Eachin decl.members
+			If mdecl.ident="finalize" decl.flags|=DECL_HASFINALIZER
+		Next
+		
 		Try
 		Try
 			Parse( "end" )
 			Parse( "end" )
 			CParse( decl.kind )
 			CParse( decl.kind )
@@ -472,6 +476,8 @@ Class Parser
 			
 			
 				If CParse( "new" )
 				If CParse( "new" )
 					ident="new"
 					ident="new"
+				Else If CParse( "finalize" )
+					ident="finalize"
 				Else If CParse( "to" )
 				Else If CParse( "to" )
 					ident="to"
 					ident="to"
 				Else
 				Else
@@ -487,20 +493,23 @@ Class Parser
 			Default
 			Default
 			
 			
 				ident=ParseIdent()
 				ident=ParseIdent()
+				
 				If ident="@typeof" ident="Typeof"
 				If ident="@typeof" ident="Typeof"
 			End
 			End
-	
-			genArgs=ParseGenArgs()
 			
 			
-'			If genArgs And (flags & DECL_EXTENSION) Error( "Extension methods cannot be generic" )
+			genArgs=ParseGenArgs()
 			
 			
+'			If genArgs And ident="finalize" Error( "Finalizers cannot be generic" )
+
 			If CParse( ":" )
 			If CParse( ":" )
 				type=Cast<FuncTypeExpr>( ParseType() )
 				type=Cast<FuncTypeExpr>( ParseType() )
 				If Not type Error( "Expecting function type" )
 				If Not type Error( "Expecting function type" )
 			Else
 			Else
 				type=ParseFuncType( New IdentExpr( "void",SrcPos,SrcPos ) )
 				type=ParseFuncType( New IdentExpr( "void",SrcPos,SrcPos ) )
 			Endif
 			Endif
-
+			
+'			If type.argTypes And ident="finalize" Error( "Finalizers cannot have any parameters" )
+			
 			If kind="lambda"
 			If kind="lambda"
 				For Local p:=Eachin type.params
 				For Local p:=Eachin type.params
 					If p.init Error( "Lambda function parameters cannot have default values" )
 					If p.init Error( "Lambda function parameters cannot have default values" )
@@ -555,19 +564,31 @@ Class Parser
 				
 				
 			End
 			End
 			
 			
+'			If Not (flags & DECL_OVERRIDE) And ident="finalize" Error( "Finalizers must be declared 'Override'" )
+			
 			If CParse( "=" )
 			If CParse( "=" )
+				
 				If Not (flags & DECL_EXTERN) Error( "Non-extern declarations cannot be assigned an extern symbol" )
 				If Not (flags & DECL_EXTERN) Error( "Non-extern declarations cannot be assigned an extern symbol" )
+					
 				symbol=ParseString()
 				symbol=ParseString()
+			
+'			Else If ident="finalize"
+				
+'				symbol="gcFinalize"
 			Endif
 			Endif
 
 
 			If CParse( "where" )
 			If CParse( "where" )
+				
 				whereExpr=ParseExpr()
 				whereExpr=ParseExpr()
 			Endif
 			Endif
 			
 			
 			If CParse( "default" )
 			If CParse( "default" )
+				
 				If Not (flags & DECL_IFACEMEMBER) Error( "Only interface methods can be declared 'Default'" )
 				If Not (flags & DECL_IFACEMEMBER) Error( "Only interface methods can be declared 'Default'" )
+					
 				flags&=~DECL_ABSTRACT
 				flags&=~DECL_ABSTRACT
 				flags|=DECL_DEFAULT
 				flags|=DECL_DEFAULT
+				
 				If CParse( "virtual" ) flags|=DECL_VIRTUAL
 				If CParse( "virtual" ) flags|=DECL_VIRTUAL
 			Endif
 			Endif
 			
 			

+ 15 - 8
src/mx2cc/test.monkey2

@@ -1,16 +1,23 @@
 
 
-#Import "<mojo>"
+Global g:C
 
 
-Using std..
-Using mojo..
+Class C
+	
+	Field c:C
+	
+	Method Finalize() Override
+		Print "Finalizing 'C'!"
+		g=Self
+	End
+
+End
 
 
 Function Main()
 Function Main()
 	
 	
-	Print "Wotzup?"
-	Print "Hello World!!!!"
+	Print "Hello World!"
 	
 	
-	Print "CurrentDir="+CurrentDir()
-	ChangeDir( "../.." )
-	Print "CurrentDir="+CurrentDir()
+	For Local i:=0 Until 1000000
+		Local c:=New C
+	Next
 
 
 End
 End

+ 1 - 1
src/mx2cc/toker.monkey2

@@ -38,7 +38,7 @@ Function InitToker:Void()
 	keyWords+="Select;Case;Default;"
 	keyWords+="Select;Case;Default;"
 	keyWords+="Try;Catch;Throw;Throwable;Variant;CString;TypeInfo;Typeof;"
 	keyWords+="Try;Catch;Throw;Throwable;Variant;CString;TypeInfo;Typeof;"
 	keyWords+="Return;Print;Static;Cast;"
 	keyWords+="Return;Print;Static;Cast;"
-	keyWords+="Extension;Protocol;Delete"
+	keyWords+="Extension;Protocol;Finalize;Delete"
 
 
 	KeyWords=New StringMap<String>
 	KeyWords=New StringMap<String>
 	
 	

+ 39 - 4
src/mx2cc/translator_cpp.monkey2

@@ -465,7 +465,7 @@ Class Translator_CPP Extends Translator
 		
 		
 		'Emit fields...
 		'Emit fields...
 		'
 		'
-		Local needsInit:=False
+		Local needsInit:=NeedsFinalize( ctype )
 		Local needsMark:=False
 		Local needsMark:=False
 
 
 		EmitBr()		
 		EmitBr()		
@@ -604,6 +604,16 @@ Class Translator_CPP Extends Translator
 		
 		
 	End
 	End
 	
 	
+	Method NeedsFinalize:Bool( ctype:ClassType )
+		If Not ctype Or Not ctype.cdecl.HasFinalizer Return false
+		ctype=ctype.superType
+		While ctype
+			If ctype.cdecl.HasFinalizer Return False
+			ctype=ctype.superType
+		Wend
+		Return True
+	End
+	
 	Method EmitClassMembers( ctype:ClassType )
 	Method EmitClassMembers( ctype:ClassType )
 	
 	
 		Local cdecl:=ctype.cdecl
 		Local cdecl:=ctype.cdecl
@@ -613,10 +623,10 @@ Class Translator_CPP Extends Translator
 		
 		
 		'Emit fields...
 		'Emit fields...
 		'
 		'
-		Local needsInit:=False
+		Local needsInit:=NeedsFinalize( ctype )
 		Local needsMark:=False
 		Local needsMark:=False
 
 
-		EmitBr()		
+		EmitBr()
 		For Local vvar:=Eachin ctype.fields
 		For Local vvar:=Eachin ctype.fields
 		
 		
 			If IsGCType( vvar.type ) needsMark=True
 			If IsGCType( vvar.type ) needsMark=True
@@ -624,7 +634,6 @@ Class Translator_CPP Extends Translator
 			If vvar.init And vvar.init.HasSideEffects needsInit=True
 			If vvar.init And vvar.init.HasSideEffects needsInit=True
 		Next
 		Next
 		
 		
-		
 		'Emit init() method
 		'Emit init() method
 		'
 		'
 		If needsInit
 		If needsInit
@@ -632,6 +641,8 @@ Class Translator_CPP Extends Translator
 			EmitBr()
 			EmitBr()
 			Emit( "void "+cname+"::init(){" )
 			Emit( "void "+cname+"::init(){" )
 			
 			
+			If NeedsFinalize( ctype ) Emit( "gcNeedsFinalize();" )
+			
 			BeginGCFrame()
 			BeginGCFrame()
 			
 			
 			For Local vvar:=Eachin ctype.fields
 			For Local vvar:=Eachin ctype.fields
@@ -1018,6 +1029,22 @@ Class Translator_CPP Extends Translator
 		Emit( "return &"+rcname+"::instance;" )
 		Emit( "return &"+rcname+"::instance;" )
 		Emit( "}" )
 		Emit( "}" )
 	End
 	End
+	
+	Method DiscardGCFields( ctype:ClassType,prefix:String )
+		
+		For Local vvar:=Eachin ctype.fields
+			
+			If Not IsGCType( vvar.type ) Continue
+			
+			Local ctype:=TCast<ClassType>( vvar.type )
+			If ctype And ctype.cdecl.kind="struct"
+				DiscardGCFields( ctype,prefix+VarName( vvar )+"." )
+			Else
+				Emit( prefix+VarName( vvar )+".discard();" )
+			Endif
+			
+		Next		
+	End
 
 
 	Method EmitFunc( func:FuncValue,init:Bool=False )
 	Method EmitFunc( func:FuncValue,init:Bool=False )
 	
 	
@@ -1045,6 +1072,14 @@ Class Translator_CPP Extends Translator
 			_gctmps=0
 			_gctmps=0
 		Endif
 		Endif
 		
 		
+		If func.fdecl.ident="finalize"
+			
+			Local ctype:=func.cscope.ctype
+			
+			DiscardGCFields( ctype,"" )
+			
+		Endif
+		
 		If init Emit( "init();" )
 		If init Emit( "init();" )
 			
 			
 		'is it 'main'?
 		'is it 'main'?

+ 1 - 1
src/ted2/monkey2document.monkey2

@@ -32,7 +32,7 @@ Function InitKeywords()
 	kws+="Select;Case;Default;"
 	kws+="Select;Case;Default;"
 	kws+="Try;Catch;Throw;Throwable;"
 	kws+="Try;Catch;Throw;Throwable;"
 	kws+="Return;Print;Static;Cast;Extension;"
 	kws+="Return;Print;Static;Cast;Extension;"
-	kws+="Typeof"
+	kws+="Typeof;Finalize"
 	
 	
 	For Local kw:=Eachin kws.Split( ";" )
 	For Local kw:=Eachin kws.Split( ";" )
 		Keywords[kw.ToLower()]=kw
 		Keywords[kw.ToLower()]=kw