mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-11-20 13:04:06 +03:00
Add raw hvm function syntax
This commit is contained in:
parent
4d43bd9405
commit
d6bdde548e
@ -14,11 +14,12 @@ and this project does not currently adhere to a particular versioning scheme.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed readback of numeric operations. ([#467][gh-467])
|
||||
- Fix readback of numeric operations. ([#467][gh-467])
|
||||
|
||||
### Added
|
||||
|
||||
- `log` and `atan2` builtin functions. ([#583][gh-583])
|
||||
- Add `log` and `atan2` builtin functions. ([#583][gh-583])
|
||||
- Create new type of top-level definition for writing native HVM definitions. ([#586][gh-586])
|
||||
|
||||
## [0.2.35] - 2024-06-06
|
||||
|
||||
@ -30,7 +31,7 @@ and this project does not currently adhere to a particular versioning scheme.
|
||||
|
||||
### Added
|
||||
|
||||
- Create `<=` and `>=` operators. ([#451][gh-451])
|
||||
- Add syntax for "less than or equal" `<=` and "greater than or equal" `>=` numeric operators. ([#451][gh-451])
|
||||
|
||||
## [0.2.33] - 2024-06-05
|
||||
|
||||
@ -340,4 +341,5 @@ and this project does not currently adhere to a particular versioning scheme.
|
||||
[gh-526]: https://github.com/HigherOrderCO/Bend/issues/526
|
||||
[gh-528]: https://github.com/HigherOrderCO/Bend/issues/528
|
||||
[gh-583]: https://github.com/HigherOrderCO/Bend/issues/583
|
||||
[gh-586]: https://github.com/HigherOrderCO/Bend/issues/586
|
||||
[Unreleased]: https://github.com/HigherOrderCO/Bend/compare/0.2.35...HEAD
|
||||
|
40
Cargo.lock
generated
40
Cargo.lock
generated
@ -43,9 +43,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.3"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
|
||||
checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
@ -80,9 +80,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.98"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f"
|
||||
checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@ -92,9 +92,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.4"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
|
||||
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@ -102,9 +102,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.2"
|
||||
version = "4.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@ -114,9 +114,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.4"
|
||||
version = "4.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
|
||||
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@ -126,9 +126,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||
checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
@ -192,9 +192,9 @@ checksum = "809e18805660d7b6b2e2b9f316a5099521b5998d5cba4dda11b5157a21aaef03"
|
||||
|
||||
[[package]]
|
||||
name = "hvm"
|
||||
version = "2.0.17"
|
||||
version = "2.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32cf1c2a5333c940ab1c5b6c64e0f3242739332446b572b07a87f46753c9f69e"
|
||||
checksum = "281675413d2dd76cb1c53ec0d318bb672f5d70fb825929af6bcadd9b7f78c11b"
|
||||
dependencies = [
|
||||
"TSPL",
|
||||
"cc",
|
||||
@ -266,9 +266,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "loaned"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f16fbe026127b8ff026fcc7419ddf201d47807295690de255bb68fced2ba15af"
|
||||
checksum = "a4c980a418236e2d8f7c239f73e49afc38e7f71772fcd3fc723d95c3d93a7591"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
@ -282,9 +282,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.84"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec96c6a92621310b51366f1e28d05ef11489516e93be030060e5fc12024a49d6"
|
||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -366,9 +366,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
|
@ -27,7 +27,7 @@ cli = ["dep:clap"]
|
||||
TSPL = "0.0.12"
|
||||
clap = { version = "4.4.1", features = ["derive"], optional = true }
|
||||
highlight_error = "0.1.1"
|
||||
hvm = "=2.0.17"
|
||||
hvm = "=2.0.19"
|
||||
indexmap = "2.2.3"
|
||||
interner = "0.2.1"
|
||||
itertools = "0.11.0"
|
||||
|
@ -1172,3 +1172,25 @@ The syntax above is desugared to:
|
||||
```
|
||||
(Nat.succ (Nat.succ (Nat.succ List.nil)))
|
||||
```
|
||||
|
||||
# Native HVM definitions
|
||||
|
||||
```py
|
||||
# This function causes two ports to be linked and returns *.
|
||||
# This can be used to interpret a lambda as an application and apply something to it for example.
|
||||
# It can be used like this: `let * = (link_ports @x x y)`
|
||||
hvm link_ports:
|
||||
(a (b *))
|
||||
& (c a) ~ (d e)
|
||||
& (e b) ~ (d c)
|
||||
```
|
||||
|
||||
It's also possible to define functions using HVM syntax. This can be
|
||||
thought of as a way to write "HVM assembly" directly in a Bend program.
|
||||
|
||||
This is meant for writing things that would otherwise be hard or
|
||||
impossible to write in normal Bend syntax.
|
||||
|
||||
It will also ignore all term-level compiler passes and so can be
|
||||
useful for writing programs with exact behaviour that won't ever be
|
||||
changed or optimized by the compiler.
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
diagnostics::Diagnostics,
|
||||
fun::{Ctx, Definitions, Name, Term},
|
||||
fun::{Book, Ctx, Name, Term},
|
||||
maybe_grow,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
@ -11,7 +11,7 @@ impl Ctx<'_> {
|
||||
for def in self.book.defs.values() {
|
||||
let mut unbounds = HashSet::new();
|
||||
for rule in def.rules.iter() {
|
||||
rule.body.check_unbound_refs(&self.book.defs, &mut unbounds);
|
||||
rule.body.check_unbound_refs(self.book, &mut unbounds);
|
||||
}
|
||||
for unbound in unbounds {
|
||||
self.info.add_rule_error(format!("Reference to undefined function '{unbound}'"), def.name.clone());
|
||||
@ -22,15 +22,15 @@ impl Ctx<'_> {
|
||||
}
|
||||
|
||||
impl Term {
|
||||
pub fn check_unbound_refs(&self, defs: &Definitions, unbounds: &mut HashSet<Name>) {
|
||||
pub fn check_unbound_refs(&self, book: &Book, unbounds: &mut HashSet<Name>) {
|
||||
maybe_grow(|| {
|
||||
if let Term::Ref { nam } = self {
|
||||
if !defs.contains_key(nam) {
|
||||
if !(book.defs.contains_key(nam) || book.hvm_defs.contains_key(nam)) {
|
||||
unbounds.insert(nam.clone());
|
||||
}
|
||||
}
|
||||
for child in self.children() {
|
||||
child.check_unbound_refs(defs, unbounds);
|
||||
child.check_unbound_refs(book, unbounds);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -221,7 +221,11 @@ impl fmt::Display for Definition {
|
||||
|
||||
impl fmt::Display for Book {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", DisplayJoin(|| self.defs.values(), "\n\n"))
|
||||
write!(f, "{}", DisplayJoin(|| self.defs.values(), "\n\n"))?;
|
||||
for def in self.hvm_defs.values() {
|
||||
writeln!(f, "hvm {}:\n{}\n", def.name, def.body.show())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,7 +293,14 @@ fn var_as_str(nam: &Option<Name>) -> &str {
|
||||
|
||||
impl Book {
|
||||
pub fn display_pretty(&self) -> impl fmt::Display + '_ {
|
||||
display!("{}", DisplayJoin(|| self.defs.values().map(|def| def.display_pretty()), "\n\n"))
|
||||
display!(
|
||||
"{}\n{}",
|
||||
DisplayJoin(|| self.defs.values().map(|def| def.display_pretty()), "\n\n"),
|
||||
DisplayJoin(
|
||||
|| self.hvm_defs.values().map(|def| display!("hvm {}:\n{}", def.name, def.body.show())),
|
||||
"\n"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,13 +35,16 @@ impl Ctx<'_> {
|
||||
/// The representation of a program.
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct Book {
|
||||
/// The function definitions.
|
||||
/// Function definitions.
|
||||
pub defs: Definitions,
|
||||
|
||||
/// The algebraic datatypes defined by the program
|
||||
/// HVM native function definitions.
|
||||
pub hvm_defs: HvmDefinitions,
|
||||
|
||||
/// Algebraic datatype definitions.
|
||||
pub adts: Adts,
|
||||
|
||||
/// To which type does each constructor belong to.
|
||||
/// Map of constructor name to type name.
|
||||
pub ctrs: Constructors,
|
||||
|
||||
/// A custom or default "main" entrypoint.
|
||||
@ -49,6 +52,7 @@ pub struct Book {
|
||||
}
|
||||
|
||||
pub type Definitions = IndexMap<Name, Definition>;
|
||||
pub type HvmDefinitions = IndexMap<Name, HvmDefinition>;
|
||||
pub type Adts = IndexMap<Name, Adt>;
|
||||
pub type Constructors = IndexMap<Name, Name>;
|
||||
|
||||
@ -60,6 +64,14 @@ pub struct Definition {
|
||||
pub builtin: bool,
|
||||
}
|
||||
|
||||
/// An HVM native definition.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HvmDefinition {
|
||||
pub name: Name,
|
||||
pub body: hvm::ast::Net,
|
||||
pub builtin: bool,
|
||||
}
|
||||
|
||||
/// A pattern matching rule of a definition.
|
||||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub struct Rule {
|
||||
|
@ -1,9 +1,11 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use crate::{
|
||||
fun::{
|
||||
display::DisplayFn, Adt, Book, CtrField, Definition, FanKind, MatchRule, Name, Num, Op, Pattern, Rule,
|
||||
Tag, Term, STRINGS,
|
||||
display::DisplayFn, Adt, Book, CtrField, Definition, FanKind, HvmDefinition, MatchRule, Name, Num, Op,
|
||||
Pattern, Rule, Tag, Term, STRINGS,
|
||||
},
|
||||
imp::parser::PyParser,
|
||||
imp::{parser::PyParser, Enum, Variant},
|
||||
maybe_grow,
|
||||
};
|
||||
use highlight_error::highlight_error;
|
||||
@ -76,7 +78,7 @@ impl<'a> TermParser<'a> {
|
||||
let (obj, nxt_indent) = prs.parse_object(indent)?;
|
||||
self.index = prs.index;
|
||||
let end_idx = *self.index();
|
||||
prs.add_object(obj, &mut book, ini_idx, end_idx, builtin)?;
|
||||
self.add_object(obj, &mut book, ini_idx..end_idx, builtin)?;
|
||||
indent = nxt_indent;
|
||||
last_rule = None;
|
||||
continue;
|
||||
@ -88,7 +90,7 @@ impl<'a> TermParser<'a> {
|
||||
let (def, nxt_indent) = prs.parse_def(indent)?;
|
||||
self.index = prs.index;
|
||||
let end_idx = *self.index();
|
||||
prs.add_def(def, &mut book, ini_idx, end_idx, builtin)?;
|
||||
self.add_imp_def(def, &mut book, ini_idx..end_idx, builtin)?;
|
||||
indent = nxt_indent;
|
||||
last_rule = None;
|
||||
continue;
|
||||
@ -101,50 +103,40 @@ impl<'a> TermParser<'a> {
|
||||
|
||||
let _ = self.labelled(|p| p.parse_top_level_name(), "datatype name")?;
|
||||
|
||||
// Imp type definition
|
||||
if self.starts_with(":") {
|
||||
let mut prs = PyParser { input: self.input, index: rewind_index };
|
||||
let (r#enum, nxt_indent) = prs.parse_type(indent)?;
|
||||
self.index = prs.index;
|
||||
let end_idx = *self.index();
|
||||
prs.add_type(r#enum, &mut book, ini_idx, end_idx, builtin)?;
|
||||
self.add_type(r#enum, &mut book, ini_idx..end_idx, builtin)?;
|
||||
indent = nxt_indent;
|
||||
last_rule = None;
|
||||
continue;
|
||||
// Fun type definition
|
||||
} else {
|
||||
self.index = rewind_index;
|
||||
let (nam, adt) = self.parse_datatype(builtin)?;
|
||||
let end_idx = *self.index();
|
||||
self.with_ctx(book.add_adt(nam, adt), ini_idx, end_idx)?;
|
||||
self.with_ctx(book.add_adt(nam, adt), ini_idx..end_idx)?;
|
||||
indent = self.advance_newlines()?;
|
||||
last_rule = None;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// HVM native function definition
|
||||
if self.try_parse_keyword("hvm") {
|
||||
let def = self.parse_hvm(builtin)?;
|
||||
let end_idx = *self.index();
|
||||
self.add_hvm(def, &mut book, ini_idx..end_idx)?;
|
||||
}
|
||||
|
||||
// Fun function definition
|
||||
let ini_idx = *self.index();
|
||||
let (name, rule) = self.parse_rule()?;
|
||||
let end_idx = *self.index();
|
||||
// Add to book
|
||||
if let Some(def) = book.defs.get_mut(&name) {
|
||||
if let Some(last_rule) = last_rule {
|
||||
if last_rule == name {
|
||||
// Continuing with a new rule to the current definition
|
||||
def.rules.push(rule);
|
||||
} else {
|
||||
// Trying to add a new rule to a previous definition, coming from a different rule.
|
||||
let msg = Self::redefinition_of_function_msg(builtin, &name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
} else {
|
||||
// Trying to add a new rule to a previous definition, coming from another kind of top-level.
|
||||
let msg = Self::redefinition_of_function_msg(builtin, &name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
} else {
|
||||
// Adding the first rule of a new definition
|
||||
book.defs.insert(name.clone(), Definition { name: name.clone(), rules: vec![rule], builtin });
|
||||
}
|
||||
self.add_fun_def(&name, rule, builtin, &last_rule, &mut book, ini_idx..end_idx)?;
|
||||
indent = self.advance_newlines()?;
|
||||
last_rule = Some(name);
|
||||
}
|
||||
@ -191,6 +183,21 @@ impl<'a> TermParser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_hvm(&mut self, builtin: bool) -> ParseResult<HvmDefinition> {
|
||||
self.skip_trivia_inline()?;
|
||||
let name = self.parse_bend_name()?;
|
||||
self.skip_trivia_inline()?;
|
||||
self.consume_exactly(":")?;
|
||||
self.consume_new_line()?;
|
||||
// TODO: This will have the wrong index
|
||||
let ini_idx = *self.index();
|
||||
let mut p = hvm::ast::CoreParser::new(&self.input[*self.index()..]);
|
||||
let body = p.parse_net()?;
|
||||
*self.index() = ini_idx + *p.index();
|
||||
let def = HvmDefinition { name: name.clone(), body, builtin };
|
||||
Ok(def)
|
||||
}
|
||||
|
||||
fn parse_rule(&mut self) -> ParseResult<(Name, Rule)> {
|
||||
// (name pat*) = term
|
||||
// name pat* = term
|
||||
@ -240,7 +247,7 @@ impl<'a> TermParser<'a> {
|
||||
// Ctr
|
||||
unexpected_tag(self)?;
|
||||
let Pattern::Var(Some(name)) = head else {
|
||||
return self.expected_spanned("constructor name", head_ini_idx, head_end_idx);
|
||||
return self.expected_spanned("constructor name", head_ini_idx..head_end_idx);
|
||||
};
|
||||
let els = self.list_like(|p| p.parse_pattern(simple), "", ")", "", false, 0)?;
|
||||
return Ok(Pattern::Ctr(name, els));
|
||||
@ -645,7 +652,7 @@ impl<'a> TermParser<'a> {
|
||||
&& !self.peek_many(2).is_some_and(|x| x.chars().nth(1).unwrap().is_ascii_digit())
|
||||
{
|
||||
let msg = "Tagged terms not supported for hvm32.".to_string();
|
||||
return self.with_ctx(Err(msg), index, index + 1);
|
||||
return self.with_ctx(Err(msg), index..index + 1);
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -654,7 +661,7 @@ impl<'a> TermParser<'a> {
|
||||
Ok((tag, move |slf: &mut Self| {
|
||||
if has_tag {
|
||||
let msg = "\x1b[1m- unexpected tag:\x1b[0m".to_string();
|
||||
slf.with_ctx(Err(msg), index, end_index)
|
||||
slf.with_ctx(Err(msg), index..end_index)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@ -674,7 +681,7 @@ impl<'a> TermParser<'a> {
|
||||
Ok((Some(std::mem::take(nam)), self.parse_term()?))
|
||||
}
|
||||
(Term::Var { nam }, false) => Ok((Some(nam.clone()), Term::Var { nam: std::mem::take(nam) })),
|
||||
(_, true) => self.expected_spanned("argument name", ini_idx, end_idx),
|
||||
(_, true) => self.expected_spanned("argument name", ini_idx..end_idx),
|
||||
(arg, false) => Ok((Some(Name::new("%arg")), std::mem::take(arg))),
|
||||
}
|
||||
}
|
||||
@ -712,6 +719,117 @@ impl<'a> TermParser<'a> {
|
||||
let bod = self.parse_term()?;
|
||||
Ok((nam, vec![], bod))
|
||||
}
|
||||
|
||||
fn add_fun_def(
|
||||
&mut self,
|
||||
name: &Name,
|
||||
rule: Rule,
|
||||
builtin: bool,
|
||||
last_rule: &Option<Name>,
|
||||
book: &mut Book,
|
||||
span: Range<usize>,
|
||||
) -> ParseResult<()> {
|
||||
match (book.defs.get_mut(name), last_rule) {
|
||||
// Continuing with a new rule to the current definition
|
||||
(Some(def), Some(last_rule)) if last_rule == name => {
|
||||
def.rules.push(rule);
|
||||
}
|
||||
// Trying to add a new rule to a previous definition, coming from a different rule.
|
||||
(Some(def), Some(_)) => {
|
||||
let msg = Self::redefinition_of_function_msg(def.builtin, name);
|
||||
return self.with_ctx(Err(msg), span);
|
||||
}
|
||||
// Trying to add a new rule to a previous definition, coming from another kind of top-level.
|
||||
(Some(def), None) => {
|
||||
let msg = Self::redefinition_of_function_msg(def.builtin, name);
|
||||
return self.with_ctx(Err(msg), span);
|
||||
}
|
||||
// Adding the first rule of a new definition
|
||||
(None, _) => {
|
||||
self.check_top_level_redefinition(name, book, span)?;
|
||||
book.defs.insert(name.clone(), Definition { name: name.clone(), rules: vec![rule], builtin });
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_imp_def(
|
||||
&mut self,
|
||||
mut def: crate::imp::Definition,
|
||||
book: &mut Book,
|
||||
span: Range<usize>,
|
||||
builtin: bool,
|
||||
) -> ParseResult<()> {
|
||||
self.check_top_level_redefinition(&def.name, book, span)?;
|
||||
def.order_kwargs(book)?;
|
||||
def.gen_map_get();
|
||||
let def = def.to_fun(builtin)?;
|
||||
book.defs.insert(def.name.clone(), def);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_hvm(&mut self, def: HvmDefinition, book: &mut Book, span: Range<usize>) -> ParseResult<()> {
|
||||
self.check_top_level_redefinition(&def.name, book, span)?;
|
||||
book.hvm_defs.insert(def.name.clone(), def);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_type(&mut self, enum_: Enum, book: &mut Book, span: Range<usize>, builtin: bool) -> ParseResult<()> {
|
||||
self.check_type_redefinition(&enum_.name, book, span.clone())?;
|
||||
let mut adt = Adt { ctrs: Default::default(), builtin };
|
||||
for variant in enum_.variants {
|
||||
self.check_top_level_redefinition(&enum_.name, book, span.clone())?;
|
||||
book.ctrs.insert(variant.name.clone(), enum_.name.clone());
|
||||
adt.ctrs.insert(variant.name, variant.fields);
|
||||
}
|
||||
book.adts.insert(enum_.name.clone(), adt);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_object(
|
||||
&mut self,
|
||||
obj: Variant,
|
||||
book: &mut Book,
|
||||
span: Range<usize>,
|
||||
builtin: bool,
|
||||
) -> ParseResult<()> {
|
||||
self.check_type_redefinition(&obj.name, book, span.clone())?;
|
||||
self.check_top_level_redefinition(&obj.name, book, span)?;
|
||||
let mut adt = Adt { ctrs: Default::default(), builtin };
|
||||
book.ctrs.insert(obj.name.clone(), obj.name.clone());
|
||||
adt.ctrs.insert(obj.name.clone(), obj.fields);
|
||||
book.adts.insert(obj.name, adt);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_top_level_redefinition(
|
||||
&mut self,
|
||||
name: &Name,
|
||||
book: &mut Book,
|
||||
span: Range<usize>,
|
||||
) -> ParseResult<()> {
|
||||
if let Some(def) = book.defs.get(name) {
|
||||
let msg = Self::redefinition_of_function_msg(def.builtin, name);
|
||||
return self.with_ctx(Err(msg), span);
|
||||
}
|
||||
if book.ctrs.contains_key(name) {
|
||||
let msg = Self::redefinition_of_constructor_msg(name);
|
||||
return self.with_ctx(Err(msg), span);
|
||||
}
|
||||
if book.hvm_defs.contains_key(name) {
|
||||
let msg = Self::redefinition_of_hvm_msg(false, name);
|
||||
return self.with_ctx(Err(msg), span);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_type_redefinition(&mut self, name: &Name, book: &mut Book, span: Range<usize>) -> ParseResult<()> {
|
||||
if book.adts.contains_key(name) {
|
||||
let msg = Self::redefinition_of_type_msg(name);
|
||||
return self.with_ctx(Err(msg), span);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> for TermParser<'a> {
|
||||
@ -729,7 +847,7 @@ impl<'a> Parser<'a> for TermParser<'a> {
|
||||
fn expected<T>(&mut self, exp: &str) -> ParseResult<T> {
|
||||
let ini_idx = *self.index();
|
||||
let end_idx = *self.index() + 1;
|
||||
self.expected_spanned(exp, ini_idx, end_idx)
|
||||
self.expected_spanned(exp, ini_idx..end_idx)
|
||||
}
|
||||
|
||||
/// Consumes an instance of the given string, erroring if it is not found.
|
||||
@ -836,10 +954,10 @@ pub trait ParserCommons<'a>: Parser<'a> {
|
||||
let end_idx = *self.index();
|
||||
if name.contains("__") {
|
||||
let msg = format!("{kind} names are not allowed to contain \"__\".");
|
||||
self.with_ctx(Err(msg), ini_idx, end_idx)
|
||||
self.with_ctx(Err(msg), ini_idx..end_idx)
|
||||
} else if name.starts_with("//") {
|
||||
let msg = format!("{kind} names are not allowed to start with \"//\".");
|
||||
self.with_ctx(Err(msg), ini_idx, end_idx)
|
||||
self.with_ctx(Err(msg), ini_idx..end_idx)
|
||||
} else {
|
||||
Ok(name)
|
||||
}
|
||||
@ -893,7 +1011,7 @@ pub trait ParserCommons<'a>: Parser<'a> {
|
||||
while let Some(c) = self.peek_one() {
|
||||
if c == '\t' {
|
||||
let idx = *self.index();
|
||||
return self.with_ctx(Err("Tabs are not accepted for indentation.".to_string()), idx, idx);
|
||||
return self.with_ctx(Err("Tabs are not accepted for indentation.".to_string()), idx..idx);
|
||||
}
|
||||
if " ".contains(c) {
|
||||
self.advance_one();
|
||||
@ -922,21 +1040,16 @@ pub trait ParserCommons<'a>: Parser<'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn expected_spanned<T>(&mut self, exp: &str, ini_idx: usize, end_idx: usize) -> ParseResult<T> {
|
||||
fn expected_spanned<T>(&mut self, exp: &str, span: Range<usize>) -> ParseResult<T> {
|
||||
let is_eof = self.is_eof();
|
||||
let detected = DisplayFn(|f| if is_eof { write!(f, " end of input") } else { Ok(()) });
|
||||
let msg = format!("\x1b[1m- expected:\x1b[0m {}\n\x1b[1m- detected:\x1b[0m{}", exp, detected);
|
||||
self.with_ctx(Err(msg), ini_idx, end_idx)
|
||||
self.with_ctx(Err(msg), span)
|
||||
}
|
||||
|
||||
fn with_ctx<T>(
|
||||
&mut self,
|
||||
res: Result<T, impl std::fmt::Display>,
|
||||
ini_idx: usize,
|
||||
end_idx: usize,
|
||||
) -> ParseResult<T> {
|
||||
fn with_ctx<T>(&mut self, res: Result<T, impl std::fmt::Display>, span: Range<usize>) -> ParseResult<T> {
|
||||
res.map_err(|msg| {
|
||||
let ctx = highlight_error(ini_idx, end_idx, self.input());
|
||||
let ctx = highlight_error(span.start, span.end, self.input());
|
||||
format!("{msg}\n{ctx}")
|
||||
})
|
||||
}
|
||||
@ -985,7 +1098,7 @@ pub trait ParserCommons<'a>: Parser<'a> {
|
||||
if !next_is_name {
|
||||
Ok(())
|
||||
} else {
|
||||
self.expected_spanned(&format!("keyword '{keyword}'"), ini_idx, end_idx + 1)
|
||||
self.expected_spanned(&format!("keyword '{keyword}'"), ini_idx..end_idx + 1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,7 +1313,7 @@ pub trait ParserCommons<'a>: Parser<'a> {
|
||||
fn num_range_err<T>(&mut self, ini_idx: usize, typ: &str) -> ParseResult<T> {
|
||||
let msg = format!("\x1b[1mNumber literal outside of range for {}.\x1b[0m", typ);
|
||||
let end_idx = *self.index();
|
||||
self.with_ctx(Err(msg), ini_idx, end_idx)
|
||||
self.with_ctx(Err(msg), ini_idx..end_idx)
|
||||
}
|
||||
|
||||
/// Parses up to 4 base64 characters surrounded by "`".
|
||||
@ -1238,6 +1351,14 @@ pub trait ParserCommons<'a>: Parser<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn redefinition_of_hvm_msg(builtin: bool, function_name: &str) -> String {
|
||||
if builtin {
|
||||
format!("Redefinition of builtin (native HVM function) '{function_name}'.")
|
||||
} else {
|
||||
format!("Redefinition of native HVM function '{function_name}'.")
|
||||
}
|
||||
}
|
||||
|
||||
fn redefinition_of_constructor_msg(constructor_name: &str) -> String {
|
||||
if crate::fun::builtins::BUILTIN_CTRS.contains(&constructor_name) {
|
||||
format!("Redefinition of builtin (constructor) '{constructor_name}'.")
|
||||
|
@ -38,6 +38,11 @@ pub fn book_to_hvm(book: &Book, diags: &mut Diagnostics) -> Result<(hvm::ast::Bo
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: native hvm nets ignore labels
|
||||
for def in book.hvm_defs.values() {
|
||||
hvm_book.defs.insert(def.name.to_string(), def.body.clone());
|
||||
}
|
||||
|
||||
labels.con.finish();
|
||||
labels.dup.finish();
|
||||
|
||||
|
@ -3,6 +3,7 @@ use crate::{
|
||||
fun::{Book, Ctx, Name, Term},
|
||||
maybe_grow,
|
||||
};
|
||||
use hvm::ast::{Net, Tree};
|
||||
use std::collections::{hash_map::Entry, HashMap};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
@ -27,7 +28,7 @@ impl Ctx<'_> {
|
||||
if let Some(main) = &self.book.entrypoint {
|
||||
let def = self.book.defs.get(main).unwrap();
|
||||
used.insert(main.clone(), Used::Main);
|
||||
self.book.find_used_definitions(&def.rule().body, Used::Main, &mut used);
|
||||
self.book.find_used_definitions_from_term(&def.rule().body, Used::Main, &mut used);
|
||||
}
|
||||
|
||||
// Get the functions that are accessible from non-builtins.
|
||||
@ -38,7 +39,13 @@ impl Ctx<'_> {
|
||||
} else {
|
||||
used.insert(def.name.clone(), Used::NonBuiltin);
|
||||
}
|
||||
self.book.find_used_definitions(&def.rule().body, Used::NonBuiltin, &mut used);
|
||||
self.book.find_used_definitions_from_term(&def.rule().body, Used::NonBuiltin, &mut used);
|
||||
}
|
||||
}
|
||||
for def in self.book.hvm_defs.values() {
|
||||
if !def.builtin && !(used.get(&def.name) == Some(&Used::Main)) {
|
||||
used.insert(def.name.clone(), Used::NonBuiltin);
|
||||
self.book.find_used_definitions_from_hvm_net(&def.body, Used::NonBuiltin, &mut used);
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,8 +84,8 @@ impl Ctx<'_> {
|
||||
}
|
||||
|
||||
impl Book {
|
||||
/// Finds all used definitions on every term that can have a def_id.
|
||||
fn find_used_definitions(&self, term: &Term, used: Used, uses: &mut Definitions) {
|
||||
/// Finds all used definitions on the book, starting from the given term.
|
||||
fn find_used_definitions_from_term(&self, term: &Term, used: Used, uses: &mut Definitions) {
|
||||
maybe_grow(|| {
|
||||
let mut to_find = vec![term];
|
||||
|
||||
@ -103,14 +110,44 @@ impl Book {
|
||||
})
|
||||
}
|
||||
|
||||
fn find_used_definitions_from_hvm_net(&self, net: &Net, used: Used, uses: &mut Definitions) {
|
||||
maybe_grow(|| {
|
||||
let mut to_find = [&net.root]
|
||||
.into_iter()
|
||||
.chain(net.rbag.iter().flat_map(|(_, lft, rgt)| [lft, rgt]))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
while let Some(term) = to_find.pop() {
|
||||
match term {
|
||||
Tree::Ref { nam } => self.insert_used(&Name::new(nam), used, uses),
|
||||
Tree::Con { fst, snd }
|
||||
| Tree::Dup { fst, snd }
|
||||
| Tree::Opr { fst, snd }
|
||||
| Tree::Swi { fst, snd } => {
|
||||
to_find.push(fst);
|
||||
to_find.push(snd);
|
||||
}
|
||||
Tree::Era | Tree::Var { .. } | Tree::Num { .. } => {}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn insert_used(&self, def_name: &Name, used: Used, uses: &mut Definitions) {
|
||||
if let Entry::Vacant(e) = uses.entry(def_name.clone()) {
|
||||
e.insert(used);
|
||||
|
||||
// This needs to be done for each rule in case the pass it's ran from has not encoded the pattern match
|
||||
// This needs to be done for each rule in case the pass it's
|
||||
// ran from has not encoded the pattern match.
|
||||
// E.g.: the `flatten_rules` golden test
|
||||
for rule in &self.defs[def_name].rules {
|
||||
self.find_used_definitions(&rule.body, used, uses);
|
||||
if let Some(def) = self.defs.get(def_name) {
|
||||
for rule in &def.rules {
|
||||
self.find_used_definitions_from_term(&rule.body, used, uses);
|
||||
}
|
||||
} else if let Some(def) = self.hvm_defs.get(def_name) {
|
||||
self.find_used_definitions_from_hvm_net(&def.body, used, uses);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,8 @@ impl Ctx<'_> {
|
||||
pub fn resolve_refs(&mut self) -> Result<(), Diagnostics> {
|
||||
self.info.start_pass();
|
||||
|
||||
let def_names = self.book.defs.keys().cloned().collect::<HashSet<_>>();
|
||||
let def_names =
|
||||
self.book.defs.keys().cloned().chain(self.book.hvm_defs.keys().cloned()).collect::<HashSet<_>>();
|
||||
for (def_name, def) in &mut self.book.defs {
|
||||
for rule in def.rules.iter_mut() {
|
||||
let mut scope = HashMap::new();
|
||||
|
129
src/hvm/mod.rs
129
src/hvm/mod.rs
@ -1,4 +1,4 @@
|
||||
use crate::{fun::display::DisplayFn, multi_iterator};
|
||||
use crate::multi_iterator;
|
||||
use hvm::ast::{Net, Tree};
|
||||
|
||||
pub mod add_recursive_priority;
|
||||
@ -36,122 +36,23 @@ pub fn net_trees_mut(net: &mut Net) -> impl DoubleEndedIterator<Item = &mut Tree
|
||||
[&mut net.root].into_iter().chain(net.rbag.iter_mut().flat_map(|(_, fst, snd)| [fst, snd]))
|
||||
}
|
||||
|
||||
pub fn display_hvm_book(book: &hvm::ast::Book) -> impl std::fmt::Display + '_ {
|
||||
DisplayFn(|f| {
|
||||
for (nam, def) in book.defs.iter() {
|
||||
writeln!(f, "@{} = {}", nam, display_hvm_tree(&def.root))?;
|
||||
for (pri, a, b) in def.rbag.iter() {
|
||||
writeln!(f, " &{}{} ~ {}", if *pri { "!" } else { " " }, display_hvm_tree(a), display_hvm_tree(b))?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: We have to reimplement these because hvm prints partially applied numbers incorrectly.
|
||||
// https://github.com/HigherOrderCO/HVM/issues/350
|
||||
pub fn display_hvm_numb(numb: &hvm::ast::Numb) -> impl std::fmt::Display + '_ {
|
||||
let numb = hvm::hvm::Numb(numb.0);
|
||||
match numb.get_typ() {
|
||||
hvm::hvm::TY_SYM => match numb.get_sym() as hvm::hvm::Tag {
|
||||
hvm::hvm::OP_ADD => "[+]".to_string(),
|
||||
hvm::hvm::OP_SUB => "[-]".to_string(),
|
||||
hvm::hvm::FP_SUB => "[:-]".to_string(),
|
||||
hvm::hvm::OP_MUL => "[*]".to_string(),
|
||||
hvm::hvm::OP_DIV => "[/]".to_string(),
|
||||
hvm::hvm::FP_DIV => "[:/]".to_string(),
|
||||
hvm::hvm::OP_REM => "[%]".to_string(),
|
||||
hvm::hvm::FP_REM => "[:%]".to_string(),
|
||||
hvm::hvm::OP_EQ => "[=]".to_string(),
|
||||
hvm::hvm::OP_NEQ => "[!]".to_string(),
|
||||
hvm::hvm::OP_LT => "[<]".to_string(),
|
||||
hvm::hvm::OP_GT => "[>]".to_string(),
|
||||
hvm::hvm::OP_AND => "[&]".to_string(),
|
||||
hvm::hvm::OP_OR => "[|]".to_string(),
|
||||
hvm::hvm::OP_XOR => "[^]".to_string(),
|
||||
hvm::hvm::OP_SHL => "[<<]".to_string(),
|
||||
hvm::hvm::FP_SHL => "[:<<]".to_string(),
|
||||
hvm::hvm::OP_SHR => "[>>]".to_string(),
|
||||
hvm::hvm::FP_SHR => "[:>>]".to_string(),
|
||||
_ => "[?]".to_string(),
|
||||
},
|
||||
hvm::hvm::TY_U24 => {
|
||||
let val = numb.get_u24();
|
||||
format!("{}", val)
|
||||
}
|
||||
hvm::hvm::TY_I24 => {
|
||||
let val = numb.get_i24();
|
||||
format!("{:+}", val)
|
||||
}
|
||||
hvm::hvm::TY_F24 => {
|
||||
let val = numb.get_f24();
|
||||
if val.is_infinite() {
|
||||
if val.is_sign_positive() {
|
||||
"+inf".to_string()
|
||||
} else {
|
||||
"-inf".to_string()
|
||||
}
|
||||
} else if val.is_nan() {
|
||||
"+NaN".to_string()
|
||||
pub fn hvm_book_show_pretty(book: &hvm::ast::Book) -> String {
|
||||
let mut s = String::new();
|
||||
for (nam, def) in book.defs.iter() {
|
||||
s.push_str(&format!("@{} = {}\n", nam, def.root.show()));
|
||||
for (pri, a, b) in def.rbag.iter() {
|
||||
s.push_str(" &");
|
||||
if *pri {
|
||||
s.push('!');
|
||||
} else {
|
||||
format!("{:?}", val)
|
||||
s.push(' ');
|
||||
}
|
||||
s.push_str(&a.show());
|
||||
s.push_str(" ~ ");
|
||||
s.push_str(&b.show());
|
||||
s.push('\n');
|
||||
}
|
||||
_ => {
|
||||
let typ = numb.get_typ();
|
||||
let val = numb.get_u24();
|
||||
format!(
|
||||
"[{}{}]",
|
||||
match typ {
|
||||
hvm::hvm::OP_ADD => "+",
|
||||
hvm::hvm::OP_SUB => "-",
|
||||
hvm::hvm::FP_SUB => ":-",
|
||||
hvm::hvm::OP_MUL => "*",
|
||||
hvm::hvm::OP_DIV => "/",
|
||||
hvm::hvm::FP_DIV => ":/",
|
||||
hvm::hvm::OP_REM => "%",
|
||||
hvm::hvm::FP_REM => ":%",
|
||||
hvm::hvm::OP_EQ => "=",
|
||||
hvm::hvm::OP_NEQ => "!",
|
||||
hvm::hvm::OP_LT => "<",
|
||||
hvm::hvm::OP_GT => ">",
|
||||
hvm::hvm::OP_AND => "&",
|
||||
hvm::hvm::OP_OR => "|",
|
||||
hvm::hvm::OP_XOR => "^",
|
||||
hvm::hvm::OP_SHL => "<<",
|
||||
hvm::hvm::FP_SHL => ":<<",
|
||||
hvm::hvm::OP_SHR => ">>",
|
||||
hvm::hvm::FP_SHR => ":>>",
|
||||
_ => "?",
|
||||
},
|
||||
val
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_hvm_tree(tree: &hvm::ast::Tree) -> impl std::fmt::Display + '_ {
|
||||
match tree {
|
||||
Tree::Var { nam } => nam.to_string(),
|
||||
Tree::Ref { nam } => format!("@{}", nam),
|
||||
Tree::Era => "*".to_string(),
|
||||
Tree::Num { val } => format!("{}", display_hvm_numb(val)),
|
||||
Tree::Con { fst, snd } => format!("({} {})", display_hvm_tree(fst), display_hvm_tree(snd)),
|
||||
Tree::Dup { fst, snd } => format!("{{{} {}}}", display_hvm_tree(fst), display_hvm_tree(snd)),
|
||||
Tree::Opr { fst, snd } => format!("$({} {})", display_hvm_tree(fst), display_hvm_tree(snd)),
|
||||
Tree::Swi { fst, snd } => format!("?({} {})", display_hvm_tree(fst), display_hvm_tree(snd)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display_hvm_net(net: &hvm::ast::Net) -> impl std::fmt::Display + '_ {
|
||||
let mut s = display_hvm_tree(&net.root).to_string();
|
||||
for (par, fst, snd) in &net.rbag {
|
||||
s.push_str(" & ");
|
||||
s.push_str(if *par { "!" } else { "" });
|
||||
s.push_str(&display_hvm_tree(fst).to_string());
|
||||
s.push_str(" ~ ");
|
||||
s.push_str(&display_hvm_tree(snd).to_string());
|
||||
s.push('\n');
|
||||
}
|
||||
s
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
fun::{
|
||||
parser::{is_num_char, Indent, ParseResult, ParserCommons},
|
||||
Adt, Book, CtrField, Name, Num, Op, STRINGS,
|
||||
CtrField, Name, Num, Op, STRINGS,
|
||||
},
|
||||
imp::{AssignPattern, Definition, Enum, Expr, InPlaceOp, MatchArm, Stmt, Variant},
|
||||
maybe_grow,
|
||||
@ -36,7 +36,7 @@ impl<'a> Parser<'a> for PyParser<'a> {
|
||||
fn expected<T>(&mut self, exp: &str) -> ParseResult<T> {
|
||||
let ini_idx = *self.index();
|
||||
let end_idx = *self.index() + 1;
|
||||
self.expected_spanned(exp, ini_idx, end_idx)
|
||||
self.expected_spanned(exp, ini_idx..end_idx)
|
||||
}
|
||||
|
||||
/// Consumes an instance of the given string, erroring if it is not found.
|
||||
@ -152,7 +152,7 @@ impl<'a> PyParser<'a> {
|
||||
kwargs.push((bnd, arg));
|
||||
} else if must_be_named {
|
||||
let msg = "Positional arguments are not allowed to go after named arguments.".to_string();
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
return self.with_ctx(Err(msg), ini_idx..end_idx);
|
||||
} else {
|
||||
args.push(arg);
|
||||
}
|
||||
@ -176,7 +176,7 @@ impl<'a> PyParser<'a> {
|
||||
return Ok(Expr::MapGet { nam, key: Box::new(key) });
|
||||
} else {
|
||||
let end_idx = *self.index();
|
||||
return self.expected_spanned("Map variable name", ini_idx, end_idx);
|
||||
return self.expected_spanned("Map variable name", ini_idx..end_idx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,7 +187,7 @@ impl<'a> PyParser<'a> {
|
||||
return Ok(Expr::Ctr { name: nam, args: Vec::new(), kwargs });
|
||||
} else {
|
||||
let end_idx = *self.index();
|
||||
return self.expected_spanned("Constructor name", ini_idx, end_idx);
|
||||
return self.expected_spanned("Constructor name", ini_idx..end_idx);
|
||||
}
|
||||
}
|
||||
|
||||
@ -361,7 +361,7 @@ impl<'a> PyParser<'a> {
|
||||
} else {
|
||||
let msg = "Unexpected '=' in unnamed argument.".to_string();
|
||||
let idx = *self.index();
|
||||
self.with_ctx(Err(msg), idx, idx + 1)
|
||||
self.with_ctx(Err(msg), idx..idx + 1)
|
||||
}
|
||||
} else {
|
||||
Ok((None, arg))
|
||||
@ -490,7 +490,7 @@ impl<'a> PyParser<'a> {
|
||||
match &pat {
|
||||
AssignPattern::Var(..) => {}
|
||||
AssignPattern::MapSet(..) => {}
|
||||
_ => self.expected_spanned("Var or Map accessor", ini_idx, end_idx)?,
|
||||
_ => self.expected_spanned("Var or Map accessor", ini_idx..end_idx)?,
|
||||
}
|
||||
if let Some(op) = self.parse_in_place_op()? {
|
||||
let val = self.parse_expr(true)?;
|
||||
@ -502,7 +502,7 @@ impl<'a> PyParser<'a> {
|
||||
return Ok((stmt, nxt_indent));
|
||||
}
|
||||
|
||||
self.expected_spanned("statement", ini_idx, end_idx)
|
||||
self.expected_spanned("statement", ini_idx..end_idx)
|
||||
}
|
||||
|
||||
fn parse_in_place_op(&mut self) -> ParseResult<Option<InPlaceOp>> {
|
||||
@ -644,7 +644,7 @@ impl<'a> PyParser<'a> {
|
||||
self.advance_one();
|
||||
Ok((Some(nam), self.parse_expr(true)?))
|
||||
}
|
||||
(_, true) => self.expected_spanned("argument name", ini_idx, end_idx),
|
||||
(_, true) => self.expected_spanned("argument name", ini_idx..end_idx),
|
||||
(Expr::Var { nam }, false) => Ok((Some(nam.clone()), Expr::Var { nam })),
|
||||
(arg, false) => Ok((Some(Name::new("%arg")), arg)),
|
||||
}
|
||||
@ -705,7 +705,7 @@ impl<'a> PyParser<'a> {
|
||||
let (fst_case, fst_stmt, mut nxt_indent) = self.parse_switch_case(indent)?;
|
||||
let end_idx = *self.index();
|
||||
if fst_case != Some(0) {
|
||||
return self.expected_spanned("case 0", ini_idx, end_idx);
|
||||
return self.expected_spanned("case 0", ini_idx..end_idx);
|
||||
}
|
||||
let mut arms = vec![fst_stmt];
|
||||
let mut should_continue = fst_case == Some(0);
|
||||
@ -967,7 +967,7 @@ impl<'a> PyParser<'a> {
|
||||
if indent != Indent::Val(0) {
|
||||
let msg = "Indentation error. Functions defined with 'def' must be at the start of the line.";
|
||||
let idx = *self.index();
|
||||
return self.with_ctx(Err(msg), idx, idx + 1);
|
||||
return self.with_ctx(Err(msg), idx..idx + 1);
|
||||
}
|
||||
|
||||
self.skip_trivia_inline()?;
|
||||
@ -995,7 +995,7 @@ impl<'a> PyParser<'a> {
|
||||
if indent != Indent::Val(0) {
|
||||
let msg = "Indentation error. Types defined with 'type' must be at the start of the line.";
|
||||
let idx = *self.index();
|
||||
return self.with_ctx(Err(msg), idx, idx + 1);
|
||||
return self.with_ctx(Err(msg), idx..idx + 1);
|
||||
}
|
||||
|
||||
self.skip_trivia_inline()?;
|
||||
@ -1036,7 +1036,7 @@ impl<'a> PyParser<'a> {
|
||||
if indent != Indent::Val(0) {
|
||||
let msg = "Indentation error. Types defined with 'object' must be at the start of the line.";
|
||||
let idx = *self.index();
|
||||
return self.with_ctx(Err(msg), idx, idx + 1);
|
||||
return self.with_ctx(Err(msg), idx..idx + 1);
|
||||
}
|
||||
|
||||
self.skip_trivia_inline()?;
|
||||
@ -1061,103 +1061,24 @@ impl<'a> PyParser<'a> {
|
||||
Ok(CtrField { nam, rec })
|
||||
}
|
||||
|
||||
pub fn add_def(
|
||||
&mut self,
|
||||
mut def: Definition,
|
||||
book: &mut Book,
|
||||
ini_idx: usize,
|
||||
end_idx: usize,
|
||||
builtin: bool,
|
||||
) -> ParseResult<()> {
|
||||
if let Some(def) = book.defs.get(&def.name) {
|
||||
let msg = Self::redefinition_of_function_msg(def.builtin, &def.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
if book.ctrs.contains_key(&def.name) {
|
||||
let msg = Self::redefinition_of_constructor_msg(&def.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
def.order_kwargs(book)?;
|
||||
def.gen_map_get();
|
||||
let def = def.to_fun(builtin)?;
|
||||
book.defs.insert(def.name.clone(), def);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_type(
|
||||
&mut self,
|
||||
r#enum: Enum,
|
||||
book: &mut Book,
|
||||
ini_idx: usize,
|
||||
end_idx: usize,
|
||||
builtin: bool,
|
||||
) -> ParseResult<()> {
|
||||
if book.adts.contains_key(&r#enum.name) {
|
||||
let msg = PyParser::redefinition_of_type_msg(&r#enum.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
let mut adt = Adt { ctrs: Default::default(), builtin };
|
||||
for variant in r#enum.variants {
|
||||
if let Some(def) = book.defs.get(&variant.name) {
|
||||
let msg = PyParser::redefinition_of_function_msg(def.builtin, &variant.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
if book.ctrs.contains_key(&variant.name) {
|
||||
let msg = PyParser::redefinition_of_constructor_msg(&variant.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
book.ctrs.insert(variant.name.clone(), r#enum.name.clone());
|
||||
adt.ctrs.insert(variant.name, variant.fields);
|
||||
}
|
||||
book.adts.insert(r#enum.name.clone(), adt);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_object(
|
||||
&mut self,
|
||||
obj: Variant,
|
||||
book: &mut Book,
|
||||
ini_idx: usize,
|
||||
end_idx: usize,
|
||||
builtin: bool,
|
||||
) -> ParseResult<()> {
|
||||
if book.adts.contains_key(&obj.name) {
|
||||
let msg = PyParser::redefinition_of_type_msg(&obj.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
let mut adt = Adt { ctrs: Default::default(), builtin };
|
||||
if let Some(def) = book.defs.get(&obj.name) {
|
||||
let msg = PyParser::redefinition_of_function_msg(def.builtin, &obj.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
if book.ctrs.contains_key(&obj.name) {
|
||||
let msg = PyParser::redefinition_of_constructor_msg(&obj.name);
|
||||
return self.with_ctx(Err(msg), ini_idx, end_idx);
|
||||
}
|
||||
book.ctrs.insert(obj.name.clone(), obj.name.clone());
|
||||
adt.ctrs.insert(obj.name.clone(), obj.fields);
|
||||
book.adts.insert(obj.name, adt);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn expected_indent<T>(&mut self, expected: Indent, got: Indent) -> ParseResult<T> {
|
||||
match (expected, got) {
|
||||
(Indent::Eof, Indent::Eof) => unreachable!(),
|
||||
(Indent::Eof, Indent::Val(got)) => {
|
||||
let msg = format!("Indentation error. Expected end-of-input, got {} spaces.", got);
|
||||
let idx = *self.index();
|
||||
self.with_ctx(Err(msg), idx, idx + 1)
|
||||
self.with_ctx(Err(msg), idx..idx + 1)
|
||||
}
|
||||
(Indent::Val(expected), Indent::Eof) => {
|
||||
let msg = format!("Indentation error. Expected {} spaces, got end-of-input.", expected);
|
||||
let idx = *self.index();
|
||||
self.with_ctx(Err(msg), idx, idx + 1)
|
||||
self.with_ctx(Err(msg), idx..idx + 1)
|
||||
}
|
||||
(Indent::Val(expected), Indent::Val(got)) => {
|
||||
if got != expected {
|
||||
let msg = format!("Indentation error. Expected {} spaces, got {}.", expected, got);
|
||||
let idx = *self.index();
|
||||
self.with_ctx(Err(msg), idx, idx + 1)
|
||||
self.with_ctx(Err(msg), idx..idx + 1)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ use crate::{
|
||||
hvm::{
|
||||
add_recursive_priority::add_recursive_priority,
|
||||
check_net_size::{check_net_sizes, MAX_NET_SIZE},
|
||||
display_hvm_book,
|
||||
eta_reduce::eta_reduce_hvm_net,
|
||||
hvm_book_show_pretty,
|
||||
inline::inline_hvm_book,
|
||||
mutual_recursion,
|
||||
prune::prune_hvm_book,
|
||||
@ -249,7 +249,7 @@ fn run_hvm(book: &::hvm::ast::Book, cmd: &str, run_opts: &RunOpts) -> Result<Str
|
||||
}
|
||||
|
||||
let out_path = ".out.hvm";
|
||||
std::fs::write(out_path, display_hvm_book(book).to_string()).map_err(|x| x.to_string())?;
|
||||
std::fs::write(out_path, hvm_book_show_pretty(book)).map_err(|x| x.to_string())?;
|
||||
let mut process = std::process::Command::new(run_opts.hvm_path.clone())
|
||||
.arg(cmd)
|
||||
.arg(out_path)
|
||||
|
@ -2,7 +2,7 @@ use bend::{
|
||||
check_book, compile_book, desugar_book,
|
||||
diagnostics::{Diagnostics, DiagnosticsConfig, Severity},
|
||||
fun::{Book, Name},
|
||||
hvm::display_hvm_book,
|
||||
hvm::hvm_book_show_pretty,
|
||||
load_file_to_book, run_book, AdtEncoding, CompileOpts, OptLevel, RunOpts,
|
||||
};
|
||||
use clap::{Args, CommandFactory, Parser, Subcommand};
|
||||
@ -300,7 +300,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> {
|
||||
let compile_res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
|
||||
|
||||
eprint!("{}", compile_res.diagnostics);
|
||||
println!("{}", display_hvm_book(&compile_res.hvm_book));
|
||||
println!("{}", hvm_book_show_pretty(&compile_res.hvm_book));
|
||||
}
|
||||
|
||||
Mode::Run(RunArgs { pretty, run_opts, comp_opts, warn_opts, path, arguments })
|
||||
@ -342,8 +342,7 @@ fn execute_cli_mode(mut cli: Cli) -> Result<(), Diagnostics> {
|
||||
let compile_res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
|
||||
|
||||
let out_path = ".out.hvm";
|
||||
std::fs::write(out_path, display_hvm_book(&compile_res.hvm_book).to_string())
|
||||
.map_err(|x| x.to_string())?;
|
||||
std::fs::write(out_path, hvm_book_show_pretty(&compile_res.hvm_book)).map_err(|x| x.to_string())?;
|
||||
|
||||
let gen_fn = |out_path: &str| {
|
||||
let mut process = std::process::Command::new(hvm_bin);
|
||||
|
@ -2,7 +2,7 @@ use bend::{
|
||||
compile_book, desugar_book,
|
||||
diagnostics::{Diagnostics, DiagnosticsConfig, Severity},
|
||||
fun::{load_book::do_parse_book, net_to_term::net_to_term, term_to_net::Labels, Book, Ctx, Name, Term},
|
||||
hvm::display_hvm_book,
|
||||
hvm::hvm_book_show_pretty,
|
||||
net::hvm_to_net::hvm_to_net,
|
||||
run_book, AdtEncoding, CompileOpts, RunOpts,
|
||||
};
|
||||
@ -108,7 +108,7 @@ fn compile_file() {
|
||||
let diagnostics_cfg = DiagnosticsConfig { unused_definition: Severity::Allow, ..Default::default() };
|
||||
|
||||
let res = compile_book(&mut book, compile_opts, diagnostics_cfg, None)?;
|
||||
Ok(format!("{}{}", res.diagnostics, display_hvm_book(&res.hvm_book)))
|
||||
Ok(format!("{}{}", res.diagnostics, hvm_book_show_pretty(&res.hvm_book)))
|
||||
})
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ fn compile_file_o_all() {
|
||||
};
|
||||
|
||||
let res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
|
||||
Ok(format!("{}{}", res.diagnostics, display_hvm_book(&res.hvm_book)))
|
||||
Ok(format!("{}{}", res.diagnostics, hvm_book_show_pretty(&res.hvm_book)))
|
||||
})
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ fn compile_file_o_no_all() {
|
||||
let compile_opts = CompileOpts::default().set_no_all();
|
||||
let diagnostics_cfg = DiagnosticsConfig::default();
|
||||
let res = compile_book(&mut book, compile_opts, diagnostics_cfg, None)?;
|
||||
Ok(format!("{}", display_hvm_book(&res.hvm_book)))
|
||||
Ok(hvm_book_show_pretty(&res.hvm_book).to_string())
|
||||
})
|
||||
}
|
||||
|
||||
@ -351,7 +351,7 @@ fn compile_entrypoint() {
|
||||
book.entrypoint = Some(Name::new("foo"));
|
||||
let diagnostics_cfg = DiagnosticsConfig { ..DiagnosticsConfig::new(Severity::Error, true) };
|
||||
let res = compile_book(&mut book, CompileOpts::default(), diagnostics_cfg, None)?;
|
||||
Ok(format!("{}{}", res.diagnostics, display_hvm_book(&res.hvm_book)))
|
||||
Ok(format!("{}{}", res.diagnostics, hvm_book_show_pretty(&res.hvm_book)))
|
||||
})
|
||||
}
|
||||
|
||||
@ -398,7 +398,7 @@ fn mutual_recursion() {
|
||||
let mut book = do_parse_book(code, path, Book::builtins())?;
|
||||
let opts = CompileOpts { merge: true, ..CompileOpts::default() };
|
||||
let res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
|
||||
Ok(format!("{}{}", res.diagnostics, display_hvm_book(&res.hvm_book)))
|
||||
Ok(format!("{}{}", res.diagnostics, hvm_book_show_pretty(&res.hvm_book)))
|
||||
})
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ fn scott_triggers_unused() {
|
||||
let diagnostics_cfg =
|
||||
DiagnosticsConfig { unused_definition: Severity::Error, ..DiagnosticsConfig::default() };
|
||||
let res = compile_book(&mut book, opts, diagnostics_cfg, None)?;
|
||||
Ok(format!("{}{}", res.diagnostics, display_hvm_book(&res.hvm_book)))
|
||||
Ok(format!("{}{}", res.diagnostics, hvm_book_show_pretty(&res.hvm_book)))
|
||||
})
|
||||
}
|
||||
|
||||
|
4
tests/golden_tests/run_file/hvm_def_cast.bend
Normal file
4
tests/golden_tests/run_file/hvm_def_cast.bend
Normal file
@ -0,0 +1,4 @@
|
||||
hvm to_f24:
|
||||
($([f24] a) a)
|
||||
|
||||
main = (to_f24 42)
|
@ -22,7 +22,7 @@ input_file: tests/golden_tests/cli/no_check_net_size.bend
|
||||
@Gen.go__C0 = a
|
||||
& @Arr/Leaf ~ a
|
||||
|
||||
@Gen.go__C1 = ({a d} ({$([*2] $([|1] e)) $([*2] b)} g))
|
||||
@Gen.go__C1 = ({a d} ({$([*0x0000002] $([|0x0000001] e)) $([*0x0000002] b)} g))
|
||||
& @Arr/Node ~ (c (f g))
|
||||
&!@Gen.go ~ (a (b c))
|
||||
&!@Gen.go ~ (d (e f))
|
||||
@ -74,7 +74,7 @@ input_file: tests/golden_tests/cli/no_check_net_size.bend
|
||||
|
||||
@Merge__C9 = ((@Merge__C4 a) a)
|
||||
|
||||
@Radix = ({$([&8388608] a) {$([&4194304] b) {$([&2097152] c) {$([&1048576] d) {$([&524288] e) {$([&262144] f) {$([&131072] g) {$([&65536] h) {$([&32768] i) {$([&16384] j) {$([&8192] k) {$([&4096] l) {$([&2048] m) {$([&1024] n) {$([&512] o) {$([&256] p) {$([&128] q) {$([&64] r) {$([&32] s) {$([&16] t) {$([&8] u) {$([&4] v) {$([&2] w) $([&1] x)}}}}}}}}}}}}}}}}}}}}}}} vb)
|
||||
@Radix = ({$([&0x0800000] a) {$([&0x0400000] b) {$([&0x0200000] c) {$([&0x0100000] d) {$([&0x0080000] e) {$([&0x0040000] f) {$([&0x0020000] g) {$([&0x0010000] h) {$([&0x0008000] i) {$([&0x0004000] j) {$([&0x0002000] k) {$([&0x0001000] l) {$([&0x0000800] m) {$([&0x0000400] n) {$([&0x0000200] o) {$([&0x0000100] p) {$([&0x0000080] q) {$([&0x0000040] r) {$([&0x0000020] s) {$([&0x0000010] t) {$([&0x0000008] u) {$([&0x0000004] v) {$([&0x0000002] w) $([&0x0000001] x)}}}}}}}}}}}}}}}}}}}}}}} vb)
|
||||
& @Swap ~ (a (ub (@Map_/Free vb)))
|
||||
& @Swap ~ (b (tb (@Map_/Free ub)))
|
||||
& @Swap ~ (c (sb (@Map_/Free tb)))
|
||||
@ -141,7 +141,7 @@ input_file: tests/golden_tests/cli/no_check_net_size.bend
|
||||
@ToArr__C0 = a
|
||||
& @Arr/Leaf ~ a
|
||||
|
||||
@ToArr__C1 = (* (b (e ({$([*2] $([+1] d)) $([*2] $([+0] a))} g))))
|
||||
@ToArr__C1 = (* (b (e ({$([*0x0000002] $([+0x0000001] d)) $([*0x0000002] $([+0x0000000] a))} g))))
|
||||
& @Arr/Node ~ (c (f g))
|
||||
&!@ToArr ~ (a (b c))
|
||||
&!@ToArr ~ (d (e f))
|
||||
|
@ -4,4 +4,4 @@ input_file: tests/golden_tests/compile_file/addition.bend
|
||||
---
|
||||
@main = c
|
||||
& (a b) ~ (8 c)
|
||||
& $(1 $([+] $(a b))) ~ [+1]
|
||||
& $(1 $([+] $(a b))) ~ [+0x0000001]
|
||||
|
@ -3,4 +3,4 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/addition_const.bend
|
||||
---
|
||||
@main = a
|
||||
& $(2 a) ~ [+1]
|
||||
& $(2 a) ~ [+0x0000001]
|
||||
|
@ -3,7 +3,7 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/elif.bend
|
||||
---
|
||||
@main = j
|
||||
& $(2 ?(((d (e (?(((b (?(((?((0 (* 2)) a) a) (* (* 3))) (b c)) c)) (* (* (* 4)))) (d (e f))) f))) (* (* (* (* 1))))) (g (h (i j))))) ~ [=1]
|
||||
& $(1 g) ~ [<2]
|
||||
& $(2 h) ~ [>3]
|
||||
& $(2 i) ~ [=2]
|
||||
& $(2 ?(((d (e (?(((b (?(((?((0 (* 2)) a) a) (* (* 3))) (b c)) c)) (* (* (* 4)))) (d (e f))) f))) (* (* (* (* 1))))) (g (h (i j))))) ~ [=0x0000001]
|
||||
& $(1 g) ~ [<0x0000002]
|
||||
& $(2 h) ~ [>0x0000003]
|
||||
& $(2 i) ~ [=0x0000002]
|
||||
|
@ -3,4 +3,6 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/error_data_def_name.bend
|
||||
---
|
||||
[4m[1m[31mErrors:[0m
|
||||
Function 'A/A' has the same name as a previously defined constructor
|
||||
In tests/golden_tests/compile_file/error_data_def_name.bend :
|
||||
Redefinition of constructor 'A/A'.
|
||||
[0m 2 | [4m[31mA/A = 0[0m
|
||||
|
@ -3,5 +3,5 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/f24_oper.bend
|
||||
---
|
||||
@main = b
|
||||
& $(1.2399902 $([/] $(a b))) ~ [*4388912]
|
||||
& $(-235.1211 a) ~ [+0]
|
||||
& $(1.2399902 $([/] $(a b))) ~ [*0x042F830]
|
||||
& $(-235.1211 a) ~ [+0x0000000]
|
||||
|
@ -3,5 +3,5 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/i24_oper.bend
|
||||
---
|
||||
@main = b
|
||||
& $(-1 $([*] $(a b))) ~ [+1]
|
||||
& $(+14 a) ~ [-134217716]
|
||||
& $(-1 $([*] $(a b))) ~ [+0x0000001]
|
||||
& $(+14 a) ~ [-0x7FFFFF4]
|
||||
|
@ -3,4 +3,4 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/match.bend
|
||||
---
|
||||
@main = c
|
||||
& $(1 ?(((a (* a)) (* (* (b b)))) c)) ~ [+0]
|
||||
& $(1 ?(((a (* a)) (* (* (b b)))) c)) ~ [+0x0000000]
|
||||
|
@ -3,5 +3,5 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/nums.bend
|
||||
---
|
||||
@main = b
|
||||
& $(a b) ~ [+16777215]
|
||||
& $(1000 a) ~ [+5]
|
||||
& $(a b) ~ [+0x0FFFFFF]
|
||||
& $(1000 a) ~ [+0x0000005]
|
||||
|
@ -3,4 +3,4 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/op2.bend
|
||||
---
|
||||
@main = a
|
||||
& $(1 $([=2] $([&3] $([|4] $([<5] $([>6] $([:/7] $([*8] $([:-9] $([+10] $([:%11] a))))))))))) ~ [!0]
|
||||
& $(1 $([=0x0000002] $([&0x0000003] $([|0x0000004] $([<0x0000005] $([>0x0000006] $([:/0x0000007] $([*0x0000008] $([:-0x0000009] $([+0x000000A] $([:%0x000000B] a))))))))))) ~ [!0x0000000]
|
||||
|
@ -22,7 +22,7 @@ input_file: tests/golden_tests/compile_file/redex_order_recursive.bend
|
||||
@List.len = ((@List.len__C1 a) a)
|
||||
|
||||
@List.len__C0 = (* (* (a c)))
|
||||
& $(b c) ~ [+1]
|
||||
& $(b c) ~ [+0x0000001]
|
||||
& @List.len ~ (a b)
|
||||
|
||||
@List.len__C1 = (?((0 @List.len__C0) a) a)
|
||||
@ -31,7 +31,7 @@ input_file: tests/golden_tests/compile_file/redex_order_recursive.bend
|
||||
|
||||
@List.len_tr__C0 = (* (* (a (b d))))
|
||||
& @List.len_tr ~ (a (c d))
|
||||
& $(b c) ~ [+1]
|
||||
& $(b c) ~ [+0x0000001]
|
||||
|
||||
@List.len_tr__C1 = (?(((a a) @List.len_tr__C0) b) b)
|
||||
|
||||
@ -100,7 +100,7 @@ input_file: tests/golden_tests/compile_file/redex_order_recursive.bend
|
||||
@Tree.height = ((@Tree.height__C1 a) a)
|
||||
|
||||
@Tree.height__C0 = (a (c f))
|
||||
& $(e f) ~ [+1]
|
||||
& $(e f) ~ [+0x0000001]
|
||||
& @max ~ (b (d e))
|
||||
&!@Tree.height ~ (a b)
|
||||
&!@Tree.height ~ (c d)
|
||||
@ -130,7 +130,7 @@ input_file: tests/golden_tests/compile_file/redex_order_recursive.bend
|
||||
@Tree.nodes = ((@Tree.nodes__C1 a) a)
|
||||
|
||||
@Tree.nodes__C0 = (a (b e))
|
||||
& $(d e) ~ [+1]
|
||||
& $(d e) ~ [+0x0000001]
|
||||
&!@Tree.nodes ~ (a $([+] $(c d)))
|
||||
&!@Tree.nodes ~ (b c)
|
||||
|
||||
@ -170,4 +170,4 @@ input_file: tests/golden_tests/compile_file/redex_order_recursive.bend
|
||||
|
||||
@tail_recursive__C0 = (a (b d))
|
||||
& @tail_recursive ~ (a (c d))
|
||||
& $(b c) ~ [+1]
|
||||
& $(b c) ~ [+0x0000001]
|
||||
|
@ -2,4 +2,4 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file/switch_in_switch_arg.bend
|
||||
---
|
||||
@main = (?((0 (a a)) ?((0 ($([+1] b) b)) c)) c)
|
||||
@main = (?((0 (a a)) ?((0 ($([+0x0000001] b) b)) c)) c)
|
||||
|
@ -4,4 +4,4 @@ input_file: tests/golden_tests/compile_file_o_all/addition.bend
|
||||
---
|
||||
@main = c
|
||||
& (a b) ~ (8 c)
|
||||
& $(1 $([+] $(a b))) ~ [+1]
|
||||
& $(1 $([+] $(a b))) ~ [+0x0000001]
|
||||
|
@ -2,4 +2,4 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_file_o_all/addition_var_fst.bend
|
||||
---
|
||||
@main = ($([+1] a) a)
|
||||
@main = ($([+0x0000001] a) a)
|
||||
|
@ -4,7 +4,7 @@ input_file: tests/golden_tests/compile_file_o_all/num_pattern_with_var.bend
|
||||
---
|
||||
@Foo = ((@Foo__C2 a) a)
|
||||
|
||||
@Foo__C0 = ($([+1] a) a)
|
||||
@Foo__C0 = ($([+0x0000001] a) a)
|
||||
|
||||
@Foo__C1 = (* (?((0 @Foo__C0) a) a))
|
||||
|
||||
|
@ -5,7 +5,7 @@ input_file: tests/golden_tests/mutual_recursion/len.bend
|
||||
@Len = ((@Len__C1 a) a)
|
||||
|
||||
@Len__C0 = (* (* (a c)))
|
||||
& $(b c) ~ [+1]
|
||||
& $(b c) ~ [+0x0000001]
|
||||
& @Len ~ (a b)
|
||||
|
||||
@Len__C1 = (?((0 @Len__C0) a) a)
|
||||
|
9
tests/snapshots/run_file__hvm_def_cast.bend.snap
Normal file
9
tests/snapshots/run_file__hvm_def_cast.bend.snap
Normal file
@ -0,0 +1,9 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/run_file/hvm_def_cast.bend
|
||||
---
|
||||
NumScott:
|
||||
42.000
|
||||
|
||||
Scott:
|
||||
42.000
|
@ -3,4 +3,6 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/run_file/override_list_ctr.bend
|
||||
---
|
||||
[4m[1m[31mErrors:[0m
|
||||
Function 'List/Nil' has the same name as a previously defined constructor
|
||||
In tests/golden_tests/run_file/override_list_ctr.bend :
|
||||
Redefinition of builtin (constructor) 'List/Nil'.
|
||||
[0m 1 | [4m[31mList/Nil = *[0m
|
||||
|
@ -3,4 +3,6 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/run_file/override_str_ctr.bend
|
||||
---
|
||||
[4m[1m[31mErrors:[0m
|
||||
Function 'String/Cons' has the same name as a previously defined constructor
|
||||
In tests/golden_tests/run_file/override_str_ctr.bend :
|
||||
Redefinition of builtin (constructor) 'String/Cons'.
|
||||
[0m 1 | [4m[31mString/Cons = *[0m
|
||||
|
Loading…
Reference in New Issue
Block a user