Skip to content

Commit 233ba1d

Browse files
authored
Update main.rs
1 parent 599419e commit 233ba1d

File tree

1 file changed

+18
-48
lines changed

1 file changed

+18
-48
lines changed

hacker-compiler/src/main.rs

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,15 @@ use std::fs::{self, File};
33
use std::io::{self, BufRead, Write};
44
use std::path::Path;
55
use std::process;
6-
76
use cranelift::prelude::*;
87
use cranelift_codegen::ir::Function;
98
use cranelift_codegen::isa;
109
use cranelift_codegen::settings;
1110
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
12-
use cranelift_module::{DataContext, Linkage, Module};
11+
use cranelift_module::{DataDescription, Linkage, Module};
1312
use cranelift_object::{ObjectBuilder, ObjectModule};
1413
use subprocess::{Exec, PopenError};
15-
1614
const HACKER_DIR: &str = "~/.hacker-lang";
17-
1815
fn expand_home(path: &str) -> String {
1916
if path.starts_with("~/") {
2017
if let Some(home) = std::env::var_os("HOME") {
@@ -23,7 +20,6 @@ fn expand_home(path: &str) -> String {
2320
}
2421
path.to_string()
2522
}
26-
2723
fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec<String>, Vec<(String, String)>, Vec<String>, Vec<String>, Vec<String>)> {
2824
let file = File::open(path)?;
2925
let mut deps = Vec::new();
@@ -35,15 +31,13 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
3531
let mut in_config = false;
3632
let mut config_lines = Vec::new();
3733
let mut line_num = 0;
38-
3934
for line in io::BufReader::new(file).lines() {
4035
line_num += 1;
4136
let line = line?;
4237
let line = line.trim().to_string();
4338
if line.is_empty() {
4439
continue;
4540
}
46-
4741
if line == "[" {
4842
if in_config {
4943
errors.push(format!("Line {}: Nested config section", line_num));
@@ -58,12 +52,10 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
5852
in_config = false;
5953
continue;
6054
}
61-
6255
if in_config {
6356
config_lines.push(line);
6457
continue;
6558
}
66-
6759
if line.starts_with("//") {
6860
let dep = line[2..].trim().to_string();
6961
if dep.is_empty() {
@@ -117,10 +109,6 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
117109
let parts: Vec<String> = line[1..].split('>').map(|s| s.trim().to_string()).collect();
118110
if parts.len() == 2 {
119111
if let Ok(num) = parts[0].parse::<usize>() {
120-
if num < 0 {
121-
errors.push(format!("Line {}: Negative loop count", line_num));
122-
continue;
123-
}
124112
let cmd_parts: Vec<String> = parts[1].split('!').map(|s| s.trim().to_string()).collect();
125113
let cmd = cmd_parts[0].clone();
126114
if cmd.is_empty() {
@@ -164,11 +152,9 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
164152
errors.push(format!("Line {}: Invalid syntax", line_num));
165153
}
166154
}
167-
168155
if in_config {
169156
errors.push("Unclosed config section".to_string());
170157
}
171-
172158
if verbose {
173159
println!("System Deps: {:?}", deps);
174160
println!("Custom Libs: {:?}", libs);
@@ -179,135 +165,119 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
179165
println!("Errors: {:?}", errors);
180166
}
181167
}
182-
183168
Ok((deps, libs, vars, cmds, includes, errors))
184169
}
185-
186170
fn generate_check_cmd(dep: &str) -> String {
187171
if dep == "sudo" {
188172
return String::new();
189173
}
190174
format!("command -v {} &> /dev/null || (sudo apt update && sudo apt install -y {})", dep, dep)
191175
}
192-
193176
fn main() -> io::Result<()> {
194-
let mut args: Vec<String> = env::args().collect();
177+
let args: Vec<String> = env::args().collect();
195178
if args.len() < 3 || args.len() > 4 {
196179
eprintln!("Usage: hacker-compiler <input.hacker> <output> [--verbose]");
197180
process::exit(1);
198181
}
199182
let verbose = args.len() == 4 && args[3] == "--verbose";
200183
let input_path = Path::new(&args[1]);
201184
let output_path = Path::new(&args[2]);
202-
203-
let (mut deps, _libs, vars, mut cmds, _includes, errors) = parse_hacker_file(input_path, verbose)?;
185+
let (deps, _libs, vars, cmds, _includes, errors) = parse_hacker_file(input_path, verbose)?;
204186
if !errors.is_empty() {
205187
for err in errors {
206188
eprintln!("{}", err);
207189
}
208190
process::exit(1);
209191
}
210-
192+
let mut final_cmds = Vec::new();
211193
for dep in deps {
212194
let check = generate_check_cmd(&dep);
213195
if !check.is_empty() {
214-
cmds.insert(0, check);
196+
final_cmds.push(check);
215197
}
216198
}
217-
199+
final_cmds.extend(cmds);
218200
let flag_builder = settings::builder();
219201
let flags = settings::Flags::new(flag_builder);
220-
221202
let triple = target_lexicon::Triple::host();
222203
let isa_builder = isa::lookup(triple).expect("Host not supported");
223204
let isa = isa_builder.finish(flags).expect("ISA build failed");
224-
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");
205+
let builder = ObjectBuilder::new(
206+
isa,
207+
output_path.file_stem().unwrap().to_str().unwrap().as_bytes().to_vec(),
208+
cranelift_module::default_libcall_names(),
209+
).expect("Failed to create ObjectBuilder");
226210
let mut module = ObjectModule::new(builder);
227-
228211
let pointer_type = module.target_config().pointer_type();
229212
let mut sig_system = module.make_signature();
230213
sig_system.params.push(AbiParam::new(pointer_type));
231214
sig_system.returns.push(AbiParam::new(types::I32));
232215
sig_system.call_conv = module.target_config().default_call_conv;
233216
let system_id = module.declare_function("system", Linkage::Import, &sig_system).unwrap();
234-
235217
let mut sig_putenv = module.make_signature();
236218
sig_putenv.params.push(AbiParam::new(pointer_type));
237219
sig_putenv.returns.push(AbiParam::new(types::I32));
238220
sig_putenv.call_conv = module.target_config().default_call_conv;
239221
let putenv_id = module.declare_function("putenv", Linkage::Import, &sig_putenv).unwrap();
240-
241222
let mut sig_main = module.make_signature();
242223
sig_main.returns.push(AbiParam::new(types::I32));
243224
sig_main.call_conv = module.target_config().default_call_conv;
244225
let main_id = module.declare_function("main", Linkage::Export, &sig_main).unwrap();
245-
246226
let mut ctx = cranelift_codegen::Context::for_function(Function::with_name_signature(Default::default(), sig_main.clone()));
247227
let mut func_builder_ctx = FunctionBuilderContext::new();
248228
let mut builder = FunctionBuilder::new(&mut ctx.func, &mut func_builder_ctx);
249-
250229
let entry_block = builder.create_block();
251230
builder.switch_to_block(entry_block);
252231
builder.seal_block(entry_block);
253-
254232
let local_system = module.declare_func_in_func(system_id, &mut builder.func);
255233
let local_putenv = module.declare_func_in_func(putenv_id, &mut builder.func);
256-
257234
let mut var_data_ids = Vec::new();
258235
for (var, value) in &vars {
259236
let env_str = format!("{}={}", var, value);
260237
let data_name = format!("env_{}", var_data_ids.len());
261238
let data_id = module.declare_data(&data_name, Linkage::Local, true, false).unwrap();
262-
let mut data_ctx = DataContext::new();
239+
let mut data_ctx = DataDescription::new();
263240
let mut bytes: Vec<u8> = env_str.into_bytes();
264241
bytes.push(0);
265242
data_ctx.define(bytes.into_boxed_slice());
266243
module.define_data(data_id, &data_ctx).unwrap();
267244
var_data_ids.push(data_id);
268245
}
269-
270246
for data_id in var_data_ids {
271247
let global = module.declare_data_in_func(data_id, &mut builder.func);
272248
let ptr = builder.ins().global_value(pointer_type, global);
273249
let _ = builder.ins().call(local_putenv, &[ptr]);
274250
}
275-
276251
let mut cmd_data_ids = Vec::new();
277-
for (i, cmd) in cmds.iter().enumerate() {
252+
for (i, cmd) in final_cmds.iter().enumerate() {
278253
let data_name = format!("cmd_{i}");
279254
let data_id = module.declare_data(&data_name, Linkage::Local, true, false).unwrap();
280-
let mut data_ctx = DataContext::new();
255+
let mut data_ctx = DataDescription::new();
281256
let mut bytes: Vec<u8> = cmd.as_bytes().to_vec();
282257
bytes.push(0);
283258
data_ctx.define(bytes.into_boxed_slice());
284259
module.define_data(data_id, &data_ctx).unwrap();
285260
cmd_data_ids.push(data_id);
286261
}
287-
288262
for data_id in cmd_data_ids {
289263
let global = module.declare_data_in_func(data_id, &mut builder.func);
290264
let ptr = builder.ins().global_value(pointer_type, global);
291265
let _ = builder.ins().call(local_system, &[ptr]);
292266
}
293-
294267
let zero = builder.ins().iconst(types::I32, 0);
295268
builder.ins().return_(&[zero]);
296269
builder.finalize();
297-
298270
module.define_function(main_id, &mut ctx).unwrap();
299-
let obj = module.finish();
300-
271+
let obj = module.finish().object.write().expect("Failed to write object");
301272
let temp_obj_path = output_path.with_extension("o");
302273
let mut file = File::create(&temp_obj_path)?;
303274
file.write_all(&obj)?;
304-
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()))?;
275+
let status = Exec::shell(format!("gcc -o {} {}", output_path.display(), temp_obj_path.display()))
276+
.join()
277+
.map_err(|e: PopenError| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
306278
if !status.success() {
307279
return Err(io::Error::new(io::ErrorKind::Other, "Linking failed"));
308280
}
309-
310281
fs::remove_file(temp_obj_path)?;
311-
312282
Ok(())
313283
}

0 commit comments

Comments
 (0)