Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 3 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,9 @@ name: CI

on:
push:
paths:
- "**.zz"
- "src/**"
- "test/zz/**"
- "include/**"
- "main.cpp"
- "**.yml"
- "**.py"
- "CMakeLists.txt"
pull_request: {}
branches: [main]
pull_request:
branches: [main]

jobs:
test-linux-llvm:
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,6 @@
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp"
}
},
"C_Cpp.default.compilerPath": "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.44.35207\\bin\\Hostx86\\x64\\cl.exe"
}
3 changes: 2 additions & 1 deletion include/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@
#include <iostream>
#include <memory>
#include <fstream>
#include <assert.h>
#include <assert.h>
#include <iomanip>
2 changes: 1 addition & 1 deletion include/ast/ASTNode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace zlang
: type(t), value(val), scope(sc) {}

static std::unique_ptr<ASTNode> makeProgramNode(const std::shared_ptr<ScopeContext> scope);
static std::unique_ptr<ASTNode> makeVariableDeclarationNode(
static std::optional<std::unique_ptr<ASTNode>> makeVariableDeclarationNode(
const std::string &name,
std::unique_ptr<ASTNode> typeAnnotation,
std::unique_ptr<ASTNode> initializer, const std::shared_ptr<ScopeContext> scope);
Expand Down
35 changes: 11 additions & 24 deletions include/codegen/CodeGen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ namespace zlang
std::ostringstream outGlobal;
std::ostringstream out;

std::string adjustReg(std::string &r64, uint64_t bits)
std::string adjustReg(const std::string &r64, uint64_t bits)
{
r64 = RegisterAllocator::getBaseReg(r64);
std::string baseRegister = RegisterAllocator::getBaseReg(r64);
static const std::unordered_map<std::string, std::array<std::string, 4>> registers_based_on_bytes = {
{"rax", {"rax", "eax", "ax", "al"}},
{"rbx", {"rbx", "ebx", "bx", "bl"}},
Expand All @@ -61,9 +61,9 @@ namespace zlang
{"r14", {"r14", "r14d", "r14w", "r14b"}},
{"r15", {"r15", "r15d", "r15w", "r15b"}}};

auto it = registers_based_on_bytes.find(r64);
auto it = registers_based_on_bytes.find(baseRegister);
if (it == registers_based_on_bytes.end())
throw std::runtime_error("Unknown register '" + r64 + "'\n\n" + out.str());
throw std::runtime_error("Unknown register '" + baseRegister + "'\n\n" + out.str());
const auto &ents = it->second;

switch (bits)
Expand Down Expand Up @@ -111,8 +111,6 @@ namespace zlang

void noteType(const std::string &register_, const TypeInfo &type_) { regType[register_] = type_; }

virtual std::string intToXmm(const std::string &r_int, uint32_t bits) = 0;

virtual void generateStatement(std::unique_ptr<ASTNode> statement) = 0;

virtual std::string emitExpression(std::unique_ptr<ASTNode> node) = 0;
Expand Down Expand Up @@ -142,15 +140,10 @@ namespace zlang
{
private:
std::unordered_map<std::uint32_t, char> integer_suffixes = {{8, 'b'}, {16, 'w'}, {32, 'l'}, {64, 'q'}};
std::string intToXmm(const std::string &r_int, uint32_t bits) override;

void generateStatement(std::unique_ptr<ASTNode> statement) override;

std::string emitExpression(std::unique_ptr<ASTNode> node) override;

void emitEpilogue() override;
void emitPrologue(std::unique_ptr<ASTNode> blockNode) override;

std::string generateIntegerLiteral(std::unique_ptr<ASTNode> node) override;
std::string generateFloatLiteral(std::unique_ptr<ASTNode> node) override;
std::string generateStringLiteral(std::unique_ptr<ASTNode> node) override;
Expand All @@ -161,26 +154,22 @@ namespace zlang
void generateIfStatement(std::unique_ptr<ASTNode> node) override;
std::string generateBinaryOperation(std::unique_ptr<ASTNode> node) override;
std::string generateUnaryOperation(std::unique_ptr<ASTNode> node) override;
std::string castValue(const std::string &val, const TypeInfo &fromType, const TypeInfo &toType);

public:
~CodeGenLinux() override = default;
CodeGenLinux(std::ostream &outstream) : CodeGen(RegisterAllocator::forSysV(), outstream){};
CodeGenLinux(std::ostream &outstream) : CodeGen(RegisterAllocator::forSysV(), outstream) {};
void generate(std::unique_ptr<ASTNode> program) override;
};

class CodeGenWindows : public CodeGen
{
private:
std::unordered_map<std::uint32_t, char> integer_suffixes = {{8, 'b'}, {16, 'w'}, {32, 'l'}, {64, 'q'}};
std::string intToXmm(const std::string &r_int, uint32_t bits) override;

void generateStatement(std::unique_ptr<ASTNode> statement) override;

std::string emitExpression(std::unique_ptr<ASTNode> node) override;

void emitEpilogue() override;
void emitPrologue(std::unique_ptr<ASTNode> blockNode) override;

std::string generateIntegerLiteral(std::unique_ptr<ASTNode> node) override;
std::string generateFloatLiteral(std::unique_ptr<ASTNode> node) override;
std::string generateStringLiteral(std::unique_ptr<ASTNode> node) override;
Expand All @@ -191,10 +180,12 @@ namespace zlang
void generateIfStatement(std::unique_ptr<ASTNode> node) override;
std::string generateBinaryOperation(std::unique_ptr<ASTNode> node) override;
std::string generateUnaryOperation(std::unique_ptr<ASTNode> node) override;
std::string castValue(const std::string &reg, const TypeInfo &fromType, const TypeInfo &toType);
std::string getVariableAddress(const ScopeContext &scope, const std::string &name) const;

public:
~CodeGenWindows() override = default;
CodeGenWindows(std::ostream &outstream) : CodeGen(RegisterAllocator::forMSVC(), outstream){};
CodeGenWindows(std::ostream &outstream) : CodeGen(RegisterAllocator::forMSVC(), outstream) {};
void generate(std::unique_ptr<ASTNode> program) override;
};

Expand All @@ -203,15 +194,10 @@ namespace zlang
private:
std::unordered_map<std::uint32_t, char> integer_suffixes = {{8, 'b'}, {16, 'w'}, {32, 'l'}, {64, 'q'}};
std::unordered_map<std::string, std::string> stringLiterals;
std::string intToXmm(const std::string &r_int, uint32_t bits) override;

void generateStatement(std::unique_ptr<ASTNode> statement) override;

std::string emitExpression(std::unique_ptr<ASTNode> node) override;

void emitEpilogue() override;
void emitPrologue(std::unique_ptr<ASTNode> blockNode) override;

std::string generateIntegerLiteral(std::unique_ptr<ASTNode> node) override;
std::string generateFloatLiteral(std::unique_ptr<ASTNode> node) override;
std::string generateStringLiteral(std::unique_ptr<ASTNode> node) override;
Expand All @@ -222,10 +208,11 @@ namespace zlang
void generateIfStatement(std::unique_ptr<ASTNode> node) override;
std::string generateBinaryOperation(std::unique_ptr<ASTNode> node) override;
std::string generateUnaryOperation(std::unique_ptr<ASTNode> node) override;
std::string castValue(const std::string &val, const TypeInfo &fromType, const TypeInfo &toType);

public:
~CodeGenLLVM() override = default;
CodeGenLLVM(std::ostream &outstream) : CodeGen(RegisterAllocator(), outstream){};
CodeGenLLVM(std::ostream &outstream) : CodeGen(RegisterAllocator(), outstream) {};
void generate(std::unique_ptr<ASTNode> program) override;
};
} // namespace zlang
4 changes: 2 additions & 2 deletions include/lexer/Lexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace zlang
size_t line;
size_t column;

