Start work on static type checking

This commit is contained in:
2025-12-24 13:15:48 +11:00
parent 7dd2b10603
commit 5ec2f86b70
5 changed files with 104 additions and 4 deletions

View File

@@ -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: {