private and protected fields

This commit is contained in:
2026-04-12 21:16:59 +10:00
parent d24462f844
commit f384e19c06
9 changed files with 133 additions and 8 deletions

View File

@@ -9,7 +9,13 @@ void addVariableToScope(SolsScope* scope, const char* name, SolsType type) {
strncpy(s->id, name, sizeof(s->id) - 1);
s->id[sizeof(s->id) - 1] = '\0';
s->typeinfo = type;
s->typeinfo = ({
ResultType(SolsType, charptr) _result = copySolsType(&type);
if (_result.error) {
return;
}
_result.as.success;
});
HASH_ADD_STR(scope->variables, id, s);
}

View File

@@ -305,7 +305,14 @@ ResultType(SolsType, charptr) getNodeType(SolsNode* node, SolsScope* scope) {
if (type.as.success.type != STT_OBJECT) {
return Error(SolsType, charptr, "Cannot use dot operator on non-object");
}
return findStructMemberType(&type.as.success, node->children.at[1].as.idName);
ResultType(SolsType, charptr) child = findStructMemberType(&type.as.success, node->children.at[1].as.idName);
if (child.error) {
return child;
}
if (child.as.success.metadata.isPrivate) {
return Error(SolsType, charptr, "Member is private, and cannot be accessed outside of object methods");
}
return child;
}
default: break;
}
@@ -377,6 +384,12 @@ static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node,
if (type.error) {
return Error(GroundProgram, charptr, type.as.error);
}
if (type.as.success.metadata.isPrivate) {
return Error(GroundProgram, charptr, "Member is private, and cannot be accessed outside of object methods");
}
if (type.as.success.metadata.isProtected) {
return Error(GroundProgram, charptr, "Member is protected, and cannot be modified outside of object methods");
}
if (compareTypes(&type.as.success, &rtype.as.success) == false) {
return Error(GroundProgram, charptr, "Type of member cannot be changed");
}
@@ -1162,13 +1175,37 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
groundAddReferenceToInstruction(&structDefInst, groundCreateReference(TYPEREF, node->as.idName));
groundAddInstructionToProgram(&structDef, structDefInst);
for (size_t i = 0; i < node->children.count; i++) {
bool private = false;
bool protected = false;
// Add to type for type system
SolsNode* child = &node->children.at[i];
if (child->type == SNT_DEF_PRIVATE) {
private = true;
child->type = SNT_DEF;
}
if (child->type == SNT_SET_PRIVATE) {
private = true;
child->type = SNT_OP_SET;
}
if (child->type == SNT_DEF_PROTECTED) {
protected = true;
child->type = SNT_DEF;
}
if (child->type == SNT_SET_PROTECTED) {
protected = true;
child->type = SNT_OP_SET;
}
if (child->type == SNT_DEF) {
ResultType(SolsType, charptr) childType = getNodeType(child, scope);
if (childType.error) {
return Error(GroundProgram, charptr, childType.as.error);
}
childType.as.success.metadata.isPrivate = private;
childType.as.success.metadata.isProtected = protected;
addChildToSolsType(&type, childType.as.success, child->children.at[0].as.idName);
// Add struct members to new scope
@@ -1230,6 +1267,8 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
if (childType.error) {
return Error(GroundProgram, charptr, childType.as.error);
}
childType.as.success.metadata.isPrivate = private;
childType.as.success.metadata.isProtected = protected;
addChildToSolsType(&type, childType.as.success, child->children.at[0].as.idName);
// Generate constant initial value
@@ -1274,6 +1313,16 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
SolsScope childScope = copySolsScope(scope);
addVariableToScope(&childScope, "self", type);
// Modify self so that all members are not private or protected
SolsVariable* variable = findSolsVariable(&childScope, "self");
if (variable == NULL) {
return Error(GroundProgram, charptr, "Failed to find self variable (this should never happen)");
}
for (size_t i = 0; i < variable->typeinfo.children.count; i++) {
variable->typeinfo.children.at[i].type.metadata.isPrivate = false;
variable->typeinfo.children.at[i].type.metadata.isProtected = false;
}
for (size_t i = 0; i < constructor->as.type.children.count; i++) {
addVariableToScope(&childScope, constructor->as.type.children.at[i].name, constructor->as.type.children.at[i].type);
}

View File

@@ -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_CONSTRUCTOR, STT_KW_DESTRUCTOR,
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
} SolsTokenType;

View File

@@ -1,5 +1,4 @@
#include "SolsType.h"
#include "lexer.h"
#include "../include/error.h"
#include "../include/estr.h"
#include <groundvm.h>
@@ -18,7 +17,9 @@ ResultType(SolsType, charptr) createSolsType(SolsTypeType in) {
.children.count = 0,
.children.at = ptr,
.typeIsKnown = true,
.needsGroundStruct = false
.needsGroundStruct = false,
.metadata.isPrivate = false,
.metadata.isProtected = false
};
return Success(SolsType, charptr, type);
}
@@ -37,7 +38,9 @@ ResultType(SolsType, charptr) createIdentifiedSolsType(char* in) {
.children.count = 0,
.children.at = NULL,
.typeIsKnown = false,
.needsGroundStruct = false
.needsGroundStruct = false,
.metadata.isPrivate = false,
.metadata.isProtected = false
}));
}
@@ -50,7 +53,8 @@ ResultType(SolsType, charptr) copySolsType(SolsType* type) {
.returnType = NULL,
.children.count = type->children.count,
.children.capacity = type->children.capacity,
.children.at = NULL
.children.at = NULL,
.metadata = type->metadata
};
if (type->identifierType != NULL) {

View File

@@ -68,6 +68,11 @@ typedef struct SolsType {
size_t count;
size_t capacity;
} children;
struct {
bool isPrivate;
bool isProtected;
} metadata;
} SolsType;
// Assists with holding child types in the SolsType struct.

