1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.millscript.millscript.expr;
22
23 import org.millscript.commons.util.IList;
24 import org.millscript.millscript.action.Action;
25 import org.millscript.millscript.action.SwitchAction;
26 import org.millscript.millscript.vm.CompilerState;
27
28 /**
29 * This class implements a <code>switch</code> expression.
30 *
31 * @see org.millscript.millscript.syntax.SwitchSyntax
32 * @see SwitchAction
33 */
34 public final class SwitchExpr extends Expr< SwitchAction > {
35
36 /**
37 * The expression representing our choice. This will be compared against the
38 * individual case expressions to find a match.
39 */
40 private final Expr< ? > choice;
41
42 /**
43 * The list of case expressions.
44 */
45 private final IList< CaseExpr > cases;
46
47 /**
48 * The default block to execute if no cases match.
49 */
50 private final Expr< ? > def;
51
52 /**
53 * Creates a new <code>switch</code> expression for the specified choice,
54 * case and default expressions.
55 *
56 * @param a the choice expression
57 * @param b the list of case expressions
58 * @param c the default expression
59 */
60 public SwitchExpr( final Expr< ? > a, final IList< CaseExpr > b, final Expr< ? > c ) {
61
62 this.choice = CheckExpr.make( a );
63
64 this.cases = b;
65
66
67 this.def = c == null ? new SkipExpr() : c;
68 }
69
70 /**
71 * @see org.millscript.millscript.expr.Expr#arity()
72 */
73 @Override
74 public int arity() {
75
76
77
78 int a = def.arity();
79 for ( int i = 1; i <= this.cases.size(); i++ ) {
80 final CaseExpr ce = this.cases.get( i );
81 if ( ce.getAct().arity() != a ) {
82 return -1;
83 }
84 }
85 return a;
86 }
87
88 /**
89 * @see org.millscript.millscript.expr.Expr#compileIt()
90 */
91 @Override
92 public SwitchAction compileIt() {
93
94
95 int count = 0;
96 for ( int i = 1; i <= this.cases.size(); i++ ) {
97 count += this.cases.get( i ).getPatterns().size();
98 }
99
100
101
102 final Action[] preds = new Action[ count ];
103
104
105 final int[] switches = new int[ count ];
106
107
108 final Action[] acts = new Action[ cases.size() ];
109
110
111
112
113 for ( int i = 0, k = 0; i < this.cases.size(); i++ ) {
114 final CaseExpr ce = this.cases.get0( i );
115
116 for ( int p = 0; p < ce.getPatterns().size(); p++, k++ ) {
117 final Expr< ? > patn = ce.getPatterns().get0( p );
118
119 preds[ k ] = patn.compile();
120
121
122 switches[ k ] = i;
123 }
124
125 acts[ i ] = ce.getAct().compile();
126 }
127 return new SwitchAction( choice.compile(), preds, switches, acts, def.compile() );
128 }
129
130 /**
131 * @see org.millscript.millscript.expr.Expr#resolve(org.millscript.millscript.vm.CompilerState)
132 */
133 @Override
134 public void resolve( final CompilerState state ) {
135 this.choice.resolve( state );
136 Expr.resolveList( state, this.cases );
137 this.def.resolve( state );
138 }
139
140 /**
141 * @see org.millscript.millscript.expr.Expr#showComponents(int)
142 */
143 @Override
144 void showComponents( final int n ) {
145 this.choice.show( n );
146 for ( int i = 1; i <= this.cases.size(); i++ ) {
147 ((Expr) this.cases.get( i )).show( n );
148 }
149 this.def.show( n );
150 }
151
152 }