Read array elements

This commit is contained in:
Rafał Grodziński
2025-07-09 17:47:59 +09:00
parent 870ecce8e4
commit 5db6703d48
10 changed files with 88 additions and 26 deletions

View File

@@ -1,9 +1,9 @@
@extern putchar fun: character sint32 -> sint32 @extern putchar fun: character sint32 -> sint32
main fun -> sint32 main fun -> sint32
text data<sint32> <- "Hello string!\n" text data<sint32> <- "Hello, world!\n"
rep i sint32 <- 0, i < 14: rep i sint32 <- 0, text[i] != 0:
putchar(text[i]) putchar(text[i])
i <- i + 1 i <- i + 1
; ;

View File

@@ -1,5 +1,23 @@
@extern putchar fun: character sint32 -> sint32 @extern putchar fun: character sint32 -> sint32
/*
User type
name data<u8, 32>
age u32
successRatio r32
isActive bool
;
*/
/*
i u32 <- 0, rep text[i] != 0:
putchar(text[i])
i++
;
*/
// text data<u8> <- "Hello world!"
main fun -> sint32 main fun -> sint32
text data<sint32> <- "Hello string!\n" text data<sint32> <- "Hello string!\n"

View File

@@ -132,12 +132,15 @@ void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement)
llvm::ArrayType *type = (llvm::ArrayType *)typeForValueType(statement->getValueType(), values.size()); llvm::ArrayType *type = (llvm::ArrayType *)typeForValueType(statement->getValueType(), values.size());
llvm::AllocaInst *alloca = builder->CreateAlloca(type, nullptr, statement->getName()); llvm::AllocaInst *alloca = builder->CreateAlloca(type, nullptr, statement->getName());
if (!setAlloca(statement->getName(), alloca))
return;
for (int i=0; i < type->getNumElements(); i++) { for (int i=0; i < type->getNumElements(); i++) {
llvm::Value *index[] = { llvm::Value *index[] = {
builder->getInt32(0), builder->getInt32(0),
builder->getInt32(i) builder->getInt32(i)
}; };
llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}_{}", statement->getName(), i)); llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}_{}", statement->getName(), i));
builder->CreateStore(values[i], elementPtr); builder->CreateStore(values[i], elementPtr);
} }
} else { } else {
@@ -150,10 +153,6 @@ void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement)
} }
} }
void ModuleBuilder::buildArrayDeclaration(shared_ptr<StatementVariable> statement) {
}
void ModuleBuilder::buildAssignment(shared_ptr<StatementAssignment> statement) { void ModuleBuilder::buildAssignment(shared_ptr<StatementAssignment> statement) {
llvm::AllocaInst *alloca = getAlloca(statement->getName()); llvm::AllocaInst *alloca = getAlloca(statement->getName());
if (alloca == nullptr) if (alloca == nullptr)
@@ -254,7 +253,6 @@ llvm::Value *ModuleBuilder::valueForExpression(shared_ptr<Expression> expression
switch (expression->getKind()) { switch (expression->getKind()) {
case ExpressionKind::LITERAL: case ExpressionKind::LITERAL:
return valueForLiteral(dynamic_pointer_cast<ExpressionLiteral>(expression)); return valueForLiteral(dynamic_pointer_cast<ExpressionLiteral>(expression));
case ExpressionKind::GROUPING: case ExpressionKind::GROUPING:
return valueForExpression(dynamic_pointer_cast<ExpressionGrouping>(expression)->getExpression()); return valueForExpression(dynamic_pointer_cast<ExpressionGrouping>(expression)->getExpression());
case ExpressionKind::BINARY: case ExpressionKind::BINARY:
@@ -313,6 +311,9 @@ llvm::Value *ModuleBuilder::valueForBinary(shared_ptr<ExpressionBinary> expressi
llvm::Value *leftValue = valueForExpression(expression->getLeft()); llvm::Value *leftValue = valueForExpression(expression->getLeft());
llvm::Value *rightValue = valueForExpression(expression->getRight()); llvm::Value *rightValue = valueForExpression(expression->getRight());
if (leftValue == nullptr || rightValue == nullptr)
return nullptr;
llvm::Type *type = leftValue->getType(); llvm::Type *type = leftValue->getType();
if (type == typeBool) { if (type == typeBool) {
@@ -450,7 +451,19 @@ llvm::Value *ModuleBuilder::valueForVar(shared_ptr<ExpressionVariable> expressio
if (alloca == nullptr) if (alloca == nullptr)
return 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<ExpressionCall> expression) { llvm::Value *ModuleBuilder::valueForCall(shared_ptr<ExpressionCall> expression) {

View File

@@ -62,7 +62,6 @@ private:
void buildStatement(shared_ptr<Statement> statement); void buildStatement(shared_ptr<Statement> statement);
void buildFunctionDeclaration(shared_ptr<StatementFunction> statement); void buildFunctionDeclaration(shared_ptr<StatementFunction> statement);
void buildVarDeclaration(shared_ptr<StatementVariable> statement); void buildVarDeclaration(shared_ptr<StatementVariable> statement);
void buildArrayDeclaration(shared_ptr<StatementVariable> statement);
void buildAssignment(shared_ptr<StatementAssignment> statement); void buildAssignment(shared_ptr<StatementAssignment> statement);
void buildBlock(shared_ptr<StatementBlock> statement); void buildBlock(shared_ptr<StatementBlock> statement);
void buildReturn(shared_ptr<StatementReturn> statement); void buildReturn(shared_ptr<StatementReturn> statement);

View File

@@ -376,7 +376,11 @@ string Logger::toString(shared_ptr<ExpressionIfElse> expression) {
} }
string Logger::toString(shared_ptr<ExpressionVariable> expression) { string Logger::toString(shared_ptr<ExpressionVariable> 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<ExpressionGrouping> expression) { string Logger::toString(shared_ptr<ExpressionGrouping> expression) {

View File

@@ -26,6 +26,13 @@ shared_ptr<ExpressionArrayLiteral> ExpressionArrayLiteral::expressionArrayLitera
shared_ptr<Token> token = make_shared<Token>(TokenKind::INTEGER_CHAR, lexme, tokenString->getLine(), tokenString->getColumn() + i); shared_ptr<Token> token = make_shared<Token>(TokenKind::INTEGER_CHAR, lexme, tokenString->getLine(), tokenString->getColumn() + i);
shared_ptr<ExpressionLiteral> expression = ExpressionLiteral::expressionLiteralForToken(token); shared_ptr<ExpressionLiteral> expression = ExpressionLiteral::expressionLiteralForToken(token);
expressions.push_back(expression); expressions.push_back(expression);
// add terminal 0 if missing
if (i == stringValue.length() - 2 && lexme.compare("\\0") != 0) {
shared_ptr<Token> token = make_shared<Token>(TokenKind::INTEGER_CHAR, "\\0", tokenString->getLine(), tokenString->getColumn() + i + lexme.length());
shared_ptr<ExpressionLiteral> expression = ExpressionLiteral::expressionLiteralForToken(token);
expressions.push_back(expression);
}
} }
expression->expressions = expressions; expression->expressions = expressions;

View File

@@ -1,8 +1,12 @@
#include "ExpressionVariable.h" #include "ExpressionVariable.h"
ExpressionVariable::ExpressionVariable(string name): ExpressionVariable::ExpressionVariable(string name, shared_ptr<Expression> indexExpression):
Expression(ExpressionKind::VAR, nullptr), name(name) { } Expression(ExpressionKind::VAR, nullptr), name(name), indexExpression(indexExpression) { }
string ExpressionVariable::getName() { string ExpressionVariable::getName() {
return name; return name;
} }
shared_ptr<Expression> ExpressionVariable::getIndexExpression() {
return indexExpression;
}

View File

@@ -3,8 +3,10 @@
class ExpressionVariable: public Expression { class ExpressionVariable: public Expression {
private: private:
string name; string name;
shared_ptr<Expression> indexExpression;
public: public:
ExpressionVariable(string name); ExpressionVariable(string name, shared_ptr<Expression> indexExpression);
string getName(); string getName();
shared_ptr<Expression> getIndexExpression();
}; };

View File

@@ -292,7 +292,7 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
// got initial, expect comma // got initial, expect comma
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) { if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
markError(TokenKind::COMMA, {}); markError(TokenKind::COMMA, {});
return nullptr; goto afterIf;
} }
// optional new line // optional new line
@@ -305,7 +305,7 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
// got pre-condition, expect comma // got pre-condition, expect comma
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) { if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
markError(TokenKind::COMMA, {}); markError(TokenKind::COMMA, {});
return nullptr; goto afterIf;
} }
// optional new line // optional new line
@@ -317,10 +317,11 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
// expect colon // expect colon
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) { if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
markError(TokenKind::COLON, {}); markError(TokenKind::COLON, {});
return nullptr; goto afterIf;
} }
} }
} }
afterIf:
isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
@@ -416,25 +417,26 @@ shared_ptr<Expression> Parser::matchFactor() {
shared_ptr<Expression> Parser::matchPrimary() { shared_ptr<Expression> Parser::matchPrimary() {
shared_ptr<Expression> expression; shared_ptr<Expression> expression;
int errorsCount = errors.size();
expression = matchExpressionGrouping(); expression = matchExpressionGrouping();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
expression = matchExpressionArrayLiteral(); expression = matchExpressionArrayLiteral();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
expression = matchExpressionLiteral(); expression = matchExpressionLiteral();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
expression = matchExpressionCall(); expression = matchExpressionCall();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
expression = matchExpressionVariable(); expression = matchExpressionVariable();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
return nullptr; return nullptr;
@@ -490,12 +492,23 @@ shared_ptr<Expression> Parser::matchExpressionArrayLiteral() {
} }
shared_ptr<Expression> Parser::matchExpressionVariable() { shared_ptr<Expression> Parser::matchExpressionVariable() {
shared_ptr<Token> token = tokens.at(currentIndex); if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, false))
return nullptr;
shared_ptr<Token> idToken = tokens.at(currentIndex++);
shared_ptr<Expression> indexExpression;
if (tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, true)) if (tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) {
return make_shared<ExpressionVariable>(token->getLexme()); 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<ExpressionVariable>(idToken->getLexme(), indexExpression);
} }
shared_ptr<Expression> Parser::matchExpressionCall() { shared_ptr<Expression> Parser::matchExpressionCall() {

View File

@@ -25,6 +25,8 @@ optional<int> Utils::charStringToInt(string charString) {
return '\''; return '\'';
case '\"': case '\"':
return '\"'; return '\"';
case '0':
return '\0';
default: default:
return {}; return {};
} }