package scope type SymbolID struct { symbolKind SymbolKind scopeID ScopeID indexInScope int } func (id SymbolID) SymbolKind() SymbolKind { return id.symbolKind } func (id SymbolID) ScopeID() ScopeID { return id.scopeID } func (id SymbolID) IndexInScope() int { return id.indexInScope } type SymbolKind int const ( // A variable symbol is bound to a local on the stack. SymbolKindVariable SymbolKind = iota // An env symbol is bound to a local on the stack, outside of the function's scope. // Emitted at lookup time, so the SymbolScope has no array for them. SymbolKindEnv SymbolKind = iota ) func (s SymbolKind) String() string { switch s { case SymbolKindVariable: return "variable" case SymbolKindEnv: return "env" default: panic("unknown symbol kind") } } type Symbol[D SymbolData] struct { name string data D } func (s Symbol[D]) Data() D { return s.data } type SymbolData interface { SymbolVariable | SymbolEnv } type SymbolVariable struct { localIndex int } func (sv SymbolVariable) LocalIndex() int { return sv.localIndex } type SymbolEnv struct { indexInEnv int } func (se SymbolEnv) IndexInEnv() int { return se.indexInEnv }