Skip to content

Commit c84e59e

Browse files
authored
Update main.rs
1 parent 9266d41 commit c84e59e

File tree

1 file changed

+43
-35
lines changed

1 file changed

+43
-35
lines changed

hacker-compiler/src/main.rs

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
// main.rs - Hacker Lang compiler using Cranelift.
2-
// Located at ~/.hacker-lang/bin/hacker-compiler.
3-
// Handles updated syntax with conditionals and includes.
4-
51
use std::env;
62
use std::fs::{self, File};
73
use std::io::{self, BufRead, Write};
84
use std::path::Path;
95
use std::process;
106

117
use cranelift::prelude::*;
8+
use cranelift_codegen::ir::Function;
129
use cranelift_codegen::isa;
1310
use cranelift_codegen::settings;
1411
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
1512
use cranelift_module::{DataContext, Linkage, Module};
1613
use cranelift_object::{ObjectBuilder, ObjectModule};
17-
use subprocess::Exec;
14+
use subprocess::{Exec, PopenError};
1815

1916
const HACKER_DIR: &str = "~/.hacker-lang";
2017

@@ -27,9 +24,10 @@ fn expand_home(path: &str) -> String {
2724
path.to_string()
2825
}
2926

30-
fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec<(String, String)>, Vec<String>, Vec<String>, Vec<String>)> {
27+
fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec<String>, Vec<(String, String)>, Vec<String>, Vec<String>, Vec<String>)> {
3128
let file = File::open(path)?;
3229
let mut deps = Vec::new();
30+
let mut libs = Vec::new();
3331
let mut vars = Vec::new();
3432
let mut cmds = Vec::new();
3533
let mut includes = Vec::new();
@@ -69,10 +67,32 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
6967
if line.starts_with("//") {
7068
let dep = line[2..].trim().to_string();
7169
if dep.is_empty() {
72-
errors.push(format!("Line {}: Empty dependency", line_num));
70+
errors.push(format!("Line {}: Empty system dependency", line_num));
7371
} else {
7472
deps.push(dep);
7573
}
74+
} else if line.starts_with("#") {
75+
let lib = line[1..].trim().to_string();
76+
if lib.is_empty() {
77+
errors.push(format!("Line {}: Empty library/include", line_num));
78+
} else {
79+
let lib_path_str = expand_home(&format!("{}/libs/{}/main.hacker", HACKER_DIR, lib));
80+
let lib_path = Path::new(&lib_path_str);
81+
if lib_path.exists() {
82+
includes.push(lib.clone());
83+
let (sub_deps, sub_libs, sub_vars, sub_cmds, sub_includes, sub_errors) = parse_hacker_file(lib_path, verbose)?;
84+
deps.extend(sub_deps);
85+
libs.extend(sub_libs);
86+
vars.extend(sub_vars);
87+
cmds.extend(sub_cmds);
88+
includes.extend(sub_includes);
89+
for err in sub_errors {
90+
errors.push(format!("In {}: {}", lib, err));
91+
}
92+
} else {
93+
libs.push(lib);
94+
}
95+
}
7696
} else if line.starts_with(">") {
7797
let parts: Vec<String> = line[1..].split('!').map(|s| s.trim().to_string()).collect();
7898
let cmd = parts[0].clone();
@@ -130,25 +150,13 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
130150
} else {
131151
errors.push(format!("Line {}: Invalid conditional syntax", line_num));
132152
}
133-
} else if line.starts_with("#") {
134-
let lib = line[1..].trim().to_string();
135-
if lib.is_empty() {
136-
errors.push(format!("Line {}: Empty include", line_num));
153+
} else if line.starts_with("&") {
154+
let parts: Vec<String> = line[1..].split('!').map(|s| s.trim().to_string()).collect();
155+
let cmd = parts[0].clone();
156+
if cmd.is_empty() {
157+
errors.push(format!("Line {}: Empty background command", line_num));
137158
} else {
138-
let lib_path = Path::new(&expand_home(&format!("{}/libs/{}.hacker", HACKER_DIR, lib)));
139-
if lib_path.exists() {
140-
includes.push(lib);
141-
let (sub_deps, sub_vars, sub_cmds, sub_includes, sub_errors) = parse_hacker_file(lib_path, verbose)?;
142-
deps.extend(sub_deps);
143-
vars.extend(sub_vars);
144-
cmds.extend(sub_cmds);
145-
includes.extend(sub_includes);
146-
for err in sub_errors {
147-
errors.push(format!("In {}: {}", lib, err));
148-
}
149-
} else {
150-
errors.push(format!("Line {}: Library {} not found", line_num, lib));
151-
}
159+
cmds.push(format!("{} &", cmd));
152160
}
153161
} else if line.starts_with("!") {
154162
// Ignore comment
@@ -162,16 +170,17 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
162170
}
163171

164172
if verbose {
165-
println!("Parsed deps: {:?}", deps);
166-
println!("Parsed vars: {:?}", vars);
167-
println!("Parsed cmds: {:?}", cmds);
168-
println!("Parsed includes: {:?}", includes);
173+
println!("System Deps: {:?}", deps);
174+
println!("Custom Libs: {:?}", libs);
175+
println!("Vars: {:?}", vars);
176+
println!("Cmds: {:?}", cmds);
177+
println!("Includes: {:?}", includes);
169178
if !errors.is_empty() {
170179
println!("Errors: {:?}", errors);
171180
}
172181
}
173182

174-
Ok((deps, vars, cmds, includes, errors))
183+
Ok((deps, libs, vars, cmds, includes, errors))
175184
}
176185

