Xmas demo out!

Community Forums/Monkey2 Talk/Xmas demo out!

marksibly(Posted 2015) [#1]
Hi all,

A monkey2 xmas demo is now out - see the monkey2 blog page: https://blitz-research.github.io/

it's been a pretty intense week putting this together, but I am having a blast with monkey2 and I hope you like where it's going.

Now, off to consume a beer I found at the back of the fridge...

Bye!
Mark


tiresius(Posted 2015) [#2]
Very cool it is nice to see something tangible like a demo. Keep up the great work !


dopeyrulz(Posted 2015) [#3]
Thanks Mark! Merry Christmas!


CopperCircle(Posted 2015) [#4]
Yay, thanks and have another beer on me!


nullterm(Posted 2015) [#5]
Christmas on the 22nd!

I like the new Ted2 direction. Clean and minimal is right up my alley.

Can't wait to sit down and play with the actual MX2 language.


Leo Santos(Posted 2015) [#6]
Sweet!
Everything compiled and ran without issues here on OS X El Capitan.


dawlane(Posted 2015) [#7]
Thanks. I will get round to having a play with it. Did you resolve the problem with the use of dollar sign variables?


abakobo(Posted 2015) [#8]
Great!

Happy to see that it already creates very fluid graphics!

Merry Christmas and happy new year.


TheRedFox(Posted 2015) [#9]
Ah, spot on for my birthday, how cool.

Now, on my Mac, I tried to rebuild but encountered issues...

OSX Yosemite, MonkeyX 85e, Deskop target working nicely.

Ideas?


[PhilMac:~/Downloads/monkey2/src philippeback$] ./rebuildall.sh
TRANS monkey compiler V1.86
Parsing...
Semanting...
Translating...
Building...
Installing mx2cc

MX2CC monkey2 compiler V0.001
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1

Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

Making module: <monkey.monkey2>
Parsing...
Semanting...
Translating...
Compiling...
Archiving...
Making module: <lib.monkey2>
Parsing...
Semanting...
Translating...
Compiling...
Archiving...
Making module: <std.monkey2>
Parsing...
Semanting...
Translating...
Compiling...

Command failed:
g++  -std=c++11 -Wno-deprecated-declarations -Wno-tautological-pointer-compare -Wno-undefined-bool-conversion -Wno-int-to-void-pointer-cast -Wno-inconsistent-missing-override -Wno-logical-op-parentheses -Wno-undefined-inline -g -O0 -I"." -I"/Users/philippeback/Downloads/monkey2/modules/std/std.buildv001/build_cache/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/std/std.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/lib/lib.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/lib/hoedown/hoedown/src" -I"/Users/philippeback/Downloads/monkey2/modules/lib/sdl2/SDL/include" -I"/Users/philippeback/Downloads/monkey2/modules/lib/sdl2mixer/SDL_mixer" -I"/Users/philippeback/Downloads/monkey2/modules/lib/litehtml/litehtml/include" -I"/Users/philippeback/Downloads/monkey2/modules/monkey/monkey.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/monkey/native" -c -o "/Users/philippeback/Downloads/monkey2/modules/std/std.buildv001/build_cache/desktop_debug_macos/native_2filesystem.cpp.o" "/Users/philippeback/Downloads/monkey2/modules/std/native/filesystem.cpp" 2>tmp/tmp0.txt


***** Error *****

warning: unknown warning option '-Wno-inconsistent-missing-override' [-Wunknown-warning-option]
/Users/philippeback/Downloads/monkey2/modules/std/native/filesystem.cpp:171:8: error: use of undeclared identifier 'getcwd'
                        if( getcwd( buf,PATH_MAX )<0 ) return "";
                            ^
/Users/philippeback/Downloads/monkey2/modules/std/native/filesystem.cpp:189:11: error: use of undeclared identifier 'chdir'
                        return chdir( path.toUtf8String() );
                               ^
1 warning and 2 errors generated.

?[?] : Error :Execute failed

MX2CC monkey2 compiler V0.001
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1

Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

Parsing...
Semanting...
Translating...
Compiling...

Command failed:
g++  -std=c++11 -Wno-deprecated-declarations -Wno-tautological-pointer-compare -Wno-undefined-bool-conversion -Wno-int-to-void-pointer-cast -Wno-inconsistent-missing-override -Wno-logical-op-parentheses -Wno-undefined-inline -g -O0 -I"." -I"/Users/philippeback/Downloads/monkey2/src/ted2/ted2.buildv001/build_cache/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/src/ted2/ted2.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/mojo/mojo.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/mojo2/mojo2.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/std/std.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/lib/lib.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/lib/hoedown/hoedown/src" -I"/Users/philippeback/Downloads/monkey2/modules/lib/sdl2/SDL/include" -I"/Users/philippeback/Downloads/monkey2/modules/lib/sdl2mixer/SDL_mixer" -I"/Users/philippeback/Downloads/monkey2/modules/lib/litehtml/litehtml/include" -I"/Users/philippeback/Downloads/monkey2/modules/monkey/monkey.buildv001/desktop_debug_macos" -I"/Users/philippeback/Downloads/monkey2/modules/monkey/native" -c -o "/Users/philippeback/Downloads/monkey2/src/ted2/ted2.buildv001/build_cache/desktop_debug_macos/ted2_ted2.cpp.o" "/Users/philippeback/Downloads/monkey2/src/ted2/ted2.buildv001/build_cache/desktop_debug_macos/ted2_ted2.cpp" 2>tmp/tmp1.txt


***** Error *****

warning: unknown warning option '-Wno-inconsistent-missing-override' [-Wunknown-warning-option]
/Users/philippeback/Downloads/monkey2/src/ted2/ted2.buildv001/build_cache/desktop_debug_macos/ted2_ted2.cpp:6:10: fatal error: 'modules/mojo/mojo.buildv001/desktop_debug_macos/mojo_app.h' file not found
#include <modules/mojo/mojo.buildv001/desktop_debug_macos/mojo_app.h>
         ^
1 warning and 1 error generated.

?[?] : Error :Execute failed
[PhilMac:~/Downloads/monkey2/src philippeback$]




impixi(Posted 2015) [#10]
Woohoo, thanks Mark.

Since I'm no longer supporting MX2 through Patreon, I purchased another Monkey X Pro license I'll never use. Hope that's acceptable...


taumel(Posted 2015) [#11]
Woohoo, a christmas present. I won't have time to play around with it today but so far: a) would be nice having an executable for os x, b) compiling ted2 worked (didn't bother to add emscripten), c) demos worked, d) ted2 only worked in fullsize/fullscreen (otherwise you couldn't click on stuff, i liked the reduced flat look), e) no OnUpdate() anymore? f) from the Auido section it's just PlaySound, no Chanel/Volume/Pan/Pitch controls yet, right? Anyway, thanks Mark. [OS X 10.11.2] Oh and Stargate suffers from QWERTZ/QWERTY issues.


ElectricBoogaloo(Posted 2015) [#12]
Kewly.. Nice to see it's already in a fairly stable status.

Findings..
Open doesn't work! I can click on a banana from that frontpage thing, and those work fine, but actually clicking Open and selecting a .monkey2 file causes TED to crash. I'm not sure if that was intentional (eg, it is a demo, after all!!) but .. thought I'd mention it, just in case!!

Compiling works fine, audio's working, graphics are moving about, all is good. Hitting Left-Alt and Return causes it to try switching to fullscreen, but it fails miserably on my system. (Win10, 1920x1080 res) It seems to want to try to do it, but just doesn't manage at all! Note : Alt+Return seems to work on all demos, so if this isn't intentional, apologies for finding it :D
..Resizing the window seems to work fine, though, where available.

Everything's looking nice and capable, and the renderer demo in particular is lovely!
Can't wait to see what juicy extras you could add to a new mojo2d. DrawLight and Shadow sound like nice additions.
ImageCollision would be a godsend, but .. I know how complicated that is.


dmaz(Posted 2015) [#13]
[edit]solved... I had GCC_EXEC_PREFIX set in my env... clearing that in bin/env_windows.txt works and would probably be a good idea[/edit]

I'm assuming I should be choosing 'run' from ted2 should build and exe on windows right? I'm just getting "Command failed"... (transpiling seems successful)
no copy/paste from the console...

g++ (tdm64-1) 4.9.2
...
Parsing...
Semanting...
Translating...
Compiling...
Command failed:
g++ -std=c++11 -m32 -g -O0 -I"." -I"C:/Users/Dave/Downloads/monkey2/bananas/helloworld/helloworld.buildv001/build_cache/desktop_debug_windows" -I"C:/Users/Dave/Downloads/monkey2/bananas/helloworld/helloworld.buildv001/desktop_debug_windows" -I"C:/Users/Dave/Downloads/monkey2/modules/mojo/mojo.buildv001/desktop_debug_

the the console must hit it's horizontal limit

tried it also by putting monkey2 into the root of c... and removing all other gcc paths from my path.... same result.

running win10 64

[edit]if I try to build the modules from and admin cmd window I get


JaviCervera(Posted 2015) [#14]
Great work. I love the GUI module, seeing Ted2 implemented with it is truly amazing. Any chance that we will see it ported to Monkey1?


arawkins(Posted 2015) [#15]
Thanks Mark, this is a great xmas present :) It's running ok for me on Xubuntu 14.04. TED2 is looking nice so far, and the readme was really appreciated. Some of the features are going to be really handy. The html view, debugger, etc...can't wait.




Danilo(Posted 2015) [#16]
Thanks Mark! Just compiled it (without problem) and taking a look now.

@TheRedFox:
Are you using an older version of Xcode? (Apple LLVM version 6.1.0 (clang-602.0.53))

It worked out-of-the-box for me using latest Xcode 7.2 and OS X 10.11.2 (El Capitan):

PS: Happy birthday! ;)


TheRedFox(Posted 2015) [#17]
Ah, having to upgrade to El Capitan just for having a new XCode. Meh.

The thing works on Windows nicely, I'll keep it there for the moment.

PS: Thx :-)


marksibly(Posted 2015) [#18]
> I had GCC_EXEC_PREFIX set in my env... clearing that in bin/env_windows.txt works and would probably be a good idea

Yikes, that's a new one on me. How should I 'clear' it in env_windows.txt? like this?

GCC_EXEC_PREFIX=



abakobo(Posted 2015) [#19]
Will I have to upgrade my mavericks to get it work on osx? Really don't want to...
Which minimal xcode version is required?

Can't wait for the docs and all the greats stuffs to come!


degac(Posted 2015) [#20]
Oh! Thanks!
A new toy for Xmax!!!

edited:

just looked deeper... too many questions! :D

"Assets::"

I suppose MX2 'handles' all resources (sound, gfx, fonts, datas etc) in a folder (Assets).
I like this approach.

GUI... it's a mistery to discover!

ps: TED2! has a 'good' feeling (maybe it's due to the gui), it's so 'linear'... it's like you have nothing to worry about (but where are options for debug?)

Thanks Again!


wiebow(Posted 2015) [#21]
Ohh, I've tried all the demos and it's working really well over here!! I LOVE the defender clone, although the control method is ... I dunno ... :)
Trying to make sense of the code but it still is a bit confusing, some of the language features make no sense to me at all at the moment but we'll see once the docs are coming along. So far so very good. Call me intrigued..


dopeyrulz(Posted 2015) [#22]
Was thinking about the docs - Microsoft for Visual Studio Code and ASP.net use Github to maintain theirs. Perhaps this could be a solution??

All working well for me on Windows 10. Looking forward to taking a closer look at the code examples!


EdzUp MkII(Posted 2015) [#23]
Very nice, one Windows issue for me was clicking new to make a new source file there was no way that I could discern to close it (I clicked it three times to see if its was opening and ended up with three untitled.monkey2 files :\).

Apart from that its looking mighty nice :)


dmaz(Posted 2015) [#24]
Yikes, that's a new one on me. How should I 'clear' it in env_windows.txt? like this?
yes, that's exactly how I did it.


marksibly(Posted 2015) [#25]
Cool, I've just uploaded a v2 demo with this fix in.

Also uploaded a new v2 source zip that *might* help with building on older MacOSs.


taumel(Posted 2015) [#26]
@abakobo
El Capitan is a good update, in all my use cases it runs better than Mavericks, on old and new machines.


Roger Lockerbie(Posted 2015) [#27]
Hi - El Capitan with latest xcode M2 compiles fine but Ted2 text font is borked (blocks with fringed edges instead of text) - I'll upload a screenshot later.... Can manually compile stargate etc. which works fine.

-Rog


Armitage1982(Posted 2015) [#28]
Hi Mark

I saw your Christmas post about Monkey 2 and give it a try :)

Sorry but under my Windows 10 64 bits config every projects just "building" forever and nothing happen (no new window or working state even as admin...).
Also, the text rendering quality of the editor is clunky. That's all I can say, I did not spot any error log files or anything.

Anyway : Merry Christmas ;-)


Danilo(Posted 2015) [#29]
Hmm, editor font worked here on OS X with MX2 Xmas demo v1.


dmaz(Posted 2015) [#30]
v2 worked for me out of the box now.

Ok, I played around and read everything and I like where this is going.

I noticed that parens are still not required for Print or any other keyword and also not required for constructors. They do seem to be require for other functions/methods? nice compromise if that stays.

The reflection / serialization stuff sounds great especially when combined with the ide dll plug-in idea you mentioned! Though instead of building a full functioning editor/ide, IMO you should follow the Atom or MSCode model and build a core and standards that can be extended with plugins(or just code) built by us. I can think of 100 things that should be added to that editor and that's, not only a lot of work... some people just don't want the same things I do. so don't waste you time with code folding (something I never use), etc... or intelisense which I love, but not when it's in my face all the time so I'd like it dock-able. another, smooth scrolling... there's no way you should waste your time with that, but if you give us the hooks we'll do it...

The GUI stuff is pretty sweet actually, I like the way if feels.

The real-time debugger sounds great... what about hooking in profiler too.... :)

I didn't see any mention of closures though... I hope you didn't scrap those?

little things...
- I think you should deal with high DPI displays before it gets too out of hand... on my windows computer with a high dpi monitor that font is even more fuzzy when scaled.
- while I like the idea of the package being it's own complete archive.... how are you going to handle our third party modules, we don't want to copy them to new installs each time.

Very Nice!


dmaz(Posted 2015) [#31]
@Armitage1982, what does it show in the console window?


DruggedBunny(Posted 2015) [#32]
All demos working fine here on Windows 7 64-bit.

I thought the homebrew edit control would bug me, but it actually works really well -- my only niggles are Ctrl + Left/Right should jump identifiers (especially in combination with Shift for quick selection), and the block cursor suggests Overwrite mode rather than Insert mode to me, which made me notice that Overwrite mode isn't an option -- not that I would ever use it, but I still see BIG RECT as Overwrite!

Mouse scrollwheel could use some acceleration for my taste -- I also like middle-mouseclick followed by Up/Down mousemove to scroll in my text editors/viewers, for what it's worth!

Noticed the editor still says "Building" when it's actually running the program, which left me wondering for a while. (The first build had somehow ended up behind everything else.)

Yours pedantically, etc... !

(Don't think I'm in a position to comment language-wise, as it stands, as it pretty much looks like Monkey for what I'd actually use, having no interest in refactor-y, test-driven, horribly formal Interface-oriented xyz features... BlitzMax is pretty much perfectly OO-enough for me!)


DruggedBunny(Posted 2015) [#33]
I just noticed in Notepad++ that most .monkey2 files display with a specific terminating [NUL] character, whereas I haven't seen this in any .monkey file ever -- try helloworld.monkey2 for an example. Not sure if it would ever be an actual problem...


mjcamerer(Posted 2015) [#34]
Compiled and ran out of the box without any issues on Win 7 Pro 64bit. Great progress! Was fun to mess around with and explore. Keep it up!


Roger Lockerbie(Posted 2015) [#35]
Weird that I'm the only one getting the font distortion on Ted 2.

* Rebooted
* Unpacked the OS/Linux v2 distribution from Mark
* Built via rebuildall.sh (clean directory structure)

Result below




GC-Martijn(Posted 2015) [#36]
@Roger Lockerbie @mark
I have the same 'font' issue on osx (older version)


taumel(Posted 2015) [#37]
Similar issues popped up on Unity when they moved on to their new desktop GL renderer, causing issues on certain low/high res display in combination with different driver support for each hardware.

Btw. Ted2 doesn't support retina displays, it's all lowres (also if you don't get messed up text).


Rumphiz(Posted 2015) [#38]
Thanks Mark,

Fonts are a bit blury as other people have mentioned but apart from that works fine here (Win7 64bit).

I like the way it just works out of the box and reading through the docs has me excited for Monkey's future.


Pakz(Posted 2015) [#39]
When I start ted then the window top and bottom is outside the screen (can not access the top bar buttons). When I jiggle/stretch the ted window then it pops to fit the sreen.


degac(Posted 2015) [#40]
@Edzup


Very nice, one Windows issue for me was clicking new to make a new source file there was no way that I could discern to close it (I clicked it three times to see if its was opening and ended up with three untitled.monkey2 files :\).



On the top right of IDE you should see a list of name (untitled. etc). If you hover with the mouse a 'X' should compare to delete/close it.


taumel(Posted 2015) [#41]
@Mark
One aspect i wonder about, is how will the future of sound look like in monkey2.

Which engine/lib will drive the audio?

What kind of features do you intend to support?


k.o.g.(Posted 2015) [#42]
windows 10 32bit, all demos works .

99€ Tablet from Medion :)


Tibit(Posted 2015) [#43]
I'm super impressed! Got it running on first try on my Macbook.

I especially like that the Stargate game is as complete as it is, having victory conditions, lots of graphics, effects, menus - looking forward to seeing it on the app stores in the future! :)

I also liked the html view - this way of setting up how menus work makes so much sense to me. Is this something that might support media-queries (responsive design)?

Still trying to get ecmascript target to work - I have it working in console when I type "emsdk" yet I get this when following the instructions:
Can't find emcc - please install emscripten or update your bin/env.txt file <-- and I also have the env.txt for mac pointed to the emsdk dir on my desktop.

Ted2 also off to a great start - mostly missing API/docs of classes/command I select that I can view in the sidebar of the editor so I can quickly learn and use all the new things, and ofc the ability to pin "build files".


marksibly(Posted 2015) [#44]
> Since I'm no longer supporting MX2 through Patreon, I purchased another Monkey X Pro license I'll never use. Hope that's acceptable...

Thanks very much!

> some of the language features make no sense to me at all at the moment

Which ones? It should all be pretty obvious if you've messed with monkey1, with the exception of perhaps the Lambda() stuff - which once you learn it (and it's not at all hard) is incredibly useful!

> I didn't see any mention of closures though... I hope you didn't scrap those?

Lambdas *are* closures AFAICWO.

> on my windows computer with a high dpi monitor that font is even more fuzzy when scaled.

How are you scaling the fonts? My plan was basically to just have a global FontScale that gets applied to font height when you use Font.Open().

> most .monkey2 files display with a specific terminating [NUL] character

Should be harmless, but will fix.

> Ted2 text font is borked

Sounds like a GL bug to me. What are your Mac specs? I'm on a Mac Mini with Intel HD Graphics 4000, El Capitan.

One thing you could try is adding 'canvas.Flush()' to the Render method in modules/mojo/view.monkey2, just after the OnRender( canvas ) call at (approx) line 436. You'll need to rebuild mods after this though - cd to 'src' and './updatemods.sh'.

> Which engine/lib will drive the audio?

I'm currently using SDL_Mixer, which has similar capabilities to mojo1 audio, but unlimited channels and some cool additions such as the ability to 'post mix' audio with custom code etc - although I assume this runs on a different thread so wont be (easily) usable in mx2 yet.

> I also liked the html view - this way of setting up how menus work makes so much sense to me. Is this something that might support media-queries (responsive design)?

The litehtml lib is pretty limited, but I really just wanted it for displaying custom documentation etc anyway (also wanted to test out externing some 'real' c++ code too), eg: the mx2 docs, the defender title screen. You wont be able to throw any old html/css at it, most docs will probably require some level of tweaking.

That said, it does handling a surprisingly wide range of css, including I think some media queries. There's a litehtml browser you can play with to get an idea of its capabilities here:

http://www.litehtml.com/download.html

I almost had the monkey1 docs showing cleanly in it, and those use some bizarre css!

> the block cursor suggests Overwrite mode rather than Insert mode to me

Yes, there will be overwrite, but there will also be the option to use a block cursor in insert mode, because the aggro of hunting down a 2 pixel wide rect in the midst of some complex source code is a pet peeve of mine! Didn't use to be this way before the PC did it?


wiebow(Posted 2015) [#45]
Hi Mark, I have not played with Monkey 1 for YEARS (I returned to Max), so it's definitely my problem. I hope the docs, once they are added, will get me back up to speed. Remember, I'm a Basic fossil, so I do not know how to properly use the fancy programming features you've added... :) And yes, I have not even heard of Lambda in programming. Reading the Wikipedia page about it confuses me even more!!! I desperately need tutorials and docs, haha.


marksibly(Posted 2015) [#46]
Just hacked together a dodgy (and exaggerated!) version of Apple's completely pointless yet super sexy 'frosted glass' effect:




taumel(Posted 2015) [#47]
@Mark
Having access to features like pan/pitch/fft/volume/channel control (allocating channels in Max was a easy and lazy way to define things)/read write access to the data/load&save (wav/[aiff/flac/]ogg)[/your mic] offers many possibilities. I would choose whatever audio engine supports such a small but important set of features best. I also wouldn't mind a tiny set of realtime filters and some mixing. It can add a lot to certain types of 2d games and for 3d you'll need positioning and stuff anyway.


nullterm(Posted 2015) [#48]
I brought this up before, but do you think it'd be possible to have something like a dealloc/destructor/finalize? Even if it's not immediate or delayed, it would make freeing up OpenGL resources (textures, shaders, vertex buffers, etc) alot easier.

I like Monkey's more Java-eqsue philosophy of "allocate it, and I'll take care of it for you". But a language driven mechanism to cleanup resources based on GC would be a big help.

Same way that a mojo Image or Sound get cleaned up automatically.


dmaz(Posted 2015) [#49]
> I didn't see any mention of closures though... I hope you didn't scrap those?
Lambdas *are* closures AFAICWO.

my bad, shoot... I keep saying closures when I actually mean coroutine.

How are you scaling the fonts? My plan was basically to just have a global FontScale that gets applied to font height when you use Font.Open().

Windows 10 is scaling them for me... if the program is "dpi aware" then it reads the current windows scale setting and should change it's interface and all fonts by that amount. if it's not "dpi aware" then win10 will actually scale the window itself... making it blurry. I can turn it off per app but ted2 end up way too small on this monitor then.


marksibly(Posted 2015) [#50]
> my bad, shoot... I keep saying closures when I actually mean coroutine.

I haven't scrapped them, but at the same time I'm not quite sure how best to implement them in monkey.

I'm sort of waiting until I run into a situation where they'd be useful, but I have a feeling that's coming soon - possibly when I attempt 'Close All' again.


taumel(Posted 2015) [#51]
@Mark
How has the garbage collector changed (compared to Max/Monkey)?


Roger Lockerbie(Posted 2015) [#52]
@MAK

MacPro laptop retina with discrete (Nvidia) graphics as well as embedded Intel (OSX chooses which one to use).

* Tried canvas.Flush() fix as suggested
* rebuilt mods (also did rebuildall.sh as well - to be safe)
* Font still broken
* Have confirmed via activity monitor that ted2 is using high performance gfx (e.g. Nvidia) - looking for a download to force OSX back to embedded only to confirm/deny whether Intel integrated versus Nvidia discrete is the source of the font corruption. Will report back with outcome.

Regards
-Roger


Roger Lockerbie(Posted 2015) [#53]
@MAK

Confirmed - using the gfxCardStatus utility I could force my macbook into using Intel rather than selectable graphics - result was that the font was fine - so some issue with font's/GL on Nvidia discrete chipsets on mac laptops.

Regards
-Roger


marksibly(Posted 2015) [#54]
Thanks for that Roger.

Fonts are just images so I have no idea what's up - do the bananas work?


Roger Lockerbie(Posted 2015) [#55]
Mark

Other comments would be that it also affects the scrollbar, stargate compiled and played fine, but the font with the score was broken there. Likewise Hello World was borked.

Renderworld worked fine.

So problem seems constrained to fonts. however Fonts in HTML view work ok.

Regards
-Roger


Beaker(Posted 2015) [#56]
Concerning Rogers font issue. Has anyone tried loading the font into an image editor and setting all the fully transparent pixels from white to black? As mentioned here with a similar issue in mojo2:
http://www.monkey-x.com/Community/posts.php?topic=9823&page=7
(see my comment near the bottom)

May or may not be related.


Beaker(Posted 2015) [#57]
Mark - well done on Stargate. It's suitably intense!


degac(Posted 2015) [#58]
Question (maybe dummy question...)

A snippet taken from MX2 dialog.monkey2

Class NotifyDialog Extends Dialog
	Field Okay:Void()
	Method New( title:String,text:String,width:Int,height:Int )
		Super.New( title,width,height )
		ContentView=New View
		ContentView.Label=text
		'-------
		AddAction( "Okay" ).Triggered=Lambda()
			Okay()
		End
                '-------
	End' of method
	
End' of class


I really don't understand the section (marked by me with -----).
I understood it's called a method AddAction() and then the Triggered field is *passed*associated* to something with the command Lamda().
I don't know what is Okay() (I haven't found a function or a method, just a Field... maybe I missed some files).
So I have no clear the meaning of this code.

Same for
		_title.Dragged=Lambda( delta:Vec2i )
			Translation=Translation+delta
		End

Here I understand that the value Delta is passed/received from the Lambda()-thing, but again I don't understand where the information is taken.
Lambda() what exactly does in these examples?



ps: with the release of MX2 to the public I suppose there will be many questions about the different syntax.
I don't think 'mixing' MonkeyX1 and MX2 is a good idea.


Pharmhaus(Posted 2015) [#59]
Field Okay:Void()

In Bmax it is possible to store functions in variables. MX2 has improved version of that. It allows you to store a function/method in a variable.
The :Void() simply states that all functions/method that have no parameters and return void could potentially be stored in the Okay field.

		'-------
		AddAction( "Okay" ).Triggered=Lambda()
			Okay()
		End
                '-------

A Lambda is basically a function/method without a name. It is useful to define something ad-hoc just before you need it.
It is frequently used to program in a more result centric way. The idea is to not think too much about how your program solves a problem. Instead you focus on the expected result / algoritm and all the dirty stuff happens under hood. This results in more readable code which is closer to the actual problem you are solving. The Lamda in this example takes 0 parameters and thus can be stored in the Triggered Field because it fits the definition
Class Action

	Field Triggered:Void()
....

It is the equivalent of method which returns Void and takes no parameters/arguments.


marksibly(Posted 2015) [#60]
> I really don't understand the section (marked by me with -----).

Ok, let's give this a shot...

AddAction() returns an 'action' object, that has a 'Triggered' field that looks like this:

Field Triggered:Void()

This is a 'function variable', ie: a variable that 'holds' a function. So it must be assigned a function, and this what 'Triggered=Lambda()...' is doing - assigning a 'lambda function' to the Triggered field of the action returned by AddAction. It's really no different from something like: AddEntity( "MyEntity!" ).X=100.0, only it's assigning a function to a field instead of a float. You can assign any kind of function to Action.Triggered, eg: a global 'Function', a member 'Method', a temporary 'Lambda' or a value from an existing 'function variable'. Here, I've chosen to use a Lambda function.

The best way to think of a Lambda function is probably just as a 'temporary' function. This code inside a Lambda function can 'see' outer locals and fields (actually, it only sees a 'snapshotted' version of outer locals...), so in this case when the Lambda function function calls 'Okay()' it is indeed calling the outer 'Okay:Void()' field - yet another function variable that code 'outside' the dialog can assign a function to. In other words, when 'client code' creates a NotifyDialog, it'll do something like this:

Local dialog:=New NotifyDialog
dialog.Okay=Lamba()
    Print "Okay!"
End


(Is it 'right' to use public fields for things like 'Okay', 'Triggered' etc like this? Possibly not, but I'm sticking with it for now.)

A lot of this is inspired by Qt, which calls such function pointer fields like Triggered:Void() and Okay:Void() 'signals', and you connect them up to special 'slot' methods. In mx2, you can still think of 'Triggered' and 'Okay' as signals (and I'll probably end up referring to them as such in the docs) only you can connect them up to any kind of function, not just special 'slot' functions.

In this case the code is, in a sense, 'converting' one kind of signal (Action.Triggered) into another, more specific signal (NotifyDialog.Okay). Actually, Action.Triggered is itself just responding to a Button.Clicked signal, so when the user actually clicks on the Okay button, the actual 'flow' of signals is:

Button.Clicked -> Action.Triggered -> NotifyDialog.Okay -> Your dialog 'okay' handling code!

(Eventually, you'l be able to assign 'hotkeys' to actions, so Action.Triggered may not be always be caused by a button click).

A simpler example of signal use is a button, that has a 'Clicked()' Signal:

Local button:=New Button( "My Button" )
button.Clicked=Lambda()
   'when the button is clicked, this code is run!
   'the code can see the 'button' var, and, if we're in a  method, the fields of the object.
End



marksibly(Posted 2015) [#61]
Nice explanation too Pharmhaus!


Shinkiro1(Posted 2015) [#62]
First of all, this looks great!
The samples, language features and even TED (I like the direction).

One thing I noticed is that you can't have an #Import on the first line of a source file.
It will fail to compile with: 'Expecting module member'
Moving that down 1 line fixes it.


degac(Posted 2015) [#63]
Local button:=New Button( "My Button" )
button.Clicked=Lambda() 'Note: could be a method, function etc instead of a lambda...
'when the button is clicked, this code is run!
'the code can see the 'button' var, and, if we're in a method, the fields of the object.
End

Ah! Ok, now it's clear the role of Lambda() and the syntax used! it's just a 'marker'!

Thank you very much to Mark and Pharmhaus!

ps: indeed the code is very readable... a very nice feature!


ziggy(Posted 2015) [#64]
@Mark: Very nice demo! How mature is the current parser? Is it very subject to change? I want to get a Jungle ide parser for it ASAP. Love the new language features.

That said, are we going to have single line lambdas? Some languages allow for single-line lambdas where data kind returned is inferred by the expression, and where Return sentence is avoided:

Local myFunction := Lambda(item:Int) item < 2

This would be a lambda that gets an integer and returns a boolean. Return keyword is avoided as it is "a single expression" lambda.

That's ultra handy with collections, where you can do quite complex logic in a very simple way. As instance we could have List methods like:

Local myList:=New List<String>
....
Local firstItemStartingWithM := myList.First(Lambda(item) item.StartsWith("M"))


Notice that, In this case, the "item" parameter data kind is inferred by its usage. The function First is defined like: List.First:Bool(condition:Bool(T)), so the anonymous function parameters and return type can be inferred by the function where they appear as a parameter, that is, the "First" function definition of the List object.

This alows for ultra nice expressions to do things like get if any item of a collection accomplish a given condition:

if myStringsList.Any(Lambda(item) item.Trim().Length=0) Then Print "The list has empty strings!!"


Or much more complex logic expressed in a very simple way.
That can be very handy (I know my examples are very sily, but I gess it shows the idea).


taumel(Posted 2015) [#65]
@Mark
Also related to the gc, will there be(/is there) something like ValueAtIndex?


Danilo(Posted 2015) [#66]
Why not use Function instead Lambda?
button.OnClick = Function()
    Print("Button clicked!")
End

I think it's more clear, also for people who have never heared about Lambda before.


degac(Posted 2015) [#67]
Probably to avoid semantic confusion in the compiler/translator


dmaz(Posted 2015) [#68]
> my bad, shoot... I keep saying closures when I actually mean coroutine.
I haven't scrapped them, but at the same time I'm not quite sure how best to implement them in monkey.
I'm sort of waiting until I run into a situation where they'd be useful, but I have a feeling that's coming soon - possibly when I attempt 'Close All' again.

They are great for any kind of iterator but in Unity the 'default' is to yield until the next frame which is super sweet for any kind of animated effects.
protected IEnumerator MoveTo( Vector3 end, float seconds ) {
		float elapsedTime = 0;
		Vector3 start = rb2D.position;

		while( elapsedTime <= seconds * .999f ) {
			elapsedTime += Time.deltaTime * inverseMoveTime;
			rb2D.MovePosition(Vector3.Lerp(start,end,elapsedTime));
			yield return null;
		}
		transform.position = end;
	}
}

What I really really want though is...
Yield Wait(3.0)
and
Yield Lambda()
End


Danilo(Posted 2015) [#69]
@degac:
That shouldn't be the case. It's the only occurrence where 'Function' occurs on the right-hand side (RHS).
The keyword 'Function' does not occur on RHS (as an expression) otherwise.

See also: Lambda Expressions (Visual Basic)

If the compiler gets confused by this, something would be wrong with the compiler.

Just compare the 2 snippets:
button.OnClick = Function()
                    Print("Button clicked!")
                 End

and:
button.OnClick = Lambda()
                    Print("Button clicked!")
                 End

Almost the same, but BlitzMax and VB.net guys, who want to convert to super-cross-platform MonkeyX 2,
probably find the 'Function' more intuitive and easier to read and to grasp.

I can get used to use Lambda(), no problem. The question is, why not make it more easy
and understandable for newcomers, outsiders and converts - while 'Function' is more inuitive and common at the same time?


GC-Martijn(Posted 2015) [#70]
@mark
Which linux os do you use ?
Im now using osx, but want to see how Ted works on linux. I want to keep it 1:1 with you, to keep it working out of the box.
Crap auto correction in Android...


marksibly(Posted 2015) [#71]
> How has the garbage collector changed (compared to Max/Monkey)?

It's currently very similar, but that will change as soon as any threading stuff happens.

> Concerning Rogers font issue. Has anyone tried loading the font into an image editor and setting all the fully transparent pixels from white to black?

Fonts are generated on the fly though, so you can't do this.

> Mark - well done on Stargate. It's suitably intense!

Thanks! It's way too hard (and only really defender right now) but I intend to keep hacking at it in my spare time. Totally enjoyed writing it too, coming up with a small 'Actor' framework etc bought back a lot of memories of what's possible with games...

> Why not use Function instead Lambda?

Because a lambda is not a 'function' in the monkey sense - it works in subtly different ways (capturing locals, self etc) that affect how it's used. Ditto a method is not a function, even though it's also 'callable'. There would be no problem using 'Function' in the parser, but I think it's more monkey-like to use the 'real' name of constructs as much as possible instead of reusing similar names.

I think it's also a little less confusing to read - using 'Function' inside a function makes the nesting a little fuzzy - and possible even a bit educational!

> Which linux os do you use ?

I'm using Mint 19.2 Cinnamon. Great distro, but you may ned to apt-get quite a bit of stuff to get it building monkey.

The distro Richard Betson is using - Mint "Rafael" I think - looks like it might be a bit easier to get started with. Either way, Mint is mint!


marksibly(Posted 2015) [#72]
> How mature is the current parser? Is it very subject to change?

Quite mature, though I am 90% through the monkey2 rewrite. Do you you plan to use this code directly, or derive your own code from it?

I'd also quite like your opinion on how I'm going about handling parse errors, ie: via exceptions. I found this a little 'grindy' but couldn't really think of a better way to do it if I want the parser to be able to catch multiple errors.

> That said, are we going to have single line lambdas?

Dunno yet, but I'm a tad dubious. They don't add anything to what the language can do, and IMO can make for some damn ugly code. These look OK to me:

Local myFunction:=Lambda:Bool( item:Int )
   Return item<2
End

Local firstItemStartingWithM:=myList.First( Lambda:Bool( item:String )
    Return item.StartsWith( "M" )
End )

If myStringsList.Any( Lambda:Bool( item:String )
   Return item.Trim().Length=0
End ) Then Print "The list has empty strings!!"


Dunno, I think my urge to stick everything on one line has mellowed over the years! But I'm also new to this stuff myself so I kind of prefer having it all explicitly laid out without any shortcuts. Perhaps that'll change too as I get used to it all.

And I haven't really tackled the comparable/sort predicate etc stuff in containers yet though (and the above looks useful) so perhaps I'll find the idea more appealing after that.

> protected IEnumerator MoveTo( Vector3 end, float seconds ) {

A little confused by that code - it never actually returns an IEnumerator, although I think I get what it's doing.

>What I really really want though is...
Yield Wait(3.0)
and
Yield Lambda()
End


Yield wait( 3.0 ) could be...

New OneShotTimer( 3.0 ).Fired=Lambda()
    'do something after 3 seconds!
End


Yield Lambda() is a little confusing though - do you mean 'execute this chunk of code on next update? eg:

New OneShotTimer( 0.0 ).Fired=Lambda()
    'do something on next update!
End


There'll probably be an 'Idle' signal too that you could use for the latter...
App.Idle+=Lambda()
    'do something on next update!
End


...and note I'm not saying that these are necessarily better - or even good - ways of achieving what you're after. Just possible ways...! There will be timers, so this approach will be at least one way.


Nobuyuki(Posted 2015) [#73]
@Danilo
Almost the same, but BlitzMax and VB.net guys, who want to convert to super-cross-platform MonkeyX 2,
probably find the 'Function' more intuitive and easier to read and to grasp.


VB.NET guy here; our Lambda syntax is absolutely terrible and is garbage for readability. MX2's is somewhat better. I'm still hoping that 1-line Lambdas use the Lambda..Returns (or similar 2-unique-keyword) syntax to make visually identifying the LHS/RHS of the function expression easier, but so far it looks like an improvement to me.


taumel(Posted 2015) [#74]
@Mark
Okay, Max like index access to lists a.o. was an easy way to create and deal with many objects without running into possible gc hickups.

Jarvis' GDC talk about Robotron is fun and Defender's laser gun fire is one of the best in the history of video games. I disagree on difficult controls by design.


marksibly(Posted 2015) [#75]
> Okay, it would be nice having Max like index access to lists.

I disagree. Indexing a list is an O(N) operation - ie: slow - and I think the [] operator should be reserved for O(1) or at least fast-ish ops.

I have made an exception for indexing a map, which is O(log n), but I'm not doing it for lists. Too open to abuse.

Besides, I'd recommend avoiding lists altogether these days - perhaps for Deque-ish ops, but for most everything else a Stack is IMO a better choice.

> i disagree on using difficult controls as a reasonable design element.

I have no idea what a 'reasonable design element' is but the controls are simply my preferred controls on MAME.

(Actually, they were originally '/' for thrust and 'right shift' for fire, but that caused the windows 'sticky shift' mode to fire...then tried apostrophe enter, but that ran into Alt-Enter problems!)

I prefer them maybe just because I'm used to them (they're based on the original game), but I also believe they give much finer control - being able to 'flick' reverse quickly without having to 'swap arrow keys' works really well - ditto for thrust. With arrow keys, reverse and thrust are 'swapped' depending on which direction you're facing. The original game could've just used a 4 way joystick too - and it no doubt wouldv'e been much cheaper, they spent a bomb on the custom controller setup - but I think they decided the same thing.

I used to be able to get a million something on stargate, and I doubt that would've been possible with a four way joystick - but I'll eventually add a 'beginner mode' and we can start comparing high scores! *If* I was actually selling the game, I'd probably have it default to 'beginner', but I'm not.


dmaz(Posted 2015) [#76]
In C# coroutines are based on iterators so that's why you need that return type. Many collections are built with this and do actually return an enumerators...
public IEnumerator<T> GetEnumerator() {
	foreach( T v in storage.Values ) yield return v;
}


Yield wait( 3.0 ) could be...

yeah, but what I was thinking was more for scripting of events where yield gives you more flexibility. In bmx I would have this verbose state machine with substates just to transition from one level to the next. like say you just finished a level, so now you...
- pause a couple seconds.
- slide in a stats overlay panel.
- do some animated stat calculation.
- pause a couple seconds.
- slide the stats panel off screen.
- pause a couple more seconds.
- set the level state machine to the next level.

this is where coroutines would clean this up a lot.

Yield Lambda() is a little confusing though - do you mean 'execute this chunk of code on next update? eg:

that might have been a bad example... what I meant was yield to a function until that function yields back... i.e. chain the coroutines. (I said lambda thinking it would be cool not having to declare the function/method)

it would be great to...
yield SomeFunction()
which can then get us...
yield nextUpdate() ' until next update
yield nextFixedUpdate()
yield nextRender()
yield Wait()

I've just used them in C# and I don't know the best way to implement any of this... but languages that do, can do it quite differently with different capabilities.

https://en.wikipedia.org/wiki/Coroutine#Implementations_for_C


taumel(Posted 2015) [#77]
@Mark
Yep, i'm aware of that it wasn't a "nice" way but practically it was effective for ensuring stable frame rates within a sweet spot, maybe offering some control over the gc could be nice.

Regarding controls: When i was playing Stargate, i had to remember some Arcades (like Jarvis' Defender) and whilst i enjoyed them for certain aspects (like pacing, gfx and sfx), i disliked them for having screwed up controls by design in order to increase the challenge for the player. This only worked for a few games. In most cases it felt like bad design. I guess i enjoyed the VCS version of Defender more than the Arcade. :O)

Did i mention that out of the box working gamepad support would be awesome already?!


Danilo(Posted 2015) [#78]
@Mark & Nobuyuki:
Thanks for your feedback and opinion, and let's hope Lambda() gets properly documented.
Including the scope, how it works/interacts with 'this', etc.


skid(Posted 2015) [#79]
I have same font issue on 2010 Mac Mini. Tried changing mojo2 data font to power of two but no help.

Chrome and other apps have also been suffering from GL issues in last few weeks leaving a trail of badly drawn rectangles when doing highlights so I currently blame Apple and expect updated driver to magically appear in next couple of weeks to fix it.

If it is a valid Apple optimisation to GL pipeline then xcode gl diagnostic and analysis tools may help detect the issue.


Roger Lockerbie(Posted 2015) [#80]
@Skid/MAK

Simon

Re: GL Issues - I have noticed since I upgraded to el capitan. I've had back rectangles sometimes in the Browser (typically Facebook?)

Re: Font - I thought it was down to Nvidia chipset/driver as when I force reverted Ted2 to the internal Intel chipset the font rendered ok. Does the 2010 Mac Mini have a dual graphics chipset (Being a mini I would of thought it was solely a onboard INTEL).

That said the rectangles have not occured in a while and I *thought* they went away with el capitan 10.11.2.....

One possible option is that Ted2 doesn't need to do whatever is forcing OSX to decide it needs to run in performance mode - but that won't then help for subsequent games that do need perfomance mode.

Doing a bit of reading (thats somewhat dated) seems to imply that any use of OpenGL means the OSX autoswitching uses the discrete card when available - so it may be impossible for Ted2 to run on the embedded chipset on these machines.....


Roger Lockerbie(Posted 2015) [#81]
@Skid/MAK

Similar looking issue here - too much low level stuff in this thread for my brain - no idea if Ted2 uses a shader or anything like that. Buried in the subcomments is a 1 pixel packing comment which I seem to remember being a MX1 issue? - Anyway posting on the off-chance it may be useful

http://stackoverflow.com/questions/27430811/text-not-rendering-correctly-opengl-using-freetype2


taumel(Posted 2015) [#82]
GL issues related, switching to the dedicated GPU (if you have the option) can help to avoid/reduce certain GL problems.


Roger Lockerbie(Posted 2015) [#83]
@Taumel

In this case its the reverse - utilising discrete nvidia gfx chipset causes problem, forcing OSX to revert to onboard Intel chipset means the problem does not occur.


taumel(Posted 2015) [#84]
I'm not experiencing the text block issues with Ted2 but i've seen them, primary temporarily, in OS X before El Capitan already.

Thinking of the GPUs Apple has used in their Intel MacBooks (let's say from GT330M up to the R9 M370X) it's has always been less trouble with the dedicated GPUs. Intel's 6100 is working better than some of their older GPUs, at least here.


dawlane(Posted 2015) [#85]
Well I finally got round to a day when I can start to have a play with this after messing around with MonkeyX and adding a few bits for GLFW.

So far Ted2 on Linux crashes when you drag a scroll bar and then release the mouse button out side of the GUI window. And something has messing up the encoding of a few of the monkey2 source files. gEdit has a problem opening them.

Will mx2 be ale to use import or another type of compiler directive to add code snippet files directly within a piece of code?


ziggy(Posted 2015) [#86]
> How mature is the current parser? Is it very subject to change?

Quite mature, though I am 90% through the monkey2 rewrite. Do you you plan to use this code directly, or derive your own code from it?

I plan on extending current Monkey parser to support Monkey 2 syntax. Currently there are not lots of complex changes other than funciotn pointers and parenthesis for functions, and lambdas. then, there's the imports system, which I'm not 100% sure how it works but as all imports solving system can be replaced very easily on the derived parser, I think this *could* be the fastest/easiest way to provide mx2 support soon.

> That said, are we going to have single line lambdas?
Dunno, I think my urge to stick everything on one line has mellowed over the years! But I'm also new to this stuff myself so I kind of prefer having it all explicitly laid out without any shortcuts. Perhaps that'll change too as I get used to it all.

Well, if we ever get any kind of mocking capabilities to the language, single-line shorter lambdas can make mock construction code a lot more readable!

Then, how is finanlly multiple sentences on a single line handled? Did you finally took the ; is optional at the end of sentence, but mandatory to chain 2 sentences on a single line?


Richard Betson(Posted 2015) [#87]
So anxious to try this demo out. Will do so soon (sudden medical issue has me in the hospital for a while).


marksibly(Posted 2015) [#88]
> I plan on extending current Monkey parser to support Monkey 2 syntax.

I think you can safely do this. The parser is likely to get added too over time - ie: there may be 'short lambdas' added, EOL handling may be 'enhanced' in future etc - but I think what's there represents a good base to build on.

> Did you finally took the ; is optional at the end of sentence,

Actually it's stricter than that - a single ';' can only appear between 2 statements so ';' at the end of line isn't currently supported. Again, this is one of several little things that may change in future if there's a demand/uproar etc.

> - pause a couple seconds.
> - slide in a stats overlay panel.
> - do some animated stat calculation.
> - pause a couple seconds.

This would indeed be cool, and I'm already facing a problem like this with 'Close All' in the IDE which needs to loop through all open files and potentially wait for a 'Save before Closing?' dialog to complete each iteration. It can be done with the existing system, but it's not too pretty.

A simple-ish way to achieve this would be to add an 'Async' modifier for functions (that, for the sake of this discussion, must return Void) and would mean the function would execute as a coroutine so could safely 'block'. Blocking could be achieved via semaphores or Future<T> objects. ConfirmDialog.Run() might look like:

Function Run:Int( title:String )
   Local result:=New Future<Int>   'effectively a semaphore/result pair.
   Local dialog:=New ConfirmDialog( title )
   dialog.Okay=Lambda()
      result.Set( 1 )   'sets results, signals semaphore...
   End
   dialog.No=Lambda()
      result.Set( 0 )
   End
   dialog.Cancel=Lambda()
      result.Set( -1 )
   End
   Return result.Get()   'waits for semaphore, returns result.
End


This can 'block' so should only be called by an Async function, eg:

Method OnCloseAll() Async
   For Local file:=Eachin OpenFiles
      If file.Modified
         Select ConfirmDialog.Run( "File has been modified - save?" )   'blocking call!
         Case 1
            file.Save()
         Case 0
         Case -1
            Exit
         End
      Endif
End


Some 'Wait' functions might look like:

Function Wait( seconds:Double )
   Local result:=New Semaphore
   New OneShotTimer( seconds ).Ticked=Lambda()
      result.Signal()
   End
   result.Wait()
End


Function WaitIdle()
   Local result:=New Semaphore
   App.Idle+=Lambda()   'App.Idle is the nearest monkey2 has to an 'update tick' right now!
      result.Signal()
   End
   result.Wait()
End


...which could be used like:

Function LevelComplete() Async
   
   MainView.Content=LevelCompleteView   'show LevelComplete page...
   Wait( 5 )   'wait 5 seconds
   For Local y:=0 Until MainView.Height  'slide down...
      MainView.y=y
      WaitIdle()   'VWait
   Next
End


How 'deep' should this go? Should it be possible to write an entities entire 'lifecycle' in a single function? eg:

Class Lander Extends Enemy

   Method Run() Async   'only returns when we die!

      While Alive
         'update stuff here...
         WaitIdle()
      Wend
   End

End


Probably not a good idea if you end up with tons of landers, which would mean tons of threads, but an interesting approach!

This is just one potential approach of course. The Semaphore/Future stuff is a bit icky, but this is low level code and most people wont be writing 'wait functions' like this. But I at least have to so I need to consider how everything works behind the scenes. It would also be nice to roll 'generators' into this too, but I haven't given that much thought yet.

This approach also means that if you forget to make a key function 'async' you can quite easily block the gui thread or worse - eg: If OnCloseAll above weren't async, the app would deadlock!

Perhaps Async could also be used to call a function, ensuring it ran on it's own thread? More thought required here obviously...!

> yield SomeFunction()
> which can then get us...
> yield nextUpdate() ' until next update
> yield nextFixedUpdate()

Still a bit confused about this - what's the different between 'yield SomeFunction' and just calling 'SomeFunction'? Is it just something you need to do in Unity to call a function that 'waits'?


Danilo(Posted 2015) [#89]
I thought line continuation works with expressions that are not finished, but it doesn't work after '='

See 'func = Lambda' in the changed 'HelloWorld' example:
#Import "<mojo.monkey2>"

Using std
Using mojo
Using mojo2

Class MyWindow Extends Window

    Field func:Void(canvas:Canvas)

    Method New()
        Super.New( "Hello World Window",0,0,640,480,WindowFlags.Center )
        Destroyed=App.Terminate
        ClearColor=Color.DarkGrey

        func = 
               Lambda:Void(c:Canvas)
                   c.SetColor( 1,1,0,1 )
                   c.DrawText( "Hello World!",ClientRect.Width/2,ClientRect.Height/2,.5,.5 )
               End
    End

    Method OnRender( canvas:Canvas ) Override
        func(canvas)
    End
End

Function Main()
    New AppInstance
    New MyWindow
    App.Run()
End

It's a bit of guesswork. What works and what does not work (yet)?


marksibly(Posted 2015) [#90]
Line continuation is only currently supported after "(", "[" and ",". I'm still not 100% how this should work so I'm gonna leave it at that for now sorry!


Patch(Posted 2015) [#91]
I'm also experiencing an issue with fonts and GUI elements on a Macbook Pro 15" (Early 2013) running El Capitan.




Danilo(Posted 2015) [#92]
> Line continuation is only currently supported after "(", "[" and ",". I'm still not 100% how this should work so I'm gonna leave it at that for now sorry!

Thanks for clarification!

Another thing that comes to mind:
canvas.SetColor( 1,1,0,1 )

Wouldn't it make sense to use macros like RGB() and RGBA() for colors? In the snippet, you have to push 4 values onto the stack,
but when using $FFFF00FF or RGBA(1,1,0,1) or RGBA(255,255,0,255) or RGB(255,255,0) only 1 value is pushed to the stack/function.
I think using macros like RGB() and RGBA() could enhance the speed, while still being platform-independent (order of R,G,B,A is different on different platforms).

Something like:
canvas.SetColor( $FFFF00FF )             ' not really cross-platform

canvas.SetColor( RGBA($FF,$FF,$00,$FF) ) ' cross-platform using macros
canvas.SetColor( RGBA(1,1,0,1) )

canvas.SetColor( RGB($FF,$FF,$00) )
canvas.SetColor( RGB(1,1,0) )



marksibly(Posted 2015) [#93]
> Wouldn't it make sense to use macros like RGB() and RGBA() for colors? In the snippet, you have to push 4 values onto the stack,
but when using $FFFF00FF or RGBA(1,1,0,1) or RGBA(255,255,0,255) or RGB(255,255,0) only 1 value is pushed to the stack/function.

I do want to add some RGB and RGBA style functions 'coz they're convenient, but I'm not sure if they'd necessarily be faster as they involve 'unpacking' as opposed to a direct copy. I prefer to store colors as float r,g,b,a 0..1 because that's what the GL expects, and it's also nice being able to store HDR values etc.

Also, in the case of Function SetColor( color:Color ), the color value is actually passed 'by reference' so it's only copying one pointer anyway. It's only when you're constructing a Color that all four values really need to be 'moved'.


dmaz(Posted 2015) [#94]
>How 'deep' should this go? Should it be possible to write an entities entire 'lifecycle' in a single function? eg:
I've never seen it taken that far but, Yes! :)
>Probably not a good idea if you end up with tons of landers, which would mean tons of threads, but an interesting approach!

So, In Monkey2 Async creates a real thread or fiber, right? I like that for a lot of things but not this type of thing... Coroutines, on the other hand can fix that as there shouldn't be hardly any overhead. You mentioned before that you had closures, I assumed that meant "continuations" as well... which might be a wrong assumption. (my knowledge is thin here)

So what I mean with Yield SomeFunction() (returning some specific type of "yield" object) is that the returned object specifies when the coroutine should resume. In Unity this functionality might be built in their own Coroutine class and on top of C# coroutines. But it really should just be part of the language.

Directed coroutines: ... Also, the syntax is different; the generator uses the "yield" command to transfer control to the parent; the parent uses the next() method of the generator to transfer control to the generator.
http://c2.com/cgi/wiki?CoRoutine

https://books.google.com/books?id=vg_QRDVR7hgC&pg=PA257&lpg=PA257&dq=coroutines+specify+when+resume&source=bl&ots=5K5Xn6abTD&sig=Xfc4wP-TDTqGjxtKY1wpDn28CHo&hl=en&sa=X&ved=0ahUKEwi_jJvQwoTKAhUK6iYKHTs4CtoQ6AEIIzAB#v=onepage&q=coroutines%20specify%20when%20resume&f=false
-1972 :)


marksibly(Posted 2015) [#95]
> So, In Monkey2 Async creates a real thread or fiber, right? I like that for a lot of things but not this type of thing... Coroutines, on the other hand can fix that as there shouldn't be hardly any overhead.

By 'fiber', I mean 'coroutine'. The 2 are pretty much the same thing. And any c# method with a 'yield' in it is effectively a coroutine too.

There are a number of ways to implement coroutines though, such as c#'s 'state machine' approach but I wont be doing that. I'll probably start with trying to adapt ordinary threads, and later on doing it in ASM, ie: easiest way I can think of first!

The key thing is that each 'coroutine' has (conceptually anyway - the state machine approach achieves the same thing) it's own little 'stack', and that they can pass the CPU around to each other.

I actually implemented a simple coroutine system in BlitzPlus - I basically chopped the stack in half, ran the 'event loop' code on one half of the stack and user code on the other. This is how BlitzPlus could handle window resize events in realtime without having to be callback based. There's also a proposal for adding async/await to c++, and in fact I believe MS already have an implementation going using fibers (can't find the exact page): https://paoloseverini.wordpress.com/2014/04/22/async-await-in-c/

I still find Unity's 'Yield' approach odd - found quite a good write up on it here: http://m.blog.csdn.net/blog/StupidCodeGenerator/11526285

It could just be that Unity was based on C# 3.5 or whatever (before Async and Await) and therefore they had no choice but to use the IEnumerator approach to get coroutines. Dunno, but I definitely find this sort of code easier to understand:

Method LevelComplete() Async

   MainView=LevelCompleteView  'change main view.

   Wait( 5 )  'wait 5 seconds.

   For Local y:=0 Until MainView.Height

      MainView.Translate( 0,y )  'scroll main view down...

      Wait( 0 ) 'wait for next 'frame'.

   Next

End


...which I guess is moving more in the 'async/await' direction than 'IEnumerator'.

Anyway, I'm writing up a little proposal for how I think this all could work which I'll post later.


marksibly(Posted 2015) [#96]
> I'm also experiencing an issue with fonts and GUI elements on a Macbook Pro 15" (Early 2013) running El Capitan.

I've got a possible solution to this!

Try adding this at line 300 of modules/mojo2/graphics.monkey2 (in the Texture.SetData method) just before the glPopTexture() at the end...

glFlush()

...if that doesn't work, try glFinish().

Shouldn't be necessary, but it fixes the problem on skidracer's mac mini + Geforce something. Thanks skid!

Please let me know if it works!

Also, if you have any graphics problems like this in the future, please mention at least what sort of video card you have.


Roger Lockerbie(Posted 2015) [#97]
@Mark

Confirmed - adding glFlush() as suggested above resolved the font issue. Many thanks.

PS: Pledged via Patreon - Good Luck with MX2.

-Rog


dmaz(Posted 2015) [#98]
Anyway, I'm writing up a little proposal for how I think this all could work which I'll post later.
ok, cool.. I'm not married to any particular solution and I don't want to hog this thread.. but just a little bit more. That article you linked on unity's implementation actually describes a few advantages... one being the custom YieldInstructions...

but I definitely find this sort of code easier to understand
...code...

Me too and I like Async and the Wait you listed above but here's some stuff to think about...
Isn't LevelComplete now decoupled with the main update thread? So how would we deal with the pause key or menu key being pressed during this level transition? With coroutines, since we have control over reentry through custom YieldInstructions, we don't have write anything extra in LevelComplete to make that work.

What about synchronization with the main thread and other async methods? Won't it be possible that an async method gets ahead or falls behind the main thread or any others? Or since you are using fibers will the scheduler keep them synchronous and not a problem?


marksibly(Posted 2015) [#99]
> I don't want to hog this thread.. but just a little bit more.

Please hog away - I need all the help I can get here! And I do think it'd be a very cool feature to have, however it's done. But it's getting late, I'll post a followup to your comments tomorrow.

And get well soon Richard!


Danilo(Posted 2015) [#100]
Google Scholar may have some interesting research papers when searching for "coroutines". For example "A Language of Coroutines".
On iPad you can use Papers to search for papers and download+view the PDF's directly.


Patch(Posted 2015) [#101]
Try adding this at line 300 of modules/mojo2/graphics.monkey2 (in the Texture.SetData method) just before the glPopTexture() at the end...

glFlush()

...if that doesn't work, try glFinish().

Shouldn't be necessary, but it fixes the problem on skidracer's mac mini + Geforce something. Thanks skid!

Please let me know if it works!


Can confirm that adding the glFlush() line above glPopTexture() works! Thanks marksibly and skid!

Just FYI this Mac has an Intel HD Graphics 4000 1536 MB card.


Gerry Quinn(Posted 2015) [#102]
>> Did you finally took the ; is optional at the end of sentence,

> Actually it's stricter than that - a single ';' can only appear between 2 statements so ';' at the end of line isn't currently supported. Again, this is one of several little things that may change in future if there's a demand/uproar etc.

I think it should be allowed at the end of lines. I probably won't use it much myself, but for someone who uses it a lot, editing will become a pain because the ; will have to be deleted if a line is removed or moved to a new line.

Regarding SetColor(), I don't think forcing the programmer to use macros is a good idea. I think there should always be a SetColor( r, g, b, a ) and SetColor( r, g, b ) in the basic language, and then for coders who want a bit more optimisation, there can be inline functions and/or macros. Maybe SetColor( xxxx:Int ) can be there with a warning that the results are machine dependent, but I'd call it something else (SetColorVals?) in case it became a trap for beginners.


Nobuyuki(Posted 2015) [#103]
Multithreading programming paradigms are a bit over my head, but I am watching this thread with excitement because a straightforward implementation will make it much easier for me to understand the concepts inside out, and I'm learning as I go along by watching everybody's posts on the topic. Thank you very much, and I look forward to seeing all the proposals!


dmaz(Posted 2015) [#104]
thanks to Danilo... I found this very short summary of boost's fiber and coroutines
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.433.8333&rep=rep1&type=pdf

a summary of this summary from the end suggests it might be better to implement fibers on top of coroutines... (I guess the scheduler is built from coroutines)
Of course it would be possible to implement coroutines on top of fibers instead. But the concepts map more neatly to
implementing fibers in terms of coroutines. The corresponding operations are:

- a coroutine yields;
- a fiber blocks.

When a coroutine yields, it passes control directly to its caller (or, in the case of symmetric coroutines, a designated
other coroutine).

When a fiber blocks, it implicitly passes control to the fiber scheduler. Coroutines have no scheduler because they
need no scheduler.


http://www.boost.org/doc/libs/1_55_0/libs/coroutine/doc/html/index.html
http://olk.github.io/libs/fiber/doc/html/


Danilo(Posted 2015) [#105]
Happy.... (research) New Year! ;)


dmaz(Posted 2015) [#106]
ok.. I've also found a ton of small/simple implementations:
http://dotat.at/cgi/git?p=picoro.git (http://dotat.at/cgi/git?p=picoro.git;a=blob;f=picoro.c;hb=HEAD)
https://github.com/mvcode/doc/wiki/Implementation-Techniques
http://www.embeddedrelated.com/showarticle/455.php (some good comments on this one)
http://fanf.livejournal.com/105413.html
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

:)


Danilo(Posted 2015) [#107]
:D


marksibly(Posted 2015) [#108]
> Happy.... (research) New Year! ;)

Yeah baby! 2016 should be very interesting!

> it might be better to implement fibers on top of coroutines.

Ha, I've just done the complete opposite!

I decided to go for fibers first since the API (the win32 one anyway) is incredibly simple, and if C++ can build async/await on top of fibers, I might be able to too.

Here's the resultant, highly experimental fiber API:

Function StartFiber:Int( entry:Void() )
Function SwitchToFiber:Void( fiber:Int )
Function GetCurrentFiber:Int()


(There will probably be CancelFiber too).

This is incredibly primitive - there is no 'scheduler' as such, but I kind of like that because we can build schedulers etc on top. It currently fakes fibers with threads but ensures that, like a real fibre or coroutine, there is only ever one fiber 'unblocked' at a time. The overhead of creating/switching fibers is likely to be quite high, but with some low down and dirty ASM is should be possible to reduce it to about that of a function call.

Fiber 0 is reserved for the main/gui fiber, which means SwitchToFiber( 0 ) will always switch to the gui fiber. This means fiber 0 *is* effectively the scheduler, and that sounds right to me. If all fibers are blocked, the ONLY thing that can unblock them is the gui thread, as ultimately all code execution begins from the gui event dispatch mechanism.

Anyway, I can now do this: it just 'fades in' the window color, but I think it's a very promising start:

Class MyWindow Extends Window

	Method New()
		Super.New( "My Window",0,0,640,480,WindowFlags.Center )
		
		Destroyed=App.Terminate
		
		StartFiber( Yeehaa )
	End
	
	Method Yeehaa()
	
		For Local i:=0 Until 256
			ClearColor=New Color( 1,0,i/255.0,1 )
			App.RequestRender()
			WaitFrame()
		Next
	End
End


The implementation of WaitFrame is a little funky, but a lot of people wont care how it's implemented, and I'm confident utility funcs for 'Wait( some_generic_condition )' etc can be written to make this sort of stuff nicer.

Function WaitFrame()

	Local fiber:=GetCurrentFiber()
	
	App.Idle+=Lambda()
		SwitchToFiber( fiber )
	End
	
	SwitchToFiber( 0 )
End



Richard Betson(Posted 2015) [#109]
Hi,

Just got back home and access to my development system and 'WOW'. Very, very nice work Mark.

I have just had time to compile the Xdemo v1 v2 on Linux Mint 17.2 "Rafaela" and all went well. First source demo up was 'Stargate' which is awesome and runs perfectly so far (desktop). Ted2 is so on the right track clean and simple. Just a great first impression. Well done.

Off to dive a little deeper.


marksibly(Posted 2016) [#110]
Wow, this fiber stuff is great!

I successfully converted defender's TitlePage, LevelComplete and GameOver pages to fiber style code so they're now discrete functions, and it all worked pretty much first time!

I even got a simple generator system going - here's an example of an int range generator:

Class IntGenerator Extends Generator<T>

   Method New( min:Int,max:Int )
      Start( Lambda()   'ok, this is a bit funky, but necessary for now...
         For Local i:=min To max
            Yield( i )
         Next
      End )
   End

End

Function Main()
   Local gen:=New IntGenerator( 1,10 )
   While gen.HasNext
      Print gen.NextValue
   Wend
End


Again, the implementation of Generator<T> will be a little 'out there' to some, but it works and I love the idea of building higher level stuff like this *in monkey2* on top of a small, simple lower level native API.

There is still no doubt lots to discover about all this - I'm still a little confused about 'who goes next' when a fiber finishes (is it always the 'parent' fiber?) and it's a little too easy to 'leak' fibers if your not careful (although using builtin Wait/Generator will always work) but I love where this is going.


therevills(Posted 2016) [#111]
Will all these new features work on all target platforms due to the base language being C++?


Richard Betson(Posted 2016) [#112]
This means fiber 0 *is* effectively the scheduler, and that sounds right to me. If all fibers are blocked, the ONLY thing that can unblock them is the gui thread, as ultimately all code execution begins from the gui event dispatch mechanism.

I'm just reading over this but what you are saying here is 'exactly' right and how I would approach it. In my current GUI design the window system is where I would schedule fibers I think. Each window having it's I guess parent fiber(s) (which could be blocked say when it's hidden) and perhaps adding to it a button and mojo2 renderer fiber for example. Hmmm.


marksibly(Posted 2016) [#113]
> Will all these new features work on all target platforms due to the base language being C++?

The only target that might be a problem with the async stuff is - surprise! - emscripten. It has a new thread API that will probably work, but it's VERY new and wont be wildly supported by many browser yet.

But it's too cool a feature to drop just because emscripten doesn't support it well! My focus with monkey2 will remain on the 'real' c++ targets, such as desktop/android/ios. Emscripten I'll do the best I can with, but I don't want it holding anything back.

> the window system is where I would schedule fibers

It's all kind of self scheduling really. The internal UpdateEvents() loop that gets messages from the system and dispatches them to monkey2 callbacks (in a variety of ways) is the ultimate 'source' of all code flow, and eventually the code flow may end up 'waking' a suspended fiber (and if the gui fiber is running, all other fibers MUST be suspended by definition) - ie: scheduling it.

But I don't plan on using fibers 'for each button/window' or whatever - yet, anyway. I'm quite happy with the Clicked/Triggered/Dragged signals system in place. In fact, even if some of this was fiberized in some way, there'd still need to be a non-fiber mechanism in there that was capable of waking them. There's probably less to fibers than your thinking!


Richard Betson(Posted 2016) [#114]
There's probably less to fibers than your thinking!

And you are probably right. This is the side of me that is exploring integrated development environments/platforms at the moment. ;)


dmaz(Posted 2016) [#115]
You must be some kind of machine... I go out for a few hours and bam! done! :)
wow... looks and sounds great!... except for
>The overhead of creating/switching fibers is likely to be quite high, but with some low down and dirty ASM is should be possible to reduce it to about that of a function call.

switching will be especially important to reduce that but yeah, hopefully startup can be reduced to close what the coro option would be... which would be a memory block copy and some jumps, right?

>I'm still a little confused about 'who goes next' when a fiber finishes (is it always the 'parent' fiber?)

for coroutine that would be yes... not sure about with this.... are you planning on building anything more to schedule them? Judging by what you wrote it doesn't sound like you need that at all in which case why not? It sounds most intuitive to me.

> I'm confident utility funcs for 'Wait( some_generic_condition )' etc can be written

wow, this is going to be great!

ok now the most important question, when do we get to play?


dmaz(Posted 2016) [#116]
another question... can you make
StartFiber:Int( entry:Void(), coreThread:int )


[edit]
sidenote, some nice insights here
http://tinyurl.com/qzwbame
(https://books.google.com/books?id=1-NfBElV97IC&pg=PA260&lpg=PA260&dq=win32+fibers+overhead&source=bl&ots=SQqjhnfTkx&sig=-YMqtCkwXnFUGtiy27M0omKF7jc&hl=en&sa=X&ved=0ahUKEwjKicTJ84jKAhVL5CYKHS8pA0QQ6AEIRDAH#v=onepage&q=win32%20fibers%20overhead&f=false)


marksibly(Posted 2016) [#117]
> You must be some kind of machine... I go out for a few hours and bam! done! :)

Well, I'd already had a crack at 'real' threads (and given up on for now) so I sort of knew what to do. What surprised my was how easy it was to get Wait() going once fibers were in!

> which would be a memory block copy and some jumps, right?

Yeah, switching fibers should only involve saving/restoring a bunch of CPU registers including SP and then JSR-ing. Creation is less of a problem because I can just use a 'thread pool'.

How many fibers do you expect to be running at once typically? I can see the overhead being significant for generators, but if you've only got a couple of fibers vwating, it's not that big a deal. Apart from 'fading out', what sort of things is this generally used for?

> are you planning on building anything more to schedule them?

That's the cool thing about having such a small API - we can add stuff and mess with it as necessary quite easily. So if we find anything that would help, we can just bung it in there.

For example, I've solved the 'who goes next' problem for now by changing the fiber function so it returns a 'next fiber' int that controls which fiber goes next after this fiber has returned/completed - kind of a 'continuation' I guess. So most fibers can (probably) just return 0, while generators set a 'finished' flag and return to the parent fiber. It may turn out that the parent fiber ALWAYS goes next (or that it prevents fiber leaks to do so or something) but for now having that int in there allows us to experiment.

I think this is similar to your 'corethread' idea? Except I've done it this way:

StartFiber:Int( entry:Int() )

ie: entry returns the fiber to switch to AFTER it completes. I was initially doing something like

GeneratorFiberCode()
   'do the 'yield' loop...
   _finished=true
   SwitchToFiber( _parent )
End


...but this leaks! The problem is the last SwitchToFiber 'suspends' the fiber, but there's nothing to resume it to allow it to actually return/exit. And if you try to resume it 'one last time' from the parent fiber, you end up with the opposite problem - the parent 'stalls'! So it now looks like this:

GeneratorFiberCode:Int()  'returns fiber to switch to after we've finished and have been cleaned up/deallocated etc.
    'do the 'yield' loop
   _finished=True
  Return _parent
End


The are other ways to deal with this - your way, something like SetFiberNextFiber() etc - but I think we'll only find out the best way by playing with things.

I was planning on adding a CreateFiber() too, that works like StartFiber() but doesn't actually run the fiber until you explicitly SwitchToFiber. In which case, a fiber could end with...

Return CreateFiber( SomeOtherFunc )

...to 'chain' fibers together. But it turns out this is really unnecessary, as you're already running on a fiber so why bother creating a new one? You can just call SomeOtherFunc() directly before you exit instead. Still, CreateFiber can easily happen if there's a need for it.


skid(Posted 2016) [#118]
oops, wrong thread...


GC-Martijn(Posted 2016) [#119]
don't forget to make a good documentation about those fibers in the Ted help doc/online.
I think i'm not the only one that never heard about those funny named things.


dmaz(Posted 2016) [#120]
How many fibers do you expect to be running at once typically? I can see the overhead being significant for generators, but if you've only got a couple of fibers vwating, it's not that big a deal. Apart from 'fading out', what sort of things is this generally used for?


I would like to use them for any kind of animation...
- AI or any othr kind of state machine or more importantly, the sub parts of the state.
- scripting any squence of events.
- spliting up processes or computations thorugh mulitple frames.
- just to do something "asynchronously" of course.
- with custom yields can then replace polling calls? (maybe that would still poll though just someplace else?)

using them should reduce things like While IsMoving()...

I'd use custom yield instructions to manage the 'global' state of the object or application... ex. if object is killed before the coroutine finishes or if pause is pressed.

The more reading I've done on this the more examples I've find using them for just about everything... even your example to write the entire lifecycle in the single function. There's a lot of talk about statckless coroutine implentations to avoid some of the overhead.

yeah, so to go to those levels, overhead and performance need to be good.

I'm getting very excited about all this...

Just to confirm, these all share memory/state right?

Also, this is probably asking too much but do you think there might be a way to serialize them for game saves?


marksibly(Posted 2016) [#121]
> I would like to use them for any kind of animation...

As an experiment, I might try and convert defender to use fibers for it's animation.

> I'd use custom yield instructions to manage the 'global' state of the object or application... ex. if object is killed before the coroutine finishes or if pause is pressed.

Could you clarify this a bit? In particular, I get the 'paused pressed' issue can be complex!

For things like 'Destroyed', I'd tend towards using something like a 'signal' similar to Window.Destroyed instead, eg:

'a signal! To 'raise', simply call GameOver().
Global GameOver:Void()

Class Actor

   'another object signal
   Field Destroyed:Void()

   Method New()

      GameOver+=Lambda()  'this adds a 'listener' to GameOver.
      End

      Destroyed+=Lambda()
         'ditto, this called when actor destroyed - maybe cancel fibers here? maybe have fibers groups? A fiber hierarchy?
      End

   End

End


It'd also be nice for a fiber to be able to 'wait' for a signal like this - shouldn't be hard although it may mean encapsulating the signal a bit for full flexibility. This is what WaitFrame() effectively does anyway, it just waits for the App.Idle signal.

Signals can often be used instead of fibers, eg: instead of starting a fiber and waiting on a signal, you can listen to a signal and (maybe) start a fiber when it fires, which is likely to be more efficient. Ted2 achieves a far amount of asynchronisity this way, but things get tricky when you want to do a 'blocking' loop, like for 'Close All Files'.

What I'm now planning to do here is something like:

'what the 'CloseAll button' does..
CloseAllAction.Triggered=Lambda()   'when Close All is clicked...
   StartFiber( Lambda:Int()    'we start a fiber...
      '
      '...which can now 'block' without blocking the gui!
      '
   End )
End


(actually, StartFiber is starting to look very much like a sort of lambda...or something...)

> Also, this is probably asking too much but do you think there might be a way to serialize them for game saves?

Wouldn't that be cool! I've actually been trying to nut out a way to serialize 'function pointer values' - something Qt does very well with its slots and signals - and this is related. So....maybe...I have some ideas...


dmaz(Posted 2016) [#122]
(actually, StartFiber is starting to look very much like a sort of lambda...or something...)

Yeah, so also have
'what the 'CloseAll button' does..
CloseAllAction.Triggered=LambdaFiber(
      '
      '...which can now 'block' without blocking the gui!
      '
End
maybe not... this is less wordy but not very clear.

Could you clarify this a bit? In particular, I get the 'paused pressed' issue can be complex!
All I was just thinking is that I would write something like this...
Function MyWaitFrame() ' gui elements would still use the standard WaitFrame
	Local fiber:=GetCurrentFiber()
	
	App.Idle+=Lambda()		' is this a stack or does this Lambda have to be removed from App.Idle somewhere?
		If game.state <> state.paused
			SwitchToFiber( fiber )
		End
	End
	
	SwitchToFiber( 0 )
	
End
or put that check into "Wait( some_generic_condition )" as the "some_generic_condition"

as for the signals and destroyed... How would that work... how do I find/identify those generic fibers?

So if App.Idle is a stack, couldn't it all clean up via the GC? if I remove object:Actor from all my references, the fiber would no longer add to App.Idle... the GC comes along and cleans it up?

-------------------------------------
couple other things I've been thinking about... these would just clean up classes a bit and maybe add some performance. I think it would be really nice to build some design patterns into the language...

- Pooling. mark a class as pooled so when the GC tries to collect it, it caches it instead and New checks the cache first. Even if it's not the GC and just some built in stuff behind the scenes that OnDestroy caches it.... I know it's trivial to add pooling to my classes but it's still a decent amount of code and this would make it real easy to make the pooling go deep.

- how about a Singleton keyword... New only ever gives you the initial allocation. again, very easy to code but man, that would be clean and clear!

- the prototype pattern would be cool too but that would probably just go into a library with serialization.


marksibly(Posted 2016) [#123]
> - Pooling. mark a class as pooled so when the GC tries to collect it, it caches it instead and New checks the cache first.

Already happens for objects <256 bytes (should probably be less). These go immediately into a 'fast allocation' pool. Malloc generally does this too anyway.

It's the 'tries to collect it' bit that'd be nice to avoid, but that really means some alternate collection scheme like ref counting etc.

> New only ever gives you the initial allocation.

Interesting idea, but could make code look a bit misleading? If I see a 'New blah' I kind of expect it to create a new blah. But yeah, something to make on the fly singleton generation easier might be nice.

Just got landers animating via fibers too! It's a bit dodgy though - fiber scheduling looks like it'll be trickier than I thought.


dopeyrulz(Posted 2016) [#124]
Great too see some nice energy around this Mark! Great conversations going on - good stuff!


marksibly(Posted 2016) [#125]
Ok, think I've got the scheduling mostly figured out - and it simplifies stuff too. No need for continuation fibers etc.

Basically, the fibre API looks like this now:

StartFiber:Int( entry:Void() )    'create a running fiber - same as create followed by resume...
CreateFiber:Int( entry:Void() )   'create a suspended fiber
ResumeFiber( fiber:Int )      'resume a suspended fiber
TerminateFiber( fiber:Int )    'terminate a fiber
SuspendFiber()     'suspend current fiber
CurrentFiber:Int()    'get current fiber.


...but you wont need to use then unless you're doing something advanced. Instead, you'll probably just use stuff like WaitFrame, WaitSeconds etc.

WaitFrame looks quite sane now:

Function WaitFrame()
   Local fiber:=CurrentFiber()
   App.Idle+=Lambda()
      ResumeFiber( fiber )
   End
   SuspendFiber()
End


I've now got the defender game state logic running in a single MainLoop() method that looks remarkably like a 'normal' b3d/bmx app! Only of course it doesn't block the GUI at all...

Note that this isn't 'multiprocessing' - if ANY fiber takes a long time to do something and doesn't wait, it'll hold up ALL other fibers, including the GUI. This means you can lock everything up with a simple empty Repeat/Forever loop.

There are still issues with collecting/ending fibers. Most fibers are either running or suspended and waiting to be run. Either way, something has a handle on them so they can't just be GC'd. But I think this just means we need to think of fibers as 'resources', like files or memory etc - and I haven't thought much about how to make resources easier to deal with yet.


nullterm(Posted 2016) [#126]
Native fiber/coroutines will be amazing. Imagine being able to write a single function to drive character behaviour.




Gerry Quinn(Posted 2016) [#127]
You're going to hate when Mark enforces brackets around function parameters, though :-D


dmaz(Posted 2016) [#128]
Ok, think I've got the scheduling mostly figured out
This looks really good... so you removed the int arg for suspendFiber, so does that mean suspend 0 or suspend parent?

I'm really looking forward to seeing the updated stargate. You should make a note of the diffs as a little example/tutorial.

Already happens for objects <256 bytes (should probably be less). These go immediately into a 'fast allocation' pool

holy buckets! that's awesome... This is new, Monkey1 didn't do that, right? I saw sizable speed gains on older iPhones when I pooled stuff using Monkey1 awhile back. Monkey2's feature list is really getting me excited again!

Note that this isn't 'multiprocessing'
right... you mentioned that you shelved threads for a bit... can you say what you issues were? now that we have coroutines on fibers maybe threading now doesn't need to be a super robust API. Maybe it can be far smaller and managed, since we could have fibers on any thread.... basically I'm thinking the back end starts up the main thread and a few optional others (maybe only 1 per core(?)) and then when creating fibers, we can assign them to a particular thread. Clearly that would be very limited....communication through messages and shared banks? but I could see putting things like pathfinding and maybe physics on them... that said... most of my stuff will be satisfied with fibers only!


EdzUp MkII(Posted 2016) [#129]
Sounds like it's coming together nicely now, will test it more later and see what it can do :)


dmaz(Posted 2016) [#130]
There are still issues with collecting/ending fibers. Most fibers are either running or suspended and waiting to be run. Either way, something has a handle on them so they can't just be GC'd.
I'm a little confused about this since I was still thinking they were not managed/scheduled?

oh, the Int's, right..duh. so you have a fiber table... You have them come off and GC'd when the fiber method returns though right (ie. no call to SuspendFiber())? is CurrentFiber() getting the int from table or is the method a closure?

if the Actor is killed and it's ref count goes to 0, App.Idle still has the Actor's fibers.... App.Idle seems to be a stack and not a list, right?

why Int's instead of object reference?


marksibly(Posted 2016) [#131]
> holy buckets! that's awesome... This is new, Monkey1 didn't do that, right?

Actually, it's probably less awesome than you think, and yes monkey1 did this.

The memory subsystem uses pools for small objects BUT the gc system still needs to detect when things are 'free' in the first place and THAT's the slow/complex bit.

Custom pools are fast NOT because memory allocation is slow, but because they 'know' things the GC doesn't - in particular, that even though there may be a bunch of references to an object, it's still safe to 'reuse' it. The GC in general can't know this, so it's frequently resigned to creating new objects.

> I saw sizable speed gains on older iPhones when I pooled stuff using Monkey1

How long ago was this? The monkey1 GC did improve significantly over time...

> so you removed the int arg for suspendFiber, so does that mean suspend 0 or suspend parent?

It means to suspend the current fiber (perhaps should be renamed?)...

The problem with only using SwitchToFiber is that it doesn't recognize that there are basically 2 states a non-running fiber can be in - 'suspended' because it's waiting for something to wake it up, or 'ready' because it's just caused another suspended fiber to 'wake up', and although it's no longer running, it's not suspended either as it needs to run again later. It's 'ready' or 'scheduled for execution' as opposed to 'suspended'.

This turned out to be surprisingly simple to do after a bit of head scratching, and it just involves a bit stackery:

Function ResumeFiber( fiber )
   readyStack.Push( CurrentFiber() )   'push current fiber on global readyStack.
   SwitchToFiber( fiber )                      'wake up suspended fiber
End

Function SuspendFiber()
   If readyStack.Empty Throw New IllegalOperation( "Fiber stack is empty!" )
   SwitchToFiber( readyStack.Pop() )  'back to next 'ready' fiber. We are now 'suspended'.
End


When a fiber exits, it basically does the SuspendFiber stuff, only it also cleans up after itself.

A nice-ish side effect is that SuspendFiber() will fail if called on the gui fiber, because fiberStack will be empty. And by the time the fiber stack is fully popped, we know we're back to the gui fiber.

SwitchToFiber could remain, although I'm not sure what it'd be useful for.

There are (at least) 2 more things I need to do to make this rock solid:

* SuspendFiber needs to skip over canceled fibers when it pops the ready stack.

* Each resume must match exactly one suspend, but there's not currently any enforcement of this. Get it wrong and crazy stuff happens! I have a few ideas here, but in general if you're just using WaitBlah() it wont be an issue.

> if the Actor is killed and it's ref count goes to 0, App.Idle still has the Actor's fibers....

Here's the problem though - there is no such thing as 'the Actor's fibers'. A fiber is not 'owned' by anything and will only end when it returns, or is cancelled.

In the case of fibers that just do something and exit, it's (almost) not a problem, but in the case of animation style fibers that effectively loop forever, something needs to cancel them.

I solved this in defender by replacing the 'repeat/forever' in the animation loop with 'while actor.alive', but this did mean I had to tweak ClearActors a bit so it cleared the 'alive' flag for all actors before clearing actor lists.

Actor classes could provide their own version of StartFiber that 'tracked' fibers and ensured they were canceled when the Actor was destroyed, but it would be kinda nice to help out here if possible.

> App.Idle seems to be a stack and not a list, right?

Actually, App.Idle is just a function pointer. You can use += with function pointers to 'add' functions to them. But you can effectively think of it as a list/stack of functions.

App.Idle is automatically 'cleared' each time it's invoked, so if something wants to be called every App.Idle continuously it needs to keep using App.Idle+= over and over.

> why Int's instead of object reference?

I did this because it allows StartFiber to return a unique id/handle for every fiber created. This int can be validated easily to make sure it really represents an active fiber, and not a fiber that may have exited or been canceled 'behind your back'. This means you can't accidentally, say, 'CancelFiber' a fiber that is no longer running.

This is a bit like audio systems that return a unique channel id when you use PlaySound. If the sound finishes, the id becomes invalid so you can't accidentally mess with a channel another sound may now be playing through.

I may eventually wrap this handle in an object and OO-ify the fiber interface a bit, but for now I'm keeping it simple.


Tibit(Posted 2016) [#132]
I'm very curious about the signals and fibers, while I get the gist of it, I'm still not 100% clear on how it could be used with everyday gameplay logic. I would really like to see an example of signals (and maybe fibers) used to map things such as input from keyboard, button with touch, mouse, joypad, key mappings, AI, cutscene movement onto different game objects. Would that be a good use case? It seems to me the main purpose is to de-couple logic between objects.

It brings to mind reactive programming. I use this programming in javascript (meteor framework), it is surprisingly intuitive and simple to use at the "high" level, and takes away a lot of common "binding/bloat" code. To me it makes even more sense to use it for games. Is this similar to signals in any way?

Reactive Programming versus Event-Driven Programming
Introduction to reactive programming


nullterm(Posted 2016) [#133]
> You're going to hate when Mark enforces brackets around function parameters, though :-D

I'm still holding out hope Mark will come to his senses, and MX2 gets optional ()s in function calls. ; )

It's minor, but one of my favourite minimal aspects of MX1.


marksibly(Posted 2016) [#134]
> I'm still holding out hope Mark will come to his senses, and MX2 gets optional ()s in function calls. ; )

Not gonna happen sorry.

A lot of this new stuff would just not be sanely possible without the compiler being able to clearly tell the difference between 'invoking' a function, and simply 'referring' to one.

The IDE should be able to help here to a degree though, just as it should be able to deal with 'fixing case' of identifiers and so on.


nullterm(Posted 2016) [#135]
> Not gonna happen sorry.

I'm still getting native coroutines, struct, and operators. So we'll call it even.


GC-Martijn(Posted 2016) [#136]
@tibit
I think, but maybe i'm wrong, that it can be used as background special effects.
For example glowing fireflys that will be rendering in a fiber at the screen. But they won't lock the main gameplay loop.
And fot other gui things like downloading async at the background


Richard Betson(Posted 2016) [#137]
Yay, MX2 is compiling Emscripten here on Linux Mint 17.2 (64). Chromium and Firefox. :)

I have to say setup was pretty easy and on Linux thats saying something. :) If I'll have to do is something like the run-a-couple scripts upgrading should be eased. Worked smoothly and initial setup compile times where not bad at all.


Danilo(Posted 2016) [#138]
@Tibit:
You can simply connect (multiple) event handlers to events.

In a game system you would probably use the event handling like this:
player1.OnCollision += soundPlayer.PlayCollision
player1.OnCollision += screen.Flash



GC-Martijn(Posted 2016) [#139]
@mark
will the building be a lot faster in the future ?
I have a fast workstation (3800 score using passmark 8, (without a good game videocard)), but building and starting the demo game cost around 15/20 seconds.
Normally I build 10000 times :) x 20 seconds = many wait time


degac(Posted 2016) [#140]
Question:
It's possible to pass as event-handler a method like Change(value)?
In the Danilo's example there are 2 methods (Inc() and Dec()) both 'linked' to the event-handler.
I looked ad the source code (button.monkey2), and the field Clicked() has no parameter.
I tried to change it, but of course I get an error (No default value for parameter).
So, It's by MX2 design?


Danilo(Posted 2016) [#141]
The signature of the Event handlers should match. So if you do
Field OnMouseMove:Void( x:Int, y:Int )
Field OnSomething:Int( e:EventArgs )

You can connect methods/lambdas that have the same signature.


degac(Posted 2016) [#142]
Oh, OK, so it needs to change the OnMouseUp event... I'm sure I will break something.
I believe it was more easy to do, changing the MX2 gui system doesn't seem a great move!
Thanks anyway!

ps:

I would add a OnMouseWheel event on button class... could do the job to pass increment/decrement of values, but this requires another field (Changed?) I suppose.


Danilo(Posted 2016) [#143]
Maybe it's better to make a new class 'MyButton' that Inherits from Button,
And add your new event handlers there (with different signature).


dmaz(Posted 2016) [#144]
How long ago was this? The monkey1 GC did improve significantly over time...

It was a few years ago and the hardware I tested was real old. This wasn't just a monkey thing though, it was common across devices and languages. Only a problem though when you New'd a butt load of items in a single frame. like particle effects for an explosion

Actor classes could provide their own version of StartFiber that 'tracked' fibers and ensured they were canceled when the Actor was destroyed, but it would be kinda nice to help out here if possible.

Yeah, we could do it ourselves... But I'm actually a huge fan of a good GC and other automatic maintenance. I'm not a fan of having to track and cancel/dispose... Now... we could also cancel in the Wait as well, right? We would still have to check a flag though but it would only be one place
Function MyWaitFrame(o:object)
	Local fiber:=CurrentFiber()
	App.Idle+=Lambda(o:object)
		IF (entity)o.IsAlive
			ResumeFiber( fiber )
		Else
			CancelFiber( fiber )
		End
	End
	SuspendFiber()
End


App.Idle is automatically 'cleared' each time it's invoked
that's what I was wondering... excellent.


dmaz(Posted 2016) [#145]
It brings to mind reactive programming.
and Reactive Extensions... I had seen a lot of talk about this but didn't really pay attention... those 2 links gave me a basic idea but I still couldn't get my head around them until I saw these 2.

https://www.youtube.com/watch?v=dwP1TNXE6fc (9mins) the best high level explanation I've found
https://channel9.msdn.com/Blogs/codefest/DC2010T0100-Keynote-Rx-curing-your-asynchronous-programming-blues (40mins)

now with fibers we can do some of this too by build asynchronous "Observables" :)


marksibly(Posted 2016) [#146]
A few words about events/signals etc...

Events are used to represent user input such as key and mouse events etc. They are sent from the mojo event loop to views, and differ from signals in that they have a 'target' - eg: key events are sent to the focus view, mouse events are sent to the view under the pointer etc, possibly via filters eventually. Events are implemented as objects that extend the Event class and are 'received' by virtual view methods such OnKeyEvent, OnMouseEvent etc. So if you want to catch input events, then yes, you have to subclass something.

Signals are higher level and used to represent more abstract things like 'button clicked', 'scrollbar value changed' etc. Its really the job of 'control' style views to transform events into signals, eg: when a button receives a 'mouse down' event it emits a 'clicked' signal. Signals have no 'target' - a view emits signals without knowing/caring who is listening for the signal. This makes signals VERY flexible as they can be 'plugged into' any system since they don't care who/what is receiving the signals. Ideally, you should be able to build apps using only signals and not have to care about events.

Signals are implemented as function pointers, and emitting a signal simply involves 'calling' the function pointer. This will cause anything listening for the signal to execute. You can use = to assign a single listener to a signal, or += to add multiple listeners, eg:

Local button:=New Button
button.Clicked=OnClicked 'sets a single signal listener (note: will 'overwrite' any previous listener(s))
button.Clicked+=OnClicked2 'adds another listener
button.Clicked+=OnClicked3 'and another

...this code means 3 functions will be called when the button is clicked.

Also, in terms of naming conventions, I think it's best to save the 'On' prefix for signal listeners, not the signals themselves. eg: the button clicked signal is simply 'Clicked', not 'OnClicked', so when you go button.Clicked=OnBlahClicked it's kind of clearer .Perhaps it doesn't matter much, but it's what Qt does and I'm sticking with it myself!

> I looked ad the source code (button.monkey2), and the field Clicked() has no parameter.

Well no, because a button has no 'value'. It's just a button, what value do you expect it to 'emit'?

If you could explain what you'd actually like to do I can perhaps be of more help!

> Oh, OK, so it needs to change the OnMouseUp event... I'm sure I will break something.

The gui has been designed so it should be easy to subclass View.

You can start by copying and pasting the button class if you want, and renaming it 'MyButton' or something. Or you can extend Button. You don't have to modify mojo, you can add the new class to your own project. You can't accidentally override a critical or otherwise method, because you need to declare 'Override' when overriding an existing method, so it should all be relatively bulletproof.

Here's a little example of an 'IntField' class I whipped up, that allows you to change the value of an int by using the mousewheel when the pointer is on top of the view:



Something like this that extends TextField will eventually be in there...

> will the building be a lot faster in the future ? x 20 seconds = many wait time

It will be slow the first 2 times you build as it has to recompile all project files (first build) and then scan for dependancies (second build), but after that the build cache should have warmed up and build times should improve greatly. Stargate takes about 4 seconds here to build after a modification once things are in the groove.

It will be sped up too. It's still compiles more files that it needs to sometimes, and I plan to support multi-process builds. And on Windows, you'll be able to use msvc eventually which is very fast.

> Only a problem though when you New'd a butt load of items in a single frame. like particle effects for an explosion

Structs can help here too, which is what I'd probably use to implement particles. If they only contain primitive type values, an array of structs will have very little GC overhead (perhaps not yet quite true), ie: as much as a single object since it's elements don't need to be marked.


taumel(Posted 2016) [#147]
Hey Mark, it's good to see you motivated. Just don't forget about the big picture this time.

It would be sad if monkey2 would tank, like Monkey did, due to spending resources on certain aspects. Some of us were there already. There is a lot of time you can spend on this stuff (splitting up code, spreading it gently across cores, states, comm, management, ...). No matter how you write code (if you use coroutines or gameStates) its about what the code is able to accomplish with all its components and the interaction it enables.

That's what the end user will experience too. From both, a dev's and user's point of view Monkey was a step backwards. Please try to go forward again, making things easy, capable and enjoyable again, bringing back that Max feeling.


Gerry Quinn(Posted 2016) [#148]
See, I never used Max at all.

I've used a lot of languages, but not that particular one.

For me, Monkey wasn't / isn't the language designed for me to love as a language per se. It's the language that gives me easy and straightforward multi-target abilities, while still being a capable and flexible - and reasonably conventional - programming language, THAT'S what I love about it.

Frankly, I'm surprised the demand is not greater - I can only assume that newbies are finding ways to work with Unity or GameMaker, or picking Monkey alternatives that are less capable...


Playniax(Posted 2016) [#149]
From both, a dev's and user's point of view Monkey was a step backwards

Absolutely not!

I'm surprised the demand is not greater

People don't know it (well enough).
I have made it my personal mission to market the hell out of Monkey once Monkey 2 (and a ported version of Pyro) is 'finished'.


Richard Betson(Posted 2016) [#150]
I have made it my personal mission to market the hell out of Monkey once Monkey 2 (and a ported version of Pyro) is 'finished'.

I agree. Nows the time to start thinking along these lines. ;)

edit- On a side note porting Monkey 1 code if written 'strictly' to MX2 seems pretty easy so far. Although MX2 is not quite ready for that kind of thing yet it is encouraging to see that MX1 code will convert fairly straight forwardly.


Playniax(Posted 2016) [#151]
it is encouraging to see that MX1 code will convert fairly straight forwardly.

Yeah, it was mentioned somewhere that some consider Monkey 1 as abandoned and seeing Monkey 2 as (yet) another new language but to me Monkey 2 looks like a powerfull upgrade!


Danilo(Posted 2016) [#152]
@taumel:
On the other hand, the very basic core of the language should be there from the beginning,
and it must be well thought-out. That's why there are those (sometimes boring) discussions here.
Of course there can be additions later on (like C# 3.0 / 3.5 / 4.0 / ...), but I think Mark is currently
still implementing stuff he wants in MX2 v1.0 Final.

@Mark:
MX2 looks very clean to me, without too many special chars, brackets, etc.
One thing that looks ugly to me is the #Import stuff at the beginning of every file:
#Import "<mojo.monkey2>"
#Import "<mojo2.monkey2>"
#Import "<std.monkey2>"

First, the double-use of " and < is weird. Wouldn't it be cleaner to differentiate between
local files and frameworks/modules just by using "" or <> (like C/C++)?

Second, why not remove the need to use '#' for Import? Make it look like an essential part
of the language, not like a preprocessor thing. Even if it is (technically, internally), you could
handle it without '#'. Like 'Namespace', 'Using', etc. - Import should also be used without '#'
Import <mojo.monkey2>
Import <mojo2.monkey2>
Import <std.monkey2>

Import "myfile.monkey2"

Import "style.css"
Import "stargatesprites.png"

Looks much cleaner in my opinion.

Another small thing I noticed yesterday:
Mojo/textview.monkey2 seems to be a full editor control. Could it possibly make sense to rename it to "Editor",
and use "TextView" later on for a more simple text view control, without full edit features?
Like on Windows, where you can just display static text, input single-line strings, multi-line input/editor,
and full RTF-editor with text styles, etc.

I'm a little bit concerned about bloat-ware. Minimal tests, that result usually in executables of under 100k
with other languages, seem to be 8MB+ currently with MX2.
Mojo always imports .ttf fonts and pictures, even if they are not used. Maybe that could be optimized a little bit later?

BTW:
What's the minimal command-line "Hello World"?
Function Main()
    Print("Hello World!")
End

I tried different 'Import' and 'Using', but somehow I can't get it working. Compiler sometimes aborts
without any message or things like that.

Thanks!


DruggedBunny(Posted 2016) [#153]

#Import "<mojo.monkey2>"
#Import "<mojo2.monkey2>"
#Import "<std.monkey2>"


Yeah, that is pretty weird/horrific!


Michael Flad(Posted 2016) [#154]
Structs can help here too, which is what I'd probably use to implement particles. If they only contain primitive type values, an array of structs will have very little GC overhead (perhaps not yet quite true), ie: as much as a single object since it's elements don't need to be marked.


So MX2 will have arrays of structs in a single block of memory on the heap? I haven't read every single message so I may missed the info in the past - so far I feared they might only be available for value types on the stack.
That's some great news :)


Koradin(Posted 2016) [#155]
+1 for Danilo's comment on imports, though #import is doable but the "<>" is tedious.
BIG +1 for the addition of structs in the form you've made them.
+1 for co-routines and fibers.

Overall I like the direction Monkey 2 is heading. Thanks, Mark!


Richard Betson(Posted 2016) [#156]
+1 on 'Using'. On #Import, I'm cool with it; and how often are you using this directive (it's used little comparatively)?

Yeah, it was mentioned somewhere that some consider Monkey 1 as abandoned and seeing Monkey 2 as (yet) another new language but to me Monkey 2 looks like a powerfull upgrade!

This is very true. MX2 is more an upgrade as opposed to a new path. From what I know Mark has made MX2 to be as backward compatible to MX1 as possible aside from a few syntax and command changes. Basically if your MX1 code is coded using 'Strict' (which I do by default) you have an excellent chance at quickly converting MX1 code to MX2. The biggest issue for some will be the required inclusion of closures with function/method creations and references as well as commands.


dmaz(Posted 2016) [#157]
Here's the problem though - there is no such thing as 'the Actor's fibers'. A fiber is not 'owned' by anything and will only end when it returns, or is cancelled.

I've been thinking about this... Why not have an optional "owner"?

StartFiber:Int( entry:Void(), owner:T=null )

on resume check whether owner has been disposed.... [edit] I don't know what I was thinking.. this is a dumb idea and I can just put it in the entry function anyway.[/edit]

or maybe it's just easier to resource count?... just spit balling! :)

also, what's the deal with the requried blank line at the top of the main src file? and it looks like you took out the For,, shortcut :( [edit] - my bad, I had dumb typo
imagine that sucker with single line lambdas ;)


degac(Posted 2016) [#158]
@Mark
Thanks for the clarification.
I have many situation where I would like to press a button and 'automatically' have an consequence effect (like: move of 10 pages ahead, zoom in of X factor etc). Instead I have to find the event, the check what button is pressed, then increment/decrement a variable.
It's just to avoid too much 'if..then' etc.
In the logic of signals/events/automatic-handler etc of the integrated GUI, at this point adding an internal value could be useful, allowing a 'shorter' programming approach.

I like the idea of SIGNALS (much better than checking the combinations of event/source like in Bmax/MaxGUI).
I suppose we can set a returned signal for each 'gadget' like a button or a windows.
So - technically - a signal of 'CLOSE_WINDOW' could be raised both from a closing window (the x button) and a button programmed for this.


taumel(Posted 2016) [#159]
@Playniax
I guess i disagree with most things you say. Dunno your background and motivation but i know what i've experienced already and where i see the biggest benefit from all this, for me and a larger community. It wasn't web and many platforms and it won't be a full fledged bag of async/events programming too. It will be about a decent mixture of many ingredients with nailing the basics.


Playniax(Posted 2016) [#160]
I guess i disagree with most things you say

I said a lot of things :) Any specifics?


taumel(Posted 2016) [#161]
Nope.


marksibly(Posted 2016) [#162]
> One thing that looks ugly to me is the #Import stuff at the beginning of every file:

Yes, this is ugly, but it's semi-temporary until I decide on the best way to deal with how the user gets to select what modules a project uses. The easiest way would be to just auto-import ALL modules, which would work, but it will eventually start hurting link times badly.

What would be nice is for the IDE to present a 'uses modules' dialog in 'project settings', where the user can manually toggle modules on and off. VC and C# does this with assemblies, which are pretty much the same thing, and I think it works well. The IDE can then pass the modules list directly to mx2cc and the user never sees any of it.

The problem is where to store this project meta data. Perhaps a separate 'blah.make.monkey2' file? The IDE could 'parse' this and present the 'build options' visually and allow the user to edit them. So the user wouldn't have to see this ugliness, but could still do so if they wanted for some reason to manually edit the 'project file'.

Dunno, this is still up in the air, but in the meantime ugly #import will remain! I actually like at the the '#' prefix, as it indicates to me this isn't a normal language construct - and it isn't, it's really an instruction to the build system.

Also note that #Imports only have to appear ONCE per project, not in every file. Multiple #imports of the same file are ignored, but perhaps they should error?

> StartFiber:Int( entry:Void(), owner:T=null )

This would actually be hard/impossible to implement the way things work right now.

For starters, the fiber itself would be keeping 'owner' alive so it would never be disposed. Even if the fiber somehow didn't keep owner alive, owner could still be recycled at any time - perhaps many times - before it is next 'polled'. So 'owner' may still refer to a valid object, just not the one it used to!

What would work here is something like a weak reference, and I've started having a few ideas of how these could work, and in a way that might reduce GC load considerably.

Keep spit balling!

> so far I feared they might only be available for value types on the stack.

The main thing with structs is that 'New' always creates the struct on the stack. This works because the struct is always copied whenever it is assigned/passed anywhere. Apart from that, you can use structs in much the same way as you can use objects.

> In the logic of signals/events/automatic-handler etc of the integrated GUI, at this point adding an internal value could be useful, allowing a 'shorter' programming approach.

Still not sure what you mean, but if you're referring to something like a 'Object userData' or 'void *context' values that gets passed back to the event handler, I have found there really is no need for this (I did wonder at the outset...). In cases where you DO need to maintain some sort of context for a handler to use, just use a lambda, as this automagically captures any context you may need. It pretty much 'writes' the context object for you...

> I suppose we can set a returned signal for each 'gadget' like a button or a windows.

It's up to the gadgets to define the signals they emit, and it's up to the app to 'listen' for signals. Signals are usually object fields, but they could be globals too - they're really just function pointers after all. App.Idle is effectively a global signal (although it's implemented as a field of a global object).

> So - technically - a signal of 'CLOSE_WINDOW' could be raised both from a closing window (the x button) and a button programmed for this.

Possible, but I'd do this differently. A CloseWindow signal is likely to be a field of a window object, and while you could theoretically listen for a button press and then invoke this signal on the window, I'd consider it a bit naughty. Only the gadget that owns/created a signal should really be invoking it.

Instead, if you want multiple signals to cause a 'shared' signal to trigger, you should probably use something like an 'Action'. More on that later...

> What's the minimal command-line "Hello World"?

A simple Main() with NO imports should work, as the core monkey module is imported automatically.

You probably want to #Import "<std.monkey2>" at least to get some minimal functionality, eg:

#Import "<std.monkey2>"

Using std  'for List, Stack, filesystem etc...

Function Main()
   Print "Hello World!"
End


...which works here. Perhaps mx2cc doesn't like the location of your source file? I've been pretty careful with 'spaces in paths' but that's always hard!


Richard Betson(Posted 2016) [#163]
Also note that #Imports only have to appear ONCE per project, not in every file. Multiple #imports of the same file are ignored, but perhaps they should error?

So this would effect imported code data (MX2) where the imported code file does not need to import anything already imported? If so I like this. :) I would think a compile warning error would work fine.


Michael Flad(Posted 2016) [#164]
> so far I feared they might only be available for value types on the stack.

The main thing with structs is that 'New' always creates the struct on the stack. This works because the struct is always copied whenever it is assigned/passed anywhere. Apart from that, you can use structs in much the same way as you can use objects.


Hm so arrays of structs won't be available as a way to use memory in a structured and efficient way?
You mentioned particle systems - how would this work then?


marksibly(Posted 2016) [#165]
Sorry, I probably wasn't clear.

This...

Local p:=New Particle

...will create a Particle on the stack (assuming Particle is a struct).

But this...

Local ps:=New Particle[1000]

...will allocate an array of particles on the heap.


Danilo(Posted 2016) [#166]
What about the following?
Local points:POINT[] Ptr = AllocateMemory( sizeOf( POINT ) * 15 )
Local points:POINT[] Ptr = AllocateStructure( POINT, 15 )

Local points:POINT Ptr[] = AllocateMemory( sizeOf( POINT ) * 15 )
Local points:POINT Ptr[] = AllocateStructure( POINT, 15 )

Don't know. How is current syntax for 'Structure Ptr' pointers?

In this case a continuous memory block would be allocated with 'X' structures,
and the whole memory block is managed by the Garbage Collector (GC).


marksibly(Posted 2016) [#167]
You'd use:

> Local points:Point Ptr=Cast<Point Ptr>( malloc( sizeof( Point ) * 15 ) )

A pointer effectively is an array, as it's just the the address of a chunk of memory.


Danilo(Posted 2016) [#168]
Ah, Okay. Thanks, Mark!


ImmutableOctet(SKNG)(Posted 2016) [#169]
@marksibly:

I haven't been keeping up with this too much, so I may be behind on some things:

Any thoughts on stack allocated or fixed size arrays coming back?

So, something like this:


Where the number specified is a numeric literal (Or constant?), and the allocation would be scope-allocated. For example, a 'Struct' could hold a fixed-size array without needing to touch the heap. If concurrency is going to be a trend, this would be useful. It would also help with cryptographic functions and the like, where small fixed-size arrays could be allocated on the stack.

The interesting part is that the compiler could determine if the array should be locally allocated or not. You could then assume that smaller arrays are scope-local, and larger arrays are ambiguous (Executable, heap, stack, etc). Obviously, something like 'Float[X]' (Where 'X' is a variable) that Monkey 1 has shouldn't really come back (Unless you use 'New'), as it makes light of potential storage demands, and could cause huge allocations.

I guess the biggest problem is the lack of "array views" or some kind of atomic access. I guess if nothing else, you could make "New Array" itself ambiguous. Or maybe the heap is good enough at this already? Well, it's just an idea.

As a follow-up question, are structures going to stay zero-initialized by default? I imagine the answer's yes, like 'Objects'. - EDIT: To clarify, I'm referring to using a structure without using 'New' beforehand.


marksibly(Posted 2016) [#170]
> Any thoughts on stack allocated or fixed size arrays coming back?

Not sure yet.

There are a few problems with this. They're not 'real' arrays, so can't be easily assigned to fields/globals, passed to functions or returned. They would probably have to be copied. I guess this could just cause a compiler error, but then I'd prefer they somehow didn't 'look' like normals arrays.

Also, small arrays aren't that much of a GC issue - the 'small object pool' system makes them fast to allocate, and since nothing's referencing them when they go out of scope, they don't cost anything to mark. This do sit there in memory until the next 'sweep' though...

Another idea would be to get the translator to detect small array allocations and optimize them into stack arrays. I don't think this'd be that hard to do - if an array is new'ed with a small enough constant length, and never passed to a function or assigned to a heap var or returned, then the translator could just use a plain C stack array. But how many situations does that happen in anyway?


Michael Flad(Posted 2016) [#171]
Local p:=New Particle

...will create a Particle on the stack (assuming Particle is a struct).

But this...

Local ps:=New Particle[1000]

...will allocate an array of particles on the heap.


Ok great - that's what I'm interested in.
One last small question. Just to be sure - accessing the fields of the structs in the array on the heap doesn't automatically create a copy on the stack each time for each arrayelement but happens directly on the heap allocated block?


Danilo(Posted 2016) [#172]
Fixed size arrays are often used in OS structures. Char name[MAX_PATH] etc.


Playniax(Posted 2016) [#173]
@taumel: Well, regarding the things I said on this topic you apparently don't agree on my view of Monkey 2 beeing a powerfull upgrade to Monkey 1 and/or my comment on your remark about Monkey beeing a step backwards from both, a dev's and user's point.
Of course it's fine if you dissagree with me but Monkey beeing a step backwards from both a dev's and user's point is an oversimplifies statement based on your opinion but you seem to write it as fact.


EdzUp MkII(Posted 2016) [#174]
Is the MX2 demo 64bit only on Linux?

I do the ./rebuild all.sh but all I get is a error that it can't run the compiler which it calls.


dawlane(Posted 2016) [#175]
@EdzUp: Which compiler? There are two used for building transcc and mx2cc. Technically there are four when GCC and Emscripten are thrown in.


ziggy(Posted 2016) [#176]
Also note that #Imports only have to appear ONCE per project, not in every file. Multiple #imports of the same file are ignored, but perhaps they should error?

well, it will be common that several modules may be importing mojo2, or any low level or core modules. If you import two modules that use mojo2, it should not cause an error.

Also, how it file/modules dependencies handled? In Monkey1 I really like that any file is aware of what it imports and this does not deppend on the program entry point (unless it's imported too). That makes intellisense and context-based semanting very delimited and clear. In blitzmax, as instance, as any keyword could be made accesible in a file because it was included in any other file that also included a module with this keyword. This forced a much more agressive tree navigation of the whole project to determine what the keyword was.

All in all, how is importing + semanting going to work in Monkey2, and are you considering maintaining one of the good things of monkey1 which involved that any file/module was aware of its own context and self-contained? Not sure if I'm explained myself properly


taumel(Posted 2016) [#177]
@Playniax
It's more like we seem to have opposite opinions on more topics, which is fine, i just got aware of it.

My statement regarding Monkey sums up the experiences i've made with it. It's an incomplete attemp trying to address the wrong topics.

I would be fine just with: import mojo


marksibly(Posted 2016) [#178]
> and are you considering maintaining one of the good things of monkey1 which involved that any file/module was aware of its own context and self-contained?

Not really sure what you mean here - monkey files still potentially depend on other monkey files for 'imports' don't they?


ziggy(Posted 2016) [#179]
Yes, but all files used (directly or indirectly) on a "module" is defined in the module, and that's very nice, while in BlitzMax you could have an import in the main file entry point, and use that imported module in any other included document.

MainFile:
   Import Mojo2
   Include File2

In this scenario (BlitzMax like), file2 could reference the Image class from mojo2 because Mojo2 is imported in the program entry point. In this case, file2 would not need to make any reference (direct or indirect) to the Mojo2 module. So, when you're editing File2, in order to know what the Image class means there, you need to navigate the whole imports structure to see what's imported and what not from the program entry point.

That caused in BLIde something not very nice: If a file was imported twice, it was possible for that file to have 2 different available scopes, and it complicated drastically all intellisense work.

My question is, more or less, how this is going to work on Monkey 2.


marksibly(Posted 2016) [#180]
It's more similar to blitzmax.

Basically, you give mx2cc a 'root' file, and any file 'reachable' via #import from that file is part of the build and can be used by any other file.


ImmutableOctet(SKNG)(Posted 2016) [#181]
@Ziggy: From the look of the current system, it's just as you describe. Imports aren't a thing anymore. Instead, we have 'Using', which allows us to use any code from loaded assemblies with the namespace we specify. So, instead of using 'Import' as you did in Monkey 1, you'd use 'Using'.

Mark has discussed '#Import' a few times now, it's not an actual import feature. It's a workaround for standalone programs. So, you would use '#Import' to add an assembly, and 'Using' to use what's in the assembly. I haven't tested it myself, but I assume anything "#Imported", or otherwise added would be accessible through a global title, like what Monkey 1 has for name resolution.

In summary: "File2" would not see any code from "MainFile" implicitly. If "File2" were to use 'mojo2', then I imagine "MainFile" would implicitly use 'mojo2' as well. Not sure on that one. Maybe Mark can clarify if "private and/or public uses" are a thing? Anyway, I think the main point to take away from this is that 'Using' is the new 'Import', it's just more abstract from the file/module structure.

EDIT: Just saw that Mark answered, still, my post should help.


Richard Betson(Posted 2016) [#182]
Based on Marks answer I would think anything imported in the head (main) source is available to any other imported file/code. ImmutableOctet(SKNG) suggest that code (assemblies) imported into the main source is available to any other imported file as long as it is within the same namespace scope and defines the import target via 'Using'. Am I right?


ziggy(Posted 2016) [#183]
Ok I see. thanks!


EdzUp MkII(Posted 2016) [#184]
Dawlane: I think it as transcc which wouldn't execute (it's all setup as a executable and everything else runs for the drive). This is why I wondered if it was a 64bit only.


dawlane(Posted 2016) [#185]
@EdzUp: Yes transcc is a 64bit in the archive. You will have to use the git hub C++ source file for transcc to build a 32 bit version for use. See the MonkeyX ./rebuildall.sh file in the MonkeyX src directory for the command line.


EdzUp MkII(Posted 2016) [#186]
Ah thanks dawlane will have a look :)


taumel(Posted 2016) [#187]
neat


EdzUp(Posted 2016) [#188]
Test?

I had mark pop up with Test... in the info :)


Danilo(Posted 2016) [#189]
Xmas demo v3 available for Linux+Mac. What has been changed?


taumel(Posted 2016) [#190]
Hmm, just read the About.

Which one would you prefer (weird tabs here)?

Class MyClass Extends BaseClass

   Field x:Float
   Field y:Float
   Field vx:Float
   Field vy:Float

   Method Update()
	Print( "Updating!" )
	x+=vx
	y+=vy
   End
End


class MyClass extends BaseClass

    float x,y,vx,vy

    method Update
        put "Updating!"
        x+=vx
        y+=vy



TheRedFox(Posted 2016) [#191]
The first one.


therevills(Posted 2016) [#192]
Yep def the first one...


Danilo(Posted 2016) [#193]
The first one as well, but I would like to add multi-var declaration for 'Global' / 'Local' / 'Field':
If one of those keywords is followed by a colon, the following word is the type - followed by a comma-separated list
of variables and optional initializers.
Global:Int x, y, z
Local:Float f1, f2 = 5.0, f3
Field:Player p1, p2, p3
Local:Int[] arr1 = [], arr2 = [10,20,30]

Should be fully compatible with the current syntax. Happens only if there is a colon after 'Global' / 'Local' / 'Field'.


abakobo(Posted 2016) [#194]
Like Danilo or
Field x,y,vx,vy:Float

would be more logical to my eyes.


taumel(Posted 2016) [#195]
Looks horrible to me but it reminds me of a humorous part in da monkey doc, fUNCTION.


Danilo(Posted 2016) [#196]
No problem, taumel. You can still use current syntax:
Class MyClass Extends BaseClass

   Field x:Float
   Field y:Float
   Field vx:Float
   Field vy:Float

   Method Update()
	Print( "Updating!" )
	x+=vx
	y+=vy
   End
End

My suggestion is an additional, new, way for multi-declarations.
Class MyClass Extends BaseClass

   Field:Float x, y, vx, vy

   Method Update()
	Print( "Updating!" )
	x+=vx
	y+=vy
   End
End

It simply means, if the Type comes first (colon after 'Global' / 'Local' / 'Field'), all following variable names are of that Type.

Both would be allowed (important for compatibility):
Local x:Float, y:Float, vx:Float, vy:Float

Local:Float x, y, vx, vy



Richard Betson(Posted 2016) [#197]
Local:Float x, y, vx, vy

Hmmmm... I think I will +1 that. :) It is kind of a sexy way to initialize things. Supporting both would be required though.


taumel(Posted 2016) [#198]
@Danilo
Nope, the current implementation, in this respect, is horrible too.

As suggested (months ago) already, get rid of the ":" ("Space" instead of "Shift"+".") making it clear, easy and fun.


therevills(Posted 2016) [#199]
Just get rid of the keywords "Local" and "Field" and be done with it. Oh... then its just like Java ;)


Richard Betson(Posted 2016) [#200]
Just getting rid of the keywords "Local" and "Field" and be done with it. . Oh... then its just like Java ;)

LOL.. We must stay on the Monkey path. Heresy :D


Sicilica(Posted 2016) [#201]
I may be a bit late to the discussion, but I really prefer the MX1 style imports. I think it's really important that I can look at a .monkey file and know exactly what code it has access to, what's in scope, what other files are accessed. Maybe good use of namespaces and Using can achieve something similar, but it sounds like what an individual file is able to do is a lot more dependent on the context, which means individual modules are harder to understand without having a deep understanding of the whole project. On big projects, that's not an insignificant thing.

I guess having an #Import elsewhere in the project making code visible to completely unrelated files sounds like what'd I'd expect and hope for in a scripting language, but for Monkey I really like the separation a stricter language provides. Heck, even if the native code that's generated has open imports like that (I know these dependencies are part of what makes C++ in particular get really complicated), I'd want trans to still enforce and treat imports the way MX1 does. But maybe that's just me?


Gerry Quinn(Posted 2016) [#202]
My impression is that 'Using' is the new 'Import' and the others are mostly just to help in finding paths to modules,.. For example if you wanted to use a particular older version of a module in one project, this is slightly awkward now.

For example, your main program would say "Import XModule_1.4" and your files that call it would say "Using xmodule".

Is this - aside from syntax details - correct?

If not, I echo your concerns. But my reading of the discussion suggests that Using replaces Import with much the same functionality.


Danilo(Posted 2016) [#203]
@Gerry Quinn:
#Import really imports files (source code, images), frameworks, etc.
Using brings things (classes, functions, structs, etc.) from a namespace into the global namespace.

Example1:
' empty line
#Import "<lib.monkey2>"        ' Import a library/framework

Struct Point
    Field x:Int
    Field y:Int
End

Function Main()
    Local pt:Point
    Print("sizeof(pt):")
    Print( lib.c.sizeof(pt)  ) ' use Function sizeof with full namespace
    Print("---")
End

Example2:
' empty line
#Import "<lib.monkey2>"        ' Import a library/framework

Using lib                      ' We are using namespace 'lib' -
                               ' That means, everything from namespace 'lib'
                               ' becomes directly available within the global namespace

Struct Point
    Field x:Int
    Field y:Int
End

Function Main()
    Local pt:Point
    Print("sizeof(pt):")
    Print( c.sizeof(pt)  )      ' use Function c.sizeof - we don't need to write lib.c.sizeof() anymore,
                                ' because we did 'Using lib' to use everything from this namespace directly
    Print("---")
End

Example3:
' empty line
#Import "<lib.monkey2>"        ' Import a library/framework

Using lib.c                    ' We are using namespace 'lib.c' -
                               ' That means, everything from namespace 'lib.c'
                               ' becomes directly available within the global namespace

Struct Point
    Field x:Int
    Field y:Int
End

Function Main()
    Local pt:Point
    Print("sizeof(pt):")
    Print( sizeof(pt)  )        ' use Function sizeof - we don't need to write lib.c.sizeof() anymore,
                                ' because we did 'Using lib.c' to use everything from this namespace directly
    Print("---")
End



marksibly(Posted 2016) [#204]
Danilo's examples give a good overview of what's going on.

Some of this is necessary because monkey2 supports 'real' libraries now. In monkey1, everything just got pasted into one mega source files so the idea of 'modules' is really kind of bogus - they're really just source files that happen to reside in a special directory that gets searched during 'import'.

This is what #Import "<blah.monkey2>" is mainly for - to indicate to the compiler that a module/library needs to be linked with. But #Import also auto imports the monkey2 source file that accompanies the library. This makes sense to me otherwise you'd always need 2 imports - one to import the library, one to import the monkey2 code that 'describes' the library.

So yes, importing a module/library does affect all files in a project, but only to the degree that it adds a single (typically...) 'global' symbol that all files in the project can then access - the top-level namespace that contains everything in the module, eg: 'lib', 'std', 'mojo' etc. It's then up to you whether you want to use 'Using' to get at the module content lazily, or access module content 'strictly' via lib.c.sizeof etc.

It's a compromise of sorts, but kind of inevitable since we're getting into 'linker' issues here. But IMO it works well and is already 101 times better than monkey1's system which had a ton of problems of its own. In particular, I love being able to just use a plain file path to import a source file instead of the mickey mouse 'relative module path' system in monkey1 that meant you had to be very careful about what you named your source files (and meant you seldom knew the true module path of a file - and couldn't even import source files that were above the root main file). Also, being able to move files around freely without breaking all imports is a massive improvement. Breaking a large file in monkey1 into bits was problematic because it instantly meant each new file suddenly had a new module path.

Monkey1 also relied a lot on 'imports importing imports' to hide a lot of messy import stuff behind the scenes, so it probably looks cleaner that it really is. But I didn't want to do that this time, ie: just dump everything in mojo into scope because of one 'Import mojo'.

This is all based a lot on C#'s system - and a to a lesser degree D's - both of which seem to handle big projects fine. The main difference is that neither C# or D support #Import to add libraries to a project - libraries must be specified on the command line. I considered this and will probably support it in addition to #Import, but being able to specify link files/modules 'in source' is very convenient, and of course very useful while developing!


Danilo(Posted 2016) [#205]
@Mark:
Quick question: Is it possible to add binary libs (.obj/.lib/.o/.a/.so/.dylib/etc.) to a project (to the linker, to be exactly)?
How? Using '#Import' as well, or some preprocessor thing like #CC_LIBS or something like this?
I want to start my first lib (tests) tomorrow... thanks


marksibly(Posted 2016) [#206]
> For example if you wanted to use a particular older version of a module in one project, this is slightly awkward now.

Not sure how easy this is in monkey1(?), but yeah, this is awkward and something monkey2 should definitely help with (eventually).


marksibly(Posted 2016) [#207]
> Is it possible to add binary libs (.obj/.lib/.o/.a/.so/.dylib/etc.) to a project (to the linker, to be exactly)?

Should pretty much work already - if I've missed a necessary extension, look in src/mx2cc/builder.monkey

Basically, just #import any files you want added to the project, eg:
#Import "native/lib/somelib.a"   'local import of a static link library.

...or...
#Import "<libwinmm.a>"     'system lib import - specify actual filename here, not -l name.

Have a look at modules/lib/gles20/gles20.monkey2 for some gnarly #Import examples!


Danilo(Posted 2016) [#208]
Great, thanks! Off to work now (real-life job)... being in a good mood, looking forward to have some MX2 fun. :)


tiresius(Posted 2016) [#209]
This might seem silly but can we have <> for modules/libs and "" for direct file imports, but not have "<>" ? It just doesn't look right to me. :/


ratking(Posted 2016) [#210]
Haha, I thought the same. #Import "<foo>" just looks silly.


Danilo(Posted 2016) [#211]
@tiresius, @ratking:
Mark talked about this on Page 7 already. But of course it's good (and important) to see more opinions about it. ;)


ratking(Posted 2016) [#212]
I guess I need to read the whole thread. ;-)


ratking(Posted 2016) [#213]
@Danilo: Okay, I read it now, and Mark actually didn't talk about the "<foo>" vs. <foo> thing (only about the # of #Import). So it's still open for discussion!

Another thing: will Monkey2 have a ternary operator? I just like the ?: syntax just too much.

And third: how about changing the comparison operator from = to ==? This way we could have chained assignments like
x = y = z = 3


(It would also make "Local b:= x = 3" look less confusing ;-)


Timotron(Posted 2016) [#214]
I agree a ternary operator would be ideal for making tighter easier to parse code. I miss it often when coding in Monkey and I have to write 3 or 5 lines of code instead of a single line.

Also using == for comparison would be very nice as well.

Just my 2 cents.


Danilo(Posted 2016) [#215]
@Mark:
When loading dynamic libraries at runtime, we usually have a function like GetProcAddress or dlsym to get a pointer to a function.
Function dlsym:Void Ptr(handle:Void Ptr, symbolName:String)
Function GetProcAddress:Void Ptr(handle:Void Ptr, symbolName:String)

But how can we actually use and call that pointer? If I use Function variables, I get the error 'Error : Can't convert from type 'void ptr' to type 'int()'.
Tried several ways (Casting etc.), but can't get it to work.

Small example for Mac OS X:
#Import "<dlfcn.h>"

Alias pMyFunc:Int()

Extern
    Const RTLD_LAZY:Int
    Const RTLD_NOW:Int
    Const RTLD_GLOBAL:Int
    Const RTLD_LOCAL:Int

    Function dlopen:Void Ptr(path:String, mode:Int = RTLD_LAZY|RTLD_GLOBAL)
    Function dlclose:Int(handle:Void Ptr)
    Function dlerror:String()
    Function dlsym:Void Ptr(handle:Void Ptr, symbolName:String)
Public

Function Main()
    Print("---")
    Local myfunc:pMyFunc
    
    Local lib := dlopen("/Users/danilo/myfile.dylib") ' OK
    Print( lib )                                      ' OK
    If lib
        Print( dlsym(lib, "myfunc") )                 ' OK
        Print( dlsym(lib, "myfunc2") )                ' OK
        
        myfunc = dlsym(lib, "myfunc")                 ' Error : Can't convert from type 'void ptr' to type 'int()'
        pMyFunc( dlsym(lib, "myfunc") )()             ' Error : Can't convert from type 'void ptr' to type 'int()'
        myfunc = Cast<pMyFunc>( dlsym(lib, "myfunc") )' Error : Can't convert from type 'void ptr' to type 'int()'
        
        dlclose(lib)                                  ' OK
    Else
        Print( dlerror() )                            ' OK
    Endif
End



Nobuyuki(Posted 2016) [#216]
And third: how about changing the comparison operator from = to ==? This way we could have chained assignments like

x = y = z = 3

(It would also make "Local b:= x = 3" look less confusing ;-)


that's not very basic-like. Chained assignments look awful to read!

I like ternary operators, though. For my own code, I take the performance penalty and use Generics to implement Iif(). It's not quite the same thing, but it provides a similar convenience. With operator overloading you might be able to simulate a ternary operator depending on what characters we have access to -- since I believe type sigils may be removed from MX2 that would free up more symbols to assign them to things like Pow, Mod, Iif, etc.


nullterm(Posted 2016) [#217]
Even as a life long C++ programmer, I think Monkey should stick with = for assignment and comparison, as is.

As Nobuyuki said, == isn't very basic-like. And at it's heart, Monkey is more novice friendly staying closer to basic than C++.


Gerry Quinn(Posted 2016) [#218]
I agree - a ternary operator would be great, but we don't need chaining.


marksibly(Posted 2016) [#219]
> When loading dynamic libraries at runtime, we usually have a function like GetProcAddress or dlsym to get a pointer to a function.

It doesn't work yet, but the general idea will be to use this approach:

Local func:=Cast<Void()>( GetProcAddress(...) )

(This is one of the reasons for the new Cast<> operator, as parsing gets incredibly messy without it).

The other option is to get hold of the 'static' lib for a dll. This contains a bunch of function pointers that are initialized for you, so you just need to Extern the entry points. And on macos I believe you can use the dylib as the static lib, although builder doesn't support this yet.

I have concentrated mainly on building libs from source so far, and haven't done a lot with dll loading. The windows lib.gles20 uses dlls for angle support, and links with the angle static libs to provide entry points but that's it.

> I agree - a ternary operator would be great, but we don't need chaining.

Ditto.


Danilo(Posted 2016) [#220]
Importing/Including does not work on OS X: Objective-C (.c/.m/.cpp/.mm) can't be included/compiled (would require "-x objective-c" switch for g++,
minus "-std=c++11" switch), libs (.so, .dylib, .a, .o) are not correctly copied & linked, etc.

Is there a planned date for the next demo?

compile.sh
g++ -framework Cocoa -ffreestanding -x objective-c -c myfile.cpp -o myfile.o

g++ -shared -framework Cocoa --target=x86_64 -ffreestanding -o myfile.so -fPIC myfile.o
g++ -dynamiclib -framework Cocoa -ffreestanding -o myfile.dylib -fPIC myfile.o
gcc -static -framework Cocoa -ffreestanding -x objective-c myfile.cpp

ar -r myfile.a myfile.o

myfile.cpp

The above should work (call myfunc & myfunc2), compiled as .o, .a, .so, .dylib, and directly included as .c/.cpp/.m/.mm


marksibly(Posted 2016) [#221]
A couple of points:

Use the .m file extension for objective c files (and .mm for objective c++).

You will also need a header '.h' file that describes the interface in C/C++. Something like:

#ifndef BB_MYLIB_H
#define BB_MYLIB_H

#ifdef __cplusplus
extern "C"{
#endif

int myfunc();
int myfunc2();

#ifdef __cplusplus
}
#endif

#endif


The 'extern "C"' is required since you are building a '.m' file, which produces code with 'C' name mangling. If you rename it '.mm' you should be able to drop the 'extern "C"' stuff.

The .h wont be necessary when dynamically linking as you are just declaring function pointers. 3rd party static libs generally always provide .h files, otherwise they're useless for use with C/C++.

So the final monkey2 code might look like:

Namespace mylib

#Import "native/mylib.h"
#import "native/mylib.m"

Extern

Function myfunc:Int()
Function myfunc2:int()



Untested!


Danilo(Posted 2016) [#222]
Thanks Mark, but this wasn't the main problem.

Anyway, found the solution now:
In the file "monkey2/bin/env_macos.txt" we need to add 2 compiler flags:
1.) Add option -ObjC to MX2_CC_OPTS_DESKTOP
2.) Add option -ObjC++ to MX2_CPP_OPTS_DESKTOP

Objective-C code works now with .c + .m files.
Objective-C++ works with .cpp and .mm files.

#Import for .o and .a works now, too. (thanks to your header example, I missed extern "C")

#Import does not work with .so and .dylib (they are not added to linker, so we get missing symbols).

BTW, minimalistic HelloWorld works now too (using Xmas demo v3 on Mac OS X):
Function Main()
    Print("Hello World!")
End

Resulting App is 43 KB, that's nice and acceptable. ;)


marksibly(Posted 2016) [#223]
> In the file "monkey2/bin/env_macos.txt" we need to add 2 compiler flags:

Did you try renaming files? SDL2 has objc some .m files and it compiles fine.

Not to keen on compiling ALL .c files with the objc compiler. It works I guess because objc is an extension to c, but '.m' is the standard file extension for objc (used by xcode etc) so I would prefer to stick with that.

> #Import does not work with .so and .dylib (they are not added to linker, so we get missing symbols).

#LD_OPTS probably needed for this...

> Resulting App is 43 KB, that's nice and acceptable. ;)

Not bad! The other env.txt files probably need a '-s' linker switch added to achieve similar results.


Danilo(Posted 2016) [#224]
> Did you try renaming files?

Yes, I tested with all 4 extensions (.c/.m/.cpp/.mm).

> Not to keen on compiling ALL .c files with the objc compiler.

Why not add the gcc (-ObjC) and g++ (-ObjC++) compiler option within builder, only for .m + .mm files?


Chroma(Posted 2016) [#225]
Where's the demo?


tiresius(Posted 2016) [#226]
Where's the demo?

It's on the first entry first page of this topic. Mark's new blog...


Chroma(Posted 2016) [#227]
Yep just found it. Sorry!


taumel(Posted 2016) [#228]
@Mark
Inspired by Danilo's question about a possible release date for a new version, which you preferred not to answer, does there generally exist a roadmap which includes time estimations for when you expect all these things (written in Ted 2's welcome text) to happen (also considering the current financial support)?

Regarding gfx, mojo2d and mojo3d sound nice, then there is mojo2 with its quirks, easier Max like gfx seem to come afterwards, ... and i haven't even touched sfx, docs and zebra. When do you expect having a more complete release (not finished but more useable, including docs, maybe like the first Max release) around?

Some more infos could be nice.


dmaz(Posted 2016) [#229]
I would second taumel's request though I'm not one for setting dates on any lists like that as they tend to be very troublesome.

what I think would be really nice, is a list of items of both features and issues and maybe milestones in semi-priority order. Then obviously marking items done as you go. Such a list would only be a guide not a strict project plan as those can be troublesome as well. I'd actually put a big disclaimer at the top indicating these things

here is a very simple example... http://www.aseprite.org/roadmap/ the only thing I'd add to this is completion dates on the things he's knocked off.

List's like this build support, keep the community active and act as marketing and buzz.


taumel(Posted 2016) [#230]
It took Unity many years to get more transparent on what they're working on but currently they (as well as Epic Games and other companies) are doing a nice job in this respect. Sometimes things work out, sometimes they don't but no matter how they turn out, you're in the queue. This doesn't matter when you're popping in here only once in a while but it can be important when you're working on stuff and you feel less blind this way.


Pharmhaus(Posted 2016) [#231]

I'm not one for setting dates on any lists like that as they tend to be very troublesome.


So true. especially when prototyping / fleshing out ideas and doing research.


what I think would be really nice, is a list of items of both features and issues and maybe milestones in semi-priority order.


I hate how many solutions get over complicated and start being a time waste or burden where a great amount of time goes toward managing.
Something very simply like Trello (free) could do the job very well.
It is possible to mark a board as "public" so that everyone can read but only mark could write/change content.
I also wouldn't mind if there was an alpha repo on github and things were tracked via issues or something similiar.


Sometimes things work out, sometimes they don't but no matter how they turn out, you're in the queue. This doesn't matter when you're popping in here only once in a while but it can be important when you're working on stuff and you feel less blind this way.


Indeed. I believe there are still things which are totally unclear but I, for example would be really interested in 'failed' attemps as well just out of curiosity.
Nonetheless I dont't think its worth overdoing it. There's only so much a man can take.