using Nub.Lang.Frontend.Parsing.Definitions; namespace Nub.Lang.Frontend.Generation; public class SymbolTable { private readonly List _functions = []; private readonly Stack _variables = []; private readonly Stack _scopes = []; public SymbolTable(IEnumerable functions) { foreach (var func in functions) { string name; switch (func) { case ExternFuncDefinitionNode externFuncDefinitionNode: { name = "$" + externFuncDefinitionNode.CallName; break; } case LocalFuncDefinitionNode localFuncDefinitionNode: { if (localFuncDefinitionNode.Exported) { name = "$" + localFuncDefinitionNode.Name; } else { name = "$" + localFuncDefinitionNode.Namespace + "_" + localFuncDefinitionNode.Name; } break; } default: { throw new ArgumentOutOfRangeException(nameof(func)); } } _functions.Add(new Func(func.Namespace, func.Name, name)); } } public void Reset() { _variables.Clear(); } public void StartScope() { _scopes.Push(_variables.Count); } public void EndScope() { var count = _scopes.Pop(); while (count > _variables.Count) { _variables.Pop(); } } public Symbol Lookup(string? @namespace, string name) { if (@namespace == null) { return LookupVariable(name); } return LookupFunc(@namespace, name); } public Func LookupFunc(string @namespace, string name) { return _functions.Single(x => x.Name == name && x.Namespace == @namespace); } public Variable LookupVariable(string name) { return _variables.Single(x => x.Name == name); } public void DeclareVariable(string name, string pointer) { _variables.Push(new Variable(name, pointer)); } public abstract class Symbol(string name) { public string Name { get; } = name; } public class Variable(string name, string pointer) : Symbol(name) { public string Pointer { get; set; } = pointer; } public class Func(string @namespace, string name, string generatedName) : Symbol(name) { public string Namespace { get; } = @namespace; public string GeneratedName { get; } = generatedName; } public class Struct(string @namespace, string name) : Symbol(name) { public string Namespace { get; } = @namespace; public string GeneratedName => $"{Namespace}_{Name}"; } }