From 7bb67d7bd5e8c600940ce8aafccdec4eb5fef89d Mon Sep 17 00:00:00 2001 From: SpookyDervish Date: Sun, 21 Jun 2026 16:15:40 +1000 Subject: [PATCH] custom exceptions!!! --- include/struct.h | 1 + src/ast.h | 1 + src/compiler.c | 59 ++++++++++++++++++++++++++++++++++++++++++++---- src/inst.c | 9 ++++++++ src/parser.c | 18 +++++++++++---- test.comet | 12 +++++++--- 6 files changed, 89 insertions(+), 11 deletions(-) diff --git a/include/struct.h b/include/struct.h index 68824c7..74b4583 100644 --- a/include/struct.h +++ b/include/struct.h @@ -20,6 +20,7 @@ struct CometStruct { char** fieldNames; CometType* fieldTypes; char* name; + CometStruct* parent; }; // an instance of a struct diff --git a/src/ast.h b/src/ast.h index 49dc0c1..5813b5f 100644 --- a/src/ast.h +++ b/src/ast.h @@ -147,6 +147,7 @@ struct CometASTNode { CometASTNode* tryBlock; CometASTNode* exceptBlock; CometASTNode* exceptionType; + CometASTNode* exceptionVarName; } AST_TRY_STATEMENT; struct AST_THROW_STATEMENT { CometASTNode* newStmt; diff --git a/src/compiler.c b/src/compiler.c index 09a04dd..d847c1d 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -111,6 +111,31 @@ char* typeToString(CometType type) { return buffer; } + case COMET_STRUCT: { + /*size_t buffSize = 256; + char* buffer = malloc(buffSize); + if (!buffer) + return NULL; + + CometType* fieldTypes = type.structType->fieldTypes; + uint32_t fieldCount = type.structType->fieldCount; + + int written = 0; + int remaining = buffSize - written; + + written += snprintf(buffer + written, remaining, "%s - { ", type.structType->name); + + for (uint32_t i = 0; i < fieldCount; i++) { + if (i < fieldCount - 1) { + written += snprintf(buffer + written, remaining, "%s, ", typeToString(fieldTypes[i])); + } else { + written += snprintf(buffer + written, remaining, "%s }", typeToString(fieldTypes[i])); + } + }*/ + + return type.structType->name; + } + default: return "unkown"; } } @@ -637,7 +662,7 @@ ResultType(CometType, ErrorMessage) getType(CometCompiler* c, CometASTNode* type // get base type CometType* baseType = malloc(sizeof(CometType)); - + List(CometTypeMapEntry) typeMap = c->typeMap; char* baseTypeName = type.baseType->data.AST_IDENTIFIER.ident; @@ -1243,7 +1268,7 @@ ResultType(CometType, ErrorMessage) resolveType(CometCompiler* c, CometASTNode* ResultType(CometType, ErrorMessage) siblingResolved = resolveType(c, siblingElem); if (siblingResolved.error) return siblingResolved; - if (!typesAreEqual(firstType, siblingResolved.as.success)) { + if (!typesAreEqual(siblingResolved.as.success, firstType)) { Estr helpMsg = CREATE_ESTR("You're trying to mix the types "); APPEND_ESTR(helpMsg, typeToString(firstType)) APPEND_ESTR(helpMsg, " and ") @@ -1571,7 +1596,7 @@ ResultType(CometOperand, ErrorMessage) visitAssignStatement(CometCompiler* c, Co if (exprResult.error) return exprResult; - if (!typesAreEqual(varType.as.success, exprType.as.success) && !canImplicitCastType(varType.as.success, exprType.as.success)) { + if (!typesAreEqual(exprType.as.success, varType.as.success) && !canImplicitCastType(varType.as.success, exprType.as.success)) { CometType castOut = buildCast(c, exprType.as.success, varType.as.success); @@ -2536,6 +2561,7 @@ ResultType(CometOperand, ErrorMessage) visitConstructorDefStatement(CometCompile argTypes[argTypeIdx+1] = argType.as.success; } + argTypes[0] = structType; buildFunction(c, constructorName, constDef.args.count + 1, structType, argTypes, false, true, false, -1); // add 1 arg for self @@ -2708,6 +2734,7 @@ ResultType(CometOperand, ErrorMessage) visitStructDefStatement(CometCompiler* c, char* structName = structDef.ident->data.AST_IDENTIFIER.ident; structType->name = structName; + structType->parent = NULL; @@ -2750,6 +2777,8 @@ ResultType(CometOperand, ErrorMessage) visitStructDefStatement(CometCompiler* c, // add parent field count parentFieldCount = parentStruct->fieldCount; parentMethodCount = parentStruct->numMethods; + + structType->parent = parentStruct; } // fill in fieldDefs @@ -3157,7 +3186,29 @@ ResultType(CometOperand, ErrorMessage) visitTryStatement(CometCompiler* c, Comet if (exceptionType.error) return Error(CometOperand, ErrorMessage, exceptionType.as.error); - uint32_t idx = defineVar(c->env, "e", RECORD_LOCAL, NO_OPERAND, exceptionType.as.success, false); + CometASTNode* exceptionVarNameNode = node->data.AST_TRY_STATEMENT.exceptionVarName; + char* exceptionVarName = exceptionVarNameNode->data.AST_IDENTIFIER.ident; + Record* existingVar = lookup(c->env, exceptionVarName); + if (existingVar) { + Estr buffer = CREATE_ESTR("Redefinition of \""); + APPEND_ESTR(buffer, exceptionVarName); + APPEND_ESTR(buffer, "\"") + + ErrorMessage errMsg = createError( + c->inputFilePath, + c->sourceCode, + "VariableRedefinition", + buffer.str, + NULL, + exceptionVarNameNode->lineNum, + exceptionVarNameNode->startCol, + exceptionVarNameNode->endCol + ); + + return Error(CometOperand, ErrorMessage, errMsg); + } + + uint32_t idx = defineVar(c->env, exceptionVarName, RECORD_LOCAL, NO_OPERAND, exceptionType.as.success, false); buildStore(c, idx); ResultType(CometOperand, ErrorMessage) exceptBody = compile(c, node->data.AST_TRY_STATEMENT.exceptBlock); diff --git a/src/inst.c b/src/inst.c index f07ad0e..ba4ed20 100644 --- a/src/inst.c +++ b/src/inst.c @@ -12,6 +12,15 @@ bool typesAreEqual(CometType a, CometType b) { } if (a.typeKind == COMET_STRUCT) { + if (a.structType->parent != NULL) { + CometType parentType = { + .typeKind = COMET_STRUCT, + .structType = a.structType->parent + }; + + return typesAreEqual(parentType, b); + } + return a.structType == b.structType; } diff --git a/src/parser.c b/src/parser.c index ad74c59..98e0992 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1630,9 +1630,11 @@ ResultType(astNodePtr, ErrorMessage) parseStructDefStatement(CometParser* parser if (expectParentName.error) return Error(astNodePtr, ErrorMessage, expectParentName.as.error); - parentName = AST_NODE(AST_IDENTIFIER, parser->currentToken->lineNum, parser->currentToken->value.literal); - parentName->startCol = parser->currentToken->startCol; - parentName->endCol = parser->currentToken->endCol; + ResultType(astNodePtr, ErrorMessage) parentNameResult = parseType(parser); + if (parentNameResult.error) + return parentNameResult; + + parentName = parentNameResult.as.success; } List(astNodePtr) fieldDefs = newList(astNodePtr); @@ -1801,11 +1803,19 @@ ResultType(astNodePtr, ErrorMessage) parseTryStatement(CometParser* parser) { if (exceptionType.error) return exceptionType; + ResultType(int, ErrorMessage) expectVarName = expectPeek(parser, CT_IDENT); + if (expectVarName.error) + return Error(astNodePtr, ErrorMessage, expectVarName.as.error); + + ResultType(astNodePtr, ErrorMessage) exceptionVarName = parseIdentifier(parser); + if (exceptionVarName.error) + return exceptionVarName; + ResultType(astNodePtr, ErrorMessage) exceptBlock = parseOptionalBlockStatement(parser); if (tryBlock.error) return tryBlock; - CometASTNode* stmt = AST_NODE(AST_TRY_STATEMENT, lineNumber, tryBlock.as.success, exceptBlock.as.success, exceptionType.as.success); + CometASTNode* stmt = AST_NODE(AST_TRY_STATEMENT, lineNumber, tryBlock.as.success, exceptBlock.as.success, exceptionType.as.success, exceptionVarName.as.success); stmt->startCol = startCol; stmt->endCol = parser->currentToken->endCol; diff --git a/test.comet b/test.comet index 70a0ed6..0262d00 100644 --- a/test.comet +++ b/test.comet @@ -10,11 +10,17 @@ struct Exception { } } +struct EpicFail : Exception { + init() { + super(self, "EpicFail", "you did an epic fail") + } +} + func main() -> int { try { - throw new Exception("Exception", "If you see this, we threw an exception!!") - } except Exception { - io.println("error: %s", e.message) + throw new EpicFail() + } except Exception e { + io.println("%s: %s", e.type, e.message) } return 0