YREA-SLS/SLS_C/src/pico_main.c

206 lines
5.6 KiB
C

// Kyler Olsen
// YREA SLS
// Pico Main File
// December 2025
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/stdio_usb.h"
#include "hardware/uart.h"
#include "hardware/gpio.h"
#include "sls/meta.h"
#include "sls/bool.h"
#include "sls/string.h"
#include "sls/errors.h"
#include "sls/lexer.h"
#include "sls/interpreter.h"
// Pico onboard LED
#define LED_PIN 25
static const SlsStr PICO_REPL_NAME = SLS_STR_CONST("<PICO-REPL>");
void print_top_of_stack(InterpreterState *interpreter_state) {
if (interpreter_state->stack == NULL) {
printf("#0: <STACK IS EMPTY>\n");
return;
}
switch (interpreter_state->stack->type) {
case STACK_IDENTIFIER:
printf("#0: ::%s\n", interpreter_state->stack->identifier.name.str);
break;
case STACK_I64:
printf("#0: %ld:i64\n", interpreter_state->stack->i64);
break;
case STACK_I32:
printf("#0: %d\n", interpreter_state->stack->i32);
break;
case STACK_I16:
printf("#0: %d:i16\n", interpreter_state->stack->i16);
break;
case STACK_I8:
printf("#0: %d:i8\n", interpreter_state->stack->i8);
break;
case STACK_U64:
printf("#0: %lu:u64\n", interpreter_state->stack->u64);
break;
case STACK_U32:
printf("#0: %u:u32\n", interpreter_state->stack->u32);
break;
case STACK_U16:
printf("#0: %u:u16\n", interpreter_state->stack->u16);
break;
case STACK_U8:
printf("#0: %u:u8\n", interpreter_state->stack->u8);
break;
case STACK_FLOAT:
printf("#0: %f:f32\n", interpreter_state->stack->f32);
break;
case STACK_DOUBLE:
printf("#0: %f\n", interpreter_state->stack->f64);
break;
case STACK_CHARACTER:
printf("#0: %c\n", interpreter_state->stack->character);
break;
case STACK_BOOLEAN:
if (interpreter_state->stack->boolean) printf("#0: TRUE\n");
else printf("#0: FALSE\n");
break;
case STACK_TOKEN_STRING:
printf("#0: <TOKEN STRING>\n");
break;
case STACK_CALLABLE:
printf("#0: <CALLABLE>\n");
break;
}
}
void led_blink(int count) {
for (int i = 0; i < count; i++) {
gpio_put(LED_PIN, 1);
sleep_ms(100);
gpio_put(LED_PIN, 0);
sleep_ms(100);
}
}
int pico_repl() {
// Initialize LED
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
// Blink to show we're ready
led_blink(3);
// Wait for a key press to start the repl
while (true) {
int c = getchar_timeout_us(100000);
if (c == PICO_ERROR_TIMEOUT) {
continue;
} else if (c == '\r' || c == '\n' || c == 8 || (c >= 32 && c < 128)) {
printf("\n");
break;
}
}
led_blink(1);
print_version();
printf("===== YREA SLS PICO REPL =====\n");
printf("Type `#exit` to exit.\n");
fflush(stdout);
LexerInfo lexer_info;
InterpreterState *interpreter_state = interpreter_create();
if (interpreter_state == NULL) {
printf("ERROR: Failed to create interpreter!\n");
return 1;
}
char buf[256];
int buf_pos = 0;
while (true) {
// Read character by character for better embedded behavior
int c = getchar_timeout_us(100000); // 100ms timeout
if (c == PICO_ERROR_TIMEOUT) {
continue;
}
if (c == '\r' || c == '\n') {
if (buf_pos == 0) continue; // Empty line
buf[buf_pos] = '\0';
printf("\n"); // Echo newline
if (strncmp(buf, "#exit", 5) == 0) {
printf("Exiting REPL...\n");
interpreter_delete(interpreter_state);
led_blink(2);
return 0;
}
SlsStr code = sls_str_malloc(buf, buf_pos);
init_lexer(&lexer_info, PICO_REPL_NAME, code);
LexerResult result = lexical_analysis(&lexer_info);
if (result.type == SLS_ERROR) {
printf("%s\n", result.error.message.str);
sls_str_free(&result.error.message);
} else {
LexerTokenResult *head = result.result;
while (head) {
if (head->type == SLS_ERROR) {
printf("%s\n", head->error.message.str);
break;
} else if (!execute(interpreter_state, head)) {
printf("A runtime error occurred!\n");
break;
}
head = head->next;
}
clean_token_result(result.result);
print_top_of_stack(interpreter_state);
}
sls_str_free(&code);
buf_pos = 0;
} else if (c == 127 || c == 8) {
// Backspace or DEL
if (buf_pos > 0) {
buf_pos--;
printf("\b \b"); // Erase character from terminal
fflush(stdout);
}
} else if (c >= 32 && c < 127 && buf_pos < 255) {
// Printable character
buf[buf_pos++] = (char)c;
putchar(c); // Echo character
fflush(stdout);
}
}
interpreter_delete(interpreter_state);
return 1;
}
int main() {
// Initialize USB/UART stdio
stdio_init_all();
// Wait a bit for USB to enumerate
sleep_ms(5000);
printf("\n\n=============================\n");
printf("YREA SLS on Raspberry Pi Pico\n");
printf("=============================\n\n");
printf("Press any key to begin...\n");
return pico_repl();
}