From 8cdfbd61a97ff19be6bc69f6eda6acdde7dbbaae Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Fri, 17 May 2024 15:01:41 -0400 Subject: [PATCH] Move code generation into a build script --- .gitignore | 2 ++ Cargo.toml | 4 --- bin/astgen.rs => build.rs | 37 ++++++++++++--------- src/ast.rs | 70 --------------------------------------- 4 files changed, 23 insertions(+), 90 deletions(-) rename bin/astgen.rs => build.rs (89%) delete mode 100644 src/ast.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..1840d43 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ /target +# Autogenerated +/src/ast.rs diff --git a/Cargo.toml b/Cargo.toml index 65dd956..385347f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,10 +4,6 @@ version = "0.1.0" edition = "2021" default-run = "jlox-rust" -[[bin]] -name = "astgen" -path = "bin/astgen.rs" - [dependencies] anyhow = "1.0.83" itertools = "0.12.1" diff --git a/bin/astgen.rs b/build.rs similarity index 89% rename from bin/astgen.rs rename to build.rs index d8b0528..b09b1af 100644 --- a/bin/astgen.rs +++ b/build.rs @@ -2,26 +2,31 @@ use std::{ collections::BTreeMap, + fs::File, io::{self, Write}, iter, }; -fn main() { - let mut stdout = io::stdout(); +pub fn main() { + let mut ast_file = File::create("./src/ast.rs").expect("could not open src/ast.rs for writing"); + do_ast_codegen(&mut ast_file); +} + +fn do_ast_codegen(mut output: W) { // Autogenerated file, clippy can leave us alone - writeln!(stdout, "#![allow(clippy::all)]").unwrap(); + writeln!(output, "#![allow(clippy::all)]").unwrap(); writeln!( - stdout, - "// This file is auto-generated. Do not modify it directly, but rather use bin/astgen.rs.\n" + output, + "// This file is auto-generated. Do not modify it directly, but rather modify build.rs.\n" ) .unwrap(); - define_imports(&mut stdout, &["crate::lex::Token"]).expect("failed to define imports"); - writeln!(stdout).unwrap(); + define_imports(&mut output, &["crate::lex::Token"]).expect("failed to define imports"); + writeln!(output).unwrap(); define_literals( - &mut stdout, + &mut output, "LiteralValue", &BTreeMap::from([ ("Number", Some("f64")), @@ -32,7 +37,7 @@ fn main() { ]), ) .expect("failed to generate literals"); - writeln!(stdout).unwrap(); + writeln!(output).unwrap(); let expr_types = BTreeMap::from([ ( @@ -44,21 +49,21 @@ fn main() { ("Literal", "value: LiteralValue"), ]); - define_ast(&mut stdout, "Expr", &expr_types).expect("failed to generate ast values"); - writeln!(stdout).unwrap(); - define_visitor_trait(&mut stdout, "ExprVisitor", "Expr", &expr_types) + define_ast(&mut output, "Expr", &expr_types).expect("failed to generate ast values"); + writeln!(output).unwrap(); + define_visitor_trait(&mut output, "ExprVisitor", "Expr", &expr_types) .expect("failed to generate visitor trait"); - writeln!(stdout).unwrap(); + writeln!(output).unwrap(); let statement_types = BTreeMap::from([ ("Expression", "expression: Expr"), ("Print", "expression: Expr"), ]); - define_ast(&mut stdout, "Stmt", &statement_types).expect("failed to generate ast values"); - writeln!(stdout).unwrap(); - define_visitor_trait(&mut stdout, "StmtVisitor", "Stmt", &statement_types) + define_ast(&mut output, "Stmt", &statement_types).expect("failed to generate ast values"); + writeln!(output).unwrap(); + define_visitor_trait(&mut output, "StmtVisitor", "Stmt", &statement_types) .expect("failed to generate visitor trait"); } diff --git a/src/ast.rs b/src/ast.rs deleted file mode 100644 index c8341ee..0000000 --- a/src/ast.rs +++ /dev/null @@ -1,70 +0,0 @@ -#![allow(clippy::all)] -// This file is auto-generated. Do not modify it directly, but rather use bin/astgen.rs. - -use crate::lex::Token; - -#[derive(Debug, Clone)] -pub enum LiteralValue { - False, - Nil, - Number(f64), - String(String), - True, -} - -#[derive(Debug, Clone)] -pub enum Expr { - Binary { - left: Box, - operator: Token, - right: Box, - }, - Grouping { - expr: Box, - }, - Literal { - value: LiteralValue, - }, - Unary { - expr: Box, - operator: Token, - }, -} - -pub trait ExprVisitor { - fn visit_expr(&mut self, expr: &Expr) -> T { - match expr { - Expr::Binary { left, operator, right } => self.visit_binary(left.as_ref(), &operator, right.as_ref()), - Expr::Grouping { expr } => self.visit_grouping(expr.as_ref()), - Expr::Literal { value } => self.visit_literal(&value), - Expr::Unary { expr, operator } => self.visit_unary(expr.as_ref(), &operator), - } - } - - fn visit_binary(&mut self, left: &Expr, operator: &Token, right: &Expr) -> T; - fn visit_grouping(&mut self, expr: &Expr) -> T; - fn visit_literal(&mut self, value: &LiteralValue) -> T; - fn visit_unary(&mut self, expr: &Expr, operator: &Token) -> T; -} - -#[derive(Debug, Clone)] -pub enum Stmt { - Expression { - expression: Expr, - }, - Print { - expression: Expr, - }, -} - -pub trait StmtVisitor { - fn visit_stmt(&mut self, stmt: &Stmt) -> T { - match stmt { - Stmt::Expression { expression } => self.visit_expression(&expression), - Stmt::Print { expression } => self.visit_print(&expression), - } - } - - fn visit_expression(&mut self, expression: &Expr) -> T; - fn visit_print(&mut self, expression: &Expr) -> T; -}