init
This commit is contained in:
		
						commit
						b99855351d
					
				
					 434 changed files with 50357 additions and 0 deletions
				
			
		
							
								
								
									
										200
									
								
								addons/inkgd/runtime/static/ink_runtime.gd
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								addons/inkgd/runtime/static/ink_runtime.gd
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,200 @@ | |||
| # warning-ignore-all:unused_class_variable | ||||
| # warning-ignore-all:shadowed_variable | ||||
| # ############################################################################ # | ||||
| # Copyright © 2015-2021 inkle Ltd. | ||||
| # Copyright © 2019-2022 Frédéric Maquin <fred@ephread.com> | ||||
| # All Rights Reserved | ||||
| # | ||||
| # This file is part of inkgd. | ||||
| # inkgd is licensed under the terms of the MIT license. | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| extends Node | ||||
| 
 | ||||
| # Hiding this type to prevent registration of "private" nodes. | ||||
| # See https://github.com/godotengine/godot-proposals/issues/1047 | ||||
| # class_name InkRuntimeNode | ||||
| 
 | ||||
| # Expected to be added to the SceneTree as a singleton object. | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Imports | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| var InkStaticJSON := load("res://addons/inkgd/runtime/static/json.gd") as GDScript | ||||
| var InkStaticNativeFunctionCall := load("res://addons/inkgd/runtime/static/native_function_call.gd") as GDScript | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Signals | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| ## Emitted when the runtime encountered an exception. Exception are not | ||||
| ## recoverable and may corrupt the state. They are the consequence of either | ||||
| ## a programmer error or a bug in the runtime. | ||||
| signal exception_raised(message, stack_trace) | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Properties | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| # Skips saving global values that remain equal to the initial values that were | ||||
| # declared in Ink. | ||||
| var dont_save_default_values: bool = true | ||||
| 
 | ||||
| ## Uses `assert` instead of `push_error` to report critical errors, thus | ||||
| ## making them more explicit during development. | ||||
| var stop_execution_on_exception: bool = true | ||||
| 
 | ||||
| ## Uses `assert` instead of `push_error` to report story errors, thus | ||||
| ## making them more explicit during development. | ||||
| var stop_execution_on_error: bool = true | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| var should_pause_execution_on_runtime_error: bool: get = get_speore, set = set_speore | ||||
| func get_speore() -> bool: | ||||
| 	printerr( | ||||
| 			"'should_pause_execution_on_runtime_error' is deprecated, " + | ||||
| 			"use 'stop_execution_on_exception' instead." | ||||
| 	) | ||||
| 	return stop_execution_on_exception | ||||
| func set_speore(value: bool): | ||||
| 	printerr( | ||||
| 			"'should_pause_execution_on_runtime_error' is deprecated, " + | ||||
| 			"use 'stop_execution_on_exception' instead." | ||||
| 	) | ||||
| 	stop_execution_on_exception = value | ||||
| 
 | ||||
| var should_pause_execution_on_story_error: bool: get = get_speose, set = set_speose | ||||
| func get_speose() -> bool: | ||||
| 	printerr( | ||||
| 		"'should_pause_execution_on_story_error' is deprecated, " + | ||||
| 		"use 'stop_execution_on_error' instead." | ||||
| 	) | ||||
| 	return stop_execution_on_error | ||||
| func set_speose(value: bool): | ||||
| 	printerr( | ||||
| 		"'should_pause_execution_on_story_error' is deprecated, " + | ||||
| 		"use 'stop_execution_on_error' instead." | ||||
| 	) | ||||
| 	stop_execution_on_error = value | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # "Static" Properties | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| var native_function_call: InkStaticNativeFunctionCall = InkStaticNativeFunctionCall.new() | ||||
| var json: InkStaticJSON = InkStaticJSON.new(native_function_call) | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Internal Properties | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| # Recorded exceptions don't emit the 'exception' signal, since they are | ||||
| # expected to be processed by the story and emitted through 'on_error'. | ||||
| var record_story_exceptions: bool = false | ||||
| var current_story_exceptions: Array = [] | ||||
| 
 | ||||
| var _argument_exception_raised: bool | ||||
| var _exception_raised: bool | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Overrides | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| func _init(): | ||||
| 	name = "__InkRuntime" | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Internal Methods | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| func clear_raised_exceptions() -> bool: | ||||
| 	if _argument_exception_raised: | ||||
| 		_argument_exception_raised = false | ||||
| 		return true | ||||
| 
 | ||||
| 	if _argument_exception_raised: | ||||
| 		_argument_exception_raised = false | ||||
| 		return true | ||||
| 
 | ||||
| 	return false | ||||
| 
 | ||||
| 
 | ||||
| func handle_exception(message: String) -> void: | ||||
| 	var exception_message = "EXCEPTION: %s" % message | ||||
| 	var stack_trace = _get_stack_trace() | ||||
| 
 | ||||
| 	_handle_generic_exception( | ||||
| 			exception_message, | ||||
| 			stop_execution_on_exception, | ||||
| 			stack_trace | ||||
| 	) | ||||
| 
 | ||||
| 	_exception_raised | ||||
| 	emit_signal("exception_raised", exception_message, stack_trace) | ||||
| 
 | ||||
| func handle_argument_exception(message: String) -> void: | ||||
| 	var exception_message = "ARGUMENT EXCEPTION: %s" % message | ||||
| 	var stack_trace = _get_stack_trace() | ||||
| 
 | ||||
| 	_handle_generic_exception( | ||||
| 			exception_message, | ||||
| 			stop_execution_on_error, | ||||
| 			stack_trace | ||||
| 	) | ||||
| 
 | ||||
| 	_argument_exception_raised = true | ||||
| 	emit_signal("exception_raised", exception_message, stack_trace) | ||||
| 
 | ||||
| func handle_story_exception(message: String, use_end_line_number: bool, metadata) -> void: | ||||
| 	# When exceptions are "recorded", they are not reported immediately. | ||||
| 	# 'Story' will take care of that at the end of the step. | ||||
| 	if record_story_exceptions: | ||||
| 		current_story_exceptions.append(StoryError.new(message, use_end_line_number, metadata)) | ||||
| 	else: | ||||
| 		var exception_message = "STORY EXCEPTION: %s" % message | ||||
| 		var stack_trace = _get_stack_trace() | ||||
| 
 | ||||
| 		_handle_generic_exception(exception_message, stop_execution_on_error, stack_trace) | ||||
| 
 | ||||
| 		emit_signal("exception_raised", exception_message, stack_trace) | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Private Methods | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| func _handle_generic_exception( | ||||
| 		message: String, | ||||
| 		should_pause_execution: bool, | ||||
| 		stack_trace: PackedStringArray | ||||
| ) -> void: | ||||
| 	if OS.is_debug_build(): | ||||
| 		if should_pause_execution: | ||||
| 			assert(false, message) | ||||
| 		elif Engine.is_editor_hint(): | ||||
| 			printerr(message) | ||||
| 			if stack_trace.size() > 0: | ||||
| 				printerr("Stack trace:") | ||||
| 				for line in stack_trace: | ||||
| 					printerr(line) | ||||
| 		else: | ||||
| 			push_error(message) | ||||
| 
 | ||||
