Skip to content

Commit

Permalink
Fix bugs found with the dijkstra example (#191)
Browse files Browse the repository at this point in the history
* Fix indirect casts for pointers masked as arrays

* Fix bug

* Add tests and fix bug

* Neighbour -> neighbor

* Fix bug and update test refs
  • Loading branch information
marcauberer authored Aug 24, 2022
1 parent 2ac461d commit 4eb6d71
Show file tree
Hide file tree
Showing 113 changed files with 751 additions and 302 deletions.
3 changes: 2 additions & 1 deletion .run/Spice_run.run.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Spice_run" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -O0 -ir ../../media/test-project/os-test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="Spice_run" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="Spice_run">
<configuration default="false" name="Spice_run" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -O2 -ir ../../media/test-project/os-test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="Spice_run" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="Spice_run">
<envs>
<env name="RUN_TESTS" value="OFF" />
<env name="SPICE_STD_DIR" value="$PROJECT_DIR$/std" />
</envs>
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
Expand Down
1 change: 1 addition & 0 deletions .run/Spice_test.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<configuration default="false" name="Spice_test" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="false" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="Spice_test" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="Spice_test">
<envs>
<env name="RUN_TESTS" value="ON" />
<env name="SPICE_STD_DIR" value="$PROJECT_DIR$/std" />
</envs>
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
Expand Down
122 changes: 70 additions & 52 deletions media/test-project/os-test.spice
Original file line number Diff line number Diff line change
Expand Up @@ -10,72 +10,90 @@ f<int> main() {
printf("Hello %s!", p1.getSecond());
}*/

import "std/type/int" as integer;
import "std/math/rand" as rand;

const int vertexCount = 9;
const int row = 10;
const int col = 10;
const int generationsToCalculate = 5;

f<int> minDistance(int[] dist, bool[] sptSet) {
int min = integer::MAX_VALUE;
int minIndex;
p rowLineTop() {
printf("\n");
for int i = 0; i < col; i++ { printf("╭─────╮"); }
printf("\n");
}

for int v = 0; v < vertexCount; v++ {
if !sptSet[v] && dist[v] <= min {
min = dist[v];
minIndex = v;
}
}
p rowLineMiddle() {
printf("\n");
for int i = 0; i < col; i++ { printf("├─────┤"); }
printf("\n");
}

return minIndex;
p rowLineBottom() {
printf("\n");
for int i = 0; i < col; i++ { printf("╰─────╯"); }
printf("\n");
}

p printSolution(int[] dist) {
printf("Vertex \t\t Distance from source\n");
for int i = 0; i < vertexCount; i++ {
printf("%d \t\t %d\n", i, dist[i]);
p printGeneration(string name, int[10][10] matrix) {
printf("%s:\n", name);
rowLineTop();
for int i = 0; i < row; i++ {
if i > 0 {
rowLineMiddle();
}
for int j = 0; j < col; j++ {
printf("│ %d │", matrix[i][j]);
}
}
rowLineBottom();
}

p dijkstra(int[vertexCount][vertexCount] graph, int src) {
int[vertexCount] dist;
bool[vertexCount] sptSet;

// Fill with default values
for int i = 0; i < vertexCount; i++ {
dist[i] = integer::MAX_VALUE;
sptSet[i] = false;
f<int> countLiveNeighborCell(int[10][10] matrix, int r, int c) {
int count = 0;
for int i = r - 1; i <= r + 1; i++ {
for int j = c - 1; j <= c + 1; j++ {
if (i == r && j == c) || (i < 0 || j < 0) || (i >= row || j >= col) {
continue;
}
if matrix[i][j] == 1 {
count++;
}
}
}
return count;
}

// Set distance to starting node to 0
dist[src] = 0;
f<int> main() {
int[10][10] a;
int[10][10] b;

for int count = 0; count < vertexCount - 1; count++ {
int u = minDistance(dist, sptSet);
sptSet[u] = true;
for int v = 0; v < vertexCount; v++ {
if (!sptSet[v] && graph[u][v] != 0 && dist[u] != integer::MAX_VALUE &&
dist[u] + graph[u][v] < dist[v]) {
dist[v] = dist[u] + graph[u][v];
}
// Generate matrix canvas with random values (live and dead cells)
for int i = 0; i < row; i++ {
for int j = 0; j < col; j++ {
a[i][j] = rand.randInt(0, 1);
}
}
printGeneration("Initial state", a);

// Print the solution
printSolution(dist);
}
for int generation = 1; generation < generationsToCalculate; generation++ {
// Calculate next generation
for int i = 0; i < row; i++ {
for int j = 0; j < col; j++ {
int neighbor_live_cell = countLiveNeighborCell(a, i, j);
if a[i][j] == 1 && (neighbor_live_cell == 2 || neighbor_live_cell == 3) {
b[i][j] = 1;
} else if a[i][j] == 0 && neighbor_live_cell == 3 {
b[i][j] = 1;
} else {
b[i][j] = 0;
}
}
}

f<int> main() {
int[vertexCount][vertexCount] graph = {};
graph[0] = { 0, 4, 0, 0, 0, 0, 0, 8, 0 };
graph[1] = { 4, 0, 8, 0, 0, 0, 0, 11, 0 };
graph[2] = { 0, 8, 0, 7, 0, 4, 0, 0, 2 };
graph[3] = { 0, 0, 7, 0, 9, 14, 0, 0, 0 };
graph[4] = { 0, 0, 0, 9, 0, 10, 0, 0, 0 };
graph[5] = { 0, 0, 4, 14, 10, 0, 2, 0, 0 };
graph[6] = { 0, 0, 0, 0, 0, 2, 0, 1, 6 };
graph[7] = { 8, 11, 0, 0, 0, 0, 1, 0, 7 };
graph[8] = { 0, 0, 2, 0, 0, 0, 6, 7, 0 };
// Print next generation
printGeneration("\nNext generation", b);

printf("Computing shortest paths with Dijkstra's algorithm ...\n");
dijkstra(graph, 0);
printf("Done.\n");
}
// Set new matrix to old matrix
a = b;
}
}
13 changes: 7 additions & 6 deletions src/analyzer/PreAnalyzerVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ std::any PreAnalyzerVisitor::visitImportStmt(ImportStmtNode *node) {
std::string stdPath;
if (FileUtil::fileExists("/usr/lib/spice/std")) {
stdPath = "/usr/lib/spice/std/";
} else if (FileUtil::dirExists(std::string(std::getenv("SPICE_STD_DIR")))) {
} else if (std::getenv("SPICE_STD_DIR") && FileUtil::dirExists(std::string(std::getenv("SPICE_STD_DIR")))) {
stdPath = std::string(std::getenv("SPICE_STD_DIR"));
if (stdPath.rfind(FileUtil::DIR_SEPARATOR) != stdPath.size() - 1)
stdPath += FileUtil::DIR_SEPARATOR;
} else {
throw err.get(node->codeLoc, STD_NOT_FOUND,
"Standard library could not be found. Check if the env var SPICE_STD_DIR exists");
throw ErrorFactory::get(node->codeLoc, STD_NOT_FOUND,
"Standard library could not be found. Check if the env var SPICE_STD_DIR exists");
}
// Check if source file exists
std::string defaultPath = stdPath + sourceFileIden + ".spice";
Expand All @@ -50,8 +50,8 @@ std::any PreAnalyzerVisitor::visitImportStmt(ImportStmtNode *node) {
} else if (FileUtil::fileExists(osArchPath)) {
importPath = osArchPath;
} else {
throw err.get(node->codeLoc, IMPORTED_FILE_NOT_EXISTING,
"The source file '" + node->importPath + ".spice' was not found in the standard library");
throw ErrorFactory::get(node->codeLoc, IMPORTED_FILE_NOT_EXISTING,
"The source file '" + node->importPath + ".spice' was not found in the standard library");
}
} else { // Include own source file
// Check in module registry if the file can be imported
Expand All @@ -69,7 +69,8 @@ std::any PreAnalyzerVisitor::visitImportStmt(ImportStmtNode *node) {
} else if (FileUtil::fileExists(osArchPath)) {
importPath = osArchPath;
} else {
throw err.get(node->codeLoc, IMPORTED_FILE_NOT_EXISTING, "The source file '" + node->importPath + ".spice' does not exist");
throw ErrorFactory::get(node->codeLoc, IMPORTED_FILE_NOT_EXISTING,
"The source file '" + node->importPath + ".spice' does not exist");
}
}
CommonUtil::replaceAll(importPath, "/", std::string(1, FileUtil::DIR_SEPARATOR));
Expand Down
21 changes: 18 additions & 3 deletions src/generator/GeneratorVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2316,7 +2316,17 @@ std::any GeneratorVisitor::visitAtomicExpr(AtomicExprNode *node) {
// Initialize if it is an external global var
if (importedScope)
entry = initExtGlobal(node->identifier, scopePath.getScopePrefix(true) + node->identifier);
return entry->getAddress();

// Return the address if modifiable
if (!entry->getSpecifiers().isConst())
return entry->getAddress();

// Save value of global to a new address to get it modifiable
llvm::Type *globalTy = entry->getType().toLLVMType(*context, accessScope);
llvm::Value *globalValue = builder->CreateLoad(globalTy, entry->getAddress());
llvm::Value *memoryAddress = insertAlloca(globalTy);
builder->CreateStore(globalValue, memoryAddress);
return memoryAddress;
}

// Struct or Struct* or Struct** or ...
Expand Down Expand Up @@ -2618,7 +2628,12 @@ std::any GeneratorVisitor::visitFunctionCall(FunctionCallNode *node) {
// Get the actual arg value
SymbolType actualArgSymbolType = arg->getEvaluatedSymbolType();
llvm::Value *actualArgPtr = resolveAddress(arg);
if (actualArgSymbolType == expectedArgSymbolType) {

// If the arrays are both of size -1 or 0, they are both pointers and do not need to be implicitly casted
bool isSameArray = actualArgSymbolType.isArray() && expectedArgSymbolType.isArray() &&
actualArgSymbolType.getArraySize() <= 0 && expectedArgSymbolType.getArraySize() <= 0;

if (actualArgSymbolType == expectedArgSymbolType || isSameArray) {
actualArgPtr = builder->CreateLoad(actualArgSymbolType.toLLVMType(*context, accessScope), actualArgPtr);
} else {
actualArgPtr = doImplicitCast(actualArgPtr, expectedArgType, actualArgSymbolType);
Expand Down Expand Up @@ -2690,7 +2705,7 @@ std::any GeneratorVisitor::visitArrayInitialization(ArrayInitializationNode *nod

// Visit all args to check if they are hardcoded or not
allArgsHardcoded = true;
for (size_t i = 0; i < std::min(node->itemLst()->args().size(), arraySize); i++) {
for (size_t i = 0; i < std::min(actualItemCount, arraySize); i++) {
currentConstValue = nullptr;
lhsVarName = lhsVarNameBackup + "." + std::to_string(i);

Expand Down
8 changes: 6 additions & 2 deletions src/parser/AstBuilderVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,8 @@ std::any AstBuilderVisitor::visitBreakStmt(SpiceParser::BreakStmtContext *ctx) {
auto breakStmtNode = dynamic_cast<BreakStmtNode *>(currentNode);

// Extract number of breaks
breakStmtNode->breakTimes = std::stoi(ctx->INT_LIT()->toString());
if (ctx->INT_LIT())
breakStmtNode->breakTimes = std::stoi(ctx->INT_LIT()->toString());

return nullptr;
}
Expand All @@ -698,7 +699,8 @@ std::any AstBuilderVisitor::visitContinueStmt(SpiceParser::ContinueStmtContext *
auto continueStmtNode = dynamic_cast<ContinueStmtNode *>(currentNode);

// Extract number of continues
continueStmtNode->continueTimes = std::stoi(ctx->INT_LIT()->toString());
if (ctx->INT_LIT())
continueStmtNode->continueTimes = std::stoi(ctx->INT_LIT()->toString());

return nullptr;
}
Expand Down Expand Up @@ -1057,6 +1059,8 @@ std::any AstBuilderVisitor::visitMultiplicativeExpr(SpiceParser::MultiplicativeE
multiplicativeExprNode->opQueue.emplace(MultiplicativeExprNode::OP_MUL, SymbolType(TY_INVALID));
else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree); t->getSymbol()->getType() == SpiceParser::DIV)
multiplicativeExprNode->opQueue.emplace(MultiplicativeExprNode::OP_DIV, SymbolType(TY_INVALID));
else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree); t->getSymbol()->getType() == SpiceParser::REM)
multiplicativeExprNode->opQueue.emplace(MultiplicativeExprNode::OP_REM, SymbolType(TY_INVALID));
else
assert(dynamic_cast<antlr4::tree::TerminalNode *>(subTree)); // Fail if we did not get a terminal

Expand Down
4 changes: 2 additions & 2 deletions std/type/int.spice
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ public f<bool> toBool(int input) {
}

// Helper function: returns the string of a small number
f<string> small(int i) {
/*f<string> small(int i) {
if i < 10 {
return smallsString10.substring(i, i+1);
}
return smallsString100.substring(i*2, i*2+2);
}
}*/
19 changes: 11 additions & 8 deletions test/StdTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,15 +284,17 @@ void executeStdTest(const TestCase &testCase) {

// Test classes
class StdDataTests : public ::testing::TestWithParam<TestCase> {};
class StdExamplesTests : public ::testing::TestWithParam<TestCase> {};
class StdIOTests : public ::testing::TestWithParam<TestCase> {};
class StdOSTests : public ::testing::TestWithParam<TestCase> {};
class StdTextTests : public ::testing::TestWithParam<TestCase> {};

// Test macros
TEST_P(StdDataTests, DataTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdIOTests, IOTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdOSTests, OSTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdTextTests, TextTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdDataTests, DataTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdExamplesTests, ExamplesTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdIOTests, IOTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdOSTests, OSTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)
TEST_P(StdTextTests, TextTests) { executeStdTest(GetParam()); } // NOLINT(cert-err58-cpp)

// Name resolver
struct NameResolver {
Expand All @@ -305,9 +307,10 @@ struct NameResolver {
// Instantiations
const std::vector<TestSuite> testSuites = detectStdTestSuites(); // NOLINT(cert-err58-cpp)

INSTANTIATE_TEST_SUITE_P(, StdDataTests, ::testing::ValuesIn(testSuites[0]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdIOTests, ::testing::ValuesIn(testSuites[1]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdOSTests, ::testing::ValuesIn(testSuites[2]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdTextTests, ::testing::ValuesIn(testSuites[3]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdDataTests, ::testing::ValuesIn(testSuites[0]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdExamplesTests, ::testing::ValuesIn(testSuites[1]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdIOTests, ::testing::ValuesIn(testSuites[2]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdOSTests, ::testing::ValuesIn(testSuites[3]), NameResolver()); // NOLINT(cert-err58-cpp)
INSTANTIATE_TEST_SUITE_P(, StdTextTests, ::testing::ValuesIn(testSuites[4]), NameResolver()); // NOLINT(cert-err58-cpp)

// GCOV_EXCL_STOP
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; ModuleID = 'source.spice'
source_filename = "source.spice"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = private unnamed_addr constant [36 x i8] c"Ackermann of base m=%d and n=%d: %d\00", align 1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; ModuleID = 'source.spice'
source_filename = "source.spice"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = private unnamed_addr constant [36 x i8] c"Ackermann of base m=%d and n=%d: %d\00", align 1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; ModuleID = 'source.spice'
source_filename = "source.spice"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = private unnamed_addr constant [21 x i8] c"Faculty of %d is: %d\00", align 1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; ModuleID = 'source.spice'
source_filename = "source.spice"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = private unnamed_addr constant [21 x i8] c"Faculty of %d is: %d\00", align 1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; ModuleID = 'source.spice'
source_filename = "source.spice"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = private unnamed_addr constant [33 x i8] c"Thread returned with result: %d\0A\00", align 1
@1 = private unnamed_addr constant [17 x i8] c"Program finished\00", align 1
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; ModuleID = 'source.spice'
source_filename = "source.spice"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = private unnamed_addr constant [20 x i8] c"Fibonacci of %d: %d\00", align 1

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; ModuleID = 'source.spice'
source_filename = "source.spice"
target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-w64-windows-gnu"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@0 = private unnamed_addr constant [20 x i8] c"Fibonacci of %d: %d\00", align 1

Expand Down
Loading

0 comments on commit 4eb6d71

Please sign in to comment.