using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Anonymus
{
public delegate void CodeCondBranchFunc(Compiler Compiler);
public abstract class CondBranch
{
}
public class JumpCodeBranch : CondBranch
{
public int Label;
public JumpCodeBranch(int Label)
{
this.Label = Label;
}
}
public class CodeCondBranch : CondBranch
{
public CodeCondBranchFunc GetCode;
public CodeCondBranch(CodeCondBranchFunc GetCode)
{
this.GetCode = GetCode;
}
}
public abstract class Instruction
{
public bool Skip = false;
public abstract string GetCode(Compiler Comp);
}
public class LabelInstruction : Instruction
{
public int Label;
public LabelInstruction(int Label)
{
this.Label = Label;
}
public override string GetCode(Compiler Comp)
{
return Comp.LabelStr("_" + Label);
}
}
public abstract class JumpInstruction : Instruction
{
public int Label;
public JumpInstruction(int Label)
{
this.Label = Label;
}
public override string GetCode(Compiler Comp)
{
return Comp.JumpStr("_" + Label);
}
}
public class ReplaceableJumpInstruction : JumpInstruction
{
public ReplaceableJumpInstruction(int Label)
: base(Label)
{
}
}
public class StrInstruction : Instruction
{
public string Instruction;
public StrInstruction(string Instruction)
{
this.Instruction = Instruction;
}
public override string GetCode(Compiler Comp)
{
return Instruction;
}
}
public delegate void ReplaceJumpsFunc(Compiler Compiler);
public abstract class Compiler
{
public CompilerState State;
public IdContainer Container;
public List<Instruction> Instructions = new List<Instruction>();
public Dictionary<int, int> LabelPositions;
public Dictionary<int, ReplaceJumpsFunc> ReplaceJumps;
public abstract string JumpStr(string Label);
public abstract string LabelStr(string Label);
public abstract void GetExprCode(ExpressionNode Node);
public abstract void GetConditionCode(ExpressionNode Condition, CondBranch Then,
CondBranch Else, bool ThenAllPathJumpAway = false, bool LinkedNodesCalced = false,
int NextLabel = -1);
public abstract void CalcCondAsmCode(ExpressionNode Node, int Then, int Else,
Operator PrewOp, bool Last, bool LinkedNodesCalced = false);
public abstract void DeclareLabelPtr(string Label);
public abstract void DeclareLabelPtr(int Label);
public abstract void Declare(Type Type, ConstData Data);
public abstract void DeclareUnknownBytes(int Count);
public abstract bool Compile(CompilerState State, PString[] Lines);
public Compiler(CompilerState State)
{
this.State = State;
}
public void Jump(int Label)
{
Instructions.Add(new ReplaceableJumpInstruction(Label));
}
public void Label(int Label, bool Chk = true)
{
if (LabelPositions == null) LabelPositions = new Dictionary<int, int>();
LabelPositions.Add(Label, Instructions.Count);
var Ins = new LabelInstruction(Label);
if (!Chk) Ins.Skip = false;
Instructions.Add(Ins);
}
public void SetJumpReplacing(int Label, ReplaceJumpsFunc Compiler)
{
if (ReplaceJumps == null) ReplaceJumps = new Dictionary<int, ReplaceJumpsFunc>();
ReplaceJumps.Add(Label, Compiler);
}
public void Jump(string Label)
{
Instructions.Add(new StrInstruction(JumpStr(Label)));
}
public void Label(string Label)
{
Instructions.Add(new StrInstruction(LabelStr(Label)));
}
public virtual void InitJumpOptimization()
{
foreach (var e in Instructions)
e.Skip = e is LabelInstruction;
}
public virtual void OptimizeJumps()
{
InitJumpOptimization();
for (var i = 0; i < Instructions.Count; i++)
{
var JumpIns = Instructions[i] as JumpInstruction;
if (JumpIns != null && !JumpIns.Skip)
{
JumpIns.Label = JumpsTo(JumpIns.Label);
var SkipPos = i + 1;
for (; SkipPos < Instructions.Count; SkipPos++)
{
var SIns = Instructions[SkipPos];
var SLabelIns = SIns as LabelInstruction;
if (SLabelIns != null && SLabelIns.Label != JumpIns.Label)
continue;
var SJumpIns = SIns as JumpInstruction;
if (SJumpIns == null || JumpIns.Label != SJumpIns.Label) break;
else SIns.Skip = true;
}
var LblIndex = LabelPositions[JumpIns.Label];
if (SkipPos == LblIndex) JumpIns.Skip = true;
else Instructions[LblIndex].Skip = false;
}
}
}
public virtual void Optimize()
{
OptimizeJumps();
if (ReplaceJumps != null)
{
var New = State.Arch.CreateCompiler(State, Container);
var Count = 0;
for (var i = 0; i < Instructions.Count; i++)
{
var Ins = Instructions[i];
var JumpIns = Ins as ReplaceableJumpInstruction;
if (!Ins.Skip && JumpIns != null && ReplaceJumps.ContainsKey(JumpIns.Label))
{
ReplaceJumps[JumpIns.Label](New);
Count++;
continue;
}
New.Append(Ins);
}
if (Count > 0)
{
Set(New);
Optimize();
}
}
}
void Set(Compiler Compiler)
{
Instructions = Compiler.Instructions;
LabelPositions = Compiler.LabelPositions;
}
public void Insert(int Index, Compiler Comp)
{
var P = Comp != null ? Comp.Instructions.Count - 1 : 0;
if (LabelPositions != null)
{
foreach (var e in LabelPositions.Keys.ToArray())
if (LabelPositions[e] >= Index) LabelPositions[e] += P;
}
if (P > 0)
{
Instructions.InsertRange(Index, Comp.Instructions);
if (Comp.LabelPositions != null)
{
foreach (var e in Comp.LabelPositions)
LabelPositions.Add(e.Key, e.Value + Index);
}
}
}
public int JumpsTo(int Label)
{
var InsIndex = LabelPositions[Label];
for (var i = InsIndex; i < Instructions.Count; i++)
{
var Ins = Instructions[i];
if (Ins is JumpInstruction)
{
var JumpIns = Ins as JumpInstruction;
return JumpsTo(JumpIns.Label);
}
else if (Ins is LabelInstruction)
continue;
else break;
}
return Label;
}
public string GetAssembly()
{
var Ret = new StringBuilder();
foreach (var Ins in Instructions)
if (!Ins.Skip) Ret.Append(Ins.GetCode(this));
return Ret.ToString();
}
public void Append(Compiler Comp)
{
var Count = Instructions.Count;
Instructions.AddRange(Comp.Instructions);
if (Comp.LabelPositions != null)
{
foreach (var e in Comp.LabelPositions)
LabelPositions.Add(e.Key, e.Value + Count);
}
}
public void Append(Instruction Ins)
{
if (Ins is LabelInstruction)
{
var LblIns = Ins as LabelInstruction;
if (LabelPositions == null) LabelPositions = new Dictionary<int, int>();
LabelPositions.Add(LblIns.Label, Instructions.Count);
}
Instructions.Add(Ins);
}
public void Append(string Str)
{
Instructions.Add(new StrInstruction(Str));
}
public void Append(StringBuilder Str)
{
Instructions.Add(new StrInstruction(Str.ToString()));
}
}
public abstract class Architecture
{
public abstract ExprPlugIn CreatePlugIn(IdContainer Container);
public abstract Compiler CreateCompiler(CompilerState State);
public abstract FuncScopeNode CreateFuncScope(IdContainer Parent, PString Name, FunctionType Type, bool IsStatic, PString[] Source);
public abstract void OnNewContainer(IdContainer Container);
public abstract void OnNewIdentifier(Identifier Id);
public abstract void CalcExprDataPos(CompilerState State, IdContainer Container, ExpressionNode Node);
public abstract int GetAlign(Type Type);
public abstract CondBranch[] GetBraches(Compiler Compiler, GlobalScopeNode Global,
Command Then, Command Else, ref ExpressionNode Condition);
public abstract int RegSize { get; }
public abstract int RegCount { get; }
public abstract int MaxStructPow2Size { get; }
public Compiler CreateCompiler(CompilerState State, IdContainer Container)
{
var Ret = CreateCompiler(State);
Ret.Container = Container;
return Ret;
}
}
}