protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose) { bool evaluateForSideEffectsOnly = false; switch (purpose) { case EvaluationIntention.SideEffectsOnly: evaluateForSideEffectsOnly = true; break; case EvaluationIntention.Value: case EvaluationIntention.ValueOrNode: break; default: throw new AssertionFailedException("unexpected evaluation intention" + purpose); } var what = Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.AddressOrNode); if (what == null) { // it is a temporary (and lvalue), so must be an address // stack has: address if (!evaluateForSideEffectsOnly) { context.GenerateInstruction("DUP"); // stack has: address, address } context.GenerateInstruction("IDEC"); // stack has: address if (!evaluateForSideEffectsOnly) { context.GenerateInstruction("Indirection"); // stack has: value } } else if (what is VariableTreeNode variable) { context.GenerateInstruction("PUSH", variable.Value.ToString( )); // stack has: value context.GenerateInstruction("DEC"); // stack has: value+1 if (!evaluateForSideEffectsOnly) { context.GenerateInstruction("DUP"); // stack has value+1, value+1 } context.GenerateInstruction("POP", variable.Value.ToString( )); } else { throw new AssertionFailedException("unexpected target" + what.ToString()); } return(null); }
protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose) { // To take the address of a child expression, we capitalize on having an evaluation intention mode that matches this. // We have this mode to support assignment and address of operations. // Note that we must have a notion of evaluating an expression for its location rather than for its value, as // we could not evaluate the left hand side of an assignment for value, and then take its address -- that doesn't work! // By using the address evaluation intention for the child, there is then sometimes no code to generate for this operator. // When it does need to generate code, the case of &a, for example, the it uses the PEA instruction // Also note that this approach automatically detects and optimizes a sequence like &* // // Contrast this above with the Indirection operator // The other operator, Indirection, needs to special case *& to collapse these two. // This is because we don't have an evaluation intention mode for indirection, // Instead we generate the indirection's value and the use an Indirection instruction to dereference it. // switch (purpose) { case EvaluationIntention.SideEffectsOnly: Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.SideEffectsOnly); break; case EvaluationIntention.Value: var ans = Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.AddressOrNode); if (ans != null) { if (ans is VariableTreeNode variable) { // PEA == Push Effective Address context.GenerateInstruction("PEA", variable.Value.ToString()); } else { throw new AssertionFailedException("unexpected result for &"); } } break; case EvaluationIntention.ValueOrNode: return(Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.AddressOrNode)); default: throw new AssertionFailedException("unexpected evaluation intention" + purpose); } return(null); }
protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose) { Arg.GenerateCodeForValueWithPrettyPrint(context, purpose); switch (purpose) { case EvaluationIntention.SideEffectsOnly: Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.SideEffectsOnly); return(null); case EvaluationIntention.Value: case EvaluationIntention.ValueOrNode: Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); context.GenerateInstruction("NEG"); return(null); default: throw new AssertionFailedException("unexpected evaluation intention" + purpose); } }
protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose) { switch (purpose) { case EvaluationIntention.SideEffectsOnly: Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.SideEffectsOnly); return(null); case EvaluationIntention.Value: case EvaluationIntention.ValueOrNode: Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); if (Op != Operators.Operator.FixPoint) { context.GenerateInstruction(Op.ToString()); } return(null); // case EvaluationIntention.AddressOrNode: // Arg.GenerateCodeForValueWithPrettyPrint ( context, EvaluationIntention.Value ); // return null; default: throw new AssertionFailedException("unexpected evaluation intention" + purpose); } }
protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose) { // NB: a C string's value is its address. // (There is no notion of a string's address as that would be an address of an address.) switch (purpose) { case EvaluationIntention.Value: case EvaluationIntention.ValueOrNode: // might be a case of *(p+i), which can be done as p[i]; if (Arg is AddressOfTreeNode addrOf1) { // 3404 // 3401: collapse *&(expr) on RHS and just generate code for the underlying expr context.SetPrettyPrintProlog("<skipped> "); context.PrettyPrint(Arg); return(addrOf1.Arg.GenerateCodeForValueWithPrettyPrint(context, purpose)); } else { if (Arg is AdditionTreeNode addition) { context.SetPrettyPrintProlog("<skipped> "); context.PrettyPrint(Arg); addition.Left.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); addition.Right.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); context.GenerateInstruction("Subscript"); } else { Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); context.GenerateInstruction("Indirection"); } } break; case EvaluationIntention.SideEffectsOnly: Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.SideEffectsOnly); break; case EvaluationIntention.AddressOrNode: if (Arg is AddressOfTreeNode addrOf2) { // 3401: collapse *&(expr) on LHS and just generate code for the underlying expr context.SetPrettyPrintProlog("<skipped> "); context.PrettyPrint(Arg); return(addrOf2.Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.AddressOrNode)); } else { // NB: if we did ValueOrNode here, we'd have to handle Node results specially // as we cannot allow a Node from ValueOrNode unmodified as AddressOrNode Arg.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.Value); } break; default: throw new AssertionFailedException("unexpected evaluation intention" + purpose); } return(null); }