177186
fn generate_check_cmd(dep: &str) -> String {
@@ -191,7 +200,7 @@ fn main() -> io::Result<()> {
191200
let input_path = Path::new(&args[1]);
192201
let output_path = Path::new(&args[2]);
193202

194-
let (mut deps, vars, mut cmds, _includes, errors) = parse_hacker_file(input_path, verbose)?;
203+
let (mut deps, _libs, vars, mut cmds, _includes, errors) = parse_hacker_file(input_path, verbose)?;
195204
if !errors.is_empty() {
196205
for err in errors {
197206
eprintln!("{}", err);
@@ -213,7 +222,7 @@ fn main() -> io::Result<()> {
213222
let isa_builder = isa::lookup(triple).expect("Host not supported");
214223
let isa = isa_builder.finish(flags).expect("ISA build failed");
215224

216-
let builder = ObjectBuilder::new(isa, output_path.file_stem().unwrap().to_str().unwrap().as_bytes().to_vec(), cranelift_module::default_libcall_names()).unwrap();
225+
let builder = ObjectBuilder::new(isa, output_path.file_stem().unwrap().to_str().unwrap().to_vec(), cranelift_module::default_libcall_names()).expect("Failed to create ObjectBuilder");
217226
let mut module = ObjectModule::new(builder);
218227

219228
let pointer_type = module.target_config().pointer_type();
@@ -287,14 +296,13 @@ fn main() -> io::Result<()> {
287296
builder.finalize();
288297

289298
module.define_function(main_id, &mut ctx).unwrap();
290-
module.finalize_definitions();
291-
let obj = module.object.finish();
299+
let obj = module.finish();
292300

293301
let temp_obj_path = output_path.with_extension("o");
294302
let mut file = File::create(&temp_obj_path)?;
295303
file.write_all(&obj)?;
296304

297-
let status = Exec::shell(format!("gcc -o {} {}", output_path.display(), temp_obj_path.display())).join()?;
305+
let status = Exec::shell(format!("gcc -o {} {}", output_path.display(), temp_obj_path.display())).join().map_err(|e: PopenError| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
298306
if !status.success() {
299307
return Err(io::Error::new(io::ErrorKind::Other, "Linking failed"));
300308
}

0 commit comments

Comments
 (0)