Loop Update
This commit is contained in:
@@ -89,7 +89,9 @@ std::string generateAssembly(const CompilerState& state) {
|
|||||||
instr.type == OpType::SUB ||
|
instr.type == OpType::SUB ||
|
||||||
instr.type == OpType::MUL ||
|
instr.type == OpType::MUL ||
|
||||||
instr.type == OpType::DIV ||
|
instr.type == OpType::DIV ||
|
||||||
instr.type == OpType::MOD);
|
instr.type == OpType::MOD ||
|
||||||
|
instr.type == OpType::LOGIC_AND ||
|
||||||
|
instr.type == OpType::LOGIC_OR);
|
||||||
|
|
||||||
if (isWriteOp && stackMap.find(instr.arg1) == stackMap.end() && instr.arg1 != "RAX") {
|
if (isWriteOp && stackMap.find(instr.arg1) == stackMap.end() && instr.arg1 != "RAX") {
|
||||||
stackMap[instr.arg1] = currentStack;
|
stackMap[instr.arg1] = currentStack;
|
||||||
@@ -182,6 +184,11 @@ std::string generateAssembly(const CompilerState& state) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OpType::JMP: {
|
||||||
|
// Skok bezwarunkowy (u¿ywany na koñcu pêtli while)
|
||||||
|
result += " jmp " + instr.arg1 + "\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OpType::LABEL: {
|
case OpType::LABEL: {
|
||||||
result += instr.arg1 + ":\n";
|
result += instr.arg1 + ":\n";
|
||||||
break;
|
break;
|
||||||
@@ -318,6 +325,61 @@ std::string generateAssembly(const CompilerState& state) {
|
|||||||
result += " mov " + dst + ", edx\n"; // EDX to reszta z dzielenia!
|
result += " mov " + dst + ", edx\n"; // EDX to reszta z dzielenia!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OpType::LOGIC_AND: {
|
||||||
|
// a && b
|
||||||
|
// Algorytm: result = (op1 != 0) * (op2 != 0)
|
||||||
|
// Ale w ASM ³atwiej:
|
||||||
|
// cmp op1, 0 -> setne al
|
||||||
|
// cmp op2, 0 -> setne bl
|
||||||
|
// and al, bl
|
||||||
|
|
||||||
|
std::string op1 = getVarLocation(instr.arg2, stackMap);
|
||||||
|
std::string op2 = getVarLocation(instr.arg3, stackMap);
|
||||||
|
std::string dst = getVarLocation(instr.arg1, stackMap);
|
||||||
|
|
||||||
|
// Sprawdzamy op1
|
||||||
|
result += " mov eax, " + op1 + "\n";
|
||||||
|
result += " cmp eax, 0\n";
|
||||||
|
result += " setne al\n"; // al = 1 jeœli eax != 0
|
||||||
|
|
||||||
|
// Sprawdzamy op2 (u¿ywamy ECX jako pomocniczy)
|
||||||
|
if (isdigit(op2[0])) result += " mov ecx, " + op2 + "\n";
|
||||||
|
else result += " mov ecx, " + op2 + "\n";
|
||||||
|
|
||||||
|
result += " cmp ecx, 0\n";
|
||||||
|
result += " setne cl\n"; // cl = 1 jeœli ecx != 0
|
||||||
|
|
||||||
|
// Logiczne AND na bajtach
|
||||||
|
result += " and al, cl\n";
|
||||||
|
|
||||||
|
// Zapisujemy wynik (rozszerzamy bajt do dword)
|
||||||
|
result += " movzx eax, al\n";
|
||||||
|
result += " mov " + dst + ", eax\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OpType::LOGIC_OR: {
|
||||||
|
// a || b
|
||||||
|
std::string op1 = getVarLocation(instr.arg2, stackMap);
|
||||||
|
std::string op2 = getVarLocation(instr.arg3, stackMap);
|
||||||
|
std::string dst = getVarLocation(instr.arg1, stackMap);
|
||||||
|
|
||||||
|
result += " mov eax, " + op1 + "\n";
|
||||||
|
result += " cmp eax, 0\n";
|
||||||
|
result += " setne al\n";
|
||||||
|
|
||||||
|
if (isdigit(op2[0])) result += " mov ecx, " + op2 + "\n";
|
||||||
|
else result += " mov ecx, " + op2 + "\n";
|
||||||
|
|
||||||
|
result += " cmp ecx, 0\n";
|
||||||
|
result += " setne cl\n";
|
||||||
|
|
||||||
|
// Logiczne OR
|
||||||
|
result += " or al, cl\n";
|
||||||
|
|
||||||
|
result += " movzx eax, al\n";
|
||||||
|
result += " mov " + dst + ", eax\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ enum class OpType {
|
|||||||
PRINT, // print(a)
|
PRINT, // print(a)
|
||||||
JMP_FALSE, // if (false) skocz...
|
JMP_FALSE, // if (false) skocz...
|
||||||
JMP, // else / pêtla
|
JMP, // else / pêtla
|
||||||
|
LOGIC_AND, // &&
|
||||||
|
LOGIC_OR, // ||
|
||||||
LABEL, // miejsce skoku
|
LABEL, // miejsce skoku
|
||||||
CALL, // wywo³anie funkcji
|
CALL, // wywo³anie funkcji
|
||||||
RETURN, // return x
|
RETURN, // return x
|
||||||
@@ -55,7 +57,7 @@ struct CompilerState {
|
|||||||
std::stack<std::string> blockStack;
|
std::stack<std::string> blockStack;
|
||||||
|
|
||||||
std::map<std::string, std::string> stringLiterals;
|
std::map<std::string, std::string> stringLiterals;
|
||||||
int stringCounter = 0; // Licznik do generowania nazw str_1, str_2...
|
int stringCounter = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ std::string getExecutablePath() {
|
|||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
std::string inputFile, outputName;
|
std::string inputFile, outputName;
|
||||||
std::string Version = "v0.0.5-beta";
|
std::string Version = "v0.0.7-beta";
|
||||||
bool showHelp = false, showVersion = false, showCredits = false;
|
bool showHelp = false, showVersion = false, showCredits = false;
|
||||||
|
|
||||||
// --- PARSOWANIE ARGUMENTÓW ---
|
// --- PARSOWANIE ARGUMENTÓW ---
|
||||||
|
|||||||
@@ -56,18 +56,40 @@ void processSource(const std::string& src, CompilerState& state) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// --- 2. ZAMYKANIE BLOKU '}' ---
|
// --- 2. ZAMYKANIE BLOKU '}' ---
|
||||||
|
// --- 2. ZAMYKANIE BLOKU '}' ---
|
||||||
if (line == "}") {
|
if (line == "}") {
|
||||||
// Najpierw sprawdzamy, czy zamykamy IF-a (czy jest coś na stosie bloków)
|
|
||||||
if (!state.blockStack.empty()) {
|
if (!state.blockStack.empty()) {
|
||||||
std::string label = state.blockStack.top();
|
std::string blockInfo = state.blockStack.top();
|
||||||
state.blockStack.pop();
|
state.blockStack.pop();
|
||||||
if (state.currentFunction) {
|
|
||||||
state.currentFunction->instructions.push_back({ OpType::LABEL, label, "", "" });
|
// Sprawdzamy czy to WHILE (czy zaczyna się od "WHILE|")
|
||||||
|
// Bezpieczniejsza metoda:
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (state.currentFunction) {
|
||||||
|
state.currentFunction->instructions.push_back({ OpType::JMP, labelStart, "", "" });
|
||||||
|
state.currentFunction->instructions.push_back({ OpType::LABEL, labelEnd, "", "" });
|
||||||
|
}
|
||||||
|
std::cout << " [PARSER] } End WHILE loop\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// To zwykły IF
|
||||||
|
if (state.currentFunction) {
|
||||||
|
state.currentFunction->instructions.push_back({ OpType::LABEL, blockInfo, "", "" });
|
||||||
|
}
|
||||||
|
std::cout << " [PARSER] } End IF block -> " << blockInfo << "\n";
|
||||||
}
|
}
|
||||||
std::cout << " [PARSER] } End IF block -> " << label << "\n";
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Jeśli stos pusty, to koniec funkcji
|
// Koniec funkcji
|
||||||
state.currentFunction = nullptr;
|
state.currentFunction = nullptr;
|
||||||
std::cout << " [PARSER] } End Function\n";
|
std::cout << " [PARSER] } End Function\n";
|
||||||
}
|
}
|
||||||
@@ -118,18 +140,128 @@ void processSource(const std::string& src, CompilerState& state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// C. IF STATEMENT
|
// C. IF STATEMENT
|
||||||
|
// --- IF (ZAAWANSOWANY) ---
|
||||||
else if (line.substr(0, 2) == "if") {
|
else if (line.substr(0, 2) == "if") {
|
||||||
|
size_t openParen = line.find("(");
|
||||||
|
size_t closeParen = line.rfind(")"); // rfind! Żeby łapać ostatni nawias
|
||||||
|
|
||||||
|
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)
|
||||||
|
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("==");
|
||||||
|
f.instructions.push_back({ OpType::EQ, tempA, trim(partA.substr(0, eq)), trim(partA.substr(eq + 2)) });
|
||||||
|
}
|
||||||
|
else f.instructions.push_back({ OpType::ASSIGN, tempA, partA, "" });
|
||||||
|
|
||||||
|
// B
|
||||||
|
if (partB.find("==") != std::string::npos) {
|
||||||
|
size_t eq = partB.find("==");
|
||||||
|
f.instructions.push_back({ OpType::EQ, tempB, trim(partB.substr(0, eq)), trim(partB.substr(eq + 2)) });
|
||||||
|
}
|
||||||
|
else f.instructions.push_back({ OpType::ASSIGN, tempB, partB, "" });
|
||||||
|
|
||||||
|
f.instructions.push_back({ OpType::LOGIC_OR, tempRes, tempA, tempB });
|
||||||
|
finalConditionVar = tempRes;
|
||||||
|
}
|
||||||
|
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 });
|
||||||
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- PĘTLA WHILE ---
|
||||||
|
else if (line.substr(0, 5) == "while") {
|
||||||
size_t openParen = line.find("(");
|
size_t openParen = line.find("(");
|
||||||
size_t closeParen = line.find(")");
|
size_t closeParen = line.find(")");
|
||||||
if (openParen != std::string::npos && closeParen > openParen) {
|
if (openParen != std::string::npos && closeParen > openParen) {
|
||||||
std::string condition = trim(line.substr(openParen + 1, closeParen - openParen - 1));
|
std::string condition = trim(line.substr(openParen + 1, closeParen - openParen - 1));
|
||||||
std::string labelName = "L_" + std::to_string(state.labelCounter++);
|
|
||||||
|
|
||||||
// Skok warunkowy
|
// 1. Generujemy etykiety
|
||||||
f.instructions.push_back({ OpType::JMP_FALSE, labelName, condition, "" });
|
std::string labelStart = "L_" + std::to_string(state.labelCounter++);
|
||||||
state.blockStack.push(labelName);
|
std::string labelEnd = "L_" + std::to_string(state.labelCounter++);
|
||||||
|
|
||||||
std::cout << " [PARSER] IF (" << condition << ") -> Jump to " << labelName << "\n";
|
// 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, "" });
|
||||||
|
|
||||||
|
// 4. Wrzucamy info na stos, żeby '}' wiedziało co robić
|
||||||
|
// Format specjalny: "WHILE|Start|End"
|
||||||
|
state.blockStack.push("WHILE|" + labelStart + "|" + labelEnd);
|
||||||
|
|
||||||
|
std::cout << " [PARSER] WHILE (" << condition << ") -> Loop between " << labelStart << " and " << labelEnd << "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// D. PRZYPISANIE ZMIENNEJ (LUB DEKLARACJA)
|
// D. PRZYPISANIE ZMIENNEJ (LUB DEKLARACJA)
|
||||||
@@ -146,7 +278,7 @@ void processSource(const std::string& src, CompilerState& state) {
|
|||||||
std::string varName = leftSide;
|
std::string varName = leftSide;
|
||||||
if (leftSide.rfind("int ", 0) == 0) varName = trim(leftSide.substr(4));
|
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("bool ", 0) == 0) varName = trim(leftSide.substr(5));
|
||||||
else if (leftSide.rfind("string ", 0) == 0) { // NOWOŚĆ
|
else if (leftSide.rfind("string ", 0) == 0) {
|
||||||
varName = trim(leftSide.substr(7));
|
varName = trim(leftSide.substr(7));
|
||||||
isStringDecl = true;
|
isStringDecl = true;
|
||||||
}
|
}
|
||||||
@@ -198,6 +330,20 @@ void processSource(const std::string& src, CompilerState& state) {
|
|||||||
std::string b = trim(rightSide.substr(opPos + 1));
|
std::string b = trim(rightSide.substr(opPos + 1));
|
||||||
f.instructions.push_back({ OpType::MOD, varName, a, b });
|
f.instructions.push_back({ OpType::MOD, varName, a, b });
|
||||||
}
|
}
|
||||||
|
// LOGICZNE AND: 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)); // +2 bo && ma 2 znaki
|
||||||
|
f.instructions.push_back({ OpType::LOGIC_AND, varName, a, b });
|
||||||
|
}
|
||||||
|
// 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 });
|
||||||
|
}
|
||||||
// 3. Czy to porównanie? a == b (Ważne: == może być w IFie, ale tu jesteśmy w linii z '=')
|
// 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
|
// 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) {
|
else if (rightSide.find("==") != std::string::npos) {
|
||||||
|
|||||||
Reference in New Issue
Block a user