aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Moon Flower <moon@coffin.ir> 2025-08-07 20:10:31 +0330
committerGravatar Moon Flower <moon@coffin.ir> 2025-08-07 20:10:31 +0330
commit2447ad82249a7d2bc3e472e1e556c3de98ed4774 (patch)
tree2e6d4bab26711407d98ce044d8ccc0be0effdc02
parentcomment (diff)
repl demo
-rw-r--r--.clangd2
-rw-r--r--code.pasm2
-rw-r--r--pu.c211
-rw-r--r--pu.out.cbin703 -> 1016 bytes
-rw-r--r--putest.c329
-rw-r--r--repl.pu1
6 files changed, 369 insertions, 176 deletions
diff --git a/.clangd b/.clangd
index 80a0695..ac5fc10 100644
--- a/.clangd
+++ b/.clangd
@@ -1,2 +1,2 @@
CompileFlags:
- Add: [-std=c89] \ No newline at end of file
+ Add: [-std=c99, -x, c] \ No newline at end of file
diff --git a/code.pasm b/code.pasm
index 89acae2..d916970 100644
--- a/code.pasm
+++ b/code.pasm
@@ -4,4 +4,4 @@ con 99
# putchar code
ar4 con 60 ar2 r4a mem con 1 ar4 con 60 ar3 con 0 ar2 con 2 hlt
-hlt
+hlt \ No newline at end of file
diff --git a/pu.c b/pu.c
index 4e93a31..7678e5d 100644
--- a/pu.c
+++ b/pu.c
@@ -1,9 +1,16 @@
+#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
+#include <unistd.h>
+
#pragma clang diagnostic ignored "-Wreturn-type"
#pragma clang diagnostic ignored "-Wc23-extensions"
+#pragma clang diagnostic ignored "-Wnull-character"
+#pragma clang diagnostic ignored "-Wimplicit-int"
+
+#define CLAY_IMPLEMENTATION
+#include "clay.h"
// clang-format off
#define S 65536
@@ -67,7 +74,7 @@ int emu() {
int size = m[ 3 ], i = 0;
for (; i < size; i++) putchar(m[ ptr++ ]);
- write(STDOUT_FILENO, &m[ ptr ], size);
+ while (size--) putchar(m[ ptr++ ]);
}
// 1: input character
@@ -87,36 +94,7 @@ int emu() {
char R_backup[] = "hlt\0 ar1\2 ar2\3 ar3\4 ar4\5 ar5\6 ar6\7 ar7\x8 ar8\x9 r1a\xA r2a\xB r3a\xC "
"r4a\xD r5a\xE r6a\xF r7a\20 r8a\21 mem\22 aca\23 add\24 sub\25 not\26 clr\27";
-int main(int argc, char **argv) {
- if (access("t", F_OK)) {
- // patch the instruction table incase you removed it.
- printf("you've deleted t! i'll write it again for you.\n\n");
- FILE *fp = fopen("t", "w+");
- fwrite(R_backup, 1, sizeof(R_backup), fp);
- fclose(fp);
- memcpy(R, R_backup, sizeof(R_backup));
- }
-
- if (argc == 1) {
- printf("Usage:\n %s <filename>", argv[ 0 ]);
- exit(1);
- }
-
- // read code
- FILE *fp = fopen(argv[ 1 ], "r");
- fseek(fp, 0, SEEK_END);
- int sz = ftell(fp);
- rewind(fp);
- char code[ sz + 1 ];
- fread(code, 1, sz, fp);
- code[ sz ] = 0;
- fclose(fp);
-
- // set pc
- m[ 7 ] = 1024;
- // assemble
- char *fail_point = as(code, &m[ 1024 ]);
-
+void error_debug(char *fail_point, char *code, int sz) {
if (fail_point != 0) {
int error_pos = (int) (fail_point - code);
int i;
@@ -132,7 +110,14 @@ int main(int argc, char **argv) {
}
fprintf(
- stderr, "Assembly failed at line %d, column %d (position %d):\n", line, col, error_pos);
+ stderr,
+ "\x1b[1m\x1b[31merror:\x1b[0m "
+ "\x1b[1massembly failed\x1b[0m "
+ "at \x1b[36mline %d\x1b[0m, \x1b[36mcolumn %d\x1b[0m "
+ "(\x1b[33mposition %d\x1b[0m):\n",
+ line,
+ col,
+ error_pos);
int line_start = error_pos;
while (line_start > 0 && code[ line_start - 1 ] != '\n') { line_start--; }
@@ -142,17 +127,169 @@ int main(int argc, char **argv) {
line_end++;
}
- fprintf(stderr, " ");
+ fprintf(stderr, " \x1b[1m");
for (i = line_start; i < line_end; i++) { fputc(code[ i ], stderr); }
- fprintf(stderr, "\n");
+ fprintf(stderr, "\x1b[0m\n");
fprintf(stderr, " ");
- for (i = line_start; i < error_pos; i++) { fputc(' ', stderr); }
- fprintf(stderr, "^ parsing stopped here\n");
+ for (i = line_start; i < error_pos; i++) {
+ fputc((code[ i ] == '\t') ? '\t' : ' ', stderr);
+ }
+ fprintf(stderr, "\x1b[1m\x1b[31m^\x1b[0m \x1b[90mparsing stopped here\x1b[0m\n");
+ }
+}
+int main(int argc, char **argv) {
+ if (access("t", F_OK)) {
+ // patch the instruction table incase you removed it.
+ printf("you've deleted `t`! i'll write it again for you.\n\n");
+ FILE *fp = fopen("t", "w+");
+ fwrite(R_backup, 1, sizeof(R_backup), fp);
+ fclose(fp);
+ memcpy(R, R_backup, sizeof(R_backup));
+ }
+
+ if (argc == 1) {
+ printf(
+ "Usage:\n %s run <filename>: Execute a file\n %s repl: Open in REPL mode",
+ argv[ 0 ],
+ argv[ 0 ]);
exit(1);
}
+ if (argc == 2 && !strcmp(argv[ 1 ], "repl")) {
+ printf("\npu repl\n"
+ "| code is inserted at address 1024\n"
+ "| submit RUN to execute the code.\n"
+ "| submit CLEAR to erase history.\n"
+ "| submit SAVE to write contents to repl.pu\n"
+ "| submit LOAD to fetch contents from repl.pu\n"
+ "\n");
+
+ char *code = malloc(1);
+ *code = '\n';
+ size_t size = 0;
+
+ while (1) {
+ printf("%li > ", size);
+ char *line;
+ size_t _len;
+ size_t len = getline(&line, &_len, stdin);
+
+ if (len == 1) continue;
+
+ if (len == 4 && strncmp(line, "run", 3) == 0) {
+ memset(m, 0, 8);
+ m[ 7 ] = 1024;
+ emu();
+ continue;
+ }
+
+ if (len == 5 && strncmp(line, "save", 4) == 0) {
+ FILE *fd = fopen("repl.pu", "w+");
+ fwrite(code, 1, size, fd);
+ fclose(fd);
+ printf("saved %li bytes.\n", size);
+
+ continue;
+ }
+
+ if (len == 5 && strncmp(line, "load", 4) == 0) {
+ FILE *fp = fopen("repl.pu", "r");
+ fseek(fp, 0, SEEK_END);
+ int sz = ftell(fp);
+ rewind(fp);
+ char *saved = malloc(sz + 1);
+ fread(saved, 1, sz, fp);
+ saved[ sz ] = 0;
+ fclose(fp);
+
+ free(code);
+ code = saved;
+ size = sz;
+ printf("loaded %i bytes.\n", sz);
+
+ goto SKIP_STRAIGHT;
+ }
+
+ if (len == 6 && strncmp(line, "clear", 5) == 0) {
+ printf("-- code cleared\n");
+ free(code);
+ code = malloc(1);
+ size = 0;
+ continue;
+ }
+
+ if (len == 7 && strncmp(line, "status", 6) == 0) {
+ printf(
+ "\nregisters\n"
+ "r1: %i r2: %i\n"
+ "r3: %i r4: %i\n"
+ "r5: %i r6: %i\n"
+ "r7: %i pc: %i\n\n",
+ m[ 0 ],
+ m[ 1 ],
+ m[ 2 ],
+ m[ 3 ],
+ m[ 4 ],
+ m[ 5 ],
+ m[ 6 ],
+ m[ 7 ]);
+
+ continue;
+ }
+
+ char *old_code = malloc(size);
+ memcpy(old_code, code, size);
+
+ code = realloc(code, size += len);
+ memcpy(&code[ size - len ], line, len);
+
+ SKIP_STRAIGHT:
+
+ char *exit_code = as(code, &m[ 1024 ]);
+
+ #define COLOR_RED "\e[0;31m"
+ #define COLOR_RESET "\e[0m"
+
+ if (exit_code != 0) {
+ printf(COLOR_RED "\n");
+ error_debug(exit_code, code, size);
+ printf("\n" COLOR_RESET);
+
+ free(code);
+ code = old_code;
+ size -= len;
+ continue;
+ }
+
+ free(old_code);
+ }
+
+ exit(0);
+ }
+
+ if (argc == 3 && strcmp(argv[ 1 ], "run") != 0) {
+ printf("Invalid mode - Only supported modes are 'run' and 'repl'\n");
+ }
+
+ // read code
+ FILE *fp = fopen(argv[ 2 ], "r");
+ fseek(fp, 0, SEEK_END);
+ int sz = ftell(fp);
+ rewind(fp);
+ char code[ sz + 1 ];
+ fread(code, 1, sz, fp);
+ code[ sz ] = 0;
+ fclose(fp);
+
+ // set pc
+ m[ 7 ] = 1024;
+ // assemble
+ char *fail_point = as(code, &m[ 1024 ]);
+
+ error_debug(fail_point, code, sz);
+
// run emulation
emu();
}
diff --git a/pu.out.c b/pu.out.c
index 4d0c9af..4f7b348 100644
--- a/pu.out.c
+++ b/pu.out.c
Binary files differ
diff --git a/putest.c b/putest.c
index d223a42..013a48b 100644
--- a/putest.c
+++ b/putest.c
@@ -2,7 +2,29 @@
#include <string.h>
#define __WRAPPER
-#include "pu.c"
+#include "pu.out.c"
+
+/* ─── color & statistics ──────────────────────────────────────────────────── */
+#define COLOR_RED "\x1b[1;31m"
+#define COLOR_BLUE "\033[1;34m"
+#define COLOR_SUM "\033[1;33m"
+#define COLOR_RESET "\x1b[0m"
+
+static int tests_run = 0;
+static int tests_passed = 0;
+
+/* PASS if cond true, else FAIL; color and bump counters */
+#define PRINT_RESULT(cond) \
+ do { \
+ tests_run++; \
+ if (cond) { \
+ tests_passed++; \
+ printf(COLOR_BLUE "PASS" COLOR_RESET "\n"); \
+ } else { \
+ printf(COLOR_RED "FAIL" COLOR_RESET "\n"); \
+ } \
+ } while (0)
+/* ───────────────────────────────────────────────────────────────────────── */
void reset() {
memset(m, 0, sizeof(m));
@@ -13,283 +35,310 @@ void reset() {
void test_opcode_0() {
printf("Testing opcode 0 (hlt)... ");
reset();
- m[0] = 0; // hlt instruction
- m[7] = 0; // pc starts at 0
+ m[ 0 ] = 0;
+ m[ 7 ] = 0;
pu();
- printf("PASS\n");
+ PRINT_RESULT(1);
}
void test_opcode_1() {
printf("Testing opcode 1 (const in r0)... ");
reset();
- m[0] = 1; // const instruction
- m[1] = 42; // constant value
- m[2] = 0; // hlt
- m[7] = 0; // pc starts at 0
+ m[ 0 ] = 1;
+ m[ 1 ] = 42;
+ m[ 2 ] = 0;
+ m[ 7 ] = 0;
pu();
- printf("r0=%d (expected 42): %s\n", m[0], m[0] == 42 ? "PASS" : "FAIL");
+ PRINT_RESULT(m[ 0 ] == 42);
}
void test_opcode_2() {
- printf("Testing opcode 4 (r0 in r2 if acc non-zero)... ");
+ printf("Testing opcode 4 (r0 in r2 if acc zero)... ");
reset();
- m[0] = 123; // r0 = 123
- a = 1; // acc = 1 (non-zero)
- m[10] = 4; // opcode 4
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ m[ 0 ] = 123;
+ a = 0;
+ m[ 10 ] = 4;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("r2=%d (expected 123): %s\n", m[2], m[2] == 123 ? "PASS" : "FAIL");
+ PRINT_RESULT(m[ 2 ] == 123);
}
void test_opcode_2_zero_acc() {
printf("Testing opcode 4 with zero acc (should not store)... ");
reset();
- m[0] = 123; // r0 = 123
- m[2] = 999; // r2 = 999 initially
- a = 0; // acc = 0
- m[10] = 4; // opcode 4
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ m[ 0 ] = 123;
+ m[ 2 ] = 999;
+ a = 1;
+ m[ 10 ] = 4;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("r2=%d (expected 999): %s\n", m[2], m[2] == 999 ? "PASS" : "FAIL");
+ PRINT_RESULT(m[ 2 ] == 999);
}
void test_opcode_10() {
printf("Testing opcode 12 (r2 in r0)... ");
reset();
- m[2] = 456; // r2 = 456
- m[10] = 12; // opcode 12
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ m[ 2 ] = 456;
+ m[ 10 ] = 12;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("r0=%d (expected 456): %s\n", m[0], m[0] == 456 ? "PASS" : "FAIL");
+ PRINT_RESULT(m[ 0 ] == 456);
}
void test_opcode_18() {
printf("Testing opcode 18 (r0 in m[r1])... ");
reset();
- m[0] = 789; // r0 = 789
- m[1] = 100; // r1 = 100 (address)
- m[10] = 18; // opcode 18
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ m[ 0 ] = 789;
+ m[ 1 ] = 100;
+ m[ 10 ] = 18;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("m[100]=%d (expected 789): %s\n", m[100], m[100] == 789 ? "PASS" : "FAIL");
+ PRINT_RESULT(m[ 100 ] == 789);
}
void test_opcode_19() {
printf("Testing opcode 19 (acc in r0)... ");
reset();
- a = 555; // acc = 555
- m[10] = 19; // opcode 19
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ a = 555;
+ m[ 10 ] = 19;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("r0=%d (expected 555): %s\n", m[0], m[0] == 555 ? "PASS" : "FAIL");
+ PRINT_RESULT(m[ 0 ] == 555);
}
void test_opcode_20() {
printf("Testing opcode 20 (acc += r0)... ");
reset();
- a = 10; // acc = 10
- m[0] = 5; // r0 = 5
- m[10] = 20; // opcode 20
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ a = 10;
+ m[ 0 ] = 5;
+ m[ 10 ] = 20;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("acc=%d (expected 15): %s\n", a, a == 15 ? "PASS" : "FAIL");
+ PRINT_RESULT(a == 15);
}
void test_opcode_21() {
printf("Testing opcode 21 (acc -= r0)... ");
reset();
- a = 20; // acc = 20
- m[0] = 7; // r0 = 7
- m[10] = 21; // opcode 21
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ a = 20;
+ m[ 0 ] = 7;
+ m[ 10 ] = 21;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("acc=%d (expected 13): %s\n", a, a == 13 ? "PASS" : "FAIL");
+ PRINT_RESULT(a == 13);
}
void test_opcode_22() {
printf("Testing opcode 22 (acc = !acc)... ");
reset();
- a = 5; // acc = 5 (non-zero)
- m[10] = 22; // opcode 22
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ a = 5;
+ m[ 10 ] = 22;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("acc=%d (expected 0): %s\n", a, a == 0 ? "PASS" : "FAIL");
+ PRINT_RESULT(a == 0);
}
void test_opcode_23() {
printf("Testing opcode 23 (acc = 0)... ");
reset();
- a = 999; // acc = 999
- m[10] = 23; // opcode 23
- m[11] = 0; // hlt
- m[7] = 10; // pc starts at 10
+ a = 999;
+ m[ 10 ] = 23;
+ m[ 11 ] = 0;
+ m[ 7 ] = 10;
pu();
- printf("acc=%d (expected 0): %s\n", a, a == 0 ? "PASS" : "FAIL");
+ PRINT_RESULT(a == 0);
}
-// Helper to compare output array with expected values
-int check_output(int *O, int *expected, int len, const char *test_name) {
- int i;
+/* ─── assembler support ───────────────────────────────────────────────────── */
+
+i;
+int check_output(int* O, int* expected, int len, const char* test_name) {
for (i = 0; i < len; i++) {
- if (O[i] != expected[i]) {
- printf("%s: output[%d]=%d (expected %d): FAIL\n", test_name, i, O[i], expected[i]);
+ if (O[ i ] != expected[ i ]) {
+ printf(
+ "%s: output[%d]=%d (expected %d): " COLOR_RED "FAIL" COLOR_RESET "\n",
+ test_name,
+ i,
+ O[ i ],
+ expected[ i ]);
return 0;
}
}
- printf("%s: PASS\n", test_name);
return 1;
}
-// Reset output array
-void reset_output(int *O, int size) {
- memset(O, 0, size * sizeof(int));
-}
+void reset_output(int* O, int size) { memset(O, 0, size * sizeof(int)); }
void test_hlt() {
printf("Testing hlt (opcode 0)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {0};
- int ret = as("hlt", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "hlt") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 0 };
+ char* ret = as("hlt", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "hlt"));
+ PRINT_RESULT(ok);
}
void test_con() {
printf("Testing con 123 (opcode 1, 123)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {1, 123};
- int ret = as("con 123", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 2, "con") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 1, 123 };
+ char* ret = as("con 123", O);
+ ok = (ret == 0 && check_output(O, exp, 2, "con"));
+ PRINT_RESULT(ok);
}
void test_ar1() {
printf("Testing ar1 (opcode 2)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {2};
- int ret = as("ar1", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "ar1") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 2 };
+ char* ret = as("ar1", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "ar1"));
+ PRINT_RESULT(ok);
}
void test_ar8() {
printf("Testing ar8 (opcode 9)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {9};
- int ret = as("ar8", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "ar8") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 9 };
+ char* ret = as("ar8", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "ar8"));
+ PRINT_RESULT(ok);
}
void test_r1a() {
printf("Testing r1a (opcode 10)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {10};
- int ret = as("r1a", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "r1a") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 10 };
+ char* ret = as("r1a", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "r1a"));
+ PRINT_RESULT(ok);
}
void test_r8a() {
printf("Testing r8a (opcode 17)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {17};
- int ret = as("r8a", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "r8a") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 17 };
+ char* ret = as("r8a", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "r8a"));
+ PRINT_RESULT(ok);
}
void test_mem() {
printf("Testing mem (opcode 18)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {18};
- int ret = as("mem", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "mem") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 18 };
+ char* ret = as("mem", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "mem"));
+ PRINT_RESULT(ok);
}
void test_aca() {
printf("Testing aca (opcode 19)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {19};
- int ret = as("aca", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "aca") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 19 };
+ char* ret = as("aca", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "aca"));
+ PRINT_RESULT(ok);
}
void test_add() {
printf("Testing add (opcode 20)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {20};
- int ret = as("add", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "add") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 20 };
+ char* ret = as("add", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "add"));
+ PRINT_RESULT(ok);
}
void test_sub() {
printf("Testing sub (opcode 21)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {21};
- int ret = as("sub", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "sub") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 21 };
+ char* ret = as("sub", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "sub"));
+ PRINT_RESULT(ok);
}
void test_not() {
printf("Testing not (opcode 22)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {22};
- int ret = as("not", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "not") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 22 };
+ char* ret = as("not", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "not"));
+ PRINT_RESULT(ok);
}
void test_clr() {
printf("Testing clr (opcode 23)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {23};
- int ret = as("clr", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 1, "clr") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 23 };
+ char* ret = as("clr", O);
+ ok = (ret == 0 && check_output(O, exp, 1, "clr"));
+ PRINT_RESULT(ok);
}
void test_multi_instruction() {
printf("Testing multi-instruction (hlt con 123 ar1 clr)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {0, 1, 123, 2, 23};
- int ret = as("hlt con 123 ar1 clr", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 5, "multi-instruction") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 0, 1, 123, 2, 23 };
+ char* ret = as("hlt con 123 ar1 clr", O);
+ ok = (ret == 0 && check_output(O, exp, 5, "multi-instruction"));
+ PRINT_RESULT(ok);
}
void test_whitespace() {
printf("Testing whitespace handling (hlt \\t\\n con 456 \\n clr)... ");
- int O[10];
+ int O[ 10 ], ok;
+ reset_output(O, 10);
+ int exp[] = { 0, 1, 456, 23 };
+ char* ret = as("hlt \t\n con 456 \n clr", O);
+ ok = (ret == 0 && check_output(O, exp, 4, "whitespace"));
+ PRINT_RESULT(ok);
+}
+
+void test_comment() {
+ printf("Testing comment handling (should ignore line)... ");
+ int O[ 10 ], ok;
reset_output(O, 10);
- int expected[] = {0, 1, 456, 23};
- int ret = as("hlt \t\n con 456 \n clr", O);
- printf("return=%d (expected 0): %s\n", ret, ret == 0 ? check_output(O, expected, 4, "whitespace") ? "PASS" : "FAIL" : "FAIL");
+ int exp[] = { 1, 90 };
+ char* ret = as("# hello\ncon 90", O);
+ ok = (ret == 0 && check_output(O, exp, 2, "comment"));
+ PRINT_RESULT(ok);
}
void test_error() {
printf("Testing error case (invalid instruction)... ");
- int O[10];
+ int O[ 10 ], ok;
reset_output(O, 10);
- int ret = as("xyz", O);
- printf("return=%d (expected 1): %s\n", ret, ret == 1 ? "PASS" : "FAIL");
+ char* ret = as("xyz", O);
+ ok = (ret != 0);
+ PRINT_RESULT(ok);
}
int main() {
- printf("Running CPU unit tests...\n\n");
-
+ printf(COLOR_SUM "Running CPU unit tests...\n\n" COLOR_RESET);
+
test_opcode_0();
test_opcode_1();
test_opcode_2();
@@ -302,8 +351,8 @@ int main() {
test_opcode_22();
test_opcode_23();
- printf("\n\nRunning assembler unit tests...\n\n");
-
+ printf(COLOR_SUM "\nRunning assembler unit tests...\n\n" COLOR_RESET);
+
test_hlt();
test_con();
test_ar1();
@@ -318,8 +367,14 @@ int main() {
test_clr();
test_multi_instruction();
test_whitespace();
+ test_comment();
test_error();
-
-
+
+ printf(
+ "\nTotal tests run: %d, passed: %d, failed: %d\n",
+ tests_run,
+ tests_passed,
+ tests_run - tests_passed);
+
return 0;
-} \ No newline at end of file
+}
diff --git a/repl.pu b/repl.pu
new file mode 100644
index 0000000..2cb3020
--- /dev/null
+++ b/repl.pu
@@ -0,0 +1 @@
+con 5