Compare commits

..

No commits in common. "main" and "v0.3.0" have entirely different histories.
main ... v0.3.0

21 changed files with 39 additions and 595 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -11,7 +11,6 @@ void SetPropExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); }
void ArrayExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); } void ArrayExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); }
void IndexExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); } void IndexExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); }
void ArrayAssignExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); } void ArrayAssignExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); }
void IncrementExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); }
void BinaryExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); } void BinaryExpr::accept(ASTVisitor& visitor) { visitor.visit(*this); }
void ReturnStmt::accept(ASTVisitor& visitor) { visitor.visit(*this); } void ReturnStmt::accept(ASTVisitor& visitor) { visitor.visit(*this); }
void VarDeclStmt::accept(ASTVisitor& visitor) { visitor.visit(*this); } void VarDeclStmt::accept(ASTVisitor& visitor) { visitor.visit(*this); }

View File

@ -108,13 +108,6 @@ public:
void accept(ASTVisitor& visitor) override; void accept(ASTVisitor& visitor) override;
}; };
class IncrementExpr : public Expr {
public:
std::unique_ptr<Expr> variable; // Can be VariableExpr, GetPropExpr, IndexExpr
IncrementExpr(std::unique_ptr<Expr> variable) : variable(std::move(variable)) {}
void accept(ASTVisitor& visitor) override;
};
class BinaryExpr : public Expr { class BinaryExpr : public Expr {
public: public:
std::unique_ptr<Expr> left; std::unique_ptr<Expr> left;
@ -246,7 +239,6 @@ public:
virtual void visit(ArrayExpr& node) = 0; virtual void visit(ArrayExpr& node) = 0;
virtual void visit(IndexExpr& node) = 0; virtual void visit(IndexExpr& node) = 0;
virtual void visit(ArrayAssignExpr& node) = 0; virtual void visit(ArrayAssignExpr& node) = 0;
virtual void visit(IncrementExpr& node) = 0;
virtual void visit(BinaryExpr& node) = 0; virtual void visit(BinaryExpr& node) = 0;
virtual void visit(ReturnStmt& node) = 0; virtual void visit(ReturnStmt& node) = 0;
virtual void visit(VarDeclStmt& node) = 0; virtual void visit(VarDeclStmt& node) = 0;

View File

@ -130,60 +130,3 @@ void ASTPrinter::visit(ClassDef& node) {
} }
std::cout << "}"; std::cout << "}";
} }
void ASTPrinter::visit(ArrayExpr& node) {
std::cout << "[";
for (size_t i = 0; i < node.elements.size(); ++i) {
node.elements[i]->accept(*this);
if (i < node.elements.size() - 1) std::cout << ", ";
}
std::cout << "]";
}
void ASTPrinter::visit(IndexExpr& node) {
node.array->accept(*this);
std::cout << "[";
node.index->accept(*this);
std::cout << "]";
}
void ASTPrinter::visit(ArrayAssignExpr& node) {
node.array->accept(*this);
std::cout << "[";
node.index->accept(*this);
std::cout << "] = ";
node.value->accept(*this);
}
void ASTPrinter::visit(IncrementExpr& node) {
node.variable->accept(*this);
std::cout << "++";
}
void ASTPrinter::visit(ForInStmt& node) {
std::cout << "for (var " << node.variableName << " in ";
node.collection->accept(*this);
std::cout << ") ";
node.body->accept(*this);
}
void ASTPrinter::visit(SwitchStmt& node) {
std::cout << "switch (";
node.condition->accept(*this);
std::cout << ") {" << std::endl;
for (const auto& c : node.cases) {
std::cout << "case ";
c.value->accept(*this);
std::cout << ": ";
c.body->accept(*this);
}
if (node.defaultCase) {
std::cout << "default: ";
node.defaultCase->accept(*this);
}
std::cout << "}";
}
void ASTPrinter::visit(BreakStmt& node) {
std::cout << "break;";
}

View File

@ -16,10 +16,6 @@ public:
void visit(NewExpr& node) override; void visit(NewExpr& node) override;
void visit(GetPropExpr& node) override; void visit(GetPropExpr& node) override;
void visit(SetPropExpr& node) override; void visit(SetPropExpr& node) override;
void visit(ArrayExpr& node) override;
void visit(IndexExpr& node) override;
void visit(ArrayAssignExpr& node) override;
void visit(IncrementExpr& node) override;
void visit(BinaryExpr& node) override; void visit(BinaryExpr& node) override;
void visit(ReturnStmt& node) override; void visit(ReturnStmt& node) override;
void visit(VarDeclStmt& node) override; void visit(VarDeclStmt& node) override;
@ -27,9 +23,6 @@ public:
void visit(IfStmt& node) override; void visit(IfStmt& node) override;
void visit(WhileStmt& node) override; void visit(WhileStmt& node) override;
void visit(ForStmt& node) override; void visit(ForStmt& node) override;
void visit(ForInStmt& node) override;
void visit(SwitchStmt& node) override;
void visit(BreakStmt& node) override;
void visit(ExpressionStmt& node) override; void visit(ExpressionStmt& node) override;
void visit(FunctionDef& node) override; void visit(FunctionDef& node) override;
void visit(ClassDef& node) override; void visit(ClassDef& node) override;

View File

