"as" in struct
This commit is contained in:
@@ -1233,6 +1233,7 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
|
||||
_result.as.success;
|
||||
});
|
||||
selfType.type = STT_OBJECT;
|
||||
selfType.metadata.isProtected = true;
|
||||
|
||||
addVariableToScope(&childScope, "self", selfType);
|
||||
|
||||
@@ -1294,11 +1295,12 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
|
||||
_result.as.success;
|
||||
});
|
||||
selfType.type = STT_OBJECT;
|
||||
selfType.metadata.isProtected = true;
|
||||
|
||||
addVariableToScope(&childScope, "self", selfType);
|
||||
|
||||
// Also add one as the old type
|
||||
addVariableToScope(&childScope, "old", type);
|
||||
addVariableToScope(&childScope, "old", selfType);
|
||||
|
||||
ResultType(GroundProgram, charptr) bodyCode = generateCode(child, &childScope);
|
||||
if (bodyCode.error) return bodyCode;
|
||||
@@ -1310,6 +1312,78 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
|
||||
groundAddInstructionToProgram(&structDef, returnInst);
|
||||
groundAddInstructionToProgram(&structDef, groundCreateInstruction(ENDFUN));
|
||||
continue;
|
||||
} else if (child->type == SNT_STRUCT_AS) {
|
||||
Estr methodName = CREATE_ESTR("");
|
||||
SolsType* asType = &child->children.at[0].as.type;
|
||||
if (asType->identifierType != NULL) {
|
||||
methodName = CREATE_ESTR(asType->identifierType);
|
||||
} else {
|
||||
switch (asType->type) {
|
||||
case STT_INT:
|
||||
methodName = CREATE_ESTR("int");
|
||||
break;
|
||||
case STT_STRING:
|
||||
methodName = CREATE_ESTR("string");
|
||||
break;
|
||||
case STT_DOUBLE:
|
||||
methodName = CREATE_ESTR("double");
|
||||
break;
|
||||
case STT_BOOL:
|
||||
methodName = CREATE_ESTR("bool");
|
||||
break;
|
||||
case STT_CHAR:
|
||||
methodName = CREATE_ESTR("char");
|
||||
break;
|
||||
case STT_FUN:
|
||||
case STT_TEMPLATE:
|
||||
case STT_OBJECT:
|
||||
case STT_UNKNOWN:
|
||||
case STT_NONE:
|
||||
// FIXME handle anonymous stuff later
|
||||
return Error(GroundProgram, charptr, "FIXME anonymous types are not yet implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
APPEND_ESTR(methodName, "_SOLS_AS");
|
||||
|
||||
GroundInstruction asInst = groundCreateInstruction(FUN);
|
||||
groundAddReferenceToInstruction(&asInst, groundCreateReference(FNREF, methodName.str));
|
||||
groundAddReferenceToInstruction(&asInst, ({
|
||||
ResultType(GroundArg, charptr) _result = createGroundArgFromSolsType(asType, scope);
|
||||
if (_result.error) {
|
||||
return Error(GroundProgram, charptr, _result.as.error);
|
||||
}
|
||||
_result.as.success;
|
||||
}));
|
||||
groundAddInstructionToProgram(&structDef, asInst);
|
||||
|
||||
SolsScope childScope = copySolsScope(scope);
|
||||
SolsType selfType = ({
|
||||
ResultType(SolsType, charptr) _result = copySolsType(&type);
|
||||
if (_result.error) {
|
||||
return Error(GroundProgram, charptr, _result.as.error);
|
||||
}
|
||||
_result.as.success;
|
||||
});
|
||||
selfType.type = STT_OBJECT;
|
||||
selfType.metadata.isProtected = true;
|
||||
|
||||
addVariableToScope(&childScope, "self", selfType);
|
||||
|
||||
childScope.returnType = *asType;
|
||||
ResultType(GroundProgram, charptr) bodyCode = generateCode(child, &childScope);
|
||||
if (bodyCode.error) return bodyCode;
|
||||
for (size_t j = 0; j < bodyCode.as.success.size; j++) {
|
||||
groundAddInstructionToProgram(&structDef, bodyCode.as.success.instructions[j]);
|
||||
}
|
||||
|
||||
groundAddInstructionToProgram(&structDef, groundCreateInstruction(ENDFUN));
|
||||
|
||||
child->as.type.metadata.isProtected = true;
|
||||
|
||||
addChildToSolsType(&type, child->as.type, methodName.str);
|
||||
continue;
|
||||
}
|
||||
ResultType(SolsType, charptr) childType = getNodeType(&child->children.at[1], scope);
|
||||
if (childType.error) {
|
||||
|
||||
@@ -18,6 +18,7 @@ typedef enum SolsTokenType {
|
||||
STT_OP_GREATER, STT_OP_LESSER, STT_OP_EQUAL, STT_OP_INEQUAL, STT_OP_EQGREATER, STT_OP_EQLESSER,
|
||||
STT_KW_DEF, STT_KW_LAMBDA, STT_KW_RETURN,
|
||||
STT_KW_USE, STT_KW_STRUCT, STT_KW_ENUM, STT_KW_CONSTRUCTOR, STT_KW_DESTRUCTOR, STT_KW_DUPLICATOR,
|
||||
STT_KW_AS,
|
||||
STT_KW_PRIVATE, STT_KW_PROTECTED,
|
||||
STT_KW_PUTS, STT_KW_IF, STT_KW_WHILE,
|
||||
STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA
|
||||
|
||||
@@ -23,6 +23,7 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
|
||||
{"protected", STT_KW_PROTECTED},
|
||||
{"ground", STT_KW_GROUND},
|
||||
{"new", STT_KW_NEW},
|
||||
{"as", STT_KW_AS},
|
||||
{"{", STT_OPEN_CURLY},
|
||||
{"}", STT_CLOSE_CURLY},
|
||||
{"(", STT_OPEN_PAREN},
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef enum SolsNodeType {
|
||||
SNT_DEF, SNT_LAMBDA, SNT_FUNCTION_CALL, SNT_RETURN,
|
||||
SNT_SET_PRIVATE, SNT_SET_PROTECTED, SNT_DEF_PRIVATE, SNT_DEF_PROTECTED,
|
||||
SNT_USE, SNT_STRUCT, SNT_ENUM, SNT_CONSTRUCTOR, SNT_DESTRUCTOR, SNT_DUPLICATOR,
|
||||
SNT_STRUCT_AS, SNT_AS,
|
||||
SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW,
|
||||
SNT_GROUND, SNT_ROOT, SNT_EXPR_IN_PAREN, SNT_DOT,
|
||||
} SolsNodeType;
|
||||
|
||||
@@ -1855,6 +1855,90 @@ static inline ResultType(Nothing, charptr) parseDuplicator(SolsParser* parser) {
|
||||
|
||||
}
|
||||
|
||||
static inline ResultType(Nothing, charptr) parseStructAs(SolsParser* parser) {
|
||||
ResultType(SolsNode, charptr) node = createSolsNode(SNT_STRUCT_AS);
|
||||
ResultType(SolsType, charptr) type = createSolsType(STT_FUN);
|
||||
if (type.error) {
|
||||
return Error(Nothing, charptr, type.as.error);
|
||||
}
|
||||
type.as.success.returnType = malloc(sizeof(SolsType));
|
||||
if (type.as.success.returnType == NULL) {
|
||||
return Error(Nothing, charptr, "Failed to allocate memory for return type");
|
||||
}
|
||||
|
||||
ResultType(SolsToken, Nothing) typeName = parserConsume(parser);
|
||||
if (typeName.error) {
|
||||
return Error(Nothing, charptr, "Expecting type name after 'as'");
|
||||
}
|
||||
if (typeName.as.success.type != STT_IDENTIFIER && typeName.as.success.type != STT_TYPE) {
|
||||
return Error(Nothing, charptr, "Expecting type name after 'as'");
|
||||
}
|
||||
|
||||
SolsNode typeNode;
|
||||
if (typeName.as.success.type == STT_IDENTIFIER) {
|
||||
ResultType(SolsType, charptr) tmp = createIdentifiedSolsType(typeName.as.success.as.idName);
|
||||
if (tmp.error) {
|
||||
return Error(Nothing, charptr, tmp.as.error);
|
||||
}
|
||||
ResultType(SolsNode, charptr) tmpNode = createSolsNode(SNT_TYPE, tmp.as.success);
|
||||
if (tmpNode.error) {
|
||||
return Error(Nothing, charptr, tmpNode.as.error);
|
||||
}
|
||||
typeNode = tmpNode.as.success;
|
||||
} else if (typeName.as.success.type == STT_TYPE) {
|
||||
ResultType(SolsNode, charptr) tmp = createSolsNode(SNT_TYPE, typeName.as.success.as.type);
|
||||
if (tmp.error) {
|
||||
return Error(Nothing, charptr, tmp.as.error);
|
||||
}
|
||||
typeNode = tmp.as.success;
|
||||
}
|
||||
|
||||
addChildToSolsNode(&node.as.success, typeNode);
|
||||
|
||||
*type.as.success.returnType = ({
|
||||
SolsType tmpType;
|
||||
if (typeName.as.success.type == STT_IDENTIFIER) {
|
||||
ResultType(SolsType, charptr) _result = createIdentifiedSolsType(typeName.as.success.as.idName);
|
||||
if (_result.error) {
|
||||
return Error(Nothing, charptr, _result.as.error);
|
||||
}
|
||||
tmpType = _result.as.success;
|
||||
} else if (typeName.as.success.type == STT_TYPE) {
|
||||
tmpType = typeName.as.success.as.type;
|
||||
}
|
||||
tmpType;
|
||||
});
|
||||
|
||||
node.as.success.as.type = type.as.success;
|
||||
|
||||
// Skip newlines before the opening curly brace
|
||||
while (parserPeek(parser, 1).as.success.type == STT_LINE_END) {
|
||||
parserConsume(parser);
|
||||
}
|
||||
|
||||
ResultType(SolsToken, Nothing) openCurly = parserConsume(parser);
|
||||
if (openCurly.error || openCurly.as.success.type != STT_OPEN_CURLY) {
|
||||
return Error(Nothing, charptr, "Expecting opening curly brace ({) for duplicator body");
|
||||
}
|
||||
|
||||
// Add node to parent
|
||||
addChildToSolsNode(parser->currentParent, node.as.success);
|
||||
|
||||
// Parse code block
|
||||
ResultType(Nothing, charptr) res = parseCodeBlock(parser);
|
||||
if (res.error) return res;
|
||||
|
||||
// Last child of parent is code block, we need to move it
|
||||
SolsNode codeBlock = parser->currentParent->children.at[parser->currentParent->children.count - 1];
|
||||
parser->currentParent->children.count--;
|
||||
|
||||
// We need to get the actual node from the parent to modify it
|
||||
SolsNode* constructorNode = &parser->currentParent->children.at[parser->currentParent->children.count - 1];
|
||||
addChildToSolsNode(constructorNode, codeBlock);
|
||||
return Success(Nothing, charptr, {});
|
||||
|
||||
}
|
||||
|
||||
static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
|
||||
// Get struct name
|
||||
SolsNode structNode = ({
|
||||
@@ -1997,6 +2081,21 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
|
||||
parser->currentParent->children.count--;
|
||||
continue;
|
||||
}
|
||||
if (keyTok.type == STT_KW_AS) {
|
||||
if (private) {
|
||||
return Error(Nothing, charptr, "as method cannot be private");
|
||||
}
|
||||
if (protected) {
|
||||
return Error(Nothing, charptr, "as method cannot be protected");
|
||||
}
|
||||
ResultType(Nothing, charptr) asNode = parseStructAs(parser);
|
||||
if (asNode.error) {
|
||||
return Error(Nothing, charptr, asNode.as.error);
|
||||
}
|
||||
addChildToSolsNode(&structNode, parser->currentParent->children.at[parser->currentParent->children.count - 1]);
|
||||
parser->currentParent->children.count--;
|
||||
continue;
|
||||
}
|
||||
if (keyTok.type != STT_IDENTIFIER) {
|
||||
return Error(Nothing, charptr, "Expecting struct key");
|
||||
}
|
||||
@@ -2179,6 +2278,10 @@ ResultType(Nothing, charptr) parseEnum(SolsParser* parser) {
|
||||
return Success(Nothing, charptr, {});
|
||||
}
|
||||
|
||||
ResultType(Nothing, charptr) parseAs(SolsParser* parser) {
|
||||
return Success(Nothing, charptr, {});
|
||||
}
|
||||
|
||||
ResultType(Nothing, charptr) parse(SolsParser* parser) {
|
||||
parser->currentParent = &parser->output;
|
||||
for (;;) {
|
||||
@@ -2213,6 +2316,7 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) {
|
||||
case STT_OP_EQLESSER: PARSER_HANDLE(EqLesser);
|
||||
case STT_OPEN_CURLY: PARSER_HANDLE(CodeBlock);
|
||||
case STT_CLOSE_CURLY: PARSER_HANDLE(CloseCurly);
|
||||
case STT_KW_AS: PARSER_HANDLE(As);
|
||||
case STT_OPEN_PAREN: {
|
||||
if (parser->output.children.count > 0 &&
|
||||
(parser->output.children.at[parser->output.children.count - 1].type == SNT_IDENTIFIER
|
||||
|
||||
Reference in New Issue
Block a user