Project

General

Profile

root / trunk / compiler / ooasCompiler / src / org / momut / ooas / codegen / prologsymbolic / OoaPrologSymbolicExpression.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.codegen.prologsymbolic;
29

    
30
import org.momut.ooas.ast.expressions.BinaryOperator;
31
import org.momut.ooas.ast.expressions.Expression;
32
import org.momut.ooas.ast.expressions.ExpressionKind;
33
import org.momut.ooas.ast.expressions.IdentifierExpression;
34
import org.momut.ooas.ast.expressions.TupleConstructor;
35
import org.momut.ooas.ast.expressions.UnaryOperator;
36
import org.momut.ooas.ast.expressions.ValueExpression;
37
import org.momut.ooas.ast.identifiers.EnumIdentifier;
38
import org.momut.ooas.ast.identifiers.IdentifierKind;
39
import org.momut.ooas.ast.types.EnumType;
40
import org.momut.ooas.ast.types.TypeKind;
41
import org.momut.ooas.ast.types.Type;
42
import org.momut.ooas.ast.types.ValuedEnumType;
43
import org.momut.ooas.codegen.OoasCodeEmitter;
44
import org.momut.ooas.codegen.prolog.OoaPrologExpression;
45
import org.momut.ooas.codegen.prolog.OoaPrologIdentifier;
46
import org.momut.ooas.codegen.prolog.OoaPrologType;
47
import org.momut.ooas.codegen.prolog.Scratchbook;
48
import org.momut.ooas.utils.exceptions.ArgumentException;
49
import org.momut.ooas.utils.exceptions.NotImplementedException;
50

    
51
public class OoaPrologSymbolicExpression extends OoaPrologExpression
52
{
53
        public static class Factory extends OoaPrologExpression.Factory
54
        {
55
                @Override
56
                public /*override*/ OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory, Scratchbook scratchbook, boolean lhs)
57
                { return new OoaPrologSymbolicExpression(idFactory, typeFactory, scratchbook, this, lhs); }
58
        }
59

    
60
        /*Also treats bools and enums as ints..*/
61
        @Override
62
        protected boolean isNumericBinary(Expression expression)
63
        {
64
                boolean result = false;
65
                if (expression instanceof BinaryOperator)
66
                {
67
                        final TypeKind leftKind = ((BinaryOperator)expression).left().type().kind();
68
                        final TypeKind rightKind = ((BinaryOperator)expression).right().type().kind();
69
                        result = (leftKind == TypeKind.IntType || leftKind == TypeKind.BoolType || leftKind == TypeKind.EnumeratedType) &&
70
                                        (rightKind == TypeKind.IntType || rightKind == TypeKind.BoolType || rightKind == TypeKind.EnumeratedType);
71
                }
72
                else if (expression instanceof UnaryOperator)
73
                {
74
                        final TypeKind childKind = ((UnaryOperator)expression).child().type().kind();
75
                        result = childKind == TypeKind.IntType || childKind == TypeKind.BoolType || childKind == TypeKind.EnumeratedType;
76
                }
77
                else throw new NotImplementedException();
78
                return result;
79
        }
80

    
81
        // we need to map all other things to Prolog constructs
82
        private String operatorString(Expression expression, Type resultingType)
