Compare commits

..
35 Commits
Author SHA1 Message Date
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
32 changed files with 407 additions and 2685 deletions
+12 -26
View File
@@ -21,9 +21,6 @@ SOURCES = $(SRC_DIR)/main.c \
$(SRC_DIR)/oop.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 +29,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 +40,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 +63,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 +79,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 +152,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 +186,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 +198,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 +223,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"
+4 -17
View File
@@ -155,25 +155,13 @@ int main() {
### HTTP Server Examples
**Simple HTTP Server** (`examples/http_simple.rc`)
Single-connection HTTP server that accepts one request and exits with a fixed response.
Single-connection HTTP server that accepts one request and exits.
**Persistent HTTP Server** (`examples/http_persistent.rc`)
HTTP server with request counter that continuously accepts connections with fixed responses.
HTTP server with request counter that continuously accepts connections.
**HTTP File Server** (`examples/http_fileserver.rc`)
HTTP server that serves files from the filesystem. Handles up to 100 connections and streams file content using proper HTTP responses. Demonstrates socket programming, file I/O, and HTTP protocol implementation within RC's type system constraints.
Run examples:
```bash
make run-http-simple # Simple single-connection server
make run-http-persistent # Persistent multi-connection server
./bin/rc examples/http_fileserver.rc # File serving server
```
Test with curl or browser:
```bash
curl http://localhost:8080/
```
**Multi-Connection HTTP Server** (`examples/http_multi.rc`)
HTTP server that handles up to 100 consecutive connections.
## Project Structure
@@ -262,7 +250,6 @@ For technical details, see:
- Pointer arithmetic works on virtual memory addresses
- Maximum 100 concurrent async operations
- Async execution is serialized (not parallel)
- **Type system constraints**: String functions (substr, strpos, strcmp) work with string pointers (`char*`) but not with char arrays used as buffers for socket operations
## Testing
+1 -510
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
@@ -896,182 +868,6 @@ close(sockfd);
- `AF_INET()` - IPv4 address family
- `SOCK_STREAM()` - TCP socket type
### Building an HTTP File Server
This section demonstrates how to build a complete HTTP file server in RC. The example shows proper socket handling, file I/O, and HTTP response generation.
#### Complete HTTP File Server Example
```c
int main() {
int server_fd;
int client_fd;
char buffer[4096];
int bytes_received;
int file;
char *line;
int line_len;
char *response_header;
int header_len;
int total_sent;
int count;
char *filename;
server_fd = socket(AF_INET(), SOCK_STREAM(), 0);
if (server_fd < 0) {
printf("Failed to create socket\n");
return 1;
}
if (bind(server_fd, 8080) < 0) {
printf("Failed to bind to port 8080\n");
close(server_fd);
return 1;
}
if (listen(server_fd, 10) < 0) {
printf("Failed to listen\n");
close(server_fd);
return 1;
}
printf("HTTP File Server listening on port 8080\n");
printf("Serving README.md for all requests\n");
printf("Example: http://localhost:8080/\n\n");
filename = "README.md";
count = 0;
while (count < 100) {
printf("Waiting for connection %d\n", count + 1);
client_fd = accept(server_fd);
if (client_fd < 0) {
printf("Failed to accept connection\n");
count = count + 1;
continue;
}
printf("Client connected\n");
bytes_received = recv(client_fd, buffer, 1024, 0);
if (bytes_received <= 0) {
printf("Failed to receive request\n");
close(client_fd);
count = count + 1;
continue;
}
printf("Received %d bytes\n", bytes_received);
file = fopen(filename, "r");
if (file == 0) {
printf("File not found: %s\n", filename);
response_header = "HTTP/1.1 404 Not Found\nContent-Type: text/html\n\n<html><body><h1>404 Not Found</h1><p>The requested file was not found.</p></body></html>";
header_len = strlen(response_header);
send(client_fd, response_header, header_len, 0);
close(client_fd);
count = count + 1;
continue;
}
printf("File opened successfully\n");
response_header = "HTTP/1.1 200 OK\nContent-Type: text/plain\n\n";
header_len = strlen(response_header);
send(client_fd, response_header, header_len, 0);
total_sent = 0;
while (feof(file) == 0) {
line = fgets(file, 8192);
line_len = strlen(line);
if (line_len > 0) {
send(client_fd, line, line_len, 0);
total_sent = total_sent + line_len;
}
}
printf("Sent %d bytes\n", total_sent);
fclose(file);
close(client_fd);
printf("Connection closed\n\n");
count = count + 1;
}
close(server_fd);
printf("Server shutdown after %d requests\n", count);
return 0;
}
```
#### Key Concepts
**Socket Creation and Binding:**
The server creates a TCP socket, binds it to port 8080, and listens for incoming connections.
**Request Loop:**
The server runs a loop accepting up to 100 connections. For each connection:
1. Accept the client connection
2. Receive the HTTP request
3. Open the requested file
4. Send HTTP response headers
5. Send file content line by line
6. Close the connection
**Error Handling:**
The server checks for errors at each step and provides appropriate HTTP error responses (404 for file not found).
**Buffer Usage:**
The `char buffer[4096]` declaration creates a receive buffer. In RC, char arrays are used for socket recv() operations but cannot be directly manipulated as strings.
**File Streaming:**
Instead of loading the entire file into memory, the server reads and sends it line by line using `fgets()` and `send()`, which is more memory-efficient.
#### Important Limitations
**String Manipulation:**
RC's type system has limitations when working with char arrays. Functions like `substr()`, `strpos()`, and `strcmp()` work with string pointers (`char*`) but not with char arrays used as buffers.
**Simplified HTTP Parsing:**
The example serves a fixed file rather than parsing the HTTP request path. Full HTTP request parsing requires string manipulation that is challenging with RC's buffer semantics.
**Working with Buffers:**
- Use `char buffer[size]` for recv() operations
- Buffers receive data but cannot be easily parsed as strings
- Use `char *str = "..."` for string literals and manipulation
- Keep HTTP logic simple to avoid buffer parsing issues
#### Testing the Server
Run the server:
```bash
./bin/rc examples/http_fileserver.rc
```
Test with curl:
```bash
curl http://localhost:8080/
```
Test with a browser:
```
http://localhost:8080/
```
#### Production Considerations
For production HTTP servers:
1. Add request timeout handling
2. Implement proper HTTP request parsing (in a more suitable language)
3. Add support for multiple file types and MIME types
4. Implement connection pooling for better performance
5. Add logging for debugging and monitoring
6. Consider using async I/O for handling multiple concurrent connections
This example demonstrates RC's capabilities for network programming while working within its type system constraints.
## Comments
RC supports single-line comments using `//`.
@@ -1338,7 +1134,6 @@ int main() {
- Coroutines cannot be cancelled once started
- ExecutionContext system ensures state isolation
- No stale state or race condition issues
- Async I/O operations are fully thread-safe with mutex protection
### Include System
- Maximum 32 levels of include nesting
@@ -1404,7 +1199,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 +1213,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
@@ -1655,7 +1448,6 @@ All async functions are executed in separate threads with proper mutex locking a
- Dynamic allocation for coroutine arguments
- Proper cleanup when coroutines complete
- No memory leaks in async/await operations
- Async I/O threads use memory_mutex for safe memory[] access
**Proven Stability:**
- 464+ consecutive test runs without failures
@@ -2055,8 +1847,6 @@ int main() {
## Async I/O (Low-level)
All async I/O operations (file read/write, socket recv/send) are thread-safe. Background threads use mutex protection when accessing shared memory, ensuring safe concurrent execution with zero race conditions.
### Async File Operations
```c
@@ -2124,302 +1914,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;
}
-102
View File
@@ -1,102 +0,0 @@
int main() {
int server_fd;
int client_fd;
char buffer[4096];
int bytes_received;
int file;
char *line;
int line_len;
char *response_header;
int header_len;
int total_sent;
int count;
char *filename;
server_fd = socket(AF_INET(), SOCK_STREAM(), 0);
if (server_fd < 0) {
printf("Failed to create socket\n");
return 1;
}
if (bind(server_fd, 8080) < 0) {
printf("Failed to bind to port 8080\n");
close(server_fd);
return 1;
}
if (listen(server_fd, 10) < 0) {
printf("Failed to listen\n");
close(server_fd);
return 1;
}
printf("HTTP File Server listening on port 8080\n");
printf("Serving README.md for all requests\n");
printf("Example: http://localhost:8080/\n\n");
filename = "README.md";
count = 1;
while (count > 0) {
printf("Waiting for connection %d\n", count + 1);
client_fd = accept(server_fd);
if (client_fd < 0) {
printf("Failed to accept connection\n");
count = count + 1;
continue;
}
printf("Client connected\n");
bytes_received = recv(client_fd, buffer, 1024, 0);
if (bytes_received <= 0) {
printf("Failed to receive request\n");
close(client_fd);
count = count + 1;
continue;
}
printf("Received %d bytes\n", bytes_received);
file = fopen(filename, "r");
if (file == 0) {
printf("File not found: %s\n", filename);
response_header = "HTTP/1.1 404 Not Found\nContent-Type: text/html\n\n<html><body><h1>404 Not Found</h1><p>The requested file was not found.</p></body></html>";
header_len = strlen(response_header);
send(client_fd, response_header, header_len, 0);
close(client_fd);
count = count + 1;
continue;
}
printf("File opened successfully\n");
response_header = "HTTP/1.1 200 OK\nContent-Type: text/plain\n\n";
header_len = strlen(response_header);
send(client_fd, response_header, header_len, 0);
total_sent = 0;
while (feof(file) == 0) {
line = fgets(file, 8192);
line_len = strlen(line);
if (line_len > 0) {
send(client_fd, line, line_len, 0);
total_sent = total_sent + line_len;
}
}
printf("Sent %d bytes\n", total_sent);
fclose(file);
close(client_fd);
printf("Connection closed\n\n");
count = count + 1;
}
close(server_fd);
printf("Server shutdown after %d requests\n", count);
return 0;
}
+8 -25
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;
@@ -57,28 +56,20 @@ ExecutionContext* context_snapshot() {
ExecutionContext *ctx = context_create();
if (!ctx) return NULL;
int safe_sp = sp;
if (safe_sp < 0) safe_sp = 0;
if (safe_sp > MEM_SIZE) safe_sp = MEM_SIZE;
for (int i = 0; i < safe_sp; i++) {
for (int i = 0; i < sp && i < MEM_SIZE; i++) {
ctx->memory[i] = memory[i];
}
int safe_loc_cnt = loc_cnt;
if (safe_loc_cnt < 0) safe_loc_cnt = 0;
if (safe_loc_cnt > VAR_MAX) safe_loc_cnt = VAR_MAX;
for (int i = 0; i < safe_loc_cnt; i++) {
for (int i = 0; i < loc_cnt && i < VAR_MAX; i++) {
ctx->locals[i] = locals[i];
}
ctx->pc = pc;
ctx->sp = safe_sp;
ctx->sp = sp;
ctx->bp = bp;
ctx->ax = ax;
ctx->return_flag = return_flag;
ctx->loc_cnt = safe_loc_cnt;
ctx->loc_cnt = loc_cnt;
return ctx;
}
@@ -86,26 +77,18 @@ ExecutionContext* context_snapshot() {
void context_restore(ExecutionContext *ctx) {
if (!ctx) return;
int safe_sp = ctx->sp;
if (safe_sp < 0) safe_sp = 0;
if (safe_sp > MEM_SIZE) safe_sp = MEM_SIZE;
for (int i = 0; i < safe_sp; i++) {
for (int i = 0; i < ctx->sp && i < MEM_SIZE; i++) {
memory[i] = ctx->memory[i];
}
int safe_loc_cnt = ctx->loc_cnt;
if (safe_loc_cnt < 0) safe_loc_cnt = 0;
if (safe_loc_cnt > VAR_MAX) safe_loc_cnt = VAR_MAX;
for (int i = 0; i < safe_loc_cnt; i++) {
for (int i = 0; i < ctx->loc_cnt && i < VAR_MAX; i++) {
locals[i] = ctx->locals[i];
}
pc = ctx->pc;
sp = safe_sp;
sp = ctx->sp;
bp = ctx->bp;
ax = ctx->ax;
return_flag = ctx->return_flag;
loc_cnt = safe_loc_cnt;
loc_cnt = ctx->loc_cnt;
}
-5
View File
@@ -1,5 +0,0 @@
#include "debug.h"
#ifdef DEBUG_MODE
FILE *debug_file = NULL;
#endif
-80
View File
@@ -1,80 +0,0 @@
#ifndef DEBUG_H
#define DEBUG_H
#include <stdio.h>
#ifdef DEBUG_MODE
extern FILE *debug_file;
#define DEBUG_INIT() do { \
debug_file = fopen("debug.log", "w"); \
if (debug_file) { \
fprintf(debug_file, "=== RC Interpreter Debug Log ===\n"); \
fflush(debug_file); \
} \
} while(0)
#define DEBUG_CLOSE() do { \
if (debug_file) { \
fprintf(debug_file, "=== Debug Log End ===\n"); \
fclose(debug_file); \
debug_file = NULL; \
} \
} while(0)
#define DEBUG_LOG(fmt, ...) do { \
if (debug_file) { \
fprintf(debug_file, "[%s:%d in %s] " fmt "\n", \
__FILE__, __LINE__, __func__, ##__VA_ARGS__); \
fflush(debug_file); \
} \
} while(0)
#define DEBUG_FUNC_ENTRY() DEBUG_LOG(">>> ENTER")
#define DEBUG_FUNC_EXIT() DEBUG_LOG("<<< EXIT")
#define DEBUG_PTR(name, ptr) DEBUG_LOG("%s = %p", name, (void*)(ptr))
#define DEBUG_INT(name, val) DEBUG_LOG("%s = %d", name, (int)(val))
#define DEBUG_LONG(name, val) DEBUG_LOG("%s = %ld", name, (long)(val))
#define DEBUG_STR(name, str) DEBUG_LOG("%s = \"%s\"", name, (str) ? (str) : "(null)")
#define DEBUG_MEMORY_ACCESS(addr, action) \
DEBUG_LOG("MEMORY %s at addr=%d (MEM_SIZE=%d)", action, (int)(addr), MEM_SIZE)
#define DEBUG_TOKEN(idx) do { \
if ((idx) >= 0 && (idx) < tk_idx && (idx) < MAX_TOK) { \
DEBUG_LOG("TOKEN[%d]: type=%d, val=%ld, line=%d, file=%s", \
idx, tokens[idx].type, tokens[idx].val, \
tokens[idx].line, \
tokens[idx].filename ? tokens[idx].filename : "<null>"); \
} else { \
DEBUG_LOG("TOKEN[%d]: OUT OF BOUNDS (tk_idx=%d)", idx, tk_idx); \
} \
} while(0)
#define DEBUG_STACK_STATE() do { \
DEBUG_LOG("STACK: sp=%d, bp=%d, pc=%d, ax=%ld", sp, bp, pc, ax); \
} while(0)
#define DEBUG_CHECKPOINT(label) DEBUG_LOG("CHECKPOINT: %s", label)
#else
#define DEBUG_INIT() do {} while(0)
#define DEBUG_CLOSE() do {} while(0)
#define DEBUG_LOG(fmt, ...) do {} while(0)
#define DEBUG_FUNC_ENTRY() do {} while(0)
#define DEBUG_FUNC_EXIT() do {} while(0)
#define DEBUG_PTR(name, ptr) do {} while(0)
#define DEBUG_INT(name, val) do {} while(0)
#define DEBUG_LONG(name, val) do {} while(0)
#define DEBUG_STR(name, str) do {} while(0)
#define DEBUG_MEMORY_ACCESS(addr, action) do {} while(0)
#define DEBUG_TOKEN(idx) do {} while(0)
#define DEBUG_STACK_STATE() do {} while(0)
#define DEBUG_CHECKPOINT(label) do {} while(0)
#endif
#endif
-6
View File
@@ -4,7 +4,6 @@
#include <pthread.h>
#include "types.h"
#include "error.h"
#include "debug.h"
extern Token tokens[];
extern int tk_idx;
@@ -171,10 +170,6 @@ static void print_code_context(int token_index) {
}
void error_with_context(const char *error_type, const char *message, const char *tip) {
DEBUG_LOG("FATAL ERROR: %s - %s", error_type ? error_type : "General Error", message);
DEBUG_STACK_STATE();
DEBUG_TOKEN(pc);
fprintf(stderr, "\n");
fprintf(stderr, "╔════════════════════════════════════════════════════════════════╗\n");
fprintf(stderr, "║ RUNTIME ERROR ║\n");
@@ -211,6 +206,5 @@ void error_with_context(const char *error_type, const char *message, const char
print_code_context(pc);
print_stacktrace();
DEBUG_CLOSE();
exit(1);
}
+1 -8
View File
@@ -24,13 +24,6 @@ int class_count = 0;
Object objects[MAX_OBJECTS];
int object_count = 0;
CallStack call_stack = {{}, 0};
pthread_mutex_t token_mutex;
pthread_rwlock_t tokens_rwlock;
pthread_mutex_t str_pool_mutex;
pthread_mutex_t memory_mutex;
pthread_mutex_t locals_mutex;
pthread_mutex_t interpreter_state_mutex;
pthread_rwlock_t funcs_rwlock;
pthread_rwlock_t native_funcs_rwlock;
pthread_rwlock_t classes_rwlock;
pthread_mutex_t objects_mutex;
pthread_mutex_t call_stack_mutex;
+16 -32
View File
@@ -6,8 +6,6 @@
#include "interpreter.h"
#include "parser.h"
#include "error.h"
#include "debug.h"
#include "memory.h"
void error(char *msg) {
error_with_context("ParseError", msg, NULL);
@@ -112,38 +110,26 @@ 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) {
error("Too many local variables");
}
if (!mem_check_sp(sp + 1, alloc_ctx)) {
if (sp >= MEM_SIZE) {
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 +144,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++;
}
+2 -28
View File
@@ -9,26 +9,11 @@
#include "native_functions.h"
#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_mutex_init(&token_mutex, NULL);
pthread_rwlock_init(&tokens_rwlock, NULL);
pthread_mutex_init(&str_pool_mutex, NULL);
pthread_mutex_init(&memory_mutex, NULL);
pthread_mutex_init(&locals_mutex, NULL);
pthread_mutex_init(&interpreter_state_mutex, NULL);
pthread_rwlock_init(&funcs_rwlock, NULL);
pthread_rwlock_init(&native_funcs_rwlock, NULL);
pthread_rwlock_init(&classes_rwlock, NULL);
pthread_mutex_init(&objects_mutex, NULL);
pthread_mutex_init(&call_stack_mutex, NULL);
if (argc < 2) {
printf("Usage: rc <file.rc>\n");
@@ -78,19 +63,8 @@ int main(int argc, char **argv) {
statement();
free(src_code);
scope_cleanup();
pthread_mutex_destroy(&token_mutex);
pthread_rwlock_destroy(&tokens_rwlock);
pthread_mutex_destroy(&str_pool_mutex);
pthread_mutex_destroy(&memory_mutex);
pthread_mutex_destroy(&locals_mutex);
pthread_mutex_destroy(&interpreter_state_mutex);
pthread_rwlock_destroy(&funcs_rwlock);
pthread_rwlock_destroy(&native_funcs_rwlock);
pthread_rwlock_destroy(&classes_rwlock);
pthread_mutex_destroy(&objects_mutex);
pthread_mutex_destroy(&call_stack_mutex);
DEBUG_LOG("RC Interpreter exiting normally");
DEBUG_CLOSE();
return 0;
}
-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;
}
+48 -62
View File
@@ -6,9 +6,6 @@
#include "interpreter.h"
#include "string_utils.h"
#include "error.h"
#include "debug.h"
#include "memory.h"
#include "scope.h"
extern Token tokens[];
extern int pc;
@@ -178,20 +175,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 +197,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 +230,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 {
@@ -329,30 +326,11 @@ long unary() {
}
if (tokens[pc].type == '*') {
pc++;
long addr = unary();
DEBUG_LONG("dereference_addr", addr);
if (addr < 0 || addr >= MEM_SIZE) {
if (addr < 0) {
DEBUG_LOG("ERROR: Negative memory address: %ld", addr);
error("Invalid memory address (negative)");
return 0;
}
if (addr > MEM_SIZE * 8) {
char *ptr = (char*)addr;
DEBUG_PTR("external_ptr", ptr);
if (ptr == NULL) {
DEBUG_LOG("ERROR: Null pointer dereference");
error("Null pointer dereference");
return 0;
}
DEBUG_LOG("Dereferencing external pointer: %p", (void*)ptr);
return *ptr;
}
DEBUG_LOG("ERROR: Memory access out of bounds: %ld (max: %d)", addr, MEM_SIZE);
error("Memory access out of bounds");
return 0;
int addr = unary();
if (addr > MEM_SIZE * 8 || addr < 0) {
return *(char*)addr;
}
DEBUG_MEMORY_ACCESS(addr, "READ");
if (addr < 0 || addr >= MEM_SIZE) return 0;
return memory[addr];
}
else if (tokens[pc].type == '&') {
@@ -429,15 +407,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 +440,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 +456,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
+88 -158
View File
@@ -5,14 +5,9 @@
#include <sys/socket.h>
#include "../../types.h"
#include "../../interpreter.h"
#include "../../scope.h"
#include "async_stdlib.h"
#include "../../debug.h"
extern void register_native_func(char *name, NativeFunc func);
extern pthread_mutex_t memory_mutex;
extern pthread_mutex_t locals_mutex;
extern pthread_mutex_t interpreter_state_mutex;
#define MAX_ASYNC_OPS 100
@@ -93,20 +88,18 @@ void* async_fread_thread(void *arg) {
int result = fread(temp_buf, 1, size, data->f);
if (result > 0) {
pthread_mutex_lock(&memory_mutex);
for (int i = 0; i < result && data->addr + i < MEM_SIZE; i++) {
memory[data->addr + i] = temp_buf[i];
}
pthread_mutex_unlock(&memory_mutex);
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
async_ops[id].data = NULL;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
@@ -125,21 +118,19 @@ void* async_fwrite_thread(void *arg) {
if (data->buf_arg + size > MEM_SIZE) {
size = MEM_SIZE - data->buf_arg;
}
pthread_mutex_lock(&memory_mutex);
for (int i = 0; i < size; i++) {
temp_buf[i] = (char)memory[data->buf_arg + i];
}
pthread_mutex_unlock(&memory_mutex);
result = fwrite(temp_buf, 1, size, data->f);
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
async_ops[id].data = NULL;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
@@ -154,20 +145,18 @@ void* async_recv_thread(void *arg) {
int result = recv(data->sockfd, temp_buf, len, data->flags);
if (result > 0) {
pthread_mutex_lock(&memory_mutex);
for (int i = 0; i < result && data->addr + i < MEM_SIZE; i++) {
memory[data->addr + i] = temp_buf[i];
}
pthread_mutex_unlock(&memory_mutex);
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
async_ops[id].data = NULL;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
@@ -186,21 +175,19 @@ void* async_send_thread(void *arg) {
if (data->buf_arg + len > MEM_SIZE) {
len = MEM_SIZE - data->buf_arg;
}
pthread_mutex_lock(&memory_mutex);
for (int i = 0; i < len; i++) {
temp_buf[i] = (char)memory[data->buf_arg + i];
}
pthread_mutex_unlock(&memory_mutex);
result = send(data->sockfd, temp_buf, len, data->flags);
}
pthread_mutex_lock(&async_mutex);
async_ops[id].result = result;
async_ops[id].complete = 1;
async_ops[id].data = NULL;
pthread_mutex_unlock(&async_mutex);
free(data);
async_ops[id].data = NULL;
return NULL;
}
@@ -278,12 +265,6 @@ long native_async_recv(long *args, int argc) {
if (id < 0) return -1;
AsyncRecvData *data = malloc(sizeof(AsyncRecvData));
if (!data) {
pthread_mutex_lock(&async_mutex);
async_ops[id].active = 0;
pthread_mutex_unlock(&async_mutex);
return -1;
}
data->sockfd = sockfd;
data->addr = addr;
data->len = len;
@@ -291,14 +272,6 @@ long native_async_recv(long *args, int argc) {
async_ops[id].data = data;
int *id_ptr = malloc(sizeof(int));
if (!id_ptr) {
free(data);
pthread_mutex_lock(&async_mutex);
async_ops[id].active = 0;
async_ops[id].data = NULL;
pthread_mutex_unlock(&async_mutex);
return -1;
}
*id_ptr = id;
pthread_create(&async_ops[id].thread, NULL, async_recv_thread, id_ptr);
return id;
@@ -315,12 +288,6 @@ long native_async_send(long *args, int argc) {
if (id < 0) return -1;
AsyncSendData *data = malloc(sizeof(AsyncSendData));
if (!data) {
pthread_mutex_lock(&async_mutex);
async_ops[id].active = 0;
pthread_mutex_unlock(&async_mutex);
return -1;
}
data->sockfd = sockfd;
data->buf_arg = buf_arg;
data->len = len;
@@ -328,14 +295,6 @@ long native_async_send(long *args, int argc) {
async_ops[id].data = data;
int *id_ptr = malloc(sizeof(int));
if (!id_ptr) {
free(data);
pthread_mutex_lock(&async_mutex);
async_ops[id].active = 0;
async_ops[id].data = NULL;
pthread_mutex_unlock(&async_mutex);
return -1;
}
*id_ptr = id;
pthread_create(&async_ops[id].thread, NULL, async_send_thread, id_ptr);
return id;
@@ -344,17 +303,9 @@ long native_async_send(long *args, int argc) {
long native_async_wait(long *args, int argc) {
if (!args || argc < 1) return -1;
int id = (int)args[0];
if (id < 0 || id >= MAX_ASYNC_OPS) return -1;
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return -1;
pthread_mutex_lock(&async_mutex);
if (!async_ops[id].active) {
pthread_mutex_unlock(&async_mutex);
return -1;
}
pthread_t thread = async_ops[id].thread;
pthread_mutex_unlock(&async_mutex);
pthread_join(thread, NULL);
pthread_join(async_ops[id].thread, NULL);
pthread_mutex_lock(&async_mutex);
long result = async_ops[id].result;
@@ -367,13 +318,9 @@ long native_async_wait(long *args, int argc) {
long native_async_poll(long *args, int argc) {
if (!args || argc < 1) return 0;
int id = (int)args[0];
if (id < 0 || id >= MAX_ASYNC_OPS) return 0;
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return 0;
pthread_mutex_lock(&async_mutex);
if (!async_ops[id].active) {
pthread_mutex_unlock(&async_mutex);
return 0;
}
int complete = async_ops[id].complete;
pthread_mutex_unlock(&async_mutex);
@@ -383,13 +330,9 @@ long native_async_poll(long *args, int argc) {
long native_async_result(long *args, int argc) {
if (!args || argc < 1) return -1;
int id = (int)args[0];
if (id < 0 || id >= MAX_ASYNC_OPS) return -1;
if (id < 0 || id >= MAX_ASYNC_OPS || !async_ops[id].active) return -1;
pthread_mutex_lock(&async_mutex);
if (!async_ops[id].active) {
pthread_mutex_unlock(&async_mutex);
return -1;
}
long result = async_ops[id].result;
async_ops[id].active = 0;
pthread_mutex_unlock(&async_mutex);
@@ -440,37 +383,26 @@ void* coroutine_thread_func(void *arg) {
int coro_id = data->coroutine_id;
free(data);
DEBUG_LOG("Coroutine thread started: coro_id=%d", coro_id);
if (coro_id < 0 || coro_id >= MAX_COROUTINES) {
DEBUG_LOG("ERROR: Invalid coro_id=%d (max=%d)", coro_id, MAX_COROUTINES);
return NULL;
}
pthread_mutex_lock(&coroutine_mutex);
Coroutine *coro = &coroutines[coro_id];
if (!coro->active) {
pthread_mutex_unlock(&coroutine_mutex);
DEBUG_LOG("ERROR: Coroutine %d was deactivated before thread started", coro_id);
return NULL;
}
int func_idx = coro->func_idx;
int argc = coro->argc;
long local_args[10];
for (int i = 0; i < argc && i < 10; i++) {
local_args[i] = coro->args ? coro->args[i] : 0;
}
long *args = coro->args;
if (func_idx < 0 || func_idx >= func_cnt) {
pthread_mutex_lock(&coroutine_mutex);
coro->complete = 1;
coro->result = 0;
pthread_mutex_unlock(&coroutine_mutex);
return NULL;
}
pthread_mutex_lock(&coroutine_mutex);
extern ExecutionContext* context_snapshot();
extern void context_restore(ExecutionContext *ctx);
extern void context_destroy(ExecutionContext *ctx);
@@ -513,66 +445,6 @@ void* coroutine_thread_func(void *arg) {
int param_base = sp;
for (int i = 0; i < argc && i < 10; i++) {
if (sp >= MEM_SIZE) break;
memory[sp++] = local_args[i];
}
pthread_rwlock_rdlock(&tokens_rwlock);
int scan_pc = funcs[func_idx].params_start;
int param_idx = 0;
int safe_tk_idx = tk_idx;
while (scan_pc < MAX_TOK && scan_pc < safe_tk_idx && tokens[scan_pc].type != ')') {
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 && 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++;
}
pthread_rwlock_unlock(&tokens_rwlock);
pc = funcs[func_idx].entry_point;
ax = 0;
extern void statement();
statement();
long result_val = ax;
context_restore(saved_ctx);
context_destroy(saved_ctx);
coro->result = result_val;
coro->complete = 1;
pthread_mutex_unlock(&coroutine_mutex);
return NULL;
}
static long execute_function_sync(int func_idx, long *args, int argc) {
if (func_idx < 0 || func_idx >= func_cnt) {
return 0;
}
int saved_pc = pc;
long saved_ax = ax;
int saved_return_flag = return_flag;
scope_push();
int param_base = sp;
for (int i = 0; i < argc && i < 10 && sp < MEM_SIZE; i++) {
memory[sp++] = args[i];
}
@@ -603,46 +475,62 @@ static long execute_function_sync(int func_idx, long *args, int argc) {
pc = funcs[func_idx].entry_point;
ax = 0;
return_flag = 0;
extern void statement();
extern pthread_rwlock_t tokens_rwlock;
pthread_rwlock_rdlock(&tokens_rwlock);
statement();
pthread_rwlock_unlock(&tokens_rwlock);
long result = ax;
long result_val = ax;
scope_pop();
context_restore(saved_ctx);
context_destroy(saved_ctx);
pc = saved_pc;
ax = saved_ax;
return_flag = saved_return_flag;
coro->result = result_val;
coro->complete = 1;
return result;
pthread_mutex_unlock(&coroutine_mutex);
return NULL;
}
int create_coroutine(int func_idx, long *args, int argc) {
DEBUG_FUNC_ENTRY();
DEBUG_INT("func_idx", func_idx);
DEBUG_INT("argc", argc);
int coro_id = alloc_coroutine();
if (coro_id < 0) {
DEBUG_LOG("ERROR: Failed to allocate coroutine");
return -1;
}
DEBUG_INT("allocated_coro_id", coro_id);
Coroutine *coro = &coroutines[coro_id];
pthread_mutex_lock(&coroutine_mutex);
coro->func_idx = func_idx;
coro->argc = argc;
coro->args = NULL;
long result = execute_function_sync(func_idx, args, argc);
if (argc > 0) {
coro->args = (long*)malloc(argc * sizeof(long));
if (!coro->args) {
pthread_mutex_unlock(&coroutine_mutex);
return -1;
}
for (int i = 0; i < argc; i++) {
coro->args[i] = args[i];
}
} else {
coro->args = NULL;
}
pthread_mutex_unlock(&coroutine_mutex);
coro->result = result;
coro->complete = 1;
CoroutineThreadData *thread_data = malloc(sizeof(CoroutineThreadData));
thread_data->coroutine_id = coro_id;
pthread_t *thread = malloc(sizeof(pthread_t));
pthread_create(thread, NULL, coroutine_thread_func, thread_data);
pthread_mutex_lock(&coroutine_mutex);
coro->thread = thread;
pthread_mutex_unlock(&coroutine_mutex);
DEBUG_FUNC_EXIT();
return coro_id;
}
@@ -659,8 +547,21 @@ long native_await(long *args, int argc) {
return 0;
}
pthread_t *thread = (pthread_t*)coro->thread;
if (thread) {
pthread_join(*thread, NULL);
free(thread);
coro->thread = NULL;
}
pthread_mutex_lock(&coroutine_mutex);
long result = coro->result;
if (coro->args) {
free(coro->args);
coro->args = NULL;
}
coro->active = 0;
pthread_mutex_unlock(&coroutine_mutex);
return result;
}
@@ -668,6 +569,35 @@ long native_await(long *args, int argc) {
long native_gather(long *args, int argc) {
if (!args || argc < 1) return 0;
int coro_ids[MAX_COROUTINES];
int count = 0;
for (int i = 0; i < argc && i < MAX_COROUTINES; i++) {
coro_ids[count++] = (int)args[i];
}
for (int i = 0; i < count; i++) {
int coro_id = coro_ids[i];
if (coro_id < 0 || coro_id >= MAX_COROUTINES) continue;
Coroutine *coro = &coroutines[coro_id];
if (!coro->active) continue;
pthread_t *thread = (pthread_t*)coro->thread;
if (thread) {
pthread_join(*thread, NULL);
free(thread);
coro->thread = NULL;
}
pthread_mutex_lock(&coroutine_mutex);
if (coro->args) {
free(coro->args);
coro->args = NULL;
}
pthread_mutex_unlock(&coroutine_mutex);
}
return 1;
}
-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
-9
View File
@@ -1,13 +1,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "../../types.h"
#include "../../interpreter.h"
#include "file_stdlib.h"
extern void register_native_func(char *name, NativeFunc func);
extern pthread_mutex_t str_pool_mutex;
long native_fopen(long *args, int argc) {
if (!args || argc < 2) {
@@ -97,10 +95,7 @@ long native_fgets(long *args, int argc) {
return (long)empty_str;
}
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -111,15 +106,11 @@ long native_fgets(long *args, int argc) {
}
if (fgets(result, max_size, f) == NULL) {
pthread_mutex_unlock(&str_pool_mutex);
return (long)empty_str;
}
int len = strlen(result);
str_pool_idx += len + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
-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();
}
+2 -47
View File
@@ -2,13 +2,11 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <pthread.h>
#include "../../types.h"
#include "../../interpreter.h"
#include "string_stdlib.h"
extern void register_native_func(char *name, NativeFunc func);
extern pthread_mutex_t str_pool_mutex;
long native_strlen(long *args, int argc) {
if (!args || argc < 1) {
@@ -49,10 +47,7 @@ long native_substr(long *args, int argc) {
int start = (int)args[1];
int length = (int)args[2];
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -61,18 +56,11 @@ long native_substr(long *args, int argc) {
int str_len = strlen(str);
if (start < 0) start = 0;
if (start >= str_len) {
pthread_mutex_unlock(&str_pool_mutex);
return (long)empty_str;
}
if (start >= str_len) return (long)empty_str;
if (start + length > str_len) length = str_len - start;
if (length < 0) {
pthread_mutex_unlock(&str_pool_mutex);
return (long)empty_str;
}
if (length < 0) return (long)empty_str;
if (str_pool_idx + length + 1 >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -81,9 +69,6 @@ long native_substr(long *args, int argc) {
result[length] = 0;
str_pool_idx += length + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
@@ -97,10 +82,7 @@ long native_upper(long *args, int argc) {
return (long)empty_str;
}
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -109,7 +91,6 @@ long native_upper(long *args, int argc) {
int len = strlen(str);
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -119,9 +100,6 @@ long native_upper(long *args, int argc) {
}
str_pool_idx += len + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
@@ -135,10 +113,7 @@ long native_lower(long *args, int argc) {
return (long)empty_str;
}
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -147,7 +122,6 @@ long native_lower(long *args, int argc) {
int len = strlen(str);
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -157,9 +131,6 @@ long native_lower(long *args, int argc) {
}
str_pool_idx += len + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
@@ -173,10 +144,7 @@ long native_strip(long *args, int argc) {
return (long)empty_str;
}
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -189,7 +157,6 @@ long native_strip(long *args, int argc) {
while (len > 0 && isspace(str[len - 1])) len--;
if (str_pool_idx + len + 1 >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -198,9 +165,6 @@ long native_strip(long *args, int argc) {
result[len] = 0;
str_pool_idx += len + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
@@ -216,10 +180,7 @@ long native_replace(long *args, int argc) {
return (long)empty_str;
}
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -233,14 +194,12 @@ long native_replace(long *args, int argc) {
if (old_len == 0) {
int str_len = strlen(str);
if (str_pool_idx + str_len + 1 >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
strncpy(result, str, str_len);
result[str_len] = '\0';
str_pool_idx += str_len + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
@@ -252,7 +211,6 @@ long native_replace(long *args, int argc) {
error("String pool overflow");
*dst = 0;
str_pool_idx += current_pos + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
strncpy(dst, new_str, new_len);
@@ -267,9 +225,6 @@ long native_replace(long *args, int argc) {
int total_len = dst - result;
str_pool_idx += total_len + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
-16
View File
@@ -1,11 +1,8 @@
#include <string.h>
#include <pthread.h>
#include "types.h"
#include "string_utils.h"
#include "interpreter.h"
extern pthread_mutex_t str_pool_mutex;
int is_string_ptr(long val) {
if (val < 0) {
return 0;
@@ -25,10 +22,7 @@ long concat_strings(long ptr1, long ptr2) {
return (long)empty_str;
}
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -39,7 +33,6 @@ long concat_strings(long ptr1, long ptr2) {
int len2 = strlen(s2);
if (str_pool_idx + len1 + len2 + 1 >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -51,8 +44,6 @@ long concat_strings(long ptr1, long ptr2) {
str_pool_idx += len1 + len2 + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
@@ -64,10 +55,7 @@ long slice_string(long str_ptr, int start, int end) {
return (long)empty_str;
}
pthread_mutex_lock(&str_pool_mutex);
if (str_pool_idx >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -85,7 +73,6 @@ long slice_string(long str_ptr, int start, int end) {
if (length < 0) length = 0;
if (str_pool_idx + length + 1 >= STR_POOL_SIZE) {
pthread_mutex_unlock(&str_pool_mutex);
error("String pool overflow");
return (long)empty_str;
}
@@ -96,8 +83,5 @@ long slice_string(long str_ptr, int start, int end) {
result[length] = 0;
str_pool_idx += length + 1;
pthread_mutex_unlock(&str_pool_mutex);
return (long)result;
}
+1 -7
View File
@@ -1,11 +1,9 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include "types.h"
#include "tokenizer.h"
#include "debug.h"
void tokenize_with_location(char *src, const char *filename) {
char *s = src;
@@ -32,12 +30,8 @@ void tokenize_with_location(char *src, const char *filename) {
}
if (tk_idx >= MAX_TOK - 1) {
DEBUG_LOG("FATAL: Token limit exceeded: tk_idx=%d (max=%d)", tk_idx, MAX_TOK);
pthread_rwlock_unlock(&tokens_rwlock);
fprintf(stderr, "Error: Token limit exceeded (max %d tokens)\n", MAX_TOK);
fprintf(stderr, "Consider increasing MULTIPLIER or reducing source size\n");
DEBUG_CLOSE();
exit(1);
return;
}
Token *t = &tokens[tk_idx++];
+1 -8
View File
@@ -188,16 +188,9 @@ typedef struct {
extern CallStack call_stack;
extern pthread_mutex_t token_mutex;
extern pthread_rwlock_t tokens_rwlock;
extern pthread_mutex_t str_pool_mutex;
extern pthread_mutex_t memory_mutex;
extern pthread_mutex_t locals_mutex;
extern pthread_mutex_t interpreter_state_mutex;
extern pthread_rwlock_t funcs_rwlock;
extern pthread_rwlock_t native_funcs_rwlock;
extern pthread_rwlock_t classes_rwlock;
extern pthread_mutex_t objects_mutex;
extern pthread_mutex_t call_stack_mutex;
ExecutionContext* context_create();
void context_destroy(ExecutionContext *ctx);
-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);