Пример #1
0
        public override int doFinalize()
        {
            int   errCount    = 0;
            Ident parentIdent = (this.Parent is Ident ? (Ident)this.Parent : default(Ident));

            //Check what we have here (possible outcomes: variableacces, arrayaccess, functioncall, namespaceaccess)
            #region typeDetection
            type = IdenType.NamespaceAccess;
            var fncCalls  = this.getAllChildrenOf <FunctionCall>();
            var arrAccess = this.getAllChildrenOf <ArrayAccess>();
            if (this.Parent is Template && !(this.Parent.Parent is Ident))
            {
                type = IdenType.TemplateVar;
            }
            else if (this.Parent is SqfCall && ((SqfCall)this.Parent).Name == this)
            {
                type = IdenType.SqfCommandName;
            }
            else if (this.IsSelfReference)
            {
                type = IdenType.ThisVar;
            }
            else if (fncCalls.Count > 0)
            {
                type = IdenType.FunctionCall;
            }
            else if (arrAccess.Count > 0)
            {
                type = IdenType.ArrayAccess;
            }
            else if (IsNamespaceAccess())
            {
                type = IdenType.NamespaceAccess;
            }
            else if (parentIdent == null && this.Access == AccessType.NA)
            {
                if (this.Parent is Interfaces.iClass || (this.Parent is Interfaces.iFunction && ((Interfaces.iFunction) this.Parent).ReturnType.ident == this) || this.Parent is Value || this.Parent is Variable)
                {
                    type = IdenType.NamespaceAccess;
                }
                else
                {
                    type = IdenType.VariableAccess;
                }
            }
            else if (parentIdent != null && (
                         (parentIdent.Access == AccessType.Namespace && this.Access == AccessType.NA) ||
                         this.Access == AccessType.Instance ||
                         (parentIdent.Access == AccessType.Instance && this.Access == AccessType.NA)
                         ))
            {
                var ntr = HelperClasses.NamespaceResolver.createNSR(this);
                if (ntr == null)
                {
                    Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0012, this.Line, this.Pos, this.File));
                    errCount++;
                    return(errCount);
                }
                if (ntr.Reference is Interfaces.iClass)
                {
                    type = IdenType.NamespaceAccess;
                }
                else
                {
                    type = IdenType.VariableAccess;
                }
            }
            else if (this.Access == AccessType.Namespace)
            {
                type = IdenType.NamespaceAccess;
            }
            else if (this.Access == AccessType.Instance && parentIdent == null)
            {
                type = IdenType.VariableAccess;
            }
            else
            {
                Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.UNKNOWN, this.Line, this.Pos, this.File));
                errCount++;
            }
            #endregion
            //And process it then ((unless its a simple ident, then we do not want to process ... here any further))
            if (
                this.IsSimpleIdentifier &&
                (
                    (this.Parent is Interfaces.iName && ((Interfaces.iName) this.Parent).Name == this) ||
                    (this.Parent is Interfaces.iHasType && !(this.Parent is Expression) && ((Interfaces.iHasType) this.Parent).ReferencedType.ident == this)
                ) &&
                !(this.Parent is AssignContainer) &&
                !(this.Parent is NewInstance) &&
                !(this.Parent is Interfaces.iHasType && ((Interfaces.iHasType) this.Parent).ReferencedType.ident == this)
                )
            {
                this.ReferencedObject = this.Parent;
                if (this.Parent is Interfaces.iHasType)
                {
                    this.ReferencedType = ((Interfaces.iHasType) this.Parent).ReferencedType;
                }
                else //todo: try to replace with proper refObject type
                {
                    this.ReferencedType = new VarTypeObject(this, (this.Parent is Interfaces.iTemplate ? ((Interfaces.iTemplate) this.Parent).TemplateObject : null));
                }
            }
            else
            {
                switch (type)
                {
                    #region ThisVar
                case IdenType.ThisVar:
                {
                    Interfaces.iClass curObject = this.getFirstOf <Interfaces.iClass>();
                    this.ReferencedObject = (pBaseLangObject)curObject;
                    this.ReferencedType   = curObject.VTO;
                    var fnc = this.getFirstOf <Interfaces.iFunction>();
                    if (fnc.FunctionEncapsulation == Encapsulation.Static)
                    {
                        Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0055, this.Line, this.Pos, this.File));
                        errCount++;
                    }
                }
                break;

                    #endregion
                    #region TemplateVar
                case IdenType.TemplateVar:
                {
                    this.ReferencedObject = (pBaseLangObject)this.getFirstOf <Interfaces.iClass>();
                    this.ReferencedType   = ((Interfaces.iClass) this.ReferencedObject).VTO;
                }
                break;

                    #endregion
                    #region SqfCommandName
                case IdenType.SqfCommandName:
                {
                    this.ReferencedObject = this.Parent;
                    this.ReferencedType   = ((SqfCall)this.Parent).ReferencedType;
                }
                break;

                    #endregion
                    #region VariableAccess & ArrayAccess
                case IdenType.VariableAccess:
                case IdenType.ArrayAccess:
                {
                    var nsr = HelperClasses.NamespaceResolver.createNSR(this);
                    if (nsr != null && nsr.IsValid && (nsr.Reference is oosEnum.EnumEntry || nsr.Reference is oosEnum))
                    {
                        if (nsr.Reference is oosEnum.EnumEntry)
                        {
                            var entry = (oosEnum.EnumEntry)nsr.Reference;
                            this.ReferencedObject = entry;
                            this.ReferencedType   = ((oosEnum)entry.Parent).ReferencedType;
                            break;
                        }
                        else if (nsr.Reference is oosEnum)
                        {
                            var e = (oosEnum)nsr.Reference;
                            this.ReferencedObject = e;
                            this.ReferencedType   = e.ReferencedType;
                            break;
                        }
                    }
                    var variable = HelperClasses.NamespaceResolver.getVariableReferenceOfFQN(HelperClasses.NamespaceResolver.createNSR(this, true), true, this);
                    if (variable == null)
                    {
                        variable = HelperClasses.NamespaceResolver.getVariableReferenceOfFQN(this, false, this);
                    }
                    if (variable == null)
                    {
                        Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0012, this.Line, this.Pos, this.File));
                        errCount++;
                    }
                    else
                    {
                        this.ReferencedObject = variable;
                        //Set type to variable type
                        this.ReferencedType = variable.varType;

                        if (type == IdenType.ArrayAccess)
                        {
                            if (variable.ReferencedType.IsObject)
                            {
                                //Check if given object is implementing the ArrayAccess operator
                                if (variable.ReferencedType.ident.LastIdent.ReferencedObject is Interfaces.iClass)
                                {
                                    Interfaces.iClass            classRef = (Interfaces.iClass)variable.ReferencedType.ident.LastIdent.ReferencedObject;
                                    Interfaces.iOperatorFunction opFnc    = classRef.getOperatorFunction(OverridableOperator.ArrayAccess);
                                    if (opFnc == null)
                                    {
                                        Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0005, this.Line, this.Pos, this.File));
                                        errCount++;
                                    }
                                    else
                                    {
                                        this.ReferencedType = opFnc.ReturnType;
                                        if (variable.TemplateObject != null)
                                        {
                                            var templateList = ((pBaseLangObject)opFnc).getAllParentsOf <Interfaces.iTemplate>();
                                            foreach (var it in templateList)
                                            {
                                                var tmp = HelperClasses.ArgList.resolveVarTypeObject(opFnc.ReturnType, it.TemplateObject, variable.TemplateObject);
                                                if (tmp != opFnc.ReturnType)
                                                {
                                                    this.ReferencedType = tmp;
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.UNKNOWN, this.Line, this.Pos, this.File));
                                    errCount++;
                                }
                            }
                            else
                            {
                                //just check if this is an array type
                                switch (this.ReferencedType.varType)
                                {
                                case VarType.BoolArray:
                                    this.ReferencedType         = new VarTypeObject(this.ReferencedType);
                                    this.ReferencedType.varType = VarType.Bool;
                                    break;

                                case VarType.ScalarArray:
                                    this.ReferencedType         = new VarTypeObject(this.ReferencedType);
                                    this.ReferencedType.varType = VarType.Scalar;
                                    break;

                                default:
                                    Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0006, this.Line, this.Pos, this.File));
                                    errCount++;
                                    break;
                                }
                            }
                        }
                    }
                }
                break;

                    #endregion
                    #region FunctionCall
                case IdenType.FunctionCall:
                {
                    List <Interfaces.iFunction> fncList;
                    var fncCall     = fncCalls[0];
                    var newInstance = this.getFirstOf <NewInstance>(true, typeof(Ident));
                    var fqn         = this.FullyQualifiedName;
                    if (parentIdent != null && parentIdent.ReferencedObject is Variable)
                    {
                        //if (((Variable)parentIdent.ReferencedObject).ReferencedType.IsObject)
                        //    fqn = ((Interfaces.iClass)((Variable)parentIdent.ReferencedObject).ReferencedType.ident.LastIdent.ReferencedObject).Name.LastIdent.FullyQualifiedName + "." + this.originalValue;
                        //else
                        parentIdent.ReferencedObject.finalize();
                        fqn = parentIdent.ReferencedType.ident.LastIdent.ReferencedType.ident.LastIdent.FullyQualifiedName + "." + this.originalValue;
                    }
                    if (newInstance == null)
                    {
                        fncList = HelperClasses.NamespaceResolver.getFunctionReferenceOfFQN(HelperClasses.NamespaceResolver.createNSR(fqn));
                    }
                    else
                    {
                        fncList = HelperClasses.NamespaceResolver.getFunctionReferenceOfFQN(HelperClasses.NamespaceResolver.createNSR(fqn + "." + this.originalValue));
                    }
                    if (fncList.Count == 0)
                    {
                        Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0001, this.Line, this.Pos, this.File));
                        errCount++;
                    }
                    else
                    {
                        //Search the correct function in the possible matches
                        Interfaces.iFunction fnc = null;
                        foreach (var it in fncList)
                        {
                            if (HelperClasses.ArgList.matchesArglist(it.ArgList, fncCall.ArgList, (parentIdent != null && parentIdent.ReferencedObject is Variable ? (Variable)parentIdent.ReferencedObject : null)))
                            {
                                fnc = it;
                                break;
                            }
                        }
                        //Raise new linker issue if we could not locate a matching function
                        if (fnc == null)
                        {
                            Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0002, this.Line, this.Pos, this.File));
                            errCount++;
                        }
                        else
                        {
                            if (fnc is Function && ((Function)fnc).IsConstructor && this.getFirstOf <NewInstance>() == null)
                            {
                                Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0026, this.Line, this.Pos, this.File));
                                errCount++;
                            }
                            //Ref the object to the function
                            this.ReferencedObject = (pBaseLangObject)fnc;
                            //Ref the type to the return type
                            this.ReferencedType = fnc.ReturnType;

                            //As last step make sure we got the correct encapsulation here
                            var enc = fnc.FunctionEncapsulation;
                            if (enc != Encapsulation.Static && enc != Encapsulation.Public)
                            {
                                var parentClass = this.getFirstOf <Interfaces.iClass>();
                                HelperClasses.NamespaceResolver fncNsr = fnc.Name;
                                if (enc == Encapsulation.Private)
                                {
                                    //Private encapsulation just requires checking the current class we are operating in
                                    if (!fncNsr.isInNamespace(parentClass == null ? null : parentClass.Name))
                                    {
                                        Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0003, this.Line, this.Pos, this.File));
                                        errCount++;
                                    }
                                }
                                else
                                {
                                    //Protected we need to check ALL extended classes ...
                                    var  classes = parentClass.ExtendedClasses;
                                    bool flag    = false;
                                    foreach (var it in classes)
                                    {
                                        if (fncNsr.isInNamespace(it))
                                        {
                                            flag = true;
                                            break;
                                        }
                                    }
                                    if (!flag)
                                    {
                                        Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0004, this.Line, this.Pos, this.File));
                                        errCount++;
                                    }
                                }
                            }
                        }
                    }
                }
                break;

                    #endregion
                    #region NamespaceAccess
                case IdenType.NamespaceAccess:
                {
                    if (this.IsAnonymousIdent)
                    {
                        this.ReferencedObject = getClassTemplate();
                        this.ReferencedObject = null;
                    }
                    else
                    {
                        var nsr = HelperClasses.NamespaceResolver.createNSR(this);
                        if (nsr == null)
                        {
                            Logger.Instance.log(Logger.LogLevel.ERROR, ErrorStringResolver.resolve(ErrorStringResolver.LinkerErrorCode.LNK0046, this.Line, this.Pos, this.File));
                            errCount++;
                        }
                        else
                        {
                            var reference = nsr.Reference;
                            this.ReferencedObject = reference;
                            if (reference is Interfaces.iClass)
                            {
                                this.ReferencedType = ((Interfaces.iClass)reference).VTO;
                            }
                            else if (reference is Interfaces.iFunction)
                            {
                                this.ReferencedType = ((Interfaces.iFunction)reference).ReturnType;
                            }
                            else
                            {
                                this.ReferencedType = null;
                            }
                        }
                    }
                }
                break;
                    #endregion
                }
            }


            return(errCount);
        }
