well, in my case, my scripting VM represents a pretty big part of the 3D engine (both in terms of architecture, and total kloc within the codebase).
arguably it is a little over-engineered for a game scripting-language though, where many other projects uses much more minimalist scripting languages, ...
like, for example, the opcode listing:
http://cr88192.dyndns.org:8080/wiki/index.php/BGBScriptVM_ByteCode
and, also, a language spec:
http://cr88192.dyndns.org:8080/SilvVMSpec/2012-12-05_BGBScript16.html
opcodes are currently numbered up to around 859, which is considerably more than either the JVM or .NET VM, albeit many of these opcodes are a bit more specialized than those in the JVM or .NET VM. sort of like in the JVM, explicit types are often used, but in many cases via the use of type-prefixes (so, the opcode itself often omits the type, more like those in .NET, although the type is still given explicitly in the bytecode).
some of this may be because for the most part, the high-level language has been used in interpreters, which costs some in terms of instruction dispatch, often making the use of a larger number of more specialized opcodes preferable to a smaller number of more general ones regarding performance (though, typically the bytecode is not executed directly, but converted into a form of "threaded code", and when used, the JIT basically just spits out a mix of some directly-handled instructions, but mostly a lot of call-threaded code).
note: http://en.wikipedia.org/wiki/Threaded_code
also, the language can be used over a range of styles, for example (using mostly dynamic types):
public class monster_enemyhead extends monster_generic2
{
public function monster_enemyhead(ent, sent)
{
printf("monster_enemyhead: ctor\n");
super(ent, sent);
}
public function think_idle(self)
{
if(btRandom()<0.1)
{
btSound(self, BT_CHAN_VOICE, self->snd_idle,
1.0, BT_ATTN_NORM);
}
}
public function think_fire(self)
{
var org, dir;
// org=self->origin;
// dir=btYawVector(btCurrentYaw(self));
// dir=BT_TargetDirection(self, self->enemy);
org=BT_AimOrigin(self);
dir=BT_AimDirection(self, self->enemy, 600);
// BT_FireRocket(self, org, dir, 10, 600, 25);
// BT_FireBlaster(self, org, dir, 10, 600, 25);
BT_FireRocket(self, org, dir, 60, 600, 160);
}
public function init(self)
{
printf("monster_enemyhead: init A self=%p\n", self);
self->solidtype=BT_SOLID_SLIDEBOX;
self->movetype=BT_MOVE_STEP;
btSetModel(self, "models/monsters/enemyhead/enemyhead.model");
self->snd_sight="sound/soldier/solsght1";
self->snd_idle="sound/soldier/solidle1";
self->origin=self->origin + #[0, 0, 256];
self->mins=#[-64, -64, -32];
self->maxs=#[64, 64, 64];
self->health=900;
btFlymonsterStart(self);
}
}
and, also in a more traditional statically-typed way (using a more conventional syntax):
package bsvm.util
{
public class Random extends Object
{
private static final long multiplier = 4294967291L;
private long seed;
public Random()
{ this(bgbrng_genvalue()); }
public Random(long seed)
{ setSeed(seed); }
protected int next(int bits)
{
seed=seed*multiplier+1;
return ((seed>>>(64-bits))&((1L<<bits)-1) as int);
}
public double nextDouble()
{ return((next(24) as double)/16777216.0); }
public float nextFloat()
{ return((next(24) as float)/16777216.0); }
public double nextGaussian()
{ return(nextDouble()*nextDouble()); }
public int nextInt()
{ return(next(32)); }
public long nextLong()
{ return(((next(32) as long)<<32)+next(32)); }
public void setSeed(long seed2)
{ seed=seed2*multiplier+1; }
}
}
and, another fragment using declared types and a different declaration syntax:
function selsort(a:int[], n:int)
{
var i:int, j:int, k:int;
for(i=0; i<n; i++)
for(j=i+1; j<n; j++)
if(a[j]<a)
{
k=a;
a=a[j];
a[j]=k;
}
}
so, does all this seem a little over-engineered?...