org.elasticsearch.painless.WriterExpression.java Source code

Java tutorial

Introduction

Here is the source code for org.elasticsearch.painless.WriterExpression.java

Source

/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.elasticsearch.painless;

import org.elasticsearch.painless.Definition.Sort;
import org.elasticsearch.painless.Definition.Type;
import org.elasticsearch.painless.Metadata.ExpressionMetadata;
import org.elasticsearch.painless.PainlessParser.AssignmentContext;
import org.elasticsearch.painless.PainlessParser.BinaryContext;
import org.elasticsearch.painless.PainlessParser.BoolContext;
import org.elasticsearch.painless.PainlessParser.CastContext;
import org.elasticsearch.painless.PainlessParser.CompContext;
import org.elasticsearch.painless.PainlessParser.ConditionalContext;
import org.elasticsearch.painless.PainlessParser.ExpressionContext;
import org.elasticsearch.painless.PainlessParser.ExternalContext;
import org.elasticsearch.painless.PainlessParser.FalseContext;
import org.elasticsearch.painless.PainlessParser.IncrementContext;
import org.elasticsearch.painless.PainlessParser.NullContext;
import org.elasticsearch.painless.PainlessParser.NumericContext;
import org.elasticsearch.painless.PainlessParser.PostincContext;
import org.elasticsearch.painless.PainlessParser.PreincContext;
import org.elasticsearch.painless.PainlessParser.TrueContext;
import org.elasticsearch.painless.PainlessParser.UnaryContext;
import org.elasticsearch.painless.WriterUtility.Branch;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.GeneratorAdapter;

import static org.elasticsearch.painless.PainlessParser.ADD;
import static org.elasticsearch.painless.PainlessParser.BWAND;
import static org.elasticsearch.painless.PainlessParser.BWOR;
import static org.elasticsearch.painless.PainlessParser.BWXOR;
import static org.elasticsearch.painless.PainlessParser.DIV;
import static org.elasticsearch.painless.PainlessParser.LSH;
import static org.elasticsearch.painless.PainlessParser.MUL;
import static org.elasticsearch.painless.PainlessParser.REM;
import static org.elasticsearch.painless.PainlessParser.RSH;
import static org.elasticsearch.painless.PainlessParser.SUB;
import static org.elasticsearch.painless.PainlessParser.USH;
import static org.elasticsearch.painless.WriterConstants.CHECKEQUALS;
import static org.elasticsearch.painless.WriterConstants.DEF_EQ_CALL;
import static org.elasticsearch.painless.WriterConstants.DEF_GTE_CALL;
import static org.elasticsearch.painless.WriterConstants.DEF_GT_CALL;
import static org.elasticsearch.painless.WriterConstants.DEF_LTE_CALL;
import static org.elasticsearch.painless.WriterConstants.DEF_LT_CALL;
import static org.elasticsearch.painless.WriterConstants.DEF_NEG_CALL;
import static org.elasticsearch.painless.WriterConstants.DEF_NOT_CALL;
import static org.elasticsearch.painless.WriterConstants.NEGATEEXACT_INT;
import static org.elasticsearch.painless.WriterConstants.NEGATEEXACT_LONG;

class WriterExpression {
    private final Metadata metadata;
    private final Definition definition;
    private final CompilerSettings settings;

    private final GeneratorAdapter execute;

    private final Writer writer;
    private final WriterUtility utility;
    private final WriterCaster caster;

    WriterExpression(final Metadata metadata, final GeneratorAdapter execute, final Writer writer,
            final WriterUtility utility, final WriterCaster caster) {
        this.metadata = metadata;
        definition = metadata.definition;
        settings = metadata.settings;

        this.execute = execute;

        this.writer = writer;
        this.utility = utility;
        this.caster = caster;
    }

    void processNumeric(final NumericContext ctx) {
        final ExpressionMetadata numericemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = numericemd.postConst;

        if (postConst == null) {
            utility.writeNumeric(ctx, numericemd.preConst);
            caster.checkWriteCast(numericemd);
        } else {
            utility.writeConstant(ctx, postConst);
        }

        utility.checkWriteBranch(ctx);
    }

    void processTrue(final TrueContext ctx) {
        final ExpressionMetadata trueemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = trueemd.postConst;
        final Branch branch = utility.getBranch(ctx);

        if (branch == null) {
            if (postConst == null) {
                utility.writeBoolean(ctx, true);
                caster.checkWriteCast(trueemd);
            } else {
                utility.writeConstant(ctx, postConst);
            }
        } else if (branch.tru != null) {
            execute.goTo(branch.tru);
        }
    }

    void processFalse(final FalseContext ctx) {
        final ExpressionMetadata falseemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = falseemd.postConst;
        final Branch branch = utility.getBranch(ctx);

        if (branch == null) {
            if (postConst == null) {
                utility.writeBoolean(ctx, false);
                caster.checkWriteCast(falseemd);
            } else {
                utility.writeConstant(ctx, postConst);
            }
        } else if (branch.fals != null) {
            execute.goTo(branch.fals);
        }
    }

    void processNull(final NullContext ctx) {
        final ExpressionMetadata nullemd = metadata.getExpressionMetadata(ctx);

        execute.visitInsn(Opcodes.ACONST_NULL);
        caster.checkWriteCast(nullemd);
        utility.checkWriteBranch(ctx);
    }

    void processExternal(final ExternalContext ctx) {
        final ExpressionMetadata expremd = metadata.getExpressionMetadata(ctx);
        writer.visit(ctx.extstart());
        caster.checkWriteCast(expremd);
        utility.checkWriteBranch(ctx);
    }

    void processPostinc(final PostincContext ctx) {
        final ExpressionMetadata expremd = metadata.getExpressionMetadata(ctx);
        writer.visit(ctx.extstart());
        caster.checkWriteCast(expremd);
        utility.checkWriteBranch(ctx);
    }

    void processPreinc(final PreincContext ctx) {
        final ExpressionMetadata expremd = metadata.getExpressionMetadata(ctx);
        writer.visit(ctx.extstart());
        caster.checkWriteCast(expremd);
        utility.checkWriteBranch(ctx);
    }

    void processUnary(final UnaryContext ctx) {
        final ExpressionMetadata unaryemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = unaryemd.postConst;
        final Object preConst = unaryemd.preConst;
        final Branch branch = utility.getBranch(ctx);

        if (postConst != null) {
            if (ctx.BOOLNOT() != null) {
                if (branch == null) {
                    utility.writeConstant(ctx, postConst);
                } else {
                    if ((boolean) postConst && branch.tru != null) {
                        execute.goTo(branch.tru);
                    } else if (!(boolean) postConst && branch.fals != null) {
                        execute.goTo(branch.fals);
                    }
                }
            } else {
                utility.writeConstant(ctx, postConst);
                utility.checkWriteBranch(ctx);
            }
        } else if (preConst != null) {
            if (branch == null) {
                utility.writeConstant(ctx, preConst);
                caster.checkWriteCast(unaryemd);
            } else {
                throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
            }
        } else {
            final ExpressionContext exprctx = ctx.expression();

            if (ctx.BOOLNOT() != null) {
                final Branch local = utility.markBranch(ctx, exprctx);

                if (branch == null) {
                    local.fals = new Label();
                    final Label aend = new Label();

                    writer.visit(exprctx);

                    execute.push(false);
                    execute.goTo(aend);
                    execute.mark(local.fals);
                    execute.push(true);
                    execute.mark(aend);

                    caster.checkWriteCast(unaryemd);
                } else {
                    local.tru = branch.fals;
                    local.fals = branch.tru;

                    writer.visit(exprctx);
                }
            } else {
                final org.objectweb.asm.Type type = unaryemd.from.type;
                final Sort sort = unaryemd.from.sort;

                writer.visit(exprctx);

                if (ctx.BWNOT() != null) {
                    if (sort == Sort.DEF) {
                        execute.invokeStatic(definition.defobjType.type, DEF_NOT_CALL);
                    } else {
                        if (sort == Sort.INT) {
                            utility.writeConstant(ctx, -1);
                        } else if (sort == Sort.LONG) {
                            utility.writeConstant(ctx, -1L);
                        } else {
                            throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                        }

                        execute.math(GeneratorAdapter.XOR, type);
                    }
                } else if (ctx.SUB() != null) {
                    if (sort == Sort.DEF) {
                        execute.invokeStatic(definition.defobjType.type, DEF_NEG_CALL);
                    } else {
                        if (settings.getNumericOverflow()) {
                            execute.math(GeneratorAdapter.NEG, type);
                        } else {
                            if (sort == Sort.INT) {
                                execute.invokeStatic(definition.mathType.type, NEGATEEXACT_INT);
                            } else if (sort == Sort.LONG) {
                                execute.invokeStatic(definition.mathType.type, NEGATEEXACT_LONG);
                            } else {
                                throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                            }
                        }
                    }
                } else if (ctx.ADD() == null) {
                    throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                }

                caster.checkWriteCast(unaryemd);
                utility.checkWriteBranch(ctx);
            }
        }
    }

