Skip to content

Commit 92d7b83

Browse files
authored
Update main.rs
1 parent e58e3fc commit 92d7b83

File tree

1 file changed

+58
-13
lines changed

1 file changed

+58
-13
lines changed

hacker-compiler/src/main.rs

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
// hacker-compiler/src/main.rs - Updated Rust compiler for Hacker Lang using Cranelift.
2-
// Syntax: // for deps, [ ... ] for config (ignored), > for cmds, ! for comments, @var=value for vars, *num > cmd for loops.
3-
// Enhanced with syntax checking and verbose output.
4-
// Compiles to native binary with putenv for vars and system for cmds.
5-
// Place binary in ~/.hackeros/hacker-lang/bin/hacker-compiler.
1+
// main.rs - Hacker Lang compiler using Cranelift.
2+
// Located at ~/.hacker-lang/bin/hacker-compiler.
3+
// Handles updated syntax with conditionals and includes.
64

75
use std::env;
86
use std::fs::{self, File};
@@ -18,11 +16,23 @@ use cranelift_module::{DataContext, Linkage, Module};
1816
use cranelift_object::{ObjectBuilder, ObjectModule};
1917
use subprocess::Exec;
2018

21-
fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec<(String, String)>, Vec<String>, Vec<String>)> {
19+
const HACKER_DIR: &str = "~/.hacker-lang";
20+
21+
fn expand_home(path: &str) -> String {
22+
if path.starts_with("~/") {
23+
if let Some(home) = std::env::var_os("HOME") {
24+
return path.replacen("~", home.to_str().unwrap(), 1);
25+
}
26+
}
27+
path.to_string()
28+
}
29+
30+
fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec<(String, String)>, Vec<String>, Vec<String>, Vec<String>)> {
2231
let file = File::open(path)?;
2332
let mut deps = Vec::new();
2433
let mut vars = Vec::new();
2534
let mut cmds = Vec::new();
35+
let mut includes = Vec::new();
2636
let mut errors = Vec::new();
2737
let mut in_config = false;
2838
let mut config_lines = Vec::new();
@@ -38,14 +48,14 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
3848

3949
if line == "[" {
4050
if in_config {
41-
errors.push(format!("Line {}: Nested config section detected", line_num));
51+
errors.push(format!("Line {}: Nested config section", line_num));
4252
}
4353
in_config = true;
4454
config_lines = Vec::new();
4555
continue;
4656
} else if line == "]" {
4757
if !in_config {
48-
errors.push(format!("Line {}: Closing ] without opening [", line_num));
58+
errors.push(format!("Line {}: Closing ] without [", line_num));
4959
}
5060
in_config = false;
5161
continue;
@@ -76,14 +86,14 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
7686
let var = line[1..eq_idx].trim().to_string();
7787
let value = line[eq_idx + 1..].trim().to_string();
7888
if var.is_empty() || value.is_empty() {
79-
errors.push(format!("Line {}: Invalid variable assignment", line_num));
89+
errors.push(format!("Line {}: Invalid variable", line_num));
8090
} else {
8191
vars.push((var, value));
8292
}
8393
} else {
8494
errors.push(format!("Line {}: Missing = in variable", line_num));
8595
}
86-
} else if line.starts_with("*") {
96+
} else if line.starts_with("=") {
8797
let parts: Vec<String> = line[1..].split('>').map(|s| s.trim().to_string()).collect();
8898
if parts.len() == 2 {
8999
if let Ok(num) = parts[0].parse::<usize>() {
@@ -106,6 +116,40 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
106116
} else {
107117
errors.push(format!("Line {}: Invalid loop syntax", line_num));
108118
}
119+
} else if line.starts_with("?") {
120+
let parts: Vec<String> = line[1..].split('>').map(|s| s.trim().to_string()).collect();
121+
if parts.len() == 2 {
122+
let condition = parts[0].clone();
123+
let cmd_parts: Vec<String> = parts[1].split('!').map(|s| s.trim().to_string()).collect();
124+
let cmd = cmd_parts[0].clone();
125+
if condition.is_empty() || cmd.is_empty() {
126+
errors.push(format!("Line {}: Invalid conditional", line_num));
127+
} else {
128+
cmds.push(format!("if {}; then {}; fi", condition, cmd));
129+
}
130+
} else {
131+
errors.push(format!("Line {}: Invalid conditional syntax", line_num));
132+
}
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));
137+
} 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+
}
152+
}
109153
} else if line.starts_with("!") {
110154
// Ignore comment
111155
} else {
@@ -114,19 +158,20 @@ fn parse_hacker_file(path: &Path, verbose: bool) -> io::Result<(Vec<String>, Vec
114158
}
115159

116160
if in_config {
117-
errors.push("File ended with unclosed config section".to_string());
161+
errors.push("Unclosed config section".to_string());
118162
}
119163

120164
if verbose {
121165
println!("Parsed deps: {:?}", deps);
122166
println!("Parsed vars: {:?}", vars);
123167
println!("Parsed cmds: {:?}", cmds);
168+
println!("Parsed includes: {:?}", includes);
124169
if !errors.is_empty() {
125170
println!("Errors: {:?}", errors);
126171
}
127172
}
128173

129-
Ok((deps, vars, cmds, errors))
174+
Ok((deps, vars, cmds, includes, errors))
130175
}
131176

132177
fn generate_check_cmd(dep: &str) -> String {
@@ -146,7 +191,7 @@ fn main() -> io::Result<()> {
146191
let input_path = Path::new(&args[1]);
147192
let output_path = Path::new(&args[2]);
148193

149-
let (mut deps, vars, mut cmds, errors) = parse_hacker_file(input_path, verbose)?;
194+
let (mut deps, vars, mut cmds, _includes, errors) = parse_hacker_file(input_path, verbose)?;
150195
if !errors.is_empty() {
151196
for err in errors {
152197
eprintln!("{}", err);

0 commit comments

Comments
 (0)