aiken/crates/uplc/src/program_builder.rs

111 lines
2.2 KiB
Rust

#![cfg_attr(test, allow(non_snake_case))]
use crate::ast::{Name, Program, Term, Unique};
use std::cell::RefCell;
use std::collections::HashMap;
#[cfg(test)]
mod tests;
mod apply;
mod builtin;
mod constant;
mod delay;
mod error;
mod force;
mod lambda;
mod var;
pub use apply::*;
pub use builtin::*;
pub use constant::*;
pub use delay::*;
pub use error::*;
pub use force::*;
pub use lambda::*;
pub use var::*;
pub struct Builder {
version: (usize, usize, usize),
term: Term<Name>,
}
struct Context {
next_unique: isize,
names: HashMap<String, Unique>,
}
impl Context {
pub fn new() -> Context {
Context {
next_unique: 0,
names: HashMap::new(),
}
}
pub fn get_name(&mut self, name_str: &str) -> Name {
if let Some(unique) = self.names.get(name_str) {
Name {
text: name_str.to_string(),
unique: *unique,
}
} else {
let next_unique = self.next_unique;
self.next_unique = next_unique + 1;
let unique = Unique::new(next_unique);
self.names.insert(name_str.to_string(), unique);
Name {
text: name_str.to_string(),
unique,
}
}
}
}
pub struct Core {
version: (usize, usize, usize),
ctx: RefCell<Context>,
}
pub trait WithTerm
where
Self: Sized,
{
type Next;
fn next(self, term: Term<Name>) -> Self::Next;
fn get_name(&self, name_str: &str) -> Name;
}
impl WithTerm for Core {
type Next = Builder;
fn next(self, term: Term<Name>) -> Self::Next {
Builder {
version: self.version,
term,
}
}
fn get_name(&self, name_str: &str) -> Name {
let mut ctx = self.ctx.borrow_mut();
ctx.get_name(name_str)
}
}
impl Builder {
/// Max: `9223372036854775807`
pub fn start(maj: usize, min: usize, patch: usize) -> Core {
Core {
version: (maj, min, patch),
ctx: RefCell::new(Context::new()),
}
}
pub fn build_named(&self) -> Program<Name> {
Program {
version: self.version,
term: self.term.clone(),
}
}
}