diff --git a/README.md b/README.md index 770532b..91f63ed 100755 --- a/README.md +++ b/README.md @@ -1,49 +1,141 @@ -# Deon programming language V0.9.2.1 +# Deon programming language V0.9.5 My computer programming language made with LEX/YACC written in C. (interpreted) +# Downloads +
+ +Win-32: download +Win-64: download +Linux-32: download +Linux-64: download + # Hello World. +
+Hello world in Deon. ``` -def Main : { - printf[ "hello world" ]; +def main: +{ + print["hello world"]; }; -call Main; +call main; ``` -Requirements to making a program: -1.) a struct/function. -2.) a call statement. # Variables -Variables are stored in a hashmap for quick and easy access. Variables also support type juggling. When you define a variable its type will be assumed when parsed. +
+- Variables support "type juggling" where types are assumed at runtime. +- Variables can be assigned to each other even if they are different types. +``` +/* main function */ +def main: +{ + my_var = 121231; /* int */ + print[my_var]; + my_var = -123.122; /* double */ + print[my_var]; + my_var = "cool string"; /* null terminating string */ + print[my_var]; + my_var = 'c'; /* char */ + print[my_var]; + my_var = { print[ "hello world" ]; }; /* lambda function */ + call my_var; +}; +call main; +``` +# Expressions +- As ov v0.9.5 expressions are only supported for int types, I need to recode the entire expression parsing system +to support up to doubles. +``` +def main: +{ + var = 10 + (5 * 2 / (11 % 2)); + /* should print 20 */ + print[var]; +}; +call main; +``` +# Scope +- As of v0.9.5 there is not scope inside of this programming language. ``` -myint = 121231; -mydouble = -123.122; -mystring = "cool string"; -mychar = 'c'; // char -myfunction = { printf[ "hello world" ]; }; (statement list) +/* changes var from 10 to 100 */ +def another_function: +{ + var = 100; +}; + +def main: +{ + var = 10; + /* should print 10 */ + print[var]; + call another_function; + /* should print 100 */ + print[var]; +}; +call main; ``` + # Logic -Logic is first evaluated and if deemed valid then a list of statements will be executed. +
+- while loops are if statements +- As of version 0.9.5, logic conditions must only be variables. + +### If statements +As stated above, if statement conditions must be a variable. ``` -if [ 10 > 9 ]: { - printf [ "10 is bigger than 9!" ]; - newInt = 100; +def main: +{ + var = 1; + if[var]: /* condition must be a variable */ + { + print["var was 1"]; + var = 0; + }; + if[var]: + { + print["this wont print! (or shouldnt)"]; + }; }; - -if [ {int} newInt > 99 ]: { - printf [ "newInt is bigger than 99" ]; +call main; +``` +### While loop +``` +def main: +{ + var = 1; + /* loop that runs forever */ + while[var]: + { + print["this will run forever"]; + print["it also wont stack overflow, so dont worry"]; + }; }; +call main; ``` + # Functions -Functions can be declared inside of a struct and accessed by anyone who uses the scope resolution operator. Do not mistake structs as functions just because you can interact with them in the same way. Functions do not have "scope" like structs do. Functions can interact with all elements in the parenting struct including other functions, and those functions local variables. +- Functions can be defined as variables (lambda) or defined normally. ``` -def NewStruct : { - someFunction = { - printf[ "hello world" ]; +def my_function: +{ + some_function = { + print["hello world"]; }; + call some_function; }; -call NewStruct; +call my_function; ``` -# Coming soon - TCP networking, file handling, and finally loops! +# Redefinitions +- As of v0.9.5 everything in this programming language can be redefined. That means everything, including the function that +is currently being executed. +``` +def main: +{ + main = { + print["i just redefined main"]; + }; +}; +call main; +call main; +``` diff --git a/deon-unix/deon.l b/deon-unix/deon.l new file mode 100644 index 0000000..d4ee70e --- /dev/null +++ b/deon-unix/deon.l @@ -0,0 +1,84 @@ +%{ + #include + #include + #include + #include "types.h" + #include "y.tab.h" + + void yyerror(char *); + + extern YYSTYPE yylval; + extern FILE *yyin; + int yylineno; + +%} +%% +\/\*.*?\*\/ { ; // comment } +-?[0-9]+ { yylval.int_num = atoi(yytext); return INTEGER; } +\'[ -~]\' { yylval.byte_num = yytext[1]; return CHAR; } +[-()<>=+*/:;,%{}\[\]] { return *yytext; } +"if" { return IF; } +"else" { return ELSE; } +"print" { return PRINT_TOKEN; } +"string" { return KEYWORD_S; } +"while" { return WHILE; } +"int" { return KEYWORD_I; } +"def" { return DEF;} +"call" { return CALL; } +"char" { return KEYWORD_C; } +"++" { return INCREASE; } +"--" { return DECREASE; } +\"(\\.|[^"\\])*\" { yytext++; yytext[strlen(yytext)-1] = 0; yylval.str_ptr = strdup(yytext); return STRING; } +[a-zA-Z0-9_]+ { yylval.str_ptr = strdup(yytext); return VARNAME; } +-?[0-9]*\.[0-9]+ { yylval.double_num = atof(yytext); return DOUBLEVAR; } +"\n" { yylineno++; } +[ ?\t\n\r] +. printf("invalid character on line %d, '%s'\n", yylineno, yytext); +<> { exit(0); } +%% + +int yywrap(void) { + + return 1; + +} + +int main(int argc, char* argv[]) +{ + _var_map = malloc(sizeof(map_void_t)); + map_init(_var_map); + _temp_statement_head = NULL; + _function_list = NULL; + FILE *fh; + if (argc > 1) + { + if (strcmp(argv[1],"help") == 0 || strcmp(argv[1],"-help") == 0 + || strcmp(argv[1],"--help") == 0 || strcmp(argv[1],"h") == 0 + || strcmp(argv[1],"-h") == 0) + { + printf("[ HELP ] put a file/path as the first flag.\n"); + printf("[ HELP ] -h, -help, --help, help, h: Prints this.\n"); + printf("[ HELP ] -d, d, -debug, debug: Enter REPL mode.\n"); + } + else if (strcmp(argv[1],"-debug") == 0 || strcmp(argv[1],"-d") == 0 + || strcmp(argv[1],"d") == 0 || strcmp(argv[1],"debug") == 0) + { + _DEON_DEBUG = 1; + printf(">>> "); + yyparse(); + } + else if (fh = fopen(argv[1], "r")) + { + yyin = fh; + yyparse(); + fclose(fh); + } + else + { + printf("[ ERROR ] please enter a correct command. try --help\n"); + fclose(fh); + } + } else + printf("[ ERROR ] missing input file. Try --help?\n"); + return 0; +} \ No newline at end of file diff --git a/deon-unix/deon.y b/deon-unix/deon.y new file mode 100644 index 0000000..98cbe16 --- /dev/null +++ b/deon-unix/deon.y @@ -0,0 +1,119 @@ +%{ +#include +#include +#include + +#include "types.h" +#include "parser/parser.c" +#include "functions/functions.c" +#include "logic/logic.c" +#include "print/print.c" +#include "vars/vars.c" + +int yylex(void); +void yyerror(char *); +extern int yylineno; + +%} + +/* doing these before multiplication and division because they have a lower presidence */ +%left '<' '>' + +%left '+' '-' +/* doing this last so they have a higher presidence */ +%left '*' '/' '%' + +%union { + char* str_ptr; + int int_num; + unsigned uint_num; + char byte_num; + double double_num; + float float_num; + struct node_info *node_ptr; +} + + +%token INCREASE DECREASE PRINT_TOKEN IF END KEYWORD_S KEYWORD_I KEYWORD_C QUOTE ELSE WHILE DEF CALL +%token INTEGER +%token STRING VARNAME +%token CHAR +%token DOUBLEVAR +%token FLOAT_NUM +%type EXPR +%type STMT PRINT VARIABLE FUNC STMT_LIST LOGIC + +%% + +PROGRAM: + MAIN '\n' + | + ; + +MAIN: + MAIN FUNC ';' { if (_DEON_DEBUG == true ) { printf(">>> "); exec_stmt($2); } else { exec_stmt($2); } } + | + ; + +FUNC: + DEF VARNAME ':' '{' STMT_LIST '}' { $$ = create_function($2, $5); } + | CALL VARNAME { $$ = create_function_call($2); } + ; + +STMT_LIST: + STMT ';' { $$ = create_compound_statement($1, _temp_statement_head); } + | STMT_LIST STMT ';' { $$ = add_to_compound_statement($2, $1); } + ; + +STMT: + VARIABLE { $$ = $1; } + | LOGIC { $$ = $1; } + | FUNC { $$ = $1; } + | PRINT_TOKEN '[' PRINT ']' { $$ = $3; } + | '{' STMT_LIST '}' { $$ = $2; } + ; + +LOGIC: + IF '[' VARNAME ']' ':' '{' STMT_LIST '}' { $$ = create_logic_node(create_logic(IF_LOGIC, $7, $3)); } + | WHILE '[' VARNAME ']' ':' '{' STMT_LIST '}' { $$ = create_logic_node(create_logic(WHILE_LOGIC, $7, $3)); } + ; + + +VARIABLE: + VARNAME '=' STRING { $$ = create_variable_const($1, (void *) $3, VAR_STRING);} + | VARNAME '=' EXPR { $$ = create_variable_const($1, alloc_value(&$3, VAR_INT), VAR_INT);} + | VARNAME '=' CHAR { $$ = create_variable_const($1, alloc_value(&$3, VAR_BYTE), VAR_BYTE);} + | VARNAME '=' DOUBLEVAR { $$ = create_variable_const($1, alloc_value(&$3, VAR_DOUBLE), VAR_DOUBLE);} + | VARNAME '=' '{' STMT_LIST '}' { $$ = create_function($1, $4); } + | VARNAME '=' VARNAME { $$ = move_value($1, $3); } + ; + +EXPR: + INTEGER { $$ = $1; } + | EXPR '+' EXPR { $$ = $1 + $3; } + | EXPR '-' EXPR { $$ = $1 - $3; } + | EXPR '*' EXPR { $$ = $1 * $3; } + | EXPR '/' EXPR { $$ = $1 / $3; } + | EXPR '%' EXPR { $$ = $1 % $3; } + | EXPR '>' EXPR { if ($1 > $3) { $$ = 1; } else { $$ = 0;}} + | EXPR '<' EXPR { if ($1 < $3) { $$ = 1; } else { $$ = 0;}} + | INCREASE EXPR { $$ = $2 + 1; } + | EXPR INCREASE { $$ = $1 + 1; } + | DECREASE EXPR { $$ = $2 - 1; } + | EXPR DECREASE { $$ = $1 - 1; } + | '(' EXPR ')' { $$ = $2; } + ; + +PRINT: + VARNAME { $$ = create_print_variable($1); } + | EXPR { $$ = create_print_statement(VAR_INT, alloc_value(&$1, VAR_INT)); } + | STRING { $$ = create_print_statement(VAR_STRING, $1); } + ; + +%% + +void yyerror(char *s) +{ + fprintf(stderr, "Error on line %d, %s\n", yylineno, s); +} + diff --git a/deon-unix/functions/functions.c b/deon-unix/functions/functions.c new file mode 100644 index 0000000..55e3e5c --- /dev/null +++ b/deon-unix/functions/functions.c @@ -0,0 +1,125 @@ +#ifndef FUNCTIONS_C +#define FUNCTIONC_C +#include "functions.h" + +/* + Author: xerox + Update: 1/20/2020 + + create a function given the name of the function and the statements +*/ +static node_info *create_function(char *p_name, node_info *p_stmts) +{ + node_info *new_node = malloc(sizeof(node_info)); + if (!p_name || !p_stmts || !new_node) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + + new_node->function_body = malloc(sizeof(node_info)); + if (!new_node->function_body) + return NULL; + + memset(new_node->function_body, NULL, sizeof(*new_node->function_body)); + new_node->operation = FUNCTION_OPERATION; + new_node->operation_type.func = FUNCTION; + new_node->name = p_name; + new_node->next = NULL; + new_node->function_body->statement_list = p_stmts; + return new_node; +} + +/* + Author: xerox + Update: 1/20/2020 + + create a function call given the name + TODO add scope. +*/ +static node_info *create_function_call(char *p_name) +{ + node_info *new_node = malloc(sizeof(node_info)); + if (!new_node || !p_name) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + + new_node->operation = FUNCTION_OPERATION; + new_node->operation_type.func = FUNCTION_CALL; + new_node->name = p_name; + new_node->next = NULL; + return new_node; +} + +/* + Author: xerox + Update: 1/20/2020 + + create compound statement given statement list and head of linked list. +*/ +static node_info *create_compound_statement(node_info *new_statement_list, node_info *statement_head) +{ + if (!new_statement_list) + return NULL; + + if(!statement_head) + { + statement_head = malloc(sizeof(node_info)); + node_info* new_node = malloc(sizeof(node_info)); + if (!new_node || !statement_head) + return NULL; + memset(statement_head, NULL, sizeof(*statement_head)); + memset(new_node, NULL, sizeof(*new_node)); + + statement_head->statement_list = malloc(sizeof(node_info)); + if (!statement_head->statement_list) + return NULL; + memset(statement_head->statement_list, NULL, + sizeof(*statement_head->statement_list)); + + statement_head->operation = EXEC_STMT_LIST_OPERATION; + statement_head->statement_list->operation = EXEC_STMT_LIST_OPERATION; + statement_head->statement_list->next = new_statement_list; + statement_head->statement_list->statement_list = NULL; + } + else + { + node_info *p_temp_head = statement_head; + //TODO update with doubly linked list + while(p_temp_head->statement_list != NULL) + p_temp_head = p_temp_head->statement_list; + + p_temp_head->statement_list = malloc(sizeof(node_info)); + if (!p_temp_head->statement_list) + return NULL; + memset(p_temp_head->statement_list, NULL, sizeof(*p_temp_head->statement_list)); + + p_temp_head->operation = EXEC_STMT_LIST_OPERATION; + p_temp_head->statement_list->operation = EXEC_STMT_LIST_OPERATION; + p_temp_head->statement_list->next = new_statement_list; + p_temp_head->statement_list->statement_list = NULL; + } + return statement_head; +} + +/* + Author: xerox + Update: 1/20/2020 + + add to compound statement given new statement and head of statement, +*/ +static node_info* add_to_compound_statement(node_info* new_statement, node_info* statement_head) +{ + if (!new_statement || !statement_head) + return NULL; + + node_info* p_head_tmp = statement_head; + while (p_head_tmp->statement_list) + p_head_tmp = p_head_tmp->statement_list; + + while (p_head_tmp->next) + p_head_tmp = p_head_tmp->next; + + p_head_tmp->next = malloc(sizeof(node_info)); + p_head_tmp->next = new_statement; + return statement_head; +} +#endif \ No newline at end of file diff --git a/deon-unix/functions/functions.h b/deon-unix/functions/functions.h new file mode 100644 index 0000000..5e2a907 --- /dev/null +++ b/deon-unix/functions/functions.h @@ -0,0 +1,11 @@ +#ifndef FUNCTIONS +#define FUNCTIONS +#include "../types.h" +#include "../linked_list/linked_list.h" +#include "../linked_list/linked_list.c" + +node_info *create_function(char *p_name, node_info *p_stmts); +node_info *create_function_call(char *p_name); +node_info *create_compound_statement(node_info *new_statement_list, node_info *statement_head); +node_info* add_to_compound_statement(node_info* new_statement, node_info* statement_head); +#endif \ No newline at end of file diff --git a/deon-unix/hashmap/map.c b/deon-unix/hashmap/map.c new file mode 100644 index 0000000..6a2a228 --- /dev/null +++ b/deon-unix/hashmap/map.c @@ -0,0 +1,190 @@ +#ifndef MAP_C +#define MAP_C + +#include +#include +#include "map.h" + +struct map_node_t { + unsigned hash; + void *value; + map_node_t *next; + /* char key[]; */ + /* char value[]; */ +}; + + +static unsigned map_hash(const char *str) { + unsigned hash = 5381; + while (*str) { + hash = ((hash << 5) + hash) ^ *str++; + } + return hash; +} + + +static map_node_t *map_newnode(const char *key, void *value, int vsize) { + map_node_t *node; + int ksize = strlen(key) + 1; + int voffset = ksize + ((sizeof(void*) - ksize) % sizeof(void*)); + node = malloc(sizeof(*node) + voffset + vsize); + if (!node) return NULL; + memcpy(node + 1, key, ksize); + node->hash = map_hash(key); + node->value = ((char*) (node + 1)) + voffset; + memcpy(node->value, value, vsize); + return node; +} + + +static int map_bucketidx(map_base_t *m, unsigned hash) { + /* If the implementation is changed to allow a non-power-of-2 bucket count, + * the line below should be changed to use mod instead of AND */ + return hash & (m->nbuckets - 1); +} + + +static void map_addnode(map_base_t *m, map_node_t *node) { + int n = map_bucketidx(m, node->hash); + node->next = m->buckets[n]; + m->buckets[n] = node; +} + + +static int map_resize(map_base_t *m, int nbuckets) { + map_node_t *nodes, *node, *next; + map_node_t **buckets; + int i; + /* Chain all nodes together */ + nodes = NULL; + i = m->nbuckets; + while (i--) { + node = (m->buckets)[i]; + while (node) { + next = node->next; + node->next = nodes; + nodes = node; + node = next; + } + } + /* Reset buckets */ + buckets = realloc(m->buckets, sizeof(*m->buckets) * nbuckets); + if (buckets != NULL) { + m->buckets = buckets; + m->nbuckets = nbuckets; + } + if (m->buckets) { + memset(m->buckets, 0, sizeof(*m->buckets) * m->nbuckets); + /* Re-add nodes to buckets */ + node = nodes; + while (node) { + next = node->next; + map_addnode(m, node); + node = next; + } + } + /* Return error code if realloc() failed */ + return (buckets == NULL) ? -1 : 0; +} + + +static map_node_t **map_getref(map_base_t *m, const char *key) { + unsigned hash = map_hash(key); + map_node_t **next; + if (m->nbuckets > 0) { + next = &m->buckets[map_bucketidx(m, hash)]; + while (*next) { + if ((*next)->hash == hash && !strcmp((char*) (*next + 1), key)) { + return next; + } + next = &(*next)->next; + } + } + return NULL; +} + + +void map_deinit_(map_base_t *m) { + map_node_t *next, *node; + int i; + i = m->nbuckets; + while (i--) { + node = m->buckets[i]; + while (node) { + next = node->next; + free(node); + node = next; + } + } + free(m->buckets); +} + + +void *map_get_(map_base_t *m, const char *key) { + map_node_t **next = map_getref(m, key); + return next ? (*next)->value : NULL; +} + + +int map_set_(map_base_t *m, const char *key, void *value, int vsize) { + int n, err; + map_node_t **next, *node; + /* Find & replace existing node */ + next = map_getref(m, key); + if (next) { + memcpy((*next)->value, value, vsize); + return 0; + } + /* Add new node */ + node = map_newnode(key, value, vsize); + if (node == NULL) goto fail; + if (m->nnodes >= m->nbuckets) { + n = (m->nbuckets > 0) ? (m->nbuckets << 1) : 1; + err = map_resize(m, n); + if (err) goto fail; + } + map_addnode(m, node); + m->nnodes++; + return 0; + fail: + if (node) free(node); + return -1; +} + + +void map_remove_(map_base_t *m, const char *key) { + map_node_t *node; + map_node_t **next = map_getref(m, key); + if (next) { + node = *next; + *next = (*next)->next; + free(node); + m->nnodes--; + } +} + + +map_iter_t map_iter_(void) { + map_iter_t iter; + iter.bucketidx = -1; + iter.node = NULL; + return iter; +} + + +const char *map_next_(map_base_t *m, map_iter_t *iter) { + if (iter->node) { + iter->node = iter->node->next; + if (iter->node == NULL) goto nextBucket; + } else { + nextBucket: + do { + if (++iter->bucketidx >= m->nbuckets) { + return NULL; + } + iter->node = m->buckets[iter->bucketidx]; + } while (iter->node == NULL); + } + return (char*) (iter->node + 1); +} +#endif \ No newline at end of file diff --git a/deon-unix/hashmap/map.h b/deon-unix/hashmap/map.h new file mode 100644 index 0000000..59758ab --- /dev/null +++ b/deon-unix/hashmap/map.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2014 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef MAP_H +#define MAP_H + +#include + +#define MAP_VERSION "0.1.0" + +struct map_node_t; +typedef struct map_node_t map_node_t; + +typedef struct { + map_node_t **buckets; + unsigned nbuckets, nnodes; +} map_base_t; + +typedef struct { + unsigned bucketidx; + map_node_t *node; +} map_iter_t; + + +#define map_t(T)\ + struct { map_base_t base; T *ref; T tmp; } + + +#define map_init(m)\ + memset(m, 0, sizeof(*(m))) + + +#define map_deinit(m)\ + map_deinit_(&(m)->base) + + +#define map_get(m, key)\ + ( (m)->ref = map_get_(&(m)->base, key) ) + + +#define map_set(m, key, value)\ + ( (m)->tmp = (value),\ + map_set_(&(m)->base, key, &(m)->tmp, sizeof((m)->tmp)) ) + + +#define map_remove(m, key)\ + map_remove_(&(m)->base, key) + + +#define map_iter(m)\ + map_iter_() + + +#define map_next(m, iter)\ + map_next_(&(m)->base, iter) + + +void map_deinit_(map_base_t *m); +void *map_get_(map_base_t *m, const char *key); +int map_set_(map_base_t *m, const char *key, void *value, int vsize); +void map_remove_(map_base_t *m, const char *key); +map_iter_t map_iter_(void); +const char *map_next_(map_base_t *m, map_iter_t *iter); + + +typedef map_t(void*) map_void_t; +typedef map_t(char*) map_str_t; +typedef map_t(int) map_int_t; +typedef map_t(char) map_char_t; +typedef map_t(float) map_float_t; +typedef map_t(double) map_double_t; + +#endif \ No newline at end of file diff --git a/deon-unix/install.sh b/deon-unix/install.sh new file mode 100644 index 0000000..e050fb1 --- /dev/null +++ b/deon-unix/install.sh @@ -0,0 +1 @@ +sudo apt install flex bison \ No newline at end of file diff --git a/deon-unix/linked_list/linked_list.c b/deon-unix/linked_list/linked_list.c new file mode 100644 index 0000000..955b954 --- /dev/null +++ b/deon-unix/linked_list/linked_list.c @@ -0,0 +1,87 @@ +#ifndef LINKED_LIST_C +#define LINKED_LIST_C +#include "linked_list.h" + +/* + Author: xerox + Update: 1/20/2020 + + free's linked list. +*/ +static void free_linked_list(node_info *p_list) +{ + if (!p_list) + return; + node_info* temp; + while (p_list->next) + { + temp = p_list; + p_list = p_list->next; + free(temp); + } +} + +/* + Author: xerox + Update: 1/20/2020 + + updates linked list. +*/ +static node_info *copy_linked_list(node_info *p_list) +{ + node_info* new_list = malloc(sizeof(node_info)); + if (!new_list || !p_list) + return NULL; + + new_list->next = NULL; + node_info *copy_list = new_list; + //TODO update with doubly linked list + while(p_list->next) + { + p_list = p_list->next; + copy_list->next = p_list; + } + return new_list; +} + +/* + Author: xerox + Update: 1/20/2020 + + append to linked list. +*/ +static void linked_list_append(node_info* p_head, node_info* new_node) +{ + if (!p_head || !new_node) + return; + node_info* p_head_temp = p_head; + while (p_head->next) + p_head_temp = p_head_temp->next; + p_head->next = NULL; //sanity check + p_head_temp->next = p_head; +} + +/* + Author: xerox + Update: 1/20/2020 + + remove link from linked list. +*/ +static bool linked_list_remove(node_info* p_head, node_info* delete_node) +{ + if (!p_head || !delete_node) + return false; + + node_info* p_head_temp = p_head; + while (p_head_temp->next) + { + if (p_head_temp->next == delete_node) + { + p_head_temp->next = delete_node->next; + free(delete_node); + return true; + } + } + return false; +} +#endif \ No newline at end of file diff --git a/deon-unix/linked_list/linked_list.h b/deon-unix/linked_list/linked_list.h new file mode 100644 index 0000000..4260885 --- /dev/null +++ b/deon-unix/linked_list/linked_list.h @@ -0,0 +1,9 @@ +#ifndef LINKED_LIST_H +#define LINKED_LIST_H +#include "../types.h" + +void free_linked_list(node_info *p_list); +node_info *copy_linked_list(node_info *p_list); +void linked_list_append(node_info* p_head, node_info* new_node); +bool linked_list_remove(node_info* p_head, node_info* delete_node); +#endif diff --git a/deon-unix/logic/logic.c b/deon-unix/logic/logic.c new file mode 100644 index 0000000..33a4880 --- /dev/null +++ b/deon-unix/logic/logic.c @@ -0,0 +1,20 @@ +#include "logic.h" + +/* + Author: xerox + Date: 1/19/2020 + + creates logic given type, statement list to execute, and variable name for condition. +*/ +static logic* create_logic(logic_type type, node_info* stmt_list, char* var_name) +{ + logic* new_logic = malloc(sizeof(logic)); + if (!new_logic || !stmt_list || !var_name) + return NULL; + + memset(new_logic, NULL, sizeof(*new_logic)); + new_logic->type = type; + new_logic->condition_var = var_name; + new_logic->stmt_list = stmt_list; + return new_logic; +} \ No newline at end of file diff --git a/deon-unix/logic/logic.h b/deon-unix/logic/logic.h new file mode 100644 index 0000000..14172a2 --- /dev/null +++ b/deon-unix/logic/logic.h @@ -0,0 +1,5 @@ +#ifndef LOGIC_H +#define LOGIC_H +#include "../types.h" +logic* create_logic(logic_type type, node_info* stmt_list, char* var_name); +#endif \ No newline at end of file diff --git a/deon-unix/make.sh b/deon-unix/make.sh new file mode 100644 index 0000000..316e335 --- /dev/null +++ b/deon-unix/make.sh @@ -0,0 +1,3 @@ +lex deon.l +yacc -d deon.y +gcc lex.yy.c y.tab.c -o deon diff --git a/deon-unix/parser/parser.c b/deon-unix/parser/parser.c new file mode 100644 index 0000000..b9067f5 --- /dev/null +++ b/deon-unix/parser/parser.c @@ -0,0 +1,257 @@ +#ifndef PARSER_C +#define PARSER_C +#include "parser.h" + +/* + Author: xerox + Updated: 1/19/2020 + + create variable given name, value, and type. +*/ +static node_info* create_variable_const(char* p_name, void* value, variable_type var_type) +{ + node_info* new_node = malloc(sizeof(*new_node)); + if (!new_node) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + variable* new_var = make_variable(p_name, value, var_type); + if (!new_var) + return NULL; + new_node->assignment = (assignment_operation*)malloc(sizeof(assignment_operation)); + if (!new_node->assignment) + return NULL; + memset(new_node->assignment, NULL, sizeof(*new_node->assignment)); + new_node->operation = ASSIGNMENT_OPERATION; + new_node->operation_type.assignment = ASSIGN_FROM_CONST; + new_node->assignment->var = new_var; + return new_node; +} + +/* + Author: xerox + Updated: 1/20/2020 + + Move value from one variable to another. +*/ +static node_info* move_value(char* to, char* from) +{ + node_info* new_node = (node_info *)malloc(sizeof(node_info)); + if (!from || !new_node || !to) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + new_node->assignment = (assignment_operation*)malloc(sizeof(*new_node->assignment)); + if (!new_node->assignment) + return NULL; + memset(new_node->assignment, NULL, sizeof(*new_node->assignment)); + new_node->operation = ASSIGNMENT_OPERATION; + new_node->operation_type.assignment = ASSIGN_FROM_VAR; + new_node->assignment->from = from; + new_node->assignment->to = to; + return new_node; +} + +/* + Author: xerox + Updated: 1/19/2020 + + create logic node (logical expression) +*/ +static node_info* create_logic_node(logic* logic_expr) +{ + node_info* new_node = malloc(sizeof(node_info)); + if (!new_node || !logic_expr) + return NULL; + + memset(new_node, NULL, sizeof(*new_node)); + new_node->operation = LOGIC_OPERATION; + new_node->logical_expr = logic_expr; + return new_node; +} + +/* + Author: xerox + Updated: 1/20/2020 + + Executes a statment. + + @param nodeInfo statement to be executed + @return void. +*/ + +static void exec_stmt(node_info *exec_node) +{ + if (!exec_node) + return; + + switch (exec_node->operation) + { + case ASSIGNMENT_OPERATION: + switch (exec_node->operation_type.assignment) + { + case ASSIGN_FROM_CONST: + add_var(exec_node->assignment->var->name, exec_node->assignment->var->value, _var_map); + break; + case ASSIGN_FROM_VAR: + add_var(exec_node->assignment->to, + get_value(exec_node->assignment->from, _var_map), _var_map); + break; + default: + ; +#if DEON_DEBUGGING + printf("[error] unkown assignment operation: 0x%x", exec_node->operation_type.assignment); +#endif + } + break; + case LOGIC_OPERATION: + { + switch (exec_node->logical_expr->type) + { + case IF_LOGIC: + { + variable_values* p_var_values = get_value(exec_node->logical_expr->condition_var, _var_map); + if (!p_var_values) + return; + if (*(unsigned char*)p_var_values->data_ptr) + exec_stmt(exec_node->logical_expr->stmt_list); + break; + } + case WHILE_LOGIC: + { + variable_values* p_var_values = get_value(exec_node->logical_expr->condition_var, _var_map); + if (!p_var_values) + return; + while (*(unsigned char*)p_var_values->data_ptr) + { + exec_stmt(exec_node->logical_expr->stmt_list); + p_var_values = get_value(exec_node->logical_expr->condition_var, _var_map); + } + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown logic operation\n"); +#endif + } + } + // execute statement list. + case EXEC_STMT_LIST_OPERATION: + { + if(exec_node->statement_list) + exec_node = exec_node->statement_list; + while (exec_node->next) + { + exec_node = exec_node->next; + exec_stmt(exec_node); + } + break; + } + // print statement + case PRINT_OPERATION: + { + switch (exec_node->operation_type.print) + { + case PRINT_CONSTANT: + { + switch (exec_node->print_expr->type) + { + case VAR_STRING: + printf("%s\n", (char*)exec_node->print_expr->value); + break; + case VAR_INT: + printf("%d\n", *(int*)exec_node->print_expr->value); + break; + case VAR_BYTE: + printf("%c\n", *(char*)exec_node->print_expr->value); + break; + case VAR_DOUBLE: + printf("%f\n", *(double*)exec_node->print_expr->value); + break; + case VAR_VOID: //TODO add void variable type + break; + default: + ; +#if DEON_DEBUGGING + printf("[error] unable to print variable of type: 0x%x\n", exec_node->print_expr->type); +#endif + } + break; + } + case PRINT_VARIABLE: + { + variable_values* p_var = get_value(exec_node->var->name, _var_map); + switch (p_var->type) + { + case VAR_STRING: + printf("%s\n", (char*)p_var->data_ptr); + break; + case VAR_INT: + printf("%d\n", *(int*)p_var->data_ptr); + break; + case VAR_BYTE: + printf("%c\n", *(char*)p_var->data_ptr); + break; + case VAR_DOUBLE: + printf("%f\n", *(double*)p_var->data_ptr); + break; + case VAR_VOID: //TODO add void variable type + break; + default: + ; +#if DEON_DEBUGGING + printf("[error] unable to print variable of type: 0x%x\n", p_var->type); +#endif + } + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown print type: 0x%x\n", exec_node->operation_type.print); +#endif + } + break; + } + case FUNCTION_OPERATION: + { + switch (exec_node->operation_type.func) + { + case FUNCTION_CALL: + { + node_info* _stmts = *map_get(&*((map_void_t*)_function_list), exec_node->name); + _stmts = _stmts->statement_list; + while (_stmts->statement_list) + { + _stmts = _stmts->statement_list; + exec_stmt(_stmts); + } + break; + } + case FUNCTION: + { + if (!_function_list) + { + _function_list = malloc(sizeof(map_void_t)); + map_init(_function_list); + map_set(_function_list, exec_node->name, exec_node->function_body); + } + else //else we dont malloc, we just put the function inside of the hashmap. + map_set(_function_list, exec_node->name, exec_node->function_body); + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown function operation: 0x%x\n", exec_node->operation_type.func); +#endif + } + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown operation: 0x%x\n", exec_node->operation); +#endif + } +} +#endif \ No newline at end of file diff --git a/deon-unix/parser/parser.h b/deon-unix/parser/parser.h new file mode 100644 index 0000000..7e86635 --- /dev/null +++ b/deon-unix/parser/parser.h @@ -0,0 +1,9 @@ +#ifndef PARSER_H +#define PARSER_H +#include "../types.h" +#include "../vars/vars.h" +node_info* create_variable_const(char* p_name, void* value, variable_type var_type); +node_info* move_value(char* to, char* from); +node_info* create_logic_node(logic* logic_expr); +void exec_stmt(node_info *exec_node); +#endif diff --git a/deon-unix/print/print.c b/deon-unix/print/print.c new file mode 100644 index 0000000..ee82467 --- /dev/null +++ b/deon-unix/print/print.c @@ -0,0 +1,54 @@ +#ifndef PRINT_C +#define PRINT_C +#include "print.h" + +/* + Author: xerox + Updated: 1/20/2020 + + creates a print statement given variable type and value. +*/ + +static node_info *create_print_statement(variable_type operation, void* value) +{ + node_info* new_print_stmt = (node_info*)malloc(sizeof(node_info)); + print* new_print = malloc(sizeof(print)); + if (!new_print_stmt || !new_print) + return NULL; + memset(new_print_stmt, NULL, sizeof(*new_print_stmt)); + memset(new_print, NULL, sizeof(*new_print)); + + new_print_stmt->operation = PRINT_OPERATION; + new_print_stmt->operation_type.print = PRINT_CONSTANT; + new_print->type = operation; + new_print->value = value; + new_print_stmt->print_expr = new_print; + new_print_stmt->next = NULL; + return new_print_stmt; +} + +/* + Author: xerox + Updated: 1/19/2020 + + create print variable from variable name. +*/ +static node_info* create_print_variable(char* var_name) +{ + node_info* new_print_stmt = (node_info*)malloc(sizeof(node_info)); + if (!new_print_stmt || !var_name) + return NULL; + memset(new_print_stmt, NULL, sizeof(*new_print_stmt)); + + new_print_stmt->var = malloc(sizeof(variable)); + if (!new_print_stmt->var) + return NULL; + memset(new_print_stmt->var, NULL, sizeof(*new_print_stmt->var)); + + new_print_stmt->operation = PRINT_OPERATION; + new_print_stmt->operation_type.print = PRINT_VARIABLE; + new_print_stmt->var->name = var_name; + new_print_stmt->next = NULL; + return new_print_stmt; +} +#endif diff --git a/deon-unix/print/print.h b/deon-unix/print/print.h new file mode 100644 index 0000000..f2bc18b --- /dev/null +++ b/deon-unix/print/print.h @@ -0,0 +1,6 @@ +#ifndef PRINT_H +#define PRINT_H +#include "../types.h" +node_info* create_print_statement(variable_type operation, void* value); +node_info* create_print_variable(char* var_name); +#endif \ No newline at end of file diff --git a/deon-unix/types.h b/deon-unix/types.h new file mode 100644 index 0000000..f81047e --- /dev/null +++ b/deon-unix/types.h @@ -0,0 +1,128 @@ +#ifndef INCLUDE_H +#define INCLUDE_H +#include +#include +#include +#include "hashmap/map.h" + +#define DEON_DEBUGGING 0 +bool _DEON_DEBUG; + +//--- different variable values +typedef enum _variable_type +{ + VAR_INT, + VAR_SHORT, + VAR_BYTE, + VAR_DOUBLE, + VAR_STRING, + VAR_VOID +} variable_type; + +//--- different function operations +typedef enum _function_type +{ + FUNCTION, + FUNCTION_CALL, +} function_type; + +//--- different print operations +typedef enum _print_type +{ + PRINT_VARIABLE, + PRINT_CONSTANT +} print_type; + +//--- different logic types +typedef enum _logic_type +{ + IF_LOGIC, + WHILE_LOGIC +} logic_type; + +typedef enum _assignment_type +{ + ASSIGN_FROM_VAR, + ASSIGN_FROM_CONST +} assignment_type; + +//--- all operations in the language +typedef enum _operation +{ + ASSIGNMENT_OPERATION, + LOGIC_OPERATION, + EXEC_STMT_LIST_OPERATION, + PRINT_OPERATION, + FUNCTION_OPERATION, +}; + +//--- variable value details +typedef struct _variable_values +{ + variable_type type; + void* data_ptr; +} variable_values; + +//--- variable details +typedef struct _variable +{ + char *name; + variable_values *value; + struct variable *next; +} variable; + +//--- print data +typedef struct _print +{ + enum _variable_type type; + void* value; +} print; + +//--- assignment data +typedef struct _assignment_operation +{ + char* from; + char* to; + variable* var; +}assignment_operation; + +//--- logic operation data +typedef struct _logic +{ + logic_type type; + char* condition_var; + struct node_info* stmt_list; +} logic; + +//--- struct that brings it all together +typedef struct node_info +{ + //--- node operation. + enum _operation operation; + + //--- sub operations. + union _operation_type + { + logic_type logic; + function_type func; + print_type print; + assignment_type assignment; + } operation_type; + + char *name; + print* print_expr; + logic* logical_expr; + assignment_operation* assignment; + variable* var; + struct node_info *next; + struct node_info *function_body; + struct node_info *statement_list; + struct node_info *new_scope; + struct map_void_t *var_map; +} node_info; + +//--- globals +map_void_t* _var_map; +node_info* _temp_statement_head; +map_void_t* _function_list; +#endif diff --git a/deon-unix/vars/vars.c b/deon-unix/vars/vars.c new file mode 100644 index 0000000..cdad775 --- /dev/null +++ b/deon-unix/vars/vars.c @@ -0,0 +1,104 @@ +#ifndef VARS_C +#define VARS_C +#include "vars.h" + +/* + Author: xerox + Date: 1/20/2020 + + add var to hashmap of variables. +*/ +static void add_var(char *p_name, variable_values *p_values, map_void_t* p_var_map) +{ + if (!p_name || !p_values) + return; + map_set(p_var_map, p_name, p_values); +} + + +/* + Author: xerox + Date: 1/20/2020 + + get value given name and hashmap. +*/ +static variable_values* get_value(char *p_name, map_void_t* p_var_map) +{ + if (!p_name) + return NULL; + return *map_get(&*((map_void_t* ) p_var_map), p_name); +} + +/* + Author: xerox + Date: 1/20/2020 + + makes a variable struct and define it. +*/ +static variable* make_variable(char *p_name, void* value, variable_type var_type) +{ + variable *new_var = malloc(sizeof(variable)); + variable_values *new_value = malloc(sizeof(variable_values)); + if (!new_var || !new_value || !p_name || !value) + return NULL; + + memset(new_var, NULL, sizeof(*new_var)); + memset(new_value, NULL, sizeof(*new_value)); + new_value->type = var_type; + new_value->data_ptr = value; + new_var->name = p_name; + new_var->value = new_value; + return new_var; +} + +/* + Author: xerox + Date: 1/20/2020 + + allocate memory for values that are 8 bytes or less. +*/ +static void* alloc_value(void* value, variable_type var_type) +{ + switch (var_type) + { + case VAR_INT: + { + int* p_int = (int*)malloc(sizeof(int)); + if (!p_int) + return NULL; + memset(p_int, NULL, sizeof(*p_int)); + *p_int = *(int*)value; + return p_int; + } + case VAR_SHORT: + { + short* p_short = (short*)malloc(sizeof(short)); + if (!p_short) + return NULL; + memset(p_short, NULL, sizeof(*p_short)); + *p_short = *(short*)value; + return p_short; + } + case VAR_BYTE: + { + char* p_char = malloc(sizeof(char)); + if (!p_char) + return NULL; + memset(p_char, NULL, sizeof(*p_char)); + *p_char = *(char*)value; + return p_char; + } + case VAR_DOUBLE: + { + double* p_double = malloc(sizeof(double)); + if (!p_double) + return NULL; + memset(p_double, NULL, sizeof(*p_double)); + *p_double = *(double*)value; + return p_double; + } + default: + return NULL; + } +} +#endif \ No newline at end of file diff --git a/deon-unix/vars/vars.h b/deon-unix/vars/vars.h new file mode 100644 index 0000000..dd2907f --- /dev/null +++ b/deon-unix/vars/vars.h @@ -0,0 +1,8 @@ +#ifndef VARS_H +#define VARS_H +#include "../types.h" +void add_var(char* name, variable_values* values, map_void_t* p_var_map); +variable* make_variable(char* p_name, void* value, variable_type var_type); +variable_values* get_value(char* p_name, map_void_t* p_var_map); +void* alloc_value(void* value, variable_type var_type); +#endif diff --git a/deon-win/.vs/deon/v16/.suo b/deon-win/.vs/deon/v16/.suo new file mode 100644 index 0000000..fcf4359 Binary files /dev/null and b/deon-win/.vs/deon/v16/.suo differ diff --git a/deon-win/.vs/deon/v16/Browse.VC.db b/deon-win/.vs/deon/v16/Browse.VC.db new file mode 100644 index 0000000..be17c37 Binary files /dev/null and b/deon-win/.vs/deon/v16/Browse.VC.db differ diff --git a/deon-win/deon.sln b/deon-win/deon.sln new file mode 100644 index 0000000..ac97aa5 --- /dev/null +++ b/deon-win/deon.sln @@ -0,0 +1,46 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.181 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deon", "deon\deon.vcxproj", "{B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + arm|ARM = arm|ARM + arm|x64 = arm|x64 + arm|x86 = arm|x86 + Debug|ARM = Debug|ARM + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.arm|ARM.ActiveCfg = Debug|ARM + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.arm|ARM.Build.0 = Debug|ARM + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.arm|x64.ActiveCfg = Release|x64 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.arm|x64.Build.0 = Release|x64 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.arm|x86.ActiveCfg = Release|Win32 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.arm|x86.Build.0 = Release|Win32 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Debug|ARM.ActiveCfg = Debug|ARM + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Debug|ARM.Build.0 = Debug|ARM + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Debug|x64.ActiveCfg = Debug|x64 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Debug|x64.Build.0 = Debug|x64 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Debug|x86.ActiveCfg = Debug|Win32 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Debug|x86.Build.0 = Debug|Win32 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Release|ARM.ActiveCfg = Release|ARM + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Release|ARM.Build.0 = Release|ARM + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Release|x64.ActiveCfg = Release|x64 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Release|x64.Build.0 = Release|x64 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Release|x86.ActiveCfg = Release|Win32 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E72D3DDB-12F2-42F7-A410-068392F5951A} + EndGlobalSection +EndGlobal diff --git a/deon-win/deon/deon.l b/deon-win/deon/deon.l new file mode 100644 index 0000000..d4ee70e --- /dev/null +++ b/deon-win/deon/deon.l @@ -0,0 +1,84 @@ +%{ + #include + #include + #include + #include "types.h" + #include "y.tab.h" + + void yyerror(char *); + + extern YYSTYPE yylval; + extern FILE *yyin; + int yylineno; + +%} +%% +\/\*.*?\*\/ { ; // comment } +-?[0-9]+ { yylval.int_num = atoi(yytext); return INTEGER; } +\'[ -~]\' { yylval.byte_num = yytext[1]; return CHAR; } +[-()<>=+*/:;,%{}\[\]] { return *yytext; } +"if" { return IF; } +"else" { return ELSE; } +"print" { return PRINT_TOKEN; } +"string" { return KEYWORD_S; } +"while" { return WHILE; } +"int" { return KEYWORD_I; } +"def" { return DEF;} +"call" { return CALL; } +"char" { return KEYWORD_C; } +"++" { return INCREASE; } +"--" { return DECREASE; } +\"(\\.|[^"\\])*\" { yytext++; yytext[strlen(yytext)-1] = 0; yylval.str_ptr = strdup(yytext); return STRING; } +[a-zA-Z0-9_]+ { yylval.str_ptr = strdup(yytext); return VARNAME; } +-?[0-9]*\.[0-9]+ { yylval.double_num = atof(yytext); return DOUBLEVAR; } +"\n" { yylineno++; } +[ ?\t\n\r] +. printf("invalid character on line %d, '%s'\n", yylineno, yytext); +<> { exit(0); } +%% + +int yywrap(void) { + + return 1; + +} + +int main(int argc, char* argv[]) +{ + _var_map = malloc(sizeof(map_void_t)); + map_init(_var_map); + _temp_statement_head = NULL; + _function_list = NULL; + FILE *fh; + if (argc > 1) + { + if (strcmp(argv[1],"help") == 0 || strcmp(argv[1],"-help") == 0 + || strcmp(argv[1],"--help") == 0 || strcmp(argv[1],"h") == 0 + || strcmp(argv[1],"-h") == 0) + { + printf("[ HELP ] put a file/path as the first flag.\n"); + printf("[ HELP ] -h, -help, --help, help, h: Prints this.\n"); + printf("[ HELP ] -d, d, -debug, debug: Enter REPL mode.\n"); + } + else if (strcmp(argv[1],"-debug") == 0 || strcmp(argv[1],"-d") == 0 + || strcmp(argv[1],"d") == 0 || strcmp(argv[1],"debug") == 0) + { + _DEON_DEBUG = 1; + printf(">>> "); + yyparse(); + } + else if (fh = fopen(argv[1], "r")) + { + yyin = fh; + yyparse(); + fclose(fh); + } + else + { + printf("[ ERROR ] please enter a correct command. try --help\n"); + fclose(fh); + } + } else + printf("[ ERROR ] missing input file. Try --help?\n"); + return 0; +} \ No newline at end of file diff --git a/deon-win/deon/deon.vcxproj b/deon-win/deon/deon.vcxproj new file mode 100644 index 0000000..dc52098 --- /dev/null +++ b/deon-win/deon/deon.vcxproj @@ -0,0 +1,249 @@ + + + + + Debug + ARM + + + Debug + Win32 + + + Release + ARM + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 16.0 + {B08E2E4F-D8D8-4089-AD3B-6AE42D6F0DBD} + Win32Proj + deon + 10.0 + + + + Application + true + v142 + Unicode + false + + + Application + false + v142 + true + Unicode + false + + + Application + true + v142 + Unicode + false + + + Application + true + v142 + Unicode + false + + + Application + false + v142 + true + Unicode + false + + + Application + false + v142 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + false + + + false + + + false + + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE + true + + + Console + true + + + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE + true + + + Console + true + + + + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE + true + + + Console + true + + + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE + true + + + Console + true + true + true + + + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE + true + + + Console + true + true + true + + + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE + true + + + Console + true + true + true + + + + + + \ No newline at end of file diff --git a/deon-win/deon/deon.vcxproj.filters b/deon-win/deon/deon.vcxproj.filters new file mode 100644 index 0000000..0ba51e0 --- /dev/null +++ b/deon-win/deon/deon.vcxproj.filters @@ -0,0 +1,125 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {e714c06a-61ed-402f-aba1-b117816214ef} + + + {09c9fb63-23fb-4550-a04d-e80dfa427087} + + + {f02fae95-5469-4a66-965c-ab6e34944acc} + + + {dfbeb42c-97f8-442c-9e2b-b06bddbaf130} + + + {cc02b417-9e26-4516-ad85-0d4635c42a8a} + + + {aa53f4f6-6c52-40a3-83ca-a40248cee33f} + + + {95c73e4f-29a8-422c-b888-7d34a098475a} + + + {d3b81bd9-e566-495b-9a64-4fa4338c0edc} + + + {0b0b872d-e26d-42e7-b04b-6dd4ca4d2b8a} + + + {a36a6e3d-0e8f-4b31-8704-d2f9cc2e8dc6} + + + {74db9698-20f2-4845-a492-79864f55ce95} + + + {f9162cac-d61b-4569-8d3f-50c3340ecfb7} + + + {b8feaf5e-1191-47dd-9c30-65893043cf41} + + + {8d996674-ea54-4b0c-a572-099444cf65a3} + + + + + Header Files\logic + + + Header Files\linked_list + + + Header Files\hashmap + + + Header Files\functions + + + Header Files\vars + + + Header Files\print + + + Header Files\parser + + + Header Files + + + Header Files + + + + + Source Files\logic + + + Source Files\linked_list + + + Source Files\hashmap + + + Source Files\functions + + + Source Files\parser + + + Source Files\print + + + Source Files\vars + + + Source Files + + + Source Files + + + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/deon-win/deon/deon.vcxproj.user b/deon-win/deon/deon.vcxproj.user new file mode 100644 index 0000000..29ad4b4 --- /dev/null +++ b/deon-win/deon/deon.vcxproj.user @@ -0,0 +1,27 @@ + + + + -d + WindowsLocalDebugger + + + -d + WindowsLocalDebugger + + + -d + WindowsLocalDebugger + + + -d + WindowsLocalDebugger + + + -d + WindowsLocalDebugger + + + -d + WindowsLocalDebugger + + \ No newline at end of file diff --git a/deon-win/deon/deon.y b/deon-win/deon/deon.y new file mode 100644 index 0000000..98cbe16 --- /dev/null +++ b/deon-win/deon/deon.y @@ -0,0 +1,119 @@ +%{ +#include +#include +#include + +#include "types.h" +#include "parser/parser.c" +#include "functions/functions.c" +#include "logic/logic.c" +#include "print/print.c" +#include "vars/vars.c" + +int yylex(void); +void yyerror(char *); +extern int yylineno; + +%} + +/* doing these before multiplication and division because they have a lower presidence */ +%left '<' '>' + +%left '+' '-' +/* doing this last so they have a higher presidence */ +%left '*' '/' '%' + +%union { + char* str_ptr; + int int_num; + unsigned uint_num; + char byte_num; + double double_num; + float float_num; + struct node_info *node_ptr; +} + + +%token INCREASE DECREASE PRINT_TOKEN IF END KEYWORD_S KEYWORD_I KEYWORD_C QUOTE ELSE WHILE DEF CALL +%token INTEGER +%token STRING VARNAME +%token CHAR +%token DOUBLEVAR +%token FLOAT_NUM +%type EXPR +%type STMT PRINT VARIABLE FUNC STMT_LIST LOGIC + +%% + +PROGRAM: + MAIN '\n' + | + ; + +MAIN: + MAIN FUNC ';' { if (_DEON_DEBUG == true ) { printf(">>> "); exec_stmt($2); } else { exec_stmt($2); } } + | + ; + +FUNC: + DEF VARNAME ':' '{' STMT_LIST '}' { $$ = create_function($2, $5); } + | CALL VARNAME { $$ = create_function_call($2); } + ; + +STMT_LIST: + STMT ';' { $$ = create_compound_statement($1, _temp_statement_head); } + | STMT_LIST STMT ';' { $$ = add_to_compound_statement($2, $1); } + ; + +STMT: + VARIABLE { $$ = $1; } + | LOGIC { $$ = $1; } + | FUNC { $$ = $1; } + | PRINT_TOKEN '[' PRINT ']' { $$ = $3; } + | '{' STMT_LIST '}' { $$ = $2; } + ; + +LOGIC: + IF '[' VARNAME ']' ':' '{' STMT_LIST '}' { $$ = create_logic_node(create_logic(IF_LOGIC, $7, $3)); } + | WHILE '[' VARNAME ']' ':' '{' STMT_LIST '}' { $$ = create_logic_node(create_logic(WHILE_LOGIC, $7, $3)); } + ; + + +VARIABLE: + VARNAME '=' STRING { $$ = create_variable_const($1, (void *) $3, VAR_STRING);} + | VARNAME '=' EXPR { $$ = create_variable_const($1, alloc_value(&$3, VAR_INT), VAR_INT);} + | VARNAME '=' CHAR { $$ = create_variable_const($1, alloc_value(&$3, VAR_BYTE), VAR_BYTE);} + | VARNAME '=' DOUBLEVAR { $$ = create_variable_const($1, alloc_value(&$3, VAR_DOUBLE), VAR_DOUBLE);} + | VARNAME '=' '{' STMT_LIST '}' { $$ = create_function($1, $4); } + | VARNAME '=' VARNAME { $$ = move_value($1, $3); } + ; + +EXPR: + INTEGER { $$ = $1; } + | EXPR '+' EXPR { $$ = $1 + $3; } + | EXPR '-' EXPR { $$ = $1 - $3; } + | EXPR '*' EXPR { $$ = $1 * $3; } + | EXPR '/' EXPR { $$ = $1 / $3; } + | EXPR '%' EXPR { $$ = $1 % $3; } + | EXPR '>' EXPR { if ($1 > $3) { $$ = 1; } else { $$ = 0;}} + | EXPR '<' EXPR { if ($1 < $3) { $$ = 1; } else { $$ = 0;}} + | INCREASE EXPR { $$ = $2 + 1; } + | EXPR INCREASE { $$ = $1 + 1; } + | DECREASE EXPR { $$ = $2 - 1; } + | EXPR DECREASE { $$ = $1 - 1; } + | '(' EXPR ')' { $$ = $2; } + ; + +PRINT: + VARNAME { $$ = create_print_variable($1); } + | EXPR { $$ = create_print_statement(VAR_INT, alloc_value(&$1, VAR_INT)); } + | STRING { $$ = create_print_statement(VAR_STRING, $1); } + ; + +%% + +void yyerror(char *s) +{ + fprintf(stderr, "Error on line %d, %s\n", yylineno, s); +} + diff --git a/deon-win/deon/functions/functions.c b/deon-win/deon/functions/functions.c new file mode 100644 index 0000000..55e3e5c --- /dev/null +++ b/deon-win/deon/functions/functions.c @@ -0,0 +1,125 @@ +#ifndef FUNCTIONS_C +#define FUNCTIONC_C +#include "functions.h" + +/* + Author: xerox + Update: 1/20/2020 + + create a function given the name of the function and the statements +*/ +static node_info *create_function(char *p_name, node_info *p_stmts) +{ + node_info *new_node = malloc(sizeof(node_info)); + if (!p_name || !p_stmts || !new_node) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + + new_node->function_body = malloc(sizeof(node_info)); + if (!new_node->function_body) + return NULL; + + memset(new_node->function_body, NULL, sizeof(*new_node->function_body)); + new_node->operation = FUNCTION_OPERATION; + new_node->operation_type.func = FUNCTION; + new_node->name = p_name; + new_node->next = NULL; + new_node->function_body->statement_list = p_stmts; + return new_node; +} + +/* + Author: xerox + Update: 1/20/2020 + + create a function call given the name + TODO add scope. +*/ +static node_info *create_function_call(char *p_name) +{ + node_info *new_node = malloc(sizeof(node_info)); + if (!new_node || !p_name) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + + new_node->operation = FUNCTION_OPERATION; + new_node->operation_type.func = FUNCTION_CALL; + new_node->name = p_name; + new_node->next = NULL; + return new_node; +} + +/* + Author: xerox + Update: 1/20/2020 + + create compound statement given statement list and head of linked list. +*/ +static node_info *create_compound_statement(node_info *new_statement_list, node_info *statement_head) +{ + if (!new_statement_list) + return NULL; + + if(!statement_head) + { + statement_head = malloc(sizeof(node_info)); + node_info* new_node = malloc(sizeof(node_info)); + if (!new_node || !statement_head) + return NULL; + memset(statement_head, NULL, sizeof(*statement_head)); + memset(new_node, NULL, sizeof(*new_node)); + + statement_head->statement_list = malloc(sizeof(node_info)); + if (!statement_head->statement_list) + return NULL; + memset(statement_head->statement_list, NULL, + sizeof(*statement_head->statement_list)); + + statement_head->operation = EXEC_STMT_LIST_OPERATION; + statement_head->statement_list->operation = EXEC_STMT_LIST_OPERATION; + statement_head->statement_list->next = new_statement_list; + statement_head->statement_list->statement_list = NULL; + } + else + { + node_info *p_temp_head = statement_head; + //TODO update with doubly linked list + while(p_temp_head->statement_list != NULL) + p_temp_head = p_temp_head->statement_list; + + p_temp_head->statement_list = malloc(sizeof(node_info)); + if (!p_temp_head->statement_list) + return NULL; + memset(p_temp_head->statement_list, NULL, sizeof(*p_temp_head->statement_list)); + + p_temp_head->operation = EXEC_STMT_LIST_OPERATION; + p_temp_head->statement_list->operation = EXEC_STMT_LIST_OPERATION; + p_temp_head->statement_list->next = new_statement_list; + p_temp_head->statement_list->statement_list = NULL; + } + return statement_head; +} + +/* + Author: xerox + Update: 1/20/2020 + + add to compound statement given new statement and head of statement, +*/ +static node_info* add_to_compound_statement(node_info* new_statement, node_info* statement_head) +{ + if (!new_statement || !statement_head) + return NULL; + + node_info* p_head_tmp = statement_head; + while (p_head_tmp->statement_list) + p_head_tmp = p_head_tmp->statement_list; + + while (p_head_tmp->next) + p_head_tmp = p_head_tmp->next; + + p_head_tmp->next = malloc(sizeof(node_info)); + p_head_tmp->next = new_statement; + return statement_head; +} +#endif \ No newline at end of file diff --git a/deon-win/deon/functions/functions.h b/deon-win/deon/functions/functions.h new file mode 100644 index 0000000..5e2a907 --- /dev/null +++ b/deon-win/deon/functions/functions.h @@ -0,0 +1,11 @@ +#ifndef FUNCTIONS +#define FUNCTIONS +#include "../types.h" +#include "../linked_list/linked_list.h" +#include "../linked_list/linked_list.c" + +node_info *create_function(char *p_name, node_info *p_stmts); +node_info *create_function_call(char *p_name); +node_info *create_compound_statement(node_info *new_statement_list, node_info *statement_head); +node_info* add_to_compound_statement(node_info* new_statement, node_info* statement_head); +#endif \ No newline at end of file diff --git a/deon-win/deon/hashmap/map.c b/deon-win/deon/hashmap/map.c new file mode 100644 index 0000000..6a2a228 --- /dev/null +++ b/deon-win/deon/hashmap/map.c @@ -0,0 +1,190 @@ +#ifndef MAP_C +#define MAP_C + +#include +#include +#include "map.h" + +struct map_node_t { + unsigned hash; + void *value; + map_node_t *next; + /* char key[]; */ + /* char value[]; */ +}; + + +static unsigned map_hash(const char *str) { + unsigned hash = 5381; + while (*str) { + hash = ((hash << 5) + hash) ^ *str++; + } + return hash; +} + + +static map_node_t *map_newnode(const char *key, void *value, int vsize) { + map_node_t *node; + int ksize = strlen(key) + 1; + int voffset = ksize + ((sizeof(void*) - ksize) % sizeof(void*)); + node = malloc(sizeof(*node) + voffset + vsize); + if (!node) return NULL; + memcpy(node + 1, key, ksize); + node->hash = map_hash(key); + node->value = ((char*) (node + 1)) + voffset; + memcpy(node->value, value, vsize); + return node; +} + + +static int map_bucketidx(map_base_t *m, unsigned hash) { + /* If the implementation is changed to allow a non-power-of-2 bucket count, + * the line below should be changed to use mod instead of AND */ + return hash & (m->nbuckets - 1); +} + + +static void map_addnode(map_base_t *m, map_node_t *node) { + int n = map_bucketidx(m, node->hash); + node->next = m->buckets[n]; + m->buckets[n] = node; +} + + +static int map_resize(map_base_t *m, int nbuckets) { + map_node_t *nodes, *node, *next; + map_node_t **buckets; + int i; + /* Chain all nodes together */ + nodes = NULL; + i = m->nbuckets; + while (i--) { + node = (m->buckets)[i]; + while (node) { + next = node->next; + node->next = nodes; + nodes = node; + node = next; + } + } + /* Reset buckets */ + buckets = realloc(m->buckets, sizeof(*m->buckets) * nbuckets); + if (buckets != NULL) { + m->buckets = buckets; + m->nbuckets = nbuckets; + } + if (m->buckets) { + memset(m->buckets, 0, sizeof(*m->buckets) * m->nbuckets); + /* Re-add nodes to buckets */ + node = nodes; + while (node) { + next = node->next; + map_addnode(m, node); + node = next; + } + } + /* Return error code if realloc() failed */ + return (buckets == NULL) ? -1 : 0; +} + + +static map_node_t **map_getref(map_base_t *m, const char *key) { + unsigned hash = map_hash(key); + map_node_t **next; + if (m->nbuckets > 0) { + next = &m->buckets[map_bucketidx(m, hash)]; + while (*next) { + if ((*next)->hash == hash && !strcmp((char*) (*next + 1), key)) { + return next; + } + next = &(*next)->next; + } + } + return NULL; +} + + +void map_deinit_(map_base_t *m) { + map_node_t *next, *node; + int i; + i = m->nbuckets; + while (i--) { + node = m->buckets[i]; + while (node) { + next = node->next; + free(node); + node = next; + } + } + free(m->buckets); +} + + +void *map_get_(map_base_t *m, const char *key) { + map_node_t **next = map_getref(m, key); + return next ? (*next)->value : NULL; +} + + +int map_set_(map_base_t *m, const char *key, void *value, int vsize) { + int n, err; + map_node_t **next, *node; + /* Find & replace existing node */ + next = map_getref(m, key); + if (next) { + memcpy((*next)->value, value, vsize); + return 0; + } + /* Add new node */ + node = map_newnode(key, value, vsize); + if (node == NULL) goto fail; + if (m->nnodes >= m->nbuckets) { + n = (m->nbuckets > 0) ? (m->nbuckets << 1) : 1; + err = map_resize(m, n); + if (err) goto fail; + } + map_addnode(m, node); + m->nnodes++; + return 0; + fail: + if (node) free(node); + return -1; +} + + +void map_remove_(map_base_t *m, const char *key) { + map_node_t *node; + map_node_t **next = map_getref(m, key); + if (next) { + node = *next; + *next = (*next)->next; + free(node); + m->nnodes--; + } +} + + +map_iter_t map_iter_(void) { + map_iter_t iter; + iter.bucketidx = -1; + iter.node = NULL; + return iter; +} + + +const char *map_next_(map_base_t *m, map_iter_t *iter) { + if (iter->node) { + iter->node = iter->node->next; + if (iter->node == NULL) goto nextBucket; + } else { + nextBucket: + do { + if (++iter->bucketidx >= m->nbuckets) { + return NULL; + } + iter->node = m->buckets[iter->bucketidx]; + } while (iter->node == NULL); + } + return (char*) (iter->node + 1); +} +#endif \ No newline at end of file diff --git a/deon-win/deon/hashmap/map.h b/deon-win/deon/hashmap/map.h new file mode 100644 index 0000000..59758ab --- /dev/null +++ b/deon-win/deon/hashmap/map.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2014 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef MAP_H +#define MAP_H + +#include + +#define MAP_VERSION "0.1.0" + +struct map_node_t; +typedef struct map_node_t map_node_t; + +typedef struct { + map_node_t **buckets; + unsigned nbuckets, nnodes; +} map_base_t; + +typedef struct { + unsigned bucketidx; + map_node_t *node; +} map_iter_t; + + +#define map_t(T)\ + struct { map_base_t base; T *ref; T tmp; } + + +#define map_init(m)\ + memset(m, 0, sizeof(*(m))) + + +#define map_deinit(m)\ + map_deinit_(&(m)->base) + + +#define map_get(m, key)\ + ( (m)->ref = map_get_(&(m)->base, key) ) + + +#define map_set(m, key, value)\ + ( (m)->tmp = (value),\ + map_set_(&(m)->base, key, &(m)->tmp, sizeof((m)->tmp)) ) + + +#define map_remove(m, key)\ + map_remove_(&(m)->base, key) + + +#define map_iter(m)\ + map_iter_() + + +#define map_next(m, iter)\ + map_next_(&(m)->base, iter) + + +void map_deinit_(map_base_t *m); +void *map_get_(map_base_t *m, const char *key); +int map_set_(map_base_t *m, const char *key, void *value, int vsize); +void map_remove_(map_base_t *m, const char *key); +map_iter_t map_iter_(void); +const char *map_next_(map_base_t *m, map_iter_t *iter); + + +typedef map_t(void*) map_void_t; +typedef map_t(char*) map_str_t; +typedef map_t(int) map_int_t; +typedef map_t(char) map_char_t; +typedef map_t(float) map_float_t; +typedef map_t(double) map_double_t; + +#endif \ No newline at end of file diff --git a/deon-win/deon/linked_list/linked_list.c b/deon-win/deon/linked_list/linked_list.c new file mode 100644 index 0000000..955b954 --- /dev/null +++ b/deon-win/deon/linked_list/linked_list.c @@ -0,0 +1,87 @@ +#ifndef LINKED_LIST_C +#define LINKED_LIST_C +#include "linked_list.h" + +/* + Author: xerox + Update: 1/20/2020 + + free's linked list. +*/ +static void free_linked_list(node_info *p_list) +{ + if (!p_list) + return; + node_info* temp; + while (p_list->next) + { + temp = p_list; + p_list = p_list->next; + free(temp); + } +} + +/* + Author: xerox + Update: 1/20/2020 + + updates linked list. +*/ +static node_info *copy_linked_list(node_info *p_list) +{ + node_info* new_list = malloc(sizeof(node_info)); + if (!new_list || !p_list) + return NULL; + + new_list->next = NULL; + node_info *copy_list = new_list; + //TODO update with doubly linked list + while(p_list->next) + { + p_list = p_list->next; + copy_list->next = p_list; + } + return new_list; +} + +/* + Author: xerox + Update: 1/20/2020 + + append to linked list. +*/ +static void linked_list_append(node_info* p_head, node_info* new_node) +{ + if (!p_head || !new_node) + return; + node_info* p_head_temp = p_head; + while (p_head->next) + p_head_temp = p_head_temp->next; + p_head->next = NULL; //sanity check + p_head_temp->next = p_head; +} + +/* + Author: xerox + Update: 1/20/2020 + + remove link from linked list. +*/ +static bool linked_list_remove(node_info* p_head, node_info* delete_node) +{ + if (!p_head || !delete_node) + return false; + + node_info* p_head_temp = p_head; + while (p_head_temp->next) + { + if (p_head_temp->next == delete_node) + { + p_head_temp->next = delete_node->next; + free(delete_node); + return true; + } + } + return false; +} +#endif \ No newline at end of file diff --git a/deon-win/deon/linked_list/linked_list.h b/deon-win/deon/linked_list/linked_list.h new file mode 100644 index 0000000..4260885 --- /dev/null +++ b/deon-win/deon/linked_list/linked_list.h @@ -0,0 +1,9 @@ +#ifndef LINKED_LIST_H +#define LINKED_LIST_H +#include "../types.h" + +void free_linked_list(node_info *p_list); +node_info *copy_linked_list(node_info *p_list); +void linked_list_append(node_info* p_head, node_info* new_node); +bool linked_list_remove(node_info* p_head, node_info* delete_node); +#endif diff --git a/deon-win/deon/logic/logic.c b/deon-win/deon/logic/logic.c new file mode 100644 index 0000000..33a4880 --- /dev/null +++ b/deon-win/deon/logic/logic.c @@ -0,0 +1,20 @@ +#include "logic.h" + +/* + Author: xerox + Date: 1/19/2020 + + creates logic given type, statement list to execute, and variable name for condition. +*/ +static logic* create_logic(logic_type type, node_info* stmt_list, char* var_name) +{ + logic* new_logic = malloc(sizeof(logic)); + if (!new_logic || !stmt_list || !var_name) + return NULL; + + memset(new_logic, NULL, sizeof(*new_logic)); + new_logic->type = type; + new_logic->condition_var = var_name; + new_logic->stmt_list = stmt_list; + return new_logic; +} \ No newline at end of file diff --git a/deon-win/deon/logic/logic.h b/deon-win/deon/logic/logic.h new file mode 100644 index 0000000..14172a2 --- /dev/null +++ b/deon-win/deon/logic/logic.h @@ -0,0 +1,5 @@ +#ifndef LOGIC_H +#define LOGIC_H +#include "../types.h" +logic* create_logic(logic_type type, node_info* stmt_list, char* var_name); +#endif \ No newline at end of file diff --git a/deon-win/deon/parser/parser.c b/deon-win/deon/parser/parser.c new file mode 100644 index 0000000..b9067f5 --- /dev/null +++ b/deon-win/deon/parser/parser.c @@ -0,0 +1,257 @@ +#ifndef PARSER_C +#define PARSER_C +#include "parser.h" + +/* + Author: xerox + Updated: 1/19/2020 + + create variable given name, value, and type. +*/ +static node_info* create_variable_const(char* p_name, void* value, variable_type var_type) +{ + node_info* new_node = malloc(sizeof(*new_node)); + if (!new_node) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + variable* new_var = make_variable(p_name, value, var_type); + if (!new_var) + return NULL; + new_node->assignment = (assignment_operation*)malloc(sizeof(assignment_operation)); + if (!new_node->assignment) + return NULL; + memset(new_node->assignment, NULL, sizeof(*new_node->assignment)); + new_node->operation = ASSIGNMENT_OPERATION; + new_node->operation_type.assignment = ASSIGN_FROM_CONST; + new_node->assignment->var = new_var; + return new_node; +} + +/* + Author: xerox + Updated: 1/20/2020 + + Move value from one variable to another. +*/ +static node_info* move_value(char* to, char* from) +{ + node_info* new_node = (node_info *)malloc(sizeof(node_info)); + if (!from || !new_node || !to) + return NULL; + memset(new_node, NULL, sizeof(*new_node)); + new_node->assignment = (assignment_operation*)malloc(sizeof(*new_node->assignment)); + if (!new_node->assignment) + return NULL; + memset(new_node->assignment, NULL, sizeof(*new_node->assignment)); + new_node->operation = ASSIGNMENT_OPERATION; + new_node->operation_type.assignment = ASSIGN_FROM_VAR; + new_node->assignment->from = from; + new_node->assignment->to = to; + return new_node; +} + +/* + Author: xerox + Updated: 1/19/2020 + + create logic node (logical expression) +*/ +static node_info* create_logic_node(logic* logic_expr) +{ + node_info* new_node = malloc(sizeof(node_info)); + if (!new_node || !logic_expr) + return NULL; + + memset(new_node, NULL, sizeof(*new_node)); + new_node->operation = LOGIC_OPERATION; + new_node->logical_expr = logic_expr; + return new_node; +} + +/* + Author: xerox + Updated: 1/20/2020 + + Executes a statment. + + @param nodeInfo statement to be executed + @return void. +*/ + +static void exec_stmt(node_info *exec_node) +{ + if (!exec_node) + return; + + switch (exec_node->operation) + { + case ASSIGNMENT_OPERATION: + switch (exec_node->operation_type.assignment) + { + case ASSIGN_FROM_CONST: + add_var(exec_node->assignment->var->name, exec_node->assignment->var->value, _var_map); + break; + case ASSIGN_FROM_VAR: + add_var(exec_node->assignment->to, + get_value(exec_node->assignment->from, _var_map), _var_map); + break; + default: + ; +#if DEON_DEBUGGING + printf("[error] unkown assignment operation: 0x%x", exec_node->operation_type.assignment); +#endif + } + break; + case LOGIC_OPERATION: + { + switch (exec_node->logical_expr->type) + { + case IF_LOGIC: + { + variable_values* p_var_values = get_value(exec_node->logical_expr->condition_var, _var_map); + if (!p_var_values) + return; + if (*(unsigned char*)p_var_values->data_ptr) + exec_stmt(exec_node->logical_expr->stmt_list); + break; + } + case WHILE_LOGIC: + { + variable_values* p_var_values = get_value(exec_node->logical_expr->condition_var, _var_map); + if (!p_var_values) + return; + while (*(unsigned char*)p_var_values->data_ptr) + { + exec_stmt(exec_node->logical_expr->stmt_list); + p_var_values = get_value(exec_node->logical_expr->condition_var, _var_map); + } + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown logic operation\n"); +#endif + } + } + // execute statement list. + case EXEC_STMT_LIST_OPERATION: + { + if(exec_node->statement_list) + exec_node = exec_node->statement_list; + while (exec_node->next) + { + exec_node = exec_node->next; + exec_stmt(exec_node); + } + break; + } + // print statement + case PRINT_OPERATION: + { + switch (exec_node->operation_type.print) + { + case PRINT_CONSTANT: + { + switch (exec_node->print_expr->type) + { + case VAR_STRING: + printf("%s\n", (char*)exec_node->print_expr->value); + break; + case VAR_INT: + printf("%d\n", *(int*)exec_node->print_expr->value); + break; + case VAR_BYTE: + printf("%c\n", *(char*)exec_node->print_expr->value); + break; + case VAR_DOUBLE: + printf("%f\n", *(double*)exec_node->print_expr->value); + break; + case VAR_VOID: //TODO add void variable type + break; + default: + ; +#if DEON_DEBUGGING + printf("[error] unable to print variable of type: 0x%x\n", exec_node->print_expr->type); +#endif + } + break; + } + case PRINT_VARIABLE: + { + variable_values* p_var = get_value(exec_node->var->name, _var_map); + switch (p_var->type) + { + case VAR_STRING: + printf("%s\n", (char*)p_var->data_ptr); + break; + case VAR_INT: + printf("%d\n", *(int*)p_var->data_ptr); + break; + case VAR_BYTE: + printf("%c\n", *(char*)p_var->data_ptr); + break; + case VAR_DOUBLE: + printf("%f\n", *(double*)p_var->data_ptr); + break; + case VAR_VOID: //TODO add void variable type + break; + default: + ; +#if DEON_DEBUGGING + printf("[error] unable to print variable of type: 0x%x\n", p_var->type); +#endif + } + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown print type: 0x%x\n", exec_node->operation_type.print); +#endif + } + break; + } + case FUNCTION_OPERATION: + { + switch (exec_node->operation_type.func) + { + case FUNCTION_CALL: + { + node_info* _stmts = *map_get(&*((map_void_t*)_function_list), exec_node->name); + _stmts = _stmts->statement_list; + while (_stmts->statement_list) + { + _stmts = _stmts->statement_list; + exec_stmt(_stmts); + } + break; + } + case FUNCTION: + { + if (!_function_list) + { + _function_list = malloc(sizeof(map_void_t)); + map_init(_function_list); + map_set(_function_list, exec_node->name, exec_node->function_body); + } + else //else we dont malloc, we just put the function inside of the hashmap. + map_set(_function_list, exec_node->name, exec_node->function_body); + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown function operation: 0x%x\n", exec_node->operation_type.func); +#endif + } + break; + } + default: + ; +#if DEON_DEBUGGING + printf("[error] unknown operation: 0x%x\n", exec_node->operation); +#endif + } +} +#endif \ No newline at end of file diff --git a/deon-win/deon/parser/parser.h b/deon-win/deon/parser/parser.h new file mode 100644 index 0000000..7e86635 --- /dev/null +++ b/deon-win/deon/parser/parser.h @@ -0,0 +1,9 @@ +#ifndef PARSER_H +#define PARSER_H +#include "../types.h" +#include "../vars/vars.h" +node_info* create_variable_const(char* p_name, void* value, variable_type var_type); +node_info* move_value(char* to, char* from); +node_info* create_logic_node(logic* logic_expr); +void exec_stmt(node_info *exec_node); +#endif diff --git a/deon-win/deon/print/print.c b/deon-win/deon/print/print.c new file mode 100644 index 0000000..ee82467 --- /dev/null +++ b/deon-win/deon/print/print.c @@ -0,0 +1,54 @@ +#ifndef PRINT_C +#define PRINT_C +#include "print.h" + +/* + Author: xerox + Updated: 1/20/2020 + + creates a print statement given variable type and value. +*/ + +static node_info *create_print_statement(variable_type operation, void* value) +{ + node_info* new_print_stmt = (node_info*)malloc(sizeof(node_info)); + print* new_print = malloc(sizeof(print)); + if (!new_print_stmt || !new_print) + return NULL; + memset(new_print_stmt, NULL, sizeof(*new_print_stmt)); + memset(new_print, NULL, sizeof(*new_print)); + + new_print_stmt->operation = PRINT_OPERATION; + new_print_stmt->operation_type.print = PRINT_CONSTANT; + new_print->type = operation; + new_print->value = value; + new_print_stmt->print_expr = new_print; + new_print_stmt->next = NULL; + return new_print_stmt; +} + +/* + Author: xerox + Updated: 1/19/2020 + + create print variable from variable name. +*/ +static node_info* create_print_variable(char* var_name) +{ + node_info* new_print_stmt = (node_info*)malloc(sizeof(node_info)); + if (!new_print_stmt || !var_name) + return NULL; + memset(new_print_stmt, NULL, sizeof(*new_print_stmt)); + + new_print_stmt->var = malloc(sizeof(variable)); + if (!new_print_stmt->var) + return NULL; + memset(new_print_stmt->var, NULL, sizeof(*new_print_stmt->var)); + + new_print_stmt->operation = PRINT_OPERATION; + new_print_stmt->operation_type.print = PRINT_VARIABLE; + new_print_stmt->var->name = var_name; + new_print_stmt->next = NULL; + return new_print_stmt; +} +#endif diff --git a/deon-win/deon/print/print.h b/deon-win/deon/print/print.h new file mode 100644 index 0000000..f2bc18b --- /dev/null +++ b/deon-win/deon/print/print.h @@ -0,0 +1,6 @@ +#ifndef PRINT_H +#define PRINT_H +#include "../types.h" +node_info* create_print_statement(variable_type operation, void* value); +node_info* create_print_variable(char* var_name); +#endif \ No newline at end of file diff --git a/deon-win/deon/types.h b/deon-win/deon/types.h new file mode 100644 index 0000000..f81047e --- /dev/null +++ b/deon-win/deon/types.h @@ -0,0 +1,128 @@ +#ifndef INCLUDE_H +#define INCLUDE_H +#include +#include +#include +#include "hashmap/map.h" + +#define DEON_DEBUGGING 0 +bool _DEON_DEBUG; + +//--- different variable values +typedef enum _variable_type +{ + VAR_INT, + VAR_SHORT, + VAR_BYTE, + VAR_DOUBLE, + VAR_STRING, + VAR_VOID +} variable_type; + +//--- different function operations +typedef enum _function_type +{ + FUNCTION, + FUNCTION_CALL, +} function_type; + +//--- different print operations +typedef enum _print_type +{ + PRINT_VARIABLE, + PRINT_CONSTANT +} print_type; + +//--- different logic types +typedef enum _logic_type +{ + IF_LOGIC, + WHILE_LOGIC +} logic_type; + +typedef enum _assignment_type +{ + ASSIGN_FROM_VAR, + ASSIGN_FROM_CONST +} assignment_type; + +//--- all operations in the language +typedef enum _operation +{ + ASSIGNMENT_OPERATION, + LOGIC_OPERATION, + EXEC_STMT_LIST_OPERATION, + PRINT_OPERATION, + FUNCTION_OPERATION, +}; + +//--- variable value details +typedef struct _variable_values +{ + variable_type type; + void* data_ptr; +} variable_values; + +//--- variable details +typedef struct _variable +{ + char *name; + variable_values *value; + struct variable *next; +} variable; + +//--- print data +typedef struct _print +{ + enum _variable_type type; + void* value; +} print; + +//--- assignment data +typedef struct _assignment_operation +{ + char* from; + char* to; + variable* var; +}assignment_operation; + +//--- logic operation data +typedef struct _logic +{ + logic_type type; + char* condition_var; + struct node_info* stmt_list; +} logic; + +//--- struct that brings it all together +typedef struct node_info +{ + //--- node operation. + enum _operation operation; + + //--- sub operations. + union _operation_type + { + logic_type logic; + function_type func; + print_type print; + assignment_type assignment; + } operation_type; + + char *name; + print* print_expr; + logic* logical_expr; + assignment_operation* assignment; + variable* var; + struct node_info *next; + struct node_info *function_body; + struct node_info *statement_list; + struct node_info *new_scope; + struct map_void_t *var_map; +} node_info; + +//--- globals +map_void_t* _var_map; +node_info* _temp_statement_head; +map_void_t* _function_list; +#endif diff --git a/deon-win/deon/vars/vars.c b/deon-win/deon/vars/vars.c new file mode 100644 index 0000000..cdad775 --- /dev/null +++ b/deon-win/deon/vars/vars.c @@ -0,0 +1,104 @@ +#ifndef VARS_C +#define VARS_C +#include "vars.h" + +/* + Author: xerox + Date: 1/20/2020 + + add var to hashmap of variables. +*/ +static void add_var(char *p_name, variable_values *p_values, map_void_t* p_var_map) +{ + if (!p_name || !p_values) + return; + map_set(p_var_map, p_name, p_values); +} + + +/* + Author: xerox + Date: 1/20/2020 + + get value given name and hashmap. +*/ +static variable_values* get_value(char *p_name, map_void_t* p_var_map) +{ + if (!p_name) + return NULL; + return *map_get(&*((map_void_t* ) p_var_map), p_name); +} + +/* + Author: xerox + Date: 1/20/2020 + + makes a variable struct and define it. +*/ +static variable* make_variable(char *p_name, void* value, variable_type var_type) +{ + variable *new_var = malloc(sizeof(variable)); + variable_values *new_value = malloc(sizeof(variable_values)); + if (!new_var || !new_value || !p_name || !value) + return NULL; + + memset(new_var, NULL, sizeof(*new_var)); + memset(new_value, NULL, sizeof(*new_value)); + new_value->type = var_type; + new_value->data_ptr = value; + new_var->name = p_name; + new_var->value = new_value; + return new_var; +} + +/* + Author: xerox + Date: 1/20/2020 + + allocate memory for values that are 8 bytes or less. +*/ +static void* alloc_value(void* value, variable_type var_type) +{ + switch (var_type) + { + case VAR_INT: + { + int* p_int = (int*)malloc(sizeof(int)); + if (!p_int) + return NULL; + memset(p_int, NULL, sizeof(*p_int)); + *p_int = *(int*)value; + return p_int; + } + case VAR_SHORT: + { + short* p_short = (short*)malloc(sizeof(short)); + if (!p_short) + return NULL; + memset(p_short, NULL, sizeof(*p_short)); + *p_short = *(short*)value; + return p_short; + } + case VAR_BYTE: + { + char* p_char = malloc(sizeof(char)); + if (!p_char) + return NULL; + memset(p_char, NULL, sizeof(*p_char)); + *p_char = *(char*)value; + return p_char; + } + case VAR_DOUBLE: + { + double* p_double = malloc(sizeof(double)); + if (!p_double) + return NULL; + memset(p_double, NULL, sizeof(*p_double)); + *p_double = *(double*)value; + return p_double; + } + default: + return NULL; + } +} +#endif \ No newline at end of file diff --git a/deon-win/deon/vars/vars.h b/deon-win/deon/vars/vars.h new file mode 100644 index 0000000..dd2907f --- /dev/null +++ b/deon-win/deon/vars/vars.h @@ -0,0 +1,8 @@ +#ifndef VARS_H +#define VARS_H +#include "../types.h" +void add_var(char* name, variable_values* values, map_void_t* p_var_map); +variable* make_variable(char* p_name, void* value, variable_type var_type); +variable_values* get_value(char* p_name, map_void_t* p_var_map); +void* alloc_value(void* value, variable_type var_type); +#endif