feat(all): a lot of features and changed to HVM2

This commit is contained in:
felipegchi 2022-11-23 13:08:02 -03:00
parent b727dc3308
commit 6dd1bffae2
23 changed files with 163 additions and 295 deletions

168
Cargo.lock generated
View File

@ -236,27 +236,6 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "filetime"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"windows-sys",
]
[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
[[package]]
name = "fxhash"
version = "0.2.1"
@ -295,66 +274,18 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03"
[[package]]
name = "hvm"
version = "1.0.1-beta"
version = "1.0.4-beta"
source = "git+https://github.com/Kindelia/HVM.git#169f82733a4cbfe15f3d49d45a8aef02c24de18d"
dependencies = [
"clap 3.2.23",
"hvm-compiler",
"hvm-derive",
"hvm-parser",
"hvm-runtime",
"hvm-syntax",
]
[[package]]
name = "hvm-compiler"
version = "0.1.0"
dependencies = [
"hvm-parser",
"hvm-runtime",
"hvm-syntax",
"itertools",
]
[[package]]
name = "hvm-derive"
version = "0.1.0"
dependencies = [
"hvm-parser",
"hvm-runtime",
"hvm-syntax",
"itertools",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "hvm-parser"
version = "0.1.0"
dependencies = [
"highlight_error",
"hvm-syntax",
]
[[package]]
name = "hvm-runtime"
version = "1.0.1-beta"
dependencies = [
"crossbeam",
"highlight_error",
"hvm-parser",
"hvm-syntax",
"im",
"instant",
"itertools",
"sysinfo",
]
[[package]]
name = "hvm-syntax"
version = "0.1.0"
[[package]]
name = "im"
version = "15.1.0"
@ -379,26 +310,6 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inotify"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
"bitflags",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -460,8 +371,6 @@ dependencies = [
"kind-driver",
"kind-query",
"kind-report",
"notify",
"notify-debouncer-mini",
"ntest",
"pretty_assertions",
"walkdir",
@ -552,6 +461,7 @@ version = "0.1.0"
name = "kind-target-hvm"
version = "0.1.0"
dependencies = [
"hvm",
"kind-derive",
"kind-report",
"kind-span",
@ -561,6 +471,13 @@ dependencies = [
[[package]]
name = "kind-target-kdl"
version = "0.1.0"
dependencies = [
"hvm",
"kind-derive",
"kind-report",
"kind-span",
"kind-tree",
]
[[package]]
name = "kind-tree"
@ -572,26 +489,6 @@ dependencies = [
"linked-hash-map",
]
[[package]]
name = "kqueue"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [
"kqueue-sys",
"libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "libc"
version = "0.2.137"
@ -632,45 +529,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mio"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys",
]
[[package]]
name = "notify"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a"
dependencies = [
"bitflags",
"crossbeam-channel",
"filetime",
"fsevent-sys",
"inotify",
"kqueue",
"libc",
"mio",
"walkdir",
"winapi 0.3.9",
]
[[package]]
name = "notify-debouncer-mini"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b"
dependencies = [
"notify",
]
[[package]]
name = "ntapi"
version = "0.4.0"
@ -1071,12 +929,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.83"

View File

@ -1,21 +1,21 @@
[workspace]
members = [
"src/kind-cli",
"src/kind-tree",
"src/kind-span",
"src/kind-parser",
"src/kind-pass",
"src/kind-report",
"src/kind-checker",
"src/kind-driver",
"src/kind-report",
"src/kind-target-kdl",
"src/kind-target-hvm",
"src/kind-derive",
# "src/kind-optimization",
# "src/kind-lint",
# "src/kind-query",
# "src/kind-macros",
"crates/kind-cli",
"crates/kind-tree",
"crates/kind-span",
"crates/kind-parser",
"crates/kind-pass",
"crates/kind-report",
"crates/kind-checker",
"crates/kind-driver",
"crates/kind-report",
"crates/kind-target-kdl",
"crates/kind-target-hvm",
"crates/kind-derive",
# "crates/kind-optimization",
# "crates/kind-lint",
# "crates/kind-query",
# "crates/kind-macros",
]
[profile.release]

View File

@ -10,7 +10,7 @@ kind-tree = { path = "../kind-tree" }
kind-span = { path = "../kind-span" }
kind-report = { path = "../kind-report" }
hvm = { path = "../../../HVM/crates/hvm", features = ["derive"] }
hvm = { git = "https://github.com/Kindelia/HVM.git" }
fxhash = "0.2.1"
im = "15.1.0"

View File

@ -956,5 +956,4 @@
(Kind.Term.set_origin new_origin (Kind.Term.fn13 fnid old_orig x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12)) = (Kind.Term.fn13 fnid new_origin x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12)
(Kind.Term.set_origin new_origin (Kind.Term.fn14 fnid old_orig x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13)) = (Kind.Term.fn14 fnid new_origin x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13)
(Kind.Term.set_origin new_origin (Kind.Term.fn15 ctid old_orig args)) = (Kind.Term.fn15 ctid new_origin args)
(Kind.Term.set_origin new_origin (Kind.Term.fn16 ctid old_orig args)) = (Kind.Term.fn16 ctid new_origin args)
(Kind.Term.set_origin new_origin (Kind.Term.fn16 ctid old_orig args)) = (Kind.Term.fn16 ctid new_origin args)

View File

@ -9,7 +9,7 @@ use kind_span::Span;
use kind_tree::desugared::{self, Book, Expr};
use kind_tree::symbol::{Ident, QualifiedIdent};
use hvm::syntax as lang;
use hvm::{syntax as lang, u60};
mod tags;
@ -68,7 +68,9 @@ fn mk_var(ident: &str) -> Box<Term> {
}
fn mk_u60(numb: u64) -> Box<Term> {
Box::new(Term::U6O { numb })
Box::new(Term::U6O {
numb: u60::new(numb),
})
}
fn mk_single_ctr(head: String) -> Box<Term> {
@ -90,7 +92,7 @@ fn mk_ctr_name_from_str(ident: &str) -> Box<Term> {
fn span_to_num(span: Span) -> Box<Term> {
Box::new(Term::U6O {
numb: span.encode().0,
numb: u60::new(span.encode().0),
})
}
@ -512,7 +514,10 @@ fn codegen_entry(file: &mut lang::File, entry: &desugared::Entry) {
/// Compiles a book into an format that is executed by the
/// type checker in HVM.
pub fn codegen_book(book: &Book, functions_to_check: Vec<String>) -> lang::File {
let mut file = lang::File { rules: vec![] };
let mut file = lang::File {
rules: vec![],
smaps: vec![],
};
let functions_entry = lang::Rule {
lhs: mk_ctr("Functions".to_owned(), vec![]),
@ -530,5 +535,14 @@ pub fn codegen_book(book: &Book, functions_to_check: Vec<String>) -> lang::File
rhs: mk_u60(book.holes),
});
for rule in &file.rules {
match &*rule.lhs {
Term::Ctr { name, args } => {
file.smaps.push((name.clone(), vec![false; args.len()]));
}
_ => todo!(),
}
}
file
}

View File

@ -78,15 +78,15 @@ impl Diagnostic for TypeError {
Subtitle::Phrase(
Color::Fst,
vec![
Word::White("Expected :".to_string()),
Word::Painted(Color::Fst, detected.to_string()),
Word::White("Got :".to_string()),
Word::Painted(Color::Fst, expected.to_string()),
],
),
Subtitle::Phrase(
Color::Snd,
vec![
Word::White("Got :".to_string()),
Word::Painted(Color::Snd, expected.to_string()),
Word::White("Expected :".to_string()),
Word::Painted(Color::Snd, detected.to_string()),
],
),
];

View File

@ -9,19 +9,42 @@ pub mod report;
use std::sync::mpsc::Sender;
use hvm::derive::pre_compute_file;
use hvm::{runtime::runtime, syntax::Term};
use hvm::language;
use hvm::{runtime, syntax::Term};
use kind_report::data::Diagnostic;
use kind_tree::desugared::Book;
use report::parse_report;
pre_compute_file!(PRECOMPILED_TYPE_CHECKER, "checker.hvm");
pub const CHECKER: &str = include_str!("checker.hvm");
pub fn eval(file: &str, term: &str, dbug: bool) -> Result<Box<Term>, String> {
let file = language::syntax::read_file(&format!("{}\nHVM_MAIN_CALL = {}", file, term))?;
let book = language::rulebook::gen_rulebook(&file);
let mut prog = runtime::Program::new();
prog.add_book(&book);
let size = runtime::default_heap_size();
let tids = runtime::default_heap_tids();
let heap = runtime::new_heap(size, tids);
let tids = runtime::new_tids(tids);
runtime::link(
&heap,
0,
runtime::Fun(*book.name_to_id.get("HVM_MAIN_CALL").unwrap(), 0),
);
let host = 0;
runtime::normalize(&heap, &prog, &tids, host, dbug);
let code = language::readback::as_term(&heap, &prog, host);
runtime::collect(&heap, &prog.aris, tids[0], runtime::load_ptr(&heap, host));
runtime::free(&heap, 0, 0, 1);
Ok(code)
}
/// Generates the checker in a string format that can be
/// parsed by HVM.
pub fn gen_checker(book: &Book, functions_to_check: Vec<String>) -> String {
let file = compiler::codegen_book(book, functions_to_check);
file.to_string()
let mut checker = CHECKER.to_string();
checker.push_str(&compiler::codegen_book(book, functions_to_check).to_string());
checker
}
/// Type checks a dessugared book. It spawns an HVM instance in order
@ -31,44 +54,24 @@ pub fn type_check(
tx: Sender<Box<dyn Diagnostic>>,
functions_to_check: Vec<String>,
) -> bool {
let file = compiler::codegen_book(book, functions_to_check);
let book = language::rulebook::gen_rulebook(&file, PRECOMPILED_TYPE_CHECKER);
let file = gen_checker(book, functions_to_check);
let mut prog = runtime::Program::new(PRECOMPILED_TYPE_CHECKER);
prog.add_book(&book);
match eval(&file.to_string(), "Main", false) {
Ok(term) => {
let errs = parse_report(&term).expect(&format!(
"Internal Error: Cannot parse the report message from the type checker: {}",
term
));
let succeeded = errs.is_empty();
let heap = runtime::new_heap(runtime::default_heap_size(), runtime::default_heap_tids());
let tids = runtime::new_tids(runtime::default_heap_tids());
for err in errs {
tx.send(Box::new(err)).unwrap()
}
// Allocates the main term
runtime::link(
&heap,
0,
runtime::Fun(*book.name_to_id.get("Main").unwrap(), 0),
);
let host = 0;
// Normalizes it
runtime::normalize(&heap, &prog, &tids, host, false);
// Reads it back to a string
let term = language::readback::as_term(&heap, &prog, host);
// Frees used memory
runtime::collect(&heap, &prog.arit, tids[0], runtime::load_ptr(&heap, host));
runtime::free(&heap, 0, 0, 1);
let errs = parse_report(&term).expect(&format!(
"Internal Error: Cannot parse the report message from the type checker: {}",
term
));
let succeeded = errs.is_empty();
for err in errs {
tx.send(Box::new(err)).unwrap()
succeeded
}
Err(_) => panic!(),
}
succeeded
}
/// Runs the type checker but instead of running the check all function
@ -76,9 +79,12 @@ pub fn type_check(
/// and the checker can understand.
pub fn eval_api(book: &Book) -> Box<Term> {
let file = compiler::codegen_book(book, Vec::new());
let book = language::rulebook::gen_rulebook(&file, PRECOMPILED_TYPE_CHECKER);
let mut prog = runtime::Program::new(PRECOMPILED_TYPE_CHECKER);
let file = language::syntax::read_file(&file.to_string()).unwrap();
let book = language::rulebook::gen_rulebook(&file);
let mut prog = runtime::Program::new();
prog.add_book(&book);
let heap = runtime::new_heap(runtime::default_heap_size(), runtime::default_heap_tids());
@ -99,7 +105,7 @@ pub fn eval_api(book: &Book) -> Box<Term> {
let term = language::readback::as_term(&heap, &prog, host);
// Frees used memory
runtime::collect(&heap, &prog.arit, tids[0], runtime::load_ptr(&heap, host));
runtime::collect(&heap, &prog.aris, tids[0], runtime::load_ptr(&heap, host));
runtime::free(&heap, 0, 0, 1);
term

View File

@ -71,9 +71,11 @@ fn parse_qualified(term: &Term) -> Result<QualifiedIdent, String> {
None,
Range::ghost_range(),
)),
Term::Ctr { name, args: _ } => {
Ok(QualifiedIdent::new_static(name, None, Range::ghost_range()))
}
Term::Ctr { name, args: _ } => Ok(QualifiedIdent::new_static(
&name[..name.len() - 1],
None,
Range::ghost_range(),
)),
_ => Err("Error while matching qualified".to_string()),
}
}

View File

@ -20,8 +20,6 @@ kind-checker = { path = "../kind-checker" }
kind-query = { path = "../kind-query" }
clap = { version = "4.0.10", features = ["derive"] }
notify-debouncer-mini = { version = "*", default-features = false }
notify = "5.0.0"
[dev-dependencies]

View File

@ -201,7 +201,7 @@ pub fn run_cli(config: Cli) {
});
if let Some(res) = res {
match driver::execute_file(res) {
match driver::execute_file(&res.to_string()) {
Ok(res) => println!("{}", res),
Err(err) => println!("{}", err),
}

View File

@ -85,7 +85,7 @@ fn test_eval() -> Result<(), Error> {
match check {
Some(file) if diagnostics.is_empty() => {
driver::execute_file(file).map_or_else(|e| e, |f| f)
driver::execute_file(&file.to_string()).map_or_else(|e| e, |f| f)
}
_ => {
let mut res_string = String::new();

View File

@ -13,8 +13,7 @@ kind-report = { path = "../kind-report" }
kind-checker = { path = "../kind-checker" }
kind-pass = { path = "../kind-pass" }
kind-target-hvm = { path = "../kind-target-hvm" }
hvm = { path = "../../../HVM/crates/hvm" }
hvm = { git = "https://github.com/Kindelia/HVM.git" }
strsim = "0.10.0"
fxhash = "0.2.1"

View File

@ -1,3 +1,4 @@
use checker::eval;
use errors::DriverError;
use fxhash::FxHashSet;
use kind_pass::{desugar, erasure, expand};
@ -102,9 +103,9 @@ pub fn check_main_entry(session: &mut Session, book: &desugared::Book) -> Option
}
}
pub fn execute_file(file: backend::File) -> Result<String, String> {
let res = hvm::eval_main_default(file)?;
Ok(res.0)
pub fn execute_file(file: &str) -> Result<String, String> {
let res = eval(file, "Main", false)?;
Ok(res.to_string())
}
pub fn eval_in_checker(book: &desugared::Book) -> Box<backend::Term> {

View File

@ -267,7 +267,7 @@ impl<'a> Parser<'a> {
},
_ => {
let (range_end, spine) = self.parse_call_tail(id.range, multiline)?;
range = range_end;
range = range.mix(range_end);
ExprKind::Constr {
name: id,
args: spine,

View File

@ -105,6 +105,10 @@ impl<'a> Lexer<'a> {
self.mk_range(start),
)
}
'_' => {
self.accumulate_while(&is_valid_id);
(Token::Hole, self.mk_range(start))
}
c if is_valid_id_start(*c) => {
let str = self.accumulate_while(&is_valid_id);
(Lexer::to_keyword(str), self.mk_range(start))

View File

@ -150,7 +150,10 @@ impl<'a> ErasureState<'a> {
// TODO: It should unify iff we want functions that are considered
// "erased" in the sense that we can just remove them from the runtime and it'll
// be fine.
(None, Relevance::Irrelevant) => false,
(None, Relevance::Irrelevant) => {
self.holes[hole] = Some(Relevance::Irrelevant);
true
}
(None, Relevance::Hole(n)) => {
self.holes[hole] = Some(Relevance::Hole(n));
@ -261,7 +264,14 @@ impl<'a> ErasureState<'a> {
use kind_tree::desugared::ExprKind::*;
match &expr.data {
Typ | NumType(_) | Num(_) | Str(_) | Err => Box::new(expr.clone()),
Num(_) | Str(_) => Box::new(expr.clone()),
Typ | NumType(_) | Err => {
let span = expr.span.to_range().unwrap();
if !self.unify(span, *on, (None, Relevance::Irrelevant), false) {
self.err_irrelevant(None, span, None)
}
Box::new(expr.clone())
}
Hole(_) | Hlp(_) => match &expr.span {
kind_span::Span::Generated => Box::new(expr.clone()),
kind_span::Span::Locatable(span) => {
@ -281,6 +291,11 @@ impl<'a> ErasureState<'a> {
Box::new(expr.clone())
}
All(name, typ, body, _erased) => {
let span = expr.span.to_range().unwrap_or_else(|| name.range.clone());
if !self.unify(span, *on, (None, Relevance::Irrelevant), false) {
self.err_irrelevant(None, span, None)
}
let ctx = self.ctx.clone();
// Relevant inside the context that is it's being used?
@ -299,6 +314,11 @@ impl<'a> ErasureState<'a> {
name.to_string(),
(name.range, (None, Relevance::Irrelevant)),
);
let span = expr.span.to_range().unwrap_or_else(|| name.range.clone());
if !self.unify(span, *on, (None, Relevance::Irrelevant), false) {
self.err_irrelevant(None, span, None)
}
} else {
self.ctx.insert(name.to_string(), (name.range, *on));
}
@ -334,6 +354,10 @@ impl<'a> ErasureState<'a> {
.iter()
.map(|x| {
let on = if x.erased {
let span = expr.span.to_range().unwrap();
if !self.unify(span, *on, (None, Relevance::Irrelevant), false) {
self.err_irrelevant(None, span, None)
}
(x.data.span.to_range(), Relevance::Irrelevant)
} else {
on.clone()

View File

@ -2,18 +2,17 @@ use fxhash::{FxHashSet, FxHashMap};
#[derive(Debug)]
pub struct Node<T> {
pub children: FxHashSet<usize>,
pub parents: FxHashSet<usize>,
pub data: T,
pub invalidated: bool,
pub hash: u64,
pub children: FxHashSet<usize>,
pub parents: FxHashSet<usize>,
pub root: bool,
pub failed: bool,
}
#[derive(Debug)]
pub struct Graph<T> {
// Using a hashmap to make it easier to add or remove node.s
nodes: FxHashMap<usize, Node<T>>,
count: usize,
}
@ -58,38 +57,7 @@ impl<T> Graph<T> {
}
}
fn remove_recursive(&mut self, node_idx: usize, to_delete: &mut FxHashSet<usize>) {
if let Some(node) = self.nodes.remove(&node_idx) {
let children = node.children.clone();
let parents = node.parents.clone();
for child_idx in children {
if let Some(child) = self.nodes.get_mut(&child_idx) {
child.parents.remove(&node_idx);
if child.parents.is_empty() && !child.root {
to_delete.insert(child_idx);
self.remove_recursive(child_idx, to_delete)
}
}
}
for parent in parents {
if let Some(parent) = self.nodes.get_mut(&parent) {
parent.children.remove(&node_idx);
}
self.flood_invalidation(parent);
}
}
}
pub fn remove(&mut self, node_idx: usize) -> FxHashSet<usize> {
let mut fx = Default::default();
self.remove_recursive(node_idx, &mut fx);
fx.insert(node_idx);
fx
}
pub fn disconnect_parent(&mut self, child: usize, parent: usize) -> bool {
pub fn disconnect(&mut self, child: usize, parent: usize) -> bool {
if let Some(parent) = self.nodes.get_mut(&parent) {
parent.children.remove(&child);
}

View File

@ -10,3 +10,5 @@ kind-span = { path = "../kind-span" }
kind-tree = { path = "../kind-tree" }
kind-report = { path = "../kind-report" }
kind-derive = { path = "../kind-derive" }
hvm = { git = "https://github.com/Kindelia/HVM.git" }

View File

@ -1,3 +1,5 @@
use hvm::u60;
use kind_tree::{
backend::{File, Rule, Term},
desugared,
@ -6,6 +8,7 @@ use kind_tree::{
pub fn compile_book(book: desugared::Book) -> File {
let mut file = File {
rules: Default::default(),
smaps: Default::default(),
};
for (_, entry) in book.entrs {
compile_entry(&mut file, *entry);
@ -40,13 +43,15 @@ pub fn compile_term(expr: &desugared::Expr) -> Box<Term> {
}),
Ann(left, _) => compile_term(left),
Sub(_, _, _, expr) => compile_term(expr),
Num(kind_tree::Number::U60(numb)) => Box::new(Term::U6O { numb: *numb }),
Num(kind_tree::Number::U60(numb)) => Box::new(Term::U6O {
numb: u60::new(*numb),
}),
Num(kind_tree::Number::U120(numb)) => {
let hi = Box::new(Term::U6O {
numb: (numb >> 60) as u64,
numb: u60::new((numb >> 60) as u64),
});
let lo = Box::new(Term::U6O {
numb: (numb & 0xFFFFFFFFFFFFFFF) as u64,
numb: u60::new((numb & 0xFFFFFFFFFFFFFFF) as u64),
});
Box::new(Term::Ctr {
name: String::from("U120.new"),

View File

@ -6,3 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
kind-span = { path = "../kind-span" }
kind-tree = { path = "../kind-tree" }
kind-report = { path = "../kind-report" }
kind-derive = { path = "../kind-derive" }
hvm = { git = "https://github.com/Kindelia/HVM.git" }

View File

@ -1,14 +1 @@
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);
}
}
mod term;

View File

@ -0,0 +1 @@

View File

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
hvm = { path = "../../../HVM/crates/hvm" }
hvm = { git = "https://github.com/Kindelia/HVM.git" }
kind-span = {path = "../kind-span"}
linked-hash-map = "0.5.6"