| func _get_stack_trace() -> PackedStringArray: | ||||
| 	var trace := PackedStringArray() | ||||
| 
 | ||||
| 	var i = 1 | ||||
| 	for stack_element in get_stack(): | ||||
| 		if i <= 3: | ||||
| 			i += 1 | ||||
| 			continue | ||||
| 
 | ||||
| 		trace.append(str( | ||||
| 				"    ", (i - 3), " - ", stack_element["source"], ":", | ||||
| 				stack_element["line"], " - at function: ", stack_element["function"] | ||||
| 		)) | ||||
| 
 | ||||
| 		i += 1 | ||||
| 
 | ||||
| 	return trace | ||||
							
								
								
									
										623
									
								
								addons/inkgd/runtime/static/json.gd
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										623
									
								
								addons/inkgd/runtime/static/json.gd
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,623 @@ | |||
| # ############################################################################ # | ||||
| # Copyright © 2015-2021 inkle Ltd. | ||||
| # Copyright © 2019-2022 Frédéric Maquin <fred@ephread.com> | ||||
| # All Rights Reserved | ||||
| # | ||||
| # This file is part of inkgd. | ||||
| # inkgd is licensed under the terms of the MIT license. | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| extends InkBase | ||||
| 
 | ||||
| class_name InkStaticJSON | ||||
| 
 | ||||
| # In the C# code this class has only static methods. In the GDScript, it will rather | ||||
| # be a unique object, added to the InkRuntime singleton. | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| var InkValue = load("res://addons/inkgd/runtime/values/value.gd") | ||||
| var InkStringValue = load("res://addons/inkgd/runtime/values/string_value.gd") | ||||
| var InkDivertTargetValue = load("res://addons/inkgd/runtime/values/divert_target_value.gd") | ||||
| var InkVariablePointerValue = load("res://addons/inkgd/runtime/values/variable_pointer_value.gd") | ||||
| var InkListValue = load("res://addons/inkgd/runtime/values/list_value.gd") | ||||
| 
 | ||||
| var InkList = load("res://addons/inkgd/runtime/lists/ink_list.gd") | ||||
| var InkListDefinition = load("res://addons/inkgd/runtime/lists/list_definition.gd") | ||||
| var InkListDefinitionsOrigin = load("res://addons/inkgd/runtime/lists/list_definitions_origin.gd") | ||||
| 
 | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| # (Array<Variant>, bool) -> Array | ||||
| func jarray_to_runtime_obj_list(jarray: Array, skip_last = false) -> Array: | ||||
| 	var count = jarray.size() | ||||
| 	if skip_last: | ||||
| 		count -= 1 | ||||
| 
 | ||||
| 	var list = [] | ||||
| 	var i = 0 | ||||
| 	while (i < count): | ||||
| 		var jtok = jarray[i] | ||||
| 		var runtime_obj = jtoken_to_runtime_object(jtok) | ||||
| 		list.append(runtime_obj) | ||||
| 
 | ||||
| 		i += 1 | ||||
| 
 | ||||
| 	return list | ||||
| 
 | ||||
| # (self.Json.Writer, Dictionary<String, InkObject>) -> void | ||||
| func write_dictionary_runtime_objs(writer, dictionary: Dictionary) -> void: | ||||
| 	writer.write_object_start() | ||||
| 	for key in dictionary: | ||||
| 		writer.write_property_start(key) | ||||
| 		write_runtime_object(writer, dictionary[key]) | ||||
| 		writer.write_property_end() | ||||
| 	writer.write_object_end() | ||||
| 
 | ||||
| # (self.Json.Writer, Array<InkObject>) -> void | ||||
| func write_list_runtime_objs(writer, list: Array) -> void: | ||||
| 	writer.write_array_start() | ||||
| 	for val in list: | ||||
| 		write_runtime_object(writer, val) | ||||
| 	writer.write_array_end() | ||||
| 
 | ||||
| # (self.Json.Writer, Array<Int>) -> void | ||||
| func write_int_dictionary(writer, dict: Dictionary) -> void: | ||||
| 	writer.write_object_start() | ||||
| 	for key in dict: | ||||
| 		writer.write_property(key, dict[key]) | ||||
| 	writer.write_object_end() | ||||
| 
 | ||||
| # (self.Json.Writer, InkObject) -> void | ||||
| func write_runtime_object(writer, obj: InkObject) -> void: | ||||
| 	var container = InkUtils.as_or_null(obj, "InkContainer") | ||||
| 	if container: | ||||
| 		write_runtime_container(writer, container) | ||||
| 		return | ||||
| 
 | ||||
| 	var divert = InkUtils.as_or_null(obj, "Divert") | ||||
| 	if divert: | ||||
| 		var div_type_key = "->" # String | ||||
| 		if divert.is_external: | ||||
| 			div_type_key = "x()" | ||||
| 		elif divert.pushes_to_stack: | ||||
| 			if divert.stack_push_type == Ink.PushPopType.FUNCTION: | ||||
| 				div_type_key = "f()" | ||||
| 			elif divert.stackPushType == Ink.PushPopType.TUNNEL: | ||||
| 				div_type_key = "->t->" | ||||
| 
 | ||||
| 		var target_str = null # String | ||||
| 		if divert.has_variable_target: | ||||
| 			target_str = divert.variable_divert_name | ||||
| 		else: | ||||
| 			target_str = divert.target_path_string | ||||
| 
 | ||||
| 		writer.write_object_start() | ||||
| 
 | ||||
| 		writer.write_property(div_type_key, target_str) | ||||
| 
 | ||||
| 		if divert.has_variable_target: | ||||
| 			writer.write_property("var", true) | ||||
| 
 | ||||
| 		if divert.is_conditional: | ||||
| 			writer.write_property("c", true) | ||||
| 
 | ||||
| 		if divert.external_args > 0: | ||||
| 			writer.write_property("exArgs", divert.external_args) | ||||
| 
 | ||||
| 		writer.write_object_end() | ||||
| 		return | ||||
| 
 | ||||
| 	var choice_point = InkUtils.as_or_null(obj, "ChoicePoint") | ||||
| 	if choice_point: | ||||
| 		writer.write_object_start() | ||||
| 		writer.write_property("*", choice_point.path_string_on_choice) | ||||
| 		writer.write_property("flg", choice_point.flags) | ||||
| 		writer.write_object_end() | ||||
| 		return | ||||
| 
 | ||||
| 	var bool_val = InkUtils.as_or_null(obj, "BoolValue") | ||||
| 	if bool_val: | ||||
| 		writer.write(bool_val.value) | ||||
| 		return | ||||
| 
 | ||||
