Skip to content

Commit 325887b

Browse files
committed
Add basic binary file
Also... Benchmarks! ~ 65 ms / Mb with `-v 0` ~ 87 ms / Mb with `-v 3` ~ 120 ms / Mb with `--features slow_dev_debugging` and `-v 0` ~ 512 ms / Mb with `--features slow_dev_debugging` and `-v 3`
1 parent e43d25e commit 325887b

7 files changed

Lines changed: 145 additions & 22 deletions

File tree

Cargo.lock

Lines changed: 48 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
clap = { version = "4.5.48", features = ["derive"] }
8+
flate2 = "1.1.4"
89

910
[features]
1011
slow_dev_debugging = []

src/binary.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use std::{error::Error, fmt::Display, io::{self, Write}};
2+
use crate::compiler::KSM;
3+
use flate2::{write::GzEncoder, Compression};
4+
5+
#[derive(Debug)]
6+
pub struct BinaryError {
7+
reason: BinaryErrorReason,
8+
descriptive: &'static str,
9+
}
10+
11+
impl BinaryError {
12+
fn new<T>(reason: BinaryErrorReason, desc: &'static str) -> Result<T, BinaryError> {
13+
Err(BinaryError {
14+
reason,
15+
descriptive: desc,
16+
})
17+
}
18+
}
19+
20+
impl Display for BinaryError {
21+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22+
if super::LOG.verbosity >= 2 {
23+
write!(f, "Binary error: \n\n{}\n({:?})", self.descriptive, self.reason)
24+
} else {
25+
write!(f, "Binary error: {:?}", self.reason)
26+
}
27+
}
28+
}
29+
30+
impl Error for BinaryError {}
31+
32+
impl From<io::Error> for BinaryError {
33+
fn from(_value: io::Error) -> Self {
34+
BinaryError { reason: BinaryErrorReason::EncodingError, descriptive: "Something went wrong while applying gzip compression" }
35+
}
36+
}
37+
38+
#[derive(Clone, Debug)]
39+
pub enum BinaryErrorReason {
40+
EncodingError,
41+
}
42+
43+
44+
pub fn ksm_to_binary(ksm: KSM) -> Result<Vec<u8>, BinaryError> {
45+
let uncompressed: Vec<u8> = todo!("ksm to binary");
46+
47+
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
48+
encoder.write_all(&uncompressed)?;
49+
let encoded = encoder.finish()?;
50+
Ok(encoded)
51+
}

src/compiler.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{error::Error, fmt::Display};
2-
use super::lexer::{Token};
3-
use super::parser::{Expr, Type, Lit, AST, Scope, Stmt};
2+
use crate::lexer::{Token};
3+
use crate::parser::{Expr, Type, Lit, AST, Scope, Stmt};
44

