OSDN Git Service

modified the val to var
[liveml/LiveML.git] / src / livemlrunner.cpp
1 /*
2  * LiveML - LiveML is screen(graphic) controling library using XML.
3  *
4  * LGPL License
5  * Copyright (C) 2010 Nothan
6  * http://github.com/nothan/liveml/
7  * All rights reserved.
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Library General Public
11  *  License as published by the Free Software Foundation; either
12  *  version 2 of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Library General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Library General Public
20  *  License along with this library; if not, write to the Free
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  * Nothan
24  * private@nothan.xrea.jp
25  *
26  * Tsuioku Denrai
27  * http://tsuioku-denrai.xrea.jp/
28  */
29
30 #include "livemlrunner.h"
31
32 // parameter types
33 float LMLParameter::getFloat(size_t index)
34 {
35   DCODE(printf("LMLParameter::getFloat(%d)\n", index);)
36   return fixed_float_to_float(getFixedFloat(index));
37 }
38
39 int LMLParameter::getInteger(size_t index)
40 {
41   DCODE(printf("LMLParameter::getInteger(%d)\n", index);)
42   return fixed_float_to_int(getFixedFloat(index));
43 }
44
45 fixed_float LMLParameter::getFixedFloat(size_t index)
46 {
47   DCODE(printf("LMLParameter::getFloat(%d)\n", index);)
48   return calcu_decode((const char*)param->get(index), LiveMLRunner::variableNumericDecoder, (void*)this);
49 }
50
51 const char* LMLParameter::getText(size_t index)
52 {
53   DCODE(printf("LMLParameter::getText(%d)\n", index);)
54   return text_decode((const char*)param->get(index), LiveMLRunner::variableStringDecoder, (void*)this);
55 }
56
57 bool LMLParameter::has(size_t index)
58 {
59   DCODE(printf("LMLParameter::has(%d)\n", index);)
60   return param->has(index);
61 }
62
63 const void* LMLParameter::get(size_t index)
64 {
65   DCODE(printf("LMLParameter::getTag(%d)\n", index);)
66   return param->get(index);
67 }
68
69 Tag* LMLParameter::getTag(size_t index)
70 {
71   DCODE(printf("LMLParameter::getTag(%d)\n", index);)
72   return param->getTag(index);
73 }
74
75 const char* LMLParameter::getString(size_t index)
76 {
77   DCODE(printf("LMLParameter::getString(%d)\n", index);)
78   return param->getString(index);
79 }
80
81 // decode variables
82 fixed_float LiveMLRunner::variableNumericDecoder(variable_size id, void *work)
83 {
84   LMLParameter &param = *(LMLParameter*)work;
85   DCODE(printf("LiveMLRunner::variableNumeric(%d)\n", id);)
86
87   return param.getVariable(id)->getFixedFloat(id);
88 }
89 const char* LiveMLRunner::variableStringDecoder(variable_size id, void *work)
90 {
91   LMLParameter &param = *(LMLParameter*)work;
92   DCODE(printf("LiveMLRunner::variableString(%d)\n", id);)
93
94   return param.getVariable(id)->getString(id);
95 }
96
97 namespace lmlCommand
98 {
99   LML_CMDFUNC(action)
100   {
101     return LML_CMDRTN_NEXT;
102   }
103
104   LML_CMDFUNC(action_close)
105   {
106     DCODE(printf("\"%s\" action closed [address: %x]\n", param.getTag(0)->param.getString(0), param.actionStack->current());)
107     param.actionStack->close();
108     DCODE(printf("current address is %x[has: %d]\n", param.actionStack->current(), param.actionStack->has());)
109
110     return LML_CMDRTN_STOP | LML_CMDRTN_REACTION;
111   }
112
113   LML_CMDFUNC(event_close)
114   {
115     DCODE(printf("\"%s\" event closed [address: %x]\n", param.getTag(0)->param.getString(0), param.actionStack->current());)
116     param.actionStack->close();
117     DCODE(printf("current address is %x[has: %d]\n", param.actionStack->current(), param.actionStack->has());)
118
119     return LML_CMDRTN_STOP | LML_CMDRTN_REACTION;
120   }
121
122   LML_CMDFUNC(print)
123   {
124     printf(param.getText(0));
125     printf("\n");
126
127     return LML_CMDRTN_NEXT;
128   }
129
130   LML_CMDFUNC(active)
131   {
132     DCODE(printf("active [%s]\n", param.getText(0));)
133     LMLActorObject *obj = param.runner->addActor(param.getText(0));
134     if (param.has(1))
135     {
136       variable_size id = *(variable_size*)param.get(1);
137       size_t objId = param.runner->getActorObjectId(*obj);
138
139       param.getVariable(id)->setFixedFloat(id, int_to_fixed_float((int)objId));
140     }
141
142     return LML_CMDRTN_NEXT;
143   }
144
145   LML_CMDFUNC(repeat)
146   {
147     *param.actionStack->repeatCounter.push_back() = param.has(1) ? param.getInteger(1) : -1;
148
149     return LML_CMDRTN_NEXT;
150   }
151
152   LML_CMDFUNC(repeat_close)
153   {
154     unsigned int *counter = param.actionStack->repeatCounter.back();
155     if (*counter > 1)
156     {
157       param.actionStack->current()->tag = param.getTag(0);
158       if (param.getTag(0)->param.has(1)) (*counter)--;
159     }
160     else param.actionStack->repeatCounter.remove(counter);
161
162     return LML_CMDRTN_NEXT;
163   }
164
165   LML_CMDFUNC(rcontinue)
166   {
167     Tag **t = &param.actionStack->current()->tag;
168     *t = param.getTag(0)->param.getTag(0);
169
170     return LML_CMDRTN_NULL;
171   }
172
173   LML_CMDFUNC(rbreak)
174   {
175     if (param.actionStack->repeatCounter.back() == NULL) return LML_CMDRTN_NEXT;
176     (*param.actionStack->repeatCounter.back()) = 0;
177
178     return rcontinue(param);
179   }
180
181   LML_CMDFUNC(wait)
182   {
183     if (param.actionStack->waitCounter) param.actionStack->waitCounter--;
184     else param.actionStack->waitCounter = param.getInteger(0);
185
186     return param.actionStack->waitCounter ? LML_CMDRTN_STOP : LML_CMDRTN_NEXT;
187   }
188
189   LML_CMDFUNC(exit)
190   {
191     param.runner->dropActor(*param.obj);
192
193     return LML_CMDRTN_STOP;
194   }
195
196   LML_CMDFUNC(var)
197   {
198     variable_size id = *(variable_size*)param.get(0);
199     DCODE(printf("var[%d] = ", id);)
200     param.getVariable(id)->setFixedFloat(id, param.getFixedFloat(1));
201
202     return LML_CMDRTN_NEXT;
203   }
204
205   LML_CMDFUNC(callAction)
206   {
207     DCODE(printf("callAction: %s\n", param.getText(0));)
208     LMLActorObject *obj;
209     if (param.has(1))
210     {
211       obj = param.runner->getActorObject(param.getInteger(1));
212     }
213     else
214     {
215       obj = param.obj;
216     }
217
218     if (!obj->setAction(param.getText(0)))
219     {
220       ActionParser *ap = param.runner->parser->actionContainer[param.getText(0)];
221       obj->setAction(ap);
222     }
223
224     if(obj != param.obj && obj->activeActionStack.has())
225     {
226       LMLParameter p(NULL, param.runner, obj, &obj->activeActionStack);
227       LML_CMDRTN result = param.runner->runAction(p);
228
229       return LML_CMDRTN_NEXT;
230     }
231
232     return LML_CMDRTN_STOP | LML_CMDRTN_NEXT | LML_CMDRTN_REACTION;
233   }
234
235   LML_CMDFUNC(callEvent)
236   {
237     DCODE(printf("callEvent: %s\n", param.getText(0));)
238     LMLActorObject *obj;
239     if (param.has(1))
240     {
241       obj = param.runner->getActorObject(param.getInteger(1));
242     }
243     else
244     {
245       obj = param.obj;
246     }
247
248     if (param.obj != obj || &param.obj->activeActionStack == param.actionStack)
249     {
250       param.runner->callEvent(*obj, param.getText(0));
251       return LML_CMDRTN_NEXT;
252     }
253
254     obj->setEvent(param.getText(0));
255
256     return LML_CMDRTN_STOP | LML_CMDRTN_NEXT | LML_CMDRTN_REACTION;
257   }
258 }
259
260 LiveMLRunner::LiveMLRunner(LiveMLParser *p)
261 {
262   DCODE(printf("LiveMLRunner::LiveMLRunner() begin.\n");)
263   parser = p;
264   setMaxActors(1000);  // unauthorised
265   text_decode_init(1024); // unauthorised
266   _commandFuncs.resize(parser->countTagType());
267
268   registerCommand("print", lmlCommand::print);
269   registerCommand("active", lmlCommand::active);
270   registerCommand("action", lmlCommand::action, lmlCommand::action_close);
271   registerCommand("event", NULL, lmlCommand::event_close);
272   registerCommand("repeat", lmlCommand::repeat, lmlCommand::repeat_close);
273   registerCommand("continue", lmlCommand::rcontinue);
274   registerCommand("break", lmlCommand::rbreak);
275 //  registerCommand("if", lmlCommand::rif);
276   registerCommand("wait", lmlCommand::wait);
277   registerCommand("exit", lmlCommand::exit);
278   registerCommand("var", lmlCommand::var);
279   registerCommand("callAction", lmlCommand::callAction);
280   registerCommand("callEvent", lmlCommand::callEvent);
281   DCODE(printf("LiveMLRunner::LiveMLRunner() end.\n");)
282 }
283
284 LiveMLRunner::~LiveMLRunner()
285 {
286   text_decode_release();
287 }
288
289 bool LiveMLRunner::registerCommand(
290   const char* name,
291   LML_CMDRTN (*func)(LMLParameter&),
292   LML_CMDRTN (*closeFunc)(LMLParameter&)
293 )
294 {
295   tag_type id = parser->getTagTypeId(name);
296   if (id == UNameContainer<TagType>::NOTFOUND) return false;
297
298   _commandFuncs[id].func = func;
299   _commandFuncs[id].closeFunc = closeFunc;
300
301   return true;
302 }
303
304 LML_CMDRTN LiveMLRunner::runCommand(LMLParameter &param, Tag *tag)
305 {
306   LML_CMDRTN (*func)(LMLParameter&) = NULL;
307   TagType *rt = tag->type;
308
309   DCODE(printf("LiveMLRunner::runCommand()\n");)
310   // close a tag
311   if (rt == NULL)
312   {
313     rt = tag->param.getTag(0)->type;
314     func = _commandFuncs[rt->id].closeFunc;
315   }
316   else
317   {
318     func = _commandFuncs[rt->id].func;
319   }
320
321   LML_CMDRTN result = LML_CMDRTN_NEXT;
322   if (func != NULL)
323   {
324     DCODE(
325     if (tag->type == NULL) printf("execute command: %s[close]\n", rt->getName().c_str());
326     else printf("execute command: %s\n", rt->getName().c_str());
327     )
328     param.param = &tag->param;
329     result = (*func)(param);
330     text_decode_clear();
331     DCODE(
332     if (tag->type == NULL) printf("finish command: %s[close]\n", rt->getName().c_str());
333     else printf("finish command: %s\n", rt->getName().c_str());
334     )
335   }
336   DCODE(else printf(tag->type == NULL ? "not execute command: %s[id: %d][close]\n" : "not execute command: %s[id: %d]\n", rt->getName().c_str());)
337
338   return result;
339 }
340
341 LML_CMDRTN LiveMLRunner::runAction(LMLParameter& param)
342 {
343   LML_CMDRTN result = LML_CMDRTN_NULL;
344   ActiveAction *aa = param.actionStack->current();
345
346   DCODE(printf("LiveMLRunner::runAction()\n");)
347
348   if (aa == NULL) return result;
349   while (aa->tag != NULL)
350   {
351     result = runCommand(param, aa->tag);
352
353     if (result & LML_CMDRTN_NEXT) aa->tag = list_next(aa->tag);
354     if (result & LML_CMDRTN_STOP) break;
355   }
356
357   return result;
358 }
359
360 void LiveMLRunner::callEvent(LMLActorObject &obj, const char *name)
361 {
362   callEvent(obj, (event_type)parser->eventTypeContainer.getId(name));
363 }
364
365 void LiveMLRunner::callEvent(LMLActorObject &obj, event_type id)
366 {
367   obj.activeEventStack.clear();
368   if (!obj.setEvent(id)) return;
369
370   LMLParameter param(NULL, this, &obj, (ActiveActionStack*)&obj.activeEventStack);
371   do
372   {
373     LML_CMDRTN result = runAction(param);
374
375     if ((result & LML_CMDRTN_STOP) && !(result & LML_CMDRTN_REACTION)) break;
376   }
377   while (param.actionStack->has());
378 }
379
380 void LiveMLRunner::callEvent(event_type id)
381 {
382   LMLActorObject *actor = _actorList.front();
383   while (actor)
384   {
385     LMLActorObject *actorNext = list_next(actor);
386     callEvent((LMLActorObject&)*actor, id);
387     actor = actorNext;
388   }
389 }
390
391 bool LiveMLRunner::runActiveActions(LMLActorObject &obj)
392 {
393   LMLParameter param(NULL, this, &obj, &obj.activeActionStack);
394
395   while (param.actionStack->has())
396   {
397     LML_CMDRTN result = runAction(param);
398
399     if ((result & LML_CMDRTN_STOP) && !(result & LML_CMDRTN_REACTION)) break;
400   }
401
402   return param.actionStack->has();
403 }
404
405 bool LiveMLRunner::runObject(LMLActorObject &obj)
406 {
407   return runActiveActions(obj);
408 }
409
410 LMLActorObject* LiveMLRunner::addActor(const char *name)
411 {
412   DCODE(printf("add actor: start\n");)
413   LMLActorObject *obj;
414   size_t type = 0;
415
416   if (parser->actorContainer[name]->tag->param.has(1))
417   {
418     type = *(size_t*)parser->actorContainer[name]->tag->param.get(1);
419   }
420
421   obj = createActor(type);
422   obj->parser = parser->actorContainer[name];
423   obj->setAction((action_type)0);
424   callEvent(*obj, (event_type)0);
425   DCODE(printf("add actor: end[%x]\n", obj);)
426
427   return obj;
428 }
429
430 void LiveMLRunner::dropActor(LMLActorObject &obj)
431 {
432   DCODE(printf("LiveMLRunner::dropActor(%x)\n", &obj);)
433   callEvent(obj, (event_type)1);
434   obj.release();
435   _actorList.remove(&obj);
436 }
437
438 bool LiveMLRunner::run(void)
439 {
440   bool running = false;
441
442   DCODE(printf("LiveMLRunner::run()\n");)
443
444   LMLActorObject *actor = _actorList.front();
445   LMLActorObject *actorPrev, *actorNext;
446   while (actor)
447   {
448     DCODE(printf("execute actor: start [%x]\n", actor);)
449     actorPrev = list_prev(actor);
450     actorNext = list_next(actor);
451     running |= runObject(*actor);
452     if (NULL == actorNext)
453     {
454       if ((LMLActorObject*)_actorList.allocator()->get_free() == actor)
455       {
456         actor = actorPrev;
457       }
458       if (NULL != actor)
459       {
460         actorNext = list_next(actor);
461       }
462     }
463     DCODE(printf("execute actor: end [%x]\n", actor);)
464     actor = actorNext;
465   }
466
467   return running;
468 }
469
470 LMLActorObject* LiveMLRunner::getActorObject(size_t id)
471 {
472   return (*_actorList.allocator())[id];
473 }
474
475 size_t LiveMLRunner::getActorObjectId(LMLActorObject &obj)
476 {
477   return ((char*)&obj - (char*)_actorList.allocator()->pool()) / sizeof(list_item<LMLActorObject>);
478 }
479
480 void LiveMLRunner::setMaxActors(size_t size)
481 {
482   _repeatAllocator.resize(size * 10);
483   _actionAllocator.resize(size * 10);
484   _numericVariableAllocator.resize(size * VAR_SCOPE_MAX * 50);
485
486   variable.numericList.allocator(&_numericVariableAllocator);
487   ActiveAction *aa;
488   while (aa = (ActiveAction*)_actionAllocator.add())
489   {
490         aa->variable.numericList.allocator(&_numericVariableAllocator);
491   }
492   _actionAllocator.clear();
493
494   _actorList.resize(size);
495   while (true)
496   {
497     LMLActorObject *obj = _actorList.push_back();
498     if (obj == NULL) break;
499
500     setObjectAllocators(*obj);
501   }
502   _actorList.clear(true);
503 }
504
505 void LiveMLRunner::setObjectAllocators(LMLActorObject &obj)
506 {
507   DCODE(printf("LiveMLRunner::setObjectAllocators(%x)\n", &obj);)
508   obj.setVariableAllocator(&_numericVariableAllocator);
509   obj.activeActionStack.list.allocator(&_actionAllocator);
510   obj.activeEventStack.list.allocator(&_actionAllocator);
511   obj.setRepeatAllocator(&_repeatAllocator);
512 }
513
514 LMLActorObject* LiveMLRunner::createActor(size_t type)
515 {
516   LMLActorObject *obj;
517
518   switch (type)
519   {
520   case 0:
521     obj = _actorList.push_back(false);
522     break;
523   case 1:
524     obj = _actorList.front();
525     if (NULL != obj && obj->parser->tag->param.has(1) && 1 == *(size_t*)obj->parser->tag->param.get(1))
526     {
527       dropActor(*obj);
528     }
529     obj = _actorList.push_front(false);
530     break;
531   }
532   obj->init();
533
534   return obj;
535 }
536
537 LMLVariable* LMLParameter::getVariable(variable_size id)
538 {
539   DCODE(printf("LiveMLRunner::getVariable(%d[%d])\n", id, VAR_SCOPE_TYPE(id));)
540   LMLVariable *v = &runner->variable;
541   switch (VAR_SCOPE_TYPE(id))
542   {
543   case VAR_SCOPE_LOCAL:
544     DCODE(printf("is local variable\n");)
545     v = &actionStack->current()->variable;
546     break;
547   case VAR_SCOPE_MEMBER:
548     DCODE(printf("is member variable\n");)
549     v = &obj->variable;
550     break;
551   }
552
553   return v;
554 }