| 	var int_val = InkUtils.as_or_null(obj, "IntValue") | ||||
| 	if int_val: | ||||
| 		writer.write(int_val.value) | ||||
| 		return | ||||
| 
 | ||||
| 	var float_val = InkUtils.as_or_null(obj, "FloatValue") | ||||
| 	if float_val: | ||||
| 		writer.write(float_val.value) | ||||
| 		return | ||||
| 
 | ||||
| 	var str_val = InkUtils.as_or_null(obj, "StringValue") | ||||
| 	if str_val: | ||||
| 		if str_val.is_newline: | ||||
| 			writer.write_string("\\n", false) | ||||
| 		else: | ||||
| 			writer.write_string_start() | ||||
| 			writer.write_string_inner("^") | ||||
| 			writer.write_string_inner(str_val.value) | ||||
| 			writer.write_string_end() | ||||
| 		return | ||||
| 
 | ||||
| 	var list_val = InkUtils.as_or_null(obj, "ListValue") | ||||
| 	if list_val: | ||||
| 		write_ink_list(writer, list_val) | ||||
| 		return | ||||
| 
 | ||||
| 	var div_target_val = InkUtils.as_or_null(obj, "DivertTargetValue") | ||||
| 	if div_target_val: | ||||
| 		writer.write_object_start() | ||||
| 		writer.write_property("^->", div_target_val.value.components_string) | ||||
| 		writer.write_object_end() | ||||
| 		return | ||||
| 
 | ||||
| 	var var_ptr_val = InkUtils.as_or_null(obj, "VariablePointerValue") | ||||
| 	if var_ptr_val: | ||||
| 		writer.write_object_start() | ||||
| 		writer.write_property("^var", var_ptr_val.value) | ||||
| 		writer.write_property("ci", var_ptr_val.context_index) | ||||
| 		writer.write_object_end() | ||||
| 		return | ||||
| 
 | ||||
| 	var glue = InkUtils.as_or_null(obj, "Glue") | ||||
| 	if glue: | ||||
| 		writer.write("<>") | ||||
| 		return | ||||
| 
 | ||||
| 	var control_cmd = InkUtils.as_or_null(obj, "ControlCommand") | ||||
| 	if control_cmd: | ||||
| 		writer.write(self._control_command_names[control_cmd.command_type]) | ||||
| 		return | ||||
| 
 | ||||
| 	var native_func = InkUtils.as_or_null(obj, "NativeFunctionCall") | ||||
| 	if native_func: | ||||
| 		var name = native_func.name | ||||
| 
 | ||||
| 		if name == "^": name = "L^" | ||||
| 
 | ||||
| 		writer.write(name) | ||||
| 		return | ||||
| 
 | ||||
| 	var var_ref = InkUtils.as_or_null(obj, "VariableReference") | ||||
| 	if var_ref: | ||||
| 		writer.write_object_start() | ||||
| 
 | ||||
| 		var read_count_path = var_ref.path_string_for_count | ||||
| 		if read_count_path != null: | ||||
| 			writer.write_property(["CNT?"], read_count_path) | ||||
| 		else: | ||||
| 			writer.write_property(["VAR?"], var_ref.name) | ||||
| 
 | ||||
| 		writer.write_object_end() | ||||
| 		return | ||||
| 
 | ||||
| 	var var_ass = InkUtils.as_or_null(obj, "VariableAssignment") | ||||
| 	if var_ass: | ||||
| 		writer.write_object_start() | ||||
| 
 | ||||
| 		var key = "VAR=" if var_ass.is_global else "temp=" | ||||
| 		writer.write_property(key, var_ass.variable_name) | ||||
| 
 | ||||
| 		if !var_ass.is_new_declaration: | ||||
| 			writer.write_property("re", true) | ||||
| 
 | ||||
| 		writer.write_object_end() | ||||
| 
 | ||||
| 		return | ||||
| 
 | ||||
| 	var void_obj = InkUtils.as_or_null(obj, "Void") | ||||
| 	if void_obj: | ||||
| 		writer.write("void") | ||||
| 		return | ||||
| 
 | ||||
| 	# Legacy Tags (replaced in 1.1+) | ||||
| 	var tag = InkUtils.as_or_null(obj, "Tag") | ||||
| 	if tag: | ||||
| 		writer.write_object_start() | ||||
| 		writer.write_property("#", tag.text) | ||||
| 		writer.write_object_end() | ||||
| 		return | ||||
| 
 | ||||
| 	var choice = InkUtils.as_or_null(obj, "Choice") | ||||
| 	if choice: | ||||
| 		write_choice(writer, choice) | ||||
| 		return | ||||
| 
 | ||||
| 	InkUtils.throw_exception("Failed to convert runtime object to Json token: %s" % obj) | ||||
| 	return | ||||
| 
 | ||||
| # (Dictionary<String, Variant>) -> Dictionary<String, InkObject> | ||||
| func jobject_to_dictionary_runtime_objs(jobject: Dictionary) -> Dictionary: | ||||
| 	var dict = {} | ||||
| 
 | ||||
| 	for key in jobject: | ||||
| 		dict[key] = jtoken_to_runtime_object(jobject[key]) | ||||
| 
 | ||||
| 	return dict | ||||
| 
 | ||||
| # (Dictionary<String, Variant>) -> Dictionary<String, int> | ||||
| func jobject_to_int_dictionary(jobject: Dictionary) -> Dictionary: | ||||
| 	var dict = {} | ||||
| 	for key in jobject: | ||||
| 		dict[key] = int(jobject[key]) | ||||
| 
 | ||||
| 	return dict | ||||
| 
 | ||||
| # (Variant) -> InkObject | ||||
| func jtoken_to_runtime_object(token) -> InkObject: | ||||
| 
 | ||||
| 	if token is int || token is float || token is bool: | ||||
| 		return InkValue.create(token) | ||||
| 
 | ||||
| 	if token is String: | ||||
| 		var _str = token | ||||
| 
 | ||||
| 		var first_char = _str[0] | ||||
| 		if first_char == "^": | ||||
| 			return InkStringValue.new_with(_str.substr(1, _str.length() - 1)) | ||||
| 		elif first_char == "\n" && _str.length() == 1: | ||||
| 			return InkStringValue.new_with("\n") | ||||
| 
 | ||||
| 		if _str == "<>": return InkGlue.new() | ||||
| 
 | ||||
| 		var i = 0 | ||||
| 		while (i < _control_command_names.size()): | ||||
| 			var cmd_name = _control_command_names[i] | ||||
| 			if _str == cmd_name: | ||||
| 				return InkControlCommand.new(i) | ||||
| 			i += 1 | ||||
| 
 | ||||
| 		if _str == "L^": _str = "^" | ||||
| 		if _static_native_function_call.call_exists_with_name(_str): | ||||
| 			return InkNativeFunctionCall.call_with_name(_str, _static_native_function_call) | ||||
| 
 | ||||
