Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compile cache machanism #217

Merged
merged 7 commits into from
Oct 16, 2022
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
27 changes: 19 additions & 8 deletions media/test-project/os-test.spice
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import "std/type/int" as i;
// See Issue #155 (fixed)

f<int> main() {
bool a = false;
bool b = true;
if a = b {
printf("a: %d, b: %d", a, b);
} else {
printf("a: %d, b: %d", a, b);
type T dyn;

public type Vector<T> struct {
T* contents
unsigned long capacity
unsigned long size
unsigned int itemSize
}

public f<int> Vector.get(long index) {
if (index <= size) { // size instead this.size
return 1;
}
return 0;
}

f<int> main() {
dyn v = Vector<int>{};
int v0 = v.get(0l);
}

/*import "std/net/http" as http;
Expand Down
24 changes: 3 additions & 21 deletions src-bootstrap/CliInterface.spice
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public type CliOptions struct {
public type CliInterface struct {
//CliApp cliApp
CliOptions cliOptions
bool compile
bool install
bool run
public bool shouldCompile
public bool shouldInstall
public bool shouldRun
}

public p CliInterface.ctor() {
Expand Down Expand Up @@ -109,24 +109,6 @@ p CliInterface.addUninstallSubcommand() {
// ToDo: Extend
}

/**
* Checks if compiling is necessary
*
* @return Compile or not
*/
f<bool> CliInterface.shouldCompile() {
return this.compile;
}

/**
* Checks if running is necessary
*
* @return Run or not
*/
f<bool> CliInterface.shoudRun() {
return this.run;
}

/**
* Start the parsing process
*
Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ set(SOURCES
ast/AstNodes.h
dependency/SourceFile.cpp
dependency/SourceFile.h
dependency/GlobalResourceManager.h
dependency/CacheManager.cpp
dependency/CacheManager.h
dependency/RuntimeModuleManager.cpp
dependency/RuntimeModuleManager.h
exception/CliError.cpp
Expand Down
86 changes: 41 additions & 45 deletions src/analyzer/AnalyzerVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <utility>

#include <cli/CliInterface.h>
#include <dependency/GlobalResourceManager.h>
#include <dependency/RuntimeModuleManager.h>
#include <dependency/SourceFile.h>
#include <exception/SemanticError.h>
Expand All @@ -16,18 +17,19 @@
#include <util/CommonUtil.h>
#include <util/CompilerWarning.h>

AnalyzerVisitor::AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder, SourceFile &sourceFile,
CliOptions &options, bool requiresMainFct, bool isStdFile)
: context(context), builder(builder), sourceFile(sourceFile), requiresMainFct(requiresMainFct), isStdFile(isStdFile) {
AnalyzerVisitor::AnalyzerVisitor(GlobalResourceManager &resourceManager, SourceFile &sourceFile, bool requiresMainFct,
bool isStdFile)
: resourceManager(resourceManager), sourceFile(sourceFile), requiresMainFct(requiresMainFct), isStdFile(isStdFile) {
// Retrieve symbol table
this->currentScope = this->rootScope = sourceFile.symbolTable.get();

// Use default target triple if empty
if (options.targetTriple.empty()) {
CliOptions &cliOptions = resourceManager.cliOptions;
if (resourceManager.cliOptions.targetTriple.empty()) {
llvm::Triple targetTriple = llvm::Triple(llvm::sys::getDefaultTargetTriple());
options.targetArch = targetTriple.getArchName();
options.targetVendor = targetTriple.getVendorName();
options.targetOs = targetTriple.getOSName();
cliOptions.targetArch = targetTriple.getArchName();
cliOptions.targetVendor = targetTriple.getVendorName();
cliOptions.targetOs = targetTriple.getOSName();
}

// Create OpRuleManager
Expand Down Expand Up @@ -107,7 +109,7 @@ std::any AnalyzerVisitor::visitMainFctDef(MainFctDefNode *node) {
// Call destructors for variables, that are going out of scope
std::vector<SymbolTableEntry *> varsToDestruct = node->fctScope->getVarsGoingOutOfScope(true);
for (SymbolTableEntry *varEntry : varsToDestruct)
insertDestructorCall(varEntry->getDeclNode(), varEntry);
insertDestructorCall(varEntry->declNode, varEntry);

// Return to root scope
currentScope = node->fctScope->parent;
Expand Down Expand Up @@ -162,20 +164,16 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) {
ParamList paramTypes;
if (node->hasParams) {
auto namedParamList = any_cast<NamedParamList>(visit(node->paramLst()));
for (const auto &namedParam : namedParamList) {
const std::string paramName = std::get<0>(namedParam);
const SymbolType paramType = std::get<1>(namedParam);
bool isOptional = std::get<2>(namedParam);

for (const auto &param : namedParamList) {
// Check if the type is present in the template for generic types
if (paramType.is(TY_GENERIC)) {
if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == paramType; }))
if (param.type.is(TY_GENERIC)) {
if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == param.type; }))
throw SemanticError(node->paramLst(), GENERIC_TYPE_NOT_IN_TEMPLATE,
"Generic arg type not included in function template");
}

paramNames.push_back(paramName);
paramTypes.push_back({paramType, isOptional});
paramNames.push_back(param.name);
paramTypes.push_back({param.type, param.isOptional});
}
}

Expand Down Expand Up @@ -244,7 +242,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) {

// Change scope to the struct specialization
if (node->isMethod) {
std::string structSignature = Struct::getSignature(node->structName, spiceFunc.getThisType().getTemplateTypes());
std::string structSignature = Struct::getSignature(node->structName, spiceFunc.thisType.getTemplateTypes());
currentScope = currentScope->getChild(STRUCT_SCOPE_PREFIX + structSignature);
assert(currentScope);
}
Expand All @@ -263,7 +261,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) {
// Morph the generic return type
SymbolTableEntry *returnVarEntry = currentScope->lookup(RETURN_VARIABLE_NAME);
if (returnVarEntry->type.is(TY_GENERIC)) {
SymbolType returnType = spiceFunc.getReturnType();
SymbolType returnType = spiceFunc.returnType;
/*if (returnType.isPointer())
throw SemanticError(node, COMING_SOON_SA,
"Spice currently not supports pointer return types due to not handling pointer escaping.");*/
Expand Down Expand Up @@ -293,7 +291,7 @@ std::any AnalyzerVisitor::visitFctDef(FctDefNode *node) {
// Call destructors for variables, that are going out of scope
std::vector<SymbolTableEntry *> varsToDestruct = currentScope->getVarsGoingOutOfScope(true);
for (SymbolTableEntry *varEntry : varsToDestruct)
insertDestructorCall(varEntry->getDeclNode(), varEntry);
insertDestructorCall(varEntry->declNode, varEntry);

// Reset generic types
for (const auto &arg : args) {
Expand Down Expand Up @@ -368,20 +366,16 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) {
ParamList paramTypes;
if (node->hasParams) {
auto namedParamList = any_cast<NamedParamList>(visit(node->paramLst()));
for (const auto &namedParam : namedParamList) {
const std::string paramName = std::get<0>(namedParam);
const SymbolType paramType = std::get<1>(namedParam);
bool isOptional = std::get<2>(namedParam);

for (const auto &param : namedParamList) {
// Check if the type is present in the template for generic types
if (paramType.is(TY_GENERIC)) {
if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == paramType; }))
if (param.type.is(TY_GENERIC)) {
if (std::none_of(templateTypes.begin(), templateTypes.end(), [&](const GenericType &t) { return t == param.type; }))
throw SemanticError(node->paramLst(), GENERIC_TYPE_NOT_IN_TEMPLATE,
"Generic arg type not included in procedure template");
}

paramNames.push_back(paramName);
paramTypes.push_back({paramType, isOptional});
paramNames.push_back(param.name);
paramTypes.push_back({param.type, param.isOptional});
}
}

Expand Down Expand Up @@ -441,7 +435,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) {

// Change scope to the struct specialization
if (node->isMethod) {
std::string structSignature = Struct::getSignature(node->structName, spiceProc.getThisType().getTemplateTypes());
std::string structSignature = Struct::getSignature(node->structName, spiceProc.thisType.getTemplateTypes());
currentScope = currentScope->getChild(STRUCT_SCOPE_PREFIX + structSignature);
assert(currentScope);
}
Expand Down Expand Up @@ -480,7 +474,7 @@ std::any AnalyzerVisitor::visitProcDef(ProcDefNode *node) {
// Call destructors for variables, that are going out of scope
std::vector<SymbolTableEntry *> varsToDestruct = currentScope->getVarsGoingOutOfScope(true);
for (SymbolTableEntry *varEntry : varsToDestruct)
insertDestructorCall(varEntry->getDeclNode(), varEntry);
insertDestructorCall(varEntry->declNode, varEntry);

// Reset generic types
for (const auto &arg : params) {
Expand Down Expand Up @@ -588,7 +582,7 @@ std::any AnalyzerVisitor::visitStructDef(StructDefNode *node) {
// Add struct
Struct s(node->structName, structSymbolSpecifiers, fieldTypes, genericTemplateTypes, node);
currentScope->insertStruct(s);
s.setSymbolTable(structScope);
s.symbolTable = structScope;

return nullptr;
}
Expand Down Expand Up @@ -764,7 +758,7 @@ std::any AnalyzerVisitor::visitExtDecl(ExtDeclNode *node) {
auto argType = any_cast<SymbolType>(visit(arg));
if (argType.is(TY_DYN))
throw SemanticError(arg, UNEXPECTED_DYN_TYPE_SA, "Dyn data type is not allowed as arg type for external functions");
argTypes.emplace_back(argType, false);
argTypes.push_back({argType, false});
}
}

Expand Down Expand Up @@ -862,7 +856,7 @@ std::any AnalyzerVisitor::visitForeachLoop(ForeachLoopNode *node) {
// Check type of the array
expectedType = SymbolType(TY_DYN);
auto arrayType = any_cast<SymbolType>(visit(node->arrayAssign()));
if (!arrayType.isArray() && !arrayType.is(TY_STRING))
if (!arrayType.isArray())
throw SemanticError(node->arrayAssign(), OPERATOR_WRONG_DATA_TYPE,
"Can only apply foreach loop on an array type. You provided " + arrayType.getName(false));

Expand Down Expand Up @@ -1016,7 +1010,7 @@ std::any AnalyzerVisitor::visitParamLst(ParamLstNode *node) {
throw SemanticError(param, INVALID_PARAM_ORDER, "Mandatory parameters must go before any optional parameters");
}

namedParamList.emplace_back(param->varName, paramType, metOptional);
namedParamList.push_back({param->varName, paramType, metOptional});
}
return namedParamList;
}
Expand Down Expand Up @@ -1117,7 +1111,7 @@ std::any AnalyzerVisitor::visitReturnStmt(ReturnStmtNode *node) {
// Call destructors for variables, that are going out of scope
std::vector<SymbolTableEntry *> varsToDestruct = currentScope->getVarsGoingOutOfScope(true);
for (SymbolTableEntry *varEntry : varsToDestruct)
insertDestructorCall(varEntry->getDeclNode(), varEntry);
insertDestructorCall(varEntry->declNode, varEntry);

return nullptr;
}
Expand Down Expand Up @@ -1685,7 +1679,7 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) {
if (lhs.is(TY_STRING)) {
insertAnonStringStructSymbol(rhs);
lhs = SymbolType(TY_STRUCT, STRING_RT_IMPORT_NAME + std::string(".String"));
SymbolTable *stringRuntimeScope = sourceFile.getRuntimeModuleScope(STRING_RT);
SymbolTable *stringRuntimeScope = resourceManager.runtimeModuleManager.getModuleScope(STRING_RT);
stringRuntimeScope = stringRuntimeScope->getChild(STRUCT_SCOPE_PREFIX + std::string("String"));
assert(stringRuntimeScope != nullptr);
scopePath.clear();
Expand Down Expand Up @@ -1758,7 +1752,7 @@ std::any AnalyzerVisitor::visitAtomicExpr(AtomicExprNode *node) {
"'" + currentVarName +
"' is a reserved keyword for future development of the language. Please use another identifier instead");

// Load symbol table entry
// Retrieve access scope
SymbolTable *accessScope = scopePath.getCurrentScope() ? scopePath.getCurrentScope() : currentScope;
assert(accessScope);

Expand Down Expand Up @@ -1914,11 +1908,12 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) {
if (symbolEntry->type.getBaseType().is(TY_STRING)) {
insertAnonStringStructSymbol(node);
symbolBaseType = SymbolType(TY_STRUCT, std::string("String"));
accessScope = sourceFile.getRuntimeModuleScope(STRING_RT);
accessScope = resourceManager.runtimeModuleManager.getModuleScope(STRING_RT);
assert(accessScope != nullptr);
} else {
symbolBaseType = symbolEntry->type.getBaseType();
}
symbolEntry->isUsed = true;
}

if (i < node->functionNameFragments.size() - 1) {
Expand All @@ -1943,6 +1938,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) {

symbolEntry = accessScope->lookup(structSignature);
assert(symbolEntry != nullptr);
symbolEntry->isUsed = true;

// Import struct if necessary
if (accessScope->isImported(currentScope))
Expand Down Expand Up @@ -1995,7 +1991,7 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) {

ParamList errArgTypes;
for (const auto &argType : argTypes)
errArgTypes.emplace_back(argType, false);
errArgTypes.push_back({argType, false});

Function f(functionName, specifiers, thisType, SymbolType(TY_DYN), errArgTypes, {}, node);

Expand Down Expand Up @@ -2026,11 +2022,11 @@ std::any AnalyzerVisitor::visitFunctionCall(FunctionCallNode *node) {
}

// If the callee is a procedure, return type bool
if (spiceFunc->isProcedure() || spiceFunc->getReturnType().is(TY_DYN))
if (spiceFunc->isProcedure() || spiceFunc->returnType.is(TY_DYN))
return node->setEvaluatedSymbolType(SymbolType(TY_BOOL));

// Retrieve the return type of the function
SymbolType returnType = spiceFunc->getReturnType();
SymbolType returnType = spiceFunc->returnType;

if (returnType.is(TY_STRUCT)) {
// Add struct scope to scope path
Expand Down Expand Up @@ -2141,17 +2137,17 @@ std::any AnalyzerVisitor::visitStructInstantiation(StructInstantiationNode *node
}

// Set template types to the struct
std::vector<GenericType> genericTemplateTypes = spiceStruct->getTemplateTypes();
std::vector<GenericType> genericTemplateTypes = spiceStruct->templateTypes;
std::vector<SymbolType> templateTypes;
for (const auto &genericType : genericTemplateTypes)
templateTypes.emplace_back(genericType.getTypeChain());
templateTypes.emplace_back(genericType.typeChain);
structType.setTemplateTypes(templateTypes);

// Check if the number of fields matches
SymbolTable *structTable = currentScope->lookupTable(STRUCT_SCOPE_PREFIX + accessScopePrefix + structName);
std::vector<SymbolType> fieldTypes;
if (node->fieldLst()) { // Check if any fields are passed. Empty braces are also allowed
if (spiceStruct->getFieldTypes().size() != node->fieldLst()->args().size())
if (spiceStruct->fieldTypes.size() != node->fieldLst()->args().size())
throw SemanticError(node->fieldLst(), NUMBER_OF_FIELDS_NOT_MATCHING,
"You've passed too less/many field values. Pass either none or all of them");

Expand Down
11 changes: 3 additions & 8 deletions src/analyzer/AnalyzerVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ const std::vector<std::string> RESERVED_KEYWORDS = {"new", "switch", "case", "yi

// Forward declarations
class OpRuleManager;
struct CliOptions;
class ThreadFactory;
class LinkerInterface;
class GlobalResourceManager;
class SymbolTable;
class SymbolTableEntry;
class SourceFile;
struct RuntimeModuleManager;

/**
* Visitor for analyzing a source file.
Expand All @@ -48,8 +45,7 @@ struct RuntimeModuleManager;
class AnalyzerVisitor : public AstVisitor {
public:
// Constructors
explicit AnalyzerVisitor(const llvm::LLVMContext *context, const llvm::IRBuilder<> *builder, SourceFile &sourceFile,
CliOptions &options, bool requiresMainFct, bool stdFile);
explicit AnalyzerVisitor(GlobalResourceManager &resourceManager, SourceFile &sourceFile, bool requiresMainFct, bool stdFile);

// Friend classes
friend class OpRuleManager;
Expand Down Expand Up @@ -110,8 +106,7 @@ class AnalyzerVisitor : public AstVisitor {

private:
// Members
const llvm::LLVMContext *context;
const llvm::IRBuilder<> *builder;
const GlobalResourceManager &resourceManager;
std::unique_ptr<OpRuleManager> opRuleManager;
SourceFile &sourceFile;
bool requiresMainFct = true;
Expand Down
Loading