Strings and Labels look the same, but Labels are completely different.
Function calls, macro calls, and rule invocations look the same, but to Bazel they are different things.
Rules have an entirely different evaluation model from functions and macros. When you call a rule, it creates a node inside of Bazel that represents the rule invoation. Every such node has a name, and you can have Bazel list which rules are in which BUILD files.
Starlark
Starlark is an imperative language, which is confusing, because BUILD files look declarative, but they are actually imperative, and are actually executed from top to bottom.
No floating point in starlark.
No set type.
Phase Model for Bazel Rule Execution
All models are wrong, but some models are useful.
Load phase
Reading and executing BUILD files. Not all of them, just the one that are needed.
Dependencies are not available during loading. You can load(…) a .bzl file, and in this way share information between BUILD files, but you can not read another BUILD file directly.
List files: glob() does run during loading, and so can be used to list files on the filesystem.
Analysis
Each rule can create output files and actions needed to generate them.
Rules can access information from their dependencies, bottom up.