feat: finished a simple version of the query handler

This commit is contained in:
Felipe g 2022-10-12 19:51:34 -03:00
parent 77a452e5fb
commit e2a4df9577
10 changed files with 306 additions and 242 deletions

View File

@ -1,8 +1,17 @@
[package]
name = "kind-cli"
version = "0.1.0"
version = "0.3.0"
edition = "2021"
description = "A pure functional functional language that uses the HVM."
repository = "https://github.com/Kindelia/Kind2"
license = "MIT"
keywords = ["functional", "language", "type-theory", "proof-assistant"]
[[bin]]
name = "kind2"
path = "src/main.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = { version = "4.0.10", features = ["derive"] }

View File

@ -1,14 +0,0 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}

79
src/kind-cli/src/main.rs Normal file
View File

@ -0,0 +1,79 @@
use std::path::PathBuf;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
#[clap(propagate_version = true)]
struct Cli {
/// Configuration file to change information about
/// pretty printing or project root.
#[arg(short, long, value_name = "FILE")]
config: Option<PathBuf>,
/// Turn on the debugging information generated
/// by the compiler.
#[arg(short, long)]
debug: bool,
/// Show warning messages
#[arg(short, long)]
warning: bool,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
/// Check a file
#[clap(aliases = &["c"])]
Check { file: String },
/// Evaluates Main on Kind2
#[clap(aliases = &["e"])]
Eval { file: String },
/// Runs Main on the HVM
#[clap(aliases = &["r"])]
Run { file: String },
/// Derives .kind2 files from a .type file
#[clap(aliases = &["der"])]
Derive { file: String },
/// Generates a checker (.hvm) for a file
#[clap(aliases = &["gc"])]
GenChecker { file: String },
/// Stringifies a file
#[clap(aliases = &["s"])]
Show { file: String },
/// Compiles a file to Kindelia (.kdl)
#[clap(aliases = &["kdl"])]
ToKDL {
file: String,
/// If given, a namespace that goes before each compiled name. Can be at most 10 charaters long.
#[clap(long, aliases = &["ns"])]
namespace: Option<String>,
},
/// Compiles a file to HVM (.hvm)
#[clap(aliases = &["hvm"])]
ToHVM { file: String },
/// Watch for file changes and then
/// check when some file change.
#[clap(aliases = &["w"])]
Watch { file: String },
/// Read eval print loop
#[clap(aliases = &["re"])]
Repl,
}
fn main() {
let _ = Cli::parse();
}

View File

@ -0,0 +1,117 @@
use std::{
collections::{HashSet},
sync::{Arc, RwLock},
};
use dashmap::DashMap;
#[derive(Default, Debug)]
pub struct Edge {
pub children: HashSet<u64>,
pub parents: HashSet<u64>,
pub updated: bool,
pub database: u8,
}
#[derive(Default, Clone, Debug)]
pub struct DepGraph {
pub edges: Arc<DashMap<u64, Arc<RwLock<Edge>>>>,
}
impl DepGraph {
pub fn add(&mut self, parent: u64, child: u64, db: u8) -> Arc<RwLock<Edge>> {
let edges = self.edges.clone();
// I'm not sure on how DashMap drops the Shard guard
// so it forces some drop I think.
{
if parent != child {
let entry_arc = edges.entry(parent).or_default();
let mut entry = entry_arc.write().unwrap();
entry.children.insert(child);
entry.database = db;
}
}
{
let entry_arc = edges.entry(child).or_default();
let mut entry = entry_arc.write().unwrap();
if parent != child {
entry.parents.insert(parent);
}
entry_arc.clone()
}
}
pub fn add_single(&self, child: u64, db: u8) -> Arc<RwLock<Edge>> {
let edges = self.edges.clone();
let entry_c = edges.entry(child).or_default();
let mut entry = entry_c.write().unwrap();
entry.database = db;
entry_c.clone()
}
pub fn updated(&self, node_id: u64) -> bool {
if let Some(res) = self.edges.get(&node_id) {
let entry = res.read().unwrap();
entry.updated
} else {
false
}
}
pub fn remove_direct_child(&self, node_id: u64) -> HashSet<u64> {
let edges = self.edges.clone();
let mut children = HashSet::new();
edges.entry(node_id).and_modify(|node| {
let mut node = node.write().unwrap();
children = node.children.clone();
node.children = HashSet::new();
});
for child_id in &children {
edges.entry(*child_id).and_modify(|child| {
let mut child = child.write().unwrap();
child.parents.remove(&node_id);
});
}
children
}
pub fn remove(&self, node_id: u64, dangling: bool) -> Vec<u64> {
let mut to_delete = Vec::new();
{
let edges = self.edges.clone();
let mut children = HashSet::new();
let mut parents = HashSet::new();
edges.entry(node_id).and_modify(|node| {
let node = node.read().unwrap();
children = node.children.clone();
parents = node.parents.clone();
});
if dangling && parents.len() != 0 {
return vec![];
}
for parent_id in parents {
edges.entry(parent_id).and_modify(|parent| {
let mut parent = parent.write().unwrap();
parent.updated = true;
parent.children.remove(&node_id);
});
}
for child_id in children {
edges.entry(child_id).and_modify(|child| {
let mut child = child.write().unwrap();
child.parents.remove(&node_id);
if child.parents.len() == 0 {
to_delete.push(child_id);
}
});
}
edges.remove(&node_id);
}
to_delete
}
}