Пример #2
0
        public override void writeOut(System.IO.StreamWriter sw, SqfConfigObjects.SqfConfigFile cfg)
        {
            string variableName = this.Name.WriteOutValue;

            if (this.ReferencedObject is Interfaces.iFunction)
            {
                Interfaces.iFunction fnc = (Interfaces.iFunction) this.ReferencedObject;
                bool flag = false;
                if (fnc is NativeInstruction)
                {
                    var           nIns       = (NativeInstruction)fnc;
                    List <string> stringList = new List <string>();
                    if (!string.IsNullOrEmpty(variableName))
                    {
                        stringList.Add(variableName);
                    }
                    foreach (var it in this.children)
                    {
                        using (MemoryStream memStream = new MemoryStream())
                        {
                            StreamWriter memStreamWriter = new StreamWriter(memStream);
                            it.writeOut(memStreamWriter, cfg);
                            memStreamWriter.Flush();
                            memStream.Seek(0, SeekOrigin.Begin);
                            stringList.Add(new StreamReader(memStream).ReadToEnd());
                        }
                    }
                    sw.Write(nIns.getCode(stringList.ToArray()));
                }
                else
                {
                    if (fnc.FunctionEncapsulation == Encapsulation.Static || fnc.IsConstructor)
                    {
                        sw.Write('[');
                    }
                    else
                    {
                        sw.Write('[' + variableName);
                        flag = true;
                    }
                    foreach (var it in this.children)
                    {
                        if (flag)
                        {
                            sw.Write(", ");
                        }
                        else
                        {
                            flag = true;
                        }
                        it.writeOut(sw, cfg);
                    }
                    if (fnc is Function)
                    {
                        if (fnc.IsVirtual)
                        {
                            sw.Write(']' + (!fnc.IsAsync ? " call (" : " spawn (") + '(' + variableName + ')' + ((Function)fnc).SqfVariableName + ')');
                        }
                        else
                        {
                            sw.Write(']' + (!fnc.IsAsync ? " call " : " spawn ") + ((Function)fnc).SqfVariableName);
                        }
                        if (((Function)fnc).IsThrowing && this.getFirstOf <TryCatch>() == null)
                        {
                            Ident ident = this.getFirstOf <Ident>();
                            Logger.Instance.log(Logger.LogLevel.WARNING, "Function '" + fnc.Name.FullyQualifiedName + "' is throwing but not catched. line " + ident.Line + ", pos " + ident.Pos + ", file '" + ident.File + '\'');
                        }
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
            }
            else
            {
                throw new Exception();
            }
        }