DeyjaScript 3 : Control structures

posted in Jemgine
Published September 16, 2011
Advertisement
Time now for control structures. But first, I made some changes. I implemented registers, and I stashed the frame pointer and the stack pointer in there. The registers, like the stack, is just an array of objects. It's inefficient for integral types, but it allows the VM to pretty much ignore types. It still assumes that the frame pointer and stack pointer registers contain ints, of course. I just have to make sure I don't emit any bytecode that violates this. I also add some instructions for dealing with them, such as loadRegisterFromVariable. I'm using long names for my instructions because there's no reason to use short, unreadable nonsense like you would see in an assembly language. So now I have three places the bytecode can store data. Variables, the top of the stack, and registers.
I also go ahead and define a function calling convention. The only functions being called right now are operators, but having a clearly defined calling convention will be important shortly. I don't know if this convention is named. Here it is - Parameters are pushed onto the stack in order. They are not popped by the calling function, and the return value is placed in the returnValue register. A bit of parameterization of the ExpressionNode's emit function lets me tell any arbitrary node whether or not to push it's return value onto the stack, but that push is now a separate instruction.
Now on with the grammar. I separate the idea of a list of statements and a block. I allow a code block to be used as a statement, but not an expression. For control structures, I'll need a jump instruction. Just two, actually. constantRelativeJump and constantRelativeJumpIfNotTrue. Why jump on false? So I can emit the then block first. Those are straightforward. I also add an operator== for ints so that I can actually try it out. Finally, the grammar, and the first real hurdle.


ifStatement.Rule = ToTerm("if") + "(" + expression + ")" + statement;
ifElseStatement.Rule = ToTerm("if") + "(" + expression + ")" + statement + this.PreferShiftHere() + "else" + statement;


I'd stumbled directly into something called the 'if-then-else ambiguity'. A bit of research told me why Irony was complaining, and led to that call to PreferShiftHere which took care of the problem. Here's some more information about it. http://docs.freebsd.org/info/bison/bison.info.Shift_Reduce.html This really hi-lites something I should probably mention, and that is that I have no idea what I am doing. That's part of the reason for blogging this whole experience. If I'm doing something obviously wrong, I'd hope someone would let me know.
So all that's left is to actually implement IfStatementNode.


public override void emitByteCode(List bytecode, ExecutionContext context, bool placeResultOnStack)
{
var hasElseClause = ChildNodes.Count == 3;
(ChildNodes[0] as ExpressionNode).emitByteCode(bytecode, context, false); //Leaves result in returnValue register
int jumpInstruction = bytecode.Count;
int elseSkipJumpInstruction = 0;
bytecode.AddBytecode(Instruction.constantRelativeJumpIfNotTrue, (byte)Register.returnValue, (byte)0, (byte)0);
(ChildNodes[1] as ExpressionNode).emitByteCode(bytecode, context, false);
if (hasElseClause)
{
elseSkipJumpInstruction = bytecode.Count;
bytecode.AddBytecode(Instruction.constantRelativeJump, (byte)0, (byte)0);
}
var jumpDistance = bytecode.Count - jumpInstruction;
var bytes = BitConverter.GetBytes((Int16)jumpDistance);
bytecode[jumpInstruction + 2] = bytes[0];
bytecode[jumpInstruction + 3] = bytes[1];
if (hasElseClause)
{
(ChildNodes[2] as ExpressionNode).emitByteCode(bytecode, context, false);
jumpDistance = bytecode.Count - elseSkipJumpInstruction;
bytes = BitConverter.GetBytes((Int16)jumpDistance);
bytecode[elseSkipJumpInstruction + 1] = bytes[0];
bytecode[elseSkipJumpInstruction + 2] = bytes[1];
}
}


It has to go back and fill in the jump instructions once it knows just how far to jump.
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement