فهرست منبع

Several compiler fixes...

* Compiler should detect attempts to create new abstract classes now.

* Fixed Self.new() and Super.New() issues.

* You can now overload class methods via extensions.

* Jagged arrays fix - array types now go backwards.
Mark Sibly 9 سال پیش
والد
کامیت
f5f65a1705

+ 9 - 2
modules/monkey/native/bbgc.cpp

@@ -55,6 +55,8 @@ namespace bbGC{
 	
 	bbGCFiber *fibers;
 	bbGCFiber *currentFiber;
+	
+	bbGCTmp *freeTmps;
 
 	bbGCNode markLists[2];
 	bbGCNode freeList;
@@ -135,7 +137,7 @@ namespace bbGC{
 		}
 	}
 	
-	void markFrames(){
+	void markFibers(){
 	
 		bbGCFiber *fiber=fibers;
 		
@@ -151,6 +153,11 @@ namespace bbGC{
 				node->gcMark();
 			}
 			
+			for( bbGCTmp *tmp=fiber->tmps;tmp;tmp=tmp->succ ){
+			
+				tmp->node->gcMark();
+			}
+			
 			fiber=fiber->succ;
 			if( fiber==fibers ) break; 
 		}
@@ -177,7 +184,7 @@ namespace bbGC{
 	
 //		puts( "bbGC::sweep()" );fflush( stdout );
 	
-		markFrames();
+		markFibers();
 	
 		markQueued();
 		

+ 35 - 2
modules/monkey/native/bbgc.h

@@ -39,11 +39,14 @@ struct bbGCNode;
 struct bbGCFiber;
 struct bbGCFrame;
 struct bbGCRoot;
+struct bbGCTmp;
 
 namespace bbGC{
 
 	extern bbGCRoot *roots;
 	
+	extern bbGCTmp *freeTmps;
+
 	extern bbGCNode *markQueue;
 	extern bbGCNode *unmarkedList;
 	
@@ -88,8 +91,9 @@ struct bbGCFiber{
 	bbGCFiber *pred;
 	bbGCFrame *frames;
 	bbGCNode *ctoring;
+	bbGCTmp *tmps;
 	
-	bbGCFiber():succ( this ),pred( this ),frames( nullptr ),ctoring( nullptr ){
+	bbGCFiber():succ( this ),pred( this ),frames( nullptr ),ctoring( nullptr ),tmps( nullptr ){
 	}
 	
 	void link(){
@@ -131,6 +135,11 @@ struct bbGCRoot{
 	}
 };
 
+struct bbGCTmp{
+	bbGCTmp *succ;
+	bbGCNode *node;
+};
+
 namespace bbGC{
 	
 	inline void insert( bbGCNode *p,bbGCNode *succ ){
@@ -157,6 +166,30 @@ namespace bbGC{
 		p->flags=markedBit;
 	}
 	
+	inline void pushTmp( bbGCNode *p ){
+		bbGCTmp *tmp=freeTmps;
+		if( !tmp ) tmp=new bbGCTmp;
+		tmp->node=p;
+		tmp->succ=currentFiber->tmps;
+		currentFiber->tmps=tmp;
+//		puts( "pushTmp" );
+	}
+	
+	inline void popTmps( int n ){
+//		printf( "popTmps %i\n",n );
+		while( n-- ){
+			bbGCTmp *tmp=currentFiber->tmps;
+			currentFiber->tmps=tmp->succ;
+			tmp->succ=freeTmps;
+			freeTmps=tmp;
+		}
+	}
+	
+	template<class T> T *tmp( T *p ){
+		pushTmp( p );
+		return p;
+	}
+	
 	inline void beginCtor( bbGCNode *p ){
 		p->succ=currentFiber->ctoring;
 		currentFiber->ctoring=p;
@@ -259,7 +292,7 @@ template<class T> struct bbGCRootVar : public bbGCVar<T>,public bbGCRoot{
 	}
 };
 
-template<class T> void bbGCMark( const T &t  ){}
+template<class T> void bbGCMark( const T &t ){}
 
 template<class T> void bbGCMark( const bbGCVar<T> &v ){
 	bbGC::enqueue( dynamic_cast<bbGCNode*>( v._ptr ) );

+ 72 - 88
src/mx2cc/class.monkey2

@@ -41,8 +41,6 @@ Class ClassType Extends Type
 	Field ifaceTypes:ClassType[]
 	Field allIfaces:ClassType[]
 	
-	Field isvoid:Bool	'Extends 'Void'?
-	
 	Field instances:Stack<ClassType>
 	
 	Field membersSemanted:Bool
@@ -53,6 +51,9 @@ Class ClassType Extends Type
 	Field ctors:=New Stack<FuncValue>
 	Field methods:=New Stack<FuncValue>
 	Field fields:=New Stack<VarValue>
+
+	Field extendsVoid:Bool
+	Field hasDefaultCtor:Bool
 	
 	Method New( cdecl:ClassDecl,outer:Scope,types:Type[],instanceOf:ClassType )
 	
@@ -99,21 +100,17 @@ Class ClassType Extends Type
 		Return cdecl.kind="struct"
 	End
 	
-	Property IsAbstract:Bool()
-		Return cdecl.IsAbstract Or abstractMethods
-	End
-	
 	Property IsVirtual:Bool()
 		Return cdecl.IsVirtual Or (superType And superType.IsVirtual)
 	End
 	
-	Property IsVoid:Bool()
-		Return isvoid Or (superType And superType.IsVoid)
+	Property ExtendsVoid:Bool()
+		Return extendsVoid
 	End
-	
+
 	Method ToString:String() Override
-		Local str:=cdecl.ident
-		If types str+="<"+Join( types )+">"
+		Local str:=Name
+		If cdecl.IsExtension str+=" Extension"
 		Return str
 	End
 	
@@ -125,6 +122,14 @@ Class ClassType Extends Type
 		Return scope.TypeId
 	End
 	
+	Property IsAbstract:Bool()
+		If Not membersSemanted
+			If membersSemanting SemantError( "ClassType.IsAbstract()" )
+			SemantMembers()
+		Endif
+		Return cdecl.IsAbstract Or abstractMethods
+	End
+	
 	Method OnSemant:SNode() Override
 	
 		If cdecl.superType
@@ -136,7 +141,7 @@ Class ClassType Extends Type
 				
 					If Not cdecl.IsExtern Or cdecl.kind<>"class" Throw New SemantEx( "Only extern classes can extend 'Void'" )
 					
-					isvoid=True
+					extendsVoid=True
 					
 				Else
 				
@@ -148,6 +153,8 @@ Class ClassType Extends Type
 					
 					If superType.cdecl.IsFinal Throw New SemantEx( "Superclass '"+superType.ToString()+"' is final" )
 					
+					extendsVoid=superType.extendsVoid
+					
 				Endif
 				
 			Catch ex:SemantEx
@@ -226,9 +233,10 @@ Class ClassType Extends Type
 	
 	Method SemantMembers()
 	
-'		Print "Semanting members: "+ToString()
+		If membersSemanted Return
 	
-		If membersSemanted Or membersSemanting Return
+		If membersSemanting SemantError( "ClassType.SemantMembers()" )
+		
 		membersSemanting=True
 		
 		'Semant funcs
@@ -249,13 +257,33 @@ Class ClassType Extends Type
 			flists.Push( flist )
 			
 			For Local func:=Eachin flist.funcs
-			
-				If func.fdecl.IsIfaceMember abstractMethods.Push( func )
-				
+
+				If func.fdecl.IsAbstract abstractMethods.Push( func )
+							
 			Next
-			
+
 		Next
 		
+		'default ctor check
+		'
+		Local flist:=Cast<FuncList>( scope.GetNode( "new" ) )
+		If flist
+			hasDefaultCtor=False
+			For Local func:=Eachin flist.funcs
+				If func.ftype.argTypes Continue
+				hasDefaultCtor=True
+			Next
+		Else
+			If superType And Not superType.hasDefaultCtor
+				Try
+					Throw New SemantEx( "Super class '"+superType.Name+"' has no default constructor" )
+				Catch ex:SemantEx
+				End
+			Endif
+			
+			hasDefaultCtor=True
+		Endif
+		
 		If (cdecl.kind="class" Or cdecl.kind="struct") And Not scope.IsGeneric
 		
 			'Enum unimplemented superclass abstract methods
@@ -264,21 +292,10 @@ Class ClassType Extends Type
 			
 				For Local func:=Eachin superType.abstractMethods
 				
-					Try
-						Local flist:=Cast<FuncList>( scope.nodes[func.fdecl.ident] )
-						If flist
-							Local func2:=flist.FindFunc( func.ftype.argTypes )
-							If func2
-								If func2.ftype.retType.ExtendsType( func.ftype.retType ) Continue
-								Throw New SemantEx( "Overriding method '"+func2.ToString()+"' has incompatible return type",func2.fdecl )
-							Endif
-						Endif
-						
-						abstractMethods.Push( func )
-						
-					Catch ex:SemantEx
-					End
+					Local flist:=Cast<FuncList>( scope.nodes[func.fdecl.ident] )
+					If flist And flist.FindFunc( func.ftype ) Continue
 					
+					abstractMethods.Push( func )
 				Next
 
 			Endif
@@ -290,52 +307,17 @@ Class ClassType Extends Type
 				If superType And superType.ExtendsType( iface ) Continue
 				
 				For Local func:=Eachin iface.abstractMethods
-				
-'					Print "abstractMethod="+func.ToString()
-
-					Try
-						#rem
-						Local flist:=Cast<FuncList>( scope.nodes[func.fdecl.ident] )
-						If flist
-							Local func2:=overload.FindOverload( flist.funcs,func.ftype.retType,func.ftype.argTypes )
-							If func2
-								If func2.IsGeneric Continue
-								If TypesEqual( func2.ftype.argTypes,func.ftype.argTypes ) Continue
-								Throw New SemantEx( "ERROR!",func2.fdecl )
-							Endif
-						Endif
-						
-						If func.fdecl.IsDefault
-							scope.Insert( func.fdecl.ident,func )
-							Continue
-						Endif
-						
-						abstractMethods.Push( func )
-						#end
-						
-						Local flist:=Cast<FuncList>( scope.nodes[func.fdecl.ident] )
-						If flist
-							Local func2:=flist.FindFunc( func.ftype.argTypes )
-							If func2
-								If func2.ftype.retType.ExtendsType( func.ftype.retType ) Continue
-								Throw New SemantEx( "Overriding method '"+func2.ToString()+"' has incompatible return type",func2.fdecl )
-							Endif
-						Endif
-						
-						If func.fdecl.IsDefault
-							scope.Insert( func.fdecl.ident,func )
-							Continue
-						Endif
-						
-						abstractMethods.Push( func )
-					
-					Catch ex:SemantEx
-					End
 
+					Local flist:=Cast<FuncList>( scope.nodes[func.fdecl.ident] )
+					If flist And flist.FindFunc( func.ftype ) Continue
+					
+					abstractMethods.Push( func )
 				Next
 			
 			Next
 			
+			'Add super class overloads to our scope.
+			'
 			If superType
 			
 				For Local flist:=Eachin flists
@@ -344,7 +326,9 @@ Class ClassType Extends Type
 					If Not flist2 Continue
 						
 					For Local func2:=Eachin flist2.funcs
-						If Not flist.FindFunc( func2.ftype.argTypes ) flist.PushFunc( func2 )
+						If Not flist.FindFunc( func2.ftype )
+							flist.PushFunc( func2 )
+						Endif
 					Next
 	
 				Next
@@ -359,16 +343,15 @@ Class ClassType Extends Type
 		'
 		membersSemanting=False
 		membersSemanted=True
-
-		'Semant vars - should probably do this in another phase?
-		'		
-		For Local it:=Eachin scope.nodes
 		
+		'Semant non-func members
+		'
+		For Local node:=Eachin scope.nodes.Values
+			If Cast<FuncList>( node ) Continue
 			Try
-				If Not Cast<FuncList>( it.Value ) it.Value.Semant()
+				node.Semant()
 			Catch ex:SemantEx
 			End
-			
 		Next
 	
 	End
@@ -384,15 +367,15 @@ Class ClassType Extends Type
 		
 		Return Null
 	End
-	
-	Method FindSuperFunc:FuncValue( ident:String,argTypes:Type[] )
+
+	Method FindSuperFunc:FuncValue( ident:String,ftype:FuncType )
 	
 		Local node:=Cast<FuncList>( FindSuperNode( ident ) )
-		If node Return node.FindFunc( argTypes )
+		If node Return node.FindFunc( ftype )
 		
 		Return Null
 	End
-	
+
 	Method FindNode2:SNode( ident:String )
 		If membersSemanting SemantError( "ClassType.FindNode() class='"+ToString()+"', ident='"+ident+"'" )
 	
@@ -417,17 +400,18 @@ Class ClassType Extends Type
 	Method FindNode:SNode( ident:String ) Override
 	
 		Local node:=FindNode2( ident )
-		If node Return node
+		If ident="new" Return node
+		
+		node=FileScope.FindExtensions( ident,Self,node )
 		
-		Return FileScope.FindExtension( ident,False,Self )
+		Return node
 	End
 		
 	Method FindType:Type( ident:String ) Override
 	
 		Local type:=FindType2( ident )
-		If type Return type
 		
-		Return Cast<Type>( FileScope.FindExtension( ident,True,Self ) )
+		Return type
 	End
 	
 	Method Index:Value( args:Value[],value:Value ) Override

+ 1 - 1
src/mx2cc/docs/docsmaker.monkey2

@@ -861,7 +861,7 @@ Class DocsMaker
 				If ctype.superType<>Type.ObjectClass
 					xtends=" Extends "+TypeName( ctype.superType,ctype.scope.outer )
 				Endif
-			Else If ctype.isvoid
+			Else If ctype.extendsVoid
 				xtends=" Extends Void"
 			Endif
 			

+ 16 - 11
src/mx2cc/expr.monkey2

@@ -85,14 +85,21 @@ Class Expr Extends PNode
 			semanting.Push( Self )
 
 			Local type:=OnSemantType( scope )
-			
+
 			Local ctype:=TCast<ClassType>( type )
-			If ctype
-				If generic
-'					If Not ctype.types Or ctype.instanceOf Throw New SemantEx( "Type '"+ctype.ToString()+"' is not generic" )
-				Else
-					If ctype.types And Not ctype.instanceOf Throw New SemantEx( "Type '"+ctype.ToString()+"' is generic" )
+			
+			If generic
+				
+				If Not ctype Or Not ctype.types 'Or ctype.instanceOf
+					Throw New SemantEx( "Type '"+type.Name+"' must be a generic class type" )
+				Endif
+			
+			Else
+			
+				If ctype And ctype.types And Not ctype.instanceOf
+					Throw New SemantEx( "Generic class type '"+ctype.Name+"' is missing type arguments" )
 				Endif
+
 			Endif
 			
 			semanting.Pop()
@@ -106,7 +113,7 @@ Class Expr Extends PNode
 		
 		Return Null
 	End
-
+	
 	Method SemantWhere:Bool( scope:Scope )
 
 		Try
@@ -309,12 +316,10 @@ Class NewObjectExpr Extends Expr
 		Local type:=Self.type.SemantType( scope )
 		
 		Local ctype:=TCast<ClassType>( type )
-		If Not ctype Throw New SemantEx( "Type '"+type.Name+"' is not a class" )
+		If Not ctype Throw New SemantEx( "Type '"+type.Name+"' is not a class type" )
 		
 		'hmmm...
-		'ctype.SemantMembers()
-		
-		If ctype.IsGeneric Throw New SemantEx( "Class '"+ctype.Name+"' is generic" )
+'		ctype.SemantMembers()
 		
 		If ctype.IsAbstract
 			Local t:=""

+ 40 - 42
src/mx2cc/filescope.monkey2

@@ -11,8 +11,6 @@ Class FileScope Extends Scope
 	
 	Field toSemant:=New Stack<SNode>
 
-'	Field classexts:=New Stack<ClassType>
-	
 	Method New( fdecl:FileDecl )
 		Super.New( Null )
 		
@@ -108,69 +106,69 @@ Class FileScope Extends Scope
 		
 	End
 	
-	Method FindInUsings:SNode( ident:String,istype:Bool )
-
-		Local finder:=New NodeFinder( ident,istype )
-		
-		For Local nmspace:=Eachin usings
-			finder.Find( nmspace )
-		Next
-		
-		Return finder.Found
-	End
-	
 	Method FindNode:SNode( ident:String ) Override
 	
+		'Search in namespace hierarchy
+		'
 		Local node:=Super.FindNode( ident )
 		If node Return node
 		
-		Return FindInUsings( ident,False )
+		'Search in usings
+		'
+		Local finder:=New NodeFinder( ident )
+		
+		For Local nmspace:=Eachin usings
+			finder.Add( nmspace.GetNode( ident ) )
+		Next
+		
+		Return finder.Found
 	End
 	
 	Method FindType:Type( ident:String ) Override
 	
+		'Search in namespace hierarchy
+		'
 		Local type:=Super.FindType( ident )
 		If type Return type
 		
-		Return Cast<Type>( FindInUsings( ident,True ) )
+		'Search in usings
+		'
+		Local finder:=New NodeFinder( ident )
+
+		For Local nmspace:=Eachin usings
+			finder.Add( nmspace.GetType( ident ) )
+		Next
+
+		Return Cast<Type>( finder.Found )
 	End
 	
-	Function FindExtension( finder:NodeFinder,nmspace:NamespaceScope,ctype:ClassType )
+	Method FindExtensions:SNode( finder:NodeFinder,ctype:ClassType )
 
-		Local exts:=nmspace.FindClassExtensions( ctype )
-		If Not exts Return
-			
-		For Local ext:=Eachin exts
-			finder.Find( ext.scope )
+		'Search nmspace hierarchy
+		'		
+		nmspace.FindExtensions( finder,ctype )
+		
+		'Search usings
+		'
+		For Local nmspace:=Eachin usings
+			nmspace.GetExtensions( finder,ctype )
 		Next
+		
+		Return finder.Found
 	End
 	
-	Function FindExtension:SNode( ident:String,istype:Bool,ctype:ClassType )
+	Function FindExtensions:SNode( ident:String,ctype:ClassType,found:SNode )
 	
 		Local scope:=Scope.Semanting()
-		If Not scope Return Null
+		If Not scope Return found
 		
 		Local fscope:=scope.FindFile()
-		If Not fscope Return Null
-		
-		Local finder:=New NodeFinder( ident,istype )
-		
-		'search hierarchy
-		Local nmspace:=fscope.nmspace
-		While nmspace
-			FindExtension( finder,nmspace,ctype )
-'			If finder.Found Return finder.Found
-			nmspace=Cast<NamespaceScope>( nmspace.outer )
-		Wend
-		If finder.Found Return finder.Found
-
-		'search usings
-		For Local nmspace:=Eachin fscope.usings
-			FindExtension( finder,nmspace,ctype )
-		Next
-		If finder.Found Return finder.Found
+		If Not fscope Return found
+		
+		Local finder:=New NodeFinder( ident )
+		finder.Add( found )
 		
-		Return Null
+		Return fscope.FindExtensions( finder,ctype )
 	End
 
 	Method FindFile:FileScope() Override

+ 30 - 33
src/mx2cc/func.monkey2

@@ -114,7 +114,7 @@ Class FuncValue Extends Value
 	Property IsGeneric:Bool()
 		If Not ftype SemantError( "FuncValue.IsGeneric()" )
 		
-		Return ftype.IsGeneric Or (types And Not instanceOf)	
+		Return ftype.IsGeneric 'Or (types And Not instanceOf)
 	End
 	
 	Property IsCtor:Bool()
@@ -236,12 +236,10 @@ Class FuncValue Extends Value
 				Case "=","<>","<",">","<=",">="
 					If ftype.retType<>Type.BoolType Throw New SemantEx( "Comparison operator '"+op+"' must return Bool" )
 					If ftype.argTypes.Length<>1 Throw New SemantEx( "Comparison operator '"+op+"' must have 1 parameter" )
-'					If Not ftype.argTypes[0].Equals( ctype ) Throw New SemantEx( "Comparison operator '"+op+"' parameter must be of type '"+ctype.ToString()+"'" )
 				Case "<=>"
 					Local ptype:=TCast<PrimType>( ftype.retType )
 					If Not ptype Or Not ptype.IsNumeric Throw New SemantEx( "Comparison operator '<=>' must return a numeric type" )
 					If ftype.argTypes.Length<>1 Throw New SemantEx( "Comparison operator '"+op+"' must have 1 parameter" )
-'					If Not ftype.argTypes[0].Equals( ctype ) Throw New SemantEx( "Comparison operator '"+op+"' parameter must be of type '"+ctype.ToString()+"'" )
 				End
 			Endif
 			
@@ -249,7 +247,7 @@ Class FuncValue Extends Value
 				Throw New SemantEx( "Virtual class methods cannot be declared 'Virtual' or 'Override'" )
 			Endif
 			
-			Local func2:=ctype.FindSuperFunc( fdecl.ident,ftype.argTypes )
+			Local func2:=ctype.FindSuperFunc( fdecl.ident,ftype )
 			
 			If func2
 			
@@ -265,7 +263,7 @@ Class FuncValue Extends Value
 					 Throw New SemantEx( "Method '"+ToString()+"' overrides a non-virtual superclass method" )
 				Endif
 					
-				If Not ftype.retType.ExtendsType( func2.ftype.retType ) 
+				If Not ftype.retType.ExtendsType( func2.ftype.retType )
 					Throw New SemantEx( "Method '"+ToString()+"' overrides a method with incompatible return type" )
 				Endif
 				
@@ -412,22 +410,6 @@ Class FuncValue Extends Value
 		
 	End
 	
-	Method SemantInvokeNew()
-	
-		If fdecl.ident<>"new" Or invokeNew Return
-
-		Local superType:=scope.FindClass().superType
-		If Not superType Return
-
-		Local flist:=Cast<FuncList>( superType.FindNode( "new" ) )
-		If Not flist Return
-		
-		Local func:=flist.FindFunc( Null )
-		If func Return
-
-		Throw New SemantEx( "Class '"+superType.ToString()+"' has no default constructor",pnode )
-	End
-	
 	Method SemantStmts()
 	
 		If block.IsGeneric SemantError( "FuncValue.SemantStmts(1)" )
@@ -444,10 +426,22 @@ Class FuncValue Extends Value
 			
 			block.Semant( fdecl.stmts )
 			
+			If fdecl.ident="new" And Not invokeNew
+			
+				Local superType:=cscope.ctype.superType
+				If superType And Not superType.hasDefaultCtor
+				
+					Try
+						Throw New SemantEx( "Super class '"+superType.Name+"' has no default constructor",pnode )
+					Catch ex:SemantEx
+					End
+					
+				Endif
+			
+			Endif
+			
 			If block.reachable And ftype.retType<>Type.VoidType Throw New SemantEx( "Missing return statement" )
 
-			SemantInvokeNew()
-
 		Endif
 		
 		If fdecl.kind="function" Or IsExtension
@@ -469,11 +463,11 @@ Class FuncValue Extends Value
 		
 			If IsCtor Or IsMethod
 			
-'				If fdecl.ident="new"
-'					cscope.ctype.ctors.Push( Self )
-'				Else
+				If fdecl.ident="new"
+					cscope.ctype.ctors.Push( Self )
+				Else
 					cscope.ctype.methods.Push( Self )
-'				Endif
+				Endif
 			Endif
 		
 			scope.transMembers.Push( Self )
@@ -694,13 +688,16 @@ Class FuncList Extends SNode
 		funcs.Push( func )
 	End
 	
-	Method FindFunc:FuncValue( argTypes:Type[] )
-	
-		If AnyTypeGeneric( argTypes ) SemantError( "FuncList.FindFunc()" )
-	
+	Method FindFunc:FuncValue( ftype:FuncType )
+
+		If AnyTypeGeneric( ftype.argTypes ) SemantError( "FuncList.FindFunc()" )
+		
 		For Local func:=Eachin funcs
 			If func.block.IsGeneric Continue
-			If TypesEqual( func.ftype.argTypes,argTypes ) Return func
+			If Not TypesEqual( func.ftype.argTypes,ftype.argTypes ) Continue
+			If ident<>"to" Return func
+			If func.ftype.retType.Equals( ftype.retType ) Return func
+			Return Null
 		Next
 		
 		Return Null
@@ -721,7 +718,7 @@ Class FuncList Extends SNode
 				If Not func Continue
 				
 				If ident<>"to" And Not func.block.IsGeneric
-					Local func2:=FindFunc( func.ftype.argTypes )
+					Local func2:=FindFunc( func.ftype )'.argTypes )
 					If func2 Throw New SemantEx( "Duplicate declaration '"+func.ToString()+"'",tfunc.pnode )
 				Endif
 				

+ 2 - 0
src/mx2cc/mung.monkey2

@@ -227,6 +227,8 @@ Function FuncName:String( func:FuncValue )
 
 		Local sym:="m_"+MungIdent( fdecl.ident )
 		
+		If fdecl.ident="to" sym+="_"+MungArg( func.ftype.retType )
+
 '		hopefully not necessary!		
 		If func.types sym+=MungArgs( func.types )
 

+ 2 - 2
src/mx2cc/mx2cc.monkey2

@@ -23,9 +23,10 @@ Global StartDir:String
 
 Const TestArgs:="mx2cc makemods"
 
-'Const TestArgs:="mx2cc makeapp -clean -config=debug -target=desktop -product=D:/test_app/test.exe -assets=D:/test_app/assets -dlls=D:/test_app/ src/mx2cc/test.monkey2"
 'Const TestArgs:="mx2cc makeapp -clean -config=debug -target=desktop src/mx2cc/test.monkey2"
 
+'Const TestArgs:="mx2cc makeapp -clean -config=debug -target=desktop -product=D:/test_app/test.exe -assets=D:/test_app/assets -dlls=D:/test_app/ src/mx2cc/test.monkey2"
+
 'Const TestArgs:="mx2cc makeapp -clean src/ted2/ted2"
 
 'Const TestArgs:="mx2cc makemods -clean -config=release monkey libc miniz stb-image hoedown std"
@@ -87,7 +88,6 @@ Function Main()
 	Catch ex:BuildEx
 	
 		Fail( "Internal mx2cc build error" )
-		
 	End
 	
 	If Not ok libc.exit_( 1 )

+ 36 - 7
src/mx2cc/namespace.monkey2

@@ -91,21 +91,26 @@ Class NamespaceScope Extends Scope
 		Return Self
 	End
 	
-	Method FindClassExtensions:Stack<ClassType>( ctype:ClassType )
+	Method GetClassExtensions:Stack<ClassType>( ctype:ClassType )
 	
 		Local exts:Stack<ClassType>
 		
 		For Local ext:=Eachin classexts
 		
 			If ext.IsGeneric
-				If ctype.instanceOf
-					If ext.superType.instanceOf.ExtendsType( ctype.instanceOf )
-						ext=TCast<ClassType>( ext.GenInstance( ctype.types ) )
+				continue
+				Local etype:=ctype
+				While etype
+					If etype.instanceOf And etype.instanceOf.Equals( ext.superType.instanceOf )
+						ext=TCast<ClassType>( ext.GenInstance( etype.types ) )
+						Exit
 					Endif
-				Endif
+					etype=etype.superType
+				Wend
+				If Not etype Continue
+			Else
+				If Not ctype.ExtendsType( ext.superType ) Continue
 			Endif
-
-			If Not ext.superType.ExtendsType( ctype ) Continue
 			
 			If Not exts exts=New Stack<ClassType>
 			exts.Push( ext )
@@ -113,5 +118,29 @@ Class NamespaceScope Extends Scope
 		
 		Return exts
 	End
+	
+	Method GetExtensions( finder:NodeFinder,ctype:ClassType )
+	
+		Local exts:=GetClassExtensions( ctype )
+		If Not exts Return
+
+		For Local ext:=Eachin exts
+			finder.Add( ext.scope.GetNode( finder.ident ) )
+		Next
+
+	End
+	
+	Method FindExtensions( finder:NodeFinder,ctype:ClassType )
+	
+		Local nmspace:=Self
+		
+		While nmspace
+		
+			nmspace.GetExtensions( finder,ctype )
+			
+			nmspace=Cast<NamespaceScope>( nmspace.outer )
+		Wend
+		
+	End
 
 End

+ 22 - 27
src/mx2cc/nodefinder.monkey2

@@ -4,70 +4,65 @@ Namespace mx2
 Class NodeFinder
 
 	Field ident:String
-	Field findType:Bool
 	Field node:SNode
 	Field flist:FuncList
 	
-	Method New( ident:String,findType:Bool )
+	Method New( ident:String )
 		Self.ident=ident
-		Self.findType=findType
 	End
 	
 	Property Found:SNode()
 		Return node
 	End
 	
-	Method Find( scope:Scope )
-		If findType 
-			Add( scope.GetType( ident ) )
-		Else
-			Add( scope.GetNode( ident ) )
-		Endif
-	End
-	
 	Method Add( node:SNode )
-	
+		
 		If Not node Return
-	
+		
 		If Not Self.node
 			Self.node=node
 			Return
 		Endif
-		
+			
 		Local flist:=Cast<FuncList>( node )
-		
+			
 		If Self.flist
-		
-			If Not flist Throw New SemantEx( "Duplicate identifier '"+ident+"'" )
 			
+			If Not flist Throw New SemantEx( "Duplicate identifier '"+ident+"'" )
+				
 			AddFuncs( flist,Self.flist )
-			
+				
 		Else If flist
-		
+			
 			Local src:=Cast<FuncList>( Self.node )
 			If Not src Throw New SemantEx( "Duplicate identifier '"+ident+"'" )
-			
+				
 			Local dst:=New FuncList( ident,Null )
-			
+				
 			AddFuncs( src,dst )
 			AddFuncs( flist,dst )
-			
+				
 			Self.flist=dst
 			Self.node=dst
-			
+				
 		Else
-
+	
 			Throw New SemantEx( "Duplicate identifier '"+ident+"'" )
-		
+			
 		End
 	End
 
 	Method AddFuncs( src:FuncList,dst:FuncList )
 	
 		For Local func:=Eachin src.funcs
-			If dst.FindFunc( func.ftype.argTypes ) 
-				Throw New SemantEx( "Duplicate identifier '"+ident+"'" )
+		
+			Local func2:=dst.FindFunc( func.ftype )
+
+			If func2
+				If func2=func Continue	'bit of a hack for extensions...
+				Throw New SemantEx( "Multiple overloads found for '"+func.ToString()+"'" )
 			Endif
+			
 			dst.funcs.Push( func )
 		Next
 	End

+ 84 - 25
src/mx2cc/parser.monkey2

@@ -1249,13 +1249,26 @@ Class Parser
 		Repeat
 			Select Toke
 			Case "["
-				Bump()
-				Local rank:=1
-				While CParse( "," )
-					rank+=1
+			
+				'Arrays are backwards! Yikes!
+				Local head:ArrayTypeExpr
+				Local tail:=head
+			
+				While CParse( "[" )
+					Local rank:=1
+					While CParse( "," )
+						rank+=1
+					Wend
+					Parse( "]" )
+					
+					Local type:=New ArrayTypeExpr( Null,rank,srcpos,EndPos )
+					If tail tail.type=type Else head=type
+					tail=type
 				Wend
-				Parse( "]" )
-				type=New ArrayTypeExpr( type,rank,srcpos,EndPos )
+				
+				tail.type=type
+				type=head
+				
 			Case "("
 				type=ParseFuncType( type )
 			Default
@@ -1265,7 +1278,7 @@ Class Parser
 		
 		Return type
 	End
-
+	
 	'THROWS! Some ugly stunt parsing to handle operator New.
 	Method ParseNewType:Expr()
 	
@@ -1275,31 +1288,64 @@ Class Parser
 		Repeat
 			Select Toke
 			Case "["
-				BeginTryParse()
-				Bump()
-				Local rank:=1
-				While CParse( "," )
-					rank+=1
+			
+				'Array types are backwards!
+				'	
+				Local head:ArrayTypeExpr
+				Local tail:=head
+				Local done:=False
+					
+				While Toke="["
+
+					BeginTryParse()
+					Parse()
+					
+					Local rank:=1
+					While CParse( "," )
+						rank+=1
+					Wend
+					
+					If Not CParse( "]" )
+						TryParseFailed()
+						done=True
+						Exit
+					Endif
+					
+					EndTryParse()
+					
+					Local type:=New ArrayTypeExpr( Null,rank,srcpos,EndPos )
+					If tail tail.type=type Else head=type
+					tail=type
+					
 				Wend
-				If Not CParse( "]" )
-					TryParseFailed()
-					Exit
-				Endif
-				EndTryParse()
-				type=New ArrayTypeExpr( type,rank,srcpos,EndPos )
+				
+				If Not head Exit
+
+				tail.type=type
+				type=head
+				
+				If done Exit
+				
 			Case "("
+			
 				BeginTryParse()
+				
 				Try
 					Local ftype:=ParseFuncType( type )
+					
 					If Toke<>"[" And Toke<>"("
 						TryParseFailed()
-						Return type
+						Exit
 					Endif
+					
 					EndTryParse()
 					type=ftype
+					
 				Catch ex:TryParseEx
+				
 					TryParseFailed()
 					Exit
+					
 				End
 			Default
 				Exit
@@ -1320,11 +1366,6 @@ Class Parser
 			Local expr:=ParseExpr()
 			Parse( ")" )
 			Return expr
-'		Case "["
-'			Bump()
-'			Local exprs:=ParseExprs()
-'			Parse( "]" )
-'			Return New ArrayLiteralExpr( exprs,srcpos,EndPos )
 		Case "self"
 			Bump()
 			Return New SelfExpr( srcpos,EndPos )
@@ -1342,7 +1383,25 @@ Class Parser
 			If CParse( "[" )
 				Local sizes:=ParseExprs()
 				Parse( "]" )
-				Return New NewArrayExpr( New ArrayTypeExpr( type,sizes.Length,srcpos,EndPos ),sizes,Null,srcpos,EndPos )
+				
+				Local head:=New ArrayTypeExpr( Null,sizes.Length,srcpos,EndPos )
+				Local tail:=head
+				
+				While CParse( "[" )
+					Local rank:=1
+					While CParse( "," )
+						rank+=1
+					Wend
+					Parse( "]" )
+					
+					Local type:=New ArrayTypeExpr( Null,rank,srcpos,EndPos )
+					tail.type=type
+					tail=type
+				Wend
+				
+				tail.type=type
+				
+				Return New NewArrayExpr( head,sizes,Null,srcpos,EndPos )
 			Endif
 			
 			If Toke="("

+ 12 - 10
src/mx2cc/test.monkey2

@@ -1,15 +1,17 @@
 
-#if __DESKTOP_TARGET__
+Class List<T>
 
-#else
-
-#if __TARGET__="emscripten"
-
-#endif
-
-KNOB!
-
-#endif
+	Struct Node
+		Field data:T
+	End
+	
+	Field head:=New Node
+End
 
 Function Main()
+
+	Local list:=New List<Int>
+	
+	list.head.data=10
+	
 End

+ 2 - 2
src/mx2cc/translator.monkey2

@@ -14,7 +14,7 @@ Function IsGCType:Bool( type:Type )
 	Local ctype:=TCast<ClassType>( type )
 	If Not ctype Return False
 	
-	If ctype.IsVoid Return False
+	If ctype.ExtendsVoid Return False
 	
 	If ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface" Return True
 	
@@ -32,7 +32,7 @@ End
 Function IsGCPtrType:Bool( type:Type )
 
 	Local ctype:=TCast<ClassType>( type )
-	If ctype Return Not ctype.IsVoid And Not ctype.IsStruct
+	If ctype Return Not ctype.ExtendsVoid And Not ctype.IsStruct
 	
 	Local atype:=TCast<ArrayType>( type )
 	If atype Return True

+ 22 - 42
src/mx2cc/translator_cpp.monkey2

@@ -5,6 +5,8 @@ Class Translator_CPP Extends Translator
 
 	Field _lambdaId:Int
 	
+	Field _gctmps:=0
+	
 	Method Translate( fdecl:FileDecl ) 'Override
 	
 		_incs[fdecl.ident]=fdecl
@@ -128,7 +130,7 @@ Class Translator_CPP Extends Translator
 	Method GCVarTypeName:String( type:Type )
 	
 		Local ctype:=TCast<ClassType>( type )
-		If ctype And Not ctype.IsVoid And (ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface") Return ClassName( ctype )
+		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 )
@@ -176,32 +178,6 @@ Class Translator_CPP Extends Translator
 		
 		TransError( "Translator.VarType (2)" )
 		Return ""
-#rem	
-		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 Not ctype.IsVoid And (ctype.cdecl.kind="class" Or ctype.cdecl.kind="interface")
-			Return gc+ClassName( ctype )+">"
-		Endif
-		
-		Local atype:=TCast<ArrayType>( type )
-		If atype
-			Return gc+ArrayName( atype )+">"
-		Endif
-		
-		Return TransType( type )
-#end
-
 	End
 
 	Method VarProto:String( vvar:VarValue ) Override
@@ -435,9 +411,7 @@ Class Translator_CPP Extends Translator
 		Local hasDefaultCtor:=False
 		
 		EmitBr()
-		For Local node:=Eachin ctype.methods
-			Local func:=Cast<FuncValue>( node )
-			If Not func Or func.fdecl.ident<>"new" Continue
+		For Local func:=Eachin ctype.ctors
 			
 			hasCtor=True
 			If Not func.ftype.argTypes hasDefaultCtor=True
@@ -451,9 +425,7 @@ Class Translator_CPP Extends Translator
 		Local hasCmp:=False
 		
 		EmitBr()
-		For Local node:=Eachin ctype.methods
-			Local func:=Cast<FuncValue>( node )
-			If Not func Or func.fdecl.ident="new" Continue
+		For Local func:=Eachin ctype.methods
 			
 			If func.fdecl.ident="<=>" hasCmp=True
 			
@@ -606,9 +578,7 @@ Class Translator_CPP Extends Translator
 	
 		'Emit ctor methods
 		'
-		For Local node:=Eachin ctype.methods
-			Local func:=Cast<FuncValue>( node )
-			If Not func Or func.fdecl.ident<>"new" Continue
+		For Local func:=Eachin ctype.ctors
 			
 			EmitBr()
 			EmitFunc( func,needsInit )
@@ -618,9 +588,7 @@ Class Translator_CPP Extends Translator
 		'
 		Local hasCmp:=False
 		
-		For Local node:=Eachin ctype.methods
-			Local func:=Cast<FuncValue>( node )
-			If Not func Or func.fdecl.ident="new" Continue
+		For Local func:=Eachin ctype.methods
 			
 			If func.fdecl.ident="<=>" 
 				hasCmp=True
@@ -640,7 +608,7 @@ Class Translator_CPP Extends Translator
 			
 			Emit( "bbString bbDBValue("+tname+"*p){" )
 			
-			If ctype.IsVoid
+			If ctype.ExtendsVoid
 				Emit( "return bbDBValue(*p);" )
 			Else
 				Select cdecl.kind
@@ -720,6 +688,11 @@ Class Translator_CPP Extends Translator
 		
 		Emit( proto+"{" )
 		
+		If _gctmps
+			Emit( "bbGC::popTmps("+_gctmps+");" )
+			_gctmps=0
+		Endif
+		
 		If init Emit( "init();" )
 		
 		'is it 'main'?
@@ -1384,7 +1357,7 @@ Class Translator_CPP Extends Translator
 		Local ctype:=value.ctype
 		Uses( ctype )
 	
-		If ctype.IsVoid
+		If ctype.ExtendsVoid
 			Return "new "+ClassName( ctype )+"("+TransArgs( value.args )+")"
 		Endif
 		
@@ -1529,7 +1502,14 @@ Class Translator_CPP Extends Translator
 		
 			Local t:=Trans( arg )
 			
-			If IsVolatile( arg ) t=AllocGCTmp( arg.type )+"="+t
+			If IsVolatile( arg )
+				If _gcframe
+					t=AllocGCTmp( arg.type )+"="+t
+				Else
+					t="bbGC::tmp("+t+")"
+					_gctmps+=1
+				Endif
+			Endif
 			
 			If targs targs+=","
 			targs+=t