mirror of
https://github.com/HigherOrderCO/Bend.git
synced 2024-09-11 03:45:29 +03:00
[sc-548] Add support for i24 and f24
This commit is contained in:
parent
ba748c95e8
commit
03fcf344f1
@ -61,6 +61,7 @@
|
||||
"peekable",
|
||||
"postcondition",
|
||||
"prec",
|
||||
"powi",
|
||||
"readback",
|
||||
"recursively",
|
||||
"redex",
|
||||
|
@ -13,8 +13,12 @@
|
||||
(SwapGT _ v x xs) = (List.cons x (Insert v xs))
|
||||
|
||||
// Generates a random list
|
||||
(Rnd 0 s) = []
|
||||
(Rnd n s) = (List.cons s (Rnd (- n 1) (% (+ (* s 1664525) 1013904223) 4294967295)))
|
||||
(Rnd 0 s) = List.nil
|
||||
(Rnd n s) =
|
||||
let s = (^ s (* s 0b10000000000000))
|
||||
let s = (^ s (/ s 0b100000000000000000))
|
||||
let s = (^ s (* s 0b100000))
|
||||
(List.cons s (Rnd (- n 1) s))
|
||||
|
||||
// Sums a list
|
||||
(Sum []) = 0
|
||||
@ -22,7 +26,7 @@
|
||||
|
||||
(Main) =
|
||||
let n = 10
|
||||
(Sum (Sort (Rnd (* 2 50) n)))
|
||||
(Sum (Sort (Rnd 0x100 n)))
|
||||
|
||||
// Use an argument from cli
|
||||
// (Main n) = (Sum (Sort (Rnd (* 2 50) n)))
|
||||
// (Main n) = (Sum (Sort (Rnd 0x100 n)))
|
||||
|
@ -17,8 +17,12 @@ data Tree = Leaf | (Node l m r)
|
||||
(Push _ x pair) = (pair λmin λmax λp (p min (List.cons x max)))
|
||||
|
||||
// Generates a random list
|
||||
(Rnd 0 s) = (List.nil)
|
||||
(Rnd n s) = (List.cons s (Rnd (- n 1) (% (+ (* s 1664525) 1013904223) 4294967295)))
|
||||
(Rnd 0 s) = List.nil
|
||||
(Rnd n s) =
|
||||
let s = (^ s (* s 0b10000000000000))
|
||||
let s = (^ s (/ s 0b100000000000000000))
|
||||
let s = (^ s (* s 0b100000))
|
||||
(List.cons s (Rnd (- n 1) s))
|
||||
|
||||
// Sums all elements in a concatenation tree
|
||||
(Sum Leaf) = 0
|
||||
@ -26,8 +30,7 @@ data Tree = Leaf | (Node l m r)
|
||||
|
||||
// Sorts and sums n random numbers
|
||||
(Main) =
|
||||
let n = 12
|
||||
(Sum (Sort (Rnd (* 2 n) 1)))
|
||||
(Sum (Sort (Rnd 0x100 1)))
|
||||
|
||||
// Use an argument from cli
|
||||
// (Main n) = (Sum (Sort (Rnd (<< 1 n) 1)))
|
||||
|
@ -36,45 +36,44 @@ data Arr = Null | (Leaf x) | (Node a b)
|
||||
// Radix : U60 -> Map
|
||||
(Radix n) =
|
||||
let r = Used
|
||||
let r = (Swap (& n 1) r Free)
|
||||
let r = (Swap (& n 2) r Free)
|
||||
let r = (Swap (& n 4) r Free)
|
||||
let r = (Swap (& n 8) r Free)
|
||||
let r = (Swap (& n 16) r Free)
|
||||
let r = (Swap (& n 0x1) r Free)
|
||||
let r = (Swap (& n 0x2) r Free)
|
||||
let r = (Swap (& n 0x4) r Free)
|
||||
let r = (Swap (& n 0x8) r Free)
|
||||
let r = (Swap (& n 0x10) r Free)
|
||||
(Radix2 n r)
|
||||
|
||||
(Radix2 n r) =
|
||||
let r = (Swap (& n 32) r Free)
|
||||
let r = (Swap (& n 64) r Free)
|
||||
let r = (Swap (& n 128) r Free)
|
||||
let r = (Swap (& n 256) r Free)
|
||||
let r = (Swap (& n 512) r Free)
|
||||
let r = (Swap (& n 0x20) r Free)
|
||||
let r = (Swap (& n 0x40) r Free)
|
||||
let r = (Swap (& n 0x80) r Free)
|
||||
let r = (Swap (& n 0x100) r Free)
|
||||
let r = (Swap (& n 0x200) r Free)
|
||||
(Radix3 n r)
|
||||
|
||||
(Radix3 n r) =
|
||||
let r = (Swap (& n 1024) r Free)
|
||||
let r = (Swap (& n 2048) r Free)
|
||||
let r = (Swap (& n 4096) r Free)
|
||||
let r = (Swap (& n 8192) r Free)
|
||||
let r = (Swap (& n 16384) r Free)
|
||||
let r = (Swap (& n 0x400) r Free)
|
||||
let r = (Swap (& n 0x800) r Free)
|
||||
let r = (Swap (& n 0x1000) r Free)
|
||||
let r = (Swap (& n 0x2000) r Free)
|
||||
let r = (Swap (& n 0x4000) r Free)
|
||||
(Radix4 n r)
|
||||
|
||||
(Radix4 n r) =
|
||||
let r = (Swap (& n 32768) r Free)
|
||||
let r = (Swap (& n 65536) r Free)
|
||||
let r = (Swap (& n 131072) r Free)
|
||||
let r = (Swap (& n 262144) r Free)
|
||||
let r = (Swap (& n 524288) r Free)
|
||||
let r = (Swap (& n 0x8000) r Free)
|
||||
let r = (Swap (& n 0x10000) r Free)
|
||||
let r = (Swap (& n 0x20000) r Free)
|
||||
let r = (Swap (& n 0x40000) r Free)
|
||||
let r = (Swap (& n 0x80000) r Free)
|
||||
(Radix5 n r)
|
||||
|
||||
(Radix5 n r) =
|
||||
let r = (Swap (& n 1048576) r Free)
|
||||
let r = (Swap (& n 2097152) r Free)
|
||||
let r = (Swap (& n 4194304) r Free)
|
||||
let r = (Swap (& n 8388608) r Free)
|
||||
let r = (Swap (& n 0x100000) r Free)
|
||||
let r = (Swap (& n 0x200000) r Free)
|
||||
let r = (Swap (& n 0x400000) r Free)
|
||||
let r = (Swap (& n 0x800000) r Free)
|
||||
r
|
||||
|
||||
|
||||
// Reverse : Arr -> Arr
|
||||
(Reverse Null) = Null
|
||||
(Reverse (Leaf a)) = (Leaf a)
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{parser::TermParser, Book, Name, NumType, Pattern, Term};
|
||||
use super::{parser::TermParser, Book, Name, Num, Pattern, Term};
|
||||
use crate::maybe_grow;
|
||||
|
||||
const BUILTINS: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/term/builtins.hvm"));
|
||||
@ -62,11 +62,11 @@ impl Term {
|
||||
|
||||
pub fn encode_str(val: &str) -> Term {
|
||||
val.chars().rfold(Term::r#ref(SNIL), |acc, char| {
|
||||
Term::call(Term::r#ref(SCONS), [Term::Num { typ: NumType::U24, val: char as u32 }, acc])
|
||||
Term::call(Term::r#ref(SCONS), [Term::Num { val: Num::U24(char as u32 & 0x00ff_ffff) }, acc])
|
||||
})
|
||||
}
|
||||
|
||||
pub fn encode_nat(val: u64) -> Term {
|
||||
pub fn encode_nat(val: u32) -> Term {
|
||||
(0 .. val).fold(Term::r#ref(NAT_ZERO), |acc, _| Term::app(Term::r#ref(NAT_SUCC), acc))
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{Book, Definition, FanKind, Name, Op, Pattern, Rule, Tag, Term};
|
||||
use super::{Book, Definition, FanKind, Name, Num, Op, Pattern, Rule, Tag, Term};
|
||||
use crate::maybe_grow;
|
||||
use std::{fmt, ops::Deref};
|
||||
|
||||
@ -114,7 +114,9 @@ impl fmt::Display for Term {
|
||||
Term::Fan { fan: FanKind::Tup, tag, els } => write!(f, "{}({})", tag, DisplayJoin(|| els.iter(), ", ")),
|
||||
Term::Fan { fan: FanKind::Dup, tag, els } => write!(f, "{}{{{}}}", tag, DisplayJoin(|| els, " ")),
|
||||
Term::Era => write!(f, "*"),
|
||||
Term::Num { typ: _, val } => write!(f, "{val}"),
|
||||
Term::Num { val: Num::U24(val) } => write!(f, "{val}"),
|
||||
Term::Num { val: Num::I24(val) } => write!(f, "{}{}", if *val < 0 { "-" } else { "+" }, val.abs()),
|
||||
Term::Num { val: Num::F24(val) } => write!(f, "{val:.3}"),
|
||||
Term::Nat { val } => write!(f, "#{val}"),
|
||||
Term::Str { val } => write!(f, "{val:?}"),
|
||||
Term::Opr { opr, fst, snd } => {
|
||||
@ -374,7 +376,9 @@ impl Term {
|
||||
}
|
||||
|
||||
Term::Nat { val } => write!(f, "#{val}"),
|
||||
Term::Num { typ: _, val } => write!(f, "{val}"),
|
||||
Term::Num { val: Num::U24(val) } => write!(f, "{val}"),
|
||||
Term::Num { val: Num::I24(val) } => write!(f, "{}{}", if *val < 0 { "-" } else { "+" }, val.abs()),
|
||||
Term::Num { val: Num::F24(val) } => write!(f, "{val:.3}"),
|
||||
Term::Str { val } => write!(f, "{val:?}"),
|
||||
Term::Ref { nam } => write!(f, "{nam}"),
|
||||
Term::Era => write!(f, "*"),
|
||||
|
@ -2,7 +2,7 @@ use indexmap::IndexMap;
|
||||
|
||||
use crate::term::Name;
|
||||
|
||||
use super::{Definition, Enum, Program, Stmt, Term, Variant};
|
||||
use super::{Definition, Enum, MBind, Program, Stmt, Term, Variant};
|
||||
|
||||
struct Ctx<'a> {
|
||||
variants: &'a IndexMap<Name, Name>,
|
||||
@ -58,9 +58,26 @@ impl Stmt {
|
||||
arm.rgt.order_kwargs(ctx);
|
||||
}
|
||||
}
|
||||
Stmt::Switch { .. } => unimplemented!(),
|
||||
Stmt::Fold { .. } => unimplemented!(),
|
||||
Stmt::Do { .. } => unimplemented!(),
|
||||
Stmt::Switch { arg, arms, .. } => {
|
||||
arg.order_kwargs(ctx);
|
||||
for arm in arms {
|
||||
arm.order_kwargs(ctx);
|
||||
}
|
||||
}
|
||||
Stmt::Fold { arg, arms, .. } => {
|
||||
arg.order_kwargs(ctx);
|
||||
for arm in arms {
|
||||
arm.rgt.order_kwargs(ctx);
|
||||
}
|
||||
}
|
||||
Stmt::Do { block, .. } => {
|
||||
for bind in block {
|
||||
match bind {
|
||||
MBind::Ask { val, .. } => val.order_kwargs(ctx),
|
||||
MBind::Stmt { stmt } => stmt.order_kwargs(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
Stmt::Return { term } => term.order_kwargs(ctx),
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ impl Term {
|
||||
match self {
|
||||
Term::None => lang::Term::Era,
|
||||
Term::Var { nam } => lang::Term::Var { nam },
|
||||
Term::Num { val } => lang::Term::Num { typ: lang::NumType::U24, val },
|
||||
Term::Num { val } => lang::Term::Num { val: lang::Num::U24(val) },
|
||||
Term::Call { fun, args, kwargs } => {
|
||||
assert!(kwargs.is_empty());
|
||||
let args = args.into_iter().map(Self::to_lang);
|
||||
|
132
src/term/mod.rs
132
src/term/mod.rs
@ -7,7 +7,7 @@ use crate::{
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use interner::global::{GlobalPool, GlobalString};
|
||||
use itertools::Itertools;
|
||||
use std::{borrow::Cow, collections::HashMap, ops::Deref};
|
||||
use std::{borrow::Cow, collections::HashMap, hash::Hash, ops::Deref};
|
||||
|
||||
pub mod builtins;
|
||||
pub mod check;
|
||||
@ -63,7 +63,7 @@ pub struct Definition {
|
||||
}
|
||||
|
||||
/// A pattern matching rule of a definition.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub struct Rule {
|
||||
pub pats: Vec<Pattern>,
|
||||
pub body: Term,
|
||||
@ -110,11 +110,10 @@ pub enum Term {
|
||||
els: Vec<Term>,
|
||||
},
|
||||
Num {
|
||||
typ: NumType,
|
||||
val: u32,
|
||||
val: Num,
|
||||
},
|
||||
Nat {
|
||||
val: u64,
|
||||
val: u32,
|
||||
},
|
||||
Str {
|
||||
val: GlobalString,
|
||||
@ -181,11 +180,11 @@ pub enum Op {
|
||||
POW,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum NumType {
|
||||
U24 = 1,
|
||||
I24 = 2,
|
||||
F24 = 3,
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Num {
|
||||
U24(u32),
|
||||
I24(i32),
|
||||
F24(f32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
@ -328,7 +327,7 @@ impl Clone for Term {
|
||||
Self::Use { nam, val, nxt } => Self::Use { nam: nam.clone(), val: val.clone(), nxt: nxt.clone() },
|
||||
Self::App { tag, fun, arg } => Self::App { tag: tag.clone(), fun: fun.clone(), arg: arg.clone() },
|
||||
Self::Fan { fan, tag, els } => Self::Fan { fan: *fan, tag: tag.clone(), els: els.clone() },
|
||||
Self::Num { typ, val } => Self::Num { typ: *typ, val: *val },
|
||||
Self::Num { val } => Self::Num { val: *val },
|
||||
Self::Nat { val } => Self::Nat { val: *val },
|
||||
Self::Str { val } => Self::Str { val: val.clone() },
|
||||
Self::Lst { els } => Self::Lst { els: els.clone() },
|
||||
@ -436,19 +435,19 @@ impl Term {
|
||||
Term::Str { val: STRINGS.get(str) }
|
||||
}
|
||||
|
||||
pub fn sub_num(arg: Term, val: u32, typ: NumType) -> Term {
|
||||
if val == 0 {
|
||||
pub fn sub_num(arg: Term, val: Num) -> Term {
|
||||
if val.is_zero() {
|
||||
arg
|
||||
} else {
|
||||
Term::Opr { opr: Op::SUB, fst: Box::new(arg), snd: Box::new(Term::Num { typ, val }) }
|
||||
Term::Opr { opr: Op::SUB, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_num(arg: Term, val: u32, typ: NumType) -> Term {
|
||||
if val == 0 {
|
||||
pub fn add_num(arg: Term, val: Num) -> Term {
|
||||
if val.is_zero() {
|
||||
arg
|
||||
} else {
|
||||
Term::Opr { opr: Op::ADD, fst: Box::new(arg), snd: Box::new(Term::Num { typ, val }) }
|
||||
Term::Opr { opr: Op::ADD, fst: Box::new(arg), snd: Box::new(Term::Num { val }) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,6 +799,71 @@ impl Term {
|
||||
}
|
||||
}
|
||||
|
||||
impl Num {
|
||||
pub fn is_zero(&self) -> bool {
|
||||
match self {
|
||||
Num::U24(val) => *val == 0,
|
||||
Num::I24(val) => *val == 0,
|
||||
Num::F24(val) => *val == 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bits(&self) -> u32 {
|
||||
match self {
|
||||
Num::U24(val) => {
|
||||
assert!(*val <= 0xFFFFFF);
|
||||
((val & 0xFFFFFF) << 4) | 0x1
|
||||
}
|
||||
Num::I24(val) => (((*val as u32) & 0xFFFFFF) << 4) | 0x2,
|
||||
Num::F24(val) => {
|
||||
let bits = val.to_bits();
|
||||
let sign = (bits >> 31) & 0x1;
|
||||
let expo = (bits >> 23) & 0xFF;
|
||||
let mantissa = bits & 0x7FFFFF;
|
||||
assert!(
|
||||
(expo == 0) || (expo == 255) || (64 ..= 127).contains(&expo) || (128 ..= 190).contains(&expo)
|
||||
);
|
||||
let expo = (expo & 0b0011_1111) | ((expo >> 7) << 6);
|
||||
let mantissa = mantissa >> 7;
|
||||
let bits = (sign << 23) | (expo << 16) | mantissa;
|
||||
(bits << 4) | 0x3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_bits(bits: u32) -> Self {
|
||||
match bits & 0xF {
|
||||
0x1 => Num::U24((bits >> 4) & 0xFFFFFF),
|
||||
0x2 => Num::I24((((bits >> 4) & 0xFFFFFF) as i32) << 8 >> 8),
|
||||
0x3 => {
|
||||
let bits = (bits >> 4) & 0xFFFFFF;
|
||||
let sign = (bits >> 23) & 0x1;
|
||||
let expo = (bits >> 16) & 0x7F;
|
||||
let mantissa = bits & 0xFFFF;
|
||||
let i_exp = (expo as i32) - 63;
|
||||
let bits = (sign << 31) | (((i_exp + 127) as u32) << 23) | (mantissa << 7);
|
||||
let bits = if mantissa == 0 && i_exp == -63 { sign << 31 } else { bits };
|
||||
Num::F24(f32::from_bits(bits))
|
||||
}
|
||||
_ => unreachable!("Invalid Num bits"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Num {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.to_bits().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Num {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.to_bits() == other.to_bits()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Num {}
|
||||
|
||||
impl Pattern {
|
||||
pub fn binds(&self) -> impl DoubleEndedIterator<Item = &Option<Name>> + Clone {
|
||||
self.iter().filter_map(|pat| match pat {
|
||||
@ -862,7 +926,7 @@ impl Pattern {
|
||||
Pattern::Ctr(ctr, args) => {
|
||||
Term::call(Term::Ref { nam: ctr.clone() }, args.iter().map(|arg| arg.to_term()))
|
||||
}
|
||||
Pattern::Num(val) => Term::Num { typ: NumType::U24, val: *val },
|
||||
Pattern::Num(val) => Term::Num { val: Num::U24(*val) },
|
||||
Pattern::Fan(fan, tag, args) => {
|
||||
Term::Fan { fan: *fan, tag: tag.clone(), els: args.iter().map(|p| p.to_term()).collect() }
|
||||
}
|
||||
@ -960,3 +1024,35 @@ impl Book {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn num_to_from_bits() {
|
||||
let a = [
|
||||
Num::U24(0),
|
||||
Num::I24(0),
|
||||
Num::F24(0.0),
|
||||
Num::U24(0xFFFFFF),
|
||||
Num::I24(0xFFFFFF),
|
||||
Num::F24(0xFFFFFF as f32),
|
||||
Num::U24(12345),
|
||||
Num::I24(12345),
|
||||
Num::I24(-12345),
|
||||
Num::I24(-0),
|
||||
Num::F24(0.0),
|
||||
Num::F24(-0.0),
|
||||
Num::F24(0.00123),
|
||||
Num::F24(12345.023),
|
||||
Num::F24(-1235.3849),
|
||||
Num::F24(1.0),
|
||||
Num::F24(-1.0),
|
||||
Num::F24(12323658716.0),
|
||||
Num::F24(-12323658716.0),
|
||||
Num::F24(-0.00000000000000001),
|
||||
Num::F24(0.00000000000000001),
|
||||
Num::F24(5447856134985749851.3457896137815694178),
|
||||
Num::F24(-5447856134985749851.3457896137815694178),
|
||||
];
|
||||
for b in a {
|
||||
assert_eq!(b, Num::from_bits(Num::to_bits(&b)));
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,12 @@
|
||||
use crate::{
|
||||
diagnostics::{DiagnosticOrigin, Diagnostics, Severity},
|
||||
maybe_grow,
|
||||
net::{
|
||||
CtrKind::*,
|
||||
INet, NodeId,
|
||||
NodeKind::{self, *},
|
||||
Port, SlotId, ROOT,
|
||||
},
|
||||
term::{num_to_name, term_to_net::Labels, Book, FanKind, Name, Pattern, Tag, Term},
|
||||
net::{CtrKind, INet, NodeId, NodeKind, Port, SlotId, ROOT},
|
||||
term::{num_to_name, term_to_net::Labels, Book, FanKind, Name, Op, Pattern, Tag, Term},
|
||||
};
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
|
||||
use super::{NumType, Op};
|
||||
use super::Num;
|
||||
|
||||
/// Converts an Interaction-INet to a Lambda Calculus term
|
||||
pub fn net_to_term(
|
||||
@ -41,8 +36,8 @@ pub fn net_to_term(
|
||||
let snd = reader.namegen.decl_name(net, Port(node, 2));
|
||||
|
||||
let (fan, tag) = match reader.net.node(node).kind {
|
||||
Ctr(Tup(lab)) => (FanKind::Tup, reader.labels.tup.to_tag(lab)),
|
||||
Ctr(Dup(lab)) => (FanKind::Dup, reader.labels.dup.to_tag(Some(lab))),
|
||||
NodeKind::Ctr(CtrKind::Tup(lab)) => (FanKind::Tup, reader.labels.tup.to_tag(lab)),
|
||||
NodeKind::Ctr(CtrKind::Dup(lab)) => (FanKind::Dup, reader.labels.dup.to_tag(Some(lab))),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@ -81,6 +76,8 @@ pub struct Reader<'a> {
|
||||
|
||||
impl Reader<'_> {
|
||||
fn read_term(&mut self, next: Port) -> Term {
|
||||
use CtrKind::*;
|
||||
|
||||
maybe_grow(|| {
|
||||
if self.dup_paths.is_none() && !self.seen.insert(next) {
|
||||
self.error(ReadbackError::Cyclic);
|
||||
@ -88,15 +85,14 @@ impl Reader<'_> {
|
||||
}
|
||||
|
||||
let node = next.node();
|
||||
|
||||
match &self.net.node(node).kind {
|
||||
Era => {
|
||||
NodeKind::Era => {
|
||||
// Only the main port actually exists in an ERA, the aux ports are just an artifact of this representation.
|
||||
debug_assert!(next.slot() == 0);
|
||||
Term::Era
|
||||
}
|
||||
// If we're visiting a con node...
|
||||
Ctr(Con(lab)) => match next.slot() {
|
||||
NodeKind::Ctr(CtrKind::Con(lab)) => match next.slot() {
|
||||
// If we're visiting a port 0, then it is a lambda.
|
||||
0 => {
|
||||
let nam = self.namegen.decl_name(self.net, Port(node, 1));
|
||||
@ -117,7 +113,7 @@ impl Reader<'_> {
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Mat => match next.slot() {
|
||||
NodeKind::Mat => match next.slot() {
|
||||
2 => {
|
||||
// Read the matched expression
|
||||
let arg = self.read_term(self.net.enter_port(Port(node, 0)));
|
||||
@ -128,7 +124,7 @@ impl Reader<'_> {
|
||||
|
||||
// We expect the pattern matching node to be a CON
|
||||
let sel_kind = &self.net.node(sel_node).kind;
|
||||
let (zero, succ) = if *sel_kind == Ctr(Con(None)) {
|
||||
let (zero, succ) = if *sel_kind == NodeKind::Ctr(Con(None)) {
|
||||
let zero_term = self.read_term(self.net.enter_port(Port(sel_node, 1)));
|
||||
let mut succ_term = self.read_term(self.net.enter_port(Port(sel_node, 2)));
|
||||
|
||||
@ -157,7 +153,7 @@ impl Reader<'_> {
|
||||
Term::Err
|
||||
}
|
||||
},
|
||||
Ref { def_name } => {
|
||||
NodeKind::Ref { def_name } => {
|
||||
if def_name.is_generated() {
|
||||
// Dereference generated names since the user is not aware of them
|
||||
let def = &self.book.defs[def_name];
|
||||
@ -170,7 +166,7 @@ impl Reader<'_> {
|
||||
}
|
||||
}
|
||||
// If we're visiting a fan node...
|
||||
Ctr(kind @ (Dup(_) | Tup(_))) => {
|
||||
NodeKind::Ctr(kind @ (Dup(_) | Tup(_))) => {
|
||||
let (fan, lab) = match *kind {
|
||||
Tup(lab) => (FanKind::Tup, lab),
|
||||
Dup(lab) => (FanKind::Dup, Some(lab)),
|
||||
@ -217,7 +213,7 @@ impl Reader<'_> {
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
Num { val: _ } => {
|
||||
NodeKind::Num { val: _ } => {
|
||||
let (flp, arg) = self.read_opr_arg(next);
|
||||
match arg {
|
||||
NumArg::Sym(opr) => Term::Opr {
|
||||
@ -225,26 +221,26 @@ impl Reader<'_> {
|
||||
fst: Box::new(Term::Err),
|
||||
snd: Box::new(Term::Err),
|
||||
},
|
||||
NumArg::Num(typ, val) => Term::Num { typ, val },
|
||||
NumArg::Num(typ, val) => Term::Num { val: Num::from_bits_and_type(val, typ) },
|
||||
NumArg::Par(opr, val) => {
|
||||
if flp {
|
||||
Term::Opr {
|
||||
opr: Op::from_native_tag(opr, NumType::U24),
|
||||
fst: Box::new(Term::Num { typ: NumType::U24, val }),
|
||||
fst: Box::new(Term::Num { val: Num::from_bits_and_type(val, NumType::U24) }),
|
||||
snd: Box::new(Term::Err),
|
||||
}
|
||||
} else {
|
||||
Term::Opr {
|
||||
opr: Op::from_native_tag(opr, NumType::U24),
|
||||
fst: Box::new(Term::Err),
|
||||
snd: Box::new(Term::Num { typ: NumType::U24, val }),
|
||||
snd: Box::new(Term::Num { val: Num::from_bits_and_type(val, NumType::U24) }),
|
||||
}
|
||||
}
|
||||
}
|
||||
NumArg::Oth(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
Opr => match next.slot() {
|
||||
NodeKind::Opr => match next.slot() {
|
||||
2 => {
|
||||
let port0_kind = self.net.node(self.net.enter_port(Port(node, 0)).node()).kind.clone();
|
||||
if port0_kind == NodeKind::Opr {
|
||||
@ -253,7 +249,7 @@ impl Reader<'_> {
|
||||
if let Term::Opr { opr, fst, snd: _ } = &fst {
|
||||
let (flip, arg) = self.read_opr_arg(self.net.enter_port(Port(node, 1)));
|
||||
let snd = Box::new(match arg {
|
||||
NumArg::Num(typ, val) => Term::Num { typ, val },
|
||||
NumArg::Num(typ, val) => Term::Num { val: Num::from_bits_and_type(val, typ) },
|
||||
NumArg::Oth(term) => term,
|
||||
NumArg::Sym(_) | NumArg::Par(_, _) => {
|
||||
self.error(ReadbackError::InvalidNumericOp);
|
||||
@ -271,34 +267,36 @@ impl Reader<'_> {
|
||||
let (flip0, arg0) = self.read_opr_arg(self.net.enter_port(Port(node, 0)));
|
||||
let (flip1, arg1) = self.read_opr_arg(self.net.enter_port(Port(node, 1)));
|
||||
let (arg0, arg1) = if flip0 != flip1 { (arg1, arg0) } else { (arg0, arg1) };
|
||||
use NumArg::*;
|
||||
match (arg0, arg1) {
|
||||
(Sym(opr), Num(typ, val)) | (Num(typ, val), Sym(opr)) => Term::Opr {
|
||||
(NumArg::Sym(opr), NumArg::Num(typ, val)) | (NumArg::Num(typ, val), NumArg::Sym(opr)) => {
|
||||
Term::Opr {
|
||||
opr: Op::from_native_tag(opr, typ),
|
||||
fst: Box::new(Term::Num { typ, val }),
|
||||
fst: Box::new(Term::Num { val: Num::from_bits_and_type(val, typ) }),
|
||||
snd: Box::new(Term::Err),
|
||||
},
|
||||
(Num(typ, num1), Par(opr, num2)) | (Par(opr, num1), Num(typ, num2)) => Term::Opr {
|
||||
}
|
||||
}
|
||||
(NumArg::Num(typ, num1), NumArg::Par(opr, num2))
|
||||
| (NumArg::Par(opr, num1), NumArg::Num(typ, num2)) => Term::Opr {
|
||||
opr: Op::from_native_tag(opr, typ),
|
||||
fst: Box::new(Term::Num { typ, val: num1 }),
|
||||
snd: Box::new(Term::Num { typ, val: num2 }),
|
||||
fst: Box::new(Term::Num { val: Num::from_bits_and_type(num1, typ) }),
|
||||
snd: Box::new(Term::Num { val: Num::from_bits_and_type(num2, typ) }),
|
||||
},
|
||||
// No type, so assuming u24
|
||||
(Sym(opr), Oth(term)) | (Oth(term), Sym(opr)) => Term::Opr {
|
||||
(NumArg::Sym(opr), NumArg::Oth(term)) | (NumArg::Oth(term), NumArg::Sym(opr)) => Term::Opr {
|
||||
opr: Op::from_native_tag(opr, NumType::U24),
|
||||
fst: Box::new(term),
|
||||
snd: Box::new(Term::Err),
|
||||
},
|
||||
|
||||
(Par(opr, num), Oth(term)) => Term::Opr {
|
||||
(NumArg::Par(opr, num), NumArg::Oth(term)) => Term::Opr {
|
||||
opr: Op::from_native_tag(opr, NumType::U24),
|
||||
fst: Box::new(Term::Num { typ: NumType::U24, val: num }),
|
||||
fst: Box::new(Term::Num { val: Num::from_bits_and_type(num, NumType::U24) }),
|
||||
snd: Box::new(term),
|
||||
},
|
||||
(Oth(term), Par(opr, num)) => Term::Opr {
|
||||
(NumArg::Oth(term), NumArg::Par(opr, num)) => Term::Opr {
|
||||
opr: Op::from_native_tag(opr, NumType::U24),
|
||||
fst: Box::new(term),
|
||||
snd: Box::new(Term::Num { typ: NumType::U24, val: num }),
|
||||
snd: Box::new(Term::Num { val: Num::from_bits_and_type(num, NumType::U24) }),
|
||||
},
|
||||
_ => {
|
||||
self.error(ReadbackError::InvalidNumericOp);
|
||||
@ -312,7 +310,7 @@ impl Reader<'_> {
|
||||
Term::Err
|
||||
}
|
||||
},
|
||||
Rot => {
|
||||
NodeKind::Rot => {
|
||||
self.error(ReadbackError::ReachedRoot);
|
||||
Term::Err
|
||||
}
|
||||
@ -323,7 +321,7 @@ impl Reader<'_> {
|
||||
fn read_opr_arg(&mut self, next: Port) -> (bool, NumArg) {
|
||||
let node = next.node();
|
||||
match &self.net.node(node).kind {
|
||||
Num { val } => {
|
||||
NodeKind::Num { val } => {
|
||||
self.seen.insert(next);
|
||||
let flipped = ((val >> 28) & 0x1) != 0;
|
||||
let typ = val & 0xf;
|
||||
@ -381,7 +379,7 @@ impl Reader<'_> {
|
||||
|
||||
// Eta-reduce the readback inet.
|
||||
// This is not valid for all kinds of nodes, only CON/TUP/DUP, due to their interaction rules.
|
||||
if matches!(node_kind, Ctr(_)) {
|
||||
if matches!(node_kind, NodeKind::Ctr(_)) {
|
||||
match (fst_port, snd_port) {
|
||||
(Port(fst_node, 1), Port(snd_node, 2)) if fst_node == snd_node => {
|
||||
if self.net.node(fst_node).kind == *node_kind {
|
||||
@ -427,6 +425,13 @@ enum NumArg {
|
||||
Oth(Term),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum NumType {
|
||||
U24 = 1,
|
||||
I24 = 2,
|
||||
F24 = 3,
|
||||
}
|
||||
|
||||
impl Op {
|
||||
fn from_native_tag(val: u32, typ: NumType) -> Op {
|
||||
match val {
|
||||
@ -476,6 +481,12 @@ impl NumType {
|
||||
}
|
||||
}
|
||||
|
||||
impl Num {
|
||||
fn from_bits_and_type(bits: u32, typ: NumType) -> Self {
|
||||
Num::from_bits((bits & 0x00ff_ffff) << 4 | (typ as u32))
|
||||
}
|
||||
}
|
||||
|
||||
/* Insertion of dups in the middle of the term */
|
||||
|
||||
/// Represents `let #tag(fst, snd) = val` / `let #tag{fst snd} = val`
|
||||
@ -589,7 +600,7 @@ impl NameGen {
|
||||
// If port is linked to an erase node, return an unused variable
|
||||
let var_use = net.enter_port(var_port);
|
||||
let var_kind = &net.node(var_use.node()).kind;
|
||||
(*var_kind != Era).then(|| self.var_name(var_port))
|
||||
(*var_kind != NodeKind::Era).then(|| self.var_name(var_port))
|
||||
}
|
||||
|
||||
pub fn unique(&mut self) -> Name {
|
||||
|
@ -1,15 +1,13 @@
|
||||
use crate::{
|
||||
maybe_grow,
|
||||
term::{
|
||||
display::DisplayFn, Adt, Book, Definition, FanKind, MatchRule, Name, Op, Pattern, Rule, Tag, Term,
|
||||
display::DisplayFn, Adt, Book, Definition, FanKind, MatchRule, Name, Num, Op, Pattern, Rule, Tag, Term,
|
||||
STRINGS,
|
||||
},
|
||||
};
|
||||
use highlight_error::highlight_error;
|
||||
use TSPL::Parser;
|
||||
|
||||
use super::NumType;
|
||||
|
||||
// hvml grammar description:
|
||||
// <Book> ::= (<Data> | <Rule>)*
|
||||
// <Data> ::= "data" <Name> "=" ( <Name> | "(" <Name> (<Name>)* ")" )+
|
||||
@ -188,8 +186,8 @@ impl<'a> TermParser<'a> {
|
||||
// Number
|
||||
if self.peek_one().map_or(false, |c| c.is_ascii_digit()) {
|
||||
unexpected_tag(self)?;
|
||||
let num = self.parse_u64()?;
|
||||
return Ok(Pattern::Num(num as u32));
|
||||
let num = self.parse_u32()?;
|
||||
return Ok(Pattern::Num(num));
|
||||
}
|
||||
|
||||
// Channel
|
||||
@ -303,7 +301,7 @@ impl<'a> TermParser<'a> {
|
||||
if self.starts_with("#") {
|
||||
self.consume("#")?;
|
||||
unexpected_tag(self)?;
|
||||
let val = self.parse_u64()?;
|
||||
let val = self.parse_u32()?;
|
||||
return Ok(Term::Nat { val });
|
||||
}
|
||||
|
||||
@ -318,14 +316,61 @@ impl<'a> TermParser<'a> {
|
||||
if self.starts_with("'") {
|
||||
unexpected_tag(self)?;
|
||||
let char = self.parse_quoted_char()?;
|
||||
return Ok(Term::Num { typ: NumType::U24, val: char as u32 });
|
||||
return Ok(Term::Num { val: Num::U24(char as u32 & 0x00ff_ffff) });
|
||||
}
|
||||
|
||||
// Native num
|
||||
if self.peek_one().map_or(false, |c| c.is_ascii_digit()) {
|
||||
// Native Number
|
||||
if self.peek_one().map_or(false, |c| "0123456789+-".contains(c)) {
|
||||
unexpected_tag(self)?;
|
||||
let val = self.parse_u64()?;
|
||||
return Ok(Term::Num { typ: NumType::U24, val: val as u32 });
|
||||
|
||||
let ini_idx = *self.index();
|
||||
|
||||
// Parses sign
|
||||
let sgn = if self.try_consume("+") {
|
||||
Some(1)
|
||||
} else if self.try_consume("-") {
|
||||
Some(-1)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Parses main value
|
||||
let num = self.parse_u32()?;
|
||||
|
||||
// Parses frac value (Float type)
|
||||
// TODO: Will lead to some rounding errors
|
||||
// TODO: Doesn't cover very large/small numbers
|
||||
let fra = if let Some('.') = self.peek_one() {
|
||||
self.consume(".")?;
|
||||
let ini_idx = *self.index();
|
||||
let fra = self.parse_u32()? as f32;
|
||||
let end_idx = *self.index();
|
||||
let fra = fra / 10f32.powi((end_idx - ini_idx) as i32);
|
||||
Some(fra)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// F24
|
||||
if let Some(fra) = fra {
|
||||
let sgn = sgn.unwrap_or(1);
|
||||
return Ok(Term::Num { val: Num::F24(sgn as f32 * (num as f32 + fra)) });
|
||||
}
|
||||
|
||||
// I24
|
||||
if let Some(sgn) = sgn {
|
||||
let num = sgn * num as i32;
|
||||
if !(-0x00800000 ..= 0x007fffff).contains(&num) {
|
||||
return self.num_range_err(ini_idx, "I24");
|
||||
}
|
||||
return Ok(Term::Num { val: Num::I24(num) });
|
||||
}
|
||||
|
||||
// U24
|
||||
if num >= 1 << 24 {
|
||||
return self.num_range_err(ini_idx, "U24");
|
||||
}
|
||||
return Ok(Term::Num { val: Num::U24(num) });
|
||||
}
|
||||
|
||||
// Use
|
||||
@ -493,7 +538,7 @@ impl<'a> TermParser<'a> {
|
||||
}
|
||||
}
|
||||
c if c.is_ascii_digit() => {
|
||||
let val = self.parse_u64()?;
|
||||
let val = self.parse_u32()?;
|
||||
if val != expected_num {
|
||||
return self.expected(&expected_num.to_string());
|
||||
}
|
||||
@ -509,6 +554,115 @@ impl<'a> TermParser<'a> {
|
||||
self.consume("}")?;
|
||||
Ok(Term::Swt { arg: Box::new(arg), bnd: Some(bnd), with, pred, arms })
|
||||
}
|
||||
|
||||
fn num_range_err<T>(&mut self, ini_idx: usize, typ: &str) -> Result<T, String> {
|
||||
let ctx = highlight_error(ini_idx, *self.index(), self.input());
|
||||
Err(format!("\x1b[1mNumber literal outside of range for {}.\x1b[0m\n{}", typ, ctx))
|
||||
}
|
||||
|
||||
/* Utils */
|
||||
|
||||
/// Checks if the next characters in the input start with the given string.
|
||||
/// Skips trivia.
|
||||
fn skip_starts_with(&mut self, text: &str) -> bool {
|
||||
self.skip_trivia();
|
||||
self.starts_with(text)
|
||||
}
|
||||
|
||||
fn skip_peek_one(&mut self) -> Option<char> {
|
||||
self.skip_trivia();
|
||||
self.peek_one()
|
||||
}
|
||||
|
||||
/// Parses a list-like structure like "[x1, x2, x3,]".
|
||||
///
|
||||
/// `parser` is a function that parses an element of the list.
|
||||
///
|
||||
/// If `hard_sep` the separator between elements is mandatory.
|
||||
/// Always accepts trailing separators.
|
||||
///
|
||||
/// `min_els` determines how many elements must be parsed at minimum.
|
||||
fn list_like<T>(
|
||||
&mut self,
|
||||
parser: impl Fn(&mut Self) -> Result<T, String>,
|
||||
start: &str,
|
||||
end: &str,
|
||||
sep: &str,
|
||||
hard_sep: bool,
|
||||
min_els: usize,
|
||||
) -> Result<Vec<T>, String> {
|
||||
self.consume(start)?;
|
||||
let mut els = vec![];
|
||||
for i in 0 .. min_els {
|
||||
els.push(parser(self)?);
|
||||
if hard_sep && !(i == min_els - 1 && self.skip_starts_with(end)) {
|
||||
self.consume(sep)?;
|
||||
} else {
|
||||
self.try_consume(sep);
|
||||
}
|
||||
}
|
||||
|
||||
while !self.try_consume(end) {
|
||||
els.push(parser(self)?);
|
||||
if hard_sep && !self.skip_starts_with(end) {
|
||||
self.consume(sep)?;
|
||||
} else {
|
||||
self.try_consume(sep);
|
||||
}
|
||||
}
|
||||
Ok(els)
|
||||
}
|
||||
|
||||
fn labelled<T>(
|
||||
&mut self,
|
||||
parser: impl Fn(&mut Self) -> Result<T, String>,
|
||||
label: &str,
|
||||
) -> Result<T, String> {
|
||||
match parser(self) {
|
||||
Ok(val) => Ok(val),
|
||||
Err(_) => self.expected(label),
|
||||
}
|
||||
}
|
||||
|
||||
fn expected_spanned<T>(&mut self, exp: &str, ini_idx: usize, end_idx: usize) -> Result<T, String> {
|
||||
let ctx = highlight_error(ini_idx, end_idx, self.input());
|
||||
let is_eof = self.is_eof();
|
||||
let detected = DisplayFn(|f| if is_eof { write!(f, " end of input") } else { write!(f, "\n{ctx}") });
|
||||
Err(format!("\x1b[1m- expected:\x1b[0m {}\n\x1b[1m- detected:\x1b[0m{}", exp, detected))
|
||||
}
|
||||
|
||||
/// Consumes text if the input starts with it. Otherwise, do nothing.
|
||||
fn try_consume(&mut self, text: &str) -> bool {
|
||||
self.skip_trivia();
|
||||
if self.starts_with(text) {
|
||||
self.consume(text).unwrap();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_u32(&mut self) -> Result<u32, String> {
|
||||
self.skip_trivia();
|
||||
let radix = match self.peek_many(2) {
|
||||
Some("0x") => {
|
||||
self.advance_many(2);
|
||||
16
|
||||
}
|
||||
Some("0b") => {
|
||||
self.advance_many(2);
|
||||
2
|
||||
}
|
||||
_ => 10,
|
||||
};
|
||||
let num_str = self.take_while(move |c| c.is_digit(radix) || c == '_');
|
||||
let num_str = num_str.chars().filter(|c| *c != '_').collect::<String>();
|
||||
if num_str.is_empty() {
|
||||
self.expected("numeric digit")
|
||||
} else {
|
||||
u32::from_str_radix(&num_str, radix).map_err(|e| e.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> for TermParser<'a> {
|
||||
|
@ -108,8 +108,8 @@ impl<'t, 'l> EncodeTermState<'t, 'l> {
|
||||
Term::Var { nam } => self.link_var(false, nam, up),
|
||||
Term::Lnk { nam } => self.link_var(true, nam, up),
|
||||
Term::Ref { nam } => self.link(up, Place::Tree(LoanedMut::new(Tree::Ref { nam: nam.to_string() }))),
|
||||
Term::Num { typ, val } => {
|
||||
let val = (*val << 4) | (*typ as u32);
|
||||
Term::Num { val } => {
|
||||
let val = val.to_bits();
|
||||
self.link(up, Place::Tree(LoanedMut::new(Tree::Num { val })))
|
||||
}
|
||||
// A lambda becomes to a con node. Ports:
|
||||
@ -170,18 +170,20 @@ impl<'t, 'l> EncodeTermState<'t, 'l> {
|
||||
// Partially apply
|
||||
match (fst.as_ref(), snd.as_ref()) {
|
||||
// Put oper in fst
|
||||
(Term::Num { typ: _, val }, snd) => {
|
||||
let num_val = (*val << 4) | opr.to_native_tag();
|
||||
let fst = Place::Tree(LoanedMut::new(Tree::Num { val: num_val }));
|
||||
(Term::Num { val }, snd) => {
|
||||
let val = val.to_bits();
|
||||
let val = (val & 0xffff_fff0) | opr.to_native_tag();
|
||||
let fst = Place::Tree(LoanedMut::new(Tree::Num { val }));
|
||||
let node = self.new_opr();
|
||||
self.link(fst, node.0);
|
||||
self.encode_term(snd, node.1);
|
||||
self.link(up, node.2);
|
||||
}
|
||||
// Put oper in snd
|
||||
(fst, Term::Num { typ: _, val }) => {
|
||||
let num_val = (*val << 4) | opr.to_native_tag();
|
||||
let snd = Place::Tree(LoanedMut::new(Tree::Num { val: num_val }));
|
||||
(fst, Term::Num { val }) => {
|
||||
let val = val.to_bits();
|
||||
let val = (val & 0xffff_fff0) | opr.to_native_tag();
|
||||
let snd = Place::Tree(LoanedMut::new(Tree::Num { val }));
|
||||
let node = self.new_opr();
|
||||
self.encode_term(fst, node.0);
|
||||
self.link(snd, node.1);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
diagnostics::{Diagnostics, WarningType},
|
||||
term::{builtins, Adts, Constructors, Ctx, Definition, FanKind, Name, NumType, Pattern, Rule, Tag, Term},
|
||||
term::{builtins, Adts, Constructors, Ctx, Definition, FanKind, Name, Num, Pattern, Rule, Tag, Term},
|
||||
};
|
||||
use std::collections::{BTreeSet, HashSet};
|
||||
|
||||
@ -280,7 +280,7 @@ fn num_rule(
|
||||
if let Some(var) = var {
|
||||
body = Term::Use {
|
||||
nam: Some(var.clone()),
|
||||
val: Box::new(Term::Num { typ: NumType::U24, val: *num }),
|
||||
val: Box::new(Term::Num { val: Num::U24(*num) }),
|
||||
nxt: Box::new(std::mem::take(&mut body)),
|
||||
};
|
||||
}
|
||||
@ -301,7 +301,7 @@ fn num_rule(
|
||||
let mut body = rule.body.clone();
|
||||
if let Some(var) = var {
|
||||
let last_num = *nums.last().unwrap();
|
||||
let var_recovered = Term::add_num(Term::Var { nam: pred_var.clone() }, 1 + last_num, NumType::U24);
|
||||
let var_recovered = Term::add_num(Term::Var { nam: pred_var.clone() }, Num::U24(1 + last_num));
|
||||
body = Term::Use { nam: Some(var.clone()), val: Box::new(var_recovered), nxt: Box::new(body) };
|
||||
}
|
||||
let rule = Rule { pats: rule.pats[1 ..].to_vec(), body };
|
||||
@ -319,10 +319,10 @@ fn num_rule(
|
||||
let val = if i > 0 {
|
||||
// switch arg = (pred +1 +num_i-1 - num_i) { 0: body_i; _: acc }
|
||||
// nums[i] >= nums[i-1]+1, so we do a sub here.
|
||||
Term::sub_num(Term::Var { nam: pred_var.clone() }, nums[i] - 1 - nums[i - 1], NumType::U24)
|
||||
Term::sub_num(Term::Var { nam: pred_var.clone() }, Num::U24(nums[i] - 1 - nums[i - 1]))
|
||||
} else {
|
||||
// switch arg = (arg -num_0) { 0: body_0; _: acc}
|
||||
Term::sub_num(Term::Var { nam: arg.clone() }, nums[i], NumType::U24)
|
||||
Term::sub_num(Term::Var { nam: arg.clone() }, Num::U24(nums[i]))
|
||||
};
|
||||
|
||||
Term::Swt {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
diagnostics::{Diagnostics, WarningType, ERR_INDENT_SIZE},
|
||||
maybe_grow,
|
||||
term::{Adts, Constructors, Ctx, MatchRule, Name, NumType, Term},
|
||||
term::{Adts, Constructors, Ctx, MatchRule, Name, Num, Term},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@ -105,9 +105,9 @@ impl Term {
|
||||
let n_nums = arms.len() - 1;
|
||||
for (i, arm) in arms.iter_mut().enumerate() {
|
||||
let orig = if i == n_nums {
|
||||
Term::add_num(Term::Var { nam: pred.clone().unwrap() }, i as u32, NumType::U24)
|
||||
Term::add_num(Term::Var { nam: pred.clone().unwrap() }, Num::U24(i as u32))
|
||||
} else {
|
||||
Term::Num { typ: NumType::U24, val: i as u32 }
|
||||
Term::Num { val: Num::U24(i as u32) }
|
||||
};
|
||||
*arm = Term::Use { nam: bnd.clone(), val: Box::new(orig), nxt: Box::new(std::mem::take(arm)) };
|
||||
}
|
||||
|
1
tests/golden_tests/compile_term/f24_oper.hvm
Normal file
1
tests/golden_tests/compile_term/f24_oper.hvm
Normal file
@ -0,0 +1 @@
|
||||
(/ (* +124.0928 1.24) (+ 0.0 -235.12235))
|
1
tests/golden_tests/compile_term/i24_oper.hvm
Normal file
1
tests/golden_tests/compile_term/i24_oper.hvm
Normal file
@ -0,0 +1 @@
|
||||
(* (+ +1 -1) (- -12 +14))
|
1
tests/golden_tests/compile_term/number_too_large.hvm
Normal file
1
tests/golden_tests/compile_term/number_too_large.hvm
Normal file
@ -0,0 +1 @@
|
||||
0x10000000
|
@ -1 +1 @@
|
||||
(+ 0xFFFF_FFFF (+ 0b101 1_000))
|
||||
(+ 0xFF_FFFF (+ 0b101 1_000))
|
@ -1 +1 @@
|
||||
(+ 0b0123456789 0FA)
|
||||
(+ 0b012345 0FA)
|
7
tests/snapshots/compile_term__f24_oper.hvm.snap
Normal file
7
tests/snapshots/compile_term__f24_oper.hvm.snap
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_term/f24_oper.hvm
|
||||
---
|
||||
b
|
||||
& $(1.240 $(:[/] $(a b))) ~ [*4583519]
|
||||
& $(-235.121 a) ~ [+0]
|
7
tests/snapshots/compile_term__i24_oper.hvm.snap
Normal file
7
tests/snapshots/compile_term__i24_oper.hvm.snap
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_term/i24_oper.hvm
|
||||
---
|
||||
b
|
||||
& $(-1 $(:[*] $(a b))) ~ [+1]
|
||||
& $(+14 a) ~ [-16777204]
|
7
tests/snapshots/compile_term__number_too_large.hvm.snap
Normal file
7
tests/snapshots/compile_term__number_too_large.hvm.snap
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_term/number_too_large.hvm
|
||||
---
|
||||
Errors:
|
||||
[1mNumber literal outside of range for U24.[0m
|
||||
[0m 1 | [4m[31m0x10000000[0m
|
@ -3,5 +3,5 @@ source: tests/golden_tests.rs
|
||||
input_file: tests/golden_tests/compile_term/nums.hvm
|
||||
---
|
||||
b
|
||||
& $(a b) ~ :[+16777215]
|
||||
& $(a b) ~ [+16777215]
|
||||
& $(1000 a) ~ [+5]
|
||||
|
@ -5,4 +5,4 @@ input_file: tests/golden_tests/compile_term/wrong_nums.hvm
|
||||
Errors:
|
||||
[1m- expected:[0m ')'
|
||||
[1m- detected:[0m
|
||||
[0m 1 | (+ 0b0123456789 [4m[31m0[0mFA)[0m
|
||||
[0m 1 | (+ 0b012345 [4m[31m0[0mFA)[0m
|
||||
|
@ -2,4 +2,4 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: examples/bubble_sort.hvm
|
||||
---
|
||||
2721105
|
||||
5525035
|
||||
|
@ -2,4 +2,4 @@
|
||||
source: tests/golden_tests.rs
|
||||
input_file: examples/quick_sort.hvm
|
||||
---
|
||||
7311046
|
||||
12741879
|
||||
|
Loading…
Reference in New Issue
Block a user