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
main fun -> sint32
text data<sint32> <- "Hello string!\n"
rep i sint32 <- 0, i < 14:
text data<sint32> <- "Hello, world!\n"
rep i sint32 <- 0, text[i] != 0:
putchar(text[i])
i <- i + 1
;

View File

@@ -1,5 +1,23 @@
@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
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::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<StatementVariable> statement)
}
}
void ModuleBuilder::buildArrayDeclaration(shared_ptr<StatementVariable> statement) {
}
void ModuleBuilder::buildAssignment(shared_ptr<StatementAssignment> statement) {
llvm::AllocaInst *alloca = getAlloca(statement->getName());
if (alloca == nullptr)
@@ -254,7 +253,6 @@ llvm::Value *ModuleBuilder::valueForExpression(shared_ptr<Expression> expression
switch (expression->getKind()) {
case ExpressionKind::LITERAL:
return valueForLiteral(dynamic_pointer_cast<ExpressionLiteral>(expression));
case ExpressionKind::GROUPING:
return valueForExpression(dynamic_pointer_cast<ExpressionGrouping>(expression)->getExpression());
case ExpressionKind::BINARY:
@@ -313,6 +311,9 @@ llvm::Value *ModuleBuilder::valueForBinary(shared_ptr<ExpressionBinary> 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<ExpressionVariable> 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<ExpressionCall> expression) {

View File

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

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<ExpressionLiteral> 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> 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;

View File

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

View File

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

View File

@@ -292,7 +292,7 @@ shared_ptr<Statement> 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<Statement> 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<Statement> 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<Expression> Parser::matchFactor() {
shared_ptr<Expression> Parser::matchPrimary() {
shared_ptr<Expression> 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<Expression> Parser::matchExpressionArrayLiteral() {
}
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))
return make_shared<ExpressionVariable>(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<ExpressionVariable>(idToken->getLexme(), indexExpression);
}
shared_ptr<Expression> Parser::matchExpressionCall() {

View File

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