| 		if _str == "->->": | ||||
| 			return InkControlCommand.pop_tunnel() | ||||
| 		elif _str == "~ret": | ||||
| 			return InkControlCommand.pop_function() | ||||
| 
 | ||||
| 		if _str == "void": | ||||
| 			return InkVoid.new() | ||||
| 
 | ||||
| 	if token is Dictionary: | ||||
| 		var obj = token | ||||
| 		var prop_value | ||||
| 
 | ||||
| 		if obj.has("^->"): | ||||
| 			prop_value = obj["^->"] | ||||
| 			return InkDivertTargetValue.new_with( | ||||
| 					InkPath.new_with_components_string(str(prop_value)) | ||||
| 			) | ||||
| 
 | ||||
| 		if obj.has("^var"): | ||||
| 			prop_value = obj["^var"] | ||||
| 			var var_ptr = InkVariablePointerValue.new_with_context(str(prop_value)) | ||||
| 			if (obj.has("ci")): | ||||
| 				prop_value = obj["ci"] | ||||
| 				var_ptr.context_index = int(prop_value) | ||||
| 			return var_ptr | ||||
| 
 | ||||
| 		var is_divert = false | ||||
| 		var pushes_to_stack = false | ||||
| 		var div_push_type = Ink.PushPopType.FUNCTION | ||||
| 		var external = false | ||||
| 
 | ||||
| 		if obj.has("->"): | ||||
| 			prop_value = obj["->"] | ||||
| 			is_divert = true | ||||
| 		elif obj.has("f()"): | ||||
| 			prop_value = obj["f()"] | ||||
| 			is_divert = true | ||||
| 			pushes_to_stack = true | ||||
| 			div_push_type = Ink.PushPopType.FUNCTION | ||||
| 		elif obj.has("->t->"): | ||||
| 			prop_value = obj["->t->"] | ||||
| 			is_divert = true | ||||
| 			pushes_to_stack = true | ||||
| 			div_push_type = Ink.PushPopType.TUNNEL | ||||
| 		elif obj.has("x()"): | ||||
| 			prop_value = obj["x()"] | ||||
| 			is_divert = true | ||||
| 			external = true | ||||
| 			pushes_to_stack = false | ||||
| 			div_push_type = Ink.PushPopType.FUNCTION | ||||
| 
 | ||||
| 		if is_divert: | ||||
| 			var divert = InkDivert.new() | ||||
| 			divert.pushes_to_stack = pushes_to_stack | ||||
| 			divert.stack_push_type = div_push_type | ||||
| 			divert.is_external = external | ||||
| 
 | ||||
| 			var target = str(prop_value) | ||||
| 
 | ||||
| 			if obj.has("var"): | ||||
| 				prop_value = obj["var"] | ||||
| 				divert.variable_divert_name = target | ||||
| 			else: | ||||
| 				divert.target_path_string = target | ||||
| 
 | ||||
| 			divert.is_conditional = obj.has("c") | ||||
| 			#if divert.is_conditional: prop_value = obj["c"] | ||||
| 
 | ||||
| 			if external: | ||||
| 				if obj.has("exArgs"): | ||||
| 					prop_value = obj["exArgs"] | ||||
| 					divert.external_args = int(prop_value) | ||||
| 
 | ||||
| 			return divert | ||||
| 
 | ||||
| 		if obj.has("*"): | ||||
| 			prop_value = obj["*"] | ||||
| 			var choice = InkChoicePoint.new() | ||||
| 			choice.path_string_on_choice = str(prop_value) | ||||
| 
 | ||||
| 			if obj.has("flg"): | ||||
| 				prop_value = obj["flg"] | ||||
| 				choice.flags = int(prop_value) | ||||
| 
 | ||||
| 			return choice | ||||
| 
 | ||||
| 		if obj.has("VAR?"): | ||||
| 			prop_value = obj["VAR?"] | ||||
| 			return InkVariableReference.new(str(prop_value)) | ||||
| 		elif obj.has("CNT?"): | ||||
| 			prop_value = obj["CNT?"] | ||||
| 			var read_count_var_ref = InkVariableReference.new() | ||||
| 			read_count_var_ref.path_string_for_count = str(prop_value) | ||||
| 			return read_count_var_ref | ||||
| 
 | ||||
| 		var is_var_ass = false | ||||
| 		var is_global_var = false | ||||
| 		if obj.has("VAR="): | ||||
| 			prop_value = obj["VAR="] | ||||
| 			is_var_ass = true | ||||
| 			is_global_var = true | ||||
| 		elif obj.has("temp="): | ||||
| 			prop_value = obj["temp="] | ||||
| 			is_var_ass = true | ||||
| 			is_global_var = false | ||||
| 
 | ||||
| 		if is_var_ass: | ||||
| 			var var_name = str(prop_value) | ||||
| 			var is_new_decl = !obj.has("re") | ||||
| 			var var_ass = InkVariableAssignment.new_with(var_name, is_new_decl) | ||||
| 			var_ass.is_global = is_global_var | ||||
| 			return var_ass | ||||
| 
 | ||||
| 		# Legacy Tags with texts (replaced in 1.1+) | ||||
| 		if obj.has("#"): | ||||
| 			prop_value = obj["#"] | ||||
| 			return InkTag.new(str(prop_value)) | ||||
| 
 | ||||
| 		if obj.has("list"): | ||||
| 			prop_value = obj["list"] | ||||
| 			var list_content = prop_value | ||||
| 			var raw_list = InkList.new() | ||||
| 			if obj.has("origins"): | ||||
| 				prop_value = obj["origins"] | ||||
| 				var names_as_objs = prop_value | ||||
| 				raw_list.set_initial_origin_names(names_as_objs) | ||||
| 
 | ||||
| 			for name_to_val_key in list_content: | ||||
| 				var item = InkListItem.new_with_full_name(name_to_val_key) | ||||
| 				var val = list_content[name_to_val_key] | ||||
| 				raw_list.set_item(item, val) | ||||
| 
 | ||||
| 			return InkListValue.new_with(raw_list) | ||||
| 
 | ||||
| 		if obj.has("originalChoicePath"): | ||||
| 			return jobject_to_choice(obj) | ||||
| 
 | ||||
| 	if token is Array: | ||||
| 		var container = jarray_to_container(token) | ||||
| 		return container | ||||
| 
 | ||||
| 	if token == null: | ||||
| 		return null | ||||
| 
 | ||||
| 	InkUtils.throw_exception("Failed to convert token to runtime object: %s" % str(token)) | ||||
| 	return null | ||||
| 
 | ||||
| # (self.Json.Writer, InkContainer, Bool) -> void | ||||
| func write_runtime_container(writer, container: InkContainer, without_name = false) -> void: | ||||
| 	writer.write_array_start() | ||||
| 
 | ||||
