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; }
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()); }
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; } } } }
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); }
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); }
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>()); } }