std::string toString() const
std::string to_string() const
{
return "Token { kind = " + kindToString(kind) +
", text = \"" + text +
Expand Down Expand Up @@ -95,7 +95,7 @@ namespace zlang

inline std::ostream &operator<<(std::ostream &os, const Token &token)
{
return os << token.toString();
return os << token.to_string();
}
using Error = zlang::Error;
class Lexer
Expand Down
5 changes: 3 additions & 2 deletions include/parser/Parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace zlang
}

private:
int blockNumber = 0;
Lexer &lexer;
Token currentToken;
std::shared_ptr<ScopeContext> currentScope;
Expand All @@ -32,14 +33,14 @@ namespace zlang
std::unique_ptr<ASTNode> parseVariableDeclaration();
std::unique_ptr<ASTNode> parseVariableReassignment();
std::unique_ptr<ASTNode> parseConditionals();
std::unique_ptr<ASTNode> parseExpression();
std::unique_ptr<ASTNode> parseExpression(bool expect_exclaim = false);
std::unique_ptr<ASTNode> parsePrimary();

int getPrecedence(const std::string &op) const;
std::unique_ptr<ASTNode> parseUnary();
std::unique_ptr<ASTNode> parseBinaryRHS(int exprPrec, std::unique_ptr<ASTNode> lhs);

void enterScope();
void enterScope(std::string name);
void exitScope();
std::unique_ptr<ASTNode> parseBlock();
};
Expand Down
17 changes: 12 additions & 5 deletions include/parser/ScopeContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <memory>
#include <stdexcept>
#include <vector>
#include <optional>
#include <map>

