using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Anonymus
{
public enum GetIdMode
{
Scope,
Function,
Everywhere,
}
public abstract class IdContainer
{
public IdContainer Parent = null;
public IdentifierList Identifiers = new IdentifierList();
public object ArchData;
public virtual bool CanIdDeclared(Identifier Id)
{
if (IsIdDefined<Identifier>(Id.Name.String, GetIdMode.Scope))
{
State.Messages.Add(MessageId.IdAlreadyDefined, Id.Name);
return false;
}
if (!Helper.IsValidIdentifierName(Id.Name.String))
{
State.Messages.Add(MessageId.NotValidName, Id.Name);
return false;
}
return true;
}
public bool DeclareVariables(PString Str, ModifierList Mods = null,
VarConvMode Mode = VarConvMode.Nothing, GetIdMode IdMode = GetIdMode.Everywhere)
{
var List = new VarDeclList();
if (!List.AddFromString(this, Str)) return false;
return DeclareVariables(List, Mods, Mode, IdMode);
}
public bool DeclareVariables(VarDeclList List, ModifierList Mods = null,
VarConvMode Mode = VarConvMode.Nothing, GetIdMode IdMode = GetIdMode.Everywhere)
{
var Variables = List.ConvToVariables(GetPlugIn(), Mods, Mode);
return DeclareVariables(Variables, IdMode);
}
public virtual bool DeclareVariables(List<Variable> Variables, GetIdMode IdMode = GetIdMode.Everywhere)
{
var RetValue = true;
foreach (var e in Variables)
{
if (e == null) RetValue = false;
else if (CanIdDeclared(e)) Identifiers.Add(e);
else RetValue = false;
}
return RetValue;
}
public abstract Variable CreateVariable(PString Name, Type Type, ModifierList Mods = null);
public virtual Function CreateFunction(PString Name, FuncScopeNode Scope,
FunctionType FuncType, ModifierList Mods = null)
{
var Ret = new Function(this, Name, FuncType, Scope);
if (Mods != null && !Mods.Apply(this, Ret)) return null;
State.Arch.OnNewIdentifier(Ret);
return Ret;
}
public Function DeclareFunction(PString TypeName, PString Name, VarDeclList Params,
PString[] Inner, ModifierList Mods = null, Function Func = null)
{
var RetType = GetId<Type>(TypeName, FuncRet: true);
if (RetType == null) return null;
if (RetType is AutomaticType)
{
State.Messages.Add(MessageId.VarFuncRetType, TypeName);
return null;
}
return DeclareFunction(RetType, Name, Params, Inner, Mods, Func);
}
public CodeScopeNode CreateCodeScopeNode(PString[] Inner)
{
var Ret = new CodeScopeNode(this, Inner);
State.Arch.OnNewContainer(Ret);
return Ret;
}
public StructuredTypeScope CreateStructuredTypeScope(PString[] Inner, StructuredType Type)
{
var Ret = new StructuredTypeScope(this, Inner, Type);
State.Arch.OnNewContainer(Ret);
return Ret;
}
public EnumTypeScope CreateEnumTypeScope(PString[] Inner, EnumType Type)
{
var Ret = new EnumTypeScope(this, Inner, Type);
State.Arch.OnNewContainer(Ret);
return Ret;
}
public virtual Function DeclareFunction(FunctionType Type, PString Name,
FuncScopeNode Scope, ModifierList Mods = null, Function Func = null)
{
if (Func == null)
{
Func = CreateFunction(Name, Scope, Type, Mods);
if (Func == null) return null;
}
else
{
Func.FunctionScope = Scope;
Func.Type = Type;
Func.Name = Name;
}
if (this is GlobalScopeNode && State.HasMainFunc && Name.String == State.Entry)
Func.SetUsed();
if (!CanIdDeclared(Func)) return null;
Identifiers.Add(Func);
return Func;
}
public virtual Function DeclareFunction(Type RetType, PString Name, VarDeclList Params,
PString[] Inner, ModifierList Mods = null, Function Func = null)
{
var Type = new FunctionType(this, Name, CallConv.AsCall, RetType, Params);
Type.SetUsed();
var Static = Mods != null ? Mods.Contains(ModifierType.Static) : false;
var FuncScope = State.Arch.CreateFuncScope(this, Name, Type, Static, Inner);
return DeclareFunction(Type, Name, FuncScope, Mods, Func);
}
public virtual void InitCodeChk(bool Unreachable = true)
{
foreach (var Ch in EnumChildren)
Ch.InitCodeChk(Unreachable);
}
public virtual bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
{
Data.ChkVars(this);
return false;
}
public virtual bool FinishCodeChk()
{
var Ret = true;
foreach (var Ch in EnumChildren)
if (!Ch.FinishCodeChk()) Ret = false;
return Ret;
}
public bool IsSubContainer(IdContainer Container)
{
if (this == Container) return true;
else if (Parent != null) return Parent.IsSubContainer(Container);
else return false;
}
public virtual void CalcExprRegs()
{
foreach (var Ch in EnumChildren)
Ch.CalcExprRegs();
}
public IdContainer(IdContainer Parent)
{
this.Parent = Parent;
}
public virtual MultiPlugIn GetPlugIn()
{
return new GlobalPlugIn(this);
}
public virtual IEnumerable<IdContainer> EnumChildren
{
get { yield break; }
}
public IEnumerable<LocalVariable> EnumLocals
{
get
{
foreach (var e in Identifiers)
if (e is LocalVariable)
yield return e as LocalVariable;
}
}
public virtual CompilerState State
{
get { return GlobalScope.State; }
}
public virtual PreprocessorState PreState
{
get { return GlobalScope.PreState; }
}
public T GetScope<T>() where T : IdContainer
{
var Scope = this;
while (Scope != null && !(Scope is T))
Scope = Scope.Parent;
return Scope as T;
}
GlobalScopeNode _GblScope;
public GlobalScopeNode GlobalScope
{
get
{
if (_GblScope == null) _GblScope = GetScope<GlobalScopeNode>();
return _GblScope;
}
}
FuncScopeNode _FuncScope;
public FuncScopeNode FuncScope
{
get
{
if (_FuncScope == null) _FuncScope = GetScope<FuncScopeNode>();
return GetScope<FuncScopeNode>();
}
}
public Type GetRetType(Type Type0, Type Type1)
{
if (Type0 is AutomaticType) return Type1;
if (Type1 is AutomaticType) return Type0;
if (Type0 is NumberType && Type1 is NumberType)
{
System.Type Tp = null;
if (Type0 is FloatType || Type1 is FloatType) Tp = typeof(FloatType);
else if (Type0 is SignedType || Type1 is SignedType) Tp = typeof(SignedType);
else Tp = typeof(UnsignedType);
var mSize = Type0.Size;
if (Type1.Size > mSize) mSize = Type1.Size;
return GetType(Tp, mSize);
}
var Tuple0 = Type0 as TupleType;
var Tuple1 = Type1 as TupleType;
if (Tuple0 != null && Tuple1 != null && Tuple0.Members.Count == Tuple1.Members.Count)
{
var Members = new IdentifierList();
for (var i = 0; i < Tuple0.Members.Count; i++)
{
var Var0 = Tuple0.Members[i] as MemberVariable;
var Var1 = Tuple1.Members[i] as MemberVariable;
var Name = new PString("%" + i.ToString());
var T = GetRetType(Var0.Type, Var1.Type);
var Member = new MemberVariable(this, Name, T);
State.Arch.OnNewIdentifier(Member);
Members.Add(Member);
}
var RetType = new TupleType(this, Members);
State.Arch.OnNewIdentifier(RetType);
return RetType;
}
return Type0;
}
private T GetBasicType<T>(string Name) where T : Identifier
{
foreach (var Id in GlobalScope.BasicTypes)
if (Id.Name.String == Name && Id is T)
return Id as T;
return null;
}
public NumberType GetType(System.Type Type, int Size)
{
foreach (var Id in GlobalScope.NumTypes)
{
var nt = Id as NumberType;
if (nt != null && nt.Size == Size && Type.IsInstanceOfType(Id))
return nt;
}
return null;
}
public virtual void ChkUnusedIds()
{
return;
foreach (var e in Identifiers)
if (!e.Used && e.DeclInThis)
State.Messages.Add(MessageId.UnusedId, e.Name);
foreach (var Ch in EnumChildren)
Ch.ChkUnusedIds();
}
public virtual ExpressionNode GetExprRec(PString Name,
ExprPlugIn PlugIn = null, GetIdMode Mode = GetIdMode.Everywhere)
{
return null;
}
public T GetId<T>(PString Code, GetIdMode Mode = GetIdMode.Everywhere,
bool FuncRet = false, bool EnableMessages = true) where T : Identifier
{
Code = BracketHelper.TrimFZ(Code);
if (Code.StrLen > 0 && Code[Code.StrLen - 1] == '*')
{
var ChildC = Code.TrimmedSubstring(0, Code.Length - 1);
var Child = GetId<Type>(ChildC, Mode, FuncRet, EnableMessages);
if (Child == null) return null;
var Ret = Child.CreatePointerType() as T;
if (Ret == null && EnableMessages)
State.Messages.Add(MessageId.UnknownId, Code);
return Ret;
}
//--------------------------------------------------------------------------
if (Code.String.StartsWith("ref"))
{
var ChildC = Code.TrimmedSubstring(3);
var Child = GetId<Type>(ChildC, Mode, FuncRet, EnableMessages);
if (Child == null) return null;
var Ret = Child.CreateRefType() as T;
if (Ret == null && EnableMessages)
State.Messages.Add(MessageId.UnknownId, Code);
return Ret;
}
//--------------------------------------------------------------------------
var Pos = Code.String.Find('.', InZ: true, Back: true);
if (Pos != -1)
{
var Left = Code.Substring(0, Pos);
var Right = Code.Substring(Pos + 1);
var Type = GetId<StructuredType>(Left, Mode, FuncRet, EnableMessages);
if (Type == null) return null;
var Ret = Type.GetId<T>(Right.String);
if (Ret == null && EnableMessages)
State.Messages.Add(MessageId.UnknownId, Right);
return Ret;
}
//--------------------------------------------------------------------------
Pos = Code.String.Find(',', InZ: true, Back: true);
if (Pos != -1) return CreateTupleType(Code, EnableMessages: EnableMessages) as T;
if (!Helper.IsValidIdentifierName(Code.String))
{
if (FuncRet)
{
var Name = Code.Word(InZ: true, Back: true);
if (!Helper.IsValidIdentifierName(Name.String))
{
if (EnableMessages)
{
if (Name == null) Name = Code;
State.Messages.Add(MessageId.NotValidName, Name);
}
return null;
}
var Type = GetId<Type>(Code, Mode, FuncRet, EnableMessages);
if (Type == null) return null;
if (Type is VoidType)
{
if (EnableMessages) State.Messages.Add(MessageId.CannotBeThisType, Code);
return null;
}
else if (Type is AutomaticType)
{
if (EnableMessages) State.Messages.Add(MessageId.Untyped, Code);
return null;
}
var Ret = new NamedFuncRetType(this, Name, Type) as T;
if (Ret == null && EnableMessages)
State.Messages.Add(MessageId.UnknownId, Code);
return Ret;
}
return null;
}
//--------------------------------------------------------------------------
var Id = GetIdRec<T>(Code, Mode);
if (Id == null && EnableMessages)
State.Messages.Add(MessageId.UnknownId, Code);
return Id;
}
public virtual T GetIdRec<T>(PString Name, GetIdMode Mode = GetIdMode.Everywhere,
bool SearchedInBasicTypes = false) where T : Identifier
{
if (!SearchedInBasicTypes)
{
var Ret = GetBasicType<T>(Name.String);
if (Ret != null) return Ret;
else SearchedInBasicTypes = true;
}
var Id = Identifiers.GetIdRec<T>(Name.String);
if (Id != null) return Id;
if (Parent != null && Mode != GetIdMode.Scope)
{
var F = FuncScope;
if (Mode != GetIdMode.Function || (Parent.FuncScope == F && F != null))
return Parent.GetIdRec<T>(Name, Mode, SearchedInBasicTypes);
}
return null;
}
public TupleType CreateTupleType(PString Name, bool EnableUnnamed = true, bool EnableMessages = true)
{
var Type = new TupleType(this, null);
Type.Members = new IdentifierList();
var DeclList = new VarDeclList();
if (!DeclList.AddFromString(this, Name, EnableUnnamed, false, EnableMessages))
return null;
for (var i = 0; i < DeclList.Count; i++)
{
var Decl = DeclList[i];
if (Decl.InitString != null)
{
if (EnableMessages) State.Messages.Add(MessageId.NotExpected, Decl.InitString);
return null;
}
if (Decl.Name == null)
Decl.Name = new PString("%" + i.ToString());
else Type.Named = true;
var Var = new MemberVariable(this, Decl.Name, Decl.Type);
State.Arch.OnNewIdentifier(Var);
Type.Members.Add(Var);
}
Type.CalcName();
Type.CalcPositions();
State.Arch.OnNewIdentifier(Type);
return Type;
}
public bool IsIdDefined<T>(string Name, GetIdMode Mode = GetIdMode.Everywhere) where T : Identifier
{
var Id = Identifiers.GetIdRec<T>(Name);
if (Id != null) return true;
if (Parent != null && Mode != GetIdMode.Scope)
{
var F = FuncScope;
if (Mode != GetIdMode.Function || (Parent.FuncScope == F && F != null))
return Parent.IsIdDefined<T>(Name, Mode);
}
return false;
}
public bool IsIdDefined(Identifier Id)
{
if (Identifiers.Contains(Id)) return true;
else if (Parent != null) return Parent.IsIdDefined(Id);
else return false;
}
public bool StartsWithType(PString Str)
{
var T = Str.Word(ModThis: false, WordStart: true);
return T.String == "var" || T.String == "ref" || GetId<Type>(T, EnableMessages: false) != null;
}
}
}