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);
|
strncpy(s->id, name, sizeof(s->id) - 1);
|
||||||
s->id[sizeof(s->id) - 1] = '\0';
|
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);
|
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) {
|
if (type.as.success.type != STT_OBJECT) {
|
||||||
return Error(SolsType, charptr, "Cannot use dot operator on non-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;
|
default: break;
|
||||||
}
|
}
|
||||||
@@ -377,6 +384,12 @@ static inline ResultType(GroundProgram, charptr) generateSetNode(SolsNode* node,
|
|||||||
if (type.error) {
|
if (type.error) {
|
||||||
return Error(GroundProgram, charptr, type.as.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) {
|
if (compareTypes(&type.as.success, &rtype.as.success) == false) {
|
||||||
return Error(GroundProgram, charptr, "Type of member cannot be changed");
|
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));
|
groundAddReferenceToInstruction(&structDefInst, groundCreateReference(TYPEREF, node->as.idName));
|
||||||
groundAddInstructionToProgram(&structDef, structDefInst);
|
groundAddInstructionToProgram(&structDef, structDefInst);
|
||||||
for (size_t i = 0; i < node->children.count; i++) {
|
for (size_t i = 0; i < node->children.count; i++) {
|
||||||
|
bool private = false;
|
||||||
|
bool protected = false;
|
||||||
// Add to type for type system
|
// Add to type for type system
|
||||||
SolsNode* child = &node->children.at[i];
|
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) {
|
if (child->type == SNT_DEF) {
|
||||||
ResultType(SolsType, charptr) childType = getNodeType(child, scope);
|
ResultType(SolsType, charptr) childType = getNodeType(child, scope);
|
||||||
if (childType.error) {
|
if (childType.error) {
|
||||||
return Error(GroundProgram, charptr, childType.as.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);
|
addChildToSolsType(&type, childType.as.success, child->children.at[0].as.idName);
|
||||||
|
|
||||||
// Add struct members to new scope
|
// Add struct members to new scope
|
||||||
@@ -1230,6 +1267,8 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
|
|||||||
if (childType.error) {
|
if (childType.error) {
|
||||||
return Error(GroundProgram, charptr, childType.as.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);
|
addChildToSolsType(&type, childType.as.success, child->children.at[0].as.idName);
|
||||||
|
|
||||||
// Generate constant initial value
|
// Generate constant initial value
|
||||||
@@ -1274,6 +1313,16 @@ ResultType(GroundProgram, charptr) generateStructNode(SolsNode* node, SolsScope*
|
|||||||
SolsScope childScope = copySolsScope(scope);
|
SolsScope childScope = copySolsScope(scope);
|
||||||
addVariableToScope(&childScope, "self", type);
|
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++) {
|
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);
|
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_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_DEF, STT_KW_LAMBDA, STT_KW_RETURN,
|
||||||
STT_KW_USE, STT_KW_STRUCT, STT_KW_CONSTRUCTOR, STT_KW_DESTRUCTOR,
|
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_PUTS, STT_KW_IF, STT_KW_WHILE,
|
||||||
STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA
|
STT_KW_NEW, STT_KW_GROUND, STT_LINE_END, STT_COMMA
|
||||||
} SolsTokenType;
|
} SolsTokenType;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "SolsType.h"
|
#include "SolsType.h"
|
||||||
#include "lexer.h"
|
|
||||||
#include "../include/error.h"
|
#include "../include/error.h"
|
||||||
#include "../include/estr.h"
|
#include "../include/estr.h"
|
||||||
#include <groundvm.h>
|
#include <groundvm.h>
|
||||||
@@ -18,7 +17,9 @@ ResultType(SolsType, charptr) createSolsType(SolsTypeType in) {
|
|||||||
.children.count = 0,
|
.children.count = 0,
|
||||||
.children.at = ptr,
|
.children.at = ptr,
|
||||||
.typeIsKnown = true,
|
.typeIsKnown = true,
|
||||||
.needsGroundStruct = false
|
.needsGroundStruct = false,
|
||||||
|
.metadata.isPrivate = false,
|
||||||
|
.metadata.isProtected = false
|
||||||
};
|
};
|
||||||
return Success(SolsType, charptr, type);
|
return Success(SolsType, charptr, type);
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,9 @@ ResultType(SolsType, charptr) createIdentifiedSolsType(char* in) {
|
|||||||
.children.count = 0,
|
.children.count = 0,
|
||||||
.children.at = NULL,
|
.children.at = NULL,
|
||||||
.typeIsKnown = false,
|
.typeIsKnown = false,
|
||||||
.needsGroundStruct = false
|
.needsGroundStruct = false,
|
||||||
|
.metadata.isPrivate = false,
|
||||||
|
.metadata.isProtected = false
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +53,8 @@ ResultType(SolsType, charptr) copySolsType(SolsType* type) {
|
|||||||
.returnType = NULL,
|
.returnType = NULL,
|
||||||
.children.count = type->children.count,
|
.children.count = type->children.count,
|
||||||
.children.capacity = type->children.capacity,
|
.children.capacity = type->children.capacity,
|
||||||
.children.at = NULL
|
.children.at = NULL,
|
||||||
|
.metadata = type->metadata
|
||||||
};
|
};
|
||||||
|
|
||||||
if (type->identifierType != NULL) {
|
if (type->identifierType != NULL) {
|
||||||
|
|||||||
@@ -68,6 +68,11 @@ typedef struct SolsType {
|
|||||||
size_t count;
|
size_t count;
|
||||||
size_t capacity;
|
size_t capacity;
|
||||||
} children;
|
} children;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
bool isPrivate;
|
||||||
|
bool isProtected;
|
||||||
|
} metadata;
|
||||||
} SolsType;
|
} SolsType;
|
||||||
|
|
||||||
// Assists with holding child types in the SolsType struct.
|
// Assists with holding child types in the SolsType struct.
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ struct _SolsTokenTypeMap SolsTokenTypeMap[] = {
|
|||||||
{"struct", STT_KW_STRUCT},
|
{"struct", STT_KW_STRUCT},
|
||||||
{"constructor", STT_KW_CONSTRUCTOR},
|
{"constructor", STT_KW_CONSTRUCTOR},
|
||||||
{"destructor", STT_KW_DESTRUCTOR},
|
{"destructor", STT_KW_DESTRUCTOR},
|
||||||
|
{"private", STT_KW_PRIVATE},
|
||||||
|
{"protected", STT_KW_PROTECTED},
|
||||||
{"ground", STT_KW_GROUND},
|
{"ground", STT_KW_GROUND},
|
||||||
{"new", STT_KW_NEW},
|
{"new", STT_KW_NEW},
|
||||||
{"{", STT_OPEN_CURLY},
|
{"{", STT_OPEN_CURLY},
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ typedef enum SolsNodeType {
|
|||||||
SNT_OP_SET,
|
SNT_OP_SET,
|
||||||
SNT_OP_GREATER, SNT_OP_LESSER, SNT_OP_EQUAL, SNT_OP_INEQUAL, SNT_OP_EQGREATER, SNT_OP_EQLESSER,
|
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_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_USE, SNT_STRUCT, SNT_CONSTRUCTOR, SNT_DESTRUCTOR,
|
||||||
SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW,
|
SNT_PUTS, SNT_IF, SNT_WHILE, SNT_NEW,
|
||||||
SNT_GROUND, SNT_ROOT, SNT_EXPR_IN_PAREN, SNT_DOT,
|
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;
|
if (done) break;
|
||||||
|
|
||||||
|
bool private = false;
|
||||||
|
bool protected = false;
|
||||||
|
|
||||||
// key = value\n
|
// key = value\n
|
||||||
SolsToken keyTok = ({
|
SolsToken keyTok = ({
|
||||||
ResultType(SolsToken, Nothing) _result = parserConsume(parser);
|
ResultType(SolsToken, Nothing) _result = parserConsume(parser);
|
||||||
@@ -1874,18 +1877,46 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
|
|||||||
}
|
}
|
||||||
_result.as.success;
|
_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) {
|
if (keyTok.type == STT_KW_DEF) {
|
||||||
// def fnName(Arg arg1, Arg arg2, ...) ReturnType {}
|
// def fnName(Arg arg1, Arg arg2, ...) ReturnType {}
|
||||||
ResultType(Nothing, charptr) defNode = parseDef(parser);
|
ResultType(Nothing, charptr) defNode = parseDef(parser);
|
||||||
if (defNode.error) {
|
if (defNode.error) {
|
||||||
return Error(Nothing, charptr, defNode.as.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]);
|
addChildToSolsNode(&structNode, parser->currentParent->children.at[parser->currentParent->children.count - 1]);
|
||||||
parser->currentParent->children.count--;
|
parser->currentParent->children.count--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (keyTok.type == STT_KW_CONSTRUCTOR) {
|
if (keyTok.type == STT_KW_CONSTRUCTOR) {
|
||||||
// constructor(Arg arg1, Arg arg2, ...) {}
|
// 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);
|
ResultType(Nothing, charptr) constructorNode = parseConstructor(parser);
|
||||||
if (constructorNode.error) {
|
if (constructorNode.error) {
|
||||||
return Error(Nothing, charptr, constructorNode.as.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) {
|
if (keyTok.type == STT_KW_DESTRUCTOR) {
|
||||||
// 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);
|
ResultType(Nothing, charptr) destructorNode = parseDestructor(parser);
|
||||||
if (destructorNode.error) {
|
if (destructorNode.error) {
|
||||||
return Error(Nothing, charptr, destructorNode.as.error);
|
return Error(Nothing, charptr, destructorNode.as.error);
|
||||||
@@ -1960,6 +1997,8 @@ static inline ResultType(Nothing, charptr) parseStruct(SolsParser* parser) {
|
|||||||
}
|
}
|
||||||
_result.as.success;
|
_result.as.success;
|
||||||
});
|
});
|
||||||
|
if (protected) setNode.type = SNT_SET_PROTECTED;
|
||||||
|
if (private) setNode.type = SNT_SET_PRIVATE;
|
||||||
addChildToSolsNode(&setNode, ({
|
addChildToSolsNode(&setNode, ({
|
||||||
ResultType(SolsNode, charptr) _result = createSolsNode(SNT_IDENTIFIER, keyTok.as.idName);
|
ResultType(SolsNode, charptr) _result = createSolsNode(SNT_IDENTIFIER, keyTok.as.idName);
|
||||||
if (_result.error) {
|
if (_result.error) {
|
||||||
@@ -2074,6 +2113,14 @@ ResultType(Nothing, charptr) parse(SolsParser* parser) {
|
|||||||
createParserError(parser, "'destructor' must be used inside a struct definition");
|
createParserError(parser, "'destructor' must be used inside a struct definition");
|
||||||
break;
|
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) {
|
if (parser->errors.count > 0) {
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
struct Person {
|
struct Person {
|
||||||
name = ""
|
protected name = ""
|
||||||
age = 0
|
private age = 0
|
||||||
|
|
||||||
def greet() string {
|
def greet() string {
|
||||||
return "Hello, " + self.name + "!"
|
return "Hello, " + self.name + "!"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def dance() string {
|
||||||
|
return "Dancing..."
|
||||||
|
}
|
||||||
|
|
||||||
constructor(string name, int age) {
|
constructor(string name, int age) {
|
||||||
self.name = name
|
self.name = name
|
||||||
self.age = age
|
self.age = age
|
||||||
@@ -20,3 +25,8 @@ max = Person("Max", 16)
|
|||||||
|
|
||||||
puts max
|
puts max
|
||||||
puts max.greet()
|
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