forked from solstice/solstice
Refactor type system, print all errors in file
This commit is contained in:
@@ -11,7 +11,9 @@ namespace Solstice {
|
|||||||
const std::string RESET = "\033[0m";
|
const std::string RESET = "\033[0m";
|
||||||
const std::string BOLD = "\033[1m";
|
const std::string BOLD = "\033[1m";
|
||||||
|
|
||||||
[[noreturn]] void syntaxError(std::string what, int line, std::string lineContent) {
|
int amountOfErrors = 0;
|
||||||
|
|
||||||
|
void syntaxError(std::string what, int line, std::string lineContent) {
|
||||||
std::cout << BOLD << RED << "Syntax Error" << RESET;
|
std::cout << BOLD << RED << "Syntax Error" << RESET;
|
||||||
if (line > 0) std::cout << " on line " << BOLD << line << RESET;
|
if (line > 0) std::cout << " on line " << BOLD << line << RESET;
|
||||||
std::cout << ":\n";
|
std::cout << ":\n";
|
||||||
@@ -22,9 +24,9 @@ namespace Solstice {
|
|||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
std::cout << YELLOW << "-> " << what << RESET << "\n";
|
std::cout << YELLOW << "-> " << what << RESET << "\n";
|
||||||
exit(1);
|
amountOfErrors++;
|
||||||
}
|
}
|
||||||
[[noreturn]] void typingError(std::string what, int line, std::string lineContent) {
|
void typingError(std::string what, int line, std::string lineContent) {
|
||||||
std::cout << BOLD << RED << "Typing Error" << RESET;
|
std::cout << BOLD << RED << "Typing Error" << RESET;
|
||||||
if (line > 0) std::cout << " on line " << BOLD << line << RESET;
|
if (line > 0) std::cout << " on line " << BOLD << line << RESET;
|
||||||
std::cout << ":\n";
|
std::cout << ":\n";
|
||||||
@@ -35,7 +37,13 @@ namespace Solstice {
|
|||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
std::cout << YELLOW << "-> " << what << RESET << "\n";
|
std::cout << YELLOW << "-> " << what << RESET << "\n";
|
||||||
exit(1);
|
amountOfErrors++;
|
||||||
|
}
|
||||||
|
void summariseErrors() {
|
||||||
|
if (amountOfErrors > 0) {
|
||||||
|
std::cout << amountOfErrors << " errors generated.\n";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
|
|
||||||
namespace Solstice {
|
namespace Solstice {
|
||||||
namespace Error {
|
namespace Error {
|
||||||
[[noreturn]] void syntaxError(std::string what, int line = 0, std::string lineContent = "");
|
void syntaxError(std::string what, int line = 0, std::string lineContent = "");
|
||||||
[[noreturn]] void typingError(std::string what, int line = 0, std::string lineContent = "");
|
void typingError(std::string what, int line = 0, std::string lineContent = "");
|
||||||
|
void summariseErrors();
|
||||||
|
extern int amountOfErrors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -111,7 +111,8 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
case '(':
|
case '(':
|
||||||
case ')':
|
case ')':
|
||||||
case '}':
|
case '}':
|
||||||
|
case ',':
|
||||||
{
|
{
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
addToken(buf);
|
addToken(buf);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "argparser.h"
|
#include "argparser.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
#define parseOneToken(token) Parser({token.value()}).parse().children[0]
|
#define parseOneToken(token) Parser({token.value()}).parse().children[0]
|
||||||
|
|
||||||
@@ -28,6 +29,7 @@ int main(int argc, char** argv) {
|
|||||||
auto lexed = Solstice::Lexer(ss.str()).lex();
|
auto lexed = Solstice::Lexer(ss.str()).lex();
|
||||||
auto parsed = Solstice::Parser::Parser(lexed).parse();
|
auto parsed = Solstice::Parser::Parser(lexed).parse();
|
||||||
GroundProgram program = Solstice::Parser::assembleProgram(parsed);
|
GroundProgram program = Solstice::Parser::assembleProgram(parsed);
|
||||||
|
Solstice::Error::summariseErrors();
|
||||||
if (args.output.has_value()) {
|
if (args.output.has_value()) {
|
||||||
std::FILE* originalStdout = stdout;
|
std::FILE* originalStdout = stdout;
|
||||||
std::FILE* tmp = std::tmpfile();
|
std::FILE* tmp = std::tmpfile();
|
||||||
|
|||||||
167
src/parser.cpp
167
src/parser.cpp
@@ -1,7 +1,6 @@
|
|||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include <groundvm.h>
|
#include <groundvm.h>
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#define parseOneToken(token) Parser({token}).parse().children[0]
|
#define parseOneToken(token) Parser({token}).parse().children[0]
|
||||||
@@ -13,9 +12,9 @@ namespace Solstice {
|
|||||||
return id.rfind("tmp_", 0) == 0;
|
return id.rfind("tmp_", 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, SolDataType> variables;
|
std::map<std::string, std::string> variables;
|
||||||
|
|
||||||
SolDataType checkNodeReturnType(SolNode i) {
|
std::string checkNodeReturnType(SolNode i) {
|
||||||
switch (i.nodeType) {
|
switch (i.nodeType) {
|
||||||
case SolNodeType::Identifier: {
|
case SolNodeType::Identifier: {
|
||||||
if (variables.find(i.outputId) != variables.end()) {
|
if (variables.find(i.outputId) != variables.end()) {
|
||||||
@@ -26,7 +25,7 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Value: {
|
case SolNodeType::Value: {
|
||||||
return i.data.type;
|
return i.data.getTypeString();
|
||||||
}
|
}
|
||||||
case SolNodeType::Equal:
|
case SolNodeType::Equal:
|
||||||
case SolNodeType::Inequal:
|
case SolNodeType::Inequal:
|
||||||
@@ -34,25 +33,25 @@ namespace Solstice {
|
|||||||
case SolNodeType::Lesser:
|
case SolNodeType::Lesser:
|
||||||
case SolNodeType::EqGreater:
|
case SolNodeType::EqGreater:
|
||||||
case SolNodeType::EqLesser:
|
case SolNodeType::EqLesser:
|
||||||
return SolDataType::Bool;
|
return "bool";
|
||||||
break;
|
break;
|
||||||
case SolNodeType::Add:
|
case SolNodeType::Add:
|
||||||
{
|
{
|
||||||
if (checkNodeReturnType(i.children[0]) == SolDataType::String && checkNodeReturnType(i.children[1]) == SolDataType::String) {
|
if (checkNodeReturnType(i.children[0]) == "string" && checkNodeReturnType(i.children[1]) == "string") {
|
||||||
return SolDataType::String;
|
return "string";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SolNodeType::Subtract:
|
case SolNodeType::Subtract:
|
||||||
case SolNodeType::Multiply:
|
case SolNodeType::Multiply:
|
||||||
case SolNodeType::Divide:
|
case SolNodeType::Divide:
|
||||||
{
|
{
|
||||||
if (checkNodeReturnType(i.children[0]) == SolDataType::Double) {
|
if (checkNodeReturnType(i.children[0]) == "double") {
|
||||||
return SolDataType::Double;
|
return "double";
|
||||||
}
|
}
|
||||||
if (checkNodeReturnType(i.children[1]) == SolDataType::Double) {
|
if (checkNodeReturnType(i.children[1]) == "double") {
|
||||||
return SolDataType::Double;
|
return "double";
|
||||||
}
|
}
|
||||||
return SolDataType::Int;
|
return "int";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Puts:
|
case SolNodeType::Puts:
|
||||||
@@ -62,10 +61,11 @@ namespace Solstice {
|
|||||||
case SolNodeType::Set:
|
case SolNodeType::Set:
|
||||||
case SolNodeType::Root:
|
case SolNodeType::Root:
|
||||||
case SolNodeType::None:
|
case SolNodeType::None:
|
||||||
return SolDataType::None;
|
case SolNodeType::FunctionDef:
|
||||||
|
return "none";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return SolDataType::None;
|
return "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
// SolData Implementation
|
// SolData Implementation
|
||||||
@@ -74,6 +74,7 @@ namespace Solstice {
|
|||||||
SolData::SolData(std::string in) : data(in), type(SolDataType::String) {}
|
SolData::SolData(std::string in) : data(in), type(SolDataType::String) {}
|
||||||
SolData::SolData(char in) : data(in), type(SolDataType::Char) {}
|
SolData::SolData(char in) : data(in), type(SolDataType::Char) {}
|
||||||
SolData::SolData(bool in) : data(in), type(SolDataType::Bool) {}
|
SolData::SolData(bool in) : data(in), type(SolDataType::Bool) {}
|
||||||
|
SolData::SolData(SolFunction in) : data(in), type(SolDataType::Function) {}
|
||||||
|
|
||||||
std::optional<int64_t> SolData::getInt() {
|
std::optional<int64_t> SolData::getInt() {
|
||||||
if (type == SolDataType::Int) {
|
if (type == SolDataType::Int) {
|
||||||
@@ -110,6 +111,26 @@ namespace Solstice {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::optional<SolFunction> SolData::getFunction() {
|
||||||
|
if (type == SolDataType::Function) {
|
||||||
|
return std::get<SolFunction>(data);
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string SolData::getTypeString() {
|
||||||
|
switch (type) {
|
||||||
|
case SolDataType::Int: return "int";
|
||||||
|
case SolDataType::Double: return "double";
|
||||||
|
case SolDataType::String: return "string";
|
||||||
|
case SolDataType::Char: return "char";
|
||||||
|
case SolDataType::Bool: return "bool";
|
||||||
|
case SolDataType::Function: return "function";
|
||||||
|
case SolDataType::None: return "none";
|
||||||
|
}
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
// SolNode Implementation
|
// SolNode Implementation
|
||||||
SolNode::SolNode(SolNodeType nodeType) : nodeType(nodeType) {}
|
SolNode::SolNode(SolNodeType nodeType) : nodeType(nodeType) {}
|
||||||
@@ -178,8 +199,8 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Add: {
|
case SolNodeType::Add: {
|
||||||
ensure3(children[0], SolDataType::Int, SolDataType::Double, SolDataType::String, "operator '+'");
|
ensure3(children[0], "int", "double", "string", "operator '+'");
|
||||||
ensure3(children[1], SolDataType::Int, SolDataType::Double, SolDataType::String, "operator '+'");
|
ensure3(children[1], "int", "double", "string", "operator '+'");
|
||||||
ensuresame(children[0], children[1], "operator '+'");
|
ensuresame(children[0], children[1], "operator '+'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
@@ -197,8 +218,8 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Subtract: {
|
case SolNodeType::Subtract: {
|
||||||
ensure2(children[0], SolDataType::Int, SolDataType::Double, "operator '-'");
|
ensure2(children[0], "int", "double", "operator '-'");
|
||||||
ensure2(children[1], SolDataType::Int, SolDataType::Double, "operator '-'");
|
ensure2(children[1], "int", "double", "operator '-'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(SUBTRACT);
|
GroundInstruction gi = groundCreateInstruction(SUBTRACT);
|
||||||
@@ -215,8 +236,8 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Multiply: {
|
case SolNodeType::Multiply: {
|
||||||
ensure2(children[0], SolDataType::Int, SolDataType::Double, "operator '*'");
|
ensure2(children[0], "int", "double", "operator '*'");
|
||||||
ensure2(children[1], SolDataType::Int, SolDataType::Double, "operator '*'");
|
ensure2(children[1], "int", "double", "operator '*'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(MULTIPLY);
|
GroundInstruction gi = groundCreateInstruction(MULTIPLY);
|
||||||
@@ -233,8 +254,8 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Divide: {
|
case SolNodeType::Divide: {
|
||||||
ensure2(children[0], SolDataType::Int, SolDataType::Double, "operator '/'");
|
ensure2(children[0], "int", "double", "operator '/'");
|
||||||
ensure2(children[1], SolDataType::Int, SolDataType::Double, "operator '/'");
|
ensure2(children[1], "int", "double", "operator '/'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(DIVIDE);
|
GroundInstruction gi = groundCreateInstruction(DIVIDE);
|
||||||
@@ -478,7 +499,7 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::If: {
|
case SolNodeType::If: {
|
||||||
ensure(children[0], SolDataType::Bool, "if condition");
|
ensure(children[0], "bool", "if condition");
|
||||||
auto conditionCode = children[0].generateCode();
|
auto conditionCode = children[0].generateCode();
|
||||||
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
|
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
@@ -510,7 +531,7 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::While: {
|
case SolNodeType::While: {
|
||||||
ensure(children[0], SolDataType::Bool, "while condition");
|
ensure(children[0], "bool", "while condition");
|
||||||
SolGroundCodeBlock startLabelBlock;
|
SolGroundCodeBlock startLabelBlock;
|
||||||
std::string startLabelIdString = "whilestart_" + std::to_string(labelIterator++);
|
std::string startLabelIdString = "whilestart_" + std::to_string(labelIterator++);
|
||||||
std::string endLabelIdString = "whileend_" + std::to_string(labelIterator);
|
std::string endLabelIdString = "whileend_" + std::to_string(labelIterator);
|
||||||
@@ -574,13 +595,14 @@ namespace Solstice {
|
|||||||
if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId);
|
if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId);
|
||||||
code.push_back(codeBlock);
|
code.push_back(codeBlock);
|
||||||
// Make sure we know what the variable type is
|
// Make sure we know what the variable type is
|
||||||
variables[children[0].outputId] = children[1].data.type;
|
variables[children[0].outputId] = children[1].data.getTypeString();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::FunctionCall: {
|
case SolNodeType::FunctionCall: {
|
||||||
// Take care of in built functions
|
// Take care of in built functions
|
||||||
|
// This will be removed when inline ground is added
|
||||||
if (children[0].outputId == "input") {
|
if (children[0].outputId == "input") {
|
||||||
ensure(children[1], SolDataType::String, "input function argument");
|
ensure(children[1], "string", "input function argument");
|
||||||
SolGroundCodeBlock inputCodeBlock;
|
SolGroundCodeBlock inputCodeBlock;
|
||||||
if (children.size() > 1) {
|
if (children.size() > 1) {
|
||||||
GroundInstruction printInstruction = groundCreateInstruction(PRINT);
|
GroundInstruction printInstruction = groundCreateInstruction(PRINT);
|
||||||
@@ -595,6 +617,7 @@ namespace Solstice {
|
|||||||
code.push_back(inputCodeBlock);
|
code.push_back(inputCodeBlock);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
std::string fnToCall = children[0].outputId;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -728,6 +751,9 @@ namespace Solstice {
|
|||||||
if (in == "while") {
|
if (in == "while") {
|
||||||
return SolNodeType::While;
|
return SolNodeType::While;
|
||||||
}
|
}
|
||||||
|
if (in == "def") {
|
||||||
|
return SolNodeType::FunctionDef;
|
||||||
|
}
|
||||||
if (in == "{") {
|
if (in == "{") {
|
||||||
return SolNodeType::CodeBlockStart;
|
return SolNodeType::CodeBlockStart;
|
||||||
}
|
}
|
||||||
@@ -1154,6 +1180,93 @@ namespace Solstice {
|
|||||||
rootNode.addNode(node);
|
rootNode.addNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case SolNodeType::FunctionDef: {
|
||||||
|
SolFunction fn;
|
||||||
|
auto nameTokenOpt = consume();
|
||||||
|
if (!nameTokenOpt || getNodeType(nameTokenOpt.value().value) != SolNodeType::Identifier) {
|
||||||
|
Error::syntaxError("Expected function name", tokenObj.line, tokenObj.lineContent);
|
||||||
|
}
|
||||||
|
std::string fnName = nameTokenOpt.value().value;
|
||||||
|
|
||||||
|
auto openParen = consume();
|
||||||
|
if (!openParen || openParen.value().value != "(") {
|
||||||
|
Error::syntaxError("Expected '(' after function name", tokenObj.line, tokenObj.lineContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string signature = "fun(";
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
while (auto next = peek()) {
|
||||||
|
if (next.value().value == ")") {
|
||||||
|
consume();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!first) {
|
||||||
|
auto comma = consume();
|
||||||
|
if (comma.value().value != ",") {
|
||||||
|
Error::syntaxError("Expected ',' between arguments", tokenObj.line, tokenObj.lineContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto typeToken = consume();
|
||||||
|
if (!typeToken) Error::syntaxError("Expected type", tokenObj.line, tokenObj.lineContent);
|
||||||
|
std::string argType = typeToken.value().value;
|
||||||
|
|
||||||
|
auto argNameToken = consume();
|
||||||
|
if (!argNameToken) Error::syntaxError("Expected argument name", tokenObj.line, tokenObj.lineContent);
|
||||||
|
std::string argName = argNameToken.value().value;
|
||||||
|
|
||||||
|
fn.parameters.push_back({argName, argType});
|
||||||
|
|
||||||
|
if (!first) signature += ", ";
|
||||||
|
signature += argType;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
signature += ") ";
|
||||||
|
|
||||||
|
while (peek() && peek().value().value == "\n") consume();
|
||||||
|
|
||||||
|
auto next = peek();
|
||||||
|
if (next && next.value().value != "{") {
|
||||||
|
auto retTypeToken = consume();
|
||||||
|
fn.returnType = retTypeToken.value().value;
|
||||||
|
} else {
|
||||||
|
fn.returnType = "void";
|
||||||
|
}
|
||||||
|
signature += fn.returnType;
|
||||||
|
fn.signature = signature;
|
||||||
|
|
||||||
|
while (peek() && peek().value().value == "\n") consume();
|
||||||
|
|
||||||
|
auto brace = peek();
|
||||||
|
if (!brace || brace.value().value != "{") {
|
||||||
|
Error::syntaxError("Expected '{' starting function body", tokenObj.line, tokenObj.lineContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
consume();
|
||||||
|
std::vector<Token> bodyTokens;
|
||||||
|
size_t brackets = 1;
|
||||||
|
while(auto t = consume()) {
|
||||||
|
if (t.value().value == "{") brackets++;
|
||||||
|
if (t.value().value == "}") brackets--;
|
||||||
|
if (brackets == 0) break;
|
||||||
|
bodyTokens.push_back(t.value());
|
||||||
|
}
|
||||||
|
if (brackets != 0) Error::syntaxError("Unclosed function body", tokenObj.line, tokenObj.lineContent);
|
||||||
|
|
||||||
|
auto parsedBody = Parser(bodyTokens).parse();
|
||||||
|
auto bodyNode = std::make_shared<SolNode>(SolNodeType::CodeBlock);
|
||||||
|
bodyNode->children = parsedBody.children;
|
||||||
|
|
||||||
|
fn.content = bodyNode;
|
||||||
|
|
||||||
|
SolNode fnNode(SolNodeType::FunctionDef);
|
||||||
|
fnNode.data = SolData(fn);
|
||||||
|
variables[fnName] = signature;
|
||||||
|
|
||||||
|
rootNode.addNode(fnNode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rootNode;
|
return rootNode;
|
||||||
@@ -1179,4 +1292,4 @@ namespace Solstice {
|
|||||||
|
|
||||||
} // namespace Parser
|
} // namespace Parser
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
43
src/parser.h
43
src/parser.h
@@ -7,34 +7,35 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include <memory>
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
#define ensure(node, datatype, op) \
|
#define ensure(node, datatype, op) \
|
||||||
if (checkNodeReturnType(node) != datatype) { \
|
if (checkNodeReturnType(node) != datatype) { \
|
||||||
Error::typingError("Expected " #datatype " for " op, node.line, node.lineContent); \
|
Error::typingError("Expected " + std::string(datatype) + " for " + op, node.line, node.lineContent); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ensure2(node, datatype1, datatype2, op) { \
|
#define ensure2(node, datatype1, datatype2, op) { \
|
||||||
SolDataType dataType = checkNodeReturnType(node); \
|
std::string dataType = checkNodeReturnType(node); \
|
||||||
if (!(dataType == datatype1 || dataType == datatype2)) { \
|
if (!(dataType == datatype1 || dataType == datatype2)) { \
|
||||||
Error::typingError("Expected either " #datatype1 " or " #datatype2 " for " op, node.line, node.lineContent); \
|
Error::typingError("Expected either " + std::string(datatype1) + " or " + std::string(datatype2) + " for " + op, node.line, node.lineContent); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ensure3(node, datatype1, datatype2, datatype3, op) { \
|
#define ensure3(node, datatype1, datatype2, datatype3, op) { \
|
||||||
SolDataType dataType = checkNodeReturnType(node); \
|
std::string dataType = checkNodeReturnType(node); \
|
||||||
if (!(dataType == datatype1 || dataType == datatype2 || dataType == datatype3)) { \
|
if (!(dataType == datatype1 || dataType == datatype2 || dataType == datatype3)) { \
|
||||||
Error::typingError("Expected either " #datatype1 ", " #datatype2 ", or " #datatype3 " for " op, node.line, node.lineContent); \
|
Error::typingError("Expected either " + std::string(datatype1) + ", " + std::string(datatype2) + ", or " + std::string(datatype3) + " for " + op, node.line, node.lineContent); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ensuresame(node1, node2, op) { \
|
#define ensuresame(node1, node2, op) { \
|
||||||
SolDataType n1t = checkNodeReturnType(node1); \
|
std::string n1t = checkNodeReturnType(node1); \
|
||||||
SolDataType n2t = checkNodeReturnType(node2); \
|
std::string n2t = checkNodeReturnType(node2); \
|
||||||
if (n1t != n2t) { \
|
if (n1t != n2t) { \
|
||||||
if (!(n1t == SolDataType::Int && n2t == SolDataType::Double || n1t == SolDataType::Double && n2t == SolDataType::Int)) { \
|
if (!(n1t == "int" && n2t == "double" || n1t == "double" && n2t == "int")) { \
|
||||||
Error::typingError("Expected types to be the same for " op, node1.line, node1.lineContent); \
|
Error::typingError("Expected types to be the same for " + std::string(op), node1.line, node1.lineContent); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
@@ -56,14 +57,14 @@ namespace Solstice {
|
|||||||
|
|
||||||
|
|
||||||
enum class SolNodeType {
|
enum class SolNodeType {
|
||||||
Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, EqGreater, EqLesser, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, FunctionCall, Expression, BracketStart, BracketEnd, Puts
|
Add, Subtract, Multiply, Divide, Equal, Inequal, Greater, Lesser, EqGreater, EqLesser, Set, While, If, Value, Identifier, None, Root, CodeBlock, CodeBlockStart, CodeBlockEnd, FunctionDef, FunctionCall, Expression, BracketStart, BracketEnd, Puts
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SolDataType {
|
enum class SolDataType {
|
||||||
Int, String, Double, Bool, Char, None
|
Int, String, Double, Bool, Char, Function, None
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::map<std::string, SolDataType> variables;
|
extern std::map<std::string, std::string> variables;
|
||||||
|
|
||||||
class SolNode;
|
class SolNode;
|
||||||
|
|
||||||
@@ -74,8 +75,17 @@ namespace Solstice {
|
|||||||
SolGroundCodeBlock() = default;
|
SolGroundCodeBlock() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SolFunction {
|
||||||
|
public:
|
||||||
|
std::string signature;
|
||||||
|
std::vector<std::pair<std::string, std::string>> parameters; // name, type
|
||||||
|
std::string returnType;
|
||||||
|
std::shared_ptr<SolNode> content;
|
||||||
|
SolFunction() = default;
|
||||||
|
};
|
||||||
|
|
||||||
class SolData {
|
class SolData {
|
||||||
typedef std::variant<int64_t, std::string, double, bool, char> varData;
|
typedef std::variant<int64_t, std::string, double, bool, char, SolFunction> varData;
|
||||||
varData data;
|
varData data;
|
||||||
public:
|
public:
|
||||||
SolDataType type = SolDataType::Int;
|
SolDataType type = SolDataType::Int;
|
||||||
@@ -85,11 +95,14 @@ namespace Solstice {
|
|||||||
SolData(std::string in);
|
SolData(std::string in);
|
||||||
SolData(char in);
|
SolData(char in);
|
||||||
SolData(bool in);
|
SolData(bool in);
|
||||||
|
SolData(SolFunction in);
|
||||||
std::optional<int64_t> getInt();
|
std::optional<int64_t> getInt();
|
||||||
std::optional<double> getDouble();
|
std::optional<double> getDouble();
|
||||||
std::optional<std::string> getString();
|
std::optional<std::string> getString();
|
||||||
std::optional<char> getChar();
|
std::optional<char> getChar();
|
||||||
std::optional<bool> getBool();
|
std::optional<bool> getBool();
|
||||||
|
std::optional<SolFunction> getFunction();
|
||||||
|
std::string getTypeString();
|
||||||
};
|
};
|
||||||
|
|
||||||
class SolNode {
|
class SolNode {
|
||||||
@@ -134,7 +147,7 @@ namespace Solstice {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GroundProgram assembleProgram(SolNode& rootNode);
|
GroundProgram assembleProgram(SolNode& rootNode);
|
||||||
SolDataType checkNodeReturnType(SolNode in);
|
std::string checkNodeReturnType(SolNode in);
|
||||||
|
|
||||||
} // namespace Parser
|
} // namespace Parser
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user