using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Anonymus
{
public class IdentifierList : List<Identifier>
{
public T GetIdRec<T>(string Name) where T : Identifier
{
var PrevList = new IdentifierList();
PrevList.AddRange(this);
foreach (var Id in this)
if ((Name == null || Id.Name.String == Name) && Id is T)
return Id as T;
return null;
}
}
public abstract class Identifier
{
public IdContainer Container;
public Architecture Arch;
public PString Name;
public object ArchData;
public bool IsStatic = false;
public bool IsSealed = false;
public bool CanBeInReg;
public bool Used = false;
public bool DeclInThis = true;
public virtual void SetUsed()
{
Used = true;
}
string _AsmName = null;
public string AsmName
{
get
{
if (_AsmName == null)
{
_AsmName = "_" + Name.String;
var Structured = Container as StructuredTypeScope;
if (Structured != null) _AsmName = Structured.GetAsmName() + _AsmName;
}
return _AsmName;
}
set
{
_AsmName = value;
}
}
public Identifier(IdContainer Container, PString Name)
{
this.Name = Name;
this.CanBeInReg = true;
this.IsStatic = false;
this.Container = Container;
if (Container != null)
this.Arch = Container.State.Arch;
}
public virtual void GetAsmCode(Compiler Comp, GetAsmCodeMode Mode)
{
}
}
public class ChkAssignedId
{
public Identifier Id;
public List<ExpressionNode> Nodes;
public bool Used;
public ChkAssignedId(Identifier Id, ExpressionNode Node, bool Used = false)
: this(Id, new List<ExpressionNode>() { Node })
{
}
public ChkAssignedId(Identifier Id, List<ExpressionNode> Nodes, bool Used = false)
{
this.Id = Id;
this.Nodes = Nodes;
this.Used = Used;
}
}
public class CodeChkData
{
public List<ChkAssignedId> Vars = new List<ChkAssignedId>();
public ChkAssignedId GetId(Identifier Id)
{
foreach (var e in Vars)
if (e.Id == Id) return e;
return null;
}
public void ChkVars(IdContainer Container)
{
for (var i = 0; i < Vars.Count; i++)
if (!Container.IsSubContainer(Vars[i].Id.Container))
{
Vars.RemoveAt(i);
i--;
}
}
public bool IsAssigned(Identifier Id)
{
foreach (var e in Vars)
if (e.Id == Id) return true;
return false;
}
public void OnAssign(CompilerState State, Identifier Id, ExpressionNode Node)
{
var I = GetId(Id);
if (I == null)
{
I = new ChkAssignedId(Id, Node);
Vars.Add(I);
}
else
{
I.Nodes.Clear();
I.Nodes.Add(Node);
if (I.Used)
{
#warning WARNING
}
}
}
public CodeChkData Copy()
{
var Ret = new CodeChkData();
Ret.Vars.AddRange(Vars);
return Ret;
}
}
public static class CodeChkDataExtensions
{
public static CodeChkData Intersect(this IEnumerable<CodeChkData> Datas)
{
var Ret = new CodeChkData();
var First = true;
foreach (var Data in Datas)
{
if (First)
{
Ret.Vars.AddRange(Data.Vars);
First = false;
continue;
}
var Old = Ret.Vars.ToArray();
Ret.Vars.Clear();
foreach (var e in Data.Vars)
foreach (var f in Old)
if (f.Id == e.Id)
{
var Nodes = f.Nodes.Union(e.Nodes).ToList();
Ret.Vars.Add(new ChkAssignedId(e.Id, Nodes, f.Used && e.Used));
break;
}
}
return Ret;
}
}
public enum ModifierType
{
Static,
Final,
Public,
Private,
Protected,
StdCall,
CDecl,
AsCall,
AsmName,
}
public class Modifier
{
public ModifierType Type;
public PString FLine;
public PString Name;
public List<PString> Params;
public Modifier(ModifierType Type, PString Name, PString FLine, List<PString> Params = null)
{
this.Type = Type;
this.Name = Name;
this.FLine = FLine;
this.Params = Params;
}
}
public class ModifierList : List<Modifier>
{
public Modifier GetModifier(ModifierType ModType)
{
foreach (var e in this)
if (e.Type == ModType) return e;
return null;
}
public bool Contains(ModifierType ModType)
{
return GetModifier(ModType) != null;
}
bool ChkCallConv(CompilerState State, Identifier Id, ModifierType ModType, ref bool CallConv)
{
var Mod = GetModifier(ModType);
if (Mod == null) return false;
if (!(Id is Function))
{
State.Messages.Add(MessageId.CallConvErr, Mod.Name);
return false;
}
else if (CallConv)
{
State.Messages.Add(MessageId.NotExpected, Mod.Name);
return false;
}
return true;
}
public bool Apply(IdContainer Container, Identifier Id)
{
var State = Container.State;
var CallConv = false;
var Mod = (Modifier)null;
//--------------------------------------------------------------------------------------
if ((Mod = GetModifier(ModifierType.Static)) != null)
{
if (!(Id is ClassType) && !(Id.Container is StructuredTypeScope))
{
State.Messages.Add(MessageId.StaticErr, Mod.Name);
return false;
}
Id.IsStatic = true;
}
else
{
var SCont = Id.Container as StructuredTypeScope;
if (SCont != null && SCont.Type.IsStatic)
{
State.Messages.Add(MessageId.NonStaticInStaticClass, Id.Name);
return false;
}
}
//--------------------------------------------------------------------------------------
if ((Mod = GetModifier(ModifierType.Final)) != null)
{
if (!(Id is StructuredType) && !(Id.Container is StructuredTypeScope))
{
State.Messages.Add(MessageId.SealedErr, Mod.Name);
return false;
}
else if (Id.IsStatic)
{
State.Messages.Add(MessageId.StaticSealed, Mod.Name);
return false;
}
Id.IsSealed = true;
}
//--------------------------------------------------------------------------------------
if ((Mod = GetModifier(ModifierType.AsmName)) != null)
{
if (Mod.Params.Count != 1)
{
State.Messages.Add(MessageId.ParamCount, Mod.FLine);
return false;
}
var PlugIn = new GlobalPlugIn(Container);
PlugIn.GetPlugIn<TypeMgrPlugIn>().RetType = Container.GlobalScope.CStrType;
var Node = Expressions.Recognize(Mod.Params[0], PlugIn, false);
if (Node == null) return false;
Id.AsmName = (Node as ConstExpressionNode).String;
}
//--------------------------------------------------------------------------------------
if (ChkCallConv(State, Id, ModifierType.StdCall, ref CallConv))
{
var Func = Id as Function;
Func.Type.Conv = Anonymus.CallConv.StdCall;
}
if (ChkCallConv(State, Id, ModifierType.CDecl, ref CallConv))
{
var Func = Id as Function;
Func.Type.Conv = Anonymus.CallConv.CDecl;
}
if (ChkCallConv(State, Id, ModifierType.AsCall, ref CallConv))
{
var Func = Id as Function;
Func.Type.Conv = Anonymus.CallConv.AsCall;
}
//--------------------------------------------------------------------------------------
return true;
}
}
public class ModifierAttributes
{
public ModifierType Type;
public string Name;
public bool AllowParameters;
public ModifierAttributes(ModifierType Type, string Name, bool AllowParameters = false)
{
this.Type = Type;
this.Name = Name;
this.AllowParameters = AllowParameters;
}
}
public static class Modifiers
{
public static List<ModifierAttributes> ModifiersLst;
static Modifiers()
{
ModifiersLst = new List<ModifierAttributes>();
ModifiersLst.Add(new ModifierAttributes(ModifierType.Static, "static"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.Final, "final"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.Public, "public"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.Protected, "protected"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.Private, "private"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.StdCall, "stdcall"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.CDecl, "cdecl"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.AsCall, "ascall"));
ModifiersLst.Add(new ModifierAttributes(ModifierType.AsmName, "asmname", true));
}
public static ModifierList GetModifiers(CompilerState State, ref PString Line)
{
var Ret = new ModifierList();
while (true)
{
var FLine = Line.Copy();
var ModifierStr = Line.Word(WordStart: true, InZ: true);
var Word = ModifierStr.Word();
var Index = 0;
var Found = false;
foreach (var e in ModifiersLst)
{
if (e.Name == Word.String)
{
if (Ret.Contains(e.Type))
{
State.Messages.Add(MessageId.NotExpected, Word);
return null;
}
var Params = (List<PString>)null;
if (ModifierStr.StrLen > 0 && ModifierStr[0] == '(')
{
var ZPos = BracketHelper.ZPos(ModifierStr.String);
if (ZPos == -1)
{
State.Messages.Add(MessageId.ZNumErr, FLine);
return null;
}
var StrParams = ModifierStr.TrimmedSubstring(1, ZPos - 1);
ModifierStr = ModifierStr.TrimmedSubstring(ZPos + 1);
Params = new List<PString>();
var Recognizer = State.Language.ArgRecognizer;
if (!Recognizer.SplitArgs(State, StrParams, Params))
return null;
if (!e.AllowParameters)
{
State.Messages.Add(MessageId.ModParamsNotAllowed, StrParams);
return null;
}
}
else if (e.AllowParameters)
{
State.Messages.Add(MessageId.MissingParam, Word);
return null;
}
if (ModifierStr.StrLen > 0)
{
State.Messages.Add(MessageId.NotExpected, ModifierStr);
return null;
}
Ret.Add(new Modifier(e.Type, Word, ModifierStr, Params));
Found = true;
break;
}
Index++;
}
if (!Found)
{
Line = FLine;
break;
}
};
return Ret;
}
}
public enum CallConv
{
StdCall,
CDecl,
AsCall,
}
public class Function : Identifier
{
public FuncScopeNode FunctionScope;
public FunctionType Type;
public Function(IdContainer Container, PString Name, FunctionType Type, FuncScopeNode Scope)
: base(Container, Name)
{
this.Type = Type;
this.FunctionScope = Scope;
}
public override void GetAsmCode(Compiler Comp, GetAsmCodeMode Mode)
{
if (Mode == GetAsmCodeMode.Code && FunctionScope != null)
{
Comp.Label(AsmName);
Comp.Append(FunctionScope.GetFunctionCode());
Comp.Append("\n");
}
}
}
public class MemberFunction : Function
{
public int Offset = -1;
public MemberFunction(IdContainer Container, PString Name, FunctionType Type, FuncScopeNode Scope)
: base(Container, Name, Type, Scope)
{
}
}
public class ConstructorFunction : Function
{
public ConstructorFunction(IdContainer Container, PString Name, FunctionType Type, FuncScopeNode Scope)
: base(Container, Name, Type, Scope)
{
;
}
}
public abstract class Variable : Identifier
{
public Type Type;
public ExpressionNode InitValue;
public ConstData GlbInitVal;
public PString InitString;
public bool ReadOnly = false;
public Variable(IdContainer Container, PString Name, Type Type)
: base(Container, Name)
{
this.Type = Type;
}
public bool CalcValue(ExprPlugIn PlugIn, bool CreateAssignInitValues = false)
{
var TypeMgrPlugIn = PlugIn.GetPlugIn<TypeMgrPlugIn>();
if (TypeMgrPlugIn != null)
{
if (!(Type is AutomaticType))
TypeMgrPlugIn.RetType = Type;
else TypeMgrPlugIn.RetType = null;
}
InitValue = null;
if (InitString != null)
{
InitValue = Expressions.NewExpressionTree(InitString, PlugIn, End: !CreateAssignInitValues);
if (InitValue == null) return false;
if (InitValue is ConstExpressionNode)
{
var ConstVal = InitValue as ConstExpressionNode;
GlbInitVal = ConstVal.Value;
}
if (Type is AutomaticType)
Type = InitValue.Type;
if (CreateAssignInitValues)
{
InitValue = InitValue.CreateAssignExpr(this, InitString, PlugIn, true);
if (InitValue == null) return false;
}
}
else if (Type is AutomaticType)
{
PlugIn.State.Messages.Add(MessageId.Untyped, Name);
return false;
}
return true;
}
}
public class GlobalVariable : Variable
{
public GlobalVariable(IdContainer Container, PString Name, Type Type)
: base(Container, Name, Type)
{
}
public override void GetAsmCode(Compiler Comp, GetAsmCodeMode Mode)
{
if (Mode == GetAsmCodeMode.Data)
{
Comp.Label(AsmName);
Type.Declare(Comp, GlbInitVal);
Comp.Append("\n");
}
}
}
public class LocalVariable : Variable
{
public bool IsParameter;
public bool PreAssigned;
public bool RetVar = false;
public LocalVariable(IdContainer Container, PString Name, Type Type)
: base(Container, Name, Type)
{
}
}
public class MemberVariable : Variable
{
public int Offset;
public MemberVariable(IdContainer Container, PString Name, Type Type)
: base(Container, Name, Type)
{
}
}
public abstract class PackedId : Identifier
{
public Type Type;
public abstract ExpressionNode Extract(ExprPlugIn PlugIn);
public PackedId(IdContainer Container, PString Name, Type Type)
: base(Container, Name)
{
this.Type = Type;
}
}
public class PackedMemberId : PackedId
{
public Identifier Id;
public Identifier Member;
public PackedMemberId(IdContainer Container, PString Name, Type Type, Identifier Id, Identifier Member)
: base(Container, Name, Type)
{
this.Id = Id;
this.Member = Member;
}
public override ExpressionNode Extract(ExprPlugIn PlugIn)
{
var Id = (ExpressionNode)new IdExpressionNode(this.Id, Name);
var Member = (ExpressionNode)new IdExpressionNode(this.Member, Name);
if (PlugIn != null && (Id = PlugIn.NewNode(Id)) == null) return null;
if (PlugIn != null && (Member = PlugIn.NewNode(Member)) == null) return null;
var NewCh = new List<ExpressionNode>() { Id, Member };
var Ret = (ExpressionNode)new OpExpressionNode(Operator.Member, NewCh, Name);
if (Ret != null && (Ret = PlugIn.NewNode(Ret)) == null) return null;
return Ret;
}
}
}