parsing and type checking types inside modules is working i thinks

This commit is contained in:
2026-06-22 18:57:18 +10:00
parent 6130904668
commit de8b1770a4
12 changed files with 406 additions and 100 deletions

View File

@@ -26,25 +26,34 @@
#define on_import void onImport(CometEnvironment* env)
typedef CometFunction* cometFuncPtr;
typedef struct {
char* name;
CometType type;
} StructField;
UseList(CometSerializedFunc);
UseList(cometFuncPtr);
UseList(charptr);
UseList(StructField);
CometType createArrayType(CometType elem, uint8_t dimensions, bool isFixedSize[], uint64_t fixedSize[]);
API_EXPORT void cometDefineFunc(
API_EXPORT CometFunction* cometDefineFunc(
CometEnvironment* env,
char* name,
CometType returnType,
uint32_t numArgs,
bool isVarArgs,
bool isMethod,
...
);
API_EXPORT CometSerializedFunc* cometDefineMethod(
CometEnvironment* env,
char* name,
CometType returnType,
uint32_t numArgs,
bool isVarArgs,
...
API_EXPORT CometSerializedFunc cometSerializeFunction(
CometVM* vm,
CometFunction* func,
externalLibFunc funcPtr
);
API_EXPORT CometSerializedStruct* cometCreateStruct(List(CometSerializedFunc) methods, uint32_t numFields);
@@ -56,5 +65,6 @@ API_EXPORT int64_t serializeValue(CometOperand value);
API_EXPORT CometOperand deserializeValue(int64_t value, CometType type);
API_EXPORT void* cometArrayToCArray(CometOperand arrayValue, CometType elemType);
API_EXPORT CometOperand CArrayToCometArray(void* arrayValue, size_t length, CometType elemType);
API_EXPORT CometType cometDefineStruct(CometEnvironment* env, char* name, List(StructField) fields, List(cometFuncPtr) methods);
#endif

View File

@@ -41,6 +41,7 @@ struct CometVM {
void** loadedLibs;
externalLibFunc* externalFuncs;
size_t numExternalFuncs;
uint32_t numFunctions;

View File

@@ -8,18 +8,19 @@
#include <string.h>
#include <sys/types.h>
void cometDefineFunc(
CometFunction* cometDefineFunc(
CometEnvironment* env,
char* name,
CometType returnType,
uint32_t numArgs,
bool isVarArgs,
bool isMethod,
...
) {
CometFunction* func = malloc(sizeof(CometFunction));
memcpy(func->name, name, 32);
func->argCount = numArgs;
func->isMethod = false;
func->isMethod = isMethod;
func->returnType = returnType;
func->startIdx = 0;
func->isExternal = true;
@@ -39,7 +40,7 @@ void cometDefineFunc(
};
va_list args;
va_start(args, isVarArgs);
va_start(args, isMethod);
CometType* argTypes = numArgs > 0 ? calloc(numArgs, sizeof(CometType)) : NULL;
for (size_t i = 0; i < numArgs; i++) {
@@ -50,7 +51,34 @@ void cometDefineFunc(
va_end(args);
if (env) {
defineVar(env, name, RECORD_LOCAL, funcVal, type, false);
}
return func;
}
CometSerializedFunc cometSerializeFunction(
CometVM* vm,
CometFunction* func,
externalLibFunc funcPtr
) {
CometSerializedFunc serializedFunc = {
.isExternal = func->isExternal,
.isVarArgs = func->isVarArgs,
.startIdx = func->startIdx,
.libIdx = 0,
.externFuncIndex = vm->numExternalFuncs
};
memcpy(serializedFunc.name, func->name, 32);
vm->externalFuncs[vm->numExternalFuncs] = funcPtr;
vm->numExternalFuncs++;
vm->functions[vm->numFunctions] = serializedFunc;
vm->numFunctions++;
return serializedFunc;
}
int64_t serializeValue(CometOperand value) {
@@ -209,6 +237,50 @@ API_EXPORT void* cometArrayToCArray(CometOperand arrayValue, CometType elemType)
return cArray;
}
CometType cometDefineStruct(CometEnvironment* env, char* name, List(StructField) fields, List(cometFuncPtr) methods) {
CometStruct* newStruct = malloc(sizeof(CometStruct));
char** fieldNames = calloc(fields.count, sizeof(char*));
CometType* fieldTypes = calloc(fields.count, sizeof(CometType));
for (size_t i = 0; i < fields.count; i++) {
StructField field = *get(fields, i);
fieldNames[i] = field.name;
fieldTypes[i] = field.type;
}
name = strdup(name);
*newStruct = (CometStruct){
.name = name,
.fieldNames = fieldNames,
.fieldTypes = fieldTypes,
.fieldCount = fields.count,
.numMethods = methods.count,
.vtable = (CometMethod**)methods.pointer,
.parent = NULL
};
CometType structType = {
.typeKind = COMET_STRUCT,
.structType = newStruct
};
CometOperand a = {
.type = CO_IMMEDIATE,
.imm.typeKind = COMET_TYPE,
.imm.typeVal = structType
};
CometType typeVal = {
.typeKind = COMET_TYPE,
};
defineVar(env, name, RECORD_LOCAL, a, typeVal, false);
return structType;
}
CometSerializedStruct* cometCreateStruct(List(CometSerializedFunc) methods, uint32_t numFields) {
CometSerializedStruct* newStruct = malloc(sizeof(CometSerializedStruct));
newStruct->numFields = numFields;

View File

@@ -138,7 +138,10 @@ void freeNode(CometASTNode* node) {
}
case AST_TYPE: {
freeNode(node->data.AST_TYPE.baseType);
for (size_t i = 0; i < node->data.AST_TYPE.baseType.count; i++) {
freeNode(*get(node->data.AST_TYPE.baseType, i));
}
destroy(node->data.AST_TYPE.baseType);
for (size_t i = 0; i < node->data.AST_TYPE.shape.count; i++) {
freeNode(*get(node->data.AST_TYPE.shape, i));
}

View File

@@ -78,7 +78,7 @@ struct CometASTNode {
struct AST_ARG_DEF { CometASTNode* type; CometASTNode* ident; } AST_ARG_DEF;
struct AST_TYPE {
CometASTNode* baseType;
List(astNodePtr) baseType;
List(astNodePtr) shape;
int dimensions;
} AST_TYPE;

View File

@@ -241,7 +241,11 @@ ResultType(CometOperand, ErrorMessage) loadExternalLib(CometCompiler* c, const c
HASH_ITER(hh, libEnv->records, current, tmp) {
if (current->type.typeKind != COMET_FUNCTION) continue;
switch (current->type.typeKind) {
case COMET_FUNCTION: {
CometFunction* funcVal = (CometFunction*)current->value.imm.bigVal; // i sure do love casting pointers to ints lmao
if (funcVal->isMethod)
continue;
CometOperand funcOperand = buildFunction(
c,
@@ -258,6 +262,13 @@ ResultType(CometOperand, ErrorMessage) loadExternalLib(CometCompiler* c, const c
current->value = funcOperand;
}
default:
continue;
}
}
CometOperand libValue = createOperand(CO_IMMEDIATE);
libValue.imm.typeKind = COMET_MODULE;
libValue.imm.moduleVal = libEnv;
@@ -657,26 +668,20 @@ CometType flattenArrayType(CometType type) {
return out;
}
ResultType(CometType, ErrorMessage) getType(CometCompiler* c, CometASTNode* typeNode) {
struct AST_TYPE type = typeNode->data.AST_TYPE;
// get base type
CometType* baseType = malloc(sizeof(CometType));
ResultType(cometTypePtr, ErrorMessage) findBuiltinType(CometCompiler* c, CometASTNode* node) {
List(CometTypeMapEntry) typeMap = c->typeMap;
char* baseTypeName = type.baseType->data.AST_IDENTIFIER.ident;
char* baseTypeName = node->data.AST_IDENTIFIER.ident;
bool found = false;
for (size_t i = 0; i < typeMap.count; i++) {
CometTypeMapEntry type = *get(typeMap, i);
CometTypeMapEntry* type = get(typeMap, i);
if (strcmp(type.name, baseTypeName) == 0) {
found = true;
*baseType = type.type;
if (strcmp(type->name, baseTypeName) == 0) {
return Success(cometTypePtr, ErrorMessage, &type->type);
}
}
if (!found) {
Estr buffer = CREATE_ESTR("Unkown type \"");
APPEND_ESTR(buffer, baseTypeName);
APPEND_ESTR(buffer, "\"");
@@ -687,20 +692,191 @@ ResultType(CometType, ErrorMessage) getType(CometCompiler* c, CometASTNode* type
"UnkownType",
buffer.str,
NULL,
typeNode->lineNum,
typeNode->data.AST_TYPE.baseType->startCol,
typeNode->data.AST_TYPE.baseType->endCol
node->lineNum,
node->startCol,
node->endCol
);
return Error(CometType, ErrorMessage, errMsg);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
ResultType(cometTypePtr, ErrorMessage) getBaseType(CometCompiler* c, nodeList chain) {
ResultType(cometTypePtr, ErrorMessage) builtinType = findBuiltinType(c, *get(chain, 0));
if (!builtinType.error)
return builtinType;
for (size_t i = 0; i < chain.count; i++) {
CometASTNode* currentNode = *get(chain, 0);
ResultType(CometType, ErrorMessage) currentType = resolveType(c, currentNode);
if (currentType.error)
return Error(cometTypePtr, ErrorMessage, currentType.as.error);
CometType current = currentType.as.success;
char* currentName = currentNode->data.AST_IDENTIFIER.ident;
switch (current.typeKind) {
case COMET_MODULE: {
Record* moduleRecord = lookup(c->env, currentName);
if (!moduleRecord) {
Estr buffer = CREATE_ESTR("Undefined module \"");
APPEND_ESTR(buffer, currentName);
APPEND_ESTR(buffer, "\"");
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"UndefinedModule",
buffer.str,
NULL,
currentNode->lineNum,
currentNode->startCol,
currentNode->endCol
);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
CometOperand module = moduleRecord->value;
if (module.imm.typeKind != COMET_MODULE) {
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"TypeError",
"Attempted to get an attribute from something that isn't a module!",
NULL,
currentNode->lineNum,
currentNode->startCol,
currentNode->endCol
);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
if (i == chain.count - 1) {
Estr buffer = CREATE_ESTR("Module \"");
APPEND_ESTR(buffer, currentName);
APPEND_ESTR(buffer, "\" is not a type.");
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"NotAType",
buffer.str,
NULL,
currentNode->lineNum,
currentNode->startCol,
currentNode->endCol
);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
CometASTNode* next = *get(chain, i+1);
char* attribName = next->data.AST_IDENTIFIER.ident;
Record* attribRecord = lookup(module.imm.moduleVal, attribName);
if (!attribRecord) {
Estr buffer = CREATE_ESTR("Can't find attribute \"");
APPEND_ESTR(buffer, attribName);
APPEND_ESTR(buffer, "\" in module \"");
APPEND_ESTR(buffer, currentName);
APPEND_ESTR(buffer, "\"");
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"UnkownAttribute",
buffer.str,
NULL,
next->lineNum,
next->startCol,
next->endCol
);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
if (attribRecord->type.typeKind != COMET_TYPE) {
Estr buffer = CREATE_ESTR("Attribute \"");
APPEND_ESTR(buffer, attribName);
APPEND_ESTR(buffer, "\" in module \"");
APPEND_ESTR(buffer, currentName);
APPEND_ESTR(buffer, "\" is not a type");
char* typeStr = typeToString(attribRecord->type);
printf("%d\n", attribRecord->type.typeKind);
Estr help = CREATE_ESTR("It is of type ");
APPEND_ESTR(help, typeStr);
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"NotAType",
buffer.str,
help.str,
next->lineNum,
next->startCol,
next->endCol
);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
return Success(cometTypePtr, ErrorMessage, &attribRecord->value.imm.typeVal);
}
default: {
Estr buffer = CREATE_ESTR("Cannot get type from \"");
APPEND_ESTR(buffer, currentName);
APPEND_ESTR(buffer, "\" because it's not a module.");
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"TypeMismatch",
buffer.str,
NULL,
currentNode->lineNum,
currentNode->startCol,
currentNode->endCol
);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
}
}
ErrorMessage errMsg = createError(
c->inputFilePath,
c->sourceCode,
"CompilerIssue",
"This error should never happen, please report this as a bug! (getBaseType)",
NULL,
chain.pointer[0]->lineNum,
chain.pointer[0]->startCol,
chain.pointer[chain.count]->endCol
);
return Error(cometTypePtr, ErrorMessage, errMsg);
}
ResultType(CometType, ErrorMessage) getType(CometCompiler* c, CometASTNode* typeNode) {
struct AST_TYPE type = typeNode->data.AST_TYPE;
// get base type
ResultType(cometTypePtr, ErrorMessage) baseType = getBaseType(c, type.baseType);
if (baseType.error)
return Error(CometType, ErrorMessage, baseType.as.error);
CometType finalType;
if (type.dimensions > 0) {
finalType.typeKind = COMET_ARRAY;
CometArrayType* arrayType = malloc(sizeof(CometArrayType));
arrayType->elem = baseType;
arrayType->elem = baseType.as.success;
if (type.shape.count > MAX_ARRAY_DEPTH) {
ErrorMessage errMsg = createError(
@@ -737,8 +913,7 @@ ResultType(CometType, ErrorMessage) getType(CometCompiler* c, CometASTNode* type
finalType.arrayType = arrayType;
} else {
finalType = *baseType;
free(baseType);
finalType = *baseType.as.success;
}
if (finalType.typeKind == COMET_ARRAY && finalType.arrayType->elem->typeKind == COMET_ARRAY) {
@@ -2997,7 +3172,7 @@ ResultType(CometOperand, ErrorMessage) visitNewStatement(CometCompiler* c, Comet
struct AST_NEW_STATEMENT newStmt = node->data.AST_NEW_STATEMENT;
// get struct type
char* structName = newStmt.structName->data.AST_TYPE.baseType->data.AST_IDENTIFIER.ident;
char* structName = newStmt.structName->data.AST_TYPE.baseType.pointer[0]->data.AST_IDENTIFIER.ident;
int32_t idx = getStructIndex(c, structName);
if (idx == -1) {

View File

@@ -19,12 +19,14 @@ typedef void* voidPtr;
typedef List(astNodePtr) astNodeList;
typedef CometType* cometTypePtr;
Result(voidPtr, ErrorMessage);
Result(CometType, ErrorMessage);
Result(astNodeList, ErrorMessage);
Result(CometFunctionTypeInfo, ErrorMessage);
Result(cometCompilerPtr, ErrorMessage);
Result(cometTypePtr, ErrorMessage);
ResultType(CometOperand, ErrorMessage) compile(CometCompiler* c, CometASTNode* node);

View File

@@ -407,7 +407,11 @@ void printNode(CometASTNode* node) {
break;
case AST_TYPE: {
printNode(node->data.AST_TYPE.baseType);
for (size_t i = 0; i < node->data.AST_TYPE.baseType.count; i++) {
printNode(*get(node->data.AST_TYPE.baseType, i));
if (i < node->data.AST_TYPE.baseType.count - 1)
putchar(',');
}
if (node->data.AST_TYPE.dimensions > 0) {
printf("[");
@@ -929,15 +933,37 @@ ResultType(astNodePtr, ErrorMessage) parsePrefixExpression(CometParser* parser)
}
// -- TYPE PARSING -- //
ResultType(nodeList, ErrorMessage) parseBaseType(CometParser* parser) {
List(astNodePtr) typeChain = newList(astNodePtr);
while (true) {
CometASTNode* current = AST_NODE(AST_IDENTIFIER, parser->currentToken->lineNum, parser->currentToken->value.literal);
current->startCol = parser->currentToken->startCol;
current->endCol = parser->currentToken->endCol;
append(typeChain, current);
if (!peekTokenIs(parser, CT_DOT))
break;
parserNextToken(parser); // consume type name
parserNextToken(parser); // consume dot
}
return Success(nodeList, ErrorMessage, typeChain);
}
ResultType(astNodePtr, ErrorMessage) parseArrayType(CometParser* parser) {
CometASTNode* baseType = AST_NODE(AST_IDENTIFIER, parser->currentToken->lineNum, parser->currentToken->value.literal);
baseType->startCol = parser->currentToken->startCol;
baseType->endCol = parser->currentToken->endCol;
parserNextToken(parser); // consume base type
uint32_t lineNum = parser->currentToken->lineNum;
uint32_t startCol = parser->currentToken->startCol;
CometASTNode* typeNode = AST_NODE(AST_TYPE, baseType->lineNum, baseType, newList(astNodePtr), 0);
typeNode->startCol = baseType->startCol;
ResultType(nodeList, ErrorMessage) baseType = parseBaseType(parser);
if (baseType.error)
return Error(astNodePtr, ErrorMessage, baseType.as.error);
CometASTNode* typeNode = AST_NODE(AST_TYPE, lineNum, baseType.as.success, newList(astNodePtr), 0);
typeNode->startCol = startCol;
parserNextToken(parser); // consume '['
@@ -1003,6 +1029,9 @@ ResultType(astNodePtr, ErrorMessage) parseArrayType(CometParser* parser) {
}
ResultType(astNodePtr, ErrorMessage) parseScalarType(CometParser* parser) {
uint32_t lineNum = parser->currentToken->lineNum;
uint32_t startCol = parser->currentToken->startCol;
if (!currentTokenIs(parser, CT_IDENT)) {
Estr buffer = CREATE_ESTR("Expected type name, got ");
APPEND_ESTR(buffer, tokenTypeToCStr(parser->currentToken->type));
@@ -1022,13 +1051,13 @@ ResultType(astNodePtr, ErrorMessage) parseScalarType(CometParser* parser) {
return Error(astNodePtr, ErrorMessage, errMsg);
}
CometASTNode* baseType = AST_NODE(AST_IDENTIFIER, parser->currentToken->lineNum, parser->currentToken->value.literal);
baseType->startCol = parser->currentToken->startCol;
baseType->endCol = parser->currentToken->endCol;
ResultType(nodeList, ErrorMessage) baseType = parseBaseType(parser);
if (baseType.error)
return Error(astNodePtr, ErrorMessage, baseType.as.error);
CometASTNode* typeNode = AST_NODE(AST_TYPE, baseType->lineNum, baseType, NULL, 0);
typeNode->startCol = baseType->startCol;
typeNode->endCol = baseType->endCol;
CometASTNode* typeNode = AST_NODE(AST_TYPE, lineNum, baseType.as.success, NULL, 0);
typeNode->startCol = startCol;
typeNode->endCol = parser->currentToken->endCol;
return Success(astNodePtr, ErrorMessage, typeNode);
}
@@ -1712,7 +1741,11 @@ ResultType(astNodePtr, ErrorMessage) parseStructCreateStatement(CometParser* par
structName->startCol = parser->currentToken->startCol;
structName->endCol = parser->currentToken->endCol;
CometASTNode* structType = AST_NODE(AST_TYPE, structName->lineNum, structName, NULL, 0);
nodeList baseType = newList(astNodePtr);
append(baseType, structName);
CometASTNode* structType = AST_NODE(AST_TYPE, structName->lineNum, baseType, NULL, 0);
structType->startCol = structName->startCol;
structType->endCol = structName->endCol;

View File

@@ -23,8 +23,10 @@ typedef struct {
typedef CometParser* parserPtr;
typedef List(astNodePtr) argList;
typedef List(astNodePtr) nodeList;
Result(astNodePtr, ErrorMessage);
Result(nodeList, ErrorMessage);
typedef ResultType(astNodePtr, ErrorMessage) (*prefixFuncType)(CometParser*);
typedef ResultType(astNodePtr, ErrorMessage) (*infixFuncType)(CometParser*, CometASTNode* left);

22
test.c Normal file
View File

@@ -0,0 +1,22 @@
#include "include/cometlib.h"
int64_t impl_Foo_add(int64_t* args, CometVM* vm) {
CometOperand a = deserializeValue(args[0], cometTypeInt);
CometOperand b = deserializeValue(args[1], cometTypeInt);
int result = a.imm.intVal + b.imm.intVal;
return result;
}
on_import {
List(StructField) fields = newList(StructField);
StructField field = (StructField){"test", cometTypeInt};
append(fields, field);
List(cometFuncPtr) methods = newList(cometFuncPtr);
CometFunction* firstFunc = cometDefineFunc(env, "add", cometTypeInt, 2, false, true, cometTypeInt, cometTypeInt);
append(methods, firstFunc);
cometDefineStruct(env, "Foo", fields, methods);
}

View File

@@ -1,21 +1,7 @@
import io
struct Exception {
string type
string msg
init(string type, string msg) {
self.type = type
self.msg = msg
}
}
import testlib
func main() -> int {
try {
throw new Exception("hi", "hi2")
} except Exception e {
io.println("%s: %s", e.type, e.msg)
}
testlib.Foo hi = 123
return 0
}

View File

@@ -790,7 +790,7 @@ ResultType(vmPtr, charptr) newCometVM(char* filePath) {
newVM->loadedLibs = calloc(loadedFile->numLibs, sizeof(void*));
newVM->externalFuncs = calloc(loadedFile->numFunctions, sizeof(void*));
size_t externalFuncIndex = 0;
newVM->numExternalFuncs = 0;
for (size_t i = 0; i < loadedFile->numLibs; i++) {
char libName[128];
snprintf(libName, 128, "%s.cometlib", cursor);
@@ -850,9 +850,9 @@ ResultType(vmPtr, charptr) newCometVM(char* filePath) {
DESTROY_ESTR(funcSymbolName);
externalFunc->externFuncIndex = externalFuncIndex;
newVM->externalFuncs[externalFuncIndex] = loadedFunc;
externalFuncIndex++;
externalFunc->externFuncIndex = newVM->numExternalFuncs;
newVM->externalFuncs[newVM->numExternalFuncs] = loadedFunc;
newVM->numExternalFuncs++;