diff --git a/examples/count_in_french.ltor b/examples/count_in_french.ltor new file mode 100644 index 0000000..663c46e --- /dev/null +++ b/examples/count_in_french.ltor @@ -0,0 +1,8 @@ +definir index comme 0 + +tant que index < 10 faire + print_number(index) + definir index comme index + 1 +fin +print_number(index) + diff --git a/examples/sandbox.ltor b/examples/sandbox.ltor deleted file mode 100644 index 250378f..0000000 --- a/examples/sandbox.ltor +++ /dev/null @@ -1,3 +0,0 @@ -set a to input_number() -print_number(a) - diff --git a/sandbox.c b/sandbox.c index f6b7ce1..d6f20d5 100644 --- a/sandbox.c +++ b/sandbox.c @@ -10,14 +10,11 @@ #include int main () { - float ex = 2.00001430511; - printf("as bin %d \n", (int) ex); - + struct VariableStore* store = var_store_init(); + printf("%d", var_store_hash_name(store, "print_number index")); + return 0; - // struct VariableStore* store = var_store_init(); - // printf("%d", var_store_hash_name(store, "var")); - // return 0; - // struct List l1; + //struct List l1; // short val = 17; // list_set(&l1, 0, TYPE_VAR_NAME, &val); diff --git a/src/config.h b/src/config.h index ab3e764..691bb59 100644 --- a/src/config.h +++ b/src/config.h @@ -1,6 +1,47 @@ #ifndef G_CONFIG_H_ #define G_CONFIG_H_ + +#define PRESET_ENGLISH 0 +#define PRESET_FRENCH 1 + +// 0: no logs; 1: medium debug; 2: full debug #define G_DEBUG_LEVEL 0 +#define SYNTAX_PRESET PRESET_ENGLISH + +// Define your own custom syntax here + +#if SYNTAX_PRESET == PRESET_ENGLISH + #define SYNTAX_END "end" + + #define SYNTAX_SET_START "set" + #define SYNTAX_SET_STOP "to" + + #define SYNTAX_IF_START "if" + #define SYNTAX_IF_STOP "then" + + #define SYNTAX_WHILE_START "while" + #define SYNTAX_WHILE_STOP "do" + + #define SYNTAX_CONTINUE "continue" + #define SYNTAX_BREAK "break" +#endif + +#if SYNTAX_PRESET == PRESET_FRENCH + #define SYNTAX_END "fin" + + #define SYNTAX_SET_START "definir" + #define SYNTAX_SET_STOP "comme" + + #define SYNTAX_IF_START "si" + #define SYNTAX_IF_STOP "alors" + + #define SYNTAX_WHILE_START "tant que" + #define SYNTAX_WHILE_STOP "faire" + + #define SYNTAX_CONTINUE "continuer" + // JPP + #define SYNTAX_BREAK "casser" +#endif #endif \ No newline at end of file diff --git a/src/evaluator.c b/src/evaluator.c index 8cfc085..97b8736 100644 --- a/src/evaluator.c +++ b/src/evaluator.c @@ -471,15 +471,11 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig int startTrimOffset = 0; int stopTrimOffset = 0; for (int z = 0; z < len; z++) { - if (inputStr[startPos+z] != ' ') { - break; - } + if (inputStr[startPos+z] != ' ') break; startTrimOffset++; } for (int z = 1; z < len; z++) { - if (inputStr[stopPos-z] != ' ') { - break; - } + if (inputStr[stopPos-z] != ' ') break; stopTrimOffset++; } startPos += startTrimOffset; @@ -500,9 +496,7 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig char dumbValue = (char) 0; - if (buff[0] == '\0') { - continue; - } + if (buff[0] == '\0') continue; if (len == 1 && buff[0] == '(') { list_set(&evalList, evalList.num_elements, TYPE_OPEN_PARENTHESIS, &dumbValue); continue; @@ -546,6 +540,7 @@ int evaluate(struct StateContainer* state, char* inputStr, int* resultPtr, unsig if (EVALUATOR_DEBUG_LEVEL >= 2) var_store_print(state->varStore); int varKey = (int) var_store_get_key(state->varStore, buff); + if (EVALUATOR_DEBUG_LEVEL >= 2) printf("got var key '%d' \n", varKey); if (varKey == -1) { // did not find the var name diff --git a/src/line_processing.c b/src/line_processing.c index 24c3745..eb01a87 100644 --- a/src/line_processing.c +++ b/src/line_processing.c @@ -1,3 +1,5 @@ +#include "./config.h" +#include "./types.h" #include "./utils.h" #include "./line_processing.h" #include "./stack.h" @@ -32,9 +34,7 @@ int recognize_comment_statement(char* lineStr) mode = 2; continue; } - if (lineStr[i] != ' ') { - break; - } + if (lineStr[i] != ' ') break; } i++; } @@ -76,8 +76,8 @@ int recognize_termination_keyword(char* needle, char* subject, int from) // recognize "set VAR_NAME to EVALUATION" int recognize_set_statement(char* lineStr, struct SetStatement* res) { - static char setStatementStartKeyword[] = "set"; - static char setStatementStopKeyword[] = "to"; + static char setStatementStartKeyword[] = SYNTAX_SET_START; + static char setStatementStopKeyword[] = SYNTAX_SET_STOP; int i = 0; int mode = 1; @@ -155,8 +155,8 @@ int recognize_set_statement(char* lineStr, struct SetStatement* res) // FIXME: allow for multiline if statement int recognize_if_statement(char* lineStr, struct IfStatement* res) { - static char ifStatementStartKeyword[] = "if"; - static char ifStatementStopKeyword[] = "then"; + static char ifStatementStartKeyword[] = SYNTAX_IF_START; + static char ifStatementStopKeyword[] = SYNTAX_IF_STOP; size_t len = strlen(lineStr); if (len < strlen(ifStatementStartKeyword) + 1 + strlen(ifStatementStopKeyword)) return 0; @@ -222,8 +222,8 @@ int recognize_if_statement(char* lineStr, struct IfStatement* res) // recognize "while EXPRESSION then \n begin (...) \n end" int recognize_while_statement(char* lineStr, struct WhileStatement* res) { - static char whileStatementStartKeyword[] = "while"; - static char whileStatementStopKeyword[] = "do"; + static char whileStatementStartKeyword[] = SYNTAX_WHILE_START; + static char whileStatementStopKeyword[] = SYNTAX_WHILE_STOP; size_t len = strlen(lineStr); if (len < strlen(whileStatementStartKeyword) + 1 + strlen(whileStatementStopKeyword)) return 0; @@ -347,7 +347,7 @@ int process_line(struct StateContainer* state, char* str) return 1; } - if (recognize_word(str, "end")) { + if (recognize_word(str, SYNTAX_END)) { byte lastBlockType; int_stack_pop(state->blockStack, (int*) &lastBlockType); // FIXME: use a stack with size byte instead of int if (!state->skipping && lastBlockType == BLOCK_WHILE) { @@ -425,10 +425,8 @@ int process_line(struct StateContainer* state, char* str) int res; byte resType; int evalStat = evaluate(state, (char*) &dest, &res, &resType); - if (evalStat != 0) { - printf("Syntax error for line \"%s\"\n", str); - return 0; - } + if (evalStat != 0) return 0; + byte doFollow = convert_to_bool(resType, res); if (LINE_PROCESSING_DEBUG_LEVEL >= 2) printf("Got %s, doFollow: %d \n", get_repr(resType, &res), doFollow); @@ -450,10 +448,10 @@ int process_line(struct StateContainer* state, char* str) return 1; } - if (recognize_word(str, "continue")) { + if (recognize_word(str, SYNTAX_CONTINUE)) { int lastLoopLine; if (!int_stack_pop(state->loopStack, &lastLoopLine)) { - printf("Syntax error: unexpected continue, not in a loop \n"); + printf("Syntax error: unexpected continue, not in a loop.\n"); return 0; } state->linePtr = lastLoopLine; @@ -462,17 +460,18 @@ int process_line(struct StateContainer* state, char* str) byte lastBlockType; while (lastBlockType != BLOCK_WHILE) { if (!int_stack_pop(state->blockStack, &lastBlockType)) { - printf("Syntax error: unexpected continue \n"); + printf("Syntax error: unexpected continue.\n"); + return 0; } } int_stack_pop(state->blockStack, &lastBlockType); return 1; } - if (recognize_word(str, "break")) { + if (recognize_word(str, SYNTAX_BREAK)) { int lastLoopLine; if (!int_stack_pop(state->loopStack, &lastLoopLine)) { - printf("Syntax error: unexpected break, not in a loop \n"); + printf("Syntax error: unexpected break, not in a loop.\n"); return 0; } @@ -517,7 +516,7 @@ int process_line(struct StateContainer* state, char* str) int evalStat = evaluate(state, (char*) &express, &res, &resType); if (evalStat != 0) { - printf("Syntax error for line \"%s\"\n", str); + printf("Error: could not evaluate the expression associated with the content of the variable to set \"%s\".\n", str); return 0; } @@ -533,7 +532,7 @@ int process_line(struct StateContainer* state, char* str) byte resType; int evalStat = evaluate(state, str, &res, &resType); if (evalStat != 0) { - printf("Syntax error for line \"%s\"\n", str); + printf("Error: could not evaluate expression \"%s\".\n", str); return 0; } state->linePtr++; @@ -587,7 +586,7 @@ int process_script(struct StateContainer* state, char* script) while (state->running && state->linePtr != lineCount) { if (state->linePtr >= lineCount) { - printf("Invalid line %d \n", state->linePtr); + printf("Error: Invalid line %d \n.", state->linePtr); break; } int lineLen = (lineEnds[state->linePtr] - lineStarts[state->linePtr]); @@ -596,7 +595,7 @@ int process_script(struct StateContainer* state, char* script) int stat = process_line(state, line); if (!stat) { - printf("Abnormal end of run at line %d: '%s' \n", state->linePtr, line); + printf("Error: Abnormal end of run at line %d: '%s'.\n", state->linePtr, line); return 0; } } diff --git a/src/var_store.c b/src/var_store.c index 8892dd9..d49f575 100644 --- a/src/var_store.c +++ b/src/var_store.c @@ -4,7 +4,7 @@ #include #include -#define MAX_INTEGER 47797852 +#define MAX_INTEGER 2147483647-1 struct VariableStore* var_store_init() { @@ -39,7 +39,8 @@ 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; + int num = get_int_rep_from_char(varName[i])*integer_pow(9, i); + hash = abs(hash + abs(num)); i++; } // FIXME: when reallocating, we should copy all variables to their new key @@ -125,20 +126,17 @@ int var_store_get_key(struct VariableStore* store, char* varName) int originalKey = var_store_hash_name(store, varName); int key = originalKey; // handle collision, walk along the array - while (1) - { + 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; - } + if (store->container[key].type == 0) return -1; + + + // check if we found the position + if (strcmp(store->container[key].namePtr, varName) == 0) return key; + key = (key+1) % store->allocatedLength; - if (key == originalKey) { - return -1; - } + + if (key == originalKey) return -1; } } diff --git a/src/var_store.h b/src/var_store.h index ac9e305..c2a6a58 100644 --- a/src/var_store.h +++ b/src/var_store.h @@ -3,6 +3,7 @@ #ifndef VAR_STORE_H_ #define VAR_STORE_H_ +#define VAR_STORE_DEBUG_LEVEL (G_DEBUG_LEVEL) #define VAR_STORE_INITIAL_ALLOC_LENGTH 32 /** diff --git a/tests/test_evaluation.c b/tests/test_evaluation.c index eefe447..2ab949b 100644 --- a/tests/test_evaluation.c +++ b/tests/test_evaluation.c @@ -21,6 +21,14 @@ void test_evaluation() assert(resType == TYPE_INT); assert(-4 == resVal); + evaluate(state, " - 6 ", &resVal, &resType); + assert(resType == TYPE_INT); + assert(-6 == resVal); + + evaluate(state, " 1+ (- 45 ) ", &resVal, &resType); + assert(resType == TYPE_INT); + assert(-44 == resVal); + evaluate(state, "-(4+9)+1", &resVal, &resType); assert(resType == TYPE_INT); assert(-12 == resVal); @@ -53,6 +61,8 @@ void test_evaluation() assert(resType == TYPE_FLOAT); assert(float_almost_equal(-0.4, get_float_from_int_rep(resVal))); + /* FUNCTIONS */ + evaluate(state, "sqrt(2)-1", &resVal, &resType); assert(resType == TYPE_FLOAT); assert(float_almost_equal(0.41421, get_float_from_int_rep(resVal))); @@ -89,11 +99,28 @@ void test_evaluation() assert(resType == TYPE_INT); assert(4 == resVal); + evaluate(state, "max(25, 4)", &resVal, &resType); + assert(resType == TYPE_INT); + assert(25 == resVal); + + evaluate(state, "max(-25, 42)", &resVal, &resType); + assert(resType == TYPE_INT); + assert(42 == resVal); + + evaluate(state, "max( (1+1)^(6+1-1) , 4+2)", &resVal, &resType); + assert(resType == TYPE_INT); + assert(64 == resVal); + + evaluate(state, "max(floor(exp(1))^(4+1) , -2)", &resVal, &resType); + assert(resType == TYPE_INT); + assert(32 == resVal); + // testing function composition is important evaluate(state, "abs(abs(-2))", &resVal, &resType); assert(resType == TYPE_INT); assert(2 == resVal); + /* COMPARAISON OPERATORS */ evaluate(state, "2 = 2", &resVal, &resType); assert(resType == TYPE_INT); assert(1 == resVal); @@ -154,6 +181,7 @@ void test_evaluation() assert(resType == TYPE_FLOAT); assert(float_almost_equal(5.3, get_float_from_int_rep(resVal))); + /* VARIABLES */ int ex = 43; var_store_set(state->varStore, "var", TYPE_INT, (void*) &ex); evaluate(state, "var", &resVal, &resType); @@ -176,6 +204,7 @@ void test_evaluation() printf("actually got: %d \n", resVal); assert(7 == resVal); + /* TYPE FUNCS */ evaluate(state, "is_number(123)", &resVal, &resType); assert(resType == TYPE_INT); assert(resVal); @@ -191,4 +220,8 @@ void test_evaluation() evaluate(state, "is_null(NULL)", &resVal, &resType); assert(resType == TYPE_INT); assert(resVal); + + evaluate(state, "(is_null(NULL) & is_number(42)) | 0", &resVal, &resType); + assert(resType == TYPE_INT); + assert(resVal); }