MODULE ConsInterp;

	(*
		A. V. Shiryaev, 2012.09, 2019.10
	*)

	IMPORT
		Console, Dialog,
		DevCommanders, TextModels,
		StdLog;

	VAR
		textR: TextModels.Reader;

	PROCEDURE ShowStdLog;
		VAR c: CHAR;
	BEGIN
		StdLog.text.Append(StdLog.buf);

		textR.SetPos(0);
		textR.ReadChar(c);
		WHILE ~textR.eot DO
			IF c = 0DX THEN
				Console.WriteLn
			ELSE
				Console.WriteChar(c)
			END;
			textR.ReadChar(c)
		END;
		StdLog.text.Delete(0, StdLog.text.Length())
	END ShowStdLog;

	PROCEDURE Call1 (IN s: ARRAY OF CHAR; i: INTEGER): BOOLEAN;
		VAR j: INTEGER;
			res: INTEGER;
			par: DevCommanders.Par;
			m: TextModels.Model; w: TextModels.Writer;
	BEGIN
		(* ASSERT 0X in s[ i:LEN(s) ) *)
		j := i;
		WHILE s[j] # 0X DO INC(j) END;
		IF j > i THEN
			m := TextModels.dir.New();
			w := m.NewWriter(NIL);
			WHILE i < j DO
				w.WriteChar(s[i]);
				INC(i)
			END;
			NEW(par); par.text := m; par.beg := 0; par.end := m.Length();
			DevCommanders.par := par
		END;
		Dialog.Call(s, " ", res);
		DevCommanders.par := NIL;
		ShowStdLog;
	RETURN res = 0
	END Call1;

	PROCEDURE Call0 (VAR s: ARRAY OF CHAR): BOOLEAN;
		VAR i: INTEGER;
			res: BOOLEAN;
			inStr: BOOLEAN;
	BEGIN
		(* ASSERT s is 0X terminated and not empty *)
		i := 0;
		WHILE (s[i] # 0X) & (s[i] # ' ') & (s[i] # '(') DO
			INC(i)
		END;
		IF s[i] = 0X THEN
			res := Call1(s, i)
		ELSIF s[i] = ' ' THEN
			s[i] := 0X;
			res := Call1(s, i + 1)
		ELSE (* s[i] = '(' *)
			INC(i);
			inStr := FALSE;
			WHILE (s[i] # 0X) & ~(~inStr & (s[i] = ')')) DO
				IF s[i] = "'" THEN inStr := ~inStr END;
				INC(i)
			END;
			IF s[i] # 0X THEN
				INC(i);
				IF s[i] = 0X THEN
					res := Call1(s, i)
				ELSE
					s[i] := 0X;
					res := Call1(s, i + 1)
				END
			ELSE
				res := FALSE
			END
		END;
	RETURN res
	END Call0;

	PROCEDURE Call (VAR s: ARRAY OF CHAR): BOOLEAN;
		VAR i: INTEGER;
			res: BOOLEAN;
	BEGIN
		i := 0;
		WHILE (i < LEN(s)) & (s[i] # 0AX) & (s[i] # 0DX) & (s[i] # 0X) DO
			INC(i)
		END;
		IF (i < LEN(s)) & (s[i] # 0X) THEN
			IF (i > 0) & (s[0] # '#') THEN
				s[i] := 0X;
				res := Call0(s)
			ELSE (* skip empty strings and comments *)
				res := TRUE
			END
		ELSE (* end of input *)
			res := FALSE
		END;
	RETURN res
	END Call;

	PROCEDURE Run*;
		VAR s: ARRAY 4096 OF CHAR;
	BEGIN
		Console.ReadLn(s);
		WHILE Call(s) DO
			Console.ReadLn(s)
		END
	END Run;

BEGIN
	textR := StdLog.text.NewReader(NIL)
END ConsInterp.
