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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
use crate::ffi::Ffi;
#[cfg(feature = "go_std")]
use crate::std::os;
#[cfg(feature = "serde_borsh")]
use borsh::{BorshDeserialize, BorshSerialize};
use std::path::Path;
use std::rc::Rc;
#[cfg(feature = "codegen")]
pub use cg::SourceRead;
#[cfg(feature = "codegen")]
extern crate go_codegen as cg;
#[cfg(feature = "codegen")]
extern crate go_parser as parser;
#[cfg(feature = "codegen")]
extern crate go_types as types;
extern crate go_vm as vm;
#[derive(Default)]
pub struct Config {
pub trace_parser: bool,
pub trace_checker: bool,
pub std_in: Option<Box<dyn std::io::Read + Sync + Send>>,
pub std_out: Option<Box<dyn std::io::Write + Sync + Send>>,
pub std_err: Option<Box<dyn std::io::Write + Sync + Send>>,
}
pub struct Engine {
ffi: vm::FfiFactory,
}
impl Engine {
pub fn new() -> Engine {
#[cfg(not(feature = "go_std"))]
{
Engine {
ffi: vm::FfiFactory::new(),
}
}
#[cfg(feature = "go_std")]
{
let mut e = Engine {
ffi: vm::FfiFactory::new(),
};
crate::std::register(&mut e.ffi);
e
}
}
pub fn with_user_data(data: usize) -> Engine {
#[cfg(not(feature = "go_std"))]
{
Engine {
ffi: vm::FfiFactory::with_user_data(data),
}
}
#[cfg(feature = "go_std")]
{
let mut e = Engine {
ffi: vm::FfiFactory::with_user_data(data),
};
crate::std::register(&mut e.ffi);
e
}
}
#[cfg(feature = "go_std")]
pub fn set_std_io(
&self,
std_in: Option<Box<dyn std::io::Read + Sync + Send>>,
std_out: Option<Box<dyn std::io::Write + Sync + Send>>,
std_err: Option<Box<dyn std::io::Write + Sync + Send>>,
) {
os::set_std_io(std_in, std_out, std_err);
}
pub fn register_extension(&mut self, name: &'static str, proto: Rc<dyn Ffi>) {
self.ffi.register(name, proto);
}
#[cfg(feature = "codegen")]
pub fn compile<S: SourceRead>(
&self,
trace_parser: bool,
trace_checker: bool,
reader: &S,
path: &Path,
) -> Result<(vm::Bytecode, parser::FileSet), parser::ErrorList> {
let cfg = types::TraceConfig {
trace_parser,
trace_checker,
};
let mut fs = parser::FileSet::new();
cg::parse_check_gen(path, &cfg, reader, &mut fs).map(|x| (x, fs))
}
#[cfg(all(feature = "codegen", feature = "serde_borsh"))]
pub fn compile_serialize<S: SourceRead>(
&self,
trace_parser: bool,
trace_checker: bool,
reader: &S,
path: &Path,
) -> Result<Vec<u8>, parser::ErrorList> {
self.compile(trace_parser, trace_checker, reader, path)
.map(|(code, _)| code.try_to_vec().unwrap())
}
pub fn run_bytecode(&self, bc: &vm::Bytecode) {
vm::run(bc, &self.ffi, None)
}
#[cfg(feature = "codegen")]
pub fn run_source<S: SourceRead>(
&self,
trace_parser: bool,
trace_checker: bool,
reader: &S,
path: &Path,
) -> Result<(), parser::ErrorList> {
self.compile(trace_parser, trace_checker, reader, path)
.map(|(code, fs)| {
#[cfg(feature = "serde_borsh")]
{
let encoded = code.try_to_vec().unwrap();
let decoded = go_vm::Bytecode::try_from_slice(&encoded).unwrap();
dbg!(encoded.len());
vm::run(&decoded, &self.ffi, Some(&fs))
}
#[cfg(not(feature = "serde_borsh"))]
{
vm::run(&code, &self.ffi, Some(&fs))
}
})
}
}