protected void GenerateAssignmentComputation(CodeGenContext context) { Operator op; switch (Op) { case Assignment: return; case AssignmentMultiplication: op = Addition; break; case AssignmentDivision: op = Division; break; case AssignmentModulo: op = Modulo; break; case AssignmentAddition: op = Addition; break; case AssignmentSubtraction: op = Subtraction; break; case AssignmentBitwiseAnd: op = BitwiseAnd; break; case AssignmentBitwiseXor: op = BitwiseXor; break; case AssignmentBitwiseOr: op = BitwiseOr; break; case AssignmentBitwiseLeftShift: op = BitwiseLeftShift; break; case AssignmentBitwiseRightShift: op = BitwiseRightShift; break; default: throw new AssertionFailedException("unexpected assignment operator: " + Op.ToString()); } context.GenerateInstruction(op.ToString()); }
protected void GenerateLHSValue(CodeGenContext context, AbstractSyntaxTree target, VariableTreeNode variable) { if (target == null) { // An address was generated onto the stack. // We need to use this address twice, as in a[i] += 4; // we need to read a[i] once, and write a[i] once, // from the same pointer computation context.GenerateInstruction("DUP"); // and now we'll convert one of them into the value at that location context.GenerateInstruction("Indirection"); } else if (variable != null) { context.GenerateInstruction("PUSH", variable.Value.ToString()); } else { throw new AssertionFailedException("unexpected result for LHS"); } }
protected override void GenerateCode(CodeGenContext context) { context.InsertComment("return statement"); ReturnValue?.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); context.GenerateInstruction("RET"); }
protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose) { // When we ask for AddressOrNode, we will get either an address // e.g. for a[i] += ..., we'll get a+i on the stack, or, // for i += ..., we'll get nothing on the stack, so we can pop directly into i var target = Left.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.AddressOrNode); var variable = target as VariableTreeNode; if (Op != Assignment) { GenerateLHSValue(context, target, variable); } Right.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); var keep = false; switch (purpose) { case EvaluationIntention.Value: case EvaluationIntention.ValueOrNode: keep = true; break; case EvaluationIntention.SideEffectsOnly: break; default: throw new AssertionFailedException("unexpected evaluation intention" + purpose); } if (Op != Assignment) { GenerateAssignmentComputation(context); } if (target == null) { // this case is that we generated an address onto the stack for the target // so, we need to use indirection operators if (keep) { // Stack has LeftY | RightTop <-- stack top // This instruction does *LeftY = RightTop // and pops only Left off the stack, leaving Right context.GenerateInstruction("ISTORE"); } else { // Stack has LeftY | RightTop <-- stack top // This instruction does *LeftYT = RightTop // and pops both Left and Right off the stack context.GenerateInstruction("IPOP"); } } else { // this case is that we generated nothing onto the stack for the left hand side // so, we'll pop or store directly into if (keep) { // Stack has RightTop <-- stack top // This instruction does var = RightTop // and does not pop Right // This form is used when the assignment is used // as in f(a=b); in which b is assigned into a, and the value is passed to f context.GenerateInstruction("STORE", variable.Value.ToString()); } else { // Stack has RightTop <-- stack top // This instruction does var = RightTop // and does pop Right off the stack, because the value is not wanted. context.GenerateInstruction("POP", variable.Value.ToString()); } } return(null); }