feat: rename to aiken and add e2e tests for uplc
This commit is contained in:
parent
1ef116fcda
commit
984c253f31
|
@ -1,2 +1 @@
|
|||
/target
|
||||
*.flat
|
||||
/target
|
|
@ -3,12 +3,12 @@
|
|||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
|
||||
name = "aiken"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"const-random",
|
||||
"anyhow",
|
||||
"clap",
|
||||
"uplc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -40,21 +40,6 @@ version = "1.3.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chumsky"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.18"
|
||||
|
@ -94,53 +79,14 @@ dependencies = [
|
|||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"lazy_static",
|
||||
"proc-macro-hack",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "flat"
|
||||
version = "0.0.0"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
|
@ -190,15 +136,6 @@ version = "0.2.126"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "neptune"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"uplc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.0.1"
|
||||
|
@ -256,12 +193,6 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.39"
|
||||
|
@ -357,15 +288,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.0"
|
||||
|
@ -374,9 +296,8 @@ checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
|
|||
|
||||
[[package]]
|
||||
name = "uplc"
|
||||
version = "0.1.0"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"chumsky",
|
||||
"flat",
|
||||
"hex",
|
||||
"peg",
|
||||
|
@ -391,12 +312,6 @@ version = "0.9.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
13
README.md
13
README.md
|
@ -1,22 +1,23 @@
|
|||
# Neptune
|
||||
# AIKEN
|
||||
|
||||
Experiments with Plutus Core
|
||||
A cardano smart contract language and toolchain
|
||||
|
||||
## Roadmap
|
||||
|
||||
These are generic milestones and the listed ordering
|
||||
is not necessariy the implementation order
|
||||
is not necessariy the implementation order or full scope.
|
||||
|
||||
- [ ] compile plutus core into it's on chain encoding
|
||||
- [ ] reverse the on chain encoding into plutus core
|
||||
- [x] compile plutus core into it's on chain encoding
|
||||
- [x] reverse the on chain encoding into plutus core
|
||||
- [ ] Plutus Core interpreter
|
||||
- [ ] create a higher level syntax with inspiration from
|
||||
- JS
|
||||
- ReasonML
|
||||
- Elm
|
||||
- Roc
|
||||
- Rust
|
||||
- Gleam
|
||||
- [ ] Language Server
|
||||
- [ ] Plutus Core interpreter
|
||||
|
||||
## Resources
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "neptune"
|
||||
version = "0.0.0"
|
||||
name = "aiken"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -12,8 +12,16 @@ pub enum Cli {
|
|||
|
||||
#[derive(Subcommand)]
|
||||
pub enum UplcCommand {
|
||||
Flat { input: PathBuf },
|
||||
Unflat { input: PathBuf },
|
||||
Flat {
|
||||
input: PathBuf,
|
||||
#[clap(short, long)]
|
||||
print: bool,
|
||||
},
|
||||
Unflat {
|
||||
input: PathBuf,
|
||||
#[clap(short, long)]
|
||||
print: bool,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for Cli {
|
||||
|
|
|
@ -3,14 +3,14 @@ use uplc::{
|
|||
parser,
|
||||
};
|
||||
|
||||
use neptune::{Cli, UplcCommand};
|
||||
use aiken::{Cli, UplcCommand};
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let args = Cli::default();
|
||||
|
||||
match args {
|
||||
Cli::Uplc(uplc) => match uplc {
|
||||
UplcCommand::Flat { input } => {
|
||||
UplcCommand::Flat { input, print } => {
|
||||
let code = std::fs::read_to_string(&input)?;
|
||||
|
||||
let program = parser::program(&code)?;
|
||||
|
@ -19,26 +19,28 @@ fn main() -> anyhow::Result<()> {
|
|||
|
||||
let bytes = program.to_flat()?;
|
||||
|
||||
for (i, byte) in bytes.iter().enumerate() {
|
||||
print!("{:08b}", byte);
|
||||
if print {
|
||||
for (i, byte) in bytes.iter().enumerate() {
|
||||
print!("{:08b}", byte);
|
||||
|
||||
if (i + 1) % 4 == 0 {
|
||||
println!();
|
||||
} else {
|
||||
print!(" ");
|
||||
if (i + 1) % 4 == 0 {
|
||||
println!();
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!();
|
||||
println!();
|
||||
}
|
||||
}
|
||||
UplcCommand::Unflat { input } => {
|
||||
UplcCommand::Unflat { input, print } => {
|
||||
let bytes = std::fs::read(&input)?;
|
||||
|
||||
let program = Program::<FakeNamedDeBruijn>::from_flat(&bytes)?;
|
||||
|
||||
let encoded_flat = program.to_flat()?;
|
||||
println!("{}", encoded_flat.len());
|
||||
assert!(bytes == encoded_flat)
|
||||
if print {
|
||||
println!("{:#?}", program);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "flat"
|
||||
version = "0.0.0"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
[package]
|
||||
name = "uplc"
|
||||
version = "0.1.0"
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
chumsky = "0.8.0"
|
||||
flat = { path = "../flat" }
|
||||
hex = "0.4.3"
|
||||
peg = "0.8.0"
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
(program 11.22.33
|
||||
[
|
||||
(
|
||||
lam x (lam x x)) (con string "PT8"
|
||||
)
|
||||
]
|
||||
)
|
|
@ -1,7 +1,8 @@
|
|||
#![recursion_limit = "10000"]
|
||||
|
||||
pub mod ast;
|
||||
pub mod builtins;
|
||||
mod debruijn;
|
||||
mod flat;
|
||||
pub mod parser;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
||||
|
|
|
@ -1,20 +1,31 @@
|
|||
use std::{collections::HashMap, str::FromStr};
|
||||
|
||||
use chumsky::{
|
||||
prelude::{end, filter, just, recursive, Simple},
|
||||
text::{ident, int, keyword, TextParser},
|
||||
Parser,
|
||||
};
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::{
|
||||
ast::{Constant, Name, Program, Term, Unique},
|
||||
ast::{Constant, Name, Program, Term},
|
||||
builtins::DefaultFunction,
|
||||
};
|
||||
|
||||
use interner::Interner;
|
||||
use peg::{error::ParseError, str::LineCol};
|
||||
|
||||
mod interner;
|
||||
|
||||
pub fn program(src: &str) -> Result<Program<Name>, ParseError<LineCol>> {
|
||||
let mut interner = Interner::new();
|
||||
|
||||
let mut program = uplc::program(src)?;
|
||||
|
||||
interner.program(&mut program);
|
||||
|
||||
Ok(program)
|
||||
}
|
||||
|
||||
peg::parser! {
|
||||
grammar parser() for str {
|
||||
grammar uplc() for str {
|
||||
pub rule program() -> Program<Name>
|
||||
= "(" _* "program" _+ v:version() _+ t:term() _* ")" { Program {version: v, term: t} }
|
||||
= _* "(" _* "program" _+ v:version() _+ t:term() _* ")" _* {
|
||||
Program {version: v, term: t}
|
||||
}
|
||||
|
||||
rule version() -> (usize, usize, usize)
|
||||
= major:number() "." minor:number() "." patch:number() {
|
||||
|
@ -43,7 +54,9 @@ peg::parser! {
|
|||
}
|
||||
|
||||
rule builtin() -> Term<Name>
|
||||
= "(" _* "builtin" _+ b:ident() _* ")" { Term::Builtin(DefaultFunction::from_str(&b).unwrap()) }
|
||||
= "(" _* "builtin" _+ b:ident() _* ")" {
|
||||
Term::Builtin(DefaultFunction::from_str(&b).unwrap())
|
||||
}
|
||||
|
||||
rule var() -> Term<Name>
|
||||
= n:name() { Term::Var(n) }
|
||||
|
@ -77,7 +90,9 @@ peg::parser! {
|
|||
= "integer" _+ i:number() { Constant::Integer(i as isize) }
|
||||
|
||||
rule constant_bytestring() -> Constant
|
||||
= "bytestring" _+ "#" i:ident()* { Constant::ByteString(hex::decode(String::from_iter(i)).unwrap()) }
|
||||
= "bytestring" _+ "#" i:ident()* {
|
||||
Constant::ByteString(hex::decode(String::from_iter(i)).unwrap())
|
||||
}
|
||||
|
||||
rule constant_string() -> Constant
|
||||
= "string" _+ "\"" s:[^ '"']* "\"" { Constant::String(String::from_iter(s)) }
|
||||
|
@ -94,195 +109,19 @@ peg::parser! {
|
|||
rule name() -> Name
|
||||
= text:ident() { Name { text, unique: 0.into() } }
|
||||
|
||||
rule ident() -> String = i:['a'..='z' | 'A'..='Z' | '0'..='9' | '_']+ { String::from_iter(i) }
|
||||
rule ident() -> String
|
||||
= i:['a'..='z' | 'A'..='Z' | '0'..='9' | '_']+ {
|
||||
String::from_iter(i)
|
||||
}
|
||||
|
||||
rule _ = [' ' | '\n']
|
||||
}
|
||||
}
|
||||
|
||||
struct ParserState {
|
||||
identifiers: HashMap<String, Unique>,
|
||||
current: Unique,
|
||||
}
|
||||
|
||||
impl ParserState {
|
||||
fn new() -> Self {
|
||||
ParserState {
|
||||
identifiers: HashMap::new(),
|
||||
current: Unique::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn intern(&mut self, text: &str) -> Unique {
|
||||
if let Some(u) = self.identifiers.get(text) {
|
||||
*u
|
||||
} else {
|
||||
let unique = self.current;
|
||||
|
||||
self.identifiers.insert(text.to_string(), unique);
|
||||
|
||||
self.current.increment();
|
||||
|
||||
unique
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn program(src: &str) -> Result<Program<Name>, peg::error::ParseError<peg::str::LineCol>> {
|
||||
parser::program(src)
|
||||
}
|
||||
|
||||
fn program_() -> impl Parser<char, Program<Name>, Error = Simple<char>> {
|
||||
keyword("program")
|
||||
.ignore_then(version().padded())
|
||||
.then(term())
|
||||
.map(|(version, term)| Program { version, term })
|
||||
.delimited_by(just('(').padded(), just(')').padded())
|
||||
.then_ignore(end())
|
||||
}
|
||||
|
||||
fn version() -> impl Parser<char, (usize, usize, usize), Error = Simple<char>> {
|
||||
int(10)
|
||||
.then_ignore(just('.'))
|
||||
.then(int(10))
|
||||
.then_ignore(just('.'))
|
||||
.then(int(10))
|
||||
.map(|((major, minor), patch)| {
|
||||
(
|
||||
major.parse::<usize>().unwrap(),
|
||||
minor.parse::<usize>().unwrap(),
|
||||
patch.parse::<usize>().unwrap(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn term() -> impl Parser<char, Term<Name>, Error = Simple<char>> {
|
||||
recursive(|term| {
|
||||
let delay = keyword("delay")
|
||||
.ignore_then(term.clone().padded())
|
||||
.delimited_by(just('(').padded(), just(')').padded())
|
||||
.map(|t| dbg!(Term::Delay(Box::new(t))));
|
||||
|
||||
let force = keyword("force")
|
||||
.ignore_then(term.clone().padded())
|
||||
.delimited_by(just('(').padded(), just(')').padded())
|
||||
.map(|t| dbg!(Term::Force(Box::new(t))));
|
||||
|
||||
let lambda = keyword("lam")
|
||||
.ignore_then(name().padded())
|
||||
.then(term.clone())
|
||||
.delimited_by(just('(').padded(), just(')').padded())
|
||||
.map(|(parameter_name, t)| {
|
||||
dbg!(Term::Lambda {
|
||||
parameter_name,
|
||||
body: Box::new(t),
|
||||
})
|
||||
});
|
||||
|
||||
let apply = term
|
||||
.clone()
|
||||
.padded()
|
||||
.then(term.clone().padded().repeated())
|
||||
.delimited_by(just('[').padded(), just(']').padded())
|
||||
.foldl(|lhs, rhs| Term::Apply {
|
||||
function: Box::new(lhs),
|
||||
argument: Box::new(rhs),
|
||||
});
|
||||
|
||||
constant()
|
||||
.or(builtin())
|
||||
.or(var())
|
||||
.or(lambda)
|
||||
.or(apply)
|
||||
.or(delay)
|
||||
.or(force)
|
||||
.or(error())
|
||||
})
|
||||
}
|
||||
|
||||
fn constant() -> impl Parser<char, Term<Name>, Error = Simple<char>> {
|
||||
keyword("con")
|
||||
.ignore_then(
|
||||
constant_integer()
|
||||
.or(constant_bytestring())
|
||||
.or(constant_string())
|
||||
.or(constant_unit())
|
||||
.or(constant_bool()),
|
||||
)
|
||||
.delimited_by(just('(').padded(), just(')').padded())
|
||||
.map(Term::Constant)
|
||||
}
|
||||
|
||||
fn builtin() -> impl Parser<char, Term<Name>, Error = Simple<char>> {
|
||||
keyword("builtin")
|
||||
.ignore_then(ident().padded())
|
||||
.delimited_by(just('(').padded(), just(')').padded())
|
||||
.map(|builtin_name: String| {
|
||||
Term::Builtin(DefaultFunction::from_str(&builtin_name).unwrap())
|
||||
})
|
||||
}
|
||||
|
||||
fn var() -> impl Parser<char, Term<Name>, Error = Simple<char>> {
|
||||
name().map(Term::Var)
|
||||
}
|
||||
|
||||
fn error() -> impl Parser<char, Term<Name>, Error = Simple<char>> {
|
||||
keyword("error")
|
||||
.ignored()
|
||||
.delimited_by(just('(').padded(), just(')').padded())
|
||||
.map(|_| Term::Error)
|
||||
}
|
||||
|
||||
fn name() -> impl Parser<char, Name, Error = Simple<char>> {
|
||||
ident().map(|text| Name {
|
||||
text,
|
||||
unique: 0.into(),
|
||||
})
|
||||
}
|
||||
|
||||
fn constant_integer() -> impl Parser<char, Constant, Error = Simple<char>> {
|
||||
keyword("integer")
|
||||
.padded()
|
||||
.ignore_then(int(10))
|
||||
.map(|d: String| Constant::Integer(d.parse::<isize>().unwrap()))
|
||||
}
|
||||
|
||||
fn constant_bytestring() -> impl Parser<char, Constant, Error = Simple<char>> {
|
||||
keyword("bytestring")
|
||||
.padded()
|
||||
.ignore_then(just('#'))
|
||||
.ignore_then(int(16))
|
||||
.map(|b: String| Constant::ByteString(hex::decode(b).unwrap()))
|
||||
}
|
||||
|
||||
fn constant_string() -> impl Parser<char, Constant, Error = Simple<char>> {
|
||||
keyword("string")
|
||||
.padded()
|
||||
.ignore_then(just('"'))
|
||||
.ignore_then(filter(|c| *c != '"').repeated())
|
||||
.then_ignore(just('"'))
|
||||
.collect::<String>()
|
||||
.map(Constant::String)
|
||||
}
|
||||
|
||||
fn constant_unit() -> impl Parser<char, Constant, Error = Simple<char>> {
|
||||
keyword("unit")
|
||||
.padded()
|
||||
.ignore_then(just('('))
|
||||
.ignore_then(just(')'))
|
||||
.ignored()
|
||||
.map(|_| Constant::Unit)
|
||||
}
|
||||
|
||||
fn constant_bool() -> impl Parser<char, Constant, Error = Simple<char>> {
|
||||
keyword("bool")
|
||||
.padded()
|
||||
.ignore_then(just("True").or(just("False")))
|
||||
.map(|b| Constant::Bool(b == "True"))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::ast::{Constant, Name, Program, Term};
|
||||
|
||||
#[test]
|
||||
fn parse_program() {
|
||||
let code = r#"
|
||||
|
@ -290,12 +129,14 @@ mod test {
|
|||
(con integer 11)
|
||||
)
|
||||
"#;
|
||||
let result = super::program(code);
|
||||
let program = super::program(code).unwrap();
|
||||
|
||||
assert!(result.is_ok());
|
||||
|
||||
let program = result.unwrap();
|
||||
|
||||
assert_eq!(program.version, (11, 22, 33));
|
||||
assert_eq!(
|
||||
program,
|
||||
Program::<Name> {
|
||||
version: (11, 22, 33),
|
||||
term: Term::Constant(Constant::Integer(11)),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::ast::{Name, Program, Term, Unique};
|
||||
|
||||
pub struct Interner {
|
||||
identifiers: HashMap<String, Unique>,
|
||||
current: Unique,
|
||||
}
|
||||
|
||||
impl Interner {
|
||||
pub fn new() -> Self {
|
||||
Interner {
|
||||
identifiers: HashMap::new(),
|
||||
current: Unique::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn program(&mut self, program: &mut Program<Name>) {
|
||||
self.term(&mut program.term);
|
||||
}
|
||||
|
||||
pub fn term(&mut self, term: &mut Term<Name>) {
|
||||
match term {
|
||||
Term::Var(name) => name.unique = self.intern(&name.text),
|
||||
Term::Delay(term) => self.term(term),
|
||||
Term::Lambda {
|
||||
parameter_name,
|
||||
body,
|
||||
} => {
|
||||
parameter_name.unique = self.intern(¶meter_name.text);
|
||||
self.term(body);
|
||||
}
|
||||
Term::Apply { function, argument } => {
|
||||
self.term(function);
|
||||
self.term(argument);
|
||||
}
|
||||
Term::Constant(_) => (),
|
||||
Term::Force(term) => self.term(term),
|
||||
Term::Error => (),
|
||||
Term::Builtin(_) => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn intern(&mut self, text: &str) -> Unique {
|
||||
if let Some(u) = self.identifiers.get(text) {
|
||||
*u
|
||||
} else {
|
||||
let unique = self.current;
|
||||
|
||||
self.identifiers.insert(text.to_string(), unique);
|
||||
|
||||
self.current.increment();
|
||||
|
||||
unique
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// e2e encoding/decoding tests
|
||||
use crate::{
|
||||
ast::{DeBruijn, Program},
|
||||
parser,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn integer() {
|
||||
let bytes = include_bytes!("../test_data/basic/integer/integer.flat");
|
||||
let code = include_str!("../test_data/basic/integer/integer.uplc");
|
||||
|
||||
let parsed_program = parser::program(code).unwrap();
|
||||
|
||||
let debruijn_program: Program<DeBruijn> = parsed_program.try_into().unwrap();
|
||||
|
||||
let decoded_program: Program<DeBruijn> = Program::from_flat(bytes).unwrap();
|
||||
|
||||
assert_eq!(debruijn_program, decoded_program);
|
||||
|
||||
let encoded_program = debruijn_program.to_flat().unwrap();
|
||||
|
||||
assert_eq!(encoded_program, bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jpg() {
|
||||
let bytes = include_bytes!("../test_data/jpg/jpg.flat");
|
||||
let code = include_str!("../test_data/jpg/jpg.uplc");
|
||||
|
||||
let parsed_program = parser::program(code).unwrap();
|
||||
|
||||
let debruijn_program: Program<DeBruijn> = parsed_program.try_into().unwrap();
|
||||
|
||||
let decoded_program: Program<DeBruijn> = Program::from_flat(bytes).unwrap();
|
||||
|
||||
assert_eq!(debruijn_program, decoded_program);
|
||||
|
||||
let encoded_program = debruijn_program.to_flat().unwrap();
|
||||
|
||||
assert_eq!(encoded_program, bytes);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
!H<05>
|
|
@ -0,0 +1,3 @@
|
|||
(program 11.22.33
|
||||
(con integer 11)
|
||||
)
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue