mirror of https://gitlab.com/nakst/essence
				
				
				
			scripting engine: inheritance of inttypes
This commit is contained in:
		
							parent
							
								
									d64d3ce44e
								
							
						
					
					
						commit
						f280516530
					
				|  | @ -4,7 +4,8 @@ | ||||||
| // 	- Other operators: remainder, ternary.
 | // 	- Other operators: remainder, ternary.
 | ||||||
| // 	- Named optional arguments with default values.
 | // 	- Named optional arguments with default values.
 | ||||||
| // 	- Accessing structs and functypes from imported modules.
 | // 	- Accessing structs and functypes from imported modules.
 | ||||||
| // 	- inttype and struct inheritance.
 | // 	- struct inheritance.
 | ||||||
|  | // 	- Allow implicit casts when passing functions parameters
 | ||||||
| 
 | 
 | ||||||
| // TODO Larger missing features:
 | // TODO Larger missing features:
 | ||||||
| // 	- Serialization.
 | // 	- Serialization.
 | ||||||
|  | @ -257,7 +258,7 @@ typedef struct Scope { | ||||||
| 
 | 
 | ||||||
| typedef struct Node { | typedef struct Node { | ||||||
| 	uint8_t type; | 	uint8_t type; | ||||||
| 	bool referencesRootScope, isExternalCall, isPersistentVariable, isOptionVariable, cycleCheck; | 	bool referencesRootScope, isExternalCall, isPersistentVariable, isOptionVariable, cycleCheck, hasTypeInheritanceParent; | ||||||
| 	uint8_t operationType; | 	uint8_t operationType; | ||||||
| 	int32_t inlineImportVariableIndex; | 	int32_t inlineImportVariableIndex; | ||||||
| 	Token token; | 	Token token; | ||||||
|  | @ -2118,6 +2119,7 @@ Node *ParseRoot(Tokenizer *tokenizer) { | ||||||
| 				node->firstChild = ParseType(tokenizer, false, false, false); | 				node->firstChild = ParseType(tokenizer, false, false, false); | ||||||
| 				if (!node->firstChild) return NULL; | 				if (!node->firstChild) return NULL; | ||||||
| 				semicolon = TokenNext(tokenizer); | 				semicolon = TokenNext(tokenizer); | ||||||
|  | 				node->hasTypeInheritanceParent = true; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (semicolon.type != T_SEMICOLON) { | 			if (semicolon.type != T_SEMICOLON) { | ||||||
|  | @ -2131,19 +2133,33 @@ Node *ParseRoot(Tokenizer *tokenizer) { | ||||||
| 			node->token = TokenNext(tokenizer); | 			node->token = TokenNext(tokenizer); | ||||||
| 			*link = node; | 			*link = node; | ||||||
| 			link = &node->sibling; | 			link = &node->sibling; | ||||||
|  | 			Node **contentLink = &node->firstChild; | ||||||
| 
 | 
 | ||||||
| 			if (node->token.type != T_IDENTIFIER) { | 			if (node->token.type != T_IDENTIFIER) { | ||||||
| 				PrintError2(tokenizer, node, "Expected the name of the inttype.\n"); | 				PrintError2(tokenizer, node, "Expected the name of the inttype.\n"); | ||||||
| 				return NULL; | 				return NULL; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (TokenNext(tokenizer).type != T_LEFT_FANCY) { | 			Token token = TokenNext(tokenizer); | ||||||
|  | 
 | ||||||
|  | 			if (token.type == T_ERROR) { | ||||||
|  | 				return NULL; | ||||||
|  | 			} else if (token.type == T_COLON) { | ||||||
|  | 				Node *parent = ParseType(tokenizer, false, false, false); | ||||||
|  | 				if (!parent) return NULL; | ||||||
|  | 				*contentLink = parent; | ||||||
|  | 				contentLink = &parent->sibling; | ||||||
|  | 				token = TokenNext(tokenizer); | ||||||
|  | 				node->hasTypeInheritanceParent = true; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if (token.type == T_ERROR) { | ||||||
|  | 				return NULL; | ||||||
|  | 			} else if (token.type != T_LEFT_FANCY) { | ||||||
| 				PrintError2(tokenizer, node, "Expected a '{' for the inttype contents after the name.\n"); | 				PrintError2(tokenizer, node, "Expected a '{' for the inttype contents after the name.\n"); | ||||||
| 				return NULL; | 				return NULL; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			Node **constantLink = &node->firstChild; |  | ||||||
| 
 |  | ||||||
| 			while (true) { | 			while (true) { | ||||||
| 				Token peek = TokenPeek(tokenizer); | 				Token peek = TokenPeek(tokenizer); | ||||||
| 				if (peek.type == T_ERROR) return NULL; | 				if (peek.type == T_ERROR) return NULL; | ||||||
|  | @ -2151,8 +2167,8 @@ Node *ParseRoot(Tokenizer *tokenizer) { | ||||||
| 				Node *constant = (Node *) AllocateFixed(sizeof(Node)); | 				Node *constant = (Node *) AllocateFixed(sizeof(Node)); | ||||||
| 				constant->token = TokenNext(tokenizer); | 				constant->token = TokenNext(tokenizer); | ||||||
| 				constant->type = T_INTTYPE_CONSTANT; | 				constant->type = T_INTTYPE_CONSTANT; | ||||||
| 				*constantLink = constant; | 				*contentLink = constant; | ||||||
| 				constantLink = &constant->sibling; | 				contentLink = &constant->sibling; | ||||||
| 
 | 
 | ||||||
| 				if (constant->token.type != T_IDENTIFIER) { | 				if (constant->token.type != T_IDENTIFIER) { | ||||||
| 					PrintError2(tokenizer, constant, "Expected an identifier for the constant.\n"); | 					PrintError2(tokenizer, constant, "Expected an identifier for the constant.\n"); | ||||||
|  | @ -2644,9 +2660,14 @@ bool ASTLookupTypeIdentifiers(Tokenizer *tokenizer, Node *node) { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (node->type == T_DECLARE || node->type == T_ARGUMENT || node->type == T_NEW || node->type == T_LIST || node->type == T_HANDLETYPE) { | 	if (node->type == T_DECLARE || node->type == T_ARGUMENT || node->type == T_NEW || node->type == T_LIST || node->hasTypeInheritanceParent) { | ||||||
| 		Node *type = node->firstChild; | 		Node *type = node->firstChild; | ||||||
| 
 | 
 | ||||||
|  | 		if (node->hasTypeInheritanceParent && type && type->type != T_IDENTIFIER) { | ||||||
|  | 			PrintError2(tokenizer, node, "Types can only inherit from similar types.\n"); | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		if (type && type->type == T_IDENTIFIER) { | 		if (type && type->type == T_IDENTIFIER) { | ||||||
| 			Node *lookup = ScopeLookup(tokenizer, type, false); | 			Node *lookup = ScopeLookup(tokenizer, type, false); | ||||||
| 
 | 
 | ||||||
|  | @ -2654,9 +2675,9 @@ bool ASTLookupTypeIdentifiers(Tokenizer *tokenizer, Node *node) { | ||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			if (node->type == T_HANDLETYPE) { | 			if (node->hasTypeInheritanceParent) { | ||||||
| 				if (lookup->type != T_HANDLETYPE) { | 				if (lookup->type != node->type) { | ||||||
| 					PrintError2(tokenizer, lookup, "handletypes can only inherit from other handletypes.\n"); | 					PrintError2(tokenizer, node, "Types can only inherit from similar types.\n"); | ||||||
| 					return false; | 					return false; | ||||||
| 				} | 				} | ||||||
| 			} else if (!node->expressionType) { | 			} else if (!node->expressionType) { | ||||||
|  | @ -2670,18 +2691,19 @@ bool ASTLookupTypeIdentifiers(Tokenizer *tokenizer, Node *node) { | ||||||
| 			} else if (lookup->type == T_FUNCTYPE) { | 			} else if (lookup->type == T_FUNCTYPE) { | ||||||
| 				MemoryCopy(node->expressionType, lookup->firstChild, sizeof(Node)); | 				MemoryCopy(node->expressionType, lookup->firstChild, sizeof(Node)); | ||||||
| 			} else if (lookup->type == T_STRUCT || lookup->type == T_INTTYPE || lookup->type == T_HANDLETYPE) { | 			} else if (lookup->type == T_STRUCT || lookup->type == T_INTTYPE || lookup->type == T_HANDLETYPE) { | ||||||
| 				if (node->type == T_HANDLETYPE) { | 				if (node->hasTypeInheritanceParent) { | ||||||
| 					if (lookup->cycleCheck) { | 					if (lookup->cycleCheck) { | ||||||
| 						PrintError2(tokenizer, lookup, "Cyclic handletype inheritance.\n"); | 						PrintError2(tokenizer, lookup, "Cyclic type inheritance.\n"); | ||||||
| 						return false; | 						return false; | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					Node *copy = (Node *) AllocateFixed(sizeof(Node)); | 					Node *copy = (Node *) AllocateFixed(sizeof(Node)); | ||||||
| 					*copy = *lookup; | 					*copy = *lookup; | ||||||
| 					copy->sibling = NULL; | 					copy->sibling = node->firstChild->sibling; | ||||||
| 					node->firstChild = copy; | 					node->firstChild = copy; | ||||||
| 					node->cycleCheck = true; | 					node->cycleCheck = true; | ||||||
| 					if (!ASTLookupTypeIdentifiers(tokenizer, copy)) return false; | 					if (!ASTLookupTypeIdentifiers(tokenizer, copy)) return false; | ||||||
|  | 					node->cycleCheck = false; | ||||||
| 				} else { | 				} else { | ||||||
| 					MemoryCopy(node->expressionType, lookup, sizeof(Node)); | 					MemoryCopy(node->expressionType, lookup, sizeof(Node)); | ||||||
| 				} | 				} | ||||||
|  | @ -2703,8 +2725,13 @@ bool ASTImplicitCastIsPossible(Node *targetType, Node *expressionType) { | ||||||
| 	} else if (targetType->type == T_ERR && ASTMatching(targetType->firstChild, expressionType)) { | 	} else if (targetType->type == T_ERR && ASTMatching(targetType->firstChild, expressionType)) { | ||||||
| 		return true; | 		return true; | ||||||
| 	} else if (targetType->type == T_HANDLETYPE && expressionType->type == T_HANDLETYPE) { | 	} else if (targetType->type == T_HANDLETYPE && expressionType->type == T_HANDLETYPE) { | ||||||
|  | 		// Only allow implicit casts to the inherited type.
 | ||||||
| 		Node *inherit = expressionType->firstChild; | 		Node *inherit = expressionType->firstChild; | ||||||
| 		return inherit && (ASTMatching(targetType, inherit) || ASTImplicitCastIsPossible(targetType, inherit)); | 		return inherit && (ASTMatching(targetType, inherit) || ASTImplicitCastIsPossible(targetType, inherit)); | ||||||
|  | 	} else if (targetType->type == T_INTTYPE && expressionType->type == T_INTTYPE) { | ||||||
|  | 		// Only allow implicit casts to a type that inherits from this.
 | ||||||
|  | 		Node *inherit = targetType->firstChild; | ||||||
|  | 		return inherit && inherit->type != T_INTTYPE_CONSTANT && (ASTMatching(inherit, expressionType) || ASTImplicitCastIsPossible(inherit, expressionType)); | ||||||
| 	} else { | 	} else { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  | @ -2723,8 +2750,9 @@ Node *ASTImplicitCastApply(Tokenizer *tokenizer, Node *parent, Node *target, Nod | ||||||
| 		cast->parent = parent; | 		cast->parent = parent; | ||||||
| 		cast->firstChild = expression; | 		cast->firstChild = expression; | ||||||
| 		return cast; | 		return cast; | ||||||
| 	} else if (target->type == T_HANDLETYPE && expression->expressionType->type == T_HANDLETYPE) { | 	} else if ((target->type == T_HANDLETYPE && expression->expressionType->type == T_HANDLETYPE) | ||||||
| 		return expression; // Nothing needs to be done to cast between handletypes.
 | 			|| (target->type == T_INTTYPE && expression->expressionType->type == T_INTTYPE)) { | ||||||
|  | 		return expression; // Nothing needs to be done to cast between handletypes or inttypes.
 | ||||||
| 	} else { | 	} else { | ||||||
| 		Assert(false); | 		Assert(false); | ||||||
| 		return NULL; | 		return NULL; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 nakst
						nakst