83
        {
84
                switch (expression.kind())
85
                {
86
                case abs:    // T_ABS:
87
                case card:   // T_CARD:
88
                case dom:    // T_DOM:
89
                case range:  // T_RNG:
90
                case merge:  // T_MERGE:
91
                case elems:  // T_ELEMS:
92
                case head:   // T_HEAD:
93
                case tail:   // T_TAIL:
94
                case conc:   // T_CONC:
95
                case inds:   // T_INDS:
96
                case dinter: // T_DINTER:
97
                case dunion: // T_DUNION:
98
                case domresby:   // T_DOMRESBY:
99
                case domresto:   // T_DOMRESTO:
100
                case rngresby:   // T_RNGRESBY:
101
                case rngresto:   // T_RNGRESTO:
102
                case inter:  // T_INTER:
103
                case union:  // T_UNION:
104
                case diff:   // T_DIFF:
105
                case munion: // T_MUNION:
106
                case seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
107
                case subset:
108
                case elemin:
109
                case notelemin:
110
                case implies:    // T_IMPLIES:
111
                case biimplies:  // T_BIIMPLIES:
112
                case Primed:
113
                case len:    // T_LEN:
114
                        throw new NotImplementedException();
115

    
116
                case div:    // T_DIV:
117
                        return "/";
118
                case idiv:   // T_IDIV:
119
                        return "/";
120
                case mod:    // T_MOD:
121
                        return "mod";
122
                case prod:   // T_PROD:
123
                        return "*";
124
                case sum:    // T_SUM:
125
                        return "+";
126
                case minus:  // T_MINUS:
127
                        return "-";
128
                case less:
129
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? "<" : "#<";
130
                case lessequal:
131
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? "=<" : "#=<";
132
                case greater:
133
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? ">" : "#>";
134
                case greaterequal:
135
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? ">=" : "#>=";
136
                case equal:
137
                        return resultingType.kind() == TypeKind.QrType ? "==" : "#=";
138
                case notequal:
139
                        return resultingType.kind() == TypeKind.QrType || !isNumericBinary(expression) ? "\\=" : "#\\=";
140
                case and:    // T_AND:
141
                        throw new NotImplementedException(); // implemented in binaryoperator
142
                case or:     // T_OR:
143
                        throw new NotImplementedException(); // implemented in binaryoperator
144
                case not:
145
                        throw new NotImplementedException(); // implemented in binaryoperator
146

    
147
                case Cast:
148
                        return "";
149

    
150
                default:
151
                        return expression.kind().name(); //Enum.GetName(typeof(ExpressionKind), expression.kind);
152
                }
153
        }
154

    
155
        @SuppressWarnings("unchecked")
156
        @Override
157
        public <T> void visit(ValueExpression<T> valueExpression)
158
        {
159
                assert(m_tmpVars.size() == 0);
160
                final String tmpVar = NewTempVariable();
161
                m_emitter.Append(String.format("%s ", tmpVar));
162

    
163

    
164
                if (valueExpression.value() == null)
165
                        m_emitter.Append("= 'null'");
166
                else if (Boolean.class.isAssignableFrom(valueExpression.m_clazz))
167
                        m_emitter.Append(((ValueExpression<Boolean>)valueExpression).value() ? " = true" : " = false");
168
                else if (Character.class.isAssignableFrom(valueExpression.m_clazz))
169
                        m_emitter.Append(String.format("= '%s'", valueExpression.toString()));
170
                else if (Integer.class.isAssignableFrom(valueExpression.m_clazz))
171
                        m_emitter.Append(String.format("= %s", valueExpression.toString()));
172
                else
173
                        m_emitter.Append(String.format("= %s", valueExpression.value().toString()));
174

    
175
                m_emitter.AppendLine(",");
176
                assert(m_tmpVars.size() == 1);
177
        }
178

    
179
        @Override
180
        public void visit(IdentifierExpression identifierExpression)
181
        {
182
                if (identifierExpression.identifier().kind() == IdentifierKind.EnumIdentifier)
183
                {
184
                        final EnumIdentifier enumid = (EnumIdentifier)identifierExpression.identifier();
185
                        final EnumType enumType = (EnumType)enumid.type();
186
                        //m_emitter.Append(enumType.listOfEnumSymbols.IndexOf(enumid));
187
                        if (enumType instanceof ValuedEnumType)
188
                                m_emitter.AppendLine(String.format("%s = %s,", NewTempVariable(), enumid.Value()));
189
                        else
190
                                m_emitter.AppendLine(String.format("%s = %s,", NewTempVariable(), enumType.listOfEnumSymbols().indexOf(enumid)));
191
                }
192
                else if (identifierExpression.isSelf())
193
                {
194
                        m_emitter.AppendLine(String.format("%s = %s,", NewTempVariable(), GetIdentifierString(identifierExpression.identifier())));
195
                }
196
                else
197
                {
198
                        m_tmpVars.add(GetIdentifierString(identifierExpression.identifier()));
199
                }
200
        }
201

    
202
        @Override
203
        public void visit(UnaryOperator unaryOperator)
204
        {
205
                assert(m_tmpVars.size() == 0);
206
                VisitSub(unaryOperator.child(), unaryOperator);
207

    
208
                if (unaryOperator.kind() == ExpressionKind.Cast)
209
                        return;
210

    
211
                final String childresult = m_tmpVars.get(0); m_tmpVars.remove(0);
212
                assert(m_tmpVars.size() == 0);
213

    
214
                final String tmpresult = NewTempVariable();
215

    
216
                switch (unaryOperator.kind())
217
                {
218
                case head:
219
                        m_emitter.AppendLine(String.format("ulyssesListHead(%s,%s),", childresult, tmpresult));
220
                        break;
221

    
222
                case tail:
223
                        m_emitter.AppendLine(String.format("ulyssesListTail(%s,%s),", childresult, tmpresult));
224
                        break;
225

    
226
                case len:    // T_LEN:
227
                        m_emitter.AppendLine(String.format("ulyssesListLength(%s,%s),", childresult, tmpresult));
228
                        break;
229

    
230
                case not:
231
                        m_emitter.Append(String.format(" %s = ( #\\", tmpresult));
232
                        m_emitter.Append("(");
233
                        m_emitter.Append(childresult);
234
                        m_emitter.AppendLine(")),");
235
                        break;
236

    
237
                case Cast:
238
                        // todo
239
                        break;
240

    
241
                default:
242
                        //do not use #= for assignments in the symbolic backend
243
                        m_emitter.Append(String.format(" %s = (%s", tmpresult, operatorString(unaryOperator, unaryOperator.child().type())));
244
                        m_emitter.Append("(");
245
                        m_emitter.Append(childresult);
246
                        m_emitter.AppendLine(")),");
247
                        break;
248
                }
249
                assert(m_tmpVars.size() == 1);
250
        }
251

    
252
        @Override
253
        public void visit(BinaryOperator binaryOperator)
254
        {
255
                // eval stack must be empty
256
                assert(m_tmpVars.size() == 0);
257

    
258
                final OoasCodeEmitter origEmitter = m_emitter;
259
                final OoasCodeEmitter leftcode = new OoasCodeEmitter();
260
                final OoasCodeEmitter rightcode = new OoasCodeEmitter();
261

    
262

    
263
                // traverse left
264
                m_emitter = leftcode;
265
                VisitSub(binaryOperator.left(), binaryOperator);
266
                final String leftresult = m_tmpVars.get(0); m_tmpVars.remove(0);
267
                assert(m_tmpVars.size() == 0);
268

    
269
                // traverse right
270
                m_emitter = rightcode;
271
                VisitSub(binaryOperator.right(), binaryOperator);
272
                final String rightresult = m_tmpVars.get(0); m_tmpVars.remove(0);
273
                // eval stack must be empty
274
                assert(m_tmpVars.size() == 0);
275

    
276
                // restore original emitter and get tmp.var
277
                m_emitter = origEmitter;
278
                final String tmpVar = NewTempVariable();
279

    
280
                switch (binaryOperator.kind())
281
                {
282
                case elemin:
283
                        m_emitter.Append(leftcode.toString());
284
                        m_emitter.Append(rightcode.toString());
285
                        m_emitter.AppendLine(String.format(" %s = member(%s,%s),",
286
                                        tmpVar, leftresult, rightresult));
287
                        break;
288
                case and:    // T_AND:
289
                        m_emitter.Append(leftcode.toString());
290
                        m_emitter.Append(rightcode.toString());
291
                        m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
292
                                        tmpVar, leftresult, "#/\\", rightresult));
