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
//! # ksl::builtin::thread
//!
//! Built-in function `Thread`.
use crate::{
Environment,
INIT_STACK_SIZE,
eval::apply::eval_apply,
init_environment,
is_invalid_symbol,
read_from_environment,
value::Value,
};
pub(crate) fn builtin(args: &[Value], env: Environment) -> Result<Value, std::sync::Arc<str>> {
if let [symbol, syms, applicable] = args {
let var_name = match symbol {
Value::Symbol(var) => {
if is_invalid_symbol(var) {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Thread]: ",
"Rebinding of symbol `{}` is not permitted."
),
var
)));
}
var.clone()
}
e => {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Thread]: ",
"Expected a Symbol for thread name, but got `{}`."
),
e
)));
}
};
// thread environment
let thread_env = init_environment(None);
match syms {
Value::List(symbols) => {
// capture symbols
for symbol in symbols.iter() {
match symbol {
Value::Symbol(name) => {
if let Some(val) = read_from_environment(&env, name) {
let _ = thread_env.store.write().insert(name.clone(), val);
} else {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Thread]: ",
"Unknown symbol `{}` in capture list."
),
name
)));
}
}
e => {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Thread]: ",
"Unexpected value in capture list: `{}`."
),
e
)));
}
}
}
}
e => {
return Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Thread]: ",
"Expected a List of symbols to capture, but got `{}`."
),
e
)));
}
}
// prepare execution body
let execution_node = match applicable {
Value::Symbol(func_sym) => match read_from_environment(&env, func_sym) {
Some(func_body) => Value::Apply(Vec::new(), func_body),
None => {
return Err(std::sync::Arc::from(format!(
"Error[ksl::builtin::Thread]: Unknown function symbol `{}`.",
func_sym
)));
}
},
node @ Value::Apply(_, _) => node.clone(),
func @ (Value::Lambda(_, _, _) | Value::Plugin(_, _)) => {
Value::Apply(Vec::new(), std::sync::Arc::new(func.clone()))
}
e => {
return Err(std::sync::Arc::from(format!(
"Error[ksl::builtin::Thread]: Invalid applicable value: `{}`.",
e
)));
}
};
// start thread
let thread_handle_res = std::thread::Builder::new()
.stack_size(INIT_STACK_SIZE)
.spawn(move || eval_apply(&execution_node, thread_env));
match thread_handle_res {
Ok(handle) => {
let _ = env.store.write().insert(
var_name,
std::sync::Arc::new(Value::Thread(std::sync::Arc::new(parking_lot::Mutex::new(
Some(handle),
)))),
);
Ok(Value::Unit)
}
Err(e) => Err(std::sync::Arc::from(format!(
"Error[ksl::builtin::Thread]: Failed to spawn thread: `{}`.",
e
))),
}
} else {
Err(std::sync::Arc::from(format!(
"Error[ksl::builtin::Thread]: Expected 3 parameters, but {} were passed.",
args.len()
)))
}
}