feat(phase88): Ring0Context Skeleton implementation

Phase 88: OS API abstraction layer implementation

**Implementation**:
- Ring0Context module added (4 files)
  - mod.rs: Public API, global initialization (OnceLock)
  - traits.rs: MemApi, IoApi, TimeApi, LogApi trait definitions
  - std_impls.rs: std-based default implementations
  - errors.rs: IoError, TimeError type definitions

**Design Principles**:
- Ring0 knows nothing about Box
- Ring0 knows nothing about Nyash
- Pure OS API abstraction

**Global Initialization**:
- NyashRunner::new() initializes Ring0Context globally
- OnceLock ensures safe initialization (idempotent)

**Migration (2 paths)**:
- src/runner/selfhost.rs:27: eprintln! → ring0.log.error() (OOB strict)
- src/runner/selfhost.rs:177: eprintln! → ring0.log.error() (PyVM error)

**Tests**:
- 4 unit tests added (ring0 module)
- All tests passed
- Build successful (0 errors)

**Migration Status**:
- Migrated: 2/3,955 (0.05%)
- Remaining: 3,953 paths (Phase 89+)

**Files Changed**:
- src/runtime/ring0/mod.rs (new, 100 lines)
- src/runtime/ring0/traits.rs (new, 93 lines)
- src/runtime/ring0/std_impls.rs (new, 77 lines)
- src/runtime/ring0/errors.rs (new, 26 lines)
- src/runtime/mod.rs (Ring0Context export)
- src/runner/mod.rs (global initialization)
- src/runner/selfhost.rs (2 paths migrated)
- docs/development/current/main/ring0-inventory.md (Phase 88 status)

Phase 88 complete. Ready for Phase 89 (gradual migration).

🐱
This commit is contained in:
nyash-codex
2025-12-02 22:38:27 +09:00
parent 8cd9729375
commit 42b09b3c1c
9 changed files with 331 additions and 5 deletions

View File

@ -6,6 +6,7 @@ pub mod box_registry;
pub mod core_box_ids; // Phase 87: CoreBoxId/CoreMethodId 型安全enum
pub mod deprecations;
pub mod gc;
pub mod ring0; // Phase 88: Ring0Context - OS API 抽象化レイヤー
pub mod gc_controller;
pub mod gc_mode;
pub mod gc_trace;
@ -38,6 +39,7 @@ mod tests;
pub use box_registry::{get_global_registry, BoxFactoryRegistry, BoxProvider};
pub use core_box_ids::{CoreBoxCategory, CoreBoxId, CoreMethodId}; // Phase 87: 型安全enum
pub use plugin_config::PluginConfig;
pub use ring0::{get_global_ring0, init_global_ring0, Ring0Context}; // Phase 88: Ring0 公開 API
pub use plugin_loader_unified::{
get_global_plugin_host, init_global_plugin_host, MethodHandle, PluginBoxType, PluginHost,
PluginLibraryHandle,

View File

@ -0,0 +1,25 @@
//! Phase 88: Ring0 エラー型定義
/// IO 操作エラー
#[derive(Debug, Clone)]
pub struct IoError(pub String);
impl std::fmt::Display for IoError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "IoError: {}", self.0)
}
}
impl std::error::Error for IoError {}
/// 時刻取得エラー
#[derive(Debug, Clone)]
pub struct TimeError(pub String);
impl std::fmt::Display for TimeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "TimeError: {}", self.0)
}
}
impl std::error::Error for TimeError {}

114
src/runtime/ring0/mod.rs Normal file
View File

@ -0,0 +1,114 @@
//! Phase 88: Ring0Context - OS API 抽象化レイヤー
//!
//! Ring0 は Box を知らない、Nyash を知らない純粋な OS API 層。
mod errors;
mod std_impls;
mod traits;
pub use errors::{IoError, TimeError};
pub use std_impls::{NoopMem, StdIo, StdLog, StdTime};
pub use traits::{IoApi, LogApi, LogLevel, MemApi, MemStats, TimeApi};
use std::sync::{Arc, OnceLock};
/// Phase 88: Ring0 コンテキスト
///
/// OS API レイヤーを trait で抽象化し、1つの構造体に束ねる。
pub struct Ring0Context {
pub mem: Arc<dyn MemApi>,
pub io: Arc<dyn IoApi>,
pub time: Arc<dyn TimeApi>,
pub log: Arc<dyn LogApi>,
}
impl Ring0Context {
/// 新規 Ring0Context を作成
pub fn new(
mem: Arc<dyn MemApi>,
io: Arc<dyn IoApi>,
time: Arc<dyn TimeApi>,
log: Arc<dyn LogApi>,
) -> Self {
Self { mem, io, time, log }
}
}
impl std::fmt::Debug for Ring0Context {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Ring0Context")
.field("mem", &"<dyn MemApi>")
.field("io", &"<dyn IoApi>")
.field("time", &"<dyn TimeApi>")
.field("log", &"<dyn LogApi>")
.finish()
}
}
/// デフォルト Ring0Context を作成std ベース)
pub fn default_ring0() -> Ring0Context {
Ring0Context {
mem: Arc::new(NoopMem),
io: Arc::new(StdIo),
time: Arc::new(StdTime),
log: Arc::new(StdLog),
}
}
// ===== グローバル Ring0Context =====
pub static GLOBAL_RING0: OnceLock<Arc<Ring0Context>> = OnceLock::new();
/// グローバル Ring0Context を初期化
pub fn init_global_ring0(ctx: Ring0Context) {
GLOBAL_RING0
.set(Arc::new(ctx))
.expect("[Phase 88] Ring0Context already initialized");
}
/// グローバル Ring0Context を取得
pub fn get_global_ring0() -> Arc<Ring0Context> {
GLOBAL_RING0
.get()
.expect("[Phase 88] Ring0Context not initialized")
.clone()
}
// ===== テスト =====
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ring0_context_creation() {
let ring0 = default_ring0();
ring0.log.info("test message");
}
#[test]
fn test_io_api() {
let ring0 = default_ring0();
let result = ring0.io.stdout_write(b"test\n");
assert!(result.is_ok());
}
#[test]
fn test_time_api() {
let ring0 = default_ring0();
let now = ring0.time.now();
assert!(now.is_ok());
let instant = ring0.time.monotonic_now();
assert!(instant.is_ok());
}
#[test]
fn test_log_levels() {
let ring0 = default_ring0();
ring0.log.debug("debug message");
ring0.log.info("info message");
ring0.log.warn("warn message");
ring0.log.error("error message");
}
}

