1use std::path::PathBuf;
2use clap::ValueEnum;
3use anyhow::{Result, Context};
4use crate::dna::mds::loader::BinaryLoader;
5use crate::dna::compiler::Compiler;
6use crate::dna::mds::optimizer::OptimizationLevel;
7
8#[derive(Clone, ValueEnum, Debug)]
9pub enum Language {
10 Rust,
11 Python,
12 JavaScript,
13 CSharp,
14 Java,
15 Go,
16 Ruby,
17 Php,
18}
19
20pub fn schema_command(
21 target: PathBuf,
22 lang: Language,
23 output: Option<PathBuf>,
24 verbose: bool,
25) -> Result<(), Box<dyn std::error::Error>> {
26 if verbose {
27 println!("🔧 Generating SDK schema...");
28 println!(" Target: {}", target.display());
29 println!(" Language: {:?}", lang);
30 println!(" Output: {:?}", output);
31 }
32
33 let source = std::fs::read_to_string(&target)
35 .context(format!("Failed to read Helix file: {}", target.display()))?;
36
37 let tokens = crate::dna::atp::lexer::tokenize(&source)
38 .map_err(|e| anyhow::anyhow!("Failed to tokenize Helix file: {} - {}", target.display(), e))?;
39 let ast = crate::dna::atp::parser::parse(tokens)
40 .map_err(|e| anyhow::anyhow!("Failed to parse Helix file: {} - {}", target.display(), e))?;
41
42 let output_path = output.unwrap_or_else(|| {
48 let stem = target.file_stem().unwrap_or_default().to_string_lossy();
49 let extension = match lang {
50 Language::Rust => "rs",
51 Language::Python => "py",
52 Language::JavaScript => "js",
53 Language::CSharp => "cs",
54 Language::Java => "java",
55 Language::Go => "go",
56 Language::Ruby => "rb",
57 Language::Php => "php",
58 };
59 target.with_file_name(format!("{}_schema.{}", stem, extension))
60 });
61
62 let schema_code = generate_schema_code(&ast, &lang)?;
64
65 std::fs::write(&output_path, schema_code)
67 .context(format!("Failed to write schema file: {}", output_path.display()))?;
68
69 println!("✅ Schema generated successfully: {}", output_path.display());
70
71 if verbose {
72 println!(" Language: {:?}", lang);
73 println!(" Sections: {}", ast.declarations.len());
74 }
75
76 Ok(())
77}
78pub fn generate_schema_code(ast: &crate::dna::atp::ast::HelixAst, lang: &Language) -> Result<String, Box<dyn std::error::Error>> {
79 match lang {
80 Language::Rust => generate_rust_schema(ast),
81 Language::Python => generate_python_schema(ast),
82 Language::JavaScript => generate_javascript_schema(ast),
83 Language::CSharp => generate_csharp_schema(ast),
84 Language::Java => generate_java_schema(ast),
85 Language::Go => generate_go_schema(ast),
86 Language::Ruby => generate_ruby_schema(ast),
87 Language::Php => generate_php_schema(ast),
88 }
89}
90pub fn generate_rust_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
91 let code = String::from("// Auto-generated Helix SDK for Rust
92use std::collections::HashMap;
93
94pub struct HelixConfig {
95 data: HashMap<String, serde_json::Value>,
96}
97
98impl HelixConfig {
99 pub pub fn new() -> Self {
100 Self {
101 data: HashMap::new(),
102 }
103 }
104
105 pub pub fn from_file(path: &str) -> Result<Self, Box<dyn std::error::Error>> {
106 let content = std::fs::read_to_string(path)?;
107 Self::from_string(&content)
108 }
109
110 pub pub fn from_string(content: &str) -> Result<Self, Box<dyn std::error::Error>> {
111 let data: HashMap<String, serde_json::Value> = serde_json::from_str(content)?;
112 Ok(Self { data })
113 }
114
115 pub pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
116 self.data.get(key)
117 }
118
119 pub pub fn set(&mut self, key: &str, value: serde_json::Value) {
120 self.data.insert(key.to_string(), value);
121 }
122
123 pub pub fn process(&self) -> Result<(), Box<dyn std::error::Error>> {
124 // Process the configuration
125 println!(\"Processing Helix configuration...\");
126 Ok(())
127 }
128
129 pub pub fn compile(&self) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
130 // Compile the configuration
131 println!(\"Compiling Helix configuration...\");
132 let json = serde_json::to_vec(&self.data)?;
133 Ok(json)
134 }
135}
136
137impl std::ops::Index<&str> for HelixConfig {
138 type Output = serde_json::Value;
139
140 pub fn index(&self, key: &str) -> &Self::Output {
141 self.data.get(key).unwrap_or(&serde_json::Value::Null)
142 }
143}
144");
145 Ok(code)
146}
147pub fn generate_python_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
148 let code = String::from("# Auto-generated Helix SDK for Python
149
150import json
151from typing import Dict, Any, Optional
152
153class HelixConfig:
154 def __init__(self):
155 self.data: Dict[str, Any] = {}
156
157 @classmethod
158 def from_file(cls, path: str) -> 'HelixConfig':
159 with open(path, 'r') as f:
160 content = f.read()
161 return cls.from_string(content)
162
163 @classmethod
164 def from_string(cls, content: str) -> 'HelixConfig':
165 instance = cls()
166 instance.data = json.loads(content)
167 return instance
168
169 def get(self, key: str) -> Any:
170 return self.data.get(key)
171
172 def set(self, key: str, value: Any):
173 self.data[key] = value
174
175 def __getitem__(self, key: str) -> Any:
176 return self.data.get(key, None)
177
178 def __setitem__(self, key: str, value: Any):
179 self.data[key] = value
180
181 def process(self):
182 \"\"\"Process the configuration\"\"\"
183 print(\"Processing Helix configuration...\")
184
185 def compile(self) -> bytes:
186 \"\"\"Compile the configuration\"\"\"
187 print(\"Compiling Helix configuration...\")
188 return json.dumps(self.data).encode('utf-8')
189");
190 Ok(code)
191}
192pub fn generate_javascript_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
193 let code = String::from("// Auto-generated Helix SDK for JavaScript
194
195class HelixConfig {
196 constructor() {
197 this.data = {};
198 }
199
200 static fromFile(path) {
201 const fs = require('fs');
202 const content = fs.readFileSync(path, 'utf8');
203 return HelixConfig.fromString(content);
204 }
205
206 static fromString(content) {
207 const instance = new HelixConfig();
208 instance.data = JSON.parse(content);
209 return instance;
210 }
211
212 get(key) {
213 return this.data[key];
214 }
215
216 set(key, value) {
217 this.data[key] = value;
218 }
219
220 process() {
221 console.log('Processing Helix configuration...');
222 }
223
224 compile() {
225 console.log('Compiling Helix configuration...');
226 return Buffer.from(JSON.stringify(this.data));
227 }
228}
229
230// Bracket notation access
231HelixConfig.prototype.__defineGetter__('hlx', function() {
232 return this;
233});
234
235module.exports = HelixConfig;
236");
237 Ok(code)
238}
239pub fn generate_csharp_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
240 let code = String::from("// Auto-generated Helix SDK for C#
241
242using System;
243using System.Collections.Generic;
244using System.IO;
245using Newtonsoft.Json;
246
247public class HelixConfig
248{
249 private Dictionary<string, object> data = new Dictionary<string, object>();
250
251 public static HelixConfig FromFile(string path)
252 {
253 string content = File.ReadAllText(path);
254 return FromString(content);
255 }
256
257 public static HelixConfig FromString(string content)
258 {
259 var instance = new HelixConfig();
260 instance.data = JsonConvert.DeserializeObject<Dictionary<string, object>>(content);
261 return instance;
262 }
263
264 public object Get(string key)
265 {
266 return data.ContainsKey(key) ? data[key] : null;
267 }
268
269 public void Set(string key, object value)
270 {
271 data[key] = value;
272 }
273
274 public object this[string key]
275 {
276 get { return Get(key); }
277 set { Set(key, value); }
278 }
279
280 public void Process()
281 {
282 Console.WriteLine(\"Processing Helix configuration...\");
283 }
284
285 public byte[] Compile()
286 {
287 Console.WriteLine(\"Compiling Helix configuration...\");
288 string json = JsonConvert.SerializeObject(data);
289 return System.Text.Encoding.UTF8.GetBytes(json);
290 }
291}
292");
293 Ok(code)
294}
295pub fn generate_java_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
296 let code = String::from("// Auto-generated Helix SDK for Java
297
298import com.fasterxml.jackson.databind.ObjectMapper;
299import java.io.File;
300import java.io.IOException;
301import java.util.HashMap;
302import java.util.Map;
303
304public class HelixConfig {
305 private Map<String, Object> data = new HashMap<>();
306 private static final ObjectMapper mapper = new ObjectMapper();
307
308 public static HelixConfig fromFile(String path) throws IOException {
309 String content = new String(java.nio.file.Files.readAllBytes(new File(path).toPath()));
310 return fromString(content);
311 }
312
313 public static HelixConfig fromString(String content) throws IOException {
314 HelixConfig instance = new HelixConfig();
315 instance.data = mapper.readValue(content, Map.class);
316 return instance;
317 }
318
319 public Object get(String key) {
320 return data.get(key);
321 }
322
323 public void set(String key, Object value) {
324 data.put(key, value);
325 }
326
327 public void process() {
328 System.out.println(\"Processing Helix configuration...\");
329 }
330
331 public byte[] compile() throws IOException {
332 System.out.println(\"Compiling Helix configuration...\");
333 String json = mapper.writeValueAsString(data);
334 return json.getBytes();
335 }
336}
337");
338 Ok(code)
339}
340pub fn generate_go_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
341 let code = String::from("// Auto-generated Helix SDK for Go
342
343package helix
344
345import (
346 \"encoding/json\"
347 \"fmt\"
348 \"io/ioutil\"
349 \"log\"
350)
351
352type HelixConfig struct {
353 Data map[string]interface{} `json:\"data\"`
354}
355
356func NewHelixConfig() *HelixConfig {
357 return &HelixConfig{
358 Data: make(map[string]interface{}),
359 }
360}
361
362func FromFile(path string) (*HelixConfig, error) {
363 content, err := ioutil.ReadFile(path)
364 if err != nil {
365 return nil, err
366 }
367 return FromString(string(content))
368}
369
370func FromString(content string) (*HelixConfig, error) {
371 var data map[string]interface{}
372 if err := json.Unmarshal([]byte(content), &data); err != nil {
373 return nil, err
374 }
375 return &HelixConfig{Data: data}, nil
376}
377
378func (h *HelixConfig) Get(key string) interface{} {
379 return h.Data[key]
380}
381
382func (h *HelixConfig) Set(key string, value interface{}) {
383 h.Data[key] = value
384}
385
386func (h *HelixConfig) Process() {
387 fmt.Println(\"Processing Helix configuration...\")
388}
389
390func (h *HelixConfig) Compile() ([]byte, error) {
391 fmt.Println(\"Compiling Helix configuration...\")
392 return json.Marshal(h.Data)
393}
394");
395 Ok(code)
396}
397pub fn generate_ruby_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
398 let code = String::from("# Auto-generated Helix SDK for Ruby
399
400require 'json'
401
402class HelixConfig
403 attr_accessor :data
404
405 def initialize
406 @data = {}
407 end
408
409 def self.from_file(path)
410 content = File.read(path)
411 from_string(content)
412 end
413
414 def self.from_string(content)
415 instance = new
416 instance.data = JSON.parse(content)
417 instance
418 end
419
420 def get(key)
421 @data[key]
422 end
423
424 def set(key, value)
425 @data[key] = value
426 end
427
428 def [](key)
429 get(key)
430 end
431
432 def []=(key, value)
433 set(key, value)
434 end
435
436 def process
437 puts 'Processing Helix configuration...'
438 end
439
440 def compile
441 puts 'Compiling Helix configuration...'
442 JSON.dump(@data).bytes
443 end
444end
445");
446 Ok(code)
447}
448pub fn generate_php_schema(_ast: &crate::dna::atp::ast::HelixAst) -> Result<String, Box<dyn std::error::Error>> {
449 let code = String::from("<?php
450// Auto-generated Helix SDK for PHP
451
452class HelixConfig {
453 private $data = [];
454
455 public static function fromFile(string $path): self {
456 $content = file_get_contents($path);
457 return self::fromString($content);
458 }
459
460 public static function fromString(string $content): self {
461 $instance = new self();
462 $instance->data = json_decode($content, true);
463 return $instance;
464 }
465
466 public function get(string $key) {
467 return $this->data[$key] ?? null;
468 }
469
470 public function set(string $key, $value): void {
471 $this->data[$key] = $value;
472 }
473
474 public function __get(string $key) {
475 return $this->get($key);
476 }
477
478 public function __set(string $key, $value): void {
479 $this->set($key, $value);
480 }
481
482 public function process(): void {
483 echo \"Processing Helix configuration...\\n\";
484 }
485
486 public function compile(): string {
487 echo \"Compiling Helix configuration...\\n\";
488 return json_encode($this->data);
489 }
490}
491");
492 Ok(code)
493}
494pub fn decompile_command(
495 input: PathBuf,
496 output: Option<PathBuf>,
497 verbose: bool,
498) -> Result<(), Box<dyn std::error::Error>> {
499 let output_path = output
500 .unwrap_or_else(|| {
501 let mut path = input.clone();
502 path.set_extension("hlx");
503 path
504 });
505 if verbose {
506 println!("🔄 Decompiling: {}", input.display());
507 }
508 let loader = BinaryLoader::new();
509 let binary = loader.load_file(&input)?;
510 let compiler = Compiler::new(OptimizationLevel::Zero);
511 let source = compiler.decompile(&binary)?;
512 std::fs::write(&output_path, source)?;
513 println!("✅ Decompiled successfully: {}", output_path.display());
514 Ok(())
515}
516pub fn validate_command(
517 file: PathBuf,
518 detailed: bool,
519) -> Result<(), Box<dyn std::error::Error>> {
520 let extension = file.extension().and_then(|s| s.to_str());
521 match extension {
522 Some("hlx") => {
523 let source = std::fs::read_to_string(&file)?;
524 let tokens = crate::dna::atp::lexer::tokenize(&source)
525 .map_err(|e| anyhow::anyhow!("Failed to tokenize: {}", e))?;
526 let ast = crate::dna::atp::parser::parse(tokens)?;
527 println!("✅ Valid HELIX file: {}", file.display());
530 if detailed {
531 println!(" Declarations: {}", ast.declarations.len());
532 }
533 }
534 Some("hlxb") => {
535 let loader = BinaryLoader::new();
536 let binary = loader.load_file(&file)?;
537 binary.validate()?;
538 println!("✅ Valid HLXB file: {}", file.display());
539 if detailed {
540 println!(" Version: {}", binary.version);
541 println!(" Sections: {}", binary.data_sections.len());
542 println!(" Checksum: {:x}", binary.checksum);
543 }
544 }
545 _ => {
546 return Err("Unknown file type (expected .hlx or .hlxb)".into());
547 }
548 }
549 Ok(())
550}