Browse Source

Major low level change to bbArray - is now a c++ 'value' (but still a mx2 reference type) so ctor with bbArray blah{10} etc...

Mark Sibly 9 years ago
parent
commit
ef9a1ef3f9

+ 1 - 1
modules/monkey/native/bbarray.cpp

@@ -1,4 +1,4 @@
 
 #include "bbarray.h"
 
-void *bb_array_null;
+void *bb_array_kludge;

+ 130 - 140
modules/monkey/native/bbarray.h

@@ -3,119 +3,145 @@
 #define BB_ARRAY_H
 
 #include "bbgc.h"
-#include "bbdebug.h"
-#include "bbobject.h"
 
-extern void *bb_array_null;
+template<class T,int D> struct bbArray{
 
-template<class T,int D> class bbArray : public bbGCNode{
-
-	int _sizes[D];
-	T _data[0];
-		
-	bbArray(){
-		memset( _sizes,0,sizeof(_sizes) );
-	}
+	struct Rep : public bbGCNode{
 	
-	bbArray( int sizes[] ){
-		bbGC::beginCtor( this );
+		int _sizes[D];
+		T _data[0];
 		
-		memcpy( _sizes,sizes,D*sizeof(int) );
-		
-		for( int i=0;i<_sizes[D-1];++i ) new( &_data[i] ) T();
-	}
-	
-	~bbArray(){
-		for( int i=0;i<_sizes[D-1];++i ) _data[i].~T();
-	}
-	
-	virtual void gcMark(){
-		for( int i=0;i<_sizes[D-1];++i ) bbGCMark( _data[i] );	
-	}
+		Rep(){
+			memset( _sizes,0,sizeof(_sizes) );
+		}
+			
+		Rep( int sizes[] ){
+			bbGC::beginCtor( this );
+				
+			memcpy( _sizes,sizes,D*sizeof(int) );
+				
+			for( int i=0;i<_sizes[D-1];++i ) new( &_data[i] ) T();
+		}
+			
+		~Rep(){
+			for( int i=0;i<_sizes[D-1];++i ) _data[i].~T();
+		}
 	
-	public:
+		virtual const char *typeName()const{
+			return "bbArray::Rep";
+		}
+			
+		virtual void gcMark(){
+			for( int i=0;i<_sizes[D-1];++i ) bbGCMark( _data[i] );
+		}
+	};
 	
-	virtual const char *typeName()const{
-		return "bbArray";
+	Rep *_rep=nullptr;
+
+	bbArray(){
 	}
-	
-	template<class...Args> static bbArray *create( Args...args ){
-	
-		int sizes[]{ args... };
-		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
 		
-		if( !sizes[D-1] ) return nullptr;
+	template<class...Args> bbArray( Args...args ){
 		
-		bbGCNode *p=bbGC::alloc( sizeof( bbArray )+sizes[D-1]*sizeof(T) );
-		
-		bbArray *r=new( p ) bbArray( sizes );
-		
-		bbGC::endCtor( r );
-		
-		return r;
-	}
-	
-	template<class...Args> static bbArray *create( std::initializer_list<T> init,Args...args ){
-	
 		int sizes[]{ args... };
 		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
+			
+		if( !sizes[D-1] ) return;
+			
+		bbGCNode *p=bbGC::alloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
+	
+		_rep=new( p ) Rep( sizes );
+			
+		bbGC::endCtor( _rep );
+	}
 		
-		if( !sizes[D-1] ) return nullptr;
-		
-		bbGCNode *p=bbGC::alloc( sizeof( bbArray )+sizes[D-1]*sizeof(T) );
-		
-		bbArray *r=new( p ) bbArray( sizes );
+	template<class...Args> bbArray( std::initializer_list<T> init,Args...args ){
 		
+		int sizes[]{ args... };
+		for( int i=1;i<D;++i ) sizes[i]*=sizes[i-1];
+			
+		if( !sizes[D-1] ) return;
+			
+		bbGCNode *p=bbGC::alloc( sizeof( Rep )+sizes[D-1]*sizeof(T) );
+			
+		_rep=new( p ) Rep( sizes );
+			
 		int i=0;
-		for( auto it=init.begin();it!=init.end();++it ) r->_data[i++]=*it;
-		
-		bbGC::endCtor( r );
-		
-		return r;
+		for( auto it=init.begin();it!=init.end();++it ) _rep->_data[i++]=*it;
+			
+		bbGC::endCtor( _rep );
 	}
-	
+		
 	T *data(){
-		return _data;
+		return _rep->_data;
 	}
-	
+		
 	const T *data()const{
-		return _data;
+		return _rep->_data;
 	}
-	
+		
 	int length()const{
-//		return this ? _sizes[D-1] : 0;
-		return this!=bb_array_null ? _sizes[D-1] : 0;
+		return _rep ? _rep->_sizes[D-1] : 0;
 	}
-	
+		
 	int size( int q )const{
-		bbDebugAssert( q<D,"Array dimension out of range" );
+		bbDebugAssert( q>=0 && q<D,"Array dimension out of range" );
+			
+		return _rep ? (q ? _rep->_sizes[q]/_rep->_sizes[q-1] : _rep->_sizes[0]) : 0;
+	}
 		
-//		return this ? (q ? _sizes[q]/_sizes[q-1] : _sizes[0]) : 0;
-		return this!=bb_array_null ? (q ? _sizes[q]/_sizes[q-1] : _sizes[0]) : 0;
+	T &operator[]( int index ){
+		bbDebugAssert( index>=0 && index<length(),"Array index out of range" );
+			
+		return data()[index];
 	}
 	
-	static int length( bbArray *array ){
-		return array ? array->_sizes[D-1] : 0;
+	T &at( int index ){
+		bbDebugAssert( index>=0 && index<length(),"Array index out of range" );
+				
+		return data()[index];
 	}
-	
-	static int size( bbArray *array,int q ){
-		bbDebugAssert( q<D,"Array dimension out of range" );
 		
-		return array ? (q ? array->_sizes[q]/array->_sizes[q-1] : array->_sizes[0]) : 0;
+	//slower N-D version
+	template<class...Args> T &at( Args...args ){
+		
+		const int indices[]{args...};
+			
+		int index=indices[0];
+		bbDebugAssert( index>=0 && _rep,"Array index out of range" );
+			
+		for( int i=1;i<D;++i ){
+			bbDebugAssert( indices[i]>=0 && index<_rep->_sizes[i-1],"Array index out of range" );
+				
+			index+=indices[i]*_rep->_sizes[i-1];
+		}
+			
+		bbDebugAssert( index<length(),"Array index out of range" );
+			
+		return data()[index];
+	}
+		
+	operator bool()const{
+		
+		return _rep;
 	}
+		
+	bbArray<T,1> slice( int from )const{
 	
-	bbArray<T,1> *slice( int from )const{
 		return slice( from,length() );
 	}
-	
-	bbArray<T,1> *slice( int from,int term )const{
+		
+	bbArray<T,1> slice( int from,int term )const{
+		
 		int length=this->length();
+			
 		if( from<0 ){
 			from+=length;
 			if( from<0 ) from=0;
 		}else if( from>length ){
 			from=length;
 		}
+			
 		if( term<0 ){
 			term+=length;
 			if( term<from ) term=from;
@@ -124,88 +150,52 @@ template<class T,int D> class bbArray : public bbGCNode{
 		}else if( term>length ){
 			term=length;
 		}
+			
 		int newlen=term-from;
-		bbArray<T,1> *r=create( newlen );
-		for( int i=0;i<newlen;++i ) r->data()[i]=data()[from+i];
-		return r;
-	}
-
-	bbArray<T,1> *resize( int newLength )const{
-		bbDebugAssert( newLength>=0,
-			"Array Resize new length must not be negative" );
-			
-		if( newLength<=0 ) newLength=0;
-		int n=this->length();
-		if( n>newLength ) n=newLength;
-		bbArray<T,1> *r=create( newLength );
-		for( int i=0;i<n;++i ) r->data()[i]=data()[i];
+			
+		bbArray<T,1> r{newlen};
+			
+		for( int i=0;i<newlen;++i ) r.data()[i]=data()[from+i];
+			
 		return r;
 	}
 	
-	void copyTo( bbArray<T,1> *dst,int offset,int dstOffset,int count )const{
-		bbDebugAssert( offset>=0 && dstOffset>=0 && count>=0 && offset+count<=length() && dstOffset+count<=dst->length(),
-			"Array CopyTo parameters out of range" );
-
-		if( dst==this && dstOffset>offset ){
-			for( int i=count-1;i>=0;--i ) dst->data()[dstOffset+i]=data()[offset+i];
-		}else{
-			for( int i=0;i<count;++i ) dst->data()[dstOffset+i]=data()[offset+i];
-		}
-	}
+	bbArray<T,1> resize( int newLength )const{
+		bbDebugAssert( newLength>=0,"Array Resize new length must not be negative" );
+			
+		int ncopy=length();
+		if( ncopy>newLength ) ncopy=newLength;
 	
-	//fast 1D version	
-	T &at( int index ){
-		bbDebugAssert( index>=0 && index<length(),
-			"Array index out of range" );
+		auto r=bbArray<T,1>( newLength );
 			
-		return data()[index];
+		for( int i=0;i<ncopy;++i ) r.data()[i]=data()[i];
+			
+		return r;
 	}
-	
-	//slower N-D version
-	template<class...Args> T &at( Args...args ){
-	
-		const int indices[]{args...};
 		
-		int index=indices[0];
-		bbDebugAssert( index>=0,"Array index out of range" );
-		
-		for( int i=1;i<D;++i ){
-			bbDebugAssert( indices[i]>=0 && index<_sizes[i-1],"Array index out of range" );
-			index+=indices[i]*_sizes[i-1];
-		}
-		
-		bbDebugAssert( index<length(),"Array index out of range" );
-		return data()[index];
-	}
-	
-	T &get( int index ){
-		if( index<0 || index>=length() ) puts( "Out of range" );
-		return data()[index];
-	}
-	
-	operator bool()const{
-		return length();
-	}
-	
-	void dbEmit(){
-		int n=length();
-		if( n>100 ) n=100;
-		bbString t=bbDBType<T>();
-		for( int i=0;i<n;++i ){
-			bbString e=BB_T("[")+bbString( i )+"]:"+t+"="+bbDBValue( &at(i) );
-			puts( e.c_str() );
+	void copyTo( bbArray<T,1> dst,int offset,int dstOffset,int count )const{
+		bbDebugAssert( offset>=0 && dstOffset>=0 && count>=0 && offset+count<=length() && dstOffset+count<=dst.length(),"Array CopyTo parameters out of range" );
+			
+		if( dst._rep==_rep && dstOffset>offset ){
+			for( int i=count-1;i>=0;--i ) dst.data()[dstOffset+i]=data()[offset+i];
+		}else{
+			for( int i=0;i<count;++i ) dst.data()[dstOffset+i]=data()[offset+i];
 		}
 	}
 };
 
-template<class T,int N> bbString bbDBType( bbArray<T,N> **p ){
+template<class T,int D> bbString bbDBType( bbArray<T,D> *p ){
 	return bbDBType<T>()+"[]";
 }
 
-template<class T,int N> bbString bbDBValue( bbArray<T,N> **p ){
+template<class T,int D> bbString bbDBValue( bbArray<T,D> *p ){
 	char buf[64];
-	sprintf( buf,"@%p",*p );
+	sprintf( buf,"@%p",p->_rep );
 	return buf;
 }
 
+template<class T,int D> void bbGCMark( bbArray<T,D> arr ){
+	bbGC::enqueue( arr._rep );
+}
+
 #endif

+ 3 - 3
modules/monkey/native/bbdebug.cpp

@@ -154,17 +154,17 @@ namespace bbDB{
 
 	}
 	
-	bbArray<bbString> *stack(){
+	bbArray<bbString> stack(){
 	
 		int n=0;
 		for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ) ++n;
 		
 		//TODO: Fix GC issues! Can't have a free local like this in case bbString ctors cause gc sweep!!!!
-		bbArray<bbString> *st=bbArray<bbString>::create( n );
+		bbArray<bbString> st=bbArray<bbString>( n );
 		
 		int i=0;
 		for( bbDBFrame *frame=currentContext->frames;frame;frame=frame->succ ){
-			st->at( i++ )=BB_T( frame->srcFile )+" ["+bbString( frame->srcPos>>12 )+"] "+frame->decl;
+			st[i++]=BB_T( frame->srcFile )+" ["+bbString( frame->srcPos>>12 )+"] "+frame->decl;
 		}
 		
 		return st;

+ 1 - 1
modules/monkey/native/bbdebug.h

@@ -100,7 +100,7 @@ namespace bbDB{
 	
 	void error( bbString err );
 	
-	bbArray<bbString> *stack();
+	bbArray<bbString> stack();
 	
 	void emitStack();
 }

+ 6 - 18
modules/monkey/native/bbgc.h

@@ -258,41 +258,29 @@ template<class T> struct bbGCVar{
 	}
 };
 
+/*
 template<class T> struct bbGCRootVar : public bbGCVar<T>,public bbGCRoot{
 	
-	using bbGCVar<T>::_ptr;
-	using bbGCVar<T>::enqueue;
+	using bbGCVar<T>::operator=;
 
 	bbGCRootVar(){
 	}
 	
 	bbGCRootVar( T *p ){
-		_ptr=p;
+		this->_ptr=p;
 		enqueue();
 	}
 	
 	bbGCRootVar( const bbGCVar<T> &p ){
-		_ptr=p._ptr;
+		this->_ptr=p._ptr;
 		enqueue();
 	}
-	
 
-	bbGCRootVar &operator=( T *p ){
-		_ptr=p;
-		enqueue();
-		return *this;
-	}
-	
-	bbGCRootVar &operator=( const bbGCVar<T> &p ){
-		_ptr=p._ptr;
-		enqueue();
-		return *this;
-	}
-	
-	virtual void gcMark(){
+	void gcMark(){
 		bbGC::enqueue( dynamic_cast<bbGCNode*>( _ptr ) );
 	}
 };
+*/
 
 template<class T> void bbGCMark( const T &t ){}
 

+ 15 - 15
modules/monkey/native/bbstring.cpp

@@ -218,12 +218,12 @@ bbString bbString::fromUtf8Data( const void *data,int size ){
 }
 
 
-bbArray<bbString> *bbString::split( bbString sep )const{
+bbArray<bbString> bbString::split( bbString sep )const{
 
 	if( !sep.length() ){
-		bbArray<bbString> *bits=bbArray<bbString>::create( length() );
+		bbArray<bbString> bits=bbArray<bbString>( length() );
 		for( int i=0;i<length();++i ){
-			bits->at(i)=bbString( &data()[i],1 );
+			bits[i]=bbString( &data()[i],1 );
 		}
 		return bits;
 	}
@@ -233,36 +233,36 @@ bbArray<bbString> *bbString::split( bbString sep )const{
 		++n;
 		i=i2+sep.length();
 	}
-	bbArray<bbString> *bits=bbArray<bbString>::create( n );
+	bbArray<bbString> bits=bbArray<bbString>( n );
 	if( n==1 ){
-		bits->at(0)=*this;
+		bits[0]=*this;
 		return bits;
 	}
 	i=0;n=0;
 	while( (i2=find( sep,i ))!=-1 ){
-		bits->at(n++)=slice( i,i2 );
+		bits[n++]=slice( i,i2 );
 		i=i2+sep.length();
 	}
-	bits->at(n)=slice( i );
+	bits[n]=slice( i );
 	return bits;
 }
 
-bbString bbString::join( bbArray<bbString> *bits )const{
+bbString bbString::join( bbArray<bbString> bits )const{
 
-	if( bits->length()==0 ) return bbString();
-	if( bits->length()==1 ) return bits->at(0);
+	if( bits.length()==0 ) return bbString();
+	if( bits.length()==1 ) return bits[0];
 	
-	int len=length() * (bits->length()-1);
-	for( int i=0;i<bits->length();++i ) len+=bits->at(i).length();
+	int len=length() * (bits.length()-1);
+	for( int i=0;i<bits.length();++i ) len+=bits[i].length();
 	
 	Rep *rep=Rep::alloc( len );
 	bbChar *p=rep->data;
 
-	p=t_memcpy( p,bits->at(0).data(),bits->at(0).length() );
+	p=t_memcpy( p,bits[0].data(),bits[0].length() );
 	
-	for( int i=1;i<bits->length();++i ){
+	for( int i=1;i<bits.length();++i ){
 		p=t_memcpy( p,data(),length() );
-		p=t_memcpy( p,bits->at(i).data(),bits->at(i).length() );
+		p=t_memcpy( p,bits[i].data(),bits[i].length() );
 	}
 	
 	return rep;

+ 2 - 2
modules/monkey/native/bbstring.h

@@ -350,9 +350,9 @@ class bbString{
 		return rep;
 	}
 	
-	bbArray<bbString> *split( bbString sep )const;
+	bbArray<bbString> split( bbString sep )const;
 	
-	bbString join( bbArray<bbString> *bits )const;
+	bbString join( bbArray<bbString> bits )const;
 	
 	int compare( const bbString &t )const{
 		int len=length()<t.length() ? length() : t.length();

+ 4 - 4
modules/std/filesystem/native/filesystem.cpp

@@ -39,7 +39,7 @@ namespace bbFileSystem{
 
 	bbString _appDir;
 	bbString _appPath;
-	bbArray<bbString> *_appArgs;
+	bbArray<bbString> _appArgs;
 	
 	struct GCRoot : public bbGCRoot{
 		void gcMark(){
@@ -55,9 +55,9 @@ namespace bbFileSystem{
 		if( done ) return;
 		done=true;
 		
-		_appArgs=bbArray<bbString>::create( bb_argc );
+		_appArgs=bbArray<bbString>( bb_argc );
 		
-		for( int i=0;i<bb_argc;++i ) _appArgs->at(i)=bbString( bb_argv[i] );
+		for( int i=0;i<bb_argc;++i ) _appArgs[i]=bbString( bb_argv[i] );
 		
 		#if _WIN32
 	
@@ -117,7 +117,7 @@ namespace bbFileSystem{
 		return _appPath;
 	}
 	
-	bbArray<bbString> *appArgs(){
+	bbArray<bbString> appArgs(){
 		init();
 		return _appArgs;
 	}

+ 1 - 1
modules/std/filesystem/native/filesystem.h

@@ -10,7 +10,7 @@ namespace bbFileSystem{
 	
 	bbString appPath();
 	
-	bbArray<bbString> *appArgs();
+	bbArray<bbString> appArgs();
 	
 	bbBool copyFile( bbString srcPath,bbString dstPath );
 }

+ 7 - 17
src/mx2cc/translator.monkey2

@@ -28,16 +28,11 @@ Function IsGCType:Bool( type:Type )
 	Return False
 End
 
-
 Function IsGCPtrType:Bool( type:Type )
 
 	Local ctype:=TCast<ClassType>( type )
-	If ctype Return Not ctype.ExtendsVoid And Not ctype.IsStruct
-	
-	Local atype:=TCast<ArrayType>( type )
-	If atype Return True
 	
-	Return False
+	Return ctype And Not ctype.ExtendsVoid And (ctype.IsClass Or ctype.IsInterface)
 End
 
 'Visitor that looks for gc params on LHS of an assignment.
@@ -212,7 +207,6 @@ Class Translator
 				Else
 					Emit( "bbGCMark("+VarName( vvar )+");" )
 				Endif
-'				Emit( "bbGCMark("+VarName( vvar )+");" )
 			Next
 			
 			For Local tmp:=Eachin _gcframe.tmps
@@ -222,7 +216,6 @@ Class Translator
 				Else
 					Emit( "bbGCMark("+tmp.ident+");" )
 				Endif
-'				Emit( "bbGCMark("+tmp.ident+");" )
 			Next
 			
 			Emit( "}" )
@@ -326,7 +319,7 @@ Class Translator
 				
 				If debug And Not ctype.cdecl.IsExtern
 					Local tname:=cname
-					If Not IsStruct( ctype ) tname+="*"
+					If Not ctype.IsStruct tname+="*"
 					Emit( "bbString bbDBType("+tname+"*);" )
 					Emit( "bbString bbDBValue("+tname+"*);" )
 				Endif
@@ -415,7 +408,7 @@ Class Translator
 		Local ctype:=TCast<ClassType>( type )
 		If ctype
 			If ctype.cdecl.IsExtern Uses( ctype.transFile ) ; return
-			If IsStruct( ctype ) Uses( ctype ) ; Return
+			If ctype.IsStruct Uses( ctype ) ; Return
 			If AddRef( ctype ) Return
 			_refsTypes.Push( ctype )
 			Return
@@ -479,15 +472,12 @@ Class Translator
 	
 	'***** MISC *****
 
-	Method IsStruct:Bool( type:Type )
-
-		Local ctype:=TCast<ClassType>( type )
-		Return ctype And ctype.cdecl.kind="struct"
-	End
+	Method IsCValueType:Bool( type:Type )
 	
-	Method IsValue:Bool( type:Type )
+		Local ctype:=TCast<ClassType>( type )
+		If ctype And ctype.IsStruct Return True
 	
-		Return TCast<PrimType>( type ) Or TCast<FuncType>( type ) Or IsStruct( type )
+		Return TCast<PrimType>( type ) Or TCast<FuncType>( type ) Or TCast<ArrayType>( type )
 	End
 	
 	Method CFuncType:String( type:FuncType )

+ 86 - 27
src/mx2cc/translator_cpp.monkey2

@@ -126,13 +126,33 @@ Class Translator_CPP Extends Translator
 	
 	'***** Decls *****
 	
+	Method HeapVarType:String( type:Type )
+	
+		If IsGCPtrType( type ) Return "bbGCVar<"+ClassName( TCast<ClassType>( type ) )+">"
+		
+		Return TransType( type )
+	End
+	
+	Method VarType:String( vvar:VarValue )
+	
+		Local type:=vvar.type
+		
+		Select vvar.vdecl.kind
+		Case "const","global","field"
+			Return HeapVarType( type )
+		End
+		
+		Return TransType( type )
+	End
+
+#rem		
 	Method GCVarTypeName:String( type:Type )
 	
 		Local ctype:=TCast<ClassType>( type )
 		If ctype And Not ctype.ExtendsVoid And (ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface") Return ClassName( ctype )
 		
-		Local atype:=TCast<ArrayType>( type )
-		If atype Return ArrayName( atype )
+'		Local atype:=TCast<ArrayType>( type )
+'		If atype Return ArrayName( atype )
 		
 		Return ""
 	End
@@ -158,12 +178,14 @@ Class Translator_CPP Extends Translator
 		Case "field"
 			Return "bbGCVar<"+name+">"
 		Case "global","const"
-			Return "bbGCRootVar<"+name+">"
+			Return "bbGCVar<"+name+">"
+'			Return "bbGCRootVar<"+name+">"
 		End
 		
 		TransError( "Translator.VarType()" )
 		Return ""
 	End
+#end
 
 	Method VarProto:String( vvar:VarValue ) Override
 	
@@ -220,21 +242,35 @@ Class Translator_CPP Extends Translator
 	Method EmitGlobalInits( fdecl:FileDecl )
 	
 		EmitBr()
-		Emit( "void mx2_"+fdecl.ident+"_init(){" )
+		Emit( "void mx2_"+fdecl.ident+"_init_f(){" )
 		BeginGCFrame()
+		
 		Emit( "static bool done;" )
 		Emit( "if(done) return;" )
 		Emit( "done=true;")
 		
+		Local gc:=False
 		For Local vvar:=Eachin fdecl.globals
 			If vvar.init Emit( Trans( vvar )+"="+Trans( vvar.init )+";" )
+			If IsGCType( vvar.type ) gc=True
 		Next
 		
 		EndGCFrame()
 		Emit( "}" )
 		
+		If gc
+			EmitBr()
+			Emit( "struct mx2_"+fdecl.ident+"_roots_t : bbGCRoot{" )
+			Emit( "void gcMark(){" )
+			For Local vvar:=Eachin fdecl.globals
+				If IsGCType( vvar.type ) Emit( "bbGCMark("+Trans(vvar)+");" )
+			Next
+			Emit( "}" )
+			Emit( "}mx2_"+fdecl.ident+"_roots;" )
+		Endif
+		
 		EmitBr()
-		Emit( "bbInit mx2_"+fdecl.ident+"_init_v(~q"+fdecl.ident+"~q,&mx2_"+fdecl.ident+"_init);" )
+		Emit( "bbInit mx2_"+fdecl.ident+"_init(~q"+fdecl.ident+"~q,&mx2_"+fdecl.ident+"_init_f);" )
 	
 	End
 	
@@ -439,13 +475,12 @@ Class Translator_CPP Extends Translator
 		
 		If debug
 			Local tname:=cname
-			If Not IsStruct( ctype ) tname+="*"
+			If Not ctype.IsStruct tname+="*"
 			Emit( "bbString bbDBType("+tname+"*);" )
 			Emit( "bbString bbDBValue("+tname+"*);" )
 		Endif
 		
-		If IsStruct( ctype )
-
+		If ctype.IsStruct
 			EmitBr()
 			If hasCmp
 				Emit( "inline int bbCompare(const "+cname+"&x,const "+cname+"&y){return x.m__cmp(y);}" )
@@ -581,7 +616,7 @@ Class Translator_CPP Extends Translator
 		
 		If debug
 			Local tname:=cname
-			If Not IsStruct( ctype ) tname+="*"
+			If Not ctype.IsStruct tname+="*"
 			
 			Emit( "bbString bbDBType("+tname+"*){" )
 			Emit( "return ~q"+ctype.Name+"~q;" )
@@ -613,8 +648,7 @@ Class Translator_CPP Extends Translator
 
 		'Emit static struct methods
 		'
-		If IsStruct( ctype ) 
-
+		If ctype.IsStruct
 			If Not hasCmp
 				EmitBr()
 				Emit( "int bbCompare(const "+cname+"&x,const "+cname+"&y){" )
@@ -946,6 +980,12 @@ Class Translator_CPP Extends Translator
 			
 			Emit( type+" "+tvar+init+";" )
 			
+			If (vdecl.kind="global" Or vdecl.kind="const") And IsGCType( vvar.type )
+				Emit( "static struct _"+tvar+"_t:bbGCRoot{" )
+				Emit( "void gcMark(){ bbGCMark("+tvar+");}" )
+				Emit( "}_"+tvar+";" )
+			Endif
+			
 		Endif
 		
 		If debug And vdecl.kind="local" Emit( "bbDBLocal(~q"+vvar.vdecl.ident+"~q,&"+tvar+");" )
@@ -1205,7 +1245,7 @@ Class Translator_CPP Extends Translator
 
 		Local t:="("+Trans( value.value )+")"
 		
-		If IsValue( value.type ) Return TransType( value.type )+t
+		If IsCValueType( value.type ) Return TransType( value.type )+t
 
 		Return "(("+TransType( value.type )+")"+t+")"
 	End
@@ -1222,7 +1262,7 @@ Class Translator_CPP Extends Translator
 		
 		Local t:="("+Trans( value.value )+")"
 		
-		If IsValue( value.type ) Return TransType( value.type )+t
+		If IsCValueType( value.type ) Return TransType( value.type )+t
 
 		Return "(("+TransType( value.type )+")"+t+")"
 	End
@@ -1242,7 +1282,10 @@ Class Translator_CPP Extends Translator
 		Local etype:=TCast<EnumType>( type )
 		If etype Return EnumName( etype )+"(0)"
 
-		If IsValue( type ) Return TransType( type )+"{}"
+		If IsCValueType( type ) 
+			Uses( type )
+			Return TransType( type )+"{}"
+		Endif
 		
 		Return "(("+TransType( type )+")0)"
 	End
@@ -1287,7 +1330,7 @@ Class Translator_CPP Extends Translator
 		
 		Local cname:=ClassName( value.ctype )
 		
-		If IsStruct( value.ctype ) Return "(*static_cast<"+cname+"*>(this))"
+		If value.ctype.IsStruct Return "(*static_cast<"+cname+"*>(this))"
 		
 		Return "static_cast<"+cname+"*>(this)"
 	End
@@ -1301,12 +1344,17 @@ Class Translator_CPP Extends Translator
 		
 		Local tinst:=Trans( instance )
 		Local tmember:=Trans( member )
-
-		If IsValue( instance.type ) Return tinst+"."+tmember
 		
 		If Cast<FuncValue>( member ) And IsVolatile( instance ) tinst="("+AllocGCTmp( instance.type )+"="+tinst+")"
+
+		If IsCValueType( instance.type ) Return tinst+"."+tmember
 		
 		Return tinst+"->"+tmember
+		
+		'have to do this for arrays too?
+'		If Cast<FuncValue>( member ) And IsVolatile( instance ) tinst="("+AllocGCTmp( instance.type )+"="+tinst+")"
+		
+'		Return tinst+"->"+tmember
 	End
 	
 	Method TransInvokeMember:String( instance:Value,member:FuncValue,args:Value[] )
@@ -1367,7 +1415,7 @@ Class Translator_CPP Extends Translator
 			Return "new "+cname+"("+TransArgs( value.args )+")"
 		Endif
 		
-		If IsStruct( ctype )
+		If ctype.IsStruct
 			If Not value.args Return cname+"(bbNullCtor)"
 			If value.args[0].type.Equals( ctype ) Return cname+"("+TransArgs( value.args )+",bbNullCtor)"
 			Return cname+"("+TransArgs( value.args )+")"
@@ -1380,14 +1428,21 @@ Class Translator_CPP Extends Translator
 	
 		Local atype:=value.atype
 		Uses( atype )
+		
+		If value.inits Return ArrayName( atype )+"({"+TransArgs( value.inits )+"},"+value.inits.Length+")"
+		
+		Return ArrayName( atype )+"("+TransArgs( value.sizes )+")"
 	
-		If value.inits Return ArrayName( atype )+"::create({"+TransArgs( value.inits )+"},"+value.inits.Length+")"
+'		If value.inits Return ArrayName( atype )+"::create({"+TransArgs( value.inits )+"},"+value.inits.Length+")"
 		
-		Return ArrayName( atype )+"::create("+TransArgs( value.sizes )+")"
+'		Return ArrayName( atype )+"::create("+TransArgs( value.sizes )+")"
 	End
 	
 	Method Trans:String( value:ArrayIndexValue )
-		Return Trans( value.value )+"->at("+TransArgs( value.args )+")"
+		If value.args.Length=1 Return Trans( value.value )+"["+TransArgs( value.args )+"]"
+		Return Trans( value.value )+".at("+TransArgs( value.args )+")"
+		
+'		Return Trans( value.value )+"->at("+TransArgs( value.args )+")"
 	End
 	
 	Method Trans:String( value:StringIndexValue )
@@ -1428,7 +1483,11 @@ Class Translator_CPP Extends Translator
 		
 			If op="=" op="==" Else If op="<>" op="!="
 			
-			If IsStruct( value.lhs.type ) Or (TCast<FuncType>( value.lhs.type ) And op<>"==" And op<>"!=" )
+			Local ctype:=TCast<ClassType>( value.lhs.type )
+			Local ftype:=TCast<FuncType>( value.lhs.type )
+			
+			If (ctype And ctype.IsStruct) Or (ftype And op<>"==" And op<>"!=" )
+'			If IsStruct( value.lhs.type ) Or (TCast<FuncType>( value.lhs.type ) And op<>"==" And op<>"!=" )
 				Return "(bbCompare("+Trans( value.lhs )+","+Trans( value.rhs )+")"+op+"0)"
 			Endif
 			
@@ -1554,7 +1613,7 @@ Class Translator_CPP Extends Translator
 	End
 	
 	Method TransType:String( type:ClassType )
-		If IsStruct( type ) Return ClassName( type )
+		If type.IsStruct Return ClassName( type )
 		Return ClassName( type )+"*"
 	End
 	
@@ -1571,7 +1630,7 @@ Class Translator_CPP Extends Translator
 	End
 	
 	Method TransType:String( type:ArrayType )
-		Return ArrayName( type )+"*"
+		Return ArrayName( type )
 	End
 	
 	Method TransType:String( type:PointerType )
@@ -1583,9 +1642,9 @@ Class Translator_CPP Extends Translator
 	End
 	
 	Method ArrayName:String( type:ArrayType )
-		Refs( type )
-		If type.rank=1 Return "bbArray<"+ElementType( type.elemType )+">"
-		Return "bbArray<"+ElementType( type.elemType )+","+type.rank+">"
+'		Refs( type )
+		If type.rank=1 Return "bbArray<"+HeapVarType( type.elemType )+">"
+		Return "bbArray<"+HeapVarType( type.elemType )+","+type.rank+">"
 	End
 	
 End