GameMonkey Script

GameMonkey Script Forums
It is currently Wed Jun 26, 2019 6:38 pm

All times are UTC




Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Wed Apr 15, 2009 12:20 am 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
I've been messing around and have added an experimental switch/case statement to my current local build of GM.

Due to how this:syntax works, the switch syntax is modified slightly from C/C++. Here's how it looks...

Code:
switch( const_expression )
{
  case const_expression { statements }
  case const_expression ( statements }
  default { statements }
}


So:
Code:
val = 100;
switch(val)
{
  case 50 { print("case 1"); }
  case 100 { print("case 2"); }
  case 150 { print("case 3"); }
  default { print("default case"); }
}


Would print... "case 2"...

Due to the way I've implemented it, the case statements can be any constant expression and they are evaluated in order; so you can case on tables, functions, strings, or any combination of them... It's basically syntactic sugar for the if(){} else if(){} else if(){} else {} sort of code.

Does anyone want this patch posting?


Top
 Profile  
Reply with quote  
PostPosted: Wed Apr 15, 2009 12:35 am 
Offline

Joined: Fri Jan 14, 2005 2:28 am
Posts: 439
I'm interested in getting that in gmscriptex


Top
 Profile  
Reply with quote  
PostPosted: Wed Apr 15, 2009 7:20 am 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
I'll look into committing it tonight (not used SVN for a while).

I'm going to change the casing a little to allow multiple values, so...

Code:
switch(var)
{
  case 1, 2, 3 { print("case 1"); }
  case 4 { print("case 2"); }
  default { }
}


This is because there's no fall through, so you need to be able to work on a list of values without having to specify each case block explicitly.


Top
 Profile  
Reply with quote  
PostPosted: Wed Apr 15, 2009 9:05 am 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
The current implementation requires at least one case statement and default is mandatory. I'm wondering if I should make default as optional.

Also, is the syntax intuitive enough? We don't have to break as we don't drop through - it's not like C++ in this way. Should the keywords be case/when or select/case rather than switch?

Eg:
Code:
select(x)
{
  case 1 { }
}


Or:
Code:
case(x)
{
  when 1 { }
}


Or is switch/case ok? I'm asking because it behaves differently enough to warrant the change in keywords - as well as the word "switch" might be quite common in scripts already.


Top
 Profile  
Reply with quote  
PostPosted: Wed Apr 15, 2009 3:29 pm 
Offline

Joined: Fri Jan 14, 2005 2:28 am
Posts: 439
case/when sounds like a good self explanatory set of keywords


Top
 Profile  
Reply with quote  
PostPosted: Wed Apr 15, 2009 9:52 pm 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
ugh, writing the code to emit the bytecode for statements such as case { when 1,2,3,4 { ... } } is horrible. I'm half tempted to go back to a single case expression, but it would limit the usefulness.


Top
 Profile  
Reply with quote  
PostPosted: Thu Apr 16, 2009 8:00 pm 
Offline

Joined: Sat Dec 09, 2006 2:41 am
Posts: 6
While it's certainly not C/C++ style, what do you think about allowing Pascal style cases that allow ranges?
ie:
Code:
switch( x )
{
 case 1..2 { print( "case 1" ); }
 case 3..10 { print( "case 2" ); }
}


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 18, 2009 3:39 pm 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
Not a bad idea; I think something like:

Code:
case (x)
{
when 1 to 5 { }
else { }
}


Might work pretty well.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 19, 2009 12:59 am 
Offline

Joined: Mon Dec 15, 2003 1:38 pm
Posts: 708
My preference would be syntax and behavior as close to C++ or C# as possible. I don't care for the classic C fall through until break though. Being GM, I'd also not mind if the switch statement was mere syntax sugar for a series of if,elseif and could take non-constant values.

So my ideal would look something like:
Code:
switch (name)
{
  case "apple": print("hurrah "); print("for apples"); // Multiple statements until next case, no break
  case "banana":                                       // Fall through multiple cases
  case "pear":
  case "cherry": { print("fell to fruit", name); }     // Braces accepted
  case favoriteFruit: print("my favorite fruit");      // MAYBE allow variable cases!
  default: print("no fruit for you");                  // Default not required
}
This would generate the exact same code as if the user had written:
Code:
if( name == "apple" )
{
  print("hurrah ");
  print("for apples");
}
else if( name == "banana" || name == "pear" || name == "cherry" )
{
  print("fell to fruit", name);
}
else if( name == favoriteFruit )
{
  print("my favorite fruit");
}
else
{
  print("no fruit for you");
}

