mirror of https://gitlab.com/nakst/essence
				
				
				
			scripting engine add unary negate; add EsTextboxAppend; fix port script issue
This commit is contained in:
		
							parent
							
								
									6d0810cb66
								
							
						
					
					
						commit
						129d072a49
					
				| 
						 | 
					@ -3123,10 +3123,10 @@ bool /* returns false on fatal error */ DesktopSyscall(EsObjectID windowID, Appl
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void EmbeddedWindowDestroyed(EsObjectID id) {
 | 
					void EmbeddedWindowDestroyed(EsObjectID id) {
 | 
				
			||||||
	EsMenuCloseAll(); // The tab will be destroyed, but menus might be keeping pointers to it.
 | 
					 | 
				
			||||||
	ApplicationInstance *instance = ApplicationInstanceFindByWindowID(id, true /* remove if found */);
 | 
						ApplicationInstance *instance = ApplicationInstanceFindByWindowID(id, true /* remove if found */);
 | 
				
			||||||
	if (!instance) return;
 | 
						if (!instance) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						EsMenuCloseAll(); // The tab will be destroyed, but menus might be keeping pointers to it.
 | 
				
			||||||
	EsHandleClose(instance->embeddedWindowHandle);
 | 
						EsHandleClose(instance->embeddedWindowHandle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ApplicationInstanceCleanup(instance);
 | 
						ApplicationInstanceCleanup(instance);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2499,6 +2499,7 @@ function EsElement *EsButtonGetCheckBuddy(EsButton *button);  // TODO Public pro
 | 
				
			||||||
function EsTextbox *EsTextboxCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
 | 
					function EsTextbox *EsTextboxCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL);
 | 
				
			||||||
function bool EsTextboxFind(EsTextbox *textbox, STRING string, int32_t *line, int32_t *byte, uint32_t flags);
 | 
					function bool EsTextboxFind(EsTextbox *textbox, STRING string, int32_t *line, int32_t *byte, uint32_t flags);
 | 
				
			||||||
function void EsTextboxInsert(EsTextbox *textbox, STRING string = BLANK_STRING, bool sendUpdatedMessage = true); // Deletes existing selection first.
 | 
					function void EsTextboxInsert(EsTextbox *textbox, STRING string = BLANK_STRING, bool sendUpdatedMessage = true); // Deletes existing selection first.
 | 
				
			||||||
 | 
					function void EsTextboxAppend(EsTextbox *textbox, STRING string = BLANK_STRING, bool sendUpdatedMessage = true); // Ignores the user's selection.
 | 
				
			||||||
function char *EsTextboxGetContents(EsTextbox *textbox, size_t *bytes = ES_NULL, uint32_t flags = ES_FLAGS_DEFAULT); // Result will be zero-terminated; free with EsHeapFree.
 | 
					function char *EsTextboxGetContents(EsTextbox *textbox, size_t *bytes = ES_NULL, uint32_t flags = ES_FLAGS_DEFAULT); // Result will be zero-terminated; free with EsHeapFree.
 | 
				
			||||||
function double EsTextboxGetContentsAsDouble(EsTextbox *textbox, uint32_t flags = ES_FLAGS_DEFAULT); 
 | 
					function double EsTextboxGetContentsAsDouble(EsTextbox *textbox, uint32_t flags = ES_FLAGS_DEFAULT); 
 | 
				
			||||||
function size_t EsTextboxGetLineLength(EsTextbox *textbox, uintptr_t line = 0);
 | 
					function size_t EsTextboxGetLineLength(EsTextbox *textbox, uintptr_t line = 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1196,6 +1196,15 @@ void EsTextboxInsert(EsTextbox *textbox, const char *string, ptrdiff_t stringByt
 | 
				
			||||||
			&& textbox->carets[1].byte >= 0 && textbox->carets[1].byte <= textbox->lines[textbox->carets[1].line].lengthBytes);
 | 
								&& textbox->carets[1].byte >= 0 && textbox->carets[1].byte <= textbox->lines[textbox->carets[1].line].lengthBytes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void EsTextboxAppend(EsTextbox *textbox, const char *string, ptrdiff_t stringBytes, bool sendUpdatedMessage) {
 | 
				
			||||||
 | 
						TextboxCaret oldCarets[2];
 | 
				
			||||||
 | 
						oldCarets[0] = textbox->carets[0];
 | 
				
			||||||
 | 
						oldCarets[1] = textbox->carets[1];
 | 
				
			||||||
 | 
						EsTextboxMoveCaretRelative(textbox, ES_TEXTBOX_MOVE_CARET_ALL);
 | 
				
			||||||
 | 
						EsTextboxInsert(textbox, string, stringBytes, sendUpdatedMessage);
 | 
				
			||||||
 | 
						EsTextboxSetSelection(textbox, oldCarets[0].line, oldCarets[0].byte, oldCarets[1].line, oldCarets[1].byte);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char *EsTextboxGetContents(EsTextbox *textbox, size_t *_bytes, uint32_t flags) {
 | 
					char *EsTextboxGetContents(EsTextbox *textbox, size_t *_bytes, uint32_t flags) {
 | 
				
			||||||
	EsMessageMutexCheck();
 | 
						EsMessageMutexCheck();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -232,20 +232,20 @@ void PortGCC() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !resumeBuild {
 | 
						if !resumeBuild {
 | 
				
			||||||
		if buildCross {
 | 
							if buildCross {
 | 
				
			||||||
			assert PathDeleteRecursively("cross");
 | 
								PathDeleteRecursively("cross");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Cleanup.
 | 
							// Cleanup.
 | 
				
			||||||
		assert PathDeleteRecursively("bin/build-binutils");
 | 
							PathDeleteRecursively("bin/build-binutils");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/build-gcc");
 | 
							PathDeleteRecursively("bin/build-gcc");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/build-mpfr");
 | 
							PathDeleteRecursively("bin/build-mpfr");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/build-mpc");
 | 
							PathDeleteRecursively("bin/build-mpc");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/build-gmp");
 | 
							PathDeleteRecursively("bin/build-gmp");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/binutils-src");
 | 
							PathDeleteRecursively("bin/binutils-src");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/gcc-src");
 | 
							PathDeleteRecursively("bin/gcc-src");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/mpfr-src");
 | 
							PathDeleteRecursively("bin/mpfr-src");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/mpc-src");
 | 
							PathDeleteRecursively("bin/mpc-src");
 | 
				
			||||||
		assert PathDeleteRecursively("bin/gmp-src");
 | 
							PathDeleteRecursively("bin/gmp-src");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Create folders.
 | 
							// Create folders.
 | 
				
			||||||
		assert PathCreateDirectory("bin/build-binutils");
 | 
							assert PathCreateDirectory("bin/build-binutils");
 | 
				
			||||||
| 
						 | 
					@ -409,16 +409,16 @@ void PortGCC() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Cleanup.
 | 
						// Cleanup.
 | 
				
			||||||
	runningMakefiles = false;
 | 
						runningMakefiles = false;
 | 
				
			||||||
	assert PathDeleteRecursively("bin/build-binutils");
 | 
						PathDeleteRecursively("bin/build-binutils");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/build-gcc");
 | 
						PathDeleteRecursively("bin/build-gcc");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/build-mpc");
 | 
						PathDeleteRecursively("bin/build-mpc");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/build-mpfr");
 | 
						PathDeleteRecursively("bin/build-mpfr");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/build-gmp");
 | 
						PathDeleteRecursively("bin/build-gmp");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/binutils-src");
 | 
						PathDeleteRecursively("bin/binutils-src");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/gcc-src");
 | 
						PathDeleteRecursively("bin/gcc-src");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/mpc-src");
 | 
						PathDeleteRecursively("bin/mpc-src");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/mpfr-src");
 | 
						PathDeleteRecursively("bin/mpfr-src");
 | 
				
			||||||
	assert PathDeleteRecursively("bin/gmp-src");
 | 
						PathDeleteRecursively("bin/gmp-src");
 | 
				
			||||||
	PrintStdErrHighlight("Build succeeded.\n");
 | 
						PrintStdErrHighlight("Build succeeded.\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -165,6 +165,7 @@ EsMountPointAdd=163
 | 
				
			||||||
EsSystemConfigurationReadFileTypes=164
 | 
					EsSystemConfigurationReadFileTypes=164
 | 
				
			||||||
EsImageLoad=165
 | 
					EsImageLoad=165
 | 
				
			||||||
EsMountPointRemove=166
 | 
					EsMountPointRemove=166
 | 
				
			||||||
 | 
					EsTextboxAppend=167
 | 
				
			||||||
EsCRTabs=168
 | 
					EsCRTabs=168
 | 
				
			||||||
EsCRTacosf=169
 | 
					EsCRTacosf=169
 | 
				
			||||||
EsCRTasinf=170
 | 
					EsCRTasinf=170
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1976,13 +1976,11 @@ void _start() {
 | 
				
			||||||
			EsCommandSetEnabled(&commandBuild, true);
 | 
								EsCommandSetEnabled(&commandBuild, true);
 | 
				
			||||||
			EsCommandSetEnabled(&commandLaunch, true);
 | 
								EsCommandSetEnabled(&commandLaunch, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			EsTextboxMoveCaretRelative(textboxLog, ES_TEXTBOX_MOVE_CARET_ALL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (message->type == MSG_BUILD_FAILED) {
 | 
								if (message->type == MSG_BUILD_FAILED) {
 | 
				
			||||||
				EsTextboxInsert(textboxLog, INTERFACE_STRING(BuildCoreBuildFailed), false);
 | 
									EsTextboxAppend(textboxLog, INTERFACE_STRING(BuildCoreBuildFailed), false);
 | 
				
			||||||
				EsElementFocus(buttonBuild, ES_ELEMENT_FOCUS_ONLY_IF_NO_FOCUSED_ELEMENT);
 | 
									EsElementFocus(buttonBuild, ES_ELEMENT_FOCUS_ONLY_IF_NO_FOCUSED_ELEMENT);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				EsTextboxInsert(textboxLog, INTERFACE_STRING(BuildCoreBuildSuccess), false);
 | 
									EsTextboxAppend(textboxLog, INTERFACE_STRING(BuildCoreBuildSuccess), false);
 | 
				
			||||||
				EsElementFocus(buttonLaunch, ES_ELEMENT_FOCUS_ONLY_IF_NO_FOCUSED_ELEMENT);
 | 
									EsElementFocus(buttonLaunch, ES_ELEMENT_FOCUS_ONLY_IF_NO_FOCUSED_ELEMENT);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1990,9 +1988,7 @@ void _start() {
 | 
				
			||||||
			_EsPathAnnouncePathMoved(NULL, 0, workingDirectory, workingDirectoryBytes);
 | 
								_EsPathAnnouncePathMoved(NULL, 0, workingDirectory, workingDirectoryBytes);
 | 
				
			||||||
		} else if (message->type == MSG_LOG) {
 | 
							} else if (message->type == MSG_LOG) {
 | 
				
			||||||
			char *copy = message->user.context1.p;
 | 
								char *copy = message->user.context1.p;
 | 
				
			||||||
			EsTextboxMoveCaretRelative(textboxLog, ES_TEXTBOX_MOVE_CARET_ALL);
 | 
								EsTextboxAppend(textboxLog, copy, -1, false);
 | 
				
			||||||
			EsTextboxInsert(textboxLog, copy, -1, false);
 | 
					 | 
				
			||||||
			EsTextboxEnsureCaretVisible(textboxLog, false);
 | 
					 | 
				
			||||||
			EsHeapFree(copy, 0, NULL);
 | 
								EsHeapFree(copy, 0, NULL);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										108
									
								
								util/script.c
								
								
								
								
							
							
						
						
									
										108
									
								
								util/script.c
								
								
								
								
							| 
						 | 
					@ -2,9 +2,9 @@
 | 
				
			||||||
// 	- Other list operations: insert_many, delete, delete_many, delete_last.
 | 
					// 	- Other list operations: insert_many, delete, delete_many, delete_last.
 | 
				
			||||||
// 	- Maps: T[int], T[str].
 | 
					// 	- Maps: T[int], T[str].
 | 
				
			||||||
// 	- Control flow: break, continue.
 | 
					// 	- Control flow: break, continue.
 | 
				
			||||||
// 	- Other operators: remainder, bitwise shifts, unary minus, bitwise AND/OR/XOR/NOT, ternary.
 | 
					// 	- Other operators: remainder, bitwise shifts, bitwise AND/OR/XOR/NOT, ternary.
 | 
				
			||||||
// 	- Enums, bitsets.
 | 
					// 	- Enums, bitsets.
 | 
				
			||||||
// 	- Resolving type identifiers when structs or function pointers contain references to other structs or function pointers.
 | 
					// 	- Named optional arguments with default values.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO Larger missing features:
 | 
					// TODO Larger missing features:
 | 
				
			||||||
// 	- Serialization.
 | 
					// 	- Serialization.
 | 
				
			||||||
| 
						 | 
					@ -44,30 +44,31 @@
 | 
				
			||||||
#define T_MINUS               (41)
 | 
					#define T_MINUS               (41)
 | 
				
			||||||
#define T_ASTERISK            (42)
 | 
					#define T_ASTERISK            (42)
 | 
				
			||||||
#define T_SLASH               (43)
 | 
					#define T_SLASH               (43)
 | 
				
			||||||
#define T_LEFT_ROUND          (44)
 | 
					#define T_NEGATE              (44)
 | 
				
			||||||
#define T_RIGHT_ROUND         (45)
 | 
					#define T_LEFT_ROUND          (45)
 | 
				
			||||||
#define T_LEFT_SQUARE         (46)
 | 
					#define T_RIGHT_ROUND         (46)
 | 
				
			||||||
#define T_RIGHT_SQUARE        (47)
 | 
					#define T_LEFT_SQUARE         (47)
 | 
				
			||||||
#define T_LEFT_FANCY          (48)
 | 
					#define T_RIGHT_SQUARE        (48)
 | 
				
			||||||
#define T_RIGHT_FANCY         (49)
 | 
					#define T_LEFT_FANCY          (49)
 | 
				
			||||||
#define T_COMMA               (50)
 | 
					#define T_RIGHT_FANCY         (50)
 | 
				
			||||||
#define T_EQUALS              (51)
 | 
					#define T_COMMA               (51)
 | 
				
			||||||
#define T_SEMICOLON           (52)
 | 
					#define T_EQUALS              (52)
 | 
				
			||||||
#define T_GREATER_THAN        (53)
 | 
					#define T_SEMICOLON           (53)
 | 
				
			||||||
#define T_LESS_THAN           (54)
 | 
					#define T_GREATER_THAN        (54)
 | 
				
			||||||
#define T_GT_OR_EQUAL         (55)
 | 
					#define T_LESS_THAN           (55)
 | 
				
			||||||
#define T_LT_OR_EQUAL         (56)
 | 
					#define T_GT_OR_EQUAL         (56)
 | 
				
			||||||
#define T_DOUBLE_EQUALS       (57)
 | 
					#define T_LT_OR_EQUAL         (57)
 | 
				
			||||||
#define T_NOT_EQUALS          (58)
 | 
					#define T_DOUBLE_EQUALS       (58)
 | 
				
			||||||
#define T_LOGICAL_AND         (59)
 | 
					#define T_NOT_EQUALS          (59)
 | 
				
			||||||
#define T_LOGICAL_OR          (60)
 | 
					#define T_LOGICAL_AND         (60)
 | 
				
			||||||
#define T_ADD_EQUALS          (61)
 | 
					#define T_LOGICAL_OR          (61)
 | 
				
			||||||
#define T_MINUS_EQUALS        (62)
 | 
					#define T_ADD_EQUALS          (62)
 | 
				
			||||||
#define T_ASTERISK_EQUALS     (63)
 | 
					#define T_MINUS_EQUALS        (63)
 | 
				
			||||||
#define T_SLASH_EQUALS        (64)
 | 
					#define T_ASTERISK_EQUALS     (64)
 | 
				
			||||||
#define T_DOT                 (65)
 | 
					#define T_SLASH_EQUALS        (65)
 | 
				
			||||||
#define T_COLON               (66)
 | 
					#define T_DOT                 (66)
 | 
				
			||||||
#define T_LOGICAL_NOT         (67)
 | 
					#define T_COLON               (67)
 | 
				
			||||||
 | 
					#define T_LOGICAL_NOT         (68)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define T_ROOT                (80)
 | 
					#define T_ROOT                (80)
 | 
				
			||||||
#define T_FUNCBODY            (81)
 | 
					#define T_FUNCBODY            (81)
 | 
				
			||||||
| 
						 | 
					@ -102,17 +103,18 @@
 | 
				
			||||||
#define T_FLOAT_MINUS         (121)
 | 
					#define T_FLOAT_MINUS         (121)
 | 
				
			||||||
#define T_FLOAT_ASTERISK      (122)
 | 
					#define T_FLOAT_ASTERISK      (122)
 | 
				
			||||||
#define T_FLOAT_SLASH         (123)
 | 
					#define T_FLOAT_SLASH         (123)
 | 
				
			||||||
#define T_FLOAT_GREATER_THAN  (124)
 | 
					#define T_FLOAT_NEGATE        (124)
 | 
				
			||||||
#define T_FLOAT_LESS_THAN     (125)
 | 
					#define T_FLOAT_GREATER_THAN  (125)
 | 
				
			||||||
#define T_FLOAT_GT_OR_EQUAL   (126)
 | 
					#define T_FLOAT_LESS_THAN     (126)
 | 
				
			||||||
#define T_FLOAT_LT_OR_EQUAL   (127)
 | 
					#define T_FLOAT_GT_OR_EQUAL   (127)
 | 
				
			||||||
#define T_FLOAT_DOUBLE_EQUALS (128)
 | 
					#define T_FLOAT_LT_OR_EQUAL   (128)
 | 
				
			||||||
#define T_FLOAT_NOT_EQUALS    (129)
 | 
					#define T_FLOAT_DOUBLE_EQUALS (129)
 | 
				
			||||||
#define T_STR_DOUBLE_EQUALS   (130)
 | 
					#define T_FLOAT_NOT_EQUALS    (130)
 | 
				
			||||||
#define T_STR_NOT_EQUALS      (131)
 | 
					#define T_STR_DOUBLE_EQUALS   (131)
 | 
				
			||||||
#define T_EQUALS_DOT          (132)
 | 
					#define T_STR_NOT_EQUALS      (132)
 | 
				
			||||||
#define T_EQUALS_LIST         (133)
 | 
					#define T_EQUALS_DOT          (133)
 | 
				
			||||||
#define T_INDEX_LIST          (134)
 | 
					#define T_EQUALS_LIST         (134)
 | 
				
			||||||
 | 
					#define T_INDEX_LIST          (135)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define T_OP_RESIZE           (140)
 | 
					#define T_OP_RESIZE           (140)
 | 
				
			||||||
#define T_OP_ADD              (141)
 | 
					#define T_OP_ADD              (141)
 | 
				
			||||||
| 
						 | 
					@ -664,6 +666,7 @@ uint8_t TokenLookupPrecedence(uint8_t t) {
 | 
				
			||||||
	if (t == T_ASTERISK)        return 60;
 | 
						if (t == T_ASTERISK)        return 60;
 | 
				
			||||||
	if (t == T_SLASH)           return 60;
 | 
						if (t == T_SLASH)           return 60;
 | 
				
			||||||
	if (t == T_LOGICAL_NOT)     return 70;
 | 
						if (t == T_LOGICAL_NOT)     return 70;
 | 
				
			||||||
 | 
						if (t == T_NEGATE)          return 70;
 | 
				
			||||||
	if (t == T_DOT)             return 80;
 | 
						if (t == T_DOT)             return 80;
 | 
				
			||||||
	if (t == T_COLON)           return 80;
 | 
						if (t == T_COLON)           return 80;
 | 
				
			||||||
	if (t == T_AWAIT)           return 90;
 | 
						if (t == T_AWAIT)           return 90;
 | 
				
			||||||
| 
						 | 
					@ -1032,9 +1035,9 @@ Node *ParseExpression(Tokenizer *tokenizer, bool allowAssignment, uint8_t preced
 | 
				
			||||||
	} else if (node->token.type == T_NUMERIC_LITERAL
 | 
						} else if (node->token.type == T_NUMERIC_LITERAL
 | 
				
			||||||
			|| node->token.type == T_TRUE || node->token.type == T_FALSE || node->token.type == T_NULL) {
 | 
								|| node->token.type == T_TRUE || node->token.type == T_FALSE || node->token.type == T_NULL) {
 | 
				
			||||||
		node->type = node->token.type;
 | 
							node->type = node->token.type;
 | 
				
			||||||
	} else if (node->token.type == T_LOGICAL_NOT) {
 | 
						} else if (node->token.type == T_LOGICAL_NOT || node->token.type == T_MINUS) {
 | 
				
			||||||
		node->type = node->token.type;
 | 
							node->type = node->token.type == T_MINUS ? T_NEGATE : T_LOGICAL_NOT;
 | 
				
			||||||
		node->firstChild = ParseExpression(tokenizer, false, TokenLookupPrecedence(node->token.type));
 | 
							node->firstChild = ParseExpression(tokenizer, false, TokenLookupPrecedence(node->type));
 | 
				
			||||||
	} else if (node->token.type == T_LEFT_ROUND) {
 | 
						} else if (node->token.type == T_LEFT_ROUND) {
 | 
				
			||||||
		node = ParseExpression(tokenizer, false, 0);
 | 
							node = ParseExpression(tokenizer, false, 0);
 | 
				
			||||||
		if (!node) return NULL;
 | 
							if (!node) return NULL;
 | 
				
			||||||
| 
						 | 
					@ -1086,7 +1089,7 @@ Node *ParseExpression(Tokenizer *tokenizer, bool allowAssignment, uint8_t preced
 | 
				
			||||||
		node->firstChild = ParseExpression(tokenizer, false, TokenLookupPrecedence(node->token.type));
 | 
							node->firstChild = ParseExpression(tokenizer, false, TokenLookupPrecedence(node->token.type));
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		PrintError2(tokenizer, node, "Expected an expression. "
 | 
							PrintError2(tokenizer, node, "Expected an expression. "
 | 
				
			||||||
				"Expressions can start with a variable identifier, a string literal, a number, 'len', 'new', '!', '[' or '('.\n");
 | 
									"Expressions can start with a variable identifier, a string literal, a number, 'await', 'new', '-', '!', '[' or '('.\n");
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1846,7 +1849,7 @@ bool ASTSetScopes(Tokenizer *tokenizer, ExecutionContext *context, Node *node, S
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->type != T_STRUCT) {
 | 
						{
 | 
				
			||||||
		child = node->firstChild;
 | 
							child = node->firstChild;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		while (child) {
 | 
							while (child) {
 | 
				
			||||||
| 
						 | 
					@ -2143,8 +2146,9 @@ bool ASTSetTypes(Tokenizer *tokenizer, Node *node) {
 | 
				
			||||||
					&& !ASTMatching(node->firstChild->expressionType, &globalExpressionTypeFloat)
 | 
										&& !ASTMatching(node->firstChild->expressionType, &globalExpressionTypeFloat)
 | 
				
			||||||
					&& !ASTMatching(node->firstChild->expressionType, &globalExpressionTypeStr)
 | 
										&& !ASTMatching(node->firstChild->expressionType, &globalExpressionTypeStr)
 | 
				
			||||||
					&& !ASTMatching(node->firstChild->expressionType, &globalExpressionTypeBool)
 | 
										&& !ASTMatching(node->firstChild->expressionType, &globalExpressionTypeBool)
 | 
				
			||||||
					&& (!node->firstChild->expressionType || node->firstChild->expressionType->type != T_LIST)) {
 | 
										&& (!node->firstChild->expressionType || node->firstChild->expressionType->type != T_LIST)
 | 
				
			||||||
				PrintError2(tokenizer, node, "This operator expects either integers, floats, strings or booleans.\n");
 | 
										&& (!node->firstChild->expressionType || node->firstChild->expressionType->type != T_STRUCT)) {
 | 
				
			||||||
 | 
									PrintError2(tokenizer, node, "These types cannot be compared.\n");
 | 
				
			||||||
				return false;
 | 
									return false;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
| 
						 | 
					@ -2439,6 +2443,14 @@ bool ASTSetTypes(Tokenizer *tokenizer, Node *node) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		node->expressionType = &globalExpressionTypeBool;
 | 
							node->expressionType = &globalExpressionTypeBool;
 | 
				
			||||||
 | 
						} else if (node->type == T_NEGATE) {
 | 
				
			||||||
 | 
							if (!ASTMatching(node->firstChild->expressionType, &globalExpressionTypeInt)
 | 
				
			||||||
 | 
									&& !ASTMatching(node->firstChild->expressionType, &globalExpressionTypeFloat)) {
 | 
				
			||||||
 | 
								PrintError2(tokenizer, node, "Expected a int or float for the unary negate '-' operator.\n");
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							node->expressionType = node->firstChild->expressionType;
 | 
				
			||||||
	} else if (node->type == T_LIST_LITERAL) {
 | 
						} else if (node->type == T_LIST_LITERAL) {
 | 
				
			||||||
		if (!node->firstChild) {
 | 
							if (!node->firstChild) {
 | 
				
			||||||
			// TODO Support empty list literals?
 | 
								// TODO Support empty list literals?
 | 
				
			||||||
| 
						 | 
					@ -2908,7 +2920,7 @@ bool FunctionBuilderRecurse(Tokenizer *tokenizer, Node *node, FunctionBuilder *b
 | 
				
			||||||
	} else if (node->type == T_ASSERT || node->type == T_NULL || node->type == T_LOGICAL_NOT || node->type == T_AWAIT) {
 | 
						} else if (node->type == T_ASSERT || node->type == T_NULL || node->type == T_LOGICAL_NOT || node->type == T_AWAIT) {
 | 
				
			||||||
		FunctionBuilderAddLineNumber(builder, node);
 | 
							FunctionBuilderAddLineNumber(builder, node);
 | 
				
			||||||
		FunctionBuilderAppend(builder, &node->type, sizeof(node->type));
 | 
							FunctionBuilderAppend(builder, &node->type, sizeof(node->type));
 | 
				
			||||||
	} else if (node->type == T_ADD || node->type == T_MINUS || node->type == T_ASTERISK || node->type == T_SLASH) {
 | 
						} else if (node->type == T_ADD || node->type == T_MINUS || node->type == T_ASTERISK || node->type == T_SLASH || node->type == T_NEGATE) {
 | 
				
			||||||
		uint8_t b = node->expressionType->type == T_FLOAT ? node->type - T_ADD + T_FLOAT_ADD 
 | 
							uint8_t b = node->expressionType->type == T_FLOAT ? node->type - T_ADD + T_FLOAT_ADD 
 | 
				
			||||||
			: node->expressionType->type == T_STR ? T_CONCAT : node->type;
 | 
								: node->expressionType->type == T_STR ? T_CONCAT : node->type;
 | 
				
			||||||
		FunctionBuilderAddLineNumber(builder, node);
 | 
							FunctionBuilderAddLineNumber(builder, node);
 | 
				
			||||||
| 
						 | 
					@ -3710,6 +3722,9 @@ int ScriptExecuteFunction(uintptr_t instructionPointer, ExecutionContext *contex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			context->c->stack[context->c->stackPointer - 2].i = context->c->stack[context->c->stackPointer - 2].f / context->c->stack[context->c->stackPointer - 1].f;
 | 
								context->c->stack[context->c->stackPointer - 2].i = context->c->stack[context->c->stackPointer - 2].f / context->c->stack[context->c->stackPointer - 1].f;
 | 
				
			||||||
			context->c->stackPointer--;
 | 
								context->c->stackPointer--;
 | 
				
			||||||
 | 
							} else if (command == T_NEGATE) {
 | 
				
			||||||
 | 
								if (context->c->stackPointer < 1) return -1;
 | 
				
			||||||
 | 
								context->c->stack[context->c->stackPointer - 1].i = -context->c->stack[context->c->stackPointer - 1].i;
 | 
				
			||||||
		} else if (command == T_FLOAT_ADD) {
 | 
							} else if (command == T_FLOAT_ADD) {
 | 
				
			||||||
			if (context->c->stackPointer < 2) return -1;
 | 
								if (context->c->stackPointer < 2) return -1;
 | 
				
			||||||
			context->c->stack[context->c->stackPointer - 2].f = context->c->stack[context->c->stackPointer - 2].f + context->c->stack[context->c->stackPointer - 1].f;
 | 
								context->c->stack[context->c->stackPointer - 2].f = context->c->stack[context->c->stackPointer - 2].f + context->c->stack[context->c->stackPointer - 1].f;
 | 
				
			||||||
| 
						 | 
					@ -3726,6 +3741,9 @@ int ScriptExecuteFunction(uintptr_t instructionPointer, ExecutionContext *contex
 | 
				
			||||||
			if (context->c->stackPointer < 2) return -1;
 | 
								if (context->c->stackPointer < 2) return -1;
 | 
				
			||||||
			context->c->stack[context->c->stackPointer - 2].f = context->c->stack[context->c->stackPointer - 2].f / context->c->stack[context->c->stackPointer - 1].f;
 | 
								context->c->stack[context->c->stackPointer - 2].f = context->c->stack[context->c->stackPointer - 2].f / context->c->stack[context->c->stackPointer - 1].f;
 | 
				
			||||||
			context->c->stackPointer--;
 | 
								context->c->stackPointer--;
 | 
				
			||||||
 | 
							} else if (command == T_FLOAT_NEGATE) {
 | 
				
			||||||
 | 
								if (context->c->stackPointer < 1) return -1;
 | 
				
			||||||
 | 
								context->c->stack[context->c->stackPointer - 1].f = -context->c->stack[context->c->stackPointer - 1].f;
 | 
				
			||||||
		} else if (command == T_LESS_THAN) {
 | 
							} else if (command == T_LESS_THAN) {
 | 
				
			||||||
			if (context->c->stackPointer < 2) return -1;
 | 
								if (context->c->stackPointer < 2) return -1;
 | 
				
			||||||
			context->c->stack[context->c->stackPointer - 2].i = context->c->stack[context->c->stackPointer - 2].i < context->c->stack[context->c->stackPointer - 1].i;
 | 
								context->c->stack[context->c->stackPointer - 2].i = context->c->stack[context->c->stackPointer - 2].i < context->c->stack[context->c->stackPointer - 1].i;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue