A bunch more stuffs

This commit is contained in:
2026-08-02 14:09:38 +10:00
parent 437260438c
commit 16846d13bb
7 changed files with 187 additions and 7 deletions

View File

@@ -242,6 +242,60 @@ namespace Solstice {
break; break;
} }
case '=': {
if (!buf.empty()) {
output.push_back(processToken(buf));
buf.clear();
}
if (peek() && *peek() == '=') {
output.push_back(TT::Comparison_Equal);
consume();
} else {
output.push_back(TT::Assign_Set);
}
break;
}
case '/': {
if (!buf.empty()) {
output.push_back(processToken(buf));
buf.clear();
}
if (peek() && *peek() == '/') {
consume();
// comment
for (;;) {
auto next = consume();
if (!next.has_value()) {
break;
}
if (*next == '\n') {
break;
}
}
} else if (peek() && *peek() == '*') {
consume();
/* comment */
for (;;) {
auto next = consume();
if (!next.has_value()) {
throw std::runtime_error("unterminated multi-line comment");
}
if (*next == '*') {
if (peek() && *peek() == '/') {
consume();
break;
}
}
}
} else {
output.push_back(TT::Assign_Set);
}
break;
}
// all the delimiters // all the delimiters
case '<': case '<':
case '>': case '>':
@@ -251,7 +305,6 @@ namespace Solstice {
case ')': case ')':
case '+': case '+':
case '*': case '*':
case '/':
case ',': case ',':
{ {
if (!buf.empty()) { if (!buf.empty()) {

View File

@@ -17,6 +17,9 @@ namespace Solstice {
{TT::Comparison_NotEqual, NodeType::NotEqual}, {TT::Comparison_NotEqual, NodeType::NotEqual},
{TT::Comparison_GreaterThan, NodeType::GreaterThan}, {TT::Comparison_GreaterThan, NodeType::GreaterThan},
{TT::Comparison_LesserThan, NodeType::LesserThan}, {TT::Comparison_LesserThan, NodeType::LesserThan},
{TT::Assign_Type, NodeType::SetType},
{TT::Assign_Set, NodeType::Set},
{TT::Assign_Bind, NodeType::Bind},
}; };
std::optional<Literal> Node::getLiteral() const { std::optional<Literal> Node::getLiteral() const {
@@ -52,6 +55,8 @@ namespace Solstice {
return "Bind"; return "Bind";
case NodeType::Set: case NodeType::Set:
return "Set"; return "Set";
case NodeType::SetType:
return "SetType";
case NodeType::Lambda: case NodeType::Lambda:
return "Lambda"; return "Lambda";
case NodeType::FunctionCall: case NodeType::FunctionCall:
@@ -383,6 +388,11 @@ namespace Solstice {
case TT::Math_Multiply: case TT::Math_Multiply:
case TT::Math_Divide: case TT::Math_Divide:
return Precedence::Multiply; return Precedence::Multiply;
case TT::Comparison_Equal:
case TT::Comparison_NotEqual:
case TT::Comparison_GreaterThan:
case TT::Comparison_LesserThan:
return Precedence::Compare;
case TT::Assign_Bind: case TT::Assign_Bind:
case TT::Assign_Set: case TT::Assign_Set:
case TT::Assign_Type: case TT::Assign_Type:
@@ -417,6 +427,13 @@ namespace Solstice {
case TT::Math_Subtract: case TT::Math_Subtract:
case TT::Math_Multiply: case TT::Math_Multiply:
case TT::Math_Divide: case TT::Math_Divide:
case TT::Comparison_Equal:
case TT::Comparison_NotEqual:
case TT::Comparison_GreaterThan:
case TT::Comparison_LesserThan:
case TT::Assign_Set:
case TT::Assign_Bind:
case TT::Assign_Type:
return parseExpr(next->type); return parseExpr(next->type);
case TT::OpenParen: case TT::OpenParen:
return parseOpenParen(); return parseOpenParen();

View File

@@ -12,7 +12,7 @@ namespace Solstice {
enum class NodeType { enum class NodeType {
Root, Literal, Identifier, Expression, Tuple, Root, Literal, Identifier, Expression, Tuple,
CodeBlock, CodeBlock,
FunctionBind, Bind, Set, FunctionBind, Bind, Set, SetType,
Lambda, FunctionCall, Lambda, FunctionCall,
Add, Subtract, Multiply, Divide, Add, Subtract, Multiply, Divide,
Equal, NotEqual, GreaterThan, LesserThan Equal, NotEqual, GreaterThan, LesserThan

View File

@@ -56,4 +56,15 @@ namespace Solstice {
return left.left == right.left && left.right == right.right; return left.left == right.left && left.right == right.right;
} }
std::optional<Type> PossibleType::getOnlyType() {
if (possiblities.size() != 1) {
return {};
}
for (const auto& type : possiblities) {
// just return one
return type;
}
return {};
}
} }

View File

@@ -30,11 +30,13 @@ namespace Solstice {
std::nullopt_t std::nullopt_t
> fields = std::nullopt; > fields = std::nullopt;
bool isConstant = false;
std::optional<std::map<std::string, Type>> getObject() const; std::optional<std::map<std::string, Type>> getObject() const;
std::optional<std::vector<Type>> getTuple() const; std::optional<std::vector<Type>> getTuple() const;
std::optional<Type> getArrayOrPointer() const; std::optional<Type> getArrayOrPointer() const;
Type() = delete; Type() = default;
Type(BaseType type) : type(type) {} Type(BaseType type) : type(type) {}
}; };
@@ -106,6 +108,18 @@ namespace Solstice {
PossibleType() = default; PossibleType() = default;
PossibleType(const std::unordered_set<Type>& possiblities) : possiblities(possiblities) {} PossibleType(const std::unordered_set<Type>& possiblities) : possiblities(possiblities) {}
std::optional<Type> getOnlyType();
};
struct Function {
PossibleType returnType = {{BaseType::None}};
std::vector<PossibleType> argumentTypes = {};
Function() = default;
Function(PossibleType returnType) : returnType(returnType) {}
Function(PossibleType returnType, std::vector<PossibleType> argumentTypes)
: returnType(returnType), argumentTypes(argumentTypes) {}
}; };
} }

View File

@@ -1,6 +1,7 @@
#include "typechecker.hpp" #include "typechecker.hpp"
#include "type.hpp" #include "type.hpp"
#include <stdexcept> #include <stdexcept>
#include <iostream>
namespace Solstice { namespace Solstice {
@@ -107,21 +108,84 @@ namespace Solstice {
throw std::runtime_error("unknown variable " + *identifier); throw std::runtime_error("unknown variable " + *identifier);
} }
node.ptype = variables[*identifier]; node.ptype = {{variables[*identifier]}};
} }
void TypeChecker::checkTupleNodeType(Node& node) { void TypeChecker::checkTupleNodeType(Node& node) {
for (auto& child : node.children) { for (auto& child : node.children) {
checkNodeType(child); checkNodeType(child);
} }
// TODO implemnt tuple type checking
} }
void TypeChecker::checkBindNodeType(Node& node) {
auto id = node.children[0].getIdentifier();
if (!id.has_value()) {
throw std::runtime_error("FIXME identifier node does not contain identifier");
}
if (variables.find(*id) != variables.end()) {
throw std::runtime_error("Cannot overwrite existing bind/variable/function with new bind");
}
checkNodeType(node.children[1]);
auto nodeType = node.children[1].ptype.getOnlyType();
if (!nodeType.has_value()) {
throw std::runtime_error("cannot assign ambiguous type to name");
}
variables[*id] = *nodeType;
variables[*id].isConstant = true;
}
void TypeChecker::checkFunctionBindNodeType(Node& node) {
auto id = node.children[0].getIdentifier();
if (!id.has_value()) {
throw std::runtime_error("FIXME identifier node does not contain identifier");
}
if (variables.find(*id) != variables.end()) {
throw std::runtime_error("Cannot overwrite existing bind/variable/function with new function");
}
checkNodeType(node.children[1]);
auto nodeType = node.children[1].ptype.getOnlyType();
if (!nodeType.has_value()) {
throw std::runtime_error("cannot assign ambiguous type to name");
}
variables[*id] = *nodeType;
variables[*id].isConstant = true;
}
void TypeChecker::checkSetNodeType(Node& node) {
auto id = node.children[0].getIdentifier();
if (!id.has_value()) {
throw std::runtime_error("FIXME identifier node does not contain identifier");
}
if (variables.find(*id) != variables.end()) {
if (variables[*id].isConstant) {
throw std::runtime_error("cannot reassign existing bind");
}
}
if (!inFunction) {
throw std::runtime_error("mutable variables may only be used in functions");
}
checkNodeType(node.children[1]);
auto nodeType = node.children[1].ptype.getOnlyType();
if (!nodeType.has_value()) {
throw std::runtime_error("cannot assign ambiguous type to name");
}
variables[*id] = *nodeType;
}
void TypeChecker::checkCodeBlockType(Node& node) {}
void TypeChecker::checkNodeType(Node& node) { void TypeChecker::checkNodeType(Node& node) {
switch (node.type) { switch (node.type) {
case NodeType::Root: case NodeType::Root:
node.ptype = {{}}; // no possible types for root node node.ptype = {{}}; // no possible types for root node
for (auto& child : node.children) {
checkNodeType(child);
}
break; break;
case NodeType::Literal: case NodeType::Literal:
checkLiteralNodeType(node); checkLiteralNodeType(node);
@@ -135,6 +199,19 @@ namespace Solstice {
case NodeType::Tuple: case NodeType::Tuple:
checkTupleNodeType(node); checkTupleNodeType(node);
break; break;
case NodeType::Bind:
checkBindNodeType(node);
break;
case NodeType::FunctionBind:
checkFunctionBindNodeType(node);
break;
case NodeType::Set:
checkSetNodeType(node);
break;
case NodeType::CodeBlock:
checkCodeBlockType(node);
break;
} }
} }

View File

@@ -9,7 +9,7 @@
namespace Solstice { namespace Solstice {
class TypeChecker { class TypeChecker {
std::unordered_map<std::string, PossibleType> variables; std::unordered_map<std::string, Type> variables;
std::unordered_map<std::string, Type> types; std::unordered_map<std::string, Type> types;
std::unordered_map<TypePair, Type> addOverloads; std::unordered_map<TypePair, Type> addOverloads;
@@ -23,12 +23,20 @@ namespace Solstice {
Node& input; Node& input;
bool inFunction = false;
void initOverloads(); void initOverloads();
void checkLiteralNodeType(Node& node); void checkLiteralNodeType(Node& node);
void checkIdentifierNodeType(Node& node); void checkIdentifierNodeType(Node& node);
void checkTupleNodeType(Node& node); void checkTupleNodeType(Node& node);
void checkBindNodeType(Node& node);
void checkFunctionBindNodeType(Node& node);
void checkSetNodeType(Node& node);
void checkCodeBlockType(Node& node);
void checkNodeType(Node& node); void checkNodeType(Node& node);
public: public: