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
|
|
@ -6,6 +6,8 @@
|
|||
#include "./operate.h"
|
||||
#include "./number_parsing.h"
|
||||
#include "./funcs.h"
|
||||
#include "./var_store.h"
|
||||
#include "./state.h"
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
*/
|
||||
int evaluator_reduce_function_call(struct List* evalList) {
|
||||
int evaluator_reduce_function_call(struct List* evalList, int initialPosition) {
|
||||
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 (
|
||||
list_get_type(evalList, i) == TYPE_FUNC_NAME &&
|
||||
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
|
||||
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
|
||||
|
||||
|
|
@ -287,7 +321,7 @@ Arguments:
|
|||
- Input String: char pointer (the source of the evaluation)
|
||||
- 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 _len = strlen(inputStr);
|
||||
// we want first to parse the expression and create a stack
|
||||
|
|
@ -461,18 +495,27 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
|||
}
|
||||
|
||||
if (st != 0) {
|
||||
// identify token
|
||||
// first try a variable then a func name
|
||||
// not a float, check if this is a common function name
|
||||
short funcID = identify_func_name(buff);
|
||||
if (funcID == -1) {
|
||||
// did not find the func name
|
||||
printf("ERR Evaluator: could not identify token \"%s\" \n", buff);
|
||||
return 200;
|
||||
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);
|
||||
if (funcID == -1) {
|
||||
// did not find the func name
|
||||
printf("ERR Evaluator: could not identify token \"%s\" \n", buff);
|
||||
return 200;
|
||||
}
|
||||
if (funcID >= 0) {
|
||||
list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID);
|
||||
}
|
||||
}
|
||||
if (funcID >= 0) {
|
||||
list_set(&evalList, evalList.num_elements, TYPE_FUNC_NAME, &funcID);
|
||||
if (varKey >= 0) {
|
||||
list_set(&evalList, evalList.num_elements, TYPE_VAR_NAME, &varKey);
|
||||
}
|
||||
}
|
||||
printf("end of l\n");
|
||||
printf("end of a token id\n");
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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 reduceOperatorOpStat = evaluator_reduce_operator_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) {
|
||||
printf("ERR Evaluator: function reducing failed, dumping evalList: \n");
|
||||
list_print(&evalList);
|
||||
return reduceOperatorOpStat;
|
||||
return reduceFuncOpStat;
|
||||
}
|
||||
if (reduceOperatorOpStat > 0) {
|
||||
printf("ERR Evaluator: operator reducing failed, dumping evalList: \n");
|
||||
|
|
@ -501,6 +550,7 @@ int evaluate(char* inputStr, int* resultPtr, unsigned char* typePtr) {
|
|||
}
|
||||
|
||||
if (
|
||||
reduceVarOpStat == -1 &&
|
||||
reduceFuncOpStat == -1 &&
|
||||
reduceOperatorOpStat == -1 &&
|
||||
reduceParenthesisOpStat == -1 &&
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "./state.h"
|
||||
#ifndef 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
|
||||
|
|
|
|||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
float x = 0;
|
||||
|
|
@ -42,14 +61,15 @@ int simple_float_func(float (*func)(float), int* res, unsigned char* resType, un
|
|||
return 0;
|
||||
}
|
||||
|
||||
// #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);\
|
||||
// }\
|
||||
// })
|
||||
//
|
||||
//
|
||||
/*
|
||||
#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);\
|
||||
}\
|
||||
})
|
||||
*/
|
||||
|
||||
// SIMPLE_FUNC_BINDING(sqrt)
|
||||
//
|
||||
// SIMPLE_FUNC_BINDING(exp)
|
||||
|
|
@ -162,8 +182,6 @@ int random_int_impl(int* res, unsigned char* resType, unsigned char* types, int*
|
|||
upper = args[1];
|
||||
}
|
||||
|
||||
int i;
|
||||
|
||||
// rand returns a value between 0 and RAND_MAX (which is close to infinite)
|
||||
int num = (rand() % (upper - lower + 1)) + lower;
|
||||
*resType = TYPE_INT;
|
||||
|
|
@ -196,6 +214,8 @@ struct FuncIntro intros[] = {
|
|||
|
||||
{"max", &max_impl, 2},
|
||||
{"get_pi", &get_pi_impl, 0},
|
||||
|
||||
{"print_number", &print_number_impl, 1},
|
||||
{"", 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) {
|
||||
if (index >= list->num_elements) {
|
||||
return 0;
|
||||
|
|
@ -84,7 +53,7 @@ int list_get(struct List* list, int index, void* resultPtr)
|
|||
if (type == TYPE_OPERATOR) {
|
||||
*((char*) resultPtr) = *((char*) valuePtr);
|
||||
}
|
||||
if (type == TYPE_FUNC_NAME) {
|
||||
if (type == TYPE_FUNC_NAME || type == TYPE_VAR_NAME) {
|
||||
*((short*) resultPtr) = *((short*) valuePtr);
|
||||
}
|
||||
|
||||
|
|
@ -245,6 +214,12 @@ void list_print(struct List* list)
|
|||
|
||||
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) {
|
||||
printf("type: OPEN_PARENTHESIS");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,13 +44,9 @@ struct List {
|
|||
int data_ptr;
|
||||
int ptrArray[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);
|
||||
|
||||
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_FLOAT 3
|
||||
#define TYPE_OPERATOR 32
|
||||
#define TYPE_COMMA 33
|
||||
#define TYPE_FUNC_NAME 34
|
||||
#define TYPE_VAR_NAME 35
|
||||
#define TYPE_OPEN_PARENTHESIS 64
|
||||
#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 custom type (unsigned char)
|
||||
typedef unsigned char byte;
|
||||
|
||||
int get_int_rep_from_float(float ft);
|
||||
|
||||
float get_float_from_int_rep(int representation);
|
||||
|
|
@ -25,6 +28,8 @@ float m_exp(float x);
|
|||
|
||||
float m_ln(float x);
|
||||
|
||||
float m_log(float base, float x);
|
||||
|
||||
float m_sin(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
|
||||
Loading…
Add table
Add a link
Reference in a new issue