2
0
Mark Sibly 9 жил өмнө
parent
commit
9421ee5371

+ 23 - 8
src/mx2new/translator.monkey2

@@ -3,6 +3,9 @@ Namespace mx2
 
 'Really only for c++ translator right now, but splits out some grunt work from main translator!
 
+
+'Does type need bbGCMark()ing?
+'
 Function IsGCType:Bool( type:Type )
 
 	If TCast<FuncType>( type ) Return True
@@ -16,11 +19,19 @@ Function IsGCType:Bool( type:Type )
 	
 	If ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface" Return True
 	
-	If ctype.cdecl.kind="struct" Return HasGCMembers( ctype.scope )
+	If ctype.cdecl.kind="struct"
+		For Local vvar:=Eachin ctype.fields
+			If IsGCType( vvar.type ) Return True
+		Next
+		Return False
+	Endif
+	
+'	 Return HasGCMembers( ctype.scope )
 	
 	Return False
 End
 
+#rem
 Function IsGCVarType:Bool( type:Type )
 
 	Local ctype:=TCast<ClassType>( type )
@@ -29,7 +40,9 @@ Function IsGCVarType:Bool( type:Type )
 	Local atype:=TCast<ArrayType>( type )
 	Return atype<>Null
 End
+#end
 
+#rem
 Function HasGCMembers:Bool( scope:Scope )
 
 	For Local node:=Eachin scope.transMembers
@@ -41,7 +54,8 @@ Function HasGCMembers:Bool( scope:Scope )
 	
 	Return False
 End
-	
+#end
+
 'Visitor that looks for gc params on LHS of an assignment.
 '
 Class AssignedGCParamsVisitor Extends StmtVisitor
@@ -292,7 +306,7 @@ Class Translator
 		_depsPos=InsertPos
 	End
 	
-	Method EndDeps()
+	Method EndDeps( baseDir:String )
 	
 		BeginInsert( _depsPos )
 	
@@ -302,7 +316,7 @@ Class Translator
 		EmitBr()
 		For Local fdecl:=Eachin _usesFiles.Values
 
-			EmitInclude( fdecl )
+			EmitInclude( fdecl,baseDir )
 		Next
 		
 		EmitBr()
@@ -313,10 +327,11 @@ Class Translator
 				Local cname:=ClassName( ctype )
 				Emit( "struct "+ClassName( ctype )+";" )
 				
-				If debug
+				If debug And Not ctype.cdecl.IsExtern
 					Local tname:=cname
 					If Not IsStruct( ctype ) tname+="*"
-					Emit( "template<> bbDBType *bbDBTypeOf("+tname+"*);" )
+					Emit( "bbString bbDBType("+tname+"*);" )
+					Emit( "bbString bbDBValue("+tname+"*);" )
 				Endif
 				
 			Endif
@@ -347,11 +362,11 @@ Class Translator
 		Return _incs.Contains( fdecl.ident )
 	End
 	
-	Method EmitInclude( fdecl:FileDecl )
+	Method EmitInclude( fdecl:FileDecl,baseDir:String )
 	
 		If _incs.Contains( fdecl.ident ) Return
 		
-		Emit( "#include ~q"+fdecl.hfile+"~q" )
+		Emit( "#include ~q"+MakeRelativePath( fdecl.hfile,baseDir )+"~q" )
 		
 		_incs[fdecl.ident]=fdecl
 	End

+ 175 - 91
src/mx2new/translator_cpp.monkey2

@@ -73,7 +73,7 @@ Class Translator_CPP Extends Translator
 			EmitClassProto( ctype,fdecl,emitted )
 		Next
 		
-		EndDeps()
+		EndDeps( ExtractDir( fdecl.hfile ) )
 		
 		EmitBr()		
 		Emit( "#endif" )
@@ -97,7 +97,7 @@ Class Translator_CPP Extends Translator
 		For Local vvar:=Eachin fdecl.globals
 			Uses( vvar.type )
 			Local proto:=VarProto( vvar )
