BlitzMax bounties

BlitzMax Forums/BlitzMax Programming/BlitzMax bounties

skidracer(Posted 2015) [#1]
I thought it would be fun to brainstorm some hypothechnical goals for BlitzMax development.

1 - case sensitivity switch for bcc / bmk toolchain


JoshK(Posted 2015) [#2]
64-bit.


Yasha(Posted 2015) [#3]
Had a bunch of ideas over the years...

Big features: Aspects/Interfaces/Lambdas/Generators (see sig for proofs-of-concept!). Mixins/class extensions. SML-style modules/namespaces. Metaprogramming.

Medium features: better type system. In particular the current subtyping rules are wrong (Array(Foo) should not be a subtype of Array(Object); this is unsafe; but how the two should be related needs discussion). Adding some notion of parametricity/generics is the only really safe way to solve this. (In practice this doesn't seem to be a problem in real world code.)

Lesser features: fast reflection. Being able to implement the array-index operator for any type. Being able to pass objects (such as strings) to the array index operator. Being able to use undeclared method/field names on Object (i.e. like JS and Lua).

Minor features: Constexpr functions. A builtin clone method. Better newline handling.

Backend features: LLVM target. Interpreter target. Seamless interop between the interpreter and compiled code so that you can load interpreted classes in a compiled program. More options for GC implementation (so you can choose a GC with the performance characteristics to suit your program: full, refcount, regions, etc.).



Modifying Mark's compiler to add front-end language features (like e.g. lambdas) may be quite difficult. Hand-written compilers are difficult to extend with new features (especially if you aren't the original author), doubly so when they aren't implementing a separate spec. The best thing that can happen in this regard is proliferation and the emergence of competing toolchains (*cough* rule-based designs *cough*).

Modifying Mark's compiler to add 64-bit should be possible, but the existing design does seem to assume 32-bit pointers throughout (it considers int32_t and void* the same thing and coalesces them at an early stage). This is another thing that will really benefit from proliferation.


Meta feature: establish a separate GitHub page from the main BlitzMax repository to act as the "BlitzMax community definition", to act as a guide for proliferators so they know what exactly constitutes BlitzMax in these changing times. It doesn't have to be an ISO standard, but it's better that the language is defined by human-readable words, rather than an undocumented code implementation.


Brucey(Posted 2015) [#4]
Hamsters.

They're just so cute :-)


LT(Posted 2015) [#5]
Modifying Mark's compiler to add 64-bit should be possible
But what would the point be? Wouldn't it make more sense to build on Brucey's version?


Yasha(Posted 2015) [#6]
Yes it would. But Josh mentioned it like it was a thing that didn't exist yet.

Still, this is a good time to be separating the language from its implementations. No longer any reason to have one Received Truth.


Brucey(Posted 2015) [#7]
Yasha, you can try 64-bit BlitzMax here if you want : https://github.com/bmx-ng/bmx-ng/releases
(In MaxIDE, choose Architecture -> x64, and then Build)


JoshK(Posted 2015) [#8]
That's come a long way since the last time I looked at it.

Win32MaxGUIEx and Pub.Win32 seem to need a lot of work still.


LT(Posted 2015) [#9]
Brucey, is MaxIDE the only option or will BlIDE work?


skidracer(Posted 2015) [#10]
2 - brl, pub and maxgui module parity with bmx-ng


DStastny(Posted 2015) [#11]
1 - Switch the codegen to LLVM tool chain and dump the native assembly.


skidracer(Posted 2015) [#12]
Heh, that native assembler would look like toxic voodoo if it was converted to C, given the stack mangling involved.

I like the sound of an llvm back end.


LT(Posted 2015) [#13]
Switch the codegen to LLVM tool chain
Sounds like a lot of work.


JoshK(Posted 2015) [#14]
What is the benefit of LLVM, besides gaining approval for buying into the latest trend?


Shagwana(Posted 2015) [#15]
Unit tests to make sure functionality remains with what ever happens!


LT(Posted 2015) [#16]
A better pre-processor and some form of inline feature would be my first choices.


John G(Posted 2015) [#17]
Incorporate Oddball's Odd2D.mod which extends OGL and DX graphic drivers.


JoshK(Posted 2015) [#18]
I'm shocked the BlitzMaxNG debugger appears to work. Seeing those extra-long memory addresses is really amazing.


Yasha(Posted 2015) [#19]
What is the benefit of LLVM, besides gaining approval for buying into the latest trend?


It eats an assembly-like language, as you might output from something like bcc, but performs C++-quality optimizations on it instead of just assembling (as demonstrated by the fact that it's used to optimize C and C++ for Clang). It's a massively-portable compiler backend designed to fit multiple input languages and multiple backend processors.

In practice? Not sure it would buy BlitzMax very much, because NG can already optimize via LLVM if its emitted C is fed through an LLVM-based C compiler. The main thing is that since LLVM is a slightly lower-level language than C, it provides much better opportunities for deeply-integrating a fast garbage collector (C is incredibly hostile to GC, resulting in either Boehm, or other solutions with similar glaring flaws despite their good designs; C cannot describe even the existing BRL refcount collector). Everything else about the BlitzMax language can already be expressed perfectly well in C with zero overhead (it's all function calls and gotos and pointers, basically), so there's not much need for a lower-level language the way there would be for e.g. Haskell.

Unless someone's going to design a new GC (or I guess import one from another LLVM-based language, if a suitable one exists), TBH this isn't really a priority. Be aware that designing a good modern GC is harder than literally the rest of the BlitzMax project combined.

That said, based on the brief exchange with Mark in the announcement thread, it shouldn't actually be hard to do for someone who a) knows LLVM and b) can work out the rules for Blitz's internal abstract assembly. The main obstacle to adding it to BRL-bcc is (as mentioned above) that it discards type data too early, so unless that can be fixed too, it's 32-bit only.


JoshK(Posted 2015) [#20]
How does garbage collection even work with this? This program never calls the Delete method:
Type TThing
	
	Field n:Int=1
	
	Method Delete()
		Print "Delete"
	EndMethod
	
EndType

Local thing:TThing=New TThing
thing = Null

GCCollect()

End



Grisu(Posted 2015) [#21]
For local i:int=0 to 999
Print "64 Bit!"
Next

- Dx 10/11/12 support => see modules from col.
- BatchAdd Listboxgadgetitems => see module from ???. Needed for Listboxes with 500+ items.
- a (simple) grid listbox.
- a module that supports MP3/AAC internet streaming, so I can do a PRP 2.0. :)
- no different syntax, so old apps stay compatible (as far as possible).
- lots of hamsters, because they are cute. ;)
- a way for normal users to support / kickstart / help BRL to fund this!


degac(Posted 2015) [#22]

I thought it would be fun to brainstorm some hypothechnical goals for BlitzMax development.

1 - case sensitivity switch for bcc / bmk toolchain


Please, delete this sentence.
I hope this is just a joke.


JoshK(Posted 2015) [#23]
no different syntax, so old apps stay compatible (as far as possible).

This+++. I really don't think more libraries and language features are needed, before the existing stock functionality works with 64-bit.


Yasha(Posted 2015) [#24]
How does garbage collection even work with this? This program never calls the Delete method

Remember that finalizers are not destructors. Under GC, a finalizer is never guaranteed to be called at all, which is why every language tells you not to put essential operations in a finalizer. If you need RAII-style reliable disposal, you need to wrap a code block in a structure that enforces it, e.g.:

Type Foo { IDisposable }
    Field x:Int = 6
    Method Dispose()
        Print "disposing foo"
    End Method
End Type

' this is our operation block
Function DoSomethingWithFoo(o:Object)
    Local f:Foo = Foo(o)
    Print "we got a foo with " + f.x
End Function

' RAII enforcer
With(New foo, DoSomethingWithFoo)

where With is something like

Function With(o:Object, f:(_:Object))
    Try
        f(o)
    Catch e:Object
        TTypeId.ForObject(o).FindMethod("Dispose").Invoke(o, Null)
        Throw e
    End Try
End Function

GC is usually assumed to be optimized for the memory use case, whereas RAII is optimized for more heavyweight resources, which is why most languages prefer GC (collect memory in large blocks, all at once, only when necessary because of usage pressure, not ASAP like you would a file handle). If a program doesn't run out of memory, never finalizing anything is perfectly correct behaviour.

Boehm GC follows this cross-language convention of focusing on memory first and effects second-or-never.


Brucey(Posted 2015) [#25]
How does garbage collection even work with this? This program never calls the Delete method

I presume your testing 1.50? I get nothing on OS X either when I run that.

As Yasha says, GC only collects when it needs to, not when you think it should.


Silver_Knee(Posted 2015) [#26]
Better Null handling:

Local nil:Object=Null
Local s:String=String(nil)
Local dafaq:Object=s

If dafaq != Null
  Print "this"
Endif


same goes for empty arrays. If I have an object and want to test if it is a string, how do I do it? This won't work:

If String(anyObject)
  'do the thing 
EndIf 



TomToad(Posted 2015) [#27]
Function overloading and Operator overloading


Brucey(Posted 2015) [#28]
Dx 10/11/12 support

What difference is a Max2D DX 11 over a Max2D DX 9? Max2D is so inefficient it's not funny. DrawText is atrocious.

Presumably we just wait for MX2's drawing framework to come out and just copy and paste it into BlitzMax? Job done. No problems.

I had considered having a go at mojo2, but it's all proprietary nonsense, so there's no point.


JoshK(Posted 2015) [#29]
What difference is a Max2D DX 11 over a Max2D DX 9? Max2D is so inefficient it's not funny. DrawText is atrocious.

Two.

Take the DirectX9 module, rename it to DX11, everyone's happy.


ziggy(Posted 2015) [#30]
Array(Foo) should not be a subtype of Array(Object)
Why? (I'm curious) I see this as a regular covariance situation. In regards of type safeness, an array is no more than a collection, or container with built-in generics (you always make an array of a given kind). Also, in its contract, the datatype of contained elements appears always in a covariant position (it is returned in the array interface/template, but not used as an input parameter) Given this, I don't see where the "wrong" comes from, but, coming from you Yasha, I'm certain that I'm missing something. Care to explain?
thanks!


ziggy(Posted 2015) [#31]
How does garbage collection even work with this? This program never calls the Delete method
This is a very nice to read article that explains lots of things that are usually common questions when you try to think deeper how a typical garbage collector works in the very high level. It explains quite nicely what a garbage collection does not do (why the finalize might not be called and that's right, etc).

http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx


Yasha(Posted 2015) [#32]
Why? (I'm curious)

Arrays are mutable:
Type foo
	Method New()
		x = 1 ; y = 97
	End Method
	Field x:Int, y:Int
End Type

Local a:String[] = ["foo", "bar", "baz"]
Local b:Object[] = a

b[1] = New foo

For Local s:String = EachIn a
	Print s
Next

Java used to face this question.

There are other solutions than just disallowing it or copying Java, but the current design isn't quite safe. "Wrong" was however the wrong word on my part (no rigorous thought behind it, sorry).


ziggy(Posted 2015) [#33]
I see! It looks like Eifel!
The assignation b[1] = New Foo is a setter, so it would be a less specialized type on a covariant position, so definitively eiflel like *problem*, not thread safe, and worth fixing IMHO before anything else. Then, count me in with delegates, generics, lambdas... I can't care less about 64 bits support as a "main" priority

EDIT: This or get rid of arrays completely :) We're not in 1980


Tachyon(Posted 2015) [#34]
Logged in after many months just to post this: BlitzMax (2.0?) needs to formally adopt a 3D engine. I don't really care which one, just pick a good open-source engine and "Blitz it out", and then continue to support it as it evolves.

I've formally switched over to Unity3D, but yet I miss the feel and ease of BlitzMax. In a perfect world I'd have BlitzMax with a strong, integrated, modern 3D engine stuck to it.


Henri(Posted 2015) [#35]
EDIT: This or get rid of arrays completely :)

I have a new grown fondness over arrays because of their superfast index based access. They are sometimes really convenient so I vote no :-)


In a perfect world I'd have BlitzMax with a strong, integrated, modern 3D engine stuck to it
In Monkey forums Mark suggested *when asked hypothetically* Irrlicht as viable possibility due to it's well structured framework .

-Henri


ziggy(Posted 2015) [#36]
@Henri, of course thei're fast, but there are collections that can be as fast, but with better type safeness if the compiler is smart enough! Anyway, I was not really serious abut it. Having generics, we could have an array-like object that can be extended and attend much more complex responsibilities/functionalities, etc. That was my point


col(Posted 2015) [#37]
Now now Joshua, calm down, you don't want to become an internet bully now do you?


Grisu(Posted 2015) [#38]

What difference is a Max2D DX 11 over a Max2D DX 9? Max2D is so inefficient it's not funny. DrawText is atrocious.



I get your point.
But with a newer driver BMX stays compatible with modern hardware (inefficient or not). For my case: I had tons of issues with the old driver on a laptop and a Win 7 machine. Newer bmx drivers fixed them (PS: Thanks col). On top of that every speed increase and new feature is welcome. In addition: The support has some markting value for BMX2.


skidracer(Posted 2015) [#39]
interesting....


+***** 1.52 Release *****
+
+* You should be able to install from git download with newer versions of mingw now! Tested with TDM-GCC-32 and TDM-GCC-64 v4.9.2
+
+* Updated bmk so it uses -O3 in release mode. Disabled -ftree-vrp optimization which was causing crashes on mingw.
+
+* Updated win32 libs and bins to mingw 4.9.2 versions.
+
+



JoshK(Posted 2015) [#40]
Non-GCed types. I would probably make this a new concept called a "Class" and make it analogous to a pointer, rather than trying to mix pointers and objects like C++ does.


DStastny(Posted 2015) [#41]
@Yasha as someone who has a working LLVM Blitzmax like language from my cursory review of the code base it looks pretty straight forward to change it out with an LLVM back end. Kudos to Mark the code is pretty easy to follow.

As for benefits:

1) the big one is not needing a C++ compiler installed with the final product.
2) As you point out emitting native LLVM IR allows for more optimizations based upon source language instead of transforming it to C/C++ and back.
3) DWARF Debug integration(Proper breakpoints)
4) Faster compile times

I would be willing to take a crack at it but people on this forum tend to be so negative and sure do want a lot of free stuff for their own commercial interests.

And for @JoshK... LLVM is not a trend considering most of the OpenGL implementations utilize it and it is got contributions from every major player today. I suggest you read up a bit more.


ziggy(Posted 2015) [#42]
Non-GCed types.
Hell, no please! I honestly think it would be a lot nicer to improve as much as possible GC speed instead of having an inconsistent mixed memory management system in BlitzMax.
Also, non managed GC classes are much more like a memory buffer than a class itself if you ask me, but that's my personal feeling about manual memory management. IMHO It's technically a step backwards.
Said otherwise, handling memory should not be an enforced part of all classes single responsibility. It makes non sense from a OOD point of view, and we're not in 1980 any more.


JoshK(Posted 2015) [#43]
Almost all of my types have to be manually freed anyways with a Free() method, so the memory management for these is pretty redundant.


ziggy(Posted 2015) [#44]
What is the benefit of LLVM, besides gaining approval for buying into the latest trend?
It was trendy like 10 years ago. Now it's common scenario for modern compilers backend. Officially supplied MacOs compilers on xcode have been GCC+LLVM or Clang for some time now (I think it was in 2009, on xcode 3).
LLVM is a fantastic piece of software, and it's becoming the defacto lower level lingua franca for compilers construction because it's good, has wonderful documentation and community, and produce incredible well optimized and stable compiled binaries.
It uses an intermediate VM to produce AOT compilation, so no VM is required at runtime and the result is pure native code that does not require any kind of JIT (which is also available if you prefer to solve machine code compilation during runtime)


JoshK(Posted 2015) [#45]
I actually like the C++ layer because then you get a C++ source. I suspect this will provide better compatibility with external C++ libraries, in the long run.


ziggy(Posted 2015) [#46]
I actually like the C++ layer because then you get a C++ source. I suspect this will provide better compatibility with external C++ libraries, in the long run.
That's very nice and it can be great to have a more c++ compatible layer but, in the other hand, it makes GC a lot less efficient and harder to optimize, so I would examine all side effects as much as possible.


Yasha(Posted 2015) [#47]
Almost all of my types have to be manually freed anyways with a Free() method, so the memory management for these is pretty redundant.


Basically this can be viewed as an inadequacy in the language runtime. In a perfect world you should never have to call a Free method, but sometimes you do anyway because the GC isn't completely aware of your needs.

The solution to this isn't to get rid of the GC - that's not fixing the problem, it's ignoring it - it's to reduce the number of scenarios it's unaware of. For instance, (since I don't know about Leadwerks) miniB3D requires the FreeEntity command because it puts entities in a couple of global lists for collision and rendering and so on, so their ownership count never drops to zero even if abandoned in user code.

How you could fix this: separate the notions of reference and ownership. Since there's no way to access an entity from user code once you've thrown away all of your normal references to it, the entry in the global entity list is redundant and shouldn't be keeping it alive anyway. So we could steal the concept of "weak references" from Java/C++/etc. and make it so that this list is non-owning, and its reference doesn't count for GC purposes; instead, the entity is removed from the list at the same time as being freed by the system.

There are plenty of other things that could be added to cover other eventualities. I've felt for a while (mentioned above) that a Region system would be very effective for games, either explicit or inferred (or both but with annotations).

GC is not a broken concept. It is better than manual memory management when implemented completely and correctly. BlitzMax's implementation using reference counting happens to be very basic and should not be taken as indicating where the true limitations of GC lie.


feeble1(Posted 2015) [#48]
I think a wrapper for the Google Cardboard SDK would be a nice hypothetical addition.


JoshK(Posted 2015) [#49]
The reason I do that is due to circular references, and also sometimes you need control over when GPU or OS resources get dumped. GC also causes ambiguity and nondeterministic behavior. The short end of that is complex applications have a lot of potential places you can screw up.


Yasha(Posted 2015) [#50]
Circular references are a bug specific to refcounting implementations. No other major implementation strategy suffers from that problem (NG's Boehm is a tracing collector: while it has other flaws, it does fix this). This side of the problem can and should be fixed in the GC, because it's an actual bug. A bug people have learned to carefully tread around, but still.

The other two problems are more pressing. You'd have to clarify "ambiguity" (haha), though. There are strategies for ensuring completely deterministic performance, although they do come at some cost.

Releasing non-memory resources is the other thing that region-based collecting could help with though (mainly I had it in mind as a way to designate "GC pauses here are OK", but it works for both). This is exactly the problem C++ uses RAII to solve, and RAII is similar in concept - tying the lifetime of dynamic objects to lexical contexts. Imagine a kind of hybrid somewhere between RAII and Objective-C 1.0's old autorelease strategy: within a marked block, anything allocated goes into the pool (can use potentially use faster allocation, etc.). At the end of the block, everything in the pool is finalized. Objects passed outside of the block by illicit means (i.e. the raw `=` operator) are marked as unusable and any access attempts after the block has ended raise an exception, unless the object was passed using an ownership-passing operator (analogous to `retain`), moving its lifetime to that of whatever object received it. Ownership is unique (or at least, constrained; you could have sharing implemented as a background detail), but transparent to the rest of BlitzMax code (so, without the nuisances of std::unique_ptr).

e.g.


Would something like that be helpful? I feel like that would be a great way to deal with the "level asset problem" people often complain about, where otherwise they have to do a manual `GCCollect() ; GCSuspend() ; RunLevel() ; GCResume() ; GCCollect()` cycle to avoid pauses during level operation (which itself cuts down on what you can use from the language runtime, e.g. no lists), and it gives guarantees about finalization that are missing from that.

(can knock together a proof-of-concept in vanilla BlitzMax if anyone wants, although it wouldn't have the syntactic integration and the object implementation would be very slow and heavyweight compared to the real thing)


Aside from simple safety and convenience, the other thing is that... well, you can allocate non-GC types in BlitzMax already, by defining your type as Extern (ain't no rule says it actually has to connect to a C++ backing type: you can provide the memory buffer and vtable yourself). I'd rather retain this shallow barrier to manual management in a language oriented to beginners, because beginners shouldn't be encouraged towards manual management - it's a hack for experts who really need it (not everyone is writing Leadwerks: most users don't ever need manual control, and should be guided towards something safe by default).


therevills(Posted 2015) [#51]
Fixing the out of memory issue when compiling:

Building executable... 
Compiling:LoS2.bmx

flat assembler  version 1.69.14  (1846 kilobytes memory)
Building has been canceled because compiling couldn't be completed


Also changing the apptitle after graphics would be nice too...


skidracer(Posted 2015) [#52]
therevills, I'd like to help with that one

in bmk_util.bmx we have this

?Win32
	cmd$=CQuote(BlitzMaxPath()+"/bin/fasm")+" "+CQuote(src)+" "+CQuote(obj)
?Linux
	Local opts$=getenv_( "BMK_FASM_OPTS" )
	If opts="" opts="-m1048560"
	cmd$=CQuote(BlitzMaxPath()+"/bin/fasm")+" "+opts+" "+CQuote(src)+" "+CQuote(obj)
?


It seems a little mean there is a fix for Linux users. My initial reaction is to reduce separate implementations.


JaviCervera(Posted 2015) [#53]
One simple thing that would be great is to prevent the compiler from generating those ".bmx" hidden folders with intermediate code, specially since cleaning them up on a Mac is not a trivial task. Something like a "build.bmx" folder looks much better to me, since it would not be hidden by default on Unix-like systems.


therevills(Posted 2015) [#54]

It seems a little mean there is a fix for Linux users. My initial reaction is to reduce separate implementations.

Thanks Skid, I remember when Mark fixed it for Linux thinking it was also going to be fixed for Windows too..


Tricky(Posted 2015) [#55]
Better pre-processor


I suggested that before. Back in my years as a Turbo Pascal coder I used this kind of getup a lot
{$DEFINE TESTPROGRAM}
Program HelloWorld;

begin
{$IFDEF TESTPROGRAM}
writeln('THIS IS A TEST YEAH!');
{$ENDIF}
writeln("Hello World!");
end.


The Pascal compiler only picks up the stuff between {$IFDEF} and {$ENDIF} if the directive was set through {$DEFINE}

Perhaps (combined with the directives we already have), the BlitzMax equivalent could look like this
?Define TESTPROGRAM
' main routine
?If TESTPROGRAM
print "THIS IS A TEST YEAH!"
?EndIf
print "Hello World"


Of course, Pascal also had support for {$ELSE} and {$ELSEIF} and in case something was supposed not to be defined {$UNDEF}

I've always missed this feature when I began programming in BlitzBasic and later BlitzMax.

At the present time I use constants to try to get the same effect, but it's not the best way to go for several reasons. a) The unneeded code still gets compiled, and b) references to unneeded stuff will also get in the executable. A proper way to get it all out of the way will be very helpful. :)


Derron(Posted 2015) [#56]
Such an enhancement is not backwards compatible as the current BCC defaults to "false" for all "definitions" it does not know.

?yabadabadoo
print "never executed"
?not yabadabadoo
print "executed"
?


Another problem is, that current bcc just allows "single variables" and no proper "if"-statement (what NG might have inherited from the monkey translator)


bye
Ron


Tricky(Posted 2015) [#57]
Should not be a big big problem, as using "?" without a proper command could still be used like the "old ways". This way older source codes will not suffer completely. Newer source codes will (of course) require to be compiled with the newest version only.


LT(Posted 2015) [#58]
Hey, as long as we're askin' ... also want to add functions as objects (first class) to the list.


GW(Posted 2015) [#59]
Ok, here goes.
Have the ability the query the GC and find out how much garbage got cleaned up since the last call.