This commit is contained in:
2026-02-27 14:54:16 +11:00
parent e7e5cc92d5
commit 8756dd08c8
4 changed files with 143 additions and 4 deletions

View File

@@ -97,6 +97,37 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
} }
return Success(SolsType, charptr, type.as.success); return Success(SolsType, charptr, type.as.success);
} }
case SNT_OP_EQUAL: {
if (node->children.count < 2) {
return Error(SolsType, charptr, "Not enough children to determine type");
}
ResultType(SolsType, charptr) leftType = getNodeType(&node->children.at[0], scope);
if (leftType.error) {
return Error(SolsType, charptr, leftType.as.error);
}
ResultType(SolsType, charptr) rightType = getNodeType(&node->children.at[1], scope);
if (rightType.error) {
return Error(SolsType, charptr, rightType.as.error);
}
if (leftType.as.success.type == STT_FUN || leftType.as.success.type == STT_TEMPLATE || leftType.as.success.type == STT_OBJECT) {
return Error(SolsType, charptr, "Cannot compare with left type");
}
if (rightType.as.success.type == STT_FUN || rightType.as.success.type == STT_TEMPLATE || rightType.as.success.type == STT_OBJECT) {
return Error(SolsType, charptr, "Cannot compare with right type");
}
if (leftType.as.success.type == rightType.as.success.type) {
return Success(SolsType, charptr, {STT_BOOL});
}
if ((leftType.as.success.type == STT_INT && rightType.as.success.type == STT_DOUBLE) || (rightType.as.success.type == STT_INT && leftType.as.success.type == STT_DOUBLE)) {
return Success(SolsType, charptr, {STT_BOOL});
}
return Error(SolsType, charptr, "");
}
case SNT_LITERAL: { case SNT_LITERAL: {
switch (node->as.literal.type) { switch (node->as.literal.type) {
case SLT_INT: { case SLT_INT: {
@@ -302,6 +333,36 @@ static inline ResultType(GroundProgram, charptr) generateDivNode(SolsNode* node,
return Success(GroundProgram, charptr, gp); return Success(GroundProgram, charptr, gp);
} }
static inline ResultType(GroundProgram, charptr) generateEqualNode(SolsNode* node, SolsScope* scope) {
if (node->children.count < 2) {
return Error(GroundProgram, charptr, "equal requires arguments");
}
// Use this function for type checking
ResultType(SolsType, charptr) type = getNodeType(node, scope);
if (type.error) {
return Error(GroundProgram, charptr, type.as.error);
}
GroundProgram gp = groundCreateProgram();
GroundInstruction add = groundCreateInstruction(EQUAL);
groundAddReferenceToInstruction(&add, node->children.at[0].accessArg);
groundAddReferenceToInstruction(&add, node->children.at[1].accessArg);
char* tmpId = malloc(sizeof(char) * 64);
if (tmpId == NULL) {
return Error(GroundProgram, charptr, "Failed to allocate memory for temporary identifier in equal");
}
snprintf(tmpId, 64, "__SOLS_TMP_EQUAL_%zu", scope->tmpCounter++);
groundAddReferenceToInstruction(&add, groundCreateReference(DIRREF, tmpId));
node->accessArg = groundCreateReference(VALREF, tmpId);
groundAddInstructionToProgram(&gp, add);
return Success(GroundProgram, charptr, gp);
}
ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) { ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope) {
GroundProgram program = groundCreateProgram(); GroundProgram program = groundCreateProgram();
@@ -326,6 +387,7 @@ ResultType(GroundProgram, charptr) generateCode(SolsNode* node, SolsScope* scope
case SNT_OP_SUB: generate(Sub); case SNT_OP_SUB: generate(Sub);
case SNT_OP_MUL: generate(Mul); case SNT_OP_MUL: generate(Mul);
case SNT_OP_DIV: generate(Div); case SNT_OP_DIV: generate(Div);
case SNT_OP_EQUAL: generate(Equal);
} }
return Success(GroundProgram, charptr, program); return Success(GroundProgram, charptr, program);
} }

View File

@@ -19,6 +19,12 @@ SolsTokenPrecedence getPrecedence(SolsToken *token) {
// FIXME figure out how to do functions // FIXME figure out how to do functions
case STT_OP_MUL: case STT_OP_DIV: return STP_MUL; case STT_OP_MUL: case STT_OP_DIV: return STP_MUL;
case STT_OP_ADD: case STT_OP_SUB: return STP_ADD; case STT_OP_ADD: case STT_OP_SUB: return STP_ADD;
case STT_OP_EQUAL:
case STT_OP_EQGREATER:
case STT_OP_EQLESSER:
case STT_OP_INEQUAL:
case STT_OP_GREATER:
case STT_OP_LESSER: return STP_COMPARE;
default: return STP_OTHER; default: return STP_OTHER;
} }
} }
@@ -466,6 +472,68 @@ static inline ResultType(Nothing, charptr) parseDiv(SolsParser* parser) {
return Success(Nothing, charptr, {}); return Success(Nothing, charptr, {});
} }
static inline ResultType(Nothing, charptr) parseEqual(SolsParser* parser) {
if (parser->currentParent->children.count < 1) {
return Error(Nothing, charptr, "Expecting something before '=='");
}
// Collect tokens for node
ResultType(SolsTokens, charptr) tokens = createSolsTokens();
if (tokens.error) {
return Error(Nothing, charptr, tokens.as.error);
}
// Get the previous node
SolsNode idNode = parser->currentParent->children.at[parser->currentParent->children.count - 1];
ResultType(SolsToken, Nothing) peek = parserPeek(parser, 0);
if (peek.error) return Error(Nothing, charptr, "ruh roh");
for (;;) {
ResultType(SolsToken, Nothing) peek = parserPeek(parser, 1);
if (peek.error) break;
if (getPrecedence(&peek.as.success) <= STP_COMPARE) {
break;
}
parserConsume(parser);
addTokenToSolsTokens(&tokens.as.success, peek.as.success);
}
// Create node
ResultType(SolsNode, charptr) node = createSolsNode(SNT_OP_EQUAL);
if (node.error) return Error(Nothing, charptr, node.as.error);
node.as.success.line = peek.as.success.line;
// Parse selected tokens
ResultType(SolsParser, charptr) putsParser = createSolsParser(&tokens.as.success);
if (putsParser.error) return Error(Nothing, charptr, putsParser.as.error);
putsParser.as.success.currentParent = &putsParser.as.success.output;
ResultType(Nothing, charptr) parsed = parse(&putsParser.as.success);
// Add any error messages from parsing
if (parsed.error) {
addToParserErrors(parser, parsed.as.error);
return Success(Nothing, charptr, {});
}
if (putsParser.as.success.output.children.count < 1) {
return Error(Nothing, charptr, "Expecting token after '=='");
}
// Copy idnode into set node
addChildToSolsNode(&node.as.success, idNode);
// Copy nodes into the set node
for (size_t i = 0; i < putsParser.as.success.output.children.count; i++) {
addChildToSolsNode(&node.as.success, putsParser.as.success.output.children.at[i]);
}
// Put the equal node where the idNode was
parser->currentParent->children.count--;
addChildToSolsNode(parser->currentParent, node.as.success);
return Success(Nothing, charptr, {});
}
static inline ResultType(Nothing, charptr) parseLiteral(SolsParser* parser) { static inline ResultType(Nothing, charptr) parseLiteral(SolsParser* parser) {
ResultType(SolsToken, Nothing) peek = parserPeek(parser, 0); ResultType(SolsToken, Nothing) peek = parserPeek(parser, 0);
@@ -574,6 +642,7 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) {
case STT_OP_SUB: PARSER_HANDLE(Sub); case STT_OP_SUB: PARSER_HANDLE(Sub);
case STT_OP_MUL: PARSER_HANDLE(Mul); case STT_OP_MUL: PARSER_HANDLE(Mul);
case STT_OP_DIV: PARSER_HANDLE(Div); case STT_OP_DIV: PARSER_HANDLE(Div);
case STT_OP_EQUAL: PARSER_HANDLE(Equal);
} }
} }
if (parser->errors.count > 0) { if (parser->errors.count > 0) {

View File

@@ -14,10 +14,11 @@
typedef enum SolsTokenPrecedence { typedef enum SolsTokenPrecedence {
STP_NEWLINE = 0, STP_NEWLINE = 0,
STP_PUTS = 1, STP_PUTS = 1,
STP_SET = 2, STP_COMPARE = 2,
STP_FUNCTION = 3, STP_SET = 3,
STP_ADD = 4, STP_FUNCTION = 4,
STP_MUL = 5, STP_ADD = 5,
STP_MUL = 6,
STP_OTHER = 7, STP_OTHER = 7,
} SolsTokenPrecedence; } SolsTokenPrecedence;

View File

@@ -5,8 +5,15 @@ puts x + 3
puts 5 * 7 puts 5 * 7
puts 3.0 / 2 puts 3.0 / 2
puts 10 - 3 puts 10 - 3
puts "dingle" + "dongle"
// Uh oh it's the order of operations // Uh oh it's the order of operations
puts 5 + 3 * 7 puts 5 + 3 * 7
puts 5 * 3 + 7 puts 5 * 3 + 7
// Let's do some equalities
puts 5 == 5
puts 3 == 2
puts "dingus" == "dongus"
puts 3.14 == 3.14