    void processCast(final CastContext ctx) {
        final ExpressionMetadata castemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = castemd.postConst;

        if (postConst == null) {
            writer.visit(ctx.expression());
            caster.checkWriteCast(castemd);
        } else {
            utility.writeConstant(ctx, postConst);
        }

        utility.checkWriteBranch(ctx);
    }

    void processBinary(final BinaryContext ctx) {
        final ExpressionMetadata binaryemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = binaryemd.postConst;
        final Object preConst = binaryemd.preConst;
        final Branch branch = utility.getBranch(ctx);

        if (postConst != null) {
            utility.writeConstant(ctx, postConst);
        } else if (preConst != null) {
            if (branch == null) {
                utility.writeConstant(ctx, preConst);
                caster.checkWriteCast(binaryemd);
            } else {
                throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
            }
        } else if (binaryemd.from.sort == Sort.STRING) {
            final boolean marked = utility.containsStrings(ctx);

            if (!marked) {
                utility.writeNewStrings();
            }

            final ExpressionContext exprctx0 = ctx.expression(0);
            final ExpressionMetadata expremd0 = metadata.getExpressionMetadata(exprctx0);
            utility.addStrings(exprctx0);
            writer.visit(exprctx0);

            if (utility.containsStrings(exprctx0)) {
                utility.writeAppendStrings(expremd0.from.sort);
                utility.removeStrings(exprctx0);
            }

            final ExpressionContext exprctx1 = ctx.expression(1);
            final ExpressionMetadata expremd1 = metadata.getExpressionMetadata(exprctx1);
            utility.addStrings(exprctx1);
            writer.visit(exprctx1);

            if (utility.containsStrings(exprctx1)) {
                utility.writeAppendStrings(expremd1.from.sort);
                utility.removeStrings(exprctx1);
            }

            if (marked) {
                utility.removeStrings(ctx);
            } else {
                utility.writeToStrings();
            }

            caster.checkWriteCast(binaryemd);
        } else {
            final ExpressionContext exprctx0 = ctx.expression(0);
            final ExpressionContext exprctx1 = ctx.expression(1);

            writer.visit(exprctx0);
            writer.visit(exprctx1);

            final Type type = binaryemd.from;

            if (ctx.MUL() != null)
                utility.writeBinaryInstruction(ctx, type, MUL);
            else if (ctx.DIV() != null)
                utility.writeBinaryInstruction(ctx, type, DIV);
            else if (ctx.REM() != null)
                utility.writeBinaryInstruction(ctx, type, REM);
            else if (ctx.ADD() != null)
                utility.writeBinaryInstruction(ctx, type, ADD);
            else if (ctx.SUB() != null)
                utility.writeBinaryInstruction(ctx, type, SUB);
            else if (ctx.LSH() != null)
                utility.writeBinaryInstruction(ctx, type, LSH);
            else if (ctx.USH() != null)
                utility.writeBinaryInstruction(ctx, type, USH);
            else if (ctx.RSH() != null)
                utility.writeBinaryInstruction(ctx, type, RSH);
            else if (ctx.BWAND() != null)
                utility.writeBinaryInstruction(ctx, type, BWAND);
            else if (ctx.BWXOR() != null)
                utility.writeBinaryInstruction(ctx, type, BWXOR);
            else if (ctx.BWOR() != null)
                utility.writeBinaryInstruction(ctx, type, BWOR);
            else {
                throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
            }

            caster.checkWriteCast(binaryemd);
        }

        utility.checkWriteBranch(ctx);
    }

