Exemplo n.º 1
0
        public void Visit(MainFuncNode n)
        {
            n.Table = GlobalSymbolTable.FunctionSymbolTable;

            var tableEntry = new FunctionSymbolTableEntry();

            tableEntry.Name = "main";

            foreach (var child in n.GetChildren())
            {
                child.SymTable = tableEntry;
                child.Accept(this);
            }

            var localScope = n.GetChildren().First().GetChildren().SelectMany(x => x.GetChildren()).ToList();

            for (int i = 0; i < localScope.Count; i += 3)
            {
                var paramType = localScope[i + 0].Token;
                var paramName = localScope[i + 1].Token.Lexeme;
                var arrayDims = NodeUtils.ExtractArrayDimListNode(localScope.GetCast <ArrayDimListNode>(i + 2));

                if (!CheckTypeExists(paramType.Lexeme))
                {
                    _errorStream.WriteLine($"Use of undeclared class, \"{paramType.Lexeme}\"({paramType.StartLine}:{paramType.StartColumn})");
                    Console.WriteLine($"Error: Use of undeclared class, \"{paramType.Lexeme}\"({paramType.StartLine}:{paramType.StartColumn})");
                }

                var entry = new FunctionSymbolTableEntryLocalScope()
                {
                    Type      = paramType,
                    Name      = paramName,
                    ArrayDims = arrayDims,
                };

                tableEntry.AddLocalScopeEntry(entry);
            }

            n.Table.AddEntry(tableEntry);
            n.SymTable = tableEntry;
        }
Exemplo n.º 2
0
        public static string GetTag(FunctionSymbolTableEntry entry)
        {
            StringBuilder sb = new StringBuilder();

            if (!string.IsNullOrEmpty(entry.ScopeSpec))
            {
                sb.Append($"{entry.ScopeSpec}_");
            }

            sb.Append($"{entry.Name}_");

            foreach (var param in entry.Params)
            {
                sb.Append($"{param.Type.type}_");
                foreach (var dim in param.Type.dims)
                {
                    sb.Append($"{dim}_");
                }
            }

            sb.Append(entry.ReturnType.Lexeme);

            return(sb.ToString());
        }
Exemplo n.º 3
0
        private void CalculateFunctionFrameSize(FunctionSymbolTableEntry functionTable)
        {
            var returnType = functionTable.ReturnType;
            var varType    = "";
            var size       = 0;

            if (returnType != null)
            {
                switch (returnType.TokenType)
                {
                case TokenType.Integer:
                    varType = TypeConstants.IntType;
                    size    = TypeConstants.IntTypeSize;
                    break;

                case TokenType.Float:
                    varType = TypeConstants.FloatType;
                    size    = TypeConstants.FloatTypeSize;
                    break;

                case TokenType.Identifier:
                {
                    var varClassTable = _globalSymbolTable.GetClassSymbolTableByName(returnType.Lexeme);
                    if (varClassTable.MemoryLayout.TotalSize == 0)
                    {
                        CalculateClassSize(varClassTable);
                    }

                    varType = varClassTable.ClassName;
                    size    = varClassTable.MemoryLayout.TotalSize;

                    break;
                }
                }
            }

            //functionTable.MemoryLayout.AddReturnValueEntry((varType, new List<int>()), size, size);

            foreach (var parameter in functionTable.Params)
            {
                var type       = parameter.Type;
                var multiplier = 1;
                foreach (var dim in type.dims)
                {
                    multiplier *= dim;
                }

                if (string.Equals(type.type, TypeConstants.IntType))
                {
                    parameter.MemSize = multiplier * TypeConstants.IntTypeSize;
                    functionTable.MemoryLayout.AddArgumentEntry(type, parameter.Name, TypeConstants.IntTypeSize, parameter.MemSize);
                }
                else if (string.Equals(type.type, TypeConstants.FloatType))
                {
                    parameter.MemSize = multiplier * TypeConstants.FloatTypeSize;
                    functionTable.MemoryLayout.AddArgumentEntry(type, parameter.Name, TypeConstants.FloatTypeSize, parameter.MemSize);
                }
                else
                {
                    var varClassTable = _globalSymbolTable.GetClassSymbolTableByName(type.type);
                    if (varClassTable.MemoryLayout.TotalSize == 0)
                    {
                        CalculateClassSize(varClassTable);
                    }

                    parameter.MemSize += multiplier * varClassTable.MemoryLayout.TotalSize;
                    functionTable.MemoryLayout.AddArgumentEntry(type, parameter.Name, varClassTable.MemoryLayout.TotalSize, parameter.MemSize);
                }
            }

            foreach (var variable in functionTable.LocalScope)
            {
                var multiplier = 1;
                foreach (var dim in variable.ArrayDims)
                {
                    multiplier *= dim;
                }

                var type = variable.Type;
                switch (type.TokenType)
                {
                case TokenType.Integer:
                    variable.MemSize += multiplier * TypeConstants.IntTypeSize;
                    functionTable.MemoryLayout.AddVariableEntry((TypeConstants.IntType, variable.ArrayDims), variable.Name, TypeConstants.IntTypeSize, variable.MemSize);
                    break;

                case TokenType.Float:
                    variable.MemSize += multiplier * TypeConstants.FloatTypeSize;
                    functionTable.MemoryLayout.AddVariableEntry((TypeConstants.FloatType, variable.ArrayDims), variable.Name, TypeConstants.IntTypeSize, variable.MemSize);
                    break;

                case TokenType.Identifier:
                {
                    var varClassTable = _globalSymbolTable.GetClassSymbolTableByName(type.Lexeme);
                    if (varClassTable.MemoryLayout.TotalSize == 0)
                    {
                        CalculateClassSize(varClassTable);
                    }

                    variable.MemSize += multiplier * varClassTable.MemoryLayout.TotalSize;
                    functionTable.MemoryLayout.AddVariableEntry((varClassTable.ClassName, variable.ArrayDims), variable.Name, varClassTable.MemoryLayout.TotalSize, variable.MemSize);

                    break;
                }
                }
            }
        }
