View Javadoc
1   package org.metricshub.jawk.backend;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * Jawk
6    * ჻჻჻჻჻჻
7    * Copyright (C) 2006 - 2025 MetricsHub
8    * ჻჻჻჻჻჻
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation, either version 3 of the
12   * License, or (at your option) any later version.
13   *
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU General Lesser Public
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
22   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
23   */
24  
25  import java.util.ArrayDeque;
26  import java.util.Arrays;
27  import java.util.Deque;
28  import java.util.LinkedList;
29  
30  import org.metricshub.jawk.intermediate.UninitializedObject;
31  import org.metricshub.jawk.jrt.AssocArray;
32  
33  /**
34   * Runtime stack used by the AVM interpreter.
35   */
36  class RuntimeStack {
37  
38  	static final UninitializedObject BLANK = new UninitializedObject();
39  
40  	private Object[] globals = null;
41  	private Object[] locals = null;
42  	private Deque<Object[]> localsStack = new LinkedList<Object[]>();
43  	private Deque<Integer> returnIndexes = new ArrayDeque<Integer>();
44  
45  	@SuppressWarnings("unused")
46  	public void dump() {
47  		System.out.println("globals = " + Arrays.toString(globals));
48  		System.out.println("locals = " + Arrays.toString(locals));
49  		System.out.println("localsStack = " + localsStack);
50  		System.out.println("returnIndexes = " + returnIndexes);
51  	}
52  
53  	Object[] getNumGlobals() {
54  		return globals;
55  	}
56  
57  	/** Must be one of the first methods executed. */
58  	void setNumGlobals(long l) {
59  		assert l >= 0;
60  		assert globals == null;
61  		globals = new Object[(int) l];
62  		for (int i = 0; i < l; i++) {
63  			globals[i] = null;
64  		}
65  		// must accept multiple executions
66  		// expandFrameIfNecessary(num_globals);
67  	}
68  
69  	/*
70  	 * // this assumes globals = Object[0] upon initialization
71  	 * private void expandFrameIfNecessary(int num_globals) {
72  	 * if (num_globals == globals.length)
73  	 * // no need for expansion;
74  	 * // do nothing
75  	 * return;
76  	 * Object[] new_frame = new Object[num_globals];
77  	 * for (int i=0;i<globals.length;++i)
78  	 * new_frame[i] = globals[i];
79  	 * globals = new_frame;
80  	 * }
81  	 */
82  
83  	Object getVariable(long offset, boolean isGlobal) {
84  		assert globals != null;
85  		assert offset != AVM.NULL_OFFSET;
86  		if (isGlobal) {
87  			return globals[(int) offset];
88  		} else {
89  			return locals[(int) offset];
90  		}
91  	}
92  
93  	Object setVariable(long offset, Object val, boolean isGlobal) {
94  		assert globals != null;
95  		assert offset != AVM.NULL_OFFSET;
96  		if (isGlobal) {
97  			globals[(int) offset] = val;
98  			return val;
99  		} else {
100 			locals[(int) offset] = val;
101 			return val;
102 		}
103 	}
104 
105 	// for _DELETE_ARRAY_
106 	void removeVariable(long offset, boolean isGlobal) {
107 		assert globals != null;
108 		assert offset != AVM.NULL_OFFSET;
109 		if (isGlobal) {
110 			assert globals[(int) offset] == null || globals[(int) offset] instanceof AssocArray;
111 			globals[(int) offset] = null;
112 		} else {
113 			assert locals[(int) offset] == null || locals[(int) offset] instanceof AssocArray;
114 			locals[(int) offset] = null;
115 		}
116 	}
117 
118 	void setFilelistVariable(int offset, Object value) {
119 		assert globals != null;
120 		assert offset != AVM.NULL_OFFSET;
121 		globals[offset] = value;
122 	}
123 
124 	void pushFrame(long numFormalParams, int positionIdx) {
125 		localsStack.push(locals);
126 		locals = new Object[(int) numFormalParams];
127 		returnIndexes.push(positionIdx);
128 	}
129 
130 	/** returns the position index */
131 	int popFrame() {
132 		locals = localsStack.pop();
133 		return returnIndexes.pop();
134 	}
135 
136 	void popAllFrames() {
137 		for (int i = localsStack.size(); i > 0; i--) {
138 			locals = localsStack.pop();
139 			returnIndexes.pop();
140 		}
141 	}
142 
143 	private Object returnValue;
144 
145 	void setReturnValue(Object obj) {
146 		assert returnValue == null;
147 		returnValue = obj;
148 	}
149 
150 	Object getReturnValue() {
151 		Object retval;
152 		if (returnValue == null) {
153 			retval = BLANK;
154 		} else {
155 			retval = returnValue;
156 		}
157 		returnValue = null;
158 		return retval;
159 	}
160 }