    void processComp(final CompContext ctx) {
        final ExpressionMetadata compemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = compemd.postConst;
        final Object preConst = compemd.preConst;
        final Branch branch = utility.getBranch(ctx);

        if (postConst != null) {
            if (branch == null) {
                utility.writeConstant(ctx, postConst);
            } else {
                if ((boolean) postConst && branch.tru != null) {
                    execute.mark(branch.tru);
                } else if (!(boolean) postConst && branch.fals != null) {
                    execute.mark(branch.fals);
                }
            }
        } else if (preConst != null) {
            if (branch == null) {
                utility.writeConstant(ctx, preConst);
                caster.checkWriteCast(compemd);
            } else {
                throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
            }
        } else {
            final ExpressionContext exprctx0 = ctx.expression(0);
            final ExpressionMetadata expremd0 = metadata.getExpressionMetadata(exprctx0);

            final ExpressionContext exprctx1 = ctx.expression(1);
            final ExpressionMetadata expremd1 = metadata.getExpressionMetadata(exprctx1);
            final org.objectweb.asm.Type type = expremd1.to.type;
            final Sort sort1 = expremd1.to.sort;

            writer.visit(exprctx0);

            if (!expremd1.isNull) {
                writer.visit(exprctx1);
            }

            final boolean tru = branch != null && branch.tru != null;
            final boolean fals = branch != null && branch.fals != null;
            final Label jump = tru ? branch.tru : fals ? branch.fals : new Label();
            final Label end = new Label();

            final boolean eq = (ctx.EQ() != null || ctx.EQR() != null) && (tru || !fals)
                    || (ctx.NE() != null || ctx.NER() != null) && fals;
            final boolean ne = (ctx.NE() != null || ctx.NER() != null) && (tru || !fals)
                    || (ctx.EQ() != null || ctx.EQR() != null) && fals;
            final boolean lt = ctx.LT() != null && (tru || !fals) || ctx.GTE() != null && fals;
            final boolean lte = ctx.LTE() != null && (tru || !fals) || ctx.GT() != null && fals;
            final boolean gt = ctx.GT() != null && (tru || !fals) || ctx.LTE() != null && fals;
            final boolean gte = ctx.GTE() != null && (tru || !fals) || ctx.LT() != null && fals;

            boolean writejump = true;

            switch (sort1) {
            case VOID:
            case BYTE:
            case SHORT:
            case CHAR:
                throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
            case BOOL:
                if (eq)
                    execute.ifZCmp(GeneratorAdapter.EQ, jump);
                else if (ne)
                    execute.ifZCmp(GeneratorAdapter.NE, jump);
                else {
                    throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                }

                break;
            case INT:
            case LONG:
            case FLOAT:
            case DOUBLE:
                if (eq)
                    execute.ifCmp(type, GeneratorAdapter.EQ, jump);
                else if (ne)
                    execute.ifCmp(type, GeneratorAdapter.NE, jump);
                else if (lt)
                    execute.ifCmp(type, GeneratorAdapter.LT, jump);
                else if (lte)
                    execute.ifCmp(type, GeneratorAdapter.LE, jump);
                else if (gt)
                    execute.ifCmp(type, GeneratorAdapter.GT, jump);
                else if (gte)
                    execute.ifCmp(type, GeneratorAdapter.GE, jump);
                else {
                    throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                }

                break;
            case DEF:
                if (eq) {
                    if (expremd1.isNull) {
                        execute.ifNull(jump);
                    } else if (!expremd0.isNull && ctx.EQ() != null) {
                        execute.invokeStatic(definition.defobjType.type, DEF_EQ_CALL);
                    } else {
                        execute.ifCmp(type, GeneratorAdapter.EQ, jump);
                    }
                } else if (ne) {
                    if (expremd1.isNull) {
                        execute.ifNonNull(jump);
                    } else if (!expremd0.isNull && ctx.NE() != null) {
                        execute.invokeStatic(definition.defobjType.type, DEF_EQ_CALL);
                        execute.ifZCmp(GeneratorAdapter.EQ, jump);
                    } else {
                        execute.ifCmp(type, GeneratorAdapter.NE, jump);
                    }
                } else if (lt) {
                    execute.invokeStatic(definition.defobjType.type, DEF_LT_CALL);
                } else if (lte) {
                    execute.invokeStatic(definition.defobjType.type, DEF_LTE_CALL);
                } else if (gt) {
                    execute.invokeStatic(definition.defobjType.type, DEF_GT_CALL);
                } else if (gte) {
                    execute.invokeStatic(definition.defobjType.type, DEF_GTE_CALL);
                } else {
                    throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                }

                writejump = expremd1.isNull || ne || ctx.EQR() != null;

                if (branch != null && !writejump) {
                    execute.ifZCmp(GeneratorAdapter.NE, jump);
                }

                break;
            default:
                if (eq) {
                    if (expremd1.isNull) {
                        execute.ifNull(jump);
                    } else if (ctx.EQ() != null) {
                        execute.invokeStatic(definition.utilityType.type, CHECKEQUALS);

                        if (branch != null) {
                            execute.ifZCmp(GeneratorAdapter.NE, jump);
                        }

                        writejump = false;
                    } else {
                        execute.ifCmp(type, GeneratorAdapter.EQ, jump);
                    }
                } else if (ne) {
                    if (expremd1.isNull) {
                        execute.ifNonNull(jump);
                    } else if (ctx.NE() != null) {
                        execute.invokeStatic(definition.utilityType.type, CHECKEQUALS);
                        execute.ifZCmp(GeneratorAdapter.EQ, jump);
                    } else {
                        execute.ifCmp(type, GeneratorAdapter.NE, jump);
                    }
                } else {
                    throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                }
            }

            if (branch == null) {
                if (writejump) {
                    execute.push(false);
                    execute.goTo(end);
                    execute.mark(jump);
                    execute.push(true);
                    execute.mark(end);
                }

                caster.checkWriteCast(compemd);
            }
        }
    }