Exemplo n.º 4
0
        public void Visit(FuncDefNode n)
        {
            var children = n.GetChildren();

            var tableEntry = new FunctionSymbolTableEntry();
            List <ASTNodeBase> funcParamList;
            List <ASTNodeBase> localScope;

            bool hasScopeSpec = children[1] is IdentifierNode;

            if (hasScopeSpec)
            {
                tableEntry.ScopeSpec  = children[0].Token.Lexeme;
                tableEntry.Name       = children[1].Token.Lexeme;
                funcParamList         = children[2].GetChildren();
                tableEntry.ReturnType = children[3].Token;
                localScope            = children.GetCast <FuncBodyNode>(4).GetChildren().First().GetChildren().SelectMany(x => x.GetChildren()).ToList();
            }
            else
            {
                tableEntry.Name       = children[0].Token.Lexeme;
                funcParamList         = children[1].GetChildren();
                tableEntry.ReturnType = children[2].Token;
                localScope            = children.GetCast <FuncBodyNode>(3).GetChildren().First().GetChildren().SelectMany(x => x.GetChildren()).ToList();
            }

            for (int i = 0; i < funcParamList.Count; i += 3)
            {
                var paramType = funcParamList[i + 0].Token;
                var paramName = funcParamList[i + 1].Token.Lexeme;
                var arrayDims = NodeUtils.ExtractArrayDimListNode(funcParamList.GetCast <ArrayDimListNode>(i + 2));

                var entry = new FunctionSymbolTableEntryParam()
                {
                    TypeToken = paramType,
                    Name      = paramName,
                    ArrayDims = arrayDims,
                };

                tableEntry.AddParamEntry(entry);
            }

            for (int i = 0; i < localScope.Count; i += 3)
            {
                var paramType = localScope[i + 0].Token;
                var paramName = localScope[i + 1].Token.Lexeme;
                var arrayDims = NodeUtils.ExtractArrayDimListNode(localScope.GetCast <ArrayDimListNode>(i + 2));

                if (!CheckTypeExists(paramType.Lexeme))
                {
                    _errorStream.WriteLine($"Use of undeclared class, \"{paramType.Lexeme}\"({paramType.StartLine}:{paramType.StartColumn})");
                    Console.WriteLine($"Error: Use of undeclared class, \"{paramType.Lexeme}\"({paramType.StartLine}:{paramType.StartColumn})");
                }

                var entry = new FunctionSymbolTableEntryLocalScope()
                {
                    Type      = paramType,
                    Name      = paramName,
                    ArrayDims = arrayDims,
                };

                tableEntry.AddLocalScopeEntry(entry);
            }

            n.Table = tableEntry;
            GlobalSymbolTable.FunctionSymbolTable.AddEntry(tableEntry);
        }
