Preparing mutation with bugfix & enhancement in jit & parse
This commit is contained in:
parent
3097c98237
commit
fb42b293e8
9 changed files with 78 additions and 150 deletions
|
|
@ -182,7 +182,7 @@ PyObject* rpnexpr_init_borrowing(rpn_expr_t *borrowed)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = PyObject_CallObject(&RPNExprType, args);
|
ret = PyObject_CallObject((PyObject*)&RPNExprType, args);
|
||||||
if(!ret || PyErr_Occurred())
|
if(!ret || PyErr_Occurred())
|
||||||
{
|
{
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
|
|
|
||||||
43
rpn_jit.c
43
rpn_jit.c
|
|
@ -68,7 +68,13 @@ int rpn_expr_reinit(rpn_expr_t* expr)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bzero(expr->code_map, expr->code_map_sz);
|
if(_rpn_expr_reset_map(expr) < 0)
|
||||||
|
{
|
||||||
|
snprintf(expr->err_reason, 128,
|
||||||
|
"Unable to re-init code map : %s", strerror(errno));
|
||||||
|
expr->state = RPN_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
bzero(expr->stack, sizeof(unsigned long) * expr->stack_sz);
|
bzero(expr->stack, sizeof(unsigned long) * expr->stack_sz);
|
||||||
if(_rpn_expr_init_map(expr) < 0)
|
if(_rpn_expr_init_map(expr) < 0)
|
||||||
{
|
{
|
||||||
|
|
@ -81,6 +87,26 @@ int rpn_expr_reinit(rpn_expr_t* expr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rpn_expr_tokens_updated(rpn_expr_t* expr)
|
||||||
|
{
|
||||||
|
if(rpn_expr_reinit(expr) < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(_rpn_expr_compile_tokens(expr) < 0)
|
||||||
|
{
|
||||||
|
expr->state = RPN_ERROR;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(expr->expr)
|
||||||
|
{
|
||||||
|
free(expr->expr);
|
||||||
|
}
|
||||||
|
expr->expr = rpn_tokenized_expr(&expr->toks, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int rpn_expr_compile(rpn_expr_t *expr, const char *code)
|
int rpn_expr_compile(rpn_expr_t *expr, const char *code)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
@ -502,3 +528,18 @@ int _rpn_expr_end_map(rpn_expr_t *expr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _rpn_expr_reset_map(rpn_expr_t *expr)
|
||||||
|
{
|
||||||
|
if(!expr->code_map_sz)
|
||||||
|
{
|
||||||
|
return _rpn_expr_init_map(expr);
|
||||||
|
}
|
||||||
|
if(mprotect(expr->code_map, expr->code_map_sz,
|
||||||
|
PROT_READ | PROT_WRITE))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bzero(expr->code_map, expr->code_map_sz);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
14
rpn_jit.h
14
rpn_jit.h
|
|
@ -152,6 +152,12 @@ int rpn_expr_init(rpn_expr_t* expr, const unsigned char stack_sz,
|
||||||
*/
|
*/
|
||||||
int rpn_expr_reinit(rpn_expr_t* expr);
|
int rpn_expr_reinit(rpn_expr_t* expr);
|
||||||
|
|
||||||
|
/**@brief Takes into account modifications in token representation
|
||||||
|
* @param rpn_expr_t*
|
||||||
|
* @return 0 if no error else -1
|
||||||
|
*/
|
||||||
|
int rpn_expr_tokens_updated(rpn_expr_t* expr);
|
||||||
|
|
||||||
/**@brief Starts a new initialized expression from an expression string
|
/**@brief Starts a new initialized expression from an expression string
|
||||||
* @param expr Pointer on an intialized expression ( see @ref rpn_expr_init )
|
* @param expr Pointer on an intialized expression ( see @ref rpn_expr_init )
|
||||||
* @param code '\0' terminated string representing the RPN expr
|
* @param code '\0' terminated string representing the RPN expr
|
||||||
|
|
@ -190,7 +196,7 @@ char* rpn_random(size_t op_sz, size_t args_count);
|
||||||
* @ingroup rpn_compile
|
* @ingroup rpn_compile
|
||||||
*/
|
*/
|
||||||
int _rpn_expr_compile_expr(rpn_expr_t* expr);
|
int _rpn_expr_compile_expr(rpn_expr_t* expr);
|
||||||
/**@brief Compile an new RPN expression from string expression
|
/**@brief Compile an new RPN expression from tokens
|
||||||
* @param expr Pointer on @ref rpn_expr_s
|
* @param expr Pointer on @ref rpn_expr_s
|
||||||
* @return 0 if no error else -1 and set @ref rpn_expr_s err_reason
|
* @return 0 if no error else -1 and set @ref rpn_expr_s err_reason
|
||||||
* @ingroup rpn_compile
|
* @ingroup rpn_compile
|
||||||
|
|
@ -255,4 +261,10 @@ int _rpn_expr_init_map(rpn_expr_t* expr);
|
||||||
*/
|
*/
|
||||||
int _rpn_expr_end_map(rpn_expr_t *expr);
|
int _rpn_expr_end_map(rpn_expr_t *expr);
|
||||||
|
|
||||||
|
/**@brief Reset the memory map, filling it with zeroes and reseting permissions
|
||||||
|
* @param rpn_expr_t*
|
||||||
|
* @return 0 if no error else -1
|
||||||
|
*/
|
||||||
|
int _rpn_expr_reset_map(rpn_expr_t *expr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Weber Yann
|
|
||||||
*
|
|
||||||
* This file is part of pyrpn.
|
|
||||||
*
|
|
||||||
* pyrpn is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* pyrpn is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include "rpn_mutation.h"
|
|
||||||
|
|
||||||
/**@file rpn_mutation.c
|
|
||||||
* @todo continue implementation */
|
|
||||||
|
|
||||||
const rpn_mutation_profile_t rpn_default_mutprof = {16,
|
|
||||||
{ RPN_del, RPN_del,
|
|
||||||
RPN_add, RPN_add,
|
|
||||||
RPN_chg, RPN_chg, RPN_chg, RPN_chg, RPN_chg, RPN_chg,
|
|
||||||
RPN_upd, RPN_upd, RPN_upd, RPN_upd, RPN_upd, RPN_upd}
|
|
||||||
};
|
|
||||||
|
|
||||||
rpn_expr_t* rpn_expr_mutation(rpn_expr_t *src, size_t mutations)
|
|
||||||
{
|
|
||||||
return rpn_expr_mutation_p(src, mutations, &rpn_default_mutprof);
|
|
||||||
}
|
|
||||||
|
|
||||||
rpn_expr_t* rpn_expr_mutation_p(rpn_expr_t *src, size_t mutations,
|
|
||||||
const rpn_mutation_profile_t *prof)
|
|
||||||
{
|
|
||||||
unsigned char op;
|
|
||||||
|
|
||||||
prof = prof?prof:&rpn_default_mutprof;
|
|
||||||
|
|
||||||
op = prof->mods[(int)(drand48() / (1.0 / prof->mods_sz))];
|
|
||||||
switch(op)
|
|
||||||
{
|
|
||||||
case 0: // add a token
|
|
||||||
break;
|
|
||||||
case 1: // delete a token
|
|
||||||
break;
|
|
||||||
case 2: // update token type
|
|
||||||
break;
|
|
||||||
default: // update token, same type
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2020 Weber Yann
|
|
||||||
*
|
|
||||||
* This file is part of pyrpn.
|
|
||||||
*
|
|
||||||
* pyrpn is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* any later version.
|
|
||||||
*
|
|
||||||
* pyrpn is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with pyrpn. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#ifndef __rpn_mutation__h__
|
|
||||||
#define __rpn_mutation__h__
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include "rpn_jit.h"
|
|
||||||
|
|
||||||
/**@defgroup mutation RPN expression mutation
|
|
||||||
* @ingroup rpn
|
|
||||||
*/
|
|
||||||
/**@file rpn_mutation.h
|
|
||||||
* @brief Contains structures and function to mutate RPN epxressions
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**@brief Defines mutation actions types */
|
|
||||||
enum rpn_mutation_op_e {
|
|
||||||
/**@brief Mutation action : delete a token */
|
|
||||||
RPN_del,
|
|
||||||
/**@brief Mutation action : add a token */
|
|
||||||
RPN_add,
|
|
||||||
/**@brief Mutation action : change a token */
|
|
||||||
RPN_chg,
|
|
||||||
/**@brief Mutation action : update a token (same type, different value) */
|
|
||||||
RPN_upd
|
|
||||||
};
|
|
||||||
|
|
||||||
/**@brief Shortcut for struct @ref rpn_mutation_profile_s */
|
|
||||||
typedef struct rpn_mutation_profile_s rpn_mutation_profile_t;
|
|
||||||
|
|
||||||
/**@brief Stores mutation informations
|
|
||||||
* @ingroup mutation
|
|
||||||
*/
|
|
||||||
struct rpn_mutation_profile_s
|
|
||||||
{
|
|
||||||
/**@brief Size of @ref rpn_mutation_profile_s::mods attribute */
|
|
||||||
size_t mods_sz;
|
|
||||||
|
|
||||||
/**@brief Modification possibilities
|
|
||||||
*
|
|
||||||
* One value is picked up randomly from this list to determine
|
|
||||||
* the type of mutation : addition, deletion, modification, value change
|
|
||||||
*/
|
|
||||||
unsigned char mods[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**@brief Default mutation profile */
|
|
||||||
extern const rpn_mutation_profile_t rpn_default_mutprof;
|
|
||||||
|
|
||||||
/**@brief Shortcut for @ref rpn_expr_mutation_p with a @ref rpn_default_mutprof
|
|
||||||
* @ingroup mutation */
|
|
||||||
rpn_expr_t* rpn_expr_mutation(rpn_expr_t *src, size_t mutations);
|
|
||||||
|
|
||||||
/**@brief Generate a new expression by applying mutations to a source
|
|
||||||
* expression
|
|
||||||
* @param src Source expression
|
|
||||||
* @param mutations number of mutations
|
|
||||||
* @param prof Mutation profile
|
|
||||||
* @return A new instance of rpn_expr_t ready to be evaluate
|
|
||||||
* @ingroup mutation
|
|
||||||
*/
|
|
||||||
rpn_expr_t* rpn_expr_mutation_p(rpn_expr_t *src, size_t mutations,
|
|
||||||
const rpn_mutation_profile_t *prof);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -42,6 +42,7 @@ const rpn_op_t rpn_ops[] = {\
|
||||||
__op(rpn_pop_op, 'p', "pop"),\
|
__op(rpn_pop_op, 'p', "pop"),\
|
||||||
};
|
};
|
||||||
#undef __op
|
#undef __op
|
||||||
|
const size_t RPN_OP_SZ = (sizeof(rpn_ops) / sizeof(rpn_op_t));
|
||||||
|
|
||||||
int rpn_tokenizer_start(rpn_tokenizer_t *tokenizer, rpn_tokenized_t *dst,
|
int rpn_tokenizer_start(rpn_tokenizer_t *tokenizer, rpn_tokenized_t *dst,
|
||||||
const char* expr, size_t argc)
|
const char* expr, size_t argc)
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**@brief Shortcut for loop on all operations list */
|
/**@brief Shortcut for loop on all operations list */
|
||||||
#define foreach_rpn_ops(IDX) for(IDX=0; IDX<rpn_op_sz(); IDX++)
|
#define foreach_rpn_ops(IDX) for(IDX=0; IDX<RPN_OP_SZ; IDX++)
|
||||||
|
|
||||||
/**@brief Check if a tokenizer is in error state
|
/**@brief Check if a tokenizer is in error state
|
||||||
* @param tokenizer Pointer on a @ref rpn_tokenizer_s
|
* @param tokenizer Pointer on a @ref rpn_tokenizer_s
|
||||||
|
|
@ -92,7 +92,7 @@ enum rpn_token_type_e {
|
||||||
/**@brief The token is an argument */
|
/**@brief The token is an argument */
|
||||||
RPN_arg,
|
RPN_arg,
|
||||||
/**@brief The token is a value */
|
/**@brief The token is a value */
|
||||||
RPN_val
|
RPN_val,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**@brief Represent an expression token (value, argument or operation)
|
/**@brief Represent an expression token (value, argument or operation)
|
||||||
|
|
@ -164,6 +164,8 @@ struct rpn_tokenizer_s
|
||||||
* Stores operation identification informations
|
* Stores operation identification informations
|
||||||
* @ingroup rpn_tokenize */
|
* @ingroup rpn_tokenize */
|
||||||
extern const rpn_op_t rpn_ops[];
|
extern const rpn_op_t rpn_ops[];
|
||||||
|
extern const size_t RPN_OP_SZ;
|
||||||
|
|
||||||
|
|
||||||
/**@brief Initialize a tokenizer and a tokenized representation
|
/**@brief Initialize a tokenizer and a tokenized representation
|
||||||
* @param tokenizer Pointer on a new tokenizer
|
* @param tokenizer Pointer on a new tokenizer
|
||||||
|
|
@ -205,7 +207,7 @@ void rpn_tokenizer_free(rpn_tokenizer_t *tokenizer);
|
||||||
*/
|
*/
|
||||||
int rpn_tokenize(const char *token, rpn_token_t *dst, char error[64]);
|
int rpn_tokenize(const char *token, rpn_token_t *dst, char error[64]);
|
||||||
|
|
||||||
/**@brief Represented a tokenized expression in a string
|
/**@brief Represent a tokenized expression in a string
|
||||||
* @param tokens Tokenized expression
|
* @param tokens Tokenized expression
|
||||||
* @param long_op If true uses @ref rpn_op_s::str else @ref rpn_op_s::chr
|
* @param long_op If true uses @ref rpn_op_s::str else @ref rpn_op_s::chr
|
||||||
* @return A newly allocated char* that should be deallocated using free()
|
* @return A newly allocated char* that should be deallocated using free()
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,18 @@ int test_add()
|
||||||
res);
|
res);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test token update
|
||||||
|
expr.toks.tokens[0].value = 15;
|
||||||
|
rpn_expr_tokens_updated(&expr);
|
||||||
|
res = rpn_expr_eval(&expr, NULL);
|
||||||
|
//printf("Result = %ld\n", res);
|
||||||
|
if(res != 41)
|
||||||
|
{
|
||||||
|
dprintf(2, "Error : expected 42 but %ld received\n",
|
||||||
|
res);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
rpn_expr_close(&expr);
|
rpn_expr_close(&expr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,10 +65,11 @@ class Test0RpnModule(unittest.TestCase):
|
||||||
|
|
||||||
def test_init_badargs(self):
|
def test_init_badargs(self):
|
||||||
""" RPNExpr instanciation with bad arguments """
|
""" RPNExpr instanciation with bad arguments """
|
||||||
badargs = [('', 2), (), ('ab+',), ('ab+',300), (42, 42), ('ab', '42')]
|
badargs = [(), ('ab+',), ('ab+',300), (42, 42), ('ab', '42')]
|
||||||
for badarg in badargs:
|
for badarg in badargs:
|
||||||
with self.assertRaises((ValueError, TypeError)):
|
with self.subTest(badargs=badarg):
|
||||||
expr = pyrpn.RPNExpr(*badarg)
|
with self.assertRaises((ValueError, TypeError)):
|
||||||
|
expr = pyrpn.RPNExpr(*badarg)
|
||||||
|
|
||||||
def test_init_loop(self):
|
def test_init_loop(self):
|
||||||
""" Testing pyrpn.RPNExpr multiple instanciation """
|
""" Testing pyrpn.RPNExpr multiple instanciation """
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue