예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="classIndex"></param>
        /// <param name="function"></param>
        /// <param name="si"></param>
        /// <param name="isStatic"></param>
        /// <returns>
        /// the key means the function index of thr procedure, not that it may be different from argument classIndex if
        /// the procedure comes from its base class
        /// </returns>
        private static List <KeyValuePair <int, ProtoCore.DSASM.ProcedureNode> > GetMemberFunctions(int classIndex, string function, ScopeInfo si, bool isStatic)
        {
            ProtoCore.DSASM.ClassNode cn = compileState.ClassTable.ClassNodes[classIndex];
            List <KeyValuePair <int, ProtoCore.DSASM.ProcedureNode> > functionList = new List <KeyValuePair <int, ProtoCore.DSASM.ProcedureNode> >();

            // first search its own functions
            if (cn.vtable == null)
            {
                return(functionList);
            }
            foreach (ProtoCore.DSASM.ProcedureNode pn in cn.vtable.procList)
            {
                if (pn.isConstructor ||
                    pn.name != function ||
                    pn.isStatic != isStatic)
                {
                    continue;
                }

                // here we have found a function with the same name
                // check if it is accessible
                if (GetAccessLevel(si.ClassScope, classIndex) >= pn.access)
                {
                    functionList.Add(new KeyValuePair <int, ProtoCore.DSASM.ProcedureNode>(classIndex, pn));
                }
            }

            // continue to search its base class
            foreach (int baseClass in cn.baseList)
            {
                functionList.AddRange(GetMemberFunctions(baseClass, function, si, isStatic));
            }

            return(functionList);
        }
예제 #2
0
        public void VerifyMethodExists(string className, string methodName, bool doAssert = true)
        {
            int classIndex = testCore.ClassTable.IndexOf(className);

            if (classIndex == ProtoCore.DSASM.Constants.kInvalidIndex)
            {
                if (doAssert)
                {
                    Assert.Fail(string.Format("\tFailed to find type \"{0}\" \n{1}", className, mErrorMessage));
                }
                return;
            }

            ProtoCore.DSASM.ClassNode thisClass = testCore.ClassTable.ClassNodes[classIndex];
            if (!thisClass.vtable.procList.Exists(memberFunc => String.Compare(memberFunc.name, methodName) == 0))
            {
                if (doAssert)
                {
                    Assert.Fail(string.Format("\tMethod \"{0}.{1}\" doesn't exist \n{2}", className, methodName, mErrorMessage));
                }
            }
            else if (!doAssert)
            {
                Assert.Fail(string.Format("\tMethod \"{0}.{1}\" does exist \n{2}", className, methodName, mErrorMessage));
            }
        }
예제 #3
0
 public void Reserve(int size)
 {
     for (int n = 0; n < size; ++n)
     {
         ProtoCore.DSASM.ClassNode cnode = new ProtoCore.DSASM.ClassNode { Name = ProtoCore.DSDefinitions.Keyword.Invalid, Size = 0, Rank = 0, Symbols = null, ProcTable = null };
         classNodes.Add(cnode);
     }
 }
예제 #4
0
 public void Reserve(int size)
 {
     for (int n = 0; n < size; ++n)
     {
         ProtoCore.DSASM.ClassNode cnode = new ProtoCore.DSASM.ClassNode {
             name = ProtoCore.DSDefinitions.Kw.kw_invalid, size = 0, rank = 0, symbols = null, vtable = null
         };
         classNodes.Add(cnode);
     }
 }