| 	for c in container.content: | ||||
| 		write_runtime_object(writer, c) | ||||
| 
 | ||||
| 	var named_only_content = container.named_only_content | ||||
| 	var count_flags = container.count_flags | ||||
| 	var has_name_property = (container.name != null) && !without_name | ||||
| 
 | ||||
| 	var has_terminator = named_only_content != null || count_flags > 0 || has_name_property | ||||
| 
 | ||||
| 	if has_terminator: | ||||
| 		writer.write_object_start() | ||||
| 
 | ||||
| 	if named_only_content != null: | ||||
| 		for named_content_key in named_only_content: | ||||
| 			var name = named_content_key | ||||
| 			var named_container = InkUtils.as_or_null(named_only_content[named_content_key], "InkContainer") | ||||
| 			writer.write_property_start(name) | ||||
| 			write_runtime_container(writer, named_container, true) | ||||
| 			writer.write_property_end() | ||||
| 
 | ||||
| 	if count_flags > 0: | ||||
| 		writer.write_property("#f", count_flags) | ||||
| 
 | ||||
| 	if has_name_property: | ||||
| 		writer.write_property("#n", container.name) | ||||
| 
 | ||||
| 	if has_terminator: | ||||
| 		writer.write_object_end() | ||||
| 	else: | ||||
| 		writer.write_null() | ||||
| 
 | ||||
| 	writer.write_array_end() | ||||
| 
 | ||||
| # (Array<Variant>) -> InkContainer | ||||
| func jarray_to_container(jarray: Array) -> InkContainer: | ||||
| 	var container = InkContainer.new() | ||||
| 	container.content = jarray_to_runtime_obj_list(jarray, true) | ||||
| 
 | ||||
| 	var terminating_obj = InkUtils.as_or_null(jarray.back(), "Dictionary") # Dictionary<string, Variant> | ||||
| 	if terminating_obj != null: | ||||
| 		var named_only_content = {} # new Dictionary<String, InkObject> | ||||
| 
 | ||||
| 		for key in terminating_obj: | ||||
| 			if key == "#f": | ||||
| 				container.count_flags = int(terminating_obj[key]) | ||||
| 			elif key == "#n": | ||||
| 				container.name = str(terminating_obj[key]) | ||||
| 			else: | ||||
| 				var named_content_item = jtoken_to_runtime_object(terminating_obj[key]) | ||||
| 				var named_sub_container = InkUtils.as_or_null(named_content_item, "InkContainer") | ||||
| 				if named_sub_container: | ||||
| 					named_sub_container.name = key | ||||
| 				named_only_content[key] = named_content_item | ||||
| 
 | ||||
| 		container.named_only_content = named_only_content | ||||
| 
 | ||||
| 	return container | ||||
| 
 | ||||
| # (Dictionary<String, Variant>) -> Choice | ||||
| func jobject_to_choice(jobj: Dictionary) -> InkChoice: | ||||
| 	var choice = InkChoice.new() | ||||
| 	choice.text = str(jobj["text"]) | ||||
| 	choice.index = int(jobj["index"]) | ||||
| 	choice.source_path = str(jobj["originalChoicePath"]) | ||||
| 	choice.original_thread_index = int(jobj["originalThreadIndex"]) | ||||
| 	choice.path_string_on_choice = str(jobj["targetPath"]) | ||||
| 	return choice | ||||
| 
 | ||||
| # (self.Json.Writer, Choice) -> Void | ||||
| func write_choice(writer, choice: InkChoice) -> void: | ||||
| 	writer.write_object_start() | ||||
| 	writer.write_property("text", choice.text) | ||||
| 	writer.write_property("index", choice.index) | ||||
| 	writer.write_property("originalChoicePath", choice.source_path) | ||||
| 	writer.write_property("originalThreadIndex", choice.original_thread_index) | ||||
| 	writer.write_property("targetPath", choice.path_string_on_choice) | ||||
| 	writer.write_object_end() | ||||
| 
 | ||||
| # (self.Json.Writer, ListValue) -> Void | ||||
| func write_ink_list(writer, list_val): | ||||
| 	var raw_list = list_val.value | ||||
| 
 | ||||
| 	writer.write_object_start() | ||||
| 
 | ||||
| 	writer.write_property_start("list") | ||||
| 
 | ||||
| 	writer.write_object_start() | ||||
| 
 | ||||
| 	for item_key in raw_list.raw_keys(): | ||||
| 		var item = InkListItem.from_serialized_key(item_key) | ||||
| 		var item_val = raw_list.get_raw(item_key) | ||||
| 
 | ||||
| 		writer.write_property_name_start() | ||||
| 		writer.write_property_name_inner(item.origin_name if item.origin_name else "?") | ||||
| 		writer.write_property_name_inner(".") | ||||
| 		writer.write_property_name_inner(item.item_name) | ||||
| 		writer.write_property_name_end() | ||||
| 
 | ||||
| 		writer.write(item_val) | ||||
| 
 | ||||
| 		writer.write_property_end() | ||||
| 
 | ||||
| 	writer.write_object_end() | ||||
| 
 | ||||
| 	writer.write_property_end() | ||||
| 
 | ||||
| 	if raw_list.size() == 0 && raw_list.origin_names != null && raw_list.origin_names.size() > 0: | ||||
| 		writer.write_property_start("origins") | ||||
| 		writer.write_array_start() | ||||
| 		for name in raw_list.origin_names: | ||||
| 			writer.write(name) | ||||
| 		writer.write_array_end() | ||||
| 		writer.write_property_end() | ||||
| 
 | ||||
| 	writer.write_object_end() | ||||
| 
 | ||||
| # (ListDefinitionsOrigin) -> Dictionary<String, Variant> | ||||
| func list_definitions_to_jtoken (origin): | ||||
| 	var result = {} # Dictionary<String, Variant> | ||||
| 	for def in origin.lists: | ||||
| 		var list_def_json = {} # Dictionary<String, Variant> | ||||
| 		for item_to_val_key in def.items: | ||||
| 			var item = InkListItem.from_serialized_key(item_to_val_key) | ||||
| 			var val = def.items[item_to_val_key] | ||||
| 			list_def_json[item.item_name] = val | ||||
| 
 | ||||
| 		result[def.name] = list_def_json | ||||
| 
 | ||||
| 	return result | ||||
| 
 | ||||
| # (Variant) -> ListDefinitionsOrigin | ||||
| func jtoken_to_list_definitions(obj): | ||||
| 	var defs_obj = obj | ||||
| 
 | ||||
| 	var all_defs = [] # Array<ListDefinition> | ||||
| 
 | ||||
| 	for k in defs_obj: | ||||
| 		var name = str(k) # String | ||||
| 		var list_def_json = defs_obj[k] # Dictionary<String, Variant> | ||||
| 
 | ||||
| 
 | ||||
