-
Notifications
You must be signed in to change notification settings - Fork 1
/
lib.rs
127 lines (104 loc) · 4.39 KB
/
lib.rs
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
mod external_functions;
use ext_php_rs::prelude::*;
use ext_php_rs::types::{ZendHashTable, Zval};
use santa_lang::{AoCRunner, Environment, Evaluator, Lexer, Parser, RunEvaluation, Time};
use std::time::{SystemTime, UNIX_EPOCH};
struct PhpTime {}
impl Time for PhpTime {
fn now(&self) -> u128 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis()
}
}
#[php_function(optional = "cwd")]
pub fn santa_aoc_run(source: &str, cwd: Option<String>) -> PhpResult<Zval> {
if let Some(dir) = cwd {
std::env::set_current_dir(dir).unwrap();
}
let mut runner = AoCRunner::new_with_external_functions(PhpTime {}, &crate::external_functions::definitions());
match runner.run(source) {
Ok(RunEvaluation::Script(result)) => {
let mut result_ht = ZendHashTable::new();
result_ht.insert("value", result.value)?;
result_ht.insert("duration", result.duration as u64)?;
let mut output_ht = ZendHashTable::new();
output_ht.insert("result", result_ht)?;
let mut zval = Zval::new();
zval.set_hashtable(output_ht);
Ok(zval)
}
Ok(RunEvaluation::Solution { part_one, part_two }) => {
let mut output_ht = ZendHashTable::new();
if let Some(part_one) = part_one {
let mut part_one_ht = ZendHashTable::new();
part_one_ht.insert("value", part_one.value)?;
part_one_ht.insert("duration", part_one.duration as u64)?;
output_ht.insert("part_one", part_one_ht)?;
}
if let Some(part_two) = part_two {
let mut part_two_ht = ZendHashTable::new();
part_two_ht.insert("value", part_two.value)?;
part_two_ht.insert("duration", part_two.duration as u64)?;
output_ht.insert("part_two", part_two_ht)?;
}
let mut zval = Zval::new();
zval.set_hashtable(output_ht);
Ok(zval)
}
Err(error) => Err(error.message.into()),
}
}
#[php_function(optional = "cwd")]
pub fn santa_aoc_test(source: &str, cwd: Option<String>) -> PhpResult<Zval> {
if let Some(dir) = cwd {
std::env::set_current_dir(dir).unwrap();
}
let mut runner = AoCRunner::new_with_external_functions(PhpTime {}, &crate::external_functions::definitions());
match runner.test(source) {
Ok(test_cases) => {
let mut output_ht = ZendHashTable::new();
for test_case in test_cases {
let mut test_case_ht = ZendHashTable::new();
if let Some(part_one) = test_case.part_one {
let mut part_one_ht = ZendHashTable::new();
part_one_ht.insert("actual", part_one.actual)?;
part_one_ht.insert("expected", part_one.expected)?;
part_one_ht.insert("passed", part_one.passed)?;
test_case_ht.insert("part_one", part_one_ht)?;
}
if let Some(part_two) = test_case.part_two {
let mut part_two_ht = ZendHashTable::new();
part_two_ht.insert("actual", part_two.actual)?;
part_two_ht.insert("expected", part_two.expected)?;
part_two_ht.insert("passed", part_two.passed)?;
test_case_ht.insert("part_two", part_two_ht)?;
}
output_ht.push(test_case_ht)?;
}
let mut zval = Zval::new();
zval.set_hashtable(output_ht);
Ok(zval)
}
Err(error) => Err(error.message.into()),
}
}
#[php_function(optional = "cwd")]
pub fn santa_evaluate(expression: &str, cwd: Option<String>) -> PhpResult<String> {
if let Some(dir) = cwd {
std::env::set_current_dir(dir).unwrap();
}
let mut evaluator = Evaluator::new_with_external_functions(&crate::external_functions::definitions());
let lexer = Lexer::new(expression);
let mut parser = Parser::new(lexer);
let program = parser.parse().map_err(|error| error.message)?;
match evaluator.evaluate_with_environment(&program, Environment::new()) {
Ok(evaluated) => Ok(evaluated.to_string()),
Err(error) => Err(error.message.into()),
}
}
#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
module
}