diff options
Diffstat (limited to 'src/runner.cpp')
-rw-r--r-- | src/runner.cpp | 922 |
1 files changed, 922 insertions, 0 deletions
diff --git a/src/runner.cpp b/src/runner.cpp new file mode 100644 index 0000000..ace9ce9 --- /dev/null +++ b/src/runner.cpp | |||
@@ -0,0 +1,922 @@ | |||
1 | #include "runner.h" | ||
2 | |||
3 | #include "ast.h" | ||
4 | #include "astnode.h" | ||
5 | #include "astleaf.h" | ||
6 | #include "astbranch.h" | ||
7 | #include "context.h" | ||
8 | #include "functionast.h" | ||
9 | #include "rule.h" | ||
10 | #include "variable.h" | ||
11 | #include "target.h" | ||
12 | #include "action.h" | ||
13 | #include "profile.h" | ||
14 | #include "view.h" | ||
15 | |||
16 | #include "bu/sio.h" | ||
17 | using Bu::sio; | ||
18 | |||
19 | Runner::Runner( Ast &rAst, Context &rCont ) : | ||
20 | rAst( rAst ), | ||
21 | rCont( rCont ), | ||
22 | pCurTarget( NULL ), | ||
23 | pCurRule( NULL ) | ||
24 | { | ||
25 | } | ||
26 | |||
27 | Runner::~Runner() | ||
28 | { | ||
29 | } | ||
30 | |||
31 | void Runner::initialize() | ||
32 | { | ||
33 | for( Ast::NodeList::const_iterator i = rAst.getNodeBegin(); i; i++ ) | ||
34 | { | ||
35 | if( (*i)->getType() == AstNode::typeFunctionDef ) | ||
36 | { | ||
37 | AstBranch *pFnc = dynamic_cast<AstBranch *>(*i); | ||
38 | rCont.addFunction( new FunctionAst( pFnc, this ) ); | ||
39 | } | ||
40 | else if( (*i)->getType() == AstNode::typeActionDef ) | ||
41 | { | ||
42 | AstBranch *pAction = dynamic_cast<AstBranch *>(*i); | ||
43 | rCont.addAction( new Action( pAction ) ); | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | |||
48 | Variable Runner::execFunc( const AstBranch *pFunc, Variable &vIn ) | ||
49 | { | ||
50 | Bu::FString sName = dynamic_cast<const AstLeaf *>( | ||
51 | (*pFunc->getBranchBegin()).first())->getStrValue(); | ||
52 | |||
53 | VarList lParams; | ||
54 | for( AstBranch::BranchList::const_iterator p = | ||
55 | pFunc->getBranchBegin()+1; p; p++ ) | ||
56 | { | ||
57 | lParams.append( execExpr( (*p).begin() ) ); | ||
58 | } | ||
59 | |||
60 | return rCont.call( sName, vIn, lParams ); | ||
61 | } | ||
62 | |||
63 | Variable Runner::execExpr( AstBranch::NodeList::const_iterator e ) | ||
64 | { | ||
65 | Variable vBlank; | ||
66 | return execExpr( e, vBlank ); | ||
67 | } | ||
68 | |||
69 | Variable Runner::execExpr( AstBranch::NodeList::const_iterator e, | ||
70 | const Variable &vIn ) | ||
71 | { | ||
72 | // Variable v( vIn ); | ||
73 | VarList lStack; | ||
74 | lStack.push( vIn ); | ||
75 | |||
76 | for(; e; e++ ) | ||
77 | { | ||
78 | if( ((*e)->getType()&AstNode::typeClassMask) == AstNode::typeBranch ) | ||
79 | { | ||
80 | const AstBranch *pBranch = dynamic_cast<const AstBranch *>( *e ); | ||
81 | switch( pBranch->getType() ) | ||
82 | { | ||
83 | case AstNode::typeFunction: | ||
84 | //sio << "FUNC: " << *pBranch << sio.nl << sio.nl; | ||
85 | { | ||
86 | Variable v = lStack.peekPop(); | ||
87 | lStack.push( execFunc( pBranch, v ) ); | ||
88 | } | ||
89 | break; | ||
90 | |||
91 | case AstNode::typeSet: | ||
92 | lStack.push( doSet( pBranch ) ); | ||
93 | break; | ||
94 | |||
95 | case AstNode::typeList: | ||
96 | { | ||
97 | Variable vLst( Variable::typeList ); | ||
98 | for( AstBranch::BranchList::const_iterator i = | ||
99 | pBranch->getBranchBegin(); i; i++ ) | ||
100 | { | ||
101 | vLst.append( execExpr( (*i).begin() ) ); | ||
102 | } | ||
103 | lStack.push( vLst ); | ||
104 | } | ||
105 | break; | ||
106 | |||
107 | case AstNode::typeExpr: | ||
108 | { | ||
109 | sio << "!!! typeExpr in an expr maybe should be an error..." << sio.nl; | ||
110 | for( AstBranch::BranchList::const_iterator i = | ||
111 | pBranch->getBranchBegin(); i; i++ ) | ||
112 | { | ||
113 | lStack.push( | ||
114 | execExpr( (*i).begin() ) // Are they atomic? | ||
115 | ); | ||
116 | } | ||
117 | if( lStack.getSize() != 1 ) | ||
118 | { | ||
119 | throw Bu::ExceptionBase( | ||
120 | "Something went wrong, expression processing " | ||
121 | "left %d elements on stack, should be 1.", | ||
122 | lStack.getSize() ); | ||
123 | } | ||
124 | } | ||
125 | break; | ||
126 | |||
127 | default: | ||
128 | sio << "?? branch ???: " | ||
129 | << (pBranch)->getType(); | ||
130 | break; | ||
131 | } | ||
132 | } | ||
133 | else | ||
134 | { | ||
135 | const AstLeaf *pLeaf = dynamic_cast<const AstLeaf *>( *e ); | ||
136 | switch( pLeaf->getType() ) | ||
137 | { | ||
138 | case AstNode::typeVariable: | ||
139 | try | ||
140 | { | ||
141 | lStack.push( | ||
142 | rCont.getVariable( pLeaf->getStrValue() ) | ||
143 | ); | ||
144 | } | ||
145 | catch(...) | ||
146 | { | ||
147 | lStack.push( Variable() ); | ||
148 | } | ||
149 | break; | ||
150 | |||
151 | case AstNode::typeVariableRef: | ||
152 | lStack.push( | ||
153 | Variable::mkRef( pLeaf->getStrValue() ) | ||
154 | ); | ||
155 | break; | ||
156 | |||
157 | case AstNode::typeString: | ||
158 | lStack.push( | ||
159 | rCont.expand( pLeaf->getStrValue() ) | ||
160 | ); | ||
161 | break; | ||
162 | |||
163 | case AstNode::typeInt: | ||
164 | lStack.push( | ||
165 | pLeaf->getIntValue() | ||
166 | ); | ||
167 | break; | ||
168 | |||
169 | case AstNode::typeFloat: | ||
170 | lStack.push( | ||
171 | pLeaf->getFloatValue() | ||
172 | ); | ||
173 | break; | ||
174 | |||
175 | case AstNode::typeBool: | ||
176 | lStack.push( | ||
177 | pLeaf->getBoolValue() | ||
178 | ); | ||
179 | break; | ||
180 | |||
181 | case AstNode::typeVersion: | ||
182 | break; | ||
183 | |||
184 | case AstNode::typeNull: | ||
185 | lStack.push( | ||
186 | Variable() | ||
187 | ); | ||
188 | break; | ||
189 | |||
190 | case AstNode::typeCmpEq: | ||
191 | { | ||
192 | Variable a, b; | ||
193 | a = lStack.peekPop(); | ||
194 | b = lStack.peekPop(); | ||
195 | lStack.push( Variable( a == b ) ); | ||
196 | } | ||
197 | break; | ||
198 | |||
199 | case AstNode::typeCmpLt: | ||
200 | { | ||
201 | Variable a, b; | ||
202 | a = lStack.peekPop(); | ||
203 | b = lStack.peekPop(); | ||
204 | lStack.push( Variable( b < a ) ); | ||
205 | } | ||
206 | break; | ||
207 | |||
208 | case AstNode::typeCmpGt: | ||
209 | { | ||
210 | Variable a, b; | ||
211 | a = lStack.peekPop(); | ||
212 | b = lStack.peekPop(); | ||
213 | lStack.push( Variable( b > a ) ); | ||
214 | } | ||
215 | break; | ||
216 | |||
217 | case AstNode::typeCmpNe: | ||
218 | { | ||
219 | Variable a, b; | ||
220 | a = lStack.peekPop(); | ||
221 | b = lStack.peekPop(); | ||
222 | lStack.push( Variable( a != b ) ); | ||
223 | } | ||
224 | break; | ||
225 | |||
226 | case AstNode::typeCmpLtEq: | ||
227 | { | ||
228 | Variable a, b; | ||
229 | a = lStack.peekPop(); | ||
230 | b = lStack.peekPop(); | ||
231 | lStack.push( Variable( b <= a ) ); | ||
232 | } | ||
233 | break; | ||
234 | |||
235 | case AstNode::typeCmpGtEq: | ||
236 | { | ||
237 | Variable a, b; | ||
238 | a = lStack.peekPop(); | ||
239 | b = lStack.peekPop(); | ||
240 | lStack.push( Variable( b >= a ) ); | ||
241 | } | ||
242 | break; | ||
243 | |||
244 | case AstNode::typeOpEq: | ||
245 | { | ||
246 | Variable ref, val; | ||
247 | val = lStack.peekPop(); | ||
248 | ref = lStack.peekPop(); | ||
249 | rCont.addVariable( ref.getString(), val ); | ||
250 | lStack.push( val ); | ||
251 | } | ||
252 | break; | ||
253 | |||
254 | case AstNode::typeOpPlusEq: | ||
255 | { | ||
256 | Variable ref, val; | ||
257 | val = lStack.peekPop(); | ||
258 | ref = lStack.peekPop(); | ||
259 | try | ||
260 | { | ||
261 | Variable &nVal = rCont.getVariable( | ||
262 | ref.getString() | ||
263 | ); | ||
264 | nVal += val; | ||
265 | lStack.push( nVal ); | ||
266 | } catch(...) | ||
267 | { | ||
268 | rCont.addVariable( ref.getString(), val ); | ||
269 | lStack.push( val ); | ||
270 | } | ||
271 | } | ||
272 | break; | ||
273 | |||
274 | case AstNode::typeOpPlusEqRaw: | ||
275 | { | ||
276 | Variable ref, val; | ||
277 | val = lStack.peekPop(); | ||
278 | ref = lStack.peekPop(); | ||
279 | try | ||
280 | { | ||
281 | Variable &nVal = rCont.getVariable( | ||
282 | ref.getString() | ||
283 | ); | ||
284 | nVal << val; | ||
285 | lStack.push( nVal ); | ||
286 | } catch(...) | ||
287 | { | ||
288 | rCont.addVariable( ref.getString(), val ); | ||
289 | lStack.push( val ); | ||
290 | } | ||
291 | } | ||
292 | break; | ||
293 | |||
294 | case AstNode::typeOpPlus: | ||
295 | { | ||
296 | Variable a, b; | ||
297 | a = lStack.peekPop(); | ||
298 | b = lStack.peekPop(); | ||
299 | lStack.push( Variable( b + a ) ); | ||
300 | } | ||
301 | break; | ||
302 | |||
303 | case AstNode::typeOpMinus: | ||
304 | { | ||
305 | Variable a, b; | ||
306 | a = lStack.peekPop(); | ||
307 | b = lStack.peekPop(); | ||
308 | lStack.push( Variable( b - a ) ); | ||
309 | } | ||
310 | break; | ||
311 | |||
312 | case AstNode::typeOpMultiply: | ||
313 | { | ||
314 | Variable a, b; | ||
315 | a = lStack.peekPop(); | ||
316 | b = lStack.peekPop(); | ||
317 | lStack.push( Variable( b * a ) ); | ||
318 | } | ||
319 | break; | ||
320 | |||
321 | case AstNode::typeOpDivide: | ||
322 | { | ||
323 | Variable a, b; | ||
324 | a = lStack.peekPop(); | ||
325 | b = lStack.peekPop(); | ||
326 | lStack.push( Variable( b / a ) ); | ||
327 | } | ||
328 | break; | ||
329 | |||
330 | case AstNode::typeOpNegate: | ||
331 | lStack.peek().doNegate(); | ||
332 | break; | ||
333 | |||
334 | case AstNode::typeOpNot: | ||
335 | lStack.peek().doNot(); | ||
336 | break; | ||
337 | |||
338 | default: | ||
339 | sio << "?? leaf ???: " | ||
340 | << (pLeaf)->getType(); | ||
341 | break; | ||
342 | } | ||
343 | } | ||
344 | } | ||
345 | |||
346 | return lStack.peek(); | ||
347 | } | ||
348 | |||
349 | void Runner::run() | ||
350 | { | ||
351 | run( rAst.getNodeBegin() ); | ||
352 | |||
353 | rCont.buildTargetTree( *this ); | ||
354 | |||
355 | rCont.attachDefaults(); | ||
356 | rCont.genDefaultActions(); | ||
357 | |||
358 | // rCont.writeTargetDot(); | ||
359 | } | ||
360 | |||
361 | Variable Runner::run( AstBranch::NodeList::const_iterator n ) | ||
362 | { | ||
363 | /* Execute the top level code. */ | ||
364 | |||
365 | Variable vReturn; | ||
366 | Bu::List<Ast::NodeList::const_iterator> sI; | ||
367 | sI.push( n ); | ||
368 | // for( Ast::NodeList::const_iterator i = rAst.getNodeBegin(); i; i++ ) | ||
369 | while( !sI.isEmpty() ) | ||
370 | { | ||
371 | while( !sI.isEmpty() && !(sI.peek()) ) | ||
372 | { | ||
373 | sI.pop(); | ||
374 | } | ||
375 | if( sI.isEmpty() ) | ||
376 | break; | ||
377 | Ast::NodeList::const_iterator &i = sI.peek(); | ||
378 | if( ((*i)->getType()&AstNode::typeClassMask) == AstNode::typeLeaf ) | ||
379 | { | ||
380 | const AstLeaf *pExpr = dynamic_cast<const AstLeaf *>( *i ); | ||
381 | switch( pExpr->getType() ) | ||
382 | { | ||
383 | case AstNode::typeError: | ||
384 | { | ||
385 | Bu::FString sMsg = rCont.expand( pExpr->getStrValue() ); | ||
386 | rCont.getView()->userError( sMsg.getStr() ); | ||
387 | throw Bu::ExceptionBase( sMsg.getStr() ); | ||
388 | } | ||
389 | break; | ||
390 | |||
391 | case AstNode::typeWarning: | ||
392 | rCont.getView()->userWarning( | ||
393 | rCont.expand( pExpr->getStrValue() ) | ||
394 | ); | ||
395 | break; | ||
396 | |||
397 | case AstNode::typeNotice: | ||
398 | rCont.getView()->userNotice( | ||
399 | rCont.expand( pExpr->getStrValue() ) | ||
400 | ); | ||
401 | break; | ||
402 | |||
403 | case AstNode::typeCondition: | ||
404 | break; | ||
405 | |||
406 | case AstNode::typeDisplay: | ||
407 | if( pCurTarget ) | ||
408 | { | ||
409 | pCurTarget->setDisplay( | ||
410 | rCont.expand( pExpr->getStrValue() ) | ||
411 | ); | ||
412 | } | ||
413 | else if( pCurRule ) | ||
414 | { | ||
415 | pCurRule->setDisplay( | ||
416 | rCont.expand( pExpr->getStrValue() ) | ||
417 | ); | ||
418 | } | ||
419 | break; | ||
420 | /* | ||
421 | case AstNode::typeCondition: | ||
422 | if( pCurTarget ) | ||
423 | { | ||
424 | if( pExpr->getStrValue() == "filetime" ) | ||
425 | { | ||
426 | pCurTarget->setCondition( | ||
427 | new ConditionFileTime() | ||
428 | ); | ||
429 | } | ||
430 | } | ||
431 | else if( pCurRule ) | ||
432 | { | ||
433 | if( pExpr->getStrValue() == "filetime" ) | ||
434 | { | ||
435 | pCurRule->setCondition( | ||
436 | new ConditionFileTime() | ||
437 | ); | ||
438 | } | ||
439 | } | ||
440 | else | ||
441 | { | ||
442 | throw Bu::ExceptionBase( | ||
443 | "You can only set a condition in a target or rule."); | ||
444 | } | ||
445 | break; | ||
446 | */ | ||
447 | default: | ||
448 | sio << "Leaf? " << (*i)->getType() << sio.nl; | ||
449 | break; | ||
450 | } | ||
451 | } | ||
452 | else | ||
453 | { | ||
454 | const AstBranch *pExpr = dynamic_cast<const AstBranch *>( *i ); | ||
455 | switch( pExpr->getType() ) | ||
456 | { | ||
457 | case AstNode::typeSet: | ||
458 | { | ||
459 | // This is effectively legacy, if we add the set | ||
460 | // keyword back in I want it to work. | ||
461 | doSet( pExpr ); | ||
462 | } | ||
463 | break; | ||
464 | |||
465 | case AstNode::typeUnset: | ||
466 | { | ||
467 | AstBranch::NodeList::const_iterator n = | ||
468 | (*pExpr->getBranchBegin()).begin(); | ||
469 | Bu::FString sVar = dynamic_cast<const AstLeaf *>( | ||
470 | *n )->getStrValue(); | ||
471 | rCont.delVariable( sVar ); | ||
472 | } | ||
473 | break; | ||
474 | |||
475 | case AstNode::typeIf: | ||
476 | { | ||
477 | AstBranch::BranchList::const_iterator b = | ||
478 | pExpr->getBranchBegin(); | ||
479 | |||
480 | Variable v = execExpr( (*b).begin() ); | ||
481 | if( v.getType() != Variable::typeBool ) | ||
482 | { | ||
483 | throw Bu::ExceptionBase( | ||
484 | "If statement evaluated to non-boolean."); | ||
485 | } | ||
486 | b++; | ||
487 | if( v.getBool() ) | ||
488 | { | ||
489 | i++; | ||
490 | sI.push( (*b).begin() ); | ||
491 | continue; | ||
492 | } | ||
493 | else | ||
494 | { | ||
495 | b++; | ||
496 | if( b ) | ||
497 | { | ||
498 | i++; | ||
499 | sI.push( (*b).begin() ); | ||
500 | continue; | ||
501 | } | ||
502 | } | ||
503 | } | ||
504 | break; | ||
505 | |||
506 | case AstNode::typeFor: | ||
507 | { | ||
508 | AstBranch::BranchList::const_iterator b = | ||
509 | pExpr->getBranchBegin(); | ||
510 | Bu::FString sVar = dynamic_cast<const AstLeaf *>( | ||
511 | (*b).first() )->getStrValue(); | ||
512 | b++; | ||
513 | Variable v = execExpr( (*b).begin() ); | ||
514 | b++; | ||
515 | for( VarList::const_iterator vi = v.getList().begin(); | ||
516 | vi; vi++ ) | ||
517 | { | ||
518 | rCont.addVariable( sVar, *vi ); | ||
519 | run( (*b).begin() ); | ||
520 | } | ||
521 | } | ||
522 | break; | ||
523 | |||
524 | case AstNode::typeFunction: | ||
525 | { | ||
526 | Variable vIn; | ||
527 | execFunc( pExpr, vIn ); | ||
528 | } | ||
529 | break; | ||
530 | |||
531 | case AstNode::typeReturn: | ||
532 | vReturn = execExpr( (*pExpr->getBranchBegin()).begin() ); | ||
533 | return vReturn; | ||
534 | break; | ||
535 | |||
536 | case AstNode::typeFunctionDef: | ||
537 | case AstNode::typeActionDef: | ||
538 | // We ignore these, we already dealt with them | ||
539 | break; | ||
540 | |||
541 | case AstNode::typeTarget: | ||
542 | // This actually runs exactly like a for loop, if there's | ||
543 | // only one item, then we only go once, if it's a list, go | ||
544 | // more than once :-P | ||
545 | if( pCurTarget == NULL ) | ||
546 | { | ||
547 | AstBranch::BranchList::const_iterator b = | ||
548 | pExpr->getBranchBegin(); | ||
549 | Variable vLoop = execExpr( (*b).begin() ); | ||
550 | b++; | ||
551 | if( vLoop.getType() == Variable::typeString ) | ||
552 | { | ||
553 | rCont.addTarget( | ||
554 | buildTarget( | ||
555 | vLoop.getString(), (*b).begin() | ||
556 | ) | ||
557 | ); | ||
558 | } | ||
559 | else if( vLoop.getType() == Variable::typeList ) | ||
560 | { | ||
561 | for( VarList::iterator i = vLoop.begin(); i; i++ ) | ||
562 | { | ||
563 | rCont.addTarget( | ||
564 | buildTarget( | ||
565 | (*i).getString(), (*b).begin() | ||
566 | ) | ||
567 | ); | ||
568 | } | ||
569 | } | ||
570 | } | ||
571 | else | ||
572 | { | ||
573 | throw Bu::ExceptionBase( | ||
574 | "You cannot declare a target within " | ||
575 | "a target decleration."); | ||
576 | } | ||
577 | break; | ||
578 | |||
579 | case AstNode::typeRuleDef: | ||
580 | if( pCurRule == NULL ) | ||
581 | { | ||
582 | AstBranch::BranchList::const_iterator b = | ||
583 | pExpr->getBranchBegin(); | ||
584 | Bu::FString sName = dynamic_cast<const AstLeaf *>( | ||
585 | (*b).first() | ||
586 | )->getStrValue(); | ||
587 | b++; | ||
588 | rCont.addRule( buildRule( sName, (*b).begin() ) ); | ||
589 | } | ||
590 | else | ||
591 | { | ||
592 | throw Bu::ExceptionBase( | ||
593 | "You cannot declare a rule within " | ||
594 | "a rule decleration."); | ||
595 | } | ||
596 | break; | ||
597 | |||
598 | case AstNode::typeInput: | ||
599 | if( pCurTarget != NULL ) | ||
600 | { | ||
601 | Variable vRet = execExpr( | ||
602 | (*pExpr->getBranchBegin()).begin() | ||
603 | ); | ||
604 | if( vRet.getType() == Variable::typeString ) | ||
605 | { | ||
606 | pCurTarget->addInput( vRet.getString() ); | ||
607 | } | ||
608 | else if( vRet.getType() == Variable::typeList ) | ||
609 | { | ||
610 | for( VarList::iterator i = vRet.begin(); i; i++ ) | ||
611 | { | ||
612 | pCurTarget->addInput( | ||
613 | (*i).getString() | ||
614 | ); | ||
615 | } | ||
616 | } | ||
617 | } | ||
618 | else if( pCurRule != NULL ) | ||
619 | { | ||
620 | pCurRule->setInput( pExpr ); | ||
621 | } | ||
622 | else | ||
623 | { | ||
624 | throw Bu::ExceptionBase( | ||
625 | "input can only occur within a target or rule."); | ||
626 | } | ||
627 | break; | ||
628 | |||
629 | case AstNode::typeRequires: | ||
630 | if( pCurTarget != NULL ) | ||
631 | { | ||
632 | Variable vRet = execExpr( | ||
633 | (*pExpr->getBranchBegin()).begin() | ||
634 | ); | ||
635 | if( vRet.getType() == Variable::typeString ) | ||
636 | { | ||
637 | pCurTarget->addRequires( vRet.getString() ); | ||
638 | } | ||
639 | else if( vRet.getType() == Variable::typeList ) | ||
640 | { | ||
641 | for( VarList::iterator i = vRet.begin(); i; i++ ) | ||
642 | { | ||
643 | pCurTarget->addRequires( | ||
644 | (*i).getString() | ||
645 | ); | ||
646 | } | ||
647 | } | ||
648 | } | ||
649 | else if( pCurRule != NULL ) | ||
650 | { | ||
651 | pCurRule->addRequires( pExpr ); | ||
652 | } | ||
653 | else | ||
654 | { | ||
655 | throw Bu::ExceptionBase( | ||
656 | "requires can only occur within a target or rule."); | ||
657 | } | ||
658 | break; | ||
659 | |||
660 | case AstNode::typeRule: | ||
661 | if( pCurTarget ) | ||
662 | { | ||
663 | pCurTarget->setRule( | ||
664 | dynamic_cast<const AstLeaf *>( | ||
665 | (*pExpr->getBranchBegin()).first() | ||
666 | )->getStrValue() | ||
667 | ); | ||
668 | } | ||
669 | else | ||
670 | { | ||
671 | throw Bu::ExceptionBase( | ||
672 | "rule can only occur within a target."); | ||
673 | } | ||
674 | break; | ||
675 | |||
676 | case AstNode::typeProfile: | ||
677 | if( pCurTarget ) | ||
678 | { | ||
679 | pCurTarget->addProfile( pExpr ); | ||
680 | } | ||
681 | else if( pCurRule ) | ||
682 | { | ||
683 | pCurRule->addProfile( pExpr ); | ||
684 | } | ||
685 | else | ||
686 | { | ||
687 | throw Bu::ExceptionBase( | ||
688 | "profile can only occur within a target or rule."); | ||
689 | } | ||
690 | break; | ||
691 | |||
692 | case AstNode::typeOutput: | ||
693 | if( pCurRule ) | ||
694 | { | ||
695 | pCurRule->addOutput( pExpr ); | ||
696 | } | ||
697 | else | ||
698 | { | ||
699 | throw Bu::ExceptionBase( | ||
700 | "output can only occur within a rule."); | ||
701 | } | ||
702 | break; | ||
703 | |||
704 | case AstNode::typeProcessTarget: | ||
705 | { | ||
706 | AstBranch::BranchList::const_iterator b = | ||
707 | pExpr->getBranchBegin(); | ||
708 | Bu::FString sProfile = dynamic_cast<const AstLeaf *>( | ||
709 | (*b).first() | ||
710 | )->getStrValue(); | ||
711 | b++; | ||
712 | Variable vTargs = execExpr( (*b).begin() ); | ||
713 | if( vTargs.getType() == Variable::typeString ) | ||
714 | { | ||
715 | rCont.getTarget( vTargs.getString() )->process( | ||
716 | *this, sProfile | ||
717 | ); | ||
718 | } | ||
719 | else if( vTargs.getType() == Variable::typeList ) | ||
720 | { | ||
721 | for( VarList::iterator v = vTargs.begin(); | ||
722 | v; v++ ) { | ||
723 | rCont.getTarget( (*v).getString() )->process( | ||
724 | *this, sProfile | ||
725 | ); | ||
726 | } | ||
727 | } | ||
728 | } | ||
729 | break; | ||
730 | |||
731 | case AstNode::typeTag: | ||
732 | if( pCurTarget ) | ||
733 | { | ||
734 | AstBranch::BranchList::const_iterator b = | ||
735 | pExpr->getBranchBegin(); | ||
736 | Variable vTags = execExpr( (*b).begin() ); | ||
737 | if( vTags.getType() == Variable::typeList ) | ||
738 | { | ||
739 | for( VarList::iterator i = vTags.begin(); i; i++ ) | ||
740 | { | ||
741 | rCont.addTargetToTag( pCurTarget, (*i).toString() ); | ||
742 | } | ||
743 | } | ||
744 | else | ||
745 | { | ||
746 | Bu::FString sTag = vTags.toString(); | ||
747 | if( sTag ) | ||
748 | { | ||
749 | rCont.addTargetToTag( pCurTarget, sTag ); | ||
750 | } | ||
751 | else | ||
752 | { | ||
753 | throw Bu::ExceptionBase( | ||
754 | "A tag evaluted to empty string." | ||
755 | ); | ||
756 | } | ||
757 | } | ||
758 | } | ||
759 | else if( pCurRule ) | ||
760 | { | ||
761 | AstBranch::BranchList::const_iterator b = | ||
762 | pExpr->getBranchBegin(); | ||
763 | Variable vTags = execExpr( (*b).begin() ); | ||
764 | if( vTags.getType() == Variable::typeList ) | ||
765 | { | ||
766 | for( VarList::iterator i = vTags.begin(); i; i++ ) | ||
767 | { | ||
768 | pCurRule->addTag( (*i).toString() ); | ||
769 | } | ||
770 | } | ||
771 | else | ||
772 | { | ||
773 | Bu::FString sTag = vTags.toString(); | ||
774 | if( sTag ) | ||
775 | { | ||
776 | pCurRule->addTag( sTag ); | ||
777 | } | ||
778 | else | ||
779 | { | ||
780 | throw Bu::ExceptionBase( | ||
781 | "A tag evaluted to empty string." | ||
782 | ); | ||
783 | } | ||
784 | } | ||
785 | } | ||
786 | else | ||
787 | { | ||
788 | throw Bu::ExceptionBase( | ||
789 | "tag can only occur within a target or rule."); | ||
790 | } | ||
791 | break; | ||
792 | |||
793 | case AstNode::typeExpr: | ||
794 | execExpr( (*pExpr->getBranchBegin()).begin() ); | ||
795 | break; | ||
796 | |||
797 | default: | ||
798 | sio << "Branch? " << (*i)->getType() << sio.nl; | ||
799 | break; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | i++; | ||
804 | } | ||
805 | |||
806 | return vReturn; | ||
807 | } | ||
808 | |||
809 | void Runner::execProfile( Target *pTarget, const Bu::FString &sProfile ) | ||
810 | { | ||
811 | rCont.pushScope( pTarget->getVars() ); | ||
812 | run( (*(pTarget->getProfile( sProfile )->getRoot()-> | ||
813 | getBranchBegin()+1)).begin() ); | ||
814 | rCont.popScope(); | ||
815 | } | ||
816 | |||
817 | void Runner::execAction( const Bu::FString &sName ) | ||
818 | { | ||
819 | try | ||
820 | { | ||
821 | Action *pAct = rCont.getAction( sName ); | ||
822 | |||
823 | pAct->call( this ); | ||
824 | } | ||
825 | catch( Bu::HashException &e ) | ||
826 | { | ||
827 | Bu::FString sError("No such action '" + sName + "' found."); | ||
828 | rCont.getView()->sysError( sError ); | ||
829 | } | ||
830 | } | ||
831 | |||
832 | Context &Runner::getContext() | ||
833 | { | ||
834 | return rCont; | ||
835 | } | ||
836 | |||
837 | Target *Runner::buildTarget( const Bu::FString &sOutput, | ||
838 | AstBranch::NodeList::const_iterator n ) | ||
839 | { | ||
840 | Target *pTrg = NULL; | ||
841 | try | ||
842 | { | ||
843 | pTrg = rCont.getTarget( sOutput ); | ||
844 | rCont.pushScope( pTrg->getVars() ); | ||
845 | } | ||
846 | catch( Bu::HashException &e ) | ||
847 | { | ||
848 | pTrg = new Target( sOutput, true ); | ||
849 | rCont.pushScope(); | ||
850 | } | ||
851 | |||
852 | // sio << " (target) \"" << sOutput << "\" explicit." << sio.nl; | ||
853 | |||
854 | rCont.addVariable("OUTPUT", sOutput ); | ||
855 | pCurTarget = pTrg; | ||
856 | run( n ); | ||
857 | |||
858 | rCont.addVariable("INPUT", pTrg->getInputList() ); | ||
859 | pCurTarget = NULL; | ||
860 | |||
861 | pTrg->setVars( rCont.getScope() ); | ||
862 | rCont.popScope(); | ||
863 | |||
864 | return pTrg; | ||
865 | } | ||
866 | |||
867 | Rule *Runner::buildRule( const Bu::FString &sName, | ||
868 | AstBranch::NodeList::const_iterator n ) | ||
869 | { | ||
870 | Rule *pRule = new Rule( sName ); | ||
871 | |||
872 | rCont.pushScope(); | ||
873 | pCurRule = pRule; | ||
874 | run( n ); | ||
875 | rCont.popScope(); | ||
876 | pCurRule = NULL; | ||
877 | |||
878 | return pRule; | ||
879 | } | ||
880 | |||
881 | Variable Runner::doSet( const AstBranch *pRoot ) | ||
882 | { | ||
883 | AstBranch::NodeList::const_iterator n = | ||
884 | (*pRoot->getBranchBegin()).begin(); | ||
885 | Bu::FString sVar = dynamic_cast<const AstLeaf *>( *n )->getStrValue(); | ||
886 | n++; | ||
887 | const AstLeaf *pLeaf = dynamic_cast<const AstLeaf *>( *n ); | ||
888 | n++; | ||
889 | Variable v = execExpr( n ); | ||
890 | |||
891 | switch( pLeaf->getType() ) | ||
892 | { | ||
893 | case AstNode::typeOpEq: | ||
894 | rCont.addVariable( sVar, v ); | ||
895 | break; | ||
896 | |||
897 | case AstNode::typeOpPlusEq: | ||
898 | try | ||
899 | { | ||
900 | rCont.getVariable( sVar ) += v; | ||
901 | } catch(...) | ||
902 | { | ||
903 | rCont.addVariable( sVar, v ); | ||
904 | } | ||
905 | break; | ||
906 | |||
907 | case AstNode::typeOpPlusEqRaw: | ||
908 | try | ||
909 | { | ||
910 | rCont.getVariable( sVar ) << v; | ||
911 | } catch(...) | ||
912 | { | ||
913 | rCont.addVariable( sVar, v ); | ||
914 | } | ||
915 | break; | ||
916 | |||
917 | default: break; | ||
918 | } | ||
919 | |||
920 | return v; | ||
921 | } | ||
922 | |||