| 		var items = {} # Dictionary<String, int> | ||||
| 		for name_value_key in list_def_json: | ||||
| 			items[name_value_key] = int(list_def_json[name_value_key]) | ||||
| 
 | ||||
| 		var def = InkListDefinition.new(name, items) | ||||
| 		all_defs.append(def) | ||||
| 
 | ||||
| 	return InkListDefinitionsOrigin.new(all_defs) | ||||
| 
 | ||||
| func _init(native_function_call): | ||||
| 	_static_native_function_call = native_function_call | ||||
| 
 | ||||
| 	_control_command_names = [] | ||||
| 
 | ||||
| 	_control_command_names.append("ev")        # EVAL_START | ||||
| 	_control_command_names.append("out")       # EVAL_OUTPUT | ||||
| 	_control_command_names.append("/ev")       # EVAL_END | ||||
| 	_control_command_names.append("du")        # DUPLICATE | ||||
| 	_control_command_names.append("pop")       # POP_EVALUATED_VALUE | ||||
| 	_control_command_names.append("~ret")      # POP_FUNCTION | ||||
| 	_control_command_names.append("->->")      # POP_TUNNEL | ||||
| 	_control_command_names.append("str")       # BEGIN_STRING | ||||
| 	_control_command_names.append("/str")      # END_STRING | ||||
| 	_control_command_names.append("nop")       # NO_OP | ||||
| 	_control_command_names.append("choiceCnt") # CHOICE_COUNT | ||||
| 	_control_command_names.append("turn")      # TURNS | ||||
| 	_control_command_names.append("turns")     # TURNS_SINCE | ||||
| 	_control_command_names.append("readc")     # READ_COUNT | ||||
| 	_control_command_names.append("rnd")       # RANDOM | ||||
| 	_control_command_names.append("srnd")      # SEED_RANDOM | ||||
| 	_control_command_names.append("visit")     # VISIT_INDEX | ||||
| 	_control_command_names.append("seq")       # SEQUENCE_SHUFFLE_INDEX | ||||
| 	_control_command_names.append("thread")    # START_THREAD | ||||
| 	_control_command_names.append("done")      # DONE | ||||
| 	_control_command_names.append("end")       # END | ||||
| 	_control_command_names.append("listInt")   # LIST_FROM_INT | ||||
| 	_control_command_names.append("range")     # LIST_RANGE | ||||
| 	_control_command_names.append("lrnd")      # LIST_RANDOM | ||||
| 	_control_command_names.append("#")         # BEGIN_TAG | ||||
| 	_control_command_names.append("/#")        # END_TAG | ||||
| 
 | ||||
| 	var i = 0 | ||||
| 	while i < InkControlCommand.CommandType.TOTAL_VALUES: | ||||
| 		if _control_command_names[i] == null: | ||||
| 			InkUtils.throw_exception("Control command not accounted for in serialisation") | ||||
| 		i += 1 | ||||
| 
 | ||||
| # Array<String> | ||||
| var _control_command_names = null | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| # Eventually a pointer to InkRuntime.StaticJson | ||||
| var _static_native_function_call = null | ||||
							
								
								
									
										284
									
								
								addons/inkgd/runtime/static/native_function_call.gd
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								addons/inkgd/runtime/static/native_function_call.gd
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,284 @@ | |||
| # warning-ignore-all:unused_class_variable | ||||
| # ############################################################################ # | ||||
| # Copyright © 2015-2021 inkle Ltd. | ||||
| # Copyright © 2019-2022 Frédéric Maquin <fred@ephread.com> | ||||
| # All Rights Reserved | ||||
| # | ||||
| # This file is part of inkgd. | ||||
| # inkgd is licensed under the terms of the MIT license. | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| extends RefCounted | ||||
| 
 | ||||
| class_name InkStaticNativeFunctionCall | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| # Imports | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| const ValueType = preload("res://addons/inkgd/runtime/values/value_type.gd").ValueType | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| const ADD                    = "+" | ||||
| const SUBTRACT               = "-" | ||||
| const DIVIDE                 = "/" | ||||
| const MULTIPLY               = "*" | ||||
| const MOD                    = "%" | ||||
| const NEGATE                 = "_" | ||||
| const EQUALS                 = "==" | ||||
| const GREATER                = ">" | ||||
| const LESS                   = "<" | ||||
| const GREATER_THAN_OR_EQUALS = ">=" | ||||
| const LESS_THAN_OR_EQUALS    = "<=" | ||||
| const NOT_EQUALS             = "!=" | ||||
| const NOT                    = "!" | ||||
| const AND                    = "&&" | ||||
| const OR                     = "||" | ||||
| const MIN                    = "MIN" | ||||
| const MAX                    = "MAX" | ||||
| const POW                    = "POW" | ||||
| const FLOOR                  = "FLOOR" | ||||
| const CEILING                = "CEILING" | ||||
| const INT                    = "INT" | ||||
| const FLOAT                  = "FLOAT" | ||||
| const HAS                    = "?" | ||||
| const HASNT                  = "!?" | ||||
| const INTERSECT              = "^" | ||||
| const LIST_MIN               = "LIST_MIN" | ||||
| const LIST_MAX               = "LIST_MAX" | ||||
| const ALL                    = "LIST_ALL" | ||||
| const COUNT                  = "LIST_COUNT" | ||||
| const VALUE_OF_LIST          = "LIST_VALUE" | ||||
| const INVERT                 = "LIST_INVERT" | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| var native_functions = null # Dictionary<String, String> | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| # (String) -> Bool | ||||
| func call_exists_with_name(function_name): | ||||
| 	generate_native_functions_if_necessary() | ||||
| 	return native_functions.has(function_name) | ||||
| 
 | ||||
| # () -> void | ||||
| func generate_native_functions_if_necessary(): | ||||
| 	if native_functions == null: | ||||
| 		native_functions = {} | ||||
| 
 | ||||
| 		add_int_binary_op(ADD,                      "int_binary_op_add") | ||||
| 		add_int_binary_op(SUBTRACT,                 "int_binary_op_substract") | ||||
| 		add_int_binary_op(MULTIPLY,                 "int_binary_op_multiply") | ||||
| 		add_int_binary_op(DIVIDE,                   "int_binary_op_divide") | ||||
| 		add_int_binary_op(MOD,                      "int_binary_op_mod") | ||||
| 		add_int_unary_op (NEGATE,                   "int_unary_op_negate") | ||||
| 
 | ||||
| 		add_int_binary_op(EQUALS,                   "int_binary_op_equals") | ||||
| 		add_int_binary_op(GREATER,                  "int_binary_op_greater") | ||||
| 		add_int_binary_op(LESS,                     "int_binary_op_less") | ||||
| 		add_int_binary_op(GREATER_THAN_OR_EQUALS,   "int_binary_op_greater_than_or_equals") | ||||
| 		add_int_binary_op(LESS_THAN_OR_EQUALS,      "int_binary_op_less_than_or_equals") | ||||
| 		add_int_binary_op(NOT_EQUALS,               "int_binary_op_not_equals") | ||||
| 		add_int_unary_op (NOT,                      "int_unary_op_not") | ||||
| 
 | ||||
