Started Implementing a BASIC interpriter
This commit is contained in:
parent
e82fb49c04
commit
3eee0f8269
22
.vscode/c_cpp_properties.json
vendored
Normal file
22
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Win32",
|
||||||
|
"includePath": [
|
||||||
|
"${default}",
|
||||||
|
"${workspaceFolder}/**"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"_DEBUG",
|
||||||
|
"UNICODE",
|
||||||
|
"_UNICODE"
|
||||||
|
],
|
||||||
|
"windowsSdkVersion": "10.0.22621.0",
|
||||||
|
"compilerPath": "C:/msys64/mingw64/bin/gcc.exe",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
BIN
EYOSx86-main/dist/x86_64/kernel.bin
vendored
BIN
EYOSx86-main/dist/x86_64/kernel.bin
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/x86_64/basic.o
Normal file
BIN
build/x86_64/basic.o
Normal file
Binary file not shown.
Binary file not shown.
BIN
build/x86_64/strings.o
Normal file
BIN
build/x86_64/strings.o
Normal file
Binary file not shown.
Binary file not shown.
BIN
dist/x86_64/kernel.bin
vendored
Normal file
BIN
dist/x86_64/kernel.bin
vendored
Normal file
Binary file not shown.
Binary file not shown.
@ -10,11 +10,9 @@
|
|||||||
#include "window.h"
|
#include "window.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "fat12.h"
|
#include "fat12.h"
|
||||||
|
#include "basic.h"
|
||||||
|
|
||||||
|
#define COMMAND_BUFFER_SIZE 256 // Increase buffer size to handle longer commands
|
||||||
|
|
||||||
|
|
||||||
#define COMMAND_BUFFER_SIZE 256 // Increase buffer size to handle longer commands
|
|
||||||
#define BACKSPACE_KEY 8
|
#define BACKSPACE_KEY 8
|
||||||
#define HISTORY_SIZE 10
|
#define HISTORY_SIZE 10
|
||||||
#define COMMAND_BUFFER_SIZE 256
|
#define COMMAND_BUFFER_SIZE 256
|
||||||
@ -22,29 +20,31 @@
|
|||||||
|
|
||||||
extern void kpanic(int error_code);
|
extern void kpanic(int error_code);
|
||||||
|
|
||||||
|
void shutdown_system()
|
||||||
void shutdown_system() {
|
{
|
||||||
__asm__ (
|
__asm__(
|
||||||
"movl $1, %eax\n" // syscall number for sys_reboot (1 in this case)
|
"movl $1, %eax\n" // syscall number for sys_reboot (1 in this case)
|
||||||
"movl $0, %ebx\n" // reboot flags
|
"movl $0, %ebx\n" // reboot flags
|
||||||
"movl $0, %ecx\n" // no additional arguments
|
"movl $0, %ecx\n" // no additional arguments
|
||||||
"movl $0, %edx\n" // no additional arguments
|
"movl $0, %edx\n" // no additional arguments
|
||||||
"int $0x80\n" // interrupt to invoke syscall
|
"int $0x80\n" // interrupt to invoke syscall
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
char commandHistory[HISTORY_SIZE][COMMAND_BUFFER_SIZE];
|
char commandHistory[HISTORY_SIZE][COMMAND_BUFFER_SIZE];
|
||||||
int currentHistoryIndex = 0;
|
int currentHistoryIndex = 0;
|
||||||
int historyCount = 0;
|
int historyCount = 0;
|
||||||
|
|
||||||
void add_to_history(const char* command) {
|
void add_to_history(const char *command)
|
||||||
if (historyCount < HISTORY_SIZE) {
|
{
|
||||||
|
if (historyCount < HISTORY_SIZE)
|
||||||
|
{
|
||||||
historyCount++;
|
historyCount++;
|
||||||
} else {
|
}
|
||||||
for (int i = 1; i < HISTORY_SIZE; i++) {
|
else
|
||||||
|
{
|
||||||
|
for (int i = 1; i < HISTORY_SIZE; i++)
|
||||||
|
{
|
||||||
strcpy(commandHistory[i - 1], commandHistory[i]);
|
strcpy(commandHistory[i - 1], commandHistory[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,23 +52,26 @@ void add_to_history(const char* command) {
|
|||||||
currentHistoryIndex = historyCount;
|
currentHistoryIndex = historyCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* get_previous_command() {
|
const char *get_previous_command()
|
||||||
if (currentHistoryIndex > 0) {
|
{
|
||||||
|
if (currentHistoryIndex > 0)
|
||||||
|
{
|
||||||
currentHistoryIndex--;
|
currentHistoryIndex--;
|
||||||
return commandHistory[currentHistoryIndex];
|
return commandHistory[currentHistoryIndex];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* get_next_command() {
|
const char *get_next_command()
|
||||||
if (currentHistoryIndex < historyCount - 1) {
|
{
|
||||||
|
if (currentHistoryIndex < historyCount - 1)
|
||||||
|
{
|
||||||
currentHistoryIndex++;
|
currentHistoryIndex++;
|
||||||
return commandHistory[currentHistoryIndex];
|
return commandHistory[currentHistoryIndex];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const void clear()
|
const void clear()
|
||||||
{
|
{
|
||||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
|
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
|
||||||
@ -79,34 +82,42 @@ const void clear()
|
|||||||
print_setup_prompt();
|
print_setup_prompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void halt()
|
||||||
|
{
|
||||||
|
|
||||||
void halt(){
|
|
||||||
print_str("[ WARN ] HALT\n");
|
print_str("[ WARN ] HALT\n");
|
||||||
while (1) {}
|
while (1)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void commandHandler(char* command) {
|
void commandHandler(char *command)
|
||||||
|
{
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if (strcmp(command, "cls") == 0) {
|
if (strcmp(command, "cls") == 0)
|
||||||
|
{
|
||||||
clear();
|
clear();
|
||||||
} else if (strcmp(command, "knp") == 0) {
|
}
|
||||||
|
else if (strcmp(command, "knp") == 0)
|
||||||
|
{
|
||||||
kpanic(1);
|
kpanic(1);
|
||||||
} else if (int_strncmp(command, "echo ", 5) == 0) {
|
}
|
||||||
char* message = command + 5; // Skip the "echo " part
|
else if (int_strncmp(command, "echo ", 5) == 0)
|
||||||
|
{
|
||||||
|
char *message = command + 5; // Skip the "echo " part
|
||||||
print_str("\n");
|
print_str("\n");
|
||||||
print_str(message);
|
print_str(message);
|
||||||
print_str("\n");
|
print_str("\n");
|
||||||
} else if (int_strncmp(command, "cwin", 4) == 0) {
|
}
|
||||||
|
else if (int_strncmp(command, "cwin", 4) == 0)
|
||||||
|
{
|
||||||
// Define window properties
|
// Define window properties
|
||||||
Window myWindow;
|
Window myWindow;
|
||||||
int x = 8; // X position of the window
|
int x = 8; // X position of the window
|
||||||
int y = 4; // Y position of the window
|
int y = 4; // Y position of the window
|
||||||
int width = 30; // Width of the window
|
int width = 30; // Width of the window
|
||||||
int height = 10; // Height of the window
|
int height = 10; // Height of the window
|
||||||
uint8_t borderColor = PRINT_COLOR_RED; // Border color
|
uint8_t borderColor = PRINT_COLOR_RED; // Border color
|
||||||
uint8_t backgroundColor = PRINT_COLOR_BLUE; // Background color
|
uint8_t backgroundColor = PRINT_COLOR_BLUE; // Background color
|
||||||
|
|
||||||
// Create and display the window
|
// Create and display the window
|
||||||
@ -116,76 +127,82 @@ void commandHandler(char* command) {
|
|||||||
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLUE); // Set text color
|
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLUE); // Set text color
|
||||||
print_text_in_window(&myWindow, 2, 2, "Window Manager is a ");
|
print_text_in_window(&myWindow, 2, 2, "Window Manager is a ");
|
||||||
print_text_in_window(&myWindow, 2, 3, "Work in progress, Sorry :("); // Print text inside the window
|
print_text_in_window(&myWindow, 2, 3, "Work in progress, Sorry :("); // Print text inside the window
|
||||||
print_text_in_window(&myWindow, 2, 4, "do [ cls ] to clear"); // Print text inside the window
|
print_text_in_window(&myWindow, 2, 4, "do [ cls ] to clear"); // Print text inside the window
|
||||||
|
}
|
||||||
|
else if (int_strncmp(command, "exit", 4) == 0)
|
||||||
|
{
|
||||||
} else if (int_strncmp(command, "exit", 4) == 0) {
|
|
||||||
printf("Driver Call [ shutdown_system(); ] \n");
|
printf("Driver Call [ shutdown_system(); ] \n");
|
||||||
shutdown_system();
|
shutdown_system();
|
||||||
|
}
|
||||||
|
else if (int_strncmp(command, "panic_test", 10) == 0)
|
||||||
} else if (int_strncmp(command, "panic_test", 10) == 0) {
|
{
|
||||||
int _y = 1/0;
|
int _y = 1 / 0;
|
||||||
printf("Output %d\n", _y);
|
printf("Output %d\n", _y);
|
||||||
|
}
|
||||||
} else if (int_strncmp(command, "test", 4) == 0) {
|
else if (int_strncmp(command, "test", 4) == 0)
|
||||||
|
{
|
||||||
|
|
||||||
//// Test custom malloc and free
|
//// Test custom malloc and free
|
||||||
//void* block1 = malloc(32);
|
// void* block1 = malloc(32);
|
||||||
//void* block2 = malloc(64);
|
// void* block2 = malloc(64);
|
||||||
//void* block3 = malloc(128);
|
// void* block3 = malloc(128);
|
||||||
//
|
//
|
||||||
//// List used blocks
|
//// List used blocks
|
||||||
//list_used_blocks();
|
// list_used_blocks();
|
||||||
//
|
//
|
||||||
//// Free a block and check again
|
//// Free a block and check again
|
||||||
//free(block2);
|
// free(block2);
|
||||||
//printf("\nAfter freeing block2:\n");
|
// printf("\nAfter freeing block2:\n");
|
||||||
//list_used_blocks();
|
// list_used_blocks();
|
||||||
//
|
//
|
||||||
//void* block4 = malloc(64);
|
// void* block4 = malloc(64);
|
||||||
//
|
//
|
||||||
//list_used_blocks();
|
// list_used_blocks();
|
||||||
|
|
||||||
|
|
||||||
create_game();
|
create_game();
|
||||||
|
}
|
||||||
} else if (int_strncmp(command, "split", 5) == 0) {
|
else if (int_strncmp(command, "split", 5) == 0)
|
||||||
|
{
|
||||||
printf("Kernel Call [ split_string(); ]\n");
|
printf("Kernel Call [ split_string(); ]\n");
|
||||||
|
|
||||||
// Check the length of the command string and use it properly
|
// Check the length of the command string and use it properly
|
||||||
char** new_command = split_string(command, ",", strlen(command));
|
char **new_command = split_string(command, ",", strlen(command));
|
||||||
|
|
||||||
//char** new_command = {{NULL, NULL, NULL, NULL}};
|
// char** new_command = {{NULL, NULL, NULL, NULL}};
|
||||||
|
|
||||||
if (new_command) {
|
if (new_command)
|
||||||
|
{
|
||||||
// Add a loop to print all the elements in the new_command array for debugging
|
// Add a loop to print all the elements in the new_command array for debugging
|
||||||
for (int i = 0; new_command[i] != NULL; i++) {
|
for (int i = 0; new_command[i] != NULL; i++)
|
||||||
|
{
|
||||||
printf("new_command[%d]: %s\n", i, new_command[i]);
|
printf("new_command[%d]: %s\n", i, new_command[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//halt(); // Debug halt
|
// halt(); // Debug halt
|
||||||
|
|
||||||
// Ensure that new_command[1] exists before accessing it
|
// Ensure that new_command[1] exists before accessing it
|
||||||
if (new_command[1] != NULL) {
|
if (new_command[1] != NULL)
|
||||||
|
{
|
||||||
printf("%s\n", new_command[1]);
|
printf("%s\n", new_command[1]);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
printf("Error: new_command[1] is NULL\n");
|
printf("Error: new_command[1] is NULL\n");
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
printf("Error: split_string returned NULL\n");
|
else
|
||||||
|
{
|
||||||
|
printf("Error: split_string returned NULL\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
} else {
|
|
||||||
printf("Unknown command: %s\n", command);
|
printf("Unknown command: %s\n", command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_setup_prompt()
|
||||||
|
{
|
||||||
void print_setup_prompt() {
|
|
||||||
move_cursor(0, 0);
|
move_cursor(0, 0);
|
||||||
print_set_color(PRINT_COLOR_LIGHT_RED, PRINT_COLOR_BLACK);
|
print_set_color(PRINT_COLOR_LIGHT_RED, PRINT_COLOR_BLACK);
|
||||||
print_str("-------------------- ");
|
print_str("-------------------- ");
|
||||||
@ -197,86 +214,118 @@ void print_setup_prompt() {
|
|||||||
print_str("V 1.5.01\n");
|
print_str("V 1.5.01\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int test_basic()
|
||||||
|
{
|
||||||
|
InterpreterState state;
|
||||||
|
init_state(&state);
|
||||||
|
|
||||||
|
const char *program[] = {
|
||||||
|
"LET A = 10",
|
||||||
|
"LET B = 20",
|
||||||
|
"PRINT A + B",
|
||||||
|
"LET A = \"Hello\"",
|
||||||
|
"LET B = \" World\"",
|
||||||
|
"PRINT A + B",
|
||||||
|
"END",
|
||||||
|
|
||||||
void kernel_main() {
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(program) / sizeof(program[0]); i++)
|
||||||
|
{
|
||||||
|
execute_line(&state, program[i]);
|
||||||
|
if (!state.running)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_main()
|
||||||
|
{
|
||||||
|
|
||||||
init_keyboard_driver();
|
init_keyboard_driver();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
idt_install();
|
idt_install();
|
||||||
|
|
||||||
|
|
||||||
print_str("[ WARN ] Skipping File System Initialization...\n[ INFO ] Do [ fsinit ] to initalize the filesystem\n");
|
print_str("[ WARN ] Skipping File System Initialization...\n[ INFO ] Do [ fsinit ] to initalize the filesystem\n");
|
||||||
|
|
||||||
if (fat12_init() == 0) {
|
if (fat12_init() == 0)
|
||||||
|
{
|
||||||
printf("Filesystem mounted\n");
|
printf("Filesystem mounted\n");
|
||||||
|
|
||||||
fat12_read_root_directory();
|
fat12_read_root_directory();
|
||||||
|
|
||||||
fat12_dir_entry_t entry;
|
fat12_dir_entry_t entry;
|
||||||
if (fat12_find_file("HELLOTXT", &entry)) {
|
if (fat12_find_file("HELLOTXT", &entry))
|
||||||
|
{
|
||||||
printf("File found: HELLO.TXT\n");
|
printf("File found: HELLO.TXT\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
clear();
|
||||||
|
|
||||||
|
test_basic();
|
||||||
|
|
||||||
print_setup_prompt();
|
print_setup_prompt();
|
||||||
|
|
||||||
|
|
||||||
print_str(" > ");
|
print_str(" > ");
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
char key;
|
char key;
|
||||||
bool keydown = false;
|
bool keydown = false;
|
||||||
char commandBuffer[COMMAND_BUFFER_SIZE];
|
char commandBuffer[COMMAND_BUFFER_SIZE];
|
||||||
size_t commandLength = 0; // To track the length of the current command
|
size_t commandLength = 0; // To track the length of the current command
|
||||||
|
|
||||||
|
while (1)
|
||||||
while (1) {
|
{
|
||||||
key = read_key();
|
key = read_key();
|
||||||
|
|
||||||
if (key != 0) {
|
if (key != 0)
|
||||||
if (!keydown) {
|
{
|
||||||
|
if (!keydown)
|
||||||
|
{
|
||||||
CursorPosition pos = get_print_cursor_pos();
|
CursorPosition pos = get_print_cursor_pos();
|
||||||
move_cursor(pos.x,pos.y);
|
move_cursor(pos.x, pos.y);
|
||||||
if (key == 10) { // Enter key
|
if (key == 10)
|
||||||
commandBuffer[commandLength] = '\0'; // Null-terminate the command
|
{ // Enter key
|
||||||
|
commandBuffer[commandLength] = '\0'; // Null-terminate the command
|
||||||
commandHandler(commandBuffer);
|
commandHandler(commandBuffer);
|
||||||
|
|
||||||
// Reset command buffer for the next input
|
// Reset command buffer for the next input
|
||||||
commandLength = 0;
|
commandLength = 0;
|
||||||
print_str(" > ");
|
print_str(" > ");
|
||||||
|
}
|
||||||
} else if (key == BACKSPACE_KEY) { // Backspace key
|
else if (key == BACKSPACE_KEY)
|
||||||
if (commandLength > 0) {
|
{ // Backspace key
|
||||||
|
if (commandLength > 0)
|
||||||
|
{
|
||||||
// Remove the last character from the buffer
|
// Remove the last character from the buffer
|
||||||
commandLength--;
|
commandLength--;
|
||||||
commandBuffer[commandLength] = '0'; // Null-terminate after removal
|
commandBuffer[commandLength] = '0'; // Null-terminate after removal
|
||||||
|
|
||||||
// Clear the character from the screen (overwrite with space)
|
// Clear the character from the screen (overwrite with space)
|
||||||
// Move cursor back one position
|
// Move cursor back one position
|
||||||
offset_print_cursor(-1,0);
|
offset_print_cursor(-1, 0);
|
||||||
print_char(' '); // Overwrite the character
|
print_char(' '); // Overwrite the character
|
||||||
offset_print_cursor(-1,0); // Move cursor back one position(because its moved left one by the rpintf)
|
offset_print_cursor(-1, 0); // Move cursor back one position(because its moved left one by the rpintf)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
if (key >= 32 && key <= 126) { // Check if the key is a printable character
|
{
|
||||||
if (commandLength < COMMAND_BUFFER_SIZE - 1) {
|
if (key >= 32 && key <= 126)
|
||||||
commandBuffer[commandLength++] = key; // Append character to buffer
|
{ // Check if the key is a printable character
|
||||||
|
if (commandLength < COMMAND_BUFFER_SIZE - 1)
|
||||||
|
{
|
||||||
|
commandBuffer[commandLength++] = key; // Append character to buffer
|
||||||
commandBuffer[commandLength] = '\0'; // Null-terminate the buffer
|
commandBuffer[commandLength] = '\0'; // Null-terminate the buffer
|
||||||
print_char(key); // Print key to the screen
|
print_char(key); // Print key to the screen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keydown = true;
|
keydown = true;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
keydown = false;
|
keydown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,5 +333,4 @@ void kernel_main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kpanic(2);
|
kpanic(2);
|
||||||
|
|
||||||
}
|
}
|
184
src/impl/x86_64/basic.c
Normal file
184
src/impl/x86_64/basic.c
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
#include "memory.h"
|
||||||
|
#include "print.h"
|
||||||
|
#include "strings.h"
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "stddef.h"
|
||||||
|
#include "basic.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Utility: Find or create a variable by name
|
||||||
|
Variable* get_variable(InterpreterState* state, const char* name) {
|
||||||
|
for (size_t i = 0; i < state->variable_count; i++) {
|
||||||
|
if (strcmp(state->variables[i].name, name) == 0) {
|
||||||
|
return &state->variables[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state->variable_count < MAX_VARIABLES) {
|
||||||
|
Variable* var = &state->variables[state->variable_count++];
|
||||||
|
strncpy(var->name, name, sizeof(var->name) - 1);
|
||||||
|
var->name[sizeof(var->name) - 1] = '\0';
|
||||||
|
var->value = 0;
|
||||||
|
var->str_value = NULL;
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
return NULL; // No space for more variables
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse an integer from a string, skipping leading whitespace
|
||||||
|
int parse_int(const char* str) {
|
||||||
|
while (*str == ' ') str++; // Skip leading spaces
|
||||||
|
int result = 0;
|
||||||
|
int sign = 1;
|
||||||
|
if (*str == '-') {
|
||||||
|
sign = -1;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
while (*str >= '0' && *str <= '9') {
|
||||||
|
result = result * 10 + (*str - '0');
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return result * sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* evaluate_expression(InterpreterState* state, const char* expr) {
|
||||||
|
char buffer[64];
|
||||||
|
strncpy(buffer, expr, sizeof(buffer) - 1);
|
||||||
|
buffer[sizeof(buffer) - 1] = '\0';
|
||||||
|
|
||||||
|
char* plus = strrchr(buffer, '+');
|
||||||
|
if (plus) {
|
||||||
|
*plus = '\0';
|
||||||
|
|
||||||
|
// Evaluate the left and right sides only once
|
||||||
|
const char* left = evaluate_expression(state, buffer);
|
||||||
|
const char* right = evaluate_expression(state, plus + 1);
|
||||||
|
|
||||||
|
// Debug output
|
||||||
|
printf("DEBUG: Left operand: %s\n", left);
|
||||||
|
printf("DEBUG: Right operand: %s\n", right);
|
||||||
|
|
||||||
|
// Check if both sides are numeric
|
||||||
|
int left_is_number = (left[0] >= '0' && left[0] <= '9') || (left[0] == '-' && left[1] >= '0' && left[1] <= '9');
|
||||||
|
int right_is_number = (right[0] >= '0' && right[0] <= '9') || (right[0] == '-' && right[1] >= '0' && right[1] <= '9');
|
||||||
|
|
||||||
|
static char result[128];
|
||||||
|
|
||||||
|
if (left_is_number && right_is_number) {
|
||||||
|
// Parse the left and right operands
|
||||||
|
int left_value = parse_int(left);
|
||||||
|
int right_value = parse_int(right);
|
||||||
|
|
||||||
|
// Correct addition logic
|
||||||
|
int sum = left_value + right_value;
|
||||||
|
|
||||||
|
// Debug addition
|
||||||
|
printf("DEBUG: Adding %d + %d = %d\n", left_value, right_value, sum);
|
||||||
|
|
||||||
|
// Format the result as a string
|
||||||
|
snprintf(result, sizeof(result), "%d", sum);
|
||||||
|
} else {
|
||||||
|
// Concatenate strings
|
||||||
|
snprintf(result, sizeof(result), "%s%s", left, right);
|
||||||
|
|
||||||
|
// Debug string concatenation
|
||||||
|
printf("DEBUG: Concatenating strings: %s + %s = %s\n", left, right, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim leading and trailing spaces
|
||||||
|
const char* start = buffer;
|
||||||
|
while (*start == ' ') start++;
|
||||||
|
|
||||||
|
char* end = buffer + strlen(buffer) - 1;
|
||||||
|
while (end > start && *end == ' ') *end-- = '\0';
|
||||||
|
|
||||||
|
if (start[0] >= 'A' && start[0] <= 'Z') {
|
||||||
|
Variable* var = get_variable(state, start);
|
||||||
|
if (var) {
|
||||||
|
static char var_result[64];
|
||||||
|
if (var->str_value) {
|
||||||
|
strncpy(var_result, var->str_value, sizeof(var_result) - 1);
|
||||||
|
var_result[sizeof(var_result) - 1] = '\0';
|
||||||
|
return var_result;
|
||||||
|
} else {
|
||||||
|
snprintf(var_result, sizeof(var_result), "%d", var->value);
|
||||||
|
return var_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start[0] == '"') {
|
||||||
|
// String literal
|
||||||
|
size_t len = strlen(start);
|
||||||
|
if (start[len - 1] == '"') {
|
||||||
|
static char str_result[64];
|
||||||
|
strncpy(str_result, start + 1, len - 2);
|
||||||
|
str_result[len - 2] = '\0';
|
||||||
|
return str_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char int_result[16];
|
||||||
|
snprintf(int_result, sizeof(int_result), "%d", parse_int(start));
|
||||||
|
return int_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Interpret a single line of code
|
||||||
|
void interpret_line(InterpreterState* state, const char* line) {
|
||||||
|
if (strncmp(line, "LET", 3) == 0) {
|
||||||
|
const char* rest = line + 3;
|
||||||
|
while (*rest == ' ') rest++;
|
||||||
|
const char* equals = strchr(rest, '=');
|
||||||
|
if (!equals) return;
|
||||||
|
|
||||||
|
char var_name[16];
|
||||||
|
strncpy(var_name, rest, equals - rest);
|
||||||
|
var_name[equals - rest] = '\0';
|
||||||
|
|
||||||
|
// Trim trailing spaces from var_name
|
||||||
|
size_t len = strlen(var_name);
|
||||||
|
while (len > 0 && var_name[len - 1] == ' ') {
|
||||||
|
var_name[--len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable* var = get_variable(state, var_name);
|
||||||
|
if (var) {
|
||||||
|
const char* value = evaluate_expression(state, equals + 1);
|
||||||
|
if (value[0] >= '0' && value[0] <= '9') {
|
||||||
|
var->value = parse_int(value);
|
||||||
|
var->str_value = NULL;
|
||||||
|
} else {
|
||||||
|
var->str_value = malloc(strlen(value) + 1);
|
||||||
|
strcpy(var->str_value, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (strncmp(line, "PRINT", 5) == 0) {
|
||||||
|
const char* rest = line + 5;
|
||||||
|
while (*rest == ' ') rest++;
|
||||||
|
const char* value = evaluate_expression(state, rest);
|
||||||
|
printf("%s\n", value);
|
||||||
|
} else if (strncmp(line, "END", 3) == 0) {
|
||||||
|
printf("Program terminated.\n");
|
||||||
|
state->running = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize interpreter state
|
||||||
|
void init_state(InterpreterState* state) {
|
||||||
|
state->variable_count = 0;
|
||||||
|
state->running = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute a single line in the context of a state
|
||||||
|
void execute_line(InterpreterState* state, const char* line) {
|
||||||
|
printf("Executing line: %s\n", line); // Debugging
|
||||||
|
interpret_line(state, line);
|
||||||
|
}
|
||||||
|
|
@ -334,6 +334,48 @@ int my_sscanf(const char *input, const char *format, char *output) {
|
|||||||
return match_count;
|
return match_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf(char* buffer, size_t size, const char* format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
const char* traverse = format;
|
||||||
|
size_t written = 0;
|
||||||
|
|
||||||
|
while (*traverse && written < size - 1) {
|
||||||
|
if (*traverse == '%' && *(traverse + 1)) {
|
||||||
|
traverse++;
|
||||||
|
if (*traverse == 's') {
|
||||||
|
const char* str = va_arg(args, const char*);
|
||||||
|
while (*str && written < size - 1) {
|
||||||
|
buffer[written++] = *str++;
|
||||||
|
}
|
||||||
|
} else if (*traverse == 'd') {
|
||||||
|
int num = va_arg(args, int);
|
||||||
|
char num_buffer[16];
|
||||||
|
int num_len = 0;
|
||||||
|
if (num < 0) {
|
||||||
|
if (written < size - 1) buffer[written++] = '-';
|
||||||
|
num = -num;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
num_buffer[num_len++] = '0' + (num % 10);
|
||||||
|
num /= 10;
|
||||||
|
} while (num > 0);
|
||||||
|
while (num_len > 0 && written < size - 1) {
|
||||||
|
buffer[written++] = num_buffer[--num_len];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer[written++] = *traverse;
|
||||||
|
}
|
||||||
|
traverse++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[written] = '\0';
|
||||||
|
va_end(args);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void printf(const char* format, ...) {
|
void printf(const char* format, ...) {
|
||||||
va_list args;
|
va_list args;
|
@ -90,3 +90,13 @@ int strncmp(const char *s1, const char *s2, size_t n) {
|
|||||||
return (*(unsigned char *)s1 - *(unsigned char *)s2);
|
return (*(unsigned char *)s1 - *(unsigned char *)s2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* strchr(const char* str, int ch) {
|
||||||
|
while (*str) {
|
||||||
|
if (*str == (char)ch) {
|
||||||
|
return (char*)str;
|
||||||
|
}
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
32
src/intf/basic.h
Normal file
32
src/intf/basic.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef BASIC_INTERPRETER_H
|
||||||
|
#define BASIC_INTERPRETER_H
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
#include "stddef.h"
|
||||||
|
|
||||||
|
#define MAX_LINE_LENGTH 128
|
||||||
|
#define MAX_VARIABLES 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char name[16];
|
||||||
|
int value;
|
||||||
|
char* str_value;
|
||||||
|
} Variable;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Variable variables[MAX_VARIABLES];
|
||||||
|
size_t variable_count;
|
||||||
|
int running;
|
||||||
|
} InterpreterState;
|
||||||
|
|
||||||
|
// Initialize the interpreter state
|
||||||
|
void init_state(InterpreterState* state);
|
||||||
|
|
||||||
|
// Execute a single line of code in the context of a state
|
||||||
|
void execute_line(InterpreterState* state, const char* line);
|
||||||
|
|
||||||
|
// Utility to evaluate an expression (exposed for potential reuse)
|
||||||
|
const char* evaluate_expression(InterpreterState* state, const char* expr);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BASIC_INTERPRETER_H
|
@ -29,6 +29,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void sscanf(const char *str, const char *format, char *filename, char *content);
|
void sscanf(const char *str, const char *format, char *filename, char *content);
|
||||||
|
snprintf(char* buffer, size_t size, const char* format, ...);
|
||||||
int my_sscanf(const char *input, const char *format, char *output);
|
int my_sscanf(const char *input, const char *format, char *output);
|
||||||
void print_clear();
|
void print_clear();
|
||||||
void print_char(char character);
|
void print_char(char character);
|
@ -5,8 +5,9 @@
|
|||||||
int strcmp(const char *str1, const char *str2);
|
int strcmp(const char *str1, const char *str2);
|
||||||
size_t strlen(const char *str);
|
size_t strlen(const char *str);
|
||||||
char *strncpy(char *dest, const char *src, size_t n);
|
char *strncpy(char *dest, const char *src, size_t n);
|
||||||
int int_strncmp(const char* s1, const char* s2, size_t n);
|
int int_strncmp(const char *s1, const char *s2, size_t n);
|
||||||
void strcpy(char *dest, const char *src);
|
void strcpy(char *dest, const char *src);
|
||||||
char* strrchr(const char* str, char ch);
|
char *strrchr(const char *str, char ch);
|
||||||
|
|
||||||
int strncmp(const char *s1, const char *s2, size_t n);
|
int strncmp(const char *s1, const char *s2, size_t n);
|
||||||
|
char *strchr(const char *str, int ch);
|
BIN
targets/x86_64/iso/boot/kernel.bin
Normal file
BIN
targets/x86_64/iso/boot/kernel.bin
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user