Browse Source

Preparing mutation with bugfix & enhancement in jit & parse

Yann Weber 1 year ago
parent
commit
fb42b293e8
9 changed files with 78 additions and 150 deletions
  1. 1
    1
      python_rpnexpr.c
  2. 42
    1
      rpn_jit.c
  3. 13
    1
      rpn_jit.h
  4. 0
    58
      rpn_mutation.c
  5. 0
    83
      rpn_mutation.h
  6. 1
    0
      rpn_parse.c
  7. 5
    3
      rpn_parse.h
  8. 12
    0
      tests/test_rpn.c
  9. 4
    3
      tests/tests_pyrpn.py

+ 1
- 1
python_rpnexpr.c View File

@@ -182,7 +182,7 @@ PyObject* rpnexpr_init_borrowing(rpn_expr_t *borrowed)
182 182
 		return NULL;
183 183
 	}
184 184
 
185
-	ret = PyObject_CallObject(&RPNExprType, args);
185
+	ret = PyObject_CallObject((PyObject*)&RPNExprType, args);
186 186
 	if(!ret || PyErr_Occurred())
187 187
 	{
188 188
 		Py_DECREF(args);

+ 42
- 1
rpn_jit.c View File

@@ -68,7 +68,13 @@ int rpn_expr_reinit(rpn_expr_t* expr)
68 68
 		return -1;
69 69
 	}
70 70
 #endif
71
-	bzero(expr->code_map, expr->code_map_sz);
71
+	if(_rpn_expr_reset_map(expr)  < 0)
72
+	{
73
+		snprintf(expr->err_reason, 128, 
74
+			"Unable to re-init code map : %s", strerror(errno));
75
+		expr->state = RPN_ERROR;
76
+		return -1;
77
+	}
72 78
 	bzero(expr->stack, sizeof(unsigned long) * expr->stack_sz);
73 79
 	if(_rpn_expr_init_map(expr) < 0)
74 80
 	{
@@ -81,6 +87,26 @@ int rpn_expr_reinit(rpn_expr_t* expr)
81 87
 	return 0;
82 88
 }
83 89
 
90
+int rpn_expr_tokens_updated(rpn_expr_t* expr)
91
+{
92
+	if(rpn_expr_reinit(expr) < 0)
93
+	{
94
+		return -1;
95
+	}
96
+	if(_rpn_expr_compile_tokens(expr) < 0)
97
+	{
98
+		expr->state = RPN_ERROR;
99
+		return -1;
100
+	}
101
+	if(expr->expr)
102
+	{
103
+		free(expr->expr);
104
+	}
105
+	expr->expr = rpn_tokenized_expr(&expr->toks, 0);
106
+	return 0;
107
+}
108
+
109
+
84 110
 int rpn_expr_compile(rpn_expr_t *expr, const char *code)
85 111
 {
86 112
 #ifdef DEBUG
@@ -502,3 +528,18 @@ int _rpn_expr_end_map(rpn_expr_t *expr)
502 528
 	return 0;
503 529
 }
504 530
 
531
+int _rpn_expr_reset_map(rpn_expr_t *expr)
532
+{
533
+	if(!expr->code_map_sz)
534
+	{
535
+		return _rpn_expr_init_map(expr);
536
+	}
537
+	if(mprotect(expr->code_map, expr->code_map_sz,
538
+			PROT_READ | PROT_WRITE))
539
+	{
540
+		return -1;
541
+	}
542
+	bzero(expr->code_map, expr->code_map_sz);
543
+	return 0;
544
+}
545
+

+ 13
- 1
rpn_jit.h View File