@ -1,6 +1,5 @@
#include "codegen.h" #include "codegen.h"
#include <iostream> #include <iostream>
#include <typeinfo>
CodeGen::CodeGen() { CodeGen::CodeGen() {
context = std::make_unique<llvm::LLVMContext>(); context = std::make_unique<llvm::LLVMContext>();
@ -51,31 +50,6 @@ CodeGen::CodeGen() {
false false
); );
llvm::Function::Create(readCsvType, llvm::Function::ExternalLinkage, "sun_read_csv", module.get()); llvm::Function::Create(readCsvType, llvm::Function::ExternalLinkage, "sun_read_csv", module.get());
// void* sun_read_json(char* filename)
llvm::FunctionType* readJsonType = llvm::FunctionType::get(
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0),
{
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0) // filename
},
false
);
llvm::Function::Create(readJsonType, llvm::Function::ExternalLinkage, "sun_read_json", module.get());
// void sun_print_json(void* val)
llvm::FunctionType* printJsonType = llvm::FunctionType::get(llvm::Type::getVoidTy(*context), {llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)}, false);
llvm::Function::Create(printJsonType, llvm::Function::ExternalLinkage, "sun_print_json", module.get());
// void* sun_map_get(void* map, char* key)
llvm::FunctionType* mapGetType = llvm::FunctionType::get(
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0),
{
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0), // map
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0) // key
},
false
);
llvm::Function::Create(mapGetType, llvm::Function::ExternalLinkage, "sun_map_get", module.get());
} }
llvm::AllocaInst* CodeGen::createEntryBlockAlloca(llvm::Function* theFunction, const std::string& varName, llvm::Type* type) { llvm::AllocaInst* CodeGen::createEntryBlockAlloca(llvm::Function* theFunction, const std::string& varName, llvm::Type* type) {
@ -124,7 +98,7 @@ void CodeGen::visit(NumberExpr& node) {
} }
void CodeGen::visit(StringExpr& node) { void CodeGen::visit(StringExpr& node) {
lastValue = builder->CreateGlobalStringPtr(node.value); lastValue = builder->CreateGlobalString(node.value);
lastClassName = "String"; // Special marker for string lastClassName = "String"; // Special marker for string
} }
@ -204,36 +178,6 @@ void CodeGen::visit(CallExpr& node) {
return; return;
} }
// Handle "readjson" specially
if (node.callee == "readjson") {
if (node.args.size() != 1) {
std::cerr << "readjson() takes exactly 1 argument." << std::endl;
lastValue = nullptr;
return;
}
node.args[0]->accept(*this);
llvm::Value* filenameVal = lastValue;
if (filenameVal->getType() != llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)) {
filenameVal = builder->CreateBitCast(filenameVal, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
}
llvm::Function* readJsonFn = module->getFunction("sun_read_json");
if (!readJsonFn) {
std::cerr << "Error: sun_read_json function not found in module!" << std::endl;
lastValue = nullptr;
return;
}
lastValue = builder->CreateCall(readJsonFn, {filenameVal}, "json_data");
if (!lastValue) {
std::cerr << "Error: CreateCall for sun_read_json returned null!" << std::endl;
return;
}
lastClassName = "JSON"; // Special marker
return;
}
// Handle "len" specially // Handle "len" specially
if (node.callee == "len") { if (node.callee == "len") {
if (node.args.size() != 1) { if (node.args.size() != 1) {
@ -267,17 +211,8 @@ void CodeGen::visit(CallExpr& node) {
std::string argType = lastClassName; std::string argType = lastClassName;
if (argType == "String") { if (argType == "String") {
if (argVal->getType() != llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)) {
argVal = builder->CreateBitCast(argVal, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
}
llvm::Function* printStr = module->getFunction("print_string"); llvm::Function* printStr = module->getFunction("print_string");
builder->CreateCall(printStr, {argVal}); builder->CreateCall(printStr, {argVal});
} else if (argType == "JSON") {
if (argVal->getType() != llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)) {
argVal = builder->CreateBitCast(argVal, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
}
llvm::Function* printJson = module->getFunction("sun_print_json");
builder->CreateCall(printJson, {argVal});
} else { } else {
// Assume int // Assume int
llvm::Function* printInt = module->getFunction("print_int"); llvm::Function* printInt = module->getFunction("print_int");
@ -313,95 +248,6 @@ void CodeGen::visit(CallExpr& node) {
lastClassName = ""; lastClassName = "";
} }
void CodeGen::visit(IncrementExpr& node) {
if (auto varExpr = dynamic_cast<VariableExpr*>(node.variable.get())) {
if (namedValues.find(varExpr->name) == namedValues.end()) {
std::cerr << "Unknown variable: " << varExpr->name << std::endl;
lastValue = nullptr;
return;
}
llvm::AllocaInst* alloca = namedValues[varExpr->name];
llvm::Value* val = builder->CreateLoad(alloca->getAllocatedType(), alloca, varExpr->name.c_str());
lastValue = val; // Return old value
llvm::Value* inc = builder->CreateAdd(val, llvm::ConstantInt::get(*context, llvm::APInt(32, 1)), "inc");
builder->CreateStore(inc, alloca);
} else if (auto getProp = dynamic_cast<GetPropExpr*>(node.variable.get())) {
getProp->object->accept(*this);
llvm::Value* objectPtr = lastValue;
std::string className = lastClassName;
if (!objectPtr) return;
if (classFields.find(className) == classFields.end()) {
std::cerr << "Unknown class type: " << className << std::endl;
lastValue = nullptr;
return;
}
const auto& fields = classFields[className];
int fieldIndex = -1;
for (size_t i = 0; i < fields.size(); ++i) {
if (fields[i] == getProp->name) {
fieldIndex = i;
break;
}
}
if (fieldIndex == -1) {
std::cerr << "Unknown field: " << getProp->name << " in class " << className << std::endl;
lastValue = nullptr;
return;
}
std::vector<llvm::Value*> indices;
indices.push_back(llvm::ConstantInt::get(*context, llvm::APInt(32, 0)));
indices.push_back(llvm::ConstantInt::get(*context, llvm::APInt(32, fieldIndex)));
llvm::Type* structType = classStructs[className];
llvm::Value* fieldPtr = builder->CreateGEP(structType, objectPtr, indices, "fieldptr");
llvm::Value* val = builder->CreateLoad(llvm::Type::getInt32Ty(*context), fieldPtr, "fieldval");
lastValue = val;
llvm::Value* inc = builder->CreateAdd(val, llvm::ConstantInt::get(*context, llvm::APInt(32, 1)), "inc");
builder->CreateStore(inc, fieldPtr);
} else if (auto indexExpr = dynamic_cast<IndexExpr*>(node.variable.get())) {
indexExpr->array->accept(*this);
llvm::Value* arrPtr = lastValue;
indexExpr->index->accept(*this);
llvm::Value* indexVal = lastValue;
std::string indexType = lastClassName;
if (indexType == "String") {
// Map increment? Not supported yet easily without sun_map_set
std::cerr << "Increment on map values not fully supported yet." << std::endl;
lastValue = nullptr;
return;
}
llvm::Function* getFn = module->getFunction("sun_array_get");
llvm::Function* setFn = module->getFunction("sun_array_set");
llvm::Value* valPtr = builder->CreateCall(getFn, {arrPtr, indexVal}, "elem");
// Assume IntArray for increment
llvm::Value* val = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt");
lastValue = val;
llvm::Value* inc = builder->CreateAdd(val, llvm::ConstantInt::get(*context, llvm::APInt(32, 1)), "inc");
// Store back
llvm::Value* voidVal = builder->CreateIntToPtr(inc, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
builder->CreateCall(setFn, {arrPtr, indexVal, voidVal});
} else {
std::cerr << "Invalid increment target." << std::endl;
lastValue = nullptr;
}
}
void CodeGen::visit(BinaryExpr& node) { void CodeGen::visit(BinaryExpr& node) {
node.left->accept(*this); node.left->accept(*this);
llvm::Value* L = lastValue; llvm::Value* L = lastValue;
@ -465,12 +311,6 @@ void CodeGen::visit(BinaryExpr& node) {
} else if (node.op == ">") { } else if (node.op == ">") {
lastValue = builder->CreateICmpSGT(L, R, "cmptmp"); lastValue = builder->CreateICmpSGT(L, R, "cmptmp");
lastValue = builder->CreateIntCast(lastValue, llvm::Type::getInt32Ty(*context), true, "booltmp"); lastValue = builder->CreateIntCast(lastValue, llvm::Type::getInt32Ty(*context), true, "booltmp");
} else if (node.op == "<=") {
lastValue = builder->CreateICmpSLE(L, R, "cmptmp");
lastValue = builder->CreateIntCast(lastValue, llvm::Type::getInt32Ty(*context), true, "booltmp");
} else if (node.op == ">=") {
lastValue = builder->CreateICmpSGE(L, R, "cmptmp");
lastValue = builder->CreateIntCast(lastValue, llvm::Type::getInt32Ty(*context), true, "booltmp");
} else if (node.op == "==") { } else if (node.op == "==") {
lastValue = builder->CreateICmpEQ(L, R, "cmptmp"); lastValue = builder->CreateICmpEQ(L, R, "cmptmp");
lastValue = builder->CreateIntCast(lastValue, llvm::Type::getInt32Ty(*context), true, "booltmp"); lastValue = builder->CreateIntCast(lastValue, llvm::Type::getInt32Ty(*context), true, "booltmp");
@ -530,8 +370,8 @@ void CodeGen::visit(IfStmt& node) {
llvm::Function* theFunction = builder->GetInsertBlock()->getParent(); llvm::Function* theFunction = builder->GetInsertBlock()->getParent();
llvm::BasicBlock* thenBB = llvm::BasicBlock::Create(*context, "then", theFunction); llvm::BasicBlock* thenBB = llvm::BasicBlock::Create(*context, "then", theFunction);
llvm::BasicBlock* elseBB = llvm::BasicBlock::Create(*context, "else", theFunction); llvm::BasicBlock* elseBB = llvm::BasicBlock::Create(*context, "else");
llvm::BasicBlock* mergeBB = llvm::BasicBlock::Create(*context, "ifcont", theFunction); llvm::BasicBlock* mergeBB = llvm::BasicBlock::Create(*context, "ifcont");
builder->CreateCondBr(condV, thenBB, elseBB); builder->CreateCondBr(condV, thenBB, elseBB);
@ -545,6 +385,7 @@ void CodeGen::visit(IfStmt& node) {
} }
// Emit else block. // Emit else block.
theFunction->insert(theFunction->end(), elseBB);
builder->SetInsertPoint(elseBB); builder->SetInsertPoint(elseBB);
if (node.elseBranch) { if (node.elseBranch) {
node.elseBranch->accept(*this); node.elseBranch->accept(*this);
@ -555,6 +396,7 @@ void CodeGen::visit(IfStmt& node) {
} }
// Emit merge block. // Emit merge block.
theFunction->insert(theFunction->end(), mergeBB);
builder->SetInsertPoint(mergeBB); builder->SetInsertPoint(mergeBB);
} }
@ -562,8 +404,8 @@ void CodeGen::visit(WhileStmt& node) {
llvm::Function* theFunction = builder->GetInsertBlock()->getParent(); llvm::Function* theFunction = builder->GetInsertBlock()->getParent();
llvm::BasicBlock* condBB = llvm::BasicBlock::Create(*context, "loopcond", theFunction); llvm::BasicBlock* condBB = llvm::BasicBlock::Create(*context, "loopcond", theFunction);
llvm::BasicBlock* bodyBB = llvm::BasicBlock::Create(*context, "loopbody", theFunction); llvm::BasicBlock* bodyBB = llvm::BasicBlock::Create(*context, "loopbody");
llvm::BasicBlock* afterBB = llvm::BasicBlock::Create(*context, "loopafter", theFunction); llvm::BasicBlock* afterBB = llvm::BasicBlock::Create(*context, "loopafter");
// Jump to condition // Jump to condition
builder->CreateBr(condBB); builder->CreateBr(condBB);
@ -578,6 +420,7 @@ void CodeGen::visit(WhileStmt& node) {
builder->CreateCondBr(condV, bodyBB, afterBB); builder->CreateCondBr(condV, bodyBB, afterBB);
// Body Block // Body Block
theFunction->insert(theFunction->end(), bodyBB);
builder->SetInsertPoint(bodyBB); builder->SetInsertPoint(bodyBB);
breakStack.push_back(afterBB); breakStack.push_back(afterBB);
@ -587,6 +430,7 @@ void CodeGen::visit(WhileStmt& node) {
builder->CreateBr(condBB); // Loop back to condition builder->CreateBr(condBB); // Loop back to condition
// After Block // After Block
theFunction->insert(theFunction->end(), afterBB);
builder->SetInsertPoint(afterBB); builder->SetInsertPoint(afterBB);
} }
@ -599,8 +443,8 @@ void CodeGen::visit(ForStmt& node) {
} }
llvm::BasicBlock* condBB = llvm::BasicBlock::Create(*context, "loopcond", theFunction); llvm::BasicBlock* condBB = llvm::BasicBlock::Create(*context, "loopcond", theFunction);
llvm::BasicBlock* bodyBB = llvm::BasicBlock::Create(*context, "loopbody", theFunction); llvm::BasicBlock* bodyBB = llvm::BasicBlock::Create(*context, "loopbody");
llvm::BasicBlock* afterBB = llvm::BasicBlock::Create(*context, "loopafter", theFunction); llvm::BasicBlock* afterBB = llvm::BasicBlock::Create(*context, "loopafter");
// Jump to condition // Jump to condition
builder->CreateBr(condBB); builder->CreateBr(condBB);
@ -622,6 +466,7 @@ void CodeGen::visit(ForStmt& node) {
builder->CreateCondBr(condV, bodyBB, afterBB); builder->CreateCondBr(condV, bodyBB, afterBB);
// Body Block // Body Block
theFunction->insert(theFunction->end(), bodyBB);
builder->SetInsertPoint(bodyBB); builder->SetInsertPoint(bodyBB);
breakStack.push_back(afterBB); breakStack.push_back(afterBB);
@ -636,6 +481,7 @@ void CodeGen::visit(ForStmt& node) {
builder->CreateBr(condBB); // Loop back to condition builder->CreateBr(condBB); // Loop back to condition
// After Block // After Block
theFunction->insert(theFunction->end(), afterBB);
builder->SetInsertPoint(afterBB); builder->SetInsertPoint(afterBB);
} }
@ -658,8 +504,8 @@ void CodeGen::visit(ForInStmt& node) {
// 4. Create Loop Blocks // 4. Create Loop Blocks
llvm::BasicBlock* condBB = llvm::BasicBlock::Create(*context, "loopcond", theFunction); llvm::BasicBlock* condBB = llvm::BasicBlock::Create(*context, "loopcond", theFunction);
llvm::BasicBlock* bodyBB = llvm::BasicBlock::Create(*context, "loopbody", theFunction); llvm::BasicBlock* bodyBB = llvm::BasicBlock::Create(*context, "loopbody");
llvm::BasicBlock* afterBB = llvm::BasicBlock::Create(*context, "loopafter", theFunction); llvm::BasicBlock* afterBB = llvm::BasicBlock::Create(*context, "loopafter");
builder->CreateBr(condBB); builder->CreateBr(condBB);
@ -670,6 +516,7 @@ void CodeGen::visit(ForInStmt& node) {
builder->CreateCondBr(condV, bodyBB, afterBB); builder->CreateCondBr(condV, bodyBB, afterBB);
// 6. Body // 6. Body
theFunction->insert(theFunction->end(), bodyBB);
builder->SetInsertPoint(bodyBB); builder->SetInsertPoint(bodyBB);
// Fetch element at index // Fetch element at index
@ -721,6 +568,7 @@ void CodeGen::visit(ForInStmt& node) {
builder->CreateBr(condBB); builder->CreateBr(condBB);
// After Block // After Block
theFunction->insert(theFunction->end(), afterBB);
builder->SetInsertPoint(afterBB); builder->SetInsertPoint(afterBB);
} }
@ -940,42 +788,8 @@ void CodeGen::visit(IndexExpr& node) {
llvm::Value* arrPtr = lastValue; llvm::Value* arrPtr = lastValue;
std::string arrayType = lastClassName; std::string arrayType = lastClassName;
if (!arrPtr) {
std::cerr << "Error: Array evaluated to null in IndexExpr" << std::endl;
return;
}
node.index->accept(*this); node.index->accept(*this);
llvm::Value* indexVal = lastValue; llvm::Value* indexVal = lastValue;
std::string indexType = lastClassName;
if (!indexVal) {
std::cerr << "Error: Index evaluated to null in IndexExpr" << std::endl;
return;
}
if (indexType == "String") {
// Map lookup
llvm::Function* getFn = module->getFunction("sun_map_get");
if (!getFn) {
std::cerr << "Error: sun_map_get function not found!" << std::endl;
return;
}
llvm::Value* valPtr = builder->CreateCall(getFn, {arrPtr, indexVal}, "elem");
// We don't know the return type, assume generic (void*) or int?
// If it's JSON, it could be anything.
// Let's assume it returns void* and we might need to cast it if we use it as int.
// But wait, if we use it in an expression, we expect int or string.
// If we assume int, we need PtrToInt.
// If we assume String, we keep it as Ptr.
// For now, let's assume JSON values are either Strings or Ints (casted to Ptr).
// If we don't know, we return Ptr.
lastValue = valPtr;
lastClassName = "JSON"; // Keep it generic
return;
}
llvm::Function* getFn = module->getFunction("sun_array_get"); llvm::Function* getFn = module->getFunction("sun_array_get");
llvm::Value* valPtr = builder->CreateCall(getFn, {arrPtr, indexVal}, "elem"); llvm::Value* valPtr = builder->CreateCall(getFn, {arrPtr, indexVal}, "elem");
@ -986,9 +800,6 @@ void CodeGen::visit(IndexExpr& node) {
} else if (arrayType == "CSVArray") { } else if (arrayType == "CSVArray") {
lastValue = valPtr; // It's a void* (pointer to array) lastValue = valPtr; // It's a void* (pointer to array)
lastClassName = "StringArray"; lastClassName = "StringArray";
} else if (arrayType == "JSON") {
lastValue = valPtr;
lastClassName = "JSON";
} else { } else {
// Assume IntArray, cast back to i32 // Assume IntArray, cast back to i32
lastValue = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt"); lastValue = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt");
@ -1029,18 +840,18 @@ void CodeGen::visit(SwitchStmt& node) {
llvm::Function* theFunction = builder->GetInsertBlock()->getParent(); llvm::Function* theFunction = builder->GetInsertBlock()->getParent();
// 2. Create Merge Block (after switch) // 2. Create Merge Block (after switch)
llvm::BasicBlock* mergeBB = llvm::BasicBlock::Create(*context, "switchmerge", theFunction); llvm::BasicBlock* mergeBB = llvm::BasicBlock::Create(*context, "switchmerge");
// Push mergeBB to breakStack so 'break' jumps here // Push mergeBB to breakStack so 'break' jumps here
breakStack.push_back(mergeBB); breakStack.push_back(mergeBB);
// 3. Create Default Block // 3. Create Default Block
llvm::BasicBlock* defaultBB = llvm::BasicBlock::Create(*context, "switchdefault", theFunction); llvm::BasicBlock* defaultBB = llvm::BasicBlock::Create(*context, "switchdefault");
// 4. Create Blocks for Cases // 4. Create Blocks for Cases
std::vector<llvm::BasicBlock*> caseBBs; std::vector<llvm::BasicBlock*> caseBBs;
for (size_t i = 0; i < node.cases.size(); ++i) { for (size_t i = 0; i < node.cases.size(); ++i) {
caseBBs.push_back(llvm::BasicBlock::Create(*context, "case" + std::to_string(i), theFunction)); caseBBs.push_back(llvm::BasicBlock::Create(*context, "case" + std::to_string(i)));
} }
// 5. Generate Comparisons (If-Else Chain) // 5. Generate Comparisons (If-Else Chain)
@ -1075,6 +886,7 @@ void CodeGen::visit(SwitchStmt& node) {
// 6. Generate Case Bodies // 6. Generate Case Bodies
for (size_t i = 0; i < node.cases.size(); ++i) { for (size_t i = 0; i < node.cases.size(); ++i) {
theFunction->insert(theFunction->end(), caseBBs[i]);
builder->SetInsertPoint(caseBBs[i]); builder->SetInsertPoint(caseBBs[i]);
node.cases[i].body->accept(*this); node.cases[i].body->accept(*this);
@ -1090,6 +902,7 @@ void CodeGen::visit(SwitchStmt& node) {
} }
// 7. Generate Default Body // 7. Generate Default Body
theFunction->insert(theFunction->end(), defaultBB);
builder->SetInsertPoint(defaultBB); builder->SetInsertPoint(defaultBB);
if (node.defaultCase) { if (node.defaultCase) {
node.defaultCase->accept(*this); node.defaultCase->accept(*this);
@ -1101,6 +914,7 @@ void CodeGen::visit(SwitchStmt& node) {
// 8. Finish // 8. Finish
breakStack.pop_back(); breakStack.pop_back();
theFunction->insert(theFunction->end(), mergeBB);
builder->SetInsertPoint(mergeBB); builder->SetInsertPoint(mergeBB);
} }
@ -1113,6 +927,7 @@ void CodeGen::visit(BreakStmt& node) {
builder->CreateBr(breakStack.back()); builder->CreateBr(breakStack.back());
llvm::Function* theFunction = builder->GetInsertBlock()->getParent(); llvm::Function* theFunction = builder->GetInsertBlock()->getParent();
llvm::BasicBlock* deadBB = llvm::BasicBlock::Create(*context, "dead", theFunction); llvm::BasicBlock* deadBB = llvm::BasicBlock::Create(*context, "dead");
theFunction->insert(theFunction->end(), deadBB);
builder->SetInsertPoint(deadBB); builder->SetInsertPoint(deadBB);
} }

View File

@ -28,7 +28,6 @@ public:
void visit(ArrayExpr& node) override; void visit(ArrayExpr& node) override;
void visit(IndexExpr& node) override; void visit(IndexExpr& node) override;
void visit(ArrayAssignExpr& node) override; void visit(ArrayAssignExpr& node) override;
void visit(IncrementExpr& node) override;
void visit(BinaryExpr& node) override; void visit(BinaryExpr& node) override;
void visit(ReturnStmt& node) override; void visit(ReturnStmt& node) override;
void visit(VarDeclStmt& node) override; void visit(VarDeclStmt& node) override;

View File

@ -107,12 +107,7 @@ Token Lexer::scanToken() {
case '.': return makeToken(TokenType::DOT, "."); case '.': return makeToken(TokenType::DOT, ".");
case ':': return makeToken(TokenType::COLON, ":"); case ':': return makeToken(TokenType::COLON, ":");
case ';': return makeToken(TokenType::SEMICOLON, ";"); case ';': return makeToken(TokenType::SEMICOLON, ";");
case '+': case '+': return makeToken(TokenType::PLUS, "+");
if (peek() == '+') {
advance();
return makeToken(TokenType::PLUS_PLUS, "++");
}
return makeToken(TokenType::PLUS, "+");
case '-': return makeToken(TokenType::MINUS, "-"); case '-': return makeToken(TokenType::MINUS, "-");
case '*': return makeToken(TokenType::STAR, "*"); case '*': return makeToken(TokenType::STAR, "*");
case '/': case '/':
@ -127,18 +122,8 @@ Token Lexer::scanToken() {
return makeToken(TokenType::EQUAL_EQUAL, "=="); return makeToken(TokenType::EQUAL_EQUAL, "==");
} }
return makeToken(TokenType::EQUALS, "="); return makeToken(TokenType::EQUALS, "=");
case '<': case '<': return makeToken(TokenType::LESS, "<");
if (peek() == '=') { case '>': return makeToken(TokenType::GREATER, ">");
advance();
return makeToken(TokenType::LESS_EQUAL, "<=");
}
return makeToken(TokenType::LESS, "<");
case '>':
if (peek() == '=') {
advance();
return makeToken(TokenType::GREATER_EQUAL, ">=");
}
return makeToken(TokenType::GREATER, ">");
case '"': return string(); case '"': return string();
default: return makeToken(TokenType::UNKNOWN, std::string(1, c)); default: return makeToken(TokenType::UNKNOWN, std::string(1, c));
} }

View File

@ -40,63 +40,20 @@ char* str_concat(char* a, char* b) {
return result; return result;
} }
// Struct Definitions
typedef struct { typedef struct {
int type; // 0=int, 1=string, 2=array, 3=map, 4=null
union {
int i;
char* s;
void* ptr;
} as;
} JsonValue;
typedef struct {
unsigned int magic; // 0x12345678
int size; int size;
void** data; void** data;
} Array; } Array;
typedef struct {
char* key;
void* value;
} MapEntry;
typedef struct {
int size;
int capacity;
MapEntry* entries;
} Map;
// Forward declarations
void* sun_array_create(int size);
JsonValue* sun_json_array(void* arr);
JsonValue* sun_json_map(void* map);
JsonValue* sun_json_string(char* s);
JsonValue* sun_json_int(int i);
JsonValue* sun_json_null();
char* sun_strdup(const char* s);
// Array Functions
void* sun_array_create(int size) { void* sun_array_create(int size) {
Array* arr = (Array*)malloc(sizeof(Array)); Array* arr = (Array*)malloc(sizeof(Array));
arr->magic = 0x12345678;
arr->size = size; arr->size = size;
arr->data = (void**)calloc(size, sizeof(void*)); arr->data = (void**)calloc(size, sizeof(void*));
return (void*)arr; return (void*)arr;
} }
void sun_array_set(void* arrPtr, int index, void* value) { void sun_array_set(void* arrPtr, int index, void* value) {
if (!arrPtr) return;
Array* arr = (Array*)arrPtr; Array* arr = (Array*)arrPtr;
if (arr->magic != 0x12345678) {
JsonValue* v = (JsonValue*)arrPtr;
if (v->type == 2) {
arr = (Array*)v->as.ptr;
} else {
printf("Error: Not an array (set)\n");
exit(1);
}
}
if (index >= 0 && index < arr->size) { if (index >= 0 && index < arr->size) {
arr->data[index] = value; arr->data[index] = value;
} else { } else {
@ -106,116 +63,19 @@ void sun_array_set(void* arrPtr, int index, void* value) {
} }
void* sun_array_get(void* arrPtr, int index) { void* sun_array_get(void* arrPtr, int index) {
if (!arrPtr) return NULL;
Array* arr = (Array*)arrPtr; Array* arr = (Array*)arrPtr;
if (arr->magic != 0x12345678) {
JsonValue* v = (JsonValue*)arrPtr;
if (v->type == 2) {
arr = (Array*)v->as.ptr;
} else {
printf("Error: Not an array (get) type=%d magic=%x\n", v->type, arr->magic);
exit(1);
}
}
if (index >= 0 && index < arr->size) { if (index >= 0 && index < arr->size) {
return arr->data[index]; return arr->data[index];
} else { } else {
printf("Error: Array index out of bounds: %d\n", index); printf("Error: Array index out of bounds: %d\n", index);
exit(1); exit(1);
} }
}
int sun_array_length(void* arrPtr) {
if (!arrPtr) return 0;
Array* arr = (Array*)arrPtr;
if (arr->magic != 0x12345678) {
JsonValue* v = (JsonValue*)arrPtr;
if (v->type == 2) {
arr = (Array*)v->as.ptr;
} else {
printf("Error: Not an array (len)\n");
exit(1);
}
}
return arr->size;
}
// Map Functions
void* sun_map_create() {
Map* map = (Map*)malloc(sizeof(Map));
map->size = 0;
map->capacity = 8;
map->entries = (MapEntry*)malloc(sizeof(MapEntry) * map->capacity);
return (void*)map;
}
void sun_map_set(void* mapPtr, char* key, void* value) {
Map* map = (Map*)mapPtr;
for (int i = 0; i < map->size; i++) {
if (strcmp(map->entries[i].key, key) == 0) {
map->entries[i].value = value;
return;
}
}
if (map->size >= map->capacity) {
map->capacity *= 2;
map->entries = (MapEntry*)realloc(map->entries, sizeof(MapEntry) * map->capacity);
}
map->entries[map->size].key = sun_strdup(key);
map->entries[map->size].value = value;
map->size++;
}
void* sun_map_get(void* mapPtr, char* key) {
if (!mapPtr) return NULL;
JsonValue* v = (JsonValue*)mapPtr;
if (v->type == 3) {
mapPtr = v->as.ptr;
}
Map* map = (Map*)mapPtr;
for (int i = 0; i < map->size; i++) {
if (strcmp(map->entries[i].key, key) == 0) {
return map->entries[i].value;
}
}
return NULL; return NULL;
} }
// JSON Constructors int sun_array_length(void* arrPtr) {
JsonValue* sun_json_int(int i) { Array* arr = (Array*)arrPtr;
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue)); return arr->size;
v->type = 0; v->as.i = i; return v;
}
JsonValue* sun_json_string(char* s) {
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
v->type = 1; v->as.s = s; return v;
}
JsonValue* sun_json_array(void* arr) {
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
v->type = 2; v->as.ptr = arr; return v;
}
JsonValue* sun_json_map(void* map) {
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
v->type = 3; v->as.ptr = map; return v;
}
JsonValue* sun_json_null() {
JsonValue* v = (JsonValue*)malloc(sizeof(JsonValue));
v->type = 4; return v;
}
void sun_print_json(void* ptr) {
if (!ptr) { printf("null\n"); return; }
JsonValue* v = (JsonValue*)ptr;
if (v->type == 0) printf("%d\n", v->as.i);
else if (v->type == 1) printf("%s\n", v->as.s);
else if (v->type == 2) printf("[Array]\n");
else if (v->type == 3) printf("[Object]\n");
else if (v->type == 4) printf("null\n");
else printf("Unknown JSON type: %d\n", v->type);
} }
char* sun_strdup(const char* s) { char* sun_strdup(const char* s) {
@ -225,122 +85,6 @@ char* sun_strdup(const char* s) {
return d; return d;
} }
// JSON Parser
char* json_pos;
void skip_whitespace() {
while (*json_pos && (*json_pos == ' ' || *json_pos == '\t' || *json_pos == '\n' || *json_pos == '\r')) {
json_pos++;
}
}
void* parse_json_value();
char* parse_json_string() {
skip_whitespace();
if (*json_pos != '"') return NULL;
json_pos++;
char* start = json_pos;
while (*json_pos && *json_pos != '"') {
json_pos++;
}
if (*json_pos == '"') {
*json_pos = '\0';
char* str = sun_strdup(start);
*json_pos = '"';
json_pos++;
return str;
}
return NULL;
}
void* parse_json_object() {
skip_whitespace();
if (*json_pos != '{') return NULL;
json_pos++;
void* map = sun_map_create();
skip_whitespace();
if (*json_pos == '}') {
json_pos++;
return sun_json_map(map);
}
while (1) {
skip_whitespace();
char* key = parse_json_string();
skip_whitespace();
if (*json_pos != ':') { printf("Expected : in JSON object\n"); exit(1); }
json_pos++;
void* value = parse_json_value();
sun_map_set(map, key, value);
skip_whitespace();
if (*json_pos == ',') { json_pos++; continue; }
else if (*json_pos == '}') { json_pos++; break; }
else { printf("Expected , or } in JSON object\n"); exit(1); }
}
return sun_json_map(map);
}
void* parse_json_array() {
skip_whitespace();
if (*json_pos != '[') return NULL;
json_pos++;
int capacity = 8;
int size = 0;
void** temp = (void**)malloc(sizeof(void*) * capacity);
skip_whitespace();
if (*json_pos == ']') {
json_pos++;
void* arr = sun_array_create(0);
free(temp);
return sun_json_array(arr);
}
while (1) {
void* val = parse_json_value();
if (size >= capacity) {
capacity *= 2;
temp = (void**)realloc(temp, sizeof(void*) * capacity);
}
temp[size++] = val;
skip_whitespace();
if (*json_pos == ',') { json_pos++; continue; }
else if (*json_pos == ']') { json_pos++; break; }
else { printf("Expected , or ] in JSON array\n"); exit(1); }
}
void* arr = sun_array_create(size);
Array* a = (Array*)arr;
for(int i=0; i<size; i++) a->data[i] = temp[i];
free(temp);
return sun_json_array(arr);
}
void* parse_json_value() {
skip_whitespace();
if (*json_pos == '{') return parse_json_object();
if (*json_pos == '[') return parse_json_array();
if (*json_pos == '"') return sun_json_string(parse_json_string());
if ((*json_pos >= '0' && *json_pos <= '9') || *json_pos == '-') {
int val = strtol(json_pos, &json_pos, 10);
return sun_json_int(val);
}
if (strncmp(json_pos, "true", 4) == 0) { json_pos += 4; return sun_json_int(1); }
if (strncmp(json_pos, "false", 5) == 0) { json_pos += 5; return sun_json_int(0); }
if (strncmp(json_pos, "null", 4) == 0) { json_pos += 4; return sun_json_null(); }
return NULL;
}
void* sun_read_json(char* filename) {
FILE* fp = fopen(filename, "r");
if (!fp) { printf("Error: Could not open file %s\n", filename); exit(1); }
fseek(fp, 0, SEEK_END);
long length = ftell(fp);
fseek(fp, 0, SEEK_SET);
char* buffer = (char*)malloc(length + 1);
fread(buffer, 1, length, fp);
buffer[length] = '\0';
fclose(fp);
json_pos = buffer;
void* result = parse_json_value();
free(buffer);
return result;
}
void* sun_read_csv(char* filename, char* separator, char* quote) { void* sun_read_csv(char* filename, char* separator, char* quote) {
FILE* fp = fopen(filename, "r"); FILE* fp = fopen(filename, "r");
if (!fp) { if (!fp) {

View File

@ -366,7 +366,7 @@ std::unique_ptr<Expr> Parser::equality() {
std::unique_ptr<Expr> Parser::comparison() { std::unique_ptr<Expr> Parser::comparison() {
std::unique_ptr<Expr> expr = term(); std::unique_ptr<Expr> expr = term();
while (match(TokenType::LESS) || match(TokenType::GREATER) || match(TokenType::LESS_EQUAL) || match(TokenType::GREATER_EQUAL)) { while (match(TokenType::LESS) || match(TokenType::GREATER)) {
std::string op = previous().value; std::string op = previous().value;
std::unique_ptr<Expr> right = term(); std::unique_ptr<Expr> right = term();
expr = std::make_unique<BinaryExpr>(std::move(expr), op, std::move(right)); expr = std::make_unique<BinaryExpr>(std::move(expr), op, std::move(right));
@ -410,8 +410,6 @@ std::unique_ptr<Expr> Parser::call() {
std::unique_ptr<Expr> index = expression(); std::unique_ptr<Expr> index = expression();
consume(TokenType::RBRACKET, "Expect ']' after index."); consume(TokenType::RBRACKET, "Expect ']' after index.");
expr = std::make_unique<IndexExpr>(std::move(expr), std::move(index)); expr = std::make_unique<IndexExpr>(std::move(expr), std::move(index));
} else if (match(TokenType::PLUS_PLUS)) {
expr = std::make_unique<IncrementExpr>(std::move(expr));
} else { } else {
break; break;
} }

View File

@ -41,9 +41,6 @@ enum class TokenType {
EQUAL_EQUAL,// == EQUAL_EQUAL,// ==
LESS, // < LESS, // <
GREATER, // > GREATER, // >
LESS_EQUAL, // <=
GREATER_EQUAL, // >=
PLUS_PLUS, // ++
END_OF_FILE, END_OF_FILE,
UNKNOWN UNKNOWN
}; };

View File

@ -1,6 +1,6 @@
#ifndef SUN_VERSION_H #ifndef SUN_VERSION_H
#define SUN_VERSION_H #define SUN_VERSION_H
#define SUN_VERSION "0.5.0" #define SUN_VERSION "0.3.0"
#endif // SUN_VERSION_H #endif // SUN_VERSION_H

BIN
sun

Binary file not shown.

View File

@ -1,9 +0,0 @@
{
"name": "SunLang",
"version": 1,
"features": ["csv", "json"],
"nested": {
"key": "value"
},
"list": [10, 20, 30]
}

View File

@ -1,4 +1,7 @@
print("Counting:"); function main() {
for (var i = 0; i <= 5; i++) { print("Counting:");
for (var i = 0; i < 5; i = i + 1) {
print(i); print(i);
}
return 0;
} }

View File

@ -1,15 +0,0 @@
function main() {
var data = readjson("./tests/test.json");
print(data["name"]);
print(data["version"]);
var list = data["list"];
print(list[0]);
print(list[1]);
var nested = data["nested"];
print(nested["key"]);
return 0;
}