Java tutorial
/* * Copyright (c) 2011-2015, Dan McNulty * All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package net.udidb.expr.lang.c; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.misc.NotNull; import org.antlr.v4.runtime.misc.ParseCancellationException; import org.antlr.v4.runtime.tree.ParseTreeProperty; import net.sourcecrumbs.api.debug.symbols.DebugType; import net.udidb.expr.ExecutionContext; import net.udidb.expr.grammar.c.CParser; import net.udidb.expr.grammar.c.CParser.ConstantContext; import net.udidb.expr.grammar.c.CParser.FloatingConstantContext; import net.udidb.expr.values.AddressValue; import net.udidb.expr.values.NumberValue; import net.udidb.expr.values.StringValue; /** * Visitor that simplifies and computes expressions that do not require debuggee execution * * @author dmcnulty */ public class ExpressionSimplificationVisitor extends BaseExpressionVisitor<Void> { private static final String INVALID_TREE_MSG = "Unexpected parse tree state encountered"; private final ExecutionContext executionContext; public ExpressionSimplificationVisitor(ParseTreeProperty<NodeState> states, ExecutionContext executionContext) { super(states); this.executionContext = executionContext; } @Override public Void visitIntegerConstant(@NotNull CParser.IntegerConstantContext ctx) { NodeState nodeState = getNodeState(ctx); String intConstantString; int base; if (ctx.DecimalConstant() != null) { base = 10; intConstantString = ctx.DecimalConstant().getText(); } else if (ctx.HexadecimalConstant() != null) { base = 16; intConstantString = ctx.HexadecimalConstant().getText().substring(2); } else if (ctx.OctalConstant() != null) { base = 8; intConstantString = ctx.OctalConstant().getText().substring(1); } else { throw new ParseCancellationException(INVALID_TREE_MSG); } Number value; DebugType intType = nodeState.getEffectiveType(); if (intType == Types.getType(Types.UNSIGNED_INT_NAME)) { value = Integer.parseUnsignedInt(intConstantString, base); } else if (intType == Types.getType(Types.SIGNED_INT_NAME)) { value = Integer.parseInt(intConstantString, base); } else if (intType == Types.getType(Types.UNSIGNED_LONG_NAME)) { value = Long.parseUnsignedLong(intConstantString, base); } else if (intType == Types.getType(Types.SIGNED_LONG_NAME)) { value = Long.parseLong(intConstantString, base); } else if (intType == Types.getType(Types.UNSIGNED_LONG_LONG_NAME)) { // TODO Need to figure out how to create a BigInteger from a String throw new ParseCancellationException("unsigned long long is currently not supported"); } else if (intType == Types.getType(Types.SIGNED_LONG_LONG_NAME)) { throw new ParseCancellationException("long long is currently not supported"); } else { throw new ParseCancellationException(INVALID_TREE_MSG); } nodeState.setExpressionValue(new NumberValue(value)); return null; } @Override public Void visitFloatingConstant(@NotNull FloatingConstantContext ctx) { NodeState nodeState = getNodeState(ctx); Number value; DebugType floatType = nodeState.getEffectiveType(); if (floatType == Types.getType(Types.FLOAT_NAME)) { value = Float.parseFloat(ctx.getText()); } else if (floatType == Types.getType(Types.DOUBLE_NAME)) { value = Double.parseDouble(ctx.getText()); } else { throw new ParseCancellationException(INVALID_TREE_MSG); } nodeState.setExpressionValue(new NumberValue(value)); return null; } @Override public Void visitStringLiteral(@NotNull CParser.StringLiteralContext ctx) { getNodeState(ctx).setExpressionValue(new StringValue(ctx.getText())); return null; } @Override public Void visitAdditiveExpression(@NotNull CParser.AdditiveExpressionContext ctx) { NodeState nodeState = getNodeState(ctx); ParserRuleContext multExpr = ctx.multiplicativeExpression(); multExpr.accept(this); if (ctx.additiveExpression() == null) { nodeState.setExpressionValue(getNodeState(multExpr).getExpressionValue()); return null; } ParserRuleContext addExpr = ctx.additiveExpression(); addExpr.accept(this); if (getNodeState(addExpr).getExpressionValue() == null || getNodeState(multExpr).getExpressionValue() == null) { // The computation cannot be performed yet return null; } String operation = ctx.getChild(1).getText(); Number left = getNodeState(addExpr).getExpressionValue().getNumberValue(); Number right = getNodeState(multExpr).getExpressionValue().getNumberValue(); DebugType effectiveType = nodeState.getEffectiveType(); Number computedValue; switch (operation) { case "+": if (effectiveType == Types.getType(Types.FLOAT_NAME)) { computedValue = left.floatValue() + right.floatValue(); } else if (effectiveType == Types.getType(Types.DOUBLE_NAME)) { computedValue = left.doubleValue() + right.doubleValue(); } else { // TODO handle other cases computedValue = 0; } break; case "-": // TODO implement computedValue = 0; break; default: throw new ParseCancellationException(INVALID_TREE_MSG); } nodeState.setExpressionValue(new NumberValue(computedValue)); return null; } @Override public Void visitConstant(@NotNull ConstantContext ctx) { super.visitConstant(ctx); if (ctx.characterConstant() != null) { getNodeState(ctx).setExpressionValue(getNodeState(ctx.characterConstant()).getExpressionValue()); } else if (ctx.floatingConstant() != null) { getNodeState(ctx).setExpressionValue(getNodeState(ctx.floatingConstant()).getExpressionValue()); } else if (ctx.integerConstant() != null) { getNodeState(ctx).setExpressionValue(getNodeState(ctx.integerConstant()).getExpressionValue()); } else { throw new ParseCancellationException(INVALID_TREE_MSG); } return null; } @Override public Void visitAssignmentExpression(@NotNull CParser.AssignmentExpressionContext ctx) { super.visitAssignmentExpression(ctx); if (ctx.unaryExpression() != null) { // For now, this will require execution in the debuggee. There may be some optimizations that can be made where // a memory location/register can just be updated return null; } getNodeState(ctx).setExpressionValue(getNodeState(ctx.conditionalExpression()).getExpressionValue()); return null; } @Override public Void visitPrimaryExpression(@NotNull CParser.PrimaryExpressionContext ctx) { super.visitPrimaryExpression(ctx); NodeState nodeState = getNodeState(ctx); if (nodeState.getFunction() != null && nodeState.getFunction().getEntryAddress() != null) { nodeState.setExpressionValue(new AddressValue(nodeState.getFunction().getEntryAddress())); } else if (nodeState.getSymbol() != null) { nodeState.setExpressionValue(new AddressValue(nodeState.getSymbol().getAddress())); } else { // TODO need to handle variable -- the value of a variable may be available by interrogating the debuggee nodeState.setExpressionValue(getNodeState(ctx.constant()).getExpressionValue()); } return null; } @Override public Void visitCastExpression(@NotNull CParser.CastExpressionContext ctx) { super.visitCastExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.unaryExpression()).getExpressionValue()); return null; } @Override public Void visitConditionalExpression(@NotNull CParser.ConditionalExpressionContext ctx) { super.visitConditionalExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.logicalOrExpression()).getExpressionValue()); return null; } @Override public Void visitConstantExpression(@NotNull CParser.ConstantExpressionContext ctx) { super.visitConstantExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.conditionalExpression()).getExpressionValue()); return null; } @Override public Void visitExpression(@NotNull CParser.ExpressionContext ctx) { super.visitExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.assignmentExpression()).getExpressionValue()); return null; } @Override public Void visitExclusiveOrExpression(@NotNull CParser.ExclusiveOrExpressionContext ctx) { super.visitExclusiveOrExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.andExpression()).getExpressionValue()); return null; } @Override public Void visitEqualityExpression(@NotNull CParser.EqualityExpressionContext ctx) { super.visitEqualityExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.relationalExpression()).getExpressionValue()); return null; } @Override public Void visitInclusiveOrExpression(@NotNull CParser.InclusiveOrExpressionContext ctx) { super.visitInclusiveOrExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.exclusiveOrExpression()).getExpressionValue()); return null; } @Override public Void visitLogicalAndExpression(@NotNull CParser.LogicalAndExpressionContext ctx) { super.visitLogicalAndExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.inclusiveOrExpression()).getExpressionValue()); return null; } @Override public Void visitLogicalOrExpression(@NotNull CParser.LogicalOrExpressionContext ctx) { super.visitLogicalOrExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.logicalAndExpression()).getExpressionValue()); return null; } @Override public Void visitMultiplicativeExpression(@NotNull CParser.MultiplicativeExpressionContext ctx) { super.visitMultiplicativeExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.castExpression()).getExpressionValue()); return null; } @Override public Void visitPostfixExpression(@NotNull CParser.PostfixExpressionContext ctx) { super.visitPostfixExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.primaryExpression()).getExpressionValue()); return null; } @Override public Void visitAndExpression(@NotNull CParser.AndExpressionContext ctx) { super.visitAndExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.equalityExpression()).getExpressionValue()); return null; } @Override public Void visitRelationalExpression(@NotNull CParser.RelationalExpressionContext ctx) { super.visitRelationalExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.shiftExpression()).getExpressionValue()); return null; } @Override public Void visitShiftExpression(@NotNull CParser.ShiftExpressionContext ctx) { super.visitShiftExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.additiveExpression()).getExpressionValue()); return null; } @Override public Void visitUnaryExpression(@NotNull CParser.UnaryExpressionContext ctx) { super.visitUnaryExpression(ctx); getNodeState(ctx).setExpressionValue(getNodeState(ctx.postfixExpression()).getExpressionValue()); return null; } }