Browse Source

Added support for extension methods as function values.

Mark Sibly 7 years ago
parent
commit
56a9eeaa41
3 changed files with 91 additions and 7 deletions
  1. 42 0
      modules/monkey/native/bbfunction.h
  2. 26 3
      src/mx2cc/test.monkey2
  3. 23 4
      src/mx2cc/translator_cpp.monkey2

+ 42 - 0
modules/monkey/native/bbfunction.h

@@ -126,6 +126,36 @@ template<class R,class...A> struct bbFunction<R(A...)>{
 		
 	};
 	
+	template<class C> struct ExtMethodRep : public Rep{
+	
+		typedef R(*T)(C*,A...);
+		C *c;
+		T p;
+		
+		ExtMethodRep( C *c,T p ):c(c),p(p){
+		}
+		
+		virtual R invoke( A...a ){
+			return (*p)( c,a... );
+		}
+		
+		virtual bool equals( Rep *rhs ){
+			ExtMethodRep *t=dynamic_cast<ExtMethodRep*>( rhs );
+			return t && c==t->c && p==t->p;
+		}
+
+		virtual int compare( Rep *rhs ){
+			ExtMethodRep *t=dynamic_cast<ExtMethodRep*>( rhs );
+			if( t && c==t->c && p==t->p ) return 0;
+			return Rep::compare( rhs );
+		}
+		
+		virtual void gcMark(){
+			bbGCMark( c );
+		}
+		
+	};
+	
 	struct SequenceRep : public Rep{
 	
 		bbFunction lhs,rhs;
@@ -229,6 +259,10 @@ template<class R,class...A> struct bbFunction<R(A...)>{
 		retain();
 	}
 	
+	template<class C> bbFunction( C *c,typename ExtMethodRep<C>::T p ):_rep( new ExtMethodRep<C>(c,p) ){
+		retain();
+	}
+	
 	bbFunction( F p ):_rep( new FunctionRep( p ) ){
 		retain();
 	}
@@ -341,6 +375,14 @@ template<class C,class R,class...A> bbFunction<R(A...)> bbMethod( const bbGCVar<
 	return bbFunction<R(A...)>( c.get(),p );
 }
 
+template<class C,class R,class...A> bbFunction<R(A...)> bbExtMethod( C *c,R(*p)(C*,A...) ){
+	return bbFunction<R(A...)>( c,p );
+}
+
+template<class C,class R,class...A> bbFunction<R(A...)> bbExtMethod( const bbGCVar<C> &c,R(*p)(C*,A...) ){
+	return bbFunction<R(A...)>( c.get(),p );
+}
+
 template<class R,class...A> bbFunction<R(A...)> bbMakefunc( R(*p)(A...) ){
 	return bbFunction<R(A...)>( p );
 }

+ 26 - 3
src/mx2cc/test.monkey2

@@ -1,7 +1,30 @@
 
+Class C
+	
+	Field x:Int=10
+	
+	Method Test2:String()
+		Return "Test2 - x="+x
+	End
+End
+
+Class C Extension
+	
+	Method Test:String()
+		Return "x="+x
+	End
+End
+
+Function Call( f:String() )
+	
+	Print "f()="+f()
+End
+
+
 Function Main()
 	
-	Print "~q".Length
-	Print "~~q".Length
+	Local c:=New C
 	
-End
+	Call( c.Test2 )
+	Call( c.Test )
+End

+ 23 - 4
src/mx2cc/translator_cpp.monkey2

@@ -2148,12 +2148,31 @@ Class Translator_CPP Extends Translator
 
 		Local ctype:=value.member.cscope.ctype
 		
-		'Uses( ctype )
-		UsesType( ctype )
+		Local func:=value.member
+		
+		If func.fdecl.IsExtension
+			
+			ctype=ctype.superType
 
-		Local cname:=ClassName( ctype )
+			UsesType( ctype )
+			
+			Local cname:=ClassName( ctype )
+
+			Local args:="<"+cname+","+TransType( func.ftype.retType )
+			For Local ty:=Eachin func.ftype.argTypes
+				args+=","+TransType( ty )
+			Next
+			args+=">"
 		
-		Local func:=value.member
+'			Print "args="+args
+		
+			Return "bbExtMethod"+args+"(("+cname+"*)("+Trans( value.instance )+"),&"+Trans( value.member )+")"
+			
+		Endif
+
+		UsesType( ctype )
+		
+		Local cname:=ClassName( ctype )
 		
 		Local args:="<"+cname+","+TransType( func.ftype.retType )
 		For Local ty:=Eachin func.ftype.argTypes