Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / ast / expressions / Expression.java @ 7

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.UlyssesType;
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 UlyssesType 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 UlyssesType 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(UlyssesType 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 UlyssesType ArithmeticCover(UlyssesType type1, UlyssesType 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