forked from solstice/solstice
private and protected fields
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user