@@ -152,6 +152,12 @@ int rpn_expr_init(rpn_expr_t* expr, const unsigned char stack_sz,
152 152
  */
153 153
 int rpn_expr_reinit(rpn_expr_t* expr);
154 154
 
155
+/**@brief Takes into account modifications in token representation
156
+ * @param rpn_expr_t*
157
+ * @return 0 if no error else -1
158
+ */
159
+int rpn_expr_tokens_updated(rpn_expr_t* expr);
160
+
155 161
 /**@brief Starts a new initialized expression from an expression string
156 162
  * @param expr Pointer on an intialized expression ( see @ref rpn_expr_init )
157 163
  * @param code '\0' terminated string representing the RPN expr
@@ -190,7 +196,7 @@ char* rpn_random(size_t op_sz, size_t args_count);
190 196
  * @ingroup rpn_compile
191 197
  */
192 198
 int _rpn_expr_compile_expr(rpn_expr_t* expr);
193
-/**@brief Compile an new RPN expression from string expression
199
+/**@brief Compile an new RPN expression from tokens
194 200
  * @param expr Pointer on @ref rpn_expr_s
195 201
  * @return 0 if no error else -1 and set @ref rpn_expr_s err_reason
196 202
  * @ingroup rpn_compile
@@ -255,4 +261,10 @@ int _rpn_expr_init_map(rpn_expr_t* expr);
255 261
  */
256 262
 int _rpn_expr_end_map(rpn_expr_t *expr);
257 263
 
264
+/**@brief Reset the memory map, filling it with zeroes and reseting permissions
265
+ * @param rpn_expr_t*
266
+ * @return 0 if no error else -1
267
+ */
268
+int _rpn_expr_reset_map(rpn_expr_t *expr);
269
+
258 270
 #endif

+ 0
- 58
rpn_mutation.c View File

@@ -1,58 +0,0 @@
1
-/*
2
- * Copyright (C) 2020 Weber Yann
3
- * 
4
- * This file is part of pyrpn.
5
- * 
6
- * pyrpn is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation, either version 3 of the License, or
9
- * any later version.
10
- * 
11
- * pyrpn is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- * GNU General Public License for more details.
15
- * 
16
- * You should have received a copy of the GNU General Public License
17
- * along with pyrpn.  If not, see <http://www.gnu.org/licenses/>.
18
- */
19
-#include "rpn_mutation.h"
20
-
21
-/**@file rpn_mutation.c
22
- * @todo continue implementation */
23
-
24
-const rpn_mutation_profile_t rpn_default_mutprof = {16,
25
-	{	RPN_del, RPN_del,
26
-		RPN_add, RPN_add,
27
-		RPN_chg, RPN_chg, RPN_chg, RPN_chg, RPN_chg, RPN_chg,
28
-		RPN_upd, RPN_upd, RPN_upd, RPN_upd, RPN_upd, RPN_upd}
29
-};
30
-
31
-rpn_expr_t* rpn_expr_mutation(rpn_expr_t *src, size_t mutations)
32
-{
33
-	return rpn_expr_mutation_p(src, mutations, &rpn_default_mutprof);
34
-}
35
-
36
-rpn_expr_t* rpn_expr_mutation_p(rpn_expr_t *src, size_t mutations,
37
-		const rpn_mutation_profile_t *prof)
38
-{
39
-	unsigned char op;
40
-	
41
-	prof = prof?prof:&rpn_default_mutprof;
42
-
43
-	op = prof->mods[(int)(drand48() / (1.0 / prof->mods_sz))];
44
-	switch(op)
45
-	{
46
-		case 0: // add a token
47
-			break;
48
-		case 1: // delete a token
49
-			break;
50
-		case 2: // update token type
51
-			break;
52
-		default: // update token, same type
53
-			break;
54
-	}
55
-	return NULL;
56
-}
57
-
58
-

+ 0
- 83
rpn_mutation.h View File

@@ -1,83 +0,0 @@
1
-/*
2
- * Copyright (C) 2020 Weber Yann
3
- * 
4
- * This file is part of pyrpn.
5
- * 
6
- * pyrpn is free software: you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation, either version 3 of the License, or
9
- * any later version.
10
- * 
11
- * pyrpn is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
- * GNU General Public License for more details.
15
- * 
16
- * You should have received a copy of the GNU General Public License
17
- * along with pyrpn.  If not, see <http://www.gnu.org/licenses/>.
18
- */
19
-#ifndef __rpn_mutation__h__
20
-#define __rpn_mutation__h__
21
-
22
-#include <stddef.h>
23
-
24
-#include "rpn_jit.h"
25
-
26
-/**@defgroup mutation RPN expression mutation
27
- * @ingroup rpn
28
- */
29
-/**@file rpn_mutation.h
30
- * @brief Contains structures and function to mutate RPN epxressions
31
- */
32
-
33
-
34
-/**@brief Defines mutation actions types */
35
-enum rpn_mutation_op_e {
36
-	/**@brief Mutation action : delete a token */
37
-	RPN_del,
38
-	/**@brief Mutation action : add a token */
39
-	RPN_add,
40
-	/**@brief Mutation action : change a token */
41
-	RPN_chg,
42
-	/**@brief Mutation action : update a token (same type, different value) */
43
-	RPN_upd
44
-};
45
-
46
-/**@brief Shortcut for struct @ref rpn_mutation_profile_s */
47
-typedef struct rpn_mutation_profile_s rpn_mutation_profile_t;
48
-
49
-/**@brief Stores mutation informations
50
- * @ingroup mutation
51
- */
52
-struct rpn_mutation_profile_s
53
-{
54
-	/**@brief Size of @ref rpn_mutation_profile_s::mods attribute */
55
-	size_t mods_sz;
56
-
57
-	/**@brief Modification possibilities
58
-	 *
59
-	 * One value is picked up randomly from this list to determine
60
-	 * the type of mutation : addition, deletion, modification, value change
61
-	 */
62
-	unsigned char mods[];
63
-};
64
-
65
-/**@brief Default mutation profile */
66
-extern const rpn_mutation_profile_t rpn_default_mutprof;
67
-
68
-/**@brief Shortcut for @ref rpn_expr_mutation_p with a @ref rpn_default_mutprof
69
- * @ingroup mutation */
70
-rpn_expr_t* rpn_expr_mutation(rpn_expr_t *src, size_t mutations);
71
-
72
-/**@brief Generate a new expression by applying mutations to a source
73
- * expression
74
- * @param src Source expression
75
- * @param mutations number of mutations
76
- * @param prof Mutation profile
77
- * @return A new instance of rpn_expr_t ready to be evaluate
78
- * @ingroup mutation
79
- */
80
-rpn_expr_t* rpn_expr_mutation_p(rpn_expr_t *src, size_t mutations,
81
-	const rpn_mutation_profile_t *prof);
82
-
83
-#endif

+ 1
- 0
rpn_parse.c View File

@@ -42,6 +42,7 @@ const rpn_op_t rpn_ops[] = {\
42 42
 	__op(rpn_pop_op, 'p', "pop"),\
43 43
 };
44 44
 #undef __op
45
+const size_t RPN_OP_SZ = (sizeof(rpn_ops) / sizeof(rpn_op_t));
45 46
 
46 47
 int rpn_tokenizer_start(rpn_tokenizer_t *tokenizer, rpn_tokenized_t *dst,
47 48
 	const char* expr, size_t argc)

+ 5
- 3
rpn_parse.h View File

@@ -49,7 +49,7 @@
49 49
  */
50 50
 
51 51
 /**@brief Shortcut for loop on all operations list */
52
-#define foreach_rpn_ops(IDX) for(IDX=0; IDX<rpn_op_sz(); IDX++)
52
+#define foreach_rpn_ops(IDX) for(IDX=0; IDX<RPN_OP_SZ; IDX++)
53 53
 
54 54
 /**@brief Check if a tokenizer is in error state
55 55
  * @param tokenizer Pointer on a @ref rpn_tokenizer_s
@@ -92,7 +92,7 @@ enum rpn_token_type_e {
92 92
 	/**@brief The token is an argument */
93 93
 	RPN_arg,
94 94
 	/**@brief The token is a value */
95
-	RPN_val
95
+	RPN_val,
96 96
 };
