Skip to main content

gaia_assembler/backends/msil/
mod.rs

1//! IL (Intermediate Language) backend compiler
2
3#[cfg(feature = "clr")]
4use crate::{
5    adapters::FunctionMapper,
6    config::{GaiaConfig, GaiaSettings},
7    instruction::{CmpCondition, CoreInstruction, GaiaInstruction},
8    program::{GaiaConstant, GaiaFunction, GaiaModule},
9    types::GaiaType,
10    Backend, GeneratedFiles,
11};
12#[cfg(feature = "clr")]
13use clr_assembler::program::*;
14#[cfg(feature = "clr")]
15#[allow(unused_imports)]
16use gaia_types::{
17    helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
18    GaiaError, Result,
19};
20#[cfg(feature = "clr")]
21use std::collections::HashMap;
22
23/// IL Backend implementation
24#[derive(Default)]
25#[cfg(feature = "clr")]
26pub struct ClrBackend {}
27
28#[cfg(feature = "clr")]
29impl Backend for ClrBackend {
30    fn name(&self) -> &'static str {
31        "MSIL"
32    }
33
34    fn primary_target(&self) -> CompilationTarget {
35        CompilationTarget {
36            build: Architecture::CLR,
37            host: AbiCompatible::MicrosoftIntermediateLanguage,
38            target: ApiCompatible::ClrRuntime(4),
39        }
40    }
41
42    fn match_score(&self, target: &CompilationTarget) -> f32 {
43        match target.build {
44            Architecture::CLR => match target.host {
45                // dll, exe output, 30% support (now real binary!)
46                AbiCompatible::Unknown => 30.0,
47                // msil output, 30% support
48                AbiCompatible::MicrosoftIntermediateLanguage => 30.0,
49                _ => -100.0,
50            },
51            _ => -100.0,
52        }
53    }
54
55    fn generate(&self, program: &GaiaModule, _config: &GaiaConfig) -> Result<GeneratedFiles> {
56        let mut files = HashMap::new();
57        match _config.target.host {
58            AbiCompatible::Unknown => {
59                // 生成真实的 CLR 二进制 (DLL/EXE)
60                let clr_program = convert_to_clr_program(program, Some(&_config.setting))?;
61                let buffer = std::io::Cursor::new(Vec::new());
62                let writer = clr_assembler::formats::dll::writer::DllWriter::new(buffer);
63                let result = writer.write(&clr_program);
64                if let Some(error) = result.diagnostics.into_iter().next() {
65                    return Err(error);
66                }
67                files.insert("main.dll".to_string(), result.result.expect("Failed to get DLL buffer").into_inner());
68            }
69            AbiCompatible::MicrosoftIntermediateLanguage => {
70                // 生成 IL 文本
71                files.insert("main.il".to_string(), compile_with_settings(program, Some(&_config.setting))?);
72            }
73            _ => Err(GaiaError::invalid_data("Unsupported host ABI for CLR backend"))?,
74        }
75
76        Ok(GeneratedFiles { files, diagnostics: vec![] })
77    }
78}
79
80#[cfg(feature = "clr")]
81impl ClrBackend {
82    /// Generate IL bytecode from Gaia program
83    pub fn generate(program: &GaiaModule) -> Result<Vec<u8>> {
84        // 使用文本模式生成 IL,然后返回字节
85        compile_with_settings(program, None)
86    }
87
88    /// Generate IL bytecode with given GaiaSettings
89    pub fn generate_with_settings(program: &GaiaModule, settings: &GaiaSettings) -> Result<Vec<u8>> {
90        // Note: compile_with_settings still returns Result<Vec<u8>>
91        compile_with_settings(program, Some(settings))
92    }
93}
94
95/// Compile Gaia program to IL bytecode
96#[cfg(feature = "clr")]
97pub fn compile(program: &GaiaModule) -> Result<Vec<u8>> {
98    ClrBackend::generate(program)
99}
100
101/// Compile with optional GaiaSettings for function mapping
102#[cfg(feature = "clr")]
103fn compile_with_settings(program: &GaiaModule, settings: Option<&GaiaSettings>) -> Result<Vec<u8>> {
104    let mut context = IlContext::new_text();
105    if let Some(s) = settings {
106        context.function_mapper = FunctionMapper::from_config(s).unwrap_or_default();
107    }
108    compile_program(&mut context, program)?;
109    context.generate_bytecode()
110}
111
112/// Compile entire program
113#[cfg(feature = "clr")]
114fn compile_program(context: &mut IlContext, program: &GaiaModule) -> Result<()> {
115    // 预填充字段类型映射
116    for s in &program.structs {
117        for (name, ty) in &s.fields {
118            context.field_types.insert((s.name.clone(), name.clone()), ty.clone());
119        }
120    }
121    for c in &program.classes {
122        for field in &c.fields {
123            context.field_types.insert((c.name.clone(), field.name.clone()), field.ty.clone());
124        }
125    }
126    for g in &program.globals {
127        context.field_types.insert(("Main".to_string(), g.name.clone()), g.ty.clone());
128    }
129
130    // 添加程序集声明
131    context.emit_assembly_declaration(&program.name)?;
132
133    // 处理导入项
134    for import in &program.imports {
135        context.emit_external_assembly(&import.library)?;
136    }
137
138    // Compile all structs
139    for s in &program.structs {
140        compile_struct(context, s)?;
141    }
142
143    // Compile all classes
144    for c in &program.classes {
145        compile_class(context, c)?;
146    }
147
148    // Compile all functions
149    for function in &program.functions {
150        compile_function(context, function)?;
151    }
152
153    Ok(())
154}
155
156/// Compile struct definition
157#[cfg(feature = "clr")]
158fn compile_struct(context: &mut IlContext, s: &crate::program::GaiaStruct) -> Result<()> {
159    context.start_class(&s.name)?;
160
161    for (name, ty) in &s.fields {
162        context.write_field(name, ty)?;
163    }
164
165    // 添加默认构造函数 (仅文本模式)
166    if let IlMode::Text(writer) = &mut context.mode {
167        writer.write_default_constructor()?;
168    }
169
170    context.end_class()?;
171    Ok(())
172}
173
174/// Compile class definition
175#[cfg(feature = "clr")]
176fn compile_class(context: &mut IlContext, c: &crate::program::GaiaClass) -> Result<()> {
177    context.start_class(&c.name)?;
178
179    for field in &c.fields {
180        context.write_field(&field.name, &field.ty)?;
181    }
182
183    for method in &c.methods {
184        compile_function(context, method)?;
185    }
186
187    context.end_class()?;
188    Ok(())
189}
190
191/// Compile single function
192#[cfg(feature = "clr")]
193fn compile_function(context: &mut IlContext, function: &GaiaFunction) -> Result<()> {
194    // Start function definition
195    start_function(
196        context,
197        &function.name,
198        &function.signature.params,
199        &Some(function.signature.return_type.clone()),
200        function.name == "main",
201    )?;
202
203    // Compile blocks
204    for block in &function.blocks {
205        context.define_label(&block.label)?;
206
207        for instruction in &block.instructions {
208            compile_instruction(context, instruction)?;
209        }
210
211        // Compile terminator
212        match &block.terminator {
213            crate::program::GaiaTerminator::Jump(label) => context.emit_br(label)?,
214            crate::program::GaiaTerminator::Branch { true_label, false_label } => {
215                context.emit_brtrue(true_label)?;
216                context.emit_br(false_label)?;
217            }
218            crate::program::GaiaTerminator::Return => context.emit_ret()?,
219            crate::program::GaiaTerminator::Call { callee, args_count: _, next_block } => {
220                context.emit_call(callee)?;
221                context.emit_br(next_block)?;
222            }
223            crate::program::GaiaTerminator::Halt => {
224                context.emit_ldc_i4(0)?;
225                context.emit_call("ExitProcess")?;
226            }
227        }
228    }
229
230    // End function definition
231    end_function(context)?;
232
233    Ok(())
234}
235
236/// Compile single instruction
237#[cfg(feature = "clr")]
238fn compile_instruction(context: &mut IlContext, instruction: &GaiaInstruction) -> Result<()> {
239    match instruction {
240        GaiaInstruction::Core(core) => match core {
241            CoreInstruction::PushConstant(constant) => compile_load_constant(context, constant),
242            CoreInstruction::Load(gaia_type) => compile_load_indirect(context, gaia_type),
243            CoreInstruction::Store(gaia_type) => compile_store_indirect(context, gaia_type),
244            CoreInstruction::Add(_) => compile_add(context),
245            CoreInstruction::Sub(_) => compile_subtract(context),
246            CoreInstruction::Mul(_) => compile_multiply(context),
247            CoreInstruction::Div(_) => compile_divide(context),
248            CoreInstruction::Pop => compile_pop(context),
249            CoreInstruction::Dup => compile_duplicate(context),
250            CoreInstruction::Cmp(cond, _) => match cond {
251                CmpCondition::Eq => compile_equal(context),
252                CmpCondition::Ne => compile_not_equal(context),
253                CmpCondition::Lt => compile_less_than(context),
254                CmpCondition::Le => compile_less_than_or_equal(context),
255                CmpCondition::Gt => compile_greater_than(context),
256                CmpCondition::Ge => compile_greater_than_or_equal(context),
257            },
258            CoreInstruction::Ret => compile_return(context),
259            CoreInstruction::Br(label) => compile_branch(context, label),
260            CoreInstruction::BrTrue(label) => compile_branch_true(context, label),
261            CoreInstruction::BrFalse(label) => compile_branch_false(context, label),
262            CoreInstruction::Label(name) => compile_label(context, name),
263            CoreInstruction::Call(name, arg_count) => compile_call(context, name, *arg_count),
264            CoreInstruction::LoadLocal(index, _) => compile_load_local(context, *index),
265            CoreInstruction::StoreLocal(index, _) => compile_store_local(context, *index),
266            CoreInstruction::LoadArg(index, _) => compile_load_argument(context, *index),
267            CoreInstruction::StoreArg(index, _) => compile_store_argument(context, *index),
268            CoreInstruction::New(type_name) => compile_new_object(context, type_name),
269            CoreInstruction::NewArray(elem_type, _) => compile_new_array(context, elem_type),
270            CoreInstruction::LoadField(type_name, field_name) => {
271                let gaia_type = context
272                    .field_types
273                    .get(&(type_name.to_string(), field_name.to_string()))
274                    .cloned()
275                    .unwrap_or(GaiaType::Object);
276                compile_load_field(context, type_name, field_name, &gaia_type)
277            }
278            CoreInstruction::StoreField(type_name, field_name) => {
279                let gaia_type = context
280                    .field_types
281                    .get(&(type_name.to_string(), field_name.to_string()))
282                    .cloned()
283                    .unwrap_or(GaiaType::Object);
284                compile_store_field(context, type_name, field_name, &gaia_type)
285            }
286            CoreInstruction::LoadElement(elem_type) => compile_load_element(context, elem_type),
287            CoreInstruction::StoreElement(elem_type) => compile_store_element(context, elem_type),
288            CoreInstruction::ArrayLength => compile_array_length(context),
289            _ => Ok(()),
290        },
291        GaiaInstruction::Managed(managed) => match managed {
292            _ => Ok(()),
293        },
294        _ => Ok(()),
295    }
296}
297
298#[cfg(feature = "clr")]
299fn compile_new_object(context: &mut IlContext, type_name: &str) -> Result<()> {
300    // 构造构造函数引用,默认为 .ctor()
301    let ctor_ref = format!("instance void {}::.ctor()", type_name);
302    context.emit_newobj(&ctor_ref)
303}
304
305#[cfg(feature = "clr")]
306fn compile_load_field(context: &mut IlContext, type_name: &str, field_name: &str, gaia_type: &GaiaType) -> Result<()> {
307    let field_ref = format!("{} {}::{}", gaia_type_to_msil_name(gaia_type), type_name, field_name);
308    context.emit_ldfld(&field_ref)
309}
310
311#[cfg(feature = "clr")]
312fn compile_store_field(context: &mut IlContext, type_name: &str, field_name: &str, gaia_type: &GaiaType) -> Result<()> {
313    let field_ref = format!("{} {}::{}", gaia_type_to_msil_name(gaia_type), type_name, field_name);
314    context.emit_stfld(&field_ref)
315}
316
317#[cfg(feature = "clr")]
318fn compile_new_array(context: &mut IlContext, elem_type: &GaiaType) -> Result<()> {
319    context.emit_newarr(&gaia_type_to_msil_name(elem_type))
320}
321
322#[cfg(feature = "clr")]
323fn compile_load_element(context: &mut IlContext, elem_type: &GaiaType) -> Result<()> {
324    context.emit_ldelem(&gaia_type_to_msil_name(elem_type))
325}
326
327#[cfg(feature = "clr")]
328fn compile_store_element(context: &mut IlContext, elem_type: &GaiaType) -> Result<()> {
329    context.emit_stelem(&gaia_type_to_msil_name(elem_type))
330}
331
332#[cfg(feature = "clr")]
333fn compile_array_length(context: &mut IlContext) -> Result<()> {
334    context.emit_ldlen()
335}
336
337#[cfg(feature = "clr")]
338fn compile_return(context: &mut IlContext) -> Result<()> {
339    context.emit_ret()
340}
341
342#[cfg(feature = "clr")]
343fn compile_branch(context: &mut IlContext, label: &str) -> Result<()> {
344    context.emit_br(label)
345}
346
347#[cfg(feature = "clr")]
348fn compile_branch_true(context: &mut IlContext, label: &str) -> Result<()> {
349    context.emit_brtrue(label)
350}
351
352#[cfg(feature = "clr")]
353fn compile_branch_false(context: &mut IlContext, label: &str) -> Result<()> {
354    context.emit_brfalse(label)
355}
356
357#[cfg(feature = "clr")]
358fn compile_label(context: &mut IlContext, name: &str) -> Result<()> {
359    context.define_label(name)
360}
361
362#[cfg(feature = "clr")]
363fn compile_call(context: &mut IlContext, name: &str, _arg_count: usize) -> Result<()> {
364    // 这是一个简化实现,实际需要根据函数名查找签名
365    // 目前假设由 context.emit_call 处理映射
366    let mapped_name = context.map_function(name);
367    context.emit_call(&mapped_name)
368}
369
370#[cfg(feature = "clr")]
371fn compile_load_constant(context: &mut IlContext, constant: &GaiaConstant) -> Result<()> {
372    match constant {
373        GaiaConstant::I8(value) => context.emit_ldc_i4(*value as i32),
374        GaiaConstant::U8(value) => context.emit_ldc_i4(*value as i32),
375        GaiaConstant::I16(value) => context.emit_ldc_i4(*value as i32),
376        GaiaConstant::U16(value) => context.emit_ldc_i4(*value as i32),
377        GaiaConstant::I32(value) => context.emit_ldc_i4(*value),
378        GaiaConstant::U32(value) => context.emit_ldc_i4(*value as i32),
379        GaiaConstant::I64(value) => context.emit_ldc_i8(*value),
380        GaiaConstant::U64(value) => context.emit_ldc_i8(*value as i64),
381        GaiaConstant::F32(value) => context.emit_ldc_r4(*value),
382        GaiaConstant::F64(value) => context.emit_ldc_r8(*value),
383        GaiaConstant::String(value) => context.emit_ldstr(value),
384        GaiaConstant::Bool(value) => context.emit_ldc_i4(if *value { 1 } else { 0 }),
385        GaiaConstant::Null => context.emit_ldnull(),
386        _ => Err(GaiaError::custom_error("Unsupported constant type for CLR")),
387    }
388}
389
390#[cfg(feature = "clr")]
391fn compile_load_local(context: &mut IlContext, index: u32) -> Result<()> {
392    context.emit_ldloc(index)
393}
394
395#[cfg(feature = "clr")]
396fn compile_store_local(context: &mut IlContext, index: u32) -> Result<()> {
397    context.emit_stloc(index)
398}
399
400#[cfg(feature = "clr")]
401fn compile_load_argument(context: &mut IlContext, index: u32) -> Result<()> {
402    context.emit_ldarg(index)
403}
404
405#[cfg(feature = "clr")]
406fn compile_store_argument(context: &mut IlContext, index: u32) -> Result<()> {
407    context.emit_starg(index)
408}
409
410#[cfg(feature = "clr")]
411fn compile_add(context: &mut IlContext) -> Result<()> {
412    context.emit_add()
413}
414
415#[cfg(feature = "clr")]
416fn compile_subtract(context: &mut IlContext) -> Result<()> {
417    context.emit_sub()
418}
419
420#[cfg(feature = "clr")]
421fn compile_multiply(context: &mut IlContext) -> Result<()> {
422    context.emit_mul()
423}
424
425#[cfg(feature = "clr")]
426fn compile_divide(context: &mut IlContext) -> Result<()> {
427    context.emit_div()
428}
429
430#[cfg(feature = "clr")]
431fn compile_equal(context: &mut IlContext) -> Result<()> {
432    context.emit_ceq()
433}
434
435#[cfg(feature = "clr")]
436fn compile_not_equal(context: &mut IlContext) -> Result<()> {
437    context.emit_ceq()?;
438    context.emit_ldc_i4(0)?;
439    context.emit_ceq()
440}
441
442#[cfg(feature = "clr")]
443fn compile_less_than(context: &mut IlContext) -> Result<()> {
444    context.emit_clt()
445}
446
447#[cfg(feature = "clr")]
448fn compile_greater_than(context: &mut IlContext) -> Result<()> {
449    context.emit_cgt()
450}
451
452#[cfg(feature = "clr")]
453fn compile_less_than_or_equal(context: &mut IlContext) -> Result<()> {
454    // a <= b  <=>  !(a > b)  <=>  (a > b) == 0
455    context.emit_cgt()?;
456    context.emit_ldc_i4(0)?;
457    context.emit_ceq()
458}
459
460#[cfg(feature = "clr")]
461fn compile_greater_than_or_equal(context: &mut IlContext) -> Result<()> {
462    // a >= b  <=>  !(a < b)  <=>  (a < b) == 0
463    context.emit_clt()?;
464    context.emit_ldc_i4(0)?;
465    context.emit_ceq()
466}
467
468#[cfg(feature = "clr")]
469fn compile_logical_not(context: &mut IlContext) -> Result<()> {
470    // !a  <=>  a == 0
471    context.emit_ldc_i4(0)?;
472    context.emit_ceq()
473}
474
475#[cfg(feature = "clr")]
476fn compile_duplicate(context: &mut IlContext) -> Result<()> {
477    context.emit_dup()
478}
479
480#[cfg(feature = "clr")]
481fn compile_pop(context: &mut IlContext) -> Result<()> {
482    context.emit_pop()
483}
484
485#[cfg(feature = "clr")]
486fn compile_logical_and(context: &mut IlContext) -> Result<()> {
487    context.emit_and()
488}
489
490#[cfg(feature = "clr")]
491fn compile_logical_or(context: &mut IlContext) -> Result<()> {
492    context.emit_or()
493}
494
495#[cfg(feature = "clr")]
496fn compile_load_address(context: &mut IlContext, addr: u32) -> Result<()> {
497    context.emit_ldloca(addr)
498}
499
500#[cfg(feature = "clr")]
501fn compile_load_indirect(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
502    match gaia_type {
503        GaiaType::I8 => context.emit_ldind_i4(),  // 8位整数加载为32位
504        GaiaType::I16 => context.emit_ldind_i4(), // 16位整数加载为32位
505        GaiaType::I32 => context.emit_ldind_i4(),
506        GaiaType::I64 => context.emit_ldind_i8(),
507        GaiaType::F32 => context.emit_ldind_r4(),
508        GaiaType::F64 => context.emit_ldind_r8(),
509        _ => context.emit_ldind_ref(),
510    }
511}
512
513#[cfg(feature = "clr")]
514fn compile_store_indirect(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
515    match gaia_type {
516        GaiaType::I8 => context.emit_stind_i4(),  // 8位整数存储为32位
517        GaiaType::I16 => context.emit_stind_i4(), // 16位整数存储为32位
518        GaiaType::I32 => context.emit_stind_i4(),
519        GaiaType::I64 => context.emit_stind_i8(),
520        GaiaType::F32 => context.emit_stind_r4(),
521        GaiaType::F64 => context.emit_stind_r8(),
522        _ => context.emit_stind_ref(),
523    }
524}
525
526#[cfg(feature = "clr")]
527fn compile_convert(_context: &mut IlContext, _from_type: &GaiaType, _to_type: &GaiaType) -> Result<()> {
528    match _to_type {
529        GaiaType::I8 => _context.emit_conv_i4(),  // 8位整数转换为32位
530        GaiaType::I16 => _context.emit_conv_i4(), // 16位整数转换为32位
531        GaiaType::I32 => _context.emit_conv_i4(),
532        GaiaType::I64 => _context.emit_conv_i8(),
533        GaiaType::F32 => _context.emit_conv_r4(),
534        GaiaType::F64 => _context.emit_conv_r8(),
535        _ => Ok(()),
536    }
537}
538
539#[cfg(feature = "clr")]
540fn compile_box(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
541    context.emit_box(gaia_type)
542}
543
544#[cfg(feature = "clr")]
545fn compile_unbox(context: &mut IlContext, gaia_type: &GaiaType) -> Result<()> {
546    context.emit_unbox(gaia_type)
547}
548
549/// Start function definition
550#[cfg(feature = "clr")]
551fn start_function(
552    context: &mut IlContext,
553    name: &str,
554    parameters: &[GaiaType],
555    return_type: &Option<GaiaType>,
556    is_entry: bool,
557) -> Result<()> {
558    context.start_method(name, parameters, return_type, is_entry)
559}
560
561#[cfg(feature = "clr")]
562fn end_function(context: &mut IlContext) -> Result<()> {
563    context.end_method()
564}
565
566/// 将 GaiaType 映射为 MSIL 类型名称
567#[cfg(feature = "clr")]
568fn gaia_type_to_msil_name(gaia_type: &GaiaType) -> String {
569    match gaia_type {
570        GaiaType::I8 => "int8".to_string(),
571        GaiaType::U8 => "uint8".to_string(),
572        GaiaType::I16 => "int16".to_string(),
573        GaiaType::U16 => "uint16".to_string(),
574        GaiaType::I32 => "int32".to_string(),
575        GaiaType::U32 => "uint32".to_string(),
576        GaiaType::I64 => "int64".to_string(),
577        GaiaType::U64 => "uint64".to_string(),
578        GaiaType::F32 => "float32".to_string(),
579        GaiaType::F64 => "float64".to_string(),
580        GaiaType::Bool => "bool".to_string(),
581        GaiaType::String => "string".to_string(),
582        GaiaType::Object => "object".to_string(),
583        GaiaType::Class(name) => name.clone(),
584        GaiaType::Struct(name) => name.clone(),
585        GaiaType::Array(elem, _) => format!("{}[]", gaia_type_to_msil_name(elem)),
586        GaiaType::Pointer(_, _) => "native int".to_string(),
587        GaiaType::Void => "void".to_string(),
588        _ => "object".to_string(),
589    }
590}
591
592/// MSIL Text Writer
593#[cfg(feature = "clr")]
594struct MsilWriter<W: std::fmt::Write> {
595    writer: gaia_types::writer::TextWriter<W>,
596}
597
598#[cfg(feature = "clr")]
599impl<W: std::fmt::Write> MsilWriter<W> {
600    fn new(writer: W) -> Self {
601        Self { writer: gaia_types::writer::TextWriter::new(writer) }
602    }
603
604    fn finish(self) -> W {
605        self.writer.into_inner()
606    }
607
608    fn write_assembly(&mut self, name: &str) -> Result<()> {
609        self.writer.write_line(&format!(".assembly {} {{}}", name))?;
610        Ok(())
611    }
612
613    fn write_external_assembly(&mut self, name: &str) -> Result<()> {
614        self.writer.write_line(&format!(".assembly extern {} {{}}", name))?;
615        Ok(())
616    }
617
618    fn start_class(&mut self, name: &str) -> Result<()> {
619        self.writer
620            .write_line(&format!(".class public auto ansi beforefieldinit {} extends [mscorlib]System.Object {{", name))?;
621        self.writer.indent("")?;
622        Ok(())
623    }
624
625    fn end_class(&mut self) -> Result<()> {
626        self.writer.dedent("}")?;
627        self.writer.write_line("")?;
628        Ok(())
629    }
630
631    fn write_field(&mut self, name: &str, msil_type: &str) -> Result<()> {
632        self.writer.write_line(&format!(".field public {} {}", msil_type, name))?;
633        Ok(())
634    }
635
636    fn write_default_constructor(&mut self) -> Result<()> {
637        self.writer.write_line(".method public hidebysig specialname rtspecialname instance void .ctor() cil managed {")?;
638        self.writer.indent("")?;
639        self.writer.write_line("ldarg.0")?;
640        self.writer.write_line("call instance void [mscorlib]System.Object::.ctor()")?;
641        self.writer.write_line("ret")?;
642        self.writer.dedent("}")?;
643        Ok(())
644    }
645
646    fn start_method(&mut self, name: &str, parameters: &[&str], return_type: Option<&str>, is_entry: bool) -> Result<()> {
647        let ret = return_type.unwrap_or("void");
648        let params = parameters.join(", ");
649        self.writer.write_line(&format!(".method public hidebysig {} {}({}) cil managed {{", ret, name, params))?;
650        self.writer.indent("")?;
651        if is_entry {
652            self.writer.write_line(".entrypoint")?;
653        }
654        self.writer.write_line(".maxstack 8")?;
655        Ok(())
656    }
657
658    fn end_method(&mut self) -> Result<()> {
659        self.writer.dedent("}")?;
660        self.writer.write_line("")?;
661        Ok(())
662    }
663
664    fn define_label(&mut self, name: &str) -> Result<()> {
665        self.writer.write_line(&format!("{}:", name))?;
666        Ok(())
667    }
668
669    fn emit_ldc_i4(&mut self, value: i32) -> Result<()> {
670        self.writer.write_line(&format!("ldc.i4 {}", value))?;
671        Ok(())
672    }
673
674    fn emit_ldc_i8(&mut self, value: i64) -> Result<()> {
675        self.writer.write_line(&format!("ldc.i8 {}", value))?;
676        Ok(())
677    }
678
679    fn emit_ldc_r4(&mut self, value: f32) -> Result<()> {
680        self.writer.write_line(&format!("ldc.r4 {}", value))?;
681        Ok(())
682    }
683
684    fn emit_ldc_r8(&mut self, value: f64) -> Result<()> {
685        self.writer.write_line(&format!("ldc.r8 {}", value))?;
686        Ok(())
687    }
688
689    fn emit_ldstr(&mut self, value: &str) -> Result<()> {
690        self.writer.write_line(&format!("ldstr \"{}\"", value))?;
691        Ok(())
692    }
693
694    fn emit_ldnull(&mut self) -> Result<()> {
695        self.writer.write_line("ldnull")?;
696        Ok(())
697    }
698
699    fn emit_ldloc(&mut self, index: u32) -> Result<()> {
700        self.writer.write_line(&format!("ldloc {}", index))?;
701        Ok(())
702    }
703
704    fn emit_stloc(&mut self, index: u32) -> Result<()> {
705        self.writer.write_line(&format!("stloc {}", index))?;
706        Ok(())
707    }
708
709    fn emit_ldarg(&mut self, index: u32) -> Result<()> {
710        self.writer.write_line(&format!("ldarg {}", index))?;
711        Ok(())
712    }
713
714    fn emit_starg(&mut self, index: u32) -> Result<()> {
715        self.writer.write_line(&format!("starg {}", index))?;
716        Ok(())
717    }
718
719    fn emit_add(&mut self) -> Result<()> {
720        self.writer.write_line("add")?;
721        Ok(())
722    }
723
724    fn emit_sub(&mut self) -> Result<()> {
725        self.writer.write_line("sub")?;
726        Ok(())
727    }
728
729    fn emit_mul(&mut self) -> Result<()> {
730        self.writer.write_line("mul")?;
731        Ok(())
732    }
733
734    fn emit_div(&mut self) -> Result<()> {
735        self.writer.write_line("div")?;
736        Ok(())
737    }
738
739    fn emit_ceq(&mut self) -> Result<()> {
740        self.writer.write_line("ceq")?;
741        Ok(())
742    }
743
744    fn emit_cgt(&mut self) -> Result<()> {
745        self.writer.write_line("cgt")?;
746        Ok(())
747    }
748
749    fn emit_clt(&mut self) -> Result<()> {
750        self.writer.write_line("clt")?;
751        Ok(())
752    }
753
754    fn emit_br(&mut self, label: &str) -> Result<()> {
755        self.writer.write_line(&format!("br {}", label))?;
756        Ok(())
757    }
758
759    fn emit_brtrue(&mut self, label: &str) -> Result<()> {
760        self.writer.write_line(&format!("brtrue {}", label))?;
761        Ok(())
762    }
763
764    fn emit_brfalse(&mut self, label: &str) -> Result<()> {
765        self.writer.write_line(&format!("brfalse {}", label))?;
766        Ok(())
767    }
768
769    fn emit_call(&mut self, method_ref: &str) -> Result<()> {
770        self.writer.write_line(&format!("call {}", method_ref))?;
771        Ok(())
772    }
773
774    fn emit_ret(&mut self) -> Result<()> {
775        self.writer.write_line("ret")?;
776        Ok(())
777    }
778
779    fn emit_dup(&mut self) -> Result<()> {
780        self.writer.write_line("dup")?;
781        Ok(())
782    }
783
784    fn emit_pop(&mut self) -> Result<()> {
785        self.writer.write_line("pop")?;
786        Ok(())
787    }
788
789    fn emit_newarr(&mut self, type_name: &str) -> Result<()> {
790        self.writer.write_line(&format!("newarr {}", type_name))?;
791        Ok(())
792    }
793
794    fn emit_ldelem(&mut self, type_name: &str) -> Result<()> {
795        self.writer.write_line(&format!("ldelem {}", type_name))?;
796        Ok(())
797    }
798
799    fn emit_stelem(&mut self, type_name: &str) -> Result<()> {
800        self.writer.write_line(&format!("stelem {}", type_name))?;
801        Ok(())
802    }
803
804    fn emit_ldlen(&mut self) -> Result<()> {
805        self.writer.write_line("ldlen")?;
806        Ok(())
807    }
808
809    fn emit_and(&mut self) -> Result<()> {
810        self.writer.write_line("and")?;
811        Ok(())
812    }
813
814    fn emit_or(&mut self) -> Result<()> {
815        self.writer.write_line("or")?;
816        Ok(())
817    }
818
819    fn emit_ldloca(&mut self, index: u32) -> Result<()> {
820        self.writer.write_line(&format!("ldloca {}", index))?;
821        Ok(())
822    }
823
824    fn emit_ldind_i4(&mut self) -> Result<()> {
825        self.writer.write_line("ldind.i4")?;
826        Ok(())
827    }
828
829    fn emit_ldind_i8(&mut self) -> Result<()> {
830        self.writer.write_line("ldind.i8")?;
831        Ok(())
832    }
833
834    fn emit_ldind_r4(&mut self) -> Result<()> {
835        self.writer.write_line("ldind.r4")?;
836        Ok(())
837    }
838
839    fn emit_ldind_r8(&mut self) -> Result<()> {
840        self.writer.write_line("ldind.r8")?;
841        Ok(())
842    }
843
844    fn emit_ldind_ref(&mut self) -> Result<()> {
845        self.writer.write_line("ldind.ref")?;
846        Ok(())
847    }
848
849    fn emit_stind_i4(&mut self) -> Result<()> {
850        self.writer.write_line("stind.i4")?;
851        Ok(())
852    }
853
854    fn emit_stind_i8(&mut self) -> Result<()> {
855        self.writer.write_line("stind.i8")?;
856        Ok(())
857    }
858
859    fn emit_stind_r4(&mut self) -> Result<()> {
860        self.writer.write_line("stind.r4")?;
861        Ok(())
862    }
863
864    fn emit_stind_r8(&mut self) -> Result<()> {
865        self.writer.write_line("stind.r8")?;
866        Ok(())
867    }
868
869    fn emit_stind_ref(&mut self) -> Result<()> {
870        self.writer.write_line("stind.ref")?;
871        Ok(())
872    }
873
874    fn emit_newobj(&mut self, method_ref: &str) -> Result<()> {
875        self.writer.write_line(&format!("newobj {}", method_ref))?;
876        Ok(())
877    }
878
879    fn emit_ldfld(&mut self, field_ref: &str) -> Result<()> {
880        self.writer.write_line(&format!("ldfld {}", field_ref))?;
881        Ok(())
882    }
883
884    fn emit_stfld(&mut self, field_ref: &str) -> Result<()> {
885        self.writer.write_line(&format!("stfld {}", field_ref))?;
886        Ok(())
887    }
888
889    fn emit_conv_i4(&mut self) -> Result<()> {
890        self.writer.write_line("conv.i4")?;
891        Ok(())
892    }
893
894    fn emit_conv_i8(&mut self) -> Result<()> {
895        self.writer.write_line("conv.i8")?;
896        Ok(())
897    }
898
899    fn emit_conv_r4(&mut self) -> Result<()> {
900        self.writer.write_line("conv.r4")?;
901        Ok(())
902    }
903
904    fn emit_conv_r8(&mut self) -> Result<()> {
905        self.writer.write_line("conv.r8")?;
906        Ok(())
907    }
908
909    fn emit_box(&mut self, type_name: &str) -> Result<()> {
910        self.writer.write_line(&format!("box {}", type_name))?;
911        Ok(())
912    }
913
914    fn emit_unbox(&mut self, type_name: &str) -> Result<()> {
915        self.writer.write_line(&format!("unbox {}", type_name))?;
916        Ok(())
917    }
918}
919
920/// IL Context for code generation
921#[cfg(feature = "clr")]
922struct IlContext {
923    mode: IlMode,
924    function_mapper: FunctionMapper,
925    /// 字段类型映射 (类名, 字段名) -> GaiaType
926    field_types: HashMap<(String, String), GaiaType>,
927}
928
929#[cfg(feature = "clr")]
930enum IlMode {
931    Text(MsilWriter<String>),
932    Binary { program: ClrProgram, current_type: Option<ClrType>, current_method: Option<ClrMethod> },
933}
934
935#[cfg(feature = "clr")]
936impl IlContext {
937    fn new_text() -> Self {
938        Self {
939            mode: IlMode::Text(MsilWriter::new(String::new())),
940            function_mapper: FunctionMapper::new(),
941            field_types: HashMap::new(),
942        }
943    }
944
945    fn new_binary(name: String) -> Self {
946        let program = ClrProgram {
947            name: name.clone(),
948            version: ClrVersion { major: 1, minor: 0, build: 0, revision: 0 },
949            access_flags: ClrAccessFlags {
950                is_public: true,
951                is_private: false,
952                is_security_transparent: false,
953                is_retargetable: false,
954            },
955            external_assemblies: vec![ClrExternalAssembly {
956                name: "mscorlib".to_string(),
957                version: ClrVersion { major: 4, minor: 0, build: 0, revision: 0 },
958                public_key_token: Some(vec![0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89]),
959                culture: None,
960                hash_algorithm: None,
961            }],
962            module: Some(ClrModule { name: format!("{}.dll", name), mvid: None }),
963            types: vec![],
964            global_methods: vec![],
965            global_fields: vec![],
966            attributes: vec![],
967            constant_pool: ClrConstantPool::new(),
968            source_file: None,
969        };
970        Self {
971            mode: IlMode::Binary { program, current_type: None, current_method: None },
972            function_mapper: FunctionMapper::new(),
973            field_types: HashMap::new(),
974        }
975    }
976
977    fn start_class(&mut self, name: &str) -> Result<()> {
978        match &mut self.mode {
979            IlMode::Text(writer) => writer.start_class(name),
980            IlMode::Binary { current_type, .. } => {
981                let clr_type = ClrType {
982                    name: name.to_string(),
983                    namespace: None,
984                    access_flags: ClrAccessFlags {
985                        is_public: true,
986                        is_private: false,
987                        is_security_transparent: false,
988                        is_retargetable: false,
989                    },
990                    base_type: Some("System.Object".to_string()),
991                    interfaces: vec![],
992                    fields: vec![],
993                    methods: vec![],
994                    properties: vec![],
995                    events: vec![],
996                    nested_types: vec![],
997                    attributes: vec![],
998                };
999                *current_type = Some(clr_type);
1000                Ok(())
1001            }
1002        }
1003    }
1004
1005    fn end_class(&mut self) -> Result<()> {
1006        match &mut self.mode {
1007            IlMode::Text(writer) => writer.end_class(),
1008            IlMode::Binary { program, current_type, .. } => {
1009                if let Some(t) = current_type.take() {
1010                    program.types.push(t);
1011                }
1012                Ok(())
1013            }
1014        }
1015    }
1016
1017    fn write_field(&mut self, name: &str, gaia_type: &GaiaType) -> Result<()> {
1018        match &mut self.mode {
1019            IlMode::Text(writer) => writer.write_field(name, &gaia_type_to_msil_name(gaia_type)),
1020            IlMode::Binary { current_type, .. } => {
1021                if let Some(t) = current_type {
1022                    t.fields.push(ClrField {
1023                        name: name.to_string(),
1024                        field_type: gaia_type_to_clr_type(gaia_type),
1025                        access_flags: ClrAccessFlags {
1026                            is_public: true,
1027                            is_private: false,
1028                            is_security_transparent: false,
1029                            is_retargetable: false,
1030                        },
1031                        default_value: None,
1032                        attributes: vec![],
1033                    });
1034                }
1035                Ok(())
1036            }
1037        }
1038    }
1039
1040    fn emit_assembly_declaration(&mut self, name: &str) -> Result<()> {
1041        match &mut self.mode {
1042            IlMode::Text(writer) => writer.write_assembly(name),
1043            IlMode::Binary { .. } => Ok(()), // Already set in constructor
1044        }
1045    }
1046
1047    fn emit_external_assembly(&mut self, name: &str) -> Result<()> {
1048        match &mut self.mode {
1049            IlMode::Text(writer) => writer.write_external_assembly(name),
1050            IlMode::Binary { program, .. } => {
1051                // 检查是否已经存在
1052                if !program.external_assemblies.iter().any(|a| a.name == name) {
1053                    program.external_assemblies.push(ClrExternalAssembly {
1054                        name: name.to_string(),
1055                        version: ClrVersion { major: 0, minor: 0, build: 0, revision: 0 },
1056                        public_key_token: None,
1057                        culture: None,
1058                        hash_algorithm: None,
1059                    });
1060                }
1061                Ok(())
1062            }
1063        }
1064    }
1065
1066    fn start_method(
1067        &mut self,
1068        name: &str,
1069        parameters: &[GaiaType],
1070        return_type: &Option<GaiaType>,
1071        is_entry: bool,
1072    ) -> Result<()> {
1073        match &mut self.mode {
1074            IlMode::Text(writer) => {
1075                let param_names: Vec<String> = parameters.iter().map(|t| gaia_type_to_msil_name(t)).collect();
1076                let param_refs: Vec<&str> = param_names.iter().map(|s| s.as_str()).collect();
1077                let ret_name_owned = return_type.as_ref().map(|t| gaia_type_to_msil_name(t));
1078                let ret_name = ret_name_owned.as_deref();
1079                writer.start_method(name, &param_refs, ret_name, is_entry)
1080            }
1081            IlMode::Binary { current_method, .. } => {
1082                let clr_params = parameters
1083                    .iter()
1084                    .enumerate()
1085                    .map(|(i, t)| ClrParameter {
1086                        name: format!("arg{}", i),
1087                        parameter_type: gaia_type_to_clr_type(t),
1088                        is_in: true,
1089                        is_out: false,
1090                        is_optional: false,
1091                        default_value: None,
1092                        attributes: vec![],
1093                    })
1094                    .collect();
1095
1096                let method = ClrMethod {
1097                    name: name.to_string(),
1098                    return_type: return_type.as_ref().map(gaia_type_to_clr_type).unwrap_or(ClrTypeReference {
1099                        name: "void".to_string(),
1100                        namespace: None,
1101                        assembly: None,
1102                        is_value_type: false,
1103                        is_reference_type: false,
1104                        generic_parameters: vec![],
1105                    }),
1106                    parameters: clr_params,
1107                    access_flags: ClrAccessFlags {
1108                        is_public: true,
1109                        is_private: false,
1110                        is_security_transparent: false,
1111                        is_retargetable: false,
1112                    },
1113                    impl_flags: ClrMethodImplFlags { is_managed: true, ..Default::default() },
1114                    instructions: vec![],
1115                    max_stack: 8u16,
1116                    locals: vec![],
1117                    exception_handlers: vec![],
1118                    attributes: vec![],
1119                    is_entry_point: is_entry,
1120                };
1121                *current_method = Some(method);
1122                Ok(())
1123            }
1124        }
1125    }
1126
1127    fn end_method(&mut self) -> Result<()> {
1128        match &mut self.mode {
1129            IlMode::Text(writer) => writer.end_method(),
1130            IlMode::Binary { program, current_type, current_method } => {
1131                if let Some(method) = current_method.take() {
1132                    if let Some(t) = current_type {
1133                        t.methods.push(method);
1134                    }
1135                    else {
1136                        program.global_methods.push(method);
1137                    }
1138                }
1139                Ok(())
1140            }
1141        }
1142    }
1143
1144    fn generate_bytecode(self) -> Result<Vec<u8>> {
1145        match self.mode {
1146            IlMode::Text(writer) => Ok(writer.finish().into_bytes()),
1147            IlMode::Binary { .. } => Err(GaiaError::custom_error("Use convert_to_clr_program for binary mode")),
1148        }
1149    }
1150
1151    fn finish_binary(self) -> Result<ClrProgram> {
1152        match self.mode {
1153            IlMode::Binary { program, .. } => Ok(program),
1154            _ => Err(GaiaError::custom_error("Use generate_bytecode for text mode")),
1155        }
1156    }
1157
1158    /// 根据当前上下文映射函数名(IL 目标)
1159    fn map_function(&self, raw_name: &str) -> String {
1160        let il_target = CompilationTarget {
1161            build: Architecture::CLR,
1162            host: AbiCompatible::MicrosoftIntermediateLanguage,
1163            target: ApiCompatible::ClrRuntime(4),
1164        };
1165        self.function_mapper.map_function(&il_target, raw_name).unwrap_or(raw_name).to_string()
1166    }
1167
1168    fn emit_ldc_i4(&mut self, value: i32) -> Result<()> {
1169        self.emit_with_immediate(ClrOpcode::LdcI4, value)
1170    }
1171
1172    fn emit_ldc_i8(&mut self, value: i64) -> Result<()> {
1173        match &mut self.mode {
1174            IlMode::Text(writer) => writer.emit_ldc_i8(value),
1175            IlMode::Binary { current_method, .. } => {
1176                if let Some(method) = current_method {
1177                    method.instructions.push(ClrInstruction::WithImmediate64 { opcode: ClrOpcode::LdcI8, value });
1178                    Ok(())
1179                }
1180                else {
1181                    Err(GaiaError::custom_error("No current method"))
1182                }
1183            }
1184        }
1185    }
1186
1187    fn emit_ldc_r4(&mut self, value: f32) -> Result<()> {
1188        match &mut self.mode {
1189            IlMode::Text(writer) => writer.emit_ldc_r4(value),
1190            IlMode::Binary { current_method, .. } => {
1191                if let Some(method) = current_method {
1192                    method.instructions.push(ClrInstruction::WithFloat32 { opcode: ClrOpcode::LdcR4, value });
1193                    Ok(())
1194                }
1195                else {
1196                    Err(GaiaError::custom_error("No current method"))
1197                }
1198            }
1199        }
1200    }
1201
1202    fn emit_ldc_r8(&mut self, value: f64) -> Result<()> {
1203        match &mut self.mode {
1204            IlMode::Text(writer) => writer.emit_ldc_r8(value),
1205            IlMode::Binary { current_method, .. } => {
1206                if let Some(method) = current_method {
1207                    method.instructions.push(ClrInstruction::WithFloat64 { opcode: ClrOpcode::LdcR8, value });
1208                    Ok(())
1209                }
1210                else {
1211                    Err(GaiaError::custom_error("No current method"))
1212                }
1213            }
1214        }
1215    }
1216
1217    fn emit_ldstr(&mut self, value: &str) -> Result<()> {
1218        match &mut self.mode {
1219            IlMode::Text(writer) => writer.emit_ldstr(value),
1220            IlMode::Binary { current_method, .. } => {
1221                if let Some(method) = current_method {
1222                    method.instructions.push(ClrInstruction::WithString { opcode: ClrOpcode::Ldstr, value: value.to_string() });
1223                    Ok(())
1224                }
1225                else {
1226                    Err(GaiaError::invalid_data("No current method context for binary IL generation"))
1227                }
1228            }
1229        }
1230    }
1231
1232    fn emit_ldnull(&mut self) -> Result<()> {
1233        self.emit_simple(ClrOpcode::Ldnull)
1234    }
1235
1236    fn emit_ldloc(&mut self, index: u32) -> Result<()> {
1237        match &mut self.mode {
1238            IlMode::Text(writer) => writer.emit_ldloc(index),
1239            IlMode::Binary { current_method, .. } => {
1240                if let Some(method) = current_method {
1241                    method.instructions.push(ClrInstruction::WithLocalVar { opcode: ClrOpcode::Ldloc, index: index as u16 });
1242                    Ok(())
1243                }
1244                else {
1245                    Err(GaiaError::custom_error("No current method"))
1246                }
1247            }
1248        }
1249    }
1250
1251    fn emit_stloc(&mut self, index: u32) -> Result<()> {
1252        match &mut self.mode {
1253            IlMode::Text(writer) => writer.emit_stloc(index),
1254            IlMode::Binary { current_method, .. } => {
1255                if let Some(method) = current_method {
1256                    method.instructions.push(ClrInstruction::WithLocalVar { opcode: ClrOpcode::Stloc, index: index as u16 });
1257                    Ok(())
1258                }
1259                else {
1260                    Err(GaiaError::custom_error("No current method"))
1261                }
1262            }
1263        }
1264    }
1265
1266    fn emit_ldarg(&mut self, index: u32) -> Result<()> {
1267        match &mut self.mode {
1268            IlMode::Text(writer) => writer.emit_ldarg(index),
1269            IlMode::Binary { current_method, .. } => {
1270                if let Some(method) = current_method {
1271                    method.instructions.push(ClrInstruction::WithParameter { opcode: ClrOpcode::Ldarg, index: index as u16 });
1272                    Ok(())
1273                }
1274                else {
1275                    Err(GaiaError::custom_error("No current method"))
1276                }
1277            }
1278        }
1279    }
1280
1281    fn emit_starg(&mut self, index: u32) -> Result<()> {
1282        match &mut self.mode {
1283            IlMode::Text(writer) => writer.emit_starg(index),
1284            IlMode::Binary { current_method, .. } => {
1285                if let Some(method) = current_method {
1286                    method.instructions.push(ClrInstruction::WithParameter { opcode: ClrOpcode::Starg, index: index as u16 });
1287                    Ok(())
1288                }
1289                else {
1290                    Err(GaiaError::custom_error("No current method"))
1291                }
1292            }
1293        }
1294    }
1295
1296    fn emit_add(&mut self) -> Result<()> {
1297        self.emit_simple(ClrOpcode::Add)
1298    }
1299
1300    fn emit_sub(&mut self) -> Result<()> {
1301        self.emit_simple(ClrOpcode::Sub)
1302    }
1303
1304    fn emit_mul(&mut self) -> Result<()> {
1305        self.emit_simple(ClrOpcode::Mul)
1306    }
1307
1308    fn emit_div(&mut self) -> Result<()> {
1309        self.emit_simple(ClrOpcode::Div)
1310    }
1311
1312    fn emit_ceq(&mut self) -> Result<()> {
1313        self.emit_simple(ClrOpcode::Ceq)
1314    }
1315
1316    fn emit_cgt(&mut self) -> Result<()> {
1317        self.emit_simple(ClrOpcode::Cgt)
1318    }
1319
1320    fn emit_clt(&mut self) -> Result<()> {
1321        self.emit_simple(ClrOpcode::Clt)
1322    }
1323
1324    fn emit_br(&mut self, label: &str) -> Result<()> {
1325        self.emit_branch(ClrOpcode::Br, label)
1326    }
1327
1328    fn emit_brtrue(&mut self, label: &str) -> Result<()> {
1329        self.emit_branch(ClrOpcode::Brtrue, label)
1330    }
1331
1332    fn emit_brfalse(&mut self, label: &str) -> Result<()> {
1333        self.emit_branch(ClrOpcode::Brfalse, label)
1334    }
1335
1336    fn emit_call(&mut self, method_ref: &str) -> Result<()> {
1337        match &mut self.mode {
1338            IlMode::Text(writer) => writer.emit_call(method_ref),
1339            IlMode::Binary { current_method, .. } => {
1340                if let Some(method) = current_method {
1341                    method
1342                        .instructions
1343                        .push(ClrInstruction::WithMethod { opcode: ClrOpcode::Call, method_ref: method_ref.to_string() });
1344                    Ok(())
1345                }
1346                else {
1347                    Err(GaiaError::custom_error("No current method"))
1348                }
1349            }
1350        }
1351    }
1352
1353    fn emit_ret(&mut self) -> Result<()> {
1354        self.emit_simple(ClrOpcode::Ret)
1355    }
1356
1357    fn define_label(&mut self, name: &str) -> Result<()> {
1358        match &mut self.mode {
1359            IlMode::Text(writer) => writer.define_label(name),
1360            IlMode::Binary { .. } => Ok(()), // Binary mode usually resolves labels later
1361        }
1362    }
1363
1364    fn emit_dup(&mut self) -> Result<()> {
1365        self.emit_simple(ClrOpcode::Dup)
1366    }
1367
1368    fn emit_pop(&mut self) -> Result<()> {
1369        self.emit_simple(ClrOpcode::Pop)
1370    }
1371
1372    fn emit_newarr(&mut self, type_name: &str) -> Result<()> {
1373        match &mut self.mode {
1374            IlMode::Text(writer) => writer.emit_newarr(type_name),
1375            IlMode::Binary { current_method, .. } => {
1376                if let Some(method) = current_method {
1377                    method
1378                        .instructions
1379                        .push(ClrInstruction::WithType { opcode: ClrOpcode::Newarr, type_ref: type_name.to_string() });
1380                    Ok(())
1381                }
1382                else {
1383                    Err(GaiaError::custom_error("No current method"))
1384                }
1385            }
1386        }
1387    }
1388
1389    fn emit_ldelem(&mut self, type_name: &str) -> Result<()> {
1390        match &mut self.mode {
1391            IlMode::Text(writer) => writer.emit_ldelem(type_name),
1392            IlMode::Binary { current_method, .. } => {
1393                if let Some(method) = current_method {
1394                    method
1395                        .instructions
1396                        .push(ClrInstruction::WithType { opcode: ClrOpcode::Ldelem, type_ref: type_name.to_string() });
1397                    Ok(())
1398                }
1399                else {
1400                    Err(GaiaError::custom_error("No current method"))
1401                }
1402            }
1403        }
1404    }
1405
1406    fn emit_stelem(&mut self, type_name: &str) -> Result<()> {
1407        match &mut self.mode {
1408            IlMode::Text(writer) => writer.emit_stelem(type_name),
1409            IlMode::Binary { current_method, .. } => {
1410                if let Some(method) = current_method {
1411                    method
1412                        .instructions
1413                        .push(ClrInstruction::WithType { opcode: ClrOpcode::Stelem, type_ref: type_name.to_string() });
1414                    Ok(())
1415                }
1416                else {
1417                    Err(GaiaError::custom_error("No current method"))
1418                }
1419            }
1420        }
1421    }
1422
1423    fn emit_ldlen(&mut self) -> Result<()> {
1424        self.emit_simple(ClrOpcode::Ldlen)
1425    }
1426
1427    fn emit_and(&mut self) -> Result<()> {
1428        self.emit_simple(ClrOpcode::And)
1429    }
1430
1431    fn emit_or(&mut self) -> Result<()> {
1432        self.emit_simple(ClrOpcode::Or)
1433    }
1434
1435    fn emit_ldloca(&mut self, index: u32) -> Result<()> {
1436        match &mut self.mode {
1437            IlMode::Text(writer) => writer.emit_ldloca(index),
1438            IlMode::Binary { current_method, .. } => {
1439                if let Some(method) = current_method {
1440                    method.instructions.push(ClrInstruction::WithLocalVar { opcode: ClrOpcode::Ldloca, index: index as u16 });
1441                    Ok(())
1442                }
1443                else {
1444                    Err(GaiaError::custom_error("No current method"))
1445                }
1446            }
1447        }
1448    }
1449
1450    fn emit_ldind_i4(&mut self) -> Result<()> {
1451        self.emit_simple(ClrOpcode::LdindI4)
1452    }
1453
1454    fn emit_ldind_i8(&mut self) -> Result<()> {
1455        self.emit_simple(ClrOpcode::LdindI8)
1456    }
1457
1458    fn emit_ldind_r4(&mut self) -> Result<()> {
1459        self.emit_simple(ClrOpcode::LdindR4)
1460    }
1461
1462    fn emit_ldind_r8(&mut self) -> Result<()> {
1463        self.emit_simple(ClrOpcode::LdindR8)
1464    }
1465
1466    fn emit_ldind_ref(&mut self) -> Result<()> {
1467        self.emit_simple(ClrOpcode::LdindRef)
1468    }
1469
1470    fn emit_stind_i4(&mut self) -> Result<()> {
1471        self.emit_simple(ClrOpcode::StindI4)
1472    }
1473
1474    fn emit_stind_i8(&mut self) -> Result<()> {
1475        self.emit_simple(ClrOpcode::StindI8)
1476    }
1477
1478    fn emit_stind_r4(&mut self) -> Result<()> {
1479        self.emit_simple(ClrOpcode::StindR4)
1480    }
1481
1482    fn emit_stind_r8(&mut self) -> Result<()> {
1483        self.emit_simple(ClrOpcode::StindR8)
1484    }
1485
1486    fn emit_stind_ref(&mut self) -> Result<()> {
1487        self.emit_simple(ClrOpcode::StindRef)
1488    }
1489
1490    fn emit_newobj(&mut self, method_ref: &str) -> Result<()> {
1491        match &mut self.mode {
1492            IlMode::Text(writer) => writer.emit_newobj(method_ref),
1493            IlMode::Binary { current_method, .. } => {
1494                if let Some(method) = current_method {
1495                    method
1496                        .instructions
1497                        .push(ClrInstruction::WithMethod { opcode: ClrOpcode::Newobj, method_ref: method_ref.to_string() });
1498                    Ok(())
1499                }
1500                else {
1501                    Err(GaiaError::custom_error("No current method"))
1502                }
1503            }
1504        }
1505    }
1506
1507    fn emit_ldfld(&mut self, field_ref: &str) -> Result<()> {
1508        match &mut self.mode {
1509            IlMode::Text(writer) => writer.emit_ldfld(field_ref),
1510            IlMode::Binary { current_method, .. } => {
1511                if let Some(method) = current_method {
1512                    method
1513                        .instructions
1514                        .push(ClrInstruction::WithField { opcode: ClrOpcode::Ldfld, field_ref: field_ref.to_string() });
1515                    Ok(())
1516                }
1517                else {
1518                    Err(GaiaError::custom_error("No current method"))
1519                }
1520            }
1521        }
1522    }
1523
1524    fn emit_stfld(&mut self, field_ref: &str) -> Result<()> {
1525        match &mut self.mode {
1526            IlMode::Text(writer) => writer.emit_stfld(field_ref),
1527            IlMode::Binary { current_method, .. } => {
1528                if let Some(method) = current_method {
1529                    method
1530                        .instructions
1531                        .push(ClrInstruction::WithField { opcode: ClrOpcode::Stfld, field_ref: field_ref.to_string() });
1532                    Ok(())
1533                }
1534                else {
1535                    Err(GaiaError::custom_error("No current method"))
1536                }
1537            }
1538        }
1539    }
1540
1541    fn emit_conv_i4(&mut self) -> Result<()> {
1542        self.emit_simple(ClrOpcode::ConvI4)
1543    }
1544
1545    fn emit_conv_i8(&mut self) -> Result<()> {
1546        self.emit_simple(ClrOpcode::ConvI8)
1547    }
1548
1549    fn emit_conv_r4(&mut self) -> Result<()> {
1550        self.emit_simple(ClrOpcode::ConvR4)
1551    }
1552
1553    fn emit_conv_r8(&mut self) -> Result<()> {
1554        self.emit_simple(ClrOpcode::ConvR8)
1555    }
1556
1557    fn emit_box(&mut self, gaia_type: &GaiaType) -> Result<()> {
1558        let type_name = gaia_type_to_msil_name(gaia_type);
1559        match &mut self.mode {
1560            IlMode::Text(writer) => writer.emit_box(&type_name),
1561            IlMode::Binary { current_method, .. } => {
1562                if let Some(method) = current_method {
1563                    method.instructions.push(ClrInstruction::WithType { opcode: ClrOpcode::Box, type_ref: type_name });
1564                    Ok(())
1565                }
1566                else {
1567                    Err(GaiaError::custom_error("No current method"))
1568                }
1569            }
1570        }
1571    }
1572
1573    fn emit_unbox(&mut self, gaia_type: &GaiaType) -> Result<()> {
1574        let type_name = gaia_type_to_msil_name(gaia_type);
1575        match &mut self.mode {
1576            IlMode::Text(writer) => writer.emit_unbox(&type_name),
1577            IlMode::Binary { current_method, .. } => {
1578                if let Some(method) = current_method {
1579                    method.instructions.push(ClrInstruction::WithType { opcode: ClrOpcode::Unbox, type_ref: type_name });
1580                    Ok(())
1581                }
1582                else {
1583                    Err(GaiaError::custom_error("No current method"))
1584                }
1585            }
1586        }
1587    }
1588
1589    fn emit_simple(&mut self, opcode: ClrOpcode) -> Result<()> {
1590        match &mut self.mode {
1591            IlMode::Text(writer) => match opcode {
1592                ClrOpcode::Add => writer.emit_add(),
1593                ClrOpcode::Sub => writer.emit_sub(),
1594                ClrOpcode::Mul => writer.emit_mul(),
1595                ClrOpcode::Div => writer.emit_div(),
1596                ClrOpcode::Ceq => writer.emit_ceq(),
1597                ClrOpcode::Cgt => writer.emit_cgt(),
1598                ClrOpcode::Clt => writer.emit_clt(),
1599                ClrOpcode::Ret => writer.emit_ret(),
1600                ClrOpcode::Dup => writer.emit_dup(),
1601                ClrOpcode::Pop => writer.emit_pop(),
1602                ClrOpcode::And => writer.emit_and(),
1603                ClrOpcode::Or => writer.emit_or(),
1604                ClrOpcode::Ldnull => writer.emit_ldnull(),
1605                ClrOpcode::LdindI4 => writer.emit_ldind_i4(),
1606                ClrOpcode::LdindI8 => writer.emit_ldind_i8(),
1607                ClrOpcode::LdindR4 => writer.emit_ldind_r4(),
1608                ClrOpcode::LdindR8 => writer.emit_ldind_r8(),
1609                ClrOpcode::LdindRef => writer.emit_ldind_ref(),
1610                ClrOpcode::StindI4 => writer.emit_stind_i4(),
1611                ClrOpcode::StindI8 => writer.emit_stind_i8(),
1612                ClrOpcode::StindR4 => writer.emit_stind_r4(),
1613                ClrOpcode::StindR8 => writer.emit_stind_r8(),
1614                ClrOpcode::StindRef => writer.emit_stind_ref(),
1615                ClrOpcode::ConvI4 => writer.emit_conv_i4(),
1616                ClrOpcode::ConvI8 => writer.emit_conv_i8(),
1617                ClrOpcode::ConvR4 => writer.emit_conv_r4(),
1618                ClrOpcode::ConvR8 => writer.emit_conv_r8(),
1619                ClrOpcode::Ldlen => writer.emit_ldlen(),
1620                _ => Err(GaiaError::custom_error(format!("Unsupported simple opcode: {:?}", opcode))),
1621            },
1622            IlMode::Binary { current_method, .. } => {
1623                if let Some(method) = current_method {
1624                    method.instructions.push(ClrInstruction::Simple { opcode });
1625                    Ok(())
1626                }
1627                else {
1628                    Err(GaiaError::custom_error("No current method"))
1629                }
1630            }
1631        }
1632    }
1633
1634    fn emit_with_immediate(&mut self, opcode: ClrOpcode, value: i32) -> Result<()> {
1635        match &mut self.mode {
1636            IlMode::Text(writer) => match opcode {
1637                ClrOpcode::LdcI4 => writer.emit_ldc_i4(value),
1638                _ => Err(GaiaError::custom_error(format!("Unsupported immediate opcode: {:?}", opcode))),
1639            },
1640            IlMode::Binary { current_method, .. } => {
1641                if let Some(method) = current_method {
1642                    method.instructions.push(ClrInstruction::WithImmediate { opcode, value });
1643                    Ok(())
1644                }
1645                else {
1646                    Err(GaiaError::custom_error("No current method"))
1647                }
1648            }
1649        }
1650    }
1651
1652    fn emit_branch(&mut self, opcode: ClrOpcode, label: &str) -> Result<()> {
1653        match &mut self.mode {
1654            IlMode::Text(writer) => match opcode {
1655                ClrOpcode::Br => writer.emit_br(label),
1656                ClrOpcode::Brtrue => writer.emit_brtrue(label),
1657                ClrOpcode::Brfalse => writer.emit_brfalse(label),
1658                _ => Err(GaiaError::custom_error(format!("Unsupported branch opcode: {:?}", opcode))),
1659            },
1660            IlMode::Binary { current_method, .. } => {
1661                if let Some(method) = current_method {
1662                    method.instructions.push(ClrInstruction::WithLabel { opcode, label: label.to_string() });
1663                    Ok(())
1664                }
1665                else {
1666                    Err(GaiaError::custom_error("No current method"))
1667                }
1668            }
1669        }
1670    }
1671}
1672
1673#[cfg(feature = "clr")]
1674fn gaia_type_to_clr_type(t: &GaiaType) -> ClrTypeReference {
1675    match t {
1676        GaiaType::Array(elem, _) => {
1677            let mut elem_ref = gaia_type_to_clr_type(elem);
1678            elem_ref.name = format!("{}[]", elem_ref.name);
1679            elem_ref.is_value_type = false;
1680            elem_ref.is_reference_type = true;
1681            elem_ref
1682        }
1683        _ => {
1684            let name = match t {
1685                GaiaType::I8 => "int8",
1686                GaiaType::U8 => "uint8",
1687                GaiaType::I16 => "int16",
1688                GaiaType::U16 => "uint16",
1689                GaiaType::I32 => "int32",
1690                GaiaType::U32 => "uint32",
1691                GaiaType::I64 => "int64",
1692                GaiaType::U64 => "uint64",
1693                GaiaType::F32 => "float32",
1694                GaiaType::F64 => "float64",
1695                GaiaType::String => "string",
1696                GaiaType::Bool => "bool",
1697                GaiaType::Void => "void",
1698                GaiaType::Class(name) => name,
1699                GaiaType::Struct(name) => name,
1700                _ => "object",
1701            };
1702            ClrTypeReference {
1703                name: name.to_string(),
1704                namespace: None,
1705                assembly: None,
1706                is_value_type: !matches!(t, GaiaType::String | GaiaType::Object | GaiaType::Array(_, _) | GaiaType::Class(_)),
1707                is_reference_type: matches!(
1708                    t,
1709                    GaiaType::String | GaiaType::Object | GaiaType::Array(_, _) | GaiaType::Class(_)
1710                ),
1711                generic_parameters: vec![],
1712            }
1713        }
1714    }
1715}
1716
1717#[cfg(feature = "clr")]
1718fn convert_to_clr_program(program: &GaiaModule, settings: Option<&GaiaSettings>) -> Result<ClrProgram> {
1719    let mut context = IlContext::new_binary(program.name.clone());
1720    if let Some(s) = settings {
1721        context.function_mapper = FunctionMapper::from_config(s).unwrap_or_default();
1722    }
1723    compile_program(&mut context, program)?;
1724    context.finish_binary()
1725}