1 #include <Esc/Esc.h>
2 
3 
4 namespace Upp {
5 
6 #ifdef _MSC_VER
7 #pragma inline_depth(255)
8 #pragma optimize("t", on)
9 #endif
10 
11 #define LTIMING(x)  // RTIMING(x)
12 
OutOfMemory()13 void Esc::OutOfMemory()
14 {
15 	ThrowError("Out of memory");
16 }
17 
TestLimit()18 void Esc::TestLimit()
19 {
20 	LTIMING("TestLimit");
21 	if(!IsNull(op_limit))
22 		if(op_limit < 0)
23 			ThrowError("out of operations limit - considered frozen");
24 	if(EscValue::GetTotalCount() >= EscValue::GetMaxTotalCount())
25 		OutOfMemory();
26 }
27 
Get(const SRVal & val)28 EscValue Esc::Get(const SRVal& val)
29 {
30 	LTIMING("Get");
31 	if(skipexp)
32 		return (int64)1;
33 	EscValue v = val.lval ? *val.lval : val.rval;
34 	if(val.sbs.IsArray()) {
35 		const Vector<EscValue>& sbs = val.sbs.GetArray();
36 		for(int i = 0; i < sbs.GetCount(); i++) {
37 			const EscValue& ss = sbs[i];
38 			if(v.IsMap()) //!!!! (problem with a[1, 2]
39 				v = v.MapGet(ss);
40 			else
41 			if(v.IsArray()) {
42 				int count = v.GetCount();
43 				if(ss.IsArray() && ss.GetArray().GetCount() >= 2) {
44 					EscValue v1 = ss.ArrayGet(0);
45 					EscValue v2 = ss.ArrayGet(1);
46 					int i = v1.GetInt();
47 					int n = count - i;
48 					if(ss.GetCount() == 2)
49 						n = v2.IsInt() ? v2.GetInt() : n;
50 					else {
51 						if(v2.IsInt()) {
52 							n = v2.GetInt();
53 							if(n < 0)
54 								n += count;
55 							n -= i;
56 						}
57 					}
58 					if(i >= 0 && n >= 0 && i + n <= count)
59 						v = v.ArrayGet(i, n);
60 					else
61 						ThrowError("slice out of range");
62 				}
63 				else {
64 					int64 i = Int(ss, "index");
65 					if(i < 0)
66 						i += count;
67 					if(i >= 0 && i < count)
68 						v = v.ArrayGet((int)i);
69 					else
70 						ThrowError("index out of range");
71 				}
72 			}
73 			else
74 				ThrowError("invalid indirection");
75 			TestLimit();
76 		}
77 	}
78 	return v;
79 }
80 
Assign(EscValue & val,const Vector<EscValue> & sbs,int si,const EscValue & src)81 void Esc::Assign(EscValue& val, const Vector<EscValue>& sbs, int si, const EscValue& src)
82 {
83 	LTIMING("Assign");
84 	const EscValue& ss = sbs[si++];
85 	if(val.IsVoid())
86 		val.SetEmptyMap();
87 	if(val.IsMap()) {
88 		if(si < sbs.GetCount()) {
89 			EscValue x = val.MapGet(ss);
90 			val.MapSet(ss, 0.0);
91 			Assign(x, sbs, si, src);
92 			val.MapSet(ss, x);
93 		}
94 		else
95 			val.MapSet(ss, src);
96 		return;
97 	}
98 	else
99 	if(val.IsArray()) {
100 		if(si < sbs.GetCount()) {
101 			if(ss.IsArray())
102 				ThrowError("slice must be last subscript");
103 			int64 i = Int(ss, "index");
104 			if(i >= 0 && i < val.GetCount()) {
105 				EscValue x = val.ArrayGet((int)i);
106 				val.ArraySet((int)i, 0.0);
107 				Assign(x, sbs, si, src);
108 				if(!val.ArraySet((int)i, x))
109 					OutOfMemory();
110 				return;
111 			}
112 		}
113 		else {
114 			int count = val.GetCount();
115 			if(ss.IsArray()) {
116 				if(!src.IsArray() || ss.GetArray().GetCount() < 2)
117 					ThrowError("only array can be assigned to the slice");
118 				EscValue v1 = ss.ArrayGet(0);
119 				EscValue v2 = ss.ArrayGet(1);
120 				int i = v1.IsInt() ? v1.GetInt() : 0;
121 				int n = count - i;
122 				if(ss.GetCount() == 2)
123 					n = v2.IsInt() ? v2.GetInt() : n;
124 				else {
125 					if(v2.IsInt()) {
126 						n = v2.GetInt();
127 						if(n < 0)
128 							n += count;
129 						n -= i;
130 					}
131 				}
132 				if(i >= 0 && n >= 0 && i + n <= count) {
133 					val.Replace(i, n, src);
134 					return;
135 				}
136 				else
137 					ThrowError("slice out of range");
138 			}
139 			else {
140 				int64 i = ss.IsVoid() ? val.GetCount() : Int(ss, "index");
141 				if(i < 0)
142 					i = count + i;
143 				if(i >= 0 && i < INT_MAX) {
144 					if(!val.ArraySet((int)i, src))
145 						ThrowError("out of memory");
146 					return;
147 				}
148 			}
149 		}
150 	}
151 	ThrowError("invalid indirection");
152 }
153 
Assign(const SRVal & val,const EscValue & src)154 void Esc::Assign(const SRVal& val, const EscValue& src)
155 {
156 	if(skipexp)
157 		return;
158 	if(!val.lval)
159 		ThrowError("l-value required");
160 	if(val.sbs.IsArray() && val.sbs.GetCount())
161 		Assign(*val.lval, val.sbs.GetArray(), 0, src);
162 	else
163 		*val.lval = src;
164 }
165 
ExecuteLambda(const String & id,EscValue lambda,SRVal self,Vector<SRVal> & arg)166 EscValue Esc::ExecuteLambda(const String& id, EscValue lambda, SRVal self, Vector<SRVal>& arg)
167 {
168 	LTIMING("ExecuteLambda");
169 	if(!lambda.IsLambda())
170 		ThrowError(Format("'%s' is not a lambda", id));
171 	const EscLambda& l = lambda.GetLambda();
172 	if(!l.varargs && arg.GetCount() > l.arg.GetCount()
173 	   || arg.GetCount() < l.arg.GetCount() - l.def.GetCount())
174 		ThrowError("invalid number of arguments in call to '" + id + "'");
175 	Esc sub(global, l.code, op_limit, l.filename, l.line);
176 	sub.self = Get(self);
177 	for(int i = 0; i < l.arg.GetCount(); i++) {
178 		sub.var.GetAdd(l.arg[i]) =
179 			i < arg.GetCount() ? Get(arg[i])
180 		                       : Evaluatex(l.def[i - (l.arg.GetCount() - l.def.GetCount())], global, op_limit);
181 		TestLimit();
182 	}
183 	EscValue retval;
184 	Array<EscValue> argvar;
185 	if(l.escape) {
186 		argvar = sub.var.PickValues();
187 		for(int i = l.arg.GetCount(); i < arg.GetCount(); i++) {
188 			argvar.Add(Get(arg[i]));
189 		}
190 		EscValue v = Get(self);
191 		EscEscape e(*this, v, argvar);
192 		e.id = id;
193 		l.escape(e);
194 		retval = e.ret_val;
195 		self = e.self;
196 	}
197 	else {
198 		if(l.varargs) {
199 			EscValue& argv = sub.var.GetAdd("argv");
200 			argv.SetEmptyArray();
201 			for(int i = l.arg.GetCount(); i < arg.GetCount(); i++)
202 				argv.ArrayAdd(Get(arg[i]));
203 		}
204 		sub.Run();
205 		retval = sub.return_value;
206 		argvar = sub.var.PickValues();
207 	}
208 	for(int i = 0; i < l.inout.GetCount(); i++)
209 		if(l.inout[i] && i < arg.GetCount() && arg[i].lval)
210 			Assign(arg[i], argvar[i]);
211 	if(self.lval)
212 		Assign(self, sub.self);
213 	return retval;
214 }
215 
Subscript(Esc::SRVal & r,Esc::SRVal _self,String id)216 void Esc::Subscript(Esc::SRVal& r, Esc::SRVal _self, String id)
217 {
218 	LTIMING("Subscript");
219 	for(;;) {
220 		TestLimit();
221 		if(Char('['))
222 			if(Char(']'))
223 				r.sbs.ArrayAdd(EscValue());
224 			else {
225 				EscValue v1, v2;
226 				if(!IsChar(',') && !IsChar(':'))
227 					v1 = GetExp();
228 				if(Char(',')) {
229 					if(!IsChar(']'))
230 						v2 = GetExp();
231 					EscValue x;
232 					x.ArrayAdd(v1);
233 					x.ArrayAdd(v2);
234 					r.sbs.ArrayAdd(x);
235 				}
236 				else
237 				if(Char(':')) {
238 					if(!IsChar(']'))
239 						v2 = GetExp();
240 					EscValue x;
241 					x.ArrayAdd(v1);
242 					x.ArrayAdd(v2);
243 					x.ArrayAdd(EscValue());
244 					r.sbs.ArrayAdd(x);
245 				}
246 				else
247 					r.sbs.ArrayAdd(v1);
248 				PassChar(']');
249 			}
250 		else
251 		if(Char('.')) {
252 			_self = r;
253 			r.sbs.ArrayAdd(id = ReadId());
254 		}
255 		else
256 		if(Char('(')) {
257 			LTIMING("call fn");
258 			Vector<SRVal> arg;
259 			if(!Char(')'))
260 				for(;;) {
261 					LTIMING("make args");
262 					Exp(arg.Add());
263 					if(Char(')')) break;
264 					PassChar(',');
265 				}
266 			if(!IsChar2('!', '=') && Char('!')) {
267 				Term(_self);
268 				EscValue g = Get(_self);
269 				if(!_self.lval || (!g.IsVoid() && !g.IsMap()))
270 					ThrowError("l-value map or l-value void expected on the right side of !");
271 				if(g.IsVoid()) {
272 					EscValue v;
273 					v.SetEmptyMap();
274 					Assign(_self, v);
275 				}
276 			}
277 			if(!skipexp)
278 				try {
279 					r = ExecuteLambda(id, Get(r), _self, arg);
280 				}
281 				catch(Exc e) {
282 					throw Error(Format("%s.%s(): %s", Get(r).GetTypeName(), id, e));
283 				}
284 		}
285 		else
286 			return;
287 	}
288 }
289 
Subscript(Esc::SRVal & r)290 void Esc::Subscript(Esc::SRVal& r)
291 {
292 	Subscript(r, SRVal(), String());
293 }
294 
Term(SRVal & r)295 void Esc::Term(SRVal& r)
296 {
297 	r.sbs = EscValue();
298 
299 	op_limit--;
300 	TestLimit();
301 	if(Char2('0', 'x') || Char2('0', 'X')) {
302 		r = ReadNumber64(16);
303 		return;
304 	}
305 	if(Char2('0', 'b') || Char2('0', 'B')) {
306 		r = ReadNumber64(2);
307 		return;
308 	}
309 	if(IsChar2('0', '.')) {
310 		r = ReadDouble();
311 		return;
312 	}
313 	if(Char('0')) {
314 		r = IsNumber() ? ReadNumber64(8) : 0;
315 		return;
316 	}
317 	if(IsNumber()) {
318 		// TODO: int64 !
319 		r = ReadDouble();
320 		return;
321 	}
322 	if(IsString()) {
323 		r = EscValue(FromUtf8(ReadString()));
324 		return;
325 	}
326 	if(IsChar('\'')) {
327 		WString s = FromUtf8(ReadString('\''));
328 		if(s.GetLength() != 1)
329 			ThrowError("invalid character literal");
330 		r = (int64)s[0];
331 		return;
332 	}
333 	if(Char('@')) {
334 		r = ReadLambda(*this);
335 		Subscript(r);
336 		return;
337 	}
338 	if(Id("void")) {
339 		r = EscValue();
340 		return;
341 	}
342 	if(Char('{')) {
343 		EscValue map;
344 		map.SetEmptyMap();
345 		if(!Char('}'))
346 			for(;;) {
347 				EscValue v = GetExp();
348 				PassChar(':');
349 				map.MapSet(v, GetExp());
350 				if(Char('}'))
351 					break;
352 				PassChar(',');
353 				TestLimit();
354 			}
355 		r = map;
356 		Subscript(r);
357 		return;
358 	}
359 	if(Char('[')) {
360 		EscValue array;
361 		array.SetEmptyArray();
362 		if(!Char(']'))
363 			for(;;) {
364 				array.ArrayAdd(GetExp());
365 				if(Char(']'))
366 					break;
367 				PassChar(',');
368 				TestLimit();
369 			}
370 		r = array;
371 		Subscript(r);
372 		return;
373 	}
374 	if(Char('(')) {
375 		Exp(r);
376 		PassChar(')');
377 		Subscript(r);
378 		return;
379 	}
380 
381 	SRVal _self;
382 	bool  _global = false;
383 	if(Char('.')) {
384 		if(!self.IsMap())
385 			ThrowError("member-access in non-member code");
386 		_self.lval = &self;
387 	}
388 	else
389 	if(Char(':'))
390 		_global = true;
391 	if(IsId()) {
392 		String id = ReadId();
393 		EscValue method;
394 		int locali = var.Find(id);
395 		int ii;
396 
397 		if(id == "self") {
398 			if(!self.IsMap())
399 				ThrowError("self in non-member code");
400 			_self.lval = &self;
401 			r = self;
402 		}
403 		else
404 		if(!_self.lval && !_global && locali < 0 && IsChar('(') &&
405 		   self.IsMap() && (method = self.MapGet(id)).IsLambda()) {
406 		    _self.lval = &self;
407 			r = method;
408 		}
409 		else
410 		if(!_self.lval && !_global && locali < 0 && IsChar('(') &&
411 		   (ii = global.Find(id)) >= 0 && global[ii].IsLambda()) {
412 			r = global[ii];
413 		}
414 		else
415 		if(_self.lval) {
416 			r = _self;
417 			r.sbs.ArrayAdd(id);
418 		}
419 		else
420 		if(_global)
421 			r.lval = &global.GetPut(id);
422 		else
423 			r.lval = &var.GetPut(id);
424 
425 		try {
426 			Subscript(r, _self, id);
427 		}
428 		catch(CParser::Error e) {
429 			throw CParser::Error(id + ": " + e);
430 		}
431 	}
432 	else
433 		ThrowError("invalid expression");
434 }
435 
Lims(const String & s)436 String Lims(const String& s)
437 {
438 	return s.GetLength() > 80 ? s.Mid(0, 80) : s;
439 }
440 
Number(const EscValue & a,const char * oper)441 double Esc::Number(const EscValue& a, const char *oper)
442 {
443 	if(!a.IsNumber())
444 		ThrowError(String().Cat() << "number expected for '" << oper << "', encountered " << Lims(a.ToString()));
445 	return a.GetNumber();
446 }
447 
Int(const EscValue & a,const char * oper)448 int64 Esc::Int(const EscValue& a, const char *oper)
449 {
450 	if(!a.IsNumber())
451 		ThrowError(String().Cat() << "integer expected for '" << oper << "', encountered " << Lims(a.ToString()));
452 	return a.GetInt64();
453 }
454 
Number(const Esc::SRVal & a,const char * oper)455 double Esc::Number(const Esc::SRVal& a, const char *oper)
456 {
457 	return Number(Get(a), oper);
458 }
459 
Int(const Esc::SRVal & a,const char * oper)460 int64 Esc::Int(const Esc::SRVal& a, const char *oper)
461 {
462 	return Int(Get(a), oper);
463 }
464 
Unary(Esc::SRVal & r)465 void Esc::Unary(Esc::SRVal& r)
466 {
467 	if(Char2('+', '+')) {
468 		Unary(r);
469 		EscValue v = Get(r);
470 		if(v.IsInt64())
471 			Assign(r, Int(v, "++") + 1);
472 		else
473 			Assign(r, Number(v, "++") + 1);
474 	}
475 	else
476 	if(Char2('-', '-')) {
477 		Unary(r);
478 		EscValue v = Get(r);
479 		if(v.IsInt64())
480 			Assign(r, Int(v, "--") - 1);
481 		else
482 			Assign(r, Number(v, "--") - 1);
483 	}
484 	else
485 	if(Char('-')) {
486 		Unary(r);
487 		EscValue v = Get(r);
488 		if(v.IsInt64())
489 			r = -Int(v, "-");
490 		else
491 			r = -Number(v, "-");
492 	}
493 	else
494 	if(Char('+')) {
495 		Unary(r);
496 		EscValue v = Get(r);
497 		if(v.IsInt64())
498 			r = Int(v, "+");
499 		else
500 			r = Number(v, "+");
501 	}
502 	else
503 	if(Char('!')) {
504 		Unary(r);
505 		r = (int64)!IsTrue(Get(r));
506 	}
507 	else
508 	if(Char('~')) {
509 		Unary(r);
510 		r = ~Int(Get(r), "~");
511 	}
512 	else
513 		Term(r);
514 
515 	if(Char2('+', '+')) {
516 		EscValue v = Get(r);
517 		if(v.IsInt64())
518 			Assign(r, Int(v, "++") + 1);
519 		else
520 			Assign(r, Number(v, "++") + 1);
521 		r = v;
522 	}
523 	if(Char2('-', '-')) {
524 		EscValue v = Get(r);
525 		if(v.IsInt64())
526 			Assign(r, Int(v, "--") - 1);
527 		else
528 			Assign(r, Number(v, "--") - 1);
529 		r = v;
530 	}
531 }
532 
MulArray(EscValue array,EscValue times)533 EscValue Esc::MulArray(EscValue array, EscValue times)
534 {
535 	EscValue r;
536 	r.SetEmptyArray();
537 	for(int n = times.GetInt(); n > 0; n >>= 1) {
538 		if(n & 1)
539 			if(!r.Append(array))
540 				OutOfMemory();
541 		if(!array.Append(array))
542 			OutOfMemory();
543 		TestLimit();
544 	}
545 	return r;
546 }
547 
Mul(Esc::SRVal & r)548 void Esc::Mul(Esc::SRVal& r)
549 {
550 	Unary(r);
551 	for(;;)
552 		if(!IsChar2('*', '=') && Char('*')) {
553 			EscValue x = Get(r);
554 			SRVal w;
555 			Unary(w);
556 			EscValue y = Get(w);
557 			if(x.IsArray() && y.IsInt())
558 				r = MulArray(x, y);
559 			else
560 			if(y.IsArray() && x.IsInt())
561 				r = MulArray(y, x);
562 			else
563 			if(x.IsInt64() && y.IsInt64())
564 				r = Int(x, "*") * Int(y, "*");
565 			else
566 				r = Number(x, "*") * Number(y, "*");
567 		}
568 		else
569 		if(!IsChar2('/', '=') && Char('/')) {
570 			SRVal w;
571 			Unary(w);
572 			EscValue x = Get(r);
573 			EscValue y = Get(w);
574 			double b = Number(y, "/");
575 			if(b == 0)
576 				ThrowError("divide by zero");
577 			r = Number(x, "/") / b;
578 		}
579 		else
580 		if(!IsChar2('%', '=') && Char('%')) {
581 			SRVal w;
582 			Unary(w);
583 			int64 b = Int(w, "%");
584 			if(b == 0)
585 				ThrowError("divide by zero");
586 			r = Int(r, "%") % b;
587 		}
588 		else
589 			return;
590 }
591 
Add(Esc::SRVal & r)592 void Esc::Add(Esc::SRVal& r)
593 {
594 	Mul(r);
595 	for(;;)
596 		if(!IsChar2('+', '=') && Char('+')) {
597 			EscValue v = Get(r);
598 			SRVal w;
599 			Mul(w);
600 			EscValue b = Get(w);
601 			if(v.IsArray() && b.IsArray()) {
602 				if(!v.Replace(v.GetCount(), 0, b))
603 					OutOfMemory();
604 				r = v;
605 			}
606 			else
607 			if(!(v.IsArray() && b.IsVoid())) {
608 				if(v.IsInt64() && b.IsInt64())
609 					r = Int(v, "+") + Int(b, "+");
610 				else
611 					r = Number(v, "+") + Number(b, "+");
612 			}
613 		}
614 		else
615 		if(!IsChar2('-', '=') && Char('-')) {
616 			SRVal w;
617 			Mul(w);
618 			EscValue v = Get(r);
619 			EscValue b = Get(w);
620 			if(v.IsInt64() && b.IsInt64())
621 				r = Int(v, "-") - Int(b, "-");
622 			else
623 				r = Number(v, "-") - Number(b, "-");
624 		}
625 		else
626 			return;
627 }
628 
Shift(Esc::SRVal & r)629 void Esc::Shift(Esc::SRVal& r)
630 {
631 	Add(r);
632 	for(;;)
633 		if(Char2('<', '<')) {
634 			EscValue v = Get(r);
635 			SRVal w;
636 			Add(w);
637 			EscValue b = Get(w);
638 			if(v.IsArray() && b.IsArray()) {
639 				if(!v.Replace(v.GetCount(), 0, b))
640 					OutOfMemory();
641 				Assign(r, v);
642 			}
643 			else
644 			if(!(v.IsArray() && b.IsVoid()))
645 				r = Int(v, "<<") << Int(b, "<<");
646 		}
647 		else
648 		if(Char2('>', '>')) {
649 			SRVal w;
650 			Add(w);
651 			r = Int(r, ">>") >> Int(w,  ">>");
652 		}
653 		else
654 			return;
655 }
656 
DoCompare(const EscValue & a,const EscValue & b,const char * op)657 double Esc::DoCompare(const EscValue& a, const EscValue& b, const char *op)
658 {
659 	LTIMING("DoCompare");
660 	if(a.IsInt64() && b.IsInt64())
661 		return SgnCompare(a.GetInt64(), b.GetInt64());
662 	if(a.IsNumber() && b.IsNumber())
663 		return SgnCompare(a.GetNumber(), b.GetNumber());
664 	if(a.IsArray() && b.IsArray()) {
665 		const Vector<EscValue>& x = a.GetArray();
666 		const Vector<EscValue>& y = b.GetArray();
667 		int i = 0;
668 		for(;;) {
669 			if(i >= x.GetCount())
670 				return i < y.GetCount() ? -1 : 0;
671 			if(i >= y.GetCount())
672 				return i < x.GetCount() ? 1 : 0;
673 			double q = DoCompare(x[i], y[i], op);
674 			if(q) return q;
675 			i++;
676 		}
677 	}
678 	if(a.IsVoid() && b.IsVoid())
679 		return 0;
680 	if(!a.IsVoid() && b.IsVoid())
681 		return 1;
682 	if(a.IsVoid() && !b.IsVoid())
683 		return -1;
684 	ThrowError("invalid values for comparison " + a.GetTypeName() + ' ' + op + ' ' + b.GetTypeName());
685 	return 0;
686 }
687 
DoCompare(const SRVal & a,const char * op)688 double Esc::DoCompare(const SRVal& a, const char *op)
689 {
690 	SRVal w;
691 	Shift(w);
692 	return DoCompare(Get(a), Get(w), op);
693 }
694 
Compare(Esc::SRVal & r)695 void Esc::Compare(Esc::SRVal& r)
696 {
697 	Shift(r);
698 	for(;;)
699 		if(Char2('>', '='))
700 			r = DoCompare(r, ">=") >= 0;
701 		else
702 		if(Char2('<', '='))
703 			r = DoCompare(r, "<=") <= 0;
704 		else
705 		if(Char('>'))
706 			r = DoCompare(r, ">") > 0;
707 		else
708 		if(Char('<'))
709 			r = DoCompare(r, "<") < 0;
710 		else
711 			return;
712 }
713 
Equal(Esc::SRVal & r)714 void Esc::Equal(Esc::SRVal& r)
715 {
716 	Compare(r);
717 	for(;;)
718 		if(Char2('=', '=')) {
719 			SRVal w;
720 			Compare(w);
721 			r = Get(r) == Get(w);
722 		}
723 		else
724 		if(Char2('!', '=')) {
725 			SRVal w;
726 			Compare(w);
727 			r = Get(r) != Get(w);
728 		}
729 		else
730 			return;
731 }
732 
BinAnd(Esc::SRVal & r)733 void Esc::BinAnd(Esc::SRVal& r)
734 {
735 	Equal(r);
736 	while(!IsChar2('&', '&') && Char('&')) {
737 		SRVal w;
738 		Equal(w);
739 		r = Int(r, "&") & Int(w, "&");
740 	}
741 }
742 
BinXor(Esc::SRVal & r)743 void Esc::BinXor(Esc::SRVal& r)
744 {
745 	BinAnd(r);
746 	while(Char('^')) {
747 		SRVal w;
748 		BinAnd(w);
749 		r = Int(r, "^") ^ Int(w, "^");
750 	}
751 }
752 
BinOr(Esc::SRVal & r)753 void Esc::BinOr(Esc::SRVal& r)
754 {
755 	BinXor(r);
756 	while(!IsChar2('|', '|') && Char('|')) {
757 		SRVal w;
758 		BinXor(w);
759 		r = Int(r, "|") | Int(w, "|");
760 	}
761 }
762 
And(Esc::SRVal & r)763 void Esc::And(Esc::SRVal& r)
764 {
765 	BinOr(r);
766 	if(IsChar2('&', '&')) {
767 		bool b = IsTrue(Get(r));
768 		while(Char2('&', '&')) {
769 			SRVal w;
770 			if(b) {
771 				BinOr(w);
772 				b = b && IsTrue(Get(w));
773 			}
774 			else {
775 				skipexp++;
776 				BinOr(w);
777 				skipexp--;
778 			}
779 		}
780 		r = b;
781 	}
782 }
783 
Or(Esc::SRVal & r)784 void Esc::Or(Esc::SRVal& r)
785 {
786 	And(r);
787 	if(IsChar2('|', '|')) {
788 		bool b = IsTrue(Get(r));
789 		while(Char2('|', '|')) {
790 			SRVal w;
791 			if(b) {
792 				skipexp++;
793 				And(w);
794 				skipexp--;
795 			}
796 			else {
797 				And(w);
798 				b = b || IsTrue(Get(w));
799 			}
800 		}
801 		r = b;
802 	}
803 }
804 
Cond(Esc::SRVal & r)805 void Esc::Cond(Esc::SRVal& r)
806 {
807 	Or(r);
808 	if(Char('?')) {
809 		bool t = IsTrue(Get(r));
810 		SRVal dummy;
811 		if(t) {
812 			Cond(r);
813 			PassChar(':');
814 			skipexp++;
815 			Cond(dummy);
816 			skipexp--;
817 		}
818 		else {
819 			skipexp++;
820 			Cond(dummy);
821 			skipexp--;
822 			PassChar(':');
823 			Cond(r);
824 		}
825 	}
826 }
827 
Assign(Esc::SRVal & r)828 void Esc::Assign(Esc::SRVal& r)
829 {
830 	Cond(r);
831 	if(Char('=')) {
832 		SRVal w;
833 		Assign(w);
834 		Assign(r, Get(w));
835 	}
836 	else
837 	if(Char2('+', '=')) {
838 		EscValue v = Get(r);
839 		SRVal w;
840 		Cond(w);
841 		EscValue b = Get(w);
842 		if(v.IsArray() && b.IsArray()) {
843 			if(!v.Replace(v.GetCount(), 0, b))
844 				OutOfMemory();
845 			Assign(r, v);
846 		}
847 		else
848 		if(!(v.IsArray() && b.IsVoid())) {
849 			if(v.IsInt64() && b.IsInt64())
850 				Assign(r, Int(v, "+=") + Int(b, "+="));
851 			else
852 				Assign(r, Number(v, "+=") + Number(b, "+="));
853 		}
854 	}
855 	else
856 	if(Char2('-', '=')) {
857 		SRVal w;
858 		Cond(w);
859 		EscValue v = Get(r);
860 		EscValue b = Get(w);
861 		if(v.IsInt64() && b.IsInt64())
862 			Assign(r, Int(v, "-=") - Int(b, "-="));
863 		else
864 			Assign(r, Number(v, "-=") - Number(b, "-="));
865 	}
866 	else
867 	if(Char2('*', '=')) {
868 		SRVal w;
869 		Cond(w);
870 		EscValue x = Get(r);
871 		EscValue y = Get(w);
872 		if(x.IsInt64() && y.IsInt64())
873 			Assign(r, Int(x, "*=") * Int(y, "*="));
874 		else
875 			Assign(r, Number(x, "*=") * Number(y, "*="));
876 	}
877 	else
878 	if(Char2('/', '=')) {
879 		SRVal w;
880 		Cond(w);
881 		EscValue v = Get(r);
882 		EscValue b = Get(w);
883 		double q = Number(v, "/=");
884 		if(q == 0)
885 			ThrowError("divide by zero");
886 		Assign(r, Number(b, "/=") / q);
887 	}
888 	else
889 	if(Char2('%', '=')) {
890 		SRVal w;
891 		Cond(w);
892 		int64 a = Int(r, "%=");
893 		int64 b = Int(w, "%=");
894 		if(b == 0)
895 			ThrowError("divide by zero");
896 		Assign(r, a % b);
897 	}
898 }
899 
900 int Esc::stack_level = 50;
901 
Exp(Esc::SRVal & r)902 void Esc::Exp(Esc::SRVal& r)
903 {
904 	LTIMING("Exp");
905 	Spaces();
906 	stack_level--;
907 	if(stack_level <= 0)
908 		ThrowError("stack overflow");
909 	Assign(r);
910 	stack_level++;
911 }
912 
GetExp()913 EscValue Esc::GetExp() {
914 	SRVal r;
915 	Exp(r);
916 	return Get(r);
917 }
918 
SkipTerm()919 void Esc::SkipTerm()
920 {
921 	if(IsEof())
922 		ThrowError("unexpected end of file");
923 	CParser::SkipTerm();
924 	Spaces();
925 }
926 
SkipExp()927 void Esc::SkipExp()
928 {
929 	int level = 0;
930 	for(;;) {
931 		if(IsChar(';'))
932 			return;
933 		if(IsChar(')') && level == 0)
934 			return;
935 		if(Char(')'))
936 			level--;
937 		else
938 		if(Char('('))
939 			level++;
940 		else
941 			SkipTerm();
942 		if(IsEof())
943 			ThrowError("unexpected end of file");
944 	}
945 }
946 
SkipBlock(CParser & p)947 void SkipBlock(CParser& p)
948 {
949 	int level = 1;
950 	while(level > 0 && !p.IsEof()) {
951 		if(p.Char('{')) level++;
952 		else
953 		if(p.Char('}')) level--;
954 		else
955 			p.SkipTerm();
956 	}
957 }
958 
SkipStatement()959 void Esc::SkipStatement()
960 {
961 	stack_level--;
962 	if(stack_level <= 0)
963 		ThrowError("stack overflow");
964 	if(Id("if")) {
965 		PassChar('(');
966 		SkipExp();
967 		PassChar(')');
968 		SkipStatement();
969 		if(Id("else"))
970 			SkipStatement();
971 	}
972 	else
973 	if(Id("for")) {
974 		PassChar('(');
975 		if(!IsChar(';'))
976 			SkipExp();
977 		PassChar(';');
978 		if(!IsChar(';'))
979 			SkipExp();
980 		PassChar(';');
981 		if(!IsChar(')'))
982 			SkipExp();
983 		PassChar(')');
984 		SkipStatement();
985 	}
986 	else
987 	if(Id("while") || Id("switch")) {
988 		PassChar('(');
989 		SkipExp();
990 		PassChar(')');
991 		SkipStatement();
992 	}
993 	else
994 	if(Id("do")) {
995 		SkipBlock(*this);
996 		PassId("while");
997 		PassChar('(');
998 		SkipExp();
999 		PassChar(')');
1000 		PassChar(';');
1001 	}
1002 	else
1003 	if(Char('{'))
1004 		SkipBlock(*this);
1005 	else {
1006 		SkipExp();
1007 		PassChar(';');
1008 	}
1009 	stack_level++;
1010 }
1011 
PCond()1012 bool  Esc::PCond()
1013 {
1014 	PassChar('(');
1015 	bool c = IsTrue(GetExp());
1016 	PassChar(')');
1017 	return c;
1018 }
1019 
FinishSwitch()1020 void Esc::FinishSwitch()
1021 {
1022 	while(no_break && no_return && no_continue) {
1023 		if(Id("case")) {
1024 			SRVal r;
1025 			Exp(r);
1026 			PassChar(':');
1027 		}
1028 		else
1029 		if(Id("default"))
1030 			PassChar(':');
1031 		else
1032 			if(Char('}'))
1033 				return;
1034 		DoStatement();
1035 	}
1036 	while(!Char('}'))
1037 		SkipStatement();
1038 }
1039 
DoStatement()1040 void  Esc::DoStatement()
1041 {
1042 	op_limit--;
1043 	TestLimit();
1044 	if(Id("if"))
1045 		if(PCond()) {
1046 			DoStatement();
1047 			if(Id("else"))
1048 				SkipStatement();
1049 		}
1050 		else {
1051 			SkipStatement();
1052 			if(Id("else"))
1053 				DoStatement();
1054 		}
1055 	else
1056 	if(Id("do")) {
1057 		loop++;
1058 		Pos pos = GetPos();
1059 		do {
1060 			SetPos(pos);
1061 			DoStatement();
1062 			PassId("while");
1063 			no_continue = true;
1064 		}
1065 		while(PCond() && no_break && no_return);
1066 		PassChar(';');
1067 		no_break = true;
1068 		loop--;
1069 	}
1070 	else
1071 	if(Id("while")) {
1072 		loop++;
1073 		Pos pos = GetPos();
1074 		for(;;) {
1075 			SetPos(pos);
1076 			if(!PCond() || !no_break || !no_return || !no_continue) {
1077 				SkipStatement();
1078 				break;
1079 			}
1080 			DoStatement();
1081 			no_continue = true;
1082 		}
1083 		no_break = true;
1084 		loop--;
1085 	}
1086 	else
1087 	if(Id("for")) {
1088 		loop++;
1089 		PassChar('(');
1090 		SRVal var;
1091 		if(!IsChar(';'))
1092 			Exp(var);
1093 		if(Id("in") || Char(':')) {
1094 			EscValue range = GetExp();
1095 			PassChar(')');
1096 			Pos stmt = GetPos();
1097 			int i = 0;
1098 			for(;;) {
1099 				SetPos(stmt);
1100 				if(range.IsArray()) {
1101 					if(i >= range.GetCount())
1102 						break;
1103 					Assign(var, (int64)i);
1104 				}
1105 				else
1106 				if(range.IsMap()) {
1107 					const VectorMap<EscValue, EscValue>& map = range.GetMap();
1108 					if(i >= map.GetCount())
1109 						break;
1110 					if(map.IsUnlinked(i)) {
1111 						i++;
1112 						continue;
1113 					}
1114 					Assign(var, map.GetKey(i));
1115 				}
1116 				if(!no_break || !no_return || !no_continue) {
1117 					SkipStatement();
1118 					break;
1119 				}
1120 				DoStatement();
1121 				no_continue = true;
1122 				i++;
1123 			}
1124 			SkipStatement();
1125 		}
1126 		else {
1127 			PassChar(';');
1128 			Pos cond;
1129 			if(!IsChar(';')) {
1130 				cond = GetPos();
1131 				SkipExp();
1132 			}
1133 			PassChar(';');
1134 			Pos after;
1135 			if(!IsChar(')')) {
1136 				after = GetPos();
1137 				SkipExp();
1138 			}
1139 			PassChar(')');
1140 			Pos stmt = GetPos();
1141 			for(;;) {
1142 				bool c = true;
1143 				if(cond.ptr) {
1144 					SetPos(cond);
1145 					c = IsTrue(GetExp());
1146 				}
1147 				SetPos(stmt);
1148 				if(!c || !no_break || !no_return || !no_continue) {
1149 					SkipStatement();
1150 					break;
1151 				}
1152 				DoStatement();
1153 				no_continue = true;
1154 				if(after.ptr) {
1155 					SetPos(after);
1156 					SRVal r;
1157 					Exp(r);
1158 				}
1159 			}
1160 		}
1161 		no_break = true;
1162 		loop--;
1163 	}
1164 	else
1165 	if(Id("break")) {
1166 		if(!loop)
1167 			ThrowError("misplaced 'break'");
1168 		no_break = false;
1169 		PassChar(';');
1170 	}
1171 	else
1172 	if(Id("continue")) {
1173 		if(!loop)
1174 			ThrowError("misplaced 'continue'");
1175 		no_continue = false;
1176 		PassChar(';');
1177 	}
1178 	else
1179 	if(Id("case"))
1180 		ThrowError("misplaced 'case'");
1181 	else
1182 	if(Id("default"))
1183 		ThrowError("misplaced 'default'");
1184 	else
1185 	if(Id("else"))
1186 		ThrowError("misplaced 'else'");
1187 	else
1188 	if(Id("return")) {
1189 		no_return = false;
1190 		if(!Char(';')) {
1191 			return_value = GetExp();
1192 			PassChar(';');
1193 		}
1194 		else
1195 			return_value = EscValue();
1196 	}
1197 	else
1198 	if(Id("switch")) {
1199 		loop++;
1200 		PassChar('(');
1201 		EscValue a = GetExp();
1202 		PassChar(')');
1203 		PassChar('{');
1204 		while(!Char('}')) {
1205 			if(Id("case")) {
1206 				EscValue b = GetExp();
1207 				PassChar(':');
1208 				if(a == b) {
1209 					FinishSwitch();
1210 					break;
1211 				}
1212 			}
1213 			else
1214 			if(Id("default")) {
1215 				PassChar(':');
1216 				FinishSwitch();
1217 				break;
1218 			}
1219 			else
1220 				SkipStatement();
1221 		}
1222 		loop--;
1223 		no_break = true;
1224 	}
1225 	else
1226 	if(Char('#')) {
1227 		int type = 0;
1228 		if(Char('.'))
1229 			type = 1;
1230 		else
1231 		if(Char(':'))
1232 			type = 2;
1233 		String id = ReadId();
1234 		EscValue l = ReadLambda(*this);
1235 		if(type == 1) {
1236 			if(self.IsVoid())
1237 				ThrowError("no instance");
1238 			self.MapSet(id, l);
1239 		}
1240 		else
1241 		if(type == 2)
1242 			global.GetAdd(id) = l;
1243 		else
1244 			var.GetAdd(id) = l;
1245 	}
1246 	else
1247 	if(Char('{')) {
1248 		while(!Char('}') && no_break && no_return && no_continue)
1249 			DoStatement();
1250 	}
1251 	else
1252 	if(!Char(';')) {
1253 		SRVal v;
1254 		Exp(v);
1255 		PassChar(';');
1256 	}
1257 }
1258 
Run()1259 void  Esc::Run()
1260 {
1261 	no_return = no_break = no_continue = true;
1262 	loop = 0;
1263 	skipexp = 0;
1264 	while(!IsEof() && no_return && no_break && no_continue)
1265 		DoStatement();
1266 }
1267 
1268 }
1269