diff --git a/src/parser.cpp b/src/parser.cpp index 0a125fa..7e6e502 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -25,6 +25,9 @@ namespace Solstice { } break; } + case SolNodeType::Value: { + return i.data.type; + } case SolNodeType::Equal: case SolNodeType::Inequal: case SolNodeType::Greater: @@ -56,7 +59,9 @@ namespace Solstice { case SolNodeType::If: case SolNodeType::While: case SolNodeType::CodeBlock: - default: + case SolNodeType::Set: + case SolNodeType::Root: + case SolNodeType::None: return SolDataType::None; break; } @@ -173,6 +178,9 @@ namespace Solstice { break; } case SolNodeType::Add: { + ensure3(children[0], SolDataType::Int, SolDataType::Double, SolDataType::String); + ensure3(children[1], SolDataType::Int, SolDataType::Double, SolDataType::String); + ensuresame(children[0], children[1]); SolGroundCodeBlock codeBlock; outputId = "tmp_" + std::to_string(tmpIdIterator++); GroundInstruction gi = groundCreateInstruction(ADD); @@ -188,7 +196,26 @@ namespace Solstice { code.push_back(codeBlock); break; } + case SolNodeType::Subtract: { + ensure2(children[0], SolDataType::Int, SolDataType::Double); + ensure2(children[1], SolDataType::Int, SolDataType::Double); + SolGroundCodeBlock codeBlock; + outputId = "tmp_" + std::to_string(tmpIdIterator++); + GroundInstruction gi = groundCreateInstruction(SUBTRACT); + if (children.size() < 2) { + std::cout << "Need more stuff to add\n"; + } + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data())); + groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data())); + codeBlock.code.push_back(gi); + if (isTemp(children[0].outputId)) codeBlock.toBeDropped.push_back(children[0].outputId); + if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId); + code.push_back(codeBlock); + break; + } case SolNodeType::Equal: { + ensuresame(children[0], children[1]); SolGroundCodeBlock codeBlock; outputId = "tmp_" + std::to_string(tmpIdIterator++); GroundInstruction gi = groundCreateInstruction(EQUAL); @@ -205,6 +232,7 @@ namespace Solstice { break; } case SolNodeType::Inequal: { + ensuresame(children[0], children[1]); SolGroundCodeBlock codeBlock; outputId = "tmp_" + std::to_string(tmpIdIterator++); GroundInstruction gi = groundCreateInstruction(INEQUAL); @@ -221,6 +249,7 @@ namespace Solstice { break; } case SolNodeType::Greater: { + ensuresame(children[0], children[1]); SolGroundCodeBlock codeBlock; outputId = "tmp_" + std::to_string(tmpIdIterator++); GroundInstruction gi = groundCreateInstruction(GREATER); @@ -237,6 +266,7 @@ namespace Solstice { break; } case SolNodeType::Lesser: { + ensuresame(children[0], children[1]); SolGroundCodeBlock codeBlock; outputId = "tmp_" + std::to_string(tmpIdIterator++); GroundInstruction gi = groundCreateInstruction(LESSER); @@ -253,6 +283,7 @@ namespace Solstice { break; } case SolNodeType::EqGreater: { + ensuresame(children[0], children[1]); SolGroundCodeBlock codeBlock; if (children.size() < 2) { std::cout << "Need more stuff to inequal\n"; @@ -325,6 +356,7 @@ namespace Solstice { break; } case SolNodeType::EqLesser: { + ensuresame(children[0], children[1]); SolGroundCodeBlock codeBlock; if (children.size() < 2) { std::cout << "Need more stuff to inequal\n"; @@ -398,6 +430,7 @@ namespace Solstice { } case SolNodeType::Puts: { SolGroundCodeBlock codeBlock; + exists(children[0]); GroundInstruction gi = groundCreateInstruction(PRINTLN); if (children.size() < 1) { std::cout << "Need more stuff to puts\n"; @@ -496,6 +529,7 @@ namespace Solstice { Error::typingError("Cannot change type of this variable"); } } + exists(children[1]); SolGroundCodeBlock codeBlock; GroundInstruction setInstruction = groundCreateInstruction(SET); groundAddReferenceToInstruction(&setInstruction, groundCreateReference(DIRREF, children[0].outputId.data())); @@ -510,6 +544,7 @@ namespace Solstice { case SolNodeType::FunctionCall: { // Take care of in built functions if (children[0].outputId == "input") { + ensure(children[1], SolDataType::String); SolGroundCodeBlock inputCodeBlock; if (children.size() > 1) { GroundInstruction printInstruction = groundCreateInstruction(PRINT); @@ -618,6 +653,15 @@ namespace Solstice { if (in == "+") { return SolNodeType::Add; } + if (in == "-") { + return SolNodeType::Subtract; + } + if (in == "*") { + return SolNodeType::Multiply; + } + if (in == "/") { + return SolNodeType::Divide; + } if (in == "=") { return SolNodeType::Set; } @@ -705,8 +749,12 @@ namespace Solstice { } break; } - case SolNodeType::Add: { - SolNode addNode(SolNodeType::Add); + case SolNodeType::Add: + case SolNodeType::Subtract: + case SolNodeType::Multiply: + case SolNodeType::Divide: + { + SolNode addNode(getNodeType(token)); addNode.addNode(rootNode.children.back()); rootNode.children.pop_back(); auto tokenopt = consume(); diff --git a/src/parser.h b/src/parser.h index b57ed2f..453683c 100644 --- a/src/parser.h +++ b/src/parser.h @@ -13,9 +13,35 @@ Error::typingError("Expected " #datatype); \ } -#define ensure2(node, datatype1, datatype2) \ - if (checkNodeReturnType(node) != datatype1 && checkNodeReturnType(node) != datatype2) { \ - Error::typingError("Expected either " #datatype1 " or " #datatype2); \ +#define ensure2(node, datatype1, datatype2) { \ + SolDataType dataType = checkNodeReturnType(node); \ + if (!(dataType == datatype1 || dataType == datatype2)) { \ + Error::typingError("Expected either " #datatype1 " or " #datatype2); \ + } \ + } + +#define ensure3(node, datatype1, datatype2, datatype3) { \ + SolDataType dataType = checkNodeReturnType(node); \ + if (!(dataType == datatype1 || dataType == datatype2 || dataType == datatype3)) { \ + Error::typingError("Expected either " #datatype1 ", " #datatype2 ", or " #datatype3); \ + } \ + } + +#define ensuresame(node1, node2) { \ + SolDataType n1t = checkNodeReturnType(node1); \ + SolDataType n2t = checkNodeReturnType(node2); \ + if (n1t != n2t) { \ + if (!(n1t == SolDataType::Int && n2t == SolDataType::Double || n1t == SolDataType::Double && n2t == SolDataType::Int)) { \ + Error::typingError("Expected types to be the same"); \ + } \ + } \ + } + +#define exists(node) \ + if (node.nodeType == SolNodeType::Identifier) { \ + if (variables.find(node.outputId) == variables.end()) { \ + Error::syntaxError("Variable does not exist"); \ + } \ } namespace Solstice { @@ -65,8 +91,8 @@ namespace Solstice { }; class SolNode { - SolData data; public: + SolData data; SolNodeType nodeType = SolNodeType::None; std::vector children; std::string outputId;