diff --git a/samples/hello.brc b/samples/hello.brc index 0ed1ff9..b8fa9d7 100644 --- a/samples/hello.brc +++ b/samples/hello.brc @@ -1,9 +1,9 @@ @extern putchar fun: character sint32 -> sint32 main fun -> sint32 - text data <- "Hello string!\n" - - rep i sint32 <- 0, i < 14: + text data <- "Hello, world!\n" + + rep i sint32 <- 0, text[i] != 0: putchar(text[i]) i <- i + 1 ; diff --git a/samples/test.brc b/samples/test.brc index 724f225..f71b061 100644 --- a/samples/test.brc +++ b/samples/test.brc @@ -1,5 +1,23 @@ @extern putchar fun: character sint32 -> sint32 +/* +User type + name data + age u32 + successRatio r32 + isActive bool +; +*/ + +/* +i u32 <- 0, rep text[i] != 0: + putchar(text[i]) + i++ +; +*/ + +// text data <- "Hello world!" + main fun -> sint32 text data <- "Hello string!\n" diff --git a/src/Compiler/ModuleBuilder.cpp b/src/Compiler/ModuleBuilder.cpp index defeae3..0215dda 100644 --- a/src/Compiler/ModuleBuilder.cpp +++ b/src/Compiler/ModuleBuilder.cpp @@ -132,12 +132,15 @@ void ModuleBuilder::buildVarDeclaration(shared_ptr statement) llvm::ArrayType *type = (llvm::ArrayType *)typeForValueType(statement->getValueType(), values.size()); llvm::AllocaInst *alloca = builder->CreateAlloca(type, nullptr, statement->getName()); + if (!setAlloca(statement->getName(), alloca)) + return; for (int i=0; i < type->getNumElements(); i++) { llvm::Value *index[] = { builder->getInt32(0), builder->getInt32(i) }; llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}_{}", statement->getName(), i)); + builder->CreateStore(values[i], elementPtr); } } else { @@ -150,10 +153,6 @@ void ModuleBuilder::buildVarDeclaration(shared_ptr statement) } } -void ModuleBuilder::buildArrayDeclaration(shared_ptr statement) { - -} - void ModuleBuilder::buildAssignment(shared_ptr statement) { llvm::AllocaInst *alloca = getAlloca(statement->getName()); if (alloca == nullptr) @@ -254,7 +253,6 @@ llvm::Value *ModuleBuilder::valueForExpression(shared_ptr expression switch (expression->getKind()) { case ExpressionKind::LITERAL: return valueForLiteral(dynamic_pointer_cast(expression)); - case ExpressionKind::GROUPING: return valueForExpression(dynamic_pointer_cast(expression)->getExpression()); case ExpressionKind::BINARY: @@ -313,6 +311,9 @@ llvm::Value *ModuleBuilder::valueForBinary(shared_ptr expressi llvm::Value *leftValue = valueForExpression(expression->getLeft()); llvm::Value *rightValue = valueForExpression(expression->getRight()); + if (leftValue == nullptr || rightValue == nullptr) + return nullptr; + llvm::Type *type = leftValue->getType(); if (type == typeBool) { @@ -450,7 +451,19 @@ llvm::Value *ModuleBuilder::valueForVar(shared_ptr expressio if (alloca == nullptr) return nullptr; - return builder->CreateLoad(alloca->getAllocatedType(), alloca, expression->getName()); + if (expression->getIndexExpression()) { + llvm::Value *indexValue = valueForExpression(expression->getIndexExpression()); + llvm::Value *index[] = { + builder->getInt32(0), + indexValue + }; + llvm::ArrayType *type = (llvm::ArrayType *)alloca->getAllocatedType(); + llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}[]", expression->getName())); + + return builder->CreateLoad(type->getArrayElementType(), elementPtr); + } else { + return builder->CreateLoad(alloca->getAllocatedType(), alloca, expression->getName()); + } } llvm::Value *ModuleBuilder::valueForCall(shared_ptr expression) { diff --git a/src/Compiler/ModuleBuilder.h b/src/Compiler/ModuleBuilder.h index 4550822..783e984 100644 --- a/src/Compiler/ModuleBuilder.h +++ b/src/Compiler/ModuleBuilder.h @@ -62,7 +62,6 @@ private: void buildStatement(shared_ptr statement); void buildFunctionDeclaration(shared_ptr statement); void buildVarDeclaration(shared_ptr statement); - void buildArrayDeclaration(shared_ptr statement); void buildAssignment(shared_ptr statement); void buildBlock(shared_ptr statement); void buildReturn(shared_ptr statement); diff --git a/src/Logger.cpp b/src/Logger.cpp index ef0883f..9055750 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -376,7 +376,11 @@ string Logger::toString(shared_ptr expression) { } string Logger::toString(shared_ptr expression) { - return format("VAR({})", expression->getName()); + string text = format("VAR({}", expression->getName()); + if (expression->getIndexExpression() != nullptr) + text += format("|{}", toString(expression->getIndexExpression())); + text += ")"; + return text; } string Logger::toString(shared_ptr expression) { diff --git a/src/Parser/Expression/ExpressionArrayLiteral.cpp b/src/Parser/Expression/ExpressionArrayLiteral.cpp index 90fb29d..da5e9df 100644 --- a/src/Parser/Expression/ExpressionArrayLiteral.cpp +++ b/src/Parser/Expression/ExpressionArrayLiteral.cpp @@ -26,6 +26,13 @@ shared_ptr ExpressionArrayLiteral::expressionArrayLitera shared_ptr token = make_shared(TokenKind::INTEGER_CHAR, lexme, tokenString->getLine(), tokenString->getColumn() + i); shared_ptr expression = ExpressionLiteral::expressionLiteralForToken(token); expressions.push_back(expression); + + // add terminal 0 if missing + if (i == stringValue.length() - 2 && lexme.compare("\\0") != 0) { + shared_ptr token = make_shared(TokenKind::INTEGER_CHAR, "\\0", tokenString->getLine(), tokenString->getColumn() + i + lexme.length()); + shared_ptr expression = ExpressionLiteral::expressionLiteralForToken(token); + expressions.push_back(expression); + } } expression->expressions = expressions; diff --git a/src/Parser/Expression/ExpressionVariable.cpp b/src/Parser/Expression/ExpressionVariable.cpp index b75cddf..61a03e2 100644 --- a/src/Parser/Expression/ExpressionVariable.cpp +++ b/src/Parser/Expression/ExpressionVariable.cpp @@ -1,8 +1,12 @@ #include "ExpressionVariable.h" -ExpressionVariable::ExpressionVariable(string name): -Expression(ExpressionKind::VAR, nullptr), name(name) { } +ExpressionVariable::ExpressionVariable(string name, shared_ptr indexExpression): +Expression(ExpressionKind::VAR, nullptr), name(name), indexExpression(indexExpression) { } string ExpressionVariable::getName() { return name; } + +shared_ptr ExpressionVariable::getIndexExpression() { + return indexExpression; +} diff --git a/src/Parser/Expression/ExpressionVariable.h b/src/Parser/Expression/ExpressionVariable.h index bd0b99f..5835d9a 100644 --- a/src/Parser/Expression/ExpressionVariable.h +++ b/src/Parser/Expression/ExpressionVariable.h @@ -3,8 +3,10 @@ class ExpressionVariable: public Expression { private: string name; + shared_ptr indexExpression; public: - ExpressionVariable(string name); + ExpressionVariable(string name, shared_ptr indexExpression); string getName(); + shared_ptr getIndexExpression(); }; \ No newline at end of file diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 916b078..d7aecec 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -292,7 +292,7 @@ shared_ptr Parser::matchStatementRepeat() { // got initial, expect comma if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) { markError(TokenKind::COMMA, {}); - return nullptr; + goto afterIf; } // optional new line @@ -305,7 +305,7 @@ shared_ptr Parser::matchStatementRepeat() { // got pre-condition, expect comma if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) { markError(TokenKind::COMMA, {}); - return nullptr; + goto afterIf; } // optional new line @@ -317,10 +317,11 @@ shared_ptr Parser::matchStatementRepeat() { // expect colon if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) { markError(TokenKind::COLON, {}); - return nullptr; + goto afterIf; } } } + afterIf: isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); @@ -416,25 +417,26 @@ shared_ptr Parser::matchFactor() { shared_ptr Parser::matchPrimary() { shared_ptr expression; + int errorsCount = errors.size(); expression = matchExpressionGrouping(); - if (expression != nullptr) + if (expression != nullptr || errors.size() > errorsCount) return expression; expression = matchExpressionArrayLiteral(); - if (expression != nullptr) + if (expression != nullptr || errors.size() > errorsCount) return expression; expression = matchExpressionLiteral(); - if (expression != nullptr) + if (expression != nullptr || errors.size() > errorsCount) return expression; expression = matchExpressionCall(); - if (expression != nullptr) + if (expression != nullptr || errors.size() > errorsCount) return expression; expression = matchExpressionVariable(); - if (expression != nullptr) + if (expression != nullptr || errors.size() > errorsCount) return expression; return nullptr; @@ -490,12 +492,23 @@ shared_ptr Parser::matchExpressionArrayLiteral() { } shared_ptr Parser::matchExpressionVariable() { - shared_ptr token = tokens.at(currentIndex); + if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, false)) + return nullptr; + shared_ptr idToken = tokens.at(currentIndex++); + shared_ptr indexExpression; - if (tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, true)) - return make_shared(token->getLexme()); + if (tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) { + indexExpression = nextExpression(); + if (indexExpression == nullptr) + return nullptr; + + if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) { + markError(TokenKind::RIGHT_SQUARE_BRACKET, {}); + return nullptr; + } + } - return nullptr; + return make_shared(idToken->getLexme(), indexExpression); } shared_ptr Parser::matchExpressionCall() { diff --git a/src/Utils.cpp b/src/Utils.cpp index ab42c4c..d3ccdbd 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -25,6 +25,8 @@ optional Utils::charStringToInt(string charString) { return '\''; case '\"': return '\"'; + case '0': + return '\0'; default: return {}; }