> ## Documentation Index
> Fetch the complete documentation index at: https://fluxon.tabooproject.org/llms.txt
> Use this file to discover all available pages before exploring further.

# 环境与作用域

> Environment 如何承载函数、变量与扩展

`Environment` 是 Fluxon 执行期的“作用域 + 符号表”。解释器与编译执行引擎都会基于同一个 `Environment` 完成变量读写、
函数调用与扩展函数分派（`target::method(...)`）。

它管理的核心要素：

* **函数**：系统函数（含命名空间函数）。
* **扩展函数**：上下文调用 `target::method(...)`。
* **变量**：根变量（全局）与局部变量（函数调用作用域）。
* **上下文目标**：`target` 槽位（由 `::` 调用临时写入）。

<Note>`Environment` 通常通过 `FluxonRuntime#getInstance().newEnvironment()` 创建。注册新的函数/扩展/变量后，
重新创建环境以刷新运行时缓存。</Note>

## Root 与子环境

* **根环境（root）**：持有函数映射、扩展函数映射、根变量映射，以及运行时生成的缓存结构（用于加速调用分派）。
* **子环境（child）**：用于函数调用作用域，只存放局部变量数组与（可选的）局部变量名；通过 `root` 引用共享根数据。

## 函数解析

普通函数通过 `Environment#getFunction(name)` 在根函数表中查找；不存在会抛出 `FunctionNotFoundError`。

命名空间函数（如 `fs:time`）需要脚本先 `import 'fs:time'` 才会被解析到（见 [术语表](/appendix/glossary)）。

## 扩展函数解析（`target::method`）

扩展函数的匹配依赖 `target` 的宿主类型：

* 解析器在可优化的场景下会为调用点生成 `extensionPositionIndex`，运行时会使用 `root.dispatchTables[index]` 快速解析。
* 对于动态注册或无法提前编号的调用点，会回退到 `root.extensionFunctions.get(name)` 的映射，并按“精确类型 →
  isAssignableFrom”顺序匹配。

<Note>如果你在运行中动态注册了扩展函数，旧的 `Environment` 可能不会包含新的派发表缓存；建议在注册完成后重新 `newEnvironment()`。</Note>

## 变量与索引

变量访问在运行时以“索引”为主：

* `index = -1`：根变量（保存在 `rootVariables`）。
* `index >= 0`：局部变量（保存在 `localVariables[index]`），必要时沿 parent 链回溯。

当索引越界且不存在 parent 时会抛出 `VariableNotFoundError`，并附带 `localVariableNames` 以便定位问题。

## 上下文目标 `target`

上下文调用会把左侧表达式写入 `Environment#target`，再执行右侧函数/扩展；执行完成后解释器会恢复旧的 `target`。

## 调试与枚举

* `Environment#getRootFunctions()`：当前系统函数表。
* `Environment#getRootExtensionFunctions()`：当前扩展函数映射（类型 → Function）。
* `Environment#getRootVariables()`：当前根变量表（含宿主注入的对象）。
* `FunctionContext#toString()`：定位一次调用的 target 与参数。

## 外部变量注入

Fluxon 提供两种方式向脚本注入外部变量：**根变量（RootVariable）** 和 **参数（Parameter）**。

### 对比

| 特性       | 根变量                   | 参数                      |
| -------- | --------------------- | ----------------------- |
| **定义时机** | 运行时                   | 编译期                     |
| **存储方式** | HashMap 查找            | 数组索引                    |
| **类型**   | 无类型（Object）           | 强类型（double、long、Object） |
| **性能**   | 中等                    | 高                       |
| **共享范围** | 全局（所有 Environment 共享） | 每个 Environment 独立       |

### 根变量

根变量通过 HashMap 存储，适合全局常量或工具对象：

```java theme={null}
// 方式一：通过 FluxonRuntime 注册（全局共享）
FluxonRuntime.getInstance().registerVariable("config", configObject);

// 方式二：在 Environment 中定义
env.defineRootVariable("logger", loggerInstance);
env.setRootVariable("logger", newLoggerInstance);  // 修改
Object logger = env.getRootVariable("logger");     // 读取
```

脚本中通过 `&` 引用访问：

```fluxon theme={null}
&config :: get("timeout")
&logger :: info("message")
```

### 参数

参数通过数组索引存储，适合高频调用场景：

```java theme={null}
// 编译期定义（必须指定类型）
CompilationContext ctx = new CompilationContext(source);
ctx.defineParameter("rate", double.class);
ctx.defineParameter("name", String.class);
CompiledScript script = ctx.compile();

// 运行时绑定
Environment env = script.newEnvironment();
env.setParameter("rate", 0.15);
env.setParameter("name", "Alice");
script.execute(env);

// 换值再执行（无需重新编译）
env.setParameter("rate", 0.20);
script.execute(env);
```

### 选择建议

* **根变量**：全局配置、工具对象、不常变化的数据
* **参数**：需要高频变化的输入值、性能敏感场景

<Note>参数必须在编译前定义，编译后无法新增；根变量可随时添加。</Note>

## 参数绑定 API

### Environment 参数方法

| 方法                           | 说明                     |
| ---------------------------- | ---------------------- |
| `setParameter(name, value)`  | 设置对象类型参数值。             |
| `setParameter(name, double)` | 设置 double 类型参数值（避免装箱）。 |
| `setParameter(name, long)`   | 设置 long 类型参数值。         |
| `getParameterInfo(name)`     | 获取参数的元信息（类型、索引）。       |

### 脚本中使用

参数通过 `&` 引用访问，与普通变量语法一致：

```fluxon theme={null}
total = &price * (1 + &rate)
greeting = "Hello, " + &name
```

## FunctionContext 参数获取

在函数实现中，通过 `FunctionContext` 获取参数：

| 方法                   | 说明                 |
| -------------------- | ------------------ |
| `getRef(index)`      | 获取指定索引的参数原始引用。     |
| `getInt(index)`      | 获取 int 类型参数。       |
| `getLong(index)`     | 获取 long 类型参数。      |
| `getDouble(index)`   | 获取 double 类型参数。    |
| `getAsDouble(index)` | 将任意数值参数转换为 double。 |
| `getString(index)`   | 获取 String 类型参数。    |

```java theme={null}
import static org.tabooproject.fluxon.runtime.FunctionSignature.returns;
import org.tabooproject.fluxon.runtime.Type;

runtime.registerFunction("multiply", returns(Type.D).params(Type.D, Type.D), ctx -> {
    double a = ctx.getAsDouble(0);
    double b = ctx.getAsDouble(1);
    ctx.setReturnDouble(a * b);
});
```

## 相关链接

* [解释器执行流](/runtime/interpreter)
* [编译执行引擎](/runtime/execution-engine)
* [运行时注册 API](/developer/runtime-registry)
* [扩展函数 API](/developer/extension-api)
* [故障排查](/developer/troubleshooting)
