Skip to content

Commit

Permalink
Merge pull request #26 from JCBurnside/feature/global_curries
Browse files Browse the repository at this point in the history
global curries and intialization of said globals.
  • Loading branch information
JCBurnside authored Apr 7, 2024
2 parents 9c816ce + 5263451 commit 62d4b0e
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 76 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
// },

"program": "${workspaceFolder}/target/debug/cli",
"args":["--llvm", "-o", "./test_output.llvm", "./cli/test.fb"],
"args":["--llvm", "-o", "./test_output.llvm", "./sample.fb"],
"cwd": "${workspaceFolder}",
"env": {"RUST_BACKTRACE": "1"},
"console": "externalTerminal",
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ impl TopLevelValue {
}

fn get_dependencies(&self) -> HashSet<String> {
self.value.get_dependencies(vec![self.ident.clone()])
let mut values = self.args.iter().flat_map(ArgDeclaration::get_idents).collect_vec();
values.push(self.ident.clone());
self.value.get_dependencies(values)
}
}
#[derive(Debug, PartialEq, Clone)]
Expand Down
49 changes: 29 additions & 20 deletions compiler/src/inference.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{cmp::Ordering, collections::HashMap};
use std::{cmp::Ordering, collections::{HashMap, HashSet}};

use itertools::Itertools;

Expand Down Expand Up @@ -556,25 +556,9 @@ impl Context {
name: _,
decls,
} = module;
let order = self.dependency_tree.iter().sorted_by(|(lhs_name,lhs_depends), (rhs_name,rhs_depends)| {
match (lhs_depends.contains(*rhs_name), rhs_depends.contains(*lhs_name)) {
(true,true) => {
if decls.iter().find(|decl| &decl.get_ident() == *lhs_name).map_or(false, ast::TopLevelDeclaration::has_ty) {
Ordering::Less//left has explict type so it can come first
} else if decls.iter().find(|decl| &decl.get_ident() == *rhs_name).map_or(false, ast::TopLevelDeclaration::has_ty) {
Ordering::Greater//right has explict type so it can come first
} else {
todo!("remove this case. both lhs and rhs. means they depend on each other.")
}
}
(false, true) => Ordering::Less,//right depends on left thus should appear after.
(true, false) => Ordering::Greater,//left depends on right thus should appear after.
(false,false) => Ordering::Equal,//neither depend on each other.
}
})
.map(|(a,_)|a)
.cloned()
.collect_vec();
let items = self.dependency_tree.keys().cloned().collect();
let order = sort_on_tree(items, &self.dependency_tree);
let order = dbg!(order);
decls.sort_by_key(|decl| order.iter().position(|name| name == &decl.get_ident()));
for decl in decls {
self.known_locals.clear();
Expand Down Expand Up @@ -1806,6 +1790,31 @@ impl Context {
}
}

fn sort_on_tree(src : Vec<String>, dependencies : &HashMap<String,Vec<String>>) -> Vec<String> {
let mut sorted = Vec::with_capacity(src.len());
let mut visited = HashSet::with_capacity(src.len());
for item in src {
visit(item,&mut visited, &mut sorted,dependencies);
}
sorted
}

fn visit(item:String, visited:&mut HashSet<String>, sorted:&mut Vec<String>, dependencies : &HashMap<String,Vec<String>>) {
if !visited.contains(&item) {
visited.insert(item.clone());
if let Some(deps) = dependencies.get(&item) {
for dep in deps {
visit(dep.clone(),visited,sorted,dependencies)
}
}
sorted.push(item)
} else {
if !sorted.contains(&item) {
panic!("cylic");
}
}
}

