root / trunk / compiler / ooasCompiler / src / org / momut / ooas / ast / expressions / Expression.java @ 9
1 |
/**
|
---|---|
2 |
*
|
3 |
* OOAS Compiler
|
4 |
*
|
5 |
* Copyright 2015, AIT Austrian Institute of Technology.
|
6 |
* This code is based on the C# Version of the OOAS Compiler, which is
|
7 |
* copyright 2015 by the Institute of Software Technology, Graz University
|
8 |
* of Technology with portions copyright by the AIT Austrian Institute of
|
9 |
* Technology. All rights reserved.
|
10 |
*
|
11 |
* SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
|
12 |
*
|
13 |
* If you modify the file please update the list of contributors below to in-
|
14 |
* clude your name. Please also stick to the coding convention of using TABs
|
15 |
* to do the basic (block-level) indentation and spaces for anything after
|
16 |
* that. (Enable the display of special chars and it should be pretty obvious
|
17 |
* what this means.) Also, remove all trailing whitespace.
|
18 |
*
|
19 |
* Contributors:
|
20 |
* Willibald Krenn (AIT)
|
21 |
* Stephan Zimmerer (AIT)
|
22 |
* Markus Demetz (AIT)
|
23 |
* Christoph Czurda (AIT)
|
24 |
*
|
25 |
*/
|
26 |
|
27 |
|
28 |
package org.momut.ooas.ast.expressions; |
29 |
|
30 |
import java.util.ArrayList; |
31 |
import java.util.List; |
32 |
|
33 |
import org.momut.ooas.ast.AstNode; |
34 |
import org.momut.ooas.ast.AstNodeTypeEnum; |
35 |
import org.momut.ooas.ast.IAst; |
36 |
import org.momut.ooas.ast.IAstVisitor; |
37 |
import org.momut.ooas.ast.identifiers.ExpressionVariableIdentifier; |
38 |
import org.momut.ooas.ast.identifiers.FunctionIdentifier; |
39 |
import org.momut.ooas.ast.identifiers.Identifier; |
40 |
import org.momut.ooas.ast.types.FloatType; |
41 |
import org.momut.ooas.ast.types.IntType; |
42 |
import org.momut.ooas.ast.types.TypeKind; |
43 |
import org.momut.ooas.ast.types.Type; |
44 |
import org.momut.ooas.ast.types.ValuedEnumType; |
45 |
import org.momut.ooas.math.AbstractOperations; |
46 |
import org.momut.ooas.math.AbstractRange; |
47 |
import org.momut.ooas.math.DoubleRange; |
48 |
import org.momut.ooas.math.IntegerRange; |
49 |
import org.momut.ooas.math.SaturatedDoubleOperations; |
50 |
import org.momut.ooas.math.SaturatedIntegerOperations; |
51 |
import org.momut.ooas.parser.SymbolTable; |
52 |
import org.momut.ooas.utils.exceptions.ArgumentException; |
53 |
import org.momut.ooas.utils.exceptions.NotImplementedException; |
54 |
import org.momut.ooas.visitors.OoaPrintVisitor; |
55 |
|
56 |
///////////////////////////////////////////////
|
57 |
/// Expressions
|
58 |
///
|
59 |
/// Note: Since we allow expression of the form
|
60 |
/// myTuple(a,b) = hd x, where a and b are newly
|
61 |
/// introduced placeholders, the expression knows
|
62 |
/// about local variables.
|
63 |
/// Scoping: Consider following expression
|
64 |
/// 3 > a and myTuple(b,d) = hd e and b < 5
|
65 |
/// which gives
|
66 |
/// and
|
67 |
/// / \
|
68 |
/// / and
|
69 |
/// / / \
|
70 |
/// > = <
|
71 |
/// / \ / \ / \
|
72 |
/// 3 a (b,d) e b 5
|
73 |
/// the scope of b and d is defined by the binary
|
74 |
/// expression that has the leaf within its left child
|
75 |
/// (== the second 'and').
|
76 |
/// Local variables may only be introduced in constructors
|
77 |
/// of sets, lists, and tuples. Therefore the type is
|
78 |
/// known.
|
79 |
|
80 |
|
81 |
public abstract class Expression extends AstNode implements IAst |
82 |
{ |
83 |
protected ExpressionKind m_kind;
|
84 |
protected Type m_type; |
85 |
protected int m_line; |
86 |
protected int m_pos; |
87 |
protected SymbolTable m_freeVariables;
|
88 |
protected ArrayList<FunctionIdentifier> m_callTargets; |
89 |
|
90 |
public ExpressionKind kind() { return m_kind; } |
91 |
public Type type() { return m_type; } |
92 |
public int line() { return m_line; } |
93 |
public int pos() { return m_pos; } |
94 |
public SymbolTable freeVariables() { return m_freeVariables; } |
95 |
public List<FunctionIdentifier> callTargets() { return m_callTargets; } |
96 |
|
97 |
public Expression(ExpressionKind aKind, int line, int pos) |
98 |
{ |
99 |
m_kind = aKind; |
100 |
m_line = line; |
101 |
m_pos = pos; |
102 |
m_callTargets = new ArrayList<FunctionIdentifier>(); |
103 |
} |
104 |
|
105 |
public Expression(Expression toCopy) |
106 |
{ |
107 |
m_kind = toCopy.m_kind; |
108 |
m_line = toCopy.m_line; |
109 |
m_pos = toCopy.m_pos; |
110 |
m_callTargets = new ArrayList<FunctionIdentifier>(toCopy.callTargets()); |
111 |
m_type = toCopy.m_type; |
112 |
m_freeVariables = new SymbolTable(toCopy.m_freeVariables);
|
113 |
} |
114 |
|
115 |
public /*virtual*/ Expression Clone() |
116 |
{ |
117 |
throw new NotImplementedException(); |
118 |
} |
119 |
|
120 |
public void SetType(Type aType) |
121 |
{ |
122 |
if (aType == null) |
123 |
throw new ArgumentException(); |
124 |
m_type = aType; |
125 |
} |
126 |
|
127 |
public void SetFreeVariables(SymbolTable aSymTab) |
128 |
{ |
129 |
m_freeVariables = aSymTab; |
130 |
} |
131 |
|
132 |
public ArrayList<ExpressionVariableIdentifier> GetUninitializedFreeVariables() |
133 |
{ |
134 |
final ArrayList<ExpressionVariableIdentifier> result = new ArrayList<ExpressionVariableIdentifier>(); |
135 |
if (m_freeVariables != null) |
136 |
for(final Identifier v: m_freeVariables.symbolList()) |
137 |
{ |
138 |
final ExpressionVariableIdentifier id = (ExpressionVariableIdentifier)v;
|
139 |
if (id.initialized() == false) |
140 |
result.add(id); |
141 |
} |
142 |
return result;
|
143 |
} |
144 |
|
145 |
|
146 |
@Override
|
147 |
public AstNodeTypeEnum nodeType() { return AstNodeTypeEnum.expression; } |
148 |
|
149 |
@Override
|
150 |
public /*virtual*/ void Accept(IAstVisitor visitor) |
151 |
{ |
152 |
throw new NotImplementedException(); |
153 |
} |
154 |
|
155 |
|
156 |
/// <summary>
|
157 |
/// Calculates the arithmetic cover, i.e. the return type of the operation, given two types.
|
158 |
/// This is different from the cover-method defined at the type level.
|
159 |
/// Note: We do saturating operations on the type boundaries.
|
160 |
/// </summary>
|
161 |
public static Type ArithmeticCover(Type type1, Type type2, ExpressionKind op) |
162 |
{ |
163 |
if (!type1.IsNumeric() || (type2 != null && !type2.IsNumeric())) |
164 |
throw new ArgumentException(); |
165 |
|
166 |
if (type1 instanceof ValuedEnumType) |
167 |
type1 = ((ValuedEnumType)type1).getIntType(); |
168 |
if (type2 instanceof ValuedEnumType) |
169 |
type2 = ((ValuedEnumType)type2).getIntType(); |
170 |
|
171 |
AbstractRange result; |
172 |
AbstractRange rangeType1 = null;
|
173 |
AbstractRange rangeType2 = null;
|
174 |
AbstractOperations operations; |
175 |
final boolean resultIsFloat = type1.kind() == TypeKind.FloatType |
176 |
|| op == ExpressionKind.div |
177 |
|| (type2 != null && type2.kind() == TypeKind.FloatType);
|
178 |
if (resultIsFloat)
|
179 |
{ |
180 |
rangeType1 = new DoubleRange(
|
181 |
type1.kind() == TypeKind.IntType ? ((IntType)type1).rangeHigh() : ((FloatType)type1).high(), |
182 |
type1.kind() == TypeKind.IntType ? ((IntType)type1).rangeLow() : ((FloatType)type1).low()); |
183 |
if (type2 != null) |
184 |
{ |
185 |
rangeType2 = new DoubleRange(
|
186 |
type2.kind() == TypeKind.IntType ? ((IntType)type2).rangeHigh() : ((FloatType)type2).high(), |
187 |
type2.kind() == TypeKind.IntType ? ((IntType)type2).rangeLow() : ((FloatType)type2).low()); |
188 |
} |
189 |
operations = new SaturatedDoubleOperations();
|
190 |
} |
191 |
else
|
192 |
{ |
193 |
rangeType1 = new IntegerRange(((IntType)type1).rangeHigh(), ((IntType)type1).rangeLow());
|
194 |
rangeType2 = new IntegerRange(((IntType)type2).rangeHigh(), ((IntType)type2).rangeLow());
|
195 |
operations = new SaturatedIntegerOperations();
|
196 |
} |
197 |
|
198 |
switch (op)
|
199 |
{ |
200 |
case pow:
|
201 |
case prod:
|
202 |
case unminus:
|
203 |
case unplus:
|
204 |
case minus:
|
205 |
case sum:
|
206 |
case div:
|
207 |
result = operations.GenericArithmeticCover(rangeType1, rangeType2, op); |
208 |
break;
|
209 |
|
210 |
case idiv:
|
211 |
if (resultIsFloat)
|
212 |
throw new ArgumentException(); |
213 |
assert(type2 != null); |
214 |
result = operations.GenericArithmeticCover(rangeType1, rangeType2, op); |
215 |
break;
|
216 |
|
217 |
case mod:
|
218 |
if (resultIsFloat)
|
219 |
throw new ArgumentException(); |
220 |
assert(type2 != null); |
221 |
// FIXME: see http://mathforum.org/library/drmath/view/52343.html; LLVM only supports rem!
|
222 |
final boolean isSigned = ((IntegerRange)rangeType2).min < 0 || ((IntegerRange)rangeType1).min < 0; |
223 |
result = new IntegerRange(((IntegerRange)rangeType2).max - 1, isSigned ? -((IntegerRange)rangeType2).max - 1 : 0); |
224 |
break;
|
225 |
|
226 |
default:
|
227 |
throw new NotImplementedException(); |
228 |
} |
229 |
|
230 |
if (resultIsFloat)
|
231 |
return new FloatType( |
232 |
((DoubleRange)result).min, |
233 |
((DoubleRange)result).max, |
234 |
FloatType.defaultPrecision(), |
235 |
null);
|
236 |
else
|
237 |
// this is crude, but see whether it works..
|
238 |
return new IntType( |
239 |
((IntegerRange)result).min, |
240 |
((IntegerRange)result).max, |
241 |
null);
|
242 |
} |
243 |
|
244 |
|
245 |
@Override
|
246 |
public String toString() |
247 |
{ |
248 |
return toString(new OoaPrintVisitor(null)); |
249 |
} |
250 |
|
251 |
public String toString(OoaPrintVisitor aFormatter) { |
252 |
this.Accept(aFormatter);
|
253 |
return aFormatter.toString();
|
254 |
} |
255 |
} |
256 |
|