gaia-assembler 0.1.1

Universal assembler framework for Gaia project
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
//! Unified Adapter Interface Definitions
//!
//! This module defines the unified interface for import and export adapters,
//! as well as related configuration and management structures.
//! These interfaces aim to abstract differences between platforms and provide a consistent API.

use crate::{config::GaiaSettings, instruction::GaiaInstruction, program::GaiaModule};
use gaia_types::{
    helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
    GaiaError, Result,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

/// Adapter configuration information.
///
/// Contains configuration parameters required for the adapter's operation.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AdapterConfig {
    /// Adapter name.
    pub name: String,
    /// Compilation target.
    pub compilation_target: CompilationTarget,
    /// Configuration parameters.
    pub parameters: HashMap<String, String>,
    /// Whether the adapter is enabled.
    pub enabled: bool,
}

/// Adapter metadata.
///
/// Describes basic information and capabilities of an adapter.
#[derive(Debug, Clone)]
pub struct AdapterMetadata {
    /// Adapter name.
    pub name: String,
    /// Adapter version.
    pub version: String,
    /// Supported compilation target.
    pub compilation_target: CompilationTarget,
    /// Adapter description.
    pub description: String,
    /// Supported instruction sets.
    pub supported_instructions: Vec<String>,
}

/// Function mapper.
#[derive(Debug)]
pub struct FunctionMapper {
    /// Function mapping table (platform -> source function -> target function).
    mappings: HashMap<CompilationTarget, HashMap<String, String>>,
}

impl FunctionMapper {
    /// Create a new function mapper with default mappings.
    pub fn new() -> Self {
        // Uniform initialization using default GaiaSettings to avoid hardcoded repetition.
        // Default mappings include universal functions like __builtin_print / malloc / free.
        Self::from_settings(&GaiaSettings::default())
    }

    /// Create a function mapper from a configuration.
    pub fn from_config(config: &GaiaSettings) -> Result<Self> {
        Ok(Self::from_settings(config))
    }

    /// Generate unified function mappings based on GaiaSettings (overrides defaults).
    fn from_settings(settings: &GaiaSettings) -> Self {
        let mut mapper = Self { mappings: HashMap::new() };

        // Predefined platform targets (uniform keys: IL/JVM/PE/WASI).
        let il_target = CompilationTarget {
            build: Architecture::CLR,
            host: AbiCompatible::MicrosoftIntermediateLanguage,
            target: ApiCompatible::ClrRuntime(4),
        };
        let jvm_target = CompilationTarget {
            build: Architecture::JVM,
            host: AbiCompatible::JavaAssembly,
            target: ApiCompatible::JvmRuntime(8),
        };
        let pe_target =
            CompilationTarget { build: Architecture::X86_64, host: AbiCompatible::PE, target: ApiCompatible::MicrosoftVisualC };
        let wasi_target = CompilationTarget {
            build: Architecture::WASM32,
            host: AbiCompatible::WebAssemblyTextFormat,
            target: ApiCompatible::WASI,
        };

        let mut platform_index: HashMap<String, CompilationTarget> = HashMap::new();
        platform_index.insert("IL".to_string(), il_target.clone());
        platform_index.insert("JVM".to_string(), jvm_target.clone());
        platform_index.insert("PE".to_string(), pe_target.clone());
        platform_index.insert("WASI".to_string(), wasi_target.clone());

        // 1) Baseline: Provide reasonable default aliases to prevent issues if settings are missing.
        // IL default: WriteLine with signature, compatible with current MsilWriter call syntax.
        mapper.add_mapping(&il_target, "console.log", "void [mscorlib]System.Console::WriteLine(string)");
        mapper.add_mapping(&il_target, "console.write", "void [mscorlib]System.Console::WriteLine(string)");
        mapper.add_mapping(&il_target, "conosole.read", "string [mscorlib]System.Console::ReadLine()");
        mapper.add_mapping(&il_target, "malloc", "System.Runtime.InteropServices.Marshal.AllocHGlobal");
        mapper.add_mapping(&il_target, "free", "System.Runtime.InteropServices.Marshal.FreeHGlobal");
        mapper.add_mapping(&il_target, "print", "void [mscorlib]System.Console::WriteLine(string)");
        mapper.add_mapping(&il_target, "println", "void [mscorlib]System.Console::WriteLine(string)");

        // JVM defaults
        mapper.add_mapping(&jvm_target, "console.log", "java.lang.System.out.println");
        mapper.add_mapping(&jvm_target, "console.write", "java.lang.System.out.println");
        mapper.add_mapping(&jvm_target, "console.read", "java.util.Scanner.nextLine");
        mapper.add_mapping(&jvm_target, "malloc", "java.nio.ByteBuffer.allocateDirect");
        mapper.add_mapping(&jvm_target, "free", "System.gc");
        mapper.add_mapping(&jvm_target, "print", "java.lang.System.out.println");
        mapper.add_mapping(&jvm_target, "println", "java.lang.System.out.println");

        // PE defaults
        mapper.add_mapping(&pe_target, "console.log", "puts");
        mapper.add_mapping(&pe_target, "console.write", "printf");
        mapper.add_mapping(&pe_target, "console.read", "gets_s");
        mapper.add_mapping(&pe_target, "malloc", "HeapAlloc");
        mapper.add_mapping(&pe_target, "free", "HeapFree");
        mapper.add_mapping(&pe_target, "print", "puts");
        mapper.add_mapping(&pe_target, "println", "puts");

        // WASI defaults
        mapper.add_mapping(&wasi_target, "console.log", "wasi_println");
        mapper.add_mapping(&wasi_target, "console.write", "wasi_print");
        mapper.add_mapping(&wasi_target, "console.read", "wasi_read");
        mapper.add_mapping(&wasi_target, "malloc", "malloc");
        mapper.add_mapping(&wasi_target, "free", "free");
        mapper.add_mapping(&wasi_target, "print", "wasi_println");
        mapper.add_mapping(&wasi_target, "println", "wasi_println");

        // 2) Override: Use settings.function_mappings to override/extend default mappings
        for fm in &settings.function_mappings {
            for (platform_name, target_func) in &fm.platform_mappings {
                let key = platform_name.to_ascii_uppercase();
                if let Some(platform_target) = platform_index.get(&key) {
                    // Directly map common name
                    mapper.add_mapping(platform_target, &fm.common_name, target_func);

                    // Provide linkage for common aliases (reducing front-end repetition)
                    if fm.common_name == "__builtin_print" {
                        let is_il = matches!(platform_target.host, AbiCompatible::MicrosoftIntermediateLanguage);
                        // The IL platform retains the default print mapping with a signature to avoid generating incomplete MSIL call operands.
                        if !is_il {
                            mapper.add_mapping(platform_target, "print", target_func);
                        }
                        mapper.add_mapping(platform_target, "console.log", target_func);
                        mapper.add_mapping(platform_target, "console.write", target_func);
                    }
                }
            }
        }

        mapper
    }

    /// Add function mapping
    pub fn add_mapping(&mut self, target: &CompilationTarget, source_func: &str, target_func: &str) {
        self.mappings
            .entry(target.clone())
            .or_insert_with(HashMap::new)
            .insert(source_func.to_string(), target_func.to_string());
    }

    /// Map function name
    pub fn map_function(&self, target: &CompilationTarget, function_name: &str) -> Option<&str> {
        self.mappings.get(target).and_then(|platform_mappings| platform_mappings.get(function_name)).map(|s| s.as_str())
    }
}

impl Default for FunctionMapper {
    fn default() -> Self {
        Self::new()
    }
}

/// Unified Export Adapter Interface
///
/// Defines a standard interface for exporting Gaia instructions and programs to platform-specific formats.
pub trait ExportAdapter: Send + Sync {
    /// Get adapter metadata
    fn metadata(&self) -> &AdapterMetadata;

    /// Configure adapter
    ///
    /// # Parameters
    /// * `config` - Adapter configuration
    ///
    /// # Return Value
    /// Returns Ok(()) on success, or an error message on failure.
    fn configure(&mut self, config: AdapterConfig) -> Result<()>;