| 		add_int_binary_op(AND,                      "int_binary_op_and") | ||||
| 		add_int_binary_op(OR,                       "int_binary_op_or") | ||||
| 
 | ||||
| 		add_int_binary_op(MAX,                      "int_binary_op_max") | ||||
| 		add_int_binary_op(MIN,                      "int_binary_op_min") | ||||
| 
 | ||||
| 		add_int_binary_op(POW,                      "int_binary_op_pow") | ||||
| 		add_int_unary_op (FLOOR,                    "int_unary_op_floor") | ||||
| 		add_int_unary_op (CEILING,                  "int_unary_op_ceiling") | ||||
| 		add_int_unary_op (INT,                      "int_unary_op_int") | ||||
| 		add_int_unary_op (FLOAT,                    "int_unary_op_float") | ||||
| 
 | ||||
| 		add_float_binary_op(ADD,                    "float_binary_op_add") | ||||
| 		add_float_binary_op(SUBTRACT,               "float_binary_op_substract") | ||||
| 		add_float_binary_op(MULTIPLY,               "float_binary_op_multiply") | ||||
| 		add_float_binary_op(DIVIDE,                 "float_binary_op_divide") | ||||
| 		add_float_binary_op(MOD,                    "float_binary_op_mod") | ||||
| 		add_float_unary_op (NEGATE,                 "float_unary_op_negate") | ||||
| 
 | ||||
| 		add_float_binary_op(EQUALS,                 "float_binary_op_equals") | ||||
| 		add_float_binary_op(GREATER,                "float_binary_op_greater") | ||||
| 		add_float_binary_op(LESS,                   "float_binary_op_less") | ||||
| 		add_float_binary_op(GREATER_THAN_OR_EQUALS, "float_binary_op_greater_than_or_equals") | ||||
| 		add_float_binary_op(LESS_THAN_OR_EQUALS,    "float_binary_op_less_than_or_equals") | ||||
| 		add_float_binary_op(NOT_EQUALS,             "float_binary_op_not_equals") | ||||
| 		add_float_unary_op (NOT,                    "float_unary_op_not") | ||||
| 
 | ||||
| 		add_float_binary_op(AND,                    "float_binary_op_and") | ||||
| 		add_float_binary_op(OR,                     "float_binary_op_or") | ||||
| 
 | ||||
| 		add_float_binary_op(MAX,                    "float_binary_op_max") | ||||
| 		add_float_binary_op(MIN,                    "float_binary_op_min") | ||||
| 
 | ||||
| 		add_float_binary_op(POW,                    "float_binary_op_pow") | ||||
| 		add_float_unary_op (FLOOR,                  "float_unary_op_floor") | ||||
| 		add_float_unary_op (CEILING,                "float_unary_op_ceiling") | ||||
| 		add_float_unary_op (INT,                    "float_unary_op_int") | ||||
| 		add_float_unary_op (FLOAT,                  "float_unary_op_float") | ||||
| 
 | ||||
| 		add_string_binary_op(ADD,                   "string_binary_op_add") | ||||
| 		add_string_binary_op(EQUALS,                "string_binary_op_equals") | ||||
| 		add_string_binary_op(NOT_EQUALS,            "string_binary_op_not_equals") | ||||
| 		add_string_binary_op(HAS,                   "string_binary_op_has") | ||||
| 		add_string_binary_op(HASNT,                 "string_binary_op_hasnt") | ||||
| 
 | ||||
| 		add_list_binary_op (ADD,                    "list_binary_op_add") | ||||
| 		add_list_binary_op (SUBTRACT,               "list_binary_op_substract") | ||||
| 		add_list_binary_op (HAS,                    "list_binary_op_has") | ||||
| 		add_list_binary_op (HASNT,                  "list_binary_op_hasnt") | ||||
| 		add_list_binary_op (INTERSECT,              "list_binary_op_intersect") | ||||
| 
 | ||||
| 		add_list_binary_op (EQUALS,                 "list_binary_op_equals") | ||||
| 		add_list_binary_op (GREATER,                "list_binary_op_greater") | ||||
| 		add_list_binary_op (LESS,                   "list_binary_op_less") | ||||
| 		add_list_binary_op (GREATER_THAN_OR_EQUALS, "list_binary_op_greater_than_or_equals") | ||||
| 		add_list_binary_op (LESS_THAN_OR_EQUALS,    "list_binary_op_less_than_or_equals") | ||||
| 		add_list_binary_op (NOT_EQUALS,             "list_binary_op_not_equals") | ||||
| 
 | ||||
| 		add_list_binary_op (AND,                    "list_binary_op_and") | ||||
| 		add_list_binary_op (OR,                     "list_binary_op_or") | ||||
| 
 | ||||
| 		add_list_unary_op (NOT,                     "list_unary_op_not") | ||||
| 
 | ||||
| 		add_list_unary_op (INVERT,                  "list_unary_op_invert") | ||||
| 		add_list_unary_op (ALL,                     "list_unary_op_all") | ||||
| 		add_list_unary_op (LIST_MIN,                "list_unary_op_list_min") | ||||
| 		add_list_unary_op (LIST_MAX,                "list_unary_op_list_max") | ||||
| 		add_list_unary_op (COUNT,                   "list_unary_op_count") | ||||
| 		add_list_unary_op (VALUE_OF_LIST,           "list_unary_op_value_of_list") | ||||
| 
 | ||||
| 		add_op_to_native_func(EQUALS, 2, ValueType.DIVERT_TARGET, | ||||
| 							  "native_func_divert_targets_equal") | ||||
| 		add_op_to_native_func(NOT_EQUALS, 2, ValueType.DIVERT_TARGET, | ||||
| 							  "native_func_divert_targets_not_equal") | ||||
| 
 | ||||
| # (String, int, ValueType, Variant) | ||||
| func add_op_to_native_func(name, args, val_type, op): | ||||
| 	var native_func = null # NativeFunctionCall | ||||
| 	if native_functions.has(name): | ||||
| 		native_func = native_functions[name] | ||||
| 	else: | ||||
| 		native_func = InkNativeFunctionCall.new_with_name_and_number_of_parameters(name, args, self) | ||||
| 		native_functions[name] = native_func | ||||
| 
 | ||||
| 	native_func.add_op_func_for_type(val_type, op) | ||||
| 
 | ||||
| func add_int_binary_op(name, op_function_name): | ||||
| 	add_op_to_native_func(name, 2, ValueType.INT, op_function_name) | ||||
| 
 | ||||
| func add_int_unary_op(name, op_function_name): | ||||
| 	add_op_to_native_func(name, 1, ValueType.INT, op_function_name) | ||||
| 
 | ||||