View File

@ -0,0 +1,73 @@
//! Phase 88: std ベースの Ring0 デフォルト実装
use super::errors::{IoError, TimeError};
use super::traits::*;
use std::time::SystemTime;
/// noop メモリ実装Phase 88: 将来 hakmem に接続)
pub struct NoopMem;
impl MemApi for NoopMem {
fn alloc(&self, _size: usize) -> *mut u8 {
std::ptr::null_mut()
}
fn free(&self, _ptr: *mut u8) {}
fn stats(&self) -> MemStats {
MemStats::default()
}
}
/// std::io ベースの IO 実装
pub struct StdIo;
impl IoApi for StdIo {
fn stdout_write(&self, data: &[u8]) -> Result<(), IoError> {
use std::io::Write;
std::io::stdout()
.write_all(data)
.map_err(|e| IoError(format!("stdout write failed: {}", e)))
}
fn stderr_write(&self, data: &[u8]) -> Result<(), IoError> {
use std::io::Write;
std::io::stderr()
.write_all(data)
.map_err(|e| IoError(format!("stderr write failed: {}", e)))
}
fn stdin_read(&self, buf: &mut [u8]) -> Result<usize, IoError> {
use std::io::Read;
std::io::stdin()
.read(buf)
.map_err(|e| IoError(format!("stdin read failed: {}", e)))
}
}
/// std::time ベースの時刻実装
pub struct StdTime;
impl TimeApi for StdTime {
fn now(&self) -> Result<SystemTime, TimeError> {
Ok(SystemTime::now())
}
fn monotonic_now(&self) -> Result<std::time::Instant, TimeError> {
Ok(std::time::Instant::now())
}
}
/// eprintln!/println! ベースのログ実装
pub struct StdLog;
impl LogApi for StdLog {
fn log(&self, level: LogLevel, msg: &str) {
match level {
LogLevel::Debug => eprintln!("[DEBUG] {}", msg),
LogLevel::Info => println!("[INFO] {}", msg),
LogLevel::Warn => eprintln!("[WARN] {}", msg),
LogLevel::Error => eprintln!("[ERROR] {}", msg),
}
}
}

View File

@ -0,0 +1,83 @@
//! Phase 88: Ring0 trait 定義
//!
//! OS API レイヤーの純粋な抽象化。
//! Box 名・Nyash 型を一切知らない。
use super::errors::{IoError, TimeError};
use std::time::SystemTime;
/// メモリ APIPhase 88: noop、将来 hakmem 接続)
pub trait MemApi: Send + Sync {
/// メモリ割り当てPhase 88: 未実装)
fn alloc(&self, size: usize) -> *mut u8;
/// メモリ解放Phase 88: 未実装)
fn free(&self, ptr: *mut u8);
/// メモリ統計Phase 88: 未実装)
fn stats(&self) -> MemStats;
}
/// メモリ統計情報
#[derive(Debug, Default, Clone)]
pub struct MemStats {
pub allocated: usize,
pub freed: usize,
pub current: usize,
}
/// IO API
pub trait IoApi: Send + Sync {
/// 標準出力への書き込み
fn stdout_write(&self, data: &[u8]) -> Result<(), IoError>;
/// 標準エラー出力への書き込み
fn stderr_write(&self, data: &[u8]) -> Result<(), IoError>;
/// 標準入力からの読み込み
fn stdin_read(&self, buf: &mut [u8]) -> Result<usize, IoError>;
}
/// 時刻 API
pub trait TimeApi: Send + Sync {
/// 現在時刻取得
fn now(&self) -> Result<SystemTime, TimeError>;
/// モノトニック時刻取得(高精度タイマー用)
fn monotonic_now(&self) -> Result<std::time::Instant, TimeError>;
}
/// ログレベル
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogLevel {
Debug,
Info,
Warn,
Error,
}
/// ログ API
pub trait LogApi: Send + Sync {
/// ログ出力
fn log(&self, level: LogLevel, msg: &str);
/// デバッグログ(便利メソッド)
fn debug(&self, msg: &str) {
self.log(LogLevel::Debug, msg);
}
/// 情報ログ(便利メソッド)
fn info(&self, msg: &str) {
self.log(LogLevel::Info, msg);
}
/// 警告ログ(便利メソッド)
fn warn(&self, msg: &str) {
self.log(LogLevel::Warn, msg);
}
/// エラーログ(便利メソッド)
fn error(&self, msg: &str) {
self.log(LogLevel::Error, msg);
}
}