    void processBool(final BoolContext ctx) {
        final ExpressionMetadata boolemd = metadata.getExpressionMetadata(ctx);
        final Object postConst = boolemd.postConst;
        final Object preConst = boolemd.preConst;
        final Branch branch = utility.getBranch(ctx);

        if (postConst != null) {
            if (branch == null) {
                utility.writeConstant(ctx, postConst);
            } else {
                if ((boolean) postConst && branch.tru != null) {
                    execute.mark(branch.tru);
                } else if (!(boolean) postConst && branch.fals != null) {
                    execute.mark(branch.fals);
                }
            }
        } else if (preConst != null) {
            if (branch == null) {
                utility.writeConstant(ctx, preConst);
                caster.checkWriteCast(boolemd);
            } else {
                throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
            }
        } else {
            final ExpressionContext exprctx0 = ctx.expression(0);
            final ExpressionContext exprctx1 = ctx.expression(1);

            if (branch == null) {
                if (ctx.BOOLAND() != null) {
                    final Branch local = utility.markBranch(ctx, exprctx0, exprctx1);
                    local.fals = new Label();
                    final Label end = new Label();

                    writer.visit(exprctx0);
                    writer.visit(exprctx1);

                    execute.push(true);
                    execute.goTo(end);
                    execute.mark(local.fals);
                    execute.push(false);
                    execute.mark(end);
                } else if (ctx.BOOLOR() != null) {
                    final Branch branch0 = utility.markBranch(ctx, exprctx0);
                    branch0.tru = new Label();
                    final Branch branch1 = utility.markBranch(ctx, exprctx1);
                    branch1.fals = new Label();
                    final Label aend = new Label();

                    writer.visit(exprctx0);
                    writer.visit(exprctx1);

                    execute.mark(branch0.tru);
                    execute.push(true);
                    execute.goTo(aend);
                    execute.mark(branch1.fals);
                    execute.push(false);
                    execute.mark(aend);
                } else {
                    throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                }

                caster.checkWriteCast(boolemd);
            } else {
                if (ctx.BOOLAND() != null) {
                    final Branch branch0 = utility.markBranch(ctx, exprctx0);
                    branch0.fals = branch.fals == null ? new Label() : branch.fals;
                    final Branch branch1 = utility.markBranch(ctx, exprctx1);
                    branch1.tru = branch.tru;
                    branch1.fals = branch.fals;

                    writer.visit(exprctx0);
                    writer.visit(exprctx1);

                    if (branch.fals == null) {
                        execute.mark(branch0.fals);
                    }
                } else if (ctx.BOOLOR() != null) {
                    final Branch branch0 = utility.markBranch(ctx, exprctx0);
                    branch0.tru = branch.tru == null ? new Label() : branch.tru;
                    final Branch branch1 = utility.markBranch(ctx, exprctx1);
                    branch1.tru = branch.tru;
                    branch1.fals = branch.fals;

                    writer.visit(exprctx0);
                    writer.visit(exprctx1);

                    if (branch.tru == null) {
                        execute.mark(branch0.tru);
                    }
                } else {
                    throw new IllegalStateException(WriterUtility.error(ctx) + "Unexpected state.");
                }
            }
        }
    }