97 97
 
98 98
 /**@brief Represent an expression token (value, argument or operation)
@@ -164,6 +164,8 @@ struct rpn_tokenizer_s
164 164
  * Stores operation identification informations
165 165
  * @ingroup rpn_tokenize */
166 166
 extern const rpn_op_t rpn_ops[];
167
+extern const size_t RPN_OP_SZ;
168
+
167 169
 
168 170
 /**@brief Initialize a tokenizer and a tokenized representation
169 171
  * @param tokenizer Pointer on a new tokenizer
@@ -205,7 +207,7 @@ void rpn_tokenizer_free(rpn_tokenizer_t *tokenizer);
205 207
  */
206 208
 int rpn_tokenize(const char *token, rpn_token_t *dst, char error[64]);
207 209
 
208
-/**@brief Represented a tokenized expression in a string
210
+/**@brief Represent a tokenized expression in a string
209 211
  * @param tokens Tokenized expression
210 212
  * @param long_op If true uses @ref rpn_op_s::str else @ref rpn_op_s::chr
211 213
  * @return A newly allocated char* that should be deallocated using free()

+ 12
- 0
tests/test_rpn.c View File

@@ -113,6 +113,18 @@ int test_add()
113 113
 			res);
114 114
 		return 2;
115 115
 	}
116
+	
117
+	// test token update
118
+	expr.toks.tokens[0].value = 15;
119
+	rpn_expr_tokens_updated(&expr);
120
+	res = rpn_expr_eval(&expr, NULL);
121
+	//printf("Result = %ld\n", res);
122
+	if(res != 41)
123
+	{
124
+		dprintf(2, "Error : expected 42 but %ld received\n",
125
+			res);
126
+		return 3;
127
+	}
116 128
 	rpn_expr_close(&expr);
117 129
 	return 0;
118 130
 }

+ 4
- 3
tests/tests_pyrpn.py View File

@@ -65,10 +65,11 @@ class Test0RpnModule(unittest.TestCase):
65 65
 
66 66
     def test_init_badargs(self):
67 67
         """ RPNExpr instanciation with bad arguments """
68
-        badargs = [('', 2), (), ('ab+',), ('ab+',300), (42, 42), ('ab', '42')]
68
+        badargs = [(), ('ab+',), ('ab+',300), (42, 42), ('ab', '42')]
69 69
         for badarg in badargs:
70
-           with self.assertRaises((ValueError, TypeError)):
71
-            expr = pyrpn.RPNExpr(*badarg)
70
+           with self.subTest(badargs=badarg):
71
+             with self.assertRaises((ValueError, TypeError)):
72
+              expr = pyrpn.RPNExpr(*badarg)
72 73
 
73 74
     def test_init_loop(self):
74 75
         """ Testing pyrpn.RPNExpr multiple instanciation """

Loading…
Cancel
Save