Compare commits

..
42 Commits
Author SHA1 Message Date
retoor f310788168 Update.
Build and Test / build (push) Successful in 8s
2025-11-24 15:07:12 +01:00
retoor e17b235ecc Update. 2025-11-24 11:21:23 +01:00
retoor 4dc33c81b4 Update. 2025-11-24 11:12:34 +01:00
retoor c08fa0cc6a Improvements. 2025-11-24 11:09:55 +01:00
retoor 3252560f94 More robuust. 2025-11-24 10:42:54 +01:00
retoor ded2448ebd Update. 2025-11-24 10:26:12 +01:00
retoor fc05199a76 Update. 2025-11-24 10:21:23 +01:00
retoor 863434f9af Update.
Build and Test / build (push) Successful in 8s
2025-11-24 10:00:49 +01:00
retoor f61c15061d Update. 2025-11-24 09:08:13 +01:00
retoor e7b8f7f68c Update. 2025-11-24 08:55:17 +01:00
retoor cecbdc4053 Update. 2025-11-24 05:51:03 +01:00
retoor 1b57b479bb global var optimizations. 2025-11-24 03:47:07 +01:00
retoor b3b117d3a5 Fixed async. 2025-11-24 03:37:40 +01:00
retoor 6aa82a613e Update. 2025-11-24 02:56:47 +01:00
retoor dfba1c40c4 Robuustness. 2025-11-24 02:19:24 +01:00
retoor 46c18308b8 Error handling. 2025-11-24 02:09:13 +01:00
retoor 0474c958fe Error handling. 2025-11-24 02:09:02 +01:00
retoor d0fc94f0c0 Error handling. 2025-11-24 01:59:54 +01:00
retoor 2f20998f22 Added eval. 2025-11-24 01:46:47 +01:00
retoor 0db921cfa3 More robuust ness. 2025-11-24 01:30:16 +01:00
retoor a1eb00caff Unit test framework with new cases. 2025-11-24 00:50:23 +01:00
retoor 8f175b3563 Added unit test framework. 2025-11-23 23:46:02 +01:00
retoor eacf4f3e36 Working OOP. 2025-11-23 23:23:17 +01:00
retoor 3cbf684dad Structuring. 2025-11-23 23:03:19 +01:00
retoor e75ccec309 Professionalize. 2025-11-23 22:14:15 +01:00
retoor 97fc55f74d UPdate documentation. 2025-11-23 21:33:07 +01:00
retoor 327eeadca4 Implemented async better. 2025-11-23 20:30:37 +01:00
retoor e5f6f89764 Removed file.
Build and Test / build (push) Successful in 17s
2025-11-23 15:59:21 +01:00
retoor 2dae3f98e9 Added build file.
Build and Test / build (push) Successful in 28s
2025-11-23 15:45:39 +01:00
retoor 0ec0590ad0 Added include functionallity. 2025-11-23 15:23:59 +01:00
retoor 6c8a15272a Implemented tests. 2025-11-23 15:07:19 +01:00
retoor 5828aa8622 Async implementation. 2025-11-23 14:30:46 +01:00
retoor 050e85b72a Break loop. 2025-11-23 13:53:36 +01:00
retoor 63f9eb48a4 Update. 2025-11-23 00:19:52 +01:00
retoor 5e1901105a Update. 2025-11-23 00:17:01 +01:00
retoor f315874236 Added tutorial. 2025-11-22 23:28:28 +01:00
retoor bd8d9d819e Update. 2025-11-22 23:15:15 +01:00
retoor e6d75958c8 Update file names. 2025-11-22 22:30:55 +01:00
retoor d087be7ab3 Clean up. 2025-11-22 22:24:53 +01:00
retoor e691b109f2 Update. 2025-11-22 22:24:34 +01:00
retoor cb9b4e2941 Structuring. 2025-11-22 22:22:43 +01:00
retoor ab71aa9999 Working. 2025-11-22 16:53:39 +01:00
21 changed files with 316 additions and 1975 deletions
+12 -25
View File
@@ -22,8 +22,6 @@ SOURCES = $(SRC_DIR)/main.c \
$(SRC_DIR)/error.c \
$(SRC_DIR)/context.c \
$(SRC_DIR)/debug.c \
$(SRC_DIR)/memory.c \
$(SRC_DIR)/scope.c \
$(SRC_DIR)/stdlib/stdlib.c \
$(SRC_DIR)/stdlib/string/string_stdlib.c \
$(SRC_DIR)/stdlib/math/math_stdlib.c \
@@ -32,7 +30,6 @@ SOURCES = $(SRC_DIR)/main.c \
$(SRC_DIR)/stdlib/async/async_stdlib.c \
$(SRC_DIR)/stdlib/constants/constants_stdlib.c \
$(SRC_DIR)/stdlib/eval/eval_stdlib.c \
$(SRC_DIR)/stdlib/benchmark/benchmark_stdlib.c \
OBJECTS = $(SOURCES:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
@@ -44,7 +41,6 @@ TESTS = $(TEST_DIR)/unittest.rc \
$(TEST_DIR)/test_stdlib_socket.rc \
$(TEST_DIR)/test_stdlib_async.rc \
$(TEST_DIR)/test_stdlib_constants.rc \
$(TEST_DIR)/test_stdlib_benchmark.rc \
$(TEST_DIR)/test_oop.rc \
$(TEST_DIR)/test_preprocessor.rc \
$(TEST_DIR)/test_eval.rc \
@@ -68,7 +64,6 @@ dirs:
@mkdir -p $(BUILD_DIR)/stdlib/async
@mkdir -p $(BUILD_DIR)/stdlib/constants
@mkdir -p $(BUILD_DIR)/stdlib/eval
@mkdir -p $(BUILD_DIR)/stdlib/benchmark
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
@mkdir -p $(dir $@)
@@ -85,40 +80,37 @@ test: $(TARGET)
@echo " RC LANGUAGE - COMPREHENSIVE TEST SUITE"
@echo "================================================================"
@echo ""
@echo "[1/12] Running Language Features Tests..."
@echo "[1/11] Running Language Features Tests..."
@$(TARGET) $(TEST_DIR)/test_language_features.rc
@echo ""
@echo "[2/12] Running String Standard Library Tests..."
@echo "[2/11] Running String Standard Library Tests..."
@$(TARGET) $(TEST_DIR)/test_stdlib_string.rc
@echo ""
@echo "[3/12] Running Math Standard Library Tests..."
@echo "[3/11] Running Math Standard Library Tests..."
@$(TARGET) $(TEST_DIR)/test_stdlib_math.rc
@echo ""
@echo "[4/12] Running I/O Standard Library Tests..."
@echo "[4/11] Running I/O Standard Library Tests..."
@$(TARGET) $(TEST_DIR)/test_stdlib_io.rc
@echo ""
@echo "[5/12] Running Socket Standard Library Tests..."
@echo "[5/11] Running Socket Standard Library Tests..."
@$(TARGET) $(TEST_DIR)/test_stdlib_socket.rc
@echo ""
@echo "[6/12] Running Async Standard Library Tests..."
@echo "[6/11] Running Async Standard Library Tests..."
@$(TARGET) $(TEST_DIR)/test_stdlib_async.rc
@echo ""
@echo "[7/12] Running Constants Standard Library Tests..."
@echo "[7/11] Running Constants Standard Library Tests..."
@$(TARGET) $(TEST_DIR)/test_stdlib_constants.rc
@echo ""
@echo "[8/12] Running Benchmark Standard Library Tests..."
@$(TARGET) $(TEST_DIR)/test_stdlib_benchmark.rc
@echo ""
@echo "[9/12] Running OOP Features Tests..."
@echo "[8/11] Running OOP Features Tests..."
@$(TARGET) $(TEST_DIR)/test_oop.rc
@echo ""
@echo "[10/12] Running Preprocessor Tests..."
@echo "[9/11] Running Preprocessor Tests..."
@$(TARGET) $(TEST_DIR)/test_preprocessor.rc
@echo ""
@echo "[11/12] Running Eval Function Tests..."
@echo "[10/11] Running Eval Function Tests..."
@$(TARGET) $(TEST_DIR)/test_eval.rc
@echo ""
@echo "[12/12] Running Input Validation Tests..."
@echo "[11/11] Running Input Validation Tests..."
@$(TARGET) $(TEST_DIR)/test_input_validation.rc
@echo ""
@echo "================================================================"
@@ -161,9 +153,6 @@ test-validation: $(TARGET)
test-constants: $(TARGET)
$(TARGET) $(TEST_DIR)/test_stdlib_constants.rc
test-benchmark: $(TARGET)
$(TARGET) $(TEST_DIR)/test_stdlib_benchmark.rc
test-robustness: $(TARGET)
$(TARGET) $(TEST_DIR)/test_robustness.rc
@@ -198,7 +187,7 @@ help:
@echo ""
@echo "Usage:"
@echo " make - Build the interpreter"
@echo " make test - Run ALL comprehensive tests (300+ tests)"
@echo " make test - Run ALL comprehensive tests (250+ tests)"
@echo " make test-smoke - Run quick smoke test (31 tests)"
@echo " make clean - Remove all build artifacts"
@echo ""
@@ -210,7 +199,6 @@ help:
@echo " make test-socket - Socket stdlib (19 tests)"
@echo " make test-async - Async stdlib (37 tests)"
@echo " make test-constants - Constants stdlib (13 tests)"
@echo " make test-benchmark - Benchmark stdlib (50 tests)"
@echo " make test-oop - OOP features (31 tests)"
@echo " make test-preprocessor - Preprocessor (2 tests)"
@echo " make test-eval - Eval function (30 tests)"
@@ -236,7 +224,6 @@ help:
@echo " stdlib/io/ - I/O functions"
@echo " stdlib/async/ - Async functions"
@echo " stdlib/eval/ - Eval function"
@echo " stdlib/benchmark/ - Benchmarking functions"
@echo " tests/ - Test programs (unittest framework)"
@echo " examples/ - Example programs (.rc files)"
@echo " build/ - Compiled object files"
+1 -330
View File
@@ -31,7 +31,6 @@ Complete guide to the RC (Retoor's C) programming language - a C-like interprete
20. [Async/Await (Python-like)](#asyncawait-python-like)
21. [Object-Oriented Programming](#object-oriented-programming)
22. [Async I/O (Low-level)](#async-io-low-level)
23. [Benchmarking](#benchmarking)
---
@@ -623,33 +622,6 @@ int main() {
}
```
### Random Number Functions
**rand()** - Returns a pseudo-random integer.
**srand(seed)** - Seeds the random number generator.
**rand_range(min, max)** - Returns a random integer in the range [min, max].
**time()** - Returns current Unix timestamp (seconds since epoch).
```c
int main() {
srand(time());
printf("Random: %d\n", rand());
printf("Random: %d\n", rand());
printf("Random: %d\n", rand());
printf("Range [1-10]: %d\n", rand_range(1, 10));
printf("Range [1-10]: %d\n", rand_range(1, 10));
printf("Timestamp: %d\n", time());
return 0;
}
```
## String Manipulation Functions
### strpos(haystack, needle) - Find Substring
@@ -1404,7 +1376,7 @@ Assignment: =
**String:** strlen, strpos, substr, upper, lower, strip, replace, startswith, endswith
**Math:** sqrt, pow, sin, cos, tan, abs, floor, ceil, rand, srand, rand_range, time
**Math:** sqrt, pow, sin, cos, tan, abs, floor, ceil
**File I/O:** fopen, fclose, fread, fwrite, fgets, fputs, fseek, ftell, feof, fremove, frename
@@ -1418,8 +1390,6 @@ Assignment: =
**Constants:** AF_INET, SOCK_STREAM, SEEK_SET, SEEK_CUR, SEEK_END
**Benchmarking:** bench_start, bench_end, bench_format, bench_format_auto, bench_reset
## File I/O
### Writing to a File
@@ -2124,302 +2094,3 @@ int main() {
}
```
---
## Benchmarking
RC provides a high-precision benchmarking system for measuring code execution time with nanosecond accuracy.
### Starting a Timer
Use `bench_start()` to begin timing code execution:
```c
int main() {
int timer = bench_start();
int i = 0;
int sum = 0;
while (i < 1000) {
sum = sum + i;
i = i + 1;
}
int elapsed = bench_end(timer);
printf("Elapsed: %d nanoseconds\n", elapsed);
return 0;
}
```
### Formatting Time
Use `bench_format()` to format time in specific units:
```c
int main() {
int timer = bench_start();
int result = fibonacci(20);
int elapsed = bench_end(timer);
printf("Nanoseconds: %s\n", bench_format(elapsed, 0));
printf("Microseconds: %s\n", bench_format(elapsed, 1));
printf("Milliseconds: %s\n", bench_format(elapsed, 2));
printf("Seconds: %s\n", bench_format(elapsed, 3));
printf("Minutes: %s\n", bench_format(elapsed, 4));
printf("Hours: %s\n", bench_format(elapsed, 5));
return 0;
}
```
**Time Units:**
- 0 = nanoseconds (ns)
- 1 = microseconds (us)
- 2 = milliseconds (ms)
- 3 = seconds (s)
- 4 = minutes (min)
- 5 = hours (h)
### Automatic Formatting
Use `bench_format_auto()` to automatically select the best time unit:
```c
int main() {
int timer = bench_start();
int i = 0;
while (i < 10000) {
i = i + 1;
}
int elapsed = bench_end(timer);
char* formatted = bench_format_auto(elapsed);
printf("Time: %s\n", formatted);
return 0;
}
```
### Multiple Timers
You can use multiple timers concurrently:
```c
int main() {
int timer1 = bench_start();
int timer2 = bench_start();
int timer3 = bench_start();
int result1 = compute_task1();
int elapsed1 = bench_end(timer1);
int result2 = compute_task2();
int elapsed2 = bench_end(timer2);
int result3 = compute_task3();
int elapsed3 = bench_end(timer3);
printf("Task 1: %s\n", bench_format_auto(elapsed1));
printf("Task 2: %s\n", bench_format_auto(elapsed2));
printf("Task 3: %s\n", bench_format_auto(elapsed3));
return 0;
}
```
### Nested Timing
Timers can be nested to measure sub-operations:
```c
int main() {
int outer_timer = bench_start();
printf("Starting outer operation\n");
int inner_timer = bench_start();
int partial_result = compute_part1();
int inner_elapsed = bench_end(inner_timer);
printf("Part 1: %s\n", bench_format_auto(inner_elapsed));
int final_result = compute_part2(partial_result);
int outer_elapsed = bench_end(outer_timer);
printf("Total: %s\n", bench_format_auto(outer_elapsed));
return 0;
}
```
### Comparing Algorithms
Benchmark different approaches:
```c
int approach1(int n) {
int sum = 0;
int i = 0;
while (i < n) {
sum = sum + i;
i = i + 1;
}
return sum;
}
int approach2(int n) {
return (n * (n - 1)) / 2;
}
int main() {
int runs = 100;
int timer1 = bench_start();
int i = 0;
while (i < runs) {
int result = approach1(1000);
i = i + 1;
}
int time1 = bench_end(timer1);
int timer2 = bench_start();
i = 0;
while (i < runs) {
int result = approach2(1000);
i = i + 1;
}
int time2 = bench_end(timer2);
printf("Approach 1: %s\n", bench_format_auto(time1));
printf("Approach 2: %s\n", bench_format_auto(time2));
int ratio = time1 / time2;
printf("Approach 2 is %dx faster\n", ratio);
return 0;
}
```
### Resetting Timers
Use `bench_reset()` to reset all timers:
```c
int main() {
int timer1 = bench_start();
int timer2 = bench_start();
bench_reset();
int timer3 = bench_start();
return 0;
}
```
### Performance Profiling
Create a performance profile of your application:
```c
int main() {
printf("=== Performance Profile ===\n");
int init_timer = bench_start();
initialize_data();
int init_time = bench_end(init_timer);
printf("Initialization: %s\n", bench_format_auto(init_time));
int process_timer = bench_start();
process_data();
int process_time = bench_end(process_timer);
printf("Processing: %s\n", bench_format_auto(process_time));
int save_timer = bench_start();
save_results();
int save_time = bench_end(save_timer);
printf("Saving: %s\n", bench_format_auto(save_time));
int total = init_time + process_time + save_time;
printf("Total: %s\n", bench_format_auto(total));
return 0;
}
```
### Best Practices
1. **Run multiple iterations** for more accurate measurements
2. **Warm up** before benchmarking to account for caching effects
3. **Use nested timers** to identify bottlenecks
4. **Compare relative performance** rather than absolute numbers
5. **Document benchmark conditions** (input size, hardware, etc.)
### Limitations
- Maximum 1000 concurrent timers
- Nanosecond precision depends on system clock
- Timers use CLOCK_MONOTONIC for accuracy
- Thread-safe timer management
### Complete Example
```c
int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
int compute_sum_of_squares(int limit) {
int sum = 0;
int i = 1;
while (i <= limit) {
sum = sum + (i * i);
i = i + 1;
}
return sum;
}
int main() {
printf("=== Benchmarking Demo ===\n\n");
printf("Test 1: Simple Loop\n");
int timer1 = bench_start();
int i = 0;
int sum = 0;
while (i < 1000) {
sum = sum + i;
i = i + 1;
}
int elapsed1 = bench_end(timer1);
printf("Result: %d\n", sum);
printf("Time: %s\n\n", bench_format_auto(elapsed1));
printf("Test 2: Fibonacci\n");
int timer2 = bench_start();
int fib_result = fibonacci(20);
int elapsed2 = bench_end(timer2);
printf("Result: %d\n", fib_result);
printf("Time: %s\n\n", bench_format_auto(elapsed2));
printf("Test 3: Sum of Squares\n");
int timer3 = bench_start();
int sum_result = compute_sum_of_squares(100);
int elapsed3 = bench_end(timer3);
printf("Result: %d\n", sum_result);
printf("Time: %s\n\n", bench_format_auto(elapsed3));
printf("=== Complete ===\n");
return 0;
}
```
For more benchmarking examples, see `examples/benchmark_demo.rc`.
-233
View File
@@ -1,233 +0,0 @@
int modulo(int a, int b) {
return a - (a / b) * b;
}
int fibonacci_recursive(int n) {
if (n <= 1) { return n; }
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
}
int loop_iteration(int iterations) {
int total = 0;
int i = 0;
while (i < iterations) {
total = total + i * 2;
i = i + 1;
}
return total;
}
int list_operations(int iterations) {
int sum = 0;
int i = 0;
int val = 0;
while (i < iterations) {
if (modulo(i, 3) == 0) {
val = i * 2;
sum = sum + val;
}
i = i + 1;
}
return sum;
}
int string_concatenation(int iterations) {
char *result = "";
int i = 0;
while (i < iterations) {
result = result + "x";
i = i + 1;
}
return strlen(result);
}
class BenchItem {
int id = 0;
int value = 0;
int active = 0;
}
int dict_creation(int iterations) {
int sum = 0;
int i = 0;
int obj = 0;
while (i < iterations) {
obj = new BenchItem();
obj.id = i;
obj.value = i * 2;
obj.active = modulo(i, 2);
sum = sum + obj.value;
i = i + 1;
}
return sum;
}
int sorting_algorithm(int iterations) {
int arr[1000];
int i = 0;
int j = 0;
int limit = 0;
int left = 0;
int right = 0;
if (iterations > 1000) { iterations = 1000; }
while (i < iterations) {
arr[i] = rand_range(0, 1000);
i = i + 1;
}
i = 0;
while (i < iterations - 1) {
j = 0;
limit = iterations - i - 1;
while (j < limit) {
left = arr[j];
right = arr[j + 1];
if (left > right) {
arr[j] = right;
arr[j + 1] = left;
}
j = j + 1;
}
i = i + 1;
}
return arr[0];
}
int math_operations(int iterations) {
int total = 0;
int i = 0;
int sq = 0;
int s = 0;
int c = 0;
while (i < iterations) {
sq = sqrt(i);
s = sin(i);
c = cos(i);
total = total + sq * s / 1000000 * c / 1000000;
i = i + 1;
}
return total;
}
int main() {
srand(time());
int iterations = 1000;
int fib_n = 20;
int timer = 0;
int t = 0;
int r = 0;
int total_time = 0;
int durations[7];
char *names[7];
int min_idx = 0;
int max_idx = 0;
int min_val = 0;
int max_val = 0;
int i = 0;
int d = 0;
names[0] = "Fibonacci Recursive";
names[1] = "Loop Iteration";
names[2] = "List Operations";
names[3] = "String Concatenation";
names[4] = "Dict Creation";
names[5] = "Sorting Algorithm";
names[6] = "Math Operations";
printf("\n======================================================================\n");
printf("RC PERFORMANCE BENCHMARK\n");
printf("======================================================================\n");
printf("Iterations: %d | Fibonacci N: %d\n", iterations, fib_n);
printf("======================================================================\n\n");
printf("Running: Fibonacci Recursive... ");
timer = bench_start();
r = fibonacci_recursive(fib_n);
t = bench_end(timer);
durations[0] = t;
total_time = total_time + t;
printf("%s\n", bench_format(t, 2));
printf(" Result: %d\n\n", r);
printf("Running: Loop Iteration... ");
timer = bench_start();
r = loop_iteration(iterations);
t = bench_end(timer);
durations[1] = t;
total_time = total_time + t;
printf("%s\n", bench_format(t, 2));
printf(" Result: %d\n\n", r);
printf("Running: List Operations... ");
timer = bench_start();
r = list_operations(iterations);
t = bench_end(timer);
durations[2] = t;
total_time = total_time + t;
printf("%s\n", bench_format(t, 2));
printf(" Result: %d\n\n", r);
printf("Running: String Concatenation... ");
timer = bench_start();
r = string_concatenation(iterations);
t = bench_end(timer);
durations[3] = t;
total_time = total_time + t;
printf("%s\n", bench_format(t, 2));
printf(" Result: %d\n\n", r);
printf("Running: Dict Creation... ");
timer = bench_start();
r = dict_creation(iterations);
t = bench_end(timer);
durations[4] = t;
total_time = total_time + t;
printf("%s\n", bench_format(t, 2));
printf(" Result: %d\n\n", r);
printf("Running: Sorting Algorithm... ");
timer = bench_start();
r = sorting_algorithm(iterations);
t = bench_end(timer);
durations[5] = t;
total_time = total_time + t;
printf("%s\n", bench_format(t, 2));
printf(" Result: %d\n\n", r);
printf("Running: Math Operations... ");
timer = bench_start();
r = math_operations(iterations);
t = bench_end(timer);
durations[6] = t;
total_time = total_time + t;
printf("%s\n", bench_format(t, 2));
printf(" Result: %d\n\n", r);
min_idx = 0;
max_idx = 0;
min_val = durations[0];
max_val = durations[0];
i = 1;
while (i < 7) {
d = durations[i];
if (d < min_val) {
min_val = d;
min_idx = i;
}
if (d > max_val) {
max_val = d;
max_idx = i;
}
i = i + 1;
}
printf("======================================================================\n");
printf("SUMMARY\n");
printf("======================================================================\n");
printf("Total Time: %s\n", bench_format(total_time, 2));
printf("Fastest Test: %s (%s)\n", names[min_idx], bench_format(durations[min_idx], 2));
printf("Slowest Test: %s (%s)\n", names[max_idx], bench_format(durations[max_idx], 2));
printf("======================================================================\n\n");
return 0;
}
-144
View File
@@ -1,144 +0,0 @@
int fibonacci(int n) {
if (n <= 1) {
return n;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
int compute_sum_of_squares(int limit) {
int sum = 0;
int i = 1;
while (i <= limit) {
sum = sum + (i * i);
i = i + 1;
}
return sum;
}
int main() {
printf("=================================================\n");
printf(" RC Language - Benchmarking Demo\n");
printf("=================================================\n\n");
printf("This demo shows how to use the benchmarking stdlib\n");
printf("to measure execution time of different operations.\n\n");
printf("=================================================\n");
printf("Test 1: Simple Loop (1000 iterations)\n");
printf("=================================================\n");
int timer1 = bench_start();
int i = 0;
int sum = 0;
while (i < 1000) {
sum = sum + i;
i = i + 1;
}
int elapsed1 = bench_end(timer1);
char* formatted1 = bench_format_auto(elapsed1);
printf("Result: sum = %d\n", sum);
printf("Time: %s (%d nanoseconds)\n\n", formatted1, elapsed1);
printf("=================================================\n");
printf("Test 2: Fibonacci Calculation (fib(20))\n");
printf("=================================================\n");
int timer2 = bench_start();
int fib_result = fibonacci(20);
int elapsed2 = bench_end(timer2);
char* formatted2 = bench_format_auto(elapsed2);
printf("Result: fibonacci(20) = %d\n", fib_result);
printf("Time: %s (%d nanoseconds)\n\n", formatted2, elapsed2);
printf("=================================================\n");
printf("Test 3: Sum of Squares (1 to 100)\n");
printf("=================================================\n");
int timer3 = bench_start();
int sum_result = compute_sum_of_squares(100);
int elapsed3 = bench_end(timer3);
char* formatted3 = bench_format_auto(elapsed3);
printf("Result: Sum of squares = %d\n", sum_result);
printf("Time: %s (%d nanoseconds)\n\n", formatted3, elapsed3);
printf("=================================================\n");
printf("Test 4: Nested Timers\n");
printf("=================================================\n");
int outer_timer = bench_start();
printf("Outer operation started...\n");
int inner_timer = bench_start();
int k = 0;
int product = 1;
while (k < 50) {
product = product + k;
k = k + 1;
}
int inner_elapsed = bench_end(inner_timer);
printf("Inner operation completed in: %s\n", bench_format_auto(inner_elapsed));
int m = 0;
while (m < 100) {
m = m + 1;
}
int outer_elapsed = bench_end(outer_timer);
printf("Outer operation completed in: %s\n\n", bench_format_auto(outer_elapsed));
printf("=================================================\n");
printf("Test 5: Manual Format with Different Units\n");
printf("=================================================\n");
int sample_time = 1234567890;
printf("Time: %d nanoseconds\n", sample_time);
printf(" As nanoseconds: %s\n", bench_format(sample_time, 0));
printf(" As microseconds: %s\n", bench_format(sample_time, 1));
printf(" As milliseconds: %s\n", bench_format(sample_time, 2));
printf(" As seconds: %s\n", bench_format(sample_time, 3));
printf(" As minutes: %s\n", bench_format(sample_time, 4));
printf(" As hours: %s\n", bench_format(sample_time, 5));
printf(" Auto format: %s\n\n", bench_format_auto(sample_time));
printf("=================================================\n");
printf("Test 6: Comparison of Algorithms\n");
printf("=================================================\n");
printf("Computing fibonacci(15) multiple times...\n");
int timer_a = bench_start();
int result_a = fibonacci(15);
int elapsed_a = bench_end(timer_a);
int timer_b = bench_start();
int result_b = fibonacci(15);
int elapsed_b = bench_end(timer_b);
int timer_c = bench_start();
int result_c = fibonacci(15);
int elapsed_c = bench_end(timer_c);
printf("Run 1: %s (result: %d)\n", bench_format_auto(elapsed_a), result_a);
printf("Run 2: %s (result: %d)\n", bench_format_auto(elapsed_b), result_b);
printf("Run 3: %s (result: %d)\n", bench_format_auto(elapsed_c), result_c);
int avg_time = (elapsed_a + elapsed_b + elapsed_c) / 3;
printf("Average time: %s\n\n", bench_format_auto(avg_time));
printf("=================================================\n");
printf("Benchmarking Complete!\n");
printf("=================================================\n");
return 0;
}
-1
View File
@@ -1,7 +1,6 @@
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "scope.h"
extern long memory[MEM_SIZE];
extern int sp;
+19 -31
View File
@@ -7,7 +7,6 @@
#include "parser.h"
#include "error.h"
#include "debug.h"
#include "memory.h"
void error(char *msg) {
error_with_context("ParseError", msg, NULL);
@@ -112,38 +111,29 @@ void statement() {
Token *t = &tokens[pc];
match(Id);
char var_name[64];
int name_len = t->val;
if (name_len < 0) name_len = 0;
if (name_len > 31) name_len = 31;
strncpy(var_name, t->text, name_len);
var_name[name_len] = 0;
char alloc_ctx[128];
snprintf(alloc_ctx, sizeof(alloc_ctx), "declare variable '%s'", var_name);
if (!mem_check_loc_cnt(loc_cnt + 1, alloc_ctx)) {
if (loc_cnt >= VAR_MAX) {
DEBUG_LOG("ERROR: Too many local variables: loc_cnt=%d (max=%d)", loc_cnt, VAR_MAX);
error("Too many local variables");
}
if (!mem_check_sp(sp + 1, alloc_ctx)) {
if (sp >= MEM_SIZE) {
DEBUG_LOG("ERROR: Stack overflow: sp=%d (max=%d)", sp, MEM_SIZE);
DEBUG_STACK_STATE();
error("Stack overflow");
}
int addr = sp;
Symbol *s = &locals[loc_cnt++];
if (!t->text) {
error("Invalid token text");
}
strncpy(s->name, var_name, 32);
s->name[31] = 0;
int name_len = t->val;
if (name_len < 0) name_len = 0;
if (name_len > 31) name_len = 31;
strncpy(s->name, t->text, name_len);
s->name[name_len] = 0;
s->type = var_type;
s->addr = addr;
s->is_array = 0;
if (loc_cnt > mem_stats.loc_cnt_high_water) {
mem_stats.loc_cnt_high_water = loc_cnt;
}
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '[') {
pc++;
long size_val = expression();
@@ -158,29 +148,27 @@ void statement() {
int size = (int)size_val;
s->is_array = 1;
snprintf(alloc_ctx, sizeof(alloc_ctx), "allocate array '%s[%d]'", var_name, size);
if (!mem_check_sp(sp + size, alloc_ctx)) {
if (sp + size >= MEM_SIZE) {
error("Stack overflow during array allocation");
}
if (sp + size < sp) {
error("Integer overflow in array allocation");
}
sp += size;
mem_stats.total_allocations += size;
} else {
if (sp + 1 >= MEM_SIZE) {
error("Stack overflow during variable allocation");
}
sp++;
mem_stats.total_allocations++;
}
if (sp > mem_stats.sp_high_water) {
mem_stats.sp_high_water = sp;
}
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == '=') {
pc++;
snprintf(alloc_ctx, sizeof(alloc_ctx), "initialize '%s'", var_name);
mem_write(addr, expression(), alloc_ctx);
if (addr >= 0 && addr < MEM_SIZE) {
memory[addr] = expression();
} else {
error("Memory access out of bounds");
}
}
if (pc < MAX_TOK && pc < tk_idx && tokens[pc].type == ',') pc++;
}
-5
View File
@@ -10,14 +10,10 @@
#include "preprocessor.h"
#include "oop.h"
#include "debug.h"
#include "memory.h"
#include "scope.h"
int main(int argc, char **argv) {
DEBUG_INIT();
DEBUG_LOG("RC Interpreter starting");
mem_init();
scope_init();
pthread_rwlock_init(&tokens_rwlock, NULL);
pthread_mutex_init(&str_pool_mutex, NULL);
@@ -78,7 +74,6 @@ int main(int argc, char **argv) {
statement();
free(src_code);
scope_cleanup();
pthread_rwlock_destroy(&tokens_rwlock);
pthread_mutex_destroy(&str_pool_mutex);
pthread_mutex_destroy(&memory_mutex);
-267
View File
@@ -1,267 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memory.h"
#include "types.h"
#include "error.h"
MemoryStats mem_stats = {0, 0, 0, 0, 0, 0};
extern long memory[];
extern int sp;
extern int bp;
extern Symbol locals[];
extern int loc_cnt;
extern int pc;
extern long ax;
static void mem_error(const char *msg, const char *context) {
fprintf(stderr, "\n");
fprintf(stderr, "╔════════════════════════════════════════════════════════════════╗\n");
fprintf(stderr, "║ MEMORY ERROR DETECTED ║\n");
fprintf(stderr, "╚════════════════════════════════════════════════════════════════╝\n");
fprintf(stderr, "\n Error: %s\n", msg);
fprintf(stderr, " Context: %s\n", context);
fprintf(stderr, "\n");
fprintf(stderr, "╔════════════════════════════════════════════════════════════════╗\n");
fprintf(stderr, "║ MEMORY STATE ║\n");
fprintf(stderr, "╚════════════════════════════════════════════════════════════════╝\n");
fprintf(stderr, " Stack Pointer (sp): %d\n", sp);
fprintf(stderr, " Base Pointer (bp): %d\n", bp);
fprintf(stderr, " Program Counter (pc): %d\n", pc);
fprintf(stderr, " Local Count (loc_cnt): %d\n", loc_cnt);
fprintf(stderr, " Accumulator (ax): %ld\n", ax);
fprintf(stderr, "\n");
fprintf(stderr, "╔════════════════════════════════════════════════════════════════╗\n");
fprintf(stderr, "║ MEMORY LIMITS ║\n");
fprintf(stderr, "╚════════════════════════════════════════════════════════════════╝\n");
fprintf(stderr, " MEM_SIZE: %d\n", MEM_SIZE);
fprintf(stderr, " VAR_MAX: %d\n", VAR_MAX);
fprintf(stderr, " MAX_TOK: %d\n", MAX_TOK);
fprintf(stderr, "\n");
fprintf(stderr, "╔════════════════════════════════════════════════════════════════╗\n");
fprintf(stderr, "║ MEMORY STATISTICS ║\n");
fprintf(stderr, "╚════════════════════════════════════════════════════════════════╝\n");
fprintf(stderr, " SP High Water Mark: %d\n", mem_stats.sp_high_water);
fprintf(stderr, " LOC_CNT High Water: %d\n", mem_stats.loc_cnt_high_water);
fprintf(stderr, " Current Call Depth: %d\n", mem_stats.call_depth);
fprintf(stderr, " Max Call Depth: %d\n", mem_stats.max_call_depth);
fprintf(stderr, " Total Allocations: %d\n", mem_stats.total_allocations);
fprintf(stderr, " Total Deallocations: %d\n", mem_stats.total_deallocations);
fprintf(stderr, "\n");
if (loc_cnt > 0 && loc_cnt <= VAR_MAX) {
fprintf(stderr, "╔════════════════════════════════════════════════════════════════╗\n");
fprintf(stderr, "║ LOCAL VARIABLES ║\n");
fprintf(stderr, "╚════════════════════════════════════════════════════════════════╝\n");
int show_count = loc_cnt < 20 ? loc_cnt : 20;
for (int i = 0; i < show_count; i++) {
fprintf(stderr, " [%3d] %-20s addr=%5d is_array=%d",
i, locals[i].name, locals[i].addr, locals[i].is_array);
if (locals[i].addr >= 0 && locals[i].addr < MEM_SIZE) {
fprintf(stderr, " value=%ld", memory[locals[i].addr]);
}
fprintf(stderr, "\n");
}
if (loc_cnt > 20) {
fprintf(stderr, " ... and %d more variables\n", loc_cnt - 20);
}
fprintf(stderr, "\n");
}
if (sp > 0 && sp <= MEM_SIZE) {
fprintf(stderr, "╔════════════════════════════════════════════════════════════════╗\n");
fprintf(stderr, "║ STACK CONTENTS ║\n");
fprintf(stderr, "╚════════════════════════════════════════════════════════════════╝\n");
int start = sp > 20 ? sp - 20 : 0;
for (int i = start; i < sp && i < MEM_SIZE; i++) {
fprintf(stderr, " memory[%5d] = %ld", i, memory[i]);
if (i == bp) fprintf(stderr, " <-- bp");
if (i == sp - 1) fprintf(stderr, " <-- sp-1 (top)");
fprintf(stderr, "\n");
}
fprintf(stderr, "\n");
}
exit(1);
}
void mem_init(void) {
mem_stats.sp_high_water = 0;
mem_stats.loc_cnt_high_water = 0;
mem_stats.call_depth = 0;
mem_stats.max_call_depth = 0;
mem_stats.total_allocations = 0;
mem_stats.total_deallocations = 0;
}
void mem_dump_stats(void) {
fprintf(stderr, "\n=== Memory Statistics ===\n");
fprintf(stderr, "SP High Water: %d / %d (%.1f%%)\n",
mem_stats.sp_high_water, MEM_SIZE,
100.0 * mem_stats.sp_high_water / MEM_SIZE);
fprintf(stderr, "LOC_CNT High: %d / %d (%.1f%%)\n",
mem_stats.loc_cnt_high_water, VAR_MAX,
100.0 * mem_stats.loc_cnt_high_water / VAR_MAX);
fprintf(stderr, "Max Call Depth: %d\n", mem_stats.max_call_depth);
fprintf(stderr, "Allocations: %d\n", mem_stats.total_allocations);
fprintf(stderr, "Deallocations: %d\n", mem_stats.total_deallocations);
fprintf(stderr, "=========================\n");
}
int mem_check_sp(int required_sp, const char *context) {
if (required_sp < 0) {
char msg[256];
snprintf(msg, sizeof(msg), "Stack underflow: required sp=%d", required_sp);
mem_error(msg, context);
return 0;
}
if (required_sp >= MEM_SIZE) {
char msg[256];
snprintf(msg, sizeof(msg), "Stack overflow: required sp=%d >= MEM_SIZE=%d",
required_sp, MEM_SIZE);
mem_error(msg, context);
return 0;
}
return 1;
}
int mem_check_addr(int addr, const char *context) {
if (addr < 0) {
char msg[256];
snprintf(msg, sizeof(msg), "Negative memory address: addr=%d", addr);
mem_error(msg, context);
return 0;
}
if (addr >= MEM_SIZE) {
char msg[256];
snprintf(msg, sizeof(msg), "Memory address out of bounds: addr=%d >= MEM_SIZE=%d",
addr, MEM_SIZE);
mem_error(msg, context);
return 0;
}
return 1;
}
int mem_check_loc_cnt(int required_cnt, const char *context) {
if (required_cnt < 0) {
char msg[256];
snprintf(msg, sizeof(msg), "Negative local count: loc_cnt=%d", required_cnt);
mem_error(msg, context);
return 0;
}
if (required_cnt >= VAR_MAX) {
char msg[256];
snprintf(msg, sizeof(msg), "Too many local variables: loc_cnt=%d >= VAR_MAX=%d",
required_cnt, VAR_MAX);
mem_error(msg, context);
return 0;
}
return 1;
}
long mem_read(int addr, const char *context) {
if (!mem_check_addr(addr, context)) {
return 0;
}
return memory[addr];
}
void mem_write(int addr, long value, const char *context) {
if (!mem_check_addr(addr, context)) {
return;
}
memory[addr] = value;
}
int mem_push(long value, const char *context) {
if (!mem_check_sp(sp + 1, context)) {
return 0;
}
memory[sp++] = value;
mem_stats.total_allocations++;
if (sp > mem_stats.sp_high_water) {
mem_stats.sp_high_water = sp;
}
return 1;
}
long mem_pop(const char *context) {
if (sp <= 0) {
mem_error("Stack underflow on pop", context);
return 0;
}
mem_stats.total_deallocations++;
return memory[--sp];
}
void mem_alloc_var(int size, const char *var_name) {
char context[256];
snprintf(context, sizeof(context), "Allocating variable '%s' (size=%d)", var_name, size);
if (!mem_check_sp(sp + size, context)) {
return;
}
if (!mem_check_loc_cnt(loc_cnt + 1, context)) {
return;
}
sp += size;
mem_stats.total_allocations += size;
if (sp > mem_stats.sp_high_water) {
mem_stats.sp_high_water = sp;
}
if (loc_cnt > mem_stats.loc_cnt_high_water) {
mem_stats.loc_cnt_high_water = loc_cnt;
}
}
void mem_free_frame(int old_sp, int old_loc_cnt, const char *context) {
if (old_sp < 0 || old_sp > sp) {
char msg[256];
snprintf(msg, sizeof(msg), "Invalid frame restoration: old_sp=%d, current sp=%d",
old_sp, sp);
mem_error(msg, context);
return;
}
if (old_loc_cnt < 0 || old_loc_cnt > loc_cnt) {
char msg[256];
snprintf(msg, sizeof(msg), "Invalid loc_cnt restoration: old_loc_cnt=%d, current loc_cnt=%d",
old_loc_cnt, loc_cnt);
mem_error(msg, context);
return;
}
mem_stats.total_deallocations += (sp - old_sp);
sp = old_sp;
loc_cnt = old_loc_cnt;
}
void mem_enter_call(const char *func_name) {
mem_stats.call_depth++;
if (mem_stats.call_depth > mem_stats.max_call_depth) {
mem_stats.max_call_depth = mem_stats.call_depth;
}
if (mem_stats.call_depth > MAX_CALL_STACK) {
char msg[256];
snprintf(msg, sizeof(msg), "Call stack overflow entering '%s'", func_name);
mem_error(msg, "mem_enter_call");
}
}
void mem_exit_call(const char *func_name) {
if (mem_stats.call_depth <= 0) {
char msg[256];
snprintf(msg, sizeof(msg), "Call stack underflow exiting '%s'", func_name);
mem_error(msg, "mem_exit_call");
return;
}
mem_stats.call_depth--;
}
void mem_trace_state(const char *label) {
fprintf(stderr, "[TRACE:%s] sp=%d bp=%d loc_cnt=%d call_depth=%d\n",
label, sp, bp, loc_cnt, mem_stats.call_depth);
}
-38
View File
@@ -1,38 +0,0 @@
#ifndef MEMORY_H
#define MEMORY_H
#include "types.h"
typedef struct {
int sp_high_water;
int loc_cnt_high_water;
int call_depth;
int max_call_depth;
int total_allocations;
int total_deallocations;
} MemoryStats;
extern MemoryStats mem_stats;
void mem_init(void);
void mem_dump_stats(void);
int mem_check_sp(int required_sp, const char *context);
int mem_check_addr(int addr, const char *context);
int mem_check_loc_cnt(int required_cnt, const char *context);
long mem_read(int addr, const char *context);
void mem_write(int addr, long value, const char *context);
int mem_push(long value, const char *context);
long mem_pop(const char *context);
void mem_alloc_var(int size, const char *var_name);
void mem_free_frame(int old_sp, int old_loc_cnt, const char *context);
void mem_enter_call(const char *func_name);
void mem_exit_call(const char *func_name);
void mem_trace_state(const char *label);
#endif
+17 -9
View File
@@ -3,7 +3,6 @@
#include <string.h>
#include "types.h"
#include "interpreter.h"
#include "scope.h"
int find_class(char *name, int len) {
if (!name || len <= 0 || len > 31) return -1;
@@ -114,15 +113,23 @@ void call_destructor(long obj_ptr) {
int func_idx = cls->methods[i].func_idx;
if (func_idx >= 0 && func_idx < func_cnt) {
int saved_pc = pc;
int saved_sp = sp;
int saved_bp = bp;
int saved_loc_cnt = loc_cnt;
long saved_ax = ax;
int saved_return_flag = return_flag;
scope_push();
if (sp >= MEM_SIZE || bp < 0 || bp >= MEM_SIZE) return;
int param_base = sp;
if (sp < MEM_SIZE) {
memory[sp++] = obj_ptr;
}
memory[sp] = bp;
bp = sp++;
if (sp >= MEM_SIZE) return;
memory[sp++] = 0;
memory[sp++] = saved_loc_cnt;
if (sp >= MEM_SIZE) return;
memory[sp++] = obj_ptr;
int scan_pc = funcs[func_idx].params_start;
if (scan_pc < MAX_TOK && scan_pc < tk_idx && tokens[scan_pc].type != ')') {
@@ -135,7 +142,7 @@ void call_destructor(long obj_ptr) {
strncpy(sym->name, param_name->text, name_len);
sym->name[name_len] = 0;
sym->type = Int;
sym->addr = param_base;
sym->addr = sp - 1;
sym->is_array = 0;
}
}
@@ -147,9 +154,10 @@ void call_destructor(long obj_ptr) {
statement();
scope_pop();
pc = saved_pc;
sp = saved_sp;
bp = saved_bp;
loc_cnt = saved_loc_cnt;
ax = saved_ax;
return_flag = saved_return_flag;
}
+44 -38
View File
@@ -7,8 +7,6 @@
#include "string_utils.h"
#include "error.h"
#include "debug.h"
#include "memory.h"
#include "scope.h"
extern Token tokens[];
extern int pc;
@@ -178,20 +176,20 @@ long factor() {
}
int ret_pc = pc;
int saved_return_flag = return_flag;
int old_loc_cnt = loc_cnt;
int old_bp = bp;
mem_enter_call(funcs[f_idx].name);
scope_push();
char call_ctx[128];
snprintf(call_ctx, sizeof(call_ctx), "call %s: push frame", funcs[f_idx].name);
if (sp >= MEM_SIZE) return 0;
if (bp < 0 || bp >= MEM_SIZE) return 0;
memory[sp] = bp; bp = sp++;
if (sp >= MEM_SIZE) return 0;
memory[sp++] = ret_pc;
memory[sp++] = old_loc_cnt;
int param_base = sp;
for(int i=0; i<argc; i++) {
if (sp < MEM_SIZE) {
memory[sp++] = args[i];
}
if (sp >= MEM_SIZE) break;
memory[sp++] = args[i];
}
int scan_pc = funcs[f_idx].params_start;
@@ -200,19 +198,17 @@ long factor() {
if (tokens[scan_pc].type == Int || tokens[scan_pc].type == Char || tokens[scan_pc].type == Double) {
scan_pc++;
while (scan_pc < MAX_TOK && tokens[scan_pc].type == '*') scan_pc++;
if (scan_pc < MAX_TOK && tokens[scan_pc].type == Id && param_idx < argc) {
if (loc_cnt < VAR_MAX) {
Token *param_name = &tokens[scan_pc];
Symbol *sym = &locals[loc_cnt++];
int name_len = param_name->val;
if (name_len > 31) name_len = 31;
strncpy(sym->name, param_name->text, name_len);
sym->name[name_len] = 0;
sym->type = Int;
sym->addr = param_base + param_idx;
sym->is_array = 0;
param_idx++;
}
if (scan_pc < MAX_TOK && tokens[scan_pc].type == Id && param_idx < argc && loc_cnt < VAR_MAX) {
Token *param_name = &tokens[scan_pc];
Symbol *sym = &locals[loc_cnt++];
int name_len = param_name->val;
if (name_len > 31) name_len = 31;
strncpy(sym->name, param_name->text, name_len);
sym->name[name_len] = 0;
sym->type = Int;
sym->addr = param_base + param_idx;
sym->is_array = 0;
param_idx++;
}
}
scan_pc++;
@@ -235,12 +231,14 @@ long factor() {
return_flag = 0;
pop_call_frame();
mem_exit_call(funcs[f_idx].name);
scope_pop();
loc_cnt = old_loc_cnt;
if (bp < 0 || bp >= MEM_SIZE) return 0;
sp = bp;
if (sp < 0 || sp >= MEM_SIZE) return 0;
bp = memory[sp];
if (sp + 1 < MEM_SIZE) ret_pc = memory[sp + 1];
pc = ret_pc;
return_flag = saved_return_flag;
return val;
}
else {
@@ -429,15 +427,22 @@ long unary() {
match(')');
int saved_pc = pc;
int saved_return_flag = return_flag;
int saved_sp = sp;
int saved_bp = bp;
int saved_loc_cnt = loc_cnt;
scope_push();
if (sp >= MEM_SIZE || bp < 0 || bp >= MEM_SIZE) return 0;
memory[sp] = bp;
bp = sp++;
if (sp >= MEM_SIZE) return 0;
memory[sp++] = 0;
memory[sp++] = saved_loc_cnt;
int param_base = sp;
for (int i = 0; i < argc && i < 10; i++) {
if (sp < MEM_SIZE) {
memory[sp++] = args[i];
}
if (sp >= MEM_SIZE) break;
memory[sp++] = args[i];
}
int scan_pc = funcs[func_idx].params_start;
@@ -455,7 +460,7 @@ long unary() {
strncpy(sym->name, param_name->text, name_len);
sym->name[name_len] = 0;
sym->type = Int;
sym->addr = param_base + param_idx;
sym->addr = saved_sp + 3 + param_idx;
sym->is_array = 0;
param_idx++;
}
@@ -471,9 +476,10 @@ long unary() {
ax = 0;
return_flag = 0;
scope_pop();
pc = saved_pc;
return_flag = saved_return_flag;
sp = saved_sp;
bp = saved_bp;
loc_cnt = saved_loc_cnt;
} else {
extern int find_class_field(int class_idx, char *name, int len);
int field_idx = find_class_field(class_idx, member->text, member->val);
-363
View File
@@ -1,363 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "scope.h"
#include "types.h"
#include "interpreter.h"
Scope *current_scope = NULL;
Scope *root_scope = NULL;
Scope* scope_create(Scope *parent) {
Scope *scope = (Scope*)calloc(1, sizeof(Scope));
if (!scope) return NULL;
scope->parent = parent;
scope->mem_size = SCOPE_MEM_SIZE;
scope->loc_capacity = SCOPE_VAR_MAX;
scope->memory = (long*)calloc(SCOPE_MEM_SIZE, sizeof(long));
if (!scope->memory) {
free(scope);
return NULL;
}
scope->locals = (Symbol*)calloc(SCOPE_VAR_MAX, sizeof(Symbol));
if (!scope->locals) {
free(scope->memory);
free(scope);
return NULL;
}
scope->sp = 0;
scope->bp = 0;
scope->loc_cnt = 0;
scope->depth = parent ? parent->depth + 1 : 0;
return scope;
}
void scope_destroy(Scope *scope) {
if (!scope) return;
if (scope->memory) free(scope->memory);
if (scope->locals) free(scope->locals);
free(scope);
}
Scope* scope_push(void) {
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
if (current_scope) {
int copy_sp = sp < current_scope->mem_size ? sp : current_scope->mem_size;
for (int i = 0; i < copy_sp; i++) {
current_scope->memory[i] = memory[i];
}
int copy_loc = loc_cnt < current_scope->loc_capacity ? loc_cnt : current_scope->loc_capacity;
for (int i = 0; i < copy_loc; i++) {
current_scope->locals[i] = locals[i];
}
current_scope->sp = sp;
current_scope->bp = bp;
current_scope->loc_cnt = loc_cnt;
}
Scope *new_scope = scope_create(current_scope);
if (!new_scope) {
error("Failed to create new scope");
return NULL;
}
current_scope = new_scope;
sp = 0;
bp = 0;
loc_cnt = 0;
return new_scope;
}
Scope* scope_pop(void) {
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
if (!current_scope || !current_scope->parent) {
return current_scope;
}
Scope *old = current_scope;
current_scope = current_scope->parent;
scope_destroy(old);
if (current_scope) {
int copy_sp = current_scope->sp < MEM_SIZE ? current_scope->sp : MEM_SIZE;
for (int i = 0; i < copy_sp; i++) {
memory[i] = current_scope->memory[i];
}
int copy_loc = current_scope->loc_cnt < VAR_MAX ? current_scope->loc_cnt : VAR_MAX;
for (int i = 0; i < copy_loc; i++) {
locals[i] = current_scope->locals[i];
}
sp = current_scope->sp;
bp = current_scope->bp;
loc_cnt = current_scope->loc_cnt;
}
return current_scope;
}
int scope_find_local_current_only(const char *name, int len) {
if (!current_scope || !name || len <= 0 || len >= 32) return -1;
Scope *scope = current_scope;
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
return i;
}
}
return -1;
}
static int scope_find_local_in_scope(Scope *scope, const char *name, int len) {
if (!scope || !name || len <= 0 || len >= 32) return -1;
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
return i;
}
}
return -1;
}
int scope_find_local(const char *name, int len) {
if (!name || len <= 0 || len >= 32) return -1;
Scope *scope = current_scope;
while (scope) {
int idx = scope_find_local_in_scope(scope, name, len);
if (idx >= 0) {
return idx;
}
scope = scope->parent;
}
return -1;
}
Symbol* scope_get_local(int idx) {
if (!current_scope || idx < 0) return NULL;
Scope *scope = current_scope;
while (scope) {
if (idx < scope->loc_cnt) {
return &scope->locals[idx];
}
scope = scope->parent;
}
return NULL;
}
Symbol* scope_add_local(const char *name, int len, int type, int addr, int is_array) {
if (!current_scope) return NULL;
if (current_scope->loc_cnt >= current_scope->loc_capacity) {
error("Too many local variables in scope");
return NULL;
}
Symbol *sym = &current_scope->locals[current_scope->loc_cnt++];
int name_len = len > 31 ? 31 : len;
strncpy(sym->name, name, name_len);
sym->name[name_len] = 0;
sym->type = type;
sym->addr = addr;
sym->is_array = is_array;
return sym;
}
long scope_mem_read(int addr) {
if (!current_scope) return 0;
if (addr < 0) return 0;
Scope *scope = current_scope;
while (scope) {
if (addr < scope->mem_size && addr < scope->sp) {
return scope->memory[addr];
}
if (addr < scope->mem_size) {
return scope->memory[addr];
}
scope = scope->parent;
}
if (addr < current_scope->mem_size) {
return current_scope->memory[addr];
}
return 0;
}
void scope_mem_write(int addr, long value) {
if (!current_scope) return;
if (addr < 0 || addr >= current_scope->mem_size) return;
current_scope->memory[addr] = value;
}
int scope_mem_alloc(int size) {
if (!current_scope || size <= 0) return -1;
if (current_scope->sp + size > current_scope->mem_size) {
error("Scope stack overflow");
return -1;
}
int addr = current_scope->sp;
current_scope->sp += size;
return addr;
}
int scope_check_sp(int required) {
if (!current_scope) return 0;
return required >= 0 && required < current_scope->mem_size;
}
int scope_check_addr(int addr) {
if (!current_scope) return 0;
return addr >= 0 && addr < current_scope->mem_size;
}
void scope_init(void) {
extern int sp, bp, loc_cnt;
if (root_scope) {
scope_cleanup();
}
root_scope = scope_create(NULL);
current_scope = root_scope;
sp = 0;
bp = 0;
loc_cnt = 0;
}
void scope_cleanup(void) {
while (current_scope && current_scope != root_scope) {
scope_pop();
}
if (root_scope) {
scope_destroy(root_scope);
root_scope = NULL;
current_scope = NULL;
}
}
void scope_save_state(int *out_sp, int *out_bp, int *out_loc_cnt) {
if (!current_scope) {
*out_sp = 0;
*out_bp = 0;
*out_loc_cnt = 0;
return;
}
*out_sp = current_scope->sp;
*out_bp = current_scope->bp;
*out_loc_cnt = current_scope->loc_cnt;
}
void scope_restore_state(int saved_sp, int saved_bp, int saved_loc_cnt) {
if (!current_scope) return;
current_scope->sp = saved_sp;
current_scope->bp = saved_bp;
current_scope->loc_cnt = saved_loc_cnt;
}
void scope_sync_to_globals(void) {
if (!current_scope) return;
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
int copy_sp = current_scope->sp < MEM_SIZE ? current_scope->sp : MEM_SIZE;
for (int i = 0; i < copy_sp; i++) {
memory[i] = current_scope->memory[i];
}
int copy_loc = current_scope->loc_cnt < VAR_MAX ? current_scope->loc_cnt : VAR_MAX;
for (int i = 0; i < copy_loc; i++) {
locals[i] = current_scope->locals[i];
}
sp = current_scope->sp;
bp = current_scope->bp;
loc_cnt = current_scope->loc_cnt;
}
void scope_sync_from_globals(void) {
if (!current_scope) return;
extern long memory[];
extern Symbol locals[];
extern int sp, bp, loc_cnt;
int copy_sp = sp < current_scope->mem_size ? sp : current_scope->mem_size;
for (int i = 0; i < copy_sp; i++) {
current_scope->memory[i] = memory[i];
}
int copy_loc = loc_cnt < current_scope->loc_capacity ? loc_cnt : current_scope->loc_capacity;
for (int i = 0; i < copy_loc; i++) {
current_scope->locals[i] = locals[i];
}
current_scope->sp = sp;
current_scope->bp = bp;
current_scope->loc_cnt = loc_cnt;
}
Symbol* scope_find_local_symbol(const char *name, int len) {
if (!name || len <= 0 || len >= 32) return NULL;
Scope *scope = current_scope;
while (scope) {
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
return &scope->locals[i];
}
}
scope = scope->parent;
}
return NULL;
}
int scope_find_local_with_scope(const char *name, int len, Scope **out_scope) {
if (!name || len <= 0 || len >= 32) return -1;
Scope *scope = current_scope;
while (scope) {
for (int i = scope->loc_cnt - 1; i >= 0; i--) {
if (!strncmp(scope->locals[i].name, name, len) && scope->locals[i].name[len] == 0) {
if (out_scope) *out_scope = scope;
return i;
}
}
scope = scope->parent;
}
return -1;
}
long scope_read_var(const char *name, int len) {
Scope *scope = NULL;
int idx = scope_find_local_with_scope(name, len, &scope);
if (idx < 0 || !scope) return 0;
Symbol *sym = &scope->locals[idx];
if (sym->addr < 0 || sym->addr >= scope->mem_size) return 0;
return scope->memory[sym->addr];
}
void scope_write_var(const char *name, int len, long value) {
Scope *scope = NULL;
int idx = scope_find_local_with_scope(name, len, &scope);
if (idx < 0 || !scope) return;
Symbol *sym = &scope->locals[idx];
if (sym->addr < 0 || sym->addr >= scope->mem_size) return;
scope->memory[sym->addr] = value;
}
-54
View File
@@ -1,54 +0,0 @@
#ifndef SCOPE_H
#define SCOPE_H
#include "types.h"
#define SCOPE_MEM_SIZE 10000
#define SCOPE_VAR_MAX 500
typedef struct Scope {
struct Scope *parent;
long *memory;
int mem_size;
Symbol *locals;
int loc_capacity;
int sp;
int bp;
int loc_cnt;
int depth;
} Scope;
extern Scope *current_scope;
extern Scope *root_scope;
Scope* scope_create(Scope *parent);
void scope_destroy(Scope *scope);
Scope* scope_push(void);
Scope* scope_pop(void);
int scope_find_local(const char *name, int len);
int scope_find_local_current_only(const char *name, int len);
Symbol* scope_get_local(int idx);
Symbol* scope_add_local(const char *name, int len, int type, int addr, int is_array);
long scope_mem_read(int addr);
void scope_mem_write(int addr, long value);
int scope_mem_alloc(int size);
int scope_check_sp(int required);
int scope_check_addr(int addr);
void scope_init(void);
void scope_cleanup(void);
void scope_save_state(int *out_sp, int *out_bp, int *out_loc_cnt);
void scope_restore_state(int saved_sp, int saved_bp, int saved_loc_cnt);
void scope_sync_to_globals(void);
void scope_sync_from_globals(void);
Symbol* scope_find_local_symbol(const char *name, int len);
int scope_find_local_with_scope(const char *name, int len, Scope **out_scope);
long scope_read_var(const char *name, int len);
void scope_write_var(const char *name, int len, long value);
#endif
+206
View File
@@ -0,0 +1,206 @@
# RC Standard Library
The RC language standard library is organized into modular categories for easy maintenance and extensibility.
## Structure
```
src/stdlib/
├── stdlib.h # Main registration header
├── stdlib.c # Registers all stdlib modules
├── string/ # String manipulation functions
│ ├── string_stdlib.h
│ └── string_stdlib.c
├── math/ # Mathematical functions
│ ├── math_stdlib.h
│ └── math_stdlib.c
├── io/ # Input/Output operations
│ ├── file_stdlib.h
│ ├── file_stdlib.c # File I/O functions
│ ├── socket_stdlib.h
│ └── socket_stdlib.c # Network socket functions
├── async/ # Asynchronous operations
│ ├── async_stdlib.h
│ └── async_stdlib.c # Async I/O and coroutines
└── constants/ # System constants
├── constants_stdlib.h
└── constants_stdlib.c
```
## Available Functions
### String Functions (string/)
- `strlen(str)` - Get string length
- `strpos(haystack, needle)` - Find substring position
- `substr(str, start, length)` - Extract substring
- `upper(str)` - Convert to uppercase
- `lower(str)` - Convert to lowercase
- `strip(str)` - Trim whitespace
- `replace(str, old, new)` - Replace substring
- `startswith(str, prefix)` - Check if starts with prefix
- `endswith(str, suffix)` - Check if ends with suffix
### Math Functions (math/)
- `sqrt(x)` - Square root
- `pow(base, exp)` - Power function
- `sin(x)`, `cos(x)`, `tan(x)` - Trigonometric functions
- `abs(x)` - Absolute value
- `floor(x)`, `ceil(x)` - Rounding functions
- `int_to_double(x)` - Convert int to double
- `double_to_int(x)` - Convert double to int
- `double_add(a, b)`, `double_sub(a, b)`, `double_mul(a, b)`, `double_div(a, b)` - Double arithmetic
### File I/O Functions (io/file_stdlib.c)
- `fopen(filename, mode)` - Open file
- `fclose(file)` - Close file
- `fread(file, addr, size)` - Read from file
- `fwrite(file, buf, size)` - Write to file
- `fgets(file, max_size)` - Read line from file
- `fputs(file, str)` - Write string to file
- `feof(file)` - Check end of file
- `ftell(file)` - Get file position
- `fseek(file, offset, whence)` - Seek in file
- `fremove(filename)` - Delete file
- `frename(oldname, newname)` - Rename file
### Socket Functions (io/socket_stdlib.c)
- `socket(domain, type, protocol)` - Create socket
- `bind(sockfd, port)` - Bind socket to port
- `listen(sockfd, backlog)` - Listen for connections
- `accept(sockfd)` - Accept connection
- `recv(sockfd, addr, len, flags)` - Receive data
- `send(sockfd, buf, len, flags)` - Send data
- `close(fd)` - Close file descriptor
### Async Functions (async/)
- `async_fread(file, addr, size)` - Async file read
- `async_fwrite(file, buf, size)` - Async file write
- `async_recv(sockfd, addr, len, flags)` - Async socket receive
- `async_send(sockfd, buf, len, flags)` - Async socket send
- `async_wait(id)` - Wait for async operation
- `async_poll(id)` - Poll async operation status
- `async_result(id)` - Get async operation result
- `await(coroutine_id)` - Await coroutine completion
- `gather(coro1, coro2, ...)` - Wait for multiple coroutines
### Constants (constants/)
- `AF_INET()` - IPv4 address family
- `SOCK_STREAM()` - TCP socket type
- `SEEK_SET()` - Seek from beginning
- `SEEK_CUR()` - Seek from current position
- `SEEK_END()` - Seek from end
## Adding New Functions
### 1. Add to Existing Category
To add a new function to an existing category (e.g., a new math function):
1. Open the appropriate category file: `src/stdlib/math/math_stdlib.c`
2. Add your function implementation:
```c
long native_my_function(long *args, int argc) {
if (!args || argc < 1) {
return 0;
}
// Your implementation here
return result;
}
```
3. Register it in the category's registration function:
```c
void register_math_stdlib() {
// ... existing registrations ...
register_native_func("my_function", native_my_function);
}
```
4. Rebuild: `make clean && make`
### 2. Add New Category
To add a new category (e.g., `datetime`):
1. Create directory: `mkdir -p src/stdlib/datetime`
2. Create header file: `src/stdlib/datetime/datetime_stdlib.h`
```c
#ifndef DATETIME_STDLIB_H
#define DATETIME_STDLIB_H
void register_datetime_stdlib();
#endif
```
3. Create implementation: `src/stdlib/datetime/datetime_stdlib.c`
```c
#include <time.h>
#include "../../types.h"
#include "datetime_stdlib.h"
extern void register_native_func(char *name, NativeFunc func);
long native_time(long *args, int argc) {
return (long)time(NULL);
}
void register_datetime_stdlib() {
register_native_func("time", native_time);
}
```
4. Add to `src/stdlib/stdlib.c`:
```c
#include "datetime/datetime_stdlib.h"
void register_stdlib() {
// ... existing registrations ...
register_datetime_stdlib();
}
```
5. Add to Makefile SOURCES:
```makefile
SOURCES = ... \
$(SRC_DIR)/stdlib/datetime/datetime_stdlib.c
```
6. Create build directory in Makefile dirs target:
```makefile
dirs:
# ... existing directories ...
@mkdir -p $(BUILD_DIR)/stdlib/datetime
```
7. Rebuild: `make clean && make`
## Function Signature
All native functions must follow this signature:
```c
long native_function_name(long *args, int argc)
```
Where:
- `args` - Array of long arguments passed from RC code
- `argc` - Number of arguments
- Returns a `long` value
## Best Practices
1. Always validate arguments (check argc and args pointer)
2. Use appropriate error handling
3. Document your functions with comments
4. Test your functions thoroughly
5. Keep functions focused and single-purpose
6. Use the string pool for string allocations (str_pool)
7. Check bounds when accessing memory array
8. Follow the existing code style
## Testing
After making changes:
1. Build: `make clean && make`
2. Run all tests: `make test`
3. Run specific category tests (e.g., `make run-math-test`)
## Architecture Notes
- All stdlib modules are automatically registered when `register_stdlib()` is called from `src/native_functions.c`
- The registration happens during interpreter initialization in `src/main.c`
- Native functions are stored in the global `native_funcs` array
- Function lookup is performed by name during parsing
+17 -6
View File
@@ -5,7 +5,6 @@
#include <sys/socket.h>
#include "../../types.h"
#include "../../interpreter.h"
#include "../../scope.h"
#include "async_stdlib.h"
#include "../../debug.h"
@@ -565,11 +564,23 @@ static long execute_function_sync(int func_idx, long *args, int argc) {
return 0;
}
int saved_sp = sp;
int saved_bp = bp;
int saved_pc = pc;
int saved_loc_cnt = loc_cnt;
long saved_ax = ax;
int saved_return_flag = return_flag;
scope_push();
if (sp >= MEM_SIZE) return 0;
memory[sp] = bp;
bp = sp++;
if (sp >= MEM_SIZE - 1) {
sp = saved_sp;
bp = saved_bp;
return 0;
}
memory[sp++] = 0;
memory[sp++] = 0;
int param_base = sp;
for (int i = 0; i < argc && i < 10 && sp < MEM_SIZE; i++) {
@@ -610,11 +621,11 @@ static long execute_function_sync(int func_idx, long *args, int argc) {
long result = ax;
scope_pop();
sp = saved_sp;
bp = saved_bp;
pc = saved_pc;
loc_cnt = saved_loc_cnt;
ax = saved_ax;
return_flag = saved_return_flag;
return result;
}
-192
View File
@@ -1,192 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include "../../types.h"
#include "benchmark_stdlib.h"
extern void register_native_func(char *name, NativeFunc func);
extern pthread_mutex_t str_pool_mutex;
extern char str_pool[STR_POOL_SIZE];
extern int str_pool_idx;
#define MAX_TIMERS 1000
typedef struct {
struct timespec start_time;
int active;
} BenchTimer;
static BenchTimer timers[MAX_TIMERS];
static pthread_mutex_t timers_mutex = PTHREAD_MUTEX_INITIALIZER;
static int next_timer_id = 0;
long native_bench_start(long *args, int argc) {
pthread_mutex_lock(&timers_mutex);
int timer_id = -1;
for (int i = 0; i < MAX_TIMERS; i++) {
if (!timers[i].active) {
timer_id = i;
break;
}
}
if (timer_id == -1) {
if (next_timer_id < MAX_TIMERS) {
timer_id = next_timer_id++;
} else {
pthread_mutex_unlock(&timers_mutex);
return -1;
}
}
timers[timer_id].active = 1;
clock_gettime(CLOCK_MONOTONIC, &timers[timer_id].start_time);
pthread_mutex_unlock(&timers_mutex);
return timer_id;
}
long native_bench_end(long *args, int argc) {
if (!args || argc < 1) {
return -1;
}
int timer_id = (int)args[0];
if (timer_id < 0 || timer_id >= MAX_TIMERS) {
return -1;
}
struct timespec end_time;
clock_gettime(CLOCK_MONOTONIC, &end_time);
pthread_mutex_lock(&timers_mutex);
if (!timers[timer_id].active) {
pthread_mutex_unlock(&timers_mutex);
return -1;
}
long elapsed_ns = (end_time.tv_sec - timers[timer_id].start_time.tv_sec) * 1000000000L +
(end_time.tv_nsec - timers[timer_id].start_time.tv_nsec);
timers[timer_id].active = 0;
pthread_mutex_unlock(&timers_mutex);
return elapsed_ns;
}
long native_bench_format(long *args, int argc) {
static char empty_str[] = "";
if (!args || argc < 2) {
return (long)empty_str;
}
long nanoseconds = args[0];
int unit = (int)args[1];
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE - 256) {
pthread_mutex_unlock(&str_pool_mutex);
return (long)empty_str;
}
char *result = &str_pool[str_pool_idx];
int len = 0;
switch (unit) {
case 0:
len = snprintf(result, 256, "%ld ns", nanoseconds);
break;
case 1: {
double microseconds = nanoseconds / 1000.0;
len = snprintf(result, 256, "%.3f us", microseconds);
break;
}
case 2: {
double milliseconds = nanoseconds / 1000000.0;
len = snprintf(result, 256, "%.3f ms", milliseconds);
break;
}
case 3: {
double seconds = nanoseconds / 1000000000.0;
len = snprintf(result, 256, "%.6f s", seconds);
break;
}
case 4: {
double minutes = nanoseconds / 60000000000.0;
len = snprintf(result, 256, "%.6f min", minutes);
break;
}
case 5: {
double hours = nanoseconds / 3600000000000.0;
len = snprintf(result, 256, "%.6f h", hours);
break;
}
default:
len = snprintf(result, 256, "%ld ns", nanoseconds);
break;
}
if (len > 0 && len < 256) {
str_pool_idx += len + 1;
}
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
long native_bench_format_auto(long *args, int argc) {
if (!args || argc < 1) {
static char empty_str[] = "";
return (long)empty_str;
}
long nanoseconds = args[0];
int unit = 0;
if (nanoseconds >= 3600000000000L) {
unit = 5;
} else if (nanoseconds >= 60000000000L) {
unit = 4;
} else if (nanoseconds >= 1000000000L) {
unit = 3;
} else if (nanoseconds >= 1000000L) {
unit = 2;
} else if (nanoseconds >= 1000L) {
unit = 1;
} else {
unit = 0;
}
long format_args[2] = {nanoseconds, unit};
return native_bench_format(format_args, 2);
}
long native_bench_reset(long *args, int argc) {
pthread_mutex_lock(&timers_mutex);
for (int i = 0; i < MAX_TIMERS; i++) {
timers[i].active = 0;
}
next_timer_id = 0;
pthread_mutex_unlock(&timers_mutex);
return 0;
}
void register_benchmark_stdlib() {
register_native_func("bench_start", native_bench_start);
register_native_func("bench_end", native_bench_end);
register_native_func("bench_format", native_bench_format);
register_native_func("bench_format_auto", native_bench_format_auto);
register_native_func("bench_reset", native_bench_reset);
}
-6
View File
@@ -1,6 +0,0 @@
#ifndef BENCHMARK_STDLIB_H
#define BENCHMARK_STDLIB_H
void register_benchmark_stdlib();
#endif
-34
View File
@@ -1,7 +1,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include "../../types.h"
#include "math_stdlib.h"
@@ -129,35 +128,6 @@ long native_double_div(long *args, int argc) {
return result.l;
}
long native_rand(long *args, int argc) {
return (long)rand();
}
long native_srand(long *args, int argc) {
if (!args || argc < 1) {
srand(1);
} else {
srand((unsigned int)args[0]);
}
return 0;
}
long native_rand_range(long *args, int argc) {
if (!args || argc < 2) {
return 0;
}
long min = args[0];
long max = args[1];
if (max <= min) {
return min;
}
return min + (rand() % (max - min + 1));
}
long native_time(long *args, int argc) {
return (long)time(NULL);
}
void register_math_stdlib() {
register_native_func("sqrt", native_sqrt);
register_native_func("pow", native_pow);
@@ -173,8 +143,4 @@ void register_math_stdlib() {
register_native_func("double_sub", native_double_sub);
register_native_func("double_mul", native_double_mul);
register_native_func("double_div", native_double_div);
register_native_func("rand", native_rand);
register_native_func("srand", native_srand);
register_native_func("rand_range", native_rand_range);
register_native_func("time", native_time);
}
-2
View File
@@ -6,7 +6,6 @@
#include "async/async_stdlib.h"
#include "constants/constants_stdlib.h"
#include "eval/eval_stdlib.h"
#include "benchmark/benchmark_stdlib.h"
void register_stdlib() {
register_string_stdlib();
@@ -16,5 +15,4 @@ void register_stdlib() {
register_async_stdlib();
register_constants_stdlib();
register_eval_stdlib();
register_benchmark_stdlib();
}
-168
View File
@@ -1,168 +0,0 @@
#include "unittest.rc"
int main() {
int tc = new TestCase();
tc.init("Benchmark Standard Library");
printf("\n=== Testing bench_start/bench_end ===\n");
int timer1 = bench_start();
tc.assertGreaterEqual(timer1, 0, "bench_start returns valid timer ID");
int i = 0;
int sum = 0;
while (i < 1000) {
sum = sum + i;
i = i + 1;
}
int elapsed1 = bench_end(timer1);
tc.assertGreater(elapsed1, 0, "bench_end returns positive elapsed time");
tc.assertLess(elapsed1, 1000000000, "elapsed time is less than 1 second");
printf("\n=== Testing multiple timers ===\n");
int timer2 = bench_start();
int timer3 = bench_start();
tc.assertNotEqual(timer2, timer3, "Multiple timers have different IDs");
int elapsed2 = bench_end(timer2);
int elapsed3 = bench_end(timer3);
tc.assertGreater(elapsed2, 0, "Timer 2 has positive elapsed time");
tc.assertGreater(elapsed3, 0, "Timer 3 has positive elapsed time");
printf("\n=== Testing bench_format with nanoseconds ===\n");
char* formatted_ns = bench_format(12345, 0);
tc.assertNotNull(formatted_ns, "bench_format(ns) returns non-null");
tc.assertStringContains(formatted_ns, "ns", "Formatted string contains 'ns'");
tc.assertStringContains(formatted_ns, "12345", "Formatted string contains value");
printf("\n=== Testing bench_format with microseconds ===\n");
char* formatted_us = bench_format(123456, 1);
tc.assertNotNull(formatted_us, "bench_format(us) returns non-null");
tc.assertStringContains(formatted_us, "us", "Formatted string contains 'us'");
printf("\n=== Testing bench_format with milliseconds ===\n");
char* formatted_ms = bench_format(1234567, 2);
tc.assertNotNull(formatted_ms, "bench_format(ms) returns non-null");
tc.assertStringContains(formatted_ms, "ms", "Formatted string contains 'ms'");
printf("\n=== Testing bench_format with seconds ===\n");
char* formatted_s = bench_format(1234567890, 3);
tc.assertNotNull(formatted_s, "bench_format(s) returns non-null");
tc.assertStringContains(formatted_s, "s", "Formatted string contains 's'");
printf("\n=== Testing bench_format with minutes ===\n");
char* formatted_min = bench_format(123456789000, 4);
tc.assertNotNull(formatted_min, "bench_format(min) returns non-null");
tc.assertStringContains(formatted_min, "min", "Formatted string contains 'min'");
printf("\n=== Testing bench_format with hours ===\n");
char* formatted_h = bench_format(7412345678900, 5);
tc.assertNotNull(formatted_h, "bench_format(h) returns non-null");
tc.assertStringContains(formatted_h, "h", "Formatted string contains 'h'");
printf("\n=== Testing bench_format_auto with nanoseconds ===\n");
char* auto_ns = bench_format_auto(500);
tc.assertNotNull(auto_ns, "bench_format_auto(500ns) returns non-null");
tc.assertStringContains(auto_ns, "ns", "Auto-format chooses nanoseconds for small values");
printf("\n=== Testing bench_format_auto with microseconds ===\n");
char* auto_us = bench_format_auto(5000);
tc.assertNotNull(auto_us, "bench_format_auto(5000ns) returns non-null");
tc.assertStringContains(auto_us, "us", "Auto-format chooses microseconds");
printf("\n=== Testing bench_format_auto with milliseconds ===\n");
char* auto_ms = bench_format_auto(5000000);
tc.assertNotNull(auto_ms, "bench_format_auto(5ms) returns non-null");
tc.assertStringContains(auto_ms, "ms", "Auto-format chooses milliseconds");
printf("\n=== Testing bench_format_auto with seconds ===\n");
char* auto_s = bench_format_auto(5000000000);
tc.assertNotNull(auto_s, "bench_format_auto(5s) returns non-null");
tc.assertStringContains(auto_s, "s", "Auto-format chooses seconds");
printf("\n=== Testing bench_format_auto with minutes ===\n");
char* auto_min = bench_format_auto(300000000000);
tc.assertNotNull(auto_min, "bench_format_auto(5min) returns non-null");
tc.assertStringContains(auto_min, "min", "Auto-format chooses minutes");
printf("\n=== Testing bench_format_auto with hours ===\n");
char* auto_h = bench_format_auto(18000000000000);
tc.assertNotNull(auto_h, "bench_format_auto(5h) returns non-null");
tc.assertStringContains(auto_h, "h", "Auto-format chooses hours");
printf("\n=== Testing practical benchmarking scenario ===\n");
int timer_practical = bench_start();
int j = 0;
int factorial = 1;
while (j < 100) {
factorial = factorial + j;
j = j + 1;
}
int elapsed_practical = bench_end(timer_practical);
char* practical_formatted = bench_format_auto(elapsed_practical);
tc.assertGreater(elapsed_practical, 0, "Practical benchmark measured time");
tc.assertNotNull(practical_formatted, "Practical benchmark formatted correctly");
printf(" Practical test took: %s\n", practical_formatted);
printf("\n=== Testing bench_reset ===\n");
int reset_result = bench_reset();
tc.assertEqual(reset_result, 0, "bench_reset returns 0");
int timer_after_reset = bench_start();
tc.assertGreaterEqual(timer_after_reset, 0, "Timer ID valid after reset");
printf("\n=== Testing error cases ===\n");
int invalid_end = bench_end(9999);
tc.assertEqual(invalid_end, -1, "bench_end with invalid timer returns -1");
int negative_timer = bench_end(-1);
tc.assertEqual(negative_timer, -1, "bench_end with negative timer returns -1");
printf("\n=== Testing nested timing ===\n");
int outer_timer = bench_start();
int inner_timer = bench_start();
int k = 0;
while (k < 50) {
k = k + 1;
}
int inner_elapsed = bench_end(inner_timer);
int outer_elapsed = bench_end(outer_timer);
tc.assertGreater(inner_elapsed, 0, "Inner timer measured time");
tc.assertGreater(outer_elapsed, 0, "Outer timer measured time");
tc.assertGreaterEqual(outer_elapsed, inner_elapsed, "Outer timer >= inner timer");
printf("\n=== Summary ===\n");
printf("Total Passed: %d\n", tc.passed);
printf("Total Failed: %d\n", tc.failed);
if (tc.failed == 0) {
printf("All benchmark stdlib tests PASSED!\n");
}
return 0;
}
-29
View File
@@ -61,35 +61,6 @@ int main() {
result_int = double_to_int(d_quot);
tc.assertEqual(result_int, 1, "Double division: 5.0 / 3.0 = 1.666... (truncated to 1)");
printf("\n=== Testing Random Functions ===\n");
srand(42);
int r1 = rand();
int r2 = rand();
tc.assertNotEqual(r1, r2, "Two consecutive rand() calls should give different values");
tc.assertGreaterEqual(r1, 0, "rand() returns non-negative");
tc.assertGreaterEqual(r2, 0, "rand() returns non-negative");
srand(42);
int r3 = rand();
tc.assertEqual(r1, r3, "Same seed produces same first value");
printf("\n=== Testing rand_range ===\n");
srand(time());
int i = 0;
int range_ok = 1;
while (i < 100) {
int val = rand_range(10, 20);
if (val < 10 || val > 20) {
range_ok = 0;
}
i = i + 1;
}
tc.assertTrue(range_ok, "rand_range(10, 20) returns values in [10, 20]");
printf("\n=== Testing time ===\n");
int t1 = time();
tc.assertGreater(t1, 0, "time() returns positive timestamp");
printf("\n=== Summary ===\n");
printf("Total Passed: %d\n", tc.passed);
printf("Total Failed: %d\n", tc.failed);