    void processConditional(final ConditionalContext ctx) {
        final ExpressionMetadata condemd = metadata.getExpressionMetadata(ctx);
        final Branch branch = utility.getBranch(ctx);

        final ExpressionContext expr0 = ctx.expression(0);
        final ExpressionContext expr1 = ctx.expression(1);
        final ExpressionContext expr2 = ctx.expression(2);

        final Branch local = utility.markBranch(ctx, expr0);
        local.fals = new Label();
        local.end = new Label();

        if (branch != null) {
            utility.copyBranch(branch, expr1, expr2);
        }

        writer.visit(expr0);
        writer.visit(expr1);
        execute.goTo(local.end);
        execute.mark(local.fals);
        writer.visit(expr2);
        execute.mark(local.end);

        if (branch == null) {
            caster.checkWriteCast(condemd);
        }
    }

    void processAssignment(final AssignmentContext ctx) {
        final ExpressionMetadata expremd = metadata.getExpressionMetadata(ctx);
        writer.visit(ctx.extstart());
        caster.checkWriteCast(expremd);
        utility.checkWriteBranch(ctx);
    }

    void processIncrement(final IncrementContext ctx) {
        final ExpressionMetadata incremd = metadata.getExpressionMetadata(ctx);
        final Object postConst = incremd.postConst;

        if (postConst == null) {
            utility.writeNumeric(ctx, incremd.preConst);
            caster.checkWriteCast(incremd);
        } else {
            utility.writeConstant(ctx, postConst);
        }

        utility.checkWriteBranch(ctx);
    }
}