/
pro_number.c
142 lines (108 loc) · 3.36 KB
/
pro_number.c
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
#include "pro_number.h"
#include "pro_string.h"
#include "prosopon/prosopon_stdlib.h"
#include "prosopon/prosopon_macros.h"
#include <assert.h>
#include <string.h>
#include <stdio.h>
#pragma mark Private
typedef enum
{
ADD_BINARY_OP,
SUB_BINARY_OP,
MUL_BINARY_OP,
DIV_BINARY_OP
} BINARY_OP;
static void math(pro_state_ref s, pro_ref t, pro_ref data, pro_ref msg, BINARY_OP op)
{
pro_ref val, cust;
pro_list_get(s, msg, 1, &val);
pro_list_get(s, msg, 2, &cust);
pro_ref val_data;
pro_actor_request_ud(s, val, &val_data);
const double d1 = pro_ud_get_number_value(s, data);
const double d2 = pro_ud_get_number_value(s, val_data);
pro_ref result;
switch (op)
{
case ADD_BINARY_OP: result = pro_number_create(s, d1 + d2); break;
case SUB_BINARY_OP: result = pro_number_create(s, d1 - d2); break;
case MUL_BINARY_OP: result = pro_number_create(s, d1 * d2); break;
case DIV_BINARY_OP: result = pro_number_create(s, d1 / d2); break;
}
pro_ref response;
pro_list_create(s, &response);
pro_list_append_inplace(s, &response, result);
pro_release(s, result);
pro_release(s, val);
pro_send(s, cust, response);
pro_release(s, cust);
pro_release(s, response);
}
static void behavior_impl(pro_state_ref s,
pro_ref t, pro_ref msg, pro_ref data)
{
unsigned int msg_length;
pro_list_length(s, msg, &msg_length);
switch (msg_length)
{
case 3:
{
pro_ref first;
pro_list_get(s, msg, 0, &first);
if (pro_match_string(s, first, "+"))
math(s, t, data, msg, ADD_BINARY_OP);
else if (pro_match_string(s, first, "-"))
math(s, t, data, msg, SUB_BINARY_OP);
else if (pro_match_string(s, first, "*"))
math(s, t, data, msg, MUL_BINARY_OP);
else if (pro_match_string(s, first, "/"))
math(s, t, data, msg, DIV_BINARY_OP);
pro_release(s, first);
} break;
default:break;
}
}
static pro_matching match(pro_state_ref s,
pro_ref t, pro_ref tData, pro_ref o, pro_ref oData)
{
pro_type t_primitive_type;
pro_get_type(s, t, &t_primitive_type);
assert(PRO_ACTOR_TYPE == t_primitive_type);
pro_type o_primitive_type;
pro_get_type(s, o, &o_primitive_type);
if (o_primitive_type != PRO_ACTOR_TYPE)
return 0;
const double d1 = pro_ud_get_number_value(s, tData);
const double d2 = pro_ud_get_number_value(s, oData);
return d1 == d2 ? PRO_MATCH_SUCCEED : PRO_MATCH_FAIL;
}
static pro_ref to_string(pro_state_ref s,
pro_ref t, pro_ref tData)
{
const double* n;
pro_ud_read(s, tData, (const void**)&n);
char* buffer;
pro_ref ud;
pro_ud_create(s, sizeof(*buffer) * (32 + 1), PRO_DEFAULT_UD_DECONSTRUCTOR, &ud);
pro_ud_write(s, ud, (void**)&buffer);
snprintf(buffer, 32, "%g", *n);
return ud;
}
#pragma mark -
#pragma mark Internal
pro_actor_type pro_number_actor_type = "number";
const pro_actor_type_info pro_number_type_info = {
.match = match,
.to_string = to_string
};
#pragma mark -
#pragma mark Public
PRO_LIBCORE pro_ref pro_number_create(pro_state_ref s, double data)
{
pro_ref actor;
pro_ref ud = pro_number_ud_create(s, data);
pro_actor_create(s, pro_number_actor_type, behavior_impl, ud, &actor);
pro_release(s, ud);
return actor;
}