Project

General

Profile

root / branches / compiler / cSharp / ooasCompiler / src / codegen / PrologSymbolic / ooaPrologSymbolicExpression.cs @ 3

1
/**
2
  *
3
  *                      OOAS Compiler (Deprecated)
4
  *
5
  * Copyright 2015, Institute for Software Technology, Graz University of
6
  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
7
  * of Technology. All rights reserved.
8
  *
9
  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
10
  *
11
  * Please notice that this version of the OOAS compiler is considered de-
12
  * precated. Only the Java version is maintained.
13
  *
14
  * Contributors:
15
  *               Willibald Krenn (TU Graz/AIT)
16
  *               Stefan Tiran (TU Graz/AIT)
17
  */
18

    
19
using System;
20
using System.Collections.Generic;
21
using System.Text;
22
using TUG.Mogentes.Codegen;
23
using TUG.Mogentes.Codegen.Prolog;
24

    
25
namespace TUG.Mogentes.Codegen.PrologSymbolic
26
{
27
    public class OoaPrologSymbolicExpression : OoaPrologExpression
28
    {
29
        new public class Factory : OoaPrologExpression.Factory
30
        {
31
            public override OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory, bool lhs)
32
            { return new OoaPrologSymbolicExpression(idFactory, typeFactory, this, lhs); }
33
        }
34
        
35
        /*Also treats bools and enums as ints..*/
36
        new protected bool isNumericBinary(Expression expression)
37
        {
38
            bool result = false;
39
            if (expression is BinaryOperator)
40
            {
41
                TypeKind leftKind = ((BinaryOperator)expression).left.type.kind;
42
                TypeKind rightKind = ((BinaryOperator)expression).right.type.kind;
43
                result = (leftKind == TypeKind.IntType || leftKind == TypeKind.BoolType || leftKind == TypeKind.EnumeratedType) &&
44
                     (rightKind == TypeKind.IntType || rightKind == TypeKind.BoolType || rightKind == TypeKind.EnumeratedType);
45
            }
46
            else if (expression is UnaryOperator)
47
            {
48
                TypeKind childKind = ((UnaryOperator)expression).child.type.kind;
49
                result = childKind == TypeKind.IntType || childKind == TypeKind.BoolType || childKind == TypeKind.EnumeratedType;
50
            }
51
            else throw new NotImplementedException();
52
            return result;
53
        }
54

    
55
        // we need to map all other things to Prolog constructs
56
        private string operatorString(Expression expression, UlyssesType resultingType)
57
        {
58
            switch (expression.kind)
59
            {
60
                case ExpressionKind.abs:    // T_ABS:
61
                case ExpressionKind.card:   // T_CARD:
62
                case ExpressionKind.dom:    // T_DOM:
63
                case ExpressionKind.range:  // T_RNG:
64
                case ExpressionKind.merge:  // T_MERGE:
65
                case ExpressionKind.elems:  // T_ELEMS:
66
                case ExpressionKind.head:   // T_HEAD:
67
                case ExpressionKind.tail:   // T_TAIL:
68
                case ExpressionKind.conc:   // T_CONC:
69
                case ExpressionKind.inds:   // T_INDS:
70
                case ExpressionKind.dinter: // T_DINTER:
71
                case ExpressionKind.dunion: // T_DUNION:
72
                case ExpressionKind.domresby:   // T_DOMRESBY:
73
                case ExpressionKind.domresto:   // T_DOMRESTO:
74
                case ExpressionKind.rngresby:   // T_RNGRESBY:
75
                case ExpressionKind.rngresto:   // T_RNGRESTO:
76
                case ExpressionKind.inter:  // T_INTER:
77
                case ExpressionKind.union:  // T_UNION:
78
                case ExpressionKind.diff:   // T_DIFF:
79
                case ExpressionKind.munion: // T_MUNION:
80
                case ExpressionKind.seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
81
                case ExpressionKind.subset:
82
                case ExpressionKind.elemin:
83
                case ExpressionKind.notelemin:
84
                case ExpressionKind.implies:    // T_IMPLIES:
85
                case ExpressionKind.biimplies:  // T_BIIMPLIES:
86
                case ExpressionKind.Primed:
87
                case ExpressionKind.len:    // T_LEN:
88
                    throw new NotImplementedException();
89

    
90
                case ExpressionKind.div:    // T_DIV:
91
                    return "/";
92
                case ExpressionKind.idiv:   // T_IDIV:
93
                    return "/";
94
                case ExpressionKind.mod:    // T_MOD:
95
                    return "mod";
96
                case ExpressionKind.prod:   // T_PROD:
97
                    return "*";
98
                case ExpressionKind.sum:    // T_SUM:
99
                    return "+";
100
                case ExpressionKind.minus:  // T_MINUS:
101
                    return "-";
102
                case ExpressionKind.less:
103
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "<" : "#<";
104
                case ExpressionKind.lessequal:
105
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "=<" : "#=<";
106
                case ExpressionKind.greater:
107
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">" : "#>";
108
                case ExpressionKind.greaterequal:
109
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">=" : "#>=";
110
                case ExpressionKind.equal:
111
                    return resultingType.kind == TypeKind.QrType ? "==" : "#=";
112
                case ExpressionKind.notequal:
113
                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "\\=" : "#\\=";
114
                case ExpressionKind.and:    // T_AND:
115
                    throw new NotImplementedException(); // implemented in binaryoperator
116
                case ExpressionKind.or:     // T_OR:
117
                    throw new NotImplementedException(); // implemented in binaryoperator
118
                case ExpressionKind.not:
119
                    throw new NotImplementedException(); // implemented in binaryoperator
120

    
121
                case ExpressionKind.Cast:
122
                    return String.Empty;
123

    
124
                default:
125
                    return Enum.GetName(typeof(ExpressionKind), expression.kind);
126
            }
127
        }
128

    
129
        public override void visit<T>(ValueExpression<T> valueExpression)
130
        {
131
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
132
            string tmpVar = NewTempVariable();
133
            m_emitter.Append(String.Format("{0} ", tmpVar));
134

    
135

    
136
            if (valueExpression.value == null)
137
                m_emitter.Append("= 'null'");
138
            else if (valueExpression is ValueExpression<bool>)
139
                m_emitter.Append((valueExpression as ValueExpression<bool>).value ? " = true" : " = false");
140
            else if (valueExpression is ValueExpression<char>)
141
                m_emitter.Append(String.Format("= '{0}'", valueExpression.ToString()));
142
            else if (valueExpression is ValueExpression<int>)
143
                m_emitter.Append(String.Format("= {0}", valueExpression.ToString()));
144
            else
145
                m_emitter.Append(String.Format("= {0}", valueExpression.value.ToString()));
146

    
147
            m_emitter.AppendLine(",");
148
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
149
        }
150

    
151
        public override void visit(IdentifierExpression identifierExpression)
152
        {
153
            if (identifierExpression.identifier.kind == IdentifierKind.LandmarkIdentifier)
154
            {
155
                LandmarkIdentifier lmid = (LandmarkIdentifier)identifierExpression.identifier;
156
                OoaPrologIdentifier pid = createIdentifierVisitor();
157
                lmid.Accept(pid);
158
                //m_emitter.Append(pid.ToString());
159
                m_tmpVars.Add(pid.ToString());
160
                return;
161
            }
162
            else if (identifierExpression.identifier.kind == IdentifierKind.EnumIdentifier)
163
            {
164
                EnumIdentifier enumid = (EnumIdentifier)identifierExpression.identifier;
165
                EnumType enumType = (EnumType)enumid.type;
166
                //m_emitter.Append(enumType.listOfEnumSymbols.IndexOf(enumid));
167
                if (enumType is ValuedEnumType)
168
                    m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), enumid.Value));
