Explorar o código

WORK IN PROGRESS updates for variants, reflection, makedocs.

Mark Sibly %!s(int64=9) %!d(string=hai) anos
pai
achega
1460d71942

+ 2 - 0
src/mx2cc/balance.monkey2

@@ -31,6 +31,8 @@ End
 
 Function BalancePrimTypes:Type( lhs:PrimType,rhs:PrimType )
 
+	If lhs=Type.VariantType Or rhs=Type.VariantType Return Type.VariantType
+
 	If lhs=Type.StringType Or rhs=Type.StringType Return Type.StringType
 	
 	If lhs=Type.BoolType Or rhs=Type.BoolType Return Type.BoolType

+ 17 - 20
src/mx2cc/builder.monkey2

@@ -33,6 +33,8 @@ Class BuildOpts
 	
 	Field wholeArchive:Bool
 	
+	Field reflection:Bool
+	
 End
 
 Class BuilderInstance
@@ -196,6 +198,7 @@ Class BuilderInstance
 			fdecl.module=module
 			fdecl.hfile=module.hfileDir+ident+".h"
 			fdecl.cfile=module.cfileDir+ident+".cpp"
+'			fdecl.rfile=module.cfileDir+"r_"+ident+".cpp"
 
 			module.fileDecls.Push( fdecl )
 
@@ -249,9 +252,11 @@ Class BuilderInstance
 		For Local i:=0 Until modules.Length
 		
 			Local module:=modules[modules.Length-i-1]
-
-			If module<>mainModule product.MOD_LIBS.Push( module.outputDir+module.name+".a" )
 			
+			If module<>mainModule 
+				product.imports.Push( module )
+				If module.name="reflection" opts.reflection=True
+			Endif
 		Next
 		
 	End
@@ -404,6 +409,7 @@ Class BuilderInstance
 					transFile.exhfile=transFile2.hfile
 					transFile.hfile=module.hfileDir+transFile.ident+".h"
 					transFile.cfile=module.cfileDir+transFile.ident+".cpp"
+'					transFile.rfile=module.cfileDir+"r_"+transFile.ident+".cpp"
 					
 					transFiles[transFile2.ident]=transFile
 					
@@ -437,21 +443,12 @@ Class BuilderInstance
 
 		If Not CreateDir( module.hfileDir ) Throw New BuildEx( "Failed to create dir:"+module.hfileDir )
 		If Not CreateDir( module.cfileDir ) Throw New BuildEx( "Failed to create dir:"+module.cfileDir )
-
-		For Local fdecl:=Eachin module.fileDecls
-		
-			If opts.verbose>0 Print "Translating "+fdecl.path
 		
-			Local translator:=New Translator_CPP
-			
-			Try
-				translator.Translate( fdecl )
-			Catch ex:TransEx
-			End
-			
-			product.SRC_FILES.Push( fdecl.cfile )
-		Next
+		Local translator:=New Translator_CPP
 		
+		translator.TranslateModule( module )
+
+		translator.TranslateTypeInfo( module )
 	End
 	
 	Method GetNamespace:NamespaceScope( path:String,mustExist:Bool=False )
@@ -662,20 +659,20 @@ Class BuilderInstance
 			Select ext
 			Case ".h"
 			
-				product.CC_OPTS.Push( "-I"+qdir )
-				product.CPP_OPTS.Push( "-I"+qdir )
+				product.CC_OPTS+=" -I"+qdir
+				product.CPP_OPTS+=" -I"+qdir
 				
 			Case ".hh",".hpp"
 			
-				product.CPP_OPTS.Push( "-I"+qdir )
+				product.CPP_OPTS+=" -I"+qdir
 				
 			Case ".a",".lib",".dylib"
 			
-				product.LD_OPTS.Push( "-L"+qdir )
+				product.LD_OPTS+=" -L"+qdir
 				
 			Case ".framework"
 			
-				product.LD_OPTS.Push( "-F"+qdir )
+				product.LD_OPTS+=" -F"+qdir
 				
 			Default
 			

+ 202 - 142
src/mx2cc/buildproduct.monkey2

@@ -5,16 +5,16 @@ Class BuildProduct
 
 	Field module:Module
 	Field opts:BuildOpts
-	
+	Field imports:=New Stack<Module>
 	Field outputFile:String
-
-	Field LD_OPTS:=New StringStack	
-	Field CC_OPTS:=New StringStack
-	Field CPP_OPTS:=New StringStack
+	
+	Field LD_OPTS:String
+	Field CC_OPTS:String
+	Field CPP_OPTS:String
+	Field AS_OPTS:String
 
 	Field SRC_FILES:=New StringStack
 	Field OBJ_FILES:=New StringStack
-	Field MOD_LIBS:=New StringStack
 	Field LD_SYSLIBS:=New StringStack
 	Field ASSET_FILES:=New StringStack
 	Field DLL_FILES:=New StringStack