namespace zlang
{
Expand All @@ -28,25 +30,29 @@ namespace zlang
bool isFloat;
bool isSigned;

std::string to_string()
std::string to_string() const
{
std::string ret = "";
ret += "TypeInfo( .bits: " + std::to_string(bits) + ", .align: " + std::to_string(align) + ", .isFloat: " + (isFloat ? "true" : "false") + ", .isSigned: " + (isSigned ? "true" : "false") + " )\n";
return ret;
}
};

static int variableNumber = 0;

class ScopeContext
{
public:
ScopeContext(std::shared_ptr<ScopeContext> parent = nullptr) : stackOffset(0), parent_(parent) {};

std::string name;
ScopeContext(std::shared_ptr<ScopeContext> parent = nullptr) : stackOffset(0), parent_(parent){};
ScopeContext(std::shared_ptr<ScopeContext> parent = nullptr, std::string name = "") : name(name), stackOffset(0), parent_(parent){};
std::unordered_map<std::string, std::string> name_mappings;
std::int64_t stackOffset;
std::shared_ptr<ScopeContext> parent_;
void defineVariable(const std::string &name, const VariableInfo &info);
bool defineVariable(const std::string &name, const VariableInfo &info);
void defineFunction(const std::string &name, const FunctionInfo &info);
void defineType(const std::string &name, const TypeInfo &info);

std::string getMapping(std::string varName);
VariableInfo lookupVariable(const std::string &name) const;
FunctionInfo lookupFunction(const std::string &name) const;
TypeInfo lookupType(const std::string &name) const;
Expand Down Expand Up @@ -101,6 +107,7 @@ namespace zlang
}
std::cout << std::endl;
}
std::optional<VariableInfo> lookupVariableInCurrentContext(const std::string &name) const;

private:
std::unordered_map<std::string, VariableInfo> vars_;
Expand Down
12 changes: 6 additions & 6 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ int main(int argc, char *argv[])
return 1;
}

if (!program.get())
{
zlang::logError(Error(ErrorType::Generic, "Parsing Failed"));
return 1;
}
if (cli.printAST())
{
if (!program.get())
{
zlang::logError(Error(ErrorType::Generic, "Parsing Failed"));
return 1;
}
program.get()->print(std::cout);
}
program.get()->print(std::cout);

// Type checking
TypeChecker typeChecker;
Expand Down
51 changes: 38 additions & 13 deletions src/ast/ASTNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,58 @@ namespace zlang

void ASTNode::setElseBranch(std::unique_ptr<ASTNode> elseNode)
{
children.push_back(std::move(elseNode));
if (children.size() < 2)
{
throw std::logic_error("setElseBranch on a non‑conditional node");
}

if (children.size() == 2)
{
// no else/elif attached yet: attach here
children.push_back(std::move(elseNode));
}
else
{
// we already have an elseBranch in children[2]:
// forward the new elseNode into _that_ node
ASTNode *existing = children[2].get();
existing->setElseBranch(std::move(elseNode));
}
}

ASTNode *ASTNode::getElseBranch() const
{
if (children.empty() or children.back().get() == nullptr)
if (children.size() < 3 || children[2] == nullptr)
return nullptr;
if (children.back().get()->type != NodeType::ElseIfStatement || children.back().get()->type != NodeType::ElseStatement)
{

auto *branch = children[2].get();
if (branch->type != NodeType::ElseIfStatement && branch->type != NodeType::ElseStatement)
return nullptr;
}
return children.back().get();

return branch;
}

std::unique_ptr<ASTNode> ASTNode::makeVariableDeclarationNode(
std::optional<std::unique_ptr<ASTNode>>
ASTNode::makeVariableDeclarationNode(
const std::string &name,
std::unique_ptr<ASTNode> typeAnnotation,
std::unique_ptr<ASTNode> initializer,
const std::shared_ptr<ScopeContext> scope)
{
auto node = std::make_unique<ASTNode>(NodeType::VariableDeclaration, name, scope);
scope.get()->defineVariable(name, {typeAnnotation.get()->value});
if (typeAnnotation)
node->addChild(std::move(typeAnnotation));
if (initializer)
node->addChild(std::move(initializer));
return node;
bool result = scope.get()->defineVariable(name, {typeAnnotation.get()->value});
if (result)
{
if (typeAnnotation)
node->addChild(std::move(typeAnnotation));
if (initializer)
node->addChild(std::move(initializer));
return node;
}
else
{
return std::nullopt;
}
}

std::unique_ptr<ASTNode> ASTNode::makeSymbolNode(const std::string &name, const std::shared_ptr<ScopeContext> scope)
Expand Down
Loading