Skip to content

RFC-015: YaoXiang Configuration System Design

Acceptance Date: 2026-02-15

Prerequisite RFC: RFC-014: Package Manager Design

Summary

Design a unified configuration system for YaoXiang language, supporting user-level and project-level scopes, providing shared configuration infrastructure for components like package manager, compiler, REPL, and LSP.

Motivation

Why is this feature/change needed?

The YaoXiang toolchain consists of multiple components:

  • Package manager (reads dependency configuration)
  • Compiler frontend (reads i18n configuration)
  • REPL (reads interactive configuration)
  • LSP (reads fmt/lint/test configuration)
  • Build system (reads build configuration)

Each component needs a unified configuration infrastructure.

Current Problems

  • Configuration is scattered across components with no unified standard
  • Users cannot manage their preferences in a unified way
  • No clear hierarchy between project configuration and user configuration

Proposal

Core Design

Layered Architecture:

Configuration Priority (High → Low):
┌─────────────────────────────────────────────┐
│ 1. Project-level yaoxiang.toml               │ ← Controlled by project team
├─────────────────────────────────────────────┤
│ 2. User-level ~/.config/yaoxiang/config.toml │ ← User preferences
├─────────────────────────────────────────────┤
│ 3. Compiler defaults                         │ ← Reasonable initial values
└─────────────────────────────────────────────┘

Rule: Upper layers override lower layers; unset options fall back to lower layers.

Configuration Layer Restrictions

Config SectionUser-levelProject-levelConsumer
[package].*Package manager
[yaoxiang]Compiler
[dependencies]Package manager
[dev-dependencies]Package manager
[bin]Package manager
[lib]Package manager
[build]Build system
[profile.*]Build system
[install]Package manager
[i18n]Compiler
[repl]REPL
[fmt]LSP
[lint]LSP
[test]LSP
[tasks]CLI

Examples

Project-level Configuration:

toml
# yaoxiang.toml
[package]
name = "my-package"
version = "0.1.0"

[yaoxiang]
version = ">=0.1.0, <1.0.0"

[dependencies]
foo = "^1.0.0"

[build]
output = "dist/"

[tasks]
build = "yaoxiang build"
test = "yaoxiang test"

User-level Configuration:

toml
# ~/.config/yaoxiang/config.toml
[install]
dir = "~/.local/share/yaoxiang"

[i18n]
lang = "zh"
fallback = "en"

[repl]
history-size = 1000
prompt = "yx> "
colors = true

[fmt]
line-width = 120
indent-width = 4

[lint]
rules = ["recommended"]

Detailed Design

Project-level-only Configuration

toml
[package]
name = "my-package"
version = "0.1.0"
description = "A short description"
authors = ["Alice <alice@example.com>"]
license = "MIT"
repository = "https://github.com/alice/my-project"

[yaoxiang]
version = ">=0.1.0, <1.0.0"

[dependencies]
foo = "^1.0.0"

[dev-dependencies]
test-utils = "0.1.0"

[lib]
path = "src/lib.yx"

[[bin]]
name = "my-cli"
path = "src/cli.yx"

[exports]
"." = "src/lib.yx"
"./foo" = "src/foo.yx"

[build]
script = "build.yx"
output = "dist/"

[profile.release]
optimize = true
lto = true

[run]
main = "src/main.yx"
args = ["--quiet"]

[tasks]
build = "yaoxiang build"
test = "yaoxiang test"
lint = "yaoxiang fmt && yaoxiang check"

User-level-only Configuration

toml
[install]
dir = "~/.local/share/yaoxiang"

Shared Configuration (Both Levels)

FieldTypeDefaultDescription
[i18n].langString"en"Language
[i18n].fallbackString"en"Fallback language
[repl].history-sizeNumber1000History entries
[repl].history-filePath~History file
[repl].promptString"yx> "Prompt
[repl].colorsBooleantrueSyntax highlighting
[repl].auto-imports[String][]Auto imports
[fmt].line-widthNumber120Line width
[fmt].indent-widthNumber4Indentation width
[fmt].use-tabsBooleanfalseTab indentation
[fmt].single-quoteBooleanfalseSingle quotes
[lint].rules[String]["recommended"]Rule set
[lint].strictBooleanfalseStrict mode
[test].reportString"console"Test report
[build].outputString"dist/"Output directory

Command Line and Environment Variable Overrides

bash
# Command line overrides
yaoxiang run main.yx --lang zh
yaoxiang fmt --config-indent-width=2

