1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
extern crate enum_map;
extern crate serde;
use crate::parse::Parser;
use crate::print::Printer;
use crate::reduce::{Consume, GroupDef, GroupDefSerial, GroupMode, ReduceType, Statement};
use crate::session::{LibrarySpec, Session};
use crate::value::Value;
use enum_map::enum_map;
use serde::{Deserialize, Serialize};
use std::io::{BufRead, BufReader, Read, Write};
use std::iter;
use std::path::PathBuf;
use std::rc::{Rc, Weak};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ProgramSerial {
pub libraries: Vec<LibrarySpec>,
pub main_statements: Vec<Statement>,
pub sub_groups: Vec<GroupDefSerial>,
}
#[derive(Clone, Debug)]
pub struct Program {
pub libraries: Vec<LibrarySpec>,
pub main_group: GroupDef,
pub sub_groups: Rc<Vec<GroupDef>>,
}
impl From<ProgramSerial> for Program {
fn from(serial: ProgramSerial) -> Program {
let main_statements = serial.main_statements;
let mut program = Program {
libraries: serial.libraries,
main_group: GroupDef {
props: vec![],
mode: GroupMode::Continue,
statements: enum_map![
ReduceType::Regular => main_statements.clone(),
ReduceType::EvalCtx => vec![],
ReduceType::AltConsume => vec![],
],
env: Weak::new(),
},
sub_groups: Rc::new(
serial
.sub_groups
.into_iter()
.map(|sub_group| GroupDef::from_no_env(sub_group))
.collect(),
),
};
unsafe {
let sub_groups = Rc::into_raw(program.sub_groups);
let sub_groups = sub_groups as *mut Vec<GroupDef>;
let sub_groups_iter = (&mut *sub_groups).iter_mut();
program.sub_groups = Rc::from_raw(sub_groups);
program.main_group.env = Rc::downgrade(&program.sub_groups);
for sub_group in sub_groups_iter {
sub_group.env = Rc::downgrade(&program.sub_groups);
}
}
return program;
}
}
impl<R: Read> From<R> for Program {
fn from(read: R) -> Program {
let mut reader = BufReader::new(read);
reader.read_line(&mut String::new()).unwrap();
let serial: ProgramSerial = rmp_serde::from_read(reader).unwrap();
return Program::from(serial);
}
}
impl Program {
pub fn new_session(&self) -> Session {
return Session::new(self.libraries.clone());
}
fn groups(&self) -> impl Iterator<Item = &GroupDef> {
return iter::once(&self.main_group).chain(self.sub_groups.iter());
}
pub fn inferred_lang(&self) -> Option<String> {
return self
.groups()
.flat_map(|group| group.statements[ReduceType::Regular].iter())
.flat_map(|statement| match statement {
Statement::Reducer(reducer) => vec![&reducer.input, &reducer.output],
Statement::Group(_) => vec![],
})
.flat_map(|clause| clause.consumes.iter())
.filter_map(|consume| match consume {
Consume::Record(head) => Some(head),
_ => None,
})
.filter_map(|head| Value::record_head_to_fun(head))
.map(|(lib, _)| lib)
.next();
}
pub fn run<R: Read, W: Write>(
&self,
session: &mut Session,
in_path: &Option<PathBuf>,
input: &mut R,
output: &mut W,
) {
let mut parser = Parser { input: input };
let mut printer = Printer { output: output };
session.start(in_path);
while let Option::Some(mut next) = parser.scan_value() {
self.main_group.reduce(session, &mut next);
printer.print_value(next).unwrap();
}
session.stop();
}
}