@@ -25,27 +25,70 @@ Class BuildProduct
 		
 		Local copts:=""
 		
+		copts+=" -I~q"+MODULES_DIR+"~q"
+		copts+=" -I~q"+MODULES_DIR+"monkey/native~q"
+		If APP_DIR copts+=" -I~q"+APP_DIR+"~q"
+		
+		CC_OPTS+=copts
+		CPP_OPTS+=copts
+		
 		copts=GetEnv( "MX2_LD_OPTS_"+opts.target.ToUpper() )
-		If copts LD_OPTS.Push( copts )
+		If copts LD_OPTS+=" "+copts
 
 		copts=GetEnv( "MX2_LD_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
-		If copts LD_OPTS.Push( copts )
+		If copts LD_OPTS+=" "+copts
 		
 		copts=GetEnv( "MX2_CC_OPTS_"+opts.target.ToUpper() )
-		If copts CC_OPTS.Push( copts )
+		If copts CC_OPTS+=" "+copts
 		
 		copts=GetEnv( "MX2_CC_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
-		If copts CC_OPTS.Push( copts )
+		If copts CC_OPTS+=" "+copts
 		
 		copts=GetEnv( "MX2_CPP_OPTS_"+opts.target.ToUpper() )
-		If opts CPP_OPTS.Push( copts )
+		If opts CPP_OPTS+=" "+copts
 		
 		copts=GetEnv( "MX2_CPP_OPTS_"+opts.target.ToUpper()+"_"+opts.config.ToUpper() )
-		If copts CPP_OPTS.Push( copts )
+		If copts CPP_OPTS+=" "+copts
 		
+		copts=GetEnv( "MX2_AS_OPTS" )
+		If copts AS_OPTS+=" "+copts
 	End
 
-	Method Build() Virtual
+	Method Build()
+	
+		If Not CreateDir( module.cacheDir ) Throw New BuildEx( "Error creating dir '"+module.cacheDir+"'" )
+		
+		If opts.reflection
+			CC_OPTS+=" -DBB_REFLECTION"
+			CPP_OPTS+=" -DBB_REFLECTION"
+		Endif
+
+		If opts.verbose=0 Print "Compiling..."
+		
+		Local srcs:=New StringStack
+
+		If opts.productType="app"
+		
+			srcs.Push( module.rfile )
+			
+			For Local imp:=Eachin imports
+			
+				srcs.Push( imp.rfile )
+			Next
+			
+		Endif
+		
+		For Local fdecl:=Eachin module.fileDecls
+		
+			srcs.Push( fdecl.cfile )
+		Next
+		
+		srcs.AddAll( SRC_FILES )
+		
+		Build( srcs )
+	End
+	
+	Method Build( srcs:StringStack ) Virtual
 	End
 	
 	Method Run() Virtual
@@ -267,33 +310,29 @@ Class GccBuildProduct Extends BuildProduct
 	End
 	
 	Method CompileSource:String( src:String )
+	
+		Local rfile:=src.EndsWith( "/_r.cpp" )
 
-		Local obj:=module.cacheDir+MungPath( MakeRelativePath( src,module.cacheDir ) )+".o"
-			
+		Local obj:=module.cacheDir+MungPath( MakeRelativePath( src,module.cacheDir ) )
+		If rfile And opts.reflection obj+="_r"
+		obj+=".o"
+		
 		Local ext:=ExtractExt( src ).ToLower()
 						
 		Local cmd:="",isasm:=False
-			
+
 		Select ext
 		Case ".c",".m"
 			
-			cmd=CC_CMD+" "+CC_OPTS.Join( " " )
-			cmd+=" -I~q"+MODULES_DIR+"monkey/native~q"
-			cmd+=" -I~q"+MODULES_DIR+"~q"
-			If APP_DIR cmd+=" -I~q"+APP_DIR+"~q"
+			cmd=CC_CMD+CC_OPTS+" -c"
 				
 		Case ".cc",".cxx",".cpp",".mm"
 
-			cmd=CXX_CMD+" "+CPP_OPTS.Join( " " )
-			cmd+=" -I~q"+MODULES_DIR+"monkey/native~q"
-			cmd+=" -I~q"+MODULES_DIR+"~q"
-			If APP_DIR cmd+=" -I~q"+APP_DIR+"~q"
+			cmd=CXX_CMD+CPP_OPTS+" -c"
 
 		Case ".asm",".s"
-			
-			cmd=AS_CMD
-			Local opts:=GetEnv( "MX2_AS_OPTS" )
-			If opts cmd+=" "+opts
+		
+			cmd=AS_CMD+AS_OPTS
 			
 			isasm=True
 		End
@@ -301,37 +340,36 @@ Class GccBuildProduct Extends BuildProduct
 		'Check dependancies
 		'			
 		Local objTime:=GetFileTime( obj )
-			
+
+		'create deps file name
+		'			
 		Local deps:=StripExt( obj )+".deps"
-			
+		
 		If opts.fast And objTime>=GetFileTime( src )	'source file up to date?
+		
+			If isasm Return obj
 			
 			Local uptodate:=True
 			
-			If Not isasm
-			
-				If GetFileType( deps )=FILETYPE_NONE
+			If GetFileType( deps )=FILETYPE_NONE
 					
-					If opts.verbose>0 Print "Scanning "+src
+				If opts.verbose>0 Print "Scanning "+src
 				
-					Exec( cmd+" -MM ~q"+src+"~q >~q"+deps+"~q" ) 
-						
-				Endif
+				Exec( cmd+" -MM ~q"+src+"~q >~q"+deps+"~q" ) 
+			Endif
 					
-				Local srcs:=LoadString( deps ).Split( " \" )
+			Local srcs:=LoadString( deps ).Split( " \" )
 					
-				For Local i:=1 Until srcs.Length
+			For Local i:=1 Until srcs.Length
 					
-					Local src:=srcs[i].Trim().Replace( "\ "," " )
+				Local src:=srcs[i].Trim().Replace( "\ "," " )
 					
-					If GetFileTime( src )>objTime
-						uptodate=False
-						Exit
-					Endif
+				If GetFileTime( src )>objTime
+					uptodate=False
+					Exit
+				Endif
 						
-				Next
-				
-			Endif
+			Next
 				
 			If uptodate Return obj
 				
@@ -343,8 +381,6 @@ Class GccBuildProduct Extends BuildProduct
 			
 		If opts.verbose>0 Print "Compiling "+src
 			
-		If Not isasm cmd+=" -c"
-		
 		cmd+=" -o ~q"+obj+"~q ~q"+src+"~q"
 			
 		Exec( cmd )
@@ -352,76 +388,68 @@ Class GccBuildProduct Extends BuildProduct
 		Return obj
 	End
 	
-	Method Build() Override
-	
-		If opts.verbose=0 Print "Compiling..."
+	Method Build( srcs:StringStack ) Override
 		
-		If Not CreateDir( module.cacheDir ) Throw New BuildEx( "Error create dir '"+module.cacheDir+"'" )
-
-		For Local src:=Eachin SRC_FILES
-			
-			OBJ_FILES.Push( CompileSource( src ) )
-			
+		Local objs:=New StringStack
+		
+		For Local src:=Eachin srcs
+		
+			objs.Push( CompileSource( src ) )
 		Next
-
+		
+		objs.AddAll( OBJ_FILES )
+		
 		If opts.productType="module"
-			
-			BuildArchive()
-			
+		
+			BuildModule( objs )
+		
 		Else
-			
-			BuildApp()
-			
-		Endif
 		
+			BuildApp( objs )
+		End
 	End
 	
-	Method BuildArchive:String()
+	Method BuildModule( objs:StringStack )
+
+		Local output:=module.afile
 
-		Local outputFile:=module.outputDir+module.name+".a"
-		
-		'AR is slow! This is probably not quite right, but it'll do for now...
-		'
 		Local maxObjTime:Long
-		For Local obj:=Eachin OBJ_FILES
+		For Local obj:=Eachin objs
 			maxObjTime=Max( maxObjTime,GetFileTime( obj ) )
 		Next
-		If GetFileTime( outputFile )>maxObjTime Return outputFile
-		
-		If opts.verbose>=0 Print "Archiving "+outputFile+"..."
+		If GetFileTime( output )>maxObjTime Return
 		
-		DeleteFile( outputFile )
+		If opts.verbose>=0 Print "Archiving "+output+"..."
 		
-		Local objs:=""
+		DeleteFile( output )
 		
-		For Local i:=0 Until OBJ_FILES.Length
+		Local args:=""
+
+		For Local i:=0 Until objs.Length
 			
-			objs+=" ~q"+OBJ_FILES.Get( i )+"~q"
+			args+=" ~q"+objs.Get( i )+"~q"
 			
-			If objs.Length<1000 And i<OBJ_FILES.Length-1 Continue
+			If args.Length<1000 And i<objs.Length-1 Continue
 
-			Local cmd:=AR_CMD+" q ~q"+outputFile+"~q"+objs
+			Local cmd:=AR_CMD+" q ~q"+output+"~q"+args
 
 			Exec( cmd )
 			
-			objs=""
+			args=""
 			
 		Next
-		
-		Return outputFile
-		
 	End
 	
-	Method BuildApp() Virtual
+	Method BuildApp( objs:StringStack ) Virtual
 	
 		outputFile=opts.product
 		If Not outputFile outputFile=module.outputDir+module.name
 		
 		Local assetsDir:=ExtractDir( outputFile )+"assets/"
+		
 		Local dllsDir:=ExtractDir( outputFile )
 
-		Local cmd:=LD_CMD
-		cmd+=" "+LD_OPTS.Join( " " )
+		Local cmd:=LD_CMD+LD_OPTS
 		
 		Select opts.target
 		Case "windows"
@@ -487,7 +515,7 @@ Class GccBuildProduct Extends BuildProduct
 		
 		Local lnkFiles:=""
 		
-		For Local obj:=Eachin OBJ_FILES
+		For Local obj:=Eachin objs
 			lnkFiles+=" ~q"+obj+"~q"
 		Next
 		
@@ -499,8 +527,8 @@ Class GccBuildProduct Extends BuildProduct
 #Endif
 		Endif
 		
-		For Local lib:=Eachin MOD_LIBS
-			lnkFiles+=" ~q"+lib+"~q"
+		For Local imp:=Eachin imports
+			lnkFiles+=" ~q"+imp.afile+"~q"
 		Next
 
 		If opts.wholeArchive 
@@ -545,13 +573,82 @@ Class GccBuildProduct Extends BuildProduct
 	
 End
 
+Class IosBuildProduct Extends GccBuildProduct
+
+	Method New( module:Module,opts:BuildOpts )
+	
+		Super.New( module,opts )
+	End
+	
+	Method BuildApp( objs:StringStack ) Override
+	
+		BuildModule( objs )
+		
+		Local arc:=module.afile
+
+		Local outputFile:=opts.product+"libmx2_main.a"
+		
+		Local cmd:="libtool -static -o ~q"+outputFile+"~q ~q"+arc+"~q"
+		
+		If opts.wholeArchive cmd+=" -Wl,--whole-archive"
+		
+		For Local imp:=Eachin imports
+			cmd+=" ~q"+imp.afile+"~q"
+		Next
+
+		If opts.wholeArchive cmd+=" -Wl,--no-whole-archive"
+		
+		For Local lib:=Eachin LD_SYSLIBS
+			If lib.ToLower().EndsWith( ".a~q" ) cmd+=" "+lib
+		Next
+		
+		Exec( cmd )
+		
+		CopyAssets( opts.product+"assets/" )
+	End
+	
+	Method Run() Override
+	End
+	
+End
+
+Function SplitOpts:String[]( opts:String )
+
+	Local out:=New StringStack
+
+	Local i0:=0
+	Repeat
+	
+		While i0<opts.Length And opts[i0]<=32
+			i0+=1
+		Wend
+		If i0>=opts.Length Exit
+
+		Local i1:=opts.Find( " ",i0 )
+		If i1=-1 i1=opts.Length
+
+		Local i2:=opts.Find( "~q",i0 )
+		If i2<>-1 And i2<i1
+			i1=opts.Find( "~q",i2+1 )+1
+			If Not i1 i1=opts.Length
+		Endif
+
+		out.Push( opts.Slice( i0,i1 ) )
+		i0=i1+1
+	
+	Forever
+	
+	Return out.ToArray()
+End
+
 Class AndroidBuildProduct Extends BuildProduct
 
 	Method New( module:Module,opts:BuildOpts )
+
 		Super.New( module,opts )
 	End
 	
-	Method Build() Override
+	Method Build( srcs:StringStack ) Override
 	
 		Local jniDir:=module.outputDir+"jni/"
 		
@@ -575,19 +672,19 @@ Class AndroidBuildProduct Extends BuildProduct
 		buf.Push( "APP_STL := c++_static" )
 		
 		CSaveString( buf.Join( "~n" ),jniDir+"Application.mk" )
+		
 		buf.Clear()
 
 		buf.Push( "LOCAL_PATH := $(call my-dir)" )
 		
 		If opts.productType="app"
 		
-			For Local extmod:=Eachin Builder.modules
-				If extmod=module continue
+			For Local imp:=Eachin imports
 			
-				Local src:=extmod.outputDir+"obj/local/$(TARGET_ARCH_ABI)/libmx2_"+extmod.name+".a"
+				Local src:=imp.outputDir+"obj/local/$(TARGET_ARCH_ABI)/libmx2_"+imp.name+".a"
 					
 				buf.Push( "include $(CLEAR_VARS)" )
-				buf.Push( "LOCAL_MODULE := mx2_"+extmod.name )
+				buf.Push( "LOCAL_MODULE := mx2_"+imp.name )
 				buf.Push( "LOCAL_SRC_FILES := "+src )
 				buf.Push( "include $(PREBUILT_STATIC_LIBRARY)" )
 			Next
@@ -611,18 +708,18 @@ Class AndroidBuildProduct Extends BuildProduct
 			buf.Push( "LOCAL_MODULE := mx2_"+module.name )
 		Endif
 		
-		buf.Push( "LOCAL_CFLAGS += -I~q"+MODULES_DIR+"monkey/native~q" )
-		buf.Push( "LOCAL_CFLAGS += -I~q"+MODULES_DIR+"~q" )
-		If APP_DIR buf.Push( "LOCAL_CFLAGS += -I~q"+APP_DIR+"~q" )
+		Local cc_opts:=SplitOpts( CC_OPTS )
 		
-		For Local opt:=Eachin CC_OPTS
-			If opt.StartsWith( "-I" ) buf.Push( "LOCAL_CFLAGS += "+opt )
+		For Local opt:=Eachin cc_opts
+			If opt.StartsWith( "-I" ) Or opt.StartsWith( "-D" ) buf.Push( "LOCAL_CFLAGS += "+opt )
 		Next
 		
 		buf.Push( "LOCAL_SRC_FILES := \" )
-		For Local src:=Eachin SRC_FILES
+		
+		For Local src:=Eachin srcs
 			buf.Push( MakeRelativePath( src,jniDir )+" \" )
 		Next
+		
 		buf.Push( "" )
 
 		buf.Push( "LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES" )
@@ -630,10 +727,10 @@ Class AndroidBuildProduct Extends BuildProduct
 		If opts.productType="app"
 		
 			buf.Push( "LOCAL_STATIC_LIBRARIES := \" )
-			For Local extmod:=Eachin Builder.modules.Backwards()
-				If extmod=module Continue
+			For Local imp:=Eachin imports	'Builder.modules.Backwards()
+				If imp=module Continue
 				
-				buf.Push( "mx2_"+extmod.name+" \" )
+				buf.Push( "mx2_"+imp.name+" \" )
 			Next
 			buf.Push( "" )
 			
@@ -661,7 +758,6 @@ Class AndroidBuildProduct Extends BuildProduct
 
 			buf.Push( "include $(BUILD_STATIC_LIBRARY)" )
 		Endif
-
 		
 		CSaveString( buf.Join( "~n" ),jniDir+"Android.mk" )
 		buf.Clear()
@@ -685,39 +781,3 @@ Class AndroidBuildProduct Extends BuildProduct
 	End
 	
 End
-
-Class IosBuildProduct Extends GccBuildProduct
-
-	Method New( module:Module,opts:BuildOpts )
-		Super.New( module,opts )
-	End
-	
-	Method BuildApp() Override
-	
-		Local arc:=BuildArchive()
-
-		Local outputFile:=opts.product+"libmx2_main.a"
-		
-		Local cmd:="libtool -static -o ~q"+outputFile+"~q ~q"+arc+"~q"
-		
-		If opts.wholeArchive cmd+=" -Wl,--whole-archive"
-		
-		For Local lib:=Eachin MOD_LIBS
-			cmd+=" ~q"+lib+"~q"
-		Next
-
-		If opts.wholeArchive cmd+=" -Wl,--no-whole-archive"
-		
-		For Local lib:=Eachin LD_SYSLIBS
-			If lib.ToLower().EndsWith( ".a~q" ) cmd+=" "+lib
-		Next
-		
-		Exec( cmd )
-		
-		CopyAssets( opts.product+"assets/" )
-	End
-	
-	Method Run() Override
-	End
-	
-End

+ 1 - 0
src/mx2cc/decl.monkey2

@@ -28,6 +28,7 @@ Class Decl Extends PNode
 	Field flags:Int
 	Field symbol:String
 	Field docs:String
+	Field meta:String
 	
 	Field members:Decl[]
 	

+ 7 - 0
src/mx2cc/module.monkey2

@@ -26,6 +26,9 @@ Class Module
 	Field cacheDir:String
 	Field hfileDir:String
 	Field cfileDir:String
+	
+	Field afile:String
+	Field rfile:String
 
 	Field fileDecls:=New Stack<FileDecl>
 	Field fileScopes:=New Stack<FileScope>
@@ -53,6 +56,10 @@ Class Module
 		hfileDir=outputDir+"include/"
 		
 		cfileDir=outputDir+"src/"
+		
+		afile=outputDir+name+".a"
+		
+		rfile=hfileDir+"_r.cpp"
 	End
 End
 

+ 1 - 0
src/mx2cc/mung.monkey2

@@ -56,6 +56,7 @@ Function MungArg:String( type:Type )
 		Case Type.FloatType	Return "f"
 		Case Type.DoubleType	Return "d"
 		Case Type.StringType	Return "s"
+		Case Type.VariantType	Return "q"
 		End
 		Return "????? MungArg ?????"
 	End

+ 1 - 1
src/mx2cc/mx2.monkey2

@@ -50,4 +50,4 @@ Using libc
 ' 3) edit .sh and .bat files to use new version (common.sh, common.bat)
 ' 4) ./rebuildall
 '
-Const MX2CC_VERSION:="1.0.9"
+Const MX2CC_VERSION:="1.0.91"

+ 51 - 7
src/mx2cc/mx2cc.monkey2

@@ -21,14 +21,16 @@ Using mx2..
 
 Global StartDir:String
 
-Const TestArgs:="mx2cc makeapp -apptype=console -clean -verbose=3 src/mx2cc/test.monkey2"
+Const TestArgs:="mx2cc makedocs"'mods -clean -target=android"' -config=release monkey lua"
+
+'Const TestArgs:="mx2cc makeapp -apptype=console src/mx2cc/test.monkey2"
 
 'To build with old mx2cc...
 '
 'Creates: src/mx2cc/mx2cc.buildv.VERSION/windows_release/mx2cc.exe
 '
 'Const TestArgs:="mx2cc makemods -clean -config=release monkey libc miniz stb-image stb-image-write stb-vorbis std"
-'Const TestArgs:="mx2cc makeapp -build -apptype=console -clean -config=release src/mx2cc/mx2cc.monkey2"
+'Const TestArgs:="mx2cc makeapp -run -apptype=console -clean -config=release src/mx2cc/mx2cc.monkey2"
 
 'To build rasbian mx2cc...
 '
@@ -37,7 +39,8 @@ Const TestArgs:="mx2cc makeapp -apptype=console -clean -verbose=3 src/mx2cc/test
 
 Function Main()
 
-	Print "mx2cc version "+MX2CC_VERSION
+	Print ""
+	Print "Mx2cc version "+MX2CC_VERSION
 	
 	StartDir=CurrentDir()
 	
@@ -58,8 +61,37 @@ Function Main()
 
 	If args.Length<2
 
-		Print "Usage: mx2cc makeapp|makemods|makedocs [-build|-run] [-clean] [-verbose[=1|2|3]] [-target=desktop|emscripten] [-config=debug|release] [-apptype=gui|console] source|modules..."
-		Print "Defaults: -run -target=desktop -config=debug -apptype=gui"
+		Print ""
+		Print "Mx2cc usage: mx2cc action options sources"
+		Print ""
+		Print "Actions:"
+		print "  makeapp      - make an application"
+		print "  makemods     - make modules"
+		print "  makedocs     - make docs"
+		Print ""
+		Print "Options:"
+		Print "  -quiet       - emit less info when building"
+		Print "  -verbose     - emit more info when building"
+		Print "  -parse       - parse only"
+		Print "  -semant      - parse and semant"
+		Print "  -translate   - parse, semant and translate"
+		Print "  -build       - parse, semant, translate and build"
+		Print "  -run         - the works! The default."
+		Print "  -apptype=    - app type to make, one of : gui, console. Defaults to gui."
+		print "  -target=     - build target, one of: windows, macos, linux, emscripten, android, ios, desktop. Desktop is alias for current host. Defaults to desktop."
+		Print "  -config=     - build config, one of: debug, release. Defaults to debug."
+		Print ""
+		Print "Sources:"
+		Print "  for makeapp  - single monkey2 source file."
+		Print "  for makemods - list of modules, or nothing to make all modules."
+		Print "  for makedocs - list of modules, or nothing to make all docs."
+
+#If __DESKTOP_TARGET__
+		CreateDir( "tmp" )
+		system( "g++ --version >tmp/_v.txt" )
+		Print ""
+		Print LoadString( "tmp/_v.txt" )
+#Endif
 
 #If __CONFIG__="release"
 		exit_(0)
@@ -125,7 +157,6 @@ Function MakeApp:Bool( args:String[] )
 	New BuilderInstance( opts )
 	
 	Builder.Parse()
-	If Builder.errors.Length Return False
 	If opts.passes=1 
 		If opts.geninfo
 			Local gen:=New ParseInfoGenerator
@@ -134,6 +165,7 @@ Function MakeApp:Bool( args:String[] )
 		Endif
 		Return True
 	Endif
+	If Builder.errors.Length Return False
 	
 	Builder.Semant()
 	If Builder.errors.Length Return False
@@ -267,6 +299,15 @@ Function MakeDocs:Bool( args:String[] )
 		
 	Next
 	
+	Local tree:=man_indices.Join( "," )
+	If tree tree+=","
+	tree+="{ text:'Modules reference',children:["+api_indices.Join( "," )+"] }"
+	
+	Local page:=LoadString( "docs/docs_template.html" )
+	page=page.Replace( "${DOCS_TREE}",tree )
+	SaveString( page,"docs/docs.html" )
+	
+	#rem
 	Local page:=LoadString( "docs/modules_template.html" )
 	page=page.Replace( "${API_INDEX}",api_indices.Join( "," ) )
 	SaveString( page,"docs/modules.html" )
@@ -274,7 +315,8 @@ Function MakeDocs:Bool( args:String[] )
 	page=LoadString( "docs/manuals_template.html" )
 	page=page.Replace( "${MAN_INDEX}",man_indices.Join( "," ) )
 	SaveString( page,"docs/manuals.html" )
-	
+	#end
+		
 	Return True
 End
 
@@ -301,6 +343,8 @@ Function ParseOpts:String[]( opts:BuildOpts,args:String[] )
 				opts.passes=1
 			Case "-clean"
 				opts.clean=True
+			Case "-quiet"
+				opts.verbose=-1
 			Case "-verbose"
 				opts.verbose=1
 			Case "-geninfo"

+ 96 - 36
src/mx2cc/parser.monkey2

@@ -81,48 +81,54 @@ Class Parser
 		Return ident
 	End
 	
+	Method Meta:String()
+	
+		Return _meta
+	End
+	
+	Method ParseMeta:String()
+	
+		If Not CParse( "[" ) Return ""
+		
+		Local meta:=""
+		Repeat
+		
+			Local key:=ParseIdent()
+			
+			Parse( "=" )
+
+			Local value:=""
+			
+			Select TokeType
+			Case TOKE_INTLIT,TOKE_FLOATLIT
+				value=Parse()
+			Case TOKE_STRINGLIT
+				value=DequoteMx2String( Parse() )
+				If value.Contains( "~~~n" ) Error( "Invalid meta data value!" )
+			Default
+				Error( "Expecting literal meta value" )
+			End
+			
+			If meta meta+="~~~n"
+			meta+=key+"="+value
+			
+		Until Not CParse( "," )
+			
+		Parse( "]" )
+		ParseEol()
+		
+		Return meta
+	End
+	
 	Method ParseDecls:Decl[]( flags:Int,fileScope:Bool )
 	
 		Local decls:=New Stack<Decl>
 		
-		While Toke
+		While Toke And Toke<>"end"
+		
 			Try
+			
 				Select Toke
-				Case "end"
-					Exit
-				Case "const"
-					ParseVars( decls,flags )
-				Case "global"
-					ParseVars( decls,flags )
-				Case "field"
-					If flags & DECL_EXTENSION Error( "Fields cannot be declared in extension classes" )
-					If fileScope Error( "Fields can only be declared inside a class, struct or interface" )
-					ParseVars( decls,flags )
-				Case "local"
-					Error( "Locals can only be declared in a statement block" )
-				Case "alias"
-					ParseAliases( decls,flags )
-				Case "class"
-					decls.Push( ParseClass( flags ) )
-				Case "struct"
-					decls.Push( ParseClass( flags ) )
-				Case "interface"
-					decls.Push( ParseClass( flags ) )
-'				Case "protocol"
-'					decls.Push( ParseClass( flags ) )
-				Case "enum"
-					decls.Push( ParseEnum( flags ) )
-				Case "function"
-					decls.Push( ParseFunc( flags ) )
-				Case "method"
-					If fileScope Error( "Methods can only be declared inside a class, struct or interface" )
-					decls.Push( ParseFunc( flags ) )
-				Case "operator"
-					If fileScope Error( "Operators can only be declared inside a class, struct or interface" )
-					decls.Push( ParseFunc( flags ) )
-				Case "property"
-					If fileScope Error( "Properties can only be declared inside a class, struct or interface" )
-					decls.Push( ParseProperty( flags ) )
 				Case "namespace"
 					If Not fileScope Or decls.Length Or _usings.Length Error( "'Namespace' must appear at the start of the file" )
 					If _fdecl.nmspace Error( "Duplicate namespace declaration" )
@@ -130,11 +136,13 @@ Class Parser
 					_fdecl.docs=Docs()
 					_fdecl.nmspace=ParseNamespaceIdent()
 					ParseEol()
+					Continue
 				Case "using"
 					If Not fileScope Or decls.Length Error( "Usings must appear before any declarations in a file" )
 					Bump()
 					_usings.Push( ParseUsingIdent() )
 					ParseEol()
+					Continue
 				Case "extern"
 					If Not fileScope Error( "'Extern' must appear at file scope" )
 					Bump()
@@ -146,6 +154,7 @@ Class Parser
 						flags|=DECL_PUBLIC
 					Endif
 					ParseEol()
+					Continue
 				Case "public","private"
 					flags&=~DECL_ACCESSMASK
 					If fileScope flags&=~DECL_EXTERN
@@ -156,17 +165,59 @@ Class Parser
 						flags|=DECL_PUBLIC
 					Endif
 					ParseEol()
+					Continue
 				Case "protected"
 					If fileScope Error( "'Protected' can only be used in a class, struct or interface" )
 					Bump()
 					flags=(flags & ~DECL_ACCESSMASK)|DECL_PROTECTED
 					ParseEol()
+					Continue
+				End
+			
+				_meta=ParseMeta()
+				
+				Select Toke
+				Case "const"
+					ParseVars( decls,flags )
+				Case "global"
+					ParseVars( decls,flags )
+				Case "field"
+					If flags & DECL_EXTENSION Error( "Fields cannot be declared in extension classes" )
+					If fileScope Error( "Fields can only be declared inside a class, struct or interface" )
+					ParseVars( decls,flags )
+				Case "local"
+					Error( "Locals can only be declared in a statement block" )
+				Case "alias"
+					ParseAliases( decls,flags )
+				Case "class"
+					decls.Push( ParseClass( flags ) )
+				Case "struct"
+					decls.Push( ParseClass( flags ) )
+				Case "interface"
+					decls.Push( ParseClass( flags ) )
+				Case "enum"
+					decls.Push( ParseEnum( flags ) )
+				Case "function"
+					decls.Push( ParseFunc( flags ) )
+				Case "method"
+					If fileScope Error( "Methods can only be declared inside a class, struct or interface" )
+					decls.Push( ParseFunc( flags ) )
+				Case "operator"
+					If fileScope Error( "Operators can only be declared inside a class, struct or interface" )
+					decls.Push( ParseFunc( flags ) )
+				Case "property"
+					If fileScope Error( "Properties can only be declared inside a class, struct or interface" )
+					decls.Push( ParseProperty( flags ) )
 				Default
 					Error( "Unexpected token '"+Toke+"'" )
 				End
+				
 			Catch ex:ParseEx
 				SkipToNextLine()
 			End
+			
+			_meta=""
+			
 		Wend
 		
 		Return decls.ToArray()
@@ -197,6 +248,7 @@ Class Parser
 				decl.srcpos=SrcPos
 				decl.kind=kind
 				decl.docs=Docs()
+				decl.meta=Meta()
 				decl.flags=flags
 				decl.ident=ParseIdent()
 				decl.genArgs=ParseGenArgs()
@@ -229,6 +281,7 @@ Class Parser
 				decl.srcpos=SrcPos
 				decl.kind=kind
 				decl.docs=Docs()
+				decl.meta=Meta()
 				decl.flags=flags
 				decl.ident=ParseIdent()
 				
@@ -262,6 +315,7 @@ Class Parser
 		decl.srcpos=SrcPos
 		decl.kind=Parse()
 		decl.docs=Docs()
+		decl.meta=Meta()
 		decl.ident="?????"
 		
 		flags&=(DECL_ACCESSMASK|DECL_EXTERN)
@@ -365,6 +419,7 @@ Class Parser
 		Local srcpos:=SrcPos
 		Local kind:=Parse()
 		Local docs:=Docs()
+		Local meta:=Meta()
 		Local ident:="?????"
 		Local genArgs:String[]
 		Local type:FuncTypeExpr
@@ -519,6 +574,7 @@ Class Parser
 		decl.srcpos=srcpos
 		decl.kind=kind
 		decl.docs=docs
+		decl.meta=meta
 		decl.ident=ident
 		decl.flags=flags
 		decl.genArgs=genArgs
@@ -564,6 +620,7 @@ Class Parser
 		decl.flags=flags
 		decl.kind=Parse()
 		decl.docs=Docs()
+		decl.meta=Meta()
 		
 		Try
 			decl.ident=ParseIdent()
@@ -592,6 +649,7 @@ Class Parser
 				decl.flags=DECL_PUBLIC|(flags & DECL_EXTERN)
 				decl.ident=ParseIdent()
 				decl.docs=Docs()
+				decl.meta=Meta()
 				
 				If flags & DECL_EXTERN
 					If CParse( "=" ) decl.symbol=ParseString()
@@ -637,6 +695,7 @@ Class Parser
 		decl.flags=flags
 		decl.kind="property"
 		decl.docs=Docs()
+		decl.meta=Meta()
 		
 		Local func:=ParseFunc( flags )
 		decl.ident=func.ident
@@ -1983,6 +2042,7 @@ Class Parser
 	
 	Field _fdecl:FileDecl
 	Field _toker:Toker
+	Field _meta:String
 	Field _stateStack:=New Stack<Toker>
 	Field _usings:=New StringStack
 	Field _errors:=New Stack<ParseEx>

+ 1 - 0
src/mx2cc/property.monkey2

@@ -55,6 +55,7 @@ Class PropertyList Extends FuncList
 			Try
 				setFunc=New FuncValue( pdecl.setFunc,scope,Null,Null )
 				setFunc.Semant()
+				If type=Type.VoidType type=setFunc.ftype.argTypes[0]
 				PushFunc( setFunc )
 			Catch ex:SemantEx
 			End