# Environment variables
export YAOXIANG_LANG=zh
export YAOXIANG_FMT_INDENT_WIDTH=2

Priority: Command Line > Environment Variables > Config File

yaoxiang config Command

Provides CLI commands for configuration management:

bash
# Initialize user-level configuration (with default options)
yaoxiang config init

# Edit user-level configuration (opens editor)
yaoxiang config edit

# Show current configuration (merged effective config)
yaoxiang config show

# Show configuration sources
yaoxiang config show --source

# Reset to default configuration
yaoxiang config reset

First Run: When a user runs any yaoxiang command for the first time, the system automatically checks if user-level configuration exists. If not, it generates one with default options automatically.

Configuration File Locations:

  • Project-level: ./yaoxiang.toml (project root directory)
  • User-level: ~/.config/yaoxiang/config.toml

Configuration Merge Semantics

Configurations from different layers are merged according to the following rules:

TypeStrategyDescription
Scalar (String/Number/Boolean)ReplaceProject-level overrides user-level
ArrayReplaceProject-level completely replaces user-level
ObjectDeep mergeField-by-field merge; undefined fields inherit from lower layer

Example - Object Deep Merge:

toml
# User-level
[lint]
rules = ["recommended"]
severity = "warn"

# Project-level
[lint]
strict = true

# Merged result
[lint]
rules = ["recommended"]    # from user-level
severity = "warn"          # from user-level
strict = true              # from project-level

Backward Compatibility

  • ✅ Existing no-config-file mode continues to be supported (all components use built-in defaults)
  • ✅ New configuration items all have reasonable defaults
  • ✅ Configuration is automatically generated with default options on first command run
  • ✅ Configuration parsing failures display friendly errors with specific line numbers and error reasons

Trade-offs

Advantages

  • Unified configuration infrastructure reduces duplicate code
  • User preferences remain consistent across projects
  • LSP/REPL/Compiler share the same configuration
  • Incremental configuration, declare as needed

Disadvantages

  • More configuration items, slightly increased learning curve
  • Requires a unified configuration parser

Alternative Approaches

ApproachWhy Not Chosen
Independent config per componentDuplicate code, fragmented user experience
Command-line arguments onlyCannot persist user preferences
Environment variables onlyProject configuration hard to version control

Implementation Strategy

Phases

PhaseContents
Phase 1Basic config parser, toml support, project-level config, yaoxiang config init
Phase 2User-level config, config merge logic, yaoxiang config edit/show
Phase 3Command line/env var overrides, platform constraints, [tool.*] extensions

Dependencies

  • Depends on RFC-014 Package Manager System

Risks

RiskMitigation
Too many config itemsProvide reasonable defaults, invisible to users
Complex parserUse existing toml library

Open Issues

  • [x] features conditional compilation syntax? → Moved to separate RFC, depends on RFC-011 Generics System
  • [x] workspace workspace design? → Moved to separate RFC, high complexity, needs independent design

Accepted Features (Phase 3)

platform Platform Constraints

Note: The following syntax is used in yaoxiang.toml configuration files, not in YaoXiang source code (.yx files). Users do not need to write cfg(...) in their code.

Supports platform-specific configuration based on target OS/architecture:

toml
# yaoxiang.toml (config file)

[target.'cfg(windows)'.build]
output = "dist/win32"

[target.'cfg(unix)'.build]
output = "dist/unix"

[target.'cfg(target_arch = "x86_64")'.build]
rustflags = ["-C target-cpu=native"]

Syntax: [target.'<condition>'.<config-section>]

Explanation:

  • This syntax only appears in yaoxiang.toml configuration files
  • During build, corresponding configuration is selected based on --target parameter
  • Users do not need, and should not, write cfg(...) syntax in .yx source code

Supported Conditions:

  • cfg(os = "windows") - Windows systems
  • cfg(os = "linux") - Linux systems
  • cfg(os = "macos") - macOS systems
  • cfg(target_arch = "x86_64") - 64-bit x86 architecture
  • cfg(target_arch = "aarch64") - ARM 64-bit architecture

[tool.*] Third-party Tool Configuration Extensions

Allows third-party tools to store configuration under [tool.<name>]:

toml
[tool.eslint]
extension = ["yx", "yxp"]
ignore = ["node_modules/", "dist/"]

[tool.prettier]
semi = false
singleQuote = true

Behavior:

  • YaoXiang ignores unknown [tool.*] sections but preserves them in the config file
  • Third-party tools can be integrated via yaoxiang tool run <name> or accessed directly
  • Tool-specific configurations are not validated

References