169
                else
170
                    m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), enumType.listOfEnumSymbols.IndexOf(enumid).ToString()));
171
            }
172
            else if (identifierExpression.isSelf)
173
            {
174
                m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
175
            }
176
            /*else if (identifierExpression.identifier.kind == IdentifierKind.AttributeIdentifier)
177
            {
178
                m_emitter.AppendLine(String.Format("getVal({1},{0},_),", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
179
            }*/
180
            else
181
            {
182
                //m_emitter.Append(GetIdentifierString(identifierExpression.identifier));
183
                m_tmpVars.Add(GetIdentifierString(identifierExpression.identifier));
184
            }
185
        }
186

    
187
        public override void visit(UnaryOperator unaryOperator)
188
        {
189
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
190
            VisitSub(unaryOperator.child, unaryOperator);
191

    
192
            if (unaryOperator.kind == ExpressionKind.Cast)
193
                return;
194

    
195
            string childresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
196
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
197

    
198
            string tmpresult = NewTempVariable();
199

    
200
            switch (unaryOperator.kind)
201
            {
202
                case ExpressionKind.head:
203
                    m_emitter.AppendLine(String.Format("ulyssesListHead({1},{0}),", tmpresult, childresult));
204
                    break;
205

    
206
                case ExpressionKind.tail:
207
                    m_emitter.AppendLine(String.Format("ulyssesListTail({1},{0}),", tmpresult, childresult));
208
                    break;
209

    
210
                case ExpressionKind.len:    // T_LEN:
211
                    m_emitter.AppendLine(String.Format("ulyssesListLength({1},{0}),", tmpresult, childresult));
212
                    break;
213

    
214
                case ExpressionKind.not:
215
//                    if (unaryOperator.type.kind == TypeKind.IntType)
216
//                        m_emitter.Append(String.Format(" {0} #= call(\\+", tmpresult));
217
//                    else
218
                        m_emitter.Append(String.Format(" {0} = ( #\\", tmpresult));
219
                    m_emitter.Append("(");
220
                    m_emitter.Append(childresult);
221
                    m_emitter.AppendLine(")),");
222
                    break;
223

    
224
                case ExpressionKind.Cast:
225
                    // todo
226
                    break;
227

    
228
                default:
229
// do not use #= for assignments in the symbolic backend
230
//                    if (unaryOperator.type.kind == TypeKind.IntType)
231
//                        m_emitter.Append(String.Format(" {0} #= ({1}", tmpresult, operatorString(unaryOperator, unaryOperator.child.type)));
232
//                    else
233
                        m_emitter.Append(String.Format(" {0} = ({1}", tmpresult, operatorString(unaryOperator, unaryOperator.child.type)));
234
                    m_emitter.Append("(");
235
                    m_emitter.Append(childresult);
236
                    m_emitter.AppendLine(")),");
237
                    break;
238
            }
239
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
240
        }
