diff --git a/README.md b/README.md index 5bd5d1f..228c71c 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ # Langatator -A very basic interpreted programming language. +A very basic interpreted imperative programming language. ## Background The goal of this project is to create a simple implementation of a BASIC-like language just to learn a few things along the way and practice my C programming skills. -No need to do complex things, just to create a simple interpreted language that can be used to do some arithmetics -and create for example a number guessing game. +No need to do complex things, just to create a simple interpreted language that can be used to do some arithmetics and create for example a number guessing game. I didn't really study how others languages works beforehand, I'm just guessing how I'm implementing things so that I can make mistakes to learn from. @@ -27,28 +26,34 @@ ToDo List: - [X] allow to set variables - [X] read line comments - [X] add modulus operator '%' -- [ ] add support for multiple characters operators -- [ ] add inclusive operators like '!=', '>=', '<=' -- [ ] add support for priority operators - [X] add input_number() std function - [X] add NULL type (dirty way to handle no returns and some errors) - [X] add type() std function and others type checking functions - [X] add ceil() and floor() std functions - [X] base of the CLI -- [ ] evaluate expression from stdin - [X] read a file - [X] if statements - [X] while statements (with break and continue) -- [ ] repeat statement + +- [ ] add multiple characters operators +- [ ] add inclusive operators like '!=', '>=', '<=' - [ ] add functions support -- [ ] add config header file -- [ ] ability to modify keywords and customize the lang +- [ ] add priority operators +- [ ] add multiline expressions +- [ ] add short hand if without 'end' +- [ ] add repeat statement - [ ] add static string support (just for ui) - [ ] add print_string function - [ ] add basic number list support - [ ] add fully features strings support + +- [ ] evaluate expression from stdin +- [ ] add config header file +- [ ] ability to modify keywords and customize the lang + - [ ] add [classic problem solving](https://rosettacode.org) with code examples - [ ] add Web Assembly support and publish a demo website + - [ ] refactor: use malloc for list - [ ] refactor: remove inconsistency on how functions returns error codes @@ -61,6 +66,9 @@ You will need to compile the code from source. I use GNU Make with GCC, but I'm sure you can use any C compilers though you may need to edit some part of the code to cope with other compilers (eg. binary constants). +## Unit testing + +I try to have some sort of code coverage, you can run the unit tests by issuing `make test` ## The language @@ -157,80 +165,3 @@ print_string(str) print_newline() print_ascii(nb) ``` - -# Evaluator (draft) - -EDIT: that's not actually quite how I implemented the evaluator. - -Map - -componentList: -bytes steam -first byte is a uint8 representing the type of the component -then depending on the type of the component there is 0 or N bytes - -components types: -- name: integer - size: 4 bytes (for int) -- name: open parenthesis - size: 0 bytes -- name: close parenthesis - size: 0 bytes -- name: float - size: 32 bytes (IEEE 754) -- name: operator - size: 1 byte (255 operators are possible) -- name: function designator - desc: id of a function - size: 2 bytes (65536 functions are possibles) - -Example map of `9+(5*(8+6))` - -lexed stream --TYPE:NUMERAL -VALUE:9 --TYPE:OPERATOR -VALUE:PLUS --TYPE:OPEN_PARENTHESIS -VALUE:NULL --TYPE:NUMERAL -VALUE:5 --TYPE:OPERATOR -VALUE:TIMES --TYPE:OPEN_PARENTHESIS -VALUE:NULL --TYPE:NUMERAL -VALUE:8 --TYPE:OPERATOR -VALUE:PLUS --TYPE:NUMERAL -VALUE:6 --TYPE:CLOSE_P -VALUE:NULL --TYPE:CLOSE_P -VALUE:NULL - -scan the whole lexed stream - -So there will be a kind of time line with reference, a list of reference - -in the begining we allocate two lists, one for the component type, one for the component values - - -## Dynamics lists - -we allocate N bytes (uint_8 list[2048]) - -methods: - -list_length() -list_assign_int(int index, int value) -list_assign_float(int index, float value) -list_assign_uint_8(int index, uint_8 value) -list_get_int(int index) - -etc... - - - - diff --git a/draft.md b/draft.md new file mode 100644 index 0000000..bb3f14b --- /dev/null +++ b/draft.md @@ -0,0 +1,77 @@ + +# Evaluator (draft) + +EDIT: that's not actually quite how I implemented the evaluator. + +Map + +componentList: +bytes steam +first byte is a uint8 representing the type of the component +then depending on the type of the component there is 0 or N bytes + +components types: +- name: integer + size: 4 bytes (for int) +- name: open parenthesis + size: 0 bytes +- name: close parenthesis + size: 0 bytes +- name: float + size: 32 bytes (IEEE 754) +- name: operator + size: 1 byte (255 operators are possible) +- name: function designator + desc: id of a function + size: 2 bytes (65536 functions are possibles) + +Example map of `9+(5*(8+6))` + +lexed stream +-TYPE:NUMERAL +VALUE:9 +-TYPE:OPERATOR +VALUE:PLUS +-TYPE:OPEN_PARENTHESIS +VALUE:NULL +-TYPE:NUMERAL +VALUE:5 +-TYPE:OPERATOR +VALUE:TIMES +-TYPE:OPEN_PARENTHESIS +VALUE:NULL +-TYPE:NUMERAL +VALUE:8 +-TYPE:OPERATOR +VALUE:PLUS +-TYPE:NUMERAL +VALUE:6 +-TYPE:CLOSE_P +VALUE:NULL +-TYPE:CLOSE_P +VALUE:NULL + +scan the whole lexed stream + +So there will be a kind of time line with reference, a list of reference + +in the begining we allocate two lists, one for the component type, one for the component values + + +## Dynamics lists + +we allocate N bytes (uint_8 list[2048]) + +methods: + +list_length() +list_assign_int(int index, int value) +list_assign_float(int index, float value) +list_assign_uint_8(int index, uint_8 value) +list_get_int(int index) + +etc... + + + + diff --git a/log.err b/log.err deleted file mode 100644 index 907dabe..0000000 --- a/log.err +++ /dev/null @@ -1,304 +0,0 @@ -./src/funcs.c:43:33: error: '#' is not followed by a macro parameter - 43 | #define SIMPLE_FUNC_BINDING(name) ({\ - | ^ -./src/funcs.c:51:1: warning: return type defaults to ‘int’ [-Wimplicit-int] - 51 | SIMPLE_FUNC_BINDING(sqrt) - | ^~~~~~~~~~~~~~~~~~~ -./src/funcs.c: In function ‘SIMPLE_FUNC_BINDING’: -./src/funcs.c:53:1: error: expected declaration specifiers before ‘SIMPLE_FUNC_BINDING’ - 53 | SIMPLE_FUNC_BINDING(exp) - | ^~~~~~~~~~~~~~~~~~~ -./src/funcs.c:114:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token - 114 | { - | ^ -./src/funcs.c:121:1: warning: empty declaration - 121 | struct FuncIntro { - | ^~~~~~ -./src/funcs.c:129:8: error: parameter ‘intros’ is initialized - 129 | struct FuncIntro intros[] = { - | ^~~~~~~~~ -./src/funcs.c:130:5: warning: braces around scalar initializer - 130 | {"abs", &abs_impl, 1}, - | ^ -./src/funcs.c:130:5: note: (near initialization for ‘intros’) -./src/funcs.c:130:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 130 | {"abs", &abs_impl, 1}, - | ^~~~~ -./src/funcs.c:130:6: note: (near initialization for ‘intros’) -./src/funcs.c:130:13: warning: excess elements in scalar initializer - 130 | {"abs", &abs_impl, 1}, - | ^ -./src/funcs.c:130:13: note: (near initialization for ‘intros’) -./src/funcs.c:130:24: warning: excess elements in scalar initializer - 130 | {"abs", &abs_impl, 1}, - | ^ -./src/funcs.c:130:24: note: (near initialization for ‘intros’) -./src/funcs.c:132:5: warning: braces around scalar initializer - 132 | {"sqrt", &sqrt_impl, 1}, - | ^ -./src/funcs.c:132:5: note: (near initialization for ‘intros’) -./src/funcs.c:132:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 132 | {"sqrt", &sqrt_impl, 1}, - | ^~~~~~ -./src/funcs.c:132:6: note: (near initialization for ‘intros’) -./src/funcs.c:132:15: error: ‘sqrt_impl’ undeclared (first use in this function) - 132 | {"sqrt", &sqrt_impl, 1}, - | ^~~~~~~~~ -./src/funcs.c:132:15: note: each undeclared identifier is reported only once for each function it appears in -./src/funcs.c:132:14: warning: excess elements in scalar initializer - 132 | {"sqrt", &sqrt_impl, 1}, - | ^ -./src/funcs.c:132:14: note: (near initialization for ‘intros’) -./src/funcs.c:132:26: warning: excess elements in scalar initializer - 132 | {"sqrt", &sqrt_impl, 1}, - | ^ -./src/funcs.c:132:26: note: (near initialization for ‘intros’) -./src/funcs.c:132:5: warning: excess elements in scalar initializer - 132 | {"sqrt", &sqrt_impl, 1}, - | ^ -./src/funcs.c:132:5: note: (near initialization for ‘intros’) -./src/funcs.c:133:5: warning: braces around scalar initializer - 133 | {"exp", &exp_impl, 1}, - | ^ -./src/funcs.c:133:5: note: (near initialization for ‘intros’) -./src/funcs.c:133:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 133 | {"exp", &exp_impl, 1}, - | ^~~~~ -./src/funcs.c:133:6: note: (near initialization for ‘intros’) -./src/funcs.c:133:14: error: ‘exp_impl’ undeclared (first use in this function) - 133 | {"exp", &exp_impl, 1}, - | ^~~~~~~~ -./src/funcs.c:133:13: warning: excess elements in scalar initializer - 133 | {"exp", &exp_impl, 1}, - | ^ -./src/funcs.c:133:13: note: (near initialization for ‘intros’) -./src/funcs.c:133:24: warning: excess elements in scalar initializer - 133 | {"exp", &exp_impl, 1}, - | ^ -./src/funcs.c:133:24: note: (near initialization for ‘intros’) -./src/funcs.c:133:5: warning: excess elements in scalar initializer - 133 | {"exp", &exp_impl, 1}, - | ^ -./src/funcs.c:133:5: note: (near initialization for ‘intros’) -./src/funcs.c:135:5: warning: braces around scalar initializer - 135 | {"sin", &sin_impl, 1}, - | ^ -./src/funcs.c:135:5: note: (near initialization for ‘intros’) -./src/funcs.c:135:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 135 | {"sin", &sin_impl, 1}, - | ^~~~~ -./src/funcs.c:135:6: note: (near initialization for ‘intros’) -./src/funcs.c:135:14: error: ‘sin_impl’ undeclared (first use in this function) - 135 | {"sin", &sin_impl, 1}, - | ^~~~~~~~ -./src/funcs.c:135:13: warning: excess elements in scalar initializer - 135 | {"sin", &sin_impl, 1}, - | ^ -./src/funcs.c:135:13: note: (near initialization for ‘intros’) -./src/funcs.c:135:24: warning: excess elements in scalar initializer - 135 | {"sin", &sin_impl, 1}, - | ^ -./src/funcs.c:135:24: note: (near initialization for ‘intros’) -./src/funcs.c:135:5: warning: excess elements in scalar initializer - 135 | {"sin", &sin_impl, 1}, - | ^ -./src/funcs.c:135:5: note: (near initialization for ‘intros’) -./src/funcs.c:136:5: warning: braces around scalar initializer - 136 | {"cos", &cos_impl, 1}, - | ^ -./src/funcs.c:136:5: note: (near initialization for ‘intros’) -./src/funcs.c:136:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 136 | {"cos", &cos_impl, 1}, - | ^~~~~ -./src/funcs.c:136:6: note: (near initialization for ‘intros’) -./src/funcs.c:136:14: error: ‘cos_impl’ undeclared (first use in this function); did you mean ‘abs_impl’? - 136 | {"cos", &cos_impl, 1}, - | ^~~~~~~~ - | abs_impl -./src/funcs.c:136:13: warning: excess elements in scalar initializer - 136 | {"cos", &cos_impl, 1}, - | ^ -./src/funcs.c:136:13: note: (near initialization for ‘intros’) -./src/funcs.c:136:24: warning: excess elements in scalar initializer - 136 | {"cos", &cos_impl, 1}, - | ^ -./src/funcs.c:136:24: note: (near initialization for ‘intros’) -./src/funcs.c:136:5: warning: excess elements in scalar initializer - 136 | {"cos", &cos_impl, 1}, - | ^ -./src/funcs.c:136:5: note: (near initialization for ‘intros’) -./src/funcs.c:137:5: warning: braces around scalar initializer - 137 | {"tan", &tan_impl, 1}, - | ^ -./src/funcs.c:137:5: note: (near initialization for ‘intros’) -./src/funcs.c:137:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 137 | {"tan", &tan_impl, 1}, - | ^~~~~ -./src/funcs.c:137:6: note: (near initialization for ‘intros’) -./src/funcs.c:137:14: error: ‘tan_impl’ undeclared (first use in this function) - 137 | {"tan", &tan_impl, 1}, - | ^~~~~~~~ -./src/funcs.c:137:13: warning: excess elements in scalar initializer - 137 | {"tan", &tan_impl, 1}, - | ^ -./src/funcs.c:137:13: note: (near initialization for ‘intros’) -./src/funcs.c:137:24: warning: excess elements in scalar initializer - 137 | {"tan", &tan_impl, 1}, - | ^ -./src/funcs.c:137:24: note: (near initialization for ‘intros’) -./src/funcs.c:137:5: warning: excess elements in scalar initializer - 137 | {"tan", &tan_impl, 1}, - | ^ -./src/funcs.c:137:5: note: (near initialization for ‘intros’) -./src/funcs.c:138:5: warning: braces around scalar initializer - 138 | {"ln", &ln_impl, 1}, - | ^ -./src/funcs.c:138:5: note: (near initialization for ‘intros’) -./src/funcs.c:138:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 138 | {"ln", &ln_impl, 1}, - | ^~~~ -./src/funcs.c:138:6: note: (near initialization for ‘intros’) -./src/funcs.c:138:13: error: ‘ln_impl’ undeclared (first use in this function) - 138 | {"ln", &ln_impl, 1}, - | ^~~~~~~ -./src/funcs.c:138:12: warning: excess elements in scalar initializer - 138 | {"ln", &ln_impl, 1}, - | ^ -./src/funcs.c:138:12: note: (near initialization for ‘intros’) -./src/funcs.c:138:22: warning: excess elements in scalar initializer - 138 | {"ln", &ln_impl, 1}, - | ^ -./src/funcs.c:138:22: note: (near initialization for ‘intros’) -./src/funcs.c:138:5: warning: excess elements in scalar initializer - 138 | {"ln", &ln_impl, 1}, - | ^ -./src/funcs.c:138:5: note: (near initialization for ‘intros’) -./src/funcs.c:139:5: warning: braces around scalar initializer - 139 | {"log", &log_impl, 1}, - | ^ -./src/funcs.c:139:5: note: (near initialization for ‘intros’) -./src/funcs.c:139:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 139 | {"log", &log_impl, 1}, - | ^~~~~ -./src/funcs.c:139:6: note: (near initialization for ‘intros’) -./src/funcs.c:139:14: error: ‘log_impl’ undeclared (first use in this function) - 139 | {"log", &log_impl, 1}, - | ^~~~~~~~ -./src/funcs.c:139:13: warning: excess elements in scalar initializer - 139 | {"log", &log_impl, 1}, - | ^ -./src/funcs.c:139:13: note: (near initialization for ‘intros’) -./src/funcs.c:139:24: warning: excess elements in scalar initializer - 139 | {"log", &log_impl, 1}, - | ^ -./src/funcs.c:139:24: note: (near initialization for ‘intros’) -./src/funcs.c:139:5: warning: excess elements in scalar initializer - 139 | {"log", &log_impl, 1}, - | ^ -./src/funcs.c:139:5: note: (near initialization for ‘intros’) -./src/funcs.c:141:5: warning: braces around scalar initializer - 141 | {"max", &max_impl, 2}, - | ^ -./src/funcs.c:141:5: note: (near initialization for ‘intros’) -./src/funcs.c:141:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 141 | {"max", &max_impl, 2}, - | ^~~~~ -./src/funcs.c:141:6: note: (near initialization for ‘intros’) -./src/funcs.c:141:14: error: ‘max_impl’ undeclared (first use in this function) - 141 | {"max", &max_impl, 2}, - | ^~~~~~~~ -./src/funcs.c:141:13: warning: excess elements in scalar initializer - 141 | {"max", &max_impl, 2}, - | ^ -./src/funcs.c:141:13: note: (near initialization for ‘intros’) -./src/funcs.c:141:24: warning: excess elements in scalar initializer - 141 | {"max", &max_impl, 2}, - | ^ -./src/funcs.c:141:24: note: (near initialization for ‘intros’) -./src/funcs.c:141:5: warning: excess elements in scalar initializer - 141 | {"max", &max_impl, 2}, - | ^ -./src/funcs.c:141:5: note: (near initialization for ‘intros’) -./src/funcs.c:142:5: warning: braces around scalar initializer - 142 | {"get_pi", &get_pi_impl, 0}, - | ^ -./src/funcs.c:142:5: note: (near initialization for ‘intros’) -./src/funcs.c:142:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 142 | {"get_pi", &get_pi_impl, 0}, - | ^~~~~~~~ -./src/funcs.c:142:6: note: (near initialization for ‘intros’) -./src/funcs.c:142:17: error: ‘get_pi_impl’ undeclared (first use in this function) - 142 | {"get_pi", &get_pi_impl, 0}, - | ^~~~~~~~~~~ -./src/funcs.c:142:16: warning: excess elements in scalar initializer - 142 | {"get_pi", &get_pi_impl, 0}, - | ^ -./src/funcs.c:142:16: note: (near initialization for ‘intros’) -./src/funcs.c:142:30: warning: excess elements in scalar initializer - 142 | {"get_pi", &get_pi_impl, 0}, - | ^ -./src/funcs.c:142:30: note: (near initialization for ‘intros’) -./src/funcs.c:142:5: warning: excess elements in scalar initializer - 142 | {"get_pi", &get_pi_impl, 0}, - | ^ -./src/funcs.c:142:5: note: (near initialization for ‘intros’) -./src/funcs.c:143:5: warning: braces around scalar initializer - 143 | {"", 0, 0} - | ^ -./src/funcs.c:143:5: note: (near initialization for ‘intros’) -./src/funcs.c:143:6: warning: initialization of ‘struct FuncIntro *’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types] - 143 | {"", 0, 0} - | ^~ -./src/funcs.c:143:6: note: (near initialization for ‘intros’) -./src/funcs.c:143:10: warning: excess elements in scalar initializer - 143 | {"", 0, 0} - | ^ -./src/funcs.c:143:10: note: (near initialization for ‘intros’) -./src/funcs.c:143:13: warning: excess elements in scalar initializer - 143 | {"", 0, 0} - | ^ -./src/funcs.c:143:13: note: (near initialization for ‘intros’) -./src/funcs.c:143:5: warning: excess elements in scalar initializer - 143 | {"", 0, 0} - | ^ -./src/funcs.c:143:5: note: (near initialization for ‘intros’) -./src/funcs.c:146:12: error: storage class specified for parameter ‘nbOfFuncs’ - 146 | static int nbOfFuncs = sizeof(intros)/sizeof(struct FuncIntro); - | ^~~~~~~~~ -./src/funcs.c:146:1: error: parameter ‘nbOfFuncs’ is initialized - 146 | static int nbOfFuncs = sizeof(intros)/sizeof(struct FuncIntro); - | ^~~~~~ -./src/funcs.c:146:30: warning: ‘sizeof’ on array function parameter ‘intros’ will return size of ‘struct FuncIntro *’ [-Wsizeof-array-argument] - 146 | static int nbOfFuncs = sizeof(intros)/sizeof(struct FuncIntro); - | ^ -./src/funcs.c:129:18: note: declared here - 129 | struct FuncIntro intros[] = { - | ^~~~~~ -./src/funcs.c:152:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token - 152 | { - | ^ -./src/funcs.c:162:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token - 162 | { - | ^ -./src/funcs.c:51:1: warning: type of ‘sqrt’ defaults to ‘int’ [-Wimplicit-int] - 51 | SIMPLE_FUNC_BINDING(sqrt) - | ^~~~~~~~~~~~~~~~~~~ -./src/funcs.c:146:12: error: declaration for parameter ‘nbOfFuncs’ but no such parameter - 146 | static int nbOfFuncs = sizeof(intros)/sizeof(struct FuncIntro); - | ^~~~~~~~~ -./src/funcs.c:129:18: error: declaration for parameter ‘intros’ but no such parameter - 129 | struct FuncIntro intros[] = { - | ^~~~~~ -./src/funcs.c:196: error: expected ‘{’ at end of input -./src/funcs.c:51:1: warning: unused parameter ‘sqrt’ [-Wunused-parameter] - 51 | SIMPLE_FUNC_BINDING(sqrt) - | ^~~~~~~~~~~~~~~~~~~ -./src/funcs.c:146:12: warning: unused parameter ‘nbOfFuncs’ [-Wunused-parameter] - 146 | static int nbOfFuncs = sizeof(intros)/sizeof(struct FuncIntro); - | ^~~~~~~~~ -./src/funcs.c:196: warning: control reaches end of non-void function [-Wreturn-type] -./src/number_parsing.c: In function ‘parse_clean_positive_integer’: -./src/number_parsing.c:21:29: warning: binary constants are a C2X feature or GCC extension - 21 | (numeralIndex & 0b001111) - | ^~~~~~~~ -make: *** [Makefile:11: test] Error 1