예제 #5
0
        /// <summary>
        /// Return all the members of a class
        /// </summary>
        /// <param name="classIndex"></param>
        /// <param name="si"></param>
        /// <param name="searchingBase">if searchingBase == true, the MemberType.FromBase of the returned members will be set </param>
        /// <param name="isStatic"></param>
        /// <param name="includeConstructor"></param>
        /// <returns></returns>
        private static List <KeyValuePair <MemberType, string> > GetClassMembers(int classIndex, ScopeInfo si, bool searchingBase, bool isStatic, bool includeConstructor)
        {
            List <KeyValuePair <MemberType, string> > members = new List <KeyValuePair <MemberType, string> >();

            ProtoCore.DSASM.ClassNode cn = compileState.ClassTable.ClassNodes[classIndex];

            // 1. search the member variable
            if (cn.symbols != null && !searchingBase) // when searching base, no need to populate the member variable, it has already been added in code gen
            {
                foreach (ProtoCore.DSASM.SymbolNode sn in cn.symbols.symbolList.Values.Where(x => x.functionIndex == ProtoCore.DSASM.Constants.kInvalidIndex))
                {
                    if (GetAccessLevel(si.ClassScope, sn.classScope) >= sn.access &&
                        isStatic == sn.isStatic &&
                        !sn.name.StartsWith("%") /* block the internally generated members*/)
                    {
                        KeyValuePair <MemberType, string> member = new KeyValuePair <MemberType, string>(MemberType.Fields | AccessToMemberType(sn.access) | StaticToMemberType(isStatic) | BaseToMemberType(sn.classScope != classIndex), sn.name);
                        members.Add(member);
                    }
                }
            }
            // 2. search the member functions and constructors
            if (cn.vtable != null)
            {
                foreach (ProtoCore.DSASM.ProcedureNode pn in cn.vtable.procList)
                {
                    // get static members
                    if (GetAccessLevel(si.ClassScope, classIndex) >= pn.access && isStatic == pn.isStatic && pn.isConstructor == false && !pn.name.StartsWith("%") && pn.isAutoGenerated != true)
                    {
                        KeyValuePair <MemberType, string> member = new KeyValuePair <MemberType, string>(MemberType.Methods | AccessToMemberType(pn.access) | StaticToMemberType(pn.isStatic) | BaseToMemberType(searchingBase) | ConstructorToMemberType(pn.isConstructor), pn.name);
                        members.Add(member);
                    }
                    // get constructor
                    if (GetAccessLevel(si.ClassScope, classIndex) >= pn.access && true == pn.isConstructor && includeConstructor == true && !pn.name.StartsWith("%") && pn.isAutoGenerated != true)
                    {
                        KeyValuePair <MemberType, string> member = new KeyValuePair <MemberType, string>(MemberType.Methods | AccessToMemberType(pn.access) | StaticToMemberType(pn.isStatic) | BaseToMemberType(searchingBase) | ConstructorToMemberType(pn.isConstructor), pn.name);
                        members.Add(member);
                    }
                }
            }

            // 3. search base class
            if (cn.baseList != null) // Note, for nonstatic members it is been copied to the derived class, hence they have been added already
            {
                foreach (int baseIndex in cn.baseList)
                {
                    // searching base will be set to true since we are searching the base class now
                    members.AddRange(GetClassMembers(baseIndex, si, true, isStatic, false));
                }
            }

            return(members);
        }
예제 #6
0
        protected void EmitReturnStatement(Node node, ProtoCore.Type inferedType)
        {
            // Check the returned type against the declared return type
            if (null != localProcedure && core.IsFunctionCodeBlock(codeBlock))
            {
                if (localProcedure.isConstructor)
                {
                    Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != inferedType.UID);

                    ProtoCore.DSASM.ClassNode typeNode = core.ClassTable.ClassNodes[inferedType.UID];
                    Debug.Assert(null != typeNode);
                }
            }
        }
예제 #7
0
        private static List <KeyValuePair <int, ProtoCore.DSASM.ProcedureNode> > GetConstructors(int classIndex, string function, ScopeInfo si)
        {
            ProtoCore.DSASM.ClassNode       cn     = compileState.ClassTable.ClassNodes[classIndex];
            ProtoCore.DSASM.AccessSpecifier access = GetAccessLevel(si.ClassScope, classIndex);
            List <KeyValuePair <int, ProtoCore.DSASM.ProcedureNode> > functionList = new List <KeyValuePair <int, ProtoCore.DSASM.ProcedureNode> >();

            if (cn.vtable == null)
            {
                return(functionList);
            }
            foreach (ProtoCore.DSASM.ProcedureNode pn in cn.vtable.procList)
            {
                if (pn.name == function && pn.isConstructor && access >= pn.access)
                {
                    functionList.Add(new KeyValuePair <int, ProtoCore.DSASM.ProcedureNode>(classIndex, pn));
                }
            }

            // no need to search base constructors,

            return(functionList);
        }
