1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.millscript.millscript.expr;
23
24 import org.millscript.millscript.action.Action;
25 import org.millscript.millscript.action.BinaryOpAction;
26 import org.millscript.millscript.action.arithmetic.AddAction;
27 import org.millscript.millscript.action.arithmetic.DivAction;
28 import org.millscript.millscript.action.arithmetic.ModAction;
29 import org.millscript.millscript.action.arithmetic.MulAction;
30 import org.millscript.millscript.action.arithmetic.SubAction;
31 import org.millscript.millscript.alert.Alerts;
32 import org.millscript.millscript.tools.IntegerTools;
33
34 /**
35 * This class implements an arithmetic expression. This expression always
36 * returns one result.
37 *
38 * @see IntegerTools
39 */
40 public final class ArithExpr extends BinaryOpExpr< BinaryOpAction > {
41
42 /**
43 * The arithmetic symbol this expression is for.
44 */
45 private final String sym;
46
47 /**
48 * Creates a new arithmetic expression for the specified symbol and left and
49 * right hand side expressions.
50 *
51 * @param s the arithmetic symbol to make an expression for
52 * @param a the left hand side expression, which should return a single
53 * result
54 * @param b the right hand side expression, which should return a single
55 * result
56 */
57 public ArithExpr( final String s, final Expr< ? > a, final Expr< ? > b ) {
58 super( a, b );
59 this.sym = s;
60 }
61
62 /**
63 * Returns an expression for the specified arithmetic expression. The
64 * arithmetic expression is composed of a symbol and left and right hand
65 * side expressions. This method provides some compile-time optimisation, as
66 * it avoids creating additional unnecessary objects in the expression tree.
67 * If the specified left and right hand side expressions are for constant
68 * integers, the specified operation is performed and a new constant
69 * expression returned.
70 *
71 * @param s the arithmetic symbol to make an expression for
72 * @param a the left hand side expression, which should return a single
73 * result
74 * @param b the right hand side expression, which should return a single
75 * result
76 * @return a {@link ConstantExpr} if the left and right hand side are
77 * constant integers, otherwise an anonymous {@link Action} for
78 * the specified symbol
79 */
80 public static Expr make( final String s, final Expr a, final Expr b ) {
81 Integer x = isIntegerExpr( a );
82 Integer y = isIntegerExpr( b );
83 if ( x != null && y != null ) {
84 return new ConstantExpr( IntegerTools.op( s, x, y ) );
85 } else if ( x != null ) {
86 return new ConstantLeftArithExpr( s, x, b );
87 } else if ( y != null ) {
88 return new ConstantRightArithExpr( s, a, y );
89 } else {
90 return new ArithExpr( s, a, b );
91 }
92 }
93
94 /**
95 * @see org.millscript.millscript.expr.BinaryOpExpr#newAction(org.millscript.millscript.action.Action, org.millscript.millscript.action.Action)
96 */
97 @Override
98 public BinaryOpAction newAction( final Action a, final Action b ) {
99 if ( sym == "+" ) {
100 return new AddAction( a, b );
101 } else if ( sym == "-" ) {
102 return new SubAction( a, b );
103 } else if ( sym == "*" ) {
104 return new MulAction( a, b );
105 } else if ( sym == "div" ) {
106 return new DivAction( a, b );
107 } else if ( sym == "mod" ) {
108 return new ModAction( a, b );
109 } else {
110 throw(
111 Alerts.fault(
112 "Unrecognized arithmetic symbol: " + sym
113 ).mishap()
114 );
115 }
116 }
117
118 }