using System;
using System.Collections.Generic;
using System.Linq;
using Anonymus.Recognizers;
namespace Anonymus
{
public enum PlugInRes
{
Failed,
Succeeded,
Ready,
}
public abstract class ExprPlugIn
{
public ExprPlugIn Root;
public IdContainer Container;
public CompilerState State;
public PreprocessorState PreState;
public ExprRecognizer Recognizer;
public virtual PlugInRes NewNode(ref ExpressionNode Node)
{
return PlugInRes.Succeeded;
}
public virtual PlugInRes End(ref ExpressionNode Node)
{
return PlugInRes.Succeeded;
}
public ExpressionNode NewNode(ExpressionNode Node)
{
if (NewNode(ref Node) == PlugInRes.Failed)
return null;
else return Node;
}
public ExpressionNode End(ExpressionNode Node)
{
if (End(ref Node) == PlugInRes.Failed)
return null;
else return Node;
}
public virtual bool Begin()
{
return true;
}
public ExprPlugIn(IdContainer Container)
{
this.Root = this;
this.Container = Container;
this.State = Container.State;
this.PreState = Container.PreState;
this.Recognizer = State.Language.ExprRecognizer;
}
public virtual ExpressionNode DeclareVariable(PString Code, PString TypeName, PString Name)
{
State.Messages.Add(MessageId.CannotDeclVar, Code);
return null;
}
public virtual T GetPlugIn<T>() where T : ExprPlugIn
{
if (this is T) return this as T;
else return null;
}
}
public class MultiPlugIn : ExprPlugIn
{
public List<ExprPlugIn> PlugIns = new List<ExprPlugIn>();
public MultiPlugIn(IdContainer Container)
: base(Container)
{
}
public override PlugInRes NewNode(ref ExpressionNode Node)
{
foreach (var e in PlugIns)
{
var Res = e.NewNode(ref Node);
if (Res == PlugInRes.Ready || Res == PlugInRes.Failed)
return Res;
}
if (Node is StrExpressionNode)
{
State.Messages.Add(MessageId.UnknownId, Node.Code);
return PlugInRes.Failed;
}
return PlugInRes.Succeeded;
}
public override bool Begin()
{
foreach (var e in PlugIns)
if (!e.Begin()) return false;
return true;
}
public override PlugInRes End(ref ExpressionNode Node)
{
foreach (var e in PlugIns)
{
var Res = e.End(ref Node);
if (Res == PlugInRes.Ready || Res == PlugInRes.Failed)
return Res;
}
return PlugInRes.Succeeded;
}
public override ExpressionNode DeclareVariable(PString Code, PString TypeName, PString Name)
{
var PlugIn = GetPlugIn<CompilerPlugIn>();
if (PlugIn != null) return PlugIn.DeclareVariable(Code, TypeName, Name);
return base.DeclareVariable(Code, TypeName, Name);
}
public override T GetPlugIn<T>()
{
foreach (var e in PlugIns)
if (e is T) return e as T;
return base.GetPlugIn<T>();
}
public void AddPlugIn(ExprPlugIn PlugIn)
{
PlugIns.Add(PlugIn);
PlugIn.Root = this;
}
}
public class GlobalPlugIn : MultiPlugIn
{
public GlobalPlugIn(IdContainer Container)
: base(Container)
{
AddPlugIn(new PreProcPlugIn(Container, false));
AddPlugIn(new TypeMgrPlugIn(Container, null));
AddPlugIn(new CalcPlugIn(Container, true));
}
}
public class LocalPlugIn : MultiPlugIn
{
public LocalPlugIn(IdContainer Container)
: base(Container)
{
var Arch = Container.State.Arch;
AddPlugIn(new PreProcPlugIn(Container, false));
AddPlugIn(new TypeMgrPlugIn(Container, null));
AddPlugIn(new CalcPlugIn(Container, false));
AddPlugIn(new CompilerPlugIn(Container));
AddPlugIn(Arch.CreatePlugIn(Container));
}
}
public class TypeMgrPlugIn : ExprPlugIn
{
public IdContainer _Container;
public Type _RetType;
public virtual bool AutoNot { get { return false; } }
public Type RetType { get { return _RetType; } set { _RetType = value; } }
public TypeMgrPlugIn(IdContainer Container, Type RetType)
: base(Container)
{
this._RetType = RetType;
}
public override bool Begin()
{
return true;
}
public override PlugInRes End(ref ExpressionNode Node)
{
if (Node != null && RetType != null && Node.Type != RetType)
Node = OnConvNeeded(Node, RetType, Node.Code);
if (!ProcTupleTypes(Node)) return PlugInRes.Failed;
return PlugInRes.Succeeded;
}
public bool ProcTupleTypes(ExpressionNode Node)
{
if (Node.Type is TupleType)
{
var Tuple = Node.Type as TupleType;
var Ok = true;
foreach (MemberVariable e in Tuple.Members)
if (e.Type is AutomaticType || e.Type is VoidType)
Ok = false;
if (!Ok)
{
State.Messages.Add(MessageId.UnknownType, Tuple.Name);
return false;
}
Tuple.CalcPositions();
}
foreach (var e in Node.EnumChildren)
if (!ProcTupleTypes(e)) return false;
return true;
}
ExpressionNode OnConvNeeded(ExpressionNode Node, Type RType, PString Code)
{
var Res = Node.Type.CanConvert(RType);
if (Res == TypeConversion.Automatic || Node.Type is AutomaticType)
{
Node = Node.CreateCastExpr(RType, PlugIn: Root);
if (Node == null) return null;
}
else
{
var Msg = MessageId.ImplicitlyCast;
if (Res == TypeConversion.Nonconvertable) Msg = MessageId.CannotConvert;
State.Messages.Add(Msg, Code, Node.Type.Name.String, RType.Name.String);
return null;
}
return Node;
}
private ExpressionNode ChkCanBeIndexerType(ExpressionNode Node, PString Code)
{
var SType = Node.Type as SignedType;
if (SType == null || SType.Size != State.Arch.RegSize)
{
var CastTo = Container.GetType(typeof(SignedType), State.Arch.RegSize);
return OnConvNeeded(Node, CastTo, Code);
}
return Node;
}
TupleType CreateTupleTypeForNodes(List<ExpressionNode> Ch, PString Name)
{
var Members = new IdentifierList();
for (var i = 0; i < Ch.Count; i++)
{
var MName = new PString("%" + i.ToString());
var MVar = new MemberVariable(Container, MName, Ch[i].Type);
State.Arch.OnNewIdentifier(MVar);
Members.Add(MVar);
}
var Type = new TupleType(Container, Members, false);
Type.Name = Name;
State.Arch.OnNewIdentifier(Type);
return Type;
}
public PlugInRes NewOpNode(ref ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
var Op = OpNode.Operator;
var Ch = OpNode.Children;
//--------------------------------------------------------------------------------------
if (Op == Operator.Indirection)
{
if (!CanOpApplied(OpNode)) return PlugInRes.Failed;
var Zero = Root.NewNode(Expressions.GetIntValue(Container, 0, Node.Code));
if (Zero == null) return PlugInRes.Failed;
var NewCh = new List<ExpressionNode>() { Ch[0], Zero };
Node = Root.NewNode(new OpExpressionNode(Operator.Index, NewCh, Node.Code));
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.CreateTuple)
{
Node.Type = CreateTupleTypeForNodes(Ch, Node.Code);
}
//--------------------------------------------------------------------------------------
else if (Operators.IsMathsOp(Op))
{
if (!CanOpApplied(OpNode)) return PlugInRes.Failed;
if (Op == Operator.Abs) Node.Type = Ch[0].Type;
else Node.Type = Container.GetType(typeof(FloatType), 8);
}
//--------------------------------------------------------------------------------------
else if (Operators.IsLogicalOp(Op))
{
var BoolType = Container.GlobalScope.BoolType;
Node.Type = BoolType;
for (var i = 0; i < Ch.Count; i++)
if (!(Ch[i].Type is BoolType))
{
Ch[i] = OnConvNeeded(Ch[1], BoolType, Node.Code);
if (Ch[i] == null) return PlugInRes.Failed;
}
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Assignment)
{
if (!CanOpApplied(OpNode)) return PlugInRes.Failed;
var OpCh0 = Ch[0] as OpExpressionNode;
if (OpCh0 != null && OpCh0.Operator == Operator.CreateTuple)
{
var Ch0Ch = OpCh0.Children;
var OpCh1 = Ch[1] as OpExpressionNode;
if (OpCh1 != null && OpCh1.Operator == Operator.CreateTuple)
{
var Ch1Ch = OpCh1.Children;
if (Ch0Ch.Count != Ch1Ch.Count) throw new Exception("ERROR");
for (var i = 0; i < Ch0Ch.Count; i++)
if ((Ch1Ch[i] = ChkAssignVar(Ch0Ch[i], Ch1Ch[i], Node.Code)) == null)
return PlugInRes.Failed;
}
else
{
var SrcType = Ch[1].Type.RealType as TupleType;
for (var i = 0; i < Ch0Ch.Count; i++)
{
var MemVar = SrcType.Members[i] as MemberVariable;
if (!ChkAssignVar(Ch0Ch[i], MemVar.Type, Node.Code))
return PlugInRes.Failed;
}
Ch[0].Type = CreateTupleTypeForNodes(Ch0Ch, Ch[0].Code);
}
}
else
{
if ((Ch[1] = ChkAssignVar(Ch[0], Ch[1], Node.Code)) == null)
return PlugInRes.Failed;
}
Node.Type = Ch[1].Type;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Call)
{
var FuncType = Ch[0].Type as FunctionType;
if (FuncType != null)
{
var Params = FuncType.Params;
if (Params.Count + 1 != Ch.Count)
{
State.Messages.Add(MessageId.ParamCount, Node.Code);
return PlugInRes.Failed;
}
for (var i = 0; i < Params.Count; i++)
{
var n = Ch[i + 1];
var DstType = Params[i].Type;
if (n.Type.IsEqual(DstType)) continue;
n = OnConvNeeded(n, DstType, Node.Code);
if (n == null) return PlugInRes.Failed;
else Ch[i + 1] = n;
}
Node.Type = FuncType.RetType;
}
else
{
State.Messages.Add(MessageId.CallingNotFunc, Node.Code);
return PlugInRes.Failed;
}
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Index)
{
var Indexed = Ch[0];
var IndexCount = -1;
var Type = Indexed.Type;
if (Type is PointerType)
{
var pType = Indexed.Type as PointerType;
Node.Type = pType.Child;
IndexCount = 1;
}
if (IndexCount == -1)
{
State.Messages.Add(MessageId.CantOpApplied, Node.Code, Type.Name.String);
return PlugInRes.Failed;
}
else if (IndexCount + 1 != Ch.Count)
{
State.Messages.Add(MessageId.ParamCount, Node.Code);
return PlugInRes.Failed;
}
else
{
for (var i = 0; i < IndexCount; i++)
{
var NewNode = ChkCanBeIndexerType(Ch[i + 1], Node.Code);
if (NewNode == null) return PlugInRes.Failed;
else Ch[i + 1] = NewNode;
}
}
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Not)
{
var Type = Ch[0].Type;
if (!(Type is BoolType))
{
Type = Container.GlobalScope.BoolType;
Ch[0] = OnConvNeeded(Ch[0], Type, Node.Code);
if (Ch[0] == null) return PlugInRes.Failed;
}
Node.Type = Type;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Condition)
{
var Type0 = Ch[0].Type;
if (!(Type0 is BoolType))
{
Type0 = Container.GlobalScope.BoolType;
Ch[0] = OnConvNeeded(Ch[0], Type0, Node.Code);
if (Ch[0] == null) return PlugInRes.Failed;
}
var Type1 = Ch[1].Type;
var Type2 = Ch[2].Type;
if (Type1 != Type2)
{
var NType1 = Type1 as NumberType;
var NType2 = Type2 as NumberType;
var RetType = (Type)null;
if (NType1 != null && NType2 != null)
RetType = Container.GetRetType(NType1, NType2);
else RetType = Type1;
var Conv = RetType == Type1 ? 2 : 1;
if ((Ch[Conv] = OnConvNeeded(Ch[Conv], RetType, Node.Code)) == null)
return PlugInRes.Failed;
}
Node.Type = Ch[1].Type;
if (Node.Type is AutomaticType)
{
State.Messages.Add(MessageId.Untyped, Node.Code);
return PlugInRes.Failed;
}
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Address)
{
var Child = Ch[0];
var OpChild = Child as OpExpressionNode;
if (OpChild != null && OpChild.Operator == Operator.Index)
{
var ChType = OpChild.Children[0].Type;
if (ChType is PointerType)
{
Node.Type = ChType;
}
else
{
throw new NotImplementedException();
}
}
else if (Child is IdExpressionNode)
{
var Var = Child as IdExpressionNode;
if (Var != null) Var.Id.CanBeInReg = false;
Node.Type = Child.Type.CreatePointerType();
}
else
{
State.Messages.Add(MessageId.AddressOfRValue, Node.Code);
return PlugInRes.Failed;
}
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Ref)
{
var NewCh = new List<ExpressionNode>() { Ch[0] };
Node = Root.NewNode(new OpExpressionNode(Operator.Address, NewCh, Node.Code));
Node.Type = Ch[0].Type.CreateRefType();
return PlugInRes.Ready;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Member)
{
Node.Type = Ch[1].Type;
}
//--------------------------------------------------------------------------------------
else if (Operators.IsBoolRetOp(Op))
{
var IdCh0 = Ch[0] as IdExpressionNode;
var IdCh1 = Ch[1] as IdExpressionNode;
if (IdCh0 != null && IdCh1 != null && IdCh0.Id == IdCh1.Id)
State.Messages.Add(MessageId.CmpSameVariable, Node.Code);
if (!CastChToSameType(OpNode)) return PlugInRes.Failed;
if (!CanOpApplied(OpNode)) return PlugInRes.Failed;
Node.Type = Container.GlobalScope.BoolType;
}
//--------------------------------------------------------------------------------------
else if (Op == Operator.Neg || Op == Operator.Complement)
{
if (!CanOpApplied(OpNode)) return PlugInRes.Failed;
Node.Type = Ch[0].Type;
}
//--------------------------------------------------------------------------------------
else if (Op != Operator.New)
{
#if DEBUG
if (!Operators.IsBitArithmOp(Op))
throw new Exception("ERROR");
#endif
if (!CastChToSameType(OpNode)) return PlugInRes.Failed;
if (!CanOpApplied(OpNode)) return PlugInRes.Failed;
Node.Type = Ch[0].Type;
}
return PlugInRes.Succeeded;
}
bool ChkAssignVar(ExpressionNode Dst, Type SrcType, PString Code)
{
var DstRIdNode = Dst as IdExpressionNode;
if (DstRIdNode != null)
{
var Var = DstRIdNode.Id as Variable;
if (Var != null && Var.ReadOnly)
{
State.Messages.Add(MessageId.ReadOnly, Dst.Code);
return false;
}
}
else
{
var ChOpNode = Dst as OpExpressionNode;
var ChOp = ChOpNode != null ? ChOpNode.Operator : Operator.Nothing;
if (ChOp != Operator.Index && ChOp != Operator.Member)
{
State.Messages.Add(MessageId.AssignRValue, Code);
return false;
}
}
if (Dst.Type is AutomaticType)
{
if (SrcType is AutomaticType)
{
State.Messages.Add(MessageId.Untyped, Code);
return false;
}
else
{
Dst.Type = SrcType;
var IdDst = Dst as IdExpressionNode;
if (IdDst != null)
{
var Var = IdDst.Id as Variable;
if (Var != null) Var.Type = SrcType;
}
}
}
return true;
}
ExpressionNode ChkAssignVar(ExpressionNode Dst, ExpressionNode Src, PString Code)
{
var SrcType = Src.Type;
if (!ChkAssignVar(Dst, SrcType, Code)) return null;
if (Src is IdExpressionNode && Dst is IdExpressionNode)
{
var IdDst = Dst as IdExpressionNode;
var IdSrc = Src as IdExpressionNode;
var DstVar = IdDst.Id;
var SrcVar = IdSrc != null ? IdSrc.Id : null;
if (SrcVar != null && DstVar == SrcVar)
State.Messages.Add(MessageId.AssignSameVar, Code);
}
var DstType = Dst.Type;
if (!DstType.IsEqual(SrcType))
{
if (DstType == null || SrcType == null || (Src = OnConvNeeded(Src, DstType, Code)) == null)
return null;
}
return Src;
}
public bool CastChToSameType(OpExpressionNode Node)
{
var Ch = Node.Children;
var Op = Node.Operator;
var Type0 = Ch[0].Type;
var Type1 = Ch[1].Type;
if (!Type0.IsEqual(Type1))
{
if (Type1 is AutomaticType)
{
Ch[1] = OnConvNeeded(Ch[1], Ch[0].Type, Node.Code);
if (Ch[1] == null) return false;
}
else if (Type0 is AutomaticType)
{
Ch[0] = OnConvNeeded(Ch[0], Ch[1].Type, Node.Code);
if (Ch[0] == null) return false;
}
else if (Type1 is PointerType)
{
Ch[0] = ChkCanBeIndexerType(Ch[0], Node.Code);
if (Ch[0] == null) return false;
}
else if (Type0 is PointerType)
{
Ch[1] = ChkCanBeIndexerType(Ch[1], Node.Code);
if (Ch[1] == null) return false;
}
else
{
var RType = Container.GetRetType(Type0, Type1);
for (var i = 0; i < Ch.Count; i++)
if (!Ch[i].Type.IsEqual(RType))
{
if ((Ch[i] = OnConvNeeded(Ch[i], RType, Node.Code)) == null)
return false;
}
}
}
// var NewNode = ChkCanBeIndexerType(Ch[1], Node.Code);
return true;
}
public bool CanOpApplied(OpExpressionNode Node)
{
var Ch = Node.Children;
var Op = Node.Operator;
var SrcType = Ch.Count > 1 ? Ch[1].Type : null;
if (!Ch[0].Type.CanOpApplied(Op, SrcType))
{
if (Ch.Count > 1)
{
State.Messages.Add(MessageId.CantOpApplied2, Node.Code,
Ch[0].Type.Name.String, Ch[1].Type.Name.String);
}
else
{
State.Messages.Add(MessageId.CantOpApplied, Node.Code, Ch[0].Type.Name.String);
}
return false;
}
return true;
}
public override PlugInRes NewNode(ref ExpressionNode Node)
{
foreach (var e in Node.EnumChildren.ToArray())
if (e is IdExpressionNode)
{
var IdNode = e as IdExpressionNode;
if (IdNode.Type is RefType)
{
var RefType = IdNode.Type as RefType;
IdNode.Type = RefType.Child.CreatePointerType();
var NewE = e.Indirection(State, Container, Node.Code, Root);
if (NewE == null) return PlugInRes.Failed;
else Node.ReplaceNodes(e, NewE);
}
}
//--------------------------------------------------------------------------------------
if (Node is MacroExpressionNode || Node is MacroArgNode || Node is StrExpressionNode)
{
return PlugInRes.Succeeded;
}
//--------------------------------------------------------------------------------------
else if (Node is LinkingNode)
{
var LnkNode = Node as LinkingNode;
var Linked = LnkNode.LinkedNode;
var RNode = Linked.Node;
if (!(RNode is OpExpressionNode || RNode is CastExpressionNode))
{
Node = Root.NewNode(RNode.Copy(State));
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
else
{
Node.Type = RNode.Type;
Linked.LinkingCount++;
}
}
//--------------------------------------------------------------------------------------
else if (Node is IdExpressionNode)
{
var RIdNode = Node as IdExpressionNode;
var Id = RIdNode.Id;
Id.SetUsed();
if (Id is Variable) RIdNode.Type = (Id as Variable).Type;
else if (Id is Function) RIdNode.Type = (Id as Function).Type;
else if (Id is Type) RIdNode.Type = Container.GlobalScope.TypeOfType;
else if (Id is PackedId) RIdNode.Type = (Id as PackedId).Type;
else throw new Exception("ERROR");
}
//--------------------------------------------------------------------------------------
else if (Node is CastExpressionNode)
{
var CastNode = Node as CastExpressionNode;
var From = CastNode.Child.Type;
var To = CastNode.Type;
if (From == To)
{
State.Messages.Add(MessageId.CastToSameType, Node.Code);
Node = CastNode.Child;
return PlugInRes.Ready;
}
if (From.CanConvert(To) == TypeConversion.Nonconvertable)
{
var Params = new[] { From.Name.String, To.Name.String };
State.Messages.Add(MessageId.CannotConvert, Node.Code, Params);
return PlugInRes.Failed;
}
}
//--------------------------------------------------------------------------------------
else if (Node is OpExpressionNode)
{
var Res = NewOpNode(ref Node);
if (Res == PlugInRes.Failed || Res == PlugInRes.Ready)
return Res;
}
//--------------------------------------------------------------------------------------
if (Node.Type == null)
throw new Exception("ERROR");
if (Node.LinkedNodes != null)
{
for (var i = 0; i < Node.LinkedNodes.Count; i++)
{
var LNode = Node.LinkedNodes[i];
if (LNode.LinkingCount == 0)
{
Node.LinkedNodes.RemoveAt(i);
i--;
}
}
if (Node.LinkedNodes.Count == 0)
Node.LinkedNodes = null;
}
return PlugInRes.Succeeded;
}
}
public class CalcPlugIn : ExprPlugIn
{
public bool Const;
public CalcPlugIn(IdContainer Container, bool Const)
: base(Container)
{
this.Const = Const;
}
public override PlugInRes End(ref ExpressionNode Node)
{
if (Const && !(Node is ConstExpressionNode))
{
State.Messages.Add(MessageId.MustConst, Node.Code);
return PlugInRes.Failed;
}
return PlugInRes.Succeeded;
}
public override PlugInRes NewNode(ref ExpressionNode Node)
{
if (Node is OpExpressionNode)
{
var OpNode = Node as OpExpressionNode;
var Op = OpNode.Operator;
var Ch = OpNode.Children;
if (Operators.IsStdOp(Op))
{
var Ok = Ch.Count > 0;
for (var i = 0; i < Ch.Count; i++)
if (!(Ch[i] is ConstExpressionNode))
Ok = false;
if (Ok)
{
var NewNode = ConstExpressionNode.DoOps(Container, OpNode);
if (NewNode != null)
{
Node = Root.NewNode(NewNode);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
}
}
}
else if (Node is CastExpressionNode)
{
var CastNode = Node as CastExpressionNode;
if (CastNode.Child is ConstExpressionNode)
{
var Child = CastNode.Child as ConstExpressionNode;
var Value = Child.ConvertTo(State, CastNode.Type);
if (Value == null) return PlugInRes.Failed;
if (Value != Node)
{
Node = Root.NewNode(Value);
if (Node == null) return PlugInRes.Failed;
else return PlugInRes.Ready;
}
}
}
return PlugInRes.Succeeded;
}
}
public class CompilerPlugIn : ExprPlugIn
{
public List<Variable> DeclaredVars;
public NodeVariables Vars;
public CompilerPlugIn(IdContainer Container)
: base(Container)
{
}
public override bool Begin()
{
Vars = new NodeVariables();
return true;
}
public override PlugInRes End(ref ExpressionNode Node)
{
if (!ChkDeclaredIds(Node))
return PlugInRes.Failed;
if (DeclaredVars != null)
{
Container.Identifiers.AddRange(DeclaredVars);
DeclaredVars = null;
}
Node.Vars = Vars;
return PlugInRes.Succeeded;
}
private void SetChUsed(ExpressionNode Node)
{
foreach (var Ch in Node.EnumChildren)
SetNUsed(Ch);
}
private void SetNUsed(ExpressionNode Ch)
{
var RIdCh = Ch as IdExpressionNode;
if (RIdCh != null) Vars.UsedBeforeAssignIds.Add(RIdCh);
}
public bool ChkDeclaredIds(ExpressionNode Node)
{
var OpNode = Node as OpExpressionNode;
if (OpNode != null && OpNode.Operator != Operator.CreateTuple)
{
var Ch = OpNode.Children;
for (var i = 0; i < Ch.Count; i++)
if (OpNode.Operator != Operator.Assignment || i != 0)
{
if (Ch[i] is IdExpressionNode && (Ch[i] as IdExpressionNode).MustBeAssigned)
{
State.Messages.Add(MessageId.MustHaveInitVal, Ch[i].Code);
return false;
}
else if (Ch[i] is OpExpressionNode)
{
var OpCh = Ch[i] as OpExpressionNode;
if (OpCh.Operator != Operator.CreateTuple) continue;
foreach (var e in OpCh.Children)
if (e is IdExpressionNode && (e as IdExpressionNode).MustBeAssigned)
{
State.Messages.Add(MessageId.MustHaveInitVal, e.Code);
return false;
}
}
}
}
return true;
}
public override PlugInRes NewNode(ref ExpressionNode Node)
{
if (!ChkDeclaredIds(Node))
return PlugInRes.Failed;
var bSetChUsed = true;
if (Node is OpExpressionNode)
{
var OpNode = Node as OpExpressionNode;
var Ch = OpNode.Children;
var Op = OpNode.Operator;
if (Op == Operator.Assignment)
{
if (Ch[0] is IdExpressionNode)
{
var IdNode = Ch[0] as IdExpressionNode;
Vars.AssignedIds.Add(IdNode);
SetNUsed(Ch[1]);
bSetChUsed = false;
}
}
else if (Op == Operator.Address)
{
bSetChUsed = false;
}
}
if (bSetChUsed) SetChUsed(Node);
foreach (var Ch in Node.EnumChildren.ToArray())
if (Ch is IdExpressionNode)
{
var IdNode = Ch as IdExpressionNode;
var Id = IdNode.Id as PackedId;
if (Id != null)
{
var New = Id.Extract(Root);
if (New == null) return PlugInRes.Failed;
Node.ReplaceNodes(Ch, New);
}
}
return PlugInRes.Succeeded;
}
public override ExpressionNode DeclareVariable(PString Code, PString TypeName, PString Name)
{
var Type = Container.GetId<Type>(TypeName);
if (Type == null) return null;
if (Type is VoidType)
{
State.Messages.Add(MessageId.CannotBeThisType, TypeName);
return null;
}
var Var = Container.CreateVariable(Name, Type);
if (Var == null) return null;
if (Container.CanIdDeclared(Var))
{
var Loc = Var as LocalVariable;
if (Loc != null) Loc.PreAssigned = true;
if (DeclaredVars == null) DeclaredVars = new List<Variable>();
DeclaredVars.Add(Var);
var IdNode = new IdExpressionNode(Var, Code);
IdNode.MustBeAssigned = true;
return Root.NewNode(IdNode);
}
return null;
}
}
}