using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Linq;
namespace Anonymus
{
public enum CommRecognizerRes
{
UnknownOp,
Succeeded,
Failed,
}
public abstract class CommRecognizer
{
public virtual CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
return CommRecognizerRes.UnknownOp;
}
public virtual T GetRecognizer<T>() where T : ExprRecognizer
{
if (this is T) return this as T;
else return null;
}
}
public enum ScopeRelation
{
Or,
And,
Other,
}
public delegate bool CommFunc(CodeScopeNode Scope);
public abstract class Command : IdContainer
{
public PString Code;
public bool ChkUnreachable = true;
public bool Unreachable = true;
public int CommIndex;
public abstract IEnumerable<ExpressionNode> EnumExpressions { get; }
public override Variable CreateVariable(PString Name, Type Type, ModifierList Mods = null)
{
var Ret = new LocalVariable(this, Name, Type);
if (Mods != null && !Mods.Apply(this, Ret)) return null;
return Ret;
}
public override void InitCodeChk(bool Unreachable = true)
{
base.InitCodeChk();
this.Unreachable = Unreachable;
}
public Command(IdContainer Parent)
: base(Parent)
{
}
public override MultiPlugIn GetPlugIn()
{
return new LocalPlugIn(this);
}
public virtual IEnumerable<CodeScopeNode> EnumScopes
{
get
{
foreach (var e in EnumChildren)
{
var Scope = e as CodeScopeNode;
if (Scope != null) yield return Scope;
}
}
}
public virtual void GetAsmCode(Compiler Compiler)
{
}
public virtual IEnumerable<CodeScopeNode> GetRunScopes(bool RunScopes = true)
{
if (RunScopes)
{
foreach (var e in EnumScopes)
yield return e;
}
yield break;
}
public override void CalcExprRegs()
{
foreach (var Expr in EnumExpressions)
State.Arch.CalcExprDataPos(State, this, Expr);
base.CalcExprRegs();
}
public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
{
base.ChkCodeRec(Data, ref Succeeded);
foreach (var Expr in EnumExpressions)
{
var D = Expr.Vars;
foreach (var Node in D.AssignedIds)
Data.OnAssign(State, Node.Id, null);
foreach (var Node in D.UsedBeforeAssignIds)
{
var Id = Data.GetId(Node.Id);
if (Id != null) continue;
var Local = Node.Id as LocalVariable;
if (Local != null && !Local.PreAssigned)
{
State.Messages.Add(MessageId.UnassignedVar, Node.Code);
Succeeded = false;
}
}
}
Unreachable = false;
foreach (var Ch in EnumScopes)
if (Ch.ChkCodeRec(Data, ref Succeeded)) return true;
return false;
}
}
public class EmptyCommand : Command
{
public EmptyCommand(IdContainer Parent)
: base(Parent)
{
}
public override IEnumerable<ExpressionNode> EnumExpressions
{ get { yield break; } }
}
public class LabelCommand : Command
{
public int Label;
public LabelCommand(IdContainer Parent, int Label)
: base(Parent)
{
this.Label = Label;
}
public override void GetAsmCode(Compiler Compiler)
{
Compiler.Label(Label);
}
public override IEnumerable<ExpressionNode> EnumExpressions
{ get { yield break; } }
}
public abstract class JumpCommand : Command
{
public int Label;
public bool CodeChk = false;
public JumpCommand(IdContainer Parent, int Label)
: base(Parent)
{
this.Label = Label;
}
public override void GetAsmCode(Compiler Compiler)
{
Compiler.Jump(Label);
}
public override IEnumerable<ExpressionNode> EnumExpressions
{ get { yield break; } }
}
public class GotoCommand : JumpCommand
{
public LabelCommand JumpTo;
public PString LabelName;
public GotoCommand(IdContainer Parent, PString LabelName)
: base(Parent, -1)
{
this.LabelName = LabelName;
}
public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
{
base.ChkCodeRec(Data, ref Succeeded);
if (!CodeChk)
{
Unreachable = false;
CodeChk = true;
var SParent = JumpTo.Parent as CodeScopeNode;
SParent.ChkCodeRec(Data, JumpTo.CommIndex, ref Succeeded);
CodeChk = false;
}
return true;
}
}
public class BreakCommand : JumpCommand
{
public BreakCommand(IdContainer Parent, int Label)
: base(Parent, Label)
{
}
public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
{
if (!CodeChk)
{
Unreachable = false;
CodeChk = true;
var Breakable = GetScope<BreakableCommand>();
var SParent = Breakable.Parent as CodeScopeNode;
SParent.ChkCodeRec(Data, Breakable.CommIndex + 1, ref Succeeded);
CodeChk = false;
}
return true;
}
}
public class ContinueCommand : JumpCommand
{
public ContinueCommand(IdContainer Parent, int Label)
: base(Parent, Label)
{
}
public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
{
Unreachable = false;
CodeChk = true;
return true;
}
}
public class RetCommand : JumpCommand
{
public bool Chk;
public RetCommand(IdContainer Parent, int Label, bool Chk)
: base(Parent, Label)
{
this.Chk = Chk;
}
public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
{
base.ChkCodeRec(Data, ref Succeeded);
if (Chk)
{
var FS = FuncScope;
if (FS.RetMembers != null && !FS.ChkRetMembers(Data, Code))
Succeeded = false;
}
return true;
}
}
public enum ConditionRes
{
True,
Unknown,
False,
}
public class SwitchCommand : ConditionCommand
{
public ExpressionNode Node;
public SwitchCommand(IdContainer Parent)
: base(Parent)
{
}
}
public class CondPart : IdContainer
{
public ExpressionNode Condition;
public CodeScopeNode Then, Else;
public CondPart(ConditionCommand Parent)
: base(Parent)
{
}
public override IEnumerable<IdContainer> EnumChildren
{
get
{
yield return Then;
if (Else != null) yield return Else;
}
}
public override MultiPlugIn GetPlugIn()
{
return new LocalPlugIn(this);
}
public override Variable CreateVariable(PString Name, Type Type, ModifierList Mods = null)
{
var Ret = new LocalVariable(this, Name, Type);
if (Mods != null && !Mods.Apply(this, Ret)) return null;
return Ret;
}
}
public class ConditionCommand : Command
{
public List<CondPart> Conditions = new List<CondPart>();
public ConditionCommand(IdContainer Parent)
: base(Parent)
{
}
public CondPart LastCondition
{
get
{
if (Conditions.Count > 0)
return Conditions[Conditions.Count - 1];
return null;
}
}
static bool ChkCodeRec(CodeScopeNode Scope, CodeChkData Data, List<CodeChkData> Datas, ref bool Failed)
{
var Ret = true;
var NewData = Data.Copy();
if (!Scope.ChkCodeRec(NewData, ref Failed)) Ret = false;
Datas.Add(NewData);
return Ret;
}
public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
{
Unreachable = false;
var Datas = new List<CodeChkData>();
var Ret = true;
foreach (var e in Conditions)
{
if (!ChkCodeRec(e.Then, Data, Datas, ref Succeeded)) Ret = false;
if (e.Else != null)
{
if (!ChkCodeRec(e.Else, Data, Datas, ref Succeeded)) Ret = false;
Data.Vars.AddRange(Datas.Intersect().Vars);
return Ret;
}
}
return false;
}
public CondPart CreateCondition()
{
var Ret = new CondPart(this);
State.Arch.OnNewContainer(Ret);
var L = LastCondition;
if (L != null && L.Condition == null)
Conditions.Insert(Conditions.Count - 1, L);
else Conditions.Add(Ret);
return Ret;
}
public bool HasElseNIf()
{
var L = LastCondition;
return L == null || L.Condition == null || L.Else != null;
}
public override IEnumerable<ExpressionNode> EnumExpressions
{
get
{
foreach (var e in Conditions)
{
if (e.Condition != null)
yield return e.Condition;
}
}
}
public override IEnumerable<IdContainer> EnumChildren
{
get
{
return Conditions;
}
}
object GetElse(CondPart Part, int Index)
{
if (Part.Else != null) return Part.Else;
else if (Index < Conditions.Count - 1) return Index + 1;
else return null;
}
void CalcElse(Compiler Comp, CondPart Part, int Index)
{
if (Part.Else != null) Part.Else.GetAsmCode(Comp);
else if (Index < Conditions.Count - 1) CalcAsmCode(Comp, Index + 1);
}
CondBranch GetDefCondBranch(object Obj)
{
CodeCondBranchFunc Func = null;
if (Obj is CodeScopeNode)
{
var Scope = Obj as CodeScopeNode;
Func = (Comp) => { Scope.GetAsmCode(Comp); };
}
else if (Obj is int)
{
Func = (Comp) => { CalcAsmCode(Comp, (int)Obj); };
}
else
{
throw new Exception("ERROR");
}
return new CodeCondBranch(Func);
}
Command GetCommand(object Obj)
{
var Scope = Obj as CodeScopeNode;
if (Scope == null || Scope.Commands.Count != 1)
return null;
return Scope.Commands[0];
}
int NextLabel;
void CalcAsmCode(Compiler Compiler, int Index)
{
var Part = Conditions[Index];
var Res = ConditionRes.True;
if (Part.Condition != null)
Res = Part.Condition.ConditionResult;
switch (Res)
{
case ConditionRes.Unknown:
var Else = GetElse(Part, Index);
var Cond = Part.Condition;
var ThenCmd = GetCommand(Part.Then);
var ElseCmd = GetCommand(Else);
var Branches = State.Arch.GetBraches(Compiler, GlobalScope, ThenCmd, ElseCmd, ref Cond);
if (Branches[0] == null) Branches[0] = GetDefCondBranch(Part.Then);
if (Branches[1] == null && Else != null) Branches[1] = GetDefCondBranch(Else);
Compiler.GetConditionCode(Cond, Branches[0], Branches[1], NextLabel: NextLabel,
ThenAllPathJumpAway: Part.Then.AllPathJumpAway);
break;
case ConditionRes.True:
Part.Then.GetAsmCode(Compiler);
break;
case ConditionRes.False:
CalcElse(Compiler, Part, Index);
break;
}
}
public override void GetAsmCode(Compiler Compiler)
{
NextLabel = State.NextLabelIndex;
CalcAsmCode(Compiler, 0);
Compiler.Label(NextLabel);
}
public override IEnumerable<CodeScopeNode> GetRunScopes(bool RunScopes = true)
{
bool Run = true;
foreach (var e in Conditions)
{
var Res = ConditionRes.False;
if (Run)
{
if (e.Condition == null) Res = ConditionRes.True;
else Res = e.Condition.ConditionResult;
}
if (Res == ConditionRes.True) Run = false;
if ((Res != ConditionRes.False) == RunScopes) yield return e.Then;
if ((Res != ConditionRes.True) == RunScopes && e.Else != null) yield return e.Else;
}
}
public override IEnumerable<CodeScopeNode> EnumScopes
{
get
{
foreach (var e in Conditions)
{
yield return e.Then;
if (e.Else != null) yield return e.Else;
}
}
}
}
public abstract class BreakableCommand : Command
{
public int BreakLabel;
public int ContinueLabel;
public BreakableCommand(IdContainer Parent)
: base(Parent)
{
BreakLabel = State.NextLabelIndex;
ContinueLabel = State.NextLabelIndex;
}
}
public class LoopCommand : BreakableCommand
{
public CodeScopeNode InnerScope;
public LoopCommand(IdContainer Parent)
: base(Parent)
{
}
public override IEnumerable<IdContainer> EnumChildren
{
get
{
yield return InnerScope;
foreach (var e in base.EnumChildren)
yield return e;
}
}
public override IEnumerable<ExpressionNode> EnumExpressions
{ get { yield break; } }
public override void GetAsmCode(Compiler Compiler)
{
Compiler.Label(ContinueLabel);
if (InnerScope != null) InnerScope.GetAsmCode(Compiler);
Compiler.Jump(ContinueLabel);
Compiler.Label(BreakLabel);
}
}
public class WhileCommand : LoopCommand
{
public ExpressionNode Condition;
public bool DoWhile;
ConditionRes _WillRun;
bool _WillRun_Calced = false;
public ConditionRes WillRun
{
get
{
if (!_WillRun_Calced) _WillRun = WillInnerScopeRun();
return _WillRun;
}
}
public WhileCommand(IdContainer Parent, ExpressionNode Condition, bool DoWhile = false)
: base(Parent)
{
this.Condition = Condition;
this.DoWhile = DoWhile;
}
private void GetConditionCode(bool JumpIfNot, int Then, Compiler Compiler)
{
var OpC = Condition as OpExpressionNode;
var Last = OpC == null ? false : OpC.Operator == Operator.Or;
if (!JumpIfNot) Last = !Last;
Compiler.CalcCondAsmCode(Condition, Then, BreakLabel, Operator.Nothing, Last);
}
public void GetAsmCodeWExp(Compiler Compiler, ExpressionNode Loop = null, bool ChkFirst = true)
{
if (WillRun == ConditionRes.False) return;
var Then = State.NextLabelIndex;
var CondLbl = State.NextLabelIndex;
//--------------------------------------------------------
ReplaceJumpsFunc Func = C =>
{
GetConditionCode(!ChkFirst, Then, C);
if (ChkFirst) C.Jump(BreakLabel);
else C.Jump(Then);
};
Compiler.SetJumpReplacing(CondLbl, Func);
//--------------------------------------------------------
if (ChkFirst)
{
Compiler.Label(CondLbl);
GetConditionCode(ChkFirst, Then, Compiler);
}
Compiler.Label(Then);
if (InnerScope != null) InnerScope.GetAsmCode(Compiler);
Compiler.Label(ContinueLabel);
if (Loop != null) Compiler.GetExprCode(Loop);
if (!ChkFirst)
{
Compiler.Label(CondLbl);
GetConditionCode(ChkFirst, Then, Compiler);
}
else
{
Compiler.Jump(CondLbl);
}
Compiler.Label(BreakLabel);
}
public virtual ConditionRes WillInnerScopeRun()
{
return Condition.ConditionResult;
}
public override IEnumerable<CodeScopeNode> GetRunScopes(bool RunScopes = true)
{
if (RunScopes)
{
if (WillRun != ConditionRes.False)
yield return InnerScope;
}
else
{
if (WillRun == ConditionRes.False)
yield return InnerScope;
}
}
public override void GetAsmCode(Compiler Compiler)
{
GetAsmCodeWExp(Compiler, null, !DoWhile);
}
public override IEnumerable<ExpressionNode> EnumExpressions
{ get { yield return Condition; } }
}
public class ForCommand : WhileCommand
{
public ExpressionNode Loop, Init;
public bool WillRunCalced = false;
public ForCommand(IdContainer Parent, ExpressionNode Condition, ExpressionNode Loop, ExpressionNode Init)
: base(Parent, Condition, false)
{
this.Loop = Loop;
this.Init = Init;
}
public override void GetAsmCode(Compiler Compiler)
{
if (Init != null) Compiler.GetExprCode(Init);
GetAsmCodeWExp(Compiler, Loop, WillInnerScopeRun() != ConditionRes.True);
}
public override ConditionRes WillInnerScopeRun()
{
var Res = base.WillInnerScopeRun();
if (Res != ConditionRes.Unknown) return Res;
ExpressionNode AssignTo = null;
Variable AssignVar = null;
if (Init is OpExpressionNode)
{
var OpNode = Init as OpExpressionNode;
if (OpNode.Operator == Operator.Assignment)
{
var Ch = OpNode.Children;
AssignTo = Ch[1];
OpNode.GetAssignVar(ref AssignVar);
}
}
if (AssignVar != null && !AssignTo.IdUsed())
{
var ConstAssignTo = AssignTo as ConstExpressionNode;
if (ConstAssignTo == null) return ConditionRes.Unknown;
var OpCondition = Condition as OpExpressionNode;
if (OpCondition == null) return ConditionRes.Unknown;
var Op = OpCondition.Operator;
var Ch = OpCondition.Children;
if (!Operators.IsRelEqualityOp(Op)) return ConditionRes.Unknown;
var IdCh0 = Ch[0] as IdExpressionNode;
if (IdCh0 == null || IdCh0.Id != AssignVar) return ConditionRes.Unknown;
var ConstCh1 = Ch[1] as ConstExpressionNode;
if (ConstCh1 == null) return ConditionRes.Unknown;
var NewCh = new List<ExpressionNode>() { ConstAssignTo, ConstCh1 };
var NewNode = new OpExpressionNode(Op, NewCh, null);
var Ret = ConstExpressionNode.DoOps(this, NewNode);
return Ret.ConditionResult;
}
return ConditionRes.Unknown;
}
public override IEnumerable<ExpressionNode> EnumExpressions
{
get
{
yield return Loop;
yield return Init;
yield return Condition;
}
}
}
public class ExpressionCommand : Command
{
public ExpressionNode Expression;
public ExpressionCommand(IdContainer Parent, ExpressionNode Expression)
: base(Parent)
{
this.Expression = Expression;
}
public override IEnumerable<ExpressionNode> EnumExpressions
{ get { yield return Expression; } }
public override void GetAsmCode(Compiler Compiler)
{
// sb.Append("\n\t; " + Expression.CompData().Code.String + "\n");
Compiler.GetExprCode(Expression);
}
}
public class AsmCommand : Command
{
public List<object> List = new List<object>();
public AsmCommand(IdContainer Parent)
: base(Parent)
{
}
public bool Process(CompilerState State, PString AsmCode)
{
var Ret = true;
var Pos = AsmCode.IndexOf('$');
var PlugIn = GetPlugIn();
while (Pos != -1)
{
List.Add(AsmCode.String.Substring(0, Pos));
AsmCode = AsmCode.Substring(Pos + 1);
var VarName = AsmCode.Word();
var Node = PlugIn.NewNode(new StrExpressionNode(VarName));
if (!(Node is IdExpressionNode))
{
State.Messages.Add(MessageId.AsmNotRId, VarName);
Node = null;
}
if (Node == null) Ret = false;
else List.Add(Node);
Pos = AsmCode.IndexOf('$');
}
if (AsmCode.String != "")
List.Add(AsmCode.String);
return Ret;
}
public override void GetAsmCode(Compiler Compiler)
{
Compiler.Append("\t");
foreach (var e in List)
{
if (e is string) Compiler.Append(e as string);
#warning WARNING
//else if (e is ExpressionNode) Compiler.Append(Compiler.GetPositionString((e as ExpressionNode), null));
else throw new Exception("ERROR");
}
Compiler.Append("\n");
}
public override IEnumerable<ExpressionNode> EnumExpressions
{ get { yield break; } }
}
}