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 internal string objects #198

Merged
merged 5 commits into from
Sep 2, 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
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ updates:
assignees:
- spicelang/compiler-team

# Github Actions
# GitHub Actions
- package-ecosystem: github-actions
directory: /
schedule:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.18
go-version: 1.19

- name: Restore Go modules cache
uses: actions/cache@v3
Expand Down Expand Up @@ -222,7 +222,7 @@ jobs:
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3
with:
version: v1.10.3
version: v1.11.2
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .run/Spice_run.run.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Spice_run" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -O2 ../../src-bootstrap/main.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 ../../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" />
Expand Down
11 changes: 10 additions & 1 deletion media/test-project/os-test.spice
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@ f<int> main() {
printf("Hello %s!", p1.getSecond());
}*/

import "std/net/http" as http;
/*import "std/net/http" as http;

f<int> main() {
http::HttpServer server = http::HttpServer();
server.serve("/test", "Hello World!");
}*/

import "std/runtime/string_rt" as _rt_str;

f<int> main() {
_rt_str::String s1 = _rt_str::String('H');
s1.append("ello");

printf("Equals: %d", s1.opEquals("Hell2"));
}
2 changes: 1 addition & 1 deletion src-bootstrap/exception/SemanticError.spice
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public type ErrorType enum {
NUMBER_OF_FIELDS_NOT_MATCHING,
FIELD_TYPE_NOT_MATCHING,
ARRAY_SIZE_INVALID,
ARRAY_INDEX_NO_INTEGER,
ARRAY_INDEX_NOT_INT_OR_LONG,
ARRAY_ITEM_TYPE_NOT_MATCHING,
EXPECTED_ARRAY_TYPE,
SIZEOF_DYNAMIC_SIZED_ARRAY,
Expand Down
11 changes: 6 additions & 5 deletions src/analyzer/AnalyzerVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ std::any AnalyzerVisitor::visitForeachLoop(ForeachLoopNode *node) {

// Check if index type is int
if (!indexType.is(TY_INT))
throw SemanticError(node->idxVarDecl()->codeLoc, ARRAY_INDEX_NO_INTEGER,
throw SemanticError(node->idxVarDecl()->codeLoc, ARRAY_INDEX_NOT_INT_OR_LONG,
"Index in foreach loop must be of type int. You provided " + indexType.getName(false));
} else {
// Declare the variable with the default index variable name
Expand Down Expand Up @@ -1657,8 +1657,8 @@ std::any AnalyzerVisitor::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) {
AssignExprNode *indexExpr = node->assignExpr()[subscriptCounter++];
auto indexType = any_cast<SymbolType>(visit(indexExpr));

if (!indexType.is(TY_INT))
throw SemanticError(node->codeLoc, ARRAY_INDEX_NO_INTEGER, "Array index must be of type int");
if (!indexType.isOneOf({TY_INT, TY_LONG}))
throw SemanticError(node->codeLoc, ARRAY_INDEX_NOT_INT_OR_LONG, "Array index must be of type int or long");
if (!lhs.isOneOf({TY_ARRAY, TY_STRING, TY_PTR}))
throw SemanticError(node->codeLoc, OPERATOR_WRONG_DATA_TYPE,
"Can only apply subscript operator on array type, got " + lhs.getName(true));
Expand Down Expand Up @@ -2070,8 +2070,9 @@ std::any AnalyzerVisitor::visitArrayInitialization(ArrayInitializationNode *node
if (actualItemType.is(TY_DYN)) { // Not enough info to perform type inference, because of empty array {}
if (expectedType.is(TY_DYN))
throw SemanticError(node->codeLoc, UNEXPECTED_DYN_TYPE_SA, "Not enough information to perform type inference");
if (expectedType.is(TY_DYN))
throw SemanticError(node->codeLoc, ARRAY_ITEM_TYPE_NOT_MATCHING, "Cannot assign an array to a primitive data type");
if (!expectedType.isArray())
throw SemanticError(node->codeLoc, ARRAY_ITEM_TYPE_NOT_MATCHING,
"Cannot initialize array for type " + expectedType.getName() + "");
actualItemType = expectedType.getContainedTy();
}

Expand Down
4 changes: 2 additions & 2 deletions src/exception/SemanticError.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ std::string SemanticError::getMessagePrefix(SemanticErrorType type) {
return "The type of a field value does not match the declaration";
case ARRAY_SIZE_INVALID:
return "Array size invalid";
case ARRAY_INDEX_NO_INTEGER:
return "Array index not of type int";
case ARRAY_INDEX_NOT_INT_OR_LONG:
return "Array index not of type int or long";
case ARRAY_ITEM_TYPE_NOT_MATCHING:
return "Array item type not matching";
case EXPECTED_ARRAY_TYPE:
Expand Down
2 changes: 1 addition & 1 deletion src/exception/SemanticError.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ enum SemanticErrorType {
NUMBER_OF_FIELDS_NOT_MATCHING,
FIELD_TYPE_NOT_MATCHING,
ARRAY_SIZE_INVALID,
ARRAY_INDEX_NO_INTEGER,
ARRAY_INDEX_NOT_INT_OR_LONG,
ARRAY_ITEM_TYPE_NOT_MATCHING,
EXPECTED_ARRAY_TYPE,
SIZEOF_DYNAMIC_SIZED_ARRAY,
Expand Down
32 changes: 16 additions & 16 deletions src/generator/OpRuleConversionsManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ llvm::Value *OpRuleConversionsManager::getPlusEqualInst(llvm::Value *lhs, llvm::
// ToDo(@marcauberer): Insert call to appendChar in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '+=' operator for lhs=string and rhs=char yet");
case COMB(TY_STRING, TY_STRING):
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to append in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '+=' operator for lhs=string and rhs=string yet");
case COMB(TY_PTR, TY_INT): // fallthrough
case COMB(TY_PTR, TY_SHORT): // fallthrough
Expand Down Expand Up @@ -466,7 +466,7 @@ llvm::Value *OpRuleConversionsManager::getEqualInst(llvm::Value *lhs, llvm::Valu
case COMB(TY_CHAR, TY_CHAR):
return builder->CreateICmpEQ(lhs, rhs);
case COMB(TY_STRING, TY_STRING):
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opEquals in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '==' operator for lhs=string and rhs=string yet");
case COMB(TY_BOOL, TY_BOOL):
return builder->CreateICmpEQ(lhs, rhs);
Expand Down Expand Up @@ -571,7 +571,7 @@ llvm::Value *OpRuleConversionsManager::getNotEqualInst(llvm::Value *lhs, llvm::V
case COMB(TY_CHAR, TY_CHAR):
return builder->CreateICmpNE(lhs, rhs);
case COMB(TY_STRING, TY_STRING):
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opNotEquals in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '!=' operator for lhs=string and rhs=string yet");
case COMB(TY_BOOL, TY_BOOL):
return builder->CreateICmpNE(lhs, rhs);
Expand Down Expand Up @@ -944,7 +944,7 @@ llvm::Value *OpRuleConversionsManager::getPlusInst(llvm::Value *lhs, llvm::Value
case COMB(TY_CHAR, TY_CHAR):
return builder->CreateAdd(lhs, rhs);
case COMB(TY_STRING, TY_STRING):
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to append in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '+' operator for lhs=string and rhs=string yet");
case COMB(TY_PTR, TY_INT): // fallthrough
case COMB(TY_PTR, TY_SHORT): // fallthrough
Expand Down Expand Up @@ -1054,11 +1054,11 @@ llvm::Value *OpRuleConversionsManager::getMulInst(llvm::Value *lhs, llvm::Value
return builder->CreateMul(lhsLong, rhs);
}
case COMB(TY_INT, TY_CHAR): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=int and rhs=char yet");
}
case COMB(TY_INT, TY_STRING): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=int and rhs=string yet");
}
case COMB(TY_SHORT, TY_DOUBLE): {
Expand All @@ -1076,11 +1076,11 @@ llvm::Value *OpRuleConversionsManager::getMulInst(llvm::Value *lhs, llvm::Value
return builder->CreateMul(lhsLong, rhs);
}
case COMB(TY_SHORT, TY_CHAR): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=short and rhs=char yet");
}
case COMB(TY_SHORT, TY_STRING): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=short and rhs=string yet");
}
case COMB(TY_LONG, TY_DOUBLE): {
Expand All @@ -1095,37 +1095,37 @@ llvm::Value *OpRuleConversionsManager::getMulInst(llvm::Value *lhs, llvm::Value
case COMB(TY_LONG, TY_LONG):
return builder->CreateMul(lhs, rhs);
case COMB(TY_LONG, TY_CHAR): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=long and rhs=char yet");
}
case COMB(TY_LONG, TY_STRING): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=long and rhs=string yet");
}
case COMB(TY_BYTE, TY_BYTE):
return builder->CreateMul(lhs, rhs);
case COMB(TY_CHAR, TY_INT): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=char and rhs=int yet");
}
case COMB(TY_CHAR, TY_SHORT): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=char and rhs=short yet");
}
case COMB(TY_CHAR, TY_LONG): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=char and rhs=long yet");
}
case COMB(TY_STRING, TY_INT): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=string and rhs=int yet");
}
case COMB(TY_STRING, TY_SHORT): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=string and rhs=short yet");
}
case COMB(TY_STRING, TY_LONG): {
// ToDo(@marcauberer): Insert call to concatStrings in the runtime lib
// ToDo(@marcauberer): Insert call to opMul in the runtime lib
throw IRError(codeLoc, COMING_SOON_IR, "The compiler does not support the '*' operator for lhs=string and rhs=long yet");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/linker/LinkerInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ class LinkerInterface {
const ThreadFactory &threadFactory;
const CliOptions &cliOptions;
std::vector<std::string> objectFilePaths;
std::vector<std::string> linkerFlags = {"-no-pie"};
std::vector<std::string> linkerFlags = {"-no-pie", "-flto"};
std::string outputPath;
};
31 changes: 29 additions & 2 deletions src/parser/AstBuilderVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1577,11 +1577,38 @@ int64_t AstBuilderVisitor::parseLong(antlr4::tree::TerminalNode *terminal) {

int8_t AstBuilderVisitor::parseChar(antlr4::tree::TerminalNode *terminal) {
std::string input = terminal->toString();
if (input.length() != 3) {
if (input.length() == 3) { // Normal char literals
return input[1];
} else if (input.length() == 4 && input[1] == '\\') { // Char literals with escape sequence
switch (input[2]) {
case '\'':
return '\'';
case '"':
return '\"';
case '\\':
return '\\';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'b':
return '\b';
case 'f':
return '\f';
case 'v':
return '\v';
case '0':
return '\0';
default:
CodeLoc codeLoc = CodeLoc(terminal->getSymbol(), fileName);
throw LexerParserError(codeLoc, PARSING_FAILED, "Invalid escape sequence " + input);
}
} else {
CodeLoc codeLoc = CodeLoc(terminal->getSymbol(), fileName);
throw LexerParserError(codeLoc, PARSING_FAILED, "Invalid char literal " + input);
}
return input[1];
}

std::string AstBuilderVisitor::parseString(std::string input) {
Expand Down
4 changes: 2 additions & 2 deletions src/symbol/SymbolType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ SymbolType SymbolType::toArray(const CodeLoc &codeLoc, int size) const {
* @return Base type
*/
SymbolType SymbolType::getContainedTy() const {
if (typeChain.empty()) // GCOV_EXCL_LINE
throw std::runtime_error("Internal compiler error: Cannot get contained type of empty type"); // GCOV_EXCL_LINE
if (typeChain.top().superType == TY_STRING)
return SymbolType(TY_CHAR);
if (typeChain.size() < 2) // GCOV_EXCL_LINE
throw std::runtime_error("Internal compiler error: Cannot get contained type of type with type chain < 2"); // GCOV_EXCL_LINE
TypeChain newTypeChain = typeChain;
newTypeChain.pop();
return SymbolType(newTypeChain);
Expand Down
Loading