refactor: centralize box type metadata

This commit is contained in:
moe-charm
2025-09-11 04:20:28 +09:00
committed by Selfhosting Dev
parent f124731764
commit c4e1728b8e
9 changed files with 3041 additions and 1515 deletions

View File

@ -0,0 +1,18 @@
use std::collections::HashMap as StdHashMap;
/// Load box type-id mapping from `nyash_box.toml`.
pub fn load_box_type_ids() -> StdHashMap<String, i64> {
let mut map = StdHashMap::new();
if let Ok(cfg) = std::fs::read_to_string("nyash_box.toml") {
if let Ok(doc) = toml::from_str::<toml::Value>(&cfg) {
if let Some(table) = doc.as_table() {
for (box_name, box_val) in table {
if let Some(id) = box_val.get("type_id").and_then(|v| v.as_integer()) {
map.insert(box_name.clone(), id as i64);
}
}
}
}
}
map
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
use super::LLVMCompiler;
use crate::box_trait::{BoolBox, IntegerBox, NyashBox, StringBox};
use crate::boxes::{function_box::FunctionBox, math_box::FloatBox, null_box::NullBox};
use crate::mir::function::MirModule;
use crate::mir::instruction::{BinaryOp, ConstValue, MirInstruction};
use std::collections::HashMap;
include!("mock_impl.in.rs");

View File

@ -0,0 +1,251 @@
impl LLVMCompiler {
pub fn new() -> Result<Self, String> {
Ok(Self {
values: HashMap::new(),
})
}
pub fn compile_module(&self, mir_module: &MirModule, output_path: &str) -> Result<(), String> {
// Mock implementation - in a real scenario this would:
// 1. Create LLVM context and module
// 2. Convert MIR instructions to LLVM IR
// 3. Generate object file
println!("🔧 Mock LLVM Compilation:");
println!(" Module: {}", mir_module.name);
println!(" Functions: {}", mir_module.functions.len());
println!(" Output: {}", output_path);
// Find entry function (prefer is_entry_point, then Main.main, then main, else first)
let main_func = if let Some((_n, f)) = mir_module
.functions
.iter()
.find(|(_n, f)| f.metadata.is_entry_point)
{
f
} else if let Some(f) = mir_module.functions.get("Main.main") {
f
} else if let Some(f) = mir_module.functions.get("main") {
f
} else if let Some((_n, f)) = mir_module.functions.iter().next() {
f
} else {
return Err("Main.main function not found");
};
println!(
" Main function found with {} blocks",
main_func.blocks.len()
);
// Simulate object file generation
std::fs::write(output_path, b"Mock object file")?;
println!(" ✅ Mock object file created");
Ok(())
}
pub fn compile_and_execute(
&mut self,
mir_module: &MirModule,
temp_path: &str,
) -> Result<Box<dyn NyashBox>, String> {
// Mock implementation - interprets MIR instructions to simulate execution
eprintln!("⚠️⚠️⚠️ WARNING: Using MOCK LLVM Implementation! ⚠️⚠️⚠️");
eprintln!("⚠️ This is NOT real LLVM execution!");
eprintln!("⚠️ Build with --features llvm for real compilation!");
println!("🚀 Mock LLVM Compile & Execute (MIR Interpreter Mode):");
// 1. Mock object file generation
let obj_path = format!("{}.o", temp_path);
self.compile_module(mir_module, &obj_path)?;
// 2. Find and execute main function
let main_func = mir_module
.functions
.get("Main.main")
.ok_or("Main.main function not found")?;
println!(" ⚡ Interpreting MIR instructions...");
// 3. Execute MIR instructions
let result = self.interpret_function(main_func)?;
// 4. Cleanup mock files
let _ = std::fs::remove_file(&obj_path);
Ok(result)
}
/// Interpret a MIR function by executing its instructions
fn interpret_function(
&mut self,
func: &crate::mir::function::MirFunction,
) -> Result<Box<dyn NyashBox>, String> {
// Clear value storage
self.values.clear();
// For now, just execute the entry block
if let Some(entry_block) = func.blocks.get(&0) {
for inst in &entry_block.instructions {
match inst {
MirInstruction::Const { dst, value } => {
let nyash_value = match value {
ConstValue::Integer(i) => {
Box::new(IntegerBox::new(*i)) as Box<dyn NyashBox>
}
ConstValue::Float(f) => {
Box::new(FloatBox::new(*f)) as Box<dyn NyashBox>
}
ConstValue::String(s) => {
Box::new(StringBox::new(s.clone())) as Box<dyn NyashBox>
}
ConstValue::Bool(b) => Box::new(BoolBox::new(*b)) as Box<dyn NyashBox>,
ConstValue::Null => Box::new(NullBox::new()) as Box<dyn NyashBox>,
};
self.values.insert(*dst, nyash_value);
println!(" 📝 %{} = const {:?}", dst.0, value);
}
MirInstruction::BinOp { dst, op, lhs, rhs } => {
// Get operands
let left = self
.values
.get(lhs)
.ok_or_else(|| format!("Value %{} not found", lhs.0))?;
let right = self
.values
.get(rhs)
.ok_or_else(|| format!("Value %{} not found", rhs.0))?;
// Simple integer arithmetic for now
if let (Some(l), Some(r)) = (
left.as_any().downcast_ref::<IntegerBox>(),
right.as_any().downcast_ref::<IntegerBox>(),
) {
let result = match op {
BinaryOp::Add => l.value + r.value,
BinaryOp::Sub => l.value - r.value,
BinaryOp::Mul => l.value * r.value,
BinaryOp::Div => {
if r.value == 0 {
return Err("Division by zero".to_string());
}
l.value / r.value
}
BinaryOp::Mod => l.value % r.value,
_ => {
return Err(
"Binary operation not supported in mock".to_string()
);
}
};
self.values.insert(*dst, Box::new(IntegerBox::new(result)));
println!(
" 📊 %{} = %{} {:?} %{} = {}",
dst.0, lhs.0, op, rhs.0, result
);
} else {
return Err(
"Binary operation on non-integer values not supported in mock"
.to_string(),
);
}
}
MirInstruction::Return { value } => {
if let Some(val_id) = value {
let result = self
.values
.get(val_id)
.ok_or_else(|| format!("Return value %{} not found", val_id.0))?
.clone_box();
println!(" ✅ Returning value from %{}", val_id.0);
return Ok(result);
} else {
println!(" ✅ Void return");
return Ok(Box::new(IntegerBox::new(0)));
}
}
MirInstruction::FunctionNew {
dst,
params,
body,
captures,
me,
} => {
// Minimal: build FunctionBox with empty captures unless provided
let mut env = crate::boxes::function_box::ClosureEnv::new();
// Materialize captures (by value) if any
for (name, vid) in captures.iter() {
let v = self.values.get(vid).ok_or_else(|| {
format!("Value %{} not found for capture {}", vid.0, name)
})?;
env.captures.insert(name.clone(), v.clone_box());
}
// me capture (weak) if provided and is a box
if let Some(m) = me {
if let Some(b) = self.values.get(m) {
if let Some(arc) = std::sync::Arc::downcast::<dyn NyashBox>({
let bx: std::sync::Arc<dyn NyashBox> =
std::sync::Arc::from(b.clone_box());
bx
})
.ok()
{
env.me_value = Some(std::sync::Arc::downgrade(&arc));
}
}
}
let fun = FunctionBox::with_env(params.clone(), body.clone(), env);
self.values.insert(*dst, Box::new(fun));
println!(" 🧰 %{} = function_new (params={})", dst.0, params.len());
}
MirInstruction::Call {
dst, func, args, ..
} => {
// Resolve callee
let cal = self
.values
.get(func)
.ok_or_else(|| format!("Call target %{} not found", func.0))?;
if let Some(fb) = cal.as_any().downcast_ref::<FunctionBox>() {
// Collect args as NyashBox
let mut argv: Vec<Box<dyn NyashBox>> = Vec::new();
for a in args {
let av = self
.values
.get(a)
.ok_or_else(|| format!("Arg %{} not found", a.0))?;
argv.push(av.clone_box());
}
let out = crate::interpreter::run_function_box(fb, argv)
.map_err(|e| format!("FunctionBox call failed: {:?}", e))?;
if let Some(d) = dst {
self.values.insert(*d, out);
}
println!(
" 📞 call %{} -> {}",
func.0,
dst.map(|v| v.0).unwrap_or(u32::MAX)
);
} else {
println!(" ⚠️ Skipping call: callee not FunctionBox");
}
}
_ => {
// Other instructions not yet implemented
println!(" ⚠️ Skipping instruction: {:?}", inst);
}
}
}
}
// Default return
Ok(Box::new(IntegerBox::new(0)))
}
}

View File

@ -0,0 +1,27 @@
use crate::box_trait::NyashBox;
use crate::mir::ValueId;
use std::collections::HashMap;
pub struct LLVMCompiler {
values: HashMap<ValueId, Box<dyn NyashBox>>,
}
#[cfg(not(feature = "llvm"))]
mod mock;
#[cfg(not(feature = "llvm"))]
pub use mock::*;
#[cfg(feature = "llvm")]
mod real;
#[cfg(feature = "llvm")]
pub use real::*;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_llvm_module_creation() {
assert!(true);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,16 @@
/*! /*!
* LLVM Backend Module - Compile MIR to LLVM IR for AOT execution * LLVM Backend Module - Compile MIR to LLVM IR for AOT execution
* *
* This module provides LLVM-based compilation of Nyash MIR to native code. * This module provides LLVM-based compilation of Nyash MIR to native code.
* Phase 9.78 PoC implementation focused on minimal "return 42" support. * Phase 9.78 PoC implementation focused on minimal "return 42" support.
*/ */
pub mod context; pub mod box_types;
pub mod compiler; pub mod compiler;
pub mod context;
use crate::box_trait::{IntegerBox, NyashBox};
use crate::mir::function::MirModule; use crate::mir::function::MirModule;
use crate::box_trait::{NyashBox, IntegerBox};
/// Compile MIR module to object file and execute /// Compile MIR module to object file and execute
pub fn compile_and_execute( pub fn compile_and_execute(
@ -21,10 +22,7 @@ pub fn compile_and_execute(
} }
/// Compile MIR module to object file only /// Compile MIR module to object file only
pub fn compile_to_object( pub fn compile_to_object(mir_module: &MirModule, output_path: &str) -> Result<(), String> {
mir_module: &MirModule,
output_path: &str,
) -> Result<(), String> {
let compiler = compiler::LLVMCompiler::new()?; let compiler = compiler::LLVMCompiler::new()?;
compiler.compile_module(mir_module, output_path) compiler.compile_module(mir_module, output_path)
} }
@ -32,11 +30,11 @@ pub fn compile_to_object(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[test] #[test]
fn test_llvm_module_creation() { fn test_llvm_module_creation() {
// Basic test to ensure the module can be loaded // Basic test to ensure the module can be loaded
// Actual compilation tests require full MIR infrastructure // Actual compilation tests require full MIR infrastructure
assert!(true); assert!(true);
} }
} }

View File

@ -27,6 +27,7 @@ mod exprs_qmark; // ?-propagate
mod exprs_peek; // peek expression mod exprs_peek; // peek expression
mod exprs_lambda; // lambda lowering mod exprs_lambda; // lambda lowering
mod exprs_include; // include lowering mod exprs_include; // include lowering
mod plugin_sigs; // plugin signature loader
// moved helpers to builder/utils.rs // moved helpers to builder/utils.rs
@ -129,37 +130,7 @@ impl MirBuilder {
} }
/// Create a new MIR builder /// Create a new MIR builder
pub fn new() -> Self { pub fn new() -> Self {
// Load plugin method signatures from nyash_box.toml if available let plugin_method_sigs = plugin_sigs::load_plugin_method_sigs();
let mut plugin_method_sigs: HashMap<(String, String), super::MirType> = HashMap::new();
if let Ok(content) = fs::read_to_string("nyash_box.toml") {
if let Ok(root) = toml::from_str::<toml::Value>(&content) {
if let Some(table) = root.as_table() {
for (box_name, box_val) in table {
if let Some(methods) = box_val.get("methods").and_then(|v| v.as_table()) {
for (mname, mval) in methods {
if let Some(ret) = mval.get("returns") {
let ty_str = ret
.as_str()
.map(|s| s.to_string())
.or_else(|| ret.get("type").and_then(|t| t.as_str()).map(|s| s.to_string()));
if let Some(ts) = ty_str {
let mir_ty = match ts.to_lowercase().as_str() {
"i64" | "int" | "integer" => super::MirType::Integer,
"f64" | "float" => super::MirType::Float,
"bool" | "boolean" => super::MirType::Bool,
"string" => super::MirType::String,
"void" | "unit" => super::MirType::Void,
other => super::MirType::Box(other.to_string()),
};
plugin_method_sigs.insert((box_name.clone(), mname.clone()), mir_ty);
}
}
}
}
}
}
}
}
Self { Self {
current_module: None, current_module: None,
current_function: None, current_function: None,

View File

@ -0,0 +1,41 @@
use std::collections::HashMap;
use super::super::MirType;
/// Load plugin method signatures from `nyash_box.toml`.
///
/// Returns mapping `(BoxName, MethodName) -> MirType`.
pub fn load_plugin_method_sigs() -> HashMap<(String, String), MirType> {
let mut sigs = HashMap::new();
if let Ok(content) = std::fs::read_to_string("nyash_box.toml") {
if let Ok(root) = toml::from_str::<toml::Value>(&content) {
if let Some(table) = root.as_table() {
for (box_name, box_val) in table {
if let Some(methods) = box_val.get("methods").and_then(|v| v.as_table()) {
for (mname, mval) in methods {
if let Some(ret) = mval.get("returns") {
let ty_str = ret.as_str().map(|s| s.to_string()).or_else(|| {
ret.get("type")
.and_then(|t| t.as_str())
.map(|s| s.to_string())
});
if let Some(ts) = ty_str {
let mir_ty = match ts.to_lowercase().as_str() {
"i64" | "int" | "integer" => MirType::Integer,
"f64" | "float" => MirType::Float,
"bool" | "boolean" => MirType::Bool,
"string" => MirType::String,
"void" | "unit" => MirType::Void,
other => MirType::Box(other.to_string()),
};
sigs.insert((box_name.clone(), mname.clone()), mir_ty);
}
}
}
}
}
}
}
}
sigs
}