comparison interps/sadol/BDSM2.cpp @ 996:859f9b4339e6

<Gregor> tar xf egobot.tar.xz
author HackBot
date Sun, 09 Dec 2012 19:30:08 +0000
parents
children
comparison
equal deleted inserted replaced
995:6883f5911eb7 996:859f9b4339e6
1 /*
2 * BDSM2
3 * Author: Adam Sawicki
4 * http://www.regedit.risp.pl
5 * mailto:regedit@risp.pl
6 */
7 #include "pch.hpp"
8 #include <iostream>
9 #include <cstdio>
10 #include "Console.hpp"
11 #include "Source.hpp"
12
13 // array of elements of type T indexed by 'A'..'Z' or 'a'..'z'
14 // 'A' and 'a' means the same elements etc.
15 template <typename T>
16 class CharIndexedArray
17 {
18 private:
19 T m_Arr[26];
20
21 public:
22 T & operator [] (char ch)
23 {
24 if (ch >= 'a' && ch <= 'z')
25 return m_Arr[ch-'a'];
26 else if (ch >= 'A' && ch <= 'Z')
27 return m_Arr[ch-'A'];
28 else
29 Error("Invalid char array index: "+CharToStr(ch));
30 return m_Arr[0];
31 }
32 const T & operator [] (char ch) const
33 {
34 if (ch >= 'a' && ch <= 'z')
35 return m_Arr[ch-'a'];
36 else if (ch >= 'A' && ch <= 'Z')
37 return m_Arr[ch-'A'];
38 else
39 Error("Invalid char array index: "+CharToStr(ch));
40 return m_Arr[0];
41 }
42 };
43
44 //==============================================================================
45
46 class Value
47 {
48 public:
49 enum TYPE {
50 TYPE_NONE,
51 TYPE_INTEGER,
52 TYPE_DOUBLE,
53 TYPE_STRING,
54 TYPE_LIST,
55 };
56
57 typedef std::vector<Value> ValueVector;
58
59 // return:
60 // value < 0 if v1 < v2
61 // value == 0 if v1 == v2
62 // value > 0 if v1 > v2
63 static int ValueCmp(const Value &v1, const Value &v2);
64
65 private:
66 struct StringRealValue
67 {
68 private:
69 int m_ReferenceCounter;
70
71 public:
72 string m_String;
73
74 // create new value with counter 1, empty
75 StringRealValue() : m_ReferenceCounter(1) { }
76 // create new value with counter 1, initialized
77 StringRealValue(const string &String) : m_ReferenceCounter(1), m_String(String) { }
78 // create new value with counter 1 based on existing value
79 StringRealValue(const StringRealValue &v) : m_ReferenceCounter(1), m_String(v.m_String) { }
80 void AddReference() { m_ReferenceCounter++; }
81 int GetReferenceCount() { return m_ReferenceCounter; }
82 // dec reference counter, free object if 0
83 static void Destroy(StringRealValue *v);
84 };
85
86 struct ListRealValue
87 {
88 private:
89 int m_ReferenceCounter;
90
91 public:
92 ValueVector m_List;
93
94 // create new value with counter 1, empty
95 ListRealValue() : m_ReferenceCounter(1) { }
96 // create new value with counter 1, initialized
97 ListRealValue(const ValueVector &List) : m_ReferenceCounter(1), m_List(List) { }
98 // create new value with counter 1 based on existing value
99 ListRealValue(const ListRealValue &v) : m_ReferenceCounter(1), m_List(v.m_List) { }
100 void AddReference() { m_ReferenceCounter++; }
101 int GetReferenceCount() { return m_ReferenceCounter; }
102 // dec reference counter, free object if 0
103 static void Destroy(ListRealValue *v);
104 };
105
106 TYPE m_Type;
107 union {
108 int m_Integer;
109 double m_Double;
110 StringRealValue *m_String;
111 ListRealValue *m_List;
112 };
113
114 void CreateCopy(const Value &v);
115 void Destroy();
116
117 void ConvertToInteger(Value *v) const;
118 void ConvertToDouble(Value *v) const;
119 void ConvertToString(Value *v) const;
120 void ConvertToList(Value *v) const;
121
122 public:
123 // create uninitialized value
124 Value() : m_Type(TYPE_NONE) { }
125 // create initialized, empty value with given type
126 // Integer or Double has undefined value, String or List is empty.
127 Value(TYPE Type);
128 // copy constructor
129 Value(const Value &v);
130 // create initialized value
131 Value(int Integer) : m_Type(TYPE_INTEGER), m_Integer(Integer) { }
132 Value(double Double) : m_Type(TYPE_DOUBLE), m_Double(Double) { }
133 Value(const string &String) : m_Type(TYPE_STRING), m_String(new StringRealValue(String)) { }
134 Value(const ValueVector &List) : m_Type(TYPE_STRING), m_List(new ListRealValue(List)) { }
135 ~Value();
136
137 Value & operator = (const Value &v);
138 Value & operator = (TYPE Type);
139 Value & operator = (int Integer);
140 Value & operator = (double Double);
141 Value & operator = (const ValueVector &List);
142 Value & operator = (const string &String);
143
144 TYPE GetType() const { return m_Type; }
145 string GetTypeName() const;
146 // only if type is Integer
147 const int & ReadInteger() const { return m_Integer; }
148 int & AcceessInteger() { return m_Integer; }
149 // only if type is Double
150 const double & ReadDouble() const { return m_Double; }
151 double & AccessDouble() { return m_Double; }
152 // only if type is List
153 // use if don't want to modify - performance!
154 const ValueVector & ReadList() const { return m_List->m_List; }
155 // only if type is String
156 // use if don't want to modify - performance!
157 const string & ReadString() const { return m_String->m_String; }
158 // only if type is List
159 ValueVector & AccessList();
160 // only if type is String
161 string & AccessString();
162
163 void ConsoleOut() const;
164
165 void ConvertTo(Value *v, TYPE Type) const;
166 bool ConvertToBool() const;
167 int ConvertToInteger() const;
168 double ConvertToDouble() const;
169 void ConvertToString(string *s) const;
170 };
171
172 int Value::ValueCmp(const Value &v1, const Value &v2)
173 {
174 // list comparison
175 if (v1.GetType() == Value::TYPE_LIST || v2.GetType() == Value::TYPE_LIST)
176 {
177 Value w1, w2;
178 v1.ConvertTo(&w1, Value::TYPE_LIST);
179 v2.ConvertTo(&w2, Value::TYPE_LIST);
180
181 int R;
182 for (size_t i = 0; true; i++)
183 {
184 if (i == w1.ReadList().size() && i == w2.ReadList().size())
185 return 0;
186 else if (i == w1.ReadList().size())
187 return -1;
188 else if (i == w2.ReadList().size())
189 return +1;
190 else
191 {
192 R = ValueCmp(w1.ReadList()[i], w2.ReadList()[i]);
193 if (R != 0)
194 return R;
195 }
196 }
197 }
198 // string comparison
199 else if (v1.GetType() == Value::TYPE_STRING || v2.GetType() == Value::TYPE_STRING)
200 {
201 Value w1, w2;
202 v1.ConvertTo(&w1, Value::TYPE_STRING);
203 v2.ConvertTo(&w2, Value::TYPE_STRING);
204
205 if (w1.ReadString() == w2.ReadString())
206 return 0;
207 else if (w1.ReadString() < w2.ReadString())
208 return -1;
209 else
210 return +1;
211 }
212 // double comparison
213 else if (v1.GetType() == Value::TYPE_DOUBLE || v2.GetType() == Value::TYPE_DOUBLE)
214 {
215 Value w1, w2;
216 v1.ConvertTo(&w1, Value::TYPE_DOUBLE);
217 v2.ConvertTo(&w2, Value::TYPE_DOUBLE);
218
219 if (w1.ReadDouble() == w2.ReadDouble())
220 return 0;
221 else if (w1.ReadDouble() < w2.ReadDouble())
222 return -1;
223 else
224 return +1;
225 }
226 // integer comparison
227 else
228 {
229 // both must be integer
230 return v1.ReadInteger() - v2.ReadInteger();
231 }
232 }
233
234 void Value::StringRealValue::Destroy(StringRealValue *v)
235 {
236 v->m_ReferenceCounter--;
237 if (v->m_ReferenceCounter == 0)
238 delete v;
239 }
240
241 void Value::ListRealValue::Destroy(ListRealValue *v)
242 {
243 v->m_ReferenceCounter--;
244 if (v->m_ReferenceCounter == 0)
245 delete v;
246 }
247
248 void Value::CreateCopy(const Value &v)
249 {
250 m_Type = v.m_Type;
251
252 switch (v.m_Type)
253 {
254 case TYPE_INTEGER:
255 m_Integer = v.m_Integer;
256 break;
257 case TYPE_DOUBLE:
258 m_Double = v.m_Double;
259 break;
260 // add reference to the same real value object
261 case TYPE_STRING:
262 m_String = v.m_String;
263 m_String->AddReference();
264 break;
265 case TYPE_LIST:
266 m_List = v.m_List;
267 m_List->AddReference();
268 break;
269 }
270 }
271
272 void Value::Destroy()
273 {
274 // dec reference, destroy if needed
275 switch (m_Type)
276 {
277 case TYPE_STRING:
278 StringRealValue::Destroy(m_String);
279 break;
280 case TYPE_LIST:
281 ListRealValue::Destroy(m_List);
282 break;
283 }
284 }
285
286 void Value::ConvertToInteger(Value *v) const
287 {
288 *v = ConvertToInteger();
289 }
290
291 void Value::ConvertToDouble(Value *v) const
292 {
293 *v = ConvertToDouble();
294 }
295
296 void Value::ConvertToString(Value *v) const
297 {
298 switch (m_Type)
299 {
300 case TYPE_INTEGER:
301 {
302 string s;
303 IntToStr(ReadInteger(), &s);
304 *v = s;
305 }
306 break;
307 case TYPE_DOUBLE:
308 *v = DoubleToStr(ReadDouble(), 'g');
309 break;
310 case TYPE_STRING:
311 *v = *this;
312 break;
313 case TYPE_LIST:
314 Error("Cannot convert list to string");
315 break;
316 case TYPE_NONE:
317 Error("Cannot convert uninitialized value to string");
318 }
319 }
320
321 void Value::ConvertToList(Value *v) const
322 {
323 switch (m_Type)
324 {
325 case TYPE_INTEGER:
326 case TYPE_DOUBLE:
327 case TYPE_STRING:
328 *v = Value::TYPE_LIST;
329 v->AccessList().push_back(*this);
330 break;
331 case TYPE_LIST:
332 *v = *this;
333 break;
334 case TYPE_NONE:
335 Error("Cannot convert uninitialized value to list");
336 }
337 }
338
339 Value::Value(TYPE Type) : m_Type(Type)
340 {
341 switch (Type)
342 {
343 case TYPE_STRING:
344 m_String = new StringRealValue();
345 break;
346 case TYPE_LIST:
347 m_List = new ListRealValue();
348 break;
349 }
350 }
351
352 Value::Value(const Value &v)
353 {
354 CreateCopy(v);
355 }
356
357 Value::~Value()
358 {
359 Destroy();
360 }
361
362 Value & Value::operator = (const Value &v)
363 {
364 if (&v != this)
365 {
366 // as destructor
367 Destroy();
368 // as constructor
369 CreateCopy(v);
370 }
371 return *this;
372 }
373
374 Value & Value::operator = (TYPE Type)
375 {
376 // as destructor
377 Destroy();
378 // as constructor
379 m_Type = Type;
380 switch (Type)
381 {
382 case TYPE_STRING:
383 m_String = new StringRealValue();
384 break;
385 case TYPE_LIST:
386 m_List = new ListRealValue();
387 break;
388 }
389
390 return *this;
391 }
392
393 Value & Value::operator = (int Integer)
394 {
395 // as destructor
396 Destroy();
397 // as constructor
398 m_Type = TYPE_INTEGER;
399 m_Integer = Integer;
400
401 return *this;
402 }
403
404 Value & Value::operator = (double Double)
405 {
406 // as destructor
407 Destroy();
408 // as constructor
409 m_Type = TYPE_DOUBLE;
410 m_Double = Double;
411
412 return *this;
413 }
414
415 Value & Value::operator = (const ValueVector &List)
416 {
417 // as destructor
418 Destroy();
419 // as constructor
420 m_Type = TYPE_LIST;
421 m_List = new ListRealValue(List);
422
423 return *this;
424 }
425
426 Value & Value::operator = (const string &String)
427 {
428 // as destructor
429 Destroy();
430 // as constructor
431 m_Type = TYPE_STRING;
432 m_String = new StringRealValue(String);
433
434 return *this;
435 }
436
437 string Value::GetTypeName() const
438 {
439 switch (m_Type)
440 {
441 case TYPE_NONE:
442 return "none";
443 case TYPE_INTEGER:
444 return "integer";
445 case TYPE_DOUBLE:
446 return "double";
447 case TYPE_STRING:
448 return "string";
449 case TYPE_LIST:
450 return "list";
451 default:
452 return "unknown";
453 }
454 }
455
456 Value::ValueVector & Value::AccessList()
457 {
458 if (m_List->GetReferenceCount() > 1)
459 {
460 // copy on write!
461 ListRealValue *l = new ListRealValue(*m_List);
462 ListRealValue::Destroy(m_List);
463 m_List = l;
464 }
465 return m_List->m_List;
466 }
467
468 string & Value::AccessString()
469 {
470 if (m_String->GetReferenceCount() > 1)
471 {
472 // copy on write!
473 StringRealValue *s = new StringRealValue(*m_String);
474 StringRealValue::Destroy(m_String);
475 m_String = s;
476 }
477 return m_String->m_String;
478 }
479
480 void Value::ConsoleOut() const
481 {
482 switch (m_Type)
483 {
484 case TYPE_INTEGER:
485 g_Console.OutInteger(ReadInteger());
486 break;
487 case TYPE_DOUBLE:
488 g_Console.OutDouble(ReadDouble());
489 break;
490 case TYPE_STRING:
491 g_Console.OutString(ReadString());
492 break;
493 case TYPE_LIST:
494 {
495 g_Console.OutString("(");
496 for (size_t i = 0; i < ReadList().size(); i++)
497 {
498 if (i > 0)
499 g_Console.OutString(",");
500 ReadList()[i].ConsoleOut();
501 }
502 g_Console.OutString(")");
503 }
504 break;
505 case TYPE_NONE:
506 Error("Cannot print uninitialized value", ERR_IO);
507 }
508 }
509
510 void Value::ConvertTo(Value *v, TYPE Type) const
511 {
512 switch (Type)
513 {
514 case TYPE_INTEGER:
515 ConvertToInteger(v);
516 break;
517 case TYPE_DOUBLE:
518 ConvertToDouble(v);
519 break;
520 case TYPE_STRING:
521 ConvertToString(v);
522 break;
523 case TYPE_LIST:
524 ConvertToList(v);
525 break;
526 case TYPE_NONE:
527 Error("Cannot convert to uninitialized value");
528 }
529 }
530
531 bool Value::ConvertToBool() const
532 {
533 switch (m_Type)
534 {
535 case TYPE_INTEGER:
536 return (m_Integer >= 1);
537 case TYPE_DOUBLE:
538 return (m_Double >= 1.0);
539 case TYPE_STRING:
540 return !ReadString().empty();
541 case TYPE_LIST:
542 return !ReadList().empty();
543 case TYPE_NONE:
544 Error("Cannot convert uninitialized value to bool");
545 }
546 return false;
547 }
548
549 int Value::ConvertToInteger() const
550 {
551 switch (m_Type)
552 {
553 case TYPE_INTEGER:
554 return ReadInteger();
555 case TYPE_DOUBLE:
556 return Round(ReadDouble());
557 case TYPE_STRING:
558 return (int)ReadString().size();
559 case TYPE_LIST:
560 return (int)ReadList().size();
561 case TYPE_NONE:
562 Error("Cannot convert uninitialized value to integer");
563 }
564 return 0;
565 }
566
567 double Value::ConvertToDouble() const
568 {
569 switch (m_Type)
570 {
571 case TYPE_INTEGER:
572 return (double)ReadInteger();
573 case TYPE_DOUBLE:
574 return ReadDouble();
575 case TYPE_STRING:
576 return (double)ReadString().size();
577 case TYPE_LIST:
578 return (double)ReadList().size();
579 case TYPE_NONE:
580 Error("Cannot convert uninitialized value to double");
581 }
582 return 0.0;
583 }
584
585 void Value::ConvertToString(string *s) const
586 {
587 switch (m_Type)
588 {
589 case TYPE_INTEGER:
590 IntToStr(ReadInteger(), s);
591 break;
592 case TYPE_DOUBLE:
593 *s = DoubleToStr(ReadDouble(), 'g');
594 break;
595 case TYPE_STRING:
596 *s = ReadString();
597 break;
598 case TYPE_LIST:
599 {
600 string s2;
601 *s = "(";
602 for (size_t i = 0; i < ReadList().size(); i++)
603 {
604 if (i > 0)
605 *s += ",";
606 ReadList()[i].ConvertToString(&s2);
607 *s += s2;
608 }
609 *s += ")";
610 }
611 break;
612 case TYPE_NONE:
613 Error("Cannot convert uninitialized value to string");
614 }
615 }
616
617 //==============================================================================
618
619 struct LValue
620 {
621 enum TYPE
622 {
623 TYPE_VALUE,
624 TYPE_STRCHAR,
625 };
626
627 TYPE m_Type;
628 union
629 {
630 // only if value
631 Value *m_Value;
632 // only if str char
633 string *m_String;
634 };
635 // only if str char
636 size_t m_StringIndex;
637
638 LValue() { }
639 LValue(Value *a_Value) : m_Type(TYPE_VALUE), m_Value(a_Value) { }
640 LValue(string *a_String, size_t a_StringIndex) : m_Type(TYPE_STRCHAR), m_String(a_String), m_StringIndex(a_StringIndex) { }
641 };
642
643 //==============================================================================
644
645 // Contains char indexed array of value pointers.
646 // Auto-init and auto-destroy.
647 struct VarContext
648 {
649 CharIndexedArray<Value*> m_Values;
650
651 VarContext()
652 {
653 for (char ch = 'A'; ch < 'Z'; ch++)
654 m_Values[ch] = 0;
655 }
656 ~VarContext()
657 {
658 for (char ch = 'A'; ch < 'Z'; ch++)
659 delete m_Values[ch];
660 }
661 };
662
663 // Stack of var contexts
664 class VarContextStack
665 {
666 private:
667 std::vector<VarContext*> m_Stack;
668 Value m_DefaultValue;
669
670 public:
671 VarContextStack();
672
673 void PushNew();
674 void Pop();
675
676 const Value & ReadVar(char ch) const;
677 Value & AccessVar(char ch);
678 };
679
680 VarContextStack::VarContextStack() : m_DefaultValue((int)0)
681 {
682 }
683
684 void VarContextStack::PushNew()
685 {
686 m_Stack.push_back(new VarContext);
687 }
688
689 void VarContextStack::Pop()
690 {
691 delete m_Stack.back();
692 m_Stack.pop_back();
693 }
694
695 const Value & VarContextStack::ReadVar(char ch) const
696 {
697 for (std::vector<VarContext*>::const_reverse_iterator rit = m_Stack.rbegin(); rit != m_Stack.rend(); ++rit)
698 if ((*rit)->m_Values[ch])
699 return *((*rit)->m_Values[ch]);
700 return m_DefaultValue;
701 }
702
703 Value & VarContextStack::AccessVar(char ch)
704 {
705 if (m_Stack.back()->m_Values[ch] == 0)
706 m_Stack.back()->m_Values[ch] = new Value(m_DefaultValue);
707 return *m_Stack.back()->m_Values[ch];
708 }
709
710 // Only in Execute call sequence.
711 VarContextStack g_VarContextStack;
712 VarContext g_GlobalVars;
713
714 //==============================================================================
715
716 struct Function;
717 struct Node;
718
719 struct Scope
720 {
721 private:
722 // zero pointer list
723 void InitLocalFunctions();
724
725 public:
726 Scope *m_Parent;
727 Node *m_Node;
728 CharIndexedArray<Function*> m_LocalFunctions;
729
730 Scope(Scope *a_Parent, Node *a_Node) : m_Parent(a_Parent), m_Node(a_Node) { InitLocalFunctions(); }
731 virtual ~Scope();
732
733 void ParseToEnd(Source &src);
734 // Parse given source as single expression, fill in this structure's fields
735 void Parse(Source &src);
736 // Value is list of arguments
737 void Execute(Value *result, Value *args);
738 void Optimize();
739 };
740
741 struct Function : public Scope
742 {
743 // -1 means variable arg count
744 int m_ArgCount;
745
746 Function(Scope *a_Parent, Node *a_Node, int a_ArgCount) : Scope(a_Parent, a_Node), m_ArgCount(a_ArgCount) { }
747 };
748
749
750
751 void Scope::InitLocalFunctions()
752 {
753 for (char ch = 'a'; ch <= 'z'; ch++)
754 m_LocalFunctions[ch] = 0;
755 }
756
757
758
759 // Used only in Parse call sequence.
760 std::vector<Scope*> g_ScopeStack;
761 CharIndexedArray<Function*> g_GlobalFunctions;
762
763 //==============================================================================
764
765 struct Node
766 {
767 private:
768 void NodeError(const string &msg, ERR_PLACE place = ERR_GENERAL);
769 // free subnodes and clear subnode list
770 void ClearSubnodes();
771
772 int Parse_Integer(Source &src);
773 // does +
774 void OpAdd(Value *result, const Value &v1, const Value &v2);
775 // does - * %
776 void OpSubMulMod(char Op, Value *result, const Value &v1, const Value &v2);
777 // does / ^
778 void OpDivPow(char Op, Value *result, const Value &v1, const Value &v2);
779 // does \ { blablabla - placeholder not to end line with \ }
780 void OpFloor(Value *result, const Value &v);
781 // does '
782 void OpAposConverter(int Kind, Value *result, const Value &v);
783 // does = < >
784 void OpComparison(char Op, Value *result, const Value &v1, const Value &v2);
785
786 public:
787 enum TYPE {
788 TYPE_SYMBOL,
789 TYPE_CONSTANT,
790 };
791
792 TYPE m_Type;
793 Source::Iterator m_SrcIterator;
794
795 // only if symbol:
796 // If 'A'..'Z' or 'a'..'z', m_Function == 0 means variable, != 0 means function call.
797 char m_Ch;
798 std::vector<Node*> m_Sub;
799 union {
800 // only if m_Ch == 'a'..'z' or 'A'..'Z' and this is a function call:
801 // Function that should be called (weak pointer).
802 Function *m_Function;
803 // only if m_Ch == ';' => 0, 1, 2, 3
804 // or m_Ch == '\'' => 1, 2
805 int m_ExtraInt;
806 };
807
808 // only if constant:
809 Value m_Value;
810
811 Node();
812 ~Node();
813 // Parse given source to the end as sequence of commands, fill in this structure's fields
814 void ParseToEnd(Source &src);
815 // Parse given source as single expression, fill in this structure's fields
816 void Parse(Source &src);
817 // Value is list of arguments.
818 void Execute(Value *result, Value *args);
819 LValue GetLValue(Value *args);
820 void Optimize();
821 };
822
823 Scope::~Scope()
824 {
825 for (char ch = 'a'; ch <= 'z'; ch++)
826 delete m_LocalFunctions[ch];
827 delete m_Node;
828 }
829
830 void Scope::ParseToEnd(Source &src)
831 {
832 g_ScopeStack.push_back(this);
833
834 m_Node = new Node;
835 m_Node->ParseToEnd(src);
836
837 g_ScopeStack.pop_back();
838 }
839
840 void Scope::Parse(Source &src)
841 {
842 g_ScopeStack.push_back(this);
843
844 m_Node = new Node;
845 m_Node->Parse(src);
846
847 g_ScopeStack.pop_back();
848 }
849
850 void Scope::Execute(Value *result, Value *args)
851 {
852 g_ScopeStack.push_back(this);
853 g_VarContextStack.PushNew();
854
855 m_Node->Execute(result, args);
856
857 g_VarContextStack.Pop();
858 g_ScopeStack.pop_back();
859 }
860
861 void Scope::Optimize()
862 {
863 // TODO - scope stack
864 m_Node->Optimize();
865 }
866
867 void Node::NodeError(const string &msg, ERR_PLACE place)
868 {
869 Error(msg + " (" + m_SrcIterator.ToString() + ')', place);
870 }
871
872 void Node::ClearSubnodes()
873 {
874 for (size_t i = 0; i < m_Sub.size(); i++)
875 delete m_Sub[i];
876 m_Sub.clear();
877 }
878
879 int Node::Parse_Integer(Source &src)
880 {
881 src.Skip();
882 src.SaveErrPos();
883 Node *node = new Node();
884 node->Parse(src);
885 node->Optimize();
886 if (node->m_Type != Node::TYPE_CONSTANT)
887 src.SrcError("Cannot evaluate number in compilation time", ERR_PARSE);
888 src.DropErrPos();
889 int R = node->m_Value.ConvertToInteger();
890 delete node;
891
892 return R;
893 }
894
895 void Node::OpAdd(Value *result, const Value &v1, const Value &v2)
896 {
897 // 0 = list cat
898 // 1 = add as lists
899 // 2 = add as strings
900 // 3 = add as double
901 // 4 = add as integer
902 int Type = -1;
903
904 if (v1.GetType() == Value::TYPE_LIST && v2.GetType() == Value::TYPE_LIST)
905 Type = 0;
906 else if (v1.GetType() == Value::TYPE_LIST || v2.GetType() == Value::TYPE_LIST)
907 Type = 1;
908 else if (v1.GetType() == Value::TYPE_STRING || v2.GetType() == Value::TYPE_STRING)
909 Type = 2;
910 else if (v1.GetType() == Value::TYPE_DOUBLE || v2.GetType() == Value::TYPE_DOUBLE)
911 Type = 3;
912 else
913 Type = 4;
914
915 switch (Type)
916 {
917 case 0:
918 *result = v1;
919 for (size_t i = 0; i < v2.ReadList().size(); i++)
920 result->AccessList().push_back(v2.ReadList()[i]);
921 break;
922 case 1:
923 {
924 Value w2;
925 v1.ConvertTo(result, Value::TYPE_LIST);
926 v2.ConvertTo(&w2, Value::TYPE_LIST);
927 for (size_t i = 0; i < w2.ReadList().size(); i++)
928 result->AccessList().push_back(w2.ReadList()[i]);
929 }
930 break;
931 case 2:
932 {
933 Value w2;
934 v1.ConvertTo(result, Value::TYPE_STRING);
935 v2.ConvertTo(&w2, Value::TYPE_STRING);
936 result->AccessString() += w2.ReadString();
937 }
938 break;
939 case 3:
940 {
941 Value w2;
942 v1.ConvertTo(result, Value::TYPE_DOUBLE);
943 v2.ConvertTo(&w2, Value::TYPE_DOUBLE);
944 result->AccessDouble() += w2.ReadDouble();
945 }
946 break;
947 case 4:
948 *result = v1.ReadInteger() + v2.ReadInteger();
949 break;
950 }
951 }
952
953 void Node::OpSubMulMod(char Op, Value *result, const Value &v1, const Value &v2)
954 {
955 // integer
956 if (v1.GetType() == Value::TYPE_INTEGER && v2.GetType() == Value::TYPE_INTEGER)
957 {
958 int i1 = v1.ReadInteger();
959 int i2 = v2.ReadInteger();
960 switch (Op)
961 {
962 case '-':
963 *result = i1 - i2;
964 break;
965 case '*':
966 *result = i1 * i2;
967 break;
968 case '%':
969 if (i2 == 0)
970 NodeError("Integer division '%' by 0");
971 *result = i1 % i2;
972 break;
973 }
974 }
975 // double
976 else if ( (v1.GetType() == Value::TYPE_INTEGER || v1.GetType() == Value::TYPE_DOUBLE) &&
977 (v2.GetType() == Value::TYPE_INTEGER || v2.GetType() == Value::TYPE_DOUBLE) )
978 {
979 double d1 = v1.ConvertToDouble();
980 double d2 = v2.ConvertToDouble();
981 switch (Op)
982 {
983 case '-':
984 *result = d1 - d2;
985 break;
986 case '*':
987 *result = d1 * d2;
988 break;
989 case '%':
990 if (d2 == 0.0)
991 NodeError("Double division '%' by 0");
992 *result = fmod(d1, d2);
993 break;
994 }
995 }
996 else
997 NodeError("Invalid argument types for '"+CharToStr(Op)+"': "+v1.GetTypeName()+", "+v2.GetTypeName());
998 }
999
1000 void Node::OpDivPow(char Op, Value *result, const Value &v1, const Value &v2)
1001 {
1002 double d1 = v1.ConvertToDouble();
1003 double d2 = v2.ConvertToDouble();
1004
1005 switch (Op)
1006 {
1007 case '/':
1008 if (d2 == 0.0)
1009 NodeError("Double division '/' by 0");
1010 *result = d1 / d2;
1011 break;
1012 case '^':
1013 *result = pow(d1, d2);
1014 break;
1015 }
1016 }
1017
1018 void Node::OpFloor(Value *result, const Value &v)
1019 {
1020 *result = floor(v.ConvertToDouble());
1021 }
1022
1023 void Node::OpAposConverter(int Kind, Value *result, const Value &v)
1024 {
1025 if (Kind == 1)
1026 {
1027 string s;
1028 v.ConvertToString(&s);
1029 if (s.empty())
1030 NodeError("Cannot convert empty string to ASCII code in '''");
1031 *result = (int)(unsigned int)(unsigned char)s[0];
1032 }
1033 else if (Kind == 2)
1034 {
1035 int i = v.ConvertToInteger();
1036 if (i < 0 || i >= 256)
1037 NodeError("Cannot convert integer value "+IntToStr(i)+" into ASCII character");
1038 *result = Value::TYPE_STRING;
1039 result->AccessString() += (char)(unsigned char)(unsigned int)i;
1040 }
1041 }
1042
1043 void Node::OpComparison(char Op, Value *result, const Value &v1, const Value &v2)
1044 {
1045 int R = Value::ValueCmp(v1, v2);
1046
1047 switch (Op)
1048 {
1049 case '=':
1050 *result = (int)( (R == 0) ? 1 : 0 );
1051 break;
1052 case '>':
1053 *result = (int)( (R > 0) ? 1 : 0 );
1054 break;
1055 case '<':
1056 *result = (int)( (R < 0) ? 1 : 0 );
1057 break;
1058 }
1059 }
1060
1061 Node::Node() : m_Function(0)
1062 {
1063 }
1064
1065 Node::~Node()
1066 {
1067 ClearSubnodes();
1068 }
1069
1070 void Node::ParseToEnd(Source &src)
1071 {
1072 // This node is ( symbol
1073 m_Type = TYPE_SYMBOL;
1074 m_SrcIterator = src.GetIterator();
1075 m_Ch = '(';
1076
1077 Node *node;
1078 for (;;)
1079 {
1080 src.Skip();
1081
1082 if (src.End())
1083 break;
1084
1085 m_Sub.push_back(node = new Node);
1086 node->Parse(src);
1087 }
1088 }
1089
1090 void Node::Parse(Source &src)
1091 {
1092 src.Skip();
1093
1094 m_Type = TYPE_SYMBOL;
1095 m_SrcIterator = src.GetIterator();
1096 m_Ch = src.GetS();
1097
1098 // zero args
1099 if (m_Ch >= '0' && m_Ch <= '9' || m_Ch == '_')
1100 {
1101 }
1102 // one arg
1103 else if (m_Ch == '[' || m_Ch == '!' || m_Ch == '`' || m_Ch == '\\')
1104 {
1105 Node *node = new Node;
1106 m_Sub.push_back(node);
1107 node->Parse(src);
1108 }
1109 // direct string
1110 else if (m_Ch == '"')
1111 {
1112 int CharCount = Parse_Integer(src);
1113 m_Type = TYPE_CONSTANT;
1114 m_Value = Value::TYPE_STRING;
1115 for (int i = 0; i < CharCount; i++)
1116 m_Value.AccessString() += src.GetS();
1117 }
1118 // function definition
1119 else if (m_Ch == '~')
1120 {
1121 // name
1122 char func_name;
1123 src.Skip();
1124 func_name = src.GetS();
1125 if (!( func_name >= 'a' && func_name <= 'z' || func_name >= 'A' && func_name <= 'Z' ))
1126 src.SrcError("Invalid function name: '" + CharToStr(func_name) + "'", ERR_PARSE);
1127
1128 // argument count
1129 int func_arg_count = Parse_Integer(src);
1130 if (func_arg_count < -1)
1131 NodeError("Invalid argument count for function '"+CharToStr(func_name)+"': "+IntToStr(func_arg_count), ERR_PARSE);
1132
1133 // - global
1134 if (func_name >= 'A' && func_name <= 'Z')
1135 {
1136 Function *func = new Function(g_ScopeStack.front(), new Node, func_arg_count);
1137 // save function
1138 if (g_GlobalFunctions[func_name])
1139 NodeError("Global function redefinition: '"+CharToStr(func_name)+"'", ERR_PARSE);
1140 g_GlobalFunctions[func_name] = func;
1141 // parse body
1142 func->Parse(src);
1143 func->Optimize();
1144 }
1145 // - local
1146 else
1147 {
1148 Function *func = new Function(g_ScopeStack.back(), new Node, func_arg_count);
1149 // save function
1150 if (g_ScopeStack.back()->m_LocalFunctions[func_name])
1151 NodeError("Local function redefinition: '"+CharToStr(func_name)+"'", ERR_PARSE);
1152 g_ScopeStack.back()->m_LocalFunctions[func_name] = func;
1153 // parse body
1154 func->Parse(src);
1155 func->Optimize();
1156 }
1157
1158 // this expression result
1159 m_Type = TYPE_CONSTANT;
1160 m_Value = (int)1;
1161 }
1162 // two args
1163 else if (m_Ch == '+' || m_Ch == '-' || m_Ch == '*' || m_Ch == '/' ||
1164 m_Ch == '^' || m_Ch == '%' || m_Ch == ':' ||
1165 m_Ch == '#' || m_Ch == ']' || m_Ch == '@' || m_Ch == '=' ||
1166 m_Ch == '>' || m_Ch == '<' || m_Ch == '&' || m_Ch == '|')
1167 {
1168 Node *node1 = new Node;
1169 Node *node2 = new Node;
1170 m_Sub.push_back(node1);
1171 m_Sub.push_back(node2);
1172 node1->Parse(src);
1173 node2->Parse(src);
1174 }
1175 // three args
1176 else if (m_Ch == '?')
1177 {
1178 Node *node1 = new Node;
1179 Node *node2 = new Node;
1180 Node *node3 = new Node;
1181 m_Sub.push_back(node1);
1182 m_Sub.push_back(node2);
1183 m_Sub.push_back(node3);
1184 node1->Parse(src);
1185 node2->Parse(src);
1186 node3->Parse(src);
1187 }
1188 // function call or variable
1189 else if (m_Ch >= 'a' && m_Ch <= 'z' || m_Ch >= 'A' && m_Ch <= 'Z')
1190 {
1191 // if function, fill in the m_Function
1192 m_Function = 0;
1193 // - global
1194 if (m_Ch >= 'A' && m_Ch <= 'Z')
1195 // assign proper pointer or 0
1196 m_Function = g_GlobalFunctions[m_Ch];
1197 // - local
1198 else
1199 {
1200 Scope *scope = g_ScopeStack.back();
1201 while (scope != 0)
1202 {
1203 if (scope->m_LocalFunctions[m_Ch])
1204 {
1205 m_Function = scope->m_LocalFunctions[m_Ch];
1206 break;
1207 }
1208 scope = scope->m_Parent;
1209 }
1210 }
1211
1212 // this is function call
1213 if (m_Function)
1214 {
1215 // pointer to function is already saved in m_Function
1216 // argument count
1217 int arg_count = m_Function->m_ArgCount;
1218 if (arg_count == -1)
1219 arg_count = Parse_Integer(src);
1220 // arguments
1221 Node *node;
1222 for (int i = 0; i < arg_count; i++)
1223 {
1224 node = new Node;
1225 node->Parse(src);
1226 m_Sub.push_back(node);
1227 }
1228 }
1229 // this is variable - do nothing
1230 // m_Function stays 0
1231 }
1232 // variable arg count
1233 else if (m_Ch == ',' || m_Ch == '.' || m_Ch == '(' || m_Ch == '$') {
1234 int SubnodeCount = Parse_Integer(src);
1235 Node *node;
1236 for (int i = 0; i < SubnodeCount; i++)
1237 {
1238 node = new Node;
1239 node->Parse(src);
1240 m_Sub.push_back(node);
1241 }
1242 }
1243 else if (m_Ch == ';')
1244 {
1245 m_ExtraInt = Parse_Integer(src);
1246 }
1247 else if (m_Ch == '\'')
1248 {
1249 m_ExtraInt = Parse_Integer(src);
1250 if (m_ExtraInt == 0)
1251 {
1252 m_Type = TYPE_CONSTANT;
1253 m_Value = (int)(unsigned int)(unsigned char)src.GetS();
1254 }
1255 else if (m_ExtraInt == 1 || m_ExtraInt == 2)
1256 {
1257 // one subnode
1258 Node *node = new Node;
1259 node->Parse(src);
1260 m_Sub.push_back(node);
1261 }
1262 else
1263 NodeError("Invalid numeric constant in ''': "+IntToStr(m_ExtraInt), ERR_PARSE);
1264 }
1265 else
1266 // Erroneous character
1267 src.SrcError("Unsupported character: '" + CharToStr(m_Ch) + "'", ERR_PARSE);
1268 }
1269
1270 void Node::Execute(Value *result, Value *args)
1271 {
1272 // Value
1273 if (m_Type == TYPE_CONSTANT)
1274 {
1275 *result = m_Value;
1276 return;
1277 }
1278
1279 // Code symbol
1280 if (m_Ch >= '0' && m_Ch <= '9')
1281 {
1282 *result = (int)(unsigned char)(m_Ch - '0');
1283 }
1284 // function call or variable
1285 else if (m_Ch >= 'a' && m_Ch <= 'z' || m_Ch >= 'A' && m_Ch <= 'Z')
1286 {
1287 // function call
1288 if (m_Function)
1289 {
1290 // construct argument list
1291 Value CallArgs = Value(Value::TYPE_LIST);
1292 Value CallArg;
1293 for (size_t i = 0; i < m_Sub.size(); i++)
1294 {
1295 m_Sub[i]->Execute(&CallArg, args);
1296 CallArgs.AccessList().push_back(CallArg);
1297 }
1298 // call function
1299 m_Function->Execute(result, &CallArgs);
1300 }
1301 // variable
1302 else
1303 {
1304 // global variable
1305 if (m_Ch >= 'A' && m_Ch <= 'Z')
1306 {
1307 if (g_GlobalVars.m_Values[m_Ch])
1308 *result = *g_GlobalVars.m_Values[m_Ch];
1309 else
1310 *result = (int)0;
1311 }
1312 // local variable
1313 else
1314 *result = g_VarContextStack.ReadVar(m_Ch);
1315 }
1316 }
1317 else if (m_Ch == '$')
1318 {
1319 Value element;
1320 *result = Value::TYPE_LIST;
1321 for (size_t i = 0; i < m_Sub.size(); i++)
1322 {
1323 m_Sub[i]->Execute(&element, args);
1324 result->AccessList().push_back(element);
1325 }
1326 }
1327 else if (m_Ch == ':')
1328 {
1329 m_Sub[1]->Execute(result, args);
1330 LValue lval = m_Sub[0]->GetLValue(args);
1331 // assign to a value
1332 if (lval.m_Type == LValue::TYPE_VALUE)
1333 *lval.m_Value = *result;
1334 // assign to a string character
1335 else
1336 {
1337 // string with length 1 is expected
1338 Value str_val;
1339 result->ConvertTo(&str_val, Value::TYPE_STRING);
1340 if (str_val.ReadString().length() != 1)
1341 NodeError("Cannot assing to string character string with length: "+Size_tToStr(str_val.ReadString().length()), ERR_EXECUTE);
1342 (*lval.m_String)[lval.m_StringIndex] = str_val.ReadString()[0];
1343 }
1344 }
1345 else if (m_Ch == '#')
1346 {
1347 Value val_l, val_n;
1348 m_Sub[1]->Execute(&val_n, args);
1349 m_Sub[0]->Execute(&val_l, args);
1350 int index = val_n.ConvertToInteger();
1351 if (val_l.GetType() == Value::TYPE_LIST)
1352 {
1353 if (index == -1)
1354 *result = (int)val_l.ReadList().size();
1355 else if (index >= 0 && index < (int)val_l.ReadList().size())
1356 *result = val_l.ReadList()[index];
1357 else
1358 NodeError("Cannot extract element from list with '#' on index: "+IntToStr(index)+" - index out of bounds (list size: "+Size_tToStr(val_l.ReadList().size())+")", ERR_EXECUTE);
1359 }
1360 else if (val_l.GetType() == Value::TYPE_STRING)
1361 {
1362 if (index == -1)
1363 *result = (int)val_l.ReadString().size();
1364 else if (index >= 0 && index < (int)val_l.ReadString().size())
1365 *result = CharToStr(val_l.ReadString()[index]);
1366 else
1367 NodeError("Cannot extract element from string with '#' on index: "+IntToStr(index)+" - index out of bounds (string size: "+Size_tToStr(val_l.ReadString().size())+")", ERR_EXECUTE);
1368 }
1369 else
1370 NodeError("Cannot extract element from "+val_l.GetTypeName()+" with '#' on index: "+IntToStr(index)+" - invalid type", ERR_EXECUTE);
1371 }
1372 else if (m_Ch == '(')
1373 {
1374 *result = (int)0;
1375 for (size_t i = 0; i < m_Sub.size(); i++)
1376 m_Sub[i]->Execute(result, args);
1377 }
1378 else if (m_Ch == '@')
1379 {
1380 *result = (int)0;
1381 Value condition_value;
1382 for (;;)
1383 {
1384 m_Sub[0]->Execute(&condition_value, args);
1385 if (!condition_value.ConvertToBool())
1386 break;
1387 m_Sub[1]->Execute(result, args);
1388 }
1389 }
1390 else if (m_Ch == '?')
1391 {
1392 Value ConditionValue;
1393 m_Sub[0]->Execute(&ConditionValue, args);
1394 if (ConditionValue.ConvertToBool())
1395 m_Sub[1]->Execute(result, args);
1396 else
1397 m_Sub[2]->Execute(result, args);
1398 }
1399 else if (m_Ch == '!') {
1400 m_Sub[0]->Execute(result, args);
1401 result->ConsoleOut();
1402 }
1403 else if (m_Ch == ';')
1404 {
1405 switch (m_ExtraInt)
1406 {
1407 case 0:
1408 *result = Value::TYPE_STRING;
1409 result->AccessString() += g_Console.InChar();
1410 break;
1411 case 1:
1412 *result = g_Console.InInteger();
1413 break;
1414 case 2:
1415 *result = g_Console.InDouble();
1416 break;
1417 case 3:
1418 *result = Value::TYPE_STRING;
1419 g_Console.InString(&result->AccessString());
1420 break;
1421 }
1422 }
1423 else if (m_Ch == '=' || m_Ch == '<' || m_Ch == '>')
1424 {
1425 Value v1, v2;
1426 m_Sub[0]->Execute(&v1, args);
1427 m_Sub[1]->Execute(&v2, args);
1428 OpComparison(m_Ch, result, v1, v2);
1429 }
1430 else if (m_Ch == '+')
1431 {
1432 Value v1, v2;
1433 m_Sub[0]->Execute(&v1, args);
1434 m_Sub[1]->Execute(&v2, args);
1435 OpAdd(result, v1, v2);
1436 }
1437 else if (m_Ch == '-' || m_Ch == '*' || m_Ch == '%')
1438 {
1439 Value v1, v2;
1440 m_Sub[0]->Execute(&v1, args);
1441 m_Sub[1]->Execute(&v2, args);
1442 OpSubMulMod(m_Ch, result, v1, v2);
1443 }
1444 else if (m_Ch == '/' || m_Ch == '^')
1445 {
1446 Value v1, v2;
1447 m_Sub[0]->Execute(&v1, args);
1448 m_Sub[1]->Execute(&v2, args);
1449 OpDivPow(m_Ch, result, v1, v2);
1450 }
1451 else if (m_Ch == '\\')
1452 {
1453 Value v;
1454 m_Sub[0]->Execute(&v, args);
1455 OpFloor(result, v);
1456 }
1457 else if (m_Ch == '&')
1458 {
1459 Value V;
1460 bool B;
1461 m_Sub[0]->Execute(&V, args);
1462 B = V.ConvertToBool();
1463 if (B)
1464 {
1465 m_Sub[1]->Execute(&V, args);
1466 B = V.ConvertToBool();
1467 }
1468 *result = (int)(B ? 1 : 0);
1469 }
1470 else if (m_Ch == '|')
1471 {
1472 Value V;
1473 bool B;
1474 m_Sub[0]->Execute(&V, args);
1475 B = ! V.ConvertToBool();
1476 if (B)
1477 {
1478 m_Sub[1]->Execute(&V, args);
1479 B = ! V.ConvertToBool();
1480 }
1481 *result = (int)(B ? 0 : 1);
1482 }
1483 else if (m_Ch == '[')
1484 {
1485 LValue lval = m_Sub[0]->GetLValue(args);
1486 if (lval.m_Type != LValue::TYPE_VALUE)
1487 NodeError("Tyme mismatch in '[' - list or string expected", ERR_EXECUTE);
1488 if (lval.m_Value->GetType() == Value::TYPE_LIST)
1489 {
1490 if (lval.m_Value->ReadList().empty())
1491 NodeError("Empty list for '['", ERR_EXECUTE);
1492 *result = lval.m_Value->ReadList().back();
1493 lval.m_Value->AccessList().pop_back();
1494 }
1495 else if (lval.m_Value->GetType() == Value::TYPE_STRING)
1496 {
1497 if (lval.m_Value->ReadString().empty())
1498 NodeError("Empty string for '['", ERR_EXECUTE);
1499 *result = CharToStr(lval.m_Value->ReadString()[lval.m_Value->ReadString().size()-1]);
1500 lval.m_Value->AccessString().erase(lval.m_Value->ReadString().size()-1);
1501 }
1502 else
1503 NodeError("Invalid l-value for '[' ("+lval.m_Value->GetTypeName()+") - list or string expected", ERR_EXECUTE);
1504 }
1505 else if (m_Ch == ']')
1506 {
1507 Value NewValue;
1508 m_Sub[1]->Execute(&NewValue, args);
1509 LValue lval = m_Sub[0]->GetLValue(args);
1510
1511 if (lval.m_Type != LValue::TYPE_VALUE)
1512 NodeError("Type mismatch in ']' - list or string expected", ERR_EXECUTE);
1513
1514 if (lval.m_Value->GetType() == Value::TYPE_LIST)
1515 lval.m_Value->AccessList().push_back(NewValue);
1516 else if (lval.m_Value->GetType() == Value::TYPE_STRING)
1517 {
1518 if (NewValue.GetType() != Value::TYPE_STRING || NewValue.ReadString().size() != 1)
1519 NodeError("Invalid argument for ']' - single character expected", ERR_EXECUTE);
1520 lval.m_Value->AccessString() += NewValue.ReadString()[0];
1521 }
1522 else
1523 NodeError("Invalid l-value for ']' ("+lval.m_Value->GetTypeName()+") - list or string expected", ERR_EXECUTE);
1524
1525 *result = *lval.m_Value;
1526 }
1527 else if (m_Ch == '_')
1528 *result = *args;
1529 else if (m_Ch == '\'')
1530 {
1531 Value v;
1532 m_Sub[0]->Execute(&v, args);
1533 OpAposConverter(m_ExtraInt, result, v);
1534 }
1535 else if (m_Ch == '`')
1536 {
1537 // read string
1538 Value str;
1539 m_Sub[0]->Execute(&str, args);
1540 if (str.GetType() != Value::TYPE_STRING)
1541 NodeError("String expected for '`' - found: "+str.GetTypeName(), ERR_EXECUTE);
1542 // parse code
1543 Source src(&str.ReadString());
1544 Node *node = new Node;
1545 node->ParseToEnd(src);
1546 node->Optimize();
1547 node->Execute(result, args);
1548 delete node;
1549 }
1550 else
1551 NodeError("Unknown command: '"+CharToStr(m_Ch)+"'", ERR_EXECUTE);
1552 }
1553
1554 LValue Node::GetLValue(Value *args)
1555 {
1556 // variable
1557 if (m_Ch >= 'a' && m_Ch <= 'z' || m_Ch >= 'A' && m_Ch <= 'Z')
1558 {
1559 // function - error
1560 if (m_Function)
1561 NodeError("Cannot return '"+CharToStr(m_Ch)+"' as l-value - it is a function call", ERR_EXECUTE);
1562 // global variable
1563 if (m_Ch >= 'A' && m_Ch <= 'Z')
1564 {
1565 if (!g_GlobalVars.m_Values[m_Ch])
1566 g_GlobalVars.m_Values[m_Ch] = new Value((int)0);
1567 return LValue(g_GlobalVars.m_Values[m_Ch]);
1568 }
1569 // local variable
1570 else
1571 return LValue(&g_VarContextStack.AccessVar(m_Ch));
1572 }
1573 else if (m_Ch == '_')
1574 return LValue(args);
1575 else if (m_Ch == '(')
1576 {
1577 if (m_Sub.size() == 0)
1578 NodeError("Cannot return empty '(' as l-value", ERR_EXECUTE);
1579 return m_Sub.back()->GetLValue(args);
1580 }
1581 else if (m_Ch == '@')
1582 {
1583 LValue lval;
1584 bool OK = false;
1585 Value condition_value;
1586 for (;;)
1587 {
1588 m_Sub[0]->Execute(&condition_value, args);
1589 if (!condition_value.ConvertToBool())
1590 break;
1591 lval = m_Sub[1]->GetLValue(args);
1592 OK = true;
1593 }
1594 if (!OK)
1595 NodeError("Cannot return loop with 0 iterations as l-value", ERR_EXECUTE);
1596 return lval;
1597 }
1598 else if (m_Ch == '#')
1599 {
1600 LValue result;
1601 Value val_n;
1602 m_Sub[1]->Execute(&val_n, args);
1603 LValue val_l = m_Sub[0]->GetLValue(args);
1604 int index = val_n.ConvertToInteger();
1605
1606 if (val_l.m_Type == LValue::TYPE_STRCHAR)
1607 {
1608 if (index == 0)
1609 result = val_l;
1610 else
1611 NodeError("Cannot return element of string's element as l-value if index "+IntToStr(index)+" is not 0", ERR_EXECUTE);
1612 }
1613 else
1614 {
1615 if (val_l.m_Value->GetType() == Value::TYPE_LIST)
1616 {
1617 if (index >= 0 && index < (int)val_l.m_Value->ReadList().size())
1618 {
1619 result.m_Type = LValue::TYPE_VALUE;
1620 result.m_Value = &val_l.m_Value->AccessList()[index];
1621 }
1622 else
1623 NodeError("Cannot return element of list as l-value - index "+IntToStr(index)+" out of bounds", ERR_EXECUTE);
1624 }
1625 else if (val_l.m_Value->GetType() == Value::TYPE_STRING)
1626 {
1627 if (index >= 0 && index < (int)val_l.m_Value->ReadString().size())
1628 {
1629 result.m_Type = LValue::TYPE_STRCHAR;
1630 result.m_String = &val_l.m_Value->AccessString();
1631 result.m_StringIndex = index;
1632 }
1633 else
1634 NodeError("Cannot return element of string as l-value - index "+IntToStr(index)+" out of bounds", ERR_EXECUTE);
1635 }
1636 else
1637 NodeError("Cannot return element of "+val_l.m_Value->GetTypeName()+" as l-value", ERR_EXECUTE);
1638 }
1639 return result;
1640 }
1641 else if (m_Ch == ']')
1642 {
1643 Value NewValue;
1644 m_Sub[1]->Execute(&NewValue, args);
1645 LValue lval = m_Sub[0]->GetLValue(args);
1646
1647 if (lval.m_Type != LValue::TYPE_VALUE)
1648 NodeError("Type mismatch in ']' - list or string expected", ERR_EXECUTE);
1649
1650 if (lval.m_Value->GetType() == Value::TYPE_LIST)
1651 lval.m_Value->AccessList().push_back(NewValue);
1652 else if (lval.m_Value->GetType() == Value::TYPE_STRING)
1653 {
1654 if (NewValue.GetType() != Value::TYPE_STRING || NewValue.ReadString().size() != 1)
1655 NodeError("Invalid argument for ']' - single character expected", ERR_EXECUTE);
1656 lval.m_Value->AccessString() += NewValue.ReadString()[0];
1657 }
1658 else
1659 NodeError("Invalid l-value for ']' ("+lval.m_Value->GetTypeName()+") - list or string expected", ERR_EXECUTE);
1660
1661 return lval;
1662 }
1663 else if (m_Ch == '?')
1664 {
1665 Value ConditionValue;
1666 m_Sub[0]->Execute(&ConditionValue, args);
1667 if (ConditionValue.ConvertToBool())
1668 return m_Sub[1]->GetLValue(args);
1669 else
1670 return m_Sub[2]->GetLValue(args);
1671 }
1672 else
1673 {
1674 NodeError("Cannot obtain l-value from symbol: '"+CharToStr(m_Ch)+"'", ERR_EXECUTE);
1675 return LValue();
1676 }
1677 }
1678
1679 void Node::Optimize()
1680 {
1681 if (m_Type == TYPE_CONSTANT)
1682 return;
1683
1684 // optimize subnodes
1685 for (size_t i = 0; i < m_Sub.size(); i++)
1686 m_Sub[i]->Optimize();
1687
1688 // optimize this node
1689 if (m_Ch >= '0' && m_Ch <= '9') {
1690 m_Type = TYPE_CONSTANT;
1691 m_Value = (int)(unsigned char)(m_Ch - '0');
1692 }
1693 else if (m_Ch == ',')
1694 {
1695 m_Type = TYPE_CONSTANT;
1696 m_Value = (int)0;
1697 for (size_t i = 0; i < m_Sub.size(); i++)
1698 {
1699 if (m_Sub[i]->m_Type != TYPE_CONSTANT)
1700 m_Sub[i]->NodeError("Cannot evaluate digit value for ',' in compilation time for digit index: " + Size_tToStr(i), ERR_OPTIMIZE);
1701 m_Value.AcceessInteger() = m_Value.AcceessInteger() * 10 + m_Sub[i]->m_Value.ConvertToInteger();
1702 }
1703 ClearSubnodes();
1704 }
1705 else if (m_Ch == '.')
1706 {
1707 m_Type = TYPE_CONSTANT;
1708 m_Value = (double)0.0;
1709 double factor = 0.1;
1710 for (size_t i = 0; i < m_Sub.size(); i++)
1711 {
1712 if (m_Sub[i]->m_Type != Node::TYPE_CONSTANT)
1713 m_Sub[i]->NodeError("Cannot evaluate digit value for '.' in compilation time for digit index: " + Size_tToStr(i), ERR_OPTIMIZE);
1714 m_Value.AccessDouble() += m_Sub[i]->m_Value.ConvertToInteger() * factor;
1715 factor *= 0.1;
1716 }
1717 ClearSubnodes();
1718 }
1719 else if (m_Ch == '(')
1720 {
1721 for (int i = (int)m_Sub.size()-2; i >= 0; i--)
1722 {
1723 if (m_Sub[i]->m_Type == TYPE_CONSTANT)
1724 {
1725 delete m_Sub[i];
1726 m_Sub.erase(m_Sub.begin()+i);
1727 }
1728 }
1729 }
1730 else if (m_Ch == '+')
1731 {
1732 if (m_Sub[0]->m_Type == TYPE_CONSTANT && m_Sub[1]->m_Type == TYPE_CONSTANT)
1733 {
1734 m_Type = TYPE_CONSTANT;
1735 OpAdd(&m_Value, m_Sub[0]->m_Value, m_Sub[1]->m_Value);
1736 ClearSubnodes();
1737 }
1738 }
1739 else if (m_Ch == '-' || m_Ch == '*' || m_Ch == '%')
1740 {
1741 if (m_Sub[0]->m_Type == TYPE_CONSTANT && m_Sub[1]->m_Type == TYPE_CONSTANT)
1742 {
1743 m_Type = TYPE_CONSTANT;
1744 OpSubMulMod(m_Ch, &m_Value, m_Sub[0]->m_Value, m_Sub[1]->m_Value);
1745 ClearSubnodes();
1746 }
1747 }
1748 else if (m_Ch == '/' || m_Ch == '^')
1749 {
1750 if (m_Sub[0]->m_Type == TYPE_CONSTANT && m_Sub[1]->m_Type == TYPE_CONSTANT)
1751 {
1752 m_Type = TYPE_CONSTANT;
1753 OpDivPow(m_Ch, &m_Value, m_Sub[0]->m_Value, m_Sub[1]->m_Value);
1754 ClearSubnodes();
1755 }
1756 }
1757 else if (m_Ch == '\\')
1758 {
1759 if (m_Sub[0]->m_Type == TYPE_CONSTANT)
1760 {
1761 m_Type = TYPE_CONSTANT;
1762 OpFloor(&m_Value, m_Sub[0]->m_Value);
1763 ClearSubnodes();
1764 }
1765 }
1766 else if (m_Ch == '\'')
1767 {
1768 if (m_Sub[0]->m_Type == TYPE_CONSTANT)
1769 {
1770 m_Type = TYPE_CONSTANT;
1771 OpAposConverter(m_ExtraInt, &m_Value, m_Sub[0]->m_Value);
1772 ClearSubnodes();
1773 }
1774 }
1775 else if (m_Ch == '@')
1776 {
1777 if (m_Sub[0]->m_Type == TYPE_CONSTANT && m_Sub[0]->m_Value.ConvertToBool() == false)
1778 {
1779 m_Type = TYPE_CONSTANT;
1780 m_Value = (int)0;
1781 ClearSubnodes();
1782 }
1783 }
1784 else if (m_Ch == '#')
1785 {
1786 if (m_Sub[0]->m_Type == TYPE_CONSTANT && m_Sub[1]->m_Type == TYPE_CONSTANT)
1787 {
1788 m_Type = TYPE_CONSTANT;
1789 Value &val_l = m_Sub[0]->m_Value;
1790 Value &val_n = m_Sub[1]->m_Value;
1791 int index = val_n.ConvertToInteger();
1792 if (val_l.GetType() == Value::TYPE_LIST)
1793 {
1794 if (index == -1)
1795 m_Value = (int)val_l.ReadList().size();
1796 else if (index >= 0 && index < (int)val_l.ReadList().size())
1797 m_Value = val_l.ReadList()[index];
1798 else
1799 NodeError("Cannot extract element from list with '#' on index: "+IntToStr(index)+" - index out of bounds", ERR_OPTIMIZE);
1800 }
1801 else if (val_l.GetType() == Value::TYPE_STRING)
1802 {
1803 if (index == -1)
1804 m_Value = (int)val_l.ReadString().size();
1805 else if (index >= 0 && index < (int)val_l.ReadString().size())
1806 m_Value = CharToStr(val_l.ReadString()[index]);
1807 else
1808 NodeError("Cannot extract element from string with '#' on index: "+IntToStr(index)+" - index out of bounds", ERR_OPTIMIZE);
1809 }
1810 else
1811 NodeError("Cannot extract element from "+val_l.GetTypeName()+" with '#' on index: "+IntToStr(index)+" - invalid type", ERR_OPTIMIZE);
1812 ClearSubnodes();
1813 }
1814 }
1815 else if (m_Ch == '$')
1816 {
1817 size_t i;
1818 for (i = 0; i < m_Sub.size(); i++)
1819 if (m_Sub[i]->m_Type != TYPE_CONSTANT)
1820 return;
1821
1822 m_Type = TYPE_CONSTANT;
1823 m_Value = Value::TYPE_LIST;
1824 Value element;
1825 for (i = 0; i < m_Sub.size(); i++)
1826 m_Value.AccessList().push_back(m_Sub[i]->m_Value);
1827
1828 ClearSubnodes();
1829 }
1830 else if (m_Ch == '&')
1831 {
1832 bool Const1 = (m_Sub[0]->m_Type == TYPE_CONSTANT);
1833 bool Const2 = (m_Sub[1]->m_Type == TYPE_CONSTANT);
1834
1835 if (Const1 && Const2)
1836 {
1837 m_Type = TYPE_CONSTANT;
1838 m_Value = (int)(m_Sub[0]->m_Value.ConvertToBool() && m_Sub[1]->m_Value.ConvertToBool() ? 1 : 0);
1839 ClearSubnodes();
1840 }
1841 else if (Const1 && m_Sub[0]->m_Value.ConvertToBool() == false)
1842 {
1843 m_Type = TYPE_CONSTANT;
1844 m_Value = (int)0;
1845 ClearSubnodes();
1846 }
1847 }
1848 else if (m_Ch == '|')
1849 {
1850 bool Const1 = (m_Sub[0]->m_Type == TYPE_CONSTANT);
1851 bool Const2 = (m_Sub[1]->m_Type == TYPE_CONSTANT);
1852
1853 if (Const1 && Const2)
1854 {
1855 m_Type = TYPE_CONSTANT;
1856 m_Value = (int)(m_Sub[0]->m_Value.ConvertToBool() || m_Sub[1]->m_Value.ConvertToBool() ? 1 : 0);
1857 ClearSubnodes();
1858 }
1859 else if (Const1 && m_Sub[0]->m_Value.ConvertToBool() == true)
1860 {
1861 m_Type = TYPE_CONSTANT;
1862 m_Value = (int)1;
1863 ClearSubnodes();
1864 }
1865 }
1866 else if (m_Ch == '=' || m_Ch == '>' || m_Ch == '<')
1867 {
1868 if (m_Sub[0]->m_Type == TYPE_CONSTANT && m_Sub[1]->m_Type == TYPE_CONSTANT)
1869 {
1870 m_Type = TYPE_CONSTANT;
1871 OpComparison(m_Ch, &m_Value, m_Sub[0]->m_Value, m_Sub[1]->m_Value);
1872 ClearSubnodes();
1873 }
1874 }
1875 else if (m_Ch == '[')
1876 {
1877 if (m_Sub[0]->m_Type == TYPE_CONSTANT)
1878 {
1879 m_Type = TYPE_CONSTANT;
1880
1881 if (m_Sub[0]->m_Value.GetType() == Value::TYPE_LIST)
1882 {
1883 if (m_Sub[0]->m_Value.ReadList().empty())
1884 NodeError("Empty list for '['", ERR_OPTIMIZE);
1885 m_Value = m_Sub[0]->m_Value.ReadList().back();
1886 }
1887 else if (m_Sub[0]->m_Value.GetType() == Value::TYPE_STRING)
1888 {
1889 if (m_Sub[0]->m_Value.ReadString().empty())
1890 NodeError("Empty string for '['", ERR_OPTIMIZE);
1891 m_Value = CharToStr(m_Sub[0]->m_Value.ReadString()[m_Sub[0]->m_Value.ReadString().size()-1]);
1892 }
1893 else
1894 NodeError("Invalid l-value for '[' ("+m_Sub[0]->m_Value.GetTypeName()+") - list or string expected", ERR_OPTIMIZE);
1895
1896 ClearSubnodes();
1897 }
1898 }
1899 else if (m_Ch == '?')
1900 {
1901 if (m_Sub[0]->m_Type == TYPE_CONSTANT && m_Sub[1]->m_Type == TYPE_CONSTANT && m_Sub[2]->m_Type == TYPE_CONSTANT)
1902 {
1903 m_Type = TYPE_CONSTANT;
1904
1905 if (m_Sub[0]->m_Value.ConvertToBool())
1906 m_Value = m_Sub[1]->m_Value;
1907 else
1908 m_Value = m_Sub[2]->m_Value;
1909
1910 ClearSubnodes();
1911 }
1912 }
1913 }
1914
1915 //==============================================================================
1916
1917 Scope *g_GlobalScope;
1918
1919 void Intro()
1920 {
1921 std::cerr << "Badly Developed SADOL Machine\n"
1922 "Version: 2.0, 21 Dec 2005\n"
1923 "\n"
1924 "Copyright (C) 2005 Adam Sawicki\n"
1925 "All rights reserved\n"
1926 "\n"
1927 "Implementation of the SADOL esoteric programming language interpreter.\n"
1928 "\n"
1929 "Usage:\n"
1930 " BDSM <source-file>\n";
1931 }
1932
1933 void Interpret(const string &Src)
1934 {
1935 // std::cout << Src << std::endl;
1936
1937 for (char ch = 'a'; ch < 'z'; ch++)
1938 g_GlobalFunctions[ch] = 0;
1939
1940 Source src_obj(&Src);
1941
1942 g_GlobalScope = new Scope(0, new Node);
1943 g_GlobalScope->ParseToEnd(src_obj);
1944 g_GlobalScope->Optimize();
1945 Value VOut;
1946 Value VArgs = Value(Value::TYPE_LIST);
1947 g_GlobalScope->Execute(&VOut, &VArgs);
1948 delete g_GlobalScope;
1949 }
1950
1951 void Go(const char *FileName)
1952 {
1953 // Open source file
1954 FILE *file = fopen(FileName, "rb");
1955 if (file == 0)
1956 Error("Cannot open file: "+string(FileName));
1957
1958 // Read source into string
1959 char buf[BUF_SIZE];
1960 size_t count;
1961 string src;
1962 for (;;) {
1963 count = fread(buf, 1, BUF_SIZE, file);
1964 if (count > 0) {
1965 src.append(buf, count);
1966 }
1967 else break;
1968 }
1969
1970 // Close source file
1971 fclose(file);
1972
1973 // Interpret!
1974 Interpret(src);
1975 }
1976
1977 int main(int argc, char **argv)
1978 {
1979 if (argc == 2)
1980 {
1981 Go(argv[1]);
1982 return 0;
1983 }
1984 else {
1985 Intro();
1986 return -1;
1987 }
1988 }
1989
1990 /* When error, every function can call Error.
1991 */