| func add_float_binary_op(name, op_function_name): | ||||
| 	add_op_to_native_func(name, 2, ValueType.FLOAT, op_function_name) | ||||
| 
 | ||||
| func add_float_unary_op(name, op_function_name): | ||||
| 	add_op_to_native_func(name, 1, ValueType.FLOAT, op_function_name) | ||||
| 
 | ||||
| func add_string_binary_op(name, op_function_name): | ||||
| 	add_op_to_native_func(name, 2, ValueType.STRING, op_function_name) | ||||
| 
 | ||||
| func add_list_binary_op(name, op_function_name): | ||||
| 	add_op_to_native_func(name, 2, ValueType.LIST, op_function_name) | ||||
| 
 | ||||
| func add_list_unary_op(name, op_function_name): | ||||
| 	add_op_to_native_func(name, 1, ValueType.LIST, op_function_name) | ||||
| 
 | ||||
| # ############################################################################ # | ||||
| 
 | ||||
| func int_binary_op_add(x, y):                      return x + y | ||||
| func int_binary_op_substract(x, y):                return x - y | ||||
| func int_binary_op_multiply(x, y):                 return x * y | ||||
| func int_binary_op_divide(x, y):                   return x / y | ||||
| func int_binary_op_mod(x, y):                      return x % y | ||||
| func int_unary_op_negate(x):                       return -x | ||||
| 
 | ||||
| func int_binary_op_equals(x, y):                   return x == y | ||||
| func int_binary_op_greater(x, y):                  return x > y | ||||
| func int_binary_op_less(x, y):                     return x < y | ||||
| func int_binary_op_greater_than_or_equals(x, y):   return x >= y | ||||
| func int_binary_op_less_than_or_equals(x, y):      return x <= y | ||||
| func int_binary_op_not_equals(x, y):               return x != y | ||||
| func int_unary_op_not(x):                          return x == 0 | ||||
| 
 | ||||
| func int_binary_op_and(x, y):                      return x != 0 && y != 0 | ||||
| func int_binary_op_or(x, y):                       return x != 0 || y != 0 | ||||
| 
 | ||||
| func int_binary_op_max(x, y):                      return max(x, y) | ||||
| func int_binary_op_min(x, y):                      return min(x, y) | ||||
| 
 | ||||
| func int_binary_op_pow(x, y):                      return pow(float(x), float(y)) | ||||
| func int_unary_op_floor(x):                        return x | ||||
| func int_unary_op_ceiling(x):                      return x | ||||
| func int_unary_op_int(x):                          return x | ||||
| func int_unary_op_float(x):                        return float(x) | ||||
| 
 | ||||
| func float_binary_op_add(x, y):                    return x + y | ||||
| func float_binary_op_substract(x, y):              return x - y | ||||
| func float_binary_op_multiply(x, y):               return x * y | ||||
| func float_binary_op_divide(x, y):                 return x / y | ||||
| func float_binary_op_mod(x, y):                    return fmod(x, y) | ||||
| func float_unary_op_negate(x):                     return -x | ||||
| 
 | ||||
| func float_binary_op_equals(x, y):                 return x == y | ||||
| func float_binary_op_greater(x, y):                return x > y | ||||
| func float_binary_op_less(x, y):                   return x < y | ||||
| func float_binary_op_greater_than_or_equals(x, y): return x >= y | ||||
| func float_binary_op_less_than_or_equals(x, y):    return x <= y | ||||
| func float_binary_op_not_equals(x, y):             return x != y | ||||
| func float_unary_op_not(x):                        return x == 0.0 | ||||
| 
 | ||||
| func float_binary_op_and(x, y):                    return x != 0.0 && y != 0.0 | ||||
| func float_binary_op_or(x, y):                     return x != 0.0 || y != 0.0 | ||||
| 
 | ||||
| func float_binary_op_max(x, y):                    return max(x, y) | ||||
| func float_binary_op_min(x, y):                    return min(x, y) | ||||
| 
 | ||||
| func float_binary_op_pow(x, y):                    return pow(x, y) | ||||
| func float_unary_op_floor(x):                      return floor(x) | ||||
| func float_unary_op_ceiling(x):                    return ceil(x) | ||||
| func float_unary_op_int(x):                        return int(x) | ||||
| func float_unary_op_float(x):                      return x | ||||
| 
 | ||||
| func string_binary_op_add(x, y):                   return str(x, y) | ||||
| func string_binary_op_equals(x, y):                return x == y | ||||
| func string_binary_op_not_equals(x, y):            return x != y | ||||
| 
 | ||||
| # Note: The Content Test (in) operator does not returns true when testing | ||||
| # against the empty string, unlike the behaviour of the original C# runtime. | ||||
| func string_binary_op_has(x, y):                   return y == "" || (y in x) | ||||
| func string_binary_op_hasnt(x, y):                 return !(y in x) && y != "" | ||||
| 
 | ||||
| func list_binary_op_add(x, y):                     return x.union(y) | ||||
| func list_binary_op_substract(x, y):               return x.without(y) | ||||
| func list_binary_op_has(x, y):                     return x.contains(y) | ||||
| func list_binary_op_hasnt(x, y):                   return !x.contains(y) | ||||
| func list_binary_op_intersect(x, y):               return x.intersection(y) | ||||
| 
 | ||||
| func list_binary_op_equals(x, y):                  return x.equals(y) | ||||
| func list_binary_op_greater(x, y):                 return x.greater_than(y) | ||||
| func list_binary_op_less(x, y):                    return x.less_than(y) | ||||
| func list_binary_op_greater_than_or_equals(x, y):  return x.greater_than_or_equals(y) | ||||
| func list_binary_op_less_than_or_equals(x, y):     return x.less_than_or_equals(y) | ||||
| func list_binary_op_not_equals(x, y):              return !x.equals(y) | ||||
| 
 | ||||
| func list_binary_op_and(x, y):                     return x.size() > 0 && y.size() > 0 | ||||
| func list_binary_op_or(x, y):                      return x.size() > 0 || y.size() > 0 | ||||
| 
 | ||||
| func list_unary_op_not(x):                         return 1 if x.size() == 0 else 0 | ||||
| 
 | ||||
| func list_unary_op_invert(x):                      return x.inverse | ||||
| func list_unary_op_all(x):                         return x.all | ||||
| func list_unary_op_list_min(x):                    return x.min_as_list() | ||||
| func list_unary_op_list_max(x):                    return x.max_as_list() | ||||
| func list_unary_op_count(x):                       return x.size() | ||||
| func list_unary_op_value_of_list(x):               return x.max_item.value | ||||
| 
 | ||||
| func native_func_divert_targets_equal(d1, d2):     return d1.equals(d2) | ||||
| func native_func_divert_targets_not_equal(d1, d2): return !d1.equals(d2) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Gerard Gascón
						Gerard Gascón