diff --git a/.gitignore b/.gitignore index 9e76a72..e4b5a08 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,6 @@ huo *.o *.mk *~ +*.exe +.vscode/ +*.exe.stackdump diff --git a/Makefile b/Makefile index 1de92d1..e81a186 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CFLAGS += -g3 LIBS = -lpthread # Be super strict about everything -CFLAGS += -std=c11 -Werror -Wall -Wextra -pedantic -O2 +CFLAGS += -std=c11 -Wall -Wextra -pedantic -O2 CPPFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 # Automatically sort out header dependencies @@ -50,6 +50,7 @@ objs = \ src/parser.o \ src/execute.o \ src/config.o \ + src/path_utils.o \ src/huo.o all: huo @@ -57,7 +58,7 @@ all: huo huo: $(objs) $(CC) $(LDFLAGS) -o huo $(objs) $(LIBS) -clean: ; rm -f -- ./src/*.mk ./src/*.o & rm -f ./src/execution_functions/*.o & rm -f ./src/structures/*.o +clean: ; rm -f -- ./src/*.mk ./src/*.o & rm -f ./src/execution_functions/*.o & rm -f ./src/structures/*.o & rm -f ./.*.mk .PHONY: all clean .DELETE_ON_ERROR: diff --git a/README.md b/README.md index 2b80e6b..dbaa327 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,12 @@ Huo is an interpreted language which I started as a hobby project. The original If you would like to contribute to Huo open an issue describing the work you would like to do. If the change is accepted then you can make a pull request with your changes and it will be merged in after review. -##compile +## compile +```shell make +``` -##run +## run Create a file containing Huo code and run it with the interpreter: ```shell $ ./huo test.huo @@ -18,7 +20,7 @@ Or you can run the included REPL which is written in Huo. To exit the REPL simpl "Hello, world!" ``` -##Functions +## Functions basic math ```lisp @@ -115,6 +117,21 @@ if you want to simply return a composition of values, use the return function (let x (pair 0 "start")) (print x) ; [ 0, "start" ] ``` +ast and run together allow you to pass functions as arguments +the keywork ast returns its first argument as a value of type ast +the keyword run will execute an ast value with whatever arguments you pass in +```lisp +(def mapper arr fnc + (do + (each arr item i + (set i (run fnc item) arr) + ) + (return arr) + ) +) + +(msg_first "Hello" (ast (cat x " World"))) +``` switch block ```lisp ; the switch block is convenient for matching a value against a large number @@ -194,17 +211,6 @@ in order, returning the value from the last function inside it ) ) ``` -a parallel block takes any number of functions and executes them -in parallel. The parallel block returns undefined. Beware of passing -the same variable to two different functions in a parallel block! -```lisp -(let x 0) -(let y []) -(parallel - (for 0 100 (let x (+ x 1))) - (for 0 100 (set (length y) (length y) y)) -) -``` reading a file is simple and returns a string ```lisp (let file (read "./files/example.txt")) diff --git a/core/numbers.huo b/core/numbers.huo index dc61f46..c3e8bdd 100644 --- a/core/numbers.huo +++ b/core/numbers.huo @@ -54,3 +54,53 @@ (return result) ) ) + +(def exponent x n + (switch n + (= 0 1) + (= 1 x) + (< 1 (do + (let result x) + (for 1 n (do + (let result (* result x)) + ) + ) + (return result) + ) + ) + (> 0 (do + (let result 1) + (for 0 n (let result (/ result x))) + (return result) + ) + ) + ) +) + +(def cross_product x y + (do + (let result []) + (each x xitem xidx + (do + (set xidx [] result) + (each y yitem yidx + (do + (let sum 0) + (each (index xidx x) kitem kidx + (let sum + (+ sum + (* + (index kidx (index xidx x)) + (index yidx (index kidx y)) + ) + ) + ) + ) + (set yidx sum (index xidx result)) + ) + ) + ) + ) + (return result) + ) +) diff --git a/examples/first-class.txt b/examples/first-class.txt new file mode 100644 index 0000000..fc86524 --- /dev/null +++ b/examples/first-class.txt @@ -0,0 +1,19 @@ +(def msg_first msg fnc + (do + (print msg) + (print (run fnc msg)) + ) +) + +(def mapper arr fnc + (do + (each arr item i + (set i (run fnc item) arr) + ) + (return arr) + ) +) + +(msg_first "Hello" (ast (cat x " World"))) + +(print (mapper [1, 2, 3] (ast (+ item 3)))) diff --git a/examples/while.txt b/examples/while.txt index 956ee0f..dbdd222 100644 --- a/examples/while.txt +++ b/examples/while.txt @@ -1,7 +1,12 @@ (let x [0]) +(let y 1) (while - (< (length x) 10000) - (push 0 x) + (< (length x) 100000) + (do + (let y (+ 1 y)) + (push y x) + ) + ) (print x) (print (length x)) diff --git a/src/apply_core_function.c b/src/apply_core_function.c index 72a78b3..8b02d04 100644 --- a/src/apply_core_function.c +++ b/src/apply_core_function.c @@ -20,7 +20,7 @@ struct Value apply_core_function(struct Value *kwd_val, struct Execution_bundle } else if(string_matches_heap(&kwd, &split_const)){ v = split(*a, *b); - } else if (a->type == ARRAY && b->type == ARRAY) { + } else if (a->type == TYPE_ARRAY && b->type == TYPE_ARRAY) { struct Value_array *a_arr = value_as_array(a); struct Value_array *b_arr = value_as_array(b); if(a_arr->size != b_arr->size){ diff --git a/src/apply_execution_function.c b/src/apply_execution_function.c index 6ac1f5d..75f7173 100644 --- a/src/apply_execution_function.c +++ b/src/apply_execution_function.c @@ -134,5 +134,25 @@ bool apply_execution_function(struct Value *kwd_val, struct Value *result, struc *result = value_from_undef(); return true; } + else if(string_matches_heap(&kwd, &run_const)){ + exec_bundle->ast = ast_child(ast, 1); + struct Value fn_value = execute(exec_bundle); + huo_ast *fn = value_as_ast(&fn_value); + size_t index = 1; + for(size_t i = 2; i < ast_size(ast); i++){ + ast_set_child(fn, index, ast_child(ast, i)); + index++; + } + + exec_bundle->ast = fn; + *result = execute(exec_bundle); + exec_bundle->ast = ast; + return true; + } + else if(string_matches_heap(&kwd, &ast_const)){ + + *result = value_from_ast(ast_copy(ast_child(ast, 1))); + return true; + } return false; } diff --git a/src/apply_single_value_func.c b/src/apply_single_value_func.c index 39244fa..dfa0a6c 100644 --- a/src/apply_single_value_func.c +++ b/src/apply_single_value_func.c @@ -17,7 +17,7 @@ struct Value apply_single_value_func(struct Value *kwd_val, struct Execution_bun if(string_matches_heap(&kwd, &print_const)){ print(*value); printf("\n"); - value->type = UNDEF; + value->type = TYPE_UNDEF; value->data.bl = false; } else if(string_matches_heap(&kwd, &length_const)){ *value = value_from_long(length(*value)); @@ -34,8 +34,10 @@ struct Value apply_single_value_func(struct Value *kwd_val, struct Execution_bun exec_bundle->ast = read_import(value_as_string(value)); *value = execute(exec_bundle); exec_bundle->ast = old_ast; + } else if(string_concat_heap(&kwd, &typeof_const)){ + *value = value_from_string(type_to_string(value->type)); } else { - value->type = UNDEF; + value->type = TYPE_UNDEF; value->data.bl = false; } return *value; diff --git a/src/base_util.c b/src/base_util.c index 0f882cf..92e4092 100644 --- a/src/base_util.c +++ b/src/base_util.c @@ -29,7 +29,7 @@ bool __size_t_mul_overflow(size_t a, size_t b, size_t *res) { return false; } else { WARN_ONCE("size_t is HOW long?"); - WARN_ONCE("Using slow but portable overflow test") + WARN_ONCE("Using slow but portable overflow test"); } #else #pragma message ("Using slow but portable overflow test") @@ -85,11 +85,11 @@ struct Value sub_vars(struct Value *v, struct Scopes *scopes, huo_depth_t max_de if (max_depth <= 0) { ERROR("Max depth exceeded in computation"); } - if (v->type == ARRAY) { + if (v->type == TYPE_ARRAY) { for (size_t i = 0; i < v->data.array->size; i++) { *(v->data.array->values[i]) = sub_vars(v->data.array->values[i], scopes, max_depth); } - } else if (v->type == KEYWORD) { + } else if (v->type == TYPE_KEYWORD) { struct Value *w = NULL; struct String kwd = value_as_keyword(v); if ((w = get_letted_value(scopes, kwd)) != NULL) { diff --git a/src/base_util.h b/src/base_util.h index 32a53c2..973e992 100644 --- a/src/base_util.h +++ b/src/base_util.h @@ -5,7 +5,9 @@ #include #include #include "structures/structures.h" +#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32) && !defined(__CYGWIN__) #include +#endif #include #include "config.h" @@ -39,6 +41,7 @@ /* Macro because it makes printf errors easier to detect at compile time */ #define ERROR(...) ERROR_AT(__FILE__, __func__, __LINE__, __VA_ARGS__) +#if !defined(WIN32) && !defined(_WIN32) && !defined(__WIN32) && !defined(__CYGWIN__) #define ERROR_AT(FILE, FUNC, LINE, ...) do {\ void * buffer[5];\ char ** strings;\ @@ -53,6 +56,15 @@ /*assert(false);*/\ exit(1);\ } while (0); +#else +#define ERROR_AT(FILE, FUNC, LINE, ...) do {\ + fprintf(stderr, "Error at %s:%s:%i: ", FILE, FUNC, LINE);\ + fprintf(stderr, __VA_ARGS__);\ + fprintf(stderr, "\n");\ + /*assert(false);*/\ + exit(1);\ +} while (0); +#endif #define ARR_MALLOC(num_elem, elem_val) malloc_or_die(arr_malloc_size((num_elem), sizeof(elem_val))) diff --git a/src/constants.c b/src/constants.c index c894d46..e30fb2a 100644 --- a/src/constants.c +++ b/src/constants.c @@ -16,6 +16,10 @@ struct String print_const = STR_NEW("print"); struct String concat_const = STR_NEW("cat"); +struct String run_const = STR_NEW("run"); + +struct String ast_const = STR_NEW("ast"); + struct String if_const = STR_NEW("if"); struct String def_const = STR_NEW("def"); @@ -66,8 +70,17 @@ struct String false_const = STR_NEW("false"); struct String true_const = STR_NEW("true"); +struct String typeof_const = STR_NEW("typeof"); + struct String function_names = STR_NEW("[if, read, let, set, each, for, do, switch, parallel, import, map, reduce, substring, while]"); +struct String keyword_const = STR_NEW("keyword"); +struct String number_const = STR_NEW("number"); +struct String string_const = STR_NEW("string"); +struct String boolean_const = STR_NEW("boolean"); +struct String array_const = STR_NEW("array"); +struct String undefined_const = STR_NEW("undefined"); + const char open_parens_const = '('; const char close_parens_const = ')'; const char root_type_const = 'r'; diff --git a/src/constants.h b/src/constants.h index 08ffcc6..c8ca698 100644 --- a/src/constants.h +++ b/src/constants.h @@ -38,6 +38,16 @@ extern struct String read_line_const; extern struct String function_names; extern struct String false_const; extern struct String true_const; +extern struct String typeof_const; +extern struct String run_const; +extern struct String ast_const; + +extern struct String keyword_const; +extern struct String number_const; +extern struct String string_const; +extern struct String boolean_const; +extern struct String array_const; +extern struct String undefined_const; extern const char open_parens_const; extern const char close_parens_const; diff --git a/src/core_functions.c b/src/core_functions.c index b9b21b7..89d91f1 100644 --- a/src/core_functions.c +++ b/src/core_functions.c @@ -8,21 +8,21 @@ #include "config.h" void print(struct Value a){ - if(a.type == STRING){ + if(a.type == TYPE_STRING){ struct String str = value_as_string(&a); printf("\"%s\"", string_to_chars(&str)); } - else if(a.type == KEYWORD){ + else if(a.type == TYPE_KEYWORD){ struct String kwd = value_as_keyword(&a); printf("%s", string_to_chars(&kwd)); } - else if(a.type == LONG) { + else if(a.type == TYPE_LONG) { printf("%" PRIhi, value_as_long(&a)); } - else if(a.type == FLOAT) { + else if(a.type == TYPE_FLOAT) { printf("%f", value_as_float(&a)); } - else if(a.type == BOOL) { + else if(a.type == TYPE_BOOL) { if (value_as_bool(&a)){ printf("True"); } @@ -30,7 +30,7 @@ void print(struct Value a){ printf("False"); } } - else if(a.type == ARRAY) { + else if(a.type == TYPE_ARRAY) { printf("[ "); struct Value_array *arr = value_as_array(&a); for(size_t i = 0; i < arr->size; i++){ @@ -41,22 +41,22 @@ void print(struct Value a){ } printf(" ]"); } - else if(a.type == UNDEF) { + else if(a.type == TYPE_UNDEF) { printf("undefined"); } } struct Value add(struct Value a, struct Value b){ - if(a.type == LONG && b.type == LONG){ + if(a.type == TYPE_LONG && b.type == TYPE_LONG){ return value_from_long(value_as_long(&a) + value_as_long(&b)); } - else if(a.type == FLOAT && b.type == FLOAT){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_FLOAT){ return value_from_float(value_as_float(&a) + value_as_float(&b)); } - else if(a.type == FLOAT && b.type == LONG){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_LONG){ return value_from_float(value_as_float(&a) + (float)value_as_long(&b)); } - else if(a.type == LONG && b.type == FLOAT){ + else if(a.type == TYPE_LONG && b.type == TYPE_FLOAT){ return value_from_float((float)value_as_long(&a) + value_as_float(&b)); } else { @@ -65,16 +65,16 @@ struct Value add(struct Value a, struct Value b){ } struct Value mul(struct Value a, struct Value b){ - if(a.type == LONG && b.type == LONG){ + if(a.type == TYPE_LONG && b.type == TYPE_LONG){ return value_from_long(value_as_long(&a) * value_as_long(&b)); } - else if(a.type == FLOAT && b.type == FLOAT){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_FLOAT){ return value_from_float(value_as_float(&a) * value_as_float(&b)); } - else if(a.type == FLOAT && b.type == LONG){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_LONG){ return value_from_float(value_as_float(&a) * (float)value_as_long(&b)); } - else if(a.type == LONG && b.type == FLOAT){ + else if(a.type == TYPE_LONG && b.type == TYPE_FLOAT){ return value_from_float((float)value_as_long(&a) * value_as_float(&b)); } else { @@ -83,16 +83,16 @@ struct Value mul(struct Value a, struct Value b){ } struct Value sub(struct Value a, struct Value b){ - if(a.type == LONG && b.type == LONG){ + if(a.type == TYPE_LONG && b.type == TYPE_LONG){ return value_from_long(value_as_long(&a) - value_as_long(&b)); } - else if(a.type == FLOAT && b.type == FLOAT){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_FLOAT){ return value_from_float(value_as_float(&a) - value_as_float(&b)); } - else if(a.type == FLOAT && b.type == LONG){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_LONG){ return value_from_float(value_as_float(&a) - (float)value_as_long(&b)); } - else if(a.type == LONG && b.type == FLOAT){ + else if(a.type == TYPE_LONG && b.type == TYPE_FLOAT){ return value_from_float((float)value_as_long(&a) - value_as_float(&b)); } else { @@ -101,28 +101,28 @@ struct Value sub(struct Value a, struct Value b){ } struct Value divide(struct Value a, struct Value b) { - if(a.type == LONG && b.type == LONG){ + if(a.type == TYPE_LONG && b.type == TYPE_LONG){ long bl = value_as_long(&b); if (bl == 0) { ERROR("Division by 0"); } return long_divide(value_as_long(&a), bl); } - else if(a.type == FLOAT && b.type == FLOAT){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_FLOAT){ long bf = value_as_float(&b); if (bf == 0) { ERROR("Division by 0"); } return value_from_float(value_as_float(&a) / bf); } - else if(a.type == FLOAT && b.type == LONG){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_LONG){ long bl = value_as_long(&b); if (bl == 0) { ERROR("Division by 0"); } return value_from_float(value_as_float(&a) / (float) bl); } - else if(a.type == LONG && b.type == FLOAT){ + else if(a.type == TYPE_LONG && b.type == TYPE_FLOAT){ long bf = value_as_float(&b); if (bf == 0) { ERROR("Division by 0"); @@ -144,9 +144,9 @@ struct Value long_divide(huo_int_t a, huo_int_t b) { } struct Value concat(struct Value a, struct Value b){ - if (a.type == STRING && b.type == STRING) { + if (a.type == TYPE_STRING && b.type == TYPE_STRING) { return string_concat(value_as_string(&a), value_as_string(&b)); - } else if (a.type == ARRAY && b.type == ARRAY) { + } else if (a.type == TYPE_ARRAY && b.type == TYPE_ARRAY) { return array_concat(value_as_array(&a), value_as_array(&b)); } else { ERROR("Tried to concat %c and %c", a.type, b.type); @@ -161,19 +161,19 @@ struct Value string_concat(struct String a, struct String b) { } struct Value not(struct Value a, struct Value b){ - if(a.type == BOOL && b.type == BOOL){ + if(a.type == TYPE_BOOL && b.type == TYPE_BOOL){ return value_from_bool(value_as_bool(&a) != value_as_bool(&b)); } - else if(a.type == FLOAT && b.type == FLOAT){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_FLOAT){ return value_from_bool(value_as_float(&a) != value_as_float(&b)); } - else if(a.type == LONG && b.type == LONG){ + else if(a.type == TYPE_LONG && b.type == TYPE_LONG){ return value_from_bool(value_as_long(&a) != value_as_long(&b)); } - else if(a.type == STRING && b.type == STRING){ + else if(a.type == TYPE_STRING && b.type == TYPE_STRING){ return value_from_bool(!string_matches_stack(value_as_string(&a), value_as_string(&b))); } - else if(a.type == ARRAY && b.type == ARRAY){ + else if(a.type == TYPE_ARRAY && b.type == TYPE_ARRAY){ return value_from_bool(!array_matches(value_as_array(&a), value_as_array(&b))); } else { @@ -182,7 +182,7 @@ struct Value not(struct Value a, struct Value b){ } struct Value and(struct Value a, struct Value b){ - if(a.type == BOOL && b.type == BOOL){ + if(a.type == TYPE_BOOL && b.type == TYPE_BOOL){ return value_from_bool(value_as_bool(&a) && value_as_bool(&b)); } else { ERROR("& operator only takes boolean values: %d | %d != 1", a.type, b.type); @@ -190,7 +190,7 @@ struct Value and(struct Value a, struct Value b){ } struct Value or(struct Value a, struct Value b){ - if(a.type == BOOL && b.type == BOOL){ + if(a.type == TYPE_BOOL && b.type == TYPE_BOOL){ return value_from_bool(value_as_bool(&a) || value_as_bool(&b)); } else { ERROR("| operator only takes boolean values: %d | %d != 1", a.type, b.type); @@ -198,34 +198,40 @@ struct Value or(struct Value a, struct Value b){ } struct Value equals(struct Value a, struct Value b){ - if(a.type == BOOL && b.type == BOOL){ + if(a.type == TYPE_BOOL && b.type == TYPE_BOOL){ return value_from_bool(value_as_bool(&a) == value_as_bool(&b)); } - else if(a.type == FLOAT && b.type == FLOAT){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_FLOAT){ return value_from_bool(value_as_float(&a) == value_as_float(&b)); } - else if(a.type == LONG && b.type == LONG){ + else if(a.type == TYPE_LONG && b.type == TYPE_LONG){ return value_from_bool(value_as_long(&a) == value_as_long(&b)); } - else if(a.type == STRING && b.type == STRING){ + else if(a.type == TYPE_STRING && b.type == TYPE_STRING){ return value_from_bool(string_matches_stack(value_as_string(&a), value_as_string(&b))); } - else if(a.type == ARRAY && b.type == ARRAY){ + else if(a.type == TYPE_ARRAY && b.type == TYPE_ARRAY){ return value_from_bool(array_matches(value_as_array(&a), value_as_array(&b))); } + else if(a.type == TYPE_FLOAT && b.type == TYPE_LONG){ + return value_from_bool(value_as_float(&a) == (float)value_as_long(&b)); + } + else if(a.type == TYPE_LONG && b.type == TYPE_FLOAT){ + return value_from_bool((float)value_as_long(&a) == value_as_float(&b)); + } else { ERROR("Mismatched types: %d != %d", a.type, b.type); } } struct Value greater_than(struct Value a, struct Value b){ - if(a.type == BOOL && b.type == BOOL){ + if(a.type == TYPE_BOOL && b.type == TYPE_BOOL){ return value_from_bool(value_as_bool(&a) > value_as_bool(&b)); } - else if(a.type == FLOAT && b.type == FLOAT){ + else if(a.type == TYPE_FLOAT && b.type == TYPE_FLOAT){ return value_from_bool(value_as_float(&a) > value_as_float(&b)); } - else if(a.type == LONG && b.type == LONG){ + else if(a.type == TYPE_LONG && b.type == TYPE_LONG){ return value_from_bool(value_as_long(&a) > value_as_long(&b)); } else { @@ -240,15 +246,16 @@ bool can_cast_to_size_t(huo_int_t i) { struct Value set(struct Value index_val, struct Value item, struct Value *to_set) { huo_int_t index = value_as_long(&index_val); if (!can_cast_to_size_t(index)) { - ERROR("Index out of range for set: should be 0 <= %" PRIhi " < %"PRIuMAX, index, SIZE_MAX); + unsigned long long size_max = SIZE_MAX; + ERROR("Index out of range for set: should be 0 <= %" PRIhi " < %llu", index, size_max); } - if (to_set->type == ARRAY) { + if (to_set->type == TYPE_ARRAY) { return value_from_array(array_set((size_t) index, item, value_as_array(to_set))); - } else if (to_set->type == STRING) { + } else if (to_set->type == TYPE_STRING) { struct String set = string_set((size_t) index, value_as_string(&item), value_as_string(to_set)); return value_from_string(string_copy_stack(&set)); } else { - ERROR("Set type invalid: ('%c' != [ARRAY, STRING])", to_set->type); + ERROR("Set type invalid: ('%c' != [TYPE_ARRAY, TYPE_STRING])", to_set->type); } } @@ -261,7 +268,7 @@ struct Value_array *array_set(size_t index, struct Value item, struct Value_arra if (index >= array->size) { RESIZE(array->values, index + 1); - struct Value undef = {.type=UNDEF}; + struct Value undef = {.type=TYPE_UNDEF}; for (size_t i = array->size; i < index; i++) { array->values[i] = value_copy_heap(&undef); } @@ -285,12 +292,12 @@ struct String string_set(size_t index, struct String item, struct String string) } struct Value push(struct Value what, struct Value where) { - if (where.type == ARRAY) { + if (where.type == TYPE_ARRAY) { return value_from_array(array_push(what, value_as_array(&where))); - } else if (where.type == STRING) { + } else if (where.type == TYPE_STRING) { return value_from_string(string_push(value_as_string(&what), value_as_string(&where))); } else { - ERROR("Push type invalid: ('%c' != [ARRAY, STRING])", where.type); + ERROR("Push type invalid: ('%c' != [TYPE_ARRAY, TYPE_STRING])", where.type); } } @@ -322,13 +329,13 @@ struct Value substring(struct Value start, struct Value end, struct Value what) } struct Value substring_ll(size_t start_i, size_t end_i, struct Value what) { - //if (what.type == ARRAY) { + //if (what.type == TYPE_ARRAY) { // return value_from_array(array_slice(start_i, end_i, value_as_array(&what))); //} else - if (what.type == STRING) { + if (what.type == TYPE_STRING) { return value_from_string(string_substring(start_i, end_i, value_as_string(&what))); } else { - ERROR("Substring type invalid: ('%c' != [ARRAY, STRING])", what.type); + ERROR("Substring type invalid: ('%c' != [TYPE_ARRAY, TYPE_STRING])", what.type); } } @@ -398,7 +405,7 @@ struct Value string_split(struct String sep, struct String what) { struct Value value_index(struct Value index, struct Value list) { huo_int_t i = value_as_long(&index); - if(list.type == ARRAY){ + if(list.type == TYPE_ARRAY){ struct Value_array *a = value_as_array(&list); if (i < 0) { ERROR("Negative index: %" PRIhi, i); @@ -409,11 +416,11 @@ struct Value value_index(struct Value index, struct Value list) { } return *a->values[i]; } - else if(list.type == STRING){ + else if(list.type == TYPE_STRING){ struct String s = value_as_string(&list); struct String indexed_char = string_from_char(string_index(&s, i)); return value_from_string(string_copy_stack(&indexed_char)); } else { - ERROR("Index takes a string or array, but got '%c' != [ARRAY|STRING]).", list.type); + ERROR("Index takes a string or array, but got '%c' != [TYPE_ARRAY|TYPE_STRING]).", list.type); } } diff --git a/src/execute.c b/src/execute.c index cb8a74e..045d058 100644 --- a/src/execute.c +++ b/src/execute.c @@ -36,20 +36,22 @@ struct Value execute(struct Execution_bundle * exec_bundle){ arr->values[i] = value_copy_heap(&v); } result = value_from_array(arr); - }else if(!ast_size(ast)) { + } else if(!ast_size(ast)) { + // ast has no children so must be a variable result = sub_vars(ast_value(ast), scopes, max_depth - 1); } else { huo_ast *func; struct Value *kwd = ast_value(ast_child(ast, 0)); - bool is_unbound_kwd = (kwd->type == KEYWORD); + bool is_unbound_kwd = (kwd->type == TYPE_KEYWORD); + if(is_unbound_kwd && apply_execution_function(kwd, &result, exec_bundle)){ - // pass + // if first item in ast node is a keyword and we can execute it we're done } else if(is_unbound_kwd && (func = get_defined_func(scopes, value_as_keyword(kwd))) != NULL) { + // here the keyword points to a user defined function make_args_map(exec_bundle, func); exec_bundle->ast = ast_copy(get_defined_body(func)); - exec_bundle->ast = ast; result = execute(exec_bundle); scopes->current--; } @@ -62,12 +64,12 @@ struct Value execute(struct Execution_bundle * exec_bundle){ else if(is_unbound_kwd && ast_size(ast) == 2) { exec_bundle->ast = ast_child(ast, 1); - //printf("'%s' = '", string_to_chars(ast_to_string(exec_bundle->ast))); + // printf("'%s' = '", string_to_chars(ast_to_string(exec_bundle->ast))); struct Value a = execute(exec_bundle); exec_bundle->ast = ast; - //print(a); - //printf("'\n"); + // print(a); + // printf("'\n"); result = apply_single_value_func(kwd, exec_bundle, &a); } else if (is_unbound_kwd && ast_size(ast) == 3) { diff --git a/src/execution_functions/for_each.c b/src/execution_functions/for_each.c index f671b03..9fecc0a 100644 --- a/src/execution_functions/for_each.c +++ b/src/execution_functions/for_each.c @@ -30,9 +30,9 @@ struct Value for_each(struct Execution_bundle * exec_bundle) { struct Value array = execute(exec_bundle); exec_bundle->ast = ast; - if(array.type == STRING){ + if(array.type == TYPE_STRING){ return for_each_string(value_as_string(&array), exec_bundle); - } else if (array.type == ARRAY) { + } else if (array.type == TYPE_ARRAY) { for(size_t i = 0; i < array.data.array->size; i++){ struct Value *item = array.data.array->values[i]; huo_ast * function = ast_copy(ast_child(ast, func_index)); @@ -47,7 +47,7 @@ struct Value for_each(struct Execution_bundle * exec_bundle) { exec_bundle->ast = ast; return array; } else { - ERROR("Invalid type for for_each iterable: '%c' != ARRAY", array.type); + ERROR("Invalid type for for_each iterable: '%c' != TYPE_ARRAY", array.type); } } diff --git a/src/execution_functions/map_array.c b/src/execution_functions/map_array.c index 15cf568..32655c8 100644 --- a/src/execution_functions/map_array.c +++ b/src/execution_functions/map_array.c @@ -22,8 +22,8 @@ struct Value map_array(struct Execution_bundle * exec_bundle){ } exec_bundle->ast = ast_child(ast, 1); struct Value array = execute(exec_bundle); - if (array.type != ARRAY) { - ERROR("Wrong type for map: '%c' != ARRAY", array.type); + if (array.type != TYPE_ARRAY) { + ERROR("Wrong type for map: '%c' != TYPE_ARRAY", array.type); } for(size_t i = 0; i < array.data.array->size; i++){ struct Value *item = value_copy_heap(array.data.array->values[i]); diff --git a/src/execution_functions/read_line.c b/src/execution_functions/read_line.c index 6ac005a..eeacf8b 100644 --- a/src/execution_functions/read_line.c +++ b/src/execution_functions/read_line.c @@ -12,9 +12,9 @@ struct String read_line(struct Value * string){ // read line takes a string to display as prompt // but displays it without quotes - string->type = KEYWORD; + string->type = TYPE_KEYWORD; print(*string); - string->type = STRING; + string->type = TYPE_STRING; struct String input = { .length = 0, diff --git a/src/execution_functions/reduce.c b/src/execution_functions/reduce.c index d19bf11..7738227 100644 --- a/src/execution_functions/reduce.c +++ b/src/execution_functions/reduce.c @@ -23,8 +23,8 @@ struct Value reduce_array(struct Execution_bundle * exec_bundle){ struct Value result; exec_bundle->ast = ast_child(ast, 1); struct Value array = execute(exec_bundle); - if (array.type != ARRAY) { - ERROR("Invalid type for reduce_array: '%c' != ARRAY\n", array.type); + if (array.type != TYPE_ARRAY) { + ERROR("Invalid type for reduce_array: '%c' != TYPE_ARRAY\n", array.type); } if (array.data.array->size <= 0) { return value_copy_stack(&array); diff --git a/src/execution_functions/switch.c b/src/execution_functions/switch.c index a4e153f..11689fb 100644 --- a/src/execution_functions/switch.c +++ b/src/execution_functions/switch.c @@ -12,7 +12,7 @@ struct Value switch_case(struct Execution_bundle * exec_bundle){ } for(size_t i = 2; i < ast_size(ast); i++){ huo_ast * routine = ast_child(ast, i); - if(ast_value(ast_child(routine, 0))->type == KEYWORD && string_matches_heap(&default_const, &ast_value(ast_child(routine, 0))->data.str)) { + if(ast_value(ast_child(routine, 0))->type == TYPE_KEYWORD && string_matches_heap(&default_const, &ast_value(ast_child(routine, 0))->data.str)) { if (i != ast_size(ast) - 1) { ERROR("Default not last case!"); } @@ -24,9 +24,8 @@ struct Value switch_case(struct Execution_bundle * exec_bundle){ if (ast_size(routine) != 3) { ERROR("Invalid syntax for switch_case: %zu != 3", ast_size(routine)); } - - huo_ast * return_value = ast_child(routine, 1); - ast_set_child(routine, 1, ast_child(ast, 1)); + huo_ast * return_value = ast_child(routine, 2); + ast_set_child(routine, 2, ast_child(ast, 1)); exec_bundle->ast = routine; struct Value result = execute(exec_bundle); if(value_as_bool(&result)){ @@ -38,6 +37,6 @@ struct Value switch_case(struct Execution_bundle * exec_bundle){ } exec_bundle->ast = ast; struct Value result; - result.type = UNDEF; + result.type = TYPE_UNDEF; return result; } diff --git a/src/huo.c b/src/huo.c index bd60fbe..268e644 100644 --- a/src/huo.c +++ b/src/huo.c @@ -15,86 +15,11 @@ #include "execute.h" #include "store_defs.h" #include "base_util.h" +#include "path_utils.h" #include "huo.h" #include "config.h" #include "core_functions.h" -#if defined(_POSIX_VERSION) || defined(__linux__) || defined(__APPLE__) -#include -char *get_exe_path(const char *called_name) { - char *path_to_exe = realpath(called_name, NULL); - - if (path_to_exe == NULL) { - ERROR("Error getting real path: %d (%s)", errno, strerror(errno)); - } - - return path_to_exe; -} - -char *get_path_dir(char *path) { - char *temp = dirname(path); - if (temp == NULL) { - ERROR("Error splitting directory: %s", path); - } - char *dup = o_strdup(temp); // dirname strings should not be freed - if (dup == NULL) { - ERROR("Malloc failure"); - } - return dup; -} - -char *path_merge(const char *dir, const char *rest) { - // Bleh - char *path = ARR_MALLOC(strlen(dir) + 1 + strlen(rest) + 1, char); // sizeof(char) is defined as 1, I know. - if (path == NULL) { - ERROR("Malloc failure"); - } - path[0] = 0; - strcat(path, dir); - strcat(path, "/"); - strcat(path, rest); - return path; -} -#elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) -// UNTESTED!! -#include - -char *get_exe_path(const char *called_name) { - char *buffer = malloc_or_die(MAX_PATH); - GetModuleFileName(NULL, buffer, MAX_PATH) ; - - return buffer; -} - -char *get_path_dir(char *path) { - // Bleh - char *temp = o_strdup(path); - size_t len = strlen(temp); - do { - temp[len] = 0; - if (len <= 1) { - ERROR("Could not find directory of %s", path); - } - } while (temp[--len] != '/'); - temp[len] = 0; - return temp; -} - -char *path_merge(const char *dir, const char *rest) { - char *path = ARR_MALLOC(strlen(dir) + 1 + strlen(rest) + 1, char); - if (path == NULL) { - ERROR("Malloc failure"); - } - path[0] = 0; - strcat(path, dir); - strcat(path, "\\"); - strcat(path, rest); - return path; -} -#else -#error "Unknown system!" -#endif - int main(int argc, char const *argv[]) { bool help_flag = false; bool command_flag = false; diff --git a/src/path_utils.c b/src/path_utils.c new file mode 100644 index 0000000..3284d3a --- /dev/null +++ b/src/path_utils.c @@ -0,0 +1,83 @@ +#include +#include +#include + +#if defined(_POSIX_VERSION) || defined(__linux__) || defined(__APPLE__) +#include +#include "base_util.h" + +char *get_exe_path(const char *called_name) { + char *path_to_exe = realpath(called_name, NULL); + + if (path_to_exe == NULL) { + ERROR("Error getting real path: %d (%s)", errno, strerror(errno)); + } + + return path_to_exe; +} + +char *get_path_dir(char *path) { + char *temp = dirname(path); + if (temp == NULL) { + ERROR("Error splitting directory: %s", path); + } + char *dup = o_strdup(temp); // dirname strings should not be freed + if (dup == NULL) { + ERROR("Malloc failure"); + } + return dup; +} + +char *path_merge(const char *dir, const char *rest) { + // Bleh + char *path = ARR_MALLOC(strlen(dir) + 1 + strlen(rest) + 1, char); // sizeof(char) is defined as 1, I know. + if (path == NULL) { + ERROR("Malloc failure"); + } + path[0] = 0; + strcat(path, dir); + strcat(path, "/"); + strcat(path, rest); + return path; +} +#elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__) +// UNTESTED!! +#include +#include "base_util.h" + + +char *get_exe_path(const char *called_name) { + char *buffer = malloc_or_die(MAX_PATH); + GetModuleFileName(NULL, buffer, MAX_PATH) ; + + return buffer; +} + +char *get_path_dir(char *path) { + // Bleh + char *temp = o_strdup(path); + size_t len = strlen(temp); + do { + temp[len] = 0; + if (len <= 1) { + ERROR("Could not find directory of %s", path); + } + } while (temp[--len] != '/' && temp[--len] != '\\'); + temp[len] = 0; + return temp; +} + +char *path_merge(const char *dir, const char *rest) { + char *path = ARR_MALLOC(strlen(dir) + 1 + strlen(rest) + 1, char); + if (path == NULL) { + ERROR("Malloc failure"); + } + path[0] = 0; + strcat(path, dir); + strcat(path, "\\"); + strcat(path, rest); + return path; +} +#else +#error "Unknown system!" +#endif diff --git a/src/path_utils.h b/src/path_utils.h new file mode 100644 index 0000000..34f91f2 --- /dev/null +++ b/src/path_utils.h @@ -0,0 +1,8 @@ +#ifndef _PATH_UTILS_H +#define _PATH_UTILS_H + +char *get_exe_path(const char *called_name); +char *get_path_dir(char *path); +char *path_merge(const char *dir, const char *rest); + +#endif diff --git a/src/process_defs.c b/src/process_defs.c index 6dc108b..2b30bbf 100644 --- a/src/process_defs.c +++ b/src/process_defs.c @@ -1,12 +1,12 @@ #include #include #include -#include "base_util.h" #include "core_functions.h" #include "process_defs.h" #include "execute.h" #include "execution_functions/let_binding.h" #include "structures/hash_table.h" +#include "base_util.h" #include "config.h" void make_args_map(struct Execution_bundle * exec_bundle, huo_ast * function) { @@ -25,8 +25,8 @@ void make_args_map(struct Execution_bundle * exec_bundle, huo_ast * function) { push_scope(exec_bundle->scopes); for(size_t i = 0; i + 1 < ast_size(ast); i++){ char t = ast_value(ast_child(function, i + 2))->type; - if (t != KEYWORD) { - ERROR("Invalid type for argument: '%c' != KEYWORD", t); + if (t != TYPE_KEYWORD) { + ERROR("Invalid type for argument: '%c' != TYPE_KEYWORD", t); } store_let_value(ast_value(ast_child(function, i + 2)), &vals[i], exec_bundle->scopes); } diff --git a/src/structures/array.c b/src/structures/array.c index 6e78ccb..e4c5f54 100644 --- a/src/structures/array.c +++ b/src/structures/array.c @@ -67,12 +67,12 @@ bool array_contains(struct Value *item, struct Value_array *array){ enum Value_type t = item->type; for(size_t i = 0; i < array->size; i++){ if(array->values[i]->type == t){ - if(array->values[i]->type == KEYWORD && t == KEYWORD){ + if(array->values[i]->type == TYPE_KEYWORD && t == TYPE_KEYWORD){ if(string_matches_heap(&array->values[i]->data.str, &item->data.str)){ return true; } } - else if (t == FLOAT){ + else if (t == TYPE_FLOAT){ if(array->values[i]->data.fl == item->data.fl){ return true; } diff --git a/src/structures/huo_ast.c b/src/structures/huo_ast.c index 3fe002d..1dbb92d 100644 --- a/src/structures/huo_ast.c +++ b/src/structures/huo_ast.c @@ -8,7 +8,6 @@ #include "../base_util.h" - struct huo_ast_t { enum ast_type_e type; size_t size; @@ -178,3 +177,16 @@ void ast_free(huo_ast *ast) { free(ast); } } + +huo_ast * value_as_ast(struct Value *v) { + CHECK_TYPE(v, TYPE_AST); + return v->data.ast; +} + +struct Value value_from_ast(huo_ast *ast) { + struct Value v = { + .type = TYPE_AST, + .data.ast = ast + }; + return v; +} diff --git a/src/structures/huo_ast.h b/src/structures/huo_ast.h index ea6fac6..6ea2c2a 100644 --- a/src/structures/huo_ast.h +++ b/src/structures/huo_ast.h @@ -18,6 +18,8 @@ enum ast_type_e { AST_KEYWORD, }; +huo_ast * value_as_ast(struct Value *v); +struct Value value_from_ast(huo_ast *ast); huo_ast *ast_new(enum ast_type_e type, struct Value v); enum ast_type_e ast_type(huo_ast *const tree); diff --git a/src/structures/token.c b/src/structures/token.c index f614f26..95519e3 100644 --- a/src/structures/token.c +++ b/src/structures/token.c @@ -52,7 +52,7 @@ bool can_be_of_type(char c, enum token_type_t type) { } switch (type) { case TOK_WHITESPACE: - return c == ' ' || c == '\t'; + return c == ' ' || c == '\t' || c == '\r'; case TOK_NEWLINE: return c == '\n'; case TOK_PLUS: @@ -82,6 +82,7 @@ bool can_be_of_type(char c, enum token_type_t type) { case TOK_COMMENT: return c == ';'; default: + printf("%i", c); ERROR("Unknown type: '%d'", type); } } diff --git a/src/structures/value.c b/src/structures/value.c index 513f621..9ebbd3d 100644 --- a/src/structures/value.c +++ b/src/structures/value.c @@ -1,31 +1,24 @@ #include #include "structures.h" +#include "../constants.h" #include "value.h" - #include "../base_util.h" #include "../config.h" -#define CHECK_TYPE(v, tp) do {\ - /* assert((v)->type == (tp)); */ \ - if ((v)->type != (tp))\ - ERROR("Invalid type: '%i' != '%i'", (v)->type, (tp));\ - } while (0) - - struct Value value_copy_stack(struct Value * b){ struct Value a; - if (b->type == STRING || b->type == KEYWORD) { + if (b->type == TYPE_STRING || b->type == TYPE_KEYWORD) { a.data.str = value_as_string_or_kwd(b); - } else if(b->type == FLOAT){ + } else if(b->type == TYPE_FLOAT){ a.data.fl = value_as_float(b); - } else if(b->type == LONG){ + } else if(b->type == TYPE_LONG){ a.data.ln = value_as_long(b); - } else if (b->type == BOOL){ + } else if (b->type == TYPE_BOOL){ a.data.bl = value_as_bool(b); - } else if (b->type == ARRAY){ + } else if (b->type == TYPE_ARRAY){ a.data.array = array_copy_heap(value_as_array(b)); - } else if (b->type == UNDEF){ - a.type = UNDEF; + } else if (b->type == TYPE_UNDEF){ + a.type = TYPE_UNDEF; } else { ERROR("Unknown type: %c", a.type); } @@ -35,18 +28,20 @@ struct Value value_copy_stack(struct Value * b){ struct Value *value_copy_heap(struct Value * b){ struct Value *a = malloc_or_die(sizeof(struct Value)); - if (b->type == STRING || b->type == KEYWORD) { + if (b->type == TYPE_STRING || b->type == TYPE_KEYWORD) { a->data.str = value_as_string_or_kwd(b); - } else if(b->type == FLOAT){ + } else if(b->type == TYPE_FLOAT){ a->data.fl = value_as_float(b); - } else if(b->type == LONG){ + } else if(b->type == TYPE_LONG){ a->data.ln = value_as_long(b); - } else if (b->type == BOOL){ + } else if (b->type == TYPE_BOOL){ a->data.bl = value_as_bool(b); - } else if (b->type == ARRAY){ + } else if (b->type == TYPE_ARRAY){ a->data.array = array_copy_heap(value_as_array(b)); - } else if (b->type == UNDEF){ - a->type = UNDEF; + } else if (b->type == TYPE_AST){ + a->data.ast = ast_copy(value_as_ast(b)); + } else if (b->type == TYPE_UNDEF){ + a->type = TYPE_UNDEF; } else { ERROR("Unknown type: %c", a->type); } @@ -56,27 +51,27 @@ struct Value *value_copy_heap(struct Value * b){ void value_copy_to(struct Value * a, struct Value * b){ #if 0 - if (a->type == STRING) { + if (a->type == TYPE_STRING) { string_free(value_as_string(a)); - } else if (a->type == KEYWORD) { + } else if (a->type == TYPE_KEYWORD) { string_free(value_as_keyword(a)); - }else if (a->type == ARRAY) { + }else if (a->type == TYPE_ARRAY) { array_free(value_as_array(a)); } #endif - if(b->type == STRING || b->type == KEYWORD){ + if(b->type == TYPE_STRING || b->type == TYPE_KEYWORD){ struct String b_str = value_as_string_or_kwd(b); string_copy_to(&a->data.str, &b_str); - } else if(b->type == FLOAT){ + } else if(b->type == TYPE_FLOAT){ a->data.fl = value_as_float(b); - } else if(b->type == LONG){ + } else if(b->type == TYPE_LONG){ a->data.ln = value_as_long(b); - } else if (b->type == BOOL){ + } else if (b->type == TYPE_BOOL){ a->data.bl = value_as_bool(b); - } else if (b->type == ARRAY){ + } else if (b->type == TYPE_ARRAY){ array_copy_to(value_as_array(a), value_as_array(b)); - } else if (b->type == UNDEF){ - // a->type == UNDEF; + } else if (b->type == TYPE_UNDEF){ + // a->type == TYPE_UNDEF; } else { ERROR("Unknown type: %c", a->type); } @@ -84,36 +79,44 @@ void value_copy_to(struct Value * a, struct Value * b){ } float value_as_float(struct Value *v) { - CHECK_TYPE(v, FLOAT); - return v->data.fl; + if(v->type == TYPE_LONG){ + return (float)v->data.ln; + } else { + CHECK_TYPE(v, TYPE_FLOAT); + return v->data.fl; + } } bool value_as_bool(struct Value *v) { - CHECK_TYPE(v, BOOL); + CHECK_TYPE(v, TYPE_BOOL); return v->data.bl; } huo_int_t value_as_long(struct Value *v) { - CHECK_TYPE(v, LONG); - return v->data.ln; + if(v->type == TYPE_FLOAT){ + return (long)v->data.fl; + } else { + CHECK_TYPE(v, TYPE_LONG); + return v->data.ln; + } } struct String value_as_string_or_kwd(struct Value *v) { - if (v->type == STRING) { + if (v->type == TYPE_STRING) { return value_as_string(v); - } else if (v->type == KEYWORD) { + } else if (v->type == TYPE_KEYWORD) { return value_as_keyword(v); } else { ERROR("Unknown type: %c", v->type); } } struct String value_as_string(struct Value *v) { - CHECK_TYPE(v, STRING); + CHECK_TYPE(v, TYPE_STRING); return v->data.str; } struct Value_array *value_as_array(struct Value *v) { - CHECK_TYPE(v, ARRAY); + CHECK_TYPE(v, TYPE_ARRAY); return v->data.array; } struct String value_as_keyword(struct Value *v) { - CHECK_TYPE(v, KEYWORD); + CHECK_TYPE(v, TYPE_KEYWORD); return v->data.str; } @@ -121,7 +124,7 @@ size_t length(struct Value a); struct Value value_from_float(float f) { struct Value v = { - .type = FLOAT, + .type = TYPE_FLOAT, .data.fl = f }; return v; @@ -129,7 +132,7 @@ struct Value value_from_float(float f) { struct Value value_from_bool(bool b) { struct Value v = { - .type = BOOL, + .type = TYPE_BOOL, .data.bl = b }; return v; @@ -137,7 +140,7 @@ struct Value value_from_bool(bool b) { struct Value value_from_long(huo_int_t l) { struct Value v = { - .type = LONG, + .type = TYPE_LONG, .data.ln = l }; return v; @@ -145,7 +148,7 @@ struct Value value_from_long(huo_int_t l) { struct Value value_from_string(struct String str) { struct Value v = { - .type = STRING, + .type = TYPE_STRING, .data.str = str }; return v; @@ -153,7 +156,7 @@ struct Value value_from_string(struct String str) { struct Value value_from_array(struct Value_array *arr) { struct Value v = { - .type = ARRAY, + .type = TYPE_ARRAY, .data.array = arr }; return v; @@ -161,22 +164,22 @@ struct Value value_from_array(struct Value_array *arr) { struct Value value_from_keyword(struct String *kwd) { struct Value v = { - .type = KEYWORD, + .type = TYPE_KEYWORD, .data.str = *kwd }; return v; } struct Value value_from_undef() { struct Value v = { - .type = UNDEF, + .type = TYPE_UNDEF, }; return v; } size_t length(struct Value a) { - if (a.type == STRING) { + if (a.type == TYPE_STRING) { return string_length(&a.data.str); - } else if (a.type == ARRAY) { + } else if (a.type == TYPE_ARRAY) { return a.data.array->size; } else { ERROR("Type error: value of type '%c' has no length property", a.type); @@ -198,17 +201,17 @@ bool value_equals_shallow(struct Value *a, struct Value *b) { if (a->type != b->type) return false; switch (a->type) { - case ARRAY: + case TYPE_ARRAY: return value_as_array(a) == value_as_array(b); - case STRING: + case TYPE_STRING: return string_matches_stack(value_as_string(a), value_as_string(b)); - case LONG: + case TYPE_LONG: return value_as_long(a) == value_as_long(b); - case FLOAT: + case TYPE_FLOAT: return value_as_float(a) == value_as_float(b); - case BOOL: + case TYPE_BOOL: return value_as_bool(a) == value_as_bool(b); - case KEYWORD: + case TYPE_KEYWORD: return string_matches_stack(value_as_keyword(a), value_as_keyword(b)); default: ERROR("Unknown type %i", a->type); @@ -216,33 +219,59 @@ bool value_equals_shallow(struct Value *a, struct Value *b) { } void value_negate(struct Value *v) { - if(v->type == FLOAT){ + if(v->type == TYPE_FLOAT){ v->data.fl = -value_as_float(v); - } else if(v->type == LONG){ + } else if(v->type == TYPE_LONG){ v->data.ln = -value_as_long(v); } else { ERROR("Type error: value of type '%c' cannot be negated", v->type); } } +struct String type_to_string(enum Value_type type){ + switch (type) { + case TYPE_STRING: + return string_copy_stack(&string_const); + break; + case TYPE_FLOAT: + case TYPE_LONG: + return string_copy_stack(&number_const); + break; + case TYPE_ARRAY: + return string_copy_stack(&array_const); + break; + case TYPE_BOOL: + return string_copy_stack(&boolean_const); + break; + case TYPE_KEYWORD: + return string_copy_stack(&keyword_const); + break; + case TYPE_UNDEF: + return string_copy_stack(&undefined_const); + break; + default: + ERROR("Type error: unrecognized type: '%c'.", type) + } +} + void value_free_stack(struct Value v) { switch (v.type) { - case ARRAY: + case TYPE_ARRAY: array_free(v.data.array); break; - case STRING: - case KEYWORD: + case TYPE_STRING: + case TYPE_KEYWORD: string_free_stack(v.data.str); break; - case LONG: - case FLOAT: - case BOOL: - case UNDEF: + case TYPE_LONG: + case TYPE_FLOAT: + case TYPE_BOOL: + case TYPE_UNDEF: break; default: ERROR("Unknown type %i", v.type); } - v.type = UNDEF; + v.type = TYPE_UNDEF; } void value_free(struct Value *v) { diff --git a/src/structures/value.h b/src/structures/value.h index a79bbe8..704e88a 100644 --- a/src/structures/value.h +++ b/src/structures/value.h @@ -6,21 +6,25 @@ #include "string.h" enum Value_type { - FLOAT, - BOOL, - LONG, - STRING, - ARRAY, - KEYWORD, - UNDEF + TYPE_FLOAT, + TYPE_BOOL, + TYPE_LONG, + TYPE_STRING, + TYPE_ARRAY, + TYPE_KEYWORD, + TYPE_AST, + TYPE_UNDEF }; +typedef struct huo_ast_t huo_ast; + union Data { bool bl; huo_int_t ln; float fl; struct String str; struct Value_array * array; + huo_ast * ast; }; struct Value { @@ -28,6 +32,12 @@ struct Value { union Data data; }; +#define CHECK_TYPE(v, tp) do {\ + /* assert((v)->type == (tp)); */ \ + if ((v)->type != (tp))\ + ERROR("Invalid type: '%i' != '%i'", (v)->type, (tp));\ + } while (0) + float value_as_float(struct Value *v); bool value_as_bool(struct Value *v); huo_int_t value_as_long(struct Value *v); @@ -53,6 +63,7 @@ size_t length(struct Value a); unsigned long value_keyword_hash_code(void *value); bool value_keyword_equality(void *a, void *b); +struct String type_to_string(enum Value_type type); bool value_equals_shallow(struct Value *a, struct Value *b); void value_negate(struct Value *v); void value_free(struct Value *v);