241

    
242
        public override void visit(BinaryOperator binaryOperator)
243
        {
244
            // eval stack must be empty
245
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
246

    
247
            OoaCodeEmitter origEmitter = m_emitter;
248
            OoaCodeEmitter leftcode = new OoaCodeEmitter();
249
            OoaCodeEmitter rightcode = new OoaCodeEmitter();
250

    
251

    
252
            // traverse left
253
            m_emitter = leftcode;
254
            VisitSub(binaryOperator.left, binaryOperator);
255
            string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
256
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
257

    
258
            // traverse right
259
            m_emitter = rightcode;
260
            VisitSub(binaryOperator.right, binaryOperator);
261
            string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
262
            // eval stack must be empty
263
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
264

    
265
            // restore original emitter and get tmp.var
266
            m_emitter = origEmitter;
267
            string tmpVar = NewTempVariable();
268

    
269
            switch (binaryOperator.kind)
270
            {
271
                case ExpressionKind.elemin:
272
                    m_emitter.Append(leftcode.ToString());
273
                    m_emitter.Append(rightcode.ToString());
274
                    m_emitter.AppendLine(String.Format(" {0} = member({1},{2}),",
275
                        tmpVar, leftresult, rightresult));
276
                    break;
277
                case ExpressionKind.and:    // T_AND:
278
                    m_emitter.Append(leftcode.ToString());
279
                    m_emitter.Append(rightcode.ToString());
280
                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
281
                        tmpVar, leftresult, "#/\\", rightresult));