예제 #8
0
        private static ProtoCore.DSASM.SymbolNode GetMemberVariable(int classIndex, string field, ScopeInfo si, bool isStatic)
        {
            if (field.IndexOfAny(new char[] { '[', ']' }) != -1)
            {
                string[] tokens = TokenizeArrayIndexers(field);
                field = tokens[0];
            }

            // one search is enough, because the code gen will copy all the accessible base
            // class member variabs to the current class table, life easier
            ProtoCore.DSASM.ClassNode cn = compileState.ClassTable.ClassNodes[classIndex];
            if (cn.symbols == null)
            {
                return(null);
            }
            for (int ix = cn.symbols.symbolList.Values.Count - 1; ix >= 0; --ix)
            {
                // we should search in reverse order because in code gen
                // the base class member variable is added first
                // hence we shoud search the its own variable first
                ProtoCore.DSASM.SymbolNode sn = cn.symbols.symbolList[ix];
                if (sn.functionIndex != ProtoCore.DSASM.Constants.kInvalidIndex ||
                    sn.name != field ||
                    isStatic != sn.isStatic)
                {
                    continue;
                }

                // here we have found a variable with the same name
                if (GetAccessLevel(si.ClassScope, sn.classScope) >= sn.access)
                {
                    return(sn);
                }
            }

            return(null);
        }
예제 #9
0
 public void Reserve(int size)
 {
     for (int n = 0; n < size; ++n)
     {
         ProtoCore.DSASM.ClassNode cnode = new ProtoCore.DSASM.ClassNode { Name = ProtoCore.DSDefinitions.Keyword.Invalid, Size = 0, Rank = 0, Symbols = null, ProcTable = null };
         classNodes.Add(cnode);
     }
 }
