From 99daf682cdc7a052e06c436fbf11117fd74b54e3 Mon Sep 17 00:00:00 2001 From: Alex Bethel Date: Mon, 22 Aug 2022 20:00:34 -0600 Subject: [PATCH] Tear out the IR and type checking systems I'm gonna re-do type checking so it's not done at the AST level, but instead the AST generates a high-level IR that then gets type-checked to a lower-level IR. --- drimc_rs/src/ast2ir.rs | 10 ---- drimc_rs/src/backends/c.rs | 4 +- drimc_rs/src/ir.rs | 5 -- drimc_rs/src/lib.rs | 2 - drimc_rs/src/main.rs | 26 +--------- drimc_rs/src/parser.rs | 100 +++++++++++++++---------------------- drimc_rs/src/syntax.rs | 18 +------ 7 files changed, 44 insertions(+), 121 deletions(-) delete mode 100644 drimc_rs/src/ast2ir.rs delete mode 100644 drimc_rs/src/ir.rs diff --git a/drimc_rs/src/ast2ir.rs b/drimc_rs/src/ast2ir.rs deleted file mode 100644 index 6e7f89b..0000000 --- a/drimc_rs/src/ast2ir.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! Conversion of AST to intermediate representation. - -use crate::ir::IR; -use crate::syntax::SyntaxTree; - -/// Compiles an abstract syntax tree into intermediate representation; this assumes the code already -/// type-checks, and emits unoptimized IR. -pub fn ast2ir(_: SyntaxTree) -> IR { - todo!() -} diff --git a/drimc_rs/src/backends/c.rs b/drimc_rs/src/backends/c.rs index 5ce4af9..0e89280 100644 --- a/drimc_rs/src/backends/c.rs +++ b/drimc_rs/src/backends/c.rs @@ -1,9 +1,7 @@ //! Backend for direct generation of C code. -use crate::ir::IR; - /// Generates C code with the same semantics as the intermediate representation. Returns the C /// source code as a string. -pub fn generate_c(_ir: &IR) -> String { +pub fn generate_c(_ir: &()) -> String { todo!() } diff --git a/drimc_rs/src/ir.rs b/drimc_rs/src/ir.rs deleted file mode 100644 index 5ae4cf2..0000000 --- a/drimc_rs/src/ir.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Intermediate code representation. - -/// The IR tree representing the whole program. -#[derive(Debug)] -pub struct IR; diff --git a/drimc_rs/src/lib.rs b/drimc_rs/src/lib.rs index 18e659c..aab544f 100644 --- a/drimc_rs/src/lib.rs +++ b/drimc_rs/src/lib.rs @@ -5,9 +5,7 @@ #![deny(missing_docs)] -pub mod ast2ir; pub mod backends; -pub mod ir; pub mod parser; pub mod syntax; pub mod typeck; diff --git a/drimc_rs/src/main.rs b/drimc_rs/src/main.rs index 7563091..8383065 100644 --- a/drimc_rs/src/main.rs +++ b/drimc_rs/src/main.rs @@ -1,11 +1,9 @@ //! Drim compiler CLI. -use std::{error::Error, fmt::Display, fs::File, io::Write, process::exit, str::FromStr}; +use std::{error::Error, fmt::Display, process::exit, str::FromStr}; use clap::Parser; use drimc_rs::{ - ast2ir::ast2ir, - backends, parser::{parser, ParserError, ParserMeta}, typeck::typeck, }; @@ -258,27 +256,7 @@ fn main() { let ast = chumsky::Parser::parse(&parser(&meta), source).map_err(ParserError)?; let ast = typeck(ast)?; - let ir = ast2ir(ast); - - match args.target { - Target::CSource => { - let c = backends::c::generate_c(&ir); - - let mut out_file = File::create("out.c")?; - write!(out_file, "{}", c)?; - } - Target::Assembly => todo!(), - Target::ObjectFile => todo!(), - Target::Executable => todo!(), - Target::SharedObject => todo!(), - Target::Spirv => todo!(), - Target::Wat => todo!(), - Target::Wasm => todo!(), - Target::Lua => todo!(), - Target::Python => todo!(), - Target::Go => todo!(), - Target::Ada => todo!(), - } + println!("{ast:?}"); Ok(()) } diff --git a/drimc_rs/src/parser.rs b/drimc_rs/src/parser.rs index 688ee9a..2ef4cc0 100644 --- a/drimc_rs/src/parser.rs +++ b/drimc_rs/src/parser.rs @@ -10,8 +10,7 @@ use chumsky::{ }; use crate::syntax::{ - ClassMember, Expr, ExprKind, Identifier, Literal, Pattern, Statement, SyntaxTree, Type, - TypeConstructor, + ClassMember, Expr, Identifier, Literal, Pattern, Statement, SyntaxTree, Type, TypeConstructor, }; /// Adapter to make `chumsky`'s parser errors usable as standard Rust errors. @@ -331,7 +330,6 @@ fn parse_func_decl<'a>( name, arguments, definition, - typ: None, }) } @@ -374,11 +372,9 @@ fn parse_expression<'a>( let application = term.repeated().at_least(1).map(|exprs| { exprs .into_iter() - .reduce(|l, r| { - expr(ExprKind::Application { - func: Box::new(l), - argument: Box::new(r), - }) + .reduce(|l, r| Expr::Application { + func: Box::new(l), + argument: Box::new(r), }) .unwrap() }); @@ -401,12 +397,10 @@ fn parse_unary( .repeated() .then(base) .map(|(ops, exp)| { - ops.into_iter().fold(exp, |exp, op| { - expr(ExprKind::UnaryOp { - kind: op.to_string(), - val: Box::new(exp), - translation: "negate".to_string(), - }) + ops.into_iter().fold(exp, |exp, op| Expr::UnaryOp { + kind: op.to_string(), + val: Box::new(exp), + translation: "negate".to_string(), }) }) } @@ -446,12 +440,12 @@ fn parse_binary<'a>( others .into_iter() .fold(first, |left, (op_name, _assoc, translation, right)| { - expr(ExprKind::BinaryOp { + Expr::BinaryOp { kind: op_name.to_owned(), left: Box::new(left), right: Box::new(right), translation: translation.to_string(), - }) + } }) } Some(Associativity::Right) => { @@ -492,13 +486,11 @@ fn parse_binary<'a>( others_l .into_iter() .rev() - .fold(last.to_owned(), |r, (l, (op, trans))| { - expr(ExprKind::BinaryOp { - kind: op.to_string(), - left: Box::new(l.to_owned()), - right: Box::new(r), - translation: trans.to_string(), - }) + .fold(last.to_owned(), |r, (l, (op, trans))| Expr::BinaryOp { + kind: op.to_string(), + left: Box::new(l.to_owned()), + right: Box::new(r), + translation: trans.to_string(), }) } } @@ -515,12 +507,10 @@ fn parse_let_expr( .then(rec.clone()) .then_ignore(pad(keyword("in"))) .then(rec) - .map(|((left, right), into)| { - expr(ExprKind::Let { - left, - right: Box::new(right), - into: Box::new(into), - }) + .map(|((left, right), into)| Expr::Let { + left, + right: Box::new(right), + into: Box::new(into), }) } @@ -538,11 +528,9 @@ fn parse_match_expr( .allow_trailing() .delimited_by(pad(just('{')), pad(just('}'))), ) - .map(|(matcher, cases)| { - expr(ExprKind::Match { - matcher: Box::new(matcher), - cases, - }) + .map(|(matcher, cases)| Expr::Match { + matcher: Box::new(matcher), + cases, }) } @@ -556,7 +544,7 @@ fn parse_record_expr( .separated_by(pad(just(','))) .allow_trailing() .delimited_by(pad(just('{')), pad(just('}'))) - .map(|elems| expr(ExprKind::Record(elems))) + .map(|elems| Expr::Record(elems)) } fn parse_lambda_expr( @@ -567,11 +555,9 @@ fn parse_lambda_expr( .ignore_then(parse_pattern(m).repeated()) .then_ignore(pad(just("->"))) .then(rec) - .map(|(arguments, result)| { - expr(ExprKind::Lambda { - arguments, - result: Box::new(result), - }) + .map(|(arguments, result)| Expr::Lambda { + arguments, + result: Box::new(result), }) } @@ -597,17 +583,15 @@ fn parse_subscript_expr( .repeated(), ) .map(|(l, subscripts): (Expr, Vec<(SubscriptKind, Expr)>)| { - subscripts.into_iter().fold(l, |l, (kind, r)| { - expr(match kind { - SubscriptKind::Dot => ExprKind::DotSubscript { - value: Box::new(l), - subscript: Box::new(r), - }, - SubscriptKind::Bracket => ExprKind::BracketSubscript { - value: Box::new(l), - subscript: Box::new(r), - }, - }) + subscripts.into_iter().fold(l, |l, (kind, r)| match kind { + SubscriptKind::Dot => Expr::DotSubscript { + value: Box::new(l), + subscript: Box::new(r), + }, + SubscriptKind::Bracket => Expr::BracketSubscript { + value: Box::new(l), + subscript: Box::new(r), + }, }) }) } @@ -622,13 +606,13 @@ fn parse_tuple_expr( if exprs.len() == 1 { exprs.into_iter().next().unwrap() } else { - expr(ExprKind::Tuple(exprs)) + Expr::Tuple(exprs) } }) } fn parse_var_ref_expr(m: &ParserMeta) -> impl Parser> + Clone { - parse_identifier(m).map(|r| expr(ExprKind::VariableReference(r))) + parse_identifier(m).map(|r| Expr::VariableReference(r)) } fn parse_literal(_m: &ParserMeta) -> impl Parser> + Clone { @@ -673,7 +657,7 @@ fn parse_literal(_m: &ParserMeta) -> impl Parser impl Parser> { // TODO: factor out literal parsing so we don't have to do this ugly `unreachable` stuff. - parse_literal(m).map(|e| match e.kind { - ExprKind::Literal(lit) => Pattern::Literal(lit), + parse_literal(m).map(|e| match e { + Expr::Literal(lit) => Pattern::Literal(lit), _ => unreachable!(), }) } @@ -843,10 +827,6 @@ fn ident() -> impl Parser> + Clone { }) } -fn expr(e: ExprKind) -> Expr { - Expr { kind: e, typ: None } -} - #[cfg(test)] mod tests { use super::*; diff --git a/drimc_rs/src/syntax.rs b/drimc_rs/src/syntax.rs index d834951..8bbdda7 100644 --- a/drimc_rs/src/syntax.rs +++ b/drimc_rs/src/syntax.rs @@ -2,8 +2,6 @@ use num_bigint::BigUint; -use crate::typeck; - /// A concrete syntax tree. This represents the full content of a Drim program, including all /// whitespace, comments, and tokens: the source code of the original program can be recovered /// completely using the syntax tree. @@ -67,10 +65,6 @@ pub enum ClassMember { /// The definition of the function. definition: Option, - - /// The type of the overall function; this is filled in by the typechecker, and is left - /// blank by the parser. - typ: Option, }, /// Declaration of a type that is a literal alias for another type. @@ -93,19 +87,9 @@ pub struct TypeConstructor { pub args: Vec, } -/// An expression. -#[derive(Clone, Debug)] -pub struct Expr { - /// The contents of the expression. - pub kind: ExprKind, - - /// An optional type signature, left as `None` by the parser and added by the type checker. - pub typ: Option, -} - /// The different kinds of expressions. #[derive(Clone, Debug)] -pub enum ExprKind { +pub enum Expr { /// Unary operators, e.g., `-5`. UnaryOp { /// The text of the operator.