feat: line processing and basic variable support
This commit is contained in:
parent
cb2a1df61f
commit
11fa2b1e6f
21 changed files with 893 additions and 136 deletions
3
Makefile
3
Makefile
|
@ -10,3 +10,6 @@ build:
|
||||||
test:
|
test:
|
||||||
gcc ${TEST_SRCS_ENC} ./tests/* -o ./bin/test ${CXXFLAGS_WITHOUT_PKGS}
|
gcc ${TEST_SRCS_ENC} ./tests/* -o ./bin/test ${CXXFLAGS_WITHOUT_PKGS}
|
||||||
./bin/test
|
./bin/test
|
||||||
|
sandbox:
|
||||||
|
gcc ${TEST_SRCS_ENC} ./sandbox.c -o ./bin/sandbox ${CXXFLAGS_WITHOUT_PKGS}
|
||||||
|
./bin/sandbox
|
||||||
|
|
92
sandbox.c
Normal file
92
sandbox.c
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "./src/types.h"
|
||||||
|
#include "./src/list.h"
|
||||||
|
#include "./src/number_parsing.h"
|
||||||
|
#include "./src/funcs.h"
|
||||||
|
#include "./src/utils.h"
|
||||||
|
#include "./src/var_store.h"
|
||||||
|
#include "./src/line_processing.h"
|
||||||
|
#include "./src/state.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
// struct List l1;
|
||||||
|
|
||||||
|
// short val = 17;
|
||||||
|
// list_set(&l1, 0, TYPE_VAR_NAME, &val);
|
||||||
|
// list_print(&l1);
|
||||||
|
|
||||||
|
// return 0;
|
||||||
|
|
||||||
|
// int yes = 1234;
|
||||||
|
// int dst = 0;
|
||||||
|
// memcpy(&dst, &yes, 4);
|
||||||
|
// printf("yes: %d \n", dst);
|
||||||
|
|
||||||
|
struct VariableStore* store = var_store_init();
|
||||||
|
|
||||||
|
// int hashRes = var_store_hash_name(store, "HelloWorld++");
|
||||||
|
// printf("hashRes: %d \n", hashRes);
|
||||||
|
int val = 1234;
|
||||||
|
var_store_set(store, "foo", TYPE_INT, &val);
|
||||||
|
|
||||||
|
//printf("Pos of var: %d \n", var_store_get_pos(store, "foo"));
|
||||||
|
|
||||||
|
//byte type = var_store_get_type(store, "foo");
|
||||||
|
//printf("Type of var: %d \n", type);
|
||||||
|
|
||||||
|
//int key = var_store_get_pos(store, "foo");
|
||||||
|
//printf("size of type %d \n", get_size_of_type(store->container[key].type));
|
||||||
|
//printf("%d \n", *((int*) store->container[key].dataPtr));
|
||||||
|
|
||||||
|
int val2 = 0;
|
||||||
|
var_store_copy(store, "foo", &val2);
|
||||||
|
|
||||||
|
printf("Value of var: %d \n", val2);
|
||||||
|
|
||||||
|
printf("==== \n");
|
||||||
|
printf("==== \n");
|
||||||
|
struct StateContainer* state = state_init();
|
||||||
|
process_line(state, "# some random comment");
|
||||||
|
process_line(state, "set VAR_A to 8.5");
|
||||||
|
process_line(state, "set VAR_B to 1.5");
|
||||||
|
process_line(state, "set VAR_C to VAR_A+VAR_B");
|
||||||
|
process_line(state, "print_number(sqrt(VAR_C))");
|
||||||
|
|
||||||
|
// struct List l1;
|
||||||
|
|
||||||
|
// list_append_int(&l1, 4);
|
||||||
|
// list_append_char(&l1, '*');
|
||||||
|
// list_append_int(&l1, 5);
|
||||||
|
|
||||||
|
// list_print(&l1);
|
||||||
|
|
||||||
|
// list_delete(&l1, 0);
|
||||||
|
|
||||||
|
// list_print(&l1);
|
||||||
|
|
||||||
|
// list_delete(&l1, 0);
|
||||||
|
|
||||||
|
// list_print(&l1);
|
||||||
|
|
||||||
|
// float res = 0;
|
||||||
|
|
||||||
|
// void* ptr = &res;
|
||||||
|
|
||||||
|
// printf("%d\n", sizeof(ptr));
|
||||||
|
// int found = identify_func_name("ABS");
|
||||||
|
// printf("found: %d \n", found);
|
||||||
|
|
||||||
|
// unsigned char argsType[1] = { TYPE_FLOAT };
|
||||||
|
// int argsVals[1] = { get_int_rep_from_float(-3.145) };
|
||||||
|
// int resVal = 0;
|
||||||
|
// unsigned char resType = 0;
|
||||||
|
// execute_func(found, 1, argsType, argsVals, &resVal, &resType);
|
||||||
|
// printf("func res type: %d \n", resType);
|
||||||
|
// printf("func res: %f \n", get_float_from_int_rep(resVal));
|
||||||
|
|
||||||
|
// int stat = parse_float("1052.254", &res);
|
||||||
|
// printf("float parsing stat: %d \n", stat);
|
||||||
|
// printf("final float: %f \n", res);
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "./operate.h"
|
#include "./operate.h"
|
||||||
#include "./number_parsing.h"
|
#include "./number_parsing.h"
|
||||||
#include "./funcs.h"
|
#include "./funcs.h"
|
||||||
|
#include "./var_store.h"
|
||||||
|
#include "./state.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This sub script will look for pattern like Number Operator Number
|
This sub script will look for pattern like Number Operator Number
|
||||||
|
@ -154,6 +156,31 @@ int evaluator_reduce_parenthesis_pattern(struct List* evalList) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int evaluator_reduce_var(struct StateContainer* state, struct List* evalList) {
|
||||||
|
int patternPos = -1;
|
||||||
|
for (int i = 0; i < evalList->num_elements; i++) {
|
||||||
|
if (
|
||||||
|
list_get_type(evalList, i) == TYPE_VAR_NAME
|
||||||
|
) {
|
||||||
|
patternPos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (patternPos == -1) return -1;
|
||||||
|
|
||||||
|
int varKey;
|
||||||
|
list_get(evalList, patternPos, &varKey);
|
||||||
|
|
||||||
|
byte type = var_store_get_type_from_key(state->varStore, varKey);
|
||||||
|
|
||||||
|
byte varVal[get_size_of_type(type)];
|
||||||
|
var_store_copy_from_key(state->varStore, varKey, &varVal);
|
||||||
|
|
||||||
|
list_set(evalList, patternPos, type, &varVal);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This func will look for a function call pattern that is ready to be evaluated
|
This func will look for a function call pattern that is ready to be evaluated
|
||||||
First we will look for this kind of pattern
|
First we will look for this kind of pattern
|
||||||
|
@ -169,10 +196,14 @@ if we don't find a comma next, we try to find a closing parenthesis
|
||||||
if we don't find that, we throw an error
|
if we don't find that, we throw an error
|
||||||
|
|
||||||
*/
|
*/
|
||||||
int evaluator_reduce_function_call(struct List* evalList) {
|
int evaluator_reduce_function_call(struct List* evalList, int initialPosition) {
|
||||||
int patternPos = -1;
|
int patternPos = -1;
|
||||||
|
|
||||||
for (int i = 0; i < evalList->num_elements; i++) {
|
if (initialPosition >= evalList->num_elements) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = initialPosition; i < evalList->num_elements; i++) {
|
||||||
if (
|
if (
|
||||||
list_get_type(evalList, i) == TYPE_FUNC_NAME &&
|
list_get_type(evalList, i) == TYPE_FUNC_NAME &&
|
||||||
list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS
|
list_get_type(evalList, i+1) == TYPE_OPEN_PARENTHESIS
|
||||||
|
@ -239,7 +270,10 @@ int evaluator_reduce_function_call(struct List* evalList) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// we cannot reduce more, it's probably because the func call is not ready to be reduced, meaning that the arguments need to be evaluated
|
// we cannot reduce more, it's probably because the func call is not ready to be reduced, meaning that the arguments need to be evaluated
|
||||||
return -1;
|
|
||||||
|
// we need to return to the state of primitive function detection, just skip this primitive
|
||||||
|
// we need to revaluate at patternPos+2
|
||||||
|
return evaluator_reduce_function_call(evalList, patternPos+2);
|
||||||
}
|
}
|
||||||
// now pos is the index of the last component for this func call
|
// now pos is the index of the last component for this func call
|
||||||
|
|
||||||
|
@ -287,7 +321,7 @@ Arguments:
|
||||||
- Input String: char pointer (the source of the evaluation)
|
- Input String: char pointer (the source of the evaluation)
|
||||||
- Result: int pointer (where the result of the evaluation will be written)
|
- Result: int pointer (where the result of the evaluation will be written)
|
||||||
*/
|
*/
|
||||||
int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int _len = strlen(inputStr);
|
int _len = strlen(inputStr);
|
||||||
// we want first to parse the expression and create a stack
|
// we want first to parse the expression and create a stack
|
||||||
|
@ -461,7 +495,12 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st != 0) {
|
if (st != 0) {
|
||||||
|
// identify token
|
||||||
|
// first try a variable then a func name
|
||||||
// not a float, check if this is a common function name
|
// not a float, check if this is a common function name
|
||||||
|
short varKey = (short) var_store_get_key(state->varStore, buff);
|
||||||
|
if (varKey == -1) {
|
||||||
|
// did not find the var name
|
||||||
short funcID = identify_func_name(buff);
|
short funcID = identify_func_name(buff);
|
||||||
if (funcID == -1) {
|
if (funcID == -1) {
|
||||||
// did not find the func name
|
// did not find the func name
|
||||||
|
@ -472,7 +511,11 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
||||||
list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID);
|
list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("end of l\n");
|
if (varKey >= 0) {
|
||||||
|
list_set(&evalList, evalList.num_elements, TYPE_VAR_NAME, &varKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("end of a token id\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the content of this thing
|
// check the content of this thing
|
||||||
|
@ -484,15 +527,21 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
||||||
|
|
||||||
// we are going to look for pattern to reduce
|
// we are going to look for pattern to reduce
|
||||||
// the order is really important here
|
// the order is really important here
|
||||||
int reduceFuncOpStat = evaluator_reduce_function_call(&evalList);
|
int reduceVarOpStat = evaluator_reduce_var(state, &evalList);
|
||||||
|
int reduceFuncOpStat = evaluator_reduce_function_call(&evalList, 0);
|
||||||
int reduceMinusOpStat = evaluator_reduce_minus_pattern(&evalList);
|
int reduceMinusOpStat = evaluator_reduce_minus_pattern(&evalList);
|
||||||
int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList);
|
int reduceOperatorOpStat = evaluator_reduce_operator_pattern(&evalList);
|
||||||
int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList);
|
int reduceParenthesisOpStat = evaluator_reduce_parenthesis_pattern(&evalList);
|
||||||
|
|
||||||
|
if (reduceVarOpStat > 0) {
|
||||||
|
printf("ERR Evaluator: var name reducing failed, dumping evalList: \n");
|
||||||
|
list_print(&evalList);
|
||||||
|
return reduceVarOpStat;
|
||||||
|
}
|
||||||
if (reduceFuncOpStat > 0) {
|
if (reduceFuncOpStat > 0) {
|
||||||
printf("ERR Evaluator: function reducing failed, dumping evalList: \n");
|
printf("ERR Evaluator: function reducing failed, dumping evalList: \n");
|
||||||
list_print(&evalList);
|
list_print(&evalList);
|
||||||
return reduceOperatorOpStat;
|
return reduceFuncOpStat;
|
||||||
}
|
}
|
||||||
if (reduceOperatorOpStat > 0) {
|
if (reduceOperatorOpStat > 0) {
|
||||||
printf("ERR Evaluator: operator reducing failed, dumping evalList: \n");
|
printf("ERR Evaluator: operator reducing failed, dumping evalList: \n");
|
||||||
|
@ -501,6 +550,7 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
reduceVarOpStat == -1 &&
|
||||||
reduceFuncOpStat == -1 &&
|
reduceFuncOpStat == -1 &&
|
||||||
reduceOperatorOpStat == -1 &&
|
reduceOperatorOpStat == -1 &&
|
||||||
reduceParenthesisOpStat == -1 &&
|
reduceParenthesisOpStat == -1 &&
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
#include "./state.h"
|
||||||
#ifndef EVALUATOR_H_
|
#ifndef EVALUATOR_H_
|
||||||
#define EVALUATOR_H_
|
#define EVALUATOR_H_
|
||||||
|
|
||||||
int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr);
|
int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsigned char* typePtr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
40
src/funcs.c
40
src/funcs.c
|
@ -27,6 +27,25 @@ int abs_impl(int* res, unsigned char* resType, unsigned char* types, int* args)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int print_number_impl(int* res, unsigned char* resType, unsigned char* types, int* args)
|
||||||
|
{
|
||||||
|
if (types[0] == TYPE_INT) {
|
||||||
|
int val = args[0];
|
||||||
|
printf("REAL_PRINT: %d\n", val);
|
||||||
|
}
|
||||||
|
if (types[0] == TYPE_FLOAT) {
|
||||||
|
float val = get_float_from_int_rep(args[0]);
|
||||||
|
printf("REAL_PRINT: %f\n", val);
|
||||||
|
}
|
||||||
|
if (is_type_number(types[0])) {
|
||||||
|
*res = 1;
|
||||||
|
*resType = TYPE_INT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int simple_float_func(float (*func)(float), int* res, unsigned char* resType, unsigned char* types, int* args)
|
int simple_float_func(float (*func)(float), int* res, unsigned char* resType, unsigned char* types, int* args)
|
||||||
{
|
{
|
||||||
float x = 0;
|
float x = 0;
|
||||||
|
@ -42,14 +61,15 @@ int simple_float_func(float (*func)(float), int* res, unsigned char* resType, un
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #define SIMPLE_FUNC_BINDING(name) ({\
|
/*
|
||||||
// int #name_impl(int* res, unsigned char* resType, unsigned char* types, int* args)\
|
#define SIMPLE_FUNC_BINDING(name) ({\
|
||||||
// {\
|
int #name_impl(int* res, unsigned char* resType, unsigned char* types, int* args)\
|
||||||
// return simple_float_func(&m_#name, res, resType, types, args);\
|
{\
|
||||||
// }\
|
return simple_float_func(&m_#name, res, resType, types, args);\
|
||||||
// })
|
}\
|
||||||
//
|
})
|
||||||
//
|
*/
|
||||||
|
|
||||||
// SIMPLE_FUNC_BINDING(sqrt)
|
// SIMPLE_FUNC_BINDING(sqrt)
|
||||||
//
|
//
|
||||||
// SIMPLE_FUNC_BINDING(exp)
|
// SIMPLE_FUNC_BINDING(exp)
|
||||||
|
@ -162,8 +182,6 @@ int random_int_impl(int* res, unsigned char* resType, unsigned char* types, int*
|
||||||
upper = args[1];
|
upper = args[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
|
||||||
|
|
||||||
// rand returns a value between 0 and RAND_MAX (which is close to infinite)
|
// rand returns a value between 0 and RAND_MAX (which is close to infinite)
|
||||||
int num = (rand() % (upper - lower + 1)) + lower;
|
int num = (rand() % (upper - lower + 1)) + lower;
|
||||||
*resType = TYPE_INT;
|
*resType = TYPE_INT;
|
||||||
|
@ -196,6 +214,8 @@ struct FuncIntro intros[] = {
|
||||||
|
|
||||||
{"max", &max_impl, 2},
|
{"max", &max_impl, 2},
|
||||||
{"get_pi", &get_pi_impl, 0},
|
{"get_pi", &get_pi_impl, 0},
|
||||||
|
|
||||||
|
{"print_number", &print_number_impl, 1},
|
||||||
{"", 0, 0}
|
{"", 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
255
src/line_processing.c
Normal file
255
src/line_processing.c
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
#include "./utils.h"
|
||||||
|
#include "./line_processing.h"
|
||||||
|
#include "./evaluator.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int cmp_str_in_place(char* against, char* str, int from)
|
||||||
|
{
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (against[i] != '\0') {
|
||||||
|
if (against[i] != str[from+i]) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_char_accepted_in_var_name(char symbol)
|
||||||
|
{
|
||||||
|
int c = (int) symbol;
|
||||||
|
return (
|
||||||
|
(c >= 65 && c <= 90) ||
|
||||||
|
(c >= 97 && c <= 122) ||
|
||||||
|
(c >= 48 && c <= 57) ||
|
||||||
|
c == 45 || c == 95
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int recognize_comment_statement(char* lineStr)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int mode = 1;
|
||||||
|
/*
|
||||||
|
recognize pattern : ^\s*#.*$
|
||||||
|
mode 1 any space
|
||||||
|
mode 2 the start of the comment
|
||||||
|
*/
|
||||||
|
while (lineStr[i] != '\0') {
|
||||||
|
if (mode == 1) {
|
||||||
|
if (lineStr[i] == '#') {
|
||||||
|
mode = 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (lineStr[i] != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (mode != 2) return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct SetStatement {
|
||||||
|
short name_start;
|
||||||
|
short name_stop;
|
||||||
|
short expression_start;
|
||||||
|
};
|
||||||
|
|
||||||
|
int recognize_set_statement(char* lineStr, struct SetStatement* res)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int mode = 1;
|
||||||
|
int arg = 0;
|
||||||
|
/*
|
||||||
|
recognize pattern : ^\s*set ([a-zA-Z0-9_-]+) to (\S)+
|
||||||
|
mode 1 any space
|
||||||
|
mode 2 set
|
||||||
|
mode 3 any space
|
||||||
|
mode 4 var name
|
||||||
|
mode 5 any space
|
||||||
|
mode 6 to
|
||||||
|
mode 7 any space
|
||||||
|
mode 8 the expression
|
||||||
|
*/
|
||||||
|
while (lineStr[i] != '\0') {
|
||||||
|
if (mode == 1) {
|
||||||
|
if (lineStr[i] == 's') {
|
||||||
|
mode = 2;
|
||||||
|
arg = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (lineStr[i] != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mode == 2) {
|
||||||
|
if (arg == 0 && lineStr[i] == 's') {
|
||||||
|
arg++;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (arg == 1 && lineStr[i] == 'e') {
|
||||||
|
arg++;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (arg == 2 && lineStr[i] == 't') {
|
||||||
|
mode = 3;
|
||||||
|
arg = 0;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mode == 3) {
|
||||||
|
if (arg > 0 && is_char_accepted_in_var_name(lineStr[i])) {
|
||||||
|
mode = 4;
|
||||||
|
arg = 0;
|
||||||
|
res->name_start = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (lineStr[i] != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
if (mode == 4) {
|
||||||
|
if (lineStr[i] == ' ') {
|
||||||
|
mode = 5;
|
||||||
|
arg = 0;
|
||||||
|
res->name_stop = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!is_char_accepted_in_var_name(lineStr[i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mode == 5) {
|
||||||
|
if (arg > 0 && lineStr[i] == 't') {
|
||||||
|
mode = 6;
|
||||||
|
arg = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (lineStr[i] != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
if (mode == 6) {
|
||||||
|
if (arg == 0 && lineStr[i] == 't') {
|
||||||
|
arg++;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (arg == 1 && lineStr[i] == 'o') {
|
||||||
|
mode = 7;
|
||||||
|
arg = 0;
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mode == 7) {
|
||||||
|
if (arg == 0 && lineStr[i] != ' ') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (arg > 0 && lineStr[i] != ' ') {
|
||||||
|
// success
|
||||||
|
mode = 8;
|
||||||
|
res->expression_start = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
// printf("End of set statement parsing \n");
|
||||||
|
// printf("index %d \n", i);
|
||||||
|
// printf("mode %d \n", mode);
|
||||||
|
// printf("arg %d \n", arg);
|
||||||
|
|
||||||
|
if (mode != 8) {
|
||||||
|
// we've failed to recognize the pattern
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return a struct with anchors to the groups
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int process_line(struct StateContainer* state, char* str)
|
||||||
|
{
|
||||||
|
printf("\n ======= PROCESSING LINE '%s' =======\n", str);
|
||||||
|
// process
|
||||||
|
int len = strlen(str);
|
||||||
|
// int startPos = 0;
|
||||||
|
// int stopPos = len-1;
|
||||||
|
// // modifiy the start and stop pos to trim spaces
|
||||||
|
// int startTrimOffset = 0;
|
||||||
|
// int stopTrimOffset = 0;
|
||||||
|
// for (int z = 0; z < len; z++) {
|
||||||
|
// if (inputStr[startPos+z] != ' ') {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// startTrimOffset++;
|
||||||
|
// }
|
||||||
|
// for (int z = 1; z < len; z++) {
|
||||||
|
// if (inputStr[stopPos-z] != ' ') {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// stopTrimOffset++;
|
||||||
|
// }
|
||||||
|
// startPos += startTrimOffset;
|
||||||
|
// stopPos -= stopTrimOffset;
|
||||||
|
|
||||||
|
// check for comment
|
||||||
|
// if (str[startPos] == '#') {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//int stat = 0;
|
||||||
|
if (recognize_comment_statement(str)) {
|
||||||
|
printf("Comment recognized \n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
struct SetStatement setStatementParsing;
|
||||||
|
if (recognize_set_statement(str, &setStatementParsing)) {
|
||||||
|
printf("Set statement recognized \n");
|
||||||
|
// handle the set statement (set a variable)
|
||||||
|
int nameLen = setStatementParsing.name_stop-setStatementParsing.name_start;
|
||||||
|
char* name = (char*) malloc(sizeof(char) * nameLen);
|
||||||
|
for (int z = 0; z < nameLen; z++) {
|
||||||
|
name[z] = str[setStatementParsing.name_start + z];
|
||||||
|
}
|
||||||
|
name[len] = '\0';
|
||||||
|
|
||||||
|
int res;
|
||||||
|
byte resType;
|
||||||
|
int evalStat = evaluate(state, str + setStatementParsing.expression_start, &res, &resType);
|
||||||
|
if (evalStat != 0) {
|
||||||
|
printf("Syntax error for line \"%s\"\n", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("==> Set '%s' to %s \n", name, get_repr(resType, &res));
|
||||||
|
var_store_set(state->varStore, name, resType, &res);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we evaluate but we dont care about the result
|
||||||
|
int res;
|
||||||
|
byte resType;
|
||||||
|
int evalStat = evaluate(state, str, &res, &resType);
|
||||||
|
if (evalStat != 0) {
|
||||||
|
printf("Syntax error for line \"%s\"\n", str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
7
src/line_processing.h
Normal file
7
src/line_processing.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#include "./state.h"
|
||||||
|
#ifndef LINE_PROCESSING_H_
|
||||||
|
#define LINE_PROCESSING_H_
|
||||||
|
|
||||||
|
int process_line(struct StateContainer* state, char* str);
|
||||||
|
|
||||||
|
#endif
|
39
src/list.c
39
src/list.c
|
@ -13,37 +13,6 @@ struct List {
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// get size in byte of a particular type
|
|
||||||
int get_size_of_type(unsigned char type)
|
|
||||||
{
|
|
||||||
int t = (int) type;
|
|
||||||
// underlying type is int (4 bytes)
|
|
||||||
if (t == TYPE_INT || t == TYPE_FLOAT) {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
// underlying type is short (1 byte)
|
|
||||||
if (t == TYPE_FUNC_NAME) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
// underlying type is char (1 byte)
|
|
||||||
if (t == TYPE_OPERATOR) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
t == TYPE_OPEN_PARENTHESIS ||
|
|
||||||
t == TYPE_CLOSE_PARENTHESIS ||
|
|
||||||
t == TYPE_COMMA
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int is_type_number(unsigned char type)
|
|
||||||
{
|
|
||||||
return type == TYPE_INT || type == TYPE_FLOAT;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char list_get_type(struct List* list, int index) {
|
unsigned char list_get_type(struct List* list, int index) {
|
||||||
if (index >= list->num_elements) {
|
if (index >= list->num_elements) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -84,7 +53,7 @@ int list_get(struct List* list, int index, void* resultPtr)
|
||||||
if (type == TYPE_OPERATOR) {
|
if (type == TYPE_OPERATOR) {
|
||||||
*((char*) resultPtr) = *((char*) valuePtr);
|
*((char*) resultPtr) = *((char*) valuePtr);
|
||||||
}
|
}
|
||||||
if (type == TYPE_FUNC_NAME) {
|
if (type == TYPE_FUNC_NAME || type == TYPE_VAR_NAME) {
|
||||||
*((short*) resultPtr) = *((short*) valuePtr);
|
*((short*) resultPtr) = *((short*) valuePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,6 +214,12 @@ void list_print(struct List* list)
|
||||||
|
|
||||||
printf("type: FUNC_NAME, val: %d", d);
|
printf("type: FUNC_NAME, val: %d", d);
|
||||||
}
|
}
|
||||||
|
if (type == TYPE_VAR_NAME) {
|
||||||
|
short d = 0;
|
||||||
|
list_get(list, i, &d);
|
||||||
|
|
||||||
|
printf("type: VAR_NAME, val: %d", d);
|
||||||
|
}
|
||||||
if (type == TYPE_OPEN_PARENTHESIS) {
|
if (type == TYPE_OPEN_PARENTHESIS) {
|
||||||
printf("type: OPEN_PARENTHESIS");
|
printf("type: OPEN_PARENTHESIS");
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,13 +44,9 @@ struct List {
|
||||||
int data_ptr;
|
int data_ptr;
|
||||||
int ptrArray[LIST_SIZE];
|
int ptrArray[LIST_SIZE];
|
||||||
unsigned char typeArray[LIST_SIZE];
|
unsigned char typeArray[LIST_SIZE];
|
||||||
unsigned char data[LIST_SIZE];
|
unsigned char data[LIST_SIZE]; // FIXME: remove this bc we want to use malloc
|
||||||
};
|
};
|
||||||
|
|
||||||
int is_type_number(unsigned char type);
|
|
||||||
|
|
||||||
int get_size_of_type(unsigned char type);
|
|
||||||
|
|
||||||
unsigned char list_get_type(struct List* list, int index);
|
unsigned char list_get_type(struct List* list, int index);
|
||||||
|
|
||||||
int list_get(struct List* list, int index, void* valuePtr);
|
int list_get(struct List* list, int index, void* valuePtr);
|
||||||
|
|
25
src/state.c
Normal file
25
src/state.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include "./utils.h"
|
||||||
|
#include "./var_store.h"
|
||||||
|
#include "./state.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
// #define STATE_LEN 255
|
||||||
|
// #define VARIABLES_LEN 255
|
||||||
|
|
||||||
|
// struct ProcessingState {
|
||||||
|
// int linePtr;
|
||||||
|
|
||||||
|
// int variableStore[VARIABLES_LEN];
|
||||||
|
// int functionStore[255];
|
||||||
|
// //int stringStore[255]
|
||||||
|
// int data[STACK_LEN];
|
||||||
|
// };
|
||||||
|
|
||||||
|
struct StateContainer* state_init()
|
||||||
|
{
|
||||||
|
struct StateContainer* ptr = (struct StateContainer*) malloc(sizeof(struct StateContainer));
|
||||||
|
ptr->varStore = var_store_init();
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
26
src/state.h
Normal file
26
src/state.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
This is where we store the state of our program
|
||||||
|
we store:
|
||||||
|
- the variables names and their values (for now only int)
|
||||||
|
- the functions names and their references
|
||||||
|
*/
|
||||||
|
#include "./utils.h"
|
||||||
|
#include "./var_store.h"
|
||||||
|
#ifndef STATE_H_
|
||||||
|
#define STATE_H_
|
||||||
|
|
||||||
|
struct StateContainer {
|
||||||
|
// the line we are currently processing
|
||||||
|
int linePtr;
|
||||||
|
// usefull when we are in SKIP_BLOCK mode, we'will count the nb of block (begin/end)
|
||||||
|
int blocStack;
|
||||||
|
// FULL, SKIP_BLOC, etc
|
||||||
|
byte mode;
|
||||||
|
struct VariableStore* varStore;
|
||||||
|
// struct FunctionStore* funcStore;
|
||||||
|
// struct StringStore* strStore ??
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StateContainer* state_init();
|
||||||
|
|
||||||
|
#endif
|
55
src/types.c
Normal file
55
src/types.c
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include "./utils.h"
|
||||||
|
#include "./types.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int is_type_number(byte type)
|
||||||
|
{
|
||||||
|
return type == TYPE_INT || type == TYPE_FLOAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get size in byte of a particular type
|
||||||
|
int get_size_of_type(byte type)
|
||||||
|
{
|
||||||
|
int t = (int) type;
|
||||||
|
// underlying type is int (4 bytes)
|
||||||
|
if (t == TYPE_INT || t == TYPE_FLOAT) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
// underlying type is short (2 bytes)
|
||||||
|
if (t == TYPE_FUNC_NAME || t == TYPE_VAR_NAME) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
// underlying type is char (1 byte)
|
||||||
|
if (t == TYPE_OPERATOR) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
t == TYPE_OPEN_PARENTHESIS ||
|
||||||
|
t == TYPE_CLOSE_PARENTHESIS ||
|
||||||
|
t == TYPE_COMMA
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_repr(byte type, void* valPtr)
|
||||||
|
{
|
||||||
|
char* res= (char*) malloc(sizeof(char)*32);
|
||||||
|
if (type == 0) {
|
||||||
|
sprintf(res, "NULL");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (type == TYPE_INT) {
|
||||||
|
sprintf(res, "INT(%d)", *((int*) valPtr));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (type == TYPE_FLOAT) {
|
||||||
|
sprintf(res, "FLOAT(%f)", *((float*) valPtr));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(res, "UNKNOWN(%d)", type);
|
||||||
|
return res;
|
||||||
|
}
|
12
src/types.h
12
src/types.h
|
@ -1,8 +1,20 @@
|
||||||
|
#include "./utils.h"
|
||||||
|
#ifndef TYPES_H_
|
||||||
|
#define TYPES_H_
|
||||||
|
|
||||||
#define TYPE_INT 2
|
#define TYPE_INT 2
|
||||||
#define TYPE_FLOAT 3
|
#define TYPE_FLOAT 3
|
||||||
#define TYPE_OPERATOR 32
|
#define TYPE_OPERATOR 32
|
||||||
#define TYPE_COMMA 33
|
#define TYPE_COMMA 33
|
||||||
#define TYPE_FUNC_NAME 34
|
#define TYPE_FUNC_NAME 34
|
||||||
|
#define TYPE_VAR_NAME 35
|
||||||
#define TYPE_OPEN_PARENTHESIS 64
|
#define TYPE_OPEN_PARENTHESIS 64
|
||||||
#define TYPE_CLOSE_PARENTHESIS 65
|
#define TYPE_CLOSE_PARENTHESIS 65
|
||||||
|
|
||||||
|
int is_type_number(byte type);
|
||||||
|
|
||||||
|
int get_size_of_type(byte type);
|
||||||
|
|
||||||
|
char* get_repr(byte type, void* data);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#define CST_PI 3.1415926535
|
#define CST_PI 3.1415926535
|
||||||
|
|
||||||
|
// define custom type (unsigned char)
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
int get_int_rep_from_float(float ft);
|
int get_int_rep_from_float(float ft);
|
||||||
|
|
||||||
float get_float_from_int_rep(int representation);
|
float get_float_from_int_rep(int representation);
|
||||||
|
@ -25,6 +28,8 @@ float m_exp(float x);
|
||||||
|
|
||||||
float m_ln(float x);
|
float m_ln(float x);
|
||||||
|
|
||||||
|
float m_log(float base, float x);
|
||||||
|
|
||||||
float m_sin(float x);
|
float m_sin(float x);
|
||||||
|
|
||||||
float m_cos(float x);
|
float m_cos(float x);
|
||||||
|
|
184
src/var_store.c
Normal file
184
src/var_store.c
Normal file
|
@ -0,0 +1,184 @@
|
||||||
|
#include "./types.h"
|
||||||
|
#include "./var_store.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
struct VariableStore* var_store_init()
|
||||||
|
{
|
||||||
|
struct VariableStore* store = (struct VariableStore*) malloc(sizeof(struct VariableStore));
|
||||||
|
if (store == NULL) {
|
||||||
|
printf("[ERR] VARSTORE: malloc failed for variable store \n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
store->allocatedLength = VAR_STORE_INITIAL_ALLOC_LENGTH;
|
||||||
|
store->length = 0;
|
||||||
|
store->container = (struct VariableContainer*) malloc(sizeof(struct VariableContainer) * store->allocatedLength);
|
||||||
|
if (store->container == NULL) {
|
||||||
|
printf("[ERR] VARSTORE: malloc failed for first variable container \n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < store->allocatedLength; i++) {
|
||||||
|
store->container[i].type = 0;
|
||||||
|
}
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_INTEGER 47797852
|
||||||
|
|
||||||
|
int var_store_hash_name(struct VariableStore* store, char* varName)
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
int i = 0;
|
||||||
|
while (varName[i] != '\0') {
|
||||||
|
hash += (get_int_rep_from_char(varName[i])*integer_pow(9, i)) % MAX_INTEGER;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return hash % store->allocatedLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte var_store_set(struct VariableStore* store, char* varName, byte type, void* valuePtr)
|
||||||
|
{
|
||||||
|
//printf("set variable at var name: '%s' \n", varName);
|
||||||
|
if (!(type == TYPE_FLOAT || type == TYPE_INT)) {
|
||||||
|
printf("[ERR] VARSTORE: unsupported type, cannot store type %d\n", type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void* dataPtr;
|
||||||
|
if (type == TYPE_FLOAT || type == TYPE_INT) {
|
||||||
|
dataPtr = malloc(sizeof(int));
|
||||||
|
if (dataPtr == NULL) {
|
||||||
|
printf("[ERR] VARSTORE: malloc failed for data\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the value to the place to store
|
||||||
|
// copy from stack to heap
|
||||||
|
memcpy(dataPtr, valuePtr, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
char* namePtr = (char*) malloc(strlen(varName));
|
||||||
|
if (namePtr == NULL) {
|
||||||
|
printf("[ERR] VARSTORE: malloc failed for var name\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
strcpy(namePtr, varName);
|
||||||
|
|
||||||
|
int originalKey = var_store_hash_name(store, varName);
|
||||||
|
int key = originalKey;
|
||||||
|
// handle collision, walk along the array
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (store->container[key].type == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcmp(store->container[key].namePtr, varName) == 0) {
|
||||||
|
// we found a variable with the same exact key, so we overwrite it
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
key = (key+1) % store->allocatedLength;
|
||||||
|
if (key == originalKey) {
|
||||||
|
// end the search to avoid endless loop
|
||||||
|
printf("[ERR] VARSTORE: cannot set variable, not enough containers \n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("set variable at key: %d \n", key);
|
||||||
|
store->container[key].type = type;
|
||||||
|
store->container[key].namePtr = namePtr;
|
||||||
|
store->container[key].dataPtr = dataPtr;
|
||||||
|
|
||||||
|
store->length++;
|
||||||
|
if (2*store->length >= store->allocatedLength) {
|
||||||
|
// do smth to double the store->allocatedLength
|
||||||
|
// e.g reallocate the store->container
|
||||||
|
store->allocatedLength = 2*store->allocatedLength;
|
||||||
|
store->container = (struct VariableContainer*) realloc(store->container, sizeof(struct VariableContainer) * store->allocatedLength);
|
||||||
|
if (store->container == NULL) {
|
||||||
|
printf("[ERR] VARSTORE: relloc failed for container \n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the real position of a variable (in order to handle collisions)
|
||||||
|
// return -1 if no pos are found
|
||||||
|
int var_store_get_key(struct VariableStore* store, char* varName)
|
||||||
|
{
|
||||||
|
//printf("get key for %s \n", varName);
|
||||||
|
int originalKey = var_store_hash_name(store, varName);
|
||||||
|
int key = originalKey;
|
||||||
|
// handle collision, walk along the array
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
//printf("inter key: %d %d \n", key, store->container[key].type);
|
||||||
|
if (store->container[key].type == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (strcmp(store->container[key].namePtr, varName) == 0) {
|
||||||
|
// we found the position
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
key = (key+1) % store->allocatedLength;
|
||||||
|
if (key == originalKey) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte var_store_exists(struct VariableStore* store, char* varName)
|
||||||
|
{
|
||||||
|
return var_store_get_key(store, varName) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte var_store_get_type_from_key(struct VariableStore* store, int key)
|
||||||
|
{
|
||||||
|
return store->container[key].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte var_store_get_type(struct VariableStore* store, char* varName)
|
||||||
|
{
|
||||||
|
int key = var_store_get_key(store, varName);
|
||||||
|
if (key < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return var_store_get_type_from_key(store, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte var_store_copy_from_key(struct VariableStore* store, int key, void* dst)
|
||||||
|
{
|
||||||
|
if (key < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
memcpy(dst, store->container[key].dataPtr, (size_t) get_size_of_type(store->container[key].type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte var_store_copy(struct VariableStore* store, char* varName, void* dst)
|
||||||
|
{
|
||||||
|
return var_store_copy_from_key(store, var_store_get_key(store, varName), dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
int var_store_get_int(struct VariableStore* store, char* varName)
|
||||||
|
{
|
||||||
|
if (var_store_get_type(store, varName) != TYPE_INT) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int val;
|
||||||
|
var_store_copy(store, varName, &val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
float var_store_get_float(struct VariableStore* store, char* varName)
|
||||||
|
{
|
||||||
|
if (var_store_get_type(store, varName) != TYPE_FLOAT) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
float val;
|
||||||
|
var_store_copy(store, varName, &val);
|
||||||
|
return val;
|
||||||
|
}
|
64
src/var_store.h
Normal file
64
src/var_store.h
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
#include "./types.h"
|
||||||
|
#include "./utils.h"
|
||||||
|
#ifndef VAR_STORE_H_
|
||||||
|
#define VAR_STORE_H_
|
||||||
|
|
||||||
|
#define VAR_STORE_INITIAL_ALLOC_LENGTH 32
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
Variable store
|
||||||
|
|
||||||
|
With an Hash Table
|
||||||
|
|
||||||
|
This is a store in the heap
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- resizable, when we have too much variable we can reallocate more memory to store
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct VariableContainer {
|
||||||
|
byte type;
|
||||||
|
char* namePtr;
|
||||||
|
void* dataPtr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VariableStore {
|
||||||
|
int allocatedLength;
|
||||||
|
int length;
|
||||||
|
struct VariableContainer* container; // with (storeAllocatedLength) items
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VariableStore* var_store_init();
|
||||||
|
|
||||||
|
int var_store_hash_name(struct VariableStore* store, char* varName);
|
||||||
|
|
||||||
|
// get a pointer to the area of memory where is store the variable
|
||||||
|
//void* var_store_get_ptr(struct VariableStore* store, char* varName);
|
||||||
|
int var_store_get_key(struct VariableStore* store, char* varName);
|
||||||
|
|
||||||
|
// return 1 if var exists 0 else
|
||||||
|
byte var_store_exists(struct VariableStore* store, char* varName);
|
||||||
|
|
||||||
|
// get type of the variable
|
||||||
|
// return NULL if the var doesn't exists
|
||||||
|
byte var_store_get_type_from_key(struct VariableStore* store, int key);
|
||||||
|
byte var_store_get_type(struct VariableStore* store, char* varName);
|
||||||
|
|
||||||
|
byte var_store_copy_from_key(struct VariableStore* store, int key, void* dest);
|
||||||
|
byte var_store_copy(struct VariableStore* store, char* varName, void* dest);
|
||||||
|
|
||||||
|
// for debug purpose
|
||||||
|
int var_store_get_int(struct VariableStore* store, char* varName);
|
||||||
|
float var_store_get_float(struct VariableStore* store, char* varName);
|
||||||
|
|
||||||
|
// OR
|
||||||
|
//byte var_store_get_ptr(char* varName, void** ptrPtr);
|
||||||
|
|
||||||
|
// store a variable
|
||||||
|
byte var_store_set(struct VariableStore* store, char* varName, byte type, void* valuePtr);
|
||||||
|
|
||||||
|
byte var_store_delete(struct VariableStore* store, char* varName);
|
||||||
|
|
||||||
|
#endif
|
60
test.c
60
test.c
|
@ -1,60 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include "./src/types.h"
|
|
||||||
#include "./src/list.h"
|
|
||||||
#include "./src/number_parsing.h"
|
|
||||||
#include "./src/funcs.h"
|
|
||||||
#include "./src/utils.h"
|
|
||||||
|
|
||||||
int some_computation(int a, int b, int* resPtr)
|
|
||||||
{
|
|
||||||
*resPtr = a+b;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float test_func(float x)
|
|
||||||
{
|
|
||||||
return m_float_pow(x,2)-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main () {
|
|
||||||
// test of euler
|
|
||||||
printf("lel : %f \n", m_sqrt(64));
|
|
||||||
|
|
||||||
|
|
||||||
// struct List l1;
|
|
||||||
|
|
||||||
// list_append_int(&l1, 4);
|
|
||||||
// list_append_char(&l1, '*');
|
|
||||||
// list_append_int(&l1, 5);
|
|
||||||
|
|
||||||
// list_print(&l1);
|
|
||||||
|
|
||||||
// list_delete(&l1, 0);
|
|
||||||
|
|
||||||
// list_print(&l1);
|
|
||||||
|
|
||||||
// list_delete(&l1, 0);
|
|
||||||
|
|
||||||
// list_print(&l1);
|
|
||||||
|
|
||||||
// float res = 0;
|
|
||||||
|
|
||||||
// void* ptr = &res;
|
|
||||||
|
|
||||||
// printf("%d\n", sizeof(ptr));
|
|
||||||
// int found = identify_func_name("ABS");
|
|
||||||
// printf("found: %d \n", found);
|
|
||||||
|
|
||||||
// unsigned char argsType[1] = { TYPE_FLOAT };
|
|
||||||
// int argsVals[1] = { get_int_rep_from_float(-3.145) };
|
|
||||||
// int resVal = 0;
|
|
||||||
// unsigned char resType = 0;
|
|
||||||
// execute_func(found, 1, argsType, argsVals, &resVal, &resType);
|
|
||||||
// printf("func res type: %d \n", resType);
|
|
||||||
// printf("func res: %f \n", get_float_from_int_rep(resVal));
|
|
||||||
|
|
||||||
// int stat = parse_float("1052.254", &res);
|
|
||||||
// printf("float parsing stat: %d \n", stat);
|
|
||||||
// printf("final float: %f \n", res);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "./test_utils.h"
|
#include "./test_utils.h"
|
||||||
#include "./test_evaluation.h"
|
#include "./test_evaluation.h"
|
||||||
|
#include "./test_line_processing.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -7,4 +8,5 @@ int main()
|
||||||
printf("== UNIT TESTS == \n");
|
printf("== UNIT TESTS == \n");
|
||||||
test_utils();
|
test_utils();
|
||||||
test_evaluation();
|
test_evaluation();
|
||||||
|
test_line_processing();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,68 +5,80 @@
|
||||||
#include "../src/number_parsing.h"
|
#include "../src/number_parsing.h"
|
||||||
#include "../src/utils.h"
|
#include "../src/utils.h"
|
||||||
#include "../src/evaluator.h"
|
#include "../src/evaluator.h"
|
||||||
|
#include "../src/state.h"
|
||||||
|
|
||||||
void test_evaluation()
|
void test_evaluation()
|
||||||
{
|
{
|
||||||
printf("== test evaluation == \n");
|
printf("== test evaluation == \n");
|
||||||
|
|
||||||
|
struct StateContainer* state = state_init();
|
||||||
|
|
||||||
// test int parsing
|
// test int parsing
|
||||||
int resVal = 0;
|
int resVal = 0;
|
||||||
unsigned char resType = 0;
|
unsigned char resType = 0;
|
||||||
|
|
||||||
evaluate("-4", &resVal, &resType);
|
evaluate(state, "-4", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(-4 == resVal);
|
assert(-4 == resVal);
|
||||||
|
|
||||||
evaluate("-(4+9)+1", &resVal, &resType);
|
evaluate(state, "-(4+9)+1", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(-12 == resVal);
|
assert(-12 == resVal);
|
||||||
|
|
||||||
evaluate("(-(8-9+5))+8", &resVal, &resType);
|
evaluate(state, "(-(8-9+5))+8", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(4 == resVal);
|
assert(4 == resVal);
|
||||||
|
|
||||||
evaluate("2^6", &resVal, &resType);
|
evaluate(state, "2^6", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(64 == resVal);
|
assert(64 == resVal);
|
||||||
|
|
||||||
evaluate("3 + 4", &resVal, &resType);
|
evaluate(state, "3 + 4", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(7 == resVal);
|
assert(7 == resVal);
|
||||||
|
|
||||||
evaluate("(2*4)+0+0", &resVal, &resType);
|
evaluate(state, "(2*4)+0+0", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(8 == resVal);
|
assert(8 == resVal);
|
||||||
|
|
||||||
evaluate("2.5-(2+0.1)", &resVal, &resType);
|
evaluate(state, "2.5-(2+0.1)", &resVal, &resType);
|
||||||
assert(resType == TYPE_FLOAT);
|
assert(resType == TYPE_FLOAT);
|
||||||
assert(float_almost_equal(0.4, get_float_from_int_rep(resVal)));
|
assert(float_almost_equal(0.4, get_float_from_int_rep(resVal)));
|
||||||
|
|
||||||
evaluate("1^0 + (7*(5 +2))", &resVal, &resType);
|
evaluate(state, "1^0 + (7*(5 +2))", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(50 == resVal);
|
assert(50 == resVal);
|
||||||
|
|
||||||
evaluate("- ( 0.1+ 0.3 )", &resVal, &resType);
|
evaluate(state, "- ( 0.1+ 0.3 )", &resVal, &resType);
|
||||||
assert(resType == TYPE_FLOAT);
|
assert(resType == TYPE_FLOAT);
|
||||||
assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal)));
|
assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal)));
|
||||||
|
|
||||||
evaluate("sqrt(2)-1", &resVal, &resType);
|
evaluate(state, "sqrt(2)-1", &resVal, &resType);
|
||||||
assert(resType == TYPE_FLOAT);
|
assert(resType == TYPE_FLOAT);
|
||||||
assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal)));
|
assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal)));
|
||||||
|
|
||||||
evaluate("(abs((0-1)*2)) + abs(2)", &resVal, &resType);
|
evaluate(state, "(abs((0-1)*2)) + abs(2)", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
assert(4 == resVal);
|
assert(4 == resVal);
|
||||||
|
|
||||||
evaluate("exp(2)-1", &resVal, &resType);
|
evaluate(state, "exp(2)-1", &resVal, &resType);
|
||||||
assert(resType == TYPE_FLOAT);
|
assert(resType == TYPE_FLOAT);
|
||||||
assert(float_almost_equal(6.389, get_float_from_int_rep(resVal)));
|
assert(float_almost_equal(6.389, get_float_from_int_rep(resVal)));
|
||||||
|
|
||||||
evaluate("(cos(2)^2)+(sin(2)^2)", &resVal, &resType);
|
evaluate(state, "(cos(2)^2)+(sin(2)^2)", &resVal, &resType);
|
||||||
assert(resType == TYPE_FLOAT);
|
assert(resType == TYPE_FLOAT);
|
||||||
assert(float_almost_equal(1, get_float_from_int_rep(resVal)));
|
assert(float_almost_equal(1, get_float_from_int_rep(resVal)));
|
||||||
|
|
||||||
evaluate("random_int(1, 100)", &resVal, &resType);
|
evaluate(state, "random_int(1, 100)", &resVal, &resType);
|
||||||
assert(resType == TYPE_INT);
|
assert(resType == TYPE_INT);
|
||||||
printf(" - random int: %d \n", resVal);
|
printf(" - random int: %d \n", resVal);
|
||||||
|
|
||||||
|
evaluate(state, "abs(2)+abs(-2)", &resVal, &resType);
|
||||||
|
assert(resType == TYPE_INT);
|
||||||
|
assert(4 == resVal);
|
||||||
|
|
||||||
|
// testing function composition is important
|
||||||
|
evaluate(state, "abs(abs(-2))", &resVal, &resType);
|
||||||
|
assert(resType == TYPE_INT);
|
||||||
|
assert(2 == resVal);
|
||||||
}
|
}
|
||||||
|
|
32
tests/test_line_processing.c
Normal file
32
tests/test_line_processing.c
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "../src/types.h"
|
||||||
|
#include "../src/number_parsing.h"
|
||||||
|
#include "../src/utils.h"
|
||||||
|
#include "../src/evaluator.h"
|
||||||
|
#include "../src/state.h"
|
||||||
|
#include "../src/var_store.h"
|
||||||
|
|
||||||
|
void test_line_processing()
|
||||||
|
{
|
||||||
|
printf("== test line processing == \n");
|
||||||
|
|
||||||
|
struct StateContainer* state = state_init();
|
||||||
|
|
||||||
|
assert(process_line(state, "#"));
|
||||||
|
assert(process_line(state, "# some random comment"));
|
||||||
|
assert(process_line(state, "set VAR_A to 8.5"));
|
||||||
|
printf("%d \n", var_store_get_int(state->varStore, "VAR_A"));
|
||||||
|
assert(float_almost_equal(8.5, var_store_get_float(state->varStore, "VAR_A")));
|
||||||
|
|
||||||
|
assert(process_line(state, "set VAR_B to 1.5"));
|
||||||
|
assert(float_almost_equal(1.5, var_store_get_float(state->varStore, "VAR_B")));
|
||||||
|
|
||||||
|
assert(process_line(state, "set VAR_C to 142"));
|
||||||
|
assert(142 == var_store_get_int(state->varStore, "VAR_C"));
|
||||||
|
|
||||||
|
assert(process_line(state, "set VAR_D to VAR_A+VAR_B"));
|
||||||
|
assert(float_almost_equal(10, var_store_get_float(state->varStore, "VAR_D")));
|
||||||
|
|
||||||
|
}
|
1
tests/test_line_processing.h
Normal file
1
tests/test_line_processing.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
void test_line_processing();
|
Loading…
Reference in a new issue