55
#[derive(Debug)]
66
pub struct CompileError {
@@ -19,7 +19,7 @@ impl CompileError {
1919

2020
impl Display for CompileError {
2121
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22-
if super::LOG.verbosity >= 2 {
22+
if crate::LOG.verbosity >= 2 {
2323
write!(f, "Compile error: \n\n{}\n({:?})", self.descriptive, self.reason)
2424
} else {
2525
write!(f, "Compile error: {:?}", self.reason)
@@ -97,6 +97,7 @@ pub fn parse_ast(ast: AST) -> Result<KSM, CompileError> {
9797
flatten_to_ksm(ast)
9898
}
9999

100+
100101
fn flatten_to_ksm(ast: AST) -> Result<KSM, CompileError> {
101102
let functions = ast.functions;
102103
let consts_raw = ast.consts;
@@ -112,10 +113,18 @@ fn flatten_to_ksm(ast: AST) -> Result<KSM, CompileError> {
112113
loop {
113114
if let Some(func) = func_iter.next() {
114115
if &func.name == "main" {
115-
if func.input == [] && func.output == Type::Unit {
116+
let main_inp = vec![Type::Identifier("Vessel".to_string())];
117+
118+
for (inp_idx, inp) in func.input.iter().enumerate() {
119+
if main_inp[inp_idx] != inp.1 {
120+
return CompileError::new(CompileErrorReason::NoMainFunction, "The `main` function must have inputs `(*: Vessel)`")
121+
}
122+
}
123+
124+
if func.output == Type::Unit {
116125
main = Some(func);
117126
} else {
118-
return CompileError::new(CompileErrorReason::NoMainFunction, "The `main` function must have inputs `()` (none) and outputs `()` (unit)")
127+
return CompileError::new(CompileErrorReason::NoMainFunction, "The `main` function must have output `()` (unit)")
119128
}
120129
} else {
121130
func_signatures.push((func.input.clone(), func.output.clone()));
@@ -132,8 +141,8 @@ fn flatten_to_ksm(ast: AST) -> Result<KSM, CompileError> {
132141
None => return CompileError::new(CompileErrorReason::NoMainFunction, "A function `name` must exist")
133142
};
134143

135-
super::LOG.debug(&format!("\nDetected function names: {:?}", func_names));
136-
super::LOG.debug(&format!("Detected function signature: {:?}", func_signatures));
144+
crate::LOG.debug(&format!("\nDetected function names: {:?}", func_names));
145+
crate::LOG.debug(&format!("Detected function signature: {:?}", func_signatures));
137146

138147
let mut consts = Vec::new();
139148

@@ -143,10 +152,10 @@ fn flatten_to_ksm(ast: AST) -> Result<KSM, CompileError> {
143152
consts.push((name, lit));
144153
}
145154

146-
super::LOG.debug(&format!("Evaluated constants: {:?}", consts));
155+
crate::LOG.debug(&format!("Evaluated constants: {:?}", consts));
147156

148157
#[cfg(feature = "slow_dev_debugging")]
149-
super::LOG.debug(&format!("Main function: {:?}", &main));
158+
crate::LOG.debug(&format!("Main function: {:?}", &main));
150159

151160
let mut ksm_functions = Vec::new();
152161
let ctx = CompileContext {

src/lexer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ pub fn lex_string(inp_str: String) -> Result<Vec<DataToken>, LexError> {
248248
let pos = (line_idx, char_idx);
249249

250250
#[cfg(feature = "slow_dev_debugging")]
251-
super::LOG.debug(&format!("Parsing char {:?}: {:?}", c, pos));
251+
crate::LOG.debug(&format!("Parsing char {:?}: {:?}", c, pos));
252252

253253
if c.is_whitespace() {
254254
if c == '\n' {
@@ -295,7 +295,7 @@ pub fn lex_string(inp_str: String) -> Result<Vec<DataToken>, LexError> {
295295
chars.next();
296296
break
297297
} else if ca == None {
298-
super::LOG.explicit("Unclosed multiline comment at the end of the file");
298+
crate::LOG.explicit("Unclosed multiline comment at the end of the file");
299299
break
300300
} else {
301301
char_idx += 1;
@@ -381,7 +381,7 @@ pub fn lex_string(inp_str: String) -> Result<Vec<DataToken>, LexError> {
381381
match cs {
382382
&('a'..='z') | &('A'..='Z') | &('0'..='9') | &'_' => {},
383383
_ => {
384-
super::LOG.explicit(&format!("Detected single character literal (consider using a more descriptive name) at: {:?}", pos));
384+
crate::LOG.explicit(&format!("Detected single character literal (consider using a more descriptive name) at: {:?}", pos));
385385
tokens.push(DataToken::new(Token::Identifier(c.to_string()), pos));
386386
continue
387387
}

src/main.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use clap::Parser;
88
mod lexer;
99
mod parser;
1010
mod compiler;
11-
11+
mod binary;
1212

1313
/// A compiler for kLang
1414
#[derive(Debug, Parser)]
@@ -118,9 +118,23 @@ fn main() {
118118
}
119119
};
120120

121-
LOG.debug(&format!("\nKSM:\n\n{:?}\n", &ksm));
121+
LOG.debug(&format!("\nKSM:\n\n{:#?}\n", &ksm));
122122

123-
todo!("Finish parsing & Compilation");
123+
let binary = match binary::ksm_to_binary(ksm) {
124+
Ok(bin) => bin,
125+
Err(e) => {
126+
LOG.surface(&format!("{e}"));
127+
std::process::exit(1);
128+
}
129+
};
130+
131+
LOG.debug(&format!("\nBinary:\n\n{:?}\n", &binary));
132+
133+
if let Some(p) = &ARGS.output {
134+
_ = fs::write(p, binary);
135+
} else {
136+
println!("{:?}", binary);
137+
}
124138
}
125139

126140
fn explanation(_: &String) -> &'static str {

src/parser.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::{error::Error, fmt::Display, hash::Hash, iter::Peekable};
2-
use super::lexer::{DataToken, Token};
2+
use crate::lexer::{DataToken, Token};
33

44
#[derive(Debug)]
55
pub struct ParseError {
@@ -20,7 +20,7 @@ impl ParseError {
2020

2121
impl Display for ParseError {
2222
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23-
if super::LOG.verbosity >= 2 {
23+
if crate::LOG.verbosity >= 2 {
2424
write!(f, "Parsing error token {:?}!\n\n{}\n({:?})", self.token, self.descriptive, self.reason)
2525
} else {
2626
write!(f, "Parsing error at token {:?}: {:?}", self.token, self.reason)
@@ -264,7 +264,7 @@ fn parse_global(tokens: &mut tokenstream!()) -> Result<AST, ParseError> {
264264

265265
loop {
266266
#[cfg(feature = "slow_dev_debugging")]
267-
super::LOG.debug(&format!("Parsing Token: {:?}", tokens.peek()));
267+
crate::LOG.debug(&format!("Parsing Token: {:?}", tokens.peek()));
268268

269269
match tokens.next() {
270270
Some(t) => match t.inner() {
@@ -398,7 +398,7 @@ fn parse_scope(tokens: &mut tokenstream!()) -> Result<Scope, ParseError> {
398398
let mut statements = Vec::new();
399399
loop {
400400
#[cfg(feature = "slow_dev_debugging")]
401-
super::LOG.debug(&format!("Parsing token in scope: {:?}", tokens.peek()));
401+
crate::LOG.debug(&format!("Parsing token in scope: {:?}", tokens.peek()));
402402

403403
expect_token_peek!(tokens, tok, match tok.inner() {
404404
Token::BracesEnd => {tokens.next(); return Ok(Scope { statements })},
@@ -487,7 +487,7 @@ fn parse_scope(tokens: &mut tokenstream!()) -> Result<Scope, ParseError> {
487487

488488
statements.push(Stmt::If { id, cond, if_cond, else_cond, })
489489
},
490-
Token::Terminator => {super::LOG.explicit(&format!("Stray terminator `;`: {:?}", &tok)); tokens.next();},
490+
Token::Terminator => {crate::LOG.explicit(&format!("Stray terminator `;`: {:?}", &tok)); tokens.next();},
491491
_ => {
492492
statements.push(Stmt::Expr(parse_expr(tokens, 0)?));
493493
optional!(tokens, Comma);
@@ -498,7 +498,7 @@ fn parse_scope(tokens: &mut tokenstream!()) -> Result<Scope, ParseError> {
498498

499499
fn parse_expr(tokens: &mut tokenstream!(), min_bp: u8) -> Result<Expr, ParseError> {
500500
#[cfg(feature = "slow_dev_debugging")]
501-
super::LOG.debug(&format!("Expr parsing: {:?}", tokens.peek()));
501+
crate::LOG.debug(&format!("Expr parsing: {:?}", tokens.peek()));
502502

503503
let mut lhs = expect_token_peek!(tokens, tok, match tok.inner() {
504504
Token::ParenthesesBegin => {
@@ -537,7 +537,7 @@ fn parse_expr(tokens: &mut tokenstream!(), min_bp: u8) -> Result<Expr, ParseErro
537537
tokens.next();
538538

539539
#[cfg(feature = "slow_dev_debugging")]
540-
super::LOG.debug(&format!("Expr parsing post ident: {:?}", tokens.peek()));
540+
crate::LOG.debug(&format!("Expr parsing post ident: {:?}", tokens.peek()));
541541

542542
expect_token_peek!(tokens, t, match t.inner() {
543543
// POSTFIX OPERATORS

0 commit comments

Comments
 (0)