282
                    break;
283
                case ExpressionKind.or:     // T_OR:
284
                    m_emitter.Append(leftcode.ToString());
285
                    m_emitter.Append(rightcode.ToString());
286
                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
287
                        tmpVar, leftresult, "#\\/", rightresult));
288
                    break;
289

    
290
                case ExpressionKind.implies:
291
                    m_emitter.Append(leftcode.ToString());
292
                    m_emitter.AppendLine(String.Format(" {0} = ({1} -> ({2}{3}); true), ", // {0} = (({1} -> ({2}{3}); true))
293
                        tmpVar, leftresult, rightcode.ToString(), rightresult));
294
                    break;
295

    
296
                case ExpressionKind.equal:
297
                    m_emitter.Append(leftcode.ToString());
298
                    m_emitter.Append(rightcode.ToString());
299
                    /*check if we have tupleconstructors as matchers*/
300
                    TupleConstructor matcher = null;
301
                    string aTuple = null;
302
                    if (binaryOperator.left.kind == ExpressionKind.TupleConstr &&
303
                        ((TupleConstructor)binaryOperator.left).isMatcher)
304
                    {
305
                        matcher = (TupleConstructor)binaryOperator.left;
306
                        aTuple = rightresult;
307
                    }
308
                    else if (binaryOperator.right.kind == ExpressionKind.TupleConstr &&
309
                        ((TupleConstructor)binaryOperator.right).isMatcher)
310
                    {
311
                        matcher = (TupleConstructor)binaryOperator.right;
312
                        aTuple = leftresult;
313
                    }
314

    
315
                    if (matcher == null)
316
                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
317
                            tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left.type), rightresult));
318
                    else
319
                    {
320
                        m_emitter.Append(String.Format("{0} = unify({1} = [", tmpVar, aTuple));
321
                        int cntr = 0;
322
                        foreach (var x in matcher.values)
323
                        {
324
                            if (cntr != 0)
325
                                m_emitter.Append(", ");
326
                            else
327
                                cntr++;
328

    
329
                            if (x.kind != ExpressionKind.Identifier)
330
                                throw new ArgumentException();
331

    
332
                            IdentifierExpression ident = (IdentifierExpression)x;
333
                            OoaPrologIdentifier avisitor = createIdentifierVisitor();
334
                            ident.Accept(avisitor);
335
                            m_emitter.Append(avisitor.ToString());
336
                        }
337
                        m_emitter.AppendLine("]),");
338
                    }
339
                    break;
340

    
341

    
342

    
343
                case ExpressionKind.conc:
344
                    m_emitter.Append(leftcode.ToString());
345
                    m_emitter.Append(rightcode.ToString());
346
                    m_emitter.AppendLine(String.Format("ulyssesListConc({1},{2},{0}),", tmpVar, leftresult, rightresult));
347
                    break;
348

    
349
                default:
350
                    m_emitter.Append(leftcode.ToString());
351
                    m_emitter.Append(rightcode.ToString());
352
                    if (binaryOperator.left.type.kind == TypeKind.QrType)
353
                        m_emitter.Append("qEval");
354

    
355
// do not use #= for assignments in the symbolic backend
356
//                    if (binaryOperator.type.kind == TypeKind.IntType)
357
//                        m_emitter.AppendLine(String.Format(" {0} #= ({1} {2} {3}), ",
358
//                            tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left.type), rightresult));
359
//                    else
360

    
361
                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
362
                            tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left.type), rightresult));
363
                    break;
364
            }
365
            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
366
        }
367

    
368

    
369

    
370
        protected OoaPrologSymbolicExpression(
371
            OoaPrologIdentifier.Factory idFactory, 
372
            OoaPrologType.Factory typeFactory, 
373
            OoaPrologExpression.Factory expressionFactory,
374
            bool lhs)
375
            : base(idFactory, typeFactory, expressionFactory, lhs)
376
        { }
377

    
378
    }
379
}