mirror of
https://github.com/HigherOrderCO/Kind.git
synced 2024-10-05 19:27:30 +03:00
first kind2-hvm2 program run! sum-tree via fold
This commit is contained in:
parent
70288ef011
commit
9201bebc01
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,3 +9,4 @@ demo/
|
|||||||
.check.hs
|
.check.hs
|
||||||
guide.txt
|
guide.txt
|
||||||
.hvm
|
.hvm
|
||||||
|
.hvm/
|
||||||
|
16
book/.hvm/Cargo.lock
generated
16
book/.hvm/Cargo.lock
generated
@ -1,16 +0,0 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 3
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hvm-core"
|
|
||||||
version = "0.2.18"
|
|
||||||
dependencies = [
|
|
||||||
"nohash-hasher",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nohash-hasher"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
|
|
@ -1,31 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "hvm-core"
|
|
||||||
version = "0.2.18"
|
|
||||||
edition = "2021"
|
|
||||||
description = "HVM-Core is a massively parallel Interaction Combinator evaluator."
|
|
||||||
license = "MIT"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "hvmc"
|
|
||||||
path = "src/main.rs"
|
|
||||||
bench = false
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
name = "hvmc"
|
|
||||||
path = "src/lib.rs"
|
|
||||||
bench = false
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
codegen-units = 1
|
|
||||||
lto = "fat"
|
|
||||||
opt-level = 3
|
|
||||||
panic = "abort"
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
hvm_cli_options = []
|
|
||||||
lazy_mode = []
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
nohash-hasher = "0.2.0"
|
|
||||||
|
|
@ -1,799 +0,0 @@
|
|||||||
// An interaction combinator language
|
|
||||||
// ----------------------------------
|
|
||||||
// This file implements a textual syntax to interact with the runtime. It includes a pure AST for
|
|
||||||
// nets, as well as functions for parsing, stringifying, and converting pure ASTs to runtime nets.
|
|
||||||
// On the runtime, a net is represented by a list of active trees, plus a root tree. The textual
|
|
||||||
// syntax reflects this representation. The grammar is specified on this repo's README.
|
|
||||||
|
|
||||||
use crate::run;
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::iter::Peekable;
|
|
||||||
use std::str::Chars;
|
|
||||||
|
|
||||||
// AST
|
|
||||||
// ---
|
|
||||||
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
|
||||||
pub enum Tree {
|
|
||||||
Era,
|
|
||||||
Con { lft: Box<Tree>, rgt: Box<Tree> },
|
|
||||||
Tup { lft: Box<Tree>, rgt: Box<Tree> },
|
|
||||||
Dup { lab: run::Lab, lft: Box<Tree>, rgt: Box<Tree> },
|
|
||||||
Var { nam: String },
|
|
||||||
Ref { nam: run::Val },
|
|
||||||
Num { val: run::Val },
|
|
||||||
Op1 { opr: run::Lab, lft: run::Val, rgt: Box<Tree> },
|
|
||||||
Op2 { opr: run::Lab, lft: Box<Tree>, rgt: Box<Tree> },
|
|
||||||
Mat { sel: Box<Tree>, ret: Box<Tree> },
|
|
||||||
}
|
|
||||||
|
|
||||||
type Redex = Vec<(Tree, Tree)>;
|
|
||||||
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq, Debug)]
|
|
||||||
pub struct Net {
|
|
||||||
pub root: Tree,
|
|
||||||
pub rdex: Redex,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Book = BTreeMap<String, Net>;
|
|
||||||
|
|
||||||
// Parser
|
|
||||||
// ------
|
|
||||||
|
|
||||||
// FIXME: remove after skip is fixed
|
|
||||||
fn skip_spaces(chars: &mut Peekable<Chars>) {
|
|
||||||
while let Some(c) = chars.peek() {
|
|
||||||
if !c.is_ascii_whitespace() {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
chars.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: detect two '/' for comments, allowing us to remove 'skip_spaces'
|
|
||||||
fn skip(chars: &mut Peekable<Chars>) {
|
|
||||||
while let Some(c) = chars.peek() {
|
|
||||||
if *c == '/' {
|
|
||||||
chars.next();
|
|
||||||
while let Some(c) = chars.peek() {
|
|
||||||
if *c == '\n' {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
chars.next();
|
|
||||||
}
|
|
||||||
} else if !c.is_ascii_whitespace() {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
chars.next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn consume(chars: &mut Peekable<Chars>, text: &str) -> Result<(), String> {
|
|
||||||
skip(chars);
|
|
||||||
for c in text.chars() {
|
|
||||||
if chars.next() != Some(c) {
|
|
||||||
return Err(format!("Expected '{}', found {:?}", text, chars.peek()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_decimal(chars: &mut Peekable<Chars>) -> Result<u64, String> {
|
|
||||||
let mut num: u64 = 0;
|
|
||||||
skip(chars);
|
|
||||||
if !chars.peek().map_or(false, |c| c.is_digit(10)) {
|
|
||||||
return Err(format!("Expected a decimal number, found {:?}", chars.peek()));
|
|
||||||
}
|
|
||||||
while let Some(c) = chars.peek() {
|
|
||||||
if !c.is_digit(10) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
num = num * 10 + c.to_digit(10).unwrap() as u64;
|
|
||||||
chars.next();
|
|
||||||
}
|
|
||||||
Ok(num)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_name(chars: &mut Peekable<Chars>) -> Result<String, String> {
|
|
||||||
let mut txt = String::new();
|
|
||||||
skip(chars);
|
|
||||||
if !chars.peek().map_or(false, |c| c.is_alphanumeric() || *c == '_' || *c == '.') {
|
|
||||||
return Err(format!("Expected a name character, found {:?}", chars.peek()))
|
|
||||||
}
|
|
||||||
while let Some(c) = chars.peek() {
|
|
||||||
if !c.is_alphanumeric() && *c != '_' && *c != '.' {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
txt.push(*c);
|
|
||||||
chars.next();
|
|
||||||
}
|
|
||||||
Ok(txt)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_opx_lit(chars: &mut Peekable<Chars>) -> Result<String, String> {
|
|
||||||
let mut opx = String::new();
|
|
||||||
skip_spaces(chars);
|
|
||||||
while let Some(c) = chars.peek() {
|
|
||||||
if !"+-=*/%<>|&^!?".contains(*c) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
opx.push(*c);
|
|
||||||
chars.next();
|
|
||||||
}
|
|
||||||
Ok(opx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_opr(chars: &mut Peekable<Chars>) -> Result<run::Lab, String> {
|
|
||||||
let opx = parse_opx_lit(chars)?;
|
|
||||||
match opx.as_str() {
|
|
||||||
"+" => Ok(run::ADD),
|
|
||||||
"-" => Ok(run::SUB),
|
|
||||||
"*" => Ok(run::MUL),
|
|
||||||
"/" => Ok(run::DIV),
|
|
||||||
"%" => Ok(run::MOD),
|
|
||||||
"==" => Ok(run::EQ),
|
|
||||||
"!=" => Ok(run::NE),
|
|
||||||
"<" => Ok(run::LT),
|
|
||||||
">" => Ok(run::GT),
|
|
||||||
"<=" => Ok(run::LTE),
|
|
||||||
">=" => Ok(run::GTE),
|
|
||||||
"&&" => Ok(run::AND),
|
|
||||||
"||" => Ok(run::OR),
|
|
||||||
"^" => Ok(run::XOR),
|
|
||||||
"!" => Ok(run::NOT),
|
|
||||||
"<<" => Ok(run::LSH),
|
|
||||||
">>" => Ok(run::RSH),
|
|
||||||
_ => Err(format!("Unknown operator: {}", opx)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_tree(chars: &mut Peekable<Chars>) -> Result<Tree, String> {
|
|
||||||
skip(chars);
|
|
||||||
match chars.peek() {
|
|
||||||
Some('*') => {
|
|
||||||
chars.next();
|
|
||||||
Ok(Tree::Era)
|
|
||||||
}
|
|
||||||
Some('(') => {
|
|
||||||
chars.next();
|
|
||||||
let lft = Box::new(parse_tree(chars)?);
|
|
||||||
let rgt = Box::new(parse_tree(chars)?);
|
|
||||||
consume(chars, ")")?;
|
|
||||||
Ok(Tree::Con { lft, rgt })
|
|
||||||
}
|
|
||||||
Some('[') => {
|
|
||||||
chars.next();
|
|
||||||
let lab = 1;
|
|
||||||
let lft = Box::new(parse_tree(chars)?);
|
|
||||||
let rgt = Box::new(parse_tree(chars)?);
|
|
||||||
consume(chars, "]")?;
|
|
||||||
Ok(Tree::Tup { lft, rgt })
|
|
||||||
}
|
|
||||||
Some('{') => {
|
|
||||||
chars.next();
|
|
||||||
let lab = parse_decimal(chars)? as run::Lab;
|
|
||||||
let lft = Box::new(parse_tree(chars)?);
|
|
||||||
let rgt = Box::new(parse_tree(chars)?);
|
|
||||||
consume(chars, "}")?;
|
|
||||||
Ok(Tree::Dup { lab, lft, rgt })
|
|
||||||
}
|
|
||||||
Some('@') => {
|
|
||||||
chars.next();
|
|
||||||
skip(chars);
|
|
||||||
let name = parse_name(chars)?;
|
|
||||||
Ok(Tree::Ref { nam: name_to_val(&name) })
|
|
||||||
}
|
|
||||||
Some('#') => {
|
|
||||||
chars.next();
|
|
||||||
Ok(Tree::Num { val: parse_decimal(chars)? })
|
|
||||||
}
|
|
||||||
Some('<') => {
|
|
||||||
chars.next();
|
|
||||||
if chars.peek().map_or(false, |c| c.is_digit(10)) {
|
|
||||||
let lft = parse_decimal(chars)?;
|
|
||||||
let opr = parse_opr(chars)?;
|
|
||||||
let rgt = Box::new(parse_tree(chars)?);
|
|
||||||
consume(chars, ">")?;
|
|
||||||
Ok(Tree::Op1 { opr, lft, rgt })
|
|
||||||
} else {
|
|
||||||
let opr = parse_opr(chars)?;
|
|
||||||
let lft = Box::new(parse_tree(chars)?);
|
|
||||||
let rgt = Box::new(parse_tree(chars)?);
|
|
||||||
consume(chars, ">")?;
|
|
||||||
Ok(Tree::Op2 { opr, lft, rgt })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some('?') => {
|
|
||||||
chars.next();
|
|
||||||
consume(chars, "<")?;
|
|
||||||
let sel = Box::new(parse_tree(chars)?);
|
|
||||||
let ret = Box::new(parse_tree(chars)?);
|
|
||||||
consume(chars, ">")?;
|
|
||||||
Ok(Tree::Mat { sel, ret })
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
Ok(Tree::Var { nam: parse_name(chars)? })
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_net(chars: &mut Peekable<Chars>) -> Result<Net, String> {
|
|
||||||
let mut rdex = Vec::new();
|
|
||||||
let root = parse_tree(chars)?;
|
|
||||||
while let Some(c) = { skip(chars); chars.peek() } {
|
|
||||||
if *c == '&' {
|
|
||||||
chars.next();
|
|
||||||
let tree1 = parse_tree(chars)?;
|
|
||||||
consume(chars, "~")?;
|
|
||||||
let tree2 = parse_tree(chars)?;
|
|
||||||
rdex.push((tree1, tree2));
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(Net { root, rdex })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_book(chars: &mut Peekable<Chars>) -> Result<Book, String> {
|
|
||||||
let mut book = BTreeMap::new();
|
|
||||||
while let Some(c) = { skip(chars); chars.peek() } {
|
|
||||||
if *c == '@' {
|
|
||||||
chars.next();
|
|
||||||
let name = parse_name(chars)?;
|
|
||||||
consume(chars, "=")?;
|
|
||||||
let net = parse_net(chars)?;
|
|
||||||
book.insert(name, net);
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(book)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_parse<T>(code: &str, parse_fn: impl Fn(&mut Peekable<Chars>) -> Result<T, String>) -> T {
|
|
||||||
let chars = &mut code.chars().peekable();
|
|
||||||
match parse_fn(chars) {
|
|
||||||
Ok(result) => {
|
|
||||||
if chars.next().is_none() {
|
|
||||||
result
|
|
||||||
} else {
|
|
||||||
eprintln!("Unable to parse the whole input. Is this not an hvmc file?");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
eprintln!("{}", err);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn do_parse_tree(code: &str) -> Tree {
|
|
||||||
do_parse(code, parse_tree)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn do_parse_net(code: &str) -> Net {
|
|
||||||
do_parse(code, parse_net)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn do_parse_book(code: &str) -> Book {
|
|
||||||
do_parse(code, parse_book)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stringifier
|
|
||||||
// -----------
|
|
||||||
|
|
||||||
pub fn show_opr(opr: run::Lab) -> String {
|
|
||||||
match opr {
|
|
||||||
run::ADD => "+".to_string(),
|
|
||||||
run::SUB => "-".to_string(),
|
|
||||||
run::MUL => "*".to_string(),
|
|
||||||
run::DIV => "/".to_string(),
|
|
||||||
run::MOD => "%".to_string(),
|
|
||||||
run::EQ => "==".to_string(),
|
|
||||||
run::NE => "!=".to_string(),
|
|
||||||
run::LT => "<".to_string(),
|
|
||||||
run::GT => ">".to_string(),
|
|
||||||
run::LTE => "<=".to_string(),
|
|
||||||
run::GTE => ">=".to_string(),
|
|
||||||
run::AND => "&&".to_string(),
|
|
||||||
run::OR => "||".to_string(),
|
|
||||||
run::XOR => "^".to_string(),
|
|
||||||
run::NOT => "!".to_string(),
|
|
||||||
run::LSH => "<<".to_string(),
|
|
||||||
run::RSH => ">>".to_string(),
|
|
||||||
_ => panic!("Unknown operator label."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show_tree(tree: &Tree) -> String {
|
|
||||||
match tree {
|
|
||||||
Tree::Era => {
|
|
||||||
"*".to_string()
|
|
||||||
}
|
|
||||||
Tree::Con { lft, rgt } => {
|
|
||||||
format!("({} {})", show_tree(&*lft), show_tree(&*rgt))
|
|
||||||
}
|
|
||||||
Tree::Tup { lft, rgt } => {
|
|
||||||
format!("[{} {}]", show_tree(&*lft), show_tree(&*rgt))
|
|
||||||
}
|
|
||||||
Tree::Dup { lab, lft, rgt } => {
|
|
||||||
format!("{{{} {} {}}}", lab, show_tree(&*lft), show_tree(&*rgt))
|
|
||||||
}
|
|
||||||
Tree::Var { nam } => {
|
|
||||||
nam.clone()
|
|
||||||
}
|
|
||||||
Tree::Ref { nam } => {
|
|
||||||
format!("@{}", val_to_name(*nam))
|
|
||||||
}
|
|
||||||
Tree::Num { val } => {
|
|
||||||
format!("#{}", (*val).to_string())
|
|
||||||
}
|
|
||||||
Tree::Op1 { opr, lft, rgt } => {
|
|
||||||
format!("<{}{} {}>", lft, show_opr(*opr), show_tree(rgt))
|
|
||||||
}
|
|
||||||
Tree::Op2 { opr, lft, rgt } => {
|
|
||||||
format!("<{} {} {}>", show_opr(*opr), show_tree(&*lft), show_tree(&*rgt))
|
|
||||||
}
|
|
||||||
Tree::Mat { sel, ret } => {
|
|
||||||
format!("?<{} {}>", show_tree(&*sel), show_tree(&*ret))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show_net(net: &Net) -> String {
|
|
||||||
let mut result = String::new();
|
|
||||||
result.push_str(&format!("{}", show_tree(&net.root)));
|
|
||||||
for (a, b) in &net.rdex {
|
|
||||||
result.push_str(&format!("\n& {} ~ {}", show_tree(a), show_tree(b)));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show_book(book: &Book) -> String {
|
|
||||||
let mut result = String::new();
|
|
||||||
for (name, net) in book {
|
|
||||||
result.push_str(&format!("@{} = {}\n", name, show_net(net)));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show_runtime_tree<const LAZY: bool>(rt_net: &run::NetFields<LAZY>, ptr: run::Ptr) -> String where [(); LAZY as usize]:{
|
|
||||||
show_tree(&tree_from_runtime_go(rt_net, ptr, PARENT_ROOT, &mut HashMap::new(), &mut 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show_runtime_net<const LAZY: bool>(rt_net: &run::NetFields<LAZY>) -> String where [(); LAZY as usize]:{
|
|
||||||
show_net(&net_from_runtime(rt_net))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn show_runtime_book(book: &run::Book) -> String {
|
|
||||||
show_book(&book_from_runtime(book))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Conversion
|
|
||||||
// ----------
|
|
||||||
|
|
||||||
pub fn num_to_str(mut num: usize) -> String {
|
|
||||||
let mut txt = String::new();
|
|
||||||
num += 1;
|
|
||||||
while num > 0 {
|
|
||||||
num -= 1;
|
|
||||||
let c = ((num % 26) as u8 + b'a') as char;
|
|
||||||
txt.push(c);
|
|
||||||
num /= 26;
|
|
||||||
}
|
|
||||||
return txt.chars().rev().collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn tag_to_port(tag: run::Tag) -> run::Port {
|
|
||||||
match tag {
|
|
||||||
run::VR1 => run::P1,
|
|
||||||
run::VR2 => run::P2,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn port_to_tag(port: run::Port) -> run::Tag {
|
|
||||||
match port {
|
|
||||||
run::P1 => run::VR1,
|
|
||||||
run::P2 => run::VR2,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name_to_letters(name: &str) -> Vec<u8> {
|
|
||||||
let mut letters = Vec::new();
|
|
||||||
for c in name.chars() {
|
|
||||||
letters.push(match c {
|
|
||||||
'0'..='9' => c as u8 - '0' as u8 + 0,
|
|
||||||
'A'..='Z' => c as u8 - 'A' as u8 + 10,
|
|
||||||
'a'..='z' => c as u8 - 'a' as u8 + 36,
|
|
||||||
'_' => 62,
|
|
||||||
'.' => 63,
|
|
||||||
_ => panic!("Invalid character in name"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return letters;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn letters_to_name(letters: Vec<u8>) -> String {
|
|
||||||
let mut name = String::new();
|
|
||||||
for letter in letters {
|
|
||||||
name.push(match letter {
|
|
||||||
0..= 9 => (letter - 0 + '0' as u8) as char,
|
|
||||||
10..=35 => (letter - 10 + 'A' as u8) as char,
|
|
||||||
36..=61 => (letter - 36 + 'a' as u8) as char,
|
|
||||||
62 => '_',
|
|
||||||
63 => '.',
|
|
||||||
_ => panic!("Invalid letter in name"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn val_to_letters(num: run::Val) -> Vec<u8> {
|
|
||||||
let mut letters = Vec::new();
|
|
||||||
let mut num = num;
|
|
||||||
while num > 0 {
|
|
||||||
letters.push((num % 64) as u8);
|
|
||||||
num /= 64;
|
|
||||||
}
|
|
||||||
letters.reverse();
|
|
||||||
return letters;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn letters_to_val(letters: Vec<u8>) -> run::Val {
|
|
||||||
let mut num = 0;
|
|
||||||
for letter in letters {
|
|
||||||
num = num * 64 + letter as run::Val;
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name_to_val(name: &str) -> run::Val {
|
|
||||||
letters_to_val(name_to_letters(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn val_to_name(num: run::Val) -> String {
|
|
||||||
letters_to_name(val_to_letters(num))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Injection and Readback
|
|
||||||
// ----------------------
|
|
||||||
|
|
||||||
// To runtime
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub enum Parent {
|
|
||||||
Redex,
|
|
||||||
Node { loc: run::Loc, port: run::Port },
|
|
||||||
}
|
|
||||||
const PARENT_ROOT: Parent = Parent::Node { loc: run::ROOT.loc(), port: tag_to_port(run::ROOT.tag()) };
|
|
||||||
|
|
||||||
pub fn tree_to_runtime_go<const LAZY: bool>(rt_net: &mut run::NetFields<LAZY>, tree: &Tree, vars: &mut HashMap<String, Parent>, parent: Parent) -> run::Ptr where [(); LAZY as usize]: {
|
|
||||||
match tree {
|
|
||||||
Tree::Era => {
|
|
||||||
run::ERAS
|
|
||||||
}
|
|
||||||
Tree::Con { lft, rgt } => {
|
|
||||||
let loc = rt_net.alloc();
|
|
||||||
let p1 = tree_to_runtime_go(rt_net, &*lft, vars, Parent::Node { loc, port: run::P1 });
|
|
||||||
rt_net.heap.set(loc, run::P1, p1);
|
|
||||||
let p2 = tree_to_runtime_go(rt_net, &*rgt, vars, Parent::Node { loc, port: run::P2 });
|
|
||||||
rt_net.heap.set(loc, run::P2, p2);
|
|
||||||
run::Ptr::new(run::LAM, 0, loc)
|
|
||||||
}
|
|
||||||
Tree::Tup { lft, rgt } => {
|
|
||||||
let loc = rt_net.alloc();
|
|
||||||
let p1 = tree_to_runtime_go(rt_net, &*lft, vars, Parent::Node { loc, port: run::P1 });
|
|
||||||
rt_net.heap.set(loc, run::P1, p1);
|
|
||||||
let p2 = tree_to_runtime_go(rt_net, &*rgt, vars, Parent::Node { loc, port: run::P2 });
|
|
||||||
rt_net.heap.set(loc, run::P2, p2);
|
|
||||||
run::Ptr::new(run::TUP, 1, loc)
|
|
||||||
}
|
|
||||||
Tree::Dup { lab, lft, rgt } => {
|
|
||||||
let loc = rt_net.alloc();
|
|
||||||
let p1 = tree_to_runtime_go(rt_net, &*lft, vars, Parent::Node { loc, port: run::P1 });
|
|
||||||
rt_net.heap.set(loc, run::P1, p1);
|
|
||||||
let p2 = tree_to_runtime_go(rt_net, &*rgt, vars, Parent::Node { loc, port: run::P2 });
|
|
||||||
rt_net.heap.set(loc, run::P2, p2);
|
|
||||||
run::Ptr::new(run::DUP, *lab, loc)
|
|
||||||
}
|
|
||||||
Tree::Var { nam } => {
|
|
||||||
if let Parent::Redex = parent {
|
|
||||||
panic!("By definition, can't have variable on active pairs.");
|
|
||||||
};
|
|
||||||
match vars.get(nam) {
|
|
||||||
Some(Parent::Redex) => {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
Some(Parent::Node { loc: other_loc, port: other_port }) => {
|
|
||||||
match parent {
|
|
||||||
Parent::Redex => { unreachable!(); }
|
|
||||||
Parent::Node { loc, port } => rt_net.heap.set(*other_loc, *other_port, run::Ptr::new(port_to_tag(port), 0, loc)),
|
|
||||||
}
|
|
||||||
return run::Ptr::new(port_to_tag(*other_port), 0, *other_loc);
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
vars.insert(nam.clone(), parent);
|
|
||||||
run::NULL
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tree::Ref { nam } => {
|
|
||||||
run::Ptr::big(run::REF, *nam)
|
|
||||||
}
|
|
||||||
Tree::Num { val } => {
|
|
||||||
run::Ptr::big(run::NUM, *val)
|
|
||||||
}
|
|
||||||
Tree::Op1 { opr, lft, rgt } => {
|
|
||||||
let loc = rt_net.alloc();
|
|
||||||
let p1 = run::Ptr::big(run::NUM, *lft);
|
|
||||||
rt_net.heap.set(loc, run::P1, p1);
|
|
||||||
let p2 = tree_to_runtime_go(rt_net, rgt, vars, Parent::Node { loc, port: run::P2 });
|
|
||||||
rt_net.heap.set(loc, run::P2, p2);
|
|
||||||
run::Ptr::new(run::OP1, *opr, loc)
|
|
||||||
}
|
|
||||||
Tree::Op2 { opr, lft, rgt } => {
|
|
||||||
let loc = rt_net.alloc();
|
|
||||||
let p1 = tree_to_runtime_go(rt_net, &*lft, vars, Parent::Node { loc, port: run::P1 });
|
|
||||||
rt_net.heap.set(loc, run::P1, p1);
|
|
||||||
let p2 = tree_to_runtime_go(rt_net, &*rgt, vars, Parent::Node { loc, port: run::P2 });
|
|
||||||
rt_net.heap.set(loc, run::P2, p2);
|
|
||||||
run::Ptr::new(run::OP2, *opr, loc)
|
|
||||||
}
|
|
||||||
Tree::Mat { sel, ret } => {
|
|
||||||
let loc = rt_net.alloc();
|
|
||||||
let p1 = tree_to_runtime_go(rt_net, &*sel, vars, Parent::Node { loc, port: run::P1 });
|
|
||||||
rt_net.heap.set(loc, run::P1, p1);
|
|
||||||
let p2 = tree_to_runtime_go(rt_net, &*ret, vars, Parent::Node { loc, port: run::P2 });
|
|
||||||
rt_net.heap.set(loc, run::P2, p2);
|
|
||||||
run::Ptr::new(run::MAT, 0, loc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tree_to_runtime<const LAZY: bool>(rt_net: &mut run::NetFields<LAZY>, tree: &Tree) -> run::Ptr where [(); LAZY as usize]: {
|
|
||||||
tree_to_runtime_go(rt_net, tree, &mut HashMap::new(), PARENT_ROOT)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn net_to_runtime<const LAZY: bool>(rt_net: &mut run::NetFields<LAZY>, net: &Net) where [(); LAZY as usize]: {
|
|
||||||
let mut vars = HashMap::new();
|
|
||||||
let root = tree_to_runtime_go(rt_net, &net.root, &mut vars, PARENT_ROOT);
|
|
||||||
rt_net.heap.set_root(root);
|
|
||||||
for (tree1, tree2) in &net.rdex {
|
|
||||||
let ptr1 = tree_to_runtime_go(rt_net, tree1, &mut vars, Parent::Redex);
|
|
||||||
let ptr2 = tree_to_runtime_go(rt_net, tree2, &mut vars, Parent::Redex);
|
|
||||||
rt_net.rdex.push((ptr1, ptr2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Holds dup labels and ref ids used by a definition
|
|
||||||
type InsideLabs = HashSet<run::Lab, nohash_hasher::BuildNoHashHasher<run::Lab>>;
|
|
||||||
type InsideRefs = HashSet<run::Val>;
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct Inside {
|
|
||||||
labs: InsideLabs,
|
|
||||||
refs: InsideRefs,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collects dup labels and ref ids used by a definition
|
|
||||||
pub fn runtime_def_get_inside(def: &run::Def) -> Inside {
|
|
||||||
let mut inside = Inside {
|
|
||||||
labs: HashSet::with_hasher(std::hash::BuildHasherDefault::default()),
|
|
||||||
refs: HashSet::new(),
|
|
||||||
};
|
|
||||||
fn register(inside: &mut Inside, ptr: run::Ptr) {
|
|
||||||
if ptr.is_dup() {
|
|
||||||
inside.labs.insert(ptr.lab());
|
|
||||||
}
|
|
||||||
if ptr.is_ref() {
|
|
||||||
inside.refs.insert(ptr.val());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i in 0 .. def.node.len() {
|
|
||||||
register(&mut inside, def.node[i].1);
|
|
||||||
register(&mut inside, def.node[i].2);
|
|
||||||
}
|
|
||||||
for i in 0 .. def.rdex.len() {
|
|
||||||
register(&mut inside, def.rdex[i].0);
|
|
||||||
register(&mut inside, def.rdex[i].1);
|
|
||||||
}
|
|
||||||
return inside;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Computes all dup labels used by a definition, direct or not.
|
|
||||||
// FIXME: memoize to avoid duplicated work
|
|
||||||
pub fn runtime_def_get_all_labs(labs: &mut InsideLabs, insides: &HashMap<run::Val, Inside>, fid: run::Val, seen: &mut HashSet<run::Val>) {
|
|
||||||
if seen.contains(&fid) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
seen.insert(fid);
|
|
||||||
if let Some(fid_insides) = insides.get(&fid) {
|
|
||||||
for dup in &fid_insides.labs {
|
|
||||||
labs.insert(*dup);
|
|
||||||
}
|
|
||||||
for child_fid in &fid_insides.refs {
|
|
||||||
runtime_def_get_all_labs(labs, insides, *child_fid, seen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a book from the pure AST representation to the runtime representation.
|
|
||||||
pub fn book_to_runtime(book: &Book) -> run::Book {
|
|
||||||
let mut rt_book = run::Book::new();
|
|
||||||
|
|
||||||
// Convert each net in 'book' to a runtime net and add to 'rt_book'
|
|
||||||
for (name, net) in book {
|
|
||||||
let fid = name_to_val(name);
|
|
||||||
let nodes = run::Heap::<false>::init(1 << 16);
|
|
||||||
let mut rt = run::NetFields::new(&nodes);
|
|
||||||
net_to_runtime(&mut rt, net);
|
|
||||||
rt_book.def(fid, runtime_net_to_runtime_def(&rt));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the 'insides' of each runtime definition
|
|
||||||
let mut insides = HashMap::new();
|
|
||||||
for (fid, def) in &rt_book.defs {
|
|
||||||
insides.insert(*fid, runtime_def_get_inside(&def));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute labs labels used in each runtime definition
|
|
||||||
let mut labs_by_fid = HashMap::new();
|
|
||||||
for (fid, _) in &rt_book.defs {
|
|
||||||
let mut labs = HashSet::with_hasher(std::hash::BuildHasherDefault::default());
|
|
||||||
let mut seen = HashSet::new();
|
|
||||||
runtime_def_get_all_labs(&mut labs, &insides, *fid, &mut seen);
|
|
||||||
labs_by_fid.insert(*fid, labs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the 'labs' field for each definition
|
|
||||||
for (fid, def) in &mut rt_book.defs {
|
|
||||||
def.labs = labs_by_fid.get(fid).unwrap().clone();
|
|
||||||
//println!("{} {:?}", val_to_name(*fid), def.labs);
|
|
||||||
}
|
|
||||||
|
|
||||||
rt_book
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts to a def.
|
|
||||||
pub fn runtime_net_to_runtime_def<const LAZY: bool>(net: &run::NetFields<LAZY>) -> run::Def where [(); LAZY as usize]: {
|
|
||||||
let mut node = vec![];
|
|
||||||
let mut rdex = vec![];
|
|
||||||
let labs = HashSet::with_hasher(std::hash::BuildHasherDefault::default());
|
|
||||||
for i in 0 .. net.heap.nodes.len() {
|
|
||||||
let p0 = run::APtr::new(run::Ptr(0));
|
|
||||||
let p1 = net.heap.get(node.len() as run::Loc, run::P1);
|
|
||||||
let p2 = net.heap.get(node.len() as run::Loc, run::P2);
|
|
||||||
if p1 != run::NULL || p2 != run::NULL {
|
|
||||||
node.push(((), p1, p2));
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i in 0 .. net.rdex.len() {
|
|
||||||
let p1 = net.rdex[i].0;
|
|
||||||
let p2 = net.rdex[i].1;
|
|
||||||
rdex.push((p1, p2));
|
|
||||||
}
|
|
||||||
return run::Def { labs, rdex, node };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads back from a def.
|
|
||||||
pub fn runtime_def_to_runtime_net<'a, const LAZY: bool>(nodes: &'a run::Nodes<LAZY>, def: &run::Def) -> run::NetFields<'a, LAZY> where [(); LAZY as usize]: {
|
|
||||||
let mut net = run::NetFields::new(&nodes);
|
|
||||||
for (i, &(p0, p1, p2)) in def.node.iter().enumerate() {
|
|
||||||
net.heap.set(i as run::Loc, run::P1, p1);
|
|
||||||
net.heap.set(i as run::Loc, run::P2, p2);
|
|
||||||
}
|
|
||||||
net.rdex = def.rdex.clone();
|
|
||||||
net
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tree_from_runtime_go<const LAZY: bool>(rt_net: &run::NetFields<LAZY>, ptr: run::Ptr, parent: Parent, vars: &mut HashMap<Parent, String>, fresh: &mut usize) -> Tree where [(); LAZY as usize]: {
|
|
||||||
match ptr.tag() {
|
|
||||||
run::ERA => {
|
|
||||||
Tree::Era
|
|
||||||
}
|
|
||||||
run::REF => {
|
|
||||||
Tree::Ref { nam: ptr.val() }
|
|
||||||
}
|
|
||||||
run::NUM => {
|
|
||||||
Tree::Num { val: ptr.val() }
|
|
||||||
}
|
|
||||||
run::OP1 => {
|
|
||||||
let opr = ptr.lab();
|
|
||||||
let lft = tree_from_runtime_go(rt_net, rt_net.heap.get(ptr.loc(), run::P1), Parent::Node { loc: ptr.loc(), port: run::P1 }, vars, fresh);
|
|
||||||
let Tree::Num { val } = lft else { unreachable!() };
|
|
||||||
let rgt = tree_from_runtime_go(rt_net, rt_net.heap.get(ptr.loc(), run::P2), Parent::Node { loc: ptr.loc(), port: run::P2 }, vars, fresh);
|
|
||||||
Tree::Op1 { opr, lft: val, rgt: Box::new(rgt) }
|
|
||||||
}
|
|
||||||
run::OP2 => {
|
|
||||||
let opr = ptr.lab();
|
|
||||||
let lft = tree_from_runtime_go(rt_net, rt_net.heap.get(ptr.loc(), run::P1), Parent::Node { loc: ptr.loc(), port: run::P1 }, vars, fresh);
|
|
||||||
let rgt = tree_from_runtime_go(rt_net, rt_net.heap.get(ptr.loc(), run::P2), Parent::Node { loc: ptr.loc(), port: run::P2 }, vars, fresh);
|
|
||||||
Tree::Op2 { opr, lft: Box::new(lft), rgt: Box::new(rgt) }
|
|
||||||
}
|
|
||||||
run::MAT => {
|
|
||||||
let sel = tree_from_runtime_go(rt_net, rt_net.heap.get(ptr.loc(), run::P1), Parent::Node { loc: ptr.loc(), port: run::P1 }, vars, fresh);
|
|
||||||
let ret = tree_from_runtime_go(rt_net, rt_net.heap.get(ptr.loc(), run::P2), Parent::Node { loc: ptr.loc(), port: run::P2 }, vars, fresh);
|
|
||||||
Tree::Mat { sel: Box::new(sel), ret: Box::new(ret) }
|
|
||||||
}
|
|
||||||
run::VR1 | run::VR2 => {
|
|
||||||
let key = match ptr.tag() {
|
|
||||||
run::VR1 => Parent::Node { loc: ptr.loc(), port: run::P1 },
|
|
||||||
run::VR2 => Parent::Node { loc: ptr.loc(), port: run::P2 },
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
if let Some(nam) = vars.get(&key) {
|
|
||||||
Tree::Var { nam: nam.clone() }
|
|
||||||
} else {
|
|
||||||
let nam = num_to_str(*fresh);
|
|
||||||
*fresh += 1;
|
|
||||||
vars.insert(parent, nam.clone());
|
|
||||||
Tree::Var { nam }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
run::LAM => {
|
|
||||||
let p1 = rt_net.heap.get(ptr.loc(), run::P1);
|
|
||||||
let p2 = rt_net.heap.get(ptr.loc(), run::P2);
|
|
||||||
let lft = tree_from_runtime_go(rt_net, p1, Parent::Node { loc: ptr.loc(), port: run::P1 }, vars, fresh);
|
|
||||||
let rgt = tree_from_runtime_go(rt_net, p2, Parent::Node { loc: ptr.loc(), port: run::P2 }, vars, fresh);
|
|
||||||
Tree::Con { lft: Box::new(lft), rgt: Box::new(rgt) }
|
|
||||||
}
|
|
||||||
run::TUP => {
|
|
||||||
let p1 = rt_net.heap.get(ptr.loc(), run::P1);
|
|
||||||
let p2 = rt_net.heap.get(ptr.loc(), run::P2);
|
|
||||||
let lft = tree_from_runtime_go(rt_net, p1, Parent::Node { loc: ptr.loc(), port: run::P1 }, vars, fresh);
|
|
||||||
let rgt = tree_from_runtime_go(rt_net, p2, Parent::Node { loc: ptr.loc(), port: run::P2 }, vars, fresh);
|
|
||||||
Tree::Tup { lft: Box::new(lft), rgt: Box::new(rgt) }
|
|
||||||
}
|
|
||||||
run::DUP => {
|
|
||||||
let p1 = rt_net.heap.get(ptr.loc(), run::P1);
|
|
||||||
let p2 = rt_net.heap.get(ptr.loc(), run::P2);
|
|
||||||
let lft = tree_from_runtime_go(rt_net, p1, Parent::Node { loc: ptr.loc(), port: run::P1 }, vars, fresh);
|
|
||||||
let rgt = tree_from_runtime_go(rt_net, p2, Parent::Node { loc: ptr.loc(), port: run::P2 }, vars, fresh);
|
|
||||||
Tree::Dup { lab: ptr.lab(), lft: Box::new(lft), rgt: Box::new(rgt) }
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tree_from_runtime<const LAZY: bool>(rt_net: &run::NetFields<LAZY>, ptr: run::Ptr) -> Tree where [(); LAZY as usize]: {
|
|
||||||
let mut vars = HashMap::new();
|
|
||||||
let mut fresh = 0;
|
|
||||||
tree_from_runtime_go(rt_net, ptr, PARENT_ROOT, &mut vars, &mut fresh)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn net_from_runtime<const LAZY: bool>(rt_net: &run::NetFields<LAZY>) -> Net where [(); LAZY as usize]: {
|
|
||||||
let mut vars = HashMap::new();
|
|
||||||
let mut fresh = 0;
|
|
||||||
let mut rdex = Vec::new();
|
|
||||||
let root = tree_from_runtime_go(rt_net, rt_net.heap.get_root(), PARENT_ROOT, &mut vars, &mut fresh);
|
|
||||||
for &(a, b) in &rt_net.rdex {
|
|
||||||
let tree_a = tree_from_runtime_go(rt_net, a, Parent::Redex, &mut vars, &mut fresh);
|
|
||||||
let tree_b = tree_from_runtime_go(rt_net, b, Parent::Redex, &mut vars, &mut fresh);
|
|
||||||
rdex.push((tree_a, tree_b));
|
|
||||||
}
|
|
||||||
Net { root, rdex }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn book_from_runtime(rt_book: &run::Book) -> Book {
|
|
||||||
let mut book = BTreeMap::new();
|
|
||||||
for (fid, def) in rt_book.defs.iter() {
|
|
||||||
if def.node.len() > 0 {
|
|
||||||
let name = val_to_name(*fid);
|
|
||||||
let nodes = run::Heap::<false>::init(def.node.len());
|
|
||||||
let net = net_from_runtime(&runtime_def_to_runtime_net(&nodes, &def));
|
|
||||||
book.insert(name, net);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
book
|
|
||||||
}
|
|
@ -1,355 +0,0 @@
|
|||||||
use crate::run::{*};
|
|
||||||
|
|
||||||
pub const F___main : Val = 0xfbec24b31;
|
|
||||||
pub const F___foo : Val = 0x3efa9cb2;
|
|
||||||
pub const F_main : Val = 0xc24b31;
|
|
||||||
pub const F_a : Val = 0x000024;
|
|
||||||
pub const F__U60.fib : Val = 0xf9e180fe9b25;
|
|
||||||
pub const F_b : Val = 0x000025;
|
|
||||||
pub const F_d : Val = 0x000027;
|
|
||||||
pub const F_c : Val = 0x000026;
|
|
||||||
|
|
||||||
impl<'a, const LAZY: bool> NetFields<'a, LAZY> where [(); LAZY as usize]: {
|
|
||||||
|
|
||||||
pub fn call_native(&mut self, book: &Book, ptr: Ptr, x: Ptr) -> bool {
|
|
||||||
match ptr.val() {
|
|
||||||
F___main => { return self.F___main(ptr, Trg::Ptr(x)); }
|
|
||||||
F___foo => { return self.F___foo(ptr, Trg::Ptr(x)); }
|
|
||||||
F_main => { return self.F_main(ptr, Trg::Ptr(x)); }
|
|
||||||
F_a => { return self.F_a(ptr, Trg::Ptr(x)); }
|
|
||||||
F__U60.fib => { return self.F__U60.fib(ptr, Trg::Ptr(x)); }
|
|
||||||
F_b => { return self.F_b(ptr, Trg::Ptr(x)); }
|
|
||||||
F_d => { return self.F_d(ptr, Trg::Ptr(x)); }
|
|
||||||
F_c => { return self.F_c(ptr, Trg::Ptr(x)); }
|
|
||||||
_ => { return false; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L___main(&mut self, lab: Lab) -> bool {
|
|
||||||
if lab == 0x5 { return true; }
|
|
||||||
if lab == 0x3 { return true; }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F___main(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L___main(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let _k1 : Trg = Trg::Ptr(Ptr::big(REF, F__U60.fib));
|
|
||||||
let _k1x : Trg;
|
|
||||||
let _k1y : Trg;
|
|
||||||
// fast apply
|
|
||||||
if self.get(_k1).tag() == LAM {
|
|
||||||
self.rwts.anni += 1;
|
|
||||||
let got = self.swap(_k1, NULL);
|
|
||||||
_k1x = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
_k1y = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
} else {
|
|
||||||
let k2 = self.alloc();
|
|
||||||
_k1x = Trg::Ptr(Ptr::new(VR1, 0, k2));
|
|
||||||
_k1y = Trg::Ptr(Ptr::new(VR2, 0, k2));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k2)), _k1);
|
|
||||||
}
|
|
||||||
// fast erase
|
|
||||||
if self.get(_k1x).is_skp() {
|
|
||||||
self.swap(_k1x, NULL);
|
|
||||||
self.rwts.eras += 1;
|
|
||||||
} else {
|
|
||||||
self.safe_link(_k1x, Trg::Ptr(Ptr::new(NUM, 0x6, 0x0)));
|
|
||||||
}
|
|
||||||
self.safe_link(trg, _k1y);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L___foo(&mut self, lab: Lab) -> bool {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F___foo(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L___foo(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// fast erase
|
|
||||||
if self.get(trg).is_skp() {
|
|
||||||
self.swap(trg, NULL);
|
|
||||||
self.rwts.eras += 1;
|
|
||||||
} else {
|
|
||||||
self.safe_link(trg, Trg::Ptr(Ptr::new(NUM, 0x2d, 0x0)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L_main(&mut self, lab: Lab) -> bool {
|
|
||||||
if lab == 0x5 { return true; }
|
|
||||||
if lab == 0x3 { return true; }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F_main(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L_main(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
self.safe_link(trg, Trg::Ptr(Ptr::big(REF, F___main)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L_a(&mut self, lab: Lab) -> bool {
|
|
||||||
if lab == 0x5 { return true; }
|
|
||||||
if lab == 0x3 { return true; }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F_a(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L_a(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let trgx : Trg;
|
|
||||||
let trgy : Trg;
|
|
||||||
// fast apply
|
|
||||||
if self.get(trg).tag() == LAM {
|
|
||||||
self.rwts.anni += 1;
|
|
||||||
let got = self.swap(trg, NULL);
|
|
||||||
trgx = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
trgy = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
} else {
|
|
||||||
let k1 = self.alloc();
|
|
||||||
trgx = Trg::Ptr(Ptr::new(VR1, 0, k1));
|
|
||||||
trgy = Trg::Ptr(Ptr::new(VR2, 0, k1));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k1)), trg);
|
|
||||||
}
|
|
||||||
let trgxx : Trg;
|
|
||||||
let trgxy : Trg;
|
|
||||||
// fast copy
|
|
||||||
if self.get(trgx).tag() == NUM {
|
|
||||||
self.rwts.comm += 1;
|
|
||||||
let got = self.swap(trgx, NULL);
|
|
||||||
trgxx = Trg::Ptr(got);
|
|
||||||
trgxy = Trg::Ptr(got);
|
|
||||||
} else {
|
|
||||||
let k2 = self.alloc();
|
|
||||||
trgxx = Trg::Ptr(Ptr::new(VR1, 0, k2));
|
|
||||||
trgxy = Trg::Ptr(Ptr::new(VR2, 0, k2));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(DUP, 3, k2)), trgx);
|
|
||||||
}
|
|
||||||
let k3 = self.alloc();
|
|
||||||
let k4 = self.alloc();
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR2, 0, k4)), trgy);
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR1, 0, k4)), trgxy);
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k4)), Trg::Ptr(Ptr::new(VR2, 0, k3)));
|
|
||||||
let k5 = self.alloc();
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR2, 0, k5)), Trg::Ptr(Ptr::big(REF, F_b)));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR1, 0, k5)), Trg::Ptr(Ptr::big(REF, F_d)));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k5)), Trg::Ptr(Ptr::new(VR1, 0, k3)));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(MAT, 0, k3)), trgxx);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L__U60.fib(&mut self, lab: Lab) -> bool {
|
|
||||||
if lab == 0x5 { return true; }
|
|
||||||
if lab == 0x3 { return true; }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F__U60.fib(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L__U60.fib(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let k1 : Trg;
|
|
||||||
let k2 : Trg;
|
|
||||||
// fast match
|
|
||||||
if self.get(trg).tag() == LAM && self.heap.get(self.get(trg).loc(), P1).is_num() {
|
|
||||||
self.rwts.anni += 2;
|
|
||||||
self.rwts.oper += 1;
|
|
||||||
let got = self.swap(trg, NULL);
|
|
||||||
let trgx = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
let trgy = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
if self.get(trgx).val() == 0 {
|
|
||||||
self.swap(trgx, NULL);
|
|
||||||
k1 = trgy;
|
|
||||||
k2 = Trg::Ptr(ERAS);
|
|
||||||
} else {
|
|
||||||
self.swap(trgx, Ptr::big(NUM, self.get(trgx).val() - 1));
|
|
||||||
k1 = Trg::Ptr(ERAS);
|
|
||||||
k2 = trg;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let k3 = self.alloc();
|
|
||||||
let k4 = self.alloc();
|
|
||||||
let k5 = self.alloc();
|
|
||||||
self.heap.set(k3, P1, Ptr::new(MAT, 0, k4));
|
|
||||||
self.heap.set(k3, P2, Ptr::new(VR2, 0, k4));
|
|
||||||
self.heap.set(k4, P1, Ptr::new(LAM, 0, k5));
|
|
||||||
self.heap.set(k4, P2, Ptr::new(VR2, 0, k3));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k3)), trg);
|
|
||||||
k1 = Trg::Ptr(Ptr::new(VR1, 0, k5));
|
|
||||||
k2 = Trg::Ptr(Ptr::new(VR2, 0, k5));
|
|
||||||
}
|
|
||||||
// fast erase
|
|
||||||
if self.get(k1).is_skp() {
|
|
||||||
self.swap(k1, NULL);
|
|
||||||
self.rwts.eras += 1;
|
|
||||||
} else {
|
|
||||||
self.safe_link(k1, Trg::Ptr(Ptr::new(NUM, 0x0, 0x0)));
|
|
||||||
}
|
|
||||||
self.safe_link(k2, Trg::Ptr(Ptr::big(REF, F_a)));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L_b(&mut self, lab: Lab) -> bool {
|
|
||||||
if lab == 0x5 { return true; }
|
|
||||||
if lab == 0x3 { return true; }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F_b(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L_b(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let trgx : Trg;
|
|
||||||
let trgy : Trg;
|
|
||||||
// fast apply
|
|
||||||
if self.get(trg).tag() == LAM {
|
|
||||||
self.rwts.anni += 1;
|
|
||||||
let got = self.swap(trg, NULL);
|
|
||||||
trgx = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
trgy = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
} else {
|
|
||||||
let k1 = self.alloc();
|
|
||||||
trgx = Trg::Ptr(Ptr::new(VR1, 0, k1));
|
|
||||||
trgy = Trg::Ptr(Ptr::new(VR2, 0, k1));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k1)), trg);
|
|
||||||
}
|
|
||||||
self.safe_link(trgy, Trg::Ptr(Ptr::big(REF, F_c)));
|
|
||||||
// fast erase
|
|
||||||
if self.get(trgx).is_skp() {
|
|
||||||
self.swap(trgx, NULL);
|
|
||||||
self.rwts.eras += 1;
|
|
||||||
} else {
|
|
||||||
self.safe_link(trgx, Trg::Ptr(Ptr::new(ERA, 0x0, 0x0)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L_d(&mut self, lab: Lab) -> bool {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F_d(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L_d(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let trgx : Trg;
|
|
||||||
let trgy : Trg;
|
|
||||||
// fast apply
|
|
||||||
if self.get(trg).tag() == LAM {
|
|
||||||
self.rwts.anni += 1;
|
|
||||||
let got = self.swap(trg, NULL);
|
|
||||||
trgx = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
trgy = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
} else {
|
|
||||||
let k1 = self.alloc();
|
|
||||||
trgx = Trg::Ptr(Ptr::new(VR1, 0, k1));
|
|
||||||
trgy = Trg::Ptr(Ptr::new(VR2, 0, k1));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k1)), trg);
|
|
||||||
}
|
|
||||||
// fast erase
|
|
||||||
if self.get(trgy).is_skp() {
|
|
||||||
self.swap(trgy, NULL);
|
|
||||||
self.rwts.eras += 1;
|
|
||||||
} else {
|
|
||||||
self.safe_link(trgy, Trg::Ptr(Ptr::new(NUM, 0x1, 0x0)));
|
|
||||||
}
|
|
||||||
// fast erase
|
|
||||||
if self.get(trgx).is_skp() {
|
|
||||||
self.swap(trgx, NULL);
|
|
||||||
self.rwts.eras += 1;
|
|
||||||
} else {
|
|
||||||
self.safe_link(trgx, Trg::Ptr(Ptr::new(ERA, 0x0, 0x0)));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn L_c(&mut self, lab: Lab) -> bool {
|
|
||||||
if lab == 0x5 { return true; }
|
|
||||||
if lab == 0x3 { return true; }
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pub fn F_c(&mut self, ptr: Ptr, trg: Trg) -> bool {
|
|
||||||
if self.get(trg).is_dup() && !self.L_c(self.get(trg).lab()) {
|
|
||||||
self.copy(self.swap(trg, NULL), ptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
let _k1 : Trg = Trg::Ptr(Ptr::big(REF, F__U60.fib));
|
|
||||||
let _k1x : Trg;
|
|
||||||
let _k1y : Trg;
|
|
||||||
// fast apply
|
|
||||||
if self.get(_k1).tag() == LAM {
|
|
||||||
self.rwts.anni += 1;
|
|
||||||
let got = self.swap(_k1, NULL);
|
|
||||||
_k1x = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
_k1y = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
} else {
|
|
||||||
let k2 = self.alloc();
|
|
||||||
_k1x = Trg::Ptr(Ptr::new(VR1, 0, k2));
|
|
||||||
_k1y = Trg::Ptr(Ptr::new(VR2, 0, k2));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k2)), _k1);
|
|
||||||
}
|
|
||||||
let k3 = self.alloc();
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(OP2, 0, k3)), _k1y);
|
|
||||||
let _k4 : Trg = Trg::Ptr(Ptr::big(REF, F__U60.fib));
|
|
||||||
let _k4x : Trg;
|
|
||||||
let _k4y : Trg;
|
|
||||||
// fast apply
|
|
||||||
if self.get(_k4).tag() == LAM {
|
|
||||||
self.rwts.anni += 1;
|
|
||||||
let got = self.swap(_k4, NULL);
|
|
||||||
_k4x = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
_k4y = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
} else {
|
|
||||||
let k5 = self.alloc();
|
|
||||||
_k4x = Trg::Ptr(Ptr::new(VR1, 0, k5));
|
|
||||||
_k4y = Trg::Ptr(Ptr::new(VR2, 0, k5));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k5)), _k4);
|
|
||||||
}
|
|
||||||
self.safe_link(_k4y, Trg::Ptr(Ptr::new(VR1, 0, k3)));
|
|
||||||
let trgx : Trg;
|
|
||||||
let trgy : Trg;
|
|
||||||
// fast apply
|
|
||||||
if self.get(trg).tag() == LAM {
|
|
||||||
self.rwts.anni += 1;
|
|
||||||
let got = self.swap(trg, NULL);
|
|
||||||
trgx = Trg::Dir(Ptr::new(VR1, 0, got.loc()));
|
|
||||||
trgy = Trg::Dir(Ptr::new(VR2, 0, got.loc()));
|
|
||||||
} else {
|
|
||||||
let k6 = self.alloc();
|
|
||||||
trgx = Trg::Ptr(Ptr::new(VR1, 0, k6));
|
|
||||||
trgy = Trg::Ptr(Ptr::new(VR2, 0, k6));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, k6)), trg);
|
|
||||||
}
|
|
||||||
self.safe_link(trgy, Trg::Ptr(Ptr::new(VR2, 0, k3)));
|
|
||||||
let trgxx : Trg;
|
|
||||||
let trgxy : Trg;
|
|
||||||
// fast copy
|
|
||||||
if self.get(trgx).tag() == NUM {
|
|
||||||
self.rwts.comm += 1;
|
|
||||||
let got = self.swap(trgx, NULL);
|
|
||||||
trgxx = Trg::Ptr(got);
|
|
||||||
trgxy = Trg::Ptr(got);
|
|
||||||
} else {
|
|
||||||
let k7 = self.alloc();
|
|
||||||
trgxx = Trg::Ptr(Ptr::new(VR1, 0, k7));
|
|
||||||
trgxy = Trg::Ptr(Ptr::new(VR2, 0, k7));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(DUP, 5, k7)), trgx);
|
|
||||||
}
|
|
||||||
let k8 = self.alloc();
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR2, 0, k8)), _k4x);
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR1, 0, k8)), Trg::Ptr(Ptr::new(NUM, 0x2, 0x0)));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(OP2, 1, k8)), trgxy);
|
|
||||||
let k9 = self.alloc();
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR2, 0, k9)), _k1x);
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(VR1, 0, k9)), Trg::Ptr(Ptr::new(NUM, 0x1, 0x0)));
|
|
||||||
self.safe_link(Trg::Ptr(Ptr::new(OP2, 1, k9)), trgxx);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,452 +0,0 @@
|
|||||||
// Despite the file name, this is not actually a JIT (yet).
|
|
||||||
|
|
||||||
use crate::run;
|
|
||||||
use crate::ast;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
pub fn compile_book(book: &run::Book) -> String {
|
|
||||||
let mut code = String::new();
|
|
||||||
|
|
||||||
code.push_str(&format!("use crate::run::{{*}};\n"));
|
|
||||||
code.push_str(&format!("\n"));
|
|
||||||
|
|
||||||
for (fid, def) in book.defs.iter() {
|
|
||||||
if def.node.len() > 0 {
|
|
||||||
let name = &ast::val_to_name(*fid as run::Val);
|
|
||||||
code.push_str(&format!("pub const F_{:4} : Val = 0x{:06x};\n", name, fid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code.push_str(&format!("\n"));
|
|
||||||
|
|
||||||
code.push_str(&format!("impl<'a, const LAZY: bool> NetFields<'a, LAZY> where [(); LAZY as usize]: {{\n"));
|
|
||||||
code.push_str(&format!("\n"));
|
|
||||||
|
|
||||||
code.push_str(&format!("{}pub fn call_native(&mut self, book: &Book, ptr: Ptr, x: Ptr) -> bool {{\n", ident(1)));
|
|
||||||
code.push_str(&format!("{}match ptr.val() {{\n", ident(2)));
|
|
||||||
for (fid, def) in book.defs.iter() {
|
|
||||||
if def.node.len() > 0 {
|
|
||||||
let fun = ast::val_to_name(*fid);
|
|
||||||
code.push_str(&format!("{}F_{} => {{ return self.F_{}(ptr, Trg::Ptr(x)); }}\n", ident(3), fun, fun));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
code.push_str(&format!("{}_ => {{ return false; }}\n", ident(3)));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(2)));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(1)));
|
|
||||||
code.push_str(&format!("\n"));
|
|
||||||
|
|
||||||
for (fid, def) in book.defs.iter() {
|
|
||||||
if def.node.len() > 0 {
|
|
||||||
code.push_str(&compile_term(&book, 1, *fid));
|
|
||||||
code.push_str(&format!("\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code.push_str(&format!("}}"));
|
|
||||||
|
|
||||||
return code;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ident(tab: usize) -> String {
|
|
||||||
return " ".repeat(tab);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tag(tag: run::Tag) -> &'static str {
|
|
||||||
match tag {
|
|
||||||
run::VR1 => "VR1",
|
|
||||||
run::VR2 => "VR2",
|
|
||||||
run::RD1 => "RD1",
|
|
||||||
run::RD2 => "RD2",
|
|
||||||
run::REF => "REF",
|
|
||||||
run::ERA => "ERA",
|
|
||||||
run::NUM => "NUM",
|
|
||||||
run::OP2 => "OP2",
|
|
||||||
run::OP1 => "OP1",
|
|
||||||
run::MAT => "MAT",
|
|
||||||
run::LAM => "LAM",
|
|
||||||
run::TUP => "TUP",
|
|
||||||
run::DUP => "DUP",
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn atom(ptr: run::Ptr) -> String {
|
|
||||||
if ptr.is_ref() {
|
|
||||||
return format!("Ptr::big(REF, F_{})", ast::val_to_name(ptr.val()));
|
|
||||||
} else {
|
|
||||||
return format!("Ptr::new({}, 0x{:x}, 0x{:x})", tag(ptr.tag()), ptr.lab(), ptr.loc());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Target {
|
|
||||||
nam: String
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Target {
|
|
||||||
fn show(&self) -> String {
|
|
||||||
format!("{}", self.nam)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get(&self) -> String {
|
|
||||||
format!("self.get({})", self.nam)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn swap(&self, value: &str) -> String {
|
|
||||||
format!("self.swap({}, {})", self.nam, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn take(&self) -> String {
|
|
||||||
self.swap(&"NULL")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compile_term(book: &run::Book, tab: usize, fid: run::Val) -> String {
|
|
||||||
|
|
||||||
// returns a fresh variable: 'v<NUM>'
|
|
||||||
fn fresh(newx: &mut usize) -> String {
|
|
||||||
*newx += 1;
|
|
||||||
format!("k{}", newx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call_redex(
|
|
||||||
book : &run::Book,
|
|
||||||
tab : usize,
|
|
||||||
newx : &mut usize,
|
|
||||||
vars : &mut HashMap<run::Ptr, String>,
|
|
||||||
def : &run::Def,
|
|
||||||
rdex : (run::Ptr, run::Ptr),
|
|
||||||
) -> String {
|
|
||||||
let (rf, rx) = adjust_redex(rdex.0, rdex.1);
|
|
||||||
let rf_name = format!("_{}", fresh(newx));
|
|
||||||
let mut code = String::new();
|
|
||||||
code.push_str(&format!("{}let {} : Trg = Trg::Ptr({});\n", ident(tab), rf_name, &atom(rf)));
|
|
||||||
code.push_str(&burn(book, tab, None, newx, vars, def, rx, &Target { nam: rf_name }));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn call(
|
|
||||||
book : &run::Book,
|
|
||||||
tab : usize,
|
|
||||||
tail : Option<run::Val>,
|
|
||||||
newx : &mut usize,
|
|
||||||
vars : &mut HashMap<run::Ptr, String>,
|
|
||||||
fid : run::Val,
|
|
||||||
trg : &Target,
|
|
||||||
) -> String {
|
|
||||||
//let newx = &mut 0;
|
|
||||||
//let vars = &mut HashMap::new();
|
|
||||||
|
|
||||||
let def = &book.get(fid).unwrap();
|
|
||||||
|
|
||||||
// Tail call
|
|
||||||
// TODO: when I manually edited a file to implement tail call, the single-core performance
|
|
||||||
// increased a lot, but it resulted in a single thread withholding all redexes and, thus,
|
|
||||||
// the program went single-core mode again. I believe a smarter redex sharing structure is
|
|
||||||
// necessary for us to implement tail calls in a way that doesn't sacrify parallelism.
|
|
||||||
//if tail.is_some() && def.rdex.len() > 0 && def.rdex[0].0.is_ref() && def.rdex[0].0.loc() == tail.unwrap() {
|
|
||||||
//println!("tco {}", ast::val_to_name(tail.unwrap() as run::Val));
|
|
||||||
//let mut code = String::new();
|
|
||||||
//for rdex in &def.rdex[1..] {
|
|
||||||
//code.push_str(&call_redex(book, tab, newx, vars, def, *rdex));
|
|
||||||
//}
|
|
||||||
//code.push_str(&burn(book, tab, Some(fid), newx, vars, def, def.node[0].1, &trg));
|
|
||||||
//code.push_str(&call_redex(book, tab, newx, vars, def, def.rdex[0]));
|
|
||||||
//return code;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Normal call
|
|
||||||
let mut code = String::new();
|
|
||||||
for rdex in &def.rdex {
|
|
||||||
code.push_str(&call_redex(book, tab, newx, vars, def, *rdex));
|
|
||||||
}
|
|
||||||
code.push_str(&burn(book, tab, Some(fid), newx, vars, def, def.node[0].2, &trg));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn burn(
|
|
||||||
book : &run::Book,
|
|
||||||
tab : usize,
|
|
||||||
tail : Option<run::Val>,
|
|
||||||
newx : &mut usize,
|
|
||||||
vars : &mut HashMap<run::Ptr, String>,
|
|
||||||
def : &run::Def,
|
|
||||||
ptr : run::Ptr,
|
|
||||||
trg : &Target,
|
|
||||||
) -> String {
|
|
||||||
//println!("burn {:08x} {}", ptr.0, x);
|
|
||||||
let mut code = String::new();
|
|
||||||
|
|
||||||
// (<?(ifz ifs) ret> ret) ~ (#X R)
|
|
||||||
// ------------------------------- fast match
|
|
||||||
// if X == 0:
|
|
||||||
// ifz ~ R
|
|
||||||
// ifs ~ *
|
|
||||||
// else:
|
|
||||||
// ifz ~ *
|
|
||||||
// ifs ~ (#(X-1) R)
|
|
||||||
// When ifs is REF, tail-call optimization is applied.
|
|
||||||
if ptr.tag() == run::LAM {
|
|
||||||
let mat = def.node[ptr.loc() as usize].1;
|
|
||||||
let rty = def.node[ptr.loc() as usize].2;
|
|
||||||
if mat.tag() == run::MAT {
|
|
||||||
let cse = def.node[mat.loc() as usize].1;
|
|
||||||
let rtx = def.node[mat.loc() as usize].2;
|
|
||||||
let got = def.node[rty.loc() as usize];
|
|
||||||
let rtz = if rty.tag() == run::VR1 { got.1 } else { got.2 };
|
|
||||||
if cse.tag() == run::LAM && rtx.is_var() && rtx == rtz {
|
|
||||||
let ifz = def.node[cse.loc() as usize].1;
|
|
||||||
let ifs = def.node[cse.loc() as usize].2;
|
|
||||||
let c_z = Target { nam: fresh(newx) };
|
|
||||||
let c_s = Target { nam: fresh(newx) };
|
|
||||||
let num = Target { nam: format!("{}x", trg.show()) };
|
|
||||||
let res = Target { nam: format!("{}y", trg.show()) };
|
|
||||||
let lam = fresh(newx);
|
|
||||||
let mat = fresh(newx);
|
|
||||||
let cse = fresh(newx);
|
|
||||||
code.push_str(&format!("{}let {} : Trg;\n", ident(tab), &c_z.show()));
|
|
||||||
code.push_str(&format!("{}let {} : Trg;\n", ident(tab), &c_s.show()));
|
|
||||||
code.push_str(&format!("{}// fast match\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}if {}.tag() == LAM && self.heap.get({}.loc(), P1).is_num() {{\n", ident(tab), trg.get(), trg.get()));
|
|
||||||
code.push_str(&format!("{}self.rwts.anni += 2;\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}self.rwts.oper += 1;\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}let got = {};\n", ident(tab+1), trg.take()));
|
|
||||||
code.push_str(&format!("{}let {} = Trg::Dir(Ptr::new(VR1, 0, got.loc()));\n", ident(tab+1), num.show()));
|
|
||||||
code.push_str(&format!("{}let {} = Trg::Dir(Ptr::new(VR2, 0, got.loc()));\n", ident(tab+1), res.show()));
|
|
||||||
code.push_str(&format!("{}if {}.val() == 0 {{\n", ident(tab+1), num.get()));
|
|
||||||
code.push_str(&format!("{}{};\n", ident(tab+2), num.take()));
|
|
||||||
code.push_str(&format!("{}{} = {};\n", ident(tab+2), &c_z.show(), res.show()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr({});\n", ident(tab+2), &c_s.show(), "ERAS"));
|
|
||||||
code.push_str(&format!("{}}} else {{\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}{};\n", ident(tab+2), num.swap(&format!("Ptr::big(NUM, {}.val() - 1)", num.get()))));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr({});\n", ident(tab+2), &c_z.show(), "ERAS"));
|
|
||||||
code.push_str(&format!("{}{} = {};\n", ident(tab+2), &c_s.show(), trg.show()));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}}} else {{\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}let {} = self.alloc();\n", ident(tab+1), lam));
|
|
||||||
code.push_str(&format!("{}let {} = self.alloc();\n", ident(tab+1), mat));
|
|
||||||
code.push_str(&format!("{}let {} = self.alloc();\n", ident(tab+1), cse));
|
|
||||||
code.push_str(&format!("{}self.heap.set({}, P1, Ptr::new(MAT, 0, {}));\n", ident(tab+1), lam, mat));
|
|
||||||
code.push_str(&format!("{}self.heap.set({}, P2, Ptr::new(VR2, 0, {}));\n", ident(tab+1), lam, mat));
|
|
||||||
code.push_str(&format!("{}self.heap.set({}, P1, Ptr::new(LAM, 0, {}));\n", ident(tab+1), mat, cse));
|
|
||||||
code.push_str(&format!("{}self.heap.set({}, P2, Ptr::new(VR2, 0, {}));\n", ident(tab+1), mat, lam));
|
|
||||||
code.push_str(&format!("{}self.safe_link(Trg::Ptr(Ptr::new(LAM, 0, {})), {});\n", ident(tab+1), lam, trg.show()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::new(VR1, 0, {}));\n", ident(tab+1), &c_z.show(), cse));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::new(VR2, 0, {}));\n", ident(tab+1), &c_s.show(), cse));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
code.push_str(&burn(book, tab, None, newx, vars, def, ifz, &c_z));
|
|
||||||
code.push_str(&burn(book, tab, tail, newx, vars, def, ifs, &c_s));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// #A ~ <+ #B r>
|
|
||||||
// ----------------- fast op
|
|
||||||
// r <~ #(op(+,A,B))
|
|
||||||
if ptr.is_op2() {
|
|
||||||
let val = def.node[ptr.loc() as usize].1;
|
|
||||||
let ret = def.node[ptr.loc() as usize].2;
|
|
||||||
if let Some(val) = got(vars, def, val) {
|
|
||||||
let val = Target { nam: val };
|
|
||||||
let nxt = Target { nam: fresh(newx) };
|
|
||||||
let op2 = fresh(newx);
|
|
||||||
code.push_str(&format!("{}let {} : Trg;\n", ident(tab), &nxt.show()));
|
|
||||||
code.push_str(&format!("{}// fast op\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}if {}.is_num() && {}.is_num() {{\n", ident(tab), trg.get(), val.get()));
|
|
||||||
code.push_str(&format!("{}self.rwts.oper += 2;\n", ident(tab+1))); // OP2 + OP1
|
|
||||||
code.push_str(&format!("{}let vx = {};\n", ident(tab+1), trg.take()));
|
|
||||||
code.push_str(&format!("{}let vy = {};\n", ident(tab+1), val.take()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::big(NUM, self.op({},vx.val(),vy.val())));\n", ident(tab+1), &nxt.show(), ptr.lab()));
|
|
||||||
code.push_str(&format!("{}}} else {{\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}let {} = self.alloc();\n", ident(tab+1), op2));
|
|
||||||
code.push_str(&format!("{}self.safe_link(Trg::Ptr(Ptr::new(VR1, 0, {})), {});\n", ident(tab+1), op2, val.show()));
|
|
||||||
code.push_str(&format!("{}self.safe_link(Trg::Ptr(Ptr::new(OP2, {}, {})), {});\n", ident(tab+1), ptr.lab(), op2, trg.show()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::new(VR2, 0, {}));\n", ident(tab+1), &nxt.show(), op2));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
code.push_str(&burn(book, tab, None, newx, vars, def, ret, &nxt));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// {p1 p2} <~ #N
|
|
||||||
// ------------- fast copy
|
|
||||||
// p1 <~ #N
|
|
||||||
// p2 <~ #N
|
|
||||||
if ptr.is_dup() {
|
|
||||||
let x1 = Target { nam: format!("{}x", trg.show()) };
|
|
||||||
let x2 = Target { nam: format!("{}y", trg.show()) };
|
|
||||||
let p1 = def.node[ptr.loc() as usize].1;
|
|
||||||
let p2 = def.node[ptr.loc() as usize].2;
|
|
||||||
let lc = fresh(newx);
|
|
||||||
code.push_str(&format!("{}let {} : Trg;\n", ident(tab), &x1.show()));
|
|
||||||
code.push_str(&format!("{}let {} : Trg;\n", ident(tab), &x2.show()));
|
|
||||||
code.push_str(&format!("{}// fast copy\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}if {}.tag() == NUM {{\n", ident(tab), trg.get()));
|
|
||||||
code.push_str(&format!("{}self.rwts.comm += 1;\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}let got = {};\n", ident(tab+1), trg.take()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(got);\n", ident(tab+1), &x1.show()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(got);\n", ident(tab+1), &x2.show()));
|
|
||||||
code.push_str(&format!("{}}} else {{\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}let {} = self.alloc();\n", ident(tab+1), lc));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::new(VR1, 0, {}));\n", ident(tab+1), &x1.show(), lc));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::new(VR2, 0, {}));\n", ident(tab+1), &x2.show(), lc));
|
|
||||||
code.push_str(&format!("{}self.safe_link(Trg::Ptr(Ptr::new({}, {}, {})), {});\n", ident(tab+1), tag(ptr.tag()), ptr.lab(), lc, trg.show()));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
code.push_str(&burn(book, tab, None, newx, vars, def, p2, &x2));
|
|
||||||
code.push_str(&burn(book, tab, None, newx, vars, def, p1, &x1));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// (p1 p2) <~ (x1 x2)
|
|
||||||
// ------------------ fast apply
|
|
||||||
// p1 <~ x1
|
|
||||||
// p2 <~ x2
|
|
||||||
if ptr.is_ctr() && ptr.tag() == run::LAM {
|
|
||||||
let x1 = Target { nam: format!("{}x", trg.show()) };
|
|
||||||
let x2 = Target { nam: format!("{}y", trg.show()) };
|
|
||||||
let p1 = def.node[ptr.loc() as usize].1;
|
|
||||||
let p2 = def.node[ptr.loc() as usize].2;
|
|
||||||
let lc = fresh(newx);
|
|
||||||
code.push_str(&format!("{}let {} : Trg;\n", ident(tab), &x1.show()));
|
|
||||||
code.push_str(&format!("{}let {} : Trg;\n", ident(tab), &x2.show()));
|
|
||||||
code.push_str(&format!("{}// fast apply\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}if {}.tag() == {} {{\n", ident(tab), trg.get(), tag(ptr.tag())));
|
|
||||||
code.push_str(&format!("{}self.rwts.anni += 1;\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}let got = {};\n", ident(tab+1), trg.take()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Dir(Ptr::new(VR1, 0, got.loc()));\n", ident(tab+1), &x1.show()));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Dir(Ptr::new(VR2, 0, got.loc()));\n", ident(tab+1), &x2.show()));
|
|
||||||
code.push_str(&format!("{}}} else {{\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}let {} = self.alloc();\n", ident(tab+1), lc));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::new(VR1, 0, {}));\n", ident(tab+1), &x1.show(), lc));
|
|
||||||
code.push_str(&format!("{}{} = Trg::Ptr(Ptr::new(VR2, 0, {}));\n", ident(tab+1), &x2.show(), lc));
|
|
||||||
code.push_str(&format!("{}self.safe_link(Trg::Ptr(Ptr::new({}, 0, {})), {});\n", ident(tab+1), tag(ptr.tag()), lc, trg.show()));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
code.push_str(&burn(book, tab, None, newx, vars, def, p2, &x2));
|
|
||||||
code.push_str(&burn(book, tab, None, newx, vars, def, p1, &x1));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
//// TODO: implement inlining correctly
|
|
||||||
//// NOTE: enabling this makes dec_bits_tree hang; investigate
|
|
||||||
//if ptr.is_ref() && tail.is_some() {
|
|
||||||
//code.push_str(&format!("{}// inline @{}\n", ident(tab), ast::val_to_name(ptr.loc() as run::Val)));
|
|
||||||
//code.push_str(&format!("{}if !{}.is_skp() {{\n", ident(tab), trg.get()));
|
|
||||||
//code.push_str(&format!("{}self.rwts.dref += 1;\n", ident(tab+1)));
|
|
||||||
//code.push_str(&call(book, tab+1, tail, newx, &mut HashMap::new(), ptr.loc(), trg));
|
|
||||||
//code.push_str(&format!("{}}} else {{\n", ident(tab)));
|
|
||||||
//code.push_str(&make(tab+1, newx, vars, def, ptr, &trg.show()));
|
|
||||||
//code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
//return code;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// ATOM <~ *
|
|
||||||
// --------- fast erase
|
|
||||||
// nothing
|
|
||||||
if ptr.is_num() || ptr.is_era() {
|
|
||||||
code.push_str(&format!("{}// fast erase\n", ident(tab)));
|
|
||||||
code.push_str(&format!("{}if {}.is_skp() {{\n", ident(tab), trg.get()));
|
|
||||||
code.push_str(&format!("{}{};\n", ident(tab+1), trg.take()));
|
|
||||||
code.push_str(&format!("{}self.rwts.eras += 1;\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}}} else {{\n", ident(tab)));
|
|
||||||
code.push_str(&make(tab+1, newx, vars, def, ptr, &trg.show()));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
code.push_str(&make(tab, newx, vars, def, ptr, &trg.show()));
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make(
|
|
||||||
tab : usize,
|
|
||||||
newx : &mut usize,
|
|
||||||
vars : &mut HashMap<run::Ptr, String>,
|
|
||||||
def : &run::Def,
|
|
||||||
ptr : run::Ptr,
|
|
||||||
trg : &String,
|
|
||||||
) -> String {
|
|
||||||
//println!("make {:08x} {}", ptr.0, x);
|
|
||||||
let mut code = String::new();
|
|
||||||
if ptr.is_nod() {
|
|
||||||
let lc = fresh(newx);
|
|
||||||
let p1 = def.node[ptr.loc() as usize].1;
|
|
||||||
let p2 = def.node[ptr.loc() as usize].2;
|
|
||||||
code.push_str(&format!("{}let {} = self.alloc();\n", ident(tab), lc));
|
|
||||||
code.push_str(&make(tab, newx, vars, def, p2, &format!("Trg::Ptr(Ptr::new(VR2, 0, {}))", lc)));
|
|
||||||
code.push_str(&make(tab, newx, vars, def, p1, &format!("Trg::Ptr(Ptr::new(VR1, 0, {}))", lc)));
|
|
||||||
code.push_str(&format!("{}self.safe_link(Trg::Ptr(Ptr::new({}, {}, {})), {});\n", ident(tab), tag(ptr.tag()), ptr.lab(), lc, trg));
|
|
||||||
} else if ptr.is_var() {
|
|
||||||
match got(vars, def, ptr) {
|
|
||||||
None => {
|
|
||||||
//println!("-var fst");
|
|
||||||
vars.insert(ptr, trg.clone());
|
|
||||||
},
|
|
||||||
Some(got) => {
|
|
||||||
//println!("-var snd");
|
|
||||||
code.push_str(&format!("{}self.safe_link({}, {});\n", ident(tab), trg, got));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
code.push_str(&format!("{}self.safe_link({}, Trg::Ptr({}));\n", ident(tab), trg, atom(ptr)));
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn got(
|
|
||||||
vars : &HashMap<run::Ptr, String>,
|
|
||||||
def : &run::Def,
|
|
||||||
ptr : run::Ptr,
|
|
||||||
) -> Option<String> {
|
|
||||||
if ptr.is_var() {
|
|
||||||
let got = def.node[ptr.loc() as usize];
|
|
||||||
let slf = if ptr.tag() == run::VR1 { got.1 } else { got.2 };
|
|
||||||
return vars.get(&slf).cloned();
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fun = ast::val_to_name(fid);
|
|
||||||
let def = &book.get(fid).unwrap();
|
|
||||||
|
|
||||||
let mut code = String::new();
|
|
||||||
// Given a label, returns true if the definition contains that dup label, directly or not
|
|
||||||
code.push_str(&format!("{}pub fn L_{}(&mut self, lab: Lab) -> bool {{\n", ident(tab), fun));
|
|
||||||
for dup in &def.labs {
|
|
||||||
code.push_str(&format!("{}if lab == 0x{:x} {{ return true; }}\n", ident(tab+1), dup));
|
|
||||||
}
|
|
||||||
code.push_str(&format!("{}return false;\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
// Calls the definition, performing inline rewrites when possible, and expanding it when not
|
|
||||||
code.push_str(&format!("{}pub fn F_{}(&mut self, ptr: Ptr, trg: Trg) -> bool {{\n", ident(tab), fun));
|
|
||||||
code.push_str(&format!("{}if self.get(trg).is_dup() && !self.L_{}(self.get(trg).lab()) {{\n", ident(tab+1), fun));
|
|
||||||
code.push_str(&format!("{}self.copy(self.swap(trg, NULL), ptr);\n", ident(tab+2)));
|
|
||||||
code.push_str(&format!("{}return true;\n", ident(tab+2)));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab+1)));
|
|
||||||
code.push_str(&call(book, tab+1, None, &mut 0, &mut HashMap::new(), fid, &Target { nam: "trg".to_string() }));
|
|
||||||
code.push_str(&format!("{}return true;\n", ident(tab+1)));
|
|
||||||
code.push_str(&format!("{}}}\n", ident(tab)));
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: HVM-Lang must always output in this form.
|
|
||||||
fn adjust_redex(rf: run::Ptr, rx: run::Ptr) -> (run::Ptr, run::Ptr) {
|
|
||||||
if rf.is_skp() && !rx.is_skp() {
|
|
||||||
return (rf, rx);
|
|
||||||
} else if !rf.is_skp() && rx.is_skp() {
|
|
||||||
return (rx, rf);
|
|
||||||
} else {
|
|
||||||
println!("Invalid redex. Compiled HVM requires that ALL defs are in the form:");
|
|
||||||
println!("@name = ROOT");
|
|
||||||
println!(" & ATOM ~ TERM");
|
|
||||||
println!(" & ATOM ~ TERM");
|
|
||||||
println!(" & ATOM ~ TERM");
|
|
||||||
println!(" ...");
|
|
||||||
println!("Where ATOM must be either a ref (`@foo`), a num (`#123`), or an era (`*`).");
|
|
||||||
println!("If you used HVM-Lang, please report on https://github.com/HigherOrderCO/hvm-lang.");
|
|
||||||
panic!("Invalid HVMC file.");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#![feature(generic_const_exprs)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(non_snake_case)]
|
|
||||||
#![allow(non_upper_case_globals)]
|
|
||||||
|
|
||||||
pub mod ast;
|
|
||||||
pub mod fns;
|
|
||||||
pub mod jit;
|
|
||||||
pub mod run;
|
|
||||||
pub mod u60;
|
|
@ -1,256 +0,0 @@
|
|||||||
#![feature(generic_const_exprs)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(non_snake_case)]
|
|
||||||
#![allow(non_upper_case_globals)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
|
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
|
||||||
|
|
||||||
use hvmc::ast;
|
|
||||||
use hvmc::fns;
|
|
||||||
use hvmc::jit;
|
|
||||||
use hvmc::run;
|
|
||||||
use hvmc::u60;
|
|
||||||
|
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
struct Args {
|
|
||||||
func: String,
|
|
||||||
argm: String,
|
|
||||||
opts: HashSet<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_args() -> Args {
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
let func = args.get(1).unwrap_or(&"help".to_string()).to_string();
|
|
||||||
let argm = args.get(2).unwrap_or(&"".to_string()).to_string();
|
|
||||||
let opts = args.iter().skip(3).map(|s| s.to_string()).collect::<HashSet<_>>();
|
|
||||||
return Args { func, argm, opts };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Runs 'main' without showing the CLI options
|
|
||||||
fn run_without_cli(args: Args) {
|
|
||||||
let lazy = args.opts.contains("-L");
|
|
||||||
let seq = lazy || args.opts.contains("-1");
|
|
||||||
let file = args.argm;
|
|
||||||
let book = run::Book::new();
|
|
||||||
let mut net = run::Net::new(1 << 28, false);
|
|
||||||
let begin = std::time::Instant::now();
|
|
||||||
if lazy { todo!() }
|
|
||||||
if seq {
|
|
||||||
net.normal(&book);
|
|
||||||
} else {
|
|
||||||
net.parallel_normal(&book);
|
|
||||||
}
|
|
||||||
println!("{}", net.show());
|
|
||||||
print_stats(&net, begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_with_cli(args: Args) -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
let lazy = args.opts.contains("-L");
|
|
||||||
let seq = lazy || args.opts.contains("-1");
|
|
||||||
match args.func.as_str() {
|
|
||||||
"run" => {
|
|
||||||
if args.argm.len() > 0 {
|
|
||||||
let file = args.argm;
|
|
||||||
let book = load_book(&file);
|
|
||||||
let mut net = run::Net::new(1 << 28, lazy);
|
|
||||||
let begin = std::time::Instant::now();
|
|
||||||
if seq {
|
|
||||||
net.normal(&book);
|
|
||||||
} else {
|
|
||||||
net.parallel_normal(&book);
|
|
||||||
}
|
|
||||||
//println!("{}", net.show());
|
|
||||||
println!("{}", net.show());
|
|
||||||
if args.opts.contains("-s") {
|
|
||||||
print_stats(&net, begin);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
println!("Usage: hvmc run <file.hvmc> [-s]");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"compile" => {
|
|
||||||
if args.argm.len() > 0 {
|
|
||||||
let file = args.argm;
|
|
||||||
let book = load_book(&file);
|
|
||||||
let net = run::Net::new(1 << 28, lazy);
|
|
||||||
let begin = std::time::Instant::now();
|
|
||||||
compile_book_to_rust_crate(&file, &book)?;
|
|
||||||
compile_rust_crate_to_executable(&file)?;
|
|
||||||
} else {
|
|
||||||
println!("Usage: hvmc compile <file.hvmc>");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"gen-cuda-book" => {
|
|
||||||
if args.argm.len() > 0 {
|
|
||||||
let file = args.argm;
|
|
||||||
let book = load_book(&file);
|
|
||||||
let net = run::Net::new(1 << 28, lazy);
|
|
||||||
let begin = std::time::Instant::now();
|
|
||||||
println!("{}", gen_cuda_book(&book));
|
|
||||||
} else {
|
|
||||||
println!("Usage: hvmc gen-cuda-book <file.hvmc>");
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
println!("Usage: hvmc <cmd> <file.hvmc> [-s]");
|
|
||||||
println!("Commands:");
|
|
||||||
println!(" run - Run the given file");
|
|
||||||
println!(" compile - Compile the given file to an executable");
|
|
||||||
println!(" gen-cuda-book - Generate a CUDA book from the given file");
|
|
||||||
println!("Options:");
|
|
||||||
println!(" [-s] Show stats, including rewrite count");
|
|
||||||
println!(" [-1] Single-core mode (no parallelism)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "hvm_cli_options"))]
|
|
||||||
fn main() {
|
|
||||||
run_without_cli(get_args())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "hvm_cli_options")]
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
run_with_cli(get_args())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_stats(net: &run::Net, begin: std::time::Instant) {
|
|
||||||
let rewrites = net.get_rewrites();
|
|
||||||
println!("RWTS : {}", rewrites.total());
|
|
||||||
println!("- ANNI : {}", rewrites.anni);
|
|
||||||
println!("- COMM : {}", rewrites.comm);
|
|
||||||
println!("- ERAS : {}", rewrites.eras);
|
|
||||||
println!("- DREF : {}", rewrites.dref);
|
|
||||||
println!("- OPER : {}", rewrites.oper);
|
|
||||||
println!("TIME : {:.3} s", (begin.elapsed().as_millis() as f64) / 1000.0);
|
|
||||||
println!("RPS : {:.3} m", (rewrites.total() as f64) / (begin.elapsed().as_millis() as f64) / 1000.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load file
|
|
||||||
fn load_book(file: &str) -> run::Book {
|
|
||||||
let Ok(file) = fs::read_to_string(file) else {
|
|
||||||
eprintln!("Input file not found");
|
|
||||||
std::process::exit(1);
|
|
||||||
};
|
|
||||||
return ast::book_to_runtime(&ast::do_parse_book(&file));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compile_book_to_rust_crate(f_name: &str, book: &run::Book) -> Result<(), std::io::Error> {
|
|
||||||
let fns_rs = jit::compile_book(book);
|
|
||||||
let outdir = ".hvm";
|
|
||||||
if std::path::Path::new(&outdir).exists() {
|
|
||||||
fs::remove_dir_all(&outdir)?;
|
|
||||||
}
|
|
||||||
let cargo_toml = include_str!("../Cargo.toml");
|
|
||||||
let cargo_toml = cargo_toml.split("##--COMPILER-CUTOFF--##").next().unwrap();
|
|
||||||
let cargo_toml = cargo_toml.replace("\"hvm_cli_options\"", "");
|
|
||||||
fs::create_dir_all(&format!("{}/src", outdir))?;
|
|
||||||
fs::write(".hvm/Cargo.toml", cargo_toml)?;
|
|
||||||
fs::write(".hvm/src/ast.rs", include_str!("../src/ast.rs"))?;
|
|
||||||
fs::write(".hvm/src/jit.rs", include_str!("../src/jit.rs"))?;
|
|
||||||
fs::write(".hvm/src/lib.rs", include_str!("../src/lib.rs"))?;
|
|
||||||
fs::write(".hvm/src/main.rs", include_str!("../src/main.rs"))?;
|
|
||||||
fs::write(".hvm/src/run.rs", include_str!("../src/run.rs"))?;
|
|
||||||
fs::write(".hvm/src/u60.rs", include_str!("../src/u60.rs"))?;
|
|
||||||
fs::write(".hvm/src/fns.rs", fns_rs)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compile_rust_crate_to_executable(f_name: &str) -> Result<(), std::io::Error> {
|
|
||||||
let output = std::process::Command::new("cargo").current_dir("./.hvm").arg("build").arg("--release").output()?;
|
|
||||||
let target = format!("./{}", f_name.replace(".hvmc", ""));
|
|
||||||
if std::path::Path::new(&target).exists() {
|
|
||||||
fs::remove_file(&target)?;
|
|
||||||
}
|
|
||||||
fs::copy("./.hvm/target/release/hvmc", target)?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: move to hvm-cuda repo
|
|
||||||
pub fn gen_cuda_book(book: &run::Book) -> String {
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
// Sort the book.defs by key
|
|
||||||
let mut defs = BTreeMap::new();
|
|
||||||
for (fid, def) in book.defs.iter() {
|
|
||||||
if def.node.len() > 0 {
|
|
||||||
defs.insert(fid, def.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initializes code
|
|
||||||
let mut code = String::new();
|
|
||||||
|
|
||||||
// Generate function ids
|
|
||||||
for (i, id) in defs.keys().enumerate() {
|
|
||||||
code.push_str(&format!("const u32 F_{} = 0x{:x};\n", crate::ast::val_to_name(**id), id));
|
|
||||||
}
|
|
||||||
code.push_str("\n");
|
|
||||||
|
|
||||||
// Create book
|
|
||||||
code.push_str("u32 BOOK_DATA[] = {\n");
|
|
||||||
|
|
||||||
// Generate book data
|
|
||||||
for (i, (id, net)) in defs.iter().enumerate() {
|
|
||||||
let node_len = net.node.len();
|
|
||||||
let rdex_len = net.rdex.len();
|
|
||||||
|
|
||||||
code.push_str(&format!(" // @{}\n", crate::ast::val_to_name(**id)));
|
|
||||||
|
|
||||||
// Collect all pointers from root, nodes and rdex into a single buffer
|
|
||||||
code.push_str(&format!(" // .nlen\n"));
|
|
||||||
code.push_str(&format!(" 0x{:08X},\n", node_len));
|
|
||||||
code.push_str(&format!(" // .rlen\n"));
|
|
||||||
code.push_str(&format!(" 0x{:08X},\n", rdex_len));
|
|
||||||
|
|
||||||
// .node
|
|
||||||
code.push_str(" // .node\n");
|
|
||||||
for (i, node) in net.node.iter().enumerate() {
|
|
||||||
code.push_str(&format!(" 0x{:08X},", node.1.0));
|
|
||||||
code.push_str(&format!(" 0x{:08X},", node.2.0));
|
|
||||||
if (i + 1) % 4 == 0 {
|
|
||||||
code.push_str("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if node_len % 4 != 0 {
|
|
||||||
code.push_str("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// .rdex
|
|
||||||
code.push_str(" // .rdex\n");
|
|
||||||
for (i, (a, b)) in net.rdex.iter().enumerate() {
|
|
||||||
code.push_str(&format!(" 0x{:08X},", a.0));
|
|
||||||
code.push_str(&format!(" 0x{:08X},", b.0));
|
|
||||||
if (i + 1) % 4 == 0 {
|
|
||||||
code.push_str("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rdex_len % 4 != 0 {
|
|
||||||
code.push_str("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
code.push_str("};\n\n");
|
|
||||||
|
|
||||||
code.push_str("u32 JUMP_DATA[] = {\n");
|
|
||||||
|
|
||||||
let mut index = 0;
|
|
||||||
for (i, fid) in defs.keys().enumerate() {
|
|
||||||
code.push_str(&format!(" 0x{:08X}, 0x{:08X}, // @{}\n", fid, index, crate::ast::val_to_name(**fid)));
|
|
||||||
index += 2 + 2 * defs[fid].node.len() as u32 + 2 * defs[fid].rdex.len() as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
code.push_str("};");
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
1389
book/.hvm/src/run.rs
1389
book/.hvm/src/run.rs
File diff suppressed because it is too large
Load Diff
@ -1,113 +0,0 @@
|
|||||||
// Implements u48: 48-bit unsigned integers using u64 and u128
|
|
||||||
|
|
||||||
type U60 = u64;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn new(a: u64) -> U60 {
|
|
||||||
return a & 0xFFF_FFFF_FFFF_FFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn val(a: u64) -> U60 {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn add(a: U60, b: U60) -> U60 {
|
|
||||||
return new(a + b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn sub(a: U60, b: U60) -> U60 {
|
|
||||||
return if a >= b { a - b } else { 0x1000000000000000 - (b - a) };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn mul(a: U60, b: U60) -> U60 {
|
|
||||||
return new((a as u128 * b as u128) as u64);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn div(a: U60, b: U60) -> U60 {
|
|
||||||
return a / b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn rem(a: U60, b: U60) -> U60 {
|
|
||||||
return a % b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn and(a: U60, b: U60) -> U60 {
|
|
||||||
return a & b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn or(a: U60, b: U60) -> U60 {
|
|
||||||
return a | b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn xor(a: U60, b: U60) -> U60 {
|
|
||||||
return a ^ b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn lsh(a: U60, b: U60) -> U60 {
|
|
||||||
return new(a << b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn rsh(a: U60, b: U60) -> U60 {
|
|
||||||
return a >> b;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn lt(a: U60, b: U60) -> U60 {
|
|
||||||
return if a < b { 1 } else { 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn gt(a: U60, b: U60) -> U60 {
|
|
||||||
return if a > b { 1 } else { 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn lte(a: U60, b: U60) -> U60 {
|
|
||||||
return if a <= b { 1 } else { 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn gte(a: U60, b: U60) -> U60 {
|
|
||||||
return if a >= b { 1 } else { 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn eq(a: U60, b: U60) -> U60 {
|
|
||||||
return if a == b { 1 } else { 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn ne(a: U60, b: U60) -> U60 {
|
|
||||||
return if a != b { 1 } else { 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn min(a: U60, b: U60) -> U60 {
|
|
||||||
return if a < b { a } else { b };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn max(a: U60, b: U60) -> U60 {
|
|
||||||
return if a > b { a } else { b };
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn not(a: U60) -> U60 {
|
|
||||||
return !a & 0xFFF_FFFF_FFFF_FFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn show(a: U60) -> String {
|
|
||||||
return format!("{}", a);
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
{"rustc_fingerprint":4802413464031946296,"outputs":{"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/v/.rustup/toolchains/nightly-aarch64-apple-darwin\noff\npacked\nunpacked\n___\ndebug_assertions\noverflow_checks\npanic=\"unwind\"\nproc_macro\nrelocation_model=\"pic\"\ntarget_abi=\"\"\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"v8.1a\"\ntarget_feature=\"v8.2a\"\ntarget_feature=\"v8.3a\"\ntarget_feature=\"v8.4a\"\ntarget_feature=\"vh\"\ntarget_has_atomic\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"128\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store\ntarget_has_atomic_load_store=\"128\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.76.0-nightly (9a66e4471 2023-11-19)\nbinary: rustc\ncommit-hash: 9a66e4471f71283fd54d80ef8147630d34756332\ncommit-date: 2023-11-19\nhost: aarch64-apple-darwin\nrelease: 1.76.0-nightly\nLLVM version: 17.0.5\n","stderr":""}},"successes":{}}
|
|
@ -1,3 +0,0 @@
|
|||||||
Signature: 8a477f597d28d172789f06886806bc55
|
|
||||||
# This file is a cache directory tag created by cargo.
|
|
||||||
# For information about cache directory tags see https://bford.info/cachedir/
|
|
@ -1 +0,0 @@
|
|||||||
This file has an mtime of when this was started.
|
|
@ -1,5 +0,0 @@
|
|||||||
{"message":"expected one of `:`, `;`, `<`, `=`, or `where`, found `.`","code":null,"level":"error","spans":[{"file_name":"src/fns.rs","byte_start":186,"byte_end":187,"line_start":7,"line_end":7,"column_start":17,"column_end":18,"is_primary":true,"text":[{"text":"pub const F__U60.fib : Val = 0xf9e180fe9b25;","highlight_start":17,"highlight_end":18}],"label":"expected one of `:`, `;`, `<`, `=`, or `where`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: expected one of `:`, `;`, `<`, `=`, or `where`, found `.`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/fns.rs:7:17\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m7\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0mpub const F__U60.fib : Val = 0xf9e180fe9b25;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mexpected one of `:`, `;`, `<`, `=`, or `where`\u001b[0m\n\n"}
|
|
||||||
{"message":"no method named `call_native` found for mutable reference `&mut NetFields<'a, LAZY>` in the current scope","code":{"code":"E0599","explanation":"This error occurs when a method is used on a type which doesn't implement it:\n\nErroneous code example:\n\n```compile_fail,E0599\nstruct Mouth;\n\nlet x = Mouth;\nx.chocolate(); // error: no method named `chocolate` found for type `Mouth`\n // in the current scope\n```\n\nIn this case, you need to implement the `chocolate` method to fix the error:\n\n```\nstruct Mouth;\n\nimpl Mouth {\n fn chocolate(&self) { // We implement the `chocolate` method here.\n println!(\"Hmmm! I love chocolate!\");\n }\n}\n\nlet x = Mouth;\nx.chocolate(); // ok!\n```\n"},"level":"error","spans":[{"file_name":"src/run.rs","byte_start":30344,"byte_end":30355,"line_start":993,"line_end":993,"column_start":24,"column_end":35,"is_primary":true,"text":[{"text":" if !LAZY && self.call_native(book, ptr, trg) {","highlight_start":24,"highlight_end":35}],"label":"method not found in `&mut NetFields<'a, LAZY>`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror[E0599]\u001b[0m\u001b[0m\u001b[1m: no method named `call_native` found for mutable reference `&mut NetFields<'a, LAZY>` in the current scope\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/run.rs:993:24\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m993\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m if !LAZY && self.call_native(book, ptr, trg) {\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^^^^^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mmethod not found in `&mut NetFields<'a, LAZY>`\u001b[0m\n\n"}
|
|
||||||
{"message":"missing type for `const` item","code":null,"level":"error","spans":[{"file_name":"src/fns.rs","byte_start":186,"byte_end":186,"line_start":7,"line_end":7,"column_start":17,"column_end":17,"is_primary":true,"text":[{"text":"pub const F__U60.fib : Val = 0xf9e180fe9b25;","highlight_start":17,"highlight_end":17}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"provide a type for the item","code":null,"level":"help","spans":[{"file_name":"src/fns.rs","byte_start":186,"byte_end":186,"line_start":7,"line_end":7,"column_start":17,"column_end":17,"is_primary":true,"text":[{"text":"pub const F__U60.fib : Val = 0xf9e180fe9b25;","highlight_start":17,"highlight_end":17}],"label":null,"suggested_replacement":": <type>","suggestion_applicability":"HasPlaceholders","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: missing type for `const` item\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/fns.rs:7:17\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m7\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0mpub const F__U60.fib : Val = 0xf9e180fe9b25;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mhelp: provide a type for the item: `: <type>`\u001b[0m\n\n"}
|
|
||||||
{"message":"aborting due to 3 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: aborting due to 3 previous errors\u001b[0m\n\n"}
|
|
||||||
{"message":"For more information about this error, try `rustc --explain E0599`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0599`.\u001b[0m\n"}
|
|
Binary file not shown.
@ -1 +0,0 @@
|
|||||||
This file has an mtime of when this was started.
|
|
@ -1 +0,0 @@
|
|||||||
7cda99c4629b01d5
|
|
@ -1 +0,0 @@
|
|||||||
{"rustc":15865603277963313838,"features":"[\"default\", \"std\"]","target":2117364898282992337,"profile":15536308671813986309,"path":6587989396380489126,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"release/.fingerprint/nohash-hasher-dc8a50f19f38f70e/dep-lib-nohash-hasher"}}],"rustflags":[],"metadata":8492774112348001440,"config":2202906307356721367,"compile_kind":0}
|
|
@ -1,12 +0,0 @@
|
|||||||
/Users/v/vic/dev/kind2/book/.hvm/target/release/deps/libhvmc-5d3b356175a8b321.rmeta: src/lib.rs src/ast.rs src/fns.rs src/jit.rs src/run.rs src/u60.rs
|
|
||||||
|
|
||||||
/Users/v/vic/dev/kind2/book/.hvm/target/release/deps/libhvmc-5d3b356175a8b321.rlib: src/lib.rs src/ast.rs src/fns.rs src/jit.rs src/run.rs src/u60.rs
|
|
||||||
|
|
||||||
/Users/v/vic/dev/kind2/book/.hvm/target/release/deps/hvmc-5d3b356175a8b321.d: src/lib.rs src/ast.rs src/fns.rs src/jit.rs src/run.rs src/u60.rs
|
|
||||||
|
|
||||||
src/lib.rs:
|
|
||||||
src/ast.rs:
|
|
||||||
src/fns.rs:
|
|
||||||
src/jit.rs:
|
|
||||||
src/run.rs:
|
|
||||||
src/u60.rs:
|
|
Binary file not shown.
Binary file not shown.
@ -1,7 +0,0 @@
|
|||||||
/Users/v/vic/dev/kind2/book/.hvm/target/release/deps/libnohash_hasher-dc8a50f19f38f70e.rmeta: /Users/v/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nohash-hasher-0.2.0/src/lib.rs
|
|
||||||
|
|
||||||
/Users/v/vic/dev/kind2/book/.hvm/target/release/deps/libnohash_hasher-dc8a50f19f38f70e.rlib: /Users/v/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nohash-hasher-0.2.0/src/lib.rs
|
|
||||||
|
|
||||||
/Users/v/vic/dev/kind2/book/.hvm/target/release/deps/nohash_hasher-dc8a50f19f38f70e.d: /Users/v/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nohash-hasher-0.2.0/src/lib.rs
|
|
||||||
|
|
||||||
/Users/v/.cargo/registry/src/index.crates.io-6f17d22bba15001f/nohash-hasher-0.2.0/src/lib.rs:
|
|
3
book/Tree.kind2
Normal file
3
book/Tree.kind2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
data Tree A
|
||||||
|
| node (val: A) (lft: (Tree A)) (rgt: (Tree A))
|
||||||
|
| leaf
|
7
book/Tree/fold.kind2
Normal file
7
book/Tree/fold.kind2
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use Tree/{node,leaf}
|
||||||
|
|
||||||
|
Tree/fold <A> <B> (bm: (Tree A)) (nd: A -> B -> B -> B) (lf: B) : B =
|
||||||
|
match bm with (nd: A -> B -> B -> B) (lf: B) {
|
||||||
|
node: (nd bm.val (Tree/fold bm.lft nd lf) (Tree/fold bm.rgt nd lf))
|
||||||
|
leaf: lf
|
||||||
|
}
|
7
book/Tree/gen.kind2
Normal file
7
book/Tree/gen.kind2
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use Tree/{node,leaf}
|
||||||
|
|
||||||
|
gen (n: U60) (x: U60) : (Tree U60) =
|
||||||
|
switch n {
|
||||||
|
0: leaf
|
||||||
|
_: (node x (gen n-1 (+ (* x 2) 1)) (gen n-1 (+ (* x 2) 2)))
|
||||||
|
}
|
3
book/Tree/leaf.kind2
Normal file
3
book/Tree/leaf.kind2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
leaf <A> : (Tree A) =
|
||||||
|
~λP λnode λleaf
|
||||||
|
leaf
|
3
book/Tree/node.kind2
Normal file
3
book/Tree/node.kind2
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node <A> (val: A) (lft: (Tree A)) (rgt: (Tree A)) : (Tree A) =
|
||||||
|
~λP λnode λleaf
|
||||||
|
(node val lft rgt)
|
18
book/Tree/sum.kind2
Normal file
18
book/Tree/sum.kind2
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use Tree/{node,leaf}
|
||||||
|
|
||||||
|
// Sums a binary tree in parallel, using fold
|
||||||
|
// __(1)__
|
||||||
|
// / \ __(1)__
|
||||||
|
// (1) (2) => / \ => (14)
|
||||||
|
// / \ / \ (4) (9)
|
||||||
|
// (1) (2) (3) (4)
|
||||||
|
|
||||||
|
sum (x: (Tree U60)) : U60 =
|
||||||
|
fold x {
|
||||||
|
node: (+ x.val (+ x.lft x.rgt))
|
||||||
|
leaf: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
book/_main
Executable file
BIN
book/_main
Executable file
Binary file not shown.
@ -1,21 +1,33 @@
|
|||||||
|
//WARNING: unsolved metas_
|
||||||
|
//WARNING: unsolved metas_
|
||||||
_Char = 0
|
_Char = 0
|
||||||
_List = λ_T 0
|
_List = λ_T 0
|
||||||
_List.Folder = λ_T 0
|
_List_cons = λ_head λ_tail λ_P λ_cons λ_nil ((_cons _head) _tail)
|
||||||
_List.cons = λ_T λ_head λ_tail λ_P λ_cons λ_nil ((_cons _head) _tail)
|
_List_nil = λ_P λ_cons λ_nil _nil
|
||||||
_List.fold = λ_list
|
|
||||||
let _list.P = 0
|
|
||||||
let _list.cons = λ_list.head λ_list.tail λ_P λ_c λ_n ((_c _list.head) (((((_List.fold) _list.tail) _P) _c) _n))
|
|
||||||
let _list.nil = λ_P λ_c λ_n _n
|
|
||||||
(((_list _list.P) _list.cons) _list.nil)
|
|
||||||
_List.map = λ_A λ_B λ_xs λ_f (((((_List.fold) _xs) 0) λ_h λ_t (((_List.cons 0) (_f _h)) _t)) (_List.nil 0))
|
|
||||||
_List.nil = λ_T λ_P λ_cons λ_nil _nil
|
|
||||||
_Nat = 0
|
_Nat = 0
|
||||||
_Nat.succ = λ_n λ_P λ_succ λ_zero (_succ _n)
|
_Nat_succ = λ_n λ_P λ_succ λ_zero (_succ _n)
|
||||||
_Nat.zero = λ_P λ_succ λ_zero _zero
|
_Nat_zero = λ_P λ_succ λ_zero _zero
|
||||||
_String = (_List _Char)
|
_String = (_List _Char)
|
||||||
_String.cons = λ_head λ_tail λ_P λ_cons λ_nil ((_cons _head) _tail)
|
_String_cons = λ_head λ_tail λ_P λ_cons λ_nil ((_cons _head) _tail)
|
||||||
_String.nil = λ_P λ_cons λ_nil _nil
|
_String_nil = λ_P λ_cons λ_nil _nil
|
||||||
__main = ((((_List.map 0) 0) (((_List.cons 0) 1) (((_List.cons 0) 2) (((_List.cons 0) 3) (_List.nil 0))))) λ_x (+ _x 1))
|
_Tree = λ_A 0
|
||||||
|
_Tree_fold = λ_bm λ_nd λ_lf
|
||||||
|
let _bm_P = 0
|
||||||
|
let _bm_node = λ_bm_val λ_bm_lft λ_bm_rgt λ_nd λ_lf (((_nd _bm_val) (((_Tree_fold _bm_lft) _nd) _lf)) (((_Tree_fold _bm_rgt) _nd) _lf))
|
||||||
|
let _bm_leaf = λ_nd λ_lf _lf
|
||||||
|
(((((_bm _bm_P) _bm_node) _bm_leaf) _nd) _lf)
|
||||||
|
_Tree_gen = λ_n λ_x match _n = _n {
|
||||||
|
0: _Tree_leaf
|
||||||
|
1+: let _n-1 = _n-1
|
||||||
|
(((_Tree_node _x) ((_Tree_gen _n-1) (+ (* _x 2) 1))) ((_Tree_gen _n-1) (+ (* _x 2) 2)))
|
||||||
|
}
|
||||||
|
_Tree_leaf = λ_P λ_node λ_leaf _leaf
|
||||||
|
_Tree_node = λ_val λ_lft λ_rgt λ_P λ_node λ_leaf (((_node _val) _lft) _rgt)
|
||||||
|
_Tree_sum = λ_x
|
||||||
|
let _x_P = 0
|
||||||
|
let _x_node = λ_x_val λ_x_lft λ_x_rgt (+ _x_val (+ _x_lft _x_rgt))
|
||||||
|
let _x_leaf = 0
|
||||||
|
(((_Tree_fold _x) _x_node) _x_leaf)
|
||||||
|
__main = (_Tree_sum ((_Tree_gen 22) 0))
|
||||||
|
|
||||||
main = __main
|
main = __main
|
||||||
|
|
||||||
|
@ -1,17 +1,37 @@
|
|||||||
@cons = (a (b ((a (b c)) (* c))))
|
@_chr = #0
|
||||||
|
@_ls = (* #0)
|
||||||
@foo = ({3 (a b) c} (a (d e)))
|
@_ls_cn = (a (b (* ((a (b c)) (* c)))))
|
||||||
& @cons ~ (b (f e))
|
@_ls_nl = (* @_ls_nl_0)
|
||||||
& @map ~ (c (d f))
|
@_ls_nl_0 = (* (a a))
|
||||||
|
@_N = #0
|
||||||
@main = a
|
@_N_s = (a (* ((a b) (* b))))
|
||||||
& @map ~ ((<+ #1 b> b) (c a))
|
@_N_z = (* @_N_z_0)
|
||||||
& @cons ~ (#1 (d c))
|
@_N_z_0 = (* (a a))
|
||||||
& @cons ~ (#2 (e d))
|
@_str = a
|
||||||
& @cons ~ (#3 (@nil e))
|
& @_ls ~ (@_chr a)
|
||||||
|
@_str_cn = (a (b (* ((a (b c)) (* c)))))
|
||||||
@map = (a ((b (@nil c)) c))
|
@_str_nl = (* @_str_nl_0)
|
||||||
& @foo ~ (a b)
|
@_str_nl_0 = (* (a a))
|
||||||
|
@_T = (* #0)
|
||||||
@nil = (* (a a))
|
@_T_f = ((#0 (@_T_f_0 (@_T_f_1 (a (b c))))) (a (b c)))
|
||||||
|
@_T_f_0 = (a (b (c ({7 (a (d (e f))) {7 g h}} ({9 i j} f)))))
|
||||||
|
& @_T_f ~ (c (h (j e)))
|
||||||
|
& @_T_f ~ (b (g (i d)))
|
||||||
|
@_T_f_1 = (* (a a))
|
||||||
|
@_T_gn = (?<(@_T_gn_0 @_T_gn_1) (a b)> (a b))
|
||||||
|
@_T_gn_0 = (* @_T_lf)
|
||||||
|
@_T_gn_1 = ({5 a b} ({3 c {3 <* #2 <+ #1 d>> <* #2 <+ #2 e>>}} f))
|
||||||
|
& @_T_nd ~ (c (g (h f)))
|
||||||
|
& @_T_gn ~ (b (e h))
|
||||||
|
& @_T_gn ~ (a (d g))
|
||||||
|
@_T_lf = (* @_T_lf_0)
|
||||||
|
@_T_lf_0 = (* (a a))
|
||||||
|
@_T_nd = (a (b (c (* ((a (b (c d))) (* d))))))
|
||||||
|
@_T_sum = (a b)
|
||||||
|
& @_T_f ~ (a (@_T_sum_0 (#0 b)))
|
||||||
|
@_T_sum_0 = (<+ a b> (<+ c a> (c b)))
|
||||||
|
@__main = a
|
||||||
|
& @_T_sum ~ (b a)
|
||||||
|
& @_T_gn ~ (#22 (#0 b))
|
||||||
|
@main = @__main
|
||||||
|
|
||||||
|
36
book/_main.js
Normal file
36
book/_main.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
let _Char = 0;
|
||||||
|
let _List = (_T) => 0;
|
||||||
|
let _List_cons = (_head) => (_tail) => (_P) => (_cons) => (_nil) => ((_cons(_head))(_tail));
|
||||||
|
let _List_nil = (_P) => (_cons) => (_nil) => _nil;
|
||||||
|
let _Nat = 0;
|
||||||
|
let _Nat_succ = (_n) => (_P) => (_succ) => (_zero) => (_succ(_n));
|
||||||
|
let _Nat_zero = (_P) => (_succ) => (_zero) => _zero;
|
||||||
|
let _String = (_List(_Char));
|
||||||
|
let _String_cons = (_head) => (_tail) => (_P) => (_cons) => (_nil) => ((_cons(_head))(_tail));
|
||||||
|
let _String_nil = (_P) => (_cons) => (_nil) => _nil;
|
||||||
|
let _Tree = (_A) => 0;
|
||||||
|
let _Tree_fold = (_bm) => (_nd) => (_lf) => {
|
||||||
|
let _bm_P = 0;
|
||||||
|
let _bm_node = (_bm_val) => (_bm_lft) => (_bm_rgt) => (_nd) => (_lf) => (((_nd(_bm_val))(((_Tree_fold(_bm_lft))(_nd))(_lf)))(((_Tree_fold(_bm_rgt))(_nd))(_lf)));
|
||||||
|
let _bm_leaf = (_nd) => (_lf) => _lf;
|
||||||
|
return (((((_bm(_bm_P))(_bm_node))(_bm_leaf))(_nd))(_lf));
|
||||||
|
};
|
||||||
|
let _Tree_gen = (_n) => (_x) => {
|
||||||
|
if (_n === 0) {
|
||||||
|
return _Tree_leaf;
|
||||||
|
} else {
|
||||||
|
let _n_1 = _n - 1;
|
||||||
|
return (((_Tree_node(_x))((_Tree_gen(_n_1))(((_x * 2) + 1))))((_Tree_gen(_n_1))(((_x * 2) + 2))));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _Tree_leaf = (_P) => (_node) => (_leaf) => _leaf;
|
||||||
|
let _Tree_node = (_val) => (_lft) => (_rgt) => (_P) => (_node) => (_leaf) => (((_node(_val))(_lft))(_rgt));
|
||||||
|
let _Tree_sum = (_x) => {
|
||||||
|
let _x_P = 0;
|
||||||
|
let _x_node = (_x_val) => (_x_lft) => (_x_rgt) => (_x_val + (_x_lft + _x_rgt));
|
||||||
|
let _x_leaf = 0;
|
||||||
|
return (((_Tree_fold(_x))(_x_node))(_x_leaf));
|
||||||
|
};
|
||||||
|
let __main = (_Tree_sum((_Tree_gen(22))(0)));
|
||||||
|
|
||||||
|
console.log(__main)
|
@ -1,11 +1,40 @@
|
|||||||
//data Vector A (len: Nat)
|
|
||||||
//| cons (len: Nat) (head: A) (tail: (Vector A len)) : (Vector A (Nat.succ len))
|
//// Sums a binary tree in parallel, using fold
|
||||||
//| nil : (Vector A Nat.zero)
|
//// __(1)__
|
||||||
|
//// / \ __(1)__
|
||||||
|
//// (1) (2) => / \ => (14)
|
||||||
|
//// / \ / \ (4) (9)
|
||||||
|
//// (1) (2) (3) (4)
|
||||||
|
|
||||||
|
//use Tree/{node,leaf}
|
||||||
|
|
||||||
|
//data Tree A
|
||||||
|
//| node (val: A) (lft: (Tree A)) (rgt: (Tree A))
|
||||||
|
//| leaf
|
||||||
|
|
||||||
|
//sum (x: (Tree U60)) : U60 =
|
||||||
|
//fold x {
|
||||||
|
//node: (+ x.val (+ x.lft x.rgt))
|
||||||
|
//leaf: 0
|
||||||
|
//}
|
||||||
|
|
||||||
|
//gen (n: U60) (x: U60) : (Tree U60) =
|
||||||
|
//switch n {
|
||||||
|
//0: leaf
|
||||||
|
//_: (node x (gen n-1 (+ (* x 2) 1)) (gen n-1 (+ (* x 2) 2)))
|
||||||
|
//}
|
||||||
|
|
||||||
|
//main = (sum (gen 16 0))
|
||||||
|
|
||||||
|
use Tree/{node,leaf,gen,sum}
|
||||||
|
|
||||||
|
_main: U60 =
|
||||||
|
(sum (gen 16 0))
|
||||||
|
|
||||||
//use Nat.{succ,zero}
|
//use Nat.{succ,zero}
|
||||||
|
|
||||||
_main: (List U60) =
|
//_main: (List U60) =
|
||||||
(List.map _ _ (List.cons _ 1 (List.cons _ 2 (List.cons _ 3 (List.nil _)))) λx(+ x 1))
|
//(List.map _ _ (List.cons _ 1 (List.cons _ 2 (List.cons _ 3 (List.nil _)))) λx(+ x 1))
|
||||||
|
|
||||||
//_main : (Maybe U60) =
|
//_main : (Maybe U60) =
|
||||||
//(Maybe.bind _ _ (Maybe.some _ 1) λx
|
//(Maybe.bind _ _ (Maybe.some _ 1) λx
|
||||||
|
@ -922,9 +922,9 @@ impl Term {
|
|||||||
// 3. Make `(~x <motive>)` or `(Type/fold/ _ <motive> x)`
|
// 3. Make `(~x <motive>)` or `(Type/fold/ _ <motive> x)`
|
||||||
if mat.fold {
|
if mat.fold {
|
||||||
term = Term::App {
|
term = Term::App {
|
||||||
era: true,
|
era: false,
|
||||||
fun: Box::new(Term::App {
|
fun: Box::new(Term::App {
|
||||||
era: false,
|
era: true,
|
||||||
fun: Box::new(Term::App {
|
fun: Box::new(Term::App {
|
||||||
era: true,
|
era: true,
|
||||||
fun: Box::new(Term::Var { nam: format!("{}/fold/", adt.name) }),
|
fun: Box::new(Term::Var { nam: format!("{}/fold/", adt.name) }),
|
||||||
@ -936,7 +936,7 @@ impl Term {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
term = Term::App {
|
term = Term::App {
|
||||||
era: true,
|
era: false,
|
||||||
fun: Box::new(Term::Ins {
|
fun: Box::new(Term::Ins {
|
||||||
val: Box::new(mat.expr.clone())
|
val: Box::new(mat.expr.clone())
|
||||||
}),
|
}),
|
||||||
|
@ -300,7 +300,7 @@ impl Term {
|
|||||||
let x = x.to_hvm2();
|
let x = x.to_hvm2();
|
||||||
let z = z.to_hvm2();
|
let z = z.to_hvm2();
|
||||||
let s = s.to_hvm2();
|
let s = s.to_hvm2();
|
||||||
format!("match {} = {} {{ 0: {} +: {} }}", Term::to_hvm2_name(nam), x, z, s)
|
format!("match {} = {} {{ 0: {} 1+: {} }}", Term::to_hvm2_name(nam), x, z, s)
|
||||||
},
|
},
|
||||||
Term::Let { nam, val, bod } => {
|
Term::Let { nam, val, bod } => {
|
||||||
let val = val.to_hvm2();
|
let val = val.to_hvm2();
|
||||||
@ -339,7 +339,7 @@ impl Term {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_hvm2_name(name: &str) -> String {
|
pub fn to_hvm2_name(name: &str) -> String {
|
||||||
format!("_{}", name)
|
format!("_{}", name.replace("/","."))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user