View File

@@ -17,6 +17,8 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
{"struct", STT_KW_STRUCT},
{"constructor", STT_KW_CONSTRUCTOR},
{"destructor", STT_KW_DESTRUCTOR},
{"private", STT_KW_PRIVATE},
{"protected", STT_KW_PROTECTED},
{"ground", STT_KW_GROUND},
{"new", STT_KW_NEW},
{"{", STT_OPEN_CURLY},

View File

@@ -19,6 +19,7 @@ typedef enum SolsNodeType {
SNT_OP_SET,
SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER,
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_CONSTRUCTOR, SNT_DESTRUCTOR,
SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW,
SNT_GROUND, SNT_ROOT, SNT_EXPR_IN_PAREN, SNT_DOT,

View File

@@ -1866,6 +1866,9 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
}
if (done) break;
bool private = false;
bool protected = false;
// key = value\n
SolsToken keyTok = ({
ResultType(SolsToken, Nothing) _result = parserConsume(parser);
@@ -1874,18 +1877,46 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
}
_result.as.success;
});
if (keyTok.type == STT_KW_PRIVATE) {
// private key = value
private = true;
ResultType(SolsToken, Nothing) result = parserConsume(parser);
if (result.error) {
return Error(Nothing, charptr, "Expecting identifier after 'private'");
}
keyTok = result.as.success;
}
if (keyTok.type == STT_KW_PROTECTED) {
// protected key = value
protected = true;
ResultType(SolsToken, Nothing) result = parserConsume(parser);
if (result.error) {
return Error(Nothing, charptr, "Expecting identifier after 'protected'");
}
keyTok = result.as.success;
}
if (keyTok.type == STT_KW_DEF) {
// def fnName(Arg arg1, Arg arg2, ...) ReturnType {}
ResultType(Nothing, charptr) defNode = parseDef(parser);
if (defNode.error) {
return Error(Nothing, charptr, defNode.as.error);
}
if (protected) parser->currentParent->children.at[parser->currentParent->children.count - 1].type = SNT_DEF_PROTECTED;
if (private) parser->currentParent->children.at[parser->currentParent->children.count - 1].type = SNT_DEF_PRIVATE;
addChildToSolsNode(&structNode, parser->currentParent->children.at[parser->currentParent->children.count - 1]);
parser->currentParent->children.count--;
continue;
}
if (keyTok.type == STT_KW_CONSTRUCTOR) {
// constructor(Arg arg1, Arg arg2, ...) {}
if (private) {
return Error(Nothing, charptr, "Constructor cannot be private");
}
if (protected) {
return Error(Nothing, charptr, "Constructor cannot be protected");
}
ResultType(Nothing, charptr) constructorNode = parseConstructor(parser);
if (constructorNode.error) {
return Error(Nothing, charptr, constructorNode.as.error);
@@ -1896,6 +1927,12 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
}
if (keyTok.type == STT_KW_DESTRUCTOR) {
// destructor {}
if (private) {
return Error(Nothing, charptr, "Destructor cannot be private");
}
if (protected) {
return Error(Nothing, charptr, "Destructor cannot be protected");
}
ResultType(Nothing, charptr) destructorNode = parseDestructor(parser);
if (destructorNode.error) {
return Error(Nothing, charptr, destructorNode.as.error);
@@ -1960,6 +1997,8 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
}
_result.as.success;
});
if (protected) setNode.type = SNT_SET_PROTECTED;
if (private) setNode.type = SNT_SET_PRIVATE;
addChildToSolsNode(&setNode, ({
ResultType(SolsNode, charptr) _result = createSolsNode(SNT_IDENTIFIER, keyTok.as.idName);
if (_result.error) {
@@ -2074,6 +2113,14 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) {
createParserError(parser, "'destructor' must be used inside a struct definition");
break;
}
case STT_KW_PRIVATE: {
createParserError(parser, "'private' must be used inside a struct definition");
break;
}
case STT_KW_PROTECTED: {
createParserError(parser, "'protected' must be used inside a struct definition");
break;
}
}
}
if (parser->errors.count > 0) {

View File

@@ -1,10 +1,15 @@
struct Person {
name = ""
age = 0
protected name = ""
private age = 0
def greet() string {
return "Hello, " + self.name + "!"
}
def dance() string {
return "Dancing..."
}
constructor(string name, int age) {
self.name = name
self.age = age
@@ -20,3 +25,8 @@ max = Person("Max", 16)
puts max
puts max.greet()
puts max.name
// puts max.age (causes compile time error, age is private)
// max.name = "Maximilian" (causes compile time error, name is protected)
max.dance()