Move and restructure how we specify scopes

This commit is contained in:
Natalie Weizenbaum 2023-10-06 16:46:51 -07:00
parent 5a339469b9
commit 353942622f
9 changed files with 65 additions and 42 deletions

View File

@ -1187,7 +1187,7 @@ Given a source file `file`, a [configuration](#configuration) `config`, and an
* Otherwise, let `scope` be the scope of the innermost block such that `scope`
already has a variable named `name`. Set `scope`'s variable `name` to `value`.
[scope]: ../spec/variables.md#scope
[scope]: ../spec/spec.md#scope
* When a top-level mixin or function declaration `declaration` is encountered:

View File

@ -125,7 +125,7 @@ To execute a `VariableDeclaration` `declaration`:
variable named `name`, set the innermost block's scope's variable `name` to
`value`.~~
[scope]: ../spec/variables.md#scope
[scope]: ../spec/spec.md#scope
* **Otherwise, if `resolved` is null, get the innermost block containing
`declaration` and set its scope's variable `name` to `value`.**

View File

@ -53,15 +53,16 @@ To execute a `@for` rule `rule`:
* While `i` is not equal to `to`:
* Let `scope` be a new [scope].
* [In a new scope]:
* Add a variable with `rule`'s `VariableName` as its name and `i` as its value
to `scope`.
* Add a variable with `rule`'s `VariableName` as its name and `i` as its value
to the [current scope].
> Note that this variable will have the same unit that `from`.
* Execute the `ForBlock`'s statements in `scope`.
* Set `i` to `i + direction`.
> Note that this variable will have the same unit that `from`.
[scope]: ../variables.md#scope
* Execute the `ForBlock`'s statements.
* Set `i` to `i + direction`.
[In a new scope]: ../spec.md#running-in-a-new-scope
[current scope]: ../spec.md#scope

View File

@ -42,6 +42,6 @@ To execute a `@function` rule `rule`:
[the current module]: ../spec.md#current-module
[the current import context]: ../spec.md#current-import-context
* Otherwise, set the innermost block's [scope][]'s function `name` to `value`.
* Otherwise, set the [current scope]'s function `name` to `rule`.
[scope]: ../variables.md#scope
[current scope]: ../spec.md#scope

View File

@ -138,7 +138,7 @@ To execute an `@import` rule `rule`:
* Add `imported`'s [extensions][] to the current module.
* If the `@import` rule is nested within at-rules and/or style rules, add each
member in `imported` to the local [scope][].
member in `imported` to the [current scope].
* Otherwise, add each member in `imported` to the current import context and
the current module.
@ -158,4 +158,4 @@ To execute an `@import` rule `rule`:
[current import context]: ../spec.md#current-import-context
[resolving `imported`'s extensions]: extend.md#resolving-a-modules-extensions
[extensions]: extend.md#extension
[scope]: ../variables.md#scope
[current scope]: ../spec.md#scope

View File

@ -33,20 +33,22 @@ To execute a `@mixin` rule `rule`:
* If `rule` is outside of any block of statements:
* If `name` *doesn't* begin with `-` or `_`, set [the current module][]'s
* If `name` *doesn't* begin with `-` or `_`, set [the current module]'s
mixin `name` to `rule`.
> This overrides the previous definition, if one exists.
* Set [the current import context][]'s mixin `name` to `rule`.
* Set [the current import context]'s mixin `name` to `rule`.
> This happens regardless of whether or not it begins with `-` or `_`.
* Otherwise, set the innermost block's [scope][]'s mixin `name` to `value`.
* Otherwise, set the [current scope]'s mixin `name` to `rule`.
[scope]: ../variables.md#scope
[the current module]: ../spec.md#current-module
[the current import context]: ../spec.md#current-import-context
> This overrides the previous definition, if one exists.
[the current module]: ../spec.md#current-module
[the current import context]: ../spec.md#current-import-context
[current scope]: ../spec.md#scope
## `@include`

View File

@ -426,13 +426,12 @@ and returns a member of type `type` or null.
* If `name` is a plain `Identifier` or a `Variable` that's not a
`NamespacedVariable`:
* Let `scope` be the [scope][] of the innermost block containing the current
statement such that `scope` has a member of type `type` named `name`, or
null if no such scope exists.
* Let `scope` be the [current scope] or its innermost parent such that `scope`
has a member of type `type` named `name`, or null if no such scope exists.
* If `scope` is not null, return `scope`'s value of type `type` named `name`.
[scope]: variables.md#scope
[current scope]: spec.md#scope
* If `name` is a [`NamespacedIdentifier`](#syntax) of the form
`namespace.raw-name` or a [`Variable`][] of the form `namespace.$raw-name`:

View File

@ -19,10 +19,14 @@ the language this way.
## Table of Contents
* [Definitions](#definitions)
* [Scope](#scope)
* [Global Scope](#global-scope)
* [Current Source File](#current-source-file)
* [Current Configuration](#current-configuration)
* [Current Import Context](#current-import-context)
* [Current Module](#current-module)
* [Procedures](#procedures)
* [Running in a New Scope](#running-in-a-new-scope)
* [Semantics](#semantics)
* [Compiling a Path](#compiling-a-path)
* [Compiling a String](#compiling-a-string)
@ -30,6 +34,23 @@ the language this way.
## Definitions
### Scope
A *scope* is a mutable structure that contains:
* The scope's *variables*: a mapping from identifiers to SassScript values.
* The scope's *mixins*: a mapping from identifiers to mixins.
* The scope's *functions*: a mapping from identifiers to functions.
* The scope's *parent*: a reference to another scope, which may be unset.
One scope at a time is designated the *current scope*. By default, this is the
[global scope](#global-scope).
### Global Scope
The *global scope* is the scope shared among the top level of all Sass files. It
has no parent.
### Current Source File
The *current source file* is the [source file][] that was passed to the
@ -64,6 +85,19 @@ invocation of [Executing a File](#executing-a-file).
> Because a module is only made immutable (other than its variables) when
> execution has finished, the current module is always mutable.
## Procedures
### Running in a New Scope
To run a set of steps *in a new scope*:
* Let `parent` be the [current scope].
[current scope]: #scope
* Return the result of running the given steps with the current scope set to an
empty scope with `parent` as its parent.
## Semantics
### Compiling a Path

View File

@ -3,9 +3,6 @@
## Table of Contents
* [Syntax](#syntax)
* [Definitions](#definitions)
* [Scope](#scope)
* [Global Scope](#global-scope)
* [Semantics](#semantics)
* [Executing a Variable Declaration](#executing-a-variable-declaration)
* [Evaluating a Variable](#evaluating-a-variable)
@ -27,18 +24,6 @@ the `.$` in `NamespacedVariable`. Each of `!global` and `!default` is allowed
at most once in `VariableDeclaration`. As with all statements, a
`VariableDeclaration` must be separated from other statements with a semicolon.
## Definitions
### Scope
A *scope* is a mapping from variable names to values. Every block of statements
delimited by `{` and `}` in SCSS or by indentation in the indented syntax has an
associated scope.
### Global Scope
The *global scope* is the scope shared among the top level of all Sass files.
## Semantics
### Executing a Variable Declaration
@ -107,8 +92,10 @@ To execute a `VariableDeclaration` `declaration`:
> This also overrides the previous definition.
* Otherwise, if `resolved` is null, get the innermost block containing
`declaration` and set its scope's variable `name` to `value`.
* Otherwise, if `resolved` is null, set the [current scope]'s variable `name` to
`value`.
[current scope]: spec.md#scope
* Otherwise, set `resolved`'s value to `value`.