using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Threading;
using System.Threading.Tasks;
using miew.String;
using miew.Enumerable;
using miew.Tokenization;
using miew.Concurrency;
using Resources = agree.Properties.Resources;
namespace agree
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public abstract class CommandToken
{
//static int next_id = 0;
public CommandToken(ISysObj iso)
{
this.iso = iso;
//this.id = Interlocked.Increment(ref next_id);
}
public ISysObj Context { get { return iso; } }
readonly public ISysObj iso;
//readonly public int id;
protected Task t;
String error_message = null;
public String ErrorMessage { get { return error_message; } }
public Task Task
{
get { return t; }
protected set { t = value; }
}
public bool IsComplete { get { return t == null || t.IsCompleted; } }
public void TransactionStatus(String fmt, params Object[] args)
{
SystemInstance.TransactionStatus(this, fmt, args);
}
public void AddTransaction(CommandToken ct)
{
SystemInstance.AddTransaction(this, ct);
}
public void Abort(params String[] args)
{
error_message = String.Format(args[0], args.Skip(1).ToArray());
if (args != null && args.Length > 0)
SystemInstance.TransactionStatus(this, error_message);
t = Tasks.CompletedTask;
}
public SysObj SystemInstance
{
get
{
SysObj o;
ISysObj t = iso;
while ((o = t as SysObj) == null)
t = t.SysObjParent;
return o;
}
}
//public void Execute()
//{
// if (t.Status == TaskStatus.Created)
// t.Start();
//}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public abstract class CommandToken<T> : CommandToken
{
public CommandToken(ISysObj so)
: base(so)
{
}
public new Task<T> Task
{
get
{
if (t == null)
throw new Exception();
return t as Task<T>;
}
protected set { t = value; }
}
internal void _complete_and_post(T result)
{
t = Tasks.FromResult<T>(result);
SystemInstance.TransactionStatus(this);
}
internal void _complete_and_post(String fmt, params Object[] args)
{
Debug.Assert(typeof(T) == typeof(String));
t = Tasks.FromResult<String>(String.Format(fmt, args));
SystemInstance.TransactionStatus(this);
}
public Task<CommandToken> QueueResultInteraction(String s)
{
return Task.ContinueWith<CommandToken>(x =>
{
var next_cmd = new SysCommands.CmdTokInteractive((ISysObj)x.Result, s);
return next_cmd.Task.Result;
},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public abstract class CommandSet
{
protected SysObj _so;
public CommandSet(SysObj so)
{
this._so = so;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class SysCommands : CommandSet
{
public SysCommands(SysObj so)
: base(so)
{
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokNop : CommandToken
{
public CmdTokNop(ISysObj iso) : base(iso) { }
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokDisplayMessage : CommandToken<String>
{
public CmdTokDisplayMessage(ISysObj iso, String resource_key, params Object[] args)
: base(iso)
{
_complete_and_post(String.Format(SystemInstance.ResourceManager.GetString(resource_key), args));
}
public CmdTokDisplayMessage(ISysObj iso) : base(iso) { }
public void SetMessage(String fmt, params Object[] args)
{
_complete_and_post(String.Format(fmt, args));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokInteractive : CommandToken<CommandToken>
{
public CmdTokInteractive(ISysObj iso, String s_input)
: base(iso)
{
this.t = Tasks.FromResult<CommandToken>(CommandFromString(iso, s_input));
}
CommandToken CommandFromString(ISysObj iso, String s_input)
{
s_input = s_input.Trim();
if (s_input.Length == 0)
return new CmdTokNop(iso);
if (s_input.StartsWith("/"))
s_input = "/ " + s_input.Substring(1);
String[] rgs = s_input.Split(default(Char[]), StringSplitOptions.RemoveEmptyEntries);
if (rgs.Length == 0)
return new CmdTokNop(iso);
String cmd = rgs[0].ToLower();
rgs = rgs.Skip(1).ToArray();
if (cmd == ".." || cmd == iso.SysObjParent.SysObjName)
return new CmdTokChangeDefaultObject(iso, iso.SysObjParent);
CommandToken ct;
switch (cmd)
{
case "version":
return new CmdTokDisplayVersionInfo(SystemInstance);
case "pwd":
return new CmdTokDisplayCurrentPath(SystemInstance);
case "cd":
if (rgs.Length != 1)
return new CmdTokDisplayMessage(SystemInstance, Resources.ihelpmsg_cd);
return new CmdTokChangeCurrentPath(SystemInstance, rgs[0]);
case "help":
{
CmdTokDisplayMessage xd = new CmdTokDisplayMessage(SystemInstance);
ct = xd;
if (rgs.Length == 0)
{
xd.SetMessage(Resources.ihelpmsg_help);
}
else
{
String sub_help_topic = rgs.StringJoin("_").ToLower();
String sub_help = SystemInstance.ResourceManager.GetString("ihelpmsg_" + sub_help_topic);
if (sub_help != null)
xd.SetMessage(sub_help);
else
xd.SetMessage(Resources.ihelpmsg_unknown_help_topic, sub_help_topic);
}
}
break;
case "/":
case "select":
if (rgs.Length == 1)
return new CmdTokChangeDefaultObject(SystemInstance, rgs[0]);
ct = new CmdTokDisplayMessage(SystemInstance, Resources.msg_need_target, "select");
break;
case "load":
{
if (rgs.Length == 0 || rgs.Length > 2)
{
ct = new CmdTokDisplayMessage(SystemInstance, Resources.ihelpmsg_load);
}
else
{
ct = new CmdTokLoadGrammar(SystemInstance, rgs[0], rgs.Length == 2 ? rgs[1] : null);
}
}
break;
case "cls":
return new CmdTokClearConsole(SystemInstance);
case "unload":
return new CmdTokUnloadGrammar(iso);
case "save":
ct = null;
break;
case "names":
case "*":
return new CmdTokQueryNamePrefix(iso, cmd);
case "show":
if (rgs.Length == 1)
{
CmdTokQueryNamePrefix qp = new CmdTokQueryNamePrefix(iso, rgs[0]);
if (qp != null && qp.Task.Result.Length == 1)
return new CmdTokShowItem(iso, qp.Task.Result[0]);
}
ct = new CmdTokDisplayMessage(SystemInstance);
(ct as CmdTokDisplayMessage).SetMessage(Resources.msg_need_name, cmd);
break;
case "parse":
return new CmdTokParse(iso, rgs.StringJoin(" "));
case "info":
return new CmdTokDisplayGrammarInfo(iso);
default:
{
CmdTokQueryNamePrefix rp = new CmdTokQueryNamePrefix(iso, cmd);
if (rp != null)
{
if (rp.Task.Result.Length == 1)
{
ISysObj so_new = rp.Task.Result[0];
if (so_new.SysObjChildren.Any())
return new CmdTokChangeDefaultObject(SystemInstance, so_new);
return new CmdTokShowItem(iso, so_new);
}
else if (rp.Task.Result.Length > 0)
return rp;
}
}
ct = new CmdTokDisplayMessage(SystemInstance);
(ct as CmdTokDisplayMessage).SetMessage(Resources.errmsg_unknown_cmd, cmd, iso.SysObjName);
break;
}
return ct;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokLoadGrammar : CommandToken<Grammar>
{
public CmdTokLoadGrammar(ISysObj iso, String filename, String name = null, Config config = null)
: base(iso)
{
if (name == null)
name = Path.GetFileNameWithoutExtension(filename);
Grammar g = new Grammar(SystemInstance, name, config);
if (!g.config.system.MultiThreading)
{
g.Load(this, filename);
TaskCompletionSource<Grammar> tcs = new TaskCompletionSource<Grammar>();
tcs.SetResult(g);
t = tcs.Task;
}
else
{
t = new Task<Grammar>(() =>
{
try
{
g.Load(this, filename);
}
catch (Exception ex)
{
TransactionStatus(ex.Message);
}
return g;
});
t.Start();
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokUnloadGrammar : CommandToken<bool>
{
public CmdTokUnloadGrammar(ISysObj target)
: base(target)
{
this.g = target as Grammar;
bool f_result = false;
if (target == null)
{
TransactionStatus(Resources.msg_need_target, "unload");
}
else
{
Grammar g = target as Grammar;
if (g == null)
TransactionStatus(Resources.ihelpmsg_cannot_unload);
else
f_result = true;
}
t = Tasks.FromResult<bool>(f_result);
}
public Grammar g;
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokSaveGrammar : CommandToken
{
public CmdTokSaveGrammar(ISysObj iso, Grammar target, String filename)
: base(iso)
{
if (target == null)
{
Abort(Resources.msg_need_target, "save");
t = Tasks.FromResult<bool>(false);
return;
}
Grammar g = target as Grammar;
if (g == null)
{
TransactionStatus(Resources.ihelpmsg_cannot_save);
t = Tasks.FromResult<bool>(false);
return;
}
else
{
t = Task.Factory.StartNew(() =>
{
g.Save(this, filename);
});
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokDisplayVersionInfo : CmdTokDisplayMessage
{
public CmdTokDisplayVersionInfo(ISysObj iso)
: base(iso)
{
_complete_and_post(SystemInstance.VersionInfo());
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokDisplayCurrentPath : CmdTokDisplayMessage
{
public CmdTokDisplayCurrentPath(ISysObj iso)
: base(iso)
{
_complete_and_post(Environment.CurrentDirectory);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokChangeCurrentPath : CmdTokDisplayMessage
{
public CmdTokChangeCurrentPath(ISysObj iso, String s)
: base(iso)
{
s = Path.Combine(Environment.CurrentDirectory, s);
s += Path.DirectorySeparatorChar;
s = Path.GetFullPath(s);
String msg;
if (Directory.Exists(s))
{
Environment.CurrentDirectory = s;
msg = Environment.CurrentDirectory;
}
else
{
s = s.Trim(Path.DirectorySeparatorChar);
msg = String.Format(Resources.msg_path_not_found, s);
}
_complete_and_post(msg);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokDisplayGrammarInfo : CmdTokDisplayMessage
{
public CmdTokDisplayGrammarInfo(ISysObj target)
: base(target)
{
if (target == null)
{
Abort(Resources.msg_need_target, "info");
return;
}
Grammar g = target as Grammar;
String s;
if (g == null)
s = Resources.ihelpmsg_no_info;
else
s = g.GetInfo();
_complete_and_post(s);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokClearConsole : CommandToken
{
public CmdTokClearConsole(SysObj so)
: base(so)
{
t = Tasks.CompletedTask;
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokQueryNamePrefix : CommandToken<ISysObj[]>
{
public CmdTokQueryNamePrefix(ISysObj target, String s_pfx)
: base(target)
{
if (target == null)
{
Abort(Resources.msg_need_target, "names");
}
else
{
t = Tasks.FromResult<ISysObj[]>(SysObjHelper<ISysObj>.GetNamePrefixMatches(target, s_pfx).ToArray());
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokShowItem : CommandToken<ISysObj>
{
public CmdTokShowItem(ISysObj target, ISysObj obj)
: base(target)
{
if (target == null)
{
Abort(Resources.msg_need_target, "show");
}
else
{
t = Tasks.FromResult<ISysObj>(obj);
}
}
public CmdTokShowItem(ISysObj target, IDerivation obj)
: base(target)
{
if (target == null)
{
Abort(Resources.msg_need_target, "show");
}
else
{
t = Tasks.FromResult<IDerivation>(obj);
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokShowHighlightedItem : CommandToken
{
public ISysObj obj_parent;
public ISysObj obj_highlight;
public CmdTokShowHighlightedItem(ISysObj target, ISysObj obj_parent, ISysObj obj_highlight)
: base(target)
{
this.obj_parent = obj_parent;
this.obj_highlight = obj_highlight;
if (target == null)
{
Abort(Resources.msg_need_target, "show");
}
else
{
t = Tasks.CompletedTask;
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokParse : CommandToken<ParseControl>
{
public CmdTokParse(ISysObj grm, String s)
: base(grm)
{
if (grm == null)
{
Abort(Resources.msg_need_target, "parse");
return;
}
if (String.IsNullOrEmpty(s))
{
Abort(Resources.msg_nothing_to_parse);
return;
}
Grammar g = grm as Grammar;
if (g == null)
{
Abort(Resources.msg_cannot_parse, grm.SysObjName, SysObj.GetObjectTypeName(grm));
}
else
{
try
{
t = g.Parse(s);
}
catch (ParseException ex)
{
Abort(ex.Message);
}
catch (DebuggingTfsDisplayException ex)
{
var exhl = ex as DebuggingTfsDisplayExceptionWithHighlighting;
if (exhl != null)
AddTransaction(new CmdTokShowHighlightedItem(grm, exhl.Tfs[0], exhl.TfsHighlight));
else
{
foreach (var te in ex.Tfs)
AddTransaction(new CmdTokShowItem(grm, te));
}
Abort("parse interrupted");
}
}
}
public CmdTokParse(ISysObj grm, TokenSet ts)
: base(grm)
{
if (grm == null)
{
Abort(Resources.msg_need_target, "parse");
return;
}
if (ts == null || ts.Count == 0)
{
Abort(Resources.msg_nothing_to_parse);
return;
}
Grammar g = grm as Grammar;
if (g == null)
{
Abort(Resources.msg_cannot_parse, grm.SysObjName, SysObj.GetObjectTypeName(grm));
}
else
{
try
{
t = g.Parse(ts);
}
catch (ParseException ex)
{
Abort(ex.Message);
}
catch (DebuggingTfsDisplayException ex)
{
var exhl = ex as DebuggingTfsDisplayExceptionWithHighlighting;
if (exhl != null)
AddTransaction(new CmdTokShowHighlightedItem(grm, exhl.Tfs[0], exhl.TfsHighlight));
else
{
foreach (var te in ex.Tfs)
AddTransaction(new CmdTokShowItem(grm, te));
}
Abort("parse interrupted");
}
}
}
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class CmdTokChangeDefaultObject : CommandToken<ISysObj>
{
public CmdTokChangeDefaultObject(ISysObj target, ISysObj so_new)
: base(target)
{
Finish(target, so_new);
}
public CmdTokChangeDefaultObject(ISysObj target, String s_obj)
: base(target)
{
if (target == null)
{
Abort(Resources.msg_need_target, "select");
return;
}
ISysObj so_new;
if (!target.SysObjChildren.TryGetValue(s_obj, out so_new))
{
Abort(Resources.errmsg_name_not_found, s_obj, target.SysObjName);
return;
}
Finish(target, so_new);
}
public void Finish(ISysObj target, ISysObj so_new)
{
if (target == null)
{
Abort(Resources.msg_need_target, "select");
return;
}
t = Tasks.FromResult<ISysObj>(so_new);
}
};
};
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// <summary>
///
/// </summary>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public class GrammarCommands : SysCommands
{
public GrammarCommands(SysObj so)
: base(so)
{
}
};
}