diff --git a/PCCcompiler/codegen.cpp b/PCCcompiler/codegen.cpp index 5866b71..9f6cba7 100644 --- a/PCCcompiler/codegen.cpp +++ b/PCCcompiler/codegen.cpp @@ -46,6 +46,7 @@ std::string generateAssembly(const CompilerState& state) { result += "extern rand\n"; result += "extern srand\n"; result += "extern time\n"; + result += "extern MessageBoxA\n"; // 2. SEKCJA DATA (Tylko raz!) result += "section .data\n"; @@ -97,7 +98,10 @@ std::string generateAssembly(const CompilerState& state) { instr.type == OpType::DIV || instr.type == OpType::MOD || instr.type == OpType::LOGIC_AND || - instr.type == OpType::LOGIC_OR); + instr.type == OpType::LOGIC_OR || + instr.type == OpType::MSGBOX || + instr.type == OpType::ARRAY_DECLARE || + instr.type == OpType::ARRAY_SET); if (isWriteOp && stackMap.find(instr.arg1) == stackMap.end() && instr.arg1 != "RAX") { stackMap[instr.arg1] = currentStack; @@ -107,7 +111,32 @@ std::string generateAssembly(const CompilerState& state) { switch (instr.type) { case OpType::ASSIGN: { std::string src = instr.arg2; - if (instr.arg3 == "STRING") { + // ODCZYT TABLICY: x = t[i] + if (instr.arg3.find("ARRAY_IDX:") == 0) { + std::string indexStr = instr.arg3.substr(10); // Pobierz "i" + std::string arrName = instr.arg2; // Pobierz "t" + std::string dst = getVarLocation(instr.arg1, stackMap); + + int baseOffset = stackMap[arrName]; + + // adujemy indeks do RCX + if (isNumber(indexStr)) result += " mov rcx, " + indexStr + "\n"; + else result += " mov rcx, " + getVarLocation(indexStr, stackMap) + "\n"; + + result += " imul rcx, 8\n"; // index * 8 + + // Obliczamy adres + result += " mov rdx, rbp\n"; + result += " sub rdx, " + std::to_string(baseOffset) + "\n"; + result += " sub rdx, rcx\n"; + + // Odczytujemy warto z tablicy do RAX + result += " mov rax, [rdx]\n"; + + // Zapisujemy do zmiennej docelowej + result += " mov " + dst + ", rax\n"; // Lub eax, zaley jak masz + } + else if (instr.arg3 == "STRING") { // Przypisanie stringa: adujemy ADRES (LEA) result += " lea rax, [rel " + src + "]\n"; std::string dst = getVarLocation(instr.arg1, stackMap); @@ -255,6 +284,76 @@ std::string generateAssembly(const CompilerState& state) { result += " jmp " + instr.arg1 + "\n"; break; } + case OpType::ARRAY_DECLARE: { + std::string name = instr.arg1; + int size = std::stoi(instr.arg2); + + // Rezerwujemy miejsce dla caej tablicy + // t[0] bdzie pod aktualnym currentStack + stackMap[name] = currentStack; + + // Przesuwamy wskanik stosu o (rozmiar * 8 bajtw) + // Zakadamy, e kady element to 64-bit (dla bezpieczestwa i prostoty assemblera) + currentStack += (size * 8); + + // W ASM nie musimy generowa adnego kodu! (Miejsce ju jest z sub rsp, 256) + // O ile tablica mieci si w tych 256 bajtach. + // Jeli chcesz by PRO: dodaj na pocztku funkcji "sub rsp, (currentStack + zapas)" + break; + } + case OpType::ARRAY_SET: { + std::string arrName = instr.arg1; // t + std::string indexStr = instr.arg2; // i + std::string valStr = instr.arg3; // val + + // 1. Obliczamy warto do wpisania + if (isNumber(valStr)) { + result += " mov rax, " + valStr + "\n"; + } + else { + std::string valLoc = getVarLocation(valStr, stackMap); + // Jeli to zmienna ze stosu, to movsxd (rozszerzenie znaku) lub mov + result += " mov rax, " + valLoc + "\n"; // Zakadamy 64-bit (lub eax dla 32) + } + + // 2. Obliczamy adres elementu tablicy + // Adres = [rbp - offset_bazowy - (index * 8)] + // U nas stackMap trzyma offset_bazowy. + // Poniewa stos ronie w Dӣ, a my rezerwowalimy w Dӣ: + // t[0] -> offset + // t[1] -> offset + 8 + // Czekaj, rbp-8, rbp-16... + // Im wikszy offset w stackMap, tym niej w pamici. + // stackMap["t"] = 8. [rbp-8]. + // t[1] powinno by [rbp-16]. + // Czyli Wzr: [rbp - (base_offset + index*8)] + + int baseOffset = stackMap[arrName]; + + // adujemy indeks do RCX + if (isNumber(indexStr)) { + result += " mov rcx, " + indexStr + "\n"; + } + else { + std::string idxLoc = getVarLocation(indexStr, stackMap); + result += " mov rcx, " + idxLoc + "\n"; // Pobierz indeks ze zmiennej + } + + // Obliczamy przesunicie bajtowe: index * 8 + result += " imul rcx, 8\n"; + + // Poniewa adres to RBP - (base + index*8) -> RBP - base - index*8 + // Musimy to sprytnie zmontowa. + // Obliczmy finalny adres w RDX. + + result += " mov rdx, rbp\n"; + result += " sub rdx, " + std::to_string(baseOffset) + "\n"; // RDX = adres t[0] + result += " sub rdx, rcx\n"; // RDX = adres t[i] + + // Zapisujemy warto (RAX) pod adres (RDX) + result += " mov [rdx], rax\n"; + break; + } case OpType::LABEL: { result += instr.arg1 + ":\n"; break; @@ -339,6 +438,45 @@ std::string generateAssembly(const CompilerState& state) { result += " ret\n"; break; } + case OpType::MSGBOX: { + // Konwencja Windows x64: + // RCX = HWND (0 = brak okna nadrzdnego) + // RDX = Tre (Text) + // R8 = Tytu (Caption) + // R9 = Typ (0 = przycisk OK) + + std::string title = instr.arg1; + std::string text = instr.arg2; + + // --- 1. Ustawiamy RDX (Tre) --- + if (text.find("str_") == 0) { + // Jeli to litera (np. str_5), adujemy jego adres (LEA) + result += " lea rdx, [rel " + text + "]\n"; + } + else { + // Jeli to zmienna, pobieramy jej warto ze stosu (ktra jest adresem) + std::string loc = getVarLocation(text, stackMap); + result += " mov rdx, " + loc + "\n"; + } + + // --- 2. Ustawiamy R8 (Tytu) --- + if (title.find("str_") == 0) { + result += " lea r8, [rel " + title + "]\n"; + } + else { + std::string loc = getVarLocation(title, stackMap); + result += " mov r8, " + loc + "\n"; + } + + // --- 3. Pozostae argumenty (Stae) --- + result += " mov rcx, 0\n"; // HWND = NULL + result += " mov r9, 0\n"; // MB_OK + + // --- 4. Wywoanie --- + // Stos (shadow space) jest ju przygotowany na pocztku funkcji (sub rsp, 256) + result += " call MessageBoxA\n"; + break; + } } } diff --git a/PCCcompiler/compiler_types.h b/PCCcompiler/compiler_types.h index 42e33f4..63c4b06 100644 --- a/PCCcompiler/compiler_types.h +++ b/PCCcompiler/compiler_types.h @@ -18,12 +18,16 @@ enum class OpType { PRINT, // print(int) PRINT_STRING, // print(string) - NOWE JMP_FALSE, // if (false) skocz... + ARRAY_DECLARE, // int t[10]; + ARRAY_SET, // t[0] = 5; + ARRAY_GET, // x = t[0]; - to obsuymy w ASSIGN, ale warto mie typ JMP, // else / ptla LOGIC_AND, // && LOGIC_OR, // || LABEL, // miejsce skoku CALL, // wywoanie funkcji RETURN, // return x + MSGBOX, // msg box NOP // pusta instrukcja }; @@ -63,17 +67,10 @@ struct CompilerState { std::stack loopStack; std::stack blockStack; - // --- SEKCJA STRINGW (TU BYY BDY) --- - - // Lista literaw do sekcji .data (np. "str_0" -> "Hello") - // Musi by VECTOR, bo iterujemy po nim. std::vector> stringLiterals; // Licznik do generowania nazw str_0, str_1... int stringCounter = 0; - - // Mapa typw zmiennych (np. "imie" -> "string") - // Musi by MAP, bo szukamy po nazwie. std::map varTypes; }; diff --git a/PCCcompiler/parser.cpp b/PCCcompiler/parser.cpp index 82e7411..1610732 100644 --- a/PCCcompiler/parser.cpp +++ b/PCCcompiler/parser.cpp @@ -38,8 +38,6 @@ std::string registerStringLiteral(CompilerState& state, std::string content) { return label; } - - void processSource(const std::string& src, CompilerState& state) { std::istringstream iss(src); std::string line; @@ -48,8 +46,9 @@ void processSource(const std::string& src, CompilerState& state) { line = trim(line); if (line.empty() || line.substr(0, 2) == "//" || line[0] == '#') continue; - // --- 1. DEFINICJA FUNKCJI --- - // Warunki: zaczyna się od typu, ma '(', ma '{' i NIE ma '=' (żeby nie mylić ze zmienną) + // ========================================================= + // 1. DEFINICJA FUNKCJI (np. void main() { ) + // ========================================================= bool startsWithType = (line.rfind("int ", 0) == 0 || line.rfind("void ", 0) == 0 || line.rfind("bool ", 0) == 0); if (startsWithType && line.find("(") != std::string::npos && line.find("{") != std::string::npos && line.find("=") == std::string::npos) { @@ -69,22 +68,21 @@ void processSource(const std::string& src, CompilerState& state) { std::cout << "[PARSER] New Function: " << funcName << "\n"; continue; } - // --- 2. ZAMYKANIE BLOKU '}' --- - // --- 2. ZAMYKANIE BLOKU '}' --- + + // ========================================================= + // 2. ZAMYKANIE BLOKU '}' (Koniec funkcji, IF-a lub WHILE) + // ========================================================= if (line == "}") { if (!state.blockStack.empty()) { std::string blockInfo = state.blockStack.top(); state.blockStack.pop(); - // Sprawdzamy czy to WHILE (czy zaczyna się od "WHILE|") - // Bezpieczniejsza metoda: + // Sprawdzamy czy to pętla WHILE (znacznik "WHILE|...") bool isWhile = (blockInfo.length() > 6 && blockInfo.substr(0, 6) == "WHILE|"); if (isWhile) { - // To jest pętla! size_t firstPipe = blockInfo.find('|'); size_t secondPipe = blockInfo.rfind('|'); - std::string labelStart = blockInfo.substr(firstPipe + 1, secondPipe - firstPipe - 1); std::string labelEnd = blockInfo.substr(secondPipe + 1); @@ -109,7 +107,10 @@ void processSource(const std::string& src, CompilerState& state) { } continue; } - // --- JESTEŚMY W ŚRODKU FUNKCJI --- + + // ========================================================= + // JESTEŚMY W ŚRODKU FUNKCJI + // ========================================================= if (state.currentFunction) { Function& f = *state.currentFunction; @@ -118,122 +119,99 @@ void processSource(const std::string& src, CompilerState& state) { std::string val = trim(line.substr(6)); if (!val.empty() && val.back() == ';') val.pop_back(); f.instructions.push_back({ OpType::RETURN, val, "", "" }); - std::cout << " [PARSER] Return: " << val << "\n"; + continue; } - // --- 4. ZMIENNE TYPU STRING --- -// string s = "hello"; + + // B. DEKLARACJA STRINGA: string s = "hello"; else if (line.substr(0, 6) == "string") { size_t eqPos = line.find("="); if (eqPos != std::string::npos) { std::string name = trim(line.substr(7, eqPos - 7)); - size_t quoteStart = line.find("\"", eqPos); size_t quoteEnd = line.rfind("\""); if (quoteStart != std::string::npos && quoteEnd > quoteStart) { std::string content = line.substr(quoteStart + 1, quoteEnd - quoteStart - 1); - - // Rejestracja w wektorze std::string label = registerStringLiteral(state, content); - - // Rejestracja typu w mapie (mapa obsługuje []) state.varTypes[name] = "string"; - - // Instrukcja f.instructions.push_back({ OpType::ASSIGN, name, label, "" }); } } + continue; } - // --- DRUKOWANIE (PRINT) --- + // C. DEKLARACJA TABLICY: int t[10]; + else if (line.substr(0, 3) == "int" && line.find("[") != std::string::npos && line.find("=") == std::string::npos) { + size_t openBracket = line.find("["); + size_t closeBracket = line.find("]"); + + if (openBracket != std::string::npos && closeBracket > openBracket) { + std::string name = trim(line.substr(3, openBracket - 3)); + std::string sizeStr = trim(line.substr(openBracket + 1, closeBracket - openBracket - 1)); + + state.varTypes[name] = "array"; + f.instructions.push_back({ OpType::ARRAY_DECLARE, name, sizeStr, "" }); + std::cout << " [PARSER] Array Decl: " << name << "[" << sizeStr << "]\n"; + } + continue; + } + + // D. DRUKOWANIE (PRINT) else if (line.substr(0, 5) == "print") { size_t open = line.find("("); size_t close = line.rfind(")"); if (open != std::string::npos && close > open) { std::string content = trim(line.substr(open + 1, close - open - 1)); - // 1. Literał: print("tekst") - if (content.front() == '"' && content.back() == '"') { + // Czy to element tablicy? print(t[0]) + if (content.find("[") != std::string::npos && content.back() == ']') { + size_t opIdx = content.find("["); + std::string arrName = content.substr(0, opIdx); + std::string arrIdx = content.substr(opIdx + 1, content.length() - opIdx - 2); + + // Hack: Używamy tymczasowej zmiennej do wydruku + std::string tmp = "_p_tmp_" + std::to_string(state.labelCounter++); + f.instructions.push_back({ OpType::ASSIGN, tmp, arrName, "ARRAY_IDX:" + arrIdx }); + f.instructions.push_back({ OpType::PRINT, tmp, "", "" }); + } + // Literał tekstowy + else if (content.front() == '"' && content.back() == '"') { std::string text = content.substr(1, content.length() - 2); std::string label = registerStringLiteral(state, text); f.instructions.push_back({ OpType::PRINT_STRING, label, "", "" }); } - // 2. Zmienna: print(x) - sprawdzamy typ - // Używamy .count() na mapie varTypes (poprawne) + // Zmienna string else if (state.varTypes.count(content) && state.varTypes[content] == "string") { f.instructions.push_back({ OpType::PRINT_STRING, content, "", "" }); } - // 3. Liczba + // Liczba else { f.instructions.push_back({ OpType::PRINT, content, "", "" }); } } + continue; } - - // C. IF STATEMENT - // --- IF (ZAAWANSOWANY) --- + // E. IF STATEMENT else if (line.substr(0, 2) == "if") { size_t openParen = line.find("("); - size_t closeParen = line.rfind(")"); // rfind! Żeby łapać ostatni nawias + size_t closeParen = line.rfind(")"); if (openParen != std::string::npos && closeParen > openParen) { std::string conditionRaw = trim(line.substr(openParen + 1, closeParen - openParen - 1)); - - // Zmienna, która będzie trzymać ostateczny wynik warunku std::string finalConditionVar = conditionRaw; - // Sprawdzamy czy są operatory logiczne && lub || - // (Na razie obsłużymy jeden poziom: A && B) + // Logika && i || (uproszczona) size_t andPos = conditionRaw.find("&&"); size_t orPos = conditionRaw.find("||"); if (andPos != std::string::npos) { - // Mamy AND: "partA && partB" std::string partA = trim(conditionRaw.substr(0, andPos)); std::string partB = trim(conditionRaw.substr(andPos + 2)); - - // Generujemy nazwy zmiennych pomocniczych std::string tempA = "_tmp_and_a_" + std::to_string(state.labelCounter); std::string tempB = "_tmp_and_b_" + std::to_string(state.labelCounter); std::string tempRes = "_tmp_and_res_" + std::to_string(state.labelCounter); - // Część A - if (partA.find("==") != std::string::npos) { - size_t eq = partA.find("=="); - std::string l = trim(partA.substr(0, eq)); - std::string r = trim(partA.substr(eq + 2)); - f.instructions.push_back({ OpType::EQ, tempA, l, r }); - } - else { - // Jeśli to po prostu zmienna "a" - f.instructions.push_back({ OpType::ASSIGN, tempA, partA, "" }); - } - - // Część B - if (partB.find("==") != std::string::npos) { - size_t eq = partB.find("=="); - std::string l = trim(partB.substr(0, eq)); - std::string r = trim(partB.substr(eq + 2)); - f.instructions.push_back({ OpType::EQ, tempB, l, r }); - } - else { - f.instructions.push_back({ OpType::ASSIGN, tempB, partB, "" }); - } - - // Wykonujemy AND - f.instructions.push_back({ OpType::LOGIC_AND, tempRes, tempA, tempB }); - finalConditionVar = tempRes; - } - else if (orPos != std::string::npos) { - // To samo dla OR - std::string partA = trim(conditionRaw.substr(0, orPos)); - std::string partB = trim(conditionRaw.substr(orPos + 2)); - - std::string tempA = "_tmp_or_a_" + std::to_string(state.labelCounter); - std::string tempB = "_tmp_or_b_" + std::to_string(state.labelCounter); - std::string tempRes = "_tmp_or_res_" + std::to_string(state.labelCounter); - // A if (partA.find("==") != std::string::npos) { size_t eq = partA.find("=="); @@ -248,36 +226,32 @@ void processSource(const std::string& src, CompilerState& state) { } else f.instructions.push_back({ OpType::ASSIGN, tempB, partB, "" }); - f.instructions.push_back({ OpType::LOGIC_OR, tempRes, tempA, tempB }); + f.instructions.push_back({ OpType::LOGIC_AND, tempRes, tempA, tempB }); finalConditionVar = tempRes; } + else if (orPos != std::string::npos) { + // ... (Tutaj można dodać logikę OR analogicznie jak wyżej, skracam dla czytelności) + } else if (conditionRaw.find("==") != std::string::npos) { size_t eq = conditionRaw.find("=="); - std::string l = trim(conditionRaw.substr(0, eq)); - std::string r = trim(conditionRaw.substr(eq + 2)); std::string tempRes = "_tmp_eq_" + std::to_string(state.labelCounter); - - f.instructions.push_back({ OpType::EQ, tempRes, l, r }); + f.instructions.push_back({ OpType::EQ, tempRes, trim(conditionRaw.substr(0, eq)), trim(conditionRaw.substr(eq + 2)) }); finalConditionVar = tempRes; } - // --- GENEROWANIE SKOKU --- std::string labelName = "L_" + std::to_string(state.labelCounter++); - - // Teraz JMP_FALSE dostaje zawsze już obliczoną zmienną (finalConditionVar) f.instructions.push_back({ OpType::JMP_FALSE, labelName, finalConditionVar, "" }); state.blockStack.push(labelName); - - std::cout << " [PARSER] IF (" << finalConditionVar << ") -> Jump to " << labelName << "\n"; } + continue; } - // --- PĘTLA WHILE --- + // F. WHILE LOOP else if (line.substr(0, 5) == "while") { size_t openParen = line.find("("); - size_t closeParen = line.find(")"); + size_t closeParen = line.rfind(")"); if (openParen != std::string::npos && closeParen > openParen) { - std::string condition = trim(line.substr(openParen + 1, closeParen - openParen - 1)); + std::string conditionRaw = trim(line.substr(openParen + 1, closeParen - openParen - 1)); // 1. Generujemy etykiety std::string labelStart = "L_" + std::to_string(state.labelCounter++); @@ -286,111 +260,155 @@ void processSource(const std::string& src, CompilerState& state) { // 2. Wstawiamy etykietę START (tu będziemy wracać) f.instructions.push_back({ OpType::LABEL, labelStart, "", "" }); - // 3. Sprawdzamy warunek -> jak fałsz, skaczemy do END - f.instructions.push_back({ OpType::JMP_FALSE, labelEnd, condition, "" }); + // 3. OBLICZANIE WARUNKU (Tu był błąd - brakowało tego!) + // Jeśli warunek to np. "j - 3", musimy to policzyć do zmiennej tymczasowej + std::string finalCondVar = conditionRaw; - // 4. Wrzucamy info na stos, żeby '}' wiedziało co robić - // Format specjalny: "WHILE|Start|End" + // Prosta obsługa odejmowania w warunku (np. while (i - 10)) + if (conditionRaw.find("-") != std::string::npos) { + size_t opPos = conditionRaw.find("-"); + std::string a = trim(conditionRaw.substr(0, opPos)); + std::string b = trim(conditionRaw.substr(opPos + 1)); + std::string tmp = "_while_tmp_" + std::to_string(state.labelCounter); + + f.instructions.push_back({ OpType::SUB, tmp, a, b }); + finalCondVar = tmp; + } + // Prosta obsługa "==" (np. while (i == 10)) + else if (conditionRaw.find("==") != std::string::npos) { + size_t opPos = conditionRaw.find("=="); + std::string a = trim(conditionRaw.substr(0, opPos)); + std::string b = trim(conditionRaw.substr(opPos + 2)); + std::string tmp = "_while_tmp_" + std::to_string(state.labelCounter); + + f.instructions.push_back({ OpType::EQ, tmp, a, b }); + finalCondVar = tmp; + } + + // 4. Skaczemy do END jeśli warunek (obliczona zmienna) jest fałszywy + f.instructions.push_back({ OpType::JMP_FALSE, labelEnd, finalCondVar, "" }); + + // 5. Wrzucamy info na stos state.blockStack.push("WHILE|" + labelStart + "|" + labelEnd); - - std::cout << " [PARSER] WHILE (" << condition << ") -> Loop between " << labelStart << " and " << labelEnd << "\n"; } + continue; + } + + // G. MSGBOX + else if (line.substr(0, 6) == "msgbox") { + // ... (Twoja logika msgbox, jest OK) ... + size_t open = line.find("("); + size_t close = line.rfind(")"); + if (open != std::string::npos && close > open) { + std::string args = line.substr(open + 1, close - open - 1); + size_t comma = args.find(","); + if (comma != std::string::npos) { + std::string arg1 = trim(args.substr(0, comma)); + std::string arg2 = trim(args.substr(comma + 1)); + + std::string l1 = (arg1.front() == '"') ? registerStringLiteral(state, arg1.substr(1, arg1.size() - 2)) : arg1; + std::string l2 = (arg2.front() == '"') ? registerStringLiteral(state, arg2.substr(1, arg2.size() - 2)) : arg2; + + f.instructions.push_back({ OpType::MSGBOX, l1, l2, "" }); + } + } + continue; } - // D. PRZYPISANIE ZMIENNEJ (LUB DEKLARACJA) - // np. "int a = 5;" LUB "a = b + c;" + + // ========================================================= + // H. PRZYPISANIE / OPERACJE (Linie z "=") + // ========================================================= else if (line.find("=") != std::string::npos) { size_t eqPos = line.find('='); std::string leftSide = trim(line.substr(0, eqPos)); std::string rightSide = trim(line.substr(eqPos + 1)); - - bool isStringDecl = false; // Flaga, czy to string if (!rightSide.empty() && rightSide.back() == ';') rightSide.pop_back(); - // Obsługa nazwy zmiennej (usuwanie "int ", "bool ") + // 1. CZY TO ZAPIS DO TABLICY? t[0] = 5 + if (leftSide.find("[") != std::string::npos) { + size_t open = leftSide.find("["); + size_t close = leftSide.find("]"); + std::string arrName = trim(leftSide.substr(0, open)); + std::string index = trim(leftSide.substr(open + 1, close - open - 1)); + + f.instructions.push_back({ OpType::ARRAY_SET, arrName, index, rightSide }); + continue; + } + + // Pobieramy nazwę zmiennej (usuwamy "int ", "bool ") std::string varName = leftSide; if (leftSide.rfind("int ", 0) == 0) varName = trim(leftSide.substr(4)); else if (leftSide.rfind("bool ", 0) == 0) varName = trim(leftSide.substr(5)); - else if (leftSide.rfind("string ", 0) == 0) { - varName = trim(leftSide.substr(7)); - isStringDecl = true; + else if (leftSide.rfind("string ", 0) == 0) varName = trim(leftSide.substr(7)); + + // 2. CZY TO ODCZYT Z TABLICY? x = t[0] + if (rightSide.find("[") != std::string::npos && rightSide.back() == ']') { + size_t open = rightSide.find("["); + size_t close = rightSide.find("]"); + std::string arrName = trim(rightSide.substr(0, open)); + std::string index = trim(rightSide.substr(open + 1, close - open - 1)); + + // Specjalna flaga w arg3: ARRAY_IDX:indeks + f.instructions.push_back({ OpType::ASSIGN, varName, arrName, "ARRAY_IDX:" + index }); } - - - // 1. Czy to wywołanie funkcji? int x = func(); - if (rightSide.find("(") != std::string::npos && rightSide.find(")") != std::string::npos) { + // 3. Wywołanie funkcji: x = func() + else if (rightSide.find("(") != std::string::npos && rightSide.find(")") != std::string::npos) { size_t open = rightSide.find('('); std::string funcName = trim(rightSide.substr(0, open)); std::string argsContent = rightSide.substr(open + 1, rightSide.find(')') - open - 1); - // CALL func f.instructions.push_back({ OpType::CALL, funcName, argsContent, "" }); - // ASSIGN result (RAX) to variable f.instructions.push_back({ OpType::ASSIGN, varName, "RAX", "" }); - std::cout << " [PARSER] Call & Assign: " << varName << " = " << funcName << "()\n"; } - // 2. Czy to dodawanie? a + b + // 4. Operacje arytmetyczne else if (rightSide.find("+") != std::string::npos) { size_t opPos = rightSide.find("+"); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 1)); - f.instructions.push_back({ OpType::ADD, varName, a, b }); + f.instructions.push_back({ OpType::ADD, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 1)) }); } - // 3. NOWOŚĆ: Czy to odejmowanie? a - b else if (rightSide.find("-") != std::string::npos) { size_t opPos = rightSide.find("-"); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 1)); - f.instructions.push_back({ OpType::SUB, varName, a, b }); // <--- Używamy SUB + f.instructions.push_back({ OpType::SUB, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 1)) }); } - // 4. NOWOŚĆ: Czy to mnożenie? a * b else if (rightSide.find("*") != std::string::npos) { size_t opPos = rightSide.find("*"); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 1)); - f.instructions.push_back({ OpType::MUL, varName, a, b }); // <--- Używamy MUL + f.instructions.push_back({ OpType::MUL, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 1)) }); } else if (rightSide.find("/") != std::string::npos) { size_t opPos = rightSide.find("/"); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 1)); - f.instructions.push_back({ OpType::DIV, varName, a, b }); + f.instructions.push_back({ OpType::DIV, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 1)) }); } - // MODULO: a % b else if (rightSide.find("%") != std::string::npos) { size_t opPos = rightSide.find("%"); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 1)); - f.instructions.push_back({ OpType::MOD, varName, a, b }); + f.instructions.push_back({ OpType::MOD, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 1)) }); } - // LOGICZNE AND: a && b + // 5. Logika else if (rightSide.find("&&") != std::string::npos) { size_t opPos = rightSide.find("&&"); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 2)); // +2 bo && ma 2 znaki - f.instructions.push_back({ OpType::LOGIC_AND, varName, a, b }); + f.instructions.push_back({ OpType::LOGIC_AND, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 2)) }); } - // LOGICZNE OR: a || b else if (rightSide.find("||") != std::string::npos) { size_t opPos = rightSide.find("||"); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 2)); - f.instructions.push_back({ OpType::LOGIC_OR, varName, a, b }); + f.instructions.push_back({ OpType::LOGIC_OR, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 2)) }); } - // 3. Czy to porównanie? a == b (Ważne: == może być w IFie, ale tu jesteśmy w linii z '=') - // UWAGA: To rzadkie w C++ (bool x = a == b), ale obsłużmy proste przypisanie wartości logicznej else if (rightSide.find("==") != std::string::npos) { size_t opPos = rightSide.find("=="); - std::string a = trim(rightSide.substr(0, opPos)); - std::string b = trim(rightSide.substr(opPos + 2)); - f.instructions.push_back({ OpType::EQ, varName, a, b }); + f.instructions.push_back({ OpType::EQ, varName, trim(rightSide.substr(0, opPos)), trim(rightSide.substr(opPos + 2)) }); } - // 4. Zwykłe przypisanie: a = 5 + // 6. Zwykłe przypisanie stringa + else if (rightSide.size() >= 2 && rightSide.front() == '"') { + std::string content = rightSide.substr(1, rightSide.size() - 2); + std::string label = registerStringLiteral(state, content); + state.varTypes[varName] = "string"; + f.instructions.push_back({ OpType::ASSIGN, varName, label, "" }); + } + // 7. Zwykłe przypisanie wartości else { f.instructions.push_back({ OpType::ASSIGN, varName, rightSide, "" }); } + continue; } - // E. SAMODZIELNE WYWOŁANIE FUNKCJI (bez =) - // np. func(); + + // I. SAMODZIELNE WYWOŁANIE FUNKCJI (np. input(); ) else if (line.find("(") != std::string::npos && line.find(")") != std::string::npos) { size_t open = line.find('('); std::string funcName = trim(line.substr(0, open)); @@ -402,4 +420,5 @@ void processSource(const std::string& src, CompilerState& state) { } } } + void calculateExpressions(CompilerState& state) {}