mirror of
https://github.com/thing-king/scope
synced 2026-01-03 06:54:44 +00:00
No description
| examples | ||
| src | ||
| .gitignore | ||
| README.md | ||
| scope.nimble | ||
scope
Lightweight library for tracking scope and identifier usage in untyped Nim macros. Builds live scope stack during AST traversal, recording definitions, usages, and shadowing with rich metadata.
Features
- Complete scope tracking - Procedures, blocks, loops, conditionals, exception handling
- Variable shadowing detection - Multi-level shadowing analysis with scope depths
- Cross-scope access patterns - Track variables used from outer scopes
- Rich metadata - Line numbers, scope depths, usage classifications
- Custom traversal callbacks - Hook into AST walking process
- Persistent storage - No data loss during scope transitions
- Zero dependencies - Pure Nim, works with any macro
Quick Start
import scope
macro analyzeScope(body: untyped): untyped =
let scope = newScope()
scope.walk(body)
# Check for variable shadowing
for name, info in scope:
if scope.isShadowed(name):
echo name, " is shadowed"
result = body
analyzeScope:
var x = 1
if true:
var x = 2 # Detected as shadow
API Reference
Core Types
type
UsageKind = enum
ukDef # Variable definition
ukUse # Variable usage
ukShadow # Shadow definition
UsageInfo = object
node*: NimNode
kind*: UsageKind
scopeDepth*: int
line*, col*: int
IdentInfo = object
name*: string
all*: seq[UsageInfo] # All usages
def*: UsageInfo # Definition info
Main API
# Create tracker
proc newScope*(): ScopeTracker
# Walk AST
proc walk*(st: ScopeTracker, root: NimNode)
proc walk*(st: ScopeTracker, root: NimNode, cb: WalkCallback)
# Query identifiers
proc info*(st: ScopeTracker, name: string): IdentInfo
proc info*(st: ScopeTracker, ident: NimNode): IdentInfo
proc allTracked*(st: ScopeTracker): seq[IdentInfo]
# Scope queries
proc currentScopeSymbols*(st: ScopeTracker): seq[string]
proc currentScopeLevel*(st: ScopeTracker): int
proc inCurrentScope*(st: ScopeTracker, name: string): bool
proc scopeOf*(st: ScopeTracker, name: string): int
# Analysis helpers
proc isDefined*(st: ScopeTracker, name: string): bool
proc isShadowed*(st: ScopeTracker, name: string): bool
proc usagesOf*(st: ScopeTracker, name: string): seq[UsageInfo]
proc shadowedIdents*(st: ScopeTracker): seq[IdentInfo]
# Iterators
iterator items*(st: ScopeTracker): IdentInfo
iterator pairs*(st: ScopeTracker): (string, IdentInfo)
iterator itemsInScope*(st: ScopeTracker, level: int): IdentInfo
Usage Patterns
Variable Shadowing Detection
macro checkShadowing(body: untyped): untyped =
let scope = newScope()
scope.walk(body)
for shadowedVar in scope.shadowedIdents():
echo "Warning: ", shadowedVar.name, " is shadowed"
result = body
Cross-Scope Analysis
macro findCrossScope(body: untyped): untyped =
let scope = newScope()
scope.walk(body)
for name, info in scope:
let usageDepths = info.all.mapIt(it.scopeDepth)
if usageDepths.len > 1:
echo name, " accessed across scopes: ", usageDepths
Macro Hygiene
macro hygieneCheck(newVarName: static[string], body: untyped): untyped =
let scope = newScope()
scope.walk(body)
if scope.isDefined(newVarName):
error("Variable name conflict: " & newVarName)
# Safe to generate code with newVarName
Custom Callbacks
proc scopeCallback(n: NimNode, st: ScopeTracker) =
if n.kind == nnkProcDef:
echo "Entering procedure at depth ", st.currentScopeLevel()
scope.walk(body, scopeCallback)
Supported Constructs
Procedures: proc, func, method, converter, iterator, template, macro
Control Flow: if/elif/else, case/of, for, while, block
Exception Handling: try/except/finally
Variable Declarations: var, let, const
Parameters: All procedure parameter types
Use Cases
- Hygiene-aware macro generation - Avoid variable name conflicts
- Static analysis tools - Detect unused variables, scope violations
- Code transformation - Safely rename/refactor variables
- Template engines - Generate code with proper scoping
- DSL implementation - Build domain-specific languages
- Debugging macros - Understand variable lifetime and visibility
Examples
See examples/example.nim for comprehensive demonstrations including:
- Multi-level variable shadowing
- Cross-scope variable access tracking
- Procedure parameter analysis
- Nested scope depth visualization
- Macro hygiene checking
Requirements
- Nim 1.6+ (uses modern macro APIs)
- No external dependencies
License
MIT