From b886a0b2a11c7e7489ab1c6f90fce71c39c0676a Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Fri, 2 Jun 2023 19:58:11 -0600 Subject: [PATCH 1/8] Clean Up --- README.md | 10 ---------- docs/language_desc.md | 2 +- src/ir8/lowir.rs | 2 -- src/prc/README.md | 3 --- src/proto/README.md | 19 ------------------- src/proton/README.md | 3 --- 6 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 src/prc/README.md delete mode 100644 src/proto/README.md delete mode 100644 src/proton/README.md diff --git a/README.md b/README.md index 10eca93..be5dd8e 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,3 @@ A compiler/tooling project for the Proto programming language. This project is a The language description can be found [here](docs/language_desc.md).
- -# Tools - -This project will come with a few tools: - -1. [prc](src/prc/README.md), the proto compiler which can be called standalone. - -2. [proto](src/proto/README.md), the toolkit for the Proto programming language. - -3. [proton](src/proton/README.md), the virtual machine for proto. diff --git a/docs/language_desc.md b/docs/language_desc.md index e0b6ec8..7e192c3 100644 --- a/docs/language_desc.md +++ b/docs/language_desc.md @@ -1,6 +1,6 @@ # Proto Language Description (v0.0.1) -Proto is a typed programming language. The long term goal is to compile to native code through LLVM. To support the REPL, it will have a Virtual Machine written in Rust ([_proton_](../src/proton/README.md)). This VM could eventually power compile time expressions. +Proto is a typed programming language. The long term goal is to compile to native code through LLVM. To support the REPL, it will have a Virtual Machine written in Rust. This VM could eventually power compile time expressions. Instead of dwelling in the future, let us describe what the language will look like. This document will get updated as more language features get added in future versions. diff --git a/src/ir8/lowir.rs b/src/ir8/lowir.rs index 5652beb..4faecb0 100644 --- a/src/ir8/lowir.rs +++ b/src/ir8/lowir.rs @@ -7,8 +7,6 @@ use crate::frontend::{ types::Type, }; -// use super::visitir::{VisitIRError, VisitsLowIR}; - #[derive(Debug, Clone)] #[allow(dead_code)] pub struct KeyValueBindings { diff --git a/src/prc/README.md b/src/prc/README.md deleted file mode 100644 index 7c7cf1f..0000000 --- a/src/prc/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# prc - -This is the proto compiler. It is the standalone compiler and can be used to compile a proto source file (with `.pr` extension) to an executable. diff --git a/src/proto/README.md b/src/proto/README.md deleted file mode 100644 index 3993030..0000000 --- a/src/proto/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# proto - -The REPL for trying out ideas in a less permanent space. Much like python, php and other languages provide. - -As a project manager for proto. It will be able to: - -- [ ] create new proto projects. - -- [ ] create new proto projects in existing folders. - -- [ ] modify existing projects to run the code formatter or linter or static analysis without compilation. Will be fleshed out before work begins. - -- [ ] compile proto projects. - -- [ ] fetch proto [units](../../docs/tbd.md) from GitHub or else where for project use. - -> will work on document generation - -> will work on testing diff --git a/src/proton/README.md b/src/proton/README.md deleted file mode 100644 index 3c194e7..0000000 --- a/src/proton/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# proton - -The virtual machine for proto. From da11a09acd7e075a26e25d84b6b6434a313b4ac0 Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Fri, 2 Jun 2023 21:27:06 -0600 Subject: [PATCH 2/8] Added exporting file dependencies during lowering --- src/analysis/dependency.rs | 11 ++++++ src/analysis/mod.rs | 1 + src/ir8/lowir.rs | 80 +++++++++++++++++++++++--------------- src/main.rs | 1 + 4 files changed, 61 insertions(+), 32 deletions(-) create mode 100644 src/analysis/dependency.rs create mode 100644 src/analysis/mod.rs diff --git a/src/analysis/dependency.rs b/src/analysis/dependency.rs new file mode 100644 index 0000000..447fdff --- /dev/null +++ b/src/analysis/dependency.rs @@ -0,0 +1,11 @@ +use crate::ir8::lowir::LowIRModule; + +pub struct ExtractDependencies<'a> { + module: &'a LowIRModule, +} + +impl<'a> ExtractDependencies<'a> { + pub fn new(module: &'a LowIRModule) -> Self { + ExtractDependencies { module } + } +} diff --git a/src/analysis/mod.rs b/src/analysis/mod.rs new file mode 100644 index 0000000..c81cea6 --- /dev/null +++ b/src/analysis/mod.rs @@ -0,0 +1 @@ +pub mod dependency; diff --git a/src/ir8/lowir.rs b/src/ir8/lowir.rs index 4faecb0..cec4392 100644 --- a/src/ir8/lowir.rs +++ b/src/ir8/lowir.rs @@ -547,11 +547,11 @@ impl InsPool { } } - pub fn lowir(&mut self, epool: &mut ExprPool, ins: Instruction) -> InsRef { + pub fn lowir(&mut self, epool: &mut ExprPool, ins: Instruction) -> (InsRef, Vec) { match ins { Instruction::SingleLineComment { comment, src } => { let ins = LowIRIns::SingleLineComment { comment, src }; - self.add(ins) + (self.add(ins), vec![]) } Instruction::NamedStructDecl { name, fields, src } => { let name_ref = epool.lowir(name); @@ -561,7 +561,7 @@ impl InsPool { fields, src, }; - self.add(ins) + (self.add(ins), vec![]) } Instruction::ConstantDecl { const_name, @@ -578,23 +578,23 @@ impl InsPool { src_ref, is_public, }; - self.add(ins) + (self.add(ins), vec![]) } Instruction::VariableDecl(name, var_type, init_expr, span) => { let init_expr = init_expr.map(|e| epool.lowir(e)); let ins = LowIRIns::VariableDecl(name, var_type, init_expr, span); - self.add(ins) + (self.add(ins), vec![]) } Instruction::AssignmentIns(dest, target) => { let dest = epool.lowir(dest); let target = epool.lowir(target); let ins = LowIRIns::AssignmentIns(dest, target); - self.add(ins) + (self.add(ins), vec![]) } Instruction::ExpressionIns(expr, semi) => { let expr = epool.lowir(expr); let ins = LowIRIns::ExpressionIns(expr, semi); - self.add(ins) + (self.add(ins), vec![]) } Instruction::FunctionDef { name, @@ -605,7 +605,7 @@ impl InsPool { src, } => { let params = params.into_iter().map(|p| epool.lowir(p)).collect(); - let body = self.lowir(epool, *body); + let (body, dependencies) = self.lowir(epool, *body); let ins = LowIRIns::FunctionDef { name, params, @@ -614,12 +614,12 @@ impl InsPool { is_public, src, }; - self.add(ins) + (self.add(ins), dependencies) } Instruction::InfiniteLoop { src, body } => { - let body = self.lowir(epool, *body); + let (body, dependencies) = self.lowir(epool, *body); let ins = LowIRIns::InfiniteLoop { src, body }; - self.add(ins) + (self.add(ins), dependencies) } Instruction::WhileLoop { src, @@ -627,21 +627,29 @@ impl InsPool { body, } => { let condition = epool.lowir(condition); - let body = self.lowir(epool, *body); + let (body, dependencies) = self.lowir(epool, *body); let ins = LowIRIns::WhileLoop { src, condition, body, }; - self.add(ins) + (self.add(ins), dependencies) } Instruction::CodeBlock { src, instructions } => { - let instructions = instructions - .into_iter() - .map(|i| self.lowir(epool, i)) - .collect(); - let ins = LowIRIns::CodeBlock { src, instructions }; - self.add(ins) + let mut new_instructions = vec![]; + let mut dependencies = vec![]; + + for i in instructions { + let (ins, deps) = self.lowir(epool, i); + new_instructions.push(ins); + dependencies.extend(deps); + } + + let ins = LowIRIns::CodeBlock { + src, + instructions: new_instructions, + }; + (self.add(ins), dependencies) } Instruction::Module { name, @@ -650,31 +658,31 @@ impl InsPool { is_public, } => { let name = epool.lowir(name); - let body = self.lowir(epool, *body); + let (body, dependencies) = self.lowir(epool, *body); let ins = LowIRIns::Module { name, body, src, is_public, }; - self.add(ins) + (self.add(ins), dependencies) } Instruction::Return { src, value } => { let value = value.map(|v| epool.lowir(v)); let ins = LowIRIns::Return { src, value }; - self.add(ins) + (self.add(ins), vec![]) } Instruction::Break(src) => { let ins = LowIRIns::Break(src); - self.add(ins) + (self.add(ins), vec![]) } Instruction::Continue(src) => { let ins = LowIRIns::Continue(src); - self.add(ins) + (self.add(ins), vec![]) } Instruction::UseDependency { paths, src } => { let ins = LowIRIns::UseDependency { paths, src }; - self.add(ins) + (self.add(ins), vec![]) } Instruction::DirectiveInstruction { directive, @@ -682,30 +690,33 @@ impl InsPool { src, } => { let directive = epool.lowir(directive); - let block = block.map(|b| self.lowir(epool, *b)); + let (block, dependencies) = block.map(|b| self.lowir(epool, *b)).unwrap(); let ins = LowIRIns::DirectiveInstruction { directive, - block, + block: Some(block), src, }; - self.add(ins) + (self.add(ins), dependencies) } Instruction::ConditionalBranchIns { pairs, src } => { + let mut dependencies = vec![]; let pairs = pairs .into_iter() .map(|(cond, body)| { if let Some(cond) = cond { let cond = epool.lowir(cond); - let body = self.lowir(epool, *body); + let (body, c_dependencies) = self.lowir(epool, *body); + dependencies.extend(c_dependencies); (Some(cond), body) } else { - let body = self.lowir(epool, *body); + let (body, c_dependencies) = self.lowir(epool, *body); + dependencies.extend(c_dependencies); (None, body) } }) .collect(); let ins = LowIRIns::ConditionalBranchIns { pairs, src }; - self.add(ins) + (self.add(ins), dependencies) } } } @@ -720,6 +731,7 @@ pub struct LowIRModule { pub ins_pool: InsPool, pub expr_pool: ExprPool, pub top_level: Vec, + pub dependencies: Vec, } #[allow(dead_code)] @@ -729,13 +741,17 @@ impl LowIRModule { ins_pool: InsPool::new(), expr_pool: ExprPool::new(), top_level: Vec::new(), + dependencies: Vec::new(), } } pub fn lowir(&mut self, cm: CompilationModule) { + let mut module_dependencies = vec![]; for ins in cm.instructions { - let id = self.ins_pool.lowir(&mut self.expr_pool, ins); + let (id, dependencies) = self.ins_pool.lowir(&mut self.expr_pool, ins); + module_dependencies.extend(dependencies); self.top_level.push(id); } + self.dependencies = module_dependencies; } } diff --git a/src/main.rs b/src/main.rs index 8eb364a..ce0673b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ use frontend::{ use ir8::{lowir::LowIRModule, tomato::Tomato}; use serde::Deserialize; +mod analysis; mod frontend; mod ir8; mod pastel; From f8e9ab9c38ea31794685f40787cd7f13e9b14e8e Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Fri, 2 Jun 2023 22:49:15 -0600 Subject: [PATCH 3/8] Added function to extract dependencies from a LowIRModule --- src/analysis/analyser.rs | 1 + src/analysis/dependency.rs | 19 +++++---- src/analysis/mod.rs | 1 + src/ir8/lowir.rs | 80 +++++++++++++++----------------------- 4 files changed, 46 insertions(+), 55 deletions(-) create mode 100644 src/analysis/analyser.rs diff --git a/src/analysis/analyser.rs b/src/analysis/analyser.rs new file mode 100644 index 0000000..e429d24 --- /dev/null +++ b/src/analysis/analyser.rs @@ -0,0 +1 @@ +pub struct Analyser {} diff --git a/src/analysis/dependency.rs b/src/analysis/dependency.rs index 447fdff..f178099 100644 --- a/src/analysis/dependency.rs +++ b/src/analysis/dependency.rs @@ -1,11 +1,16 @@ -use crate::ir8::lowir::LowIRModule; +use crate::ir8::lowir::{LowIRIns, LowIRModule}; -pub struct ExtractDependencies<'a> { - module: &'a LowIRModule, -} +pub fn extract(module: &LowIRModule) -> Vec { + let mut dependencies = vec![]; -impl<'a> ExtractDependencies<'a> { - pub fn new(module: &'a LowIRModule) -> Self { - ExtractDependencies { module } + for ins in &module.ins_pool.pool { + if let LowIRIns::UseDependency { paths: _, src: _ } = ins { + dependencies.push(ins.clone()); + } } + dependencies +} + +pub fn resolve_use_to_path(use_ins: &LowIRIns) -> String { + todo!("resolve_use_to_path") } diff --git a/src/analysis/mod.rs b/src/analysis/mod.rs index c81cea6..090ad65 100644 --- a/src/analysis/mod.rs +++ b/src/analysis/mod.rs @@ -1 +1,2 @@ +pub mod analyser; pub mod dependency; diff --git a/src/ir8/lowir.rs b/src/ir8/lowir.rs index cec4392..4faecb0 100644 --- a/src/ir8/lowir.rs +++ b/src/ir8/lowir.rs @@ -547,11 +547,11 @@ impl InsPool { } } - pub fn lowir(&mut self, epool: &mut ExprPool, ins: Instruction) -> (InsRef, Vec) { + pub fn lowir(&mut self, epool: &mut ExprPool, ins: Instruction) -> InsRef { match ins { Instruction::SingleLineComment { comment, src } => { let ins = LowIRIns::SingleLineComment { comment, src }; - (self.add(ins), vec![]) + self.add(ins) } Instruction::NamedStructDecl { name, fields, src } => { let name_ref = epool.lowir(name); @@ -561,7 +561,7 @@ impl InsPool { fields, src, }; - (self.add(ins), vec![]) + self.add(ins) } Instruction::ConstantDecl { const_name, @@ -578,23 +578,23 @@ impl InsPool { src_ref, is_public, }; - (self.add(ins), vec![]) + self.add(ins) } Instruction::VariableDecl(name, var_type, init_expr, span) => { let init_expr = init_expr.map(|e| epool.lowir(e)); let ins = LowIRIns::VariableDecl(name, var_type, init_expr, span); - (self.add(ins), vec![]) + self.add(ins) } Instruction::AssignmentIns(dest, target) => { let dest = epool.lowir(dest); let target = epool.lowir(target); let ins = LowIRIns::AssignmentIns(dest, target); - (self.add(ins), vec![]) + self.add(ins) } Instruction::ExpressionIns(expr, semi) => { let expr = epool.lowir(expr); let ins = LowIRIns::ExpressionIns(expr, semi); - (self.add(ins), vec![]) + self.add(ins) } Instruction::FunctionDef { name, @@ -605,7 +605,7 @@ impl InsPool { src, } => { let params = params.into_iter().map(|p| epool.lowir(p)).collect(); - let (body, dependencies) = self.lowir(epool, *body); + let body = self.lowir(epool, *body); let ins = LowIRIns::FunctionDef { name, params, @@ -614,12 +614,12 @@ impl InsPool { is_public, src, }; - (self.add(ins), dependencies) + self.add(ins) } Instruction::InfiniteLoop { src, body } => { - let (body, dependencies) = self.lowir(epool, *body); + let body = self.lowir(epool, *body); let ins = LowIRIns::InfiniteLoop { src, body }; - (self.add(ins), dependencies) + self.add(ins) } Instruction::WhileLoop { src, @@ -627,29 +627,21 @@ impl InsPool { body, } => { let condition = epool.lowir(condition); - let (body, dependencies) = self.lowir(epool, *body); + let body = self.lowir(epool, *body); let ins = LowIRIns::WhileLoop { src, condition, body, }; - (self.add(ins), dependencies) + self.add(ins) } Instruction::CodeBlock { src, instructions } => { - let mut new_instructions = vec![]; - let mut dependencies = vec![]; - - for i in instructions { - let (ins, deps) = self.lowir(epool, i); - new_instructions.push(ins); - dependencies.extend(deps); - } - - let ins = LowIRIns::CodeBlock { - src, - instructions: new_instructions, - }; - (self.add(ins), dependencies) + let instructions = instructions + .into_iter() + .map(|i| self.lowir(epool, i)) + .collect(); + let ins = LowIRIns::CodeBlock { src, instructions }; + self.add(ins) } Instruction::Module { name, @@ -658,31 +650,31 @@ impl InsPool { is_public, } => { let name = epool.lowir(name); - let (body, dependencies) = self.lowir(epool, *body); + let body = self.lowir(epool, *body); let ins = LowIRIns::Module { name, body, src, is_public, }; - (self.add(ins), dependencies) + self.add(ins) } Instruction::Return { src, value } => { let value = value.map(|v| epool.lowir(v)); let ins = LowIRIns::Return { src, value }; - (self.add(ins), vec![]) + self.add(ins) } Instruction::Break(src) => { let ins = LowIRIns::Break(src); - (self.add(ins), vec![]) + self.add(ins) } Instruction::Continue(src) => { let ins = LowIRIns::Continue(src); - (self.add(ins), vec![]) + self.add(ins) } Instruction::UseDependency { paths, src } => { let ins = LowIRIns::UseDependency { paths, src }; - (self.add(ins), vec![]) + self.add(ins) } Instruction::DirectiveInstruction { directive, @@ -690,33 +682,30 @@ impl InsPool { src, } => { let directive = epool.lowir(directive); - let (block, dependencies) = block.map(|b| self.lowir(epool, *b)).unwrap(); + let block = block.map(|b| self.lowir(epool, *b)); let ins = LowIRIns::DirectiveInstruction { directive, - block: Some(block), + block, src, }; - (self.add(ins), dependencies) + self.add(ins) } Instruction::ConditionalBranchIns { pairs, src } => { - let mut dependencies = vec![]; let pairs = pairs .into_iter() .map(|(cond, body)| { if let Some(cond) = cond { let cond = epool.lowir(cond); - let (body, c_dependencies) = self.lowir(epool, *body); - dependencies.extend(c_dependencies); + let body = self.lowir(epool, *body); (Some(cond), body) } else { - let (body, c_dependencies) = self.lowir(epool, *body); - dependencies.extend(c_dependencies); + let body = self.lowir(epool, *body); (None, body) } }) .collect(); let ins = LowIRIns::ConditionalBranchIns { pairs, src }; - (self.add(ins), dependencies) + self.add(ins) } } } @@ -731,7 +720,6 @@ pub struct LowIRModule { pub ins_pool: InsPool, pub expr_pool: ExprPool, pub top_level: Vec, - pub dependencies: Vec, } #[allow(dead_code)] @@ -741,17 +729,13 @@ impl LowIRModule { ins_pool: InsPool::new(), expr_pool: ExprPool::new(), top_level: Vec::new(), - dependencies: Vec::new(), } } pub fn lowir(&mut self, cm: CompilationModule) { - let mut module_dependencies = vec![]; for ins in cm.instructions { - let (id, dependencies) = self.ins_pool.lowir(&mut self.expr_pool, ins); - module_dependencies.extend(dependencies); + let id = self.ins_pool.lowir(&mut self.expr_pool, ins); self.top_level.push(id); } - self.dependencies = module_dependencies; } } From 82368a127f7f351343a56454bb11a44ff87aa3e6 Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Sat, 1 Jul 2023 21:44:47 -0600 Subject: [PATCH 4/8] Cleaned up Module and Passes code to be simpler --- src/analysis/analyser.rs | 1 - src/analysis/dependency.rs | 16 -- src/analysis/mod.rs | 2 - src/ir8/mod.rs | 4 - src/ir8/tomato.rs | 36 --- src/ir8/visitir.rs | 30 -- src/main.rs | 25 +- src/{ir8/lowir.rs => pir/ir.rs} | 193 +++++++------ src/pir/mod.rs | 1 + src/tools/mod.rs | 2 + src/{ir8/codeviewer.rs => tools/pcodeview.rs} | 272 +++++++++--------- src/tools/pfmt.rs | 1 + 12 files changed, 247 insertions(+), 336 deletions(-) delete mode 100644 src/analysis/analyser.rs delete mode 100644 src/analysis/dependency.rs delete mode 100644 src/analysis/mod.rs delete mode 100644 src/ir8/mod.rs delete mode 100644 src/ir8/tomato.rs delete mode 100644 src/ir8/visitir.rs rename src/{ir8/lowir.rs => pir/ir.rs} (78%) create mode 100644 src/pir/mod.rs create mode 100644 src/tools/mod.rs rename src/{ir8/codeviewer.rs => tools/pcodeview.rs} (67%) create mode 100644 src/tools/pfmt.rs diff --git a/src/analysis/analyser.rs b/src/analysis/analyser.rs deleted file mode 100644 index e429d24..0000000 --- a/src/analysis/analyser.rs +++ /dev/null @@ -1 +0,0 @@ -pub struct Analyser {} diff --git a/src/analysis/dependency.rs b/src/analysis/dependency.rs deleted file mode 100644 index f178099..0000000 --- a/src/analysis/dependency.rs +++ /dev/null @@ -1,16 +0,0 @@ -use crate::ir8::lowir::{LowIRIns, LowIRModule}; - -pub fn extract(module: &LowIRModule) -> Vec { - let mut dependencies = vec![]; - - for ins in &module.ins_pool.pool { - if let LowIRIns::UseDependency { paths: _, src: _ } = ins { - dependencies.push(ins.clone()); - } - } - dependencies -} - -pub fn resolve_use_to_path(use_ins: &LowIRIns) -> String { - todo!("resolve_use_to_path") -} diff --git a/src/analysis/mod.rs b/src/analysis/mod.rs deleted file mode 100644 index 090ad65..0000000 --- a/src/analysis/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod analyser; -pub mod dependency; diff --git a/src/ir8/mod.rs b/src/ir8/mod.rs deleted file mode 100644 index 75c4997..0000000 --- a/src/ir8/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod codeviewer; -pub mod lowir; -pub mod tomato; -pub mod visitir; diff --git a/src/ir8/tomato.rs b/src/ir8/tomato.rs deleted file mode 100644 index a8b0765..0000000 --- a/src/ir8/tomato.rs +++ /dev/null @@ -1,36 +0,0 @@ -use super::codeviewer::CodeViewer; -#[allow(unused_imports)] -use super::lowir::{ExprPool, InsPool, InsRef, KeyValueBindings, LowIRModule}; -#[allow(unused_imports)] -use super::visitir::apply_to_module; -use std::fs; -use std::io::Error; - -#[allow(dead_code)] -pub struct Tomato { - pub filepath: String, - viewer: CodeViewer, -} - -#[allow(dead_code)] -impl Tomato { - pub fn new(filename: String, ins_pool: InsPool, expr_pool: ExprPool) -> Tomato { - Tomato { - filepath: filename, - viewer: CodeViewer::new(ins_pool, expr_pool), - } - } - - pub fn format(&mut self, ir_module: &LowIRModule) -> Result<(), Error> { - let res = apply_to_module(&mut self.viewer, &ir_module); - let res = self.viewer.unwrap(res); - - let contents = res.join("\n"); - self.update_file_contents(contents) - } - - fn update_file_contents(&self, contents: String) -> Result<(), Error> { - // open file - fs::write(&self.filepath, contents) - } -} diff --git a/src/ir8/visitir.rs b/src/ir8/visitir.rs deleted file mode 100644 index 6335f01..0000000 --- a/src/ir8/visitir.rs +++ /dev/null @@ -1,30 +0,0 @@ -use super::lowir::{ExprRef, InsRef, KeyValueBindings, LowIRModule}; - -#[allow(dead_code)] -pub enum VisitIRError {} - -#[allow(dead_code)] -pub trait VisitsLowIR { - fn visit_ins(&mut self, ins: &InsRef) -> Result; - fn visit_expr(&mut self, expr: &ExprRef) -> Result; - fn visit_pairs(&mut self, kv: &KeyValueBindings) -> Result; -} - -pub fn apply_visitor>( - visitor: &mut V, - ins: &InsRef, -) -> Result { - visitor.visit_ins(ins) -} - -pub fn apply_to_module>( - visitor: &mut V, - module: &LowIRModule, -) -> Vec> { - let mut result = vec![]; - for ins_ref in module.top_level.iter() { - let res = apply_visitor(visitor, &ins_ref); - result.push(res); - } - result -} diff --git a/src/main.rs b/src/main.rs index ce0673b..42a415b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,13 +7,14 @@ use frontend::{ source::{SourceFile, SourceReporter}, token::Token, }; -use ir8::{lowir::LowIRModule, tomato::Tomato}; +use pir::ir::{PIRModule, PIRModulePass}; use serde::Deserialize; +use tools::pcodeview::PCodeView; -mod analysis; mod frontend; -mod ir8; mod pastel; +mod pir; +mod tools; const USAGE: &str = " Usage: proto (-h | -l | -p) -f @@ -95,17 +96,11 @@ fn main() { // } let module = parser.compilation_module; - let mut ir_mod = LowIRModule::new(); - ir_mod.lowir(module); - let mut tomato = Tomato::new( - path.clone(), - ir_mod.ins_pool.clone(), - ir_mod.expr_pool.clone(), - ); - - match tomato.format(&ir_mod) { - Ok(()) => reporter.show_info(format!("formatted {}", path)), - Err(e) => reporter.show_info(format!("failed to format {}: {}", path, e)), - } + let mut ir_mod = PIRModule::new(module); + + let mut code_view = PCodeView::new(&mut ir_mod); + let res = code_view.process_module().unwrap(); + + println!("{}", res); } } diff --git a/src/ir8/lowir.rs b/src/pir/ir.rs similarity index 78% rename from src/ir8/lowir.rs rename to src/pir/ir.rs index 4faecb0..b1030c4 100644 --- a/src/ir8/lowir.rs +++ b/src/pir/ir.rs @@ -40,7 +40,7 @@ impl KeyValueBindings { #[derive(Debug, Clone)] #[allow(dead_code)] -pub enum LowIRExpr { +pub enum PIRExpr { Id(Token, Option), Number(Token, Option), StringLiteral(Token, Option), @@ -77,37 +77,37 @@ pub enum LowIRExpr { } #[allow(dead_code)] -impl LowIRExpr { +impl PIRExpr { pub fn type_info(&self) -> Option { match &self { - LowIRExpr::Id(_, t) => t.clone(), - LowIRExpr::Number(_, t) => t.clone(), - LowIRExpr::Binary(_, _, _, t) => t.clone(), - LowIRExpr::Boolean(_, t) => t.clone(), - LowIRExpr::Unary(_, _, t) => t.clone(), - LowIRExpr::Comparison(_, _, _, t) => t.clone(), - LowIRExpr::FnCall { + PIRExpr::Id(_, t) => t.clone(), + PIRExpr::Number(_, t) => t.clone(), + PIRExpr::Binary(_, _, _, t) => t.clone(), + PIRExpr::Boolean(_, t) => t.clone(), + PIRExpr::Unary(_, _, t) => t.clone(), + PIRExpr::Comparison(_, _, _, t) => t.clone(), + PIRExpr::FnCall { func: _, args: _, span: _, fn_type, } => fn_type.clone(), - LowIRExpr::Grouped(_, t, _) => t.clone(), - LowIRExpr::ScopeInto { + PIRExpr::Grouped(_, t, _) => t.clone(), + PIRExpr::ScopeInto { module: _, target: _, src: _, resolved_type, } => resolved_type.clone(), - LowIRExpr::DirectiveExpr { + PIRExpr::DirectiveExpr { directive: _, expr: _, resolved_type, src: _, } => resolved_type.clone(), - LowIRExpr::StringLiteral(_, t) => t.clone(), - LowIRExpr::CharacterLiteral(_, t) => t.clone(), - LowIRExpr::NamedStructInit { + PIRExpr::StringLiteral(_, t) => t.clone(), + PIRExpr::CharacterLiteral(_, t) => t.clone(), + PIRExpr::NamedStructInit { name: _, fields: _, src: _, @@ -131,7 +131,7 @@ impl ExprRef { #[derive(Debug, Clone)] pub struct ExprPool { - pub pool: Vec, + pub pool: Vec, } #[allow(dead_code)] @@ -140,7 +140,7 @@ impl ExprPool { ExprPool { pool: Vec::new() } } - fn add(&mut self, expr: LowIRExpr) -> ExprRef { + fn add(&mut self, expr: PIRExpr) -> ExprRef { self.pool.push(expr); ExprRef { loc: self.pool.len() - 1, @@ -149,28 +149,28 @@ impl ExprPool { pub fn lowir(&mut self, expr: Expr) -> ExprRef { match expr { - Expr::Id(id, t) => self.add(LowIRExpr::Id(id, t)), - Expr::Number(n, t) => self.add(LowIRExpr::Number(n, t)), - Expr::StringLiteral(s, t) => self.add(LowIRExpr::StringLiteral(s, t)), - Expr::CharacterLiteral(c, t) => self.add(LowIRExpr::CharacterLiteral(c, t)), + Expr::Id(id, t) => self.add(PIRExpr::Id(id, t)), + Expr::Number(n, t) => self.add(PIRExpr::Number(n, t)), + Expr::StringLiteral(s, t) => self.add(PIRExpr::StringLiteral(s, t)), + Expr::CharacterLiteral(c, t) => self.add(PIRExpr::CharacterLiteral(c, t)), Expr::Binary(op, lhs, rhs, t) => { let lhs = self.lowir(*lhs); let rhs = self.lowir(*rhs); - self.add(LowIRExpr::Binary(op, lhs, rhs, t)) + self.add(PIRExpr::Binary(op, lhs, rhs, t)) } Expr::Comparison(op, lhs, rhs, t) => { let lhs = self.lowir(*lhs); let rhs = self.lowir(*rhs); - self.add(LowIRExpr::Comparison(op, lhs, rhs, t)) + self.add(PIRExpr::Comparison(op, lhs, rhs, t)) } - Expr::Boolean(b, t) => self.add(LowIRExpr::Boolean(b, t)), + Expr::Boolean(b, t) => self.add(PIRExpr::Boolean(b, t)), Expr::Unary(op, expr, t) => { let expr = self.lowir(*expr); - self.add(LowIRExpr::Unary(op, expr, t)) + self.add(PIRExpr::Unary(op, expr, t)) } Expr::Grouped(expr, t, src) => { let expr = self.lowir(*expr); - self.add(LowIRExpr::Grouped(expr, t, src)) + self.add(PIRExpr::Grouped(expr, t, src)) } Expr::FnCall { func, @@ -183,7 +183,7 @@ impl ExprPool { .into_iter() .map(|arg| self.lowir(arg)) .collect::>(); - self.add(LowIRExpr::FnCall { + self.add(PIRExpr::FnCall { func, args, span, @@ -198,7 +198,7 @@ impl ExprPool { } => { let module = self.lowir(*module); let target = self.lowir(*target); - self.add(LowIRExpr::ScopeInto { + self.add(PIRExpr::ScopeInto { module, target, src, @@ -213,7 +213,7 @@ impl ExprPool { } => { let directive = self.lowir(*directive); let expr = expr.map(|expr| self.lowir(*expr)); - self.add(LowIRExpr::DirectiveExpr { + self.add(PIRExpr::DirectiveExpr { directive, expr, resolved_type, @@ -227,8 +227,8 @@ impl ExprPool { resolved_type, } => { let name = self.lowir(*name); - let fields = self.lowir_bindings(fields); - self.add(LowIRExpr::NamedStructInit { + let fields = self.pir_bindings(fields); + self.add(PIRExpr::NamedStructInit { name, fields, src, @@ -238,7 +238,7 @@ impl ExprPool { } } - fn lowir_bindings(&mut self, bindings: TreeKVBindings) -> KeyValueBindings { + fn pir_bindings(&mut self, bindings: TreeKVBindings) -> KeyValueBindings { let nbindings = bindings .pairs .iter() @@ -258,14 +258,14 @@ impl ExprPool { } } - pub fn get(&self, expr_ref: &ExprRef) -> LowIRExpr { + pub fn get(&self, expr_ref: &ExprRef) -> PIRExpr { self.pool[expr_ref.loc].clone() } } #[derive(Debug, Clone)] #[allow(dead_code)] -pub enum LowIRIns { +pub enum PIRIns { SingleLineComment { comment: String, src: SourceRef, @@ -333,18 +333,18 @@ pub enum LowIRIns { }, } -impl LowIRIns { +impl PIRIns { pub fn as_str(&self) -> String { match self { - LowIRIns::SingleLineComment { comment, src: _ } => comment.clone(), - LowIRIns::NamedStructDecl { + PIRIns::SingleLineComment { comment, src: _ } => comment.clone(), + PIRIns::NamedStructDecl { name, fields, src: _, } => { format!(":{} {}", name.as_str(), fields.as_str()) } - LowIRIns::ConstantDecl { + PIRIns::ConstantDecl { const_name, const_type: t, init_expr, @@ -363,7 +363,7 @@ impl LowIRIns { format!("let {} = {};", const_name.as_str(), init_expr.as_str()) } }, - LowIRIns::VariableDecl(name, t, init, _) => match (t, init) { + PIRIns::VariableDecl(name, t, init, _) => match (t, init) { (None, None) => format!("mut {};", name.as_str()), (None, Some(init)) => format!("mut {} = {};", name.as_str(), init.as_str()), (Some(c_type), None) => { @@ -376,11 +376,11 @@ impl LowIRIns { init.as_str() ), }, - LowIRIns::AssignmentIns(target, value) => { + PIRIns::AssignmentIns(target, value) => { format!("{} = {};", target.as_str(), value.as_str()) } - LowIRIns::ExpressionIns(expr, _) => format!("{};", expr.as_str()), - LowIRIns::FunctionDef { + PIRIns::ExpressionIns(expr, _) => format!("{};", expr.as_str()), + PIRIns::FunctionDef { name, params, return_type, @@ -408,7 +408,7 @@ impl LowIRIns { str_rep } } - LowIRIns::CodeBlock { + PIRIns::CodeBlock { src: _, instructions, } => { @@ -423,7 +423,7 @@ impl LowIRIns { } ins_str + " }" } - LowIRIns::Module { + PIRIns::Module { name, body, src: _, @@ -436,23 +436,23 @@ impl LowIRIns { "pub ".to_string() + &mod_str } } - LowIRIns::Return { src: _, value } => match value { + PIRIns::Return { src: _, value } => match value { Some(v) => format!("return {};", v.as_str()), None => "return;".to_string(), }, - LowIRIns::InfiniteLoop { src: _, body } => { + PIRIns::InfiniteLoop { src: _, body } => { format!("loop {}", body.as_str()) } - LowIRIns::WhileLoop { + PIRIns::WhileLoop { src: _, condition, body, } => { format!("while {} {}", condition.as_str(), body.as_str()) } - LowIRIns::Break(_) => "break;".to_string(), - LowIRIns::Continue(_) => "continue;".to_string(), - LowIRIns::UseDependency { paths, src: _ } => { + PIRIns::Break(_) => "break;".to_string(), + PIRIns::Continue(_) => "continue;".to_string(), + PIRIns::UseDependency { paths, src: _ } => { let mut path_str = String::new(); for (i, path) in paths.iter().enumerate() { for (j, part) in path.actions.iter().enumerate() { @@ -467,7 +467,7 @@ impl LowIRIns { } format!("use {};", path_str) } - LowIRIns::DirectiveInstruction { + PIRIns::DirectiveInstruction { directive, block, src: _, @@ -478,7 +478,7 @@ impl LowIRIns { format!("@{}", directive.as_str()) } } - LowIRIns::ConditionalBranchIns { pairs, src: _ } => { + PIRIns::ConditionalBranchIns { pairs, src: _ } => { let mut str_rep = String::new(); for i in 0..pairs.len() { let (cond, ins) = &pairs[i]; @@ -522,7 +522,7 @@ impl InsRef { #[derive(Debug, Clone)] #[allow(dead_code)] pub struct InsPool { - pub pool: Vec, + pub pool: Vec, } #[allow(dead_code)] @@ -531,7 +531,7 @@ impl InsPool { InsPool { pool: Vec::new() } } - fn exists(&self, ins: &LowIRIns) -> Option { + fn exists(&self, ins: &PIRIns) -> Option { for (i, ins2) in self.pool.iter().enumerate() { if ins.as_str() == ins2.as_str() { return Some(InsRef { loc: i }); @@ -540,23 +540,23 @@ impl InsPool { None } - fn add(&mut self, ins: LowIRIns) -> InsRef { + fn add(&mut self, ins: PIRIns) -> InsRef { self.pool.push(ins); InsRef { loc: self.pool.len() - 1, } } - pub fn lowir(&mut self, epool: &mut ExprPool, ins: Instruction) -> InsRef { + pub fn to_pir(&mut self, epool: &mut ExprPool, ins: Instruction) -> InsRef { match ins { Instruction::SingleLineComment { comment, src } => { - let ins = LowIRIns::SingleLineComment { comment, src }; + let ins = PIRIns::SingleLineComment { comment, src }; self.add(ins) } Instruction::NamedStructDecl { name, fields, src } => { let name_ref = epool.lowir(name); - let fields = epool.lowir_bindings(fields); - let ins = LowIRIns::NamedStructDecl { + let fields = epool.pir_bindings(fields); + let ins = PIRIns::NamedStructDecl { name: name_ref, fields, src, @@ -571,7 +571,7 @@ impl InsPool { is_public, } => { let init_expr = epool.lowir(init_expr); - let ins = LowIRIns::ConstantDecl { + let ins = PIRIns::ConstantDecl { const_name, const_type, init_expr, @@ -582,18 +582,18 @@ impl InsPool { } Instruction::VariableDecl(name, var_type, init_expr, span) => { let init_expr = init_expr.map(|e| epool.lowir(e)); - let ins = LowIRIns::VariableDecl(name, var_type, init_expr, span); + let ins = PIRIns::VariableDecl(name, var_type, init_expr, span); self.add(ins) } Instruction::AssignmentIns(dest, target) => { let dest = epool.lowir(dest); let target = epool.lowir(target); - let ins = LowIRIns::AssignmentIns(dest, target); + let ins = PIRIns::AssignmentIns(dest, target); self.add(ins) } Instruction::ExpressionIns(expr, semi) => { let expr = epool.lowir(expr); - let ins = LowIRIns::ExpressionIns(expr, semi); + let ins = PIRIns::ExpressionIns(expr, semi); self.add(ins) } Instruction::FunctionDef { @@ -605,8 +605,8 @@ impl InsPool { src, } => { let params = params.into_iter().map(|p| epool.lowir(p)).collect(); - let body = self.lowir(epool, *body); - let ins = LowIRIns::FunctionDef { + let body = self.to_pir(epool, *body); + let ins = PIRIns::FunctionDef { name, params, return_type, @@ -617,8 +617,8 @@ impl InsPool { self.add(ins) } Instruction::InfiniteLoop { src, body } => { - let body = self.lowir(epool, *body); - let ins = LowIRIns::InfiniteLoop { src, body }; + let body = self.to_pir(epool, *body); + let ins = PIRIns::InfiniteLoop { src, body }; self.add(ins) } Instruction::WhileLoop { @@ -627,8 +627,8 @@ impl InsPool { body, } => { let condition = epool.lowir(condition); - let body = self.lowir(epool, *body); - let ins = LowIRIns::WhileLoop { + let body = self.to_pir(epool, *body); + let ins = PIRIns::WhileLoop { src, condition, body, @@ -638,9 +638,9 @@ impl InsPool { Instruction::CodeBlock { src, instructions } => { let instructions = instructions .into_iter() - .map(|i| self.lowir(epool, i)) + .map(|i| self.to_pir(epool, i)) .collect(); - let ins = LowIRIns::CodeBlock { src, instructions }; + let ins = PIRIns::CodeBlock { src, instructions }; self.add(ins) } Instruction::Module { @@ -650,8 +650,8 @@ impl InsPool { is_public, } => { let name = epool.lowir(name); - let body = self.lowir(epool, *body); - let ins = LowIRIns::Module { + let body = self.to_pir(epool, *body); + let ins = PIRIns::Module { name, body, src, @@ -661,19 +661,19 @@ impl InsPool { } Instruction::Return { src, value } => { let value = value.map(|v| epool.lowir(v)); - let ins = LowIRIns::Return { src, value }; + let ins = PIRIns::Return { src, value }; self.add(ins) } Instruction::Break(src) => { - let ins = LowIRIns::Break(src); + let ins = PIRIns::Break(src); self.add(ins) } Instruction::Continue(src) => { - let ins = LowIRIns::Continue(src); + let ins = PIRIns::Continue(src); self.add(ins) } Instruction::UseDependency { paths, src } => { - let ins = LowIRIns::UseDependency { paths, src }; + let ins = PIRIns::UseDependency { paths, src }; self.add(ins) } Instruction::DirectiveInstruction { @@ -682,8 +682,8 @@ impl InsPool { src, } => { let directive = epool.lowir(directive); - let block = block.map(|b| self.lowir(epool, *b)); - let ins = LowIRIns::DirectiveInstruction { + let block = block.map(|b| self.to_pir(epool, *b)); + let ins = PIRIns::DirectiveInstruction { directive, block, src, @@ -696,46 +696,53 @@ impl InsPool { .map(|(cond, body)| { if let Some(cond) = cond { let cond = epool.lowir(cond); - let body = self.lowir(epool, *body); + let body = self.to_pir(epool, *body); (Some(cond), body) } else { - let body = self.lowir(epool, *body); + let body = self.to_pir(epool, *body); (None, body) } }) .collect(); - let ins = LowIRIns::ConditionalBranchIns { pairs, src }; + let ins = PIRIns::ConditionalBranchIns { pairs, src }; self.add(ins) } } } - pub fn get(&self, ins_ref: &InsRef) -> LowIRIns { + pub fn get(&self, ins_ref: &InsRef) -> PIRIns { self.pool[ins_ref.loc].clone() } } #[derive(Debug, Clone)] -pub struct LowIRModule { +pub struct PIRModule { pub ins_pool: InsPool, pub expr_pool: ExprPool, pub top_level: Vec, } #[allow(dead_code)] -impl LowIRModule { - pub fn new() -> LowIRModule { - LowIRModule { +impl PIRModule { + pub fn new(cm: CompilationModule) -> PIRModule { + let mut pirmod = PIRModule { ins_pool: InsPool::new(), expr_pool: ExprPool::new(), top_level: Vec::new(), - } - } - - pub fn lowir(&mut self, cm: CompilationModule) { + }; for ins in cm.instructions { - let id = self.ins_pool.lowir(&mut self.expr_pool, ins); - self.top_level.push(id); + let id = pirmod.ins_pool.to_pir(&mut pirmod.expr_pool, ins); + pirmod.top_level.push(id); } + pirmod } } + +#[allow(dead_code)] +pub trait PIRModulePass<'a, A, B, C, M, T> { + fn process_ins(&mut self, ins: &InsRef) -> Result; + fn process_expr(&mut self, expr: &ExprRef) -> Result; + fn process_pairs(&mut self, kv: &KeyValueBindings) -> Result; + fn process_module(&mut self) -> Result; + fn new(module: &'a mut PIRModule) -> Self; +} diff --git a/src/pir/mod.rs b/src/pir/mod.rs new file mode 100644 index 0000000..19d2d13 --- /dev/null +++ b/src/pir/mod.rs @@ -0,0 +1 @@ +pub mod ir; diff --git a/src/tools/mod.rs b/src/tools/mod.rs new file mode 100644 index 0000000..5ae395a --- /dev/null +++ b/src/tools/mod.rs @@ -0,0 +1,2 @@ +pub mod pcodeview; +pub mod pfmt; diff --git a/src/ir8/codeviewer.rs b/src/tools/pcodeview.rs similarity index 67% rename from src/ir8/codeviewer.rs rename to src/tools/pcodeview.rs index 9773148..a0af5c3 100644 --- a/src/ir8/codeviewer.rs +++ b/src/tools/pcodeview.rs @@ -1,5 +1,6 @@ -use super::lowir::{ExprPool, ExprRef, InsPool, InsRef, KeyValueBindings, LowIRExpr, LowIRIns}; -use super::visitir::{VisitIRError, VisitsLowIR}; +use crate::pir::ir::{ + ExprRef, InsRef, KeyValueBindings, PIRExpr, PIRIns, PIRModule, PIRModulePass, +}; #[derive(Clone)] #[allow(dead_code)] @@ -9,35 +10,14 @@ enum CodeBlockType { } #[allow(dead_code)] -pub struct CodeViewer { - ins_pool: InsPool, - expr_pool: ExprPool, +pub struct PCodeView<'a> { + module: Option<&'a PIRModule>, left_padding: u16, block_type: CodeBlockType, } #[allow(dead_code)] -impl CodeViewer { - pub fn new(ins_pool: InsPool, expr_pool: ExprPool) -> Self { - Self { - left_padding: 0, - ins_pool, - expr_pool, - block_type: CodeBlockType::Regular, - } - } - - pub fn unwrap(&mut self, res: Vec>) -> Vec { - let mut result = vec![]; - for r in res { - match r { - Ok(s) => result.push(s.clone()), - Err(_) => {} - } - } - result - } - +impl<'a> PCodeView<'a> { pub fn increase_padding(&mut self) { self.left_padding += 2; } @@ -50,74 +30,35 @@ impl CodeViewer { let padding = " ".repeat(self.left_padding as usize); format!("{}{}", padding, text) } - - pub fn get_ins_pool(self) -> InsPool { - self.ins_pool - } - - pub fn get_expr_pool(self) -> ExprPool { - self.expr_pool - } } -impl VisitsLowIR for CodeViewer { - fn visit_pairs(&mut self, kv: &KeyValueBindings) -> Result { - let mut view = String::from("{"); - let kv_pair_len = kv.pairs.len(); - if kv_pair_len > 0 { - self.increase_padding(); - } else { - view.push_str(" }"); - return Ok(view); - } - - let mut count = 0; - for (key, value) in &kv.pairs { - let key = self.visit_expr(&key)?; - if let Some(value) = value { - let value = self.visit_expr(&value)?; - view.push('\n'); - view.push_str(&self.pad_text(format!("{} = {}", key, value))); - } else { - view.push('\n'); - view.push_str(&self.pad_text(format!("{}", key))); - } - count += 1; - if count < kv_pair_len { - view.push(','); - } - } - self.decrease_padding(); - view.push('\n'); - view.push_str(&self.pad_text("}".to_string())); - Ok(view) - } - - fn visit_ins(&mut self, ins: &InsRef) -> Result { +impl<'a> PIRModulePass<'a, String, String, String, String, ()> for PCodeView<'a> { + fn process_ins(&mut self, ins: &InsRef) -> Result { // get instruction from pool - let ins_node = self.ins_pool.get(&ins); + let module = self.module.unwrap(); + let ins_node = module.ins_pool.get(&ins); match ins_node { - LowIRIns::SingleLineComment { comment, src: _ } => { + PIRIns::SingleLineComment { comment, src: _ } => { let comment = comment.clone(); Ok(self.pad_text(comment)) } - LowIRIns::NamedStructDecl { + PIRIns::NamedStructDecl { name, fields, src: _, } => { - let name = self.visit_expr(&name)?; + let name = self.process_expr(&name)?; let mut view = String::new(); view.push_str(&self.pad_text(format!(":{} ", name))); if fields.pairs.len() > 0 { - view.push_str(&self.visit_pairs(&fields)?); + view.push_str(&self.process_pairs(&fields)?); } else { view.push_str("{ }"); } Ok(view) } - LowIRIns::ConstantDecl { + PIRIns::ConstantDecl { const_name, const_type: _, init_expr, @@ -125,32 +66,32 @@ impl VisitsLowIR for CodeViewer { is_public, } => { let const_name = const_name.as_str(); - let init_expr = self.visit_expr(&init_expr)?; + let init_expr = self.process_expr(&init_expr)?; let mut view = format!("let {} = {}", const_name, init_expr); if is_public { view = format!("pub {}", view); } Ok(self.pad_text(view)) } - LowIRIns::VariableDecl(var_name, _, init_expr, _) => { + PIRIns::VariableDecl(var_name, _, init_expr, _) => { let var_name = var_name.as_str(); if let Some(init_expr) = init_expr { - let init_expr = self.visit_expr(&init_expr)?; + let init_expr = self.process_expr(&init_expr)?; Ok(self.pad_text(format!("mut {} = {}", var_name, init_expr))) } else { Ok(self.pad_text(format!("mut {}", var_name))) } } - LowIRIns::AssignmentIns(target, val) => { - let target = self.visit_expr(&target)?; - let val = self.visit_expr(&val)?; + PIRIns::AssignmentIns(target, val) => { + let target = self.process_expr(&target)?; + let val = self.process_expr(&val)?; Ok(self.pad_text(format!("{} = {};", target, val))) } - LowIRIns::ExpressionIns(expr, _) => { - let expr = self.visit_expr(&expr)?; + PIRIns::ExpressionIns(expr, _) => { + let expr = self.process_expr(&expr)?; Ok(self.pad_text(format!("{};", expr))) } - LowIRIns::FunctionDef { + PIRIns::FunctionDef { name, params, return_type, @@ -161,13 +102,13 @@ impl VisitsLowIR for CodeViewer { let name = name.as_str(); let mut param_strs = vec![]; for param in params { - param_strs.push(self.visit_expr(¶m)?); + param_strs.push(self.process_expr(¶m)?); } let params = param_strs.join(", "); let return_type = return_type.as_str(); let block_type = self.block_type.clone(); self.block_type = CodeBlockType::InstructionPart; - let body = self.visit_ins(&body)?; + let body = self.process_ins(&body)?; self.block_type = block_type; let mut view = format!("fn {name}({params}) {return_type} {body}"); if is_public { @@ -175,26 +116,26 @@ impl VisitsLowIR for CodeViewer { } Ok(self.pad_text(view)) } - LowIRIns::InfiniteLoop { src: _, body } => { + PIRIns::InfiniteLoop { src: _, body } => { let block_type = self.block_type.clone(); self.block_type = CodeBlockType::InstructionPart; - let body = self.visit_ins(&body)?; + let body = self.process_ins(&body)?; self.block_type = block_type; Ok(self.pad_text(format!("loop {}", body))) } - LowIRIns::WhileLoop { + PIRIns::WhileLoop { src: _, condition, body, } => { - let condition = self.visit_expr(&condition)?; + let condition = self.process_expr(&condition)?; let block_type = self.block_type.clone(); self.block_type = CodeBlockType::InstructionPart; - let body = self.visit_ins(&body)?; + let body = self.process_ins(&body)?; self.block_type = block_type; Ok(self.pad_text(format!("while {} {}", condition, body))) } - LowIRIns::CodeBlock { + PIRIns::CodeBlock { src: _, instructions, } => { @@ -215,7 +156,7 @@ impl VisitsLowIR for CodeViewer { self.increase_padding(); let mut ins_strs = vec![]; for ins in instructions { - ins_strs.push(self.visit_ins(&ins)?); + ins_strs.push(self.process_ins(&ins)?); } self.decrease_padding(); view.push_str(&ins_strs.join("\n\n")); @@ -223,16 +164,16 @@ impl VisitsLowIR for CodeViewer { } Ok(view) } - LowIRIns::Module { + PIRIns::Module { name, body, src: _, is_public, } => { - let name = self.visit_expr(&name)?; + let name = self.process_expr(&name)?; let block_type = self.block_type.clone(); self.block_type = CodeBlockType::InstructionPart; - let body = self.visit_ins(&body)?; + let body = self.process_ins(&body)?; self.block_type = block_type; let mut view = format!("mod {} {}", name, body); if is_public { @@ -240,17 +181,17 @@ impl VisitsLowIR for CodeViewer { } Ok(self.pad_text(view)) } - LowIRIns::Return { src: _, value } => { + PIRIns::Return { src: _, value } => { if let Some(value) = value { - let value = self.visit_expr(&value)?; + let value = self.process_expr(&value)?; Ok(self.pad_text(format!("return {};", value))) } else { Ok(self.pad_text("return;".to_string())) } } - LowIRIns::Break(_) => Ok(self.pad_text("break;".to_string())), - LowIRIns::Continue(_) => Ok(self.pad_text("continue;".to_string())), - LowIRIns::UseDependency { paths, src: _ } => { + PIRIns::Break(_) => Ok(self.pad_text("break;".to_string())), + PIRIns::Continue(_) => Ok(self.pad_text("continue;".to_string())), + PIRIns::UseDependency { paths, src: _ } => { let mut path_str = String::new(); for (i, path) in paths.iter().enumerate() { for (j, part) in path.actions.iter().enumerate() { @@ -265,45 +206,45 @@ impl VisitsLowIR for CodeViewer { } Ok(format!("use {};", path_str)) } - LowIRIns::DirectiveInstruction { + PIRIns::DirectiveInstruction { directive, block, src: _, } => { - let directive = self.visit_expr(&directive)?; + let directive = self.process_expr(&directive)?; if let Some(block) = block { let block_type = self.block_type.clone(); self.block_type = CodeBlockType::InstructionPart; - let block = self.visit_ins(&block)?; + let block = self.process_ins(&block)?; self.block_type = block_type; Ok(self.pad_text(format!("@{} {}", directive, block))) } else { Ok(self.pad_text(format!("@{};", directive))) } } - LowIRIns::ConditionalBranchIns { pairs, src: _ } => { + PIRIns::ConditionalBranchIns { pairs, src: _ } => { let mut view = String::new(); let block_type = self.block_type.clone(); self.block_type = CodeBlockType::InstructionPart; for i in 0..pairs.len() { let (cond, ins) = &pairs[i]; if i == 0 { - let cond = self.visit_expr(&cond.clone().unwrap())?; - let ins = self.visit_ins(&ins)?; + let cond = self.process_expr(&cond.clone().unwrap())?; + let ins = self.process_ins(&ins)?; // self.increase_padding(); // for the first pair, we do if view.push_str(&self.pad_text(format!("if {} {}", cond, ins))); // self.decrease_padding(); } else if i < pairs.len() - 1 { - let cond = self.visit_expr(&cond.clone().unwrap())?; - let ins = self.visit_ins(&ins)?; + let cond = self.process_expr(&cond.clone().unwrap())?; + let ins = self.process_ins(&ins)?; self.increase_padding(); // for the rest, we do else if view.push_str(&format!(" else if {} {}", cond, ins)); self.decrease_padding(); } else { // for the last, we do else - let ins = self.visit_ins(&ins)?; + let ins = self.process_ins(&ins)?; self.increase_padding(); view.push_str(&format!(" else {}", ins)); self.decrease_padding(); @@ -315,91 +256,144 @@ impl VisitsLowIR for CodeViewer { } } - fn visit_expr(&mut self, expr: &ExprRef) -> Result { + fn process_expr(&mut self, expr: &ExprRef) -> Result { // get expr from pool - let expr_node = self.expr_pool.get(&expr); + let module = self.module.unwrap(); + let expr_node = module.expr_pool.get(&expr); match expr_node { - LowIRExpr::Id(token, id_type) => { + PIRExpr::Id(token, id_type) => { if let Some(id_type) = id_type { Ok(format!("{} {}", token.as_str(), id_type.as_str())) } else { Ok(token.as_str()) } } - LowIRExpr::Number(num, _) => Ok(num.as_str()), - LowIRExpr::StringLiteral(lit, _) => Ok(lit.as_str()), - LowIRExpr::CharacterLiteral(lit, _) => Ok(lit.as_str()), - LowIRExpr::Binary(operator, lhs, rhs, _) => { - let lhs = self.visit_expr(&lhs)?; - let rhs = self.visit_expr(&rhs)?; + PIRExpr::Number(num, _) => Ok(num.as_str()), + PIRExpr::StringLiteral(lit, _) => Ok(lit.as_str()), + PIRExpr::CharacterLiteral(lit, _) => Ok(lit.as_str()), + PIRExpr::Binary(operator, lhs, rhs, _) => { + let lhs = self.process_expr(&lhs)?; + let rhs = self.process_expr(&rhs)?; Ok(format!("{} {} {}", lhs, operator.as_str(), rhs)) } - LowIRExpr::Comparison(operator, lhs, rhs, _) => { - let lhs = self.visit_expr(&lhs)?; - let rhs = self.visit_expr(&rhs)?; + PIRExpr::Comparison(operator, lhs, rhs, _) => { + let lhs = self.process_expr(&lhs)?; + let rhs = self.process_expr(&rhs)?; Ok(format!("{} {} {}", lhs, operator.as_str(), rhs)) } - LowIRExpr::Boolean(lit, _) => Ok(lit.as_str()), - LowIRExpr::Unary(operator, expr, _) => { - let expr = self.visit_expr(&expr)?; + PIRExpr::Boolean(lit, _) => Ok(lit.as_str()), + PIRExpr::Unary(operator, expr, _) => { + let expr = self.process_expr(&expr)?; Ok(format!("{}{}", operator.as_str(), expr)) } - LowIRExpr::Grouped(inner_expr, _, _) => { - let inner_expr = self.visit_expr(&inner_expr)?; + PIRExpr::Grouped(inner_expr, _, _) => { + let inner_expr = self.process_expr(&inner_expr)?; Ok(format!("({})", inner_expr)) } - LowIRExpr::FnCall { + PIRExpr::FnCall { func, args, span: _, fn_type: _, } => { - let func = self.visit_expr(&func)?; + let func = self.process_expr(&func)?; let args_str = args .iter() - .map(|arg| self.visit_expr(&arg)) - .collect::, VisitIRError>>()?; + .map(|arg| self.process_expr(&arg)) + .collect::, ()>>()?; let args_str = args_str.join(", "); Ok(format!("{}({})", func, args_str)) } - LowIRExpr::ScopeInto { + PIRExpr::ScopeInto { module, target, src: _, resolved_type: _, } => { - let module = self.visit_expr(&module)?; - let target = self.visit_expr(&target)?; + let module = self.process_expr(&module)?; + let target = self.process_expr(&target)?; Ok(format!("{}::{}", module, target)) } - LowIRExpr::DirectiveExpr { + PIRExpr::DirectiveExpr { directive, expr, resolved_type: _, src: _, } => { - let directive = self.visit_expr(&directive)?; + let directive = self.process_expr(&directive)?; if let Some(expr) = expr { - let expr = self.visit_expr(&expr)?; + let expr = self.process_expr(&expr)?; Ok(format!("@{} {}", directive, expr)) } else { Ok(format!("@{}", directive)) } } - LowIRExpr::NamedStructInit { + PIRExpr::NamedStructInit { name, fields, src: _, resolved_type: _, } => { - let name = self.visit_expr(&name)?; + let name = self.process_expr(&name)?; let block_type = self.block_type.clone(); self.block_type = CodeBlockType::InstructionPart; - let fields = self.visit_pairs(&fields)?; + let fields = self.process_pairs(&fields)?; self.block_type = block_type; Ok(format!(":{} {}", name, fields)) } } } + + fn process_pairs(&mut self, kv: &KeyValueBindings) -> Result { + let mut view = String::from("{"); + let kv_pair_len = kv.pairs.len(); + if kv_pair_len > 0 { + self.increase_padding(); + } else { + view.push_str(" }"); + return Ok(view); + } + + let mut count = 0; + for (key, value) in &kv.pairs { + let key = self.process_expr(&key)?; + if let Some(value) = value { + let value = self.process_expr(&value)?; + view.push('\n'); + view.push_str(&self.pad_text(format!("{} = {}", key, value))); + } else { + view.push('\n'); + view.push_str(&self.pad_text(format!("{}", key))); + } + count += 1; + if count < kv_pair_len { + view.push(','); + } + } + self.decrease_padding(); + view.push('\n'); + view.push_str(&self.pad_text("}".to_string())); + Ok(view) + } + + fn process_module(&mut self) -> Result { + let mut res = vec![]; + + let module = self.module.unwrap(); + for ins_ref in module.top_level.iter() { + let ins_str = self.process_ins(&ins_ref)?; + res.push(ins_str); + } + + Ok(res.join("\n")) + } + + fn new(module: &'a mut PIRModule) -> Self { + Self { + left_padding: 0, + module: Some(module), + block_type: CodeBlockType::Regular, + } + } } diff --git a/src/tools/pfmt.rs b/src/tools/pfmt.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/tools/pfmt.rs @@ -0,0 +1 @@ + From 453dc8864799ffc1c6af6034f6ad90d13594fdf6 Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Sat, 1 Jul 2023 22:25:33 -0600 Subject: [PATCH 5/8] Improved passes and wrote pfmt based on pcodeview --- src/frontend/source.rs | 5 +++++ src/main.rs | 16 ++++++++------ src/pir/ir.rs | 28 ++++++++++++++++++------ src/tools/pcodeview.rs | 19 +++++++--------- src/tools/pfmt.rs | 49 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 25 deletions(-) diff --git a/src/frontend/source.rs b/src/frontend/source.rs index 772361b..c24e490 100644 --- a/src/frontend/source.rs +++ b/src/frontend/source.rs @@ -392,6 +392,11 @@ impl SourceReporter { println!("{}", pastel(&output)); } + pub fn show_error(&self, msg: String) { + let output = format!("*[_, *, l_red:d_black]Error:[/] *[*, l_white:d_black]{msg}[/]"); + println!("{}", pastel(&output)); + } + fn report_with_ref(&self, src: &SourceRef, msg: String, tip: Option) { let err_col = "d_red"; let target_col = "l_magenta"; diff --git a/src/main.rs b/src/main.rs index 42a415b..1726925 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,8 @@ use frontend::{ }; use pir::ir::{PIRModule, PIRModulePass}; use serde::Deserialize; -use tools::pcodeview::PCodeView; + +use crate::tools::pfmt::Pfmt; mod frontend; mod pastel; @@ -96,11 +97,12 @@ fn main() { // } let module = parser.compilation_module; - let mut ir_mod = PIRModule::new(module); - - let mut code_view = PCodeView::new(&mut ir_mod); - let res = code_view.process_module().unwrap(); - - println!("{}", res); + let mut ir_mod = PIRModule::new(module, path); + let mut pfmt = Pfmt::new(&mut ir_mod); + let res = pfmt.process(); + match res { + Ok(msg) => reporter.show_info(msg), + Err(e) => reporter.show_error(e), + } } } diff --git a/src/pir/ir.rs b/src/pir/ir.rs index b1030c4..57437fb 100644 --- a/src/pir/ir.rs +++ b/src/pir/ir.rs @@ -720,15 +720,17 @@ pub struct PIRModule { pub ins_pool: InsPool, pub expr_pool: ExprPool, pub top_level: Vec, + pub path: String, } #[allow(dead_code)] impl PIRModule { - pub fn new(cm: CompilationModule) -> PIRModule { + pub fn new(cm: CompilationModule, path: String) -> PIRModule { let mut pirmod = PIRModule { ins_pool: InsPool::new(), expr_pool: ExprPool::new(), top_level: Vec::new(), + path, }; for ins in cm.instructions { let id = pirmod.ins_pool.to_pir(&mut pirmod.expr_pool, ins); @@ -739,10 +741,22 @@ impl PIRModule { } #[allow(dead_code)] -pub trait PIRModulePass<'a, A, B, C, M, T> { - fn process_ins(&mut self, ins: &InsRef) -> Result; - fn process_expr(&mut self, expr: &ExprRef) -> Result; - fn process_pairs(&mut self, kv: &KeyValueBindings) -> Result; - fn process_module(&mut self) -> Result; - fn new(module: &'a mut PIRModule) -> Self; +pub trait PIRModulePass<'a, InsRes, ExprRes, KVRes, ModRes, Error> { + fn process_ins(&mut self, ins: &InsRef) -> Result; + fn process_expr(&mut self, expr: &ExprRef) -> Result; + fn process_pairs(&mut self, kv: &KeyValueBindings) -> Result; + fn process_module(&mut self) -> Result, Error> { + let mut res = vec![]; + + let module = self.get_module(); + for ins_ref in module.top_level.iter() { + let ins_res = self.process_ins(&ins_ref)?; + res.push(ins_res); + } + + Ok(res) + } + fn process(&mut self) -> Result; + fn new(module: &'a PIRModule) -> Self; + fn get_module(&mut self) -> &'a PIRModule; } diff --git a/src/tools/pcodeview.rs b/src/tools/pcodeview.rs index a0af5c3..84b73fa 100644 --- a/src/tools/pcodeview.rs +++ b/src/tools/pcodeview.rs @@ -377,23 +377,20 @@ impl<'a> PIRModulePass<'a, String, String, String, String, ()> for PCodeView<'a> Ok(view) } - fn process_module(&mut self) -> Result { - let mut res = vec![]; - - let module = self.module.unwrap(); - for ins_ref in module.top_level.iter() { - let ins_str = self.process_ins(&ins_ref)?; - res.push(ins_str); - } - - Ok(res.join("\n")) + fn process(&mut self) -> Result { + let content = self.process_module()?; + Ok(content.join("\n")) } - fn new(module: &'a mut PIRModule) -> Self { + fn new(module: &'a PIRModule) -> Self { Self { left_padding: 0, module: Some(module), block_type: CodeBlockType::Regular, } } + + fn get_module(&mut self) -> &'a PIRModule { + self.module.unwrap() + } } diff --git a/src/tools/pfmt.rs b/src/tools/pfmt.rs index 8b13789..4a6267a 100644 --- a/src/tools/pfmt.rs +++ b/src/tools/pfmt.rs @@ -1 +1,50 @@ +use std::fs; +use crate::pir::ir::{ExprRef, InsRef, KeyValueBindings, PIRModule, PIRModulePass}; + +use super::pcodeview::PCodeView; + +pub struct Pfmt<'a> { + module: Option<&'a PIRModule>, +} + +impl<'a> PIRModulePass<'a, (), (), (), String, String> for Pfmt<'a> { + fn new(module: &'a PIRModule) -> Self { + Self { + module: Some(module), + } + } + + fn process_ins(&mut self, _: &InsRef) -> Result<(), String> { + Ok(()) + } + + fn process_expr(&mut self, _: &ExprRef) -> Result<(), String> { + Ok(()) + } + + fn process_pairs(&mut self, _: &KeyValueBindings) -> Result<(), String> { + Ok(()) + } + + fn process(&mut self) -> Result { + let mut module = self.module.unwrap(); + let mut code_view = PCodeView::new(&mut module); + let contents = code_view.process().unwrap(); + + // write out to module path + let write_res = fs::write(&module.path, contents); + if let Err(e) = write_res { + Err(format!( + "Failed to write to file at path `{}`. \n{}", + module.path, e + )) + } else { + Ok(format!("Successfully formatted `{}`", module.path)) + } + } + + fn get_module(&mut self) -> &'a PIRModule { + self.module.unwrap() + } +} From a91b7a9c986dca110f35620a137d4ccb22d955f9 Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Sun, 2 Jul 2023 04:47:51 -0600 Subject: [PATCH 6/8] Started work on compilation config but paused --- src/main.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main.rs b/src/main.rs index 1726925..cd8011f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,12 +36,38 @@ struct Args { flag_f: String, } +#[allow(dead_code)] +enum Backend { + PIR, // will go to PVM + CPP, // will go to C++ +} + +#[allow(dead_code)] enum Stage { Lexer, Parser, + PfmtFile, } +#[allow(dead_code)] +struct ProtoConfig { + backend: Backend, + target_file: String, + max_stage: Stage, + show_help: bool, +} + +// fn create_config(args: Vec) { +// let args = args.iter().skip(1); +// for arg in args { +// println!("{}", arg); +// } +// } + fn main() { + // let args = env::args().collect::>(); + // let config = create_config(args); + let args: Args = Docopt::new(USAGE) .and_then(|d| d.deserialize()) .unwrap_or_else(|e| e.exit()); From 98dccba09ab1a54df72b23d874b3faff1cdbb028 Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Sun, 2 Jul 2023 05:35:44 -0600 Subject: [PATCH 7/8] Removed dependency on DocOpt and impld better cmdline arg processing --- Cargo.toml | 1 - src/main.rs | 199 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 143 insertions(+), 57 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2dd13bf..f947f10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -docopt = "1.1.1" phf = { version = "0.11.1", features = ["macros"] } serde = { version = "1.0.152", features = ["derive"] } serde_json = "1.0.94" diff --git a/src/main.rs b/src/main.rs index cd8011f..8436e87 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,5 @@ use std::{env, fs, path::PathBuf}; -use docopt::Docopt; use frontend::{ lexer::Lexer, parser::Parser, @@ -8,7 +7,6 @@ use frontend::{ token::Token, }; use pir::ir::{PIRModule, PIRModulePass}; -use serde::Deserialize; use crate::tools::pfmt::Pfmt; @@ -18,24 +16,25 @@ mod pir; mod tools; const USAGE: &str = " -Usage: proto (-h | -l | -p) -f - -Options: - -h, --help Show this message. - -l Run lexer and show its output. - -p Run parser and show its output. - -f File to be processed. +Usage: proto command [options]? + +commands: + - c | compile [configurations]? + - [configurations]: + (*) backends: + - pir (default): use PIR backend. + - cpp: use C++ backend. + (*) stages: + - lex: stop after lexing. + - parse: stop after parsing. + - fmt (default): stop after formatting. + (*) flags: + - nofmt: do not format the file. Default: false. + - dbg: show debug info. Default: false. + - help: show this help message. Default: false. + - h | help: show this help message. "; -#[derive(Debug, Deserialize)] -#[allow(dead_code)] -struct Args { - flag_h: bool, - flag_l: bool, - flag_p: bool, - flag_f: String, -} - #[allow(dead_code)] enum Backend { PIR, // will go to PVM @@ -49,36 +48,115 @@ enum Stage { PfmtFile, } +#[allow(dead_code)] +enum Command { + Compile, +} + #[allow(dead_code)] struct ProtoConfig { + cmd: Option, backend: Backend, target_file: String, max_stage: Stage, show_help: bool, + dbg_info: bool, } -// fn create_config(args: Vec) { -// let args = args.iter().skip(1); -// for arg in args { -// println!("{}", arg); -// } -// } +fn create_config(args: Vec) -> ProtoConfig { + let mut args = args.iter().skip(1); + + // make sure there is at least 1 more arg + if args.len() < 1 { + return ProtoConfig { + cmd: None, + backend: Backend::PIR, + target_file: "".to_string(), + max_stage: Stage::PfmtFile, + show_help: true, + dbg_info: false, + }; + } + + // expect one of: + // c which will accept a file name and configurations + let command = args.next().unwrap(); + match command.as_str() { + "c" | "compile" => { + // make sure there is at least 1 more arg + // which is the file name + if args.len() < 1 { + return ProtoConfig { + cmd: None, + backend: Backend::PIR, + target_file: "".to_string(), + max_stage: Stage::PfmtFile, + show_help: true, + dbg_info: false, + }; + } + let target_file = args.next().unwrap(); + let mut backend = Backend::PIR; + let mut max_stage = Stage::PfmtFile; + let mut show_help = false; + let mut dbg_info = false; + for arg in args { + match arg.as_str() { + "pir" => backend = Backend::PIR, + "cpp" => backend = Backend::CPP, + "lex" => max_stage = Stage::Lexer, + "parse" => max_stage = Stage::Parser, + "fmt" => max_stage = Stage::PfmtFile, + "dbg" => dbg_info = true, + "help" => show_help = true, + _ => {} + } + } + ProtoConfig { + cmd: Some(Command::Compile), + backend, + target_file: target_file.to_string(), + max_stage, + show_help, + dbg_info, + } + } + "h" | "help" => ProtoConfig { + backend: Backend::PIR, + target_file: "".to_string(), + max_stage: Stage::PfmtFile, + show_help: true, + dbg_info: false, + cmd: None, + }, + _ => ProtoConfig { + backend: Backend::PIR, + target_file: "".to_string(), + max_stage: Stage::PfmtFile, + show_help: true, + dbg_info: false, + cmd: None, + }, + } +} + +fn show_help() { + println!("{}", USAGE); +} fn main() { - // let args = env::args().collect::>(); - // let config = create_config(args); + let args = env::args().collect::>(); + let config = create_config(args); - let args: Args = Docopt::new(USAGE) - .and_then(|d| d.deserialize()) - .unwrap_or_else(|e| e.exit()); + if config.show_help { + show_help(); + } - let stage = if args.flag_l { - Stage::Lexer - } else { - Stage::Parser - }; + if let None = config.cmd { + return; + } - let fpath = args.flag_f; + let fpath = config.target_file; let cwd = env::current_dir().unwrap(); let path = format!("{}/{}", cwd.display(), fpath); let path = fs::canonicalize(PathBuf::from(path)).unwrap(); @@ -88,7 +166,7 @@ fn main() { let reporter = SourceReporter::new(src.clone()); let mut lexer = Lexer::new(src); - if let Stage::Lexer = stage { + if let Stage::Lexer = config.max_stage { loop { let maybe_tok = lexer.next_token(); match maybe_tok { @@ -100,34 +178,43 @@ fn main() { Err(le) => reporter.report_lexer_error(&le), } } - } else { - let mut parser = Parser::new(lexer); - parser.parse(); + } - if !parser.lexer_errors.is_empty() { - for le in parser.lexer_errors { - reporter.report_lexer_error(&le); - } + let mut parser = Parser::new(lexer); + parser.parse(); + + if !parser.lexer_errors.is_empty() { + for le in parser.lexer_errors { + reporter.report_lexer_error(&le); } - // else { - // reporter.show_info("No errors during lexing.".to_string()); - // } + } - if !parser.parser_errors.is_empty() { - for pe in parser.parser_errors { - reporter.report_parser_error(pe); - } + if config.dbg_info { + reporter.show_info("No errors during lexing.".to_string()); + } + + if !parser.parser_errors.is_empty() { + for pe in parser.parser_errors { + reporter.report_parser_error(pe); } - // else { - // reporter.show_info("No errors during parsing.".to_string()); - // } + } + + if config.dbg_info { + reporter.show_info("No errors during parsing.".to_string()); + } + + let module = parser.compilation_module; + let mut ir_mod = PIRModule::new(module, path); - let module = parser.compilation_module; - let mut ir_mod = PIRModule::new(module, path); + if let Stage::PfmtFile = config.max_stage { let mut pfmt = Pfmt::new(&mut ir_mod); let res = pfmt.process(); match res { - Ok(msg) => reporter.show_info(msg), + Ok(msg) => { + if config.dbg_info { + reporter.show_info(msg); + } + } Err(e) => reporter.show_error(e), } } From a1a21384d4ef629280ae8f90bcfc816643193c6f Mon Sep 17 00:00:00 2001 From: Joshua Pepple Date: Thu, 6 Jul 2023 10:51:14 -0600 Subject: [PATCH 8/8] Started dependency resolution pass --- src/analysis_a/dependency_res.rs | 206 +++++++++++++++++++++++++++++++ src/analysis_a/mod.rs | 1 + src/frontend/ast.rs | 17 ++- src/main.rs | 28 +++-- src/pir/ir.rs | 56 ++++----- 5 files changed, 266 insertions(+), 42 deletions(-) create mode 100644 src/analysis_a/dependency_res.rs create mode 100644 src/analysis_a/mod.rs diff --git a/src/analysis_a/dependency_res.rs b/src/analysis_a/dependency_res.rs new file mode 100644 index 0000000..aca4236 --- /dev/null +++ b/src/analysis_a/dependency_res.rs @@ -0,0 +1,206 @@ +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; + +use crate::{ + frontend::{ + ast::{DependencyPath, PathAction}, + source::SourceRef, + }, + pir::ir::{ExprRef, InsRef, KeyValueBindings, PIRIns, PIRModule, PIRModulePass}, +}; + +#[derive(Clone)] +#[allow(dead_code)] +pub struct DependencyResolvr<'a> { + module: Option<&'a PIRModule>, + file_path: String, + resolution_errors: Vec<(String, SourceRef)>, +} + +// expect to first process the module and get a Vec as the result +// we can then use these indices to get the corresponding ins from the module +// for each of these dependencies, we will: +// - process the actions until we get to a file path. The remainder of the actions will +// be the path to the dependency. +impl<'a> DependencyResolvr<'a> { + pub fn resolve(&mut self, dependencies: Vec) { + let module = self.get_module(); + let ins_pool = &module.ins_pool.pool; + + // for each dependency, we will: + // - get the Instruction (UseDependency) + // - each UseDependency has a list of DependencyPaths: + // - each of the DependencyPaths has a list of actions which will be used to get + // the path + // - we will process the actions (while updating depenedency path) until we: + // * get to a file path. Stop. + // * get to a folder. Continue. + // * path is invalid. Error. + // - once we have a valid file path, whatever is left of the actions + // will be the path to the dependency + // - cluster the dependencies by their paths and return that structure + + let mut res: HashMap> = HashMap::new(); + + for index in dependencies { + let dep = ins_pool.get(index).unwrap(); + if let PIRIns::UseDependency { paths, src: _ } = dep { + for path in paths { + let resolved_res = self.evaluate_dependency_path(path); + match resolved_res { + Ok((res_path, rem_actions)) => { + // add to res + let res_vec = res.entry(index).or_insert(Vec::new()); + res_vec.push((res_path, rem_actions)); + } + Err(msg) => { + self.resolution_errors.push((msg, path.source_ref())); + } + } + } + } + } + + // show contents of res array + for (index, m) in res { + let dep = ins_pool.get(index).unwrap(); + println!("{} resolves to the following path:", dep.as_str()); + for (path, actions) in m { + println!("\t{}: {}", path.display(), actions.as_str()); + } + } + } + + fn evaluate_dependency_path( + &mut self, + dep: &DependencyPath, + ) -> Result<(PathBuf, DependencyPath), String> { + let mut start_dir = PathBuf::from(&self.file_path.clone()); + start_dir.pop(); + let mut search_dep_path = start_dir; + let mut skip_to = 0; + + for action in &dep.actions { + match action { + PathAction::ToParentDir(_) => { + search_dep_path.pop(); + } + PathAction::ImportAll(_) => { + break; + } + PathAction::SearchFor(path_section) => { + // append path_section to search_dep_path + search_dep_path.push(path_section.as_str()); + } + PathAction::SearchCoreModulesFor(_) => todo!(), + PathAction::SearchProjectRootFor(_) => todo!(), + PathAction::SearchCurrentFileFor(_) => { + search_dep_path = PathBuf::from(&self.file_path); + search_dep_path.set_extension("pr"); + break; + } + PathAction::NameLastItemAs(_) => todo!(), + } + + // check that updated path exists + let (path_exists, is_file, is_dir) = self.path_exists(&search_dep_path); + if !path_exists { + // report error + let msg = format!("Unable to resolve dependency path: {}", dep.as_str()); + return Err(msg); + } + + // update skip_to by 1, with a max of actions.len() + skip_to += 1; + if skip_to >= dep.actions.len() { + break; + } + + if is_dir { + // continue + continue; + } + + if is_file { + // stop + break; + } else { + } + } + + // we have to verify that the path is a file + let (path_exists, is_file, _) = self.path_exists(&search_dep_path); + if !path_exists { + // report error + let msg = format!("Unable to resolve dependency path: {}", dep.as_str()); + return Err(msg); + } + + if !is_file { + // report error + let msg = format!("Dependency path must contain a file: {}", dep.as_str()); + return Err(msg); + } + + // we have a valid file path + // we need to collect the remainder of the actions into a Vector of PathActions + let mut remainder = Vec::new(); + for action in &dep.actions[skip_to..] { + remainder.push(action.clone()); + } + let remainder = DependencyPath { actions: remainder }; + Ok((search_dep_path, remainder)) + } + + // checks if path exists and also if it is a file + fn path_exists(&self, path: &PathBuf) -> (bool, bool, bool) { + let mut file_path = path.clone(); + file_path.set_extension("pr"); + let file_path = Path::new(&file_path); + let file_exists = file_path.exists(); + let dir_exists = path.exists(); + (dir_exists || file_exists, file_exists, dir_exists) + } +} + +impl<'a> PIRModulePass<'a, (), (), (), Vec, ()> for DependencyResolvr<'a> { + fn process_ins(&mut self, _: &InsRef) -> Result<(), ()> { + Ok(()) + } + + fn process_expr(&mut self, _: &ExprRef) -> Result<(), ()> { + Ok(()) + } + + fn process_pairs(&mut self, _: &KeyValueBindings) -> Result<(), ()> { + Ok(()) + } + + fn process(&mut self) -> Result, ()> { + let module = self.get_module(); + let ins_pool = &module.ins_pool.pool; + let mut dependencies = Vec::new(); + + for (index, ins) in ins_pool.iter().enumerate() { + if matches!(ins, PIRIns::UseDependency { paths: _, src: _ }) { + dependencies.push(index); + } + } + + Ok(dependencies) + } + + fn new(module: &'a PIRModule) -> Self { + Self { + module: Some(module), + file_path: module.path.clone(), + resolution_errors: Vec::new(), + } + } + + fn get_module(&mut self) -> &'a PIRModule { + self.module.unwrap() + } +} diff --git a/src/analysis_a/mod.rs b/src/analysis_a/mod.rs new file mode 100644 index 0000000..bffc631 --- /dev/null +++ b/src/analysis_a/mod.rs @@ -0,0 +1 @@ +pub mod dependency_res; diff --git a/src/frontend/ast.rs b/src/frontend/ast.rs index d16a931..79ea3f5 100644 --- a/src/frontend/ast.rs +++ b/src/frontend/ast.rs @@ -208,7 +208,6 @@ pub enum PathAction { SearchFor(Expr), SearchCoreModulesFor(Expr), SearchProjectRootFor(Expr), - SearchLastModuleFor(Expr), SearchCurrentFileFor(Expr), NameLastItemAs(Expr), } @@ -222,7 +221,6 @@ impl PathAction { PathAction::SearchFor(_) => true, PathAction::SearchCoreModulesFor(_) => true, PathAction::SearchProjectRootFor(_) => true, - PathAction::SearchLastModuleFor(_) => true, PathAction::SearchCurrentFileFor(_) => true, PathAction::ImportAll(_) => false, } @@ -235,7 +233,6 @@ impl PathAction { PathAction::NameLastItemAs(_) => true, PathAction::SearchCoreModulesFor(_) => true, PathAction::SearchProjectRootFor(_) => true, - PathAction::SearchLastModuleFor(_) => true, PathAction::SearchCurrentFileFor(_) => false, PathAction::ImportAll(_) => true, } @@ -248,7 +245,6 @@ impl PathAction { PathAction::NameLastItemAs(_) => false, PathAction::SearchCoreModulesFor(_) => true, PathAction::SearchProjectRootFor(_) => true, - PathAction::SearchLastModuleFor(_) => true, PathAction::SearchCurrentFileFor(_) => false, PathAction::ImportAll(_) => false, } @@ -261,7 +257,6 @@ impl PathAction { PathAction::NameLastItemAs(alias) => format!(" as {}", alias.as_str()), PathAction::SearchCoreModulesFor(e) => format!("@{}", e.as_str()), PathAction::SearchProjectRootFor(m) => format!("${}", m.as_str()), - PathAction::SearchLastModuleFor(n) => n.as_str(), PathAction::SearchCurrentFileFor(inner_m) => format!("!{}", inner_m.as_str()), PathAction::ImportAll(_) => "*".to_string(), } @@ -273,7 +268,6 @@ impl PathAction { PathAction::SearchFor(e) => e.source_ref(), PathAction::SearchCoreModulesFor(e) => e.source_ref(), PathAction::SearchProjectRootFor(e) => e.source_ref(), - PathAction::SearchLastModuleFor(e) => e.source_ref(), PathAction::SearchCurrentFileFor(e) => e.source_ref(), PathAction::NameLastItemAs(e) => e.source_ref(), PathAction::ImportAll(src) => src.clone(), @@ -303,6 +297,17 @@ impl DependencyPath { let last_action = self.actions.last().unwrap(); first_action.source_ref().combine(last_action.source_ref()) } + + pub fn as_str(&self) -> String { + let mut s = String::new(); + for (index, action) in self.actions.iter().enumerate() { + s.push_str(&action.as_str()); + if index < self.actions.len() - 1 { + s.push_str("::"); + } + } + s + } } #[derive(Debug, Clone)] diff --git a/src/main.rs b/src/main.rs index 8436e87..311da50 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use std::{env, fs, path::PathBuf}; +use analysis_a::dependency_res::DependencyResolvr; use frontend::{ lexer::Lexer, parser::Parser, @@ -8,8 +9,9 @@ use frontend::{ }; use pir::ir::{PIRModule, PIRModulePass}; -use crate::tools::pfmt::Pfmt; +// use crate::tools::pfmt::Pfmt; +mod analysis_a; mod frontend; mod pastel; mod pir; @@ -46,6 +48,7 @@ enum Stage { Lexer, Parser, PfmtFile, + DependencyResolvr, } #[allow(dead_code)] @@ -107,6 +110,7 @@ fn create_config(args: Vec) -> ProtoConfig { "lex" => max_stage = Stage::Lexer, "parse" => max_stage = Stage::Parser, "fmt" => max_stage = Stage::PfmtFile, + "dep" => max_stage = Stage::DependencyResolvr, "dbg" => dbg_info = true, "help" => show_help = true, _ => {} @@ -207,15 +211,23 @@ fn main() { let mut ir_mod = PIRModule::new(module, path); if let Stage::PfmtFile = config.max_stage { - let mut pfmt = Pfmt::new(&mut ir_mod); - let res = pfmt.process(); + // let mut pfmt = Pfmt::new(&mut ir_mod); + // let res = pfmt.process(); + // match res { + // Ok(msg) if config.dbg_info => reporter.show_info(msg), + // Err(e) => reporter.show_error(e), + // _ => {} + // } + } + + if let Stage::DependencyResolvr = config.max_stage { + let mut dep_resolvr = DependencyResolvr::new(&mut ir_mod); + let res = dep_resolvr.process(); match res { - Ok(msg) => { - if config.dbg_info { - reporter.show_info(msg); - } + Ok(indices) => { + let _ = dep_resolvr.resolve(indices); } - Err(e) => reporter.show_error(e), + Err(_) => todo!(), } } } diff --git a/src/pir/ir.rs b/src/pir/ir.rs index 57437fb..963a3d2 100644 --- a/src/pir/ir.rs +++ b/src/pir/ir.rs @@ -147,29 +147,29 @@ impl ExprPool { } } - pub fn lowir(&mut self, expr: Expr) -> ExprRef { + pub fn to_pir(&mut self, expr: Expr) -> ExprRef { match expr { Expr::Id(id, t) => self.add(PIRExpr::Id(id, t)), Expr::Number(n, t) => self.add(PIRExpr::Number(n, t)), Expr::StringLiteral(s, t) => self.add(PIRExpr::StringLiteral(s, t)), Expr::CharacterLiteral(c, t) => self.add(PIRExpr::CharacterLiteral(c, t)), Expr::Binary(op, lhs, rhs, t) => { - let lhs = self.lowir(*lhs); - let rhs = self.lowir(*rhs); + let lhs = self.to_pir(*lhs); + let rhs = self.to_pir(*rhs); self.add(PIRExpr::Binary(op, lhs, rhs, t)) } Expr::Comparison(op, lhs, rhs, t) => { - let lhs = self.lowir(*lhs); - let rhs = self.lowir(*rhs); + let lhs = self.to_pir(*lhs); + let rhs = self.to_pir(*rhs); self.add(PIRExpr::Comparison(op, lhs, rhs, t)) } Expr::Boolean(b, t) => self.add(PIRExpr::Boolean(b, t)), Expr::Unary(op, expr, t) => { - let expr = self.lowir(*expr); + let expr = self.to_pir(*expr); self.add(PIRExpr::Unary(op, expr, t)) } Expr::Grouped(expr, t, src) => { - let expr = self.lowir(*expr); + let expr = self.to_pir(*expr); self.add(PIRExpr::Grouped(expr, t, src)) } Expr::FnCall { @@ -178,10 +178,10 @@ impl ExprPool { span, fn_type, } => { - let func = self.lowir(*func); + let func = self.to_pir(*func); let args = args .into_iter() - .map(|arg| self.lowir(arg)) + .map(|arg| self.to_pir(arg)) .collect::>(); self.add(PIRExpr::FnCall { func, @@ -196,8 +196,8 @@ impl ExprPool { src, resolved_type, } => { - let module = self.lowir(*module); - let target = self.lowir(*target); + let module = self.to_pir(*module); + let target = self.to_pir(*target); self.add(PIRExpr::ScopeInto { module, target, @@ -211,8 +211,8 @@ impl ExprPool { resolved_type, src, } => { - let directive = self.lowir(*directive); - let expr = expr.map(|expr| self.lowir(*expr)); + let directive = self.to_pir(*directive); + let expr = expr.map(|expr| self.to_pir(*expr)); self.add(PIRExpr::DirectiveExpr { directive, expr, @@ -226,7 +226,7 @@ impl ExprPool { src, resolved_type, } => { - let name = self.lowir(*name); + let name = self.to_pir(*name); let fields = self.pir_bindings(fields); self.add(PIRExpr::NamedStructInit { name, @@ -243,9 +243,9 @@ impl ExprPool { .pairs .iter() .map(|pair| { - let key = self.lowir(pair.0.clone()); + let key = self.to_pir(pair.0.clone()); if let Some(value) = pair.1.clone() { - let value = self.lowir(value); + let value = self.to_pir(value); (key, Some(value)) } else { (key, None) @@ -554,7 +554,7 @@ impl InsPool { self.add(ins) } Instruction::NamedStructDecl { name, fields, src } => { - let name_ref = epool.lowir(name); + let name_ref = epool.to_pir(name); let fields = epool.pir_bindings(fields); let ins = PIRIns::NamedStructDecl { name: name_ref, @@ -570,7 +570,7 @@ impl InsPool { src_ref, is_public, } => { - let init_expr = epool.lowir(init_expr); + let init_expr = epool.to_pir(init_expr); let ins = PIRIns::ConstantDecl { const_name, const_type, @@ -581,18 +581,18 @@ impl InsPool { self.add(ins) } Instruction::VariableDecl(name, var_type, init_expr, span) => { - let init_expr = init_expr.map(|e| epool.lowir(e)); + let init_expr = init_expr.map(|e| epool.to_pir(e)); let ins = PIRIns::VariableDecl(name, var_type, init_expr, span); self.add(ins) } Instruction::AssignmentIns(dest, target) => { - let dest = epool.lowir(dest); - let target = epool.lowir(target); + let dest = epool.to_pir(dest); + let target = epool.to_pir(target); let ins = PIRIns::AssignmentIns(dest, target); self.add(ins) } Instruction::ExpressionIns(expr, semi) => { - let expr = epool.lowir(expr); + let expr = epool.to_pir(expr); let ins = PIRIns::ExpressionIns(expr, semi); self.add(ins) } @@ -604,7 +604,7 @@ impl InsPool { is_public, src, } => { - let params = params.into_iter().map(|p| epool.lowir(p)).collect(); + let params = params.into_iter().map(|p| epool.to_pir(p)).collect(); let body = self.to_pir(epool, *body); let ins = PIRIns::FunctionDef { name, @@ -626,7 +626,7 @@ impl InsPool { condition, body, } => { - let condition = epool.lowir(condition); + let condition = epool.to_pir(condition); let body = self.to_pir(epool, *body); let ins = PIRIns::WhileLoop { src, @@ -649,7 +649,7 @@ impl InsPool { src, is_public, } => { - let name = epool.lowir(name); + let name = epool.to_pir(name); let body = self.to_pir(epool, *body); let ins = PIRIns::Module { name, @@ -660,7 +660,7 @@ impl InsPool { self.add(ins) } Instruction::Return { src, value } => { - let value = value.map(|v| epool.lowir(v)); + let value = value.map(|v| epool.to_pir(v)); let ins = PIRIns::Return { src, value }; self.add(ins) } @@ -681,7 +681,7 @@ impl InsPool { block, src, } => { - let directive = epool.lowir(directive); + let directive = epool.to_pir(directive); let block = block.map(|b| self.to_pir(epool, *b)); let ins = PIRIns::DirectiveInstruction { directive, @@ -695,7 +695,7 @@ impl InsPool { .into_iter() .map(|(cond, body)| { if let Some(cond) = cond { - let cond = epool.lowir(cond); + let cond = epool.to_pir(cond); let body = self.to_pir(epool, *body); (Some(cond), body) } else {