Macro in Monkey
Monkey Forums/Monkey Programming/Macro in Monkey
| ||
Hi all, just i want to ask before thinking to implement it. does Monkey has a Macro keyword ? if not what do you think about implementing one. i have 2 idea , 1- first using CPP #define directive that will work in cpp compiling. 2- second make it with Preprocesser and work in Monkey stage. thanks. |
| ||
I don't doubt that people have toyed with the idea. I could imagine an unofficial pre-processor getting built sometime... There's no Macro command though, and the pre-processor options are limited. Possibly that's a good choice in terms of usability for all but a hard core of programmers. |
| ||
Emil_halim wrote: 2- second make it with Preprocesser and work in Monkey stage. It's more universal. |
| ||
ok , of cource if i will make any changing to monkey , it will be unofficial monkey version. i will try implementing Macro in Preprocessor . |
| ||
a gcc preprocessor work with every language... also with java or monkey... or any other you should run preprocessor before monkey compile... so something need to change in monkey... see this here: If you use the -E option, nothing is done except preprocessing. http://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html example: http://www.network-theory.co.uk/docs/gccintro/gccintro_36.html |
| ||
thanks dragon, I am thinking in first implementing Macro that will work in monkey translator stage. Also i have an idea , inline some c/c++ asm code within monkey source code itself, so using gcc preprocessor will help at this time. |
| ||
Emil_halim wrote: of cource if i will make any changing to monkey , it will be unofficial monkey version. You may extend transcc(.monkey) or use any other tool to create preprocessor, set its name to transcc and call original transcc (under other name) when preprocessor ends work. |
| ||
nikoniko wrote: You may extend transcc(.monkey) It's not even required. Call first preprocessor (better if it will be a part of MonkeyX distro), then call transcc to build. |
| ||
Would be nice to have in Monkey:Macro abc ' replaces all occurences of 'abc' with 'x' x End Macro abc:Integer ' becomes 'x:Integer' '---------------------------------- Macro DoIt(a,b) something(a) something(b) doSomething(a,b) End DoIt(1,2) DoIt(1,"string") '---------------------------------- Macro myMacro(_a_) ' '#'-operator within macros joins things x#_a_#z End myMacro(y) ' becomes 'xyz' For embedding native code: '!' operator on line start means native code. It get's inserted without modification. So we could directly write C++, C#, Java, JavaScript. Depends on the target. ' Desktop/C++ target !int func(int a) { ! std::cout << a << std::endl; ! doSomething(a); !} Import Function func(a:Int) Public func(1) ' JavaScript targets !alert("alert"); '!' is used in PureBasic and PowerBasic to directly write ASM |
| ||
Macros could also be used for inlining Monkey code. |
| ||
@nikoniko when i was working in c-- Extension , i was having no source code of c-- so i made c--Ext that translates my new extension stuff to c-- code then c-- made the remain stuff. so here i have the source code of transcc so it is more easy to extend it, and i see that the best point to do a macro is after preprocessor. i mean in the end of PreProcess$ function. @Danilo that's exactly what i wes thinking , also i think in block of c , c++ or asm code with a kewword for each one. and with asm block i will support heigh level asm , something like this EAX = 10 -----> mov EAX,10 BTW BCX also uses ! for inlining c/c++ with basic code @Gerry Quinn of course that wright. |
| ||
Hi all, I have successfully finished inline block to c/c++. Example Function Main:Int() Local kiro:Int = 20 Print kiro inlineC // Inline c source code t_kiro=200; endC Print kiro Return 0 End that will print 20 200 as you see i uesd inlineC--endC to send block to c/c++ compiler. Note Well that the local variable kiro will be t_kiro in c/c++ phase. |
| ||
Hi all, Also added inline symbol "!" to send the line to c/c++ compiler the Previous Exm Function Main:Int() Local kiro:Int = 20 Print kiro inlineC // Inline c source code t_kiro=200; endC ! // Inline Sym C ! bbPrint(String(t_kiro)); Return 0 End NoteWell tile now we can use inline only in Function Body. |
| ||
Sounds good. :) |
| ||
thanks Danilo, now i can use ! symbol or inlinC in declaration area Example !DWORD put( String a ) { ! bbPrint( a ); !} inlineC // Inline c in declration area endC Extern Function put:Int(a:String) Public Function Main:Int() Local kiro:Int = 20 Print kiro inlineC // Inline c source code t_kiro=200; endC ! /* Inline Sym C */ ! bbPrint(String(t_kiro)); put("Monkey Ext is very good") Return 0 End i will post the transcc Ext later. |
| ||
It would be cool to have a preprocessor variable like:#transcc_ext |
| ||
see how haxe handle this http://haxe.org/doc/advanced/magic |
| ||
Thanks for the link! Looks much more advanced, and has basic stuff I am wondering about in Monkey X, for example enums, macros, ... |
| ||
@Kog if i got it well, #transcc_ext is a switch to on/of extension features. if so i will do it later. @dragon thanks again for your link, when i decided to change Transcc i put some roles to obay,which are 1- changes are done with a very little modification in monkey source code itself. 2- as possible as any changes will work for all targets. 3-try to collect changes and put then in one place and remark it for easy access. @Danilo with the monkey extension we can make what we want , for example , implementing Enum feature. actually implementing it is very easy , the idea is change each term of Enum to a const and let monkey pares it. started making it yesterday. |
| ||
Hi all, Enum feature done. Example Enum ONE,TWO,THREE EndEnum Function Main:Int() Print ONE Print TWO Print THREE Return 0 End will print 0 1 2 |
| ||
This enum has some problems; it is no different than an auto enumerated const scoped at the parent level. Many people use enums as a namespace... Furthermore, some people deliberately enumerate in different orders, for example to support bitwise flags. Your example doesn't seem to show this as possible. |
| ||
could you pleas feed some examples for enums as a namespace , deliberately enumerate in different orders , support bitwise flags. any way , i have extend Enum to support that Example Enum ONE,TWO,THREE EndEnum Enum AA,BB=10,CC,PP=60,ZZ EndEnum Function Main:Int() Print ONE Print TWO Print THREE Print CC Print ZZ Return 0 End print that 0 1 2 11 61 |
| ||
Does this work?Enum AA,BB=10,CC,PP=60,ZZ ENUM_1 = 1 ' restart at 1 ENUM_2 = CC ' 11 ENUM_3 ' 12 EndEnum Enum 20 ENUM_4 ' will start at 20 ENUM_5 ' will be 21 End Class ABC ' enum in class Enum 50 Step 5 ENUM_6 ' will start at 50 ENUM_7 ' will be 55 ENUM_8 ' will be 60 End End Enum ENUM_10 = 1 << 0 ENUM_11 = 1 << 1 ENUM_12 = 1 << 2 ENUM_13 = 1 << 3 End Enum Function Main:Int() Print AA Print BB Print CC Print PP Print ZZ Print ENUM_1 Print ENUM_2 Print ENUM_3 Print ENUM_4 Print ENUM_5 Print ABC.ENUM_6 Print ABC.ENUM_7 Print ABC.ENUM_8 Print ENUM_10 Print ENUM_11 Print ENUM_12 Print ENUM_13 Return 0 End |
| ||
here is enum in class namespace exampleEnum Option INVALID = -1 NONE = 0 A = 1 B = 2 C = 4 D = 8 End Enum Function Main() Print ( Option.B ) ' Prints 2 Print ( Option.A | Option.B ) 'Prints 3 Local everything:Int = Option.A | Option.B | Option.C | Option.D Print ( everything ) 'Prints 15 Local currentOption:Option 'Declares as an Enum type currentOption = Option.C Print currentOption 'Prints 4 If HasFlag(everything, Option.D) Then Print "True" Else Print "False" 'Prints True End Function Function HasFlag?(value:Int, flag:Int) Return (value & flag = flag) End Function scope of Options is in global namespace. Other scopes must call Options.Whatever. Anything that can evaluate to an int constant should be supported, eg: A = "A"[0] should return 65 because it can be statically evaluated at compile time. VB.NET has some pseudo-methods for Enums similar to how Monkey has pseudo-methods for Strings and Arrays. Enum.HasFlag() for example is a feature of .NET 4.0 and can easily be supported as in the above example. |
| ||
Hi all, this is what done till now. Example Enum ONE,TWO,THREE EndEnum Enum AA,BB=10+4,CC,PP=60,ZZ ENUM_1 = 1 ' restart at 1 ENUM_2 = CC ' 11 ENUM_3 ' ---------> still not supported End Enum 20 ENUM_4 ' will start at 20 ENUM_5 ' will be 21 End Enum Enum 50*10 Step 5*10 ENUM_6 ' will start at 500 ENUM_7 ' will be 550 ENUM_8 ' will be 600 EndEnum Enum ENUM_10 = 1 Shl 0 ENUM_11 = 1 Shl 1 ENUM_12 = 1 Shl 2 ENUM_13 = 1 Shl 3 EndEnum Enum POINT TA,TB,TC EndEnum Function Main:Int() Print ONE Print TWO Print THREE Print AA Print BB Print CC Print PP Print ZZ Print ENUM_1 Print ENUM_2 Print ENUM_3 Print ENUM_4 Print ENUM_5 Print ENUM_6 Print ENUM_7 Print ENUM_8 Print ENUM_10 Print ENUM_11 Print ENUM_12 Print ENUM_13 Print POINT_TA ' _ instead of . for scope stuff Print POINT_TB Print POINT_TC Return 0 End I will try to support other feature. |
| ||
Do you release a pre-alpha Version for testing? |
| ||
I will release it as soon as finishing Enum Keyword. here is the new feature of Enum until now Enum ONE,TWO,THREE EndEnum Enum AA,BB=10+4,CC,PP=60,ZZ ENUM_1 = 1 ' restart at 1 ENUM_2 = CC ' 15 ENUM_3 ' ---------> still not supported End Enum 20 ENUM_4 ' will start at 20 ENUM_5 ' will be 21 End Enum Enum 50*10 Step 5*10 ENUM_6 ' will start at 500 ENUM_7 ' will be 550 ENUM_8 ' will be 600 EndEnum Enum ENUM_10 = 1 Shl 0 ENUM_11 = 1 Shl 1 ENUM_12 = 1 Shl 2 ENUM_13 = 1 Shl 3 EndEnum Class ABC ' enum in class Enum 50 Step 5 ENUM_14 ' will start at 50 ENUM_15 ' will be 55 ENUM_16 ' will be 60 End End Enum POINT TA,TB,TC EndEnum Enum Option INVALID = -1 NONE = 0 A = 1 B = 2 C = 4 D = 8 End Enum Function Main:Int() Print ONE Print TWO Print THREE Print AA Print BB Print CC Print PP Print ZZ Print ENUM_1 Print ENUM_2 Print ENUM_3 Print ENUM_4 Print ENUM_5 Print ENUM_6 Print ENUM_7 Print ENUM_8 Print ENUM_10 Print ENUM_11 Print ENUM_12 Print ENUM_13 Print POINT_TA Print POINT_TB Print POINT_TC Print ( Option_A | Option_B ) 'Prints 3 Local everything:Int = Option_A | Option_B | Option_C | Option_D Print ( everything ) 'Prints 15 If HasFlag(everything, Option_D) Then Print "True" Else Print "False" 'Prints True Print ABC_ENUM_14 ' Enum in class Return 0 End Function HasFlag?(value:Int, flag:Int) Return (value & flag = flag) End Function |
| ||
@Emil_halim: Using underscore '_' instead dot '.' for named Enums in global space and within classes is not good IMO. It should be like this: ' Enum in class Print ABC.ENUM_14 Print ABC.ENUM_15 Print ABC.ENUM_16 ' Named Enum in global space Print POINT.TA Print POINT.TB Print POINT.TC ' Named Enum in Class Print MyClass.Option.INVALID Print MyClass.Option.NONE Here is a run-able code that shows how generated code could look like: |
| ||
by the way, if it wasn't clear in my earlier post, the primary advantage of declaring a variable to an enum type would be to hint the IDE. It would of course still be an Int, but the compiler could also optimize it based on the highest enum value available to a shorter type (like Short / unsigned char / Int8 / Int16), and more advanced IDE's like Jungle can auto-suggest an enumerated member. |
| ||
Pretty sure optimisation won't happen - any benefits would generally be insignificant, and Monkey is not about super-optimisation anyway. [For everything except C++, Monkey is structurally close to the target language - that's why it generates reasonably fast code. And C++ has structures of every kind, including ones that are reasonably easy to translate Monkey into.] Auto-suggestion, yes. But enums are mostly about giving names to magic numbers. They are mainly a handy alternative to consts when there is a long sequence of different values required. |
| ||
I don't disagree, but namespaces can start to get long with enums, and it probably wouldn't hurt to have just a tiny bit more sugar to go with them. Auto-suggesting a value the moment an enum's data provider is determined would save some typing of the class name and reduce scope confusion for newbies as well. And on a purely subjective personal preference note...Defining enums more like a class than some sort of static struct would be more in line with some the languages that seem to be the inspiration behind monkey's departure from bmax. C/C++ seem to me to be secondary design inspirations compared to newer languages like c#/vb.net and even java. While in the end they all compile to consts anyway, I'd rather see consistent scoping rules in line with the aforementioned expectation than something resembling a struct or union. |
| ||
@Nobuyuki: I indeed overlooked that part in your example: Enum Option INVALID = -1 NONE = 0 A = 1 B = 2 C = 4 D = 8 End Enum Function Main() ' ... Local everything:Int = Option.A | Option.B | Option.C | Option.D Print ( everything ) 'Prints 15 Local currentOption:Option 'Declares as an Enum type currentOption = Option.C Print currentOption 'Prints 4 '.. Thing is, making Enums a full type is more complicated, because you would also need to add some type checks. It is the main reason I wrote my examples only to represent Int and Const values. With a full type, the compiler should also check the values, whenever possible. And a full type would need to be supported everywhere, for example in Function/Method arguments: Class MyClass Enum Flags None Dithering End Enum Function Main() Local f:MyClass.Flags f = MyClass.Flags.Dithering ' OK f = 1 ' OK, same like Dithering f = 18 ' clearly not a valid value for this Enum f = x ' not check-able most of the time, because Enums are compatible with Int End Function LoadBitmap(file:String, f:MyClass.Flags) If HasFlag(f, MyClass.Flags.Dithering) ' ... Else ' ... Endif End I agree, this would be very nice. I just think it could be too much for users to implement, and Mark Sibly (who knows Monkey best) is silent and didn't say a word yet what he thinks about enhancing the language itself. There is even more stuff missing in the language, that other, similar cross-platform-tools (like Haxe), support. See Macros, the original topic of the thread. Would be nice to hear something from Mark about it, because it all doesn't make sense if it does not find its way into Monkey X at the end. ;) I'm also curious how Mark ticks. Maybe he thinks the core language is already finished? Maybe he is open minded for new suggestions and improvements? I would like to know, because that's also very important for the future of the language. Do we need to do 45 forks, or will he integrate the good stuff into the main distribution, etc..? Is it worth to invest time in Monkey X? Very much depends on the boss, that's why I'm curious what he thinks about it. ;) It is very clear that the users here want to enhance Monkey X to bring it forward... There is just some stuff missing that is available with all other languages I know, and I would like to know if it is possible Monkey X gets some of this stuff in the near future, or not. |
| ||
Valid point about using classes as scope - personally my enums always have a name with an underscore e.g. COLOUR_BLACK which I suppose is a kind of fake scoping. |
| ||
Okay , this is progress that done.Enum ONE,TWO,THREE EndEnum Enum AA,BB=10+4,CC,PP=60,ZZ ENUM_1 = 1 ' restart at 1 ENUM_2 = CC ' 15 ENUM_3 ' Err should print 16 End Enum 20 ENUM_4 ' will start at 20 ENUM_5 ' will be 21 End Enum Enum 50*10 Step 5*10 ENUM_6 ' will start at 500 ENUM_7 ' will be 550 ENUM_8 ' will be 600 EndEnum Enum ENUM_10 = 1 Shl 0 ENUM_11 = 1 Shl 1 ENUM_12 = 1 Shl 2 ENUM_13 = 1 Shl 3 EndEnum Class ABC ' enum in class Enum 50 Step 5 ENUM_14 ' will start at 50 ENUM_15 ' will be 55 ENUM_16 ' will be 60 End Enum DEF ENUM_17 ENUM_18 ENUM_19 End End Enum POINT TA,TB,TC EndEnum Enum Option INVALID = -1 NONE = 0 A = 1 B = 2 C = 4 D = 8 End Enum Function Main:Int() Print ONE Print TWO Print THREE Print AA Print BB Print CC Print PP Print ZZ Print ENUM_1 Print ENUM_2 Print ENUM_3 Print ENUM_4 Print ENUM_5 Print ENUM_6 Print ENUM_7 Print ENUM_8 Print ENUM_10 Print ENUM_11 Print ENUM_12 Print ENUM_13 Print POINT.TA Print POINT.TB Print POINT.TC Print ( Option.A | Option.B ) 'Prints 3 Local everything:Int = Option.A | Option.B | Option.C | Option.D Print ( everything ) 'Prints 15 If HasFlag(everything, Option.D) Then Print "True" Else Print "False" 'Prints True Print ABC.ENUM_14 ' Enum in class Print ABC.ENUM_19 ' Err must be ABC.DEF.ENUM_19 Local currentOption:Option 'Declares as an Enum type ' currentOption = Option.C ' Err connot convert from Int to Option ' Print currentOption 'Prints 4 Return 0 End Function HasFlag?(value:Int, flag:Int) Return (value & flag = flag) End Function |
| ||
Just to make sure this works, too:Enum Option 50*10 Step 5*10 ENUM_6 ' will start at 500 ENUM_7 ' will be 550 ENUM_8 ' will be 600 EndEnum So Syntax would be: Enum [ [Name] [StartValue [Step StepValue]] ] |
| ||
done , Enum OptionExt 50*10 Step 5*10 ENUM_6 ' will start at 500 ENUM_7 ' will be 550 ENUM_8 ' will be 600 EndEnum Function Main:Int() Print OptionExt.ENUM_8 'print 600 Return 0 End but still have 3 issues. ========================== Enum AA,BB=10+4,CC,PP=60,ZZ ENUM_1 = 1 ' restart at 1 ENUM_2 = CC ' 15 ENUM_3 ' Err should print 16 <<<------------------- End ========================== Print ABC.ENUM_19 ' Err must be ABC.DEF.ENUM_19 ========================== Local currentOption:Option 'Declares as an Enum type currentOption = Option.C ' Err connot convert from Int to Option |
| ||
Hi all, just started to support float type Enum. only simple stuff till now. Example Enum :Float F1,F2,F3 ' 0.0 ,1.0 , 2.0 End Function Main:Int() Print F1 Print F2 Print F3 Return 0 End |
| ||
Hi all while taking a rest of making Enum KeyWord , i created this ?Win32 Const My_OS:String = "Win32" ?MacOS Const My_OS:String = "MacOS" ?Linux Const My_OS:String = "Linux" ? Const My_Sys:String = "My system is " Function Main:Int() Print My_Sys + My_OS Return 0 End prints that "My system is Win32" |
| ||
Hi all , also this add ?Win32 Const My_OS:String = "Win32" ?MacOS Const My_OS:String = "MacOS" ?Linux Const My_OS:String = "Linux" ? Const My_Sys:String = "My system is " ?DeskTop Const My_target:String = "monkey game for win32,mac,lunix" ?CppTool Const My_target:String = "monkey tool" ?Html Const My_target:String = "monkey net browser" ? Global my_var : Int = 10 Function Main:Int() Print My_Sys + My_OS Print "Target is " + My_target ?Release ?Debug Print my_var ? Return 0 End Here is the first release of MonkeyExt , please backup your old one please. http://bcxdx.spoilerspace.com/Monkey/Tranc_EXT_02.zip |
| ||
Hi all, I have found a small conflict with my last Ext. i added "?" as a symbol so monkey toker will pares it as a token , and in box classes there is a function name "Equal?" , when toker pares this name will split it into two tokens "Equal" and "?". so that i modified "?" to be "??" symbol. here is the new release of MonkeyExt , included source code , for easy access search for '----Ext---- then you will find my code. http://bcxdx.spoilerspace.com/Monkey/Tranc_EXT_02a.zip |
| ||
The os module already has this functionality; if you're determining os in preprocessor then you should probably consider using existing preprocessor syntax.. |
| ||
thanks Nobuyuki for your hint. i was having no idea about os functions , i will remove mine. |