Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jcb/nom and syntax #383

Merged
merged 3 commits into from
May 2, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -39,6 +39,8 @@ num-bigint = "0.4.3"
num-integer = "0.1.45"
num-traits = "0.2.15"
nom = "7.1.3"
nom_locate = "4.1.0"
base-x = "0.2.11"
clap = "4.1.8"
tap = "1.0.1"
stable_deref_trait = "1.1.1"
4 changes: 2 additions & 2 deletions src/circuit/circuit_frame.rs
Original file line number Diff line number Diff line change
@@ -1413,7 +1413,7 @@ fn reduce_cons<F: LurkField, CS: ConstraintSystem<F>, C: Coprocessor<F>>(
let mut head_is_coprocessor_bools = Vec::with_capacity(lang.coprocessors().len());

for (sym, (_coproc, scalar_ptr)) in lang.coprocessors().iter() {
let cs = &mut cs.namespace(|| format!("head is {}", sym.full_name()));
let cs = &mut cs.namespace(|| format!("head is {}", sym));

let allocated_boolean = head.alloc_hash_equal(cs, *scalar_ptr.value())?;

@@ -2636,7 +2636,7 @@ fn reduce_cons<F: LurkField, CS: ConstraintSystem<F>, C: Coprocessor<F>>(
)?;

for (sym, (coproc, scalar_ptr)) in lang.coprocessors().iter() {
let cs = &mut cs.namespace(|| format!("{} coprocessor", sym.full_name()));
let cs = &mut cs.namespace(|| format!("{} coprocessor", sym));

let arity = coproc.arity();

10 changes: 5 additions & 5 deletions src/eval/lang.rs
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ use crate::coprocessor::{CoCircuit, Coprocessor};
use crate::field::LurkField;
use crate::ptr::Ptr;
use crate::store::Store;
use crate::sym::Sym;
use crate::symbol::Symbol;
use crate::z_ptr::ZExprPtr;

/// `DummyCoprocessor` is a concrete implementation of the [`crate::coprocessor::Coprocessor`] trait.
@@ -114,7 +114,7 @@ impl<F: LurkField> CoCircuit<F> for Coproc<F> {
#[derive(Debug, Default, Clone)]
pub struct Lang<F: LurkField, C: Coprocessor<F>> {
// A HashMap that stores coprocessors with their associated `Sym` keys.
coprocessors: HashMap<Sym, (C, ZExprPtr<F>)>,
coprocessors: HashMap<Symbol, (C, ZExprPtr<F>)>,
}

impl<F: LurkField, C: Coprocessor<F>> Lang<F, C> {
@@ -124,14 +124,14 @@ impl<F: LurkField, C: Coprocessor<F>> Lang<F, C> {
}
}

pub fn add_coprocessor(&mut self, name: Sym, cproc: C, store: &mut Store<F>) {
let ptr = store.intern_sym(name.clone());
pub fn add_coprocessor(&mut self, name: Symbol, cproc: C, store: &mut Store<F>) {
let ptr = store.intern_symbol(name.clone());
let scalar_ptr = store.hash_expr(&ptr).unwrap();

self.coprocessors.insert(name, (cproc, scalar_ptr));
}

pub fn coprocessors(&self) -> &HashMap<Sym, (C, ZExprPtr<F>)> {
pub fn coprocessors(&self) -> &HashMap<Symbol, (C, ZExprPtr<F>)> {
&self.coprocessors
}

18 changes: 9 additions & 9 deletions src/eval/reduction.rs
Original file line number Diff line number Diff line change
@@ -7,9 +7,9 @@ use crate::expr::{Expression, Thunk};
use crate::field::LurkField;
use crate::hash_witness::{ConsName, ConsWitness, ContName, ContWitness};
use crate::num::Num;
use crate::ptr::{ContPtr, Ptr};
use crate::ptr::{ContPtr, Ptr, TypePredicates};
use crate::store;
use crate::store::{NamedConstants, Store, TypePredicates};
use crate::store::{NamedConstants, Store};
use crate::tag::{ContTag, ExprTag, Op1, Op2};
use crate::writer::Write;

@@ -916,7 +916,7 @@ fn apply_continuation<F: LurkField>(
.hash_expr(&result)
.ok_or_else(|| store::Error("expr hash missing".into()))?;

store.get_u64(scalar_ptr.value().to_u64_unchecked())
store.intern_u64(scalar_ptr.value().to_u64_unchecked())
}
ExprTag::U64 => result,
_ => return Ok(Control::Error(result, env)),
@@ -935,7 +935,7 @@ fn apply_continuation<F: LurkField>(
let scalar_ptr = store
.hash_expr(&result)
.ok_or_else(|| store::Error("expr hash missing".into()))?;
store.get_char_from_u32(scalar_ptr.value().to_u32_unchecked())
store.intern_char(scalar_ptr.value().to_char().unwrap())
}
_ => return Ok(Control::Error(result, env)),
},
@@ -1062,9 +1062,9 @@ fn apply_continuation<F: LurkField>(
}
(Expression::UInt(a), Expression::UInt(b)) if operator.is_numeric() => {
match operator {
Op2::Sum => store.get_u64((a + b).into()),
Op2::Diff => store.get_u64((a - b).into()),
Op2::Product => store.get_u64((a * b).into()),
Op2::Sum => store.intern_u64((a + b).into()),
Op2::Diff => store.intern_u64((a - b).into()),
Op2::Product => store.intern_u64((a * b).into()),
Op2::Quotient => {
if b.is_zero() {
return Ok(Control::Return(
@@ -1073,7 +1073,7 @@ fn apply_continuation<F: LurkField>(
store.intern_cont_error(),
));
} else {
store.get_u64((a / b).into())
store.intern_u64((a / b).into())
}
}
Op2::Modulo => {
@@ -1084,7 +1084,7 @@ fn apply_continuation<F: LurkField>(
store.intern_cont_error(),
));
} else {
store.get_u64((a % b).into())
store.intern_u64((a % b).into())
}
}
Op2::Equal | Op2::NumEqual => store.as_lurk_boolean(a == b),
7 changes: 4 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -14,13 +14,14 @@ pub mod expr;
pub mod field;
pub mod hash;
pub mod hash_witness;
pub mod package;
//pub mod package;
pub mod parser;
pub mod proof;
pub mod ptr;
pub mod repl;
pub mod store;
pub mod sym;
pub mod symbol;
pub mod syntax;
pub mod tag;
pub mod uint;
pub mod writer;
@@ -33,7 +34,7 @@ pub mod z_store;
pub mod error;
mod num;
pub use num::Num;
pub use sym::{Sym, Symbol};
pub use symbol::Symbol;
pub use uint::UInt;

pub const TEST_SEED: [u8; 16] = [
31 changes: 18 additions & 13 deletions src/num.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@ use std::{
ops::{AddAssign, DivAssign, MulAssign, SubAssign},
};

#[cfg(not(target_arch = "wasm32"))]
use proptest::prelude::*;

use crate::field::LurkField;
use crate::uint::UInt;

@@ -24,6 +27,21 @@ pub enum Num<F: LurkField> {
U64(u64),
}

#[cfg(not(target_arch = "wasm32"))]
impl<Fr: LurkField> Arbitrary for Num<Fr> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
any::<FWrap<Fr>>()
.prop_map(|f| match f.0.to_u64() {
Some(x) => Self::U64(x),
None => Self::Scalar(f.0),
})
.boxed()
}
}

impl<F: LurkField> Copy for Num<F> {}

impl<F: LurkField> Display for Num<F> {
@@ -281,19 +299,6 @@ mod tests {
use blstrs::Scalar as Fr;
use ff::Field;

impl<Fr: LurkField> Arbitrary for Num<Fr> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
prop_oneof!(
any::<u64>().prop_map(Num::U64),
any::<FWrap<Fr>>().prop_map(|f| Num::Scalar(f.0)),
)
.boxed()
}
}

//proptest! {
// #[test]
// fn prop_num_ipld(x in any::<Num<Fr>>()) {
28 changes: 14 additions & 14 deletions src/package.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::collections::HashSet;

use crate::sym::Sym;
use crate::symbol::Symbol;

#[derive(Clone, Debug)]
pub struct Package {
pub name: Sym,
pub external_symbols: HashSet<Sym>,
pub name: Symbol,
pub external_symbols: HashSet<Symbol>,
}

pub const LURK_EXTERNAL_SYMBOL_NAMES: &[&str] = &[
@@ -48,18 +48,18 @@ pub const LURK_EXTERNAL_SYMBOL_NAMES: &[&str] = &[
];

impl Package {
pub fn new(name: Sym) -> Self {
pub fn new(name: Symbol) -> Self {
Self {
name,
external_symbols: Default::default(),
}
}

pub fn root() -> Self {
Self::new(Sym::root())
Self::new(Symbol::root())
}

pub fn name(&self) -> &Sym {
pub fn name(&self) -> &Symbol {
&self.name
}

@@ -79,44 +79,44 @@ impl Package {
}
}

pub fn remove_external_symbol(&mut self, sym: &Sym) {
pub fn remove_external_symbol(&mut self, sym: &Symbol) {
self.external_symbols.remove(sym);
}

pub fn remove_external_symbols(&mut self, syms: &[Sym]) {
pub fn remove_external_symbols(&mut self, syms: &[Symbol]) {
for sym in syms.iter() {
self.external_symbols.remove(sym);
}
}

pub fn local_symbol(&self, sym: &Sym) -> Option<&Sym> {
pub fn local_symbol(&self, sym: &Symbol) -> Option<&Symbol> {
self.external_symbols.get(sym)
}

pub fn relative_abbreviation(&self, sym: &Sym) -> Sym {
pub fn relative_abbreviation(&self, sym: &Symbol) -> Symbol {
let name = &self.name;
let name_path = name.path();
let sym_path = sym.path();

if sym.is_keyword() != name.is_keyword() {
if sym.is_key() != name.is_key() {
return sym.clone();
}

if sym_path.len() < name_path.len() {
return sym.clone();
}

let name_is_prefix = sym_path.iter().zip(name.path()).all(|(a, b)| a == b);
let name_is_prefix = sym_path.iter().zip(name.path()).all(|(a, b)| *a == b);

if name_is_prefix && sym_path != name_path {
Sym::new_from_path(false, sym_path[name_path.len()..].to_vec())
Symbol::Sym(sym_path[name_path.len()..].to_vec())
} else {
sym.clone()
}
}

pub fn lurk() -> Self {
let lurk_sym = Sym::new_from_path(false, vec!["".into(), "LURK".into()]);
let lurk_sym = Symbol::new(vec!["LURK"]);
let mut package = Package::new(lurk_sym);

package.add_external_symbols(LURK_EXTERNAL_SYMBOL_NAMES);
2,489 changes: 1,255 additions & 1,234 deletions src/parser.rs

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions src/parser/position.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use crate::parser::Span;
#[cfg(not(target_arch = "wasm32"))]
use proptest::prelude::*;

/// Source code position of an expression in a file
#[derive(Clone, Copy, Debug)]
pub enum Pos {
No,
Pos {
from_offset: usize,
from_line: usize,
from_column: usize,
upto_offset: usize,
upto_line: usize,
upto_column: usize,
},
}

impl PartialEq for Pos {
fn eq(&self, other: &Self) -> bool {
true
}
}

impl Eq for Pos {}

#[cfg(not(target_arch = "wasm32"))]
impl Arbitrary for Pos {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
any::<()>().prop_map(|_| Pos::No).boxed()
}
}

impl Pos {
/// Use the range information in a Position to pretty-print that range within
/// a string
pub fn range(
input: String,
from_line: usize,
from_column: usize,
upto_line: usize,
upto_column: usize,
) -> String {
let mut res = String::new();
let gutter = format!("{}", upto_line).len();
let pad = format!("{: >gutter$}", from_line, gutter = gutter).len() + 3 + from_column;
res.push_str(&format!("{}▼\n", " ".to_owned().repeat(pad)));
for (line_number, line) in input.lines().enumerate() {
if ((line_number + 1) >= from_line) && ((line_number + 1) <= upto_line) {
res.push_str(&format!(
"{: >gutter$} | {}\n",
line_number + 1,
line,
gutter = gutter
));
}
}
let pad = format!("{: >gutter$}", upto_line, gutter = gutter).len() + 3 + upto_column;
res.push_str(&format!("{}▲", " ".to_owned().repeat(pad)));
res
}

/// Construct a position from the difference of two Spans
pub fn from_upto(from: Span, upto: Span) -> Self {
Self::Pos {
from_offset: from.location_offset(),
from_line: from.location_line() as usize,
from_column: from.get_utf8_column(),
upto_offset: (upto.location_offset()),
upto_line: upto.location_line() as usize,
upto_column: upto.get_utf8_column(),
}
}
}

// impl fmt::Display for Position {
// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// write!(
// f,
// "{}@{}:{}-{}:{}",
// self.input, self.from_line, self.from_column, self.upto_line,
// self.upto_column )
// }
//}
18 changes: 18 additions & 0 deletions src/ptr.rs
Original file line number Diff line number Diff line change
@@ -185,3 +185,21 @@ impl<F: LurkField> ContPtr<F> {
}
}
}

pub trait TypePredicates {
fn is_fun(&self) -> bool;
fn is_self_evaluating(&self) -> bool;
fn is_potentially(&self, tag: ExprTag) -> bool;
}

impl<F: LurkField> TypePredicates for Ptr<F> {
fn is_fun(&self) -> bool {
self.tag.is_fun()
}
fn is_self_evaluating(&self) -> bool {
self.tag.is_self_evaluating()
}
fn is_potentially(&self, tag: ExprTag) -> bool {
self.tag.is_potentially(tag)
}
}
61 changes: 24 additions & 37 deletions src/repl.rs
Original file line number Diff line number Diff line change
@@ -3,11 +3,10 @@ use crate::error::LurkError;
use crate::eval::{empty_sym_env, lang::Lang, Evaluator, IO};
use crate::expr::Expression;
use crate::field::LurkField;
use crate::package::Package;
use crate::parser;
use crate::ptr::{ContPtr, Ptr};
use crate::store::Store;
use crate::sym::Sym;
use crate::symbol::Symbol;
use crate::tag::ContTag;
use crate::writer::Write;
use crate::z_data::{Encodable, ZData};
@@ -72,34 +71,27 @@ pub trait ReplTrait<F: LurkField, C: Coprocessor<F>> {
&mut self,
store: &mut Store<F>,
chars: &mut peekmore::PeekMoreIterator<T>,
package: &Package,
pwd: P,
) -> Result<()> {
let (ptr, is_meta) = store.read_maybe_meta(chars, package)?;
let (ptr, is_meta) = store.read_maybe_meta(chars)?;

if is_meta {
let pwd: &Path = pwd.as_ref();
self.handle_meta(store, ptr, package, pwd)
self.handle_meta(store, ptr, pwd)
} else {
self.handle_non_meta(store, ptr).map(|_| ())
}
}

fn handle_load<P: AsRef<Path>>(
&mut self,
store: &mut Store<F>,
file_path: P,
package: &Package,
) -> Result<()> {
fn handle_load<P: AsRef<Path>>(&mut self, store: &mut Store<F>, file_path: P) -> Result<()> {
eprintln!("Loading from {}.", file_path.as_ref().to_str().unwrap());
self.handle_file(store, file_path.as_ref(), package)
self.handle_file(store, file_path.as_ref())
}

fn handle_file<P: AsRef<Path> + Copy>(
&mut self,
store: &mut Store<F>,
file_path: P,
package: &Package,
) -> Result<()> {
let file_path = file_path;

@@ -115,7 +107,6 @@ pub trait ReplTrait<F: LurkField, C: Coprocessor<F>> {
if let Err(e) = self.handle_form(
store,
&mut chars,
package,
// use this file's dir as pwd for further loading
file_path.as_ref().parent().unwrap(),
) {
@@ -133,7 +124,6 @@ pub trait ReplTrait<F: LurkField, C: Coprocessor<F>> {
&mut self,
store: &mut Store<F>,
expr_ptr: Ptr<F>,
package: &Package,
p: P,
) -> Result<()>;

@@ -238,16 +228,14 @@ pub fn run_repl<P: AsRef<Path>, F: LurkField, T: ReplTrait<F, C>, C: Coprocessor
mut repl: Repl<F, T, C>,
lurk_file: Option<P>,
) -> Result<()> {
let package = Package::lurk();

if lurk_file.is_none() {
let name = T::name();
eprintln!("{name} welcomes you.");
}

{
if let Some(lurk_file) = lurk_file {
repl.state.handle_load(s, &lurk_file, &package).unwrap();
repl.state.handle_load(s, &lurk_file).unwrap();
return Ok(());
}
}
@@ -266,10 +254,10 @@ pub fn run_repl<P: AsRef<Path>, F: LurkField, T: ReplTrait<F, C>, C: Coprocessor

let mut chars = line.chars().peekmore();

match s.read_maybe_meta(&mut chars, &package) {
match s.read_maybe_meta(&mut chars) {
Ok((expr, is_meta)) => {
if is_meta {
if let Err(e) = repl.state.handle_meta(s, expr, &package, p) {
if let Err(e) = repl.state.handle_meta(s, expr, p) {
eprintln!("!Error: {e:?}");
};
continue;
@@ -380,19 +368,18 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
&mut self,
store: &mut Store<F>,
expr_ptr: Ptr<F>,
package: &Package,
p: P,
) -> Result<()> {
let expr = store.fetch(&expr_ptr).unwrap();

let res = match expr {
Expression::Cons(car, rest) => match &store.fetch(&car).unwrap() {
Expression::SymCons(..) => {
let s: Sym = store
let s: Symbol = store
.fetch_sym(&car)
.ok_or(Error::msg("handle_meta fetch symbol"))?;
match s.name().as_str() {
"ASSERT" => {
match s.print_escape().as_str() {
"assert" => {
let (first, rest) = store.car_cdr(&rest)?;
assert!(rest.is_nil());
let (first_evaled, _, _, _) = self
@@ -402,7 +389,7 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
assert!(!first_evaled.is_nil());
None
}
"ASSERT-EQ" => {
"assert-eq" => {
let (first, rest) = store.car_cdr(&rest)?;
let (second, rest) = store.car_cdr(&rest)?;
assert!(rest.is_nil());
@@ -424,7 +411,7 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
);
None
}
"ASSERT-EMITTED" => {
"assert-emitted" => {
let (first, rest) = store.car_cdr(&rest)?;
let (second, rest) = store.car_cdr(&rest)?;

@@ -449,19 +436,19 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
}
None
}
"ASSERT-ERROR" => {
"assert-error" => {
let (first, rest) = store.car_cdr(&rest)?;

assert!(rest.is_nil());
assert!(self.clone().eval_expr(first, store).is_err());

None
}
"CLEAR" => {
"clear" => {
self.env = empty_sym_env(store);
None
}
"DEF" => {
"def" => {
// Extends env with a non-recursive binding.
//
// This: !(:def foo (lambda () 123))
@@ -473,8 +460,8 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
let (first, rest) = store.car_cdr(&rest)?;
let (second, rest) = store.car_cdr(&rest)?;
assert!(rest.is_nil());
let l = store.sym("LET");
let current_env = store.sym("CURRENT-ENV");
let l = store.sym("let");
let current_env = store.sym("current-env");
let binding = store.list(&[first, second]);
let bindings = store.list(&[binding]);
let current_env_call = store.list(&[current_env]);
@@ -487,7 +474,7 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
let (new_name, _) = store.car_cdr(&new_binding)?;
Some(new_name)
}
"DEFREC" => {
"defrec" => {
// Extends env with a recursive binding.
//
// This: !(:def foo (lambda () 123))
@@ -499,8 +486,8 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
let (first, rest) = store.car_cdr(&rest)?;
let (second, rest) = store.car_cdr(&rest)?;
assert!(rest.is_nil());
let l = store.sym("LETREC");
let current_env = store.sym("CURRENT-ENV");
let l = store.sym("letrec");
let current_env = store.sym("current-env");
let binding = store.list(&[first, second]);
let bindings = store.list(&[binding]);
let current_env_call = store.list(&[current_env]);
@@ -514,21 +501,21 @@ impl<F: LurkField, C: Coprocessor<F>> ReplTrait<F, C> for ReplState<F, C> {
let (new_name, _) = store.car_cdr(&new_binding_inner)?;
Some(new_name)
}
"LOAD" => {
"load" => {
match store.fetch(&store.car(&rest)?).unwrap() {
Expression::StrCons(..) => {
let path: String = store
.fetch_string(&car)
.ok_or(Error::msg("handle_meta fetch_string"))?;
let joined = p.as_ref().join(Path::new(&path));
self.handle_load(store, &joined, package)?
self.handle_load(store, &joined)?
}
_ => bail!("Argument to LOAD must be a string."),
}
io::stdout().flush().unwrap();
None
}
"SET-ENV" => {
"set-env" => {
// The state's env is set to the result of evaluating the first argument.
let (first, rest) = store.car_cdr(&rest)?;
assert!(rest.is_nil());
166 changes: 66 additions & 100 deletions src/store.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,6 @@ use rayon::prelude::*;
use std::cell::RefCell;
use std::fmt;
use std::rc::Rc;
use std::sync::Arc;
use std::usize;
use thiserror;

@@ -13,9 +12,8 @@ use crate::cont::Continuation;
use crate::expr;
use crate::expr::{Expression, Thunk};
use crate::field::{FWrap, LurkField};
use crate::package::{Package, LURK_EXTERNAL_SYMBOL_NAMES};
use crate::ptr::{ContPtr, Ptr, RawPtr};
use crate::sym::{Sym, Symbol};
use crate::symbol::Symbol;
use crate::tag::{ContTag, ExprTag, Op1, Op2, Tag};
use crate::z_cont::ZCont;
use crate::z_expr::ZExpr;
@@ -70,30 +68,11 @@ pub struct Store<F: LurkField> {

// improve intern_str, intern_sym performance
//pub string_cache: CacheMap<String, Box<Ptr<F>>>,
pub symbol_cache: CacheMap<Sym, Box<Ptr<F>>>,
pub symbol_cache: CacheMap<Symbol, Box<Ptr<F>>>,

pub lurk_package: Arc<Package>,
pub constants: OnceCell<NamedConstants<F>>,
}

pub trait TypePredicates {
fn is_fun(&self) -> bool;
fn is_self_evaluating(&self) -> bool;
fn is_potentially(&self, tag: ExprTag) -> bool;
}

impl<F: LurkField> TypePredicates for Ptr<F> {
fn is_fun(&self) -> bool {
self.tag.is_fun()
}
fn is_self_evaluating(&self) -> bool {
self.tag.is_self_evaluating()
}
fn is_potentially(&self, tag: ExprTag) -> bool {
self.tag.is_potentially(tag)
}
}

impl<F: LurkField> Default for Store<F> {
fn default() -> Self {
let mut store = Store {
@@ -123,14 +102,12 @@ impl<F: LurkField> Default for Store<F> {
poseidon_cache: Default::default(),
dehydrated: Default::default(),
dehydrated_cont: Default::default(),
lurk_package: Arc::new(Package::lurk()),
constants: Default::default(),
symbol_cache: Default::default(),
};

for name in LURK_EXTERNAL_SYMBOL_NAMES {
let sym = Sym::new_absolute(format!(".LURK.{}", name));
store.intern_sym(sym);
for sym in Symbol::lurk_syms() {
store.intern_symbol(sym);
}

store
@@ -156,15 +133,17 @@ impl<F: LurkField> Store<F> {
}

pub fn t(&mut self) -> Ptr<F> {
self.lurk_sym("T")
self.lurk_sym("t")
}

pub fn cons(&mut self, car: Ptr<F>, cdr: Ptr<F>) -> Ptr<F> {
self.intern_cons(car, cdr)
}

pub fn strcons(&mut self, car: Ptr<F>, cdr: Ptr<F>) -> Ptr<F> {
self.intern_strcons(car, cdr)
}

pub fn strnil(&self) -> Ptr<F> {
Ptr::null(ExprTag::Str)
}
@@ -254,33 +233,23 @@ impl<F: LurkField> Store<F> {
}

pub fn uint64(&mut self, n: u64) -> Ptr<F> {
self.get_u64(n)
self.intern_u64(n)
}

pub fn str<T: AsRef<str>>(&mut self, name: T) -> Ptr<F> {
self.intern_str(name)
self.intern_string(name)
}

pub fn lurk_sym<T: AsRef<str>>(&mut self, name: T) -> Ptr<F> {
let package = self.lurk_package.clone();
let mut name: String = String::from(name.as_ref());
name.make_ascii_uppercase();
let sym = Sym::new_absolute(String::from(name));
self.intern_sym_in_package(sym, &package)
self.intern_symbol(Symbol::sym(vec!["lurk", name.as_ref()]))
}

pub fn sym<T: AsRef<str>>(&mut self, name: T) -> Ptr<F> {
let package = Default::default();
let mut name: String = String::from(name.as_ref());
name.make_ascii_uppercase();
let sym = Sym::new_absolute(String::from(name));
self.intern_sym_in_package(sym, &package)
self.intern_symbol(Symbol::sym(vec![name.as_ref()]))
}

pub fn key<T: AsRef<str>>(&mut self, name: T) -> Ptr<F> {
let mut name: String = String::from(name.as_ref());
name.make_ascii_uppercase();
self.intern_keyword(Symbol::new_absolute(name))
self.intern_symbol(Symbol::key(vec![name.as_ref()]))
}

pub fn car(&self, expr: &Ptr<F>) -> Result<Ptr<F>, Error> {
@@ -316,19 +285,19 @@ impl<F: LurkField> Store<F> {
}

pub fn get_nil(&self) -> Ptr<F> {
self.get_lurk_sym("nil", true).expect("missing NIL")
self.get_lurk_sym("nil").expect("missing NIL")
}

pub fn get_begin(&self) -> Ptr<F> {
self.get_lurk_sym("begin", true).expect("missing BEGIN")
self.get_lurk_sym("begin").expect("missing BEGIN")
}

pub fn get_quote(&self) -> Ptr<F> {
self.get_lurk_sym("quote", true).expect("missing QUOTE")
self.get_lurk_sym("quote").expect("missing QUOTE")
}

pub fn get_t(&self) -> Ptr<F> {
self.get_lurk_sym("t", true).expect("missing T")
self.get_lurk_sym("t").expect("missing T")
}

pub fn intern_cons(&mut self, car: Ptr<F>, cdr: Ptr<F>) -> Ptr<F> {
@@ -465,52 +434,45 @@ impl<F: LurkField> Store<F> {
.fold(self.lurk_sym("nil"), |acc, elt| self.intern_cons(*elt, acc))
}

pub fn intern_keyword(&mut self, sym: Symbol) -> Ptr<F> {
let s = self.intern_symbol(sym);
Ptr {
tag: ExprTag::Key,
raw: s.raw,
_f: s._f,
pub fn intern_symbol_path(&mut self, path: Vec<String>) -> Ptr<F> {
let mut ptr = self.symnil();
for s in path.iter() {
let str_ptr = self.intern_string(s);
ptr = self.intern_symcons(str_ptr, ptr);
}
self.symbol_cache
.insert(Symbol::Sym(path.clone()), Box::new(ptr));
ptr
}

pub fn intern_symbol(&mut self, sym: Symbol) -> Ptr<F> {
let mut ptr = self.symnil();
for s in sym.path.iter() {
let str_ptr = self.intern_str(s);
ptr = self.intern_symcons(str_ptr, ptr);
}
if sym.path == vec!["", "LURK", "NIL"] {
let ptr = self.intern_symbol_path(sym.path());
let ptr = if sym.path() == vec!["lurk".to_string(), "nil".to_string()] {
Ptr {
tag: ExprTag::Nil,
raw: ptr.raw,
_f: ptr._f,
}
} else if sym.is_key() {
Ptr {
tag: ExprTag::Key,
raw: ptr.raw,
_f: ptr._f,
}
} else {
ptr
}
}

pub fn intern_sym(&mut self, sym: Sym) -> Ptr<F> {
let ptr = match sym.clone() {
Sym::Sym(s) => self.intern_symbol(s),
Sym::Key(s) => self.intern_keyword(s),
};
self.symbol_cache.insert(sym, Box::new(ptr));
ptr
}

pub fn get_sym(&self, sym: Sym) -> Option<Ptr<F>> {
pub fn get_sym(&self, sym: Symbol) -> Option<Ptr<F>> {
self.symbol_cache.get(&sym).cloned()
}

pub fn get_lurk_sym<T: AsRef<str>>(&self, name: T, convert_case: bool) -> Option<Ptr<F>> {
let mut name = format!(".lurk.{}", name.as_ref());
if convert_case {
crate::parser::convert_sym_case(&mut name);
}

self.get_sym(Sym::new_absolute(name))
pub fn get_lurk_sym<T: AsRef<str>>(&self, name: T) -> Option<Ptr<F>> {
let mut sym = Symbol::lurk_sym(name.as_ref());
self.get_sym(sym)
}

pub fn intern_num<T: Into<Num<F>>>(&mut self, num: T) -> Ptr<F> {
@@ -548,26 +510,27 @@ impl<F: LurkField> Store<F> {
.map(|x| Ptr::index(ExprTag::Num, x))
}

// TODO: rename this to intern_char
pub fn get_char(&self, c: char) -> Ptr<F> {
self.get_char_from_u32(u32::from(c))
pub fn intern_char(&self, c: char) -> Ptr<F> {
Ptr::index(ExprTag::Char, u32::from(c) as usize)
}

pub fn get_char_from_u32(&self, code: u32) -> Ptr<F> {
Ptr::index(ExprTag::Char, code as usize)
pub fn intern_uint(&self, n: UInt) -> Ptr<F> {
match n {
UInt::U64(x) => self.intern_u64(x),
}
}

pub fn get_u64(&self, n: u64) -> Ptr<F> {
pub fn intern_u64(&self, n: u64) -> Ptr<F> {
Ptr::index(ExprTag::U64, n as usize)
}

// intern a string into the Store, which generates the cons'ed representation
// TODO: short-circuit interning if we hit the cache
pub fn intern_str<T: AsRef<str>>(&mut self, s: T) -> Ptr<F> {
pub fn intern_string<T: AsRef<str>>(&mut self, s: T) -> Ptr<F> {
let s: String = String::from(s.as_ref());
let mut ptr = self.strnil();
for c in s.chars().rev() {
ptr = self.intern_strcons(self.get_char(c), ptr);
ptr = self.intern_strcons(self.intern_char(c), ptr);
}
ptr
}
@@ -652,7 +615,7 @@ impl<F: LurkField> Store<F> {
self.z_cont_ptr_map.get(scalar_ptr).map(|p| *p)
}

pub fn fetch_maybe_sym(&self, ptr: &Ptr<F>) -> Option<Sym> {
pub fn fetch_maybe_sym(&self, ptr: &Ptr<F>) -> Option<Symbol> {
if matches!(ptr.tag, ExprTag::Sym) {
self.fetch_sym(ptr)
} else {
@@ -671,30 +634,33 @@ impl<F: LurkField> Store<F> {
}
}

pub fn fetch_symbol(&self, ptr: &Ptr<F>) -> Option<Symbol> {
pub fn fetch_sym(&self, ptr: &Ptr<F>) -> Option<Symbol> {
let mut ptr = *ptr;
let mut path = Vec::new();
while let Some((car, cdr)) = self.fetch_symcons(&ptr) {
let string = self.fetch_string(&car)?;
path.push(string);
ptr = cdr
}
Some(Symbol { path })
Some(Symbol::Sym(path))
}

pub fn fetch_key(&self, ptr: &Ptr<F>) -> Option<Symbol> {
let symbol = self.fetch_sym(&Ptr {
tag: ExprTag::Sym,
raw: ptr.raw,
_f: ptr._f,
})?;
Some(Symbol::Key(symbol.path()))
}

pub fn fetch_sym(&self, ptr: &Ptr<F>) -> Option<Sym> {
pub fn fetch_symbol(&self, ptr: &Ptr<F>) -> Option<Symbol> {
if ptr.tag == ExprTag::Nil {
Some(Sym::new(".LURK.NIL".into()))
Some(Symbol::nil())
} else if ptr.tag == ExprTag::Key {
let symbol = self.fetch_symbol(&Ptr {
tag: ExprTag::Sym,
raw: ptr.raw,
_f: ptr._f,
})?;
Some(Sym::Key(symbol))
self.fetch_key(ptr)
} else {
let symbol = self.fetch_symbol(ptr)?;
Some(Sym::Sym(symbol))
self.fetch_sym(ptr)
}
}

@@ -1282,14 +1248,14 @@ impl<F: LurkField> Store<F> {
}

pub fn hash_string(&mut self, s: &str) -> ZExprPtr<F> {
let ptr = self.intern_str(s);
let ptr = self.intern_string(s);
self.get_z_expr(&ptr, None)
.expect("known string can't be opaque")
.0
}

pub fn hash_symbol(&mut self, s: Sym) -> ZExprPtr<F> {
let ptr = self.intern_sym(s);
pub fn hash_symbol(&mut self, s: Symbol) -> ZExprPtr<F> {
let ptr = self.intern_symbol(s);
self.get_z_expr(&ptr, None)
.expect("known symbol can't be opaque")
.0
@@ -1641,7 +1607,7 @@ impl<F: LurkField> Expression<F> {
//}
}

pub const fn as_sym(&self) -> Option<&Sym> {
pub const fn as_sym(&self) -> Option<&Symbol> {
todo!()
//match self {
// Expression::Sym(s) => Some(s),
@@ -1747,7 +1713,7 @@ pub struct NamedConstants<F: LurkField> {
impl<F: LurkField> NamedConstants<F> {
pub fn new(store: &Store<F>) -> Self {
let hash_sym = |name: &str| {
let ptr = store.get_lurk_sym(name, true).unwrap();
let ptr = store.get_lurk_sym(name).unwrap();
let maybe_z_ptr = store.hash_expr(&ptr);
ConstantPtrs(maybe_z_ptr, ptr)
};
380 changes: 0 additions & 380 deletions src/sym.rs

This file was deleted.

233 changes: 233 additions & 0 deletions src/symbol.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
use std::fmt;

use crate::parser::whitespace;
#[cfg(not(target_arch = "wasm32"))]
use proptest_derive::Arbitrary;
/// Module for symbol type, Sym.
use serde::{Deserialize, Serialize};

pub const KEYWORD_MARKER: char = ':';
pub const SYM_SEPARATOR: char = '.';
pub const SYM_MARKER: char = '.';
pub const ESCAPE_CHARS: &'static str = "(){}[]=,.:";

pub const LURK_SYMBOL_NAMES: &[&str] = &[
"atom",
"begin",
"car",
"cdr",
"char",
"comm",
"commit",
"cons",
"current-env",
"emit",
"eval",
"eq",
"hide",
"if",
"lambda",
"let",
"letrec",
"nil",
"num",
"u64",
"open",
"quote",
"secret",
"strcons",
"t",
"_",
"+",
"-",
"*",
"/",
"%",
"=",
"<",
">",
"<=",
">=",
];

#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
#[cfg_attr(not(target_arch = "wasm32"), derive(Arbitrary))]
/// Type for hierarchical symbol names
pub enum Symbol {
Sym(Vec<String>),
Key(Vec<String>),
}

impl Symbol {
pub fn sym(path: Vec<&str>) -> Symbol {
Symbol::Sym(path.iter().map(|x| x.to_string()).collect())
}

pub fn key(path: Vec<&str>) -> Symbol {
Symbol::Key(path.iter().map(|x| x.to_string()).collect())
}
/// Creates a new Symbol with the root path `[""]`.
pub fn root() -> Self {
Self::Sym(vec![])
}

/// Returns true if the Symbol is the root sym or keyword, i.e. if it has a path of `[]`.
pub fn path(&self) -> Vec<String> {
match self {
Self::Sym(path) => path.clone(),
Self::Key(path) => path.clone(),
}
}

/// Returns true if the Symbol is the root sym or keyword, i.e. if it has a path of `[]`.
pub fn is_root(&self) -> bool {
self.path().is_empty()
}

pub fn is_key(&self) -> bool {
matches!(self, Self::Key(_))
}

/// Creates a new Symbol with the path extended by the given vector of path segments.
pub fn extend(&self, path: &[String]) -> Self {
let mut new_path = Vec::with_capacity(self.path().len() + path.len());
for elt in self.path().iter() {
new_path.push(elt.clone());
}
for elt in path.iter() {
new_path.push(elt.clone());
}

if self.is_key() {
Self::Key(new_path)
} else {
Self::Sym(new_path)
}
}

pub fn marker(&self) -> char {
match self {
Self::Sym(_) => SYM_MARKER,
Self::Key(_) => KEYWORD_MARKER,
}
}

pub fn nil() -> Symbol {
Symbol::Sym(vec!["LURK".to_string(), "NIL".to_string()])
}

pub fn lurk_sym(name: &str) -> Symbol {
Symbol::Sym(vec!["LURK".to_string(), name.to_string()])
}

pub fn lurk_syms() -> Vec<Symbol> {
let mut vec = Vec::new();
for name in LURK_SYMBOL_NAMES {
vec.push(Self::lurk_sym(name))
}
vec
}

pub fn is_whitespace(c: char) -> bool {
whitespace().iter().any(|x| *x == c)
}

pub fn escape_symbol_element(xs: &str) -> String {
let mut res = String::new();
for x in xs.chars() {
if ESCAPE_CHARS.chars().any(|c| c == x) {
res.push_str(&format!("\\{}", x));
} else if Self::is_whitespace(x) {
res.push_str(&format!("{}", x.escape_unicode()));
} else {
res.push(x)
}
}
res
}

pub fn print_root(&self) -> String {
format!("_{}", self.marker())
}

pub fn print_escape(&self) -> String {
if self.is_root() {
return self.print_root();
}
let mut res = String::new();
let xs = self.path();
if Self::sym_needs_marker(self) {
res.push(self.marker())
}
res.push_str(&Self::escape_symbol_element(&xs[0]));
for x in xs[1..].iter() {
res.push(SYM_SEPARATOR);
res.push_str(&Self::escape_symbol_element(&x));
}
res
}

pub fn sym_needs_marker(&self) -> bool {
let xs = self.path();
if self.is_root()
|| self.is_key()
|| xs[0].is_empty()
|| xs[0] == "_"
|| xs[0] == self.print_root()
{
return true;
};
let c = xs[0].chars().next().unwrap();
"1234567890.:'[](){}=,\"\\".chars().any(|x| x == c)
|| char::is_whitespace(c)
|| char::is_control(c)
}
}

impl fmt::Display for Symbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_root() {
write!(f, "_{}", self.marker())
} else {
write!(f, "{}", self.print_escape())
}
}
}

#[cfg(test)]
pub mod test {

//use super::*;

//#[test]
//fn test_sym() {
// let root = Sym::root();
// dbg!(root.path());
// let a = root.child("a".into());
// let a_b = a.child("b".into());
// let a_b_path = vec!["", "a", "b"];

// assert_eq!(".|a|", a.full_name());
// assert_eq!(".|a|.|b|", a_b.full_name());
// assert_eq!(&a_b_path, a_b.path());
// assert_eq!(Some(a.clone()), a_b.parent());
// assert_eq!(Some(root.clone()), a.parent());
// assert_eq!(None, root.parent());
//}

//#[test]
//fn test_keywords() {
// let root = Sym::root();
// let key_root = Sym::key_root();

// let apple = root.child("APPLE".into());
// let orange = key_root.child("ORANGE".into());

// assert_eq!("APPLE", apple.name());
// assert_eq!("ORANGE", orange.name());
// assert!(!apple.is_keyword());
// assert!(orange.is_keyword());
// assert_eq!(key_root, orange.parent().unwrap());
// assert!(apple.parent().unwrap() != key_root);
//}
}
166 changes: 166 additions & 0 deletions src/syntax.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
use std::fmt;

use crate::field::LurkField;
use crate::num::Num;
use crate::parser::position::Pos;
use crate::ptr::Ptr;
use crate::store::Store;
use crate::symbol::Symbol;
use crate::uint::UInt;

#[cfg(not(target_arch = "wasm32"))]
use proptest::prelude::*;

// Lurk syntax
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Syntax<F: LurkField> {
Num(Pos, Num<F>),
// A u64 integer: 1u64, 0xffu64
UInt(Pos, UInt),
// A hierarchical symbol foo, foo.bar.baz or keyword :foo
Symbol(Pos, Symbol),
// A string literal: "foobar", "foo\nbar"
String(Pos, String),
// A character literal: #\A #\λ #\u03BB
Char(Pos, char),
// A quoted expression: 'a, '(1 2)
Quote(Pos, Box<Syntax<F>>),
// A nil-terminated cons-list of expressions: (1 2 3)
List(Pos, Vec<Syntax<F>>),
// An imprpoer cons-list of expressions: (1 2 . 3)
Improper(Pos, Vec<Syntax<F>>, Box<Syntax<F>>),
}

#[cfg(not(target_arch = "wasm32"))]
impl<Fr: LurkField> Arbitrary for Syntax<Fr> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
let leaf = prop_oneof![
any::<Num<Fr>>().prop_map(|x| Syntax::Num(Pos::No, x)),
any::<UInt>().prop_map(|x| Syntax::UInt(Pos::No, x)),
any::<Symbol>().prop_map(|x| Syntax::Symbol(Pos::No, x)),
any::<String>().prop_map(|x| Syntax::String(Pos::No, x)),
any::<char>().prop_map(|x| Syntax::Char(Pos::No, x))
];
leaf.prop_recursive(8, 256, 10, |inner| {
prop_oneof![
inner
.clone()
.prop_map(|x| Syntax::Quote(Pos::No, Box::new(x))),
prop::collection::vec(inner.clone(), 0..10).prop_map(|x| Syntax::List(Pos::No, x)),
prop::collection::vec(inner.clone(), 1..11).prop_map(|mut xs| {
let x = xs.pop().unwrap();
Syntax::Improper(Pos::No, xs, Box::new(x))
})
]
})
.boxed()
}
}

impl<F: LurkField> fmt::Display for Syntax<F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Num(_, x) => write!(f, "{}", x),
Self::UInt(_, x) => write!(f, "{}", x),
Self::Symbol(_, sym) => write!(f, "{}", sym),
Self::String(_, x) => write!(f, "\"{}\"", x.escape_default()),
Self::Char(_, x) => write!(f, "#\\{}", x.escape_default()),
Self::Quote(_, x) => write!(f, "'{}", x),
Self::List(_, xs) => {
let mut iter = xs.iter().peekable();
write!(f, "(")?;
while let Some(x) = iter.next() {
match iter.peek() {
Some(_) => write!(f, "{} ", x)?,
None => write!(f, "{}", x)?,
}
}
write!(f, ")")
}
Self::Improper(_, xs, end) => {
let mut iter = xs.iter().peekable();
write!(f, "(")?;
while let Some(x) = iter.next() {
match iter.peek() {
Some(_) => write!(f, "{} ", x)?,
None => write!(f, "{} . {}", x, *end)?,
}
}
write!(f, ")")
}
}
}
}

impl<F: LurkField> Store<F> {
pub fn intern_syntax(&mut self, syn: Syntax<F>) -> Ptr<F> {
match syn {
Syntax::Num(_, x) => self.intern_num(x),
Syntax::UInt(_, x) => self.intern_uint(x),
Syntax::Char(_, x) => self.intern_char(x),
Syntax::Symbol(_, x) => self.intern_symbol(x),
Syntax::String(_, x) => self.intern_string(x),
Syntax::Quote(pos, x) => {
let xs = vec![Syntax::Symbol(pos, Symbol::lurk_sym("quote")), *x];
self.intern_syntax(Syntax::List(pos, xs))
}
Syntax::List(_, xs) => {
let mut cdr = self.nil();
for x in xs.into_iter().rev() {
let car = self.intern_syntax(x);
cdr = self.intern_cons(car, cdr);
}
cdr
}
Syntax::Improper(_, xs, end) => {
let mut cdr = self.intern_syntax(*end);
for x in xs.into_iter().rev() {
let car = self.intern_syntax(x);
cdr = self.intern_cons(car, cdr);
}
cdr
}
}
}

pub fn fetch_syntax(&mut self, ptr: Ptr<F>) -> Option<Syntax<F>> {
todo!()
}
}

//#[cfg(test)]
//mod test {
// use super::*;
// use blstrs::Scalar as Fr;
// use proptest::prelude::*;
//
// //#[test]
// //fn display_syntax() {
// // assert_eq!("NIL", format!("{}", Lurk::<Fr>::Nil(Pos::No)));
// // assert_eq!(
// // "(NIL)",
// // format!(
// // "{}",
// // Lurk::<Fr>::Cons(Pos::No, Box::new((Lurk::Nil(Pos::No), Lurk::Nil(Pos::No))))
// // )
// // );
// // assert_eq!(
// // "(#\\a . #\\b)",
// // format!(
// // "{}",
// // Lurk::<Fr>::Cons(Pos::No, Box::new((Lurk::Nil(Pos::No), Lurk::Nil(Pos::No))))
// // )
// // )
// //}
//
// //proptest! {
// //#[test]
// //fn prop_display_syntax(x in any::<Lurk<Fr>>()) {
// // println!("{}", x);
// // assert!(false)
// //}
// //}
//}
2 changes: 1 addition & 1 deletion src/tag.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
use std::{convert::TryFrom, fmt};

use crate::field::LurkField;
use crate::store::TypePredicates;
use crate::ptr::TypePredicates;
use crate::z_data::Encodable;
use crate::z_data::ZData;

18 changes: 6 additions & 12 deletions src/writer.rs
Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@ use crate::expr::Expression;
use crate::field::LurkField;
use crate::ptr::{ContPtr, Ptr};
use crate::store::Store;
use crate::symbol::Symbol;
use crate::z_expr::ZExpr;
use crate::Sym;
use std::io;

pub trait Write<F: LurkField> {
@@ -49,12 +49,9 @@ impl<F: LurkField> Write<F> for ContPtr<F> {
fn write_symbol<F: LurkField, W: io::Write>(
w: &mut W,
store: &Store<F>,
sym: &Sym,
sym: &Symbol,
) -> io::Result<()> {
let package = &store.lurk_package;
let maybe_abbr = package.relative_abbreviation(sym);
let symbol_name = maybe_abbr.full_name();
write!(w, "{symbol_name}")
todo!()
}

impl<F: LurkField> Write<F> for Expression<F> {
@@ -63,7 +60,7 @@ impl<F: LurkField> Write<F> for Expression<F> {

match self {
Nil => write!(w, "NIL"),
SymNil => write_symbol::<F, _>(w, store, &Sym::root()),
SymNil => write_symbol::<F, _>(w, store, &Symbol::root()),
SymCons(car, cdr) => {
let head = store.fetch_string(car).expect("missing symbol head");
let tail = store.fetch_sym(cdr).expect("missing symbol tail");
@@ -77,13 +74,10 @@ impl<F: LurkField> Write<F> for Expression<F> {
}
Key(sym) => {
let symbol = store.fetch_symbol(sym).expect("missing symbol");
write_symbol::<F, _>(w, store, &Sym::Key(symbol))
write_symbol::<F, _>(w, store, &Symbol::Key(symbol.path()))
}
Fun(arg, body, _closed_env) => {
let is_zero_arg = *arg
== store
.get_lurk_sym("_", true)
.expect("dummy_arg (_) missing");
let is_zero_arg = *arg == store.get_lurk_sym("_").expect("dummy_arg (_) missing");
let arg = store.fetch(arg).unwrap();
write!(w, "<FUNCTION (")?;
if !is_zero_arg {
11 changes: 4 additions & 7 deletions src/z_store.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use proptest_derive::Arbitrary;
use std::collections::BTreeMap;

use crate::hash::PoseidonCache;
use crate::sym::Sym;
use crate::symbol::Symbol;
use crate::tag::ExprTag;
use crate::z_cont::ZCont;
use crate::z_data::Encodable;
@@ -59,11 +59,8 @@ impl<F: LurkField> ZStore<F> {
}

pub fn nil_z_ptr(&mut self, poseidon_cache: &PoseidonCache<F>) -> ZExprPtr<F> {
self.put_symbol(
Sym::new_from_path(false, vec!["".into(), "LURK".into(), "NIL".into()]),
poseidon_cache,
)
.0
self.put_symbol(Symbol::sym(vec!["lurk", "nil"]), poseidon_cache)
.0
}

pub fn put_string(
@@ -82,7 +79,7 @@ impl<F: LurkField> ZStore<F> {

pub fn put_symbol(
&mut self,
sym: Sym,
sym: Symbol,
poseidon_cache: &PoseidonCache<F>,
) -> (ZExprPtr<F>, ZExpr<F>) {
let mut expr = ZExpr::SymNil;