ic/term/
views.rs

1use super::*;
2
3// Converts a lambda term (with non-affine functions) to a net. Reduction of the resulting net is
4// *not* guaranteed to return the normal form of the original lambda term.
5#[allow(dead_code)]
6pub fn lambda_term_to_inet(term : &Term) -> INet {
7  fn encode(inet : &mut INet, label : &mut u32, scope : &mut Vec<(Vec<u8>, u32)>, term : &Term) -> Port {
8    match term {
9      &App{ref fun, ref arg} => {
10        let app = new_node(inet, CON);
11        let fun = encode(inet, label, scope, fun);
12        link(inet, port(app, 0), fun);
13        let arg = encode(inet, label, scope, arg);
14        link(inet, port(app, 1), arg);
15        port(app, 2)
16      },
17      &Lam{ref nam, ref typ, ref bod} => {
18        // TODO: handle typ
19        let fun = new_node(inet, CON);
20        let era = new_node(inet, ERA);
21        link(inet, port(fun, 1), port(era, 0));
22        link(inet, port(era, 1), port(era, 2));
23        scope.push((nam.to_vec(), fun));
24        let bod = encode(inet, label, scope, bod);
25        scope.pop();
26        link(inet, port(fun, 2), bod);
27        port(fun, 0)
28      },
29      &Ann{..} => {
30        todo!();
31      },
32      &Var{ref nam} => {
33        let mut lam = 0;
34        for i in 0..scope.len() {
35          if *nam == scope[i].0 {
36            lam = scope[i].1
37          }
38        }
39        if lam == 0 {
40          panic!("Invalid λ-term.");
41        }
42        let arg = enter(inet, port(lam, 1));
43        if kind(inet, addr(arg)) == 0 {
44          inet.reuse.push(addr(arg));
45          port(lam, 1)
46        } else {
47          *label += 1;
48          let dup = new_node(inet, *label);
49          link(inet, port(dup, 2), arg);
50          link(inet, port(dup, 0), port(lam, 1));
51          port(dup, 1)
52        }
53      },
54      _ => panic!("Invalid λ-term.")
55    }
56  }
57  let mut inet : INet = new_inet();
58  let mut label : u32 = 1;
59  let mut scope : Vec<(Vec<u8>, u32)> = Vec::new();
60  let ptr : Port = encode(&mut inet, &mut label, &mut scope, term);
61  link(&mut inet, 0, ptr);
62  inet
63}
64
65// Converts a net to a lambda term, turning explicit "lets" into non-affine functions. Will fail if
66// the corresponding abstract-calculus term includes variables that scape a lambda's scope.
67#[allow(dead_code)]
68pub fn lambda_term_from_inet(inet : &INet) -> Term {
69  fn go(inet : &INet, node_depth : &mut Vec<u32>, next : Port, exit : &mut Vec<Port>, depth : u32) -> Term {
70    let prev_port = enter(inet, next);
71    let prev_slot = slot(prev_port);
72    let prev_node = addr(prev_port);
73    if kind(inet, prev_node) == 1 {
74      match prev_slot {
75        0 => {
76          node_depth[prev_node as usize] = depth;
77          let nam = index_to_name(depth + 1);
78          let typ = None; // TODO: handle
79          let bod = Box::new(go(inet, node_depth, port(prev_node, 2), exit, depth + 1));
80          Lam {nam, typ, bod}
81        },
82        1 => {
83          let nam = index_to_name(node_depth[prev_node as usize] + 1);
84          Var {nam}
85        },
86        _ => {
87          let fun = Box::new(go(inet, node_depth, port(prev_node, 0), exit, depth));
88          let arg = Box::new(go(inet, node_depth, port(prev_node, 1), exit, depth));
89          App {fun, arg}
90        }
91      }
92    } else if prev_slot > 0 {
93      exit.push(prev_slot);
94      let term = go(inet, node_depth, port(prev_node, 0), exit, depth);
95      exit.pop();
96      term
97    } else {
98      let e = exit.pop().unwrap();
99      let term = go(inet, node_depth, port(prev_node, e), exit, depth);
100      exit.push(e);
101      term
102    }
103  }
104  let mut node_depth : Vec<u32> = Vec::with_capacity(inet.nodes.len() / 4);
105  let mut exit : Vec<u32> = Vec::new();
106  node_depth.resize(inet.nodes.len() / 4, 0);
107  go(inet, &mut node_depth, 0, &mut exit, 0)
108}
109
110// Converts a binary input such as b"1001" into a λ-encoded bitstring
111// such as λa.λb.λc.(a λa.λb.λc.(b λa.λb.λc.(b λa.λb.λc.(a λa.λb.λc.c))))
112pub fn bitstring_to_term(s : &[u8], i : u32) -> Term {
113  match if s.len() > 0 { s[0] } else { b' ' } {
114    b'0' => {
115      let nam = index_to_name(i+1);
116      let app = Term::App{
117        fun: Box::new(Var{nam: nam.clone()}),
118        arg: Box::new(bitstring_to_term(&s[1..], i+1))
119      };
120      let e_lam = Term::Lam{
121        nam: b"-".to_vec(),
122        typ: None, // TODO
123        bod: Box::new(app)
124      };
125      let i_lam = Term::Lam{
126        nam: b"-".to_vec(),
127        typ: None, // TODO
128        bod: Box::new(e_lam)
129      };
130      let o_lam = Term::Lam{
131        nam: nam,
132        typ: None, // TODO
133        bod: Box::new(i_lam)
134      };
135      o_lam
136    },
137    b'1' => {
138      let nam = index_to_name(i+1);
139      let app = Term::App{
140        fun: Box::new(Var{nam: nam.clone()}),
141        arg: Box::new(bitstring_to_term(&s[1..], i+1))
142      };
143      let e_lam = Term::Lam{
144        nam: b"-".to_vec(),
145        typ: None, // TODO
146        bod: Box::new(app)
147      };
148      let i_lam = Term::Lam{
149        nam: nam,
150        typ: None, // TODO
151        bod: Box::new(e_lam)
152      };
153      let o_lam = Term::Lam{
154        nam: b"-".to_vec(),
155        typ: None, // TODO
156        bod: Box::new(i_lam)
157      };
158      o_lam
159    },
160    _ => {
161      let nam = index_to_name(i+1);
162      let var = Var{nam: nam.clone()};
163      let e_lam = Term::Lam{
164        nam: nam,
165        typ: None, // TODO
166        bod: Box::new(var)
167      };
168      let i_lam = Term::Lam{
169        nam: b"-".to_vec(),
170        typ: None, // TODO
171        bod: Box::new(e_lam)
172      };
173      let o_lam = Term::Lam{
174        nam: b"-".to_vec(),
175        typ: None, // TODO
176        bod: Box::new(i_lam)
177      };
178      o_lam
179    }
180  }
181}
182
183// Can this highly-idented style be improved?
184pub fn term_to_bitstring(t : &Term) -> Vec<u8> {
185  fn format_binary_output(t : &Term, v : &mut Vec<u8>) {
186    match t {
187      Term::Lam{nam: ref o_nam, typ: _, bod: ref o_bod} => { // TODO: handle typ
188        match **o_bod {
189          Term::Lam{nam: ref i_nam, typ: _, bod: ref i_bod} => { // TODO: handle typ
190            match **i_bod {
191              Term::Lam{nam: _, typ: _, bod: ref e_bod} => { // TODO: handle typ
192                match **e_bod {
193                  Term::App{fun: ref app_fun, arg: ref app_arg} => {
194                    match **app_fun {
195                      Term::Var{nam: ref var_nam} => {
196                        if var_nam == o_nam {
197                          v.extend_from_slice(b"0");
198                          format_binary_output(app_arg, v);
199                        } else if var_nam == i_nam {
200                          v.extend_from_slice(b"1");
201                          format_binary_output(app_arg, v);
202                        }
203                      },
204                      _ => {}
205                    }
206                  },
207                  _ => {}
208                }
209              },
210              _ => {}
211            }
212          },
213          _ => {}
214        }
215      },
216      _ => {}
217    }
218  }
219  let mut v : Vec<u8> = Vec::new();
220  format_binary_output(t, &mut v);
221  v
222}
223
224// Converts a bitstring (up to 8 bits) to a character.
225pub fn bits_to_char(s : &[u8]) -> u8 {
226  let mut c = 0;
227  for i in 0..8 {
228    c = c * 2 + (if s[i] == b'0' { 0 } else { 1 });
229  }
230  c
231}
232
233// Converts a character to a bitstring.
234pub fn char_to_bits(c : u8) -> Vec<u8> {
235  let mut v : Vec<u8> = Vec::new();
236  let mut c = c;
237  for _i in 0..8 {
238    v.extend_from_slice(if c % 2 == 0 { b"0" } else { b"1" });
239    c = c / 2;
240  }
241  v.reverse();
242  v
243}
244
245// Converts a bitstring to an ascii string.
246pub fn bits_to_ascii(s : &[u8]) -> Vec<u8> {
247  let mut v : Vec<u8> = Vec::new();
248  for i in 0..s.len()/8 {
249    v.push(bits_to_char(&s[i*8..i*8+8]));
250  }
251  v
252}
253
254// Converts an ascii string to a bitstring.
255pub fn ascii_to_bits(a : &[u8]) -> Vec<u8> {
256  let mut v : Vec<u8> = Vec::new();
257  for i in 0..a.len() {
258    v.append(&mut char_to_bits(a[i]))
259  }
260  v
261}