#[cfg(test)]
impl Context {
fn reset(&mut self) {
Expand Down
83 changes: 75 additions & 8 deletions compiler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::HashMap;
use std::{cmp::Ordering, collections::HashMap};
use std::path::PathBuf;

pub mod ast;
Expand All @@ -12,9 +12,10 @@ pub mod types;
mod util;

use itertools::Itertools;
use regex::CaptureNames;
use thiserror::Error;

use typed_ast::TypedModuleDeclaration;
use typed_ast::{TypedDeclaration, TypedExpr, TypedFnCall, TypedModuleDeclaration, TypedTopLevelValue, TypedValueType};

#[derive(Error, Debug)]
#[error(transparent)]
Expand Down Expand Up @@ -90,6 +91,75 @@ pub fn get_ast(input: &str, file_name: &str) -> typed_ast::TypedModuleDeclaratio
let ast = infer_context.inference(module);
TypedModuleDeclaration::from(ast, &HashMap::new(), &ops)
}
fn unfold_global_curries(mut ast:TypedModuleDeclaration, external_globals : HashMap<String,TypedExpr>, dtree : HashMap<String,Vec<String>>) -> TypedModuleDeclaration {
let decls = &mut ast.declarations;
let order = dtree.into_iter().sorted_by(|(lhs_name,lhs_depends), (rhs_name,rhs_depends)| {
match (lhs_depends.contains(rhs_name), rhs_depends.contains(lhs_name)) {
(true,true) => {
todo!("remove this case. both lhs and rhs. means they depend on each other.")
}
(false, true) => Ordering::Less,//right depends on left thus should appear after.
(true, false) => Ordering::Greater,//left depends on right thus should appear after.
(false,false) => Ordering::Equal,//neither depend on each other.
}
})
.map(|(a,_)|a)
.collect_vec();
let mut values = external_globals;
values.extend(decls.iter().filter(|decl|if let TypedDeclaration::Value(TypedTopLevelValue{args, ..}) = decl {
args.is_empty()
} else {
false
}).map(|decl| {
let TypedDeclaration::Value(decl) = decl else { unreachable!() };
let TypedValueType::Expr(expr) = &decl.value else { unreachable!() };
(decl.ident.clone(), expr.clone())
}));
for decl in decls.iter_mut()
.filter(|decl|
if let TypedDeclaration::Value(TypedTopLevelValue{args, ..}) =decl {
args.is_empty()
} else {
false
}
)
.sorted_by_cached_key(|decl| order.iter().position(|name| name == &decl.get_ident())) {
let TypedDeclaration::Value(decl) = decl else {unreachable!() };
let TypedValueType::Expr(expr) = &mut decl.value else { unreachable!() };
replace_values(expr, &values);
values.insert(decl.ident.clone(), expr.clone());
}
ast
}

fn replace_values(expr:&mut TypedExpr, values : &HashMap<String,TypedExpr>) {
match expr {
TypedExpr::FnCall(call) if call.is_extern => {
call.arg.as_mut().map(|arg| replace_values(arg.as_mut(), values));
},
TypedExpr::FnCall(call) => {
replace_values(call.value.as_mut(), values);
call.arg.as_mut().map(|expr| replace_values(expr.as_mut(), values));
},
TypedExpr::ValueRead(name, _, _) => {
if let Some(new_expr) = values.get(name) {
*expr = new_expr.clone();
}
}
TypedExpr::TupleLiteral { contents,.. }
| TypedExpr::ListLiteral { contents }
| TypedExpr::ArrayLiteral { contents, .. } => {
for expr in contents {
replace_values(expr, values);
}
}
TypedExpr::BinaryOpCall(biop) => {
replace_values(&mut biop.lhs, values);
replace_values(&mut biop.rhs, values);
}
_ => ()
}
}

pub fn from_file<'ctx>(
file: &PathBuf,
Expand Down Expand Up @@ -134,24 +204,21 @@ pub fn from_file<'ctx>(
let errors = errors.into_iter().map(Error::from).collect_vec();
ast.canonialize(vec![project_name]);
let dependency_graph = ast.get_dependencies();
let dependency_tree = dependency_graph
let dependency_tree : HashMap<_,_> = dependency_graph
.into_iter()
.map(|(key, value)| (key, value.into_iter().collect()))
.collect();
let mut inference_context = inference::Context::new(
dependency_tree,
dbg!(dependency_tree.clone()),
fwd_declarations.clone(),
HashMap::new(),
fwd_ops.clone(),
HashMap::new(),
);
let ast = inference_context.inference(ast);

let mut ast = TypedModuleDeclaration::from(ast, &fwd_declarations, &fwd_ops); //TODO: foward declare std lib
// #[cfg(debug_assertions)]
// println!("{:?}", ast.declarations);
use std::io::Write;
ast.lower_generics(&HashMap::new());
let ast = unfold_global_curries(ast,HashMap::new(),dependency_tree);
(
if errors.is_empty() {
Ok(ast)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/typed_ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ pub enum TypedDeclaration {
}

impl TypedDeclaration {
fn get_ident(&self) -> String {
pub(crate) fn get_ident(&self) -> String {
match self {
Self::Value(v) => v.ident.clone(),
Self::TypeDefinition(decl) => decl.get_ident(),
Expand Down
Loading

0 comments on commit 62d4b0e

Please sign in to comment.