1/*
2 * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25using System;
26using System.Collections.Generic;
27
28/*
29 * Each value is represented with a TValue structure. Integers use the 'x'
30 * field, and 'ptr' is null; for pointers, the 'ptr' field is used, and the
31 * 'x' is then an offset in the object represented by 'ptr'.
32 */
33
34struct TValue {
35
36	internal int x;
37	internal TPointerBase ptr;
38
39	internal TValue(int x)
40	{
41		this.x = x;
42		this.ptr = null;
43	}
44
45	internal TValue(uint x)
46	{
47		this.x = (int)x;
48		this.ptr = null;
49	}
50
51	internal TValue(bool b)
52	{
53		this.x = b ? -1 : 0;
54		this.ptr = null;
55	}
56
57	internal TValue(int x, TPointerBase ptr)
58	{
59		this.x = x;
60		this.ptr = ptr;
61	}
62
63	/*
64	 * Convert this value to a boolean; integer 0 and null pointer are
65	 * 'false', other values are 'true'.
66	 */
67	internal bool Bool {
68		get {
69			if (ptr == null) {
70				return x != 0;
71			} else {
72				return ptr.ToBool(this);
73			}
74		}
75	}
76
77	/*
78	 * Get this value as an integer. Pointers cannot be converted to
79	 * integers.
80	 */
81	internal int Int {
82		get {
83			if (ptr == null) {
84				return x;
85			}
86			throw new Exception("not an integer: " + ToString());
87		}
88	}
89
90	/*
91	 * Get this value as an unsigned integer. This is the integer
92	 * value, reduced modulo 2^32 in the 0..2^32-1 range.
93	 */
94	internal uint UInt {
95		get {
96			return (uint)Int;
97		}
98	}
99
100	/*
101	 * String format of integers uses decimal representation. For
102	 * pointers, this depends on the pointed-to value.
103	 */
104	public override string ToString()
105	{
106		if (ptr == null) {
107			return String.Format("{0}", x);
108		} else {
109			return ptr.ToString(this);
110		}
111	}
112
113	/*
114	 * If this value is an XT, then execute it. Otherwise, an exception
115	 * is thrown.
116	 */
117	internal void Execute(T0Comp ctx, CPU cpu)
118	{
119		ToXT().Execute(ctx, cpu);
120	}
121
122	/*
123	 * Convert this value to an XT. On failure, an exception is thrown.
124	 */
125	internal TPointerXT ToXT()
126	{
127		TPointerXT xt = ptr as TPointerXT;
128		if (xt == null) {
129			throw new Exception(
130				"value is not an xt: " + ToString());
131		}
132		return xt;
133	}
134
135	/*
136	 * Compare this value to another.
137	 */
138	internal bool Equals(TValue v)
139	{
140		if (x != v.x) {
141			return false;
142		}
143		if (ptr == v.ptr) {
144			return true;
145		}
146		if (ptr == null || v.ptr == null) {
147			return false;
148		}
149		return ptr.Equals(v.ptr);
150	}
151
152	public static implicit operator TValue(bool val)
153	{
154		return new TValue(val);
155	}
156
157	public static implicit operator TValue(sbyte val)
158	{
159		return new TValue((int)val);
160	}
161
162	public static implicit operator TValue(byte val)
163	{
164		return new TValue((int)val);
165	}
166
167	public static implicit operator TValue(short val)
168	{
169		return new TValue((int)val);
170	}
171
172	public static implicit operator TValue(ushort val)
173	{
174		return new TValue((int)val);
175	}
176
177	public static implicit operator TValue(char val)
178	{
179		return new TValue((int)val);
180	}
181
182	public static implicit operator TValue(int val)
183	{
184		return new TValue((int)val);
185	}
186
187	public static implicit operator TValue(uint val)
188	{
189		return new TValue((int)val);
190	}
191
192	public static implicit operator bool(TValue v)
193	{
194		return v.Bool;
195	}
196
197	public static implicit operator sbyte(TValue v)
198	{
199		return (sbyte)v.Int;
200	}
201
202	public static implicit operator byte(TValue v)
203	{
204		return (byte)v.Int;
205	}
206
207	public static implicit operator short(TValue v)
208	{
209		return (short)v.Int;
210	}
211
212	public static implicit operator ushort(TValue v)
213	{
214		return (ushort)v.Int;
215	}
216
217	public static implicit operator char(TValue v)
218	{
219		return (char)v.Int;
220	}
221
222	public static implicit operator int(TValue v)
223	{
224		return (int)v.Int;
225	}
226
227	public static implicit operator uint(TValue v)
228	{
229		return (uint)v.Int;
230	}
231}
232