Added upstream from http://ftp.icm.edu.pl/pub/loglan/
[loglan.git] / loglan96 / loglan93 / instr.cc
1 //****************************************************************
2 //*                                                              *
3 //*    Instr.h : Header file for the object class hierarchy for  *
4 //*              the instructions.                               *
5 //*                                                              *
6 //* (c) LITA, university of PAU (France), summer 1993.           *
7 //****************************************************************
8
9 #include <String.h>
10 #include <iostream.h>
11 #include "Objects.h"
12 #include "Expr.h"
13 #include "Instr.h"
14
15 //***************************************
16 //**                                   **
17 //**  Objects decribing an instruction **
18 //**  inside an abstract tree.         **
19 //**                                   **
20 //***************************************
21
22 /*
23                         Instruction
24
25              Single_Instruction                Complex_Instruction
26
27
28                            Single_Instruction
29
30 *:=      *job        io       signal        control      object
31
32         Attach      Put       Raise         Return       Wind  
33         Resume      Get                     Call         Inner
34         Stop        Read                    Exit         Kill
35         Detach      ReadLn                               Generator
36         Terminate   Write
37                     WriteLn
38
39
40                            Complex_instructions
41
42    *Loop                         Block                  Condition
43
44    *For                        Pref Block              *If
45    *While                                               Case
46 */
47
48 virtual void Instruction::Print( ostream& stream )
49 {
50   stream << " \"" << kind << "\" ";
51 }
52
53 ostream& operator << ( ostream& stream , Instruction TheInstr )
54 {
55   TheInstr.Print( stream );
56 }
57
58 OneArgInstr::OneArgInstr( Expression * TheExpr, String TheStr, Location *TheLoc ) :
59              Instruction( TheStr, TheLoc )
60 {
61   argument = TheExpr;
62 }
63
64 void OneArgInstr::Print( ostream& stream )
65 {
66   Instruction::Print( stream );
67   stream << "(" << *argument << ");\n";
68 }
69
70 TwoArgInstr::TwoArgInstr( Expression *TheExpr1, Expression *TheExpr2,
71                           String TheStr , Location *TheLoc) :
72              Instruction( TheStr, TheLoc )
73 {
74   arg1 = TheExpr1;
75   arg2 = TheExpr2;
76 }
77
78 void TwoArgInstr::Print( ostream& stream )
79 {
80   Instruction::Print( stream );
81   stream << "(" << *arg1 << "," << *arg2 << ");";
82 }
83
84 Affectation::Affectation( Expression *L_Value, Expression *R_Value ) :
85              TwoArgInstr( L_Value , R_Value, String("Affectation"),
86                           new Location(*L_Value->place + *R_Value->place) )
87 {
88   switch( L_Value->returntype )
89   {
90     case Ident:
91       /* Here we should verify if the returntype of the Expression is coherent
92          with the type of the Identifier ( if it is declared ). */
93       break;
94     default:
95       L_Value->Print( cout );
96       cout << " is not an Identifier .\n" ;
97       break;
98   }
99 }
100
101 void Affectation::Print( ostream& stream )
102 {
103   arg1->Print( stream );
104   cout << " := ";
105   arg2->Print( stream );
106 }
107
108 Attach::Attach( Expression *TheExpr, Location *TheLoc ) :
109         OneArgInstr( TheExpr, String("Attach"),
110                      new Location( *TheLoc + *TheExpr->place ))
111 {
112   switch( TheExpr->returntype )
113   {
114      case Ident:
115      case ObjExpr:
116      case ObjConst:
117        /* Here we should verify if the Expression
118           is coherent with a coroutine object. */
119        break;
120
121      case ExprError:
122        /* Here we test if the expression is correct or not.
123           If it is not correct, a report of the error has already been
124           emited and we have to go ahead without any comment for avoiding
125           errors provoked by the wrong expression. */
126        break;
127
128      default:
129        /* Here the Expression is correct according to the rules of building
130           an expression but the expression is not an object type so we emit
131           an error saying that there is a mismatched expression used with
132           the Attach instruction. */
133        cout << " Operand \"";
134        TheExpr->Print( cout );
135        cout << "\" for instruction Attach is wrong.\n";
136        break;
137    }
138 }
139
140 Resume::Resume( Expression *TheExpr, Location *TheLoc ) :
141         OneArgInstr( TheExpr, String("Resume"),
142                      new Location( *TheLoc + *TheExpr->place ) )
143 {
144   switch( TheExpr->returntype )
145   {
146      case Ident:
147      case ObjExpr:
148      case ObjConst:
149        /* Here we should verify if the Expression
150           is coherent with a process object. */
151        break;
152
153      case ExprError:
154        /* Here we test if the expression is correct or not.
155           If it is not correct, a report of the error has already been
156           emited and we have to go ahead without any comment for avoiding
157           errors provoked by the wrong expression. */
158        break;
159
160      default:
161        /* Here the Expression is correct according to the rules of building
162           an expression but the expression is not an object type so we emit
163           an error saying that there is a mismatched expression used with
164           the Resume instruction. */
165        cout << " Operand \"";
166        TheExpr->Print( cout );
167        cout << "\" for instruction Resume is wrong.\n";
168        break;
169    }
170 }
171
172 Stop::Stop( Expression *TheExpr, Location *TheLoc ) :
173       OneArgInstr( TheExpr, String("Stop"),
174                    new Location( *TheLoc + *TheExpr->place) )
175 {
176   switch( TheExpr->returntype )
177   {
178      case Ident:
179      case ObjExpr:
180      case ObjConst:
181        /* Here we should verify if the Expression
182           is coherent with a process object. */
183        break;
184
185      case ExprError:
186        /* Here we test if the expression is correct or not.
187           If it is not correct, a report of the error has already been
188           emited and we have to go ahead without any comment for avoiding
189           errors provoked by the wrong expression. */
190        break;
191
192      default:
193        /* Here the Expression is correct according to the rules of building
194           an expression but the expression is not an object type so we emit
195           an error saying that there is a mismatched expression used with
196           the instruction Stop. */
197        cout << " Operand \"";
198        TheExpr->Print( cout );
199        cout << "\" for instruction Stop is wrong.\n";
200        break;
201    }
202 }
203
204 Stop::Stop( Location *TheLoc ) : OneArgInstr( NULL, String("Stop"), TheLoc ) {}
205
206 void Stop::Print( ostream& stream )
207 {
208   if (argument)
209     OneArgInstr::Print( stream );
210   else
211     cout << "Stop;\n";
212 }
213
214 Get::Get( Expression *TheArg, Location *TheLoc) :
215   OneArgInstr( TheArg, String("Get"),
216                new Location(*TheArg->place + *TheLoc) )
217 {
218   switch(TheArg->returntype)
219   {
220     case Ident:
221     case ExprError:
222       break;
223
224     default:
225       cout << " Operand \"";
226       TheArg->Print( cout );
227       cout << "\" for instruction Get is wrong.\n";
228       break;
229   }
230 }
231
232 Put::Put( Expression *TheArg, Location *TheLoc) :
233      OneArgInstr( TheArg, String("Put"),
234                   new Location(*TheArg->place + *TheLoc) )
235 {
236   switch(TheArg->returntype)
237   {
238     case Ident:
239     case ExprError:
240       break;
241
242     default:
243       cout << " Operand \"";
244       TheArg->Print( cout );
245       cout << "\" for instruction Put is wrong.\n";
246       break;
247   }
248 }
249
250 Block::Block( Instruction *FirstInstr, Location *TheLoc ) :
251        Instruction( String("Block"), TheLoc ), InstrList( FirstInstr )
252 {
253
254 // We have to test the pointer because a block of instruction could be empty.
255 // i.e. : for i := 1 to 2 do od;
256 //                        \___/-> empty block;
257   if (FirstInstr)
258     *place = *place + *FirstInstr->place;
259
260 }
261
262 Block& operator += ( Block& TheBlock, Instruction *TheInstr )
263 {
264   TheBlock.InstrList += TheInstr;
265 // The test is not worth here because the block is expanded only if there is
266 // a new instruction who of course is not empty.
267   *TheBlock.place = *TheBlock.place + *TheInstr->place;
268   return TheBlock;
269 }
270
271 void Block::Print( ostream& stream )
272 {
273   stream << "Block\n";
274   InstrList.Print( stream );
275   stream << "End of Block.\n";
276 }
277
278 ListOfInstr::ListOfInstr( Instruction *TheInstr )
279 {
280   Instruct = TheInstr;
281   NextInst = NULL;
282 }
283
284 ListOfInstr& operator += ( ListOfInstr& TheList , Instruction *TheInstr )
285 {
286   ListOfInstr *Current = &TheList;
287
288   while (Current->NextInst != NULL ) Current = Current->NextInst;
289   Current->NextInst = new ListOfInstr( TheInstr );
290   return TheList;
291 }
292
293 void ListOfInstr::Print( ostream& stream )
294 {
295   ListOfInstr *Current;
296
297   Current = NextInst;
298   Instruct->Print( stream );
299   stream << "\n";
300
301   while (Current != NULL)
302   {
303     Current->Instruct->Print( stream );
304     stream << "\n";
305     Current = Current->NextInst;
306   }
307
308 }
309
310 ConditionIf::ConditionIf( Expression *TheCondition,
311                           Block *Block1, Block *Block2, Location *TheLoc ) :
312              Instruction( String( " If " ),
313   new Location( *TheLoc + *Block1->place + *Block2->place ) ),
314              Condition( TheCondition ), BlockThen( Block1 ), BlockElse( Block2 )
315 {
316   switch( TheCondition->returntype )
317   {
318     case BoolExpr:
319     case BoolConst:
320     case Ident:
321     case ExprError:
322       break;
323
324     default:
325       cout << " Bad Expression \"";
326       TheCondition->Print( cout );
327       cout << " for If condition.\n";
328       break;
329   }
330 }
331
332 void ConditionIf::Print( ostream& stream )
333 {
334   cout << "If (";
335   Condition->Print( cout );
336   cout << ")\nThen \n";
337   BlockThen->Print( cout );
338   if (BlockElse)
339   {
340     cout <<"Else\n";
341     BlockElse->Print( cout );
342   }
343 }
344
345 void Loop::Print( ostream& stream )
346 {
347   stream << " DO\n";
348   Body->Print( stream );
349   stream << "\nOD\n";
350 }
351
352 While::While( Expression *TheExpr, Block *TheBlock, Location *TheLoc ) :
353        Loop( TheBlock, String("While") ), Condition( TheExpr )
354 {
355   if (TheExpr)
356   {
357     *place = *TheLoc + *TheBlock->place;
358     switch( TheExpr->returntype )
359     {
360       case Ident:
361       case BoolConst:
362       case BoolExpr:
363       case ExprError:
364         break;
365
366       default:
367         cout << "Wrong expression \"";
368         TheExpr->Print( cout );
369         cout << "\" for Instruction While.\n";
370         break;
371     }
372   }
373 }
374
375 void While::Print( ostream& stream )
376 {
377   stream << "While ";
378   Condition->Print( stream );
379   Loop::Print( stream );
380 }
381
382 For::For( Expression *TheVar, Expression *Initial, Expression *Final,
383           Expression *Step,   Block *TheBlock, Location *TheLoc ) :
384      Loop( TheBlock, String("For") ), Counter( TheVar ),
385      CounterInit( Initial ), CounterStop( Final ), CounterStep( Step )
386 {
387   *place = *TheLoc + *TheVar->place + *Initial->place + *Final->place +
388            *Step->place + *TheBlock->place;
389   switch( CounterInit->returntype )
390   {
391     case Ident:
392     case IntegerConst:
393     case IntegerExpr:
394     case RealExpr:
395     case RealConst:
396     case ExprError:
397       break;
398
399     default:
400       cout << " Bad Expression type for Initial value \"";
401       CounterInit->Print( cout );
402       cout << "\" of variable ";
403       Counter->Print( cout );
404       cout << ".\n";
405   }
406
407   switch( CounterStop->returntype )
408   {
409     case Ident:
410     case IntegerConst:
411     case IntegerExpr:
412     case RealExpr:
413     case RealConst:
414     case ExprError:
415       break;
416
417     default:
418       cout << " Bad Expression type for Initial value \"";
419       CounterInit->Print( cout );
420       cout << "\" of variable ";
421       Counter->Print( cout );
422       cout << ".\n";
423   }
424
425   switch( CounterStep->returntype )
426   {
427     case Ident:
428     case IntegerConst:
429     case IntegerExpr:
430     case RealExpr:
431     case RealConst:
432     case ExprError:
433       break;
434
435     default:
436       cout << " Bad Expression type for Step value \"";
437       CounterStep->Print( cout );
438       cout << ".\n";
439   }
440
441 }
442
443 void For::Print( ostream& stream )
444 {
445   stream << "For ";
446   Counter->Print( cout );
447   stream << " := ";
448   CounterInit->Print( cout );
449   stream << " TO ";
450   CounterStop->Print( cout );
451   stream << " Step ";
452   CounterStep->Print( cout );
453   Loop::Print( stream );
454 }