View File

@ -0,0 +1,2 @@
pub mod graph;
pub mod store;

View File

@ -0,0 +1,86 @@
use std::sync::{Arc, RwLock};
use crate::core::graph::{DepGraph, Edge};
pub trait Session: Clone {
fn delete_from_cache(&self, node_id: u64, db_idx: u8);
fn dependency_graph(&self) -> DepGraph;
fn get_parent(&self) -> Option<u64>;
fn set_parent(&mut self, hash: u64);
fn delete(&self, node_id: u64) {
let graph = self.dependency_graph();
let edge = graph.edges.get(&node_id).map(|arc| arc.read().unwrap().database);
if let Some(db_idx) = edge {
let other_ones = graph.remove(node_id, false);
self.delete_from_cache(node_id, db_idx);
for other in other_ones {
self.delete(other);
}
}
}
fn create_edge(&self, child_hash: u64, db_idx: u8) -> Arc<RwLock<Edge>> {
let mut graph = self.dependency_graph();
if let Some(parent) = self.get_parent() {
graph.add(parent, child_hash, db_idx)
} else {
graph.add_single(child_hash, db_idx)
}
}
fn get_or_create_node(&self, child_hash: u64, db_idx: u8) -> Arc<RwLock<Edge>> {
let graph = self.dependency_graph();
let res = graph.edges.get(&child_hash);
if let Some(edge) = res {
edge.clone()
} else {
graph.add_single(child_hash, db_idx)
}
}
fn run_query_memoized<T: Clone>(&self, child_hash: u64, db: std::sync::Arc<dashmap::DashMap<u64, T>>, db_idx: u8, fun: impl FnOnce(&Self) -> T) -> (T, bool) {
let graph = self.dependency_graph();
self.create_edge(child_hash, db_idx);
if let Some(res) = db.get(&child_hash).map(|x| x.clone()) {
if !graph.updated(child_hash) {
return (res.clone(), true);
}
}
let mut ctx = self.clone();
ctx.set_parent(child_hash);
let res = fun(&ctx);
db.insert(child_hash, res.clone());
(res, false)
}
fn run_query_flat<T>(&self, child_hash: u64, fun: impl FnOnce(&Self) -> T) -> T
where
T: Clone,
{
// TODO: DbIDX sohudl be NONE \/
let edge = self.create_edge(child_hash, 255);
let children = self.dependency_graph().remove_direct_child(child_hash);
let mut ctx = self.clone();
ctx.set_parent(child_hash);
let res = fun(&ctx);
let new_children = edge.read().unwrap().children.clone();
let diff = children.difference(&new_children);
for diff_hash in diff {
self.delete(*diff_hash);
}
res
}
}

View File

@ -1,93 +0,0 @@
use std::{collections::HashSet, sync::{Arc, Condvar, Mutex}};
use dashmap::DashMap;
#[derive(Default, Debug)]
pub struct Edge {
pub children: HashSet<u64>,
pub parents: HashSet<u64>,
pub hash: u64,
pub updated: bool,
pub database: u8,
pub computing: Mutex<()>
}
#[derive(Default, Clone, Debug)]
pub struct DepGraph {
pub edges: Arc<DashMap<u64, Edge>>,
}
impl DepGraph {
pub fn add(&mut self, parent: u64, child: u64, db: u8) {
let edges = self.edges.clone();
{
let mut entry = edges.entry(parent).or_default();
entry.children.insert(child);
entry.database = db;
}
{
let mut entry = edges.entry(child).or_default();
entry.parents.insert(parent);
}
}
pub fn add_single(&mut self, child: u64, db: u8) {
let edges = self.edges.clone();
let mut entry = edges.entry(child).or_default();
entry.database = db;
}
pub fn updated(&self, node_id:u64) -> bool {
if let Some(res) = self.edges.get(&node_id) {
res.updated
} else {
false
}
}
pub fn remove(&mut self, node_id: u64, dangling: bool) -> Vec<u64> {
let mut to_delete = Vec::new();
{
let edges = self.edges.clone();
let mut children = HashSet::new();
let mut parents = HashSet::new();
edges.entry(node_id).and_modify(|node| {
children = node.children.clone();
parents = node.parents.clone();
});
if dangling && parents.len() != 0 {
return vec![];
}
for parent_id in parents {
edges.entry(parent_id).and_modify(|parent| {
parent.updated = true;
parent.children.remove(&node_id);
});
}
for child_id in children {
edges.entry(child_id).and_modify(|child| {
child.parents.remove(&node_id);
if child.parents.len() == 0 {
to_delete.push(child_id);
}
});
}
edges.remove(&node_id);
}
to_delete
}
pub fn set_hash(&mut self, node_id: u64, hash: u64) {
let edges = self.edges.clone();
edges.entry(node_id).and_modify(|node| {
if node.hash != hash {
node.hash = hash;
node.updated = true;
}
});
}
}

