Skip to content

Commit

Permalink
Merge pull request #20 from pepplejoshua/analysis
Browse files Browse the repository at this point in the history
Analysis stage
  • Loading branch information
pepplejoshua authored Jul 6, 2023
2 parents a38025e + a1a2138 commit 8913a01
Show file tree
Hide file tree
Showing 19 changed files with 724 additions and 427 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
10 changes: 0 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).

<br>

# 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.
2 changes: 1 addition & 1 deletion docs/language_desc.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
206 changes: 206 additions & 0 deletions src/analysis_a/dependency_res.rs
Original file line number Diff line number Diff line change
@@ -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<usize> 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<usize>) {
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<usize, Vec<(PathBuf, DependencyPath)>> = 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<usize>, ()> 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<Vec<usize>, ()> {
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()
}
}
1 change: 1 addition & 0 deletions src/analysis_a/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod dependency_res;
17 changes: 11 additions & 6 deletions src/frontend/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,6 @@ pub enum PathAction {
SearchFor(Expr),
SearchCoreModulesFor(Expr),
SearchProjectRootFor(Expr),
SearchLastModuleFor(Expr),
SearchCurrentFileFor(Expr),
NameLastItemAs(Expr),
}
Expand All @@ -222,7 +221,6 @@ impl PathAction {
PathAction::SearchFor(_) => true,
PathAction::SearchCoreModulesFor(_) => true,
PathAction::SearchProjectRootFor(_) => true,
PathAction::SearchLastModuleFor(_) => true,
PathAction::SearchCurrentFileFor(_) => true,
PathAction::ImportAll(_) => false,
}
Expand All @@ -235,7 +233,6 @@ impl PathAction {
PathAction::NameLastItemAs(_) => true,
PathAction::SearchCoreModulesFor(_) => true,
PathAction::SearchProjectRootFor(_) => true,
PathAction::SearchLastModuleFor(_) => true,
PathAction::SearchCurrentFileFor(_) => false,
PathAction::ImportAll(_) => true,
}
Expand All @@ -248,7 +245,6 @@ impl PathAction {
PathAction::NameLastItemAs(_) => false,
PathAction::SearchCoreModulesFor(_) => true,
PathAction::SearchProjectRootFor(_) => true,
PathAction::SearchLastModuleFor(_) => true,
PathAction::SearchCurrentFileFor(_) => false,
PathAction::ImportAll(_) => false,
}
Expand All @@ -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(),
}
Expand All @@ -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(),
Expand Down Expand Up @@ -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)]
Expand Down
5 changes: 5 additions & 0 deletions src/frontend/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>) {
let err_col = "d_red";
let target_col = "l_magenta";
Expand Down
4 changes: 0 additions & 4 deletions src/ir8/mod.rs

This file was deleted.

36 changes: 0 additions & 36 deletions src/ir8/tomato.rs

This file was deleted.

30 changes: 0 additions & 30 deletions src/ir8/visitir.rs

This file was deleted.

Loading

0 comments on commit 8913a01

Please sign in to comment.