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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
use crate::multistackvm::VM;
use rust_dynamic::value::Value;
use rust_dynamic::types::*;
use easy_error::{Error, bail};
fn if_object_of_class_in_stack(vm: &mut VM, name: String) -> bool {
if vm.stack.current_stack_len() < 1 {
return false;
}
let obj = match vm.stack.peek() {
Some(obj) => obj,
None => return false,
};
if obj.type_of() == OBJECT {
return match obj.get(".class_name") {
Ok(class_name_value) => match class_name_value.cast_string() {
Ok(class_name) => class_name == name,
Err(_) => false,
},
Err(_) => false,
};
} else {
return false;
}
}
fn make_bund_object(vm: &mut VM, name: String, value: Value) -> Result<Value, Error> {
match value.type_of() {
CLASS => {
let mut res = match value.dup() {
Ok(res) => res,
Err(err) => bail!("VM error running DUP for the CLASS in OBJECT creation: {}", err),
};
log::debug!("Creating object from class: {}", &name);
res.dt = OBJECT;
res = res.set(".class_name", Value::from_string(name.clone()));
let mut super_list = Value::list();
let super_classes = match value.get(".super") {
Ok(super_classes) => super_classes,
Err(_) => Value::list(),
};
for o in super_classes {
match o.cast_string() {
Ok(class_name) => {
if vm.is_class(class_name.clone()) {
let parent_value = match vm.get_class(class_name.clone()) {
Ok(class_value) => class_value,
Err(err) => bail!("VM error getting class {}: {}", &class_name, err),
};
match make_bund_object(vm, class_name.clone(), parent_value) {
Ok(parent_object) => {
let init_lambda = match parent_object.get(".init") {
Ok(init_lambda) => init_lambda,
Err(_) => Value::lambda(),
};
vm.stack.push(parent_object.clone());
match init_lambda.type_of() {
PTR => {
let init_method_name = match init_lambda.cast_string() {
Ok(init_method_name) => init_method_name,
Err(err) => bail!("Error casting init method name: {}", err),
};
if vm.is_method(init_method_name.clone()) {
match vm.get_method(init_method_name.clone()) {
Ok(init_method) => {
match init_method(vm) {
Ok(_) => {},
Err(err) => bail!("CLASS {} constructor returns: {}", &class_name, err),
};
}
Err(err) => bail!("Error getting constructor for class {}: {}", &class_name, err),
}
}
}
LAMBDA => {
match vm.lambda_eval(init_lambda) {
Ok(_) => {},
Err(err) => bail!("CLASS {} LAMBDA constructor returns: {}", &class_name, err),
};
}
_ => log::debug!("Constructor for the class {} is not STRING or LAMBDA", &class_name),
}
if if_object_of_class_in_stack(vm, class_name.clone()) {
match vm.stack.pull() {
Some(parent_object_in_stack) => {
super_list = super_list.push(parent_object_in_stack);
}
None => {
super_list = super_list.push(parent_object);
}
}
} else {
super_list = super_list.push(parent_object);
}
}
Err(err) => bail!("VM error making parent object {}: {}", &class_name, err),
}
} else {
bail!("OBJECT class {} not registered", &name);
}
}
Err(err) => bail!("VM error casting class name: {}", err),
}
}
res = res.set(".super", super_list);
return Ok(res);
}
OBJECT => {
return Ok(value);
}
_ => bail!("VM source object for creating OBJECT is of incorrect type"),
}
}
pub fn stdlib_object_inline(vm: &mut VM) -> Result<&mut VM, Error> {
if vm.stack.current_stack_len() < 1 {
bail!("Stack is too shallow for inline object()");
}
match vm.stack.pull() {
Some(name_value) => {
match name_value.cast_string() {
Ok(name) => {
if vm.is_class(name.clone()) {
let object_value_res = match vm.get_class(name.clone()) {
Ok(class_value) => make_bund_object(vm, name.clone(), class_value),
Err(err) => bail!("VM error making object from class {}: {}", &name, err),
};
let object_value = match object_value_res {
Ok(object_value) => object_value,
Err(err) => bail!("VM OBJECT returns error: {}", err),
};
vm.stack.push(object_value.clone());
let init_lambda = match object_value.get(".init") {
Ok(init_lambda) => init_lambda,
Err(_) => Value::lambda(),
};
match init_lambda.type_of() {
PTR => {
let init_method_name = match init_lambda.cast_string() {
Ok(init_method_name) => init_method_name,
Err(err) => bail!("Error casting init method name: {}", err),
};
if vm.is_method(init_method_name.clone()) {
match vm.get_method(init_method_name.clone()) {
Ok(init_method) => {
match init_method(vm) {
Ok(_) => {},
Err(err) => bail!("CLASS {} constructor returns: {}", &name, err),
};
}
Err(err) => bail!("Error getting constructor for class {}: {}", &name, err),
}
}
}
LAMBDA => {
match vm.lambda_eval(init_lambda) {
Ok(_) => {},
Err(err) => bail!("CLASS {} LAMBDA constructor returns: {}", &name, err),
};
}
_ => log::debug!("Constructor for the class {} is not STRING or LAMBDA", &name),
}
if if_object_of_class_in_stack(vm, name.clone()) {
match vm.stack.pull() {
Some(object_value_in_stack) => {
return vm.apply(object_value_in_stack);
}
None => {
return vm.apply(object_value);
}
}
} else {
return vm.apply(object_value);
}
} else {
bail!("OBJECT class {} not registered", &name);
}
}
Err(err) => {
bail!("OBJECT returns error: {}", err);
}
}
}
None => {
bail!("OBJECT returns: NO DATA");
}
}
}
pub fn init_stdlib(vm: &mut VM) {
let _ = vm.register_inline("object".to_string(), stdlib_object_inline);
}