View File

@ -1,40 +1,17 @@
pub mod graph;
pub mod query;
pub mod session;
pub mod store;
pub mod core;
use std::sync::Arc;
use std::{rc::Rc};
use kind_macros::make_provider;
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
use crate::store::Session;
#[make_provider]
pub trait Teste {
#[input_node]
fn fib(&self, kek: u64) -> Box<u64>;
}
pub fn teste() {
let provider = TesteProvider {
fib: |db, c| {
if c > 10 {
println!("Computing {}", c);
let t = (1..10).collect::<Vec<u64>>().par_iter().map(|x| *db.fib(c-x)).sum();
println!("Finalized {}", c);
Box::new(t)
} else {
Box::new(c)
}
},
};
let db = TesteDatabase::new(Arc::new(provider));
println!("Res {}", db.fib(15));
println!("Res {}", db.fib(2));
println!("Res {}", db.fib(1));
println!("Res {}", db.fib(0));
db.delete(1);
println!("Res {}", db.fib(2));
println!("Res {}", db.fib(1));
println!("Res {}", db.fib(0));
use kind_tree::{concrete, desugared};
#[kind_macros::make_provider]
pub trait Query {
#[memoize]
fn parse_book(&self, code: String) -> Rc<concrete::Book>;
#[memoize]
fn desugarize_book(&self, book: concrete::Book) -> Rc<desugared::Book>;
}

View File

@ -1,36 +0,0 @@
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{Arc, RwLock};
use kind_report::{Chars, RenderConfig};
pub struct SessionData {
pub loaded_paths: RwLock<HashMap<PathBuf, usize>>,
pub loaded_files: RwLock<Vec<(PathBuf, String)>>,
pub render_config: RenderConfig<'static>,
pub root: PathBuf,
}
impl SessionData {
pub fn add_file(&self, path: PathBuf, code: String) -> usize {
let mut files = self.loaded_files.write().unwrap();
let mut paths = self.loaded_paths.write().unwrap();
paths.insert(path.clone(), files.len());
files.push((path, code));
files.len() - 1
}
pub fn new(root: PathBuf) -> SessionData {
SessionData {
loaded_paths: RwLock::new(HashMap::new()),
loaded_files: RwLock::new(Vec::new()),
render_config: RenderConfig {
indent: 2,
chars: Chars::unicode(),
},
root,
}
}
}
pub type Session = Arc<SessionData>;

View File

@ -1,63 +0,0 @@
use std::sync::Arc;
use crate::graph::DepGraph;
pub trait Session : Clone {
fn delete_from_cache(&self, node_id: u64, db_idx: u8);
fn dependency_graph(&self) -> DepGraph;
fn get_parent(&self) -> Option<u64>;
fn set_parent(&mut self, hash: u64);
fn delete(&self, node_id: u64) {
let edge = {self.dependency_graph().edges.get(&node_id).map(|x| x.database)};
if let Some(db_idx) = edge {
let other_ones = self.dependency_graph().remove(node_id, false);
self.delete_from_cache(node_id, db_idx);
for other in other_ones {
self.delete(other);
}
}
}
fn run_query<T: Clone>(&self, child_hash: u64, db: std::sync::Arc<dashmap::DashMap<u64,T >>, db_idx: u8, fun: impl FnOnce(&Self) -> T) -> T {
let mut graph = self.dependency_graph();
if let Some(parent) = self.get_parent() {
graph.add(
parent,
child_hash,
db_idx
);
} else {
graph.add_single(
child_hash,
db_idx
);
}
let m = {
let res = graph.edges.get(&child_hash).unwrap();
res.computing.lock().unwrap()
};
let result = db.get(&child_hash).map(|x| x.clone());
if let Some(res) = result {
if graph.updated(child_hash) {
let mut ctx = self.clone();
ctx.set_parent(child_hash);
let res = fun(&ctx);
db.insert(child_hash, res.clone());
res
} else {
res.clone()
}
} else {
let mut ctx = self.clone();
ctx.set_parent(child_hash);
let res = fun(&ctx);
db.insert(child_hash, res.clone());
res
}
}
}