bytecode programming requires a pretty decent knowledge of assembler programming - you just make a generic (and simple) assembler instruction set, and then implement a script compiler that generates instructions for that. I'm sure the Java bytecode is documented somewhere, but that may not be much help.
It is of course possible to implement all the primitives (builtin functions and keywords) as "bytecode ops", but you still end up with something similar to machine code, but less flexible.
However, it's probably easier to implement your language as an interpreted language first, then start thinking about how it can be compiled.
A common problem with most scripting languages is the "dynamic typing" - for example in the code above, you do not give $i a type, it becomes (presumably) an integer when it's first assigned an integer value. This makes compiling it (whether to bytecode or "proper" machine-code) much harder, as you'd have to find all the uses of $i in that particular scope to find the proper type or, perhaps, you will have to allow a variable to change type throughout the code - I know PHP can do things like this:
Code:
$x = 0;
... use $x as an integer ...
$x = "Hello, World" . $x; // Assign $x as a string made from constant and it's integral value
... use $x as a string.
--
Mats