diff --git a/Cargo.lock b/Cargo.lock index 29c1d96..d216c43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,6 +140,7 @@ dependencies = [ "ariadne", "chumsky", "clap", + "hir", "lexer", "parser", ] @@ -159,6 +160,13 @@ dependencies = [ "libc", ] +[[package]] +name = "hir" +version = "0.1.0" +dependencies = [ + "parser", +] + [[package]] name = "indexmap" version = "1.8.0" diff --git a/Cargo.toml b/Cargo.toml index 1575ccd..338c470 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,5 @@ members = [ "crates/main", "crates/lexer", "crates/parser", + "crates/hir", ] \ No newline at end of file diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml new file mode 100644 index 0000000..178f2d3 --- /dev/null +++ b/crates/hir/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "hir" +license = "MIT OR Apache-2.0" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +parser = { path = "../parser" } \ No newline at end of file diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs new file mode 100644 index 0000000..7b593c2 --- /dev/null +++ b/crates/hir/src/lib.rs @@ -0,0 +1,49 @@ +use std::ops::Range; +use parser::Expr; + +#[derive(Debug)] +pub enum Value { Int(i64), Float(f64), Bool(bool), String(String), Ident(String) } + +#[derive(Debug)] +pub enum IRKind { + Define { name: String, type_hint: String, value: Box }, + Fun { name: String, return_type_hint: String, args: Vec<(String, String)>, body: Box }, + Call { name: String, args: Vec }, + Do { body: Box }, + If { cond: Box, body: Box, else_body: Box }, + Value { value: Value }, + Binary { op: String, left: Box, right: Box }, +} + +#[derive(Debug)] +pub struct IR { + pub kind: IRKind, + pub span: Range +} + +impl IR { + pub fn new(kind: IRKind, span: Range) -> Self { + Self { kind, span } + } +} + +pub fn ast_to_ir(ast: Vec<(Expr, Range)>) -> Vec { + let mut irs = Vec::new(); + for expr in ast { + let ir_kind = expr_to_ir(&expr.0); + let ir = IR::new(ir_kind, expr.1); + irs.push(ir); + } + irs +} + +pub fn expr_to_ir(expr: &Expr) -> IRKind { + match expr { + Expr::Let { name, type_hint, value } => { + let value = expr_to_ir(&value.0); + IRKind::Define { name: name.clone(), type_hint: type_hint.clone(), value: Box::new(value) } + }, + Expr::Int(value) => IRKind::Value { value: Value::Int(*value) }, + _ => { dbg!(expr); todo!() } + } +} \ No newline at end of file diff --git a/crates/main/Cargo.toml b/crates/main/Cargo.toml index c338af3..cd63448 100644 --- a/crates/main/Cargo.toml +++ b/crates/main/Cargo.toml @@ -8,5 +8,6 @@ edition = "2021" clap = { version = "3.0.14", features = ["derive"] } lexer = { path = "../lexer" } parser = { path = "../parser" } +hir = { path = "../hir" } chumsky = "0.8.0" ariadne = "0.1.5" \ No newline at end of file diff --git a/crates/main/src/main.rs b/crates/main/src/main.rs index 14f5731..a606a54 100644 --- a/crates/main/src/main.rs +++ b/crates/main/src/main.rs @@ -4,6 +4,7 @@ use clap::Parser as ArgParser; use ariadne::{Report, ReportKind, Label, Source, Color, Fmt}; use lexer::lex; use parser::parse; +use hir::ast_to_ir; pub mod args; use args::{Args, Options}; @@ -25,6 +26,7 @@ fn main() { let (tokens, lex_error) = lex(src.clone()); let (ast, parse_error) = parse(tokens.unwrap(), src.chars().count()); + // Report errors. lex_error.into_iter() .map(|e| e.map(|e| e.to_string())) .chain(parse_error.into_iter().map(|e| e.map(|tok| tok.to_string()))) @@ -84,9 +86,6 @@ fn main() { .fg(Color::Red) )) .with_color(Color::Red) - ) - .with_help( - "You might have forgotten to end a previous line with semicolon" ), _ => { println!("{:?}", e); @@ -99,7 +98,11 @@ fn main() { match ast { Some(ast) => { - println!("{:#?}", ast); + // Convert the AST to HIR. + let ir = ast_to_ir(ast); + + // Print the HIR. + println!("{:#?}", ir); }, None => { log(2, "Failed to parse."); diff --git a/example/ex.hades b/example/ex.hades index a403401..6f77848 100644 --- a/example/ex.hades +++ b/example/ex.hades @@ -1,17 +1 @@ --- Variables -let foo: Int = 1; -let bar: String = "bar"; - --- Functions -fun add (lhs: Int) (rhs: Int): Int = lhs + rhs; -fun add_2 (lhs: Int) (rhs: Int): Int = do - let a: Int = lhs + rhs; - let b: Int = a + lhs; - return b; -end; - --- Entry point (maybe) -fun main: Void = do - print(add(34, 35)); - return 0; -end; \ No newline at end of file +let foo: int = 1; \ No newline at end of file