KogenCredo.CoreSupport.Scope (KogenCredo v0.1.0)

View Source

Lexical walk over an AST that tracks alias, import and the enclosing module.

walk/3 calls fun.(node, env, acc) for every node, pre-order, with the env that is in force at that node:

  • env.aliases: short name => module name ("MyApp.Repo", see KogenCredo.CoreSupport.Ast.module_name/0), plus :__MODULE__ => the enclosing module's name when it is known (use KogenCredo.CoreSupport.Aliases.resolve/2);
  • env.imports: [{module_name, only}] where only is :all, a list of {name, arity}, or {:except, [{name, arity}]};
  • env.locals: {name, arity} of the functions the enclosing module defines itself (nested modules excluded), so a local definition can shadow an import.

Scoping follows Elixir: a declaration is visible to the following expressions of the same block and below, and never leaks out of the block, function or module that contains it. A nested defmodule Inner is Outer.Inner and aliases Inner. This is still syntactic: use-injected aliases/imports and alias generated by macros are invisible.

Summary

Functions

Empty environment.

Pre-order accumulate with the lexical environment in force at each node.

Types

env()

@type env() :: %{
  aliases: %{optional(atom()) => KogenCredo.CoreSupport.Ast.module_name()},
  imports: [
    {KogenCredo.CoreSupport.Ast.module_name(),
     :all | [{atom(), arity()}] | {:except, [{atom(), arity()}]}}
  ],
  locals: MapSet.t()
}

Functions

new_env()

@spec new_env() :: env()

Empty environment.

walk(ast, acc, fun)

@spec walk(Macro.t(), acc, (Macro.t(), env(), acc -> acc)) :: acc when acc: term()

Pre-order accumulate with the lexical environment in force at each node.