From dccb717812cbc00a5422a8d03b8c60c529625ade Mon Sep 17 00:00:00 2001 From: OusmBlueNinja <89956790+OusmBlueNinja@users.noreply.github.com> Date: Fri, 11 Apr 2025 11:46:02 -0500 Subject: [PATCH] simple poc --- Makefile | 15 ++++ main.lua | 7 ++ src/main.cpp | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 Makefile create mode 100644 main.lua create mode 100644 src/main.cpp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6cd0481 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +CXX := g++ +CXXFLAGS := -std=c++17 -Wall -Wextra -O2 + +SRCS := $(wildcard src/*.cpp) +BIN := minilua + +all: $(BIN) + +$(BIN): $(SRCS) + $(CXX) $(CXXFLAGS) $^ -o $@ + +clean: + rm -f $(BIN) + +.PHONY: all clean diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..ebdda53 --- /dev/null +++ b/main.lua @@ -0,0 +1,7 @@ +local x = 10 + +function main() + print("Hello: " .. x + 12) +end + +main() \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..dd65b97 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,221 @@ +#include +#include +#include +#include + +#define MAX_TOKENS 1024 +#define MAX_SOURCE 65536 +#define MAX_STACK 256 +#define MAX_VARS 256 + +typedef enum { + T_EOF, T_NUMBER, T_STRING, T_IDENT, + T_PLUS, T_MINUS, T_MUL, T_DIV, T_EQ, + T_LPAREN, T_RPAREN, T_LBRACE, T_RBRACE, + T_IF, T_WHILE, T_FUNCTION, T_RETURN, + T_SEMI, T_COMMA, T_ASSIGN, T_PRINT +} TokenType; + +typedef struct { + TokenType type; + char text[64]; +} Token; + +char* source; +Token tokens[MAX_TOKENS]; +int tok_index = 0, tok_count = 0; + +void error(const char* msg) { + fprintf(stderr, "Error: %s\n", msg); + exit(1); +} + +void next_token() { if (tok_index < tok_count) tok_index++; } +Token* current_token() { return &tokens[tok_index]; } + +void tokenize() { + char* s = source; + while (*s) { + while (isspace(*s)) s++; + if (!*s) break; + + if (isdigit(*s)) { + Token t = {}; + t.type = T_NUMBER; + int len = 0; + while (isdigit(*s)) t.text[len++] = *s++; + t.text[len] = '\0'; + tokens[tok_count++] = t; + continue; + } + + if (isalpha(*s) || *s == '_') { + Token t = {}; + t.type = T_IDENT; + int len = 0; + while (isalnum(*s) || *s == '_') t.text[len++] = *s++; + t.text[len] = '\0'; + + if (strcmp(t.text, "if") == 0) t.type = T_IF; + else if (strcmp(t.text, "while") == 0) t.type = T_WHILE; + else if (strcmp(t.text, "function") == 0) t.type = T_FUNCTION; + else if (strcmp(t.text, "return") == 0) t.type = T_RETURN; + else if (strcmp(t.text, "print") == 0) t.type = T_PRINT; + + tokens[tok_count++] = t; + continue; + } + + if (*s == '"') { + Token t = {}; + t.type = T_STRING; + s++; + int len = 0; + while (*s && *s != '"') t.text[len++] = *s++; + if (*s == '"') s++; + t.text[len] = '\0'; + tokens[tok_count++] = t; + continue; + } + + switch (*s) { + case '+': tokens[tok_count++] = Token{ T_PLUS, "+" }; s++; break; + case '-': tokens[tok_count++] = Token{ T_MINUS, "-" }; s++; break; + case '*': tokens[tok_count++] = Token{ T_MUL, "*" }; s++; break; + case '/': tokens[tok_count++] = Token{ T_DIV, "/" }; s++; break; + case '=': tokens[tok_count++] = Token{ T_ASSIGN, "=" }; s++; break; + case ';': tokens[tok_count++] = Token{ T_SEMI, ";" }; s++; break; + case ',': tokens[tok_count++] = Token{ T_COMMA, "," }; s++; break; + case '(': tokens[tok_count++] = Token{ T_LPAREN, "(" }; s++; break; + case ')': tokens[tok_count++] = Token{ T_RPAREN, ")" }; s++; break; + case '{': tokens[tok_count++] = Token{ T_LBRACE, "{" }; s++; break; + case '}': tokens[tok_count++] = Token{ T_RBRACE, "}" }; s++; break; + default: error("Unknown character"); + } + } + + Token eof = {}; + eof.type = T_EOF; + tokens[tok_count++] = eof; +} + +typedef struct { + char name[32]; + int value; +} Variable; + +Variable vars[MAX_VARS]; +int var_count = 0; + +int get_var(const char* name) { + for (int i = 0; i < var_count; i++) { + if (strcmp(vars[i].name, name) == 0) + return vars[i].value; + } + error("Undefined variable"); + return 0; +} + +void set_var(const char* name, int value) { + for (int i = 0; i < var_count; i++) { + if (strcmp(vars[i].name, name) == 0) { + vars[i].value = value; + return; + } + } + strcpy(vars[var_count].name, name); + vars[var_count++].value = value; +} + +int eval_expr(); + +int eval_factor() { + Token* t = current_token(); + if (t->type == T_NUMBER) { + int val = atoi(t->text); + next_token(); + return val; + } + if (t->type == T_IDENT) { + int val = get_var(t->text); + next_token(); + return val; + } + error("Invalid factor"); + return 0; +} + +int eval_term() { + int val = eval_factor(); + Token* t = current_token(); + while (t->type == T_MUL || t->type == T_DIV) { + TokenType op = t->type; + next_token(); + int rhs = eval_factor(); + if (op == T_MUL) val *= rhs; + else val /= rhs; + t = current_token(); + } + return val; +} + +int eval_expr() { + int val = eval_term(); + Token* t = current_token(); + while (t->type == T_PLUS || t->type == T_MINUS) { + TokenType op = t->type; + next_token(); + int rhs = eval_term(); + if (op == T_PLUS) val += rhs; + else val -= rhs; + t = current_token(); + } + return val; +} + +void execute() { + while (current_token()->type != T_EOF) { + Token* t = current_token(); + if (t->type == T_IDENT) { + char varname[32]; + strcpy(varname, t->text); + next_token(); + if (current_token()->type == T_ASSIGN) { + next_token(); + int val = eval_expr(); + set_var(varname, val); + } + } else if (t->type == T_PRINT) { + next_token(); + int val = eval_expr(); + printf("%d\n", val); + } + + if (current_token()->type == T_SEMI) + next_token(); + } +} + +void load_file(const char* filename) { + FILE* f = fopen(filename, "rb"); + if (!f) { + perror("fopen"); + exit(1); + } + source = (char*)malloc(MAX_SOURCE); + fread(source, 1, MAX_SOURCE, f); + fclose(f); +} + +int main(int argc, char** argv) { + if (argc < 2) { + printf("Usage: minilua \n"); + return 1; + } + + load_file(argv[1]); + tokenize(); + execute(); + + return 0; +}