293
                        break;
294
                case or:     // T_OR:
295
                        m_emitter.Append(leftcode.toString());
296
                        m_emitter.Append(rightcode.toString());
297
                        m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
298
                                        tmpVar, leftresult, "#\\/", rightresult));
299
                        break;
300

    
301
                case implies:
302
                        m_emitter.Append(leftcode.toString());
303
                        m_emitter.AppendLine(String.format(" %s = (%s -> (%s%s); true), ", // {0} = (({1} -> ({2}{3}); true))
304
                                        tmpVar, leftresult, rightcode.toString(), rightresult));
305
                        break;
306

    
307
                case equal:
308
                        m_emitter.Append(leftcode.toString());
309
                        m_emitter.Append(rightcode.toString());
310
                        /*check if we have tupleconstructors as matchers*/
311
                        TupleConstructor matcher = null;
312
                        String aTuple = null;
313
                        if (binaryOperator.left().kind() == ExpressionKind.TupleConstr &&
314
                                        ((TupleConstructor)binaryOperator.left()).isMatcher())
315
                        {
316
                                matcher = (TupleConstructor)binaryOperator.left();
317
                                aTuple = rightresult;
318
                        }
319
                        else if (binaryOperator.right().kind() == ExpressionKind.TupleConstr &&
320
                                        ((TupleConstructor)binaryOperator.right()).isMatcher())
321
                        {
322
                                matcher = (TupleConstructor)binaryOperator.right();
323
                                aTuple = leftresult;
324
                        }
325

    
326
                        if (matcher == null)
327
                                m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
328
                                tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left().type()), rightresult));
329
                        else
330
                        {
331
                                m_emitter.Append(String.format("%s = unify(%s = [", tmpVar, aTuple));
332
                                int cntr = 0;
333
                                for (final Expression x: matcher.values())
334
                                {
335
                                        if (cntr != 0)
336
                                                m_emitter.Append(", ");
337
                                        else
338
                                                cntr++;
339

    
340
                                        if (x.kind() != ExpressionKind.Identifier)
341
                                                throw new ArgumentException();
342

    
343
                                        final IdentifierExpression ident = (IdentifierExpression)x;
344
                                        final OoaPrologIdentifier avisitor = createIdentifierVisitor();
345
                                        ident.Accept(avisitor);
346
                                        m_emitter.Append(avisitor.toString());
347
                                }
348
                                m_emitter.AppendLine("]),");
349
                        }
350
                        break;
351

    
352

    
353

    
354
                case conc:
355
                        m_emitter.Append(leftcode.toString());
356
                        m_emitter.Append(rightcode.toString());
357
                        m_emitter.AppendLine(String.format("ulyssesListConc(%s,%s,%s),", leftresult, rightresult, tmpVar));
358
                        break;
359

    
360
                default:
361
                        m_emitter.Append(leftcode.toString());
362
                        m_emitter.Append(rightcode.toString());
363
                        if (binaryOperator.left().type().kind() == TypeKind.QrType)
364
                                m_emitter.Append("qEval");
365

    
366
                        //do not use #= for assignments in the symbolic backend
367
                        m_emitter.AppendLine(String.format(" %s = (%s %s %s), ",
368
                                        tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left().type()), rightresult));
369
                        break;
370
                }
371
                assert(m_tmpVars.size() == 1);
372
        }
373

    
374

    
375

    
376
        protected OoaPrologSymbolicExpression(
377
                        OoaPrologIdentifier.Factory idFactory,
378
                        OoaPrologType.Factory typeFactory,
379
                        Scratchbook scratchbook,
380
                        OoaPrologExpression.Factory expressionFactory,
381
                        boolean lhs)
382
        {
383
                super (idFactory, typeFactory, scratchbook, expressionFactory,  lhs);
384
        }
385

    
386
}