November 01, 2014 Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Third part of the "A Programming Language for Games", by Jonathan Blow: https://www.youtube.com/watch?v=UTqZNujQOlA Discussions: http://www.reddit.com/r/programming/comments/2kxi89/jonathan_blow_a_programming_language_for_games/ His language seems to disallow comparisons of different types: void main() { int x = 10; assert(x == 10.0); // Refused. } I like the part about compile-time tests for printf: http://youtu.be/UTqZNujQOlA?t=38m6s The same strategy is used to validate game data statically: http://youtu.be/UTqZNujQOlA?t=55m12s A screenshot for the printf case: http://oi57.tinypic.com/2m5b680.jpg He writes a function that is called to verify at compile-time the arguments of another function. This does the same I am asking for a "static precondition", but it has some disadvantages and advantages. One advantage is that the testing function doesn't need to be in the same module as the function, unlike static enums. So you can have the function compiled (separated compilation). Perhaps it's time for DIP. Bye, bearophile |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Saturday, 1 November 2014 at 11:31:32 UTC, bearophile wrote: > Third part of the "A Programming Language for Games", by Jonathan Blow: > https://www.youtube.com/watch?v=UTqZNujQOlA Thanks for the link. I only have time to skim it, but I think the region-based allocation that he was concerned about in the previous talk might be handled with some kind of tuple-magic? bike := uniqptr_tuple<Frame,Wheel,Wheel>(myallocator) // =>uniq_ptr to tupleof(frameinstance,wheelinstance,wheelinstance) |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | Am 01.11.2014 um 12:31 schrieb bearophile:
> Third part of the "A Programming Language for Games", by Jonathan Blow:
> https://www.youtube.com/watch?v=UTqZNujQOlA
>
> Discussions:
> http://www.reddit.com/r/programming/comments/2kxi89/jonathan_blow_a_programming_language_for_games/
>
>
> His language seems to disallow comparisons of different types:
>
> void main() {
> int x = 10;
> assert(x == 10.0); // Refused.
> }
>
>
> I like the part about compile-time tests for printf:
> http://youtu.be/UTqZNujQOlA?t=38m6s
>
> The same strategy is used to validate game data statically:
> http://youtu.be/UTqZNujQOlA?t=55m12s
>
> A screenshot for the printf case:
> http://oi57.tinypic.com/2m5b680.jpg
>
> He writes a function that is called to verify at compile-time the
> arguments of another function. This does the same I am asking for a
> "static precondition", but it has some disadvantages and advantages. One
> advantage is that the testing function doesn't need to be in the same
> module as the function, unlike static enums. So you can have the
> function compiled (separated compilation). Perhaps it's time for DIP.
>
> Bye,
> bearophile
Just started watched the beginning, will watch the rest later.
I find interesting that he also bases part of the language in how the ML languages look like.
So it seems that being C like is out for language design, as most modern languages are following ML like grammars.
Another trend, which I find positive, is how many people are now (finally!) assuming that C widespread into the industry was after all not that good, in terms of bugs/line of code.
Now we need another 30 years until D, Rust, Swift, Nim, <place language name here>, get to replace C and C++.
--
Paulo
|
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 11/1/2014 4:31 AM, bearophile wrote: > His language seems to disallow comparisons of different types: > > void main() { > int x = 10; > assert(x == 10.0); // Refused. > } More than that, he disallows mixing different integer types, even if no truncation would occur. > I like the part about compile-time tests for printf: > http://youtu.be/UTqZNujQOlA?t=38m6s Unnecessary with D because writeln checks it all. Even so, if printf were a template function, D can also check these things at compile time. > The same strategy is used to validate game data statically: > http://youtu.be/UTqZNujQOlA?t=55m12s D allows extensive use of compile time validation. > He writes a function that is called to verify at compile-time the arguments of > another function. This does the same I am asking for a "static precondition", > but it has some disadvantages and advantages. One advantage is that the testing > function doesn't need to be in the same module as the function, unlike static > enums. So you can have the function compiled (separated compilation). Perhaps > it's time for DIP. D can run arbitrary functions at compile time even if they are in different files. |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 11/1/2014 4:31 AM, bearophile wrote: > Third part of the "A Programming Language for Games", by Jonathan Blow: > https://www.youtube.com/watch?v=UTqZNujQOlA Jonathan is reinventing D with a somewhat different syntax. Some points on the video: * The defer statement works pretty much exactly like D's scope guard: http://dlang.org/statement.html#ScopeGuardStatement * "for n: 1..count" is the same as D's "foreach (n; 1..count)" * dynamic arrays work pretty much the same as D's * for over an array in D: foreach (it; results) ... * D does the check function thing using compile time function execution to check template arguments. * D also has full compile time function execution - it's a very heavily used feature. It's mainly used for metaprogramming, introspection, checking of template arguments, etc. Someone has written a ray tracer that runs at compile time in D. D's compile time execution doesn't go as far as running external functions in DLLs. * D has static assert, which runs the code at compile time, too. The space invaders won't run at compile time, because D's compile time code running doesn't call external functions in DLLs. I actually suspect that could be a problematic feature, because it allows the compiler to execute user supplied code which can do anything to your system - a great vector for supplying malware to an unsuspecting developer. The ascii_map function will work, however. |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright: > * for over an array in D: > foreach (it; results) ... D is better here, because it doesn't introduce magically named variables. > * D does the check function thing using compile time function execution to check template arguments. This is not nearly enough. I have written a lot about this. > * D also has full compile time function execution - it's a very heavily used feature. It's mainly used for metaprogramming, introspection, checking of template arguments, etc. Someone has written a ray tracer that runs at compile time in D. D's compile time execution doesn't go as far as running external functions in DLLs. His "compile time execution" is different and probably better: the whole language is available because it uses an intermediate bytecode. This makes it more flexible and avoids the need of having essentially two different implementations of the language. > The ascii_map function will work, however. The ASCII map example doesn't work in D because of reasons I have explained a lot in past posts. Bye, bearophile |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paulo Pinto | On Saturday, 1 November 2014 at 17:17:34 UTC, Paulo Pinto wrote: > Another trend, which I find positive, is how many people are now (finally!) assuming that C widespread into the industry was after all not that good, in terms of bugs/line of code. > > Now we need another 30 years until D, Rust, Swift, Nim, <place language name here>, get to replace C and C++. Jonathan referenced Mike Action, who when asked about what C++ vs C said he preferred C and that using C++ was cultural: http://www.youtube.com/watch?v=rX0ItVEVjHc&feature=youtu.be&t=1m23s He also stated time and time again that the hardware is the platform. I think that aspect is missing a bit from D unfortunately. But in 30 years hardware will have changed a lot… |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 11/1/2014 1:33 PM, bearophile wrote: > Walter Bright: > D is better here, because it doesn't introduce magically named variables. I agree that the implicit variable is not good. >> * D does the check function thing using compile time function execution to >> check template arguments. > This is not nearly enough. I have written a lot about this. I don't agree. Compile time checking can only be done on compile time arguments (obviously) and template functions can arbitrarily check compile time arguments. I know you've suggested extensive data flow analysis, but Jonathan's language doesn't do that at all and he neither mentioned nor alluded to the concept of that. >> * D also has full compile time function execution - it's a very heavily used >> feature. It's mainly used for metaprogramming, introspection, checking of >> template arguments, etc. Someone has written a ray tracer that runs at compile >> time in D. D's compile time execution doesn't go as far as running external >> functions in DLLs. > > His "compile time execution" is different and probably better: the whole > language is available because it uses an intermediate bytecode. This makes it > more flexible and avoids the need of having essentially two different > implementations of the language. He has two implementations - a bytecode interpreter, and a C code generator. D's CTFE restrictions are: 1. no global variables 2. no pointer math 3. no external code execution While this prevents you from running space invaders at compile time, I haven't seen much of any practical limitation for things that CTFE is used for. >> The ascii_map function will work, however. > The ASCII map example doesn't work in D because of reasons I have explained a > lot in past posts. Like what? |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ola Fosheim Grøstad | Am 01.11.2014 um 22:20 schrieb "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= <ola.fosheim.grostad+dlang@gmail.com>": > On Saturday, 1 November 2014 at 17:17:34 UTC, Paulo Pinto wrote: >> Another trend, which I find positive, is how many people are now >> (finally!) assuming that C widespread into the industry was after all >> not that good, in terms of bugs/line of code. >> >> Now we need another 30 years until D, Rust, Swift, Nim, <place >> language name here>, get to replace C and C++. > > Jonathan referenced Mike Action, who when asked about what C++ vs C said > he preferred C and that using C++ was cultural: > I mean in terms of unsafe code and the amount of money spent in research and bug fixing that could have been avoided, if C wasn't as it is. I wouldn't be that vocal about C if: - arrays were bound checked (just use a compiler flags and dataflow to remove them like any sane language) - enums were strong typed - had reference parameters - had namespaces or real modules - no implicit type conversions - had a sane macro system But I guess D already covers it... -- Paulo |
November 01, 2014 Re: Programming Language for Games, part 3 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright: > I know you've suggested extensive data flow analysis, The "static enum" (and related ideas) I've suggested require no flow analysis. > Compile time checking can only be done on compile time arguments (obviously) and template functions can arbitrarily check compile time arguments. In D it's easy to define a function that you call at compile-time to test that some compile-time data is well formed, I do this often. This is a simple example: import std.range, std.algorithm; alias Nibble = ubyte; // 4 bits used. alias SBox = immutable Nibble[16][8]; private bool _validateSBox(in SBox data) @safe pure nothrow @nogc { return data[].all!((ref row) => row[].all!(ub => ub < 16)); } struct GOST(s...) if (s.length == 1 && s[0]._validateSBox) { private static generate(ubyte k)() @safe pure nothrow { return k87.length.iota .map!(i=> (s[0][k][i >> 4] << 4) | s[0][k - 1][i & 0xF]) .array; } // ... } void main() { enum SBox cbrf = [ [ 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3], [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9], [ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11], [ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3], [ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2], [ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14], [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12], [ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]]; GOST!cbrf g; // ... } But you can run such compile-time tests only on template arguments, or on regular arguments of functions/constructors that are forced to run at compile-time. But for me this is _not_ enough. You can't implement the printf test example he shows (unless you turn the formatting string into a template argument of printf, this introduces template bloat and forbids you to have run-time format strings, or forces you to use two different syntaxes or to create two different print functions). I'd like a way to run compile-time tests for the arguments of a regular function/constructor if they are known at compile-time. So here I'd like a way to perform a compile-time test of the arguments of the call of #1 (and to not perform them for the call #2 because its argument is not a compile-time constant) (note that here both foo calls are not run at compile-time, and this is good): void main() { auto x = foo(1); // #1 int n = bar(); auto y = foo(n); // #2 } Currently if you want to do the same thing in D you have to use something like: void main() { auto x = foo(ctEval!test(1)); // #1b } (Where "test" is a function that tests the argument and "ctEval" is a little template that forces to run "test" at compile time (here "foo" itself is not run). This becomes not much practical if you have arrays of values, or lot of data, etc, it's not *transparent* at all for the user, and the user can forget to use ctEval). So this is useful in a large number of cases. If instead of foo() there's a call to a constructor, we become able to verify "game data" at compile time where possible while avoiding templates, and running the actual functions only at run-time. Probably there are various ways to solve this problem. A lot of time ago I have suggested a "enum precondition": int foo(in int x) enum in(x) { // Optional enum pre-condition. } in { // Optional normal pre-condition. } body { // Function body. } The idea is that if foo is called with literals or compile-time (enum) arguments (here just the x argument is required to be known at compile-time) then it performs the tests inside the enum precondition at compile-time. If the arguments are run-time values then the enum precondition is ignored (and eventually the normal pre condition runs at run-time. Sometimes the two pre-conditions contain the same code or call the same testing function). If you want to implement this idea very well, you can keep the enum precondition as source code (like with templates) so you can run it at compile-time when the arguments are known at compile-time. Bye, bearophile |
Copyright © 1999-2021 by the D Language Foundation