Exemplo n.º 5
0
        private bool FunctionDeclFound(IEnumerable <ClassSymbolTableEntryFunction> decls, FunctionSymbolTableEntry defn)
        {
            bool found = false;

            foreach (var decl in decls)
            {
                if (string.Equals(defn.ScopeSpec, ((ClassSymbolTable)decl.Parent).ClassName) &&
                    string.Equals(defn.Name, decl.Name) &&
                    FunctionDefnDeclParamsMatch(decl.ParamsTable, defn.Params))
                {
                    found = true;
                }
            }

            return(found);
        }
Exemplo n.º 6
0
        public void Visit(SubFuncCallNode n)
        {
            var children = n.GetChildren();

            var token = ((IdentifierNode)children[0]).Token;

            n.FuncName = token.Lexeme;

            List <FunctionSymbolTableEntry> candidateFuncsInScope;

            switch (n.SymTable)
            {
            case FunctionSymbolTableEntry f:
            {
                candidateFuncsInScope = new List <FunctionSymbolTableEntry>();
                if (!string.IsNullOrEmpty(f.ScopeSpec))
                {
                    ClassSymbolTable s = _globalTable.GetClassSymbolTableByName(f.ScopeSpec);
                    var funcsInClass   = s.GetFunctions().Where(x => string.Equals(x.Name, n.FuncName)).ToList();
                    candidateFuncsInScope = candidateFuncsInScope.Concat(funcsInClass).ToList();
                }

                var candidateFuncsInGlobalScope = _globalTable.FunctionSymbolTable.Entries
                                                  .Cast <FunctionSymbolTableEntry>()
                                                  .Where(x => string.Equals(x.Name, n.FuncName) && string.IsNullOrEmpty(x.ScopeSpec)).ToList();

                // Same name, in class or free function
                //candidateFuncsInScope = s.GetFunctions().Where(x => string.Equals(x.Name, n.FuncName)).ToList();
                candidateFuncsInScope = candidateFuncsInScope.Concat(candidateFuncsInGlobalScope).ToList();
            }
            break;

            case ClassSymbolTable s:
            {
                // Same name, in class
                candidateFuncsInScope = s.GetFunctions().Where(x => string.Equals(x.Name, n.FuncName)).ToList();
            }
            break;

            default:
                throw new InvalidOperationException("Unknown table entry type found");
            }

            if (candidateFuncsInScope.Count == 0)
            {
                _errorStream.WriteLine($"Use of undefined function: \"{n.FuncName}\" ({token.StartLine}:{token.StartColumn})");
                Console.WriteLine($"Error: Use of undefined function: \"{n.FuncName}\" ({token.StartLine}:{token.StartColumn})");
            }

            // Visit FuncCallParamsNode to get parameter types used
            var funcParams = (FuncCallParamsNode)children[1];

            funcParams.CallerTable = n.CallerTable;
            funcParams.Accept(this);
            var funcParamTypes = funcParams.ParamsTypes;

            FunctionSymbolTableEntry matchingFunc = null;

            foreach (var candidateFunc in candidateFuncsInScope)
            {
                if (candidateFunc.Params.Count != funcParamTypes.Count)
                {
                    continue;
                }

                bool matches = true;
                for (int i = 0; i < candidateFunc.Params.Count; ++i)
                {
                    (string type, List <int> dims)unpacked = funcParamTypes[i];

                    if (!string.Equals(candidateFunc.Params[i].Type.type, unpacked.type))
                    {
                        matches = false;
                        break;
                    }

                    if (candidateFunc.Params[i].Type.dims.Count == unpacked.dims.Count && candidateFunc.Params[i].Type.dims.All(x => x == 0))
                    {
                        matches = true;
                        break;
                    }

                    if (!candidateFunc.Params[i].Type.dims.SequenceEqual(unpacked.dims))
                    {
                        matches = false;
                        break;
                    }
                }

                if (matches)
                {
                    matchingFunc = candidateFunc;
                    break;
                }
            }

            if (matchingFunc == null)
            {
                _errorStream.WriteLine($"Use of function: \"{n.FuncName}\" ({token.StartLine}:{token.StartColumn}) with invalid parameters (no matching overload was found)");
                Console.WriteLine($"Error: Use of function: \"{n.FuncName}\" ({token.StartLine}:{token.StartColumn}) with invalid parameters (no matching overload was found)");
            }
            else
            {
                n.CallerTable       = n.SecondarySymTable;
                n.SecondarySymTable = matchingFunc;
                n.ScopeSpec         = matchingFunc.ReturnType.Lexeme;
                n.ExprType          = (matchingFunc.ReturnType.Lexeme, new List <int>());
            }
        }