Compare commits
	
		
			197 Commits
		
	
	
		
			933418895e
			...
			v1.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 24f93ce750 | |||
| 2fc3f1e1df | |||
| 9525535323 | |||
| 0fa1c176f4 | |||
| 868dcb6788 | |||
| 4fb698918c | |||
| df74d29e54 | |||
| 7181b31d4b | |||
| 7630e4b99f | |||
| 74d5a212cd | |||
| 90fce2fce4 | |||
| 94689be83b | |||
| cb5fa27eb3 | |||
| 7c08e8da4d | |||
| fdf526750d | |||
| 4e5b12b5b2 | |||
| b102a32999 | |||
| 518f2e9803 | |||
| 0e6bb7aa16 | |||
| 14ddf51f3c | |||
| ac1d76361f | |||
| b789193484 | |||
| ab97f78fab | |||
| 7c0b212ab4 | |||
| 80c8038374 | |||
| e3cd78e1b4 | |||
| b7b90f528b | |||
| 0ef44be808 | |||
| 8924818ec4 | |||
| 73efa7e136 | |||
| 4e8d7131d6 | |||
| bfce18ab81 | |||
| 7b648c4bd7 | |||
| 4ec5d1c075 | |||
| 5ba070ced7 | |||
| 8256643c0b | |||
| 29a217928e | |||
| 482f2b4877 | |||
| 36fd838a8f | |||
| 289243de38 | |||
| 67aafb3ead | |||
| 3b5bee0695 | |||
| 970fc39198 | |||
| 8d3e43d7dc | |||
| d4293e87f3 | |||
| abb8ff6b58 | |||
| 80122b6572 | |||
| a4afd3b58a | |||
| 90c8c91410 | |||
| f5ab0e9cb0 | |||
| 0fb1f1d55f | |||
| 1d83aa65a4 | |||
| 3f30662cde | |||
| 743d16f696 | |||
| 7b99292547 | |||
| 4a516d8edb | |||
| 5b0950cabb | |||
| 40051de9ae | |||
| 2d01b09ee9 | |||
| ff68b756ef | |||
| c2f2658e9c | |||
| 3e80f6430d | |||
| 5b50d423fa | |||
| a04d318e45 | |||
| 7258f162c9 | |||
| 6e05f1334a | |||
| 4e66f7875a | |||
| 845a7f87b2 | |||
| 5b163b26dd | |||
| f8ee7cc66e | |||
| d699f492fa | |||
| 018404eea1 | |||
| 18c61d86dc | |||
| eaf65697de | |||
| ce6e558761 | |||
| db6e591d77 | |||
| 58554e8727 | |||
| 4b9f269938 | |||
| 3d0f534017 | |||
| 38c6a9113c | |||
| 109bcb3fa5 | |||
| 79b60e4853 | |||
| 8cab531129 | |||
| eb3fbca030 | |||
| 40b91b96bd | |||
| 67f659e263 | |||
| b8ce193299 | |||
| 11401e75a7 | |||
| a6be116a2d | |||
| 3678940537 | |||
| cddf5eed76 | |||
| c685d6e55f | |||
| 6cbc28e092 | |||
| 408a5a46c0 | |||
| 6903aeb383 | |||
| fbabf71d64 | |||
| 78e31c3e27 | |||
| be3baee74e | |||
| d5a07fae56 | |||
| 4153903443 | |||
| 77d58bd69e | |||
| 47a3143752 | |||
| 4fb73b3c6f | |||
| e5c58d5fc5 | |||
| 5d81054cf6 | |||
| 66c518fe43 | |||
| 5ecdf2d89a | |||
| a5a86dc080 | |||
| 70393ef9ae | |||
| efac7f7747 | |||
| 3fcffc81ad | |||
| 27e61471a8 | |||
| c94d7863a7 | |||
| 4dd1f2b5f1 | |||
| 1a2249a0da | |||
| 8b01407374 | |||
| 3ab2696705 | |||
| 0293c925d2 | |||
| 16d62f280f | |||
| 0dbeff7077 | |||
| 96038f4baa | |||
| 6d7ff5d43f | |||
| 868ee84aeb | |||
| 694eb43eab | |||
| 694d40124f | |||
| 39778ce08d | |||
| cfd44621d5 | |||
| 4be71317b0 | |||
| 49642553e1 | |||
| 1e11b5921d | |||
| 7343c3b9d9 | |||
| 9e8410d4cf | |||
| bc0c4f33ad | |||
| 1098fa252f | |||
| 0b1905429c | |||
| e7d3ea3697 | |||
| 577bde6e57 | |||
| 60b9ed9eb2 | |||
| d13bf883b5 | |||
| 681e005a68 | |||
| 2ce89fb39a | |||
| 907bc26264 | |||
| e243e862ae | |||
| 5e930b9847 | |||
| ed3ec885c0 | |||
| 835bcfe121 | |||
| 9432496875 | |||
| 0731e40e6a | |||
| 35322de3ac | |||
| c3d8d6f8e5 | |||
| 1f2bca5028 | |||
| 9a9e5cd3e0 | |||
| 4d828500af | |||
| deac5ca5b8 | |||
| e05ebeef2a | |||
| bdca40bae4 | |||
| b4cd46a1e7 | |||
| a57acc1176 | |||
| ffcf2fb013 | |||
| c7a9c8215c | |||
| ca4cf2cd68 | |||
| e19fc8820a | |||
| ee3f2919c6 | |||
| 653736622f | |||
| e3afe52ab7 | |||
| 905acacd07 | |||
| 8763fa35dd | |||
| feae5d560a | |||
| ec268f6047 | |||
| 6fff5e5cc8 | |||
| 7b19e553f2 | |||
| 64ef797727 | |||
| 85e17ede84 | |||
| 8e5b39a6e4 | |||
| 4514d94be9 | |||
| 4080d1a80a | |||
| a36ae22d52 | |||
| ad8ac61b98 | |||
| e5bb4dfd96 | |||
| 363188d7d6 | |||
| 139d6fcb22 | |||
| 92d9da14c2 | |||
| b43fd46260 | |||
| a6dc46149c | |||
| 120038ea8f | |||
| 8cf09e43c9 | |||
| ecc12f6f3b | |||
| a1f210fee1 | |||
| 2662f54c51 | |||
| 950c25bace | |||
| 1c0dd7aa0b | |||
| 5b345e6bf5 | |||
| 891d8bf7ef | |||
| 68fc644ea6 | |||
| ca9d2aabe4 | |||
| 7a04ccfd9f | |||
| 4df9808859 | 
| @@ -1,12 +1,13 @@ | |||||||
| --- | --- | ||||||
| BasedOnStyle: LLVM |  | ||||||
| AlignConsecutiveShortCaseStatements: | AlignConsecutiveShortCaseStatements: | ||||||
|   Enabled: true |   Enabled: true | ||||||
|   AcrossEmptyLines: true |   AcrossEmptyLines: true | ||||||
|   AcrossComments: true |   AcrossComments: true | ||||||
|  | IndentCaseLabels: true | ||||||
| AllowShortBlocksOnASingleLine: Always | AllowShortBlocksOnASingleLine: Always | ||||||
| AllowShortCaseLabelsOnASingleLine: true | AllowShortCaseLabelsOnASingleLine: true | ||||||
| AllowShortIfStatementsOnASingleLine: AllIfsAndElse | AllowShortIfStatementsOnASingleLine: AllIfsAndElse | ||||||
| AllowShortLoopsOnASingleLine: true | AllowShortLoopsOnASingleLine: true | ||||||
| IndentWidth: 4 | IndentWidth: 4 | ||||||
| PointerAlignment: Left | PointerAlignment: Left | ||||||
|  | AlignAfterOpenBracket: BlockIndent | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,4 +3,6 @@ | |||||||
| tags | tags | ||||||
| *.out | *.out | ||||||
| .cache | .cache | ||||||
|  | build/* | ||||||
|  | vgcore.* | ||||||
| compile_commands.json | compile_commands.json | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | [submodule "test/Unity"] | ||||||
|  | 	path = test/Unity | ||||||
|  | 	url = https://github.com/ThrowTheSwitch/Unity | ||||||
							
								
								
									
										109
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,30 +1,4 @@ | |||||||
| NAME = scl | include config.mk | ||||||
|  |  | ||||||
| TARGET = $(NAME).out |  | ||||||
|  |  | ||||||
| SRC_DIR = src |  | ||||||
| BUILD_DIR = build |  | ||||||
| OBJ_DIR = $(BUILD_DIR)/obj |  | ||||||
| TEST_DIR = test |  | ||||||
| TEST_BUILD_DIR = $(BUILD_DIR)/test |  | ||||||
| TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj |  | ||||||
|  |  | ||||||
| CC = clang |  | ||||||
| LINK = clang |  | ||||||
| CFLAGS = -Wall -DDBG -ggdb |  | ||||||
| LDFLAGS = |  | ||||||
|  |  | ||||||
| SRC_FILES = $(wildcard $(SRC_DIR)/*.c) |  | ||||||
| OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC_FILES)) |  | ||||||
| OBJ_FILES_NOMAIN = $(filter-out $(OBJ_DIR)/main.o, $(OBJ_FILES)) # Object files without main.c. |  | ||||||
| UNITY_C = $(TEST_DIR)/unity/unity.c |  | ||||||
| TEST_SRC_FILES = $(wildcard $(TEST_DIR)/*.c) |  | ||||||
| TEST_OBJ_FILES = $(patsubst $(TEST_DIR)/%.c, $(TEST_OBJ_DIR)/%.o, $(TEST_SRC_FILES)) |  | ||||||
|  |  | ||||||
| # Stupid things. |  | ||||||
| RESETCOLOR = \x1b[0m |  | ||||||
| WHITE = $(RESETCOLOR)\x1b[37m |  | ||||||
| WHITE_BOLD = $(RESETCOLOR)\x1b[37;1m |  | ||||||
|  |  | ||||||
| all: $(TARGET) | all: $(TARGET) | ||||||
|  |  | ||||||
| @@ -32,37 +6,72 @@ release: clean | |||||||
| release: CFLAGS = -Wall -O2 | release: CFLAGS = -Wall -O2 | ||||||
| release: $(TARGET) | release: $(TARGET) | ||||||
|  |  | ||||||
|  | # Run the target. | ||||||
| run: $(TARGET) | run: $(TARGET) | ||||||
| 	@ echo -e "$(WHITE_BOLD)Running... $(RESETCOLOR)./$(TARGET)" | 	./$(TARGET) | ||||||
| 	@ ./$(TARGET) |  | ||||||
|  | # Generate grammars with bison. | ||||||
|  | $(GRAM_FILES): $(SRC_DIR)/grammar.y | ||||||
|  | 	@ mkdir -p $(GRAM_DIR) | ||||||
|  | 	@ $(PRINT) "$(WHITE_BOLD)Generating grammars...$(RESETCOLOR)" | ||||||
|  | 	$(BISON) $< -o$(GRAM_DIR)/grammar.tab.c -H$(GRAM_DIR)/grammar.tab.h | ||||||
|  |  | ||||||
|  | # Compile grammars. | ||||||
|  | $(OBJ_DIR)/grammar.o: $(GRAM_DIR)/grammar.tab.c $(GRAM_DIR)/grammar.tab.h $(OBJ_DIR)/lexer.o | ||||||
|  | 	@ $(PRINT) "$(WHITE_BOLD)Compiling grammars...$(RESETCOLOR)" | ||||||
|  | 	$(CC) $(CFLAGS) -c $< -o $@ | ||||||
|  |  | ||||||
|  | # Lexer depends on grammars. | ||||||
|  | $(OBJ_DIR)/lexer.o: $(SRC_DIR)/lexer.c $(GRAM_FILES) | ||||||
|  | 	@ mkdir -p $(OBJ_DIR) | ||||||
|  | 	@ $(PRINT) "$(WHITE_BOLD)Compiling source object $(WHITE)$@$(WHITE_BOLD)... $(RESETCOLOR)" | ||||||
|  | 	$(CC) $(CFLAGS) -c $< -o $@ | ||||||
|  |  | ||||||
|  | # Compile project source objects. | ||||||
|  | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h | ||||||
|  | 	@ mkdir -p $(OBJ_DIR) | ||||||
|  | 	@ $(PRINT) "$(WHITE_BOLD)Compiling source object $(WHITE)$@$(WHITE_BOLD)... $(RESETCOLOR)" | ||||||
|  | 	$(CC) $(CFLAGS) -c $< -o $@ | ||||||
|  |  | ||||||
| # Link to final binary. | # Link to final binary. | ||||||
| $(TARGET): $(OBJ_FILES) | $(TARGET): $(OBJ_DIR)/grammar.o $(OBJ_FILES) | ||||||
| 	@ echo -e "$(WHITE_BOLD)Linking $(WHITE)$(TARGET)$(WHITE_BOLD)...$(RESETCOLOR) $(CC) -o $(TARGET) $(OBJ_FILES) $(LDFLAGS)" | 	@ $(PRINT) "$(WHITE_BOLD)Linking $(WHITE)$@$(WHITE_BOLD)...$(RESETCOLOR)" | ||||||
| 	@ $(LINK) -o $(TARGET) $(OBJ_FILES) $(LDFLAGS) | 	$(LINK) -o $(TARGET) $(OBJ_FILES) $(OBJ_DIR)/grammar.o $(LDFLAGS) | ||||||
|  |  | ||||||
| # Compile project sources. | # Compile Unity object. | ||||||
| $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/include/%.h | $(UNITY_OBJ): $(UNITY_C) $(UNITY_H) | ||||||
| 	@ mkdir -p $(OBJ_DIR) | 	@ $(PRINT) "$(WHITE_BOLD)Compiling Unity...$(RESETCOLOR)" | ||||||
| 	@ echo -e "$(WHITE_BOLD)Compiling $(WHITE)$<$(WHITE_BOLD)... $(RESETCOLOR)$(CC) $(CFLAGS) -c $< -o $@" | 	$(CC) $(CFLAGS) -D UNITY_OUTPUT_COLOR -c $< -o $@ | ||||||
| 	@ $(CC) $(CFLAGS) -c $< -o $@ |  | ||||||
|  |  | ||||||
| # Compile test sources. | # Compile test object. | ||||||
| $(TEST_OBJ_DIR)/%.o: $(TEST_DIR)/%.c | $(TEST_OBJ_DIR)/test_%.o: $(TEST_DIR)/test_%.c | ||||||
| 	@ mkdir -p $(TEST_OBJ_DIR) | 	@ mkdir -p $(TEST_OBJ_DIR) | ||||||
| 	@ echo -e "$(WHITE_BOLD)Compiling Test $(WHITE)$<$(WHITE_BOLD)... $(WHITE)$(CC) $(CFLAGS) -I$(SRC_DIR)/include -c $< -o $@$(RESETCOLOR)" | 	@ $(PRINT) "$(WHITE_BOLD)Compiling test object $(WHITE)$@$(WHITE_BOLD)...$(RESETCOLOR)" | ||||||
| 	@ $(CC) $(CFLAGS) -I$(SRC_DIR)/include -c $< -o $@ | 	$(CC) $(CFLAGS) -c $< -o $@ | ||||||
|  |  | ||||||
| # Link the test executable. | # Link final test binary. | ||||||
| test: $(TEST_OBJ_FILES) $(OBJ_FILES_NOMAIN) $(UNITY_C) | $(TEST_BUILD_DIR)/test_%.out: $(TEST_OBJ_DIR)/test_%.o $(OBJ_DIR)/grammar.o $(OBJ_FILES_NOMAIN) $(UNITY_OBJ) | ||||||
| 	@ echo -e "$(WHITE_BOLD)Linking test binary$(WHITE)...$(RESETCOLOR)" | 	@ mkdir -p $(TEST_BUILD_DIR) | ||||||
| 	@ $(LINK) -DUNITY_OUTPUT_COLOR $(TEST_OBJ_FILES) $(OBJ_FILES_NOMAIN) $(UNITY_C) -o $(TEST_BUILD_DIR)/test.out | 	@ $(PRINT) "$(WHITE_BOLD)Linking test binary $(WHITE)$@$(WHITE_BOLD)...$(RESETCOLOR)" | ||||||
| 	@ echo -e "$(WHITE_BOLD)Running tests$(WHITE)...$(RESETCOLOR)" | 	$(LINK) -o $@ $? $(LDFLAGS) | ||||||
| 	@ ./$(TEST_BUILD_DIR)/test.out |  | ||||||
|  |  | ||||||
|  | # Run the test files. | ||||||
|  | test: $(TARGET) $(TEST_BIN_FILES) | ||||||
|  | 	@ $(PRINT) "$(WHITE_BOLD)Running unit tests...$(RESETCOLOR)" | ||||||
|  | 	for test in $(TEST_BIN_FILES); do ./$${test} || echo -e "$(RED_BOLD) BAD EXIT ON $${test} $(RESETCOLOR)"; done | ||||||
|  | 	@ $(PRINT) "$(WHITE_BOLD)Running validation tests...$(RESETCOLOR)" | ||||||
|  | 	$(BATS) $(TEST_VAL_DIR) | ||||||
|  |  | ||||||
|  | # Clean out objects, binaries, and built artifacts. | ||||||
| clean: | clean: | ||||||
| 	@ echo -e "$(WHITE_BOLD)Cleaning up...$(WHITE) $(OBJ_DIR)/*.o $(TEST_OBJ_DIR)/*.o $(TEST_BUILD_DIR)/test.out $(TARGET)$(RESETCOLOR)" | 	@ $(PRINT) "$(WHITE_BOLD)Cleaning up...$(RESETCOLOR)" | ||||||
| 	@ rm -rf $(OBJ_DIR)/*.o $(TEST_OBJ_DIR)/*.o $(TEST_BUILD_DIR)/test.out $(TARGET) | 	rm -rf $(OBJ_DIR)/*.o $(TEST_OBJ_DIR)/*.o $(TEST_BUILD_DIR)/test.out $(TARGET) $(GRAM_DIR)/* $(UNITY_OBJ) | ||||||
|  |  | ||||||
| .PHONY: all clean test nocolor release run | # Get LOC. | ||||||
|  | lines: | ||||||
|  | 	@ wc -l $(SRC_FILES) $(INC_FILES) $(GRAM_SRC) | ||||||
|  |  | ||||||
|  | .PHONY: all clean test nocolor release run lines | ||||||
|  |  | ||||||
|  | # Run this intermediary even though make thinks it's useless. | ||||||
|  | .PRECIOUS: $(TEST_OBJ_FILES) | ||||||
|   | |||||||
							
								
								
									
										72
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,3 +1,71 @@ | |||||||
| # SCL: Simple Calculator Language | # SCL: Simple CAS Language | ||||||
|  |  | ||||||
| A spiritual successor to halk. | *v0.3* | ||||||
|  |  | ||||||
|  | SCL aims to be a human-friendly Computer Algebra System (CAS) inspired by | ||||||
|  | [maxima](https://maxima.sourceforge.io/) that feels like writing on paper. In | ||||||
|  | its current state, SCL can be used as a functional programming language capable | ||||||
|  | of performing simple arithmetic. The codebase is about 2,000 lines of | ||||||
|  | handwritten C, including a parser, interpreter, and runtime. It uses a linked | ||||||
|  | environment scoping model. | ||||||
|  |  | ||||||
|  | ## Usage | ||||||
|  |  | ||||||
|  | To download and run: | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | git clone https://git.signorovitch.org/scl/scl -b stable && cd scl | ||||||
|  | make release | ||||||
|  | ./scl.out | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### For Development | ||||||
|  |  | ||||||
|  | ```bash | ||||||
|  | git clone git@signorovitch.org:scl/scl --recurse-submodules && cd scl | ||||||
|  | make all test | ||||||
|  | ./scl.out | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | If you wish to run tests, make sure to run `git clone --recurse-submodules` to | ||||||
|  | include the [Unity](https://github.com/ThrowTheSwitch/Unity) test framework. | ||||||
|  | *Note that tests are currently in poor use. I hope to amend this in the future.* | ||||||
|  |  | ||||||
|  | ## Syntax | ||||||
|  |  | ||||||
|  | SCL's syntax will feel familiar to other functional programming languages. | ||||||
|  |  | ||||||
|  | ```scl | ||||||
|  | > x = 3 + 3 * 3; x + 1 | ||||||
|  | = 13 | ||||||
|  | > f(x) x + 1 | ||||||
|  | > f(1) | ||||||
|  | = 2 | ||||||
|  | > (\(x) 2 * x)(5) | ||||||
|  | = 10 | ||||||
|  | > f(g) g(2) | ||||||
|  | > f(\(x) 2 * x) | ||||||
|  | = 4 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Here's a simple factorial function, using recursion: | ||||||
|  |  | ||||||
|  | ```scl | ||||||
|  | > fac(n) = { | ||||||
|  | >   f(n, a) = { | ||||||
|  | >     if n == 1 | ||||||
|  | >       a | ||||||
|  | >     else | ||||||
|  | >       f(n - 1, a * n); | ||||||
|  | >   } | ||||||
|  | > | ||||||
|  | >   f(n, 1); | ||||||
|  | > } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | SCL's syntax is quite flexible. The above function could be more concisely | ||||||
|  | written as: | ||||||
|  |  | ||||||
|  | ```scl | ||||||
|  | > fac(n) (n, 1) -> f(n, a) ? n == 1 a f(n - 1, a * n) | ||||||
|  | ``` | ||||||
|   | |||||||
							
								
								
									
										55
									
								
								STATUS.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								STATUS.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | |||||||
|  | # SCL Design Status | ||||||
|  |  | ||||||
|  | - [x] Data definitions | ||||||
|  |   - [x] Token Definitions | ||||||
|  |   - [x] AST Definitions | ||||||
|  |  | ||||||
|  | - [ ] Parser | ||||||
|  |   - [x] Parse numbers | ||||||
|  |   - [x] Parse floats | ||||||
|  |   - [x] Parse negative numbers | ||||||
|  |   - [x] Parse infix operators | ||||||
|  |   - [x] Order of operations | ||||||
|  |   - [x] Parse function application | ||||||
|  |   - [x] Parse order of operations with parenthesis | ||||||
|  |   - [x] Parse variable invocation | ||||||
|  |   - [x] Parse variable definition | ||||||
|  |     - [ ] Parse types | ||||||
|  |   - [x] Parse function definition | ||||||
|  |   - [ ] Parse lists/arrays/vectors | ||||||
|  |   - [x] Parse blocks | ||||||
|  |   - [ ] Parse control flow | ||||||
|  |     - [x] Parse `if` statements | ||||||
|  |     - [ ] Parse `loop`s | ||||||
|  |     - [ ] Parse `for` loops | ||||||
|  |     - [ ] Parse `while` loops | ||||||
|  |     - [ ] Parse `case` statements | ||||||
|  |     - [ ] Parse `goto` statements | ||||||
|  |   - [x] Parse lambda function definition | ||||||
|  |   - [ ] Parse function calling with positional arguments | ||||||
|  |   - [ ] Parse variadic functions | ||||||
|  |   - [ ] Parse infix function definition | ||||||
|  |  | ||||||
|  | - [ ] Executer | ||||||
|  |   - [x] Exec function calls | ||||||
|  |   - [x] Exec variable use | ||||||
|  |   - [x] Exec variable definition | ||||||
|  |   - [x] Exec function definition | ||||||
|  |   - [ ] Exec symbolic variables | ||||||
|  |   - [ ] Exec control flow statements | ||||||
|  |   - [ ] Exec variadic functions | ||||||
|  |   - [x] Exec lambda functions | ||||||
|  |   - [ ] Exec lists | ||||||
|  |   - [ ] Exec arrays | ||||||
|  |   - [ ] Exec vectors | ||||||
|  |  | ||||||
|  | - [ ] Interface | ||||||
|  |   - [ ] Interactive interpreter | ||||||
|  |     - [ ] Use GNU readline | ||||||
|  |     - [ ] Multi-line input | ||||||
|  |     - [ ] Syntax highlighting | ||||||
|  |     - [ ] Autocompletion/suggestion | ||||||
|  |   - [ ] Command line interface | ||||||
|  |     - [ ] Pass in a file | ||||||
|  |     - [ ] Save AST to a file | ||||||
|  |     - [ ] Run from AST file | ||||||
							
								
								
									
										10
									
								
								TODO.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								TODO.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | Differentiate kind literals, constructors, and kinds themselves. | ||||||
|  | EXCEPTION HANDLING: exception ast type should have as data a giant enum of | ||||||
|  | possible types, rather than a char* message. A description of each type could be | ||||||
|  | handled under the exception type and print logic. For now, executor checks | ||||||
|  | message for special exceptions e.g. exit(). | ||||||
|  |  | ||||||
|  | Change editor to GNU Readline. | ||||||
|  | Make variables persist through lines in the editor. | ||||||
|  |  | ||||||
|  | Return syntax errors as exceptions. | ||||||
							
								
								
									
										40
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								config.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | NAME = scl | ||||||
|  |  | ||||||
|  | TARGET = $(NAME).out | ||||||
|  |  | ||||||
|  | SRC_DIR = src | ||||||
|  | INC_DIR = $(SRC_DIR)/include | ||||||
|  | BUILD_DIR = build | ||||||
|  | OBJ_DIR = $(BUILD_DIR)/obj | ||||||
|  | GRAM_DIR = $(BUILD_DIR)/grammars | ||||||
|  | TEST_DIR = test | ||||||
|  | TEST_BUILD_DIR = $(BUILD_DIR)/test | ||||||
|  | TEST_OBJ_DIR = $(TEST_BUILD_DIR)/obj | ||||||
|  |  | ||||||
|  | CC = clang -std=c23 | ||||||
|  | LINK = clang | ||||||
|  | CFLAGS = -Wall -DDBG -ggdb -fsanitize=leak | ||||||
|  | LDFLAGS = -lm | ||||||
|  | BATS = bats | ||||||
|  | BISON = bison | ||||||
|  | PRINT = echo -e | ||||||
|  |  | ||||||
|  | SRC_FILES = $(wildcard $(SRC_DIR)/*.c) | ||||||
|  | INC_FILES = $(wildcard $(INC_DIR)/*.h) | ||||||
|  | OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC_FILES)) | ||||||
|  | OBJ_FILES_NOMAIN = $(filter-out $(OBJ_DIR)/main.o, $(OBJ_FILES)) # Object files without main.c. | ||||||
|  | GRAM_SRC = $(SRC_DIR)/grammar.y | ||||||
|  | GRAM_FILES = $(GRAM_DIR)/grammar.tab.c $(GRAM_DIR)/grammar.tab.h | ||||||
|  | UNITY_DIR = $(TEST_DIR)/Unity | ||||||
|  | UNITY_C = $(UNITY_DIR)/src/unity.c | ||||||
|  | UNITY_H = $(UNITY_DIR)/src/unity.h | ||||||
|  | UNITY_OBJ = $(TEST_BUILD_DIR)/unity.o | ||||||
|  | TEST_SRC_FILES = $(wildcard $(TEST_DIR)/*.c) | ||||||
|  | TEST_OBJ_FILES = $(patsubst $(TEST_DIR)/%.c, $(TEST_OBJ_DIR)/%.o, $(TEST_SRC_FILES)) | ||||||
|  | TEST_BIN_FILES = $(patsubst $(TEST_DIR)/%.c, $(TEST_BUILD_DIR)/%.out, $(TEST_SRC_FILES)) | ||||||
|  | TEST_VAL_DIR = $(TEST_DIR)/val | ||||||
|  |  | ||||||
|  | RESETCOLOR = \033[0m | ||||||
|  | WHITE = $(RESETCOLOR)\033[37m | ||||||
|  | WHITE_BOLD = $(RESETCOLOR)\033[37;1m | ||||||
|  | RED_BOLD = $(RESETCOLOR)\033[31;1m | ||||||
							
								
								
									
										25
									
								
								definitions.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								definitions.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | f = \(x) 2 * x | ||||||
|  | g = \(h) \(x) h(h(x)) | ||||||
|  |  | ||||||
|  | f(2) => 4 | ||||||
|  | g(f)(2) => 8 | ||||||
|  |  | ||||||
|  | CALL | ||||||
|  |  argc: 1 | ||||||
|  |  argv: [ 2 ] | ||||||
|  |  to: | ||||||
|  |   CALL | ||||||
|  |    argc: 1 | ||||||
|  |    argv: [ | ||||||
|  |     VREF | ||||||
|  |      name: f | ||||||
|  |    ] | ||||||
|  |    to: | ||||||
|  |     VREF | ||||||
|  |      name: g | ||||||
|  |  fname: NULL | ||||||
|  |  | ||||||
|  |  | ||||||
|  | expression + arguments = call = expression | ||||||
|  | expression + parameters = lambda = expression | ||||||
|  | expression + name = variable = expression | ||||||
							
								
								
									
										2
									
								
								examples/function.scl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								examples/function.scl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | apply(f, x) f(x) | ||||||
|  | apply(\(x) x + 1, 2) | ||||||
							
								
								
									
										3
									
								
								examples/types.scl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								examples/types.scl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | x: Int = 3 | ||||||
|  |  | ||||||
|  | <name> : <expression> = <expression> | ||||||
							
								
								
									
										228
									
								
								src/ast.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								src/ast.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,228 @@ | |||||||
|  | #include <inttypes.h> | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #include "include/ast.h" | ||||||
|  | #include "include/gc.h" | ||||||
|  | #include "include/scope.h" | ||||||
|  | #include "include/util.h" | ||||||
|  |  | ||||||
|  | extern AST* root; | ||||||
|  |  | ||||||
|  | AST* ast_init(ASTType type, void* data) { | ||||||
|  |     AST* ast = gc_alloc(sizeof(AST), GC_TYPE_AST); | ||||||
|  |  | ||||||
|  |     ast->type = type; | ||||||
|  |     ast->data = data; | ||||||
|  |     ast->scope = NULL; | ||||||
|  |  | ||||||
|  |     if (ast->type > AST_TYPE_MAX) { | ||||||
|  |         log_dbgf( | ||||||
|  |             "Attempted to create invalid AST (%i > %i) to GC: ast:%p", | ||||||
|  |             ast->type, AST_TYPE_MAX, ast | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ast; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* ast_init_scope(ASTType type, void* data, Scope* scope) { | ||||||
|  |     AST* ast = malloc(sizeof(AST)); | ||||||
|  |  | ||||||
|  |     ast->type = type; | ||||||
|  |     ast->data = data; | ||||||
|  |     ast->scope = scope; | ||||||
|  |  | ||||||
|  |     return ast; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_destroy(AST* ast) { | ||||||
|  |     if (!ast) return; | ||||||
|  |  | ||||||
|  |     switch (ast->type) { | ||||||
|  |         case AST_TYPE_LIT_NUM:  ast_num_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_LIT_BOOL: ast_bool_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_LIT_KIND: ast_kind_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_CALL:     ast_call_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_REF:      ast_ref_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_DEF:      ast_def_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_BLOCK:    ast_block_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_ARG:      ast_arg_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_BIF:      ast_bif_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_EXC:      ast_exc_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_LAMBDA:   ast_lambda_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_FORCE:    ast_force_data_destroy(ast->data); break; | ||||||
|  |         case AST_TYPE_PRESERVE: ast_preserve_data_destroy(ast->data); break; | ||||||
|  |         default: | ||||||
|  |             log_dbgf("Unknown ast type %d (max: %d)", ast->type, AST_TYPE_MAX); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     free(ast); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ASTNumData* ast_num_data_init(double val) { | ||||||
|  |     talloc(ASTNumData, num); | ||||||
|  |  | ||||||
|  |     *num = val; | ||||||
|  |  | ||||||
|  |     return num; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_num_data_destroy(ASTNumData* num) { free(num); } | ||||||
|  |  | ||||||
|  | ASTBoolData* ast_bool_data_init(int val) { | ||||||
|  |     talloc(ASTBoolData, bol); | ||||||
|  |  | ||||||
|  |     *bol = val; | ||||||
|  |  | ||||||
|  |     return bol; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_bool_data_destroy(ASTBoolData* bol) { free(bol); } | ||||||
|  |  | ||||||
|  | const char* ast_lit_kind_names[AST_LIT_KIND_MAX + 2] = { | ||||||
|  |     [AST_LIT_KIND_NUM] = "Number", | ||||||
|  |     [AST_LIT_KIND_BOOL] = "Boolean", | ||||||
|  |     [AST_LIT_KIND_KIND] = "Type", | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | ASTKindData* ast_kind_data_init(ASTKindData val) { | ||||||
|  |     talloc(ASTKindData, kind); | ||||||
|  |     *kind = val; | ||||||
|  |  | ||||||
|  |     return kind; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_kind_data_destroy(ASTKindData* kind) { free(kind); } | ||||||
|  |  | ||||||
|  | ASTExcData* ast_exc_data_init(const char* msg, AST* trace) { | ||||||
|  |     ASTExcData* data = malloc(sizeof(ASTExcData)); | ||||||
|  |     data->msg = msg; | ||||||
|  |     data->trace = trace; | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_exc_data_destroy(ASTExcData* exc) { | ||||||
|  |     // `msg` is static, and `trace` will get freed in GC. | ||||||
|  |     free(exc); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**, Scope*)) { | ||||||
|  |     return (ASTBIFData*)fn; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_bif_data_destroy(ASTBIFData* bif) { return; } | ||||||
|  |  | ||||||
|  | // Lambda. | ||||||
|  |  | ||||||
|  | ASTLambdaData* ast_lambda_data_init(size_t parc, AST** parv, AST* body) { | ||||||
|  |     talloc(ASTLambdaData, lambda); | ||||||
|  |  | ||||||
|  |     lambda->parc = parc; | ||||||
|  |     lambda->parv = parv; | ||||||
|  |     lambda->body = body; | ||||||
|  |  | ||||||
|  |     return lambda; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_lambda_data_destroy(ASTLambdaData* lambda) { | ||||||
|  |     free(lambda->parv); | ||||||
|  |     free(lambda); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Call. | ||||||
|  |  | ||||||
|  | ASTCallData* ast_call_data_init(size_t argc, AST** argv, AST* exp) { | ||||||
|  |     talloc(ASTCallData, call); | ||||||
|  |  | ||||||
|  |     call->exp = exp; | ||||||
|  |     call->argc = argc; | ||||||
|  |     call->argv = argv; | ||||||
|  |  | ||||||
|  |     return call; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_call_data_destroy(ASTCallData* call) { | ||||||
|  |     if (!call) return; | ||||||
|  |     free(call->argv); | ||||||
|  |     free(call); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Def. | ||||||
|  |  | ||||||
|  | ASTDefData* ast_def_data_init(char* name, AST* kind, AST* exp) { | ||||||
|  |     talloc(ASTDefData, def); | ||||||
|  |  | ||||||
|  |     def->name = name; | ||||||
|  |     def->kind = kind; | ||||||
|  |     def->exp = exp; | ||||||
|  |  | ||||||
|  |     return def; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_def_data_destroy(ASTDefData* vdef) { | ||||||
|  |     free(vdef->name); | ||||||
|  |     free(vdef); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Ref. | ||||||
|  |  | ||||||
|  | ASTRefData* ast_ref_data_init(char* to) { | ||||||
|  |     talloc(ASTRefData, ref); | ||||||
|  |  | ||||||
|  |     ref->to = to; | ||||||
|  |  | ||||||
|  |     return ref; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_ref_data_destroy(ASTRefData* ref) { | ||||||
|  |     free(ref->to); | ||||||
|  |     free(ref); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ASTBlockData* ast_block_data_init(AST** inside, size_t ln) { | ||||||
|  |     ASTBlockData* block = malloc(sizeof(ASTBlockData)); | ||||||
|  |  | ||||||
|  |     block->inside = inside; | ||||||
|  |     block->ln = ln; | ||||||
|  |  | ||||||
|  |     return block; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_block_data_destroy(ASTBlockData* block) { | ||||||
|  |     free(block->inside); | ||||||
|  |     free(block); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ASTArgData* ast_arg_data_init(char* name) { | ||||||
|  |     ASTArgData* arg = malloc(sizeof(ASTArgData)); | ||||||
|  |     arg->name = name; | ||||||
|  |     return arg; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_arg_data_destroy(ASTArgData* arg) { free(arg->name); } | ||||||
|  |  | ||||||
|  | AST* ast_find(Scope* scope, char* name) { | ||||||
|  |     while (scope) { | ||||||
|  |         AST* gotten = htab_get(scope->here, name); | ||||||
|  |         if (gotten) return gotten; | ||||||
|  |         else scope = scope->inherit; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ASTForceData* ast_force_data_init(AST* body) { | ||||||
|  |     talloc(ASTForceData, force); | ||||||
|  |     force->body = body; | ||||||
|  |     return force; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_force_data_destroy(ASTForceData* force) { free(force); } | ||||||
|  |  | ||||||
|  | ASTPreserveData* ast_preserve_data_init(AST* body) { | ||||||
|  |     talloc(ASTPreserveData, preserve); | ||||||
|  |     preserve->body = body; | ||||||
|  |     return preserve; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_preserve_data_destroy(ASTPreserveData* preserve) { free(preserve); } | ||||||
							
								
								
									
										199
									
								
								src/ast_print.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								src/ast_print.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | |||||||
|  | #include "include/ast_print.h" | ||||||
|  | #include "include/ast.h" | ||||||
|  | #include "include/builtin.h" | ||||||
|  | #include "include/dstr.h" | ||||||
|  | #include "include/util.h" | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | static char* asttype_names[] = { | ||||||
|  |     [AST_TYPE_CALL] = "CALL", | ||||||
|  |     [AST_TYPE_LIT_NUM] = "LITERAL NUMBER", | ||||||
|  |     [AST_TYPE_LIT_BOOL] = "LITERAL BOOLEAN", | ||||||
|  |     [AST_TYPE_REF] = "REFERENCE", | ||||||
|  |     [AST_TYPE_DEF] = "DEFINITION", | ||||||
|  |     [AST_TYPE_BLOCK] = "BLOCK", | ||||||
|  |     [AST_TYPE_EXC] = "EXCEPTION", | ||||||
|  |     [AST_TYPE_ARG] = "DEFINITION ARGUMENT", | ||||||
|  |     [AST_TYPE_LAMBDA] = "LAMBDA", | ||||||
|  |     [AST_TYPE_BIF] = "BUILTIN FUNCTION", | ||||||
|  |     [AST_TYPE_FORCE] = "FORCE", | ||||||
|  |     [AST_TYPE_PRESERVE] = "PRESERVE" | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | void ast_print(AST* ast) { | ||||||
|  |     if (!ast) return; | ||||||
|  |     ast_print_i(ast, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_print_i(AST* ast, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("AST", ast); | ||||||
|  |     INDENT_FIELD("type", "%s", asttype_names[ast->type]); | ||||||
|  |     INDENT_FIELD_EXT_NONL_START("data"); | ||||||
|  |     switch (ast->type) { | ||||||
|  |         case AST_TYPE_LIT_NUM: | ||||||
|  |             printf("%s  %lf\n", INDENT_spacing->buf, *(ASTNumData*)ast->data); | ||||||
|  |             break; | ||||||
|  |         case AST_TYPE_LIT_BOOL: | ||||||
|  |             printf( | ||||||
|  |                 "%s  %s\n", INDENT_spacing->buf, | ||||||
|  |                 *(ASTBoolData*)ast->data ? "true" : "false" | ||||||
|  |             ); | ||||||
|  |             break; | ||||||
|  |         case AST_TYPE_LIT_KIND: | ||||||
|  |             printf( | ||||||
|  |                 "%s  %s\n", INDENT_spacing->buf, | ||||||
|  |                 ast_lit_kind_names[*(ASTKindData*)ast->data] | ||||||
|  |             ); | ||||||
|  |             break; | ||||||
|  |         case AST_TYPE_CALL:     ast_call_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_EXC:      ast_exc_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_REF:      ast_ref_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_DEF:      ast_def_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_BLOCK:    ast_block_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_ARG:      ast_arg_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_LAMBDA:   ast_lambda_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_BIF:      ast_bif_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_FORCE:    ast_force_print(ast->data, i + 2); break; | ||||||
|  |         case AST_TYPE_PRESERVE: ast_preserve_print(ast->data, i + 2); break; | ||||||
|  |         default:                exit(1); | ||||||
|  |     } | ||||||
|  |     INDENT_FIELD_NONL_END; | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_num_print(ASTNumData* data, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_FIELD("data", "%lf", *data); | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_bool_print(ASTBoolData* data, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_FIELD("data", "%s", *data ? "true" : "false"); | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_exc_print(ASTExcData* data, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("ASTExcData", data); | ||||||
|  |     INDENT_FIELD("msg", "\"%s\"", data->msg); | ||||||
|  |     if (data->trace == NULL) { | ||||||
|  |         INDENT_FIELD("trace", "%p", NULL) | ||||||
|  |     } else { | ||||||
|  |         INDENT_FIELD_EXT_NONL_START("trace"); | ||||||
|  |         ast_print_i(data->trace, i + 1); | ||||||
|  |         INDENT_FIELD_NONL_END; | ||||||
|  |     } | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_call_print(ASTCallData* data, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("ASTCallData", data); | ||||||
|  |     INDENT_FIELD("argc", "%ld", data->argc); | ||||||
|  |     INDENT_FIELD_LIST("argv", data->argv, data->argc, ast_print_i); | ||||||
|  |     INDENT_FIELD_EXT_NONL_START("exp"); | ||||||
|  |     ast_print_i(data->exp, i + 2); | ||||||
|  |     INDENT_FIELD_NONL_END; | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  | void ast_def_print(ASTDefData* def, int depth) { | ||||||
|  |     INDENT_BEGIN(depth); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("ASTDefData", def); | ||||||
|  |     INDENT_FIELD("name", "%s", def->name); | ||||||
|  |     if (def->kind) { | ||||||
|  |         INDENT_FIELD_EXT_NONL_START("kind"); | ||||||
|  |         ast_print_i(def->kind, depth + 2); | ||||||
|  |         INDENT_FIELD_NONL_END; | ||||||
|  |     } else INDENT_FIELD("kind", "%s", "Any"); | ||||||
|  |  | ||||||
|  |     INDENT_FIELD_EXT_NONL_START("exp"); | ||||||
|  |     ast_print_i(def->exp, depth + 2); // 2 because already indented. | ||||||
|  |     INDENT_FIELD_NONL_END; | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_ref_print(ASTRefData* data, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("ASTRefData", data); | ||||||
|  |     INDENT_FIELD("to", "%s", data->to); | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_block_print(ASTBlockData* data, int depth) { | ||||||
|  |     INDENT_BEGIN(depth); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("ASTBlockData", data); | ||||||
|  |     INDENT_FIELD("ln", "%ld", data->ln); | ||||||
|  |     INDENT_FIELD_LIST("inside", data->inside, data->ln, ast_print_i); | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  | void ast_arg_print(ASTArgData* arg, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |     INDENT_TITLE("ASTArgData", arg); | ||||||
|  |     INDENT_FIELD("name", "%s", arg->name); | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_lambda_print(ASTLambdaData* lambda, int i) { | ||||||
|  |     INDENT_BEGIN(i) | ||||||
|  |     INDENT_TITLE("ASTLambdaData", lambda); | ||||||
|  |     INDENT_FIELD("parc", "%ld", lambda->parc); | ||||||
|  |     INDENT_FIELD_LIST("parv", lambda->parv, lambda->parc, ast_print_i); | ||||||
|  |     INDENT_FIELD_EXT_NONL_START("body"); | ||||||
|  |     ast_print_i(lambda->body, i + 2); | ||||||
|  |     INDENT_FIELD_NONL_END; | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_bif_print(ASTBIFData* bif, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |     INDENT_TITLE("ASTBIFData", bif); | ||||||
|  |  | ||||||
|  |     char* name = "unknown"; | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < BUILTIN_FNS_LN; i++) | ||||||
|  |         if ((void*)BUILTIN_FNS[i].fn == bif) { | ||||||
|  |             name = BUILTIN_FNS[i].name; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     INDENT_FIELD("name", "%s", name); | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_force_print(ASTForceData* force, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("ASTForceData", force); | ||||||
|  |     INDENT_FIELD_EXT_NONL_START("body"); | ||||||
|  |     ast_print_i(force->body, i + 2); | ||||||
|  |     INDENT_FIELD_NONL_END; | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ast_preserve_print(ASTPreserveData* preserve, int i) { | ||||||
|  |     INDENT_BEGIN(i); | ||||||
|  |  | ||||||
|  |     INDENT_TITLE("ASTPreserveData", preserve); | ||||||
|  |     INDENT_FIELD_EXT_NONL_START("body"); | ||||||
|  |     ast_print_i(preserve->body, i + 2); | ||||||
|  |     INDENT_FIELD_NONL_END; | ||||||
|  |  | ||||||
|  |     INDENT_END; | ||||||
|  | } | ||||||
							
								
								
									
										211
									
								
								src/builtin.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								src/builtin.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | |||||||
|  | #include <stdarg.h> | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #include "include/ast.h" | ||||||
|  | #include "include/builtin.h" | ||||||
|  | #include "include/exec.h" | ||||||
|  |  | ||||||
|  | AST* builtin_sum(size_t argc, AST** argv, Scope* parent) { | ||||||
|  |     ASTNumData total = 0; | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < argc; i++) { | ||||||
|  |         AST* arg = exec_exp(argv[i], parent); | ||||||
|  |         if (arg->type == AST_TYPE_EXC) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("`sum` encountered an exception.", arg) | ||||||
|  |             ); | ||||||
|  |         if (arg->type != AST_TYPE_LIT_NUM) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("Sum can't sum some non-num arguments.", NULL) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |         total += *(ASTNumData*)arg->data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(total)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* builtin_sub(size_t argc, AST** argv, Scope* parent) { | ||||||
|  |     if (argc <= 0) return ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(0)); | ||||||
|  |  | ||||||
|  |     AST* first = exec_exp(*argv, parent); | ||||||
|  |     if (first->type == AST_TYPE_EXC) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("`sub` encountered an exception.", first) | ||||||
|  |         ); | ||||||
|  |     if (first->type != AST_TYPE_LIT_NUM) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("Can't subtract non-num arguments.", NULL) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     ASTNumData total = *(ASTNumData*)first->data; | ||||||
|  |  | ||||||
|  |     for (int i = 1; i < argc; i++) { | ||||||
|  |         AST* arg = exec_exp(argv[i], parent); | ||||||
|  |         if (arg->type == AST_TYPE_EXC) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("`sub` encountered an exception.", arg) | ||||||
|  |             ); | ||||||
|  |         if (arg->type != AST_TYPE_LIT_NUM) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("Can't subtract non-num arguments.", NULL) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |         total -= *(ASTNumData*)arg->data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(total)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* builtin_mul(size_t argc, AST** argv, Scope* parent) { | ||||||
|  |     if (argc <= 0) return ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(0)); | ||||||
|  |  | ||||||
|  |     AST* first = exec_exp(*argv, parent); | ||||||
|  |     if (first->type == AST_TYPE_EXC) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("`mul` encountered an expection.", first) | ||||||
|  |         ); | ||||||
|  |     if (first->type != AST_TYPE_LIT_NUM) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("Can't multiply non-num arguments.", NULL) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     ASTNumData total = *(ASTNumData*)first->data; | ||||||
|  |  | ||||||
|  |     for (int i = 1; i < argc; i++) { | ||||||
|  |         AST* arg = exec_exp(argv[i], parent); | ||||||
|  |         if (arg->type == AST_TYPE_EXC) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("`mul` encountered an execption.", arg) | ||||||
|  |             ); | ||||||
|  |         if (arg->type != AST_TYPE_LIT_NUM) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("Can't multiply non-num arguments.", NULL) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |         total *= *(ASTNumData*)arg->data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(total)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* builtin_div(size_t argc, AST** argv, Scope* parent) { | ||||||
|  |     if (argc <= 0) return ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(0)); | ||||||
|  |  | ||||||
|  |     AST* first = exec_exp(*argv, parent); | ||||||
|  |     if (first->type == AST_TYPE_EXC) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("`div` encountered an exception.", first) | ||||||
|  |         ); | ||||||
|  |     if (first->type != AST_TYPE_LIT_NUM) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("Can't divide non-num arguments.", NULL) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     ASTNumData total = *(ASTNumData*)first->data; | ||||||
|  |  | ||||||
|  |     for (int i = 1; i < argc; i++) { | ||||||
|  |         AST* arg = exec_exp(argv[i], parent); | ||||||
|  |         if (arg->type == AST_TYPE_EXC) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("`div` encountered an exception.", arg) | ||||||
|  |             ); | ||||||
|  |         if (arg->type != AST_TYPE_LIT_NUM) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("Can't divide non-num arguments.", NULL) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |         total /= *(ASTNumData*)arg->data; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(total)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* builtin_die(size_t argc, AST** argv, Scope* parent) { | ||||||
|  |     return ast_init(AST_TYPE_EXC, ast_exc_data_init("8", NULL)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* builtin_if(size_t argc, AST** argv, Scope* parent) { | ||||||
|  |     if (argc != 3) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("If invoked with too few args.", NULL) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     AST* pred = exec_exp(argv[0], parent); | ||||||
|  |     AST* body = argv[1]; | ||||||
|  |     AST* alt = argv[2]; | ||||||
|  |  | ||||||
|  |     if (pred->type != AST_TYPE_LIT_BOOL) { | ||||||
|  |         if (pred->type == AST_TYPE_EXC) { | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, ast_exc_data_init("if touched an error", pred) | ||||||
|  |             ); | ||||||
|  |         } else { | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, | ||||||
|  |                 ast_exc_data_init("if works on booleans idiot", NULL) | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (*(ASTBoolData*)pred->data) return exec_exp(body, parent); | ||||||
|  |     else return exec_exp(alt, parent); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* builtin_eq(size_t argc, AST** argv, Scope* parent) { | ||||||
|  |     if (argc < 1) return ast_init(AST_TYPE_EXC, ast_exc_data_init("bad", NULL)); | ||||||
|  |     else if (argc == 1) | ||||||
|  |         return ast_init(AST_TYPE_LIT_BOOL, ast_bool_data_init(1)); | ||||||
|  |  | ||||||
|  |     AST* first = exec_exp(argv[0], parent); | ||||||
|  |     ASTType type = first->type; | ||||||
|  |  | ||||||
|  |     AST* second = exec_exp(argv[1], parent); | ||||||
|  |     if (first->type == AST_TYPE_EXC) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, ast_exc_data_init("first was bad", first) | ||||||
|  |         ); | ||||||
|  |     if (second->type == AST_TYPE_EXC) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, ast_exc_data_init("second was bad", second) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     if (second->type != type) | ||||||
|  |         return ast_init( | ||||||
|  |             AST_TYPE_EXC, | ||||||
|  |             ast_exc_data_init("apples and oranges or something idk", NULL) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     // Later when I put together an anctual type system I'll have this | ||||||
|  |     // delegated to each type. For now this works. | ||||||
|  |  | ||||||
|  |     switch (type) { | ||||||
|  |         case AST_TYPE_LIT_NUM: | ||||||
|  |             if (*(ASTNumData*)first->data == *(ASTNumData*)second->data) | ||||||
|  |                 return ast_init(AST_TYPE_LIT_BOOL, ast_bool_data_init(1)); | ||||||
|  |             else return ast_init(AST_TYPE_LIT_BOOL, ast_bool_data_init(0)); | ||||||
|  |         case AST_TYPE_LIT_BOOL: | ||||||
|  |             if (*(ASTNumData*)first->data == *(ASTNumData*)second->data) | ||||||
|  |                 return ast_init(AST_TYPE_LIT_BOOL, ast_bool_data_init(1)); | ||||||
|  |             else return ast_init(AST_TYPE_LIT_BOOL, ast_bool_data_init(0)); | ||||||
|  |         default: | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_LIT_BOOL, ast_bool_data_init(0) | ||||||
|  |             ); // Can't equate nonprimatives. I think. Maybe. | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								src/dlist.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/dlist.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdio.h> // IWYU pragma: keep. Req by util macros. | ||||||
|  |  | ||||||
|  | #include "include/dlist.h" | ||||||
|  | #include "include/util.h" | ||||||
|  |  | ||||||
|  | DList* dlist_init(void) { | ||||||
|  |     DList* dlist = malloc(sizeof(DList)); | ||||||
|  |  | ||||||
|  |     dlist->sz = DLIST_INITSZ; | ||||||
|  |     dlist->buf = malloc(DLIST_INITSZ); | ||||||
|  |     dlist->ln = 0; | ||||||
|  |  | ||||||
|  |     return dlist; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void dlist_destroy(DList* dlist) { | ||||||
|  |     free(dlist->buf); | ||||||
|  |     free(dlist); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void dlist_destroypsv(DList* dlist) { free(dlist); } | ||||||
|  |  | ||||||
|  | // Check whether the buffer is about to overflow and resize it if necessary. | ||||||
|  | void dlist_check_resz(DList* dlist) { | ||||||
|  |     while ((dlist->ln + 1) * sizeof(void*) >= dlist->sz) { | ||||||
|  |         // Double the buffer size when overflown. | ||||||
|  |         dlist->sz *= 2; | ||||||
|  |         dlist->buf = realloc(dlist->buf, dlist->sz); | ||||||
|  |         log_dbgf( | ||||||
|  |             "dlist @ %p doubled from %ld to %ld", dlist, dlist->sz / 2, | ||||||
|  |             dlist->sz | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void dlist_append(DList* dest, void* src) { | ||||||
|  |     dlist_check_resz(dest); | ||||||
|  |  | ||||||
|  |     log_dbgf("added %p to dlist@%p", src, dest); | ||||||
|  |  | ||||||
|  |     dest->buf[dest->ln] = src; | ||||||
|  |     dest->ln++; | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								src/dstr.c
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								src/dstr.c
									
									
									
									
									
								
							| @@ -1,13 +1,14 @@ | |||||||
| #include "include/dstr.h" | #include "include/dstr.h" | ||||||
| #include "include/util.h" | #include "include/util.h" | ||||||
|  |  | ||||||
| #include <string.h> | #include <stddef.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
| Dstr* dstr_init(void) { | Dstr* dstr_init(void) { | ||||||
|     Dstr* dstr = malloc(sizeof(Dstr)); |     Dstr* dstr = malloc(sizeof(Dstr)); | ||||||
|  |  | ||||||
|     dstr->bufsz = DSTR_INITSZ; |     dstr->sz = DSTR_INITSZ; | ||||||
|     dstr->buf = malloc(DSTR_INITSZ); |     dstr->buf = malloc(DSTR_INITSZ); | ||||||
|     *dstr->buf = '\0'; |     *dstr->buf = '\0'; | ||||||
|     dstr->ln = 0; |     dstr->ln = 0; | ||||||
| @@ -20,13 +21,22 @@ void dstr_destroy(Dstr* dstr) { | |||||||
|     free(dstr); |     free(dstr); | ||||||
| } | } | ||||||
|  |  | ||||||
| void dstr_append(Dstr* dest, char* src, size_t ln) { | void dstr_destroypsv(Dstr* dstr) { free(dstr); } | ||||||
|     while (dest->ln + ln + 1 > dest->bufsz) { |  | ||||||
|  | // Check whether the buffer is overflowing and resize it if necessary. | ||||||
|  | void dstr_check_resz(Dstr* dstr, size_t ln) { | ||||||
|  |     while (dstr->ln + ln + 1 > dstr->sz) { | ||||||
|         // Double the buffer size when overflown. |         // Double the buffer size when overflown. | ||||||
|         dest->bufsz *= 2; |         dstr->sz *= 2; | ||||||
|         dest->buf = realloc(dest->buf, dest->bufsz); |         dstr->buf = realloc(dstr->buf, dstr->sz); | ||||||
|         log_dbgf("dstr @ %p doubled from %ld to %ld", dest, dest->bufsz/2, dest->bufsz); |         log_dbgf( | ||||||
|  |             "dstr @ %p doubled from %ld to %ld", dstr, dstr->sz / 2, dstr->sz | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void dstr_append(Dstr* dest, char* src, size_t ln) { | ||||||
|  |     dstr_check_resz(dest, ln); | ||||||
|  |  | ||||||
|     // Overwrites the \0 at the end of the string, keeps the null from the given |     // Overwrites the \0 at the end of the string, keeps the null from the given | ||||||
|     // string. |     // string. | ||||||
| @@ -34,16 +44,11 @@ void dstr_append(Dstr* dest, char* src, size_t ln) { | |||||||
|     dest->ln += ln; |     dest->ln += ln; | ||||||
| } | } | ||||||
|  |  | ||||||
| void dstr_appendch(Dstr *dest, char ch) { | void dstr_appendch(Dstr* dest, char ch) { | ||||||
|     if (dest->ln + 1 + 1 > dest->bufsz) { |     dstr_check_resz(dest, 1); | ||||||
|         // Double the buffer size when overflown. |  | ||||||
|         dest->bufsz *= 2; |  | ||||||
|         dest->buf = realloc(dest->buf, dest->bufsz); |  | ||||||
|         log_dbgf("dstr @ %p doubled from %ld to %ld", dest, dest->bufsz/2, dest->bufsz); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Overwrites the preexisting null terminator, and adds one of its own. |     // Overwrites the preexisting null terminator, and adds one of its own. | ||||||
|     dest->buf[dest->ln] = ch; |     dest->buf[dest->ln] = ch; | ||||||
|     dest->buf[dest->ln+1] = '\0'; |     dest->buf[dest->ln + 1] = '\0'; | ||||||
|     dest->ln += 1; |     dest->ln += 1; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										192
									
								
								src/exec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								src/exec.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | |||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include "include/ast.h" | ||||||
|  | #include "include/builtin.h" | ||||||
|  | #include "include/exec.h" | ||||||
|  | #include "include/htab.h" | ||||||
|  | #include "include/scope.h" | ||||||
|  | #include "include/util.h" | ||||||
|  |  | ||||||
|  | AST* exec_start(AST* ast) { | ||||||
|  |     log_dbg("Started execution."); | ||||||
|  |  | ||||||
|  |     if (!ast) return ast; | ||||||
|  |  | ||||||
|  |     Scope* global = scope_init(NULL); | ||||||
|  |     global->uses = 1; | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < BUILTIN_FNS_LN; i++) | ||||||
|  |         htab_ins( | ||||||
|  |             global->here, BUILTIN_FNS[i].name, | ||||||
|  |             ast_init(AST_TYPE_BIF, ast_bif_data_init(BUILTIN_FNS[i].fn)) | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |     AST* defnum = | ||||||
|  |         ast_init(AST_TYPE_LIT_KIND, ast_kind_data_init(AST_LIT_KIND_NUM)); | ||||||
|  |     htab_ins(global->here, "Num", defnum); | ||||||
|  |  | ||||||
|  |     AST* defbool = | ||||||
|  |         ast_init(AST_TYPE_LIT_KIND, ast_kind_data_init(AST_LIT_KIND_BOOL)); | ||||||
|  |     htab_ins(global->here, "Bool", defbool); | ||||||
|  |  | ||||||
|  |     AST* defkind = | ||||||
|  |         ast_init(AST_TYPE_LIT_KIND, ast_kind_data_init(AST_LIT_KIND_KIND)); | ||||||
|  |     htab_ins(global->here, "Type", defkind); | ||||||
|  |  | ||||||
|  |     log_dbg("Completed startup sequence."); | ||||||
|  |  | ||||||
|  |     AST* res = exec_exp(ast, global); | ||||||
|  |  | ||||||
|  |     return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_exp(AST* ast, Scope* parent) { | ||||||
|  |     switch (ast->type) { | ||||||
|  |         case AST_TYPE_BLOCK: return exec_block(ast, parent); | ||||||
|  |         case AST_TYPE_CALL:  return exec_call(ast, parent); | ||||||
|  |         case AST_TYPE_LIT_NUM: | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_LIT_NUM, ast_num_data_init(*(ASTNumData*)ast->data) | ||||||
|  |             ); | ||||||
|  |         case AST_TYPE_LIT_BOOL: | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_LIT_BOOL, ast_bool_data_init(*(ASTBoolData*)ast->data) | ||||||
|  |             ); | ||||||
|  |         case AST_TYPE_REF:      return exec_ref(ast, parent); | ||||||
|  |         case AST_TYPE_DEF:      return exec_def(ast, parent); | ||||||
|  |         case AST_TYPE_BIF: | ||||||
|  |         case AST_TYPE_LAMBDA:   return ast; | ||||||
|  |         case AST_TYPE_FORCE:    return exec_force(ast, parent); | ||||||
|  |         case AST_TYPE_PRESERVE: return exec_preserve(ast, parent); | ||||||
|  |         default:                printf("what\n"); exit(1); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_block(AST* ast, Scope* parent) { | ||||||
|  |     ASTBlockData* block = (ASTBlockData*)ast->data; | ||||||
|  |  | ||||||
|  |     exec_new_scope(ast, parent); | ||||||
|  |  | ||||||
|  |     // Loop through all but last ast. | ||||||
|  |     for (int i = 0; i < block->ln - 1; i++) | ||||||
|  |         exec_exp(block->inside[i], ast->scope); | ||||||
|  |     AST* last = exec_exp(block->inside[block->ln - 1], ast->scope); | ||||||
|  |  | ||||||
|  |     return last; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_call(AST* ast, Scope* parent) { | ||||||
|  |     ASTCallData* calldata = (ASTCallData*)ast->data; | ||||||
|  |  | ||||||
|  |     AST* exp = exec_exp(calldata->exp, parent); | ||||||
|  |  | ||||||
|  |     switch (exp->type) { | ||||||
|  |         case AST_TYPE_BIF: | ||||||
|  |             return ((ASTBIFData)exp->data)( | ||||||
|  |                 calldata->argc, calldata->argv, parent | ||||||
|  |             ); | ||||||
|  |         case AST_TYPE_LAMBDA: | ||||||
|  |             return exec_lambda(calldata->argc, calldata->argv, exp, parent); | ||||||
|  |         default: | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, ast_exc_data_init("Uncallable.", NULL) | ||||||
|  |             ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_def(AST* ast, Scope* parent) { | ||||||
|  |     // Use parent's scope. | ||||||
|  |     exec_inherit_scope(ast, parent); | ||||||
|  |  | ||||||
|  |     ASTDefData* data = (ASTDefData*)ast->data; | ||||||
|  |     AST* val = data->exp; | ||||||
|  |     char* key = data->name; | ||||||
|  |  | ||||||
|  |     if (data->kind) { | ||||||
|  |  | ||||||
|  |         ASTKindData kind = *(ASTKindData*)exec_exp(data->kind, parent)->data == | ||||||
|  |                            AST_LIT_KIND_NUM; | ||||||
|  |  | ||||||
|  |         if (kind == AST_LIT_KIND_NUM && data->exp->type != AST_TYPE_LIT_NUM) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, ast_exc_data_init("Expected Num.", NULL) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |         if (kind == AST_LIT_KIND_BOOL && data->exp->type != AST_TYPE_LIT_BOOL) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, ast_exc_data_init("Expected Bool.", NULL) | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |         if (kind == AST_LIT_KIND_KIND && data->exp->type != AST_TYPE_LIT_KIND) | ||||||
|  |             return ast_init( | ||||||
|  |                 AST_TYPE_EXC, ast_exc_data_init("Expected Type.", NULL) | ||||||
|  |             ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     scope_add(parent, key, val); // Add variable definition to parent scope. | ||||||
|  |     return exec_exp(val, parent); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_ref(AST* ast, Scope* parent) { | ||||||
|  |     // Use parent's scope. | ||||||
|  |     exec_inherit_scope(ast, parent); | ||||||
|  |     log_dbg("attempting to reference var"); | ||||||
|  |     ASTRefData* ref = (ASTRefData*)ast->data; | ||||||
|  |  | ||||||
|  |     AST* found = ast_find(parent, ref->to); | ||||||
|  |  | ||||||
|  |     if (found == NULL) { | ||||||
|  |         // TODO: Better memory management here. | ||||||
|  |         static char msg[256]; | ||||||
|  |         snprintf( | ||||||
|  |             msg, sizeof(msg), "Could not find value in scope for `%s`.", ref->to | ||||||
|  |         ); | ||||||
|  |         return ast_init(AST_TYPE_EXC, ast_exc_data_init(msg, NULL)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // return exec_exp(found, ast->scope); | ||||||
|  |     return found; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_lambda(size_t argc, AST** argv, AST* exp, Scope* parent) { | ||||||
|  |     Scope* callscope = scope_init(parent); | ||||||
|  |     ASTLambdaData* lambda = (ASTLambdaData*)exp->data; | ||||||
|  |     for (int i = 0; i < argc; i++) { | ||||||
|  |         char* key = ((ASTArgData*)lambda->parv[i]->data)->name; | ||||||
|  |         AST* val = exec_exp(argv[i], parent); | ||||||
|  |         scope_add(callscope, key, val); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return exec_exp(lambda->body, callscope); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_force(AST* ast, Scope* parent) { | ||||||
|  |     AST* body = ((ASTForceData*)ast->data)->body; | ||||||
|  |  | ||||||
|  |     if (body->type == AST_TYPE_REF) { | ||||||
|  |         return exec_exp(exec_ref(body, parent), parent); | ||||||
|  |     } else return exec_exp(body, parent); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | AST* exec_preserve(AST* ast, Scope* parent) { | ||||||
|  |     return ((ASTPreserveData*)ast->data)->body; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void exec_print(double n) { printf("= %lf\n", n); } | ||||||
|  |  | ||||||
|  | inline void exec_new_scope(AST* ast, Scope* inherit) { | ||||||
|  |     Scope* scope = scope_init(inherit); | ||||||
|  |     ast->scope = scope; | ||||||
|  |  | ||||||
|  |     // Update linked status. | ||||||
|  |     scope->uses++; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void exec_inherit_scope(AST* ast, Scope* inherit) { | ||||||
|  |     ast->scope = inherit; | ||||||
|  |  | ||||||
|  |     // Update uses. | ||||||
|  |     inherit->uses++; | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								src/fnv1a.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/fnv1a.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | #include "include/fnv1a.h" | ||||||
|  | #include "include/util.h" | ||||||
|  | #include "include/util.h" | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | uint64_t fnv1a_hash(char* key, size_t ln) { | ||||||
|  |     uint64_t hash = FNV1A_BASIS_64; | ||||||
|  |  | ||||||
|  |     for (size_t i = 0; i < ln; i++) { | ||||||
|  |         hash ^= (unsigned char)key[i]; | ||||||
|  |         hash *= FNV1A_PRIME_64; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     log_dbgf("Hash of %s was %lu", key, hash); | ||||||
|  |  | ||||||
|  |     return hash; | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								src/gc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/gc.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | #include "include/gc.h" | ||||||
|  | #include "include/ast.h" | ||||||
|  | #include "include/scope.h" | ||||||
|  | #include "include/util.h" | ||||||
|  | #include <assert.h> | ||||||
|  | #include <stdio.h> | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | GC* gclist = NULL; | ||||||
|  |  | ||||||
|  | void gc_destroy(GC* gc) { free(gc); } | ||||||
|  |  | ||||||
|  | void* gc_alloc(size_t sz, GCType type) { | ||||||
|  |     assert(type <= GC_TYPE_MAX); | ||||||
|  |  | ||||||
|  |     void* mem = malloc(sz); | ||||||
|  |     GC* gc = malloc(sizeof(GC)); | ||||||
|  |  | ||||||
|  |     gc->p = mem; | ||||||
|  |     gc->type = type; | ||||||
|  |     gc->marked = false; | ||||||
|  |     gc->nxt = gclist; | ||||||
|  |     gclist = gc; | ||||||
|  |  | ||||||
|  |     if (type == GC_TYPE_AST) { | ||||||
|  |         log_dbgf("Alloc'd AST for GC: %p", mem); | ||||||
|  |     } else if (type == GC_TYPE_SCOPE) { | ||||||
|  |         log_dbgf("Alloc'd scope for GC: %p", mem); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return mem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void gc_hack_free() { | ||||||
|  |     while (gclist) { | ||||||
|  |         GC* gc = gclist; | ||||||
|  |         gclist = gclist->nxt; | ||||||
|  |         switch (gc->type) { | ||||||
|  |             case GC_TYPE_AST: | ||||||
|  |                 if (((AST*)gc->p)->type > AST_TYPE_MAX) { | ||||||
|  |                     log_dbgf( | ||||||
|  |                         "Attempted to free invalid AST (%i > %i) to GC: gc:%p " | ||||||
|  |                         "ast:%p", | ||||||
|  |                         ((AST*)gc->p)->type, AST_TYPE_MAX, gc, gc->p | ||||||
|  |                     ); | ||||||
|  |                 } | ||||||
|  |                 ast_destroy(gc->p); | ||||||
|  |                 break; | ||||||
|  |             case GC_TYPE_SCOPE: scope_destroy_psv(gc->p); break; | ||||||
|  |         } | ||||||
|  |         gc_destroy(gc); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										6
									
								
								src/global.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/global.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | #include "include/global.h" | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | // Global input text. | ||||||
|  | char* inp = NULL; | ||||||
							
								
								
									
										412
									
								
								src/grammar.y
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										412
									
								
								src/grammar.y
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,412 @@ | |||||||
|  | %{ | ||||||
|  |     #include <string.h> | ||||||
|  |     #include <stdio.h> | ||||||
|  |     #include "../../src/include/ast.h" | ||||||
|  |     #include "../../src/include/lexer.h" | ||||||
|  |     #include "../../src/include/dlist.h" | ||||||
|  |     #include "../../src/include/builtin.h" | ||||||
|  |  | ||||||
|  |     int yylex(void); | ||||||
|  |     void yyerror(char const*); | ||||||
|  |  | ||||||
|  |     AST* root = NULL; | ||||||
|  | %} | ||||||
|  |  | ||||||
|  | %code requires { | ||||||
|  |     #include "../../src/include/ast.h" | ||||||
|  |     #include "../../src/include/dlist.h" | ||||||
|  |     #include "../../src/include/builtin.h" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | %union { | ||||||
|  |     double fval; | ||||||
|  |     char* strval; | ||||||
|  |     AST* ast; | ||||||
|  |     ArgArr* argarr; | ||||||
|  |     DList* exps; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | %define parse.error verbose | ||||||
|  |  | ||||||
|  | %token BOOLT // Boolean true (TRUE or T). | ||||||
|  | %token BOOLF // Boolean false (FALSE or F). | ||||||
|  |  | ||||||
|  | %token IF // if or ?. | ||||||
|  | %token ELSE // else or :. | ||||||
|  |  | ||||||
|  | %token BLOCKS // Block start {. | ||||||
|  | %token BLOCKE // Block end }. | ||||||
|  |  | ||||||
|  | %token GROUPS // Group start (. | ||||||
|  | %token GROUPE // Group end ). | ||||||
|  | %token SEP // Seperator ,. | ||||||
|  |  | ||||||
|  | %token EQ // Equals =. | ||||||
|  | %token DEQ // Double equals ==. | ||||||
|  |  | ||||||
|  | %token RARROW // Right arrow ->. | ||||||
|  | %token LARROW // Left arrow <-. | ||||||
|  |  | ||||||
|  | %token EXPSEP // Expression seperator ;. | ||||||
|  |  | ||||||
|  | %token<strval> WORD // Word, i.e. keyword. | ||||||
|  | %token<fval> NUM // Number. | ||||||
|  |  | ||||||
|  | %token SUB // Subtract -. | ||||||
|  | %token ADD // Addition *. | ||||||
|  | %token MUL // Multiplication *. | ||||||
|  | %token DIV // Division /. | ||||||
|  |  | ||||||
|  | %token NL // Newline. | ||||||
|  |  | ||||||
|  | %token COLON // Colon :. | ||||||
|  | %token STOP // Stop sign $. | ||||||
|  |  | ||||||
|  | %token FORCE // Force operator !. | ||||||
|  | %token PRESERVE // Preserve operator @. | ||||||
|  |  | ||||||
|  | %token BACKSLASH | ||||||
|  |  | ||||||
|  | %left ADD SUB | ||||||
|  | %left MUL DIV | ||||||
|  | %left RARROW | ||||||
|  | %right LARROW | ||||||
|  | %nonassoc STOP | ||||||
|  | %precedence NEG | ||||||
|  |  | ||||||
|  | %type<ast> exp; | ||||||
|  | %type<argarr> arg; | ||||||
|  | %type<argarr> argstart; | ||||||
|  | %type<exps> blockstart; | ||||||
|  | %type<exps> block; | ||||||
|  | %type<exps> inputstart | ||||||
|  | %type<exps> input | ||||||
|  |  | ||||||
|  | %start inputend // This makes no sense but w/e. | ||||||
|  |  | ||||||
|  | %% | ||||||
|  |  | ||||||
|  | maybe_stop: %empty | STOP; | ||||||
|  |  | ||||||
|  | inputstart: | ||||||
|  |     exp { | ||||||
|  |         DList* exps = dlist_init(); | ||||||
|  |         dlist_append(exps, $1); | ||||||
|  |         $$ = exps; | ||||||
|  |     } | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  | input: | ||||||
|  |     inputstart { | ||||||
|  |         $$ = $1; | ||||||
|  |     } | ||||||
|  |     | input EXPSEP exp { | ||||||
|  |         dlist_append($1, $3); | ||||||
|  |         $$ = $1; | ||||||
|  |     } | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  | inputend: | ||||||
|  |     %empty | ||||||
|  |     | input { | ||||||
|  |         root = ast_init(AST_TYPE_BLOCK, ast_block_data_init((AST**) $1->buf, $1->ln)); | ||||||
|  |         dlist_destroypsv($1); | ||||||
|  |     } | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  | argstart: | ||||||
|  |     exp { | ||||||
|  |         ArgArr* argarr = argarr_init(); | ||||||
|  |         argarr_add(argarr, $1); | ||||||
|  |         $$ = argarr; | ||||||
|  |     } | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  | arg: | ||||||
|  |     argstart { $$ = $1; } | ||||||
|  |     | arg SEP exp { | ||||||
|  |         argarr_add($1, $3); | ||||||
|  |         $$ = $1; | ||||||
|  |     } | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  | blockstart: | ||||||
|  |     exp { | ||||||
|  |         DList* exps = dlist_init(); // List of expressions. | ||||||
|  |         dlist_append(exps, $1); | ||||||
|  |         $$ = exps; | ||||||
|  |     } | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  | block: | ||||||
|  |      blockstart { $$ = $1; } | ||||||
|  |      | block EXPSEP exp { | ||||||
|  |         dlist_append($1, $3); | ||||||
|  |         $$ = $1; | ||||||
|  |     } | ||||||
|  |     ; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | exp: | ||||||
|  |     // Stop sign. | ||||||
|  |     exp STOP { $$ = $1; } | ||||||
|  |  | ||||||
|  |     // Variable reference. | ||||||
|  |     | WORD { | ||||||
|  |         $$ = ast_init(AST_TYPE_REF, ast_ref_data_init($1)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Call (general form). | ||||||
|  |     | exp GROUPS arg GROUPE { | ||||||
|  |         size_t argc = $3->ln; | ||||||
|  |         AST** argv = $3->buf; | ||||||
|  |         argarr_destroypsv($3); | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             argc, | ||||||
|  |             argv, | ||||||
|  |             $1 | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Call (general hacky form). | ||||||
|  |     | exp GROUPS GROUPE { | ||||||
|  |         size_t argc = 1; | ||||||
|  |         AST** argv = NULL; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             argc, | ||||||
|  |             argv, | ||||||
|  |             $1 | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Call (right arrow general form). | ||||||
|  |     | GROUPS arg GROUPE RARROW exp { | ||||||
|  |         size_t argc = $2->ln; | ||||||
|  |         AST** argv = $2->buf; | ||||||
|  |         argarr_destroypsv($2); | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             argc, | ||||||
|  |             argv, | ||||||
|  |             $5 | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | exp RARROW exp { | ||||||
|  |         size_t argc = 1; | ||||||
|  |         AST** argv = malloc(sizeof(AST*)); | ||||||
|  |         argv[0] = $1; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             argc, | ||||||
|  |             argv, | ||||||
|  |             $3 | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | exp LARROW exp { | ||||||
|  |         size_t argc = 1; | ||||||
|  |         AST** argv = malloc(sizeof(AST*)); | ||||||
|  |         argv[0] = $3; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             argc, | ||||||
|  |             argv, | ||||||
|  |             $1 | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Call (convenient form). | ||||||
|  |     | WORD GROUPS arg GROUPE { | ||||||
|  |         size_t argc = $3->ln; | ||||||
|  |         AST** argv = $3->buf; | ||||||
|  |         argarr_destroypsv($3); | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             argc, | ||||||
|  |             argv, | ||||||
|  |             ast_init(AST_TYPE_REF, ast_ref_data_init($1)) | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     // Call (hacky convenient form). | ||||||
|  |     | WORD GROUPS GROUPE { | ||||||
|  |         size_t argc = 0; | ||||||
|  |         AST** argv = NULL; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             argc, | ||||||
|  |             argv, | ||||||
|  |             ast_init(AST_TYPE_REF, ast_ref_data_init($1)) | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Number. | ||||||
|  |     | NUM { $$ = ast_init(AST_TYPE_LIT_NUM, ast_num_data_init($1)); } | ||||||
|  |  | ||||||
|  |     | BOOLT { $$ = ast_init(AST_TYPE_LIT_BOOL, ast_bool_data_init(1)); } | ||||||
|  |     | BOOLF { $$ = ast_init(AST_TYPE_LIT_BOOL, ast_bool_data_init(0)); } | ||||||
|  |  | ||||||
|  |     | exp DEQ exp { | ||||||
|  |         AST** argv = calloc(2, sizeof(AST*)); | ||||||
|  |         argv[0] = $1; | ||||||
|  |         argv[1] = $3; | ||||||
|  |  | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             2, | ||||||
|  |             argv, | ||||||
|  |             ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_eq)) | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | IF exp exp exp { | ||||||
|  |         AST** argv = calloc(3, sizeof(AST*)); | ||||||
|  |         argv[0] = $2; | ||||||
|  |         argv[1] = $3; | ||||||
|  |         argv[2] = $4; | ||||||
|  |  | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             3, | ||||||
|  |             argv, | ||||||
|  |             ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_if)) | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | IF exp exp ELSE exp { | ||||||
|  |         AST** argv = calloc(3, sizeof(AST*)); | ||||||
|  |         argv[0] = $2; | ||||||
|  |         argv[1] = $3; | ||||||
|  |         argv[2] = $5; | ||||||
|  |  | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, ast_call_data_init( | ||||||
|  |             3, | ||||||
|  |             argv, | ||||||
|  |             ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_if)) | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Function definitions. Convert to Def of Lambda. | ||||||
|  |     | WORD GROUPS arg GROUPE exp maybe_stop { | ||||||
|  |         size_t parc = $3->ln; | ||||||
|  |         AST** parv = $3->buf; | ||||||
|  |         argarr_destroypsv($3); | ||||||
|  |         $$ = ast_init(AST_TYPE_DEF, ast_def_data_init( | ||||||
|  |             $1, | ||||||
|  |             NULL, | ||||||
|  |             ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init( | ||||||
|  |                 parc, parv, $5 | ||||||
|  |             )) | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Lambda definitions. | ||||||
|  |     | BACKSLASH GROUPS arg GROUPE exp { | ||||||
|  |         size_t parc = $3->ln; | ||||||
|  |         AST** parv = $3->buf; | ||||||
|  |         argarr_destroypsv($3); | ||||||
|  |         $$ = ast_init(AST_TYPE_LAMBDA, ast_lambda_data_init(parc, parv, $5)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Force operator. | ||||||
|  |     | FORCE exp { | ||||||
|  |         $$ = ast_init(AST_TYPE_FORCE, ast_force_data_init($2)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Preserve operator. | ||||||
|  |     | PRESERVE exp { | ||||||
|  |         $$ = ast_init(AST_TYPE_PRESERVE, ast_preserve_data_init($2)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Block. | ||||||
|  |     | BLOCKS block BLOCKE { | ||||||
|  |         AST** exps = (AST**) $2->buf; | ||||||
|  |         dlist_destroypsv($2); | ||||||
|  |         $$ = ast_init(AST_TYPE_BLOCK, ast_block_data_init((AST**) exps, $2->ln)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Negative. | ||||||
|  |     | SUB exp { | ||||||
|  |         AST** argv = calloc(2, sizeof(AST*)); | ||||||
|  |         argv[0] = ast_init(AST_TYPE_LIT_NUM, ast_num_data_init(-1)); | ||||||
|  |         argv[1] = $2; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, | ||||||
|  |             ast_call_data_init( | ||||||
|  |                 2, | ||||||
|  |                 argv, | ||||||
|  |                 ast_init(AST_TYPE_BIF, | ||||||
|  |                     ast_bif_data_init(builtin_mul) | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Group. | ||||||
|  |     | GROUPS exp GROUPE { $$ = $2; } | ||||||
|  |  | ||||||
|  |     // Definition with type annotation. | ||||||
|  |     | WORD COLON exp EQ exp { | ||||||
|  |         $$ = ast_init(AST_TYPE_DEF, ast_def_data_init($1, $3, $5)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Definition with type annotation. | ||||||
|  |     | WORD COLON WORD EQ exp { | ||||||
|  |         $$ = ast_init(AST_TYPE_DEF, ast_def_data_init( | ||||||
|  |             $1, | ||||||
|  |             ast_init(AST_TYPE_REF, ast_ref_data_init($3)), | ||||||
|  |             $5 | ||||||
|  |         )); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Definition. | ||||||
|  |     | WORD EQ exp { | ||||||
|  |         $$ = ast_init(AST_TYPE_DEF, ast_def_data_init($1, NULL, $3)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | exp ADD exp { | ||||||
|  |         AST** argv = calloc(2, sizeof(AST*)); | ||||||
|  |         argv[0] = $1; | ||||||
|  |         argv[1] = $3; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, | ||||||
|  |             ast_call_data_init( | ||||||
|  |                 2, | ||||||
|  |                 argv, | ||||||
|  |                 ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_sum)) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | exp SUB exp { | ||||||
|  |         AST** argv = calloc(2, sizeof(AST*)); | ||||||
|  |         argv[0] = $1; | ||||||
|  |         argv[1] = $3; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, | ||||||
|  |             ast_call_data_init( | ||||||
|  |                 2, | ||||||
|  |                 argv, | ||||||
|  |                 ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_sub)) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | exp MUL exp { | ||||||
|  |         AST** argv = calloc(2, sizeof(AST*)); | ||||||
|  |         argv[0] = $1; | ||||||
|  |         argv[1] = $3; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, | ||||||
|  |             ast_call_data_init( | ||||||
|  |                 2, | ||||||
|  |                 argv, | ||||||
|  |                 ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_mul)) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     | exp DIV exp { | ||||||
|  |         AST** argv = calloc(2, sizeof(AST*)); | ||||||
|  |         argv[0] = $1; | ||||||
|  |         argv[1] = $3; | ||||||
|  |         $$ = ast_init(AST_TYPE_CALL, | ||||||
|  |             ast_call_data_init( | ||||||
|  |                 2, | ||||||
|  |                 argv, | ||||||
|  |                 ast_init(AST_TYPE_BIF, ast_bif_data_init(builtin_div)) | ||||||
|  |             ) | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | %% | ||||||
							
								
								
									
										36
									
								
								src/htab.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/htab.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | #include "include/htab.h" | ||||||
|  | #include "include/fnv1a.h" | ||||||
|  | #include "include/util.h" | ||||||
|  |  | ||||||
|  | #include <assert.h> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | HTab* htab_init() { | ||||||
|  |     HTab* htab = calloc(1, sizeof(HTab)); | ||||||
|  |  | ||||||
|  |     log_dbgf("HTAB %p", htab); | ||||||
|  |  | ||||||
|  |     return htab; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void htab_destroy(HTab* htab) { free(htab); } | ||||||
|  |  | ||||||
|  | // Get the index of a key. | ||||||
|  | size_t geti(char* key) { | ||||||
|  |     uint64_t hash = fnv1a_hash(key, strlen(key)); | ||||||
|  |     size_t i = hash & (HTAB_SPACE - 1); // Magic. | ||||||
|  |     return i; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void* htab_get(HTab* htab, char* key) { | ||||||
|  |     size_t i = geti(key); | ||||||
|  |     log_dbgf("Getting something from hash table @ index %lu", i); | ||||||
|  |     return (*htab)[i]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void htab_ins(HTab* htab, char* key, void* data) { | ||||||
|  |     size_t i = geti(key); | ||||||
|  |     (*htab)[i] = data; | ||||||
|  |     log_dbgf("Inserted something to hash table @ index %lu", i); | ||||||
|  | } | ||||||
							
								
								
									
										193
									
								
								src/include/ast.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								src/include/ast.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | |||||||
|  | #ifndef AST_H | ||||||
|  | #define AST_H | ||||||
|  |  | ||||||
|  | #include "scope.h" | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | // The type of an `AST`. | ||||||
|  | typedef enum { | ||||||
|  |     // Primitive type literals. | ||||||
|  |     AST_TYPE_LIT_NUM,  // A number (float) literal. | ||||||
|  |     AST_TYPE_LIT_BOOL, // A boolean literal. | ||||||
|  |     AST_TYPE_LIT_VEC,  // A vector literal. | ||||||
|  |     AST_TYPE_LIT_KIND, // A kind literal. | ||||||
|  |  | ||||||
|  |     AST_TYPE_EXC_CON,  // Exception constructor `Exc`. | ||||||
|  |     AST_TYPE_VEC_CON,  // Vectpr constructor `Vec()`. | ||||||
|  |  | ||||||
|  |     // Collection types: | ||||||
|  |     AST_TYPE_VEC,  // A vector (fixed size, fixed type). | ||||||
|  |     AST_TYPE_LIST, // A list (variable size, variable type). | ||||||
|  |  | ||||||
|  |     // Syntactic types: | ||||||
|  |     AST_TYPE_FORCE, | ||||||
|  |     AST_TYPE_PRESERVE, | ||||||
|  |     AST_TYPE_BLOCK,  // A block of code (scope). | ||||||
|  |     AST_TYPE_ARG,    // A definition argument. | ||||||
|  |  | ||||||
|  |     // Misc. types. | ||||||
|  |     AST_TYPE_BIF,    // Built-in function. | ||||||
|  |     AST_TYPE_CALL,   // A function call. | ||||||
|  |     AST_TYPE_DEF,   // A definition. | ||||||
|  |     AST_TYPE_REF,   // A variable reference. | ||||||
|  |     AST_TYPE_LAMBDA, // An anonymous function definition. | ||||||
|  |     AST_TYPE_EXC,   // An exception. | ||||||
|  |     AST_TYPE_MAX = AST_TYPE_EXC, | ||||||
|  | } ASTType; | ||||||
|  |  | ||||||
|  | // An Abstract Syntax Tree. | ||||||
|  | typedef struct { | ||||||
|  |     ASTType type; // The type of the `AST`. | ||||||
|  |     void* data;   // The data of the `AST`. | ||||||
|  |     Scope* scope; // The scope of the `AST`. | ||||||
|  | } AST; | ||||||
|  |  | ||||||
|  | // Create a new `AST`. | ||||||
|  | AST* ast_init(ASTType type, void* data); | ||||||
|  | // Create a new `AST` with a specified scope. | ||||||
|  | AST* ast_init_scope(ASTType type, void* data, Scope* scope); | ||||||
|  | // Destroy an `AST`. | ||||||
|  | void ast_destroy(AST* ast); | ||||||
|  |  | ||||||
|  | // A number. | ||||||
|  | typedef double ASTNumData; | ||||||
|  |  | ||||||
|  | // Create a new `ASTNumData`. | ||||||
|  | ASTNumData* ast_num_data_init(double val); | ||||||
|  | // Destroy an `ASTNumData`. | ||||||
|  | void ast_num_data_destroy(ASTNumData* num); | ||||||
|  |  | ||||||
|  | // A boolean. | ||||||
|  | typedef int ASTBoolData; | ||||||
|  |  | ||||||
|  | // Create a new `ASTBoolData`. | ||||||
|  | ASTBoolData* ast_bool_data_init(int val); | ||||||
|  | // Destroy an `ASTBoolData`. | ||||||
|  | void ast_bool_data_destroy(ASTBoolData* bol); | ||||||
|  |  | ||||||
|  | // A literal kind. | ||||||
|  | typedef enum { | ||||||
|  |     AST_LIT_KIND_BOOL, | ||||||
|  |     AST_LIT_KIND_NUM, | ||||||
|  |     AST_LIT_KIND_KIND, | ||||||
|  |     AST_LIT_KIND_MAX = AST_LIT_KIND_KIND | ||||||
|  | } ASTKindData; | ||||||
|  |  | ||||||
|  | extern const char* ast_lit_kind_names[AST_LIT_KIND_MAX + 2]; | ||||||
|  |  | ||||||
|  | // Create a new `ASTKindData`. | ||||||
|  | ASTKindData* ast_kind_data_init(ASTKindData); | ||||||
|  |  | ||||||
|  | // Destroy an `ASTKindData`. | ||||||
|  | void ast_kind_data_destroy(ASTKindData*); | ||||||
|  |  | ||||||
|  | // An exception. | ||||||
|  | typedef struct ASTEXCDATA { | ||||||
|  |     const char* msg; // The exception message. | ||||||
|  |     AST* trace;      // The previous exception. | ||||||
|  | } ASTExcData; | ||||||
|  | // Create a new `ASTExecData. `msg` should be static. | ||||||
|  | ASTExcData* ast_exc_data_init(const char* msg, AST* trace); | ||||||
|  | // Destroy an `ASTExecData`. | ||||||
|  | void ast_exc_data_destroy(ASTExcData* exc); | ||||||
|  |  | ||||||
|  | // Argument list as anonymous struct. | ||||||
|  | #define ARGS                                                                   \ | ||||||
|  |     struct {                                                                   \ | ||||||
|  |         size_t argc;                                                           \ | ||||||
|  |         AST** argv;                                                            \ | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | // Parameter list as anonymous struct. | ||||||
|  | #define PARS                                                                   \ | ||||||
|  |     struct {                                                                   \ | ||||||
|  |         size_t parc;                                                           \ | ||||||
|  |         AST** parv;                                                            \ | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | // A built-in function. | ||||||
|  | typedef AST* (*ASTBIFData)(size_t argc, AST** argv, Scope* scope); | ||||||
|  |  | ||||||
|  | // Create a built-in function. | ||||||
|  | ASTBIFData* ast_bif_data_init(AST* fn(size_t, AST**, Scope*)); | ||||||
|  | // Destroy an `ASTBIFData`. | ||||||
|  | void ast_bif_data_destroy(ASTBIFData* bif); | ||||||
|  |  | ||||||
|  | // A lambda. | ||||||
|  | typedef struct { | ||||||
|  |     PARS;      // The parameters the lambda can accept. | ||||||
|  |     AST* body; // The body expression to be executed. | ||||||
|  | } ASTLambdaData; | ||||||
|  |  | ||||||
|  | // Creates a new `ASTLambdaData`. | ||||||
|  | ASTLambdaData* ast_lambda_data_init(size_t parc, AST** parv, AST* body); | ||||||
|  | // Destroy an `ASTLambdaData`. | ||||||
|  | void ast_lambda_data_destroy(ASTLambdaData*); | ||||||
|  |  | ||||||
|  | // A call. | ||||||
|  | typedef struct { | ||||||
|  |     ARGS;     // The arguments the call is made with. | ||||||
|  |     AST* exp; // The expression the call is to. | ||||||
|  | } ASTCallData; | ||||||
|  |  | ||||||
|  | // Create a new `ASTCallData`. | ||||||
|  | ASTCallData* ast_call_data_init(size_t argc, AST** argv, AST* exp); | ||||||
|  | // Destroy an `ASTCallData`. | ||||||
|  | void ast_call_data_destroy(ASTCallData* call); | ||||||
|  |  | ||||||
|  | // A definition. Associates a name and kind with an expression. | ||||||
|  | typedef struct { | ||||||
|  |     char* name; | ||||||
|  |     AST* kind; // If NULL, assume `Any` kind. | ||||||
|  |     AST* exp; | ||||||
|  | } ASTDefData; | ||||||
|  |  | ||||||
|  | // Create a new `ASTDefData`. | ||||||
|  | ASTDefData* ast_def_data_init(char* name, AST* kind, AST* exp); | ||||||
|  | // Destroy an `ASTDefData`. | ||||||
|  | void ast_def_data_destroy(ASTDefData* vdef); | ||||||
|  |  | ||||||
|  | // A reference. | ||||||
|  | typedef struct { | ||||||
|  |     char* to; // What the reference's to. | ||||||
|  | } ASTRefData; | ||||||
|  |  | ||||||
|  | // Create a new `ASTRefData`. | ||||||
|  | ASTRefData* ast_ref_data_init(char* to); | ||||||
|  | // Destroy an `ASTRefData`. | ||||||
|  | void ast_ref_data_destroy(ASTRefData* call); | ||||||
|  |  | ||||||
|  | // A code block. | ||||||
|  | typedef struct { | ||||||
|  |     AST** inside; // What's inside the block. | ||||||
|  |     size_t ln;    // How many ASTs are in the block. | ||||||
|  | } ASTBlockData; | ||||||
|  |  | ||||||
|  | // Create a new `ASTBlockData`. | ||||||
|  | ASTBlockData* ast_block_data_init(AST** inside, size_t ln); | ||||||
|  | // Destroy an `ASTBlockData`, recursively. | ||||||
|  | void ast_block_data_destroy(ASTBlockData* block); | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     char* name; // Argument name. | ||||||
|  | } ASTArgData; | ||||||
|  |  | ||||||
|  | // Create a new `ASTArgData`. | ||||||
|  | ASTArgData* ast_arg_data_init(char* name); | ||||||
|  | // Destroy an `ASTArgData`. | ||||||
|  | void ast_arg_data_destroy(ASTArgData* arg); | ||||||
|  |  | ||||||
|  | // Find the expression associated with a name in the nearest scope. | ||||||
|  | AST* ast_find(Scope* scope, char* name); | ||||||
|  |  | ||||||
|  | // A force operator. | ||||||
|  | typedef struct {AST* body;} ASTForceData; | ||||||
|  | ASTForceData* ast_force_data_init(AST* body); | ||||||
|  | void ast_force_data_destroy(ASTForceData* force); | ||||||
|  |  | ||||||
|  | // A preserve operator. | ||||||
|  | typedef struct {AST* body;} ASTPreserveData; | ||||||
|  | ASTPreserveData* ast_preserve_data_init(AST* body); | ||||||
|  | void ast_preserve_data_destroy(ASTPreserveData* preserve); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										49
									
								
								src/include/ast_print.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								src/include/ast_print.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | #ifndef AST_PRINT_H | ||||||
|  | #define AST_PRINT_H | ||||||
|  |  | ||||||
|  | #include "ast.h" | ||||||
|  |  | ||||||
|  | // Print an `AST`, recursively. | ||||||
|  | void ast_print(AST* ast); | ||||||
|  | // Helper function to `ast_print()`, where `i` is indentation level. | ||||||
|  | void ast_print_i(AST* ast, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTNumData`. | ||||||
|  | void ast_num_print(ASTNumData*, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTBoolData`. | ||||||
|  | void ast_bool_print(ASTBoolData*, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTKindData`. | ||||||
|  | void ast_kind_print(ASTKindData*, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTExecData`. | ||||||
|  | void ast_exc_print(ASTExcData*, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTCallData`. | ||||||
|  | void ast_call_print(ASTCallData*, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTDefData`. | ||||||
|  | void ast_def_print(ASTDefData*, int depth); | ||||||
|  |  | ||||||
|  | // Print an `ASTRefData`. | ||||||
|  | void ast_ref_print(ASTRefData*, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTBlockData`. | ||||||
|  | void ast_block_print(ASTBlockData*, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTArgData`. | ||||||
|  | void ast_arg_print(ASTArgData* arg, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTLambdaData`. | ||||||
|  | void ast_lambda_print(ASTLambdaData* arg, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTBIFData`. | ||||||
|  | void ast_bif_print(ASTBIFData* arg, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTForceData`. | ||||||
|  | void ast_force_print(ASTForceData* force, int i); | ||||||
|  |  | ||||||
|  | // Print an `ASTPreserveData`. | ||||||
|  | void ast_preserve_print(ASTPreserveData* preserve, int i); | ||||||
|  | #endif | ||||||
							
								
								
									
										44
									
								
								src/include/builtin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/include/builtin.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | #ifndef BUILTIN_H | ||||||
|  | #define BUILTIN_H | ||||||
|  |  | ||||||
|  | #include "ast.h" | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
|  | // Sum some nums. | ||||||
|  | AST* builtin_sum(size_t argc, AST** argv, Scope* parent); | ||||||
|  |  | ||||||
|  | // Subtract nums. | ||||||
|  | AST* builtin_sub(size_t argc, AST** argv, Scope* parent); | ||||||
|  |  | ||||||
|  | // Multiply nums. | ||||||
|  | AST* builtin_mul(size_t argc, AST** argv, Scope* parent); | ||||||
|  |  | ||||||
|  | // Divide nums. | ||||||
|  | AST* builtin_div(size_t argc, AST** argv, Scope* parent); | ||||||
|  |  | ||||||
|  | // Die. | ||||||
|  | AST* builtin_die(size_t argc, AST** argv, Scope* parent); | ||||||
|  |  | ||||||
|  | // If statement. | ||||||
|  | AST* builtin_if(size_t argc, AST** argv, Scope* parent); | ||||||
|  |  | ||||||
|  | // Equality. | ||||||
|  | AST* builtin_eq(size_t argc, AST** argv, Scope* parent); | ||||||
|  |  | ||||||
|  | struct builtin_data { | ||||||
|  |     char* name; | ||||||
|  |     AST* (*fn)(size_t argc, AST** argv, Scope* parent); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static struct builtin_data BUILTIN_FNS[] = { | ||||||
|  |     { "sum", builtin_sum }, | ||||||
|  |     { "sub", builtin_sub }, | ||||||
|  |     { "mul", builtin_mul }, | ||||||
|  |     { "div", builtin_div }, | ||||||
|  |     { "die", builtin_die }, | ||||||
|  |     {"_if", builtin_if}, | ||||||
|  |     {"eq", builtin_eq}, | ||||||
|  | }; | ||||||
|  | #define BUILTIN_FNS_LN (arrln(BUILTIN_FNS)) | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										24
									
								
								src/include/dlist.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/include/dlist.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #ifndef DLIST_H | ||||||
|  | #define DLIST_H | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #define DLIST_INITSZ 128 * sizeof(void*) | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     void** buf; // The buffer containing the list. | ||||||
|  |     size_t sz;  // The size of the buffer. | ||||||
|  |     size_t ln;  // The number of elements in the list. | ||||||
|  | } DList; | ||||||
|  |  | ||||||
|  | // Create a new `DList`. | ||||||
|  | DList* dlist_init(void); | ||||||
|  | // Destroy a `DList`. | ||||||
|  | void dlist_destroy(DList* dstr); | ||||||
|  | // Destroy `DList` structure but preserve `->buf`. | ||||||
|  | void dlist_destroypsv(DList* dstr); | ||||||
|  |  | ||||||
|  | // Append `src` to `dest`. | ||||||
|  | void dlist_append(DList* dest, void* src); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -7,17 +7,21 @@ | |||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     char* buf; // The buffer containing the string. |     char* buf; // The buffer containing the string. | ||||||
|     size_t bufsz; // The size of the buffer. |     size_t sz; // The size of the buffer. | ||||||
|     size_t ln; // The number of characters in the buffer. |     size_t ln; // The number of characters in the buffer. | ||||||
| } Dstr; | } Dstr; | ||||||
|  |  | ||||||
|  | // Initialize a `DStr`. | ||||||
| Dstr* dstr_init(void); | Dstr* dstr_init(void); | ||||||
|  | // Destroy a `DStr`. | ||||||
| void dstr_destroy(Dstr* dstr); | void dstr_destroy(Dstr* dstr); | ||||||
|  | // Destroy `DStr` structure but preserve `DStr->buf`. | ||||||
|  | void dstr_destroypsv(Dstr* dstr); | ||||||
|  |  | ||||||
| // Append ln characters of src to dest. | // Append `ln` characters of `src` to `dest`. | ||||||
| void dstr_append(Dstr* dest, char* src, size_t ln); | void dstr_append(Dstr* dest, char* src, size_t ln); | ||||||
|  |  | ||||||
| // Append ch to dest. | // Append `ch` to `dest`. | ||||||
| void dstr_appendch(Dstr* dest, char ch); | void dstr_appendch(Dstr* dest, char ch); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								src/include/exec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/include/exec.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | #ifndef EXEC_H | ||||||
|  | #define EXEC_H | ||||||
|  |  | ||||||
|  | #include "ast.h" | ||||||
|  | #include "scope.h" | ||||||
|  |  | ||||||
|  | // Start executing at the root of the AST. Initialize the `scope`. | ||||||
|  | AST* exec_start(AST* ast); | ||||||
|  | // Execute an expression. Delegates to the other executor functions. | ||||||
|  | AST* exec_exp(AST* ast, Scope* parent); | ||||||
|  | // Execute the expressions of a block. | ||||||
|  | AST* exec_block(AST* ast, Scope* parent); | ||||||
|  | // Execute a call. | ||||||
|  | AST* exec_call(AST* ast, Scope* parent); | ||||||
|  | // Execute a definition. | ||||||
|  | AST* exec_def(AST* ast, Scope* parent); | ||||||
|  | // Execute a reference. | ||||||
|  | AST* exec_ref(AST* ast, Scope* parent); | ||||||
|  | // Execute a function definition. | ||||||
|  | AST* exec_fdef(AST* ast, Scope* parent); | ||||||
|  | // Execute a lambda expression. | ||||||
|  | AST* exec_lambda(size_t argc, AST** argv, AST* exp, Scope* parent); | ||||||
|  | // Execute a force expression. | ||||||
|  | AST* exec_force(AST* ast, Scope* parent); | ||||||
|  | // Execute a preserve expression. | ||||||
|  | AST* exec_preserve(AST* ast, Scope* parent); | ||||||
|  | // Print the result of an execution. | ||||||
|  | void exec_print(double n); | ||||||
|  |  | ||||||
|  | // Create a new scope and mark it as linked. Also update inherited scope. | ||||||
|  | void exec_new_scope(AST* ast, Scope* inherit); | ||||||
|  |  | ||||||
|  | // Inherit from another scope and mark it as linked. | ||||||
|  | void exec_inherit_scope(AST* ast, Scope* inherit); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										18
									
								
								src/include/fnv1a.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/include/fnv1a.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | #ifndef FNV1A_H | ||||||
|  | #define FNV1A_H | ||||||
|  |  | ||||||
|  | // Implements the FNV-1a hash algorithm. | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | // FNV prime. | ||||||
|  | #define FNV1A_PRIME_64 0x00000100000001b3u | ||||||
|  |  | ||||||
|  | // Offset basis. | ||||||
|  | #define FNV1A_BASIS_64 0xcbf29ce484222325u | ||||||
|  |  | ||||||
|  | // Hash a string `str` of length `ln`. | ||||||
|  | uint64_t fnv1a_hash(char* str, size_t ln); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										32
									
								
								src/include/gc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/include/gc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | #ifndef GC_H | ||||||
|  | #define GC_H | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  |  | ||||||
|  | // The type a GC can refer to. | ||||||
|  | typedef enum { | ||||||
|  |     GC_TYPE_AST, | ||||||
|  |     GC_TYPE_SCOPE, | ||||||
|  |     GC_TYPE_MAX = GC_TYPE_SCOPE | ||||||
|  | } GCType; | ||||||
|  |  | ||||||
|  | // Added to each AST and Scope; keep track of what's actually still accessible. | ||||||
|  | typedef struct GC_STRUCT { | ||||||
|  |     void* p;               // Pointer to the data. | ||||||
|  |     struct GC_STRUCT* nxt; // The next GC in the linked list. | ||||||
|  |     GCType type;           // What type of data. | ||||||
|  |     bool marked;           // Whether the data is still accessible. | ||||||
|  | } GC; | ||||||
|  |  | ||||||
|  | GC* gc_init(void* p, GCType type, GC*); | ||||||
|  | // Does not free ->p or ->nxt. | ||||||
|  | void gc_destroy(GC* gc); | ||||||
|  |  | ||||||
|  | // Allocate for an object in the heap, and keep track of it in the GC. | ||||||
|  | void* gc_alloc(size_t sz, GCType type); | ||||||
|  |  | ||||||
|  | // Free everything, immediately. | ||||||
|  | void gc_hack_free(); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										4
									
								
								src/include/global.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/include/global.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | #ifndef GLOBAL_H | ||||||
|  | #define GLOBAL_H | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										29
									
								
								src/include/htab.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/include/htab.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | #ifndef HTAB_H | ||||||
|  | #define HTAB_H | ||||||
|  |  | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdint.h> | ||||||
|  |  | ||||||
|  | #define HTAB_FN fnv1a_hash // Function used for hashing. | ||||||
|  | #define HTAB_SPACE                                                             \ | ||||||
|  |     1024 // Number of entries possible in the hash table; must be | ||||||
|  |          // power of 2. | ||||||
|  |  | ||||||
|  | // Hash Table. | ||||||
|  | typedef void* HTab[HTAB_SPACE]; | ||||||
|  |  | ||||||
|  | // Create a new hash table. | ||||||
|  | HTab* htab_init(); | ||||||
|  | // Destroy a hash table, but not its elements. | ||||||
|  | void htab_destroy(HTab* htab); | ||||||
|  |  | ||||||
|  | // Get element at `hash`. Return its contents, or NULL if nothing found. | ||||||
|  | void* htab_get(HTab* htab, char* str); | ||||||
|  |  | ||||||
|  | // Insert `data` at index `hash`. | ||||||
|  | void htab_ins(HTab* htab, char* key, void* data); | ||||||
|  |  | ||||||
|  | // Gets the length of the hash table. | ||||||
|  | size_t htab_ln(HTab* htab); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -1,60 +1,39 @@ | |||||||
| #ifndef LEXER_H | #ifndef LEXER_H | ||||||
| #define LEXER_H | #define LEXER_H | ||||||
|  |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|  | #include <stddef.h> | ||||||
|  |  | ||||||
| #include "token.h" | #include "ast.h" | ||||||
|  |  | ||||||
| #define TOKENS_MAX 32 | #define ARLN 8 | ||||||
| #define ZERO_CHAR 30 |  | ||||||
|  |  | ||||||
| // What the lexer is currently looking at. | extern char* inp; | ||||||
| typedef enum { |  | ||||||
|     LEXER_STATE_CONFUSED, // Can't decide what it's looking at (also initial |  | ||||||
|                           // state). |  | ||||||
|     LEXER_STATE_NUM,      // Looking at a number. |  | ||||||
|     LEXER_STATE_CALL,     // Looking at a call. |  | ||||||
| } LexerState; |  | ||||||
|  |  | ||||||
| // Lexer: converts text to tokens. |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     char* src;        // The source text. |     size_t sz; | ||||||
|     size_t srcln;     // The number of source chars. |     size_t ln; | ||||||
|     char* cchar;      // The current character. |     AST** buf; | ||||||
|     Token** tokens;   // The tokens produced. | } ArgArr; | ||||||
|     size_t ntokens;   // The number of tokens. |  | ||||||
|     LexerState state; // What the lexer is looking at. |  | ||||||
| } Lexer; |  | ||||||
|  |  | ||||||
| // Create a lexer. | ArgArr* argarr_init(); | ||||||
| Lexer* lexer_init(char* src); | void argarr_destroy(ArgArr* argarr); | ||||||
|  | // Destroy ArgArr structure but preserve -> buf. | ||||||
|  | void argarr_destroypsv(ArgArr* argarr); | ||||||
|  | void argarr_add(ArgArr* argarr, AST* arg); | ||||||
|  |  | ||||||
| // Destroy a lexer. | #include "../../build/grammars/grammar.tab.h" | ||||||
| void lexer_destroy(Lexer* lexer); |  | ||||||
|  |  | ||||||
| // Convert text to tokens. | extern YYSTYPE yylval; | ||||||
| void lexer_lex(Lexer* lexer); |  | ||||||
|  |  | ||||||
| // Lex in confused mode. | // Accumulate an integer. | ||||||
| void lexer_do_confused(Lexer* lexer); | int acc_int(int c); | ||||||
|  |  | ||||||
| // Lex in number mode. | // Accumulate a floating-point number. | ||||||
| void lexer_do_number(Lexer* lexer); | double acc_float(int c); | ||||||
|  |  | ||||||
| // Lex in call mode. | // Called by `yyparse()` (in bison-generated files.) | ||||||
| void lexer_do_call(Lexer* lexer); | int yylex(); | ||||||
|  | void yyerror(char const* s); | ||||||
| // Increment the lexer's current character pointer. |  | ||||||
| void lexer_inc(Lexer* lexer); |  | ||||||
|  |  | ||||||
| // Add a token to the lexer. |  | ||||||
| void lexer_add_token(Lexer* lexer, Token* token); |  | ||||||
|  |  | ||||||
| // Returns a dynamic string representation of the Lexer. |  | ||||||
| Dstr* lexer_to_dstr(Lexer* lexer); |  | ||||||
|  |  | ||||||
| // Returns a string representation of the LexerState. |  | ||||||
| char* lexer_state_to_str(LexerState s); |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -1,13 +0,0 @@ | |||||||
| #ifndef PARSER_H |  | ||||||
| #define PARSER_H |  | ||||||
|  |  | ||||||
| // Expression one of: |  | ||||||
| // - Operation |  | ||||||
| // - Number |  | ||||||
|  |  | ||||||
| // Operation contains: |  | ||||||
| // - Type |  | ||||||
| // - Expression 1 |  | ||||||
| // - Expression 2 |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
							
								
								
									
										22
									
								
								src/include/scope.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/include/scope.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | #ifndef SCOPE_H | ||||||
|  | #define SCOPE_H | ||||||
|  |  | ||||||
|  | #include "htab.h" | ||||||
|  |  | ||||||
|  | // Represents the reverse linked tree of scope. | ||||||
|  | typedef struct SCOPE_T { | ||||||
|  |     HTab* here; // This scope's hash table. | ||||||
|  |     struct SCOPE_T* inherit; // The scope to inherit from. | ||||||
|  |     int uses; // How many `AST`s are linked to this scope. // TODO: REMOVE. | ||||||
|  | } Scope; | ||||||
|  |  | ||||||
|  | // Create a new `Scope`. Creates new empty `HTab` for current scope. | ||||||
|  | Scope* scope_init(Scope* inherit); | ||||||
|  | // Destroy all linked `Scope`s this inherits from. | ||||||
|  | void scope_destroy(Scope* scope); | ||||||
|  | // Destroy the current `Scope` only. | ||||||
|  | void scope_destroy_psv(Scope *scope); | ||||||
|  | // Insert a key/val pair into the `HTab` of a `Scope`. | ||||||
|  | void scope_add(Scope* scope, char* key, void* val); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										24
									
								
								src/include/stack.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/include/stack.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | #ifndef STACK_H | ||||||
|  | #define STACK_H | ||||||
|  |  | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #define STACK_MAX 64 | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     size_t ln;            // The length of the stack (i.e., how many elements). | ||||||
|  |     void* buf[STACK_MAX]; // The stack itself. | ||||||
|  | } Stack; | ||||||
|  |  | ||||||
|  | // Create a `Stack`. | ||||||
|  | Stack* stack_init(); | ||||||
|  | // Destroy a `Stack`. | ||||||
|  | // Note that `->i` must be `0`, i.e. the `Stack` must be empty. | ||||||
|  | void stack_destroy(Stack* stack); | ||||||
|  |  | ||||||
|  | // Push a value to the `Stack`. | ||||||
|  | void stack_push(Stack* stack, void* val); | ||||||
|  | // Pop a value from the `Stack`. | ||||||
|  | void* stack_pop(Stack* stack); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -1,32 +0,0 @@ | |||||||
| #ifndef TOKEN_H |  | ||||||
| #define TOKEN_H |  | ||||||
|  |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <stdio.h> |  | ||||||
| #include <ctype.h> |  | ||||||
|  |  | ||||||
| #include "dstr.h" |  | ||||||
|  |  | ||||||
| typedef enum { |  | ||||||
|     TOKEN_TYPE_CALL, |  | ||||||
|     TOKEN_TYPE_NUMBER, |  | ||||||
| } TokenType; |  | ||||||
|  |  | ||||||
| // Token. |  | ||||||
| typedef struct { |  | ||||||
|     TokenType type; // The type of the Token. |  | ||||||
|     size_t valn;    // The length of val. |  | ||||||
|     char* val;      // The text of the Token. |  | ||||||
|     size_t len;     // Length of the text of the Token. |  | ||||||
| } Token; |  | ||||||
|  |  | ||||||
| Token* token_init(TokenType type, char* val, size_t valn); |  | ||||||
| void token_destroy(Token* token); |  | ||||||
|  |  | ||||||
| // Returns a string representation of the Token. |  | ||||||
| Dstr* token_to_dstr(Token* token); |  | ||||||
|  |  | ||||||
| // Returns a string representation of the TokenType. |  | ||||||
| char* token_type_to_str(TokenType t); |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
| @@ -1,28 +1,115 @@ | |||||||
| #ifndef UTIL_H | #ifndef UTIL_H | ||||||
| #define UTIL_H | #define UTIL_H | ||||||
|  |  | ||||||
|  | #include <signal.h> | ||||||
|  |  | ||||||
|  | // Most of this file is cursed printing macros for `ast_print()`. Do not attempt | ||||||
|  | // to comprehend. | ||||||
|  |  | ||||||
|  | // Allocate a pointer with a type. | ||||||
|  | #define talloc(T, X) T* X = malloc(sizeof(T)); | ||||||
|  |  | ||||||
|  | // Get the length of an array. | ||||||
|  | #define arrln(A) (sizeof(A)/sizeof(*A)) | ||||||
|  |  | ||||||
|  | // Trap GDB &c. | ||||||
|  | #define TRAP() RAISE(SIGTRAP) | ||||||
|  |  | ||||||
| #ifdef DBG // Debug macros | #ifdef DBG // Debug macros | ||||||
|  |  | ||||||
| // Log a message. | // Log a message. | ||||||
| #define log_dbg(msg)                                                           \ | #define log_dbg(msg)                                                           \ | ||||||
|     printf("\033[37;1mdbg\033[0m:\033[37;5m%s\033[0m:\033[32m " msg            \ |     printf(                                                                    \ | ||||||
|            "\033[0m\n",                                                        \ |         "\033[37;1mdbg\033[0m:\033[37m%s\033[0m:\033[32m " msg "\033[0m\n",    \ | ||||||
|            __func__); |         __func__                                                               \ | ||||||
|  |     ); | ||||||
|  |  | ||||||
| // Log a message with formatting. | // Log a message with formatting. | ||||||
| #define log_dbgf(msg, ...)                                                     \ | #define log_dbgf(msg, ...)                                                     \ | ||||||
|     printf("\033[37;1mdbg\033[0m:\033[37;5m%s\033[0m:\033[32m " msg            \ |     printf(                                                                    \ | ||||||
|            "\033[0m\n",                                                        \ |         "\033[37;1mdbg\033[0m:\033[37m%s\033[0m:\033[32m " msg "\033[0m\n",    \ | ||||||
|            __func__, __VA_ARGS__); |         __func__, __VA_ARGS__                                                  \ | ||||||
|  |     ); | ||||||
|  |  | ||||||
| #else // ifdef DBG | #else // ifdef DBG | ||||||
| #define log_dbg(msg) | #define log_dbg(msg) | ||||||
|  | #define log_dbgf(msg, ...) | ||||||
| #endif // ifdef DBG else | #endif // ifdef DBG else | ||||||
|  |  | ||||||
| // Maximum size of a string containing only an int. | // Resent color code. | ||||||
| #define MAXSTRINTSZ ((CHAR_BIT * sizeof(int) - 1) / 3 + 2) | #define COL_RESET "\e[0m" | ||||||
|  |  | ||||||
| // Maximum size of a string containing only a size_t. | // Regular color codes. | ||||||
| #define MAXSTRIZE_TSZ ((CHAR_BIT * sizeof(size_t) - 1) / 3 + 2) | #define COL_BLA "\e[0;30m" | ||||||
|  | #define COL_RED "\e[0;31m" | ||||||
|  | #define COL_GRE "\e[0;32m" | ||||||
|  | #define COL_YEL "\e[0;33m" | ||||||
|  | #define COL_BLU "\e[0;34m" | ||||||
|  | #define COL_MAG "\e[0;35m" | ||||||
|  | #define COL_CYA "\e[0;36m" | ||||||
|  | #define COL_WHI "\e[0;37m" | ||||||
|  |  | ||||||
|  | // Bold color codes. | ||||||
|  | #define COL_BBLA "\e[1;30m" | ||||||
|  | #define COL_BRED "\e[1;31m" | ||||||
|  | #define COL_BGRE "\e[1;32m" | ||||||
|  | #define COL_BYEL "\e[1;33m" | ||||||
|  | #define COL_BBLU "\e[1;34m" | ||||||
|  | #define COL_BMAG "\e[1;35m" | ||||||
|  | #define COL_BCYA "\e[1;36m" | ||||||
|  | #define COL_BWHI "\e[1;37m" | ||||||
|  |  | ||||||
|  | // Start in indent block. | ||||||
|  | #define INDENT_BEGIN(ILVL)                                                     \ | ||||||
|  |     __attribute__((unused)) int INDENT_lvl = ILVL;                             \ | ||||||
|  |     Dstr* INDENT_spacing = dstr_init();                                        \ | ||||||
|  |     for (int INDENT_j = 0; INDENT_j < ILVL; INDENT_j++)                        \ | ||||||
|  |         dstr_appendch(INDENT_spacing, ' '); | ||||||
|  |  | ||||||
|  | // Print & indent the title of a section. | ||||||
|  | #define INDENT_TITLE(THING, WHERE)                                             \ | ||||||
|  |     printf(                                                                    \ | ||||||
|  |         "%s" COL_BCYA THING COL_RESET " @" COL_MAG " %p\n" COL_RESET,          \ | ||||||
|  |         INDENT_spacing->buf, WHERE                                             \ | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  | // Print & indent a thing. | ||||||
|  | #define INDENT_FIELD(FIELD, VAL, ...)                                          \ | ||||||
|  |     printf(                                                                    \ | ||||||
|  |         "%s " COL_BWHI FIELD ": " COL_RESET COL_WHI VAL COL_RESET "\n",        \ | ||||||
|  |         INDENT_spacing->buf, __VA_ARGS__                                       \ | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  | // Print & indent a thing with a newline before the val. | ||||||
|  | #define INDENT_FIELD_NL(FIELD, VAL, ...)                                       \ | ||||||
|  |     printf(                                                                    \ | ||||||
|  |         "%s " COL_BWHI FIELD ":" COL_RESET "\n %s " COL_WHI VAL COL_RESET      \ | ||||||
|  |         "\n",                                                                  \ | ||||||
|  |         INDENT_spacing->buf, INDENT_spacing->buf, __VA_ARGS__                  \ | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  | // Print & indent a thing without any newline. | ||||||
|  | #define INDENT_FIELD_EXT_NONL_START(FIELD)                                     \ | ||||||
|  |     printf("%s " COL_BWHI FIELD ":\n" COL_RESET COL_WHI, INDENT_spacing->buf); | ||||||
|  | #define INDENT_FIELD_NONL_END printf("\n" COL_RESET); | ||||||
|  |  | ||||||
|  | // Print an array A of N things, by calling the function F. | ||||||
|  | #define INDENT_FIELD_LIST(FIELD, A, N, F)                                      \ | ||||||
|  |     printf("%s " COL_BWHI FIELD ": [\n" COL_RESET, INDENT_spacing->buf);       \ | ||||||
|  |     for (int INDENT_i = 0; INDENT_i < N; INDENT_i++) {                         \ | ||||||
|  |         F(A[INDENT_i], INDENT_lvl + 2);                                        \ | ||||||
|  |     }                                                                          \ | ||||||
|  |     printf(COL_BWHI "%s ]\n" COL_RESET, INDENT_spacing->buf); | ||||||
|  |  | ||||||
|  | // End an indent block. | ||||||
|  | #define INDENT_END                                                             \ | ||||||
|  |     printf(COL_RESET);                                                         \ | ||||||
|  |     dstr_destroy(INDENT_spacing); | ||||||
|  |  | ||||||
|  | #define INDENT_FIELD_LIST_OPEN(FIELD)                                          \ | ||||||
|  |     printf("%s " COL_BWHI FIELD ": [\n" COL_RESET, INDENT_spacing->buf); | ||||||
|  |  | ||||||
|  | #define INDENT_FIELD_LIST_CLOSE                                                \ | ||||||
|  |     printf(COL_BWHI "%s ]\n" COL_RESET, INDENT_spacing->buf); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
							
								
								
									
										243
									
								
								src/lexer.c
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								src/lexer.c
									
									
									
									
									
								
							| @@ -1,135 +1,156 @@ | |||||||
|  | #include <complex.h> | ||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
|  | #include <limits.h> | ||||||
|  | #include <math.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <limits.h> |  | ||||||
|  |  | ||||||
| #include "include/lexer.h" |  | ||||||
| #include "include/dstr.h" | #include "include/dstr.h" | ||||||
|  | #include "include/lexer.h" | ||||||
| #include "include/util.h" | #include "include/util.h" | ||||||
|  |  | ||||||
| Lexer* lexer_init(char* src) { | ArgArr* argarr_init() { | ||||||
|     Lexer* lexer = malloc(sizeof(Lexer)); |     ArgArr* argarr = malloc(sizeof(ArgArr)); | ||||||
|  |  | ||||||
|     lexer->src = src; |     argarr->sz = ARLN * sizeof(AST*); | ||||||
|     lexer->srcln = strlen(src); |     argarr->ln = 0; | ||||||
|     lexer->cchar = lexer->src; |     argarr->buf = malloc(argarr->sz); | ||||||
|  |  | ||||||
|     lexer->tokens = calloc(TOKENS_MAX, sizeof(Token*)); |     return argarr; | ||||||
|     lexer->ntokens = 0; |  | ||||||
|     lexer->state = LEXER_STATE_CONFUSED; |  | ||||||
|  |  | ||||||
|     log_dbgf("created new lexer @ %p", lexer); |  | ||||||
|  |  | ||||||
|     return lexer; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void lexer_destroy(Lexer* lexer) { | void argarr_destroy(ArgArr* argarr) { | ||||||
|     free(lexer->src); |     free(argarr->buf); | ||||||
|  |     free(argarr); | ||||||
|     for (int i = 0; i < lexer->ntokens; i++) token_destroy(lexer->tokens[i]); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void lexer_lex(Lexer* lexer) { | void argarr_destroypsv(ArgArr* argarr) { free(argarr); } | ||||||
|     while (*lexer->cchar) { |  | ||||||
|         switch (lexer->state) { | void argarr_add(ArgArr* argarr, AST* arg) { | ||||||
|         case LEXER_STATE_CONFUSED: lexer_do_confused(lexer); break; |     if ((argarr->ln + 1) * sizeof(AST*) > argarr->sz) { | ||||||
|         case LEXER_STATE_NUM:      lexer_do_number(lexer); break; |         argarr->sz *= 2; | ||||||
|         case LEXER_STATE_CALL:     lexer_do_call(lexer); break; |         argarr->buf = realloc(argarr->buf, argarr->sz); | ||||||
|         default:                   break; |         log_dbgf( | ||||||
|  |             "ArgArr @ %p doubled from %ld to %ld", argarr, argarr->sz / 2, | ||||||
|  |             argarr->sz | ||||||
|  |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     argarr->buf[argarr->ln++] = arg; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int acc_int(int c) { | ||||||
|  |     int value = c - '0'; | ||||||
|  |     while (isdigit(*inp)) { | ||||||
|  |         value = value * 10 + (*inp - '0'); // Accumulate value. | ||||||
|  |         inp++; | ||||||
|     } |     } | ||||||
|  |     return value; | ||||||
| } | } | ||||||
|  |  | ||||||
| void lexer_do_confused(Lexer* lexer) { | double acc_float(int c) { | ||||||
|     log_dbgf("lexer @ %p entered confused mode @ char '%c' (%d)", lexer, *lexer->cchar, (int)*lexer->cchar); |     int dplaces = 0; | ||||||
|  |     double value = (double)(c - '0'); | ||||||
|  |  | ||||||
|     if (isdigit(*lexer->cchar)) { |     // Grab everything prior to '.'. | ||||||
|         lexer->state = LEXER_STATE_NUM; |     while (isdigit(*inp)) { | ||||||
|         lexer_do_number(lexer); |         value = value * 10 + (*inp - '0'); // Accumulate value. | ||||||
|     } else { |         inp++; | ||||||
|         lexer->state = LEXER_STATE_CALL; |  | ||||||
|         lexer_do_call(lexer); |  | ||||||
|     } |     } | ||||||
| } |  | ||||||
|  |  | ||||||
| void lexer_do_number(Lexer* lexer) { |     if (*inp == '.') { | ||||||
|     log_dbgf("lexer @ %p entered number mode @ char '%c' (%d)", lexer, *lexer->cchar, (int)*lexer->cchar); |         inp++; | ||||||
|  |  | ||||||
|     // Size of the number string. |         while (isdigit(*inp)) { | ||||||
|     size_t numsz; |             value = value * 10 + (*inp - '0'); // Accumulate value. | ||||||
|  |             dplaces++; | ||||||
|     // Where the number string starts. |             inp++; | ||||||
|     char* start = lexer->cchar; |  | ||||||
|  |  | ||||||
|     for (numsz = 0; *lexer->cchar && isdigit(*lexer->cchar); numsz++) |  | ||||||
|         lexer_inc(lexer); |  | ||||||
|  |  | ||||||
|     char* num = malloc(numsz + 1); |  | ||||||
|     memcpy(num, start, numsz); |  | ||||||
|     num[numsz] = '\0'; |  | ||||||
|  |  | ||||||
|     lexer_add_token(lexer, token_init(TOKEN_TYPE_NUMBER, num, 1)); |  | ||||||
|     lexer->state = LEXER_STATE_CONFUSED; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void lexer_do_call(Lexer* lexer) { |  | ||||||
|     log_dbgf("lexer @ %p entered call mode @ char '%c' (%d)", lexer, *lexer->cchar, (int)*lexer->cchar); |  | ||||||
|  |  | ||||||
|     // Size of the call string. |  | ||||||
|     size_t callsz; |  | ||||||
|  |  | ||||||
|     // Where the call string starts. |  | ||||||
|     char* start = lexer->cchar; |  | ||||||
|  |  | ||||||
|     for (callsz = 0; *lexer->cchar && (!isdigit(*lexer->cchar)); callsz++) |  | ||||||
|         lexer_inc(lexer); |  | ||||||
|  |  | ||||||
|     char* call = malloc(callsz + 1); |  | ||||||
|     memcpy(call, start, callsz); |  | ||||||
|     call[callsz] = '\0'; |  | ||||||
|  |  | ||||||
|     lexer_add_token(lexer, token_init(TOKEN_TYPE_CALL, call, 1)); |  | ||||||
|  |  | ||||||
|     lexer->state = LEXER_STATE_CONFUSED; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void lexer_inc(Lexer* lexer) { |  | ||||||
|     lexer->cchar += sizeof(char); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void lexer_add_token(Lexer* lexer, Token* token) { |  | ||||||
|     assert(lexer->ntokens < TOKENS_MAX); |  | ||||||
|  |  | ||||||
|     if (lexer->ntokens < TOKENS_MAX - 1) { |  | ||||||
|         lexer->tokens[lexer->ntokens] = token; |  | ||||||
|         lexer->ntokens++; |  | ||||||
|         } |         } | ||||||
| } |         value = value / pow(10, dplaces); | ||||||
|  |  | ||||||
| Dstr* lexer_to_dstr(Lexer* lexer) { |  | ||||||
|     Dstr* str = dstr_init(); |  | ||||||
|  |  | ||||||
|     size_t titlesz = sizeof("Lexer @ 0x00000000"); |  | ||||||
|     char title[titlesz]; |  | ||||||
|     sprintf(title, "Lexer @ %p", lexer); |  | ||||||
|     dstr_append(str, title, titlesz - 1); |  | ||||||
|  |  | ||||||
|     size_t ln = snprintf(NULL, 0, "srcln: %ld", lexer->srcln);  |  | ||||||
|     char src_sz[ln + 1]; |  | ||||||
|     snprintf(src_sz, ln + 1, "srcln: %ld", lexer->srcln); |  | ||||||
|     dstr_append(str, src_sz, ln - 1); |  | ||||||
|  |  | ||||||
|     dstr_append(str, "\nsrc: ", 5); |  | ||||||
|     dstr_append(str, lexer->src, lexer->srcln); |  | ||||||
|  |  | ||||||
|     return str; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| char* lexer_state_to_str(LexerState s) { |  | ||||||
|     switch (s) { |  | ||||||
|     case LEXER_STATE_NUM:      return "NUM"; |  | ||||||
|     case LEXER_STATE_CALL:     return "CALL"; |  | ||||||
|     case LEXER_STATE_CONFUSED: return "CONFUSED"; |  | ||||||
|     default:                   return "UNKNOWN"; |  | ||||||
|     } |     } | ||||||
|  |     return value; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | char* acc_word(int c) { | ||||||
|  |     Dstr* val = dstr_init(); | ||||||
|  |     while (isalpha(*inp) || *inp == '_') { | ||||||
|  |         dstr_appendch(val, *(inp - 1)); | ||||||
|  |         inp++; | ||||||
|  |     } | ||||||
|  |     dstr_appendch(val, *(inp - 1)); | ||||||
|  |  | ||||||
|  |     char* ret = val->buf; | ||||||
|  |     dstr_destroypsv(val); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | char* acc_deq(int c) { | ||||||
|  |     Dstr* val = dstr_init(); | ||||||
|  |     while (*inp == '=') { | ||||||
|  |         dstr_appendch(val, *(inp - 1)); | ||||||
|  |         inp++; | ||||||
|  |     } | ||||||
|  |     dstr_appendch(val, *(inp - 1)); | ||||||
|  |  | ||||||
|  |     char* ret = val->buf; | ||||||
|  |     dstr_destroypsv(val); | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int yylex() { | ||||||
|  |     if (*inp == '\0') return YYEOF; | ||||||
|  |  | ||||||
|  |     // Skip all whitespace. | ||||||
|  |     while (*inp == ' ' || *inp == '\t') inp++; | ||||||
|  |  | ||||||
|  |     // Assign & consume current character. | ||||||
|  |     int c = *inp++; | ||||||
|  |  | ||||||
|  |     if (c == '-' && *inp == '>' && inp++) { return RARROW; } | ||||||
|  |     if (c == '<' && *inp == '-' && inp++) { return LARROW; } | ||||||
|  |     if (c == '=' && *inp == '=' && inp++) { return DEQ; } | ||||||
|  |     if (c == '=' && *inp != '=') { return EQ; } | ||||||
|  |  | ||||||
|  |     // Check for NUM. | ||||||
|  |     if (isdigit(c)) { | ||||||
|  |         yylval.fval = acc_float(c); // Set the token value. | ||||||
|  |         return NUM; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (isalpha(c) || c == '_') { | ||||||
|  |         yylval.strval = acc_word(c); | ||||||
|  |  | ||||||
|  |         if (!strcmp(yylval.strval, "TRUE") || !strcmp(yylval.strval, "T")) | ||||||
|  |             return BOOLT; | ||||||
|  |         if (!strcmp(yylval.strval, "FALSE") || !strcmp(yylval.strval, "F")) | ||||||
|  |             return BOOLF; | ||||||
|  |         if (!strcmp(yylval.strval, "if")) return IF; | ||||||
|  |         if (!strcmp(yylval.strval, "else")) return ELSE; | ||||||
|  |  | ||||||
|  |         return WORD; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     switch (c) { | ||||||
|  |         case '+':  return ADD; | ||||||
|  |         case '\n': return NL; | ||||||
|  |         case '-':  return SUB; | ||||||
|  |         case '*':  return MUL; | ||||||
|  |         case '/':  return DIV; | ||||||
|  |         case '(':  return GROUPS; | ||||||
|  |         case ')':  return GROUPE; | ||||||
|  |         case ',':  return SEP; | ||||||
|  |         case ';':  return EXPSEP; | ||||||
|  |         case '{':  return BLOCKS; | ||||||
|  |         case '}':  return BLOCKE; | ||||||
|  |         case '\\': return BACKSLASH; | ||||||
|  |         case '?':  return IF; | ||||||
|  |         case ':':  return COLON; | ||||||
|  |         case '$':  return STOP; | ||||||
|  |         case '!':  return FORCE; | ||||||
|  |         case '@':  return PRESERVE; | ||||||
|  |         default:   fprintf(stderr, "Unexpected character: %c\n", c); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | void yyerror(char const* s) { fprintf(stderr, "Parse error: %s\n", s); } | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								src/main.c
									
									
									
									
									
								
							| @@ -1,26 +1,84 @@ | |||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include "include/ast.h" | ||||||
|  | #include "include/ast_print.h" | ||||||
| #include "include/dstr.h" | #include "include/dstr.h" | ||||||
| #include "include/token.h" | #include "include/exec.h" | ||||||
| #include "include/util.h" | #include "include/gc.h" | ||||||
| #include "include/lexer.h" | #include "include/lexer.h" | ||||||
|  | #include "include/util.h" | ||||||
|  |  | ||||||
|  | #include "../build/grammars/grammar.tab.h" | ||||||
|  |  | ||||||
|  | // Global Abstract Syntax Tree. | ||||||
|  | extern AST* root; | ||||||
|  | extern char* inp; | ||||||
|  | extern int yyparse(); | ||||||
|  |  | ||||||
| int main(int argc, char** argv) { | int main(int argc, char** argv) { | ||||||
|     while(1) { |  | ||||||
|         Dstr* cline = dstr_init(); // The current line. |     if (argc - 1 && strlen(argv[1]) > 0 && (inp = argv[1]) && !yyparse()) { | ||||||
|  |         // log_dbg("Parsed successfully!\n"); | ||||||
|  |         // ast_print(root); | ||||||
|  |         AST* eval = exec_start(root); | ||||||
|  |         ast_print(eval); | ||||||
|  |         // ast_destroy(eval); | ||||||
|  |         // ast_destroy(root); | ||||||
|  |         gc_hack_free(); | ||||||
|  |         exit(0); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     while (1) { | ||||||
|  |         Dstr* ln = dstr_init(); | ||||||
|  |         char c; | ||||||
|  |  | ||||||
|         printf("> "); |         printf("> "); | ||||||
|         fflush(stdout); |         fflush(stdout); | ||||||
|         for (char cch; (cch = getc(stdin)) != '\n';) { |  | ||||||
|             log_dbgf("cchar: %c", cch); |         // Accumulate line. | ||||||
|             dstr_appendch(cline, cch); |         do { | ||||||
|  |             c = getc(stdin); | ||||||
|  |             switch (c) { | ||||||
|  |                 case EOF:  dstr_destroy(ln); goto lnskip; | ||||||
|  |                 case '\n': goto lnend; | ||||||
|  |                 default:   dstr_appendch(ln, c); | ||||||
|  |             } | ||||||
|  |         } while (1); | ||||||
|  |  | ||||||
|  |     lnend: | ||||||
|  |  | ||||||
|  |         log_dbgf("cline: %s", ln->buf); | ||||||
|  |  | ||||||
|  |         if (ln->ln > 0) { | ||||||
|  |             inp = ln->buf; | ||||||
|  |             if (yyparse() == 0) { | ||||||
|  |                 log_dbg("Parsed successfully!\n"); | ||||||
|  |             } else { | ||||||
|  |                 printf("Parse error.\n"); | ||||||
|  |                 dstr_destroy(ln); | ||||||
|  |                 continue; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         log_dbgf("cline: %s", cline->buf); | #ifdef DBG | ||||||
|  |             ast_print(root); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|         if (cline->ln > 0) { |             AST* eval = exec_start(root); | ||||||
|             Lexer* lexer = lexer_init(cline->buf); |             ast_print(eval); | ||||||
|             lexer_lex(lexer); |             // Awful hack to exit when die() is called, until proper exception | ||||||
|             printf("\n%s\n", lexer_to_dstr(lexer)->buf); |             // handling is implemented. TODO TODO TODO PLSFIX. | ||||||
|  |             if (eval->type == AST_TYPE_EXC && | ||||||
|  |                 ((ASTExcData*)eval->data)->msg[0] == '8') { | ||||||
|  |                 gc_hack_free(); | ||||||
|  |                 exit(1); | ||||||
|             } |             } | ||||||
|  |             gc_hack_free(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         dstr_destroy(ln); | ||||||
|  |     } | ||||||
|  | lnskip:; | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								src/scope.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/scope.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | #include "include/scope.h" | ||||||
|  | #include "include/gc.h" | ||||||
|  | #include "include/htab.h" | ||||||
|  | #include "include/util.h" | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | Scope* scope_init(Scope* inherit) { | ||||||
|  |     Scope* scope = gc_alloc(sizeof(Scope), GC_TYPE_SCOPE); | ||||||
|  |  | ||||||
|  |     scope->here = htab_init(); | ||||||
|  |     scope->inherit = inherit; | ||||||
|  |     scope->uses = 0; | ||||||
|  |  | ||||||
|  |     log_dbgf("%p: new scope, inherits from %p", scope, inherit); | ||||||
|  |  | ||||||
|  |     return scope; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void scope_destroy(Scope* scope) { | ||||||
|  |     if (!scope) return; | ||||||
|  |     htab_destroy(scope->here); | ||||||
|  |     if (scope->inherit != NULL) scope_destroy(scope->inherit); | ||||||
|  |     free(scope); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void scope_destroy_psv(Scope* scope) { | ||||||
|  |     if (!scope) return; | ||||||
|  |     log_dbgf("%p: destroying", scope); | ||||||
|  |     htab_destroy(scope->here); | ||||||
|  |     scope->inherit = NULL; | ||||||
|  |     free(scope); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | inline void scope_add(Scope* scope, char* key, void* val) { | ||||||
|  |     htab_ins(scope->here, key, val); | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								src/stack.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/stack.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | #include <assert.h> | ||||||
|  | #include <stdio.h> // IWYU pragma: keep. Req by util macros. | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | #include "include/stack.h" | ||||||
|  | #include "include/util.h" | ||||||
|  |  | ||||||
|  | Stack* stack_init() { | ||||||
|  |     talloc(Stack, stack); | ||||||
|  |  | ||||||
|  |     memset(stack->buf, 0, sizeof(void*) * STACK_MAX); | ||||||
|  |     stack->ln = 0; | ||||||
|  |  | ||||||
|  |     return stack; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void stack_destroy(Stack* stack) { | ||||||
|  |     // Can only free an empty stack. | ||||||
|  |     assert(stack->ln == 0); | ||||||
|  |     free(stack); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void stack_push(Stack* stack, void* val) { | ||||||
|  |     if (stack->ln >= STACK_MAX) { | ||||||
|  |         log_dbgf("Ran out of stack (max: %d)", STACK_MAX); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     stack->buf[stack->ln] = val; | ||||||
|  |     stack->ln++; | ||||||
|  |     log_dbgf("pushed to stack, inc ln to %ld", stack->ln); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void* stack_pop(Stack* stack) { | ||||||
|  |     if (stack->ln <= 0) { | ||||||
|  |         log_dbg("Can't pop empty stack."); | ||||||
|  |         return (void*)-1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return stack->buf[--stack->ln]; | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								src/token.c
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								src/token.c
									
									
									
									
									
								
							| @@ -1,41 +0,0 @@ | |||||||
| #include "include/token.h" |  | ||||||
| #include "include/dstr.h" |  | ||||||
| #include <stdlib.h> |  | ||||||
|  |  | ||||||
| Token* token_init(TokenType type, char* val, size_t valn) { |  | ||||||
|     Token* t = malloc(sizeof(Token)); |  | ||||||
|  |  | ||||||
|     t->type = type; |  | ||||||
|     t->val = val; |  | ||||||
|     t->valn = valn; |  | ||||||
|  |  | ||||||
|     return t; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void token_destroy(Token* t) { |  | ||||||
|     free(t->val); |  | ||||||
|     free(t); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| Dstr* token_to_dstr(Token* token) { |  | ||||||
|     Dstr* str = dstr_init(); |  | ||||||
|  |  | ||||||
|     size_t titlesz = sizeof("Token @ 0x00000000"); |  | ||||||
|     char title[titlesz]; |  | ||||||
|     sprintf(title, "Token @ %p", token); |  | ||||||
|     dstr_append(str, title, titlesz - 1); |  | ||||||
|     dstr_append(str, "\n", 1); |  | ||||||
|  |  | ||||||
|     size_t typesz = sizeof("type: 1"); |  | ||||||
|     char type[typesz]; |  | ||||||
|     // If token_to_dstr starts breaking, it might be because there're more than |  | ||||||
|     // 10 types. FIXME. |  | ||||||
|     sprintf(type, "type: %d", token->type); |  | ||||||
|     dstr_append(str, type, typesz - 1); |  | ||||||
|     dstr_append(str, "\n", 1); |  | ||||||
|  |  | ||||||
|     dstr_append(str, "val: ", 5); |  | ||||||
|     dstr_append(str, token->val, token->valn); |  | ||||||
|  |  | ||||||
|     return str; |  | ||||||
| } |  | ||||||
							
								
								
									
										1
									
								
								test/Unity
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								test/Unity
									
									
									
									
									
										Submodule
									
								
							 Submodule test/Unity added at 73237c5d22
									
								
							
							
								
								
									
										39
									
								
								test/dstr.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								test/dstr.c
									
									
									
									
									
								
							| @@ -1,39 +0,0 @@ | |||||||
| #include "../src/include/dstr.h" |  | ||||||
| #include "unity/unity.h" |  | ||||||
| #include "registry.h" |  | ||||||
|  |  | ||||||
| void test_dstr_init() { |  | ||||||
|     Dstr* dstr = dstr_init(); |  | ||||||
|  |  | ||||||
|     TEST_ASSERT_EQUAL_INT(DSTR_INITSZ, dstr->bufsz); |  | ||||||
|     TEST_ASSERT_EQUAL_STRING(malloc(DSTR_INITSZ), dstr->buf); |  | ||||||
|     TEST_ASSERT_EQUAL_size_t(0, dstr->ln); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void test_dstr_append() { |  | ||||||
|     char* str1 = malloc(2); |  | ||||||
|     str1[0] = 'h'; |  | ||||||
|     str1[1] = '\0'; |  | ||||||
|  |  | ||||||
|     char* str2 = malloc(DSTR_INITSZ); |  | ||||||
|     str2[0] = 'h'; |  | ||||||
|     str2[1] = '\0'; |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     Dstr* dstr = dstr_init(); |  | ||||||
|     dstr_append(dstr, str1, 1); |  | ||||||
|  |  | ||||||
|     TEST_ASSERT_EQUAL_STRING(str2, dstr->buf); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int test_dstr() { |  | ||||||
|     UNITY_BEGIN(); |  | ||||||
|     RUN_TEST(test_dstr_init); |  | ||||||
|     RUN_TEST(test_dstr_append); |  | ||||||
|     UNITY_END(); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| __attribute__((constructor)) void register_dstr() { |  | ||||||
|     register_test(test_dstr); |  | ||||||
| } |  | ||||||
							
								
								
									
										52
									
								
								test/lexer.c
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								test/lexer.c
									
									
									
									
									
								
							| @@ -1,52 +0,0 @@ | |||||||
| #include "../src/include/lexer.h" |  | ||||||
| #include "unity/unity.h" |  | ||||||
| #include "registry.h" |  | ||||||
|  |  | ||||||
| void test_lexer_init() { |  | ||||||
|     char* src = malloc(sizeof("a1b2")); |  | ||||||
|     src = "a1b2"; |  | ||||||
|     Lexer* lexer = lexer_init(src); |  | ||||||
|  |  | ||||||
|     TEST_ASSERT_EQUAL_STRING(src, lexer->src); |  | ||||||
|     TEST_ASSERT_EQUAL_INT(4, lexer->srcl); |  | ||||||
|     TEST_ASSERT_EQUAL_CHAR(src[0], *lexer->cchar); |  | ||||||
|     TEST_ASSERT_EQUAL_INT(LEXER_STATE_CONFUSED, lexer->state); |  | ||||||
|     // Hope that token arr. is right size :). |  | ||||||
|     TEST_ASSERT_EQUAL_INT(0, lexer->ntokens); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void test_lexer_lex_callnum() { |  | ||||||
|     char* src = malloc(sizeof("a1b2")); |  | ||||||
|     src = "a1b2"; |  | ||||||
|     Lexer* lexer = lexer_init(src); |  | ||||||
|  |  | ||||||
|     Token* tokens[4] = { |  | ||||||
|         token_init(TOKEN_TYPE_CALL, "a"), |  | ||||||
|         token_init(TOKEN_TYPE_NUMBER, "1"), |  | ||||||
|         token_init(TOKEN_TYPE_CALL, "b"), |  | ||||||
|         token_init(TOKEN_TYPE_NUMBER, "2"), |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     lexer_lex(lexer); |  | ||||||
|  |  | ||||||
|     TEST_ASSERT_EQUAL_INT(4, lexer->ntokens); |  | ||||||
|  |  | ||||||
|     for (int i = 0; i < 4; i++) { |  | ||||||
|         printf("h"); |  | ||||||
|         fflush(stdout); |  | ||||||
|         TEST_ASSERT_EQUAL_INT(tokens[i]->type, lexer->tokens[i]->type); |  | ||||||
|         TEST_ASSERT_EQUAL_STRING(tokens[i]->val, lexer->tokens[i]->val); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int test_lexer() { |  | ||||||
|     UNITY_BEGIN(); |  | ||||||
|     RUN_TEST(test_lexer_init); |  | ||||||
|     RUN_TEST(test_lexer_lex_callnum); |  | ||||||
|     UNITY_END(); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| __attribute__((constructor)) void register_lexer() { |  | ||||||
|     register_test(test_lexer); |  | ||||||
| } |  | ||||||
							
								
								
									
										12
									
								
								test/main.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								test/main.c
									
									
									
									
									
								
							| @@ -1,12 +0,0 @@ | |||||||
| #include "registry.h" |  | ||||||
| #include "unity/unity.h" |  | ||||||
|  |  | ||||||
| void (*tests[30])(); |  | ||||||
|  |  | ||||||
| void setUp() {} |  | ||||||
| void tearDown() {} |  | ||||||
|  |  | ||||||
| int main() { |  | ||||||
|     run_all_tests(); |  | ||||||
|     return 0; |  | ||||||
| } |  | ||||||
| @@ -1,20 +0,0 @@ | |||||||
| #include "registry.h" |  | ||||||
| #include "unity/unity_internals.h" |  | ||||||
|  |  | ||||||
| #define TESTS_MAX 128 |  | ||||||
|  |  | ||||||
| static Test tests[TESTS_MAX]; |  | ||||||
| static int test_count = 0; |  | ||||||
|  |  | ||||||
| void register_test(Test t) { |  | ||||||
|     if (test_count < TESTS_MAX) { |  | ||||||
|         tests[test_count] = t; |  | ||||||
|         test_count++; |  | ||||||
|     } else printf("Maximum number of tests (%d) exceeded.\n", TESTS_MAX); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void run_all_tests() { |  | ||||||
|     for (int i = 0; i < test_count; i++) { |  | ||||||
|         int res = tests[i](); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,15 +0,0 @@ | |||||||
| #ifndef REGISTRY_H |  | ||||||
| #define REGISTRY_H |  | ||||||
|  |  | ||||||
| #include <stdio.h> |  | ||||||
| #include "unity/unity.h" |  | ||||||
|  |  | ||||||
| typedef int (*Test)(void); |  | ||||||
|  |  | ||||||
| // Register a new test function. |  | ||||||
| void register_test(Test); |  | ||||||
|  |  | ||||||
| // Run all registered tests. |  | ||||||
| void run_all_tests(); |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
							
								
								
									
										44
									
								
								test/test_ast.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								test/test_ast.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | #include "../src/include/ast.h" | ||||||
|  | #include "Unity/src/unity.h" | ||||||
|  | #include "Unity/src/unity_internals.h" | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | void setUp() {} | ||||||
|  | void tearDown() {} | ||||||
|  |  | ||||||
|  | void test_ast_num() { | ||||||
|  |     ASTNumData* num = ast_num_data_init(12.0); | ||||||
|  |     AST* ast = ast_init(AST_TYPE_NUM, num); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL(AST_TYPE_NUM, ast->type); | ||||||
|  |     TEST_ASSERT_EQUAL(12.0, *(ASTNumData*)ast->data); | ||||||
|  |  | ||||||
|  |     ast_destroy(ast); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void test_ast_call() { | ||||||
|  |     AST** argv = malloc(2 * sizeof(AST*)); | ||||||
|  |     argv[0] = ast_init(AST_TYPE_NUM, ast_num_data_init(1.0)); | ||||||
|  |     argv[1] = ast_init(AST_TYPE_NUM, ast_num_data_init(2.0)); | ||||||
|  |  | ||||||
|  |     char* name = malloc(2); | ||||||
|  |     strcpy(name, "f"); | ||||||
|  |  | ||||||
|  |     ASTCallData* call = ast_call_data_init(name, 2, argv); | ||||||
|  |  | ||||||
|  |     AST* ast = ast_init(AST_TYPE_CALL, call); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL(AST_TYPE_CALL, ast->type); | ||||||
|  |     TEST_ASSERT_EQUAL(name, ((ASTCallData*)ast->data)->to); | ||||||
|  |     TEST_ASSERT_EQUAL(2, ((ASTCallData*)ast->data)->argc); | ||||||
|  |     TEST_ASSERT_EQUAL(1.0, ((ASTCallData*)ast->data)->argv[0]); | ||||||
|  |     TEST_ASSERT_EQUAL(2.0, ((ASTCallData*)ast->data)->argv[1]); | ||||||
|  |  | ||||||
|  |     ast_destroy(ast); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ast_destroy(ast); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     UNITY_BEGIN(); | ||||||
							
								
								
									
										41
									
								
								test/test_dlist.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								test/test_dlist.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | #include "../src/include/dlist.h" | ||||||
|  | #include "Unity/src/unity.h" | ||||||
|  |  | ||||||
|  | void setUp() {}; | ||||||
|  | void tearDown() {}; | ||||||
|  |  | ||||||
|  | void test_dlist_init() { | ||||||
|  |     DList* dlist = dlist_init(); | ||||||
|  |     TEST_ASSERT_EQUAL(0, dlist->ln); | ||||||
|  |     TEST_ASSERT_EQUAL(DLIST_INITSZ, dlist->sz); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void test_dlist_append() { | ||||||
|  |     DList* dlist; | ||||||
|  |  | ||||||
|  |     // Test simple appending. | ||||||
|  |     dlist = dlist_init(); | ||||||
|  |     int* n = malloc(sizeof(int)); | ||||||
|  |     *n = 1; | ||||||
|  |     dlist_append(dlist, n); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL(n, dlist->buf[0]); | ||||||
|  |     TEST_ASSERT_EQUAL(1, dlist->ln); | ||||||
|  |  | ||||||
|  |     dlist_destroy(dlist); | ||||||
|  |  | ||||||
|  |     // Test buffer doubling. | ||||||
|  |     dlist = dlist_init(); | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < 129; i++) dlist_append(dlist, &i); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL(129, dlist->ln); | ||||||
|  |     TEST_ASSERT_EQUAL(DLIST_INITSZ*2, dlist->sz); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     UNITY_BEGIN(); | ||||||
|  |     RUN_TEST(test_dlist_init); | ||||||
|  |     RUN_TEST(test_dlist_append); | ||||||
|  |     return UNITY_END(); | ||||||
|  | } | ||||||
							
								
								
									
										78
									
								
								test/test_dstr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								test/test_dstr.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | |||||||
|  | #include "../src/include/dstr.h" | ||||||
|  | #include "Unity/src/unity.h" | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | void setUp() {}; | ||||||
|  | void tearDown() {}; | ||||||
|  |  | ||||||
|  | void test_dstr_init() { | ||||||
|  |     Dstr* dstr = dstr_init(); | ||||||
|  |     TEST_ASSERT_EQUAL(0, strlen(dstr->buf)); | ||||||
|  |     TEST_ASSERT_EQUAL(0, dstr->ln); | ||||||
|  |     TEST_ASSERT_EQUAL(DSTR_INITSZ, dstr->sz); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void test_dstr_append() { | ||||||
|  |     Dstr* dstr; | ||||||
|  |  | ||||||
|  |     // Test simple appending. | ||||||
|  |     dstr = dstr_init(); | ||||||
|  |     char* hello_world = "Hello, world!"; | ||||||
|  |     dstr_append(dstr, hello_world, strlen(hello_world)); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL_STRING(hello_world, dstr->buf); | ||||||
|  |     TEST_ASSERT_EQUAL(strlen(hello_world), dstr->ln); | ||||||
|  |     TEST_ASSERT_EQUAL(DSTR_INITSZ, dstr->sz); | ||||||
|  |  | ||||||
|  |     dstr_destroy(dstr); | ||||||
|  |  | ||||||
|  |     // Test buffer doubling. | ||||||
|  |     dstr = dstr_init(); | ||||||
|  |  | ||||||
|  |     char h[DSTR_INITSZ + 20]; | ||||||
|  |     memset(h, 'h', DSTR_INITSZ + 19); | ||||||
|  |     h[DSTR_INITSZ + 19] = '\0'; | ||||||
|  |     dstr_append(dstr, h, strlen(h)); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL_STRING(h, dstr->buf); | ||||||
|  |     TEST_ASSERT_EQUAL(strlen(h), dstr->ln); | ||||||
|  |     TEST_ASSERT_EQUAL(DSTR_INITSZ * 2, dstr->sz); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void test_dstr_appendch() { | ||||||
|  |     Dstr* dstr; | ||||||
|  |  | ||||||
|  |     // Test simple character appending. | ||||||
|  |     dstr = dstr_init(); | ||||||
|  |     char c = 'c'; | ||||||
|  |     char* c_str = "c"; | ||||||
|  |     dstr_appendch(dstr, c); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL_STRING(c_str, dstr->buf); | ||||||
|  |     TEST_ASSERT_EQUAL(strlen(c_str), dstr->ln); | ||||||
|  |     TEST_ASSERT_EQUAL(DSTR_INITSZ, dstr->sz); | ||||||
|  |  | ||||||
|  |     dstr_destroy(dstr); | ||||||
|  |  | ||||||
|  |     // Test buffer doubling. | ||||||
|  |     dstr = dstr_init(); | ||||||
|  |  | ||||||
|  |     // Test against this string. | ||||||
|  |     char h[DSTR_INITSZ + 20]; | ||||||
|  |     memset(h, 'h', DSTR_INITSZ + 19); | ||||||
|  |     h[DSTR_INITSZ + 19] = '\0'; | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < DSTR_INITSZ + 19; i++) dstr_appendch(dstr, 'h'); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL_STRING(h, dstr->buf); | ||||||
|  |     TEST_ASSERT_EQUAL(strlen(h), dstr->ln); | ||||||
|  |     TEST_ASSERT_EQUAL(DSTR_INITSZ * 2, dstr->sz); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     UNITY_BEGIN(); | ||||||
|  |     RUN_TEST(test_dstr_init); | ||||||
|  |     RUN_TEST(test_dstr_append); | ||||||
|  |     RUN_TEST(test_dstr_appendch); | ||||||
|  |     return UNITY_END(); | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								test/test_htab.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								test/test_htab.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | #include "../src/include/htab.h" | ||||||
|  | #include "Unity/src/unity.h" | ||||||
|  | #include "Unity/src/unity_internals.h" | ||||||
|  | #include <string.h> | ||||||
|  |  | ||||||
|  | void setUp() {} | ||||||
|  | void tearDown() {} | ||||||
|  |  | ||||||
|  | void test_htab() { | ||||||
|  |     char* key = "hello"; | ||||||
|  |     char* data = "world"; | ||||||
|  |  | ||||||
|  |     HTab* htab = htab_init(); | ||||||
|  |  | ||||||
|  |     htab_ins(htab, key, data); | ||||||
|  |  | ||||||
|  |     TEST_ASSERT_EQUAL_STRING(data, htab_get(htab, key)); | ||||||
|  |     TEST_ASSERT_NOT_EQUAL(data, htab_get(htab, "h")); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int main() { | ||||||
|  |     UNITY_BEGIN(); | ||||||
|  |  | ||||||
|  |     RUN_TEST(test_htab); | ||||||
|  |  | ||||||
|  |     return UNITY_END(); | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								test/token.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								test/token.c
									
									
									
									
									
								
							| @@ -1,24 +0,0 @@ | |||||||
| #include "unity/unity.h" |  | ||||||
| #include <stdlib.h> |  | ||||||
|  |  | ||||||
| #include "../src/include/token.h" |  | ||||||
| #include "registry.h" |  | ||||||
| #include "unity/unity_internals.h" |  | ||||||
|  |  | ||||||
| void test_token_init() { |  | ||||||
|     char* s = malloc(sizeof("Hello, world!")); |  | ||||||
|     s = "Hello, world!"; |  | ||||||
|     Token* t = token_init(TOKEN_TYPE_CALL, s); |  | ||||||
|     TEST_ASSERT_EQUAL(TOKEN_TYPE_CALL, t->type); |  | ||||||
|     TEST_ASSERT_EQUAL_STRING("Hello, world!", t->val); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int test_token() { |  | ||||||
|     UNITY_BEGIN(); |  | ||||||
|     RUN_TEST(test_token_init); |  | ||||||
|     return UNITY_END(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| __attribute__((constructor)) void register_token() { |  | ||||||
|     register_test(test_token); |  | ||||||
| } |  | ||||||
| @@ -1,21 +0,0 @@ | |||||||
| The MIT License (MIT) |  | ||||||
|  |  | ||||||
| Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, Greg Williams |  | ||||||
|  |  | ||||||
| Permission is hereby granted, free of charge, to any person obtaining a copy |  | ||||||
| of this software and associated documentation files (the "Software"), to deal |  | ||||||
| in the Software without restriction, including without limitation the rights |  | ||||||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |  | ||||||
| copies of the Software, and to permit persons to whom the Software is |  | ||||||
| furnished to do so, subject to the following conditions: |  | ||||||
|  |  | ||||||
| The above copyright notice and this permission notice shall be included in |  | ||||||
| all copies or substantial portions of the Software. |  | ||||||
|  |  | ||||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |  | ||||||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |  | ||||||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |  | ||||||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |  | ||||||
| THE SOFTWARE. |  | ||||||
							
								
								
									
										2501
									
								
								test/unity/unity.c
									
									
									
									
									
								
							
							
						
						
									
										2501
									
								
								test/unity/unity.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,698 +0,0 @@ | |||||||
| /* ========================================================================= |  | ||||||
|     Unity - A Test Framework for C |  | ||||||
|     ThrowTheSwitch.org |  | ||||||
|     Copyright (c) 2007-24 Mike Karlesky, Mark VanderVoord, & Greg Williams |  | ||||||
|     SPDX-License-Identifier: MIT |  | ||||||
| ========================================================================= */ |  | ||||||
|  |  | ||||||
| #ifndef UNITY_FRAMEWORK_H |  | ||||||
| #define UNITY_FRAMEWORK_H |  | ||||||
| #define UNITY |  | ||||||
|  |  | ||||||
| #define UNITY_VERSION_MAJOR    2 |  | ||||||
| #define UNITY_VERSION_MINOR    6 |  | ||||||
| #define UNITY_VERSION_BUILD    0 |  | ||||||
| #define UNITY_VERSION          ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) |  | ||||||
|  |  | ||||||
| #ifdef __cplusplus |  | ||||||
| extern "C" |  | ||||||
| { |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include "unity_internals.h" |  | ||||||
|  |  | ||||||
| /*------------------------------------------------------- |  | ||||||
|  * Test Setup / Teardown |  | ||||||
|  *-------------------------------------------------------*/ |  | ||||||
|  |  | ||||||
| /* These functions are intended to be called before and after each test. |  | ||||||
|  * If using unity directly, these will need to be provided for each test |  | ||||||
|  * executable built. If you are using the test runner generator and/or |  | ||||||
|  * Ceedling, these are optional. */ |  | ||||||
| void setUp(void); |  | ||||||
| void tearDown(void); |  | ||||||
|  |  | ||||||
| /* These functions are intended to be called at the beginning and end of an |  | ||||||
|  * entire test suite.  suiteTearDown() is passed the number of tests that |  | ||||||
|  * failed, and its return value becomes the exit code of main(). If using |  | ||||||
|  * Unity directly, you're in charge of calling these if they are desired. |  | ||||||
|  * If using Ceedling or the test runner generator, these will be called |  | ||||||
|  * automatically if they exist. */ |  | ||||||
| void suiteSetUp(void); |  | ||||||
| int suiteTearDown(int num_failures); |  | ||||||
|  |  | ||||||
| /*------------------------------------------------------- |  | ||||||
|  * Test Reset and Verify |  | ||||||
|  *-------------------------------------------------------*/ |  | ||||||
|  |  | ||||||
| /* These functions are intended to be called before during tests in order |  | ||||||
|  * to support complex test loops, etc. Both are NOT built into Unity. Instead |  | ||||||
|  * the test runner generator will create them. resetTest will run teardown and |  | ||||||
|  * setup again, verifying any end-of-test needs between. verifyTest will only |  | ||||||
|  * run the verification. */ |  | ||||||
| void resetTest(void); |  | ||||||
| void verifyTest(void); |  | ||||||
|  |  | ||||||
| /*------------------------------------------------------- |  | ||||||
|  * Configuration Options |  | ||||||
|  *------------------------------------------------------- |  | ||||||
|  * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. |  | ||||||
|  |  | ||||||
|  * Integers/longs/pointers |  | ||||||
|  *     - Unity attempts to automatically discover your integer sizes |  | ||||||
|  *       - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h> |  | ||||||
|  *       - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h> |  | ||||||
|  *     - If you cannot use the automatic methods above, you can force Unity by using these options: |  | ||||||
|  *       - define UNITY_SUPPORT_64 |  | ||||||
|  *       - set UNITY_INT_WIDTH |  | ||||||
|  *       - set UNITY_LONG_WIDTH |  | ||||||
|  *       - set UNITY_POINTER_WIDTH |  | ||||||
|  |  | ||||||
|  * Floats |  | ||||||
|  *     - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons |  | ||||||
|  *     - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT |  | ||||||
|  *     - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats |  | ||||||
|  *     - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons |  | ||||||
|  *     - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) |  | ||||||
|  *     - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE |  | ||||||
|  *     - define UNITY_DOUBLE_TYPE to specify something other than double |  | ||||||
|  *     - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors |  | ||||||
|  |  | ||||||
|  * Output |  | ||||||
|  *     - by default, Unity prints to standard out with putchar.  define UNITY_OUTPUT_CHAR(a) with a different function if desired |  | ||||||
|  *     - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure |  | ||||||
|  |  | ||||||
|  * Optimization |  | ||||||
|  *     - by default, line numbers are stored in unsigned shorts.  Define UNITY_LINE_TYPE with a different type if your files are huge |  | ||||||
|  *     - by default, test and failure counters are unsigned shorts.  Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. |  | ||||||
|  |  | ||||||
|  * Test Cases |  | ||||||
|  *     - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script |  | ||||||
|  |  | ||||||
|  * Parameterized Tests |  | ||||||
|  *     - you'll want to create a define of TEST_CASE(...), TEST_RANGE(...) and/or TEST_MATRIX(...) which basically evaluates to nothing |  | ||||||
|  |  | ||||||
|  * Tests with Arguments |  | ||||||
|  *     - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity |  | ||||||
|  |  | ||||||
|  *------------------------------------------------------- |  | ||||||
|  * Basic Fail and Ignore |  | ||||||
|  *-------------------------------------------------------*/ |  | ||||||
|  |  | ||||||
| #define TEST_FAIL_MESSAGE(message)                                                                 UNITY_TEST_FAIL(__LINE__, (message)) |  | ||||||
| #define TEST_FAIL()                                                                                UNITY_TEST_FAIL(__LINE__, NULL) |  | ||||||
| #define TEST_IGNORE_MESSAGE(message)                                                               UNITY_TEST_IGNORE(__LINE__, (message)) |  | ||||||
| #define TEST_IGNORE()                                                                              UNITY_TEST_IGNORE(__LINE__, NULL) |  | ||||||
| #define TEST_MESSAGE(message)                                                                      UnityMessage((message), __LINE__) |  | ||||||
| #define TEST_ONLY() |  | ||||||
| #ifdef UNITY_INCLUDE_PRINT_FORMATTED |  | ||||||
| #define TEST_PRINTF(message, ...)                                                                  UnityPrintF(__LINE__, (message), ##__VA_ARGS__) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| /* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. |  | ||||||
|  * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ |  | ||||||
| #define TEST_PASS()                                                                                TEST_ABORT() |  | ||||||
| #define TEST_PASS_MESSAGE(message)                                                                 do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) |  | ||||||
|  |  | ||||||
| /*------------------------------------------------------- |  | ||||||
|  * Build Directives |  | ||||||
|  *------------------------------------------------------- |  | ||||||
|  |  | ||||||
|  * These macros do nothing, but they are useful for additional build context. |  | ||||||
|  * Tools (like Ceedling) can scan for these directives and make use of them for  |  | ||||||
|  * per-test-executable #include search paths and linking. */ |  | ||||||
|  |  | ||||||
| /* Add source files to a test executable's compilation and linking. Ex: TEST_SOURCE_FILE("sandwiches.c") */ |  | ||||||
| #define TEST_SOURCE_FILE(a) |  | ||||||
|  |  | ||||||
| /* Customize #include search paths for a test executable's compilation. Ex: TEST_INCLUDE_PATH("src/module_a/inc") */ |  | ||||||
| #define TEST_INCLUDE_PATH(a) |  | ||||||
|  |  | ||||||
| /*------------------------------------------------------- |  | ||||||
|  * Test Asserts (simple) |  | ||||||
|  *-------------------------------------------------------*/ |  | ||||||
|  |  | ||||||
| /* Boolean */ |  | ||||||
| #define TEST_ASSERT(condition)                                                                     UNITY_TEST_ASSERT(       (condition), __LINE__, " Expression Evaluated To FALSE") |  | ||||||
| #define TEST_ASSERT_TRUE(condition)                                                                UNITY_TEST_ASSERT(       (condition), __LINE__, " Expected TRUE Was FALSE") |  | ||||||
| #define TEST_ASSERT_UNLESS(condition)                                                              UNITY_TEST_ASSERT(      !(condition), __LINE__, " Expression Evaluated To TRUE") |  | ||||||
| #define TEST_ASSERT_FALSE(condition)                                                               UNITY_TEST_ASSERT(      !(condition), __LINE__, " Expected FALSE Was TRUE") |  | ||||||
| #define TEST_ASSERT_NULL(pointer)                                                                  UNITY_TEST_ASSERT_NULL(    (pointer), __LINE__, " Expected NULL") |  | ||||||
| #define TEST_ASSERT_NOT_NULL(pointer)                                                              UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") |  | ||||||
| #define TEST_ASSERT_EMPTY(pointer)                                                                 UNITY_TEST_ASSERT_EMPTY(    (pointer), __LINE__, " Expected Empty") |  | ||||||
| #define TEST_ASSERT_NOT_EMPTY(pointer)                                                             UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") |  | ||||||
|  |  | ||||||
| /* Integers (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_EQUAL_INT(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT8(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT16(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT32(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT64(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT8(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT16(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT32(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT64(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_size_t(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX8(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX16(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX32(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX64(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_CHAR(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_BITS(mask, expected, actual)                                                   UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_BITS_HIGH(mask, actual)                                                        UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_BITS_LOW(mask, actual)                                                         UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_BIT_HIGH(bit, actual)                                                          UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_BIT_LOW(bit, actual)                                                           UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Integer Not Equal To (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual)                                               UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual)                                              UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual)                                              UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual)                                            UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual)                                            UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual)                                            UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual)                                            UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual)                                              UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual)                                              UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Integer Greater Than/ Less Than (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_GREATER_THAN(threshold, actual)                                                UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT(threshold, actual)                                            UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual)                                           UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| #define TEST_ASSERT_LESS_THAN(threshold, actual)                                                   UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT(threshold, actual)                                               UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT8(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT16(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT32(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT64(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_size_t(threshold, actual)                                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual)                                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual)                                              UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual)                                            UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual)                                        UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual)                                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual)                                               UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual)                                           UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual)                                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual)                                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual)                                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Integer Ranges (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_INT_WITHIN(delta, expected, actual)                                            UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT8_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT16_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT32_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT64_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_size_t_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX_WITHIN(delta, expected, actual)                                            UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Integer Array Ranges (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements)                        UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements)                        UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements)                       UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Structs and Strings */ |  | ||||||
| #define TEST_ASSERT_EQUAL_PTR(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_STRING(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)                                        UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)                                            UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Arrays */ |  | ||||||
| #define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements)                        UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Arrays Compared To Single Value */ |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements)                                 UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements)                                 UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements)                                 UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements)                         UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Floating Point (If Enabled) */ |  | ||||||
| #define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual)                                      UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_FLOAT(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual)                                              UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements)                      UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual)                                          UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual)                                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual)                                             UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual)                                         UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_INF(actual)                                                           UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NEG_INF(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NAN(actual)                                                           UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual)                                                   UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_INF(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual)                                                   UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual)                                               UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Double (If Enabled) */ |  | ||||||
| #define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual)                                     UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_DOUBLE(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual)                                             UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements)                     UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual)                                         UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual)                                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual)                                            UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual)                                        UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_INF(actual)                                                          UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NAN(actual)                                                          UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual)                                                  UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual)                                                  UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual)                                              UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) |  | ||||||
|  |  | ||||||
| /* Shorthand */ |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_OLD |  | ||||||
| #define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") |  | ||||||
| #endif |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_INT |  | ||||||
| #define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #endif |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_MEM |  | ||||||
| #define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #endif |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_RAW |  | ||||||
| #define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") |  | ||||||
| #endif |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_NONE |  | ||||||
| #define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| /*------------------------------------------------------- |  | ||||||
|  * Test Asserts (with additional messages) |  | ||||||
|  *-------------------------------------------------------*/ |  | ||||||
|  |  | ||||||
| /* Boolean */ |  | ||||||
| #define TEST_ASSERT_MESSAGE(condition, message)                                                    UNITY_TEST_ASSERT(       (condition), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_TRUE_MESSAGE(condition, message)                                               UNITY_TEST_ASSERT(       (condition), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UNLESS_MESSAGE(condition, message)                                             UNITY_TEST_ASSERT(      !(condition), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FALSE_MESSAGE(condition, message)                                              UNITY_TEST_ASSERT(      !(condition), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NULL_MESSAGE(pointer, message)                                                 UNITY_TEST_ASSERT_NULL(    (pointer), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message)                                             UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EMPTY_MESSAGE(pointer, message)                                                UNITY_TEST_ASSERT_EMPTY(    (pointer), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message)                                            UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Integers (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message)                                  UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message)                                       UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message)                                        UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message)                                         UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message)                                          UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Integer Not Equal To (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message)                              UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Integer Greater Than/ Less Than (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message)                               UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| #define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message)                                  UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message)                              UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message)                             UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message)                      UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message)                              UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message)                          UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Integer Ranges (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message)                           UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message)                           UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Integer Array Ranges (of all sizes) */ |  | ||||||
| #define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)       UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)       UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)      UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* Structs and Strings */ |  | ||||||
| #define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message)                       UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message)                           UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Arrays */ |  | ||||||
| #define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message)       UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Arrays Compared To Single Value*/ |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message)                UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message)                UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message)                UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message)        UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Floating Point (If Enabled) */ |  | ||||||
| #define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message)                             UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)     UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message)                         UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message)                     UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message)                            UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message)                                          UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message)                                          UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message)                                  UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message)                                  UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message)                              UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Double (If Enabled) */ |  | ||||||
| #define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message)                            UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message)    UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message)                        UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message)                    UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message)                           UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message)                       UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message)                                         UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message)                                         UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message)                                 UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message)                                 UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message)                             UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) |  | ||||||
|  |  | ||||||
| /* Shorthand */ |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_OLD |  | ||||||
| #define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) |  | ||||||
| #endif |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_INT |  | ||||||
| #define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #endif |  | ||||||
| #ifdef  UNITY_SHORTHAND_AS_MEM |  | ||||||
| #define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #endif |  | ||||||
| #ifdef  UNITY_SHORTHAND_AS_RAW |  | ||||||
| #define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) |  | ||||||
| #endif |  | ||||||
| #ifdef UNITY_SHORTHAND_AS_NONE |  | ||||||
| #define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| /* end of UNITY_FRAMEWORK_H */ |  | ||||||
| #ifdef __cplusplus |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| #endif |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										131
									
								
								test/val/test.bats
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								test/val/test.bats
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | #!/usr/bin/env bats | ||||||
|  |  | ||||||
|  | bin() { ./scl.out $1 | tail -n1; } | ||||||
|  |  | ||||||
|  | @test "simple addition" { | ||||||
|  |     run bin "1+1" | ||||||
|  |     [ "$output" = "= 2.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1+1" | ||||||
|  |     echo $output | ||||||
|  |     [ "$output" = "= 0.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "1+-1" | ||||||
|  |     [ "$output" = "= 0.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1+-1" | ||||||
|  |     [ "$output" = "= -2.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "simple subtraction" { | ||||||
|  |     run bin "1-1" | ||||||
|  |     [ "$output" = "= 0.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1-1" | ||||||
|  |     [ "$output" = "= -2.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "1--1" | ||||||
|  |     [ "$output" = "= 2.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1--1" | ||||||
|  |     [ "$output" = "= 0.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "simple multiplication" { | ||||||
|  |     run bin "1*2" | ||||||
|  |     [ "$output" = "= 2.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1*2" | ||||||
|  |     [ "$output" = "= -2.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "1*-1" | ||||||
|  |     [ "$output" = "= -1.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1*-1" | ||||||
|  |     [ "$output" = "= 1.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "simple division" { | ||||||
|  |     run bin "1/2" | ||||||
|  |     [ "$output" = "= 0.500000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1/2" | ||||||
|  |     [ "$output" = "= -0.500000" ] | ||||||
|  |  | ||||||
|  |     run bin "1/-1" | ||||||
|  |     [ "$output" = "= -1.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-1/-1" | ||||||
|  |     [ "$output" = "= 1.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "order of operations" { | ||||||
|  |     run bin "1+2*3" | ||||||
|  |     [ "$output" = "= 7.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "2*3+1" | ||||||
|  |     [ "$output" = "= 7.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "6/2-1" | ||||||
|  |     [ "$output" = "= 2.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "1-6/2" | ||||||
|  |     [ "$output" = "= -2.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "order of operations with parenthesis" { | ||||||
|  |     run bin "(1+2)*3" | ||||||
|  |     [ "$output" = "= 9.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-(1+2*3)" | ||||||
|  |     [ "$output" = "= -7.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "-(-(1+2)*3)" | ||||||
|  |     [ "$output" = "= 9.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "basic blocks" { | ||||||
|  |     run bin "{1}" | ||||||
|  |     [ "$output" = "= 1.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "2+{3;4}" | ||||||
|  |     [ "$output" = "= 6.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "5*{1+1;5*2}" | ||||||
|  |     echo $output | ||||||
|  |     [ "$output" = "= 50.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @test "variable definition" { | ||||||
|  |     run bin "x=1" | ||||||
|  |     [ "$output" = "= 1.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "x=1;x+1" | ||||||
|  |     [ "$output" = "= 2.000000" ] | ||||||
|  |  | ||||||
|  |     run bin "h=7;j=2;k=8;l=4;h*h-l+j*k" | ||||||
|  |     echo $output | ||||||
|  |     [ "$output" = "= 61.000000" ] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #@test "function definition" { | ||||||
|  | #    run bin "f(n)=2*n; f(2)" | ||||||
|  | #    [ "$output" = "= 4.000000" ] | ||||||
|  | #} | ||||||
|  |  | ||||||
|  | @test "type stuff" { | ||||||
|  |     run bin "x:int=1" | ||||||
|  |     [ "$output" = "= 1" ] | ||||||
|  |  | ||||||
|  |     run bin "x=1.5; type(x)" | ||||||
|  |     [ "$output" = "= num"] | ||||||
|  |  | ||||||
|  |     run bin "x:int=1.5; type(x)" | ||||||
|  |     [ "$output" = "= int" ] | ||||||
|  |  | ||||||
|  |     run bin "x:int=1.5" | ||||||
|  |     [ "$output" = "= 1" ] | ||||||
|  |  | ||||||
|  |     run bin "print(\"Hello, world!\")" | ||||||
|  |     [ "$output" = "= Hello, world!" ] | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								type_notes.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								type_notes.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | n: Int = 3 | ||||||
|  |  | ||||||
|  | - 'Int': integer constructor | ||||||
|  | - '3': integer literal | ||||||
|  |  | ||||||
|  | v: Vec(3, Int) = <1, 2, 3> | ||||||
|  |  | ||||||
|  | Point: Struct = { x: Int, y: Int } | ||||||
|  |  | ||||||
|  | p: Point = { .x = 1, .y = 2 } | ||||||
|  | p.x + p.y | ||||||
|  |  | ||||||
|  | VecOf(n: Int, t: Type): Type = Vec(n, t) | ||||||
|  | strings: VecOf(3, Str) = <"Hello", ",", " world."> | ||||||
|  |  | ||||||
|  | f(g) = g(2) | ||||||
|  |  | ||||||
|  | g(n: Int): Int = n * 2 | ||||||
|  | g: Lambda(Int, Int) = \(n: Int):Int n * 2 | ||||||
|  |  | ||||||
|  | Int, Vec, Str | ||||||
|  |  | ||||||
|  | f(g: \(Int):Int ):Int = g(2) | ||||||
|  | f(g: Lambda(Int, Int)): Int = g(2) | ||||||
|  |  | ||||||
|  | f: Lambda(Int, Str, Str) = \(s1: Str, s2: Str) length(s) + length(s2) | ||||||
|  |  | ||||||
|  | Bad: Type = if Until.time() % 2 == 0 Str Int | ||||||
|  |  | ||||||
|  | - Types are code. | ||||||
|  | - All types inherit from `Type` (the type of `Type` is `Type`). | ||||||
		Reference in New Issue
	
	Block a user