Added more context to all errors.
@@ -7,7 +7,7 @@
hex: src/hex.c $(CC) $(CFLAGS) $(LDFLAGS) $< -o hex -src/hex.c: src/hex.h src/error.c src/doc.c src/utils.c src/interpreter.c src/main.c src/parser.c src/registry.c src/stack.c src/stacktrace.c src/symbols.c src/vm.c src/symboltable.c src/opcodes.c +src/hex.c: src/hex.h src/error.c src/doc.c src/utils.c src/interpreter.c src/main.c src/parser.c src/registry.c src/stack.c src/symbols.c src/vm.c src/symboltable.c src/opcodes.c bash scripts/amalgamate.sh web/assets/hex.wasm: src/hex.c web/assets/hex-playground.js
@@ -7,7 +7,6 @@ "src/stack.c"
"src/registry.c" "src/error.c" "src/doc.c" - "src/stacktrace.c" "src/parser.c" "src/symboltable.c" "src/opcodes.c"
@@ -89,8 +89,8 @@ ;32
("hello" " world" cat "hello world" ==) ((0x1 "a") ("b") cat (0x1 "a" "b") ==) - ((() not) (error) try "Symbol 'not' requires an integer" ==) - ((() 0x1 xor) (error) try "Symbol 'xor' requires two integers" ==) + ((() not) (error) try "[symbol not] Integer required" ==) + ((() 0x1 xor) (error) try "[symbol xor] Two integers required" ==) ;36 ("aaaaa" len 0x5 ==)@@ -101,8 +101,8 @@ ;40
("a/b/c" "t-path" : (t-path "/" index 0x0 >=) (t-path "/" "\\" replace "t-path" :) while t-path "a\\b\\c" == "t-path" #) ("assets\"" "\"" "/" replace "assets/" ==) - (("" () cat) (error) try "Symbol 'cat' requires two quotations or two strings" ==) - ((0x4 len) (error) try "Symbol 'len' requires a quotation or a string" ==) + (("" () cat) (error) try "[symbol cat] Two quotations or two strings required" ==) + ((0x4 len) (error) try "[symbol len] Quotation or string required" ==) ;44 ("this is a test" "is" index 0x2 ==)@@ -129,7 +129,7 @@ (0x1 "tmp-a" : (tmp-a 0x3 <) (tmp-a 0x1 + "tmp-a" :) while tmp-a 0x3 ==)
(0x0 "tmp-b" : (0x1 0x2 0x3) (tmp-b + "tmp-b" :) each tmp-b 0x6 ==) ;60 - ((0x2 0x0 /) (error "Division by zero" ==) try) + ((0x2 0x0 /) (error "[symbol /] Division by zero" ==) try) (error "" ==) ("a" ' ' ' ((("a"))) ==) ((0x1 0x2 0x3) (dup dup * *) map (0x1 0x8 0x1b) ==)@@ -141,16 +141,16 @@ (clear stack () ==)
(0x1 0x2 swap pop stack (0x2) ==) ;68 - (("aaa" "puts" :) (error) try "Failed to store symbol 'puts'" ==) - (("puts" #) (error) try "Cannot free native symbol 'puts'" ==) - (("aaa" 0x2 :) (error) try "Symbol name must be a string" ==) - ((0x2 #) (error) try "Symbol name must be a string" ==) + (("aaa" "puts" :) (error) try "[symbol :] Failed to store symbol 'puts'" ==) + (("puts" #) (error) try "[symbol #] Cannot free native symbol 'puts'" ==) + (("aaa" 0x2 :) (error) try "[symbol :] Symbol name must be a string" ==) + ((0x2 #) (error) try "[symbol #] Symbol name must be a string" ==) ;72 - (("puts" .) (error) try "Symbol '.' requires a quotation" ==) - (((puts) !) (error) try "Quotation must contain only integers" ==) - (("3" 0x3 +) (error) try "Symbol '+' requires two integers" ==) - (("3" 0x3 -) (error) try "Symbol '-' requires two integers" ==) + (("puts" .) (error) try "[symbol .] Quotation required" ==) + (((puts) !) (error) try "[symbol !] Quotation must contain only integers" ==) + (("3" 0x3 +) (error) try "[symbol +] Two integers required" ==) + (("3" 0x3 -) (error) try "[symbol -] Two integers required" ==) ;76 ((0x2 0x3 0x3) (0x2 0x3) > 0x1 ==)@@ -160,27 +160,27 @@ (("test" "abc") ("test" "abc") <= 0x1 ==)
;80 ("hello" "" split ("h" "e" "l" "l" "o") ==) - (("3" 0x3 /) (error) try "Symbol '/' requires two integers" ==) - ((0x4 0x0 %) (error) try "Division by zero" ==) - ((() 0x3 %) (error) try "Symbol '%' requires two integers" ==) + (("3" 0x3 /) (error) try "[symbol /] Two integers required" ==) + ((0x4 0x0 %) (error) try "[symbol %] Division by zero" ==) + ((() 0x3 %) (error) try "[symbol %] Two integers required" ==) ;84 - ((() 0x3 &) (error) try "Symbol '&' requires two integers" ==) - ((0x2 "" |) (error) try "Symbol '|' requires two integers" ==) - ((() "" ^) (error) try "Symbol '^' requires two integers" ==) - ((() 0x1 >>) (error) try "Symbol '>>' requires two integers" ==) + ((() 0x3 &) (error) try "[symbol &] Two integers required" ==) + ((0x2 "" |) (error) try "[symbol |] Two integers required" ==) + ((() "" ^) (error) try "[symbol ^] Two integers required" ==) + ((() 0x1 >>) (error) try "[symbol >>] Two integers required" ==) ;88 - ((() 0x1 <<) (error) try "Symbol '<<' requires two integers" ==) - (("" ~) (error) try "Symbol '~' requires an integer" ==) - ((0x5 int) (error) try "Symbol 'int' requires a string" ==) - (((0x3) int) (error) try "Symbol 'int' requires a string" ==) + ((() 0x1 <<) (error) try "[symbol <<] Two integers required" ==) + (("" ~) (error) try "[symbol ~] Integer required" ==) + ((0x5 int) (error) try "[symbol int] String representing a hexadecimal integer required" ==) + (((0x3) int) (error) try "[symbol int] String representing a hexadecimal integer required" ==) ;92 - (("5" str) (error) try "Symbol 'str' requires an integer" ==) - ((("aaa") str) (error) try "Symbol 'str' requires an integer" ==) - (("10" dec) (error) try "Symbol 'dec' requires an integer" ==) - ((0x5 hex) (error) try "Symbol 'hex' requires a string representing a decimal integer" ==) + (("5" str) (error) try "[symbol str] Integer required" ==) + ((("aaa") str) (error) try "[symbol str] Integer required" ==) + (("10" dec) (error) try "[symbol dec] Integer required" ==) + ((0x5 hex) (error) try "[symbol hex] String representing a decimal integer required" ==) ;96 ("0x2" 0x2 == 0x0 ==)@@ -191,18 +191,18 @@ ;100
((test "aaa") (test "aaa" 0x5) < 0x1 ==) (("aaa" 0x5) ("" "aaa" 0x5) <= 0x0 ==) - (("a" "b" and) (error) try "Symbol 'and' requires two integers" ==) - ((0x1 "a" or) (error) try "Symbol 'or' requires two integers" ==) + (("a" "b" and) (error) try "[symbol and] Two integers required" ==) + ((0x1 "a" or) (error) try "[symbol or] Two integers required" ==) ;104 - (("abc" 0x3 get) (error) try "Index out of range" ==) - (((0x2) 0x2 get) (error) try "Index out of range" ==) - ((() 0x0 get) (error) try "Index out of range" ==) - ((0x4 0x4 get) (error) try "Symbol 'get' requires a quotation or a string" ==) + (("abc" 0x3 get) (error) try "[symbol get] Index out of range" ==) + (((0x2) 0x2 get) (error) try "[symbol get] Index out of range" ==) + ((() 0x0 get) (error) try "[symbol get] Index out of range" ==) + ((0x4 0x4 get) (error) try "[symbol get] Quotation or string required" ==) ;108 - (("abc" "b" get) (error) try "Index must be an integer" ==) - (((0x4 "aa" test) "b" get) (error) try "Index must be an integer" ==) + (("abc" "b" get) (error) try "[symbol get] Index must be an integer" ==) + (((0x4 "aa" test) "b" get) (error) try "[symbol get] Index must be an integer" ==) ("a" ord 0x61 ==) (0x61 chr "a" ==) ;112@@ -214,9 +214,9 @@ (0x80 chr "" ==)
;116 ("abc" ord 0xffffffff ==) - ((0x56 ord) (error) try "Symbol 'ord' requires a string" ==) - (("t" chr) (error) try "Symbol 'chr' requires an integer" ==) - ((() chr) (error) try "Symbol 'chr' requires an integer" ==) + ((0x56 ord) (error) try "[symbol ord] String required" ==) + (("t" chr) (error) try "[symbol chr] Integer required" ==) + ((() chr) (error) try "[symbol chr] Integer required" ==) ;120 (0xffffffff dec "-1" ==)
@@ -6,7 +6,7 @@ ////////////////////////////////////////
// Help System // //////////////////////////////////////// -void hex_doc(hex_doc_dictionary_t *dict, const char *name, const char *input, const char *output, const char *description) +void hex_set_doc(hex_doc_dictionary_t *dict, const char *name, const char *input, const char *output, const char *description) { hex_doc_entry_t doc = {.name = name, .description = description, .input = input, .output = output}; // No overflow check as the dictionary is fixed size@@ -30,96 +30,96 @@
void hex_create_docs(hex_doc_dictionary_t *docs) { // Memory - hex_doc(docs, ":", "a s", "", "Stores 'a' as symbol 's'."); - hex_doc(docs, "#", "s", "", "Deletes user symbol 's'."); + hex_set_doc(docs, ":", "a s", "", "Stores 'a' as symbol 's'."); + hex_set_doc(docs, "#", "s", "", "Deletes user symbol 's'."); // Control flow - hex_doc(docs, "if", "q q q", "*", "If 'q1' is not 0x0, executes 'q2', else 'q3'."); - hex_doc(docs, "when", "q1 q2", "*", "If 'q1' is not 0x0, executes 'q2'."); - hex_doc(docs, "while", "q1 q2", "*", "While 'q1' is not 0x0, executes 'q2'."); - hex_doc(docs, "error", "", "s", "Returns the last error message."); - hex_doc(docs, "try", "q1 q2", "*", "If 'q1' fails, executes 'q2'."); + hex_set_doc(docs, "if", "q q q", "*", "If 'q1' is not 0x0, executes 'q2', else 'q3'."); + hex_set_doc(docs, "when", "q1 q2", "*", "If 'q1' is not 0x0, executes 'q2'."); + hex_set_doc(docs, "while", "q1 q2", "*", "While 'q1' is not 0x0, executes 'q2'."); + hex_set_doc(docs, "error", "", "s", "Returns the last error message."); + hex_set_doc(docs, "try", "q1 q2", "*", "If 'q1' fails, executes 'q2'."); // Stack - hex_doc(docs, "dup", "a", "a a", "Duplicates 'a'."); - hex_doc(docs, "pop", "a", "", "Removes the top item from the stack."); - hex_doc(docs, "swap", "a1 a2", "a2 a1", "Swaps 'a2' with 'a1'."); - hex_doc(docs, "stack", "", "q", "Returns the contents of the stack."); - hex_doc(docs, "clear", "", "", "Clears the stack."); + hex_set_doc(docs, "dup", "a", "a a", "Duplicates 'a'."); + hex_set_doc(docs, "pop", "a", "", "Removes the top item from the stack."); + hex_set_doc(docs, "swap", "a1 a2", "a2 a1", "Swaps 'a2' with 'a1'."); + hex_set_doc(docs, "stack", "", "q", "Returns the contents of the stack."); + hex_set_doc(docs, "clear", "", "", "Clears the stack."); // Evaluation - hex_doc(docs, ".", "q", "*", "Pushes each item of 'q' on the stack."); - hex_doc(docs, "!", "(s|q)", "*", "Evaluates 's' as a hex program or 'q' as hex bytecode."); - hex_doc(docs, "'", "a", "q", "Wraps 'a' in a quotation."); + hex_set_doc(docs, ".", "q", "*", "Pushes each item of 'q' on the stack."); + hex_set_doc(docs, "!", "(s|q)", "*", "Evaluates 's' as a hex program or 'q' as hex bytecode."); + hex_set_doc(docs, "'", "a", "q", "Wraps 'a' in a quotation."); // Arithmetic - hex_doc(docs, "+", "i1 12", "i", "Adds two integers."); - hex_doc(docs, "-", "i1 12", "i", "Subtracts 'i2' from 'i1'."); - hex_doc(docs, "*", "i1 12", "i", "Multiplies two integers."); - hex_doc(docs, "/", "i1 12", "i", "Divides 'i1' by 'i2'."); - hex_doc(docs, "%", "i1 12", "i", "Calculates the modulo of 'i1' divided by 'i2'."); + hex_set_doc(docs, "+", "i1 12", "i", "Adds two integers."); + hex_set_doc(docs, "-", "i1 12", "i", "Subtracts 'i2' from 'i1'."); + hex_set_doc(docs, "*", "i1 12", "i", "Multiplies two integers."); + hex_set_doc(docs, "/", "i1 12", "i", "Divides 'i1' by 'i2'."); + hex_set_doc(docs, "%", "i1 12", "i", "Calculates the modulo of 'i1' divided by 'i2'."); // Bitwise - hex_doc(docs, "&", "i1 12", "i", "Calculates the bitwise AND of two integers."); - hex_doc(docs, "|", "i1 12", "i", "Calculates the bitwise OR of two integers."); - hex_doc(docs, "^", "i1 12", "i", "Calculates the bitwise XOR of two integers."); - hex_doc(docs, "~", "i", "i", "Calculates the bitwise NOT of an integer."); - hex_doc(docs, "<<", "i1 12", "i", "Shifts 'i1' by 'i2' bytes to the left."); - hex_doc(docs, ">>", "i1 12", "i", "Shifts 'i1' by 'i2' bytes to the right."); + hex_set_doc(docs, "&", "i1 12", "i", "Calculates the bitwise AND of two integers."); + hex_set_doc(docs, "|", "i1 12", "i", "Calculates the bitwise OR of two integers."); + hex_set_doc(docs, "^", "i1 12", "i", "Calculates the bitwise XOR of two integers."); + hex_set_doc(docs, "~", "i", "i", "Calculates the bitwise NOT of an integer."); + hex_set_doc(docs, "<<", "i1 12", "i", "Shifts 'i1' by 'i2' bytes to the left."); + hex_set_doc(docs, ">>", "i1 12", "i", "Shifts 'i1' by 'i2' bytes to the right."); // Comparison - hex_doc(docs, "==", "a1 a2", "i", "Returns 0x1 if 'a1' == 'a2', 0x0 otherwise."); - hex_doc(docs, "!=", "a1 a2", "i", "Returns 0x1 if 'a1' != 'a2', 0x0 otherwise."); - hex_doc(docs, ">", "a1 a2", "i", "Returns 0x1 if 'a1' > 'a2', 0x0 otherwise."); - hex_doc(docs, "<", "a1 a2", "i", "Returns 0x1 if 'a1' < 'a2', 0x0 otherwise."); - hex_doc(docs, ">=", "a1 a2", "i", "Returns 0x1 if 'a1' >= 'a2', 0x0 otherwise."); - hex_doc(docs, "<=", "a1 a2", "i", "Returns 0x1 if 'a1' <= 'a2', 0x0 otherwise."); + hex_set_doc(docs, "==", "a1 a2", "i", "Returns 0x1 if 'a1' == 'a2', 0x0 otherwise."); + hex_set_doc(docs, "!=", "a1 a2", "i", "Returns 0x1 if 'a1' != 'a2', 0x0 otherwise."); + hex_set_doc(docs, ">", "a1 a2", "i", "Returns 0x1 if 'a1' > 'a2', 0x0 otherwise."); + hex_set_doc(docs, "<", "a1 a2", "i", "Returns 0x1 if 'a1' < 'a2', 0x0 otherwise."); + hex_set_doc(docs, ">=", "a1 a2", "i", "Returns 0x1 if 'a1' >= 'a2', 0x0 otherwise."); + hex_set_doc(docs, "<=", "a1 a2", "i", "Returns 0x1 if 'a1' <= 'a2', 0x0 otherwise."); // Logical - hex_doc(docs, "and", "i1 i2", "i", "Returns 0x1 if both 'i1' and 'i2' are not 0x0."); - hex_doc(docs, "or", "i1 i2", "i", "Returns 0x1 if either 'i1' or 'i2' are not 0x0."); - hex_doc(docs, "not", "i", "i", "Returns 0x1 if 'i' is 0x0, 0x0 otherwise."); - hex_doc(docs, "xor", "i1 i2", "i", "Returns 0x1 if only one item is not 0x0."); + hex_set_doc(docs, "and", "i1 i2", "i", "Returns 0x1 if both 'i1' and 'i2' are not 0x0."); + hex_set_doc(docs, "or", "i1 i2", "i", "Returns 0x1 if either 'i1' or 'i2' are not 0x0."); + hex_set_doc(docs, "not", "i", "i", "Returns 0x1 if 'i' is 0x0, 0x0 otherwise."); + hex_set_doc(docs, "xor", "i1 i2", "i", "Returns 0x1 if only one item is not 0x0."); // Type - hex_doc(docs, "int", "s", "i", "Converts a string to a hex integer."); - hex_doc(docs, "str", "i", "s", "Converts a hex integer to a string."); - hex_doc(docs, "dec", "i", "s", "Converts a hex integer to a decimal string."); - hex_doc(docs, "hex", "s", "i", "Converter a decimal string to a hex integer."); - hex_doc(docs, "chr", "i", "s", "Converts an integer to a single-character."); - hex_doc(docs, "ord", "s", "i", "Converts a single-character to an integer."); - hex_doc(docs, "type", "a", "s", "Pushes the data type of 'a' on the stack."); + hex_set_doc(docs, "int", "s", "i", "Converts a string to a hex integer."); + hex_set_doc(docs, "str", "i", "s", "Converts a hex integer to a string."); + hex_set_doc(docs, "dec", "i", "s", "Converts a hex integer to a decimal string."); + hex_set_doc(docs, "hex", "s", "i", "Converter a decimal string to a hex integer."); + hex_set_doc(docs, "chr", "i", "s", "Converts an integer to a single-character."); + hex_set_doc(docs, "ord", "s", "i", "Converts a single-character to an integer."); + hex_set_doc(docs, "type", "a", "s", "Pushes the data type of 'a' on the stack."); // List - hex_doc(docs, "cat", "(s1 s2|q1 q2) ", "(s3|q3)", "Concatenates two quotations or two strings."); - hex_doc(docs, "len", "(s|q)", "i ", "Returns the length of 's' or 'q'."); - hex_doc(docs, "get", "(s|q)", "a", "Gets the item at position 'i' in 's' or 'q'."); - hex_doc(docs, "index", "(s a|q a)", "i", "Returns the index of 'a' within 's' or 'q'."); - hex_doc(docs, "join", "q s", "s", "Joins the strings in 'q' using separator 's'."); + hex_set_doc(docs, "cat", "(s1 s2|q1 q2) ", "(s3|q3)", "Concatenates two quotations or two strings."); + hex_set_doc(docs, "len", "(s|q)", "i ", "Returns the length of 's' or 'q'."); + hex_set_doc(docs, "get", "(s|q)", "a", "Gets the item at position 'i' in 's' or 'q'."); + hex_set_doc(docs, "index", "(s a|q a)", "i", "Returns the index of 'a' within 's' or 'q'."); + hex_set_doc(docs, "join", "q s", "s", "Joins the strings in 'q' using separator 's'."); // String - hex_doc(docs, "split", "s1 s2", "q", "Splits 's1' using separator 's2'."); - hex_doc(docs, "replace", "s1 s2 s3", "s", "Replaces 's2' with 's3' within 's1'."); + hex_set_doc(docs, "split", "s1 s2", "q", "Splits 's1' using separator 's2'."); + hex_set_doc(docs, "replace", "s1 s2 s3", "s", "Replaces 's2' with 's3' within 's1'."); // Quotation - hex_doc(docs, "each", "q1 q2", "*", "Executes 'q2' for each item of 'q1'."); - hex_doc(docs, "map", "q1 q2", "q3", "Applies 'q2' to 'q1' items and returns results."); - hex_doc(docs, "filter", "q1 q2", "q3", "Filters 'q2' by applying 'q1'."); + hex_set_doc(docs, "each", "q1 q2", "*", "Executes 'q2' for each item of 'q1'."); + hex_set_doc(docs, "map", "q1 q2", "q3", "Applies 'q2' to 'q1' items and returns results."); + hex_set_doc(docs, "filter", "q1 q2", "q3", "Filters 'q2' by applying 'q1'."); // I/O - hex_doc(docs, "puts", "a", "", "Prints 'a' and a new line to standard output."); - hex_doc(docs, "warn", "a", "", "Prints 'a' and a new line to standard error."); - hex_doc(docs, "print", "a", "", "Prints 'a' to standard output."); - hex_doc(docs, "gets", "", "s", "Gets a string from standard input."); + hex_set_doc(docs, "puts", "a", "", "Prints 'a' and a new line to standard output."); + hex_set_doc(docs, "warn", "a", "", "Prints 'a' and a new line to standard error."); + hex_set_doc(docs, "print", "a", "", "Prints 'a' to standard output."); + hex_set_doc(docs, "gets", "", "s", "Gets a string from standard input."); // File - hex_doc(docs, "read", "s1", "(s2|q)", "Returns the contents of the specified file."); - hex_doc(docs, "write", "(s1|q) s2", "", "Writes 's1' or 'q' to the file 's2'."); - hex_doc(docs, "append", "(s1|q) s2", "", "Appends 's1' or 'q' to the file 's2'."); + hex_set_doc(docs, "read", "s1", "(s2|q)", "Returns the contents of the specified file."); + hex_set_doc(docs, "write", "(s1|q) s2", "", "Writes 's1' or 'q' to the file 's2'."); + hex_set_doc(docs, "append", "(s1|q) s2", "", "Appends 's1' or 'q' to the file 's2'."); // Shell - hex_doc(docs, "args", "", "q", "Returns the program arguments."); - hex_doc(docs, "exit", "i", "", "Exits the program with exit code 'i'."); - hex_doc(docs, "exec", "s", "i", "Executes the command 's'."); - hex_doc(docs, "run", "s", "q", "Executes 's' and returns code, stdout, stderr."); + hex_set_doc(docs, "args", "", "q", "Returns the program arguments."); + hex_set_doc(docs, "exit", "i", "", "Exits the program with exit code 'i'."); + hex_set_doc(docs, "exec", "s", "i", "Executes the command 's'."); + hex_set_doc(docs, "run", "s", "q", "Executes 's' and returns code, stdout, stderr."); }
@@ -13,7 +13,7 @@ va_start(args, format);
vsnprintf(ctx->error, sizeof(ctx->error), format, args); if (ctx->settings.errors_enabled) /// FC { - fprintf(stderr, "[error] "); + fprintf(stderr, "ERROR: "); fprintf(stderr, "%s\n", ctx->error); } va_end(args);@@ -62,3 +62,43 @@ hex_print_item(stdout, item);
fprintf(stdout, "\n"); } } + +//////////////////////////////////////// +// Stack trace implementation // +//////////////////////////////////////// + +// Add an entry to the circular stack trace +void add_to_stack_trace(hex_context_t *ctx, hex_token_t *token) +{ + int index = (ctx->stack_trace.start + ctx->stack_trace.size) % HEX_STACK_TRACE_SIZE; + + if (ctx->stack_trace.size < HEX_STACK_TRACE_SIZE) + { + // Buffer is not full; add item + ctx->stack_trace.entries[index] = *token; + ctx->stack_trace.size++; + } + else + { + // Buffer is full; overwrite the oldest item + ctx->stack_trace.entries[index] = *token; + ctx->stack_trace.start = (ctx->stack_trace.start + 1) % HEX_STACK_TRACE_SIZE; + } +} + +// Print the stack trace +void print_stack_trace(hex_context_t *ctx) +{ + if (!ctx->settings.stack_trace_enabled || !ctx->settings.errors_enabled || ctx->stack_trace.size <= 0) + { + return; + } + fprintf(stderr, "[stack trace] (most recent symbol first):\n"); + + for (size_t i = 0; i < ctx->stack_trace.size; i++) + { + int index = (ctx->stack_trace.start + ctx->stack_trace.size - 1 - i) % HEX_STACK_TRACE_SIZE; + hex_token_t token = ctx->stack_trace.entries[index]; + fprintf(stderr, " %s (%s:%d:%d)\n", token.value, token.position.filename, token.position.line, token.position.column); + } +}
@@ -239,7 +239,7 @@
} hex_opcode_t; // Help System -void hex_doc(hex_doc_dictionary_t *docs, const char *name, const char *description, const char *input, const char *output); +void hex_set_doc(hex_doc_dictionary_t *docs, const char *name, const char *description, const char *input, const char *output); int hex_get_doc(hex_doc_dictionary_t *docs, const char *key, hex_doc_entry_t *result); void hex_create_docs(hex_doc_dictionary_t *docs); void hex_print_help();
@@ -8,7 +8,7 @@ {
FILE *file = fopen(filename, "r"); if (file == NULL) { - hex_error(ctx, "Failed to open file: %s", filename); + hex_error(ctx, "[read input file] Failed to open file: %s", filename); return NULL; }@@ -17,7 +17,7 @@ int bufferSize = 1024; // Start with a 1 KB buffer
char *content = (char *)malloc(bufferSize); if (content == NULL) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[read input file] Memory allocation failed"); fclose(file); return NULL; }@@ -52,7 +52,7 @@ bufferSize *= 2; // Double the buffer size
char *temp = (char *)realloc(content, bufferSize); if (temp == NULL) { - hex_error(ctx, "Memory reallocation failed"); + hex_error(ctx, "[read input bytecode file] Memory reallocation failed"); free(content); fclose(file); return NULL;@@ -63,7 +63,7 @@ }
if (ferror(file)) { - hex_error(ctx, "Error reading the file"); + hex_error(ctx, "[read input file] Error reading the file"); free(content); fclose(file); return NULL;@@ -73,7 +73,7 @@ // Null-terminate the content
char *finalContent = (char *)realloc(content, bytesReadTotal + 1); if (finalContent == NULL) { - hex_error(ctx, "Final memory allocation failed"); + hex_error(ctx, "[read file] Final memory allocation failed"); free(content); fclose(file); return NULL;@@ -199,7 +199,7 @@ char buffer[8192]; // Adjust buffer size as needed
int bytesRead = fread(buffer, 1, sizeof(buffer) - 1, stdin); if (bytesRead == 0) { - hex_error(ctx, "Error: No input provided via stdin."); + hex_error(ctx, "[read stdin] No input provided via stdin."); return; }@@ -279,7 +279,7 @@ {
FILE *file = fopen(filename, "wb"); if (file == NULL) { - hex_error(ctx, "Failed to write file: %s", filename); + hex_error(ctx, "[write bytecode] Failed to write file: %s", filename); return 1; } hex_debug(ctx, "Writing bytecode to file: %s", filename);@@ -358,7 +358,7 @@ {
FILE *bytecode_file = fopen(file, "rb"); if (bytecode_file == NULL) { - hex_error(&ctx, "Failed to open bytecode file: %s", file); + hex_error(&ctx, "[open hbx file] Failed to open bytecode file: %s", file); return 1; } fseek(bytecode_file, 0, SEEK_END);@@ -367,7 +367,7 @@ fseek(bytecode_file, 0, SEEK_SET);
uint8_t *bytecode = (uint8_t *)malloc(bytecode_size); if (bytecode == NULL) { - hex_error(&ctx, "Memory allocation failed"); + hex_error(&ctx, "[read hbx file] Memory allocation failed"); fclose(bytecode_file); return 1; }@@ -399,7 +399,7 @@ strcat(bytecode_file, ".hbx");
} if (hex_bytecode(&ctx, fileContent, &bytecode, &bytecode_size, &position) != 0) { - hex_error(&ctx, "Failed to generate bytecode"); + hex_error(&ctx, "[generate bytecode] Failed to generate bytecode"); return 1; } if (hex_write_bytecode_file(&ctx, bytecode_file, bytecode, bytecode_size) != 0)
@@ -254,7 +254,7 @@
quotation = (hex_item_t **)malloc(capacity * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[parse quotation] Memory allocation failed"); return 1; }
@@ -50,7 +50,7 @@ if (strcmp(ctx->registry.entries[i].key, key) == 0)
{ if (ctx->registry.entries[i].value.type == HEX_TYPE_NATIVE_SYMBOL) { - hex_error(ctx, "Cannot overwrite native symbol '%s'", key); + hex_error(ctx, "[set symbol] Cannot overwrite native symbol '%s'", key); return 1; } free(ctx->registry.entries[i].key);
@@ -22,7 +22,7 @@ {
if (ctx->stack.top >= HEX_STACK_SIZE - 1) { - hex_error(ctx, "Stack overflow"); + hex_error(ctx, "[push] Stack overflow"); return 1; } hex_debug_item(ctx, "PUSH", item);@@ -37,7 +37,7 @@ result = HEX_PUSH(ctx, value);
} else { - hex_error(ctx, "Undefined user symbol: %s", item.token->value); + hex_error(ctx, "[push] Undefined user symbol: %s", item.token->value); HEX_FREE(ctx, value); result = 1; }@@ -68,7 +68,7 @@ {
char *str = hex_process_string(value); if (str == NULL) { - hex_error(ctx, "Failed to allocate memory for string"); + hex_error(ctx, "[create string] Failed to allocate memory for string"); return (hex_item_t){.type = HEX_TYPE_INVALID}; } hex_item_t item = {.type = HEX_TYPE_STRING, .data.str_value = str};@@ -114,7 +114,7 @@ return HEX_PUSH(ctx, value);
} else { - hex_error(ctx, "Undefined symbol: %s", token->value); + hex_error(ctx, "[push] Undefined symbol: %s", token->value); return 1; } }@@ -124,7 +124,7 @@ hex_item_t hex_pop(hex_context_t *ctx)
{ if (ctx->stack.top < 0) { - hex_error(ctx, "Insufficient items on the stack"); + hex_error(ctx, "[pop] Insufficient items on the stack"); return (hex_item_t){.type = HEX_TYPE_INVALID}; } hex_debug_item(ctx, " POP", ctx->stack.entries[ctx->stack.top]);
@@ -1,43 +0,0 @@
-#ifndef HEX_H -#include "hex.h" -#endif - -//////////////////////////////////////// -// Stack trace implementation // -//////////////////////////////////////// - -// Add an entry to the circular stack trace -void add_to_stack_trace(hex_context_t *ctx, hex_token_t *token) -{ - int index = (ctx->stack_trace.start + ctx->stack_trace.size) % HEX_STACK_TRACE_SIZE; - - if (ctx->stack_trace.size < HEX_STACK_TRACE_SIZE) - { - // Buffer is not full; add item - ctx->stack_trace.entries[index] = *token; - ctx->stack_trace.size++; - } - else - { - // Buffer is full; overwrite the oldest item - ctx->stack_trace.entries[index] = *token; - ctx->stack_trace.start = (ctx->stack_trace.start + 1) % HEX_STACK_TRACE_SIZE; - } -} - -// Print the stack trace -void print_stack_trace(hex_context_t *ctx) -{ - if (!ctx->settings.stack_trace_enabled || !ctx->settings.errors_enabled || ctx->stack_trace.size <= 0) - { - return; - } - fprintf(stderr, "[stack trace] (most recent symbol first):\n"); - - for (size_t i = 0; i < ctx->stack_trace.size; i++) - { - int index = (ctx->stack_trace.start + ctx->stack_trace.size - 1 - i) % HEX_STACK_TRACE_SIZE; - hex_token_t token = ctx->stack_trace.entries[index]; - fprintf(stderr, " %s (%s:%d:%d)\n", token.value, token.position.filename, token.position.line, token.position.column); - } -}
@@ -26,14 +26,14 @@ return 1;
} if (name.type != HEX_TYPE_STRING) { - hex_error(ctx, "Symbol name must be a string"); + hex_error(ctx, "[symbol :] Symbol name must be a string"); HEX_FREE(ctx, name); HEX_FREE(ctx, value); return 1; } if (hex_set_symbol(ctx, name.data.str_value, value, 0) != 0) { - hex_error(ctx, "Failed to store symbol '%s'", name.data.str_value); + hex_error(ctx, "[symbol :] Failed to store symbol '%s'", name.data.str_value); HEX_FREE(ctx, name); HEX_FREE(ctx, value); return 1;@@ -53,12 +53,12 @@ }
if (item.type != HEX_TYPE_STRING) { HEX_FREE(ctx, item); - hex_error(ctx, "Symbol name must be a string"); + hex_error(ctx, "[symbol #] Symbol name must be a string"); return 1; } if (hex_valid_native_symbol(ctx, item.data.str_value)) { - hex_error(ctx, "Cannot free native symbol '%s'", item.data.str_value); + hex_error(ctx, "[symbol #] Cannot free native symbol '%s'", item.data.str_value); HEX_FREE(ctx, item); return 1; }@@ -106,7 +106,7 @@ return 1;
} if (item.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "Symbol '.' requires a quotation"); + hex_error(ctx, "[symbol .] Quotation required"); HEX_FREE(ctx, item); return 1; }@@ -140,7 +140,7 @@ for (size_t i = 0; i < item.quotation_size; i++)
{ if (item.data.quotation_value[i]->type != HEX_TYPE_INTEGER) { - hex_error(ctx, "Quotation must contain only integers"); + hex_error(ctx, "[symbol !] Quotation must contain only integers"); HEX_FREE(ctx, item); return 1; }@@ -148,7 +148,7 @@ }
uint8_t *bytecode = (uint8_t *)malloc(item.quotation_size * sizeof(uint8_t)); if (!bytecode) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol !] Memory allocation failed"); HEX_FREE(ctx, item); return 1; }@@ -156,7 +156,7 @@ for (size_t i = 0; i < item.quotation_size; i++)
{ if (item.data.quotation_value[i]->type != HEX_TYPE_INTEGER) { - hex_error(ctx, "Quotation must contain only integers"); + hex_error(ctx, "[symbol !] Quotation must contain only integers"); free(bytecode); HEX_FREE(ctx, item); return 1;@@ -169,7 +169,7 @@ return result;
} else { - hex_error(ctx, "Symbol '!' requires a string or a quotation of integers"); + hex_error(ctx, "[symbol !] String or a quotation of integers required"); HEX_FREE(ctx, item); return 1; }@@ -240,7 +240,7 @@ return hex_push_string(ctx, input);
} else { - hex_error(ctx, "Failed to read input"); + hex_error(ctx, "[symbol gets] Failed to read input"); return 1; } }@@ -265,7 +265,7 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, a.data.int_value + b.data.int_value); } - hex_error(ctx, "Symbol '+' requires two integers"); + hex_error(ctx, "[symbol +] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -291,7 +291,7 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, a.data.int_value - b.data.int_value); } - hex_error(ctx, "Symbol '-' requires two integers"); + hex_error(ctx, "[symbol -] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -317,7 +317,7 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, a.data.int_value * b.data.int_value); } - hex_error(ctx, "'*' symbol requires two integers"); + hex_error(ctx, "[symbol *] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -343,12 +343,12 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ if (b.data.int_value == 0) { - hex_error(ctx, "Division by zero"); + hex_error(ctx, "[symbol /] Division by zero"); return 1; } return hex_push_integer(ctx, a.data.int_value / b.data.int_value); } - hex_error(ctx, "Symbol '/' requires two integers"); + hex_error(ctx, "[symbol /] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -374,12 +374,12 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ if (b.data.int_value == 0) { - hex_error(ctx, "Division by zero"); + hex_error(ctx, "[symbol %%] Division by zero"); return 1; } return hex_push_integer(ctx, a.data.int_value % b.data.int_value); } - hex_error(ctx, "Symbol '%%' requires two integers"); + hex_error(ctx, "[symbol %%] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -407,7 +407,7 @@ if (left.type == HEX_TYPE_INTEGER && right.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, left.data.int_value & right.data.int_value); } - hex_error(ctx, "Symbol '&' requires two integers"); + hex_error(ctx, "[symbol &] Two integers required"); HEX_FREE(ctx, left); HEX_FREE(ctx, right); return 1;@@ -433,7 +433,7 @@ if (left.type == HEX_TYPE_INTEGER && right.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, left.data.int_value | right.data.int_value); } - hex_error(ctx, "Symbol '|' requires two integers"); + hex_error(ctx, "[symbol |] Two integers required"); HEX_FREE(ctx, left); HEX_FREE(ctx, right); return 1;@@ -459,7 +459,7 @@ if (left.type == HEX_TYPE_INTEGER && right.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, left.data.int_value ^ right.data.int_value); } - hex_error(ctx, "Symbol '^' requires two integers"); + hex_error(ctx, "[symbol ^] Two integers required"); HEX_FREE(ctx, left); HEX_FREE(ctx, right); return 1;@@ -485,7 +485,7 @@ if (left.type == HEX_TYPE_INTEGER && right.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, left.data.int_value << right.data.int_value); } - hex_error(ctx, "Symbol '<<' requires two integers"); + hex_error(ctx, "[symbol <<] Two integers required"); HEX_FREE(ctx, left); HEX_FREE(ctx, right); return 1;@@ -511,7 +511,7 @@ if (left.type == HEX_TYPE_INTEGER && right.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, left.data.int_value >> right.data.int_value); } - hex_error(ctx, "Symbol '>>' requires two integers"); + hex_error(ctx, "[symbol >>] Two integers required"); HEX_FREE(ctx, left); HEX_FREE(ctx, right); return 1;@@ -530,7 +530,7 @@ if (item.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, ~item.data.int_value); } - hex_error(ctx, "Symbol '~' requires an integer"); + hex_error(ctx, "[symbol ~] Integer required"); HEX_FREE(ctx, item); return 1; }@@ -550,7 +550,7 @@ if (a.type == HEX_TYPE_STRING)
{ return hex_push_integer(ctx, strtol(a.data.str_value, NULL, 16)); } - hex_error(ctx, "Symbol 'int' requires a string"); + hex_error(ctx, "[symbol int] String representing a hexadecimal integer required"); HEX_FREE(ctx, a); return 1; }@@ -568,7 +568,7 @@ if (a.type == HEX_TYPE_INTEGER)
{ return hex_push_string(ctx, hex_itoa_hex(a.data.int_value)); } - hex_error(ctx, "Symbol 'str' requires an integer"); + hex_error(ctx, "[symbol str] Integer required"); HEX_FREE(ctx, a); return 1; }@@ -587,7 +587,7 @@ char buffer[32];
snprintf(buffer, sizeof(buffer), "%d", a.data.int_value); return hex_push_string(ctx, buffer); } - hex_error(ctx, "Symbol 'dec' requires an integer"); + hex_error(ctx, "[symbol dec] Integer required"); HEX_FREE(ctx, a); return 1; }@@ -605,7 +605,7 @@ if (item.type == HEX_TYPE_STRING)
{ return hex_push_integer(ctx, strtol(item.data.str_value, NULL, 10)); } - hex_error(ctx, "Symbol 'hex' requires a string representing a decimal integer"); + hex_error(ctx, "[symbol hex] String representing a decimal integer required"); HEX_FREE(ctx, item); return 1; }@@ -634,7 +634,7 @@ {
return hex_push_integer(ctx, -1); } } - hex_error(ctx, "Symbol 'ord' requires a string"); + hex_error(ctx, "[symbol ord] String required"); HEX_FREE(ctx, item); return 1; }@@ -659,7 +659,7 @@ {
return hex_push_string(ctx, ""); } } - hex_error(ctx, "Symbol 'chr' requires an integer"); + hex_error(ctx, "[symbol chr] Integer required"); HEX_FREE(ctx, item); return 1; }@@ -788,7 +788,7 @@ return is_greater;
} else { - hex_error(ctx, "'%s' symbol requires two integers, two strings, or two quotations", symbol); + hex_error(ctx, "[symbol %s] Two integers, two strings, or two quotations required", symbol); return -1; } }@@ -951,7 +951,7 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, a.data.int_value && b.data.int_value); } - hex_error(ctx, "Symbol 'and' requires two integers"); + hex_error(ctx, "[symbol and] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -977,7 +977,7 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, a.data.int_value || b.data.int_value); } - hex_error(ctx, "Symbol 'or' requires two integers"); + hex_error(ctx, "[symbol or] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -996,7 +996,7 @@ if (a.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, !a.data.int_value); } - hex_error(ctx, "Symbol 'not' requires an integer"); + hex_error(ctx, "[symbol not] Integer required"); HEX_FREE(ctx, a); return 1; }@@ -1021,7 +1021,7 @@ if (a.type == HEX_TYPE_INTEGER && b.type == HEX_TYPE_INTEGER)
{ return hex_push_integer(ctx, a.data.int_value ^ b.data.int_value); } - hex_error(ctx, "Symbol 'xor' requires two integers"); + hex_error(ctx, "[symbol xor] Two integers required"); HEX_FREE(ctx, a); HEX_FREE(ctx, b); return 1;@@ -1057,7 +1057,7 @@ hex_item_t **newQuotation = (hex_item_t **)realloc(
list.data.quotation_value, newSize * sizeof(hex_item_t *)); if (!newQuotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol cat] Memory allocation failed"); result = 1; } else@@ -1080,7 +1080,7 @@ size_t newLength = strlen(list.data.str_value) + strlen(value.data.str_value) + 1;
char *newStr = (char *)malloc(newLength); if (!newStr) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol cat] Memory allocation failed"); result = 1; } else@@ -1092,7 +1092,7 @@ }
} else { - hex_error(ctx, "Symbol 'cat' requires two quotations or two strings"); + hex_error(ctx, "[symbol cat] Two quotations or two strings required"); result = 1; }@@ -1126,7 +1126,7 @@ result = hex_push_integer(ctx, strlen(item.data.str_value));
} else { - hex_error(ctx, "Symbol 'len' requires a quotation or a string"); + hex_error(ctx, "[symbol len] Quotation or string required"); result = 1; } if (result != 0)@@ -1157,12 +1157,12 @@ if (list.type == HEX_TYPE_QUOTATION)
{ if (index.type != HEX_TYPE_INTEGER) { - hex_error(ctx, "Index must be an integer"); + hex_error(ctx, "[symbol get] Index must be an integer"); result = 1; } else if (index.data.int_value < 0 || (size_t)index.data.int_value >= list.quotation_size) { - hex_error(ctx, "Index out of range"); + hex_error(ctx, "[symbol get] Index out of range"); result = 1; } else@@ -1174,12 +1174,12 @@ else if (list.type == HEX_TYPE_STRING)
{ if (index.type != HEX_TYPE_INTEGER) { - hex_error(ctx, "Index must be an integer"); + hex_error(ctx, "[symbol get] Index must be an integer"); result = 1; } else if (index.data.int_value < 0 || index.data.int_value >= (int)strlen(list.data.str_value)) { - hex_error(ctx, "Index out of range"); + hex_error(ctx, "[symbol get] Index out of range"); result = 1; } else@@ -1190,7 +1190,7 @@ }
} else { - hex_error(ctx, "Symbol 'get' requires a quotation or a string"); + hex_error(ctx, "[symbol get] Quotation or string required"); result = 1; } if (result != 0)@@ -1240,7 +1240,7 @@ }
} else { - hex_error(ctx, "Symbol 'index' requires a quotation or a string"); + hex_error(ctx, "[symbol index] Quotation or string required"); HEX_FREE(ctx, list); HEX_FREE(ctx, item); return 1;@@ -1278,7 +1278,7 @@ length += strlen(list.data.quotation_value[i]->data.str_value);
} else { - hex_error(ctx, "Quotation must contain only strings"); + hex_error(ctx, "[symbol join] Quotation must contain only strings"); HEX_FREE(ctx, list); HEX_FREE(ctx, separator); return 1;@@ -1290,7 +1290,7 @@ length += (list.quotation_size - 1) * strlen(separator.data.str_value);
char *newStr = (char *)malloc(length + 1); if (!newStr) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol join] Memory allocation failed"); HEX_FREE(ctx, list); HEX_FREE(ctx, separator); return 1;@@ -1309,7 +1309,7 @@ }
} else { - hex_error(ctx, "Symbol 'join' requires a quotation and a string"); + hex_error(ctx, "[symbol join] Quotation and string required"); result = 1; } if (result != 0)@@ -1345,7 +1345,7 @@ size_t size = strlen(str.data.str_value);
hex_item_t **quotation = (hex_item_t **)malloc(size * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol split] Memory allocation failed"); result = 1; } else@@ -1355,7 +1355,7 @@ {
quotation[i] = (hex_item_t *)malloc(sizeof(hex_item_t)); if (!quotation[i]) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol split] Memory allocation failed"); result = 1; break; }@@ -1363,7 +1363,7 @@ quotation[i]->type = HEX_TYPE_STRING;
quotation[i]->data.str_value = (char *)malloc(2); // Allocate 2 bytes: 1 for the character and 1 for null terminator if (!quotation[i]->data.str_value) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol split] Memory allocation failed"); result = 1; break; }@@ -1385,7 +1385,7 @@ size_t size = 0;
hex_item_t **quotation = (hex_item_t **)malloc(capacity * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol split] Memory allocation failed"); result = 1; } else@@ -1398,7 +1398,7 @@ capacity *= 2;
quotation = (hex_item_t **)realloc(quotation, capacity * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol split] Memory allocation failed"); result = 1; break; }@@ -1418,7 +1418,7 @@ }
} else { - hex_error(ctx, "Symbol 'split' requires two strings"); + hex_error(ctx, "[symbol split] Two strings required"); result = 1; } if (result != 0)@@ -1468,7 +1468,7 @@ int newLen = strlen(str) - findLen + replaceLen + 1;
char *newStr = (char *)malloc(newLen); if (!newStr) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol replace] Memory allocation failed"); result = 1; } else@@ -1486,7 +1486,7 @@ }
} else { - hex_error(ctx, "Symbol 'replace' requires three strings"); + hex_error(ctx, "[symbol replace] Three strings required"); result = 1; } if (result != 0)@@ -1514,7 +1514,7 @@ {
FILE *file = fopen(filename.data.str_value, "rb"); if (!file) { - hex_error(ctx, "Could not open file for reading: %s", filename.data.str_value); + hex_error(ctx, "[symbol read] Could not open file for reading: %s", filename.data.str_value); result = 1; } else@@ -1526,7 +1526,7 @@
uint8_t *buffer = (uint8_t *)malloc(length); if (!buffer) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol read] Memory allocation failed"); result = 1; } else@@ -1537,7 +1537,7 @@ {
hex_item_t **quotation = (hex_item_t **)malloc(bytesRead * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol read] Memory allocation failed"); result = 1; } else@@ -1556,12 +1556,12 @@ {
char *str = hex_bytes_to_string(buffer, bytesRead); if (!str) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol read] Memory allocation failed"); result = 1; } else { - hex_item_t item = {.type = HEX_TYPE_STRING, .data.str_value = str}; + hex_item_t item = {.type = HEX_TYPE_STRING, .data.str_value = str}; result = HEX_PUSH(ctx, item); } }@@ -1572,7 +1572,7 @@ }
} else { - hex_error(ctx, "Symbol 'read' requires a string"); + hex_error(ctx, "[symbol read] String required"); result = 1; } if (result != 0)@@ -1612,7 +1612,7 @@ result = 0;
} else { - hex_error(ctx, "Could not open file for writing: %s", filename.data.str_value); + hex_error(ctx, "[symbol write] Could not open file for writing: %s", filename.data.str_value); result = 1; } }@@ -1625,7 +1625,7 @@ for (size_t i = 0; i < data.quotation_size; i++)
{ if (data.data.quotation_value[i]->type != HEX_TYPE_INTEGER) { - hex_error(ctx, "Quotation must contain only integers"); + hex_error(ctx, "[symbol write] Quotation must contain only integers"); result = 1; break; }@@ -1637,19 +1637,19 @@ result = 0;
} else { - hex_error(ctx, "Could not open file for writing: %s", filename.data.str_value); + hex_error(ctx, "[symbol write] Could not open file for writing: %s", filename.data.str_value); result = 1; } } else { - hex_error(ctx, "Symbol 'write' requires a string or a quotation of integers"); + hex_error(ctx, "[symbol write] String or quotation of integers required"); result = 1; } } else { - hex_error(ctx, "Symbol 'write' requires a string"); + hex_error(ctx, "[symbol write] String required"); result = 1; } if (result != 0)@@ -1690,7 +1690,7 @@ result = 0;
} else { - hex_error(ctx, "Could not open file for appending: %s", filename.data.str_value); + hex_error(ctx, "[symbol append] Could not open file for appending: %s", filename.data.str_value); result = 1; } }@@ -1703,7 +1703,7 @@ for (size_t i = 0; i < data.quotation_size; i++)
{ if (data.data.quotation_value[i]->type != HEX_TYPE_INTEGER) { - hex_error(ctx, "Quotation must contain only integers"); + hex_error(ctx, "[symbol append] Quotation must contain only integers"); result = 1; break; }@@ -1715,19 +1715,19 @@ result = 0;
} else { - hex_error(ctx, "Could not open file for appending: %s", filename.data.str_value); + hex_error(ctx, "[symbol append] Could not open file for appending: %s", filename.data.str_value); result = 1; } } else { - hex_error(ctx, "Symbol 'append' requires a string or a quotation of integers"); + hex_error(ctx, "[symbol append] String or quotation of integers required"); result = 1; } } else { - hex_error(ctx, "Symbol 'append' requires a string"); + hex_error(ctx, "[symbol append] String required"); result = 1; } if (result != 0)@@ -1746,7 +1746,7 @@
hex_item_t **quotation = (hex_item_t **)malloc(ctx->argc * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol args] Memory allocation failed"); return 1; } else@@ -1777,7 +1777,7 @@ return 1;
} if (item.type != HEX_TYPE_INTEGER) { - hex_error(ctx, "Exit status must be an integer"); + hex_error(ctx, "[symbol exit] Integer required"); HEX_FREE(ctx, item); return 1; }@@ -1803,7 +1803,7 @@ result = hex_push_integer(ctx, status);
} else { - hex_error(ctx, "Symbol 'exec' requires a string"); + hex_error(ctx, "[symbol exec] String required"); result = 1; } if (result != 0)@@ -1824,7 +1824,7 @@ return 1;
} if (command.type != HEX_TYPE_STRING) { - hex_error(ctx, "Symbol 'run' requires a string"); + hex_error(ctx, "[symbol run] String required"); HEX_FREE(ctx, command); return 1; }@@ -1849,7 +1849,7 @@
// Create pipes for capturing stdout and stderr if (!CreatePipe(&hOutputRead, &hOutputWrite, &sa, 0) || !CreatePipe(&hErrorRead, &hErrorWrite, &sa, 0)) { - hex_error(ctx, "Failed to create pipes"); + hex_error(ctx, "[symbol run] Failed to create pipes"); HEX_FREE(ctx, command); return 1; }@@ -1864,7 +1864,7 @@
// Create the child process if (!CreateProcess(NULL, command.data.str_value, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { - hex_error(ctx, "Failed to create process"); + hex_error(ctx, "[symbol run] Failed to create process"); HEX_FREE(ctx, command); return 1; }@@ -1905,7 +1905,7 @@ int stdout_pipe[2];
int stderr_pipe[2]; if (pipe(stdout_pipe) != 0 || pipe(stderr_pipe) != 0) { - hex_error(ctx, "Failed to create pipes"); + hex_error(ctx, "[symbol run] Failed to create pipes"); HEX_FREE(ctx, command); return 1; }@@ -1913,7 +1913,7 @@
pid_t pid = fork(); if (pid == -1) { - hex_error(ctx, "Failed to fork process"); + hex_error(ctx, "[symbol run] Failed to fork process"); HEX_FREE(ctx, command); return 1; }@@ -2002,7 +2002,7 @@ return 1;
} if (condition.type != HEX_TYPE_QUOTATION || thenBlock.type != HEX_TYPE_QUOTATION || elseBlock.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "'if' symbol requires three quotations"); + hex_error(ctx, "[symbol if] Three quotations required"); return 1; } else@@ -2067,7 +2067,7 @@ }
int result = 0; if (condition.type != HEX_TYPE_QUOTATION || action.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "'when' symbol requires two quotations"); + hex_error(ctx, "[symbol when] Two quotations required"); result = 1; } else@@ -2119,7 +2119,7 @@ return 1;
} if (condition.type != HEX_TYPE_QUOTATION || action.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "'while' symbol requires two quotations"); + hex_error(ctx, "[symbol while] Two quotations required"); HEX_FREE(ctx, action); HEX_FREE(ctx, condition); return 1;@@ -2174,7 +2174,7 @@ return 1;
} if (list.type != HEX_TYPE_QUOTATION || action.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "'each' symbol requires two quotations"); + hex_error(ctx, "[symbol each] Two quotations required"); HEX_FREE(ctx, action); HEX_FREE(ctx, list); return 1;@@ -2229,7 +2229,7 @@ return 1;
} if (try_block.type != HEX_TYPE_QUOTATION || catch_block.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "'try' symbol requires two quotations"); + hex_error(ctx, "[symbol try] Two quotations required"); HEX_FREE(ctx, catch_block); HEX_FREE(ctx, try_block); return 1;@@ -2283,7 +2283,7 @@
hex_item_t *quotation = (hex_item_t *)malloc(sizeof(hex_item_t)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol '] Memory allocation failed"); HEX_FREE(ctx, item); return 1; }@@ -2297,7 +2297,7 @@ if (!result.data.quotation_value)
{ HEX_FREE(ctx, item); free(quotation); - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol '] Memory allocation failed"); return 1; }@@ -2333,7 +2333,7 @@ return 1;
} if (list.type != HEX_TYPE_QUOTATION || action.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "'map' symbol requires two quotations"); + hex_error(ctx, "[symbol map] Two quotations required"); HEX_FREE(ctx, action); HEX_FREE(ctx, list); return 1;@@ -2343,7 +2343,7 @@ {
hex_item_t **quotation = (hex_item_t **)malloc(list.quotation_size * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol map] Memory allocation failed"); HEX_FREE(ctx, action); HEX_FREE(ctx, list); return 1;@@ -2399,7 +2399,7 @@ return 1;
} if (list.type != HEX_TYPE_QUOTATION || action.type != HEX_TYPE_QUOTATION) { - hex_error(ctx, "'filter' symbol requires two quotations"); + hex_error(ctx, "[symbol filter] Two quotations required"); HEX_FREE(ctx, action); HEX_FREE(ctx, list); return 1;@@ -2409,7 +2409,7 @@ {
hex_item_t **quotation = (hex_item_t **)malloc(list.quotation_size * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol filter] Memory allocation failed"); HEX_FREE(ctx, action); HEX_FREE(ctx, list); return 1;@@ -2440,7 +2440,7 @@ {
quotation[count] = (hex_item_t *)malloc(sizeof(hex_item_t)); if (!quotation[count]) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol filter] Memory allocation failed"); HEX_FREE(ctx, action); HEX_FREE(ctx, list); hex_free_list(ctx, quotation, count);@@ -2452,7 +2452,7 @@ }
} if (hex_push_quotation(ctx, quotation, count) != 0) { - hex_error(ctx, "An error occurred while filtering the list"); + hex_error(ctx, "[symbol filter] An error occurred while pushing quotation"); HEX_FREE(ctx, action); HEX_FREE(ctx, list); for (size_t i = 0; i < count; i++)@@ -2521,7 +2521,7 @@
hex_item_t **quotation = (hex_item_t **)malloc((ctx->stack.top + 1) * sizeof(hex_item_t *)); if (!quotation) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol stack] Memory allocation failed"); return 1; } int count = 0;@@ -2530,7 +2530,7 @@ {
quotation[i] = (hex_item_t *)malloc(sizeof(hex_item_t)); if (!quotation[i]) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[symbol stack] Memory allocation failed"); hex_free_list(ctx, quotation, count); return 1; }@@ -2540,7 +2540,7 @@ }
if (hex_push_quotation(ctx, quotation, ctx->stack.top + 1) != 0) { - hex_error(ctx, "An error occurred while fetching stack contents"); + hex_error(ctx, "[symbol stack] An error occurred while pushing quotation"); hex_free_list(ctx, quotation, count); return 1; }
@@ -2,41 +2,34 @@ #ifndef HEX_H
#include "hex.h" #endif -// Add a symbol to the table if it does not already exist -// Returns 0 on success, -1 if the symbol is too long or table is full int hex_symboltable_set(hex_context_t *ctx, const char *symbol) { hex_symbol_table_t *table = &ctx->symbol_table; size_t len = strlen(symbol); - // Check symbol length if (len > HEX_MAX_SYMBOL_LENGTH) { - return -1; // Symbol too long + return -1; } - // Check if table is full if (table->count >= HEX_MAX_USER_SYMBOLS) { return -1; // Table full } - // Check if symbol already exists for (uint16_t i = 0; i < table->count; ++i) { if (strcmp(table->symbols[i], symbol) == 0) { - return 0; // Symbol already exists, no-op + return 0; } } - // Add the symbol table->symbols[table->count] = strdup(symbol); table->count++; return 0; } -// Get the index of a symbol in the table, or -1 if not found int hex_symboltable_get_index(hex_context_t *ctx, const char *symbol) { hex_symbol_table_t *table = &ctx->symbol_table;@@ -47,10 +40,9 @@ {
return i; } } - return -1; // Symbol not found + return -1; } -// Get a symbol from the table by index char *hex_symboltable_get_value(hex_context_t *ctx, uint16_t index) { if (index >= ctx->symbol_table.count)@@ -60,8 +52,6 @@ }
return ctx->symbol_table.symbols[index]; } -// Decode a bytecode's symbol table into the hex_symbol_table_t structure -// Assumes input is well-formed int hex_decode_bytecode_symboltable(hex_context_t *ctx, uint8_t **bytecode, size_t *size, size_t total) { hex_symbol_table_t *table = &ctx->symbol_table;@@ -77,7 +67,7 @@
char *symbol = malloc(len + 1); if (symbol == NULL) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[decode symbol table] Memory allocation failed"); // Handle memory allocation failure return -1; }@@ -91,14 +81,11 @@ }
return 0; } -// Encode the symbol table into a bytecode representation -// Returns bytecode buffer and sets out_size to the bytecode length uint8_t *hex_encode_bytecode_symboltable(hex_context_t *ctx, size_t *out_size) { hex_symbol_table_t *table = &ctx->symbol_table; size_t total_size = 0; - // Calculate total size for (uint16_t i = 0; i < table->count; ++i) { total_size += 1 + strlen(table->symbols[i]);
@@ -16,7 +16,7 @@ *capacity = (*size + sizeof(int32_t) + 1 + 4 + *capacity) * 2;
uint8_t *new_bytecode = (uint8_t *)realloc(*bytecode, *capacity); if (!new_bytecode) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[add bytecode integer] Memory allocation failed"); return 1; } *bytecode = new_bytecode;@@ -77,7 +77,7 @@ {
char *str = hex_process_string(value); if (!str) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[add bytecode string] Memory allocation failed"); return 1; } hex_debug(ctx, "PUSHST: \"%s\"", str);@@ -89,7 +89,7 @@ *capacity = (*size + len + 1 + 4 + *capacity) * 2;
uint8_t *new_bytecode = (uint8_t *)realloc(*bytecode, *capacity); if (!new_bytecode) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[add bytecode string] Memory allocation failed"); return 1; } *bytecode = new_bytecode;@@ -114,7 +114,7 @@ *capacity = (*size + 1 + *capacity) * 2;
uint8_t *new_bytecode = (uint8_t *)realloc(*bytecode, *capacity); if (!new_bytecode) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[add bytecode native symbol] Memory allocation failed"); return 1; } *bytecode = new_bytecode;@@ -135,7 +135,7 @@ *capacity = (*size + 1 + 2) * 2;
uint8_t *new_bytecode = (uint8_t *)realloc(*bytecode, *capacity); if (!new_bytecode) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[add bytecode user symbol] Memory allocation failed"); return 1; } *bytecode = new_bytecode;@@ -181,7 +181,7 @@ size_t size = 0;
uint8_t *bytecode = (uint8_t *)malloc(capacity); if (!bytecode) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[generate bytecode] Memory allocation failed"); return 1; } hex_debug(ctx, "Generating bytecode");@@ -208,7 +208,7 @@ size_t quotation_size = 0;
hex_debug(ctx, "PUSHQT: <start>"); if (hex_generate_quotation_bytecode(ctx, &input, "ation_bytecode, "ation_size, &n_items, position) != 0) { - hex_error(ctx, "Failed to generate quotation bytecode (main)"); + hex_error(ctx, "[generate quotation bytecode] Failed to generate quotation bytecode (main)"); return 1; } hex_bytecode_quotation(ctx, &bytecode, &size, &capacity, "ation_bytecode, "ation_size, &n_items);@@ -238,7 +238,7 @@ int balanced = 1;
uint8_t *bytecode = (uint8_t *)malloc(capacity); if (!bytecode) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[generate quotation bytecode] Memory allocation failed"); return 1; } *n_items = 0;@@ -266,7 +266,7 @@ size_t quotation_size = 0;
hex_debug(ctx, "PUSHQT: <start>"); if (hex_generate_quotation_bytecode(ctx, input, "ation_bytecode, "ation_size, &n_items, position) != 0) { - hex_error(ctx, "Failed to generate quotation bytecode"); + hex_error(ctx, "[generate quotation bytecode] Failed to generate quotation bytecode"); return 1; } hex_bytecode_quotation(ctx, &bytecode, &size, &capacity, "ation_bytecode, "ation_size, &n_items);@@ -305,7 +305,7 @@ do
{ if (*size == 0) { - hex_error(ctx, "Bytecode size too small to contain an integer length"); + hex_error(ctx, "[interpret bytecode integer] Bytecode size too small to contain an integer length"); return 1; } length |= ((**bytecode & 0x7F) << shift);@@ -316,7 +316,7 @@ *size -= shift / 7;
if (*size < length) { - hex_error(ctx, "Bytecode size too small to contain the integer value"); + hex_error(ctx, "[interpret bytecode integer] Bytecode size too small to contain the integer value"); return 1; }@@ -356,7 +356,7 @@ do
{ if (*size == 0) { - hex_error(ctx, "Bytecode size too small to contain a string length"); + hex_error(ctx, "[interpret bytecode string] Bytecode size too small to contain a string length"); return 1; } length |= ((**bytecode & 0x7F) << shift);@@ -367,14 +367,14 @@ } while (**bytecode & 0x80);
if (*size < length) { - hex_error(ctx, "Bytecode size too small to contain the string"); + hex_error(ctx, "[interpret bytecode string] Bytecode size too small to contain the string"); return 1; } char *value = (char *)malloc(length + 1); if (!value) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[interpret bytecode string] Memory allocation failed"); return 1; } memcpy(value, *bytecode, length);@@ -387,7 +387,7 @@ *result = item;
char *str = hex_process_string(value); if (!str) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[interpret bytecode string] Memory allocation failed"); return 1; } hex_debug(ctx, ">> PUSHST: \"%s\"", str);@@ -400,7 +400,7 @@
const char *symbol = hex_opcode_to_symbol(opcode); if (!symbol) { - hex_error(ctx, "Invalid opcode for symbol"); + hex_error(ctx, "[interpret bytecode nattive symbol] Invalid opcode for symbol"); return 1; }@@ -433,7 +433,7 @@ {
// Get the index of the symbol (one byte) if (*size == 0) { - hex_error(ctx, "Bytecode size too small to contain a symbol length"); + hex_error(ctx, "[interpret bytecode user symbol] Bytecode size too small to contain a symbol length"); return 1; } size_t index = **bytecode;@@ -442,7 +442,7 @@ (*size)--;
if (index >= ctx->symbol_table.count) { - hex_error(ctx, "Symbol index out of bounds"); + hex_error(ctx, "[interpret bytecode user symbol] Symbol index out of bounds"); return 1; } char *value = hex_symboltable_get_value(ctx, index);@@ -450,7 +450,7 @@ size_t length = strlen(value);
if (!value) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[interpret bytecode user symbol] Memory allocation failed"); return 1; }@@ -483,7 +483,7 @@ do
{ if (*size == 0) { - hex_error(ctx, "Bytecode size too small to contain a quotation length"); + hex_error(ctx, "[interpret bytecode quotation] Bytecode size too small to contain a quotation length"); return 1; } n_items |= ((**bytecode & 0x7F) << shift);@@ -497,7 +497,7 @@
hex_item_t **items = (hex_item_t **)malloc(n_items * sizeof(hex_item_t)); if (!items) { - hex_error(ctx, "Memory allocation failed"); + hex_error(ctx, "[interpret bytecode quotation] Memory allocation failed"); return 1; }@@ -564,7 +564,7 @@ size_t position = bytecode_size;
uint8_t header[8]; if (size < 8) { - hex_error(ctx, "Bytecode size too small to contain a header"); + hex_error(ctx, "[interpret bytecode header] Bytecode size too small to contain a header"); return 1; } memcpy(header, bytecode, 8);@@ -572,7 +572,7 @@ int symbol_table_size = hex_validate_header(header);
hex_debug(ctx, "hex executable file - version: %d - symbols: %d", header[4], symbol_table_size); if (symbol_table_size < 0) { - hex_error(ctx, "Invalid bytecode header"); + hex_error(ctx, "[interpret bytecode header] Invalid bytecode header"); return 1; } bytecode += 8;@@ -582,7 +582,7 @@ if (symbol_table_size > 0)
{ if (hex_decode_bytecode_symboltable(ctx, &bytecode, &size, symbol_table_size) != 0) { - hex_error(ctx, "Failed to decode the symbol table"); + hex_error(ctx, "[interpret bytecode symbol table] Failed to decode the symbol table"); return 1; } }