    /// Export a single instruction
    ///
    /// # Parameters
    /// * `instruction` - Gaia instruction to export
    ///
    /// # Return Value
    /// Returns platform-specific instruction data on success, or an error message on failure.
    fn export_instruction(&self, instruction: &GaiaInstruction) -> Result<Vec<u8>>;

    /// Export the complete program
    ///
    /// # Parameters
    /// * `program` - Gaia program to be exported
    ///
    /// # Return Value
    /// Returns platform-specific program data on success, or an error message on failure.
    fn export_program(&self, program: &GaiaModule) -> Result<Vec<u8>>;

    /// Verify if the instruction is supported
    ///
    /// # Parameters
    /// * `instruction` - Instruction to verify
    ///
    /// # Return Value
    /// Returns true if supported, false otherwise.
    fn supports_instruction(&self, instruction: &GaiaInstruction) -> bool;

    /// Get the output file extension
    ///
    /// # Return Value
    /// Platform-specific file extension
    fn file_extension(&self) -> &str;

    /// Clean up resources
    ///
    /// Called when the adapter is no longer in use to clean up related resources
    fn cleanup(&mut self) -> Result<()> {
        Ok(())
    }
}

/// Unified Import Adapter Interface
///
/// Defines a standard interface for importing from platform-specific formats to Gaia instructions and programs.
pub trait ImportAdapter: Send + Sync {
    /// Get adapter metadata
    fn metadata(&self) -> &AdapterMetadata;

    /// Configure adapter
    ///
    /// # Parameters
    /// * `config` - Adapter configuration
    ///
    /// # Return Value
    /// Returns Ok(()) on success, or an error message on failure.
    fn configure(&mut self, config: AdapterConfig) -> Result<()>;

    /// Import a single instruction
    ///
    /// # Parameters
    /// * `data` - Platform-specific instruction data
    ///
    /// # Return Value
    /// Returns Gaia instruction on success, or an error message on failure.
    fn import_instruction(&self, data: &[u8]) -> Result<GaiaInstruction>;

    /// Import program
    ///
    /// # Parameters
    /// * `data` - Platform-specific program data
    ///
    /// # Return Value
    /// Returns the converted Gaia program on success, or an error message on failure.
    fn import_program(&self, data: &[u8]) -> Result<GaiaModule>;

    /// Validate data format
    ///
    /// # Parameters
    /// * `data` - Data to validate
    ///
    /// # Return Value
    /// Returns true if the format is correct, false otherwise.
    fn validate_format(&self, data: &[u8]) -> bool;

    /// Get supported file extensions
    ///
    /// # Return Value
    /// List of supported file extensions
    fn supported_extensions(&self) -> Vec<&str>;

    /// Clean up resources
    ///
    /// Called when the adapter is no longer in use to clean up related resources
    fn cleanup(&mut self) -> Result<()> {
        Ok(())
    }
}

/// Adapter Manager
pub struct AdapterManager {
    /// Export adapter registry
    export_adapters: HashMap<CompilationTarget, Box<dyn ExportAdapter>>,
    /// Import adapter registry
    import_adapters: HashMap<CompilationTarget, Box<dyn ImportAdapter>>,
}

impl AdapterManager {
    /// Create a new adapter manager
    pub fn new() -> Self {
        Self { export_adapters: HashMap::new(), import_adapters: HashMap::new() }
    }

    /// Register export adapter
    ///
    /// # Parameters
    /// * `target` - Compilation target
    /// * `adapter` - Export adapter to register
    ///
    /// # Return Value
    /// Returns Ok(()) on success, or an error message on failure.
    pub fn register_export_adapter(&mut self, target: CompilationTarget, adapter: Box<dyn ExportAdapter>) -> Result<()> {
        if self.export_adapters.contains_key(&target) {
            return Err(GaiaError::adapter_error(&format!("{:?}", target), "Export adapter already exists", None));
        }
        self.export_adapters.insert(target, adapter);
        Ok(())
    }

    /// Register import adapter
    ///
    /// # Parameters
    /// * `target` - Compilation target
    /// * `adapter` - Import adapter to register
    ///
    /// # Return Value
    /// Returns Ok(()) on success, or an error message on failure.
    pub fn register_import_adapter(&mut self, target: CompilationTarget, adapter: Box<dyn ImportAdapter>) -> Result<()> {
        if self.import_adapters.contains_key(&target) {
            return Err(GaiaError::adapter_error(&format!("{:?}", target), "Import adapter already exists", None));
        }
        self.import_adapters.insert(target, adapter);
        Ok(())
    }

    /// Get export adapter
    ///
    /// # Parameters
    /// * `target` - Compilation target
    ///
    /// # Return Value
    /// Returns adapter reference if found, or an error otherwise.
    pub fn get_export_adapter(&self, target: &CompilationTarget) -> Result<&dyn ExportAdapter> {
        self.export_adapters
            .get(target)
            .map(|adapter| adapter.as_ref())
            .ok_or_else(|| GaiaError::adapter_error(&format!("{:?}", target), "Export adapter not found", None))
    }

    /// Get mutable export adapter
    ///
    /// # Parameters
    /// * `target` - Compilation target
    ///
    /// # Return Value
    /// Returns mutable adapter reference if found, or an error otherwise.
    pub fn get_export_adapter_mut(&mut self, target: &CompilationTarget) -> Result<&mut (dyn ExportAdapter + '_)> {
        match self.export_adapters.get_mut(target) {
            Some(adapter) => Ok(adapter.as_mut()),
            None => Err(GaiaError::adapter_error(&format!("{:?}", target), "Export adapter not found", None)),
        }
    }

    /// Get import adapter
    ///
    /// # Parameters
    /// * `target` - Compilation target
    ///
    /// # Return Value
    /// Returns adapter reference if found, or an error otherwise.
    pub fn get_import_adapter(&self, target: &CompilationTarget) -> Result<&dyn ImportAdapter> {
        self.import_adapters
            .get(target)
            .map(|adapter| adapter.as_ref())
            .ok_or_else(|| GaiaError::adapter_error(&format!("{:?}", target), "Import adapter not found", None))
    }

    /// Get mutable import adapter
    ///
    /// # Parameters
    /// * `target` - Compilation target
    ///
    /// # Return Value
    /// Returns mutable adapter reference if found, or an error otherwise.
    pub fn get_import_adapter_mut(&mut self, target: &CompilationTarget) -> Result<&mut (dyn ImportAdapter + '_)> {
        match self.import_adapters.get_mut(target) {
            Some(adapter) => Ok(adapter.as_mut()),
            None => Err(GaiaError::adapter_error(&format!("{:?}", target), "Import adapter not found", None)),
        }
    }

    /// List all supported compilation targets
    ///
    /// # Return Value
    /// List of compilation targets
    pub fn list_supported_targets(&self) -> Vec<CompilationTarget> {
        let mut targets = Vec::new();
        targets.extend(self.export_adapters.keys().cloned());
        targets.extend(self.import_adapters.keys().cloned());
        targets.sort_by_key(|t| format!("{:?}", t));
        targets.dedup();
        targets
    }

    /// Clean up all adapter resources
    ///
    /// # Return Value
    /// Returns Ok(()) on success, or an error message on failure.
    pub fn cleanup_all(&mut self) -> Result<()> {
        for (target, adapter) in &mut self.export_adapters {
            if let Err(e) = adapter.cleanup() {
                return Err(GaiaError::adapter_error(
                    &format!("{:?}", target),
                    "Failed to clean up export adapter",
                    Some(Box::new(e)),
                ));
            }
        }

        for (target, adapter) in &mut self.import_adapters {
            if let Err(e) = adapter.cleanup() {
                return Err(GaiaError::adapter_error(
                    &format!("{:?}", target),
                    "Failed to clean up import adapter",
                    Some(Box::new(e)),
                ));
            }
        }

        Ok(())
    }
}

impl Default for AdapterManager {
    fn default() -> Self {
        Self::new()
    }
}