예제 #10
0
        private void EmitClassDeclNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            ClassDeclNode classDecl = node as ClassDeclNode;

            // Handling n-pass on class declaration
            if (ProtoCore.DSASM.AssociativeCompilePass.kClassName == compilePass)
            {
                ProtoCore.DSASM.ClassNode cnode = new ProtoCore.DSASM.ClassNode();
                cnode.name = classDecl.className;
                cnode.size = classDecl.varlist.Count;
                cnode.IsImportedClass = classDecl.IsImportedClass;
                cnode.typeSystem = core.TypeSystem;
                globalClassIndex = core.ClassTable.Append(cnode);
                CodeRangeTable.AddClassBlockRangeEntry(globalClassIndex,
                    classDecl.line,
                    classDecl.col,
                    classDecl.endLine,
                    classDecl.endCol,
                    core.CurrentDSFileName);
            }
            else if (ProtoCore.DSASM.AssociativeCompilePass.kClassHeirarchy == compilePass)
            {
                // Class heirarchy pass
                // Populating each class entry with their respective base classes
                globalClassIndex = core.ClassTable.IndexOf(classDecl.className);

                ProtoCore.DSASM.ClassNode cnode = core.ClassTable.ClassNodes[globalClassIndex];

                if (null != classDecl.superClass)
                {
                    for (int n = 0; n < classDecl.superClass.Count; ++n)
                    {
                        int baseClass = core.ClassTable.IndexOf(classDecl.superClass[n]);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex != baseClass)
                        {
                            cnode.baseList.Add(baseClass);
                            cnode.coerceTypes.Add(baseClass, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceBaseClass);
                        }
                    }
                }

            }
            else if (ProtoCore.DSASM.AssociativeCompilePass.kClassMemVar == compilePass)
            {
                // Class member variable pass
                // Populating each class entry symbols with their respective member variables

                globalClassIndex = core.ClassTable.IndexOf(classDecl.className);
                ProtoCore.DSASM.ClassNode cnode = core.ClassTable.ClassNodes[globalClassIndex];

                // Handle member vars from base class
                if (null != classDecl.superClass)
                {
                    for (int n = 0; n < classDecl.superClass.Count; ++n)
                    {
                        int baseClass = core.ClassTable.IndexOf(classDecl.superClass[n]);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex != baseClass)
                        {
                            // Append the members variables of every class that this class inherits from
                            foreach (ProtoCore.DSASM.SymbolNode symnode in core.ClassTable.ClassNodes[baseClass].symbols.symbolList.Values)
                            {
                                // It is a member variables
                                if (ProtoCore.DSASM.Constants.kGlobalScope == symnode.functionIndex)
                                {
                                    Debug.Assert(!symnode.isArgument);
                                    int symbolIndex = AllocateMemberVariable(globalClassIndex, symnode.isStatic ? symnode.classScope : baseClass, symnode.name, symnode.datatype, symnode.access, symnode.isStatic);

                                    if (symbolIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                                        cnode.size += ProtoCore.DSASM.Constants.kPointerSize;
                                }
                            }
                        }
                        else
                        {
                            Debug.Assert(false, "n-pass compile error, fixme Jun....");
                        }
                    }
                }

                // This list will store all static properties initialization
                // expression (say x = 1).
                List<BinaryExpressionNode> staticPropertyInitList = new List<BinaryExpressionNode>();

                foreach (VarDeclNode vardecl in classDecl.varlist)
                {
                    IdentifierNode varIdent = null;
                    if (vardecl.NameNode is IdentifierNode)
                    {
                        varIdent = vardecl.NameNode as IdentifierNode;
                    }
                    else if (vardecl.NameNode is BinaryExpressionNode)
                    {
                        BinaryExpressionNode bNode = vardecl.NameNode as BinaryExpressionNode;
                        varIdent = bNode.LeftNode as IdentifierNode;
                        if (vardecl.IsStatic)
                            staticPropertyInitList.Add(bNode);
                        else
                            cnode.defaultArgExprList.Add(bNode);
                    }
                    else
                    {
                        Debug.Assert(false, "Check generated AST");
                    }

                    // It is possible that fail to allocate variable. In that
                    // case we should remove initializing expression from
                    // cnode's defaultArgExprList
                    ProtoCore.Type datatype = vardecl.ArgumentType;
                    if (string.IsNullOrEmpty(vardecl.ArgumentType.Name))
                        datatype.UID = (int)PrimitiveType.kTypeVar;
                    else
                    {
                        datatype.UID = core.TypeSystem.GetType(vardecl.ArgumentType.Name);
                        if (datatype.UID == ProtoCore.DSASM.Constants.kInvalidIndex)
                            datatype.UID = (int)PrimitiveType.kTypeVar;
                    }
                    datatype.Name = core.TypeSystem.GetType(datatype.UID);
                    int symbolIndex = ProtoCore.DSASM.Constants.kInvalidIndex;

                    if (varIdent is ProtoCore.AST.AssociativeAST.TypedIdentifierNode)
                        symbolIndex = AllocateTypedMemberVariable(globalClassIndex, globalClassIndex, varIdent.Value, datatype, vardecl.access, vardecl.IsStatic);
                    else
                        symbolIndex = AllocateMemberVariable(globalClassIndex, globalClassIndex, varIdent.Value, datatype, vardecl.access, vardecl.IsStatic);

                    if (symbolIndex != ProtoCore.DSASM.Constants.kInvalidIndex &&
                        !classDecl.IsExternLib)
                    {
                        ProtoCore.DSASM.SymbolNode memVar =
                            vardecl.IsStatic
                            ? core.CodeBlockList[0].symbolTable.symbolList[symbolIndex]
                            : core.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex];

                        EmitGetterForMemVar(classDecl, memVar);
                        EmitSetterForMemVar(classDecl, memVar);
                    }
                }
                classOffset = 0;

                // Now we are going to create a static function __init_static_properties()
                // which will initialize all static properties. We will emit a
                // call to this function after all classes have been compiled.
                if (staticPropertyInitList.Count > 0)
                {
                    FunctionDefinitionNode initFunc = new FunctionDefinitionNode()
                    {
                        Name = ProtoCore.DSASM.Constants.kStaticPropertiesInitializer,
                        Singnature = new ArgumentSignatureNode(),
                        Pattern = null,
                        ReturnType = new ProtoCore.Type { Name = core.TypeSystem.GetType((int)PrimitiveType.kTypeNull), UID = (int)PrimitiveType.kTypeNull },
                        FunctionBody = new CodeBlockNode(),
                        IsExternLib = false,
                        IsDNI = false,
                        ExternLibName = null,
                        access = ProtoCore.DSASM.AccessSpecifier.kPublic,
                        IsStatic = true
                    };
                    classDecl.funclist.Add(initFunc);

                    staticPropertyInitList.ForEach(bNode => initFunc.FunctionBody.Body.Add(bNode));
                    initFunc.FunctionBody.Body.Add(new BinaryExpressionNode()
                    {
                        LeftNode = new IdentifierNode()
                        {
                            Value = ProtoCore.DSDefinitions.Kw.kw_return,
                            Name = ProtoCore.DSDefinitions.Kw.kw_return,
                            datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeReturn, false)
                        },
                        Optr = ProtoCore.DSASM.Operator.assign,
                        RightNode = new NullNode()
                    });
                }
            }
            else if (ProtoCore.DSASM.AssociativeCompilePass.kClassMemFuncSig == compilePass)
            {
                // Class member variable pass
                // Populating each class entry vtables with their respective member variables signatures

                globalClassIndex = core.ClassTable.IndexOf(classDecl.className);
                foreach (AssociativeNode funcdecl in classDecl.funclist)
                {
                    DfsTraverse(funcdecl, ref inferedType);
                }

                if (!classDecl.IsExternLib)
                {
                    ProtoCore.DSASM.ProcedureTable vtable = core.ClassTable.ClassNodes[globalClassIndex].vtable;
                    if (vtable.IndexOfExact(classDecl.className, new List<ProtoCore.Type>()) == ProtoCore.DSASM.Constants.kInvalidIndex)
                    {
                        ConstructorDefinitionNode defaultConstructor = new ConstructorDefinitionNode();
                        defaultConstructor.Name = classDecl.className;
                        defaultConstructor.localVars = 0;
                        defaultConstructor.Signature = new ArgumentSignatureNode();
                        defaultConstructor.Pattern = null;
                        defaultConstructor.ReturnType = new ProtoCore.Type { Name = "var", UID = 0 };
                        defaultConstructor.FunctionBody = new CodeBlockNode();
                        defaultConstructor.baseConstr = null;
                        defaultConstructor.access = ProtoCore.DSASM.AccessSpecifier.kPublic;
                        defaultConstructor.IsExternLib = false;
                        defaultConstructor.ExternLibName = null;
                        DfsTraverse(defaultConstructor, ref inferedType);
                        classDecl.funclist.Add(defaultConstructor);
                    }
                }
            }
            else if (ProtoCore.DSASM.AssociativeCompilePass.kClassMemFuncBody == compilePass)
            {
                // Class member variable pass
                // Populating the function body of each member function defined in the class vtables

                globalClassIndex = core.ClassTable.IndexOf(classDecl.className);

                foreach (AssociativeNode funcdecl in classDecl.funclist)
                {
                    // reset the inferedtype between functions
                    inferedType = new ProtoCore.Type();
                    DfsTraverse(funcdecl, ref inferedType, false, null, subPass);
                }
            }

            // Reset the class index
            core.ClassIndex = globalClassIndex = ProtoCore.DSASM.Constants.kGlobalScope;
        }
예제 #11
0
 public void Reserve(int size)
 {
     for (int n = 0; n < size; ++n)
     {
         ProtoCore.DSASM.ClassNode cnode = new ProtoCore.DSASM.ClassNode { name = ProtoCore.DSDefinitions.Kw.kw_invalid, size = 0, rank = 0, symbols = null, vtable = null };
         classNodes.Add(cnode);
     }
 }