forked from solstice/solstice
Start work on static type checking
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
#include "parser.h"
|
||||
#include "error.h"
|
||||
#include <groundvm.h>
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#define parseOneToken(token) Parser({token.value()}).parse().children[0]
|
||||
|
||||
@@ -13,6 +13,56 @@ namespace Solstice {
|
||||
return id.rfind("tmp_", 0) == 0;
|
||||
}
|
||||
|
||||
std::map<std::string, SolDataType> variables;
|
||||
|
||||
SolDataType checkNodeReturnType(SolNode i) {
|
||||
switch (i.nodeType) {
|
||||
case SolNodeType::Identifier: {
|
||||
if (variables.find(i.outputId) != variables.end()) {
|
||||
return variables[i.outputId];
|
||||
} else {
|
||||
Error::syntaxError("Unknown variable");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Equal:
|
||||
case SolNodeType::Inequal:
|
||||
case SolNodeType::Greater:
|
||||
case SolNodeType::Lesser:
|
||||
case SolNodeType::EqGreater:
|
||||
case SolNodeType::EqLesser:
|
||||
return SolDataType::Bool;
|
||||
break;
|
||||
case SolNodeType::Add:
|
||||
{
|
||||
if (checkNodeReturnType(i.children[0]) == SolDataType::String && checkNodeReturnType(i.children[1]) == SolDataType::String) {
|
||||
return SolDataType::String;
|
||||
}
|
||||
}
|
||||
case SolNodeType::Subtract:
|
||||
case SolNodeType::Multiply:
|
||||
case SolNodeType::Divide:
|
||||
{
|
||||
if (checkNodeReturnType(i.children[0]) == SolDataType::Double) {
|
||||
return SolDataType::Double;
|
||||
}
|
||||
if (checkNodeReturnType(i.children[1]) == SolDataType::Double) {
|
||||
return SolDataType::Double;
|
||||
}
|
||||
return SolDataType::Int;
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Puts:
|
||||
case SolNodeType::If:
|
||||
case SolNodeType::While:
|
||||
case SolNodeType::CodeBlock:
|
||||
default:
|
||||
return SolDataType::None;
|
||||
break;
|
||||
}
|
||||
return SolDataType::None;
|
||||
}
|
||||
|
||||
// SolData Implementation
|
||||
SolData::SolData(int64_t in) : data(in), type(SolDataType::Int) {}
|
||||
SolData::SolData(double in) : data(in), type(SolDataType::Double) {}
|
||||
@@ -359,6 +409,7 @@ namespace Solstice {
|
||||
break;
|
||||
}
|
||||
case SolNodeType::If: {
|
||||
ensure(children[0], SolDataType::Bool);
|
||||
auto conditionCode = children[0].generateCode();
|
||||
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
@@ -390,6 +441,7 @@ namespace Solstice {
|
||||
break;
|
||||
}
|
||||
case SolNodeType::While: {
|
||||
ensure(children[0], SolDataType::Bool);
|
||||
SolGroundCodeBlock startLabelBlock;
|
||||
std::string startLabelIdString = "whilestart_" + std::to_string(labelIterator++);
|
||||
std::string endLabelIdString = "whileend_" + std::to_string(labelIterator);
|
||||
@@ -439,6 +491,11 @@ namespace Solstice {
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Set: {
|
||||
if (variables.find(children[0].outputId) != variables.end()) {
|
||||
if (variables[children[0].outputId] != checkNodeReturnType(children[1])) {
|
||||
Error::typingError("Cannot change type of this variable");
|
||||
}
|
||||
}
|
||||
SolGroundCodeBlock codeBlock;
|
||||
GroundInstruction setInstruction = groundCreateInstruction(SET);
|
||||
groundAddReferenceToInstruction(&setInstruction, groundCreateReference(DIRREF, children[0].outputId.data()));
|
||||
@@ -446,6 +503,8 @@ namespace Solstice {
|
||||
codeBlock.code.push_back(setInstruction);
|
||||
if (isTemp(children[1].outputId)) codeBlock.toBeDropped.push_back(children[1].outputId);
|
||||
code.push_back(codeBlock);
|
||||
// Make sure we know what the variable type is
|
||||
variables[children[0].outputId] = children[1].data.type;
|
||||
break;
|
||||
}
|
||||
case SolNodeType::FunctionCall: {
|
||||
|
||||
Reference in New Issue
Block a user