I think other ranges like 1...1000 etc. are pointless and turn switch into something unnecessarily complex. I mean how much of a syntax saving beyond a few if,elseif is it anyway?

I also don't care if the syntax does not support evaluated cases like:
Code:
case 42:                 // Constants of course
case somenumber:    // MAYBE variables
case var1 + var2:     // Why stretch it this far, what is the value?
case calcValue():     //  Same for this


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 19, 2009 12:08 pm 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
Greg wrote:
So my ideal would look something like:
Code:
switch (name)
{
  case "apple": print("hurrah "); print("for apples"); // Multiple statements until next case, no break
  case "banana":                                       // Fall through multiple cases
  case "pear":
  case "cherry": { print("fell to fruit", name); }     // Braces accepted
  case favoriteFruit: print("my favorite fruit");      // MAYBE allow variable cases!
  default: print("no fruit for you");                  // Default not required
}


I'm not sure I agree with all that. The first reason being that GM itself doesn't support single line statements without the braces, so the case condition wouldn't fit in at all with GM syntax - you'd have to enclose all of them in braces.

When it came to using the syntax "case xxx:", the parse didn't like the use of the colon because of its use for passing "this" in a constant expression - I see what you're saying about not allowing full expressions, so maybe removing their use would allow for more C++ style syntax.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 19, 2009 1:56 pm 
Offline

Joined: Mon Dec 15, 2003 1:38 pm
Posts: 708
By the way, I never said it would be easy ;) Just my opinion on switch.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 25, 2009 1:21 pm 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
Ok, I've got a version of the switch code that works in a way that's very similar to greg's example, except that each statement needs to be surrounded by braces - this makes it consistent with the rest of GM's compound statements.

So:

Code:
name = "cherry";
switch (name)
{
  case "apple": { print("hurrah "); print("for apples"); } // braces are required
  case "banana":                                       // Fall through multiple cases
  case "pear":
  case "cherry": { print("fell to fruit", name); } 
  case favoriteFruit: { print("my favorite fruit"); }     // allow variable cases!
  default: { print("no fruit for you"); }                 // Default not required
}


Cases will fall through if there's no statement body, this lets you do things like:

Code:
  case 1:
  case 2:
  case 3:
  case 4: { ... do something ... }


The case can be any constant, variable (including 'this'). Function calls are not supported. The case expression will evaluate complex variables, such as getdot/getind operations, so case x.y.z[0].a: { ... } will work. Default is optional and will be called if all case evaluations fail.

The switch expression can be any constant expression and is evaluated only once, keeping the value of it on the stack until the end - this actually gives a small performance boost over the equivalent if/else/if combination which evaluates the expression for each if statement. I tested it on a relatively simple case with 4 case statements, looping a million times for each the case and the if equivalent - switch was approx 2s faster overall, indicating that each call of switch was slightly more efficient than if/else if for lhs expressions that need to be evaluated once.

Modified code to implement switch is attached.


Enjoy!


Attachments:
gmsrc_1_25l_switch.rar [47.04 KiB]
Downloaded 414 times
Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 25, 2009 6:03 pm 
Offline

Joined: Fri Jan 14, 2005 2:28 am
Posts: 439
sweet, good job dude.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 26, 2009 2:14 pm 
Offline

Joined: Sat Apr 25, 2009 1:40 am
Posts: 66
I can't compile GM using these scripts. Compiling in mingw:

Code:
d:\code\GameMonkey\src\gm\gmCodeGen.cpp:982: warning: unused variable 'end_of_stmt'
d:\code\GameMonkey\src\gm\gmCodeGen.cpp:994: warning: unused variable 'default_loc'
d:\code\GameMonkey\src\gm\gmCodeGen.cpp: In member function `bool gmCodeGenPrivate::GenStmtFork(const gmCodeTreeNode*, gmByteCodeGen*)':
d:\code\GameMonkey\src\gm\gmCodeGen.cpp:1072: error: `BC_FORK' was not declared in this scope
d:\code\GameMonkey\src\gm\gmCodeGen.cpp:1072: warning: unused variable 'BC_FORK'


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 26, 2009 2:36 pm 
Offline

Joined: Thu Jan 01, 2004 4:31 pm
Posts: 307
I added switch to 1.25j and had to roll it forward into 1.25l, I might have made an error. I'll take a look.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 23 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group