-			If IsStruct( vvar.type ) proto+="( bbNullCtor )"
+'			If IsStruct( vvar.type ) proto+="( bbNullCtor )"
 			Emit( proto+";" )
 		Next
 		
@@ -111,7 +111,7 @@ Class Translator_CPP Extends Translator
 		
 		EmitGlobalInits( fdecl )
 
-		EndDeps()
+		EndDeps( ExtractDir( fdecl.cfile ) )
 		
 		EmitBr()
 		
@@ -120,35 +120,51 @@ Class Translator_CPP Extends Translator
 	
 	'***** Decls *****
 	
-	Method IsGCVarType:Bool( type:Type )
-	
-		Local ctype:=TCast<ClassType>( type )
-		If ctype Return (ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface") 
+	Method ElementType:String( type:Type )
 
+		Local ctype:=TCast<ClassType>( type )
+		If ctype And (ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface")
+			Return "bbGCVar<"+ClassName( ctype )+">"
+		Endif
+		
 		Local atype:=TCast<ArrayType>( type )
-		If atype Return True
+		If atype
+			Return "bbGCVar<"+ArrayName( atype )+">"
+		Endif
 		
-		Return False
+		Return TransType( type )
 	End
 	
-	Method VarType:String( type:Type )
+	Method VarType:String( vvar:VarValue )
 	
+		Local type:=vvar.type
+	
+		Local gc:=""
+		Select vvar.vdecl.kind
+		Case "field"
+			gc="bbGCVar<"
+		Case "global","const"
+			gc="bbGCRootVar<"
+		Default
+			Return TransType( type )
+		End
+
 		Local ctype:=TCast<ClassType>( type )
 		If ctype And (ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface")
-			Return "bbGCVar<"+ClassName( ctype )+">"
+			Return gc+ClassName( ctype )+">"
 		Endif
 		
 		Local atype:=TCast<ArrayType>( type )
 		If atype
-			Return "bbGCVar<"+ArrayName( atype )+">"
+			Return gc+ArrayName( atype )+">"
 		Endif
 		
 		Return TransType( type )
 	End
-	
+
 	Method VarProto:String( vvar:VarValue ) Override
 	
-		Return VarType( vvar.type )+" "+VarName( vvar )
+		Return VarType( vvar )+" "+VarName( vvar )
 	End
 	
 	Method FuncProto:String( func:FuncValue ) Override
@@ -172,6 +188,12 @@ Class Translator_CPP Extends Translator
 			If params params+=","
 			params+=TransType( p.type )+" "+VarName( p )
 		Next
+
+		'default struct ctor?		
+		If func.IsCtor And ctype.cdecl.kind="struct" And Not ftype.argTypes.Length
+			Assert( Not params )
+			params="bbNullCtor_t"
+		Endif
 		
 		Local ident:=FuncName( func )
 		If Not header And fdecl.kind="method" And Not func.IsExtension ident=ClassName( ctype )+"::"+ident
@@ -190,41 +212,17 @@ Class Translator_CPP Extends Translator
 	
 	Method EmitGlobalInits( fdecl:FileDecl )
 	
-		Local gcFrame:=""		
-		For Local vvar:=Eachin fdecl.globals
-			If Not IsGCType( vvar.type ) Continue
-			gcFrame="mx2_"+fdecl.ident+"_root"
-			Exit
-		Next
-		
-		If gcFrame
-			EmitBr()
-			Emit( "struct "+gcFrame+" : public bbGCRoot{" )
-			Emit( "void gcMark(){" )
-			For Local vvar:=Eachin fdecl.globals
-				If Not IsGCType( vvar.type ) Continue
-				Emit( "bbGCMark("+Trans( vvar )+");" )
-			Next
-			Emit( "}" )
-			Emit( "};" )
-		Endif
-		
-'		In case something get stripped...
-'		Emit( "extern bbInit mx2_"+fdecl.ident+"_init;" )
-
 		EmitBr()
 		Emit( "void mx2_"+fdecl.ident+"_init(){" )
 		BeginGCFrame()
 		Emit( "static bool done;" )
 		Emit( "if(done) return;" )
 		Emit( "done=true;")
-		If gcFrame Emit( "new "+gcFrame+";" )
 		
-'		Emit( "(void)mx2_"+fdecl.ident+"_init;" )
-
 		For Local vvar:=Eachin fdecl.globals
 			If vvar.init Emit( Trans( vvar )+"="+Trans( vvar.init )+";" )
 		Next
+		
 		EndGCFrame()
 		Emit( "}" )
 		
@@ -331,7 +329,7 @@ Class Translator_CPP Extends Translator
 		Local needsMark:=False
 
 		EmitBr()		
-		For Local node:=Eachin ctype.fields	'scope.transMembers
+		For Local node:=Eachin ctype.fields
 			Local vvar:=Cast<VarValue>( node )
 			If Not vvar Continue
 
@@ -347,27 +345,45 @@ Class Translator_CPP Extends Translator
 
 			If IsGCType( vvar.type ) needsMark=True
 			
-			If Cast<LiteralValue>( vvar.init )
+			Local proto:=VarProto( vvar )
+			
+			If vvar.init
+				If vvar.init.HasSideEffects
+					Emit( proto+"{};" )
+					needsInit=True
+				Else
+					Emit( proto+"="+Trans( vvar.init )+";" )
+				Endif
+			Else
+				Emit( proto+"{};" )
+			Endif
+			
+			#rem
+			If Cast<LiteralValue>( vvar.init ) And cdecl.kind="class"
 				Emit( VarProto( vvar )+"="+Trans( vvar.init )+";" )
 			Else
 				Emit( VarProto( vvar )+"{};" )
 				If vvar.init needsInit=True
 			Endif
+			#end
 
 		Next
 
 		If needsInit
-		
 			EmitBr()
 			Emit( "void init();" )
-			
 		Endif
 		
-		If needsMark And cdecl.kind="class"
+		If cdecl.kind="class"
 		
-			EmitBr()
-			Emit( "void gcMark();" )
+			If needsMark
+				EmitBr()
+				Emit( "void gcMark();" )
+			Endif
 			
+			If debug
+				Emit( "void dbEmit();" )
+			Endif
 		Endif
 
 		'Emit ctor methods
@@ -376,7 +392,7 @@ Class Translator_CPP Extends Translator
 		Local hasDefaultCtor:=False
 		
 		EmitBr()
-		For Local node:=Eachin ctype.methods	'scope.transMembers
+		For Local node:=Eachin ctype.methods
 			Local func:=Cast<FuncValue>( node )
 			If Not func Or func.fdecl.ident<>"new" Continue
 			
@@ -392,7 +408,7 @@ Class Translator_CPP Extends Translator
 		Local hasCmp:=False
 		
 		EmitBr()
-		For Local node:=Eachin ctype.methods	'scope.transMembers
+		For Local node:=Eachin ctype.methods
 			Local func:=Cast<FuncValue>( node )
 			If Not func Or func.fdecl.ident="new" Continue
 			
@@ -402,6 +418,28 @@ Class Translator_CPP Extends Translator
 			Emit( FuncProto( func,True )+";" )
 		Next
 		
+		If cdecl.kind="struct"
+			If hasCtor Or Not hasDefaultCtor
+				EmitBr()
+				Emit( cname+"(){" )
+				Emit( "}" )
+			Endif
+			If Not hasDefaultCtor
+				EmitBr()
+				Emit( cname+"(bbNullCtor_t){" )
+				If needsInit Emit( "init();" )
+				Emit( "}" )
+			Endif
+		Else If cdecl.kind="class"
+			If Not hasDefaultCtor
+				EmitBr()
+				Emit( cname+"(){" )
+				If needsInit Emit( "init();" )
+				Emit( "}" )
+			Endif
+		Endif
+
+		#rem		
 		'Emit default ctor
 		'		
 		If Not hasDefaultCtor
@@ -410,19 +448,23 @@ Class Translator_CPP Extends Translator
 			If needsInit Emit( "init();" )
 			Emit( "}" )
 		Endif
+		#end
 		
+		#rem
 		If IsStruct( ctype )
 			EmitBr()
 			Emit( cname+"(bbNullCtor_t){" )
 			Emit( "}" )
 		Endif
+		#end
 		
 		Emit( "};" )
 		
 		If debug
 			Local tname:=cname
 			If Not IsStruct( ctype ) tname+="*"
-			Emit( "template<> bbDBType *bbDBTypeOf("+tname+"*);" )
+			Emit( "bbString bbDBType("+tname+"*);" )
+			Emit( "bbString bbDBValue("+tname+"*);" )
 		Endif
 		
 		If IsStruct( ctype )
@@ -445,9 +487,9 @@ Class Translator_CPP Extends Translator
 	
 	Method EmitClassMembers( ctype:ClassType )
 	
-		If ctype.cdecl.kind="protocol" Return
-		
 		Local cdecl:=ctype.cdecl
+		If cdecl.kind="protocol" Return
+		
 		Local cname:=ClassName( ctype )
 		
 		'Emit fields...
@@ -456,12 +498,15 @@ Class Translator_CPP Extends Translator
 		Local needsMark:=False
 
 		EmitBr()		
-		For Local node:=Eachin ctype.fields	'scope.transMembers
+		For Local node:=Eachin ctype.fields
 			Local vvar:=Cast<VarValue>( node )
 			If Not vvar Continue
 			
 			If IsGCType( vvar.type ) needsMark=True
-			If vvar.init And Not Cast<LiteralValue>( vvar.init ) needsInit=True
+			
+			If vvar.init And vvar.init.HasSideEffects needsInit=True
+			
+'			If vvar.init And Not Cast<LiteralValue>( vvar.init ) needsInit=True
 		Next
 		
 		'Emit init() method
@@ -473,10 +518,10 @@ Class Translator_CPP Extends Translator
 			
 			BeginGCFrame()
 			
-			For Local node:=Eachin ctype.fields	'scope.transMembers
+			For Local node:=Eachin ctype.fields
 				Local vvar:=Cast<VarValue>( node )
-				If Not vvar Or Not vvar.init Or Cast<LiteralValue>( vvar.init ) Continue
-				
+				If Not vvar Or Not vvar.init Or Not vvar.init.HasSideEffects Continue
+
 				Emit( Trans( vvar )+"="+Trans( vvar.init )+";" )
 			Next
 			
@@ -486,32 +531,55 @@ Class Translator_CPP Extends Translator
 		
 		Endif
 		
-		'Emit virtual gcMark() for class
-		'
-		If needsMark And ctype.cdecl.kind="class"
+		If cdecl.kind="class"
 		
-			EmitBr()
-			Emit( "void "+cname+"::gcMark(){" )
+			If needsMark
 			
-			If ctype.superType And ctype.superType<>Type.ObjectClass
-				Emit( ClassName( ctype.superType )+"::gcMark();" )
-			End
-		
-			For Local node:=Eachin ctype.fields	'scope.transMembers
-				Local vvar:=Cast<VarValue>( node )
-				If Not vvar Or Not IsGCType( vvar.type ) Continue
+				EmitBr()
+				Emit( "void "+cname+"::gcMark(){" )
 				
-				Uses( vvar.type )
-				Emit( "bbGCMark("+VarName( vvar )+");" )
-			Next
+				If ctype.superType And ctype.superType<>Type.ObjectClass
+					Emit( ClassName( ctype.superType )+"::gcMark();" )
+				End
 			
-			Emit( "}" )
+				For Local node:=Eachin ctype.fields
+					Local vvar:=Cast<VarValue>( node )
+					If Not vvar Or Not IsGCType( vvar.type ) Continue
+					
+					Uses( vvar.type )
+					Emit( "bbGCMark("+VarName( vvar )+");" )
+				Next
+				
+				Emit( "}" )
+			
+			Endif
+			
+			If debug
+			
+				EmitBr()
+				Emit( "void "+cname+"::dbEmit(){" )
+
+				If ctype.superType And ctype.superType<>Type.ObjectClass
+					Emit( ClassName( ctype.superType )+"::dbEmit();" )
+				End
+				
+				For Local node:=Eachin ctype.fields
+					Local vvar:=Cast<VarValue>( node )
+					If Not vvar Continue
+					
+					'Uses( vvar.type )
+					Emit( "bbDBEmit(~q"+vvar.vdecl.ident+"~q,&"+VarName( vvar )+");" )
+				Next
+				
+				Emit( "}" )
+			
+			Endif
 			
 		Endif
 	
 		'Emit ctor methods
 		'
-		For Local node:=Eachin ctype.methods	'scope.transMembers
+		For Local node:=Eachin ctype.methods
 			Local func:=Cast<FuncValue>( node )
 			If Not func Or func.fdecl.ident<>"new" Continue
 			
@@ -523,7 +591,7 @@ Class Translator_CPP Extends Translator
 		'
 		Local hasCmp:=False
 		
-		For Local node:=Eachin ctype.methods	'scope.transMembers
+		For Local node:=Eachin ctype.methods
 			Local func:=Cast<FuncValue>( node )
 			If Not func Or func.fdecl.ident="new" Continue
 			
@@ -538,13 +606,19 @@ Class Translator_CPP Extends Translator
 		If debug
 			Local tname:=cname
 			If Not IsStruct( ctype ) tname+="*"
-			Emit(	"template<> bbDBType *bbDBTypeOf("+tname+"*){" )
-			Emit(		"struct type : public bbDBType{" )
-			Emit(			"bbString name(){return ~q"+ctype.Name+"~q;}" )
-			Emit(		"};" )
-			Emit(		"static type _type;" )
-			Emit(	 	"return &_type;" )
-			Emit(	"}" )
+			Emit( "bbString bbDBType("+tname+"*){" )
+			Emit( "return ~q"+ctype.Name+"~q;" )
+			Emit( "}" )
+			Emit( "bbString bbDBValue("+tname+"*p){" )
+			Select cdecl.kind
+			Case "class"
+				Emit( "return bbDBObjectValue(*p);" )
+			Case "interface"
+				Emit( "return bbDBInterfaceValue(*p);" )
+			Case "struct"
+				Emit( "return bbDBStructValue(p);" )
+			End
+			Emit( "}" )
 		Endif
 
 		'Emit static struct methods
@@ -554,7 +628,7 @@ Class Translator_CPP Extends Translator
 			If Not hasCmp
 				EmitBr()
 				Emit( "int bbCompare(const "+cname+"&x,const "+cname+"&y){" )
-				For Local node:=Eachin ctype.fields	'scope.transMembers
+				For Local node:=Eachin ctype.fields
 					Local vvar:=Cast<VarValue>( node )
 					If Not vvar Continue
 					Local vname:=VarName( vvar )
@@ -573,7 +647,7 @@ Class Translator_CPP Extends Translator
 					Emit( "bbGCMark(("+ClassName( ctype.superType )+"&)t);" )
 				Endif
 	
-				For Local node:=Eachin ctype.fields	'scope.transMembers
+				For Local node:=Eachin ctype.fields
 					Local vvar:=Cast<VarValue>( node )
 					If Not vvar Or Not IsGCType( vvar.type ) Continue
 					
@@ -840,17 +914,22 @@ Class Translator_CPP Extends Translator
 			dbvar=InsertGCTmp( vvar )
 
 			If vvar.init Emit( dbvar+"="+Trans( vvar.init )+";" )
-		Else
 
+		Else
+		
 			dbvar=VarName( vvar )
-
+			
+			Local type:=VarType( vvar )
+			If vdecl.kind="global" Or vdecl.kind="const" type="static "+type
+			
 			Local init:="{}"
 			If vvar.init init="="+Trans( vvar.init )
 			
-			Emit( TransType( vvar.type )+" "+dbvar+init+";" )
+			Emit( type+" "+dbvar+init+";" )
+			
 		Endif
 		
-		If debug And dbvar Emit( "bbDBLocal(~q"+vvar.vdecl.ident+"~q,&"+dbvar+");" )
+		If debug And vdecl.kind="local" Emit( "bbDBLocal(~q"+vvar.vdecl.ident+"~q,&"+dbvar+");" )
 
 	End
 	
@@ -1234,9 +1313,14 @@ Class Translator_CPP Extends Translator
 		Local ctype:=value.ctype
 		Uses( ctype )
 	
-		If IsStruct( ctype ) Return ClassName( ctype )+"("+TransArgs( value.args )+")"
+		If ctype.IsVoid
+			Return "new "+ClassName( ctype )+"("+TransArgs( value.args )+")"
+		Endif
 		
-		If ctype.IsVoid Return "new "+ClassName( ctype )+"("+TransArgs( value.args )+")"
+		If IsStruct( ctype )
+			If Not value.args Return ClassName( ctype )+"(bbNullCtor)"
+			Return ClassName( ctype )+"("+TransArgs( value.args )+")"
+		Endif
 		
 		Return "bbGCNew<"+ClassName( ctype )+">("+TransArgs( value.args )+")"
 	End
@@ -1429,8 +1513,8 @@ Class Translator_CPP Extends Translator
 	End
 	
 	Method ArrayName:String( type:ArrayType )
-		If type.rank=1 Return "bbArray<"+VarType( type.elemType )+">"
-		Return "bbArray<"+VarType( type.elemType )+","+type.rank+">"
+		If type.rank=1 Return "bbArray<"+ElementType( type.elemType )+">"
+		Return "bbArray<"+ElementType( type.elemType )+","+type.rank+">"
 	End
 	
 End

+ 9 - 3
src/mx2new/var.monkey2

@@ -48,7 +48,7 @@ Class VarValue Extends Value
 		Self.scope=scope
 		Self.transFile=scope.FindFile().fdecl
 		
-		If vdecl.kind="global" Or vdecl.kind="local" Or vdecl.kind="param"	flags|=VALUE_LVALUE|VALUE_ASSIGNABLE
+		If vdecl.kind="global" Or vdecl.kind="local" Or vdecl.kind="param" flags|=VALUE_LVALUE|VALUE_ASSIGNABLE
 	End
 	
 	Method New( kind:String,ident:String,init:Value,scope:Scope )
@@ -62,7 +62,7 @@ Class VarValue Extends Value
 		Self.scope=scope
 		Self.init=init
 		
-		If vdecl.kind="global" Or vdecl.kind="local" Or vdecl.kind="param"	flags|=VALUE_LVALUE|VALUE_ASSIGNABLE
+		If vdecl.kind="global" Or vdecl.kind="local" Or vdecl.kind="param" flags|=VALUE_LVALUE|VALUE_ASSIGNABLE
 		
 		semanted=Self
 	End
@@ -77,7 +77,13 @@ Class VarValue Extends Value
 			type=init.type
 		Endif
 		
-		If Not type.IsGeneric And Not vdecl.IsExtern
+		'struct field?
+'		Local cscope:=Cast<ClassScope>( scope )
+'		If vdecl.kind="field" And cscope And cscope.ctype.cdecl.kind="struct"
+'			If init And init.HasSideEffects Throw New SemantEx( "Struct field initializers cannot have side effects" )
+'		Endif
+		
+		If Not type.IsGeneric And Not vdecl.IsExtern And Not Cast<Block>( scope )
 			If vdecl.kind="global" Or vdecl.kind="const"
 				transFile.globals.Push( Self )
 			Else