summaryrefslogtreecommitdiffstats
path: root/src/CBot/CBotAddExpr.cpp
blob: 1d2555a597ee95daf9841e29a54ff3d15252a31b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
///////////////////////////////////////////////////
// expression du genre Op�rande1 + Op�rande2
//					   Op�rande1 - Op�rande2

#include "CBot.h"

// divers constructeurs

CBotAddExpr::CBotAddExpr()
{
	m_leftop	=
	m_rightop	= NULL;			// NULL pour pouvoir faire delete sans autre
	name = "CBotAddExpr";		// debug
}

CBotAddExpr::~CBotAddExpr()
{
	delete	m_leftop;
	delete	m_rightop;
}


// compile une instruction de type A + B

CBotInstr* CBotAddExpr::Compile(CBotToken* &p, CBotStack* pStack)
{
	CBotStack* pStk = pStack->TokenStack();					// un bout de pile svp

	// cherche des instructions qui peuvent convenir � gauche de l'op�ration + ou -

	CBotInstr*	left = CBotMulExpr::Compile( p, pStk );		// expression A * B � gauche
	if (left == NULL) return pStack->Return(NULL, pStk);	// si erreur, la transmet

	// est-ce qu'on a le token + ou - ensuite ?

	if ( p->GetType() == ID_ADD ||
		 p->GetType() == ID_SUB)							// plus ou moins
	{
		CBotAddExpr* inst = new CBotAddExpr();				// �l�ment pour op�ration
		inst->SetToken(p);									// m�morise l'op�ration

		int			 type1, type2;
		type1 = pStack->GetType();							// de quel type le premier op�rande ?

		p = p->Next();										// saute le token de l'op�ration 

		// cherche des instructions qui peuvent convenir � droite

		if ( NULL != (inst->m_rightop = CBotAddExpr::Compile( p, pStk )) )	// expression (...) � droite
		{
			// il y a un second op�rande acceptable

			type2 = pStack->GetType();						// de quel type le r�sultat ?

			if ( type1 == type2 )							// les r�sultats sont-ils compatibles
			{
				// si ok, enregistre l'op�rande dans l'objet
				inst->m_leftop = left;
				// et rend l'object � qui l'a demand�
				return pStack->Return(inst, pStk);
			}
		}

		// en cas d'erreur, lib�re les �l�ments
		delete left;
		delete inst;
		// et transmet l'erreur qui se trouve sur la pile
		return pStack->Return(NULL, pStk);
	}

	// si on n'a pas affaire � une op�ration + ou -
	// rend � qui l'a demand�, l'op�rande (de gauche) trouv�
	// � la place de l'objet "addition"
	return pStack->Return(left, pStk);
}




// fait l'op�ration d'addition ou de soustraction

BOOL CBotAddExpr::Execute(CBotStack* &pStack)
{
	CBotStack* pStk1 = pStack->AddStack(this);	// ajoute un �l�ment � la pile
												// ou le retrouve en cas de reprise
//	if ( pSk1 == EOX ) return TRUE;


	// selon la reprise, on peut �tre dans l'un des 2 �tats

	if ( pStk1->GetState() == 0 &&				// 1er �tat, �value l'op�rande de gauche
		!m_leftop->Execute(pStk1) ) return FALSE; // interrompu ici ?

	// passe � l'�tape suivante
	pStk1->SetState(1);							// pr�t pour la suite

	// demande un peu plus de stack pour ne pas toucher le r�sultat de gauche
	// qui se trouve sur la pile, justement.

	CBotStack* pStk2 = pStk1->AddStack();		// ajoute un �l�ment � la pile
												// ou le retrouve en cas de reprise

	// 2e �tat, �value l'op�rande de droite
	if ( !m_rightop->Execute(pStk2) ) return FALSE; // interrompu ici ?

	int		type1 = pStk1->GetType();			// de quels types les r�sultats ?
	int		type2 = pStk2->GetType();

	// cr�e une variable temporaire pour y mettre le r�sultat
	CBotVar*	result = new CBotVar( NULL, MAX(type1, type2));

	// fait l'op�ration selon la demande
	switch (GetTokenType())
	{
	case ID_ADD:
		result->Add(pStk1->GetVar(), pStk2->GetVar());		// additionne
		break;
	case ID_SUB:
		result->Sub(pStk1->GetVar(), pStk2->GetVar());		// soustrait
		break;
	}
	pStk2->SetVar(result);						// met le r�sultat sur la pile

	pStk1->Return(pStk2);						// lib�re la pile
	return pStack->Return(pStk1);				// transmet le r�sultat
}