39 Commits

Author SHA1 Message Date
UnlegitDqrk
67429a7a31 Fixed issue: #55 2026-03-02 15:49:57 +01:00
UnlegitDqrk
139af3f28b Implemented issue: #19 2026-03-02 15:42:55 +01:00
UnlegitDqrk
33d745d667 Implemented issue: #47 2026-03-02 15:36:05 +01:00
UnlegitDqrk
06c74072be Fixed issue: #47 2026-03-02 15:31:22 +01:00
UnlegitDqrk
63edacbb5f Fixed issue: #51 2026-03-02 15:28:31 +01:00
UnlegitDqrk
7aea99d650 Implemented issue: #56 2026-03-02 14:58:31 +01:00
UnlegitDqrk
921606b93f Implemented issue: #65 2026-03-02 14:48:30 +01:00
UnlegitDqrk
5f11997446 Implemented issue: #67 2026-03-02 14:44:54 +01:00
UnlegitDqrk
c735ac67a0 Fixed issue: #68 2026-03-02 14:37:27 +01:00
UnlegitDqrk
7f7185aa08 Fixed issue: #70 2026-03-02 14:27:11 +01:00
UnlegitDqrk
39ff4f204d Fixed issue: #71 2026-03-02 14:22:54 +01:00
UnlegitDqrk
9cb10a390f Fixed issue: #74 2026-03-02 14:14:14 +01:00
UnlegitDqrk
c60991a33c Fixed issue: #75 2026-03-02 14:11:08 +01:00
UnlegitDqrk
c8fdc62495 Fixed issue: #81 2026-03-02 14:07:54 +01:00
UnlegitDqrk
ff4033cad4 Implemented issue: #82 2026-03-02 13:48:14 +01:00
UnlegitDqrk
572fd95692 Fixed issue: #86 2026-03-02 13:31:34 +01:00
UnlegitDqrk
db392c4763 Implemented issue: #87 2026-03-02 13:10:29 +01:00
UnlegitDqrk
98437da1fa Fixed issue: #96 2026-03-02 12:52:07 +01:00
UnlegitDqrk
85ed36de51 Fixed issue: #101 2026-03-02 11:58:39 +01:00
UnlegitDqrk
1d3459e0d3 Started with upgrading to Lua 5.3 2026-03-01 21:42:37 +01:00
UnlegitDqrk
493b055a26 Started with upgrading to Lua 5.3 2026-03-01 21:42:19 +01:00
UnlegitDqrk
01a8bd944e Fixed issue: #108 2026-03-01 19:57:26 +01:00
UnlegitDqrk
4c2add3832 Fixed issue: #94 2026-03-01 19:36:19 +01:00
UnlegitDqrk
364dbecb17 Fixed issue: Invalid escape sequences in string literals not raising errors (e.g. \q) 2026-03-01 19:11:18 +01:00
UnlegitDqrk
86e4d78761 Fixed issue: tonumber("-") returns 0 #6 2026-03-01 18:47:22 +01:00
UnlegitDqrk
7338475ae4 Fixed LuaJC not writing java package to bytecode correctly 2026-03-01 13:11:33 +01:00
UnlegitDqrk
01739d4e77 Pull request: MAXSTACK = 1024;LUAI_MAXVARS = 1024; #46 2026-03-01 13:08:19 +01:00
UnlegitDqrk
37b68d4d85 Pull request: Reduce allocations per LuaClosure call #76 2026-03-01 13:06:19 +01:00
UnlegitDqrk
f30c4c3bec Fixed varargs invocation from luajava 2026-03-01 13:04:22 +01:00
UnlegitDqrk
d0c84972dd fixed bug: invoke java variable parameter type method problem 2026-03-01 13:01:18 +01:00
UnlegitDqrk
068451886d fixed bug: invoke overload method disorder 2026-03-01 12:59:23 +01:00
UnlegitDqrk
ba3d1d8ef9 Added missed Classes 2026-03-01 12:57:18 +01:00
UnlegitDqrk
405fd633fd Added missed Classes 2026-03-01 12:56:55 +01:00
UnlegitDqrk
f087e87806 Updated to Java 25 2026-03-01 12:50:46 +01:00
UnlegitDqrk
95ea3d84b6 Added licenses 2026-03-01 12:40:00 +01:00
UnlegitDqrk
f40e89e19c Implemented Support of Java 21 VirtualThread 2026-03-01 12:39:42 +01:00
40831d0f2d Update README.md 2026-03-01 10:33:16 +00:00
bba6df42fd Update README.md 2026-03-01 10:29:43 +00:00
3df6dc9e96 Update README.md 2026-03-01 10:29:28 +00:00
821 changed files with 31288 additions and 60485 deletions

17
.gitignore vendored
View File

@@ -1,4 +1,15 @@
bin/
target/ target/
.classpath build/
.project lib/
.settings/ jit/
*.ser
*.gz
*.jar
*.lua
*.out
*.tar
*.txt
*.zip
docs
*.0

View File

@@ -1,138 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="2">
<profile kind="CleanUpProfile" name="Default" version="2">
<setting id="cleanup.array_with_curly" value="true"/>
<setting id="cleanup.use_autoboxing" value="true"/>
<setting id="cleanup.always_use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.remove_trailing_whitespaces_ignore_empty" value="false"/>
<setting id="cleanup.primitive_comparison" value="false"/>
<setting id="cleanup.system_property_file_encoding" value="true"/>
<setting id="cleanup.format_source_code_changes_only" value="false"/>
<setting id="cleanup.remove_redundant_semicolons" value="true"/>
<setting id="cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class" value="true"/>
<setting id="cleanup.useless_continue" value="true"/>
<setting id="cleanup.remove_redundant_type_arguments" value="true"/>
<setting id="cleanup.remove_unused_imports" value="true"/>
<setting id="cleanup.break_loop" value="false"/>
<setting id="cleanup.pull_up_assignment" value="false"/>
<setting id="cleanup.stringbuilder" value="false"/>
<setting id="cleanup.no_super" value="true"/>
<setting id="cleanup.arrays_fill" value="false"/>
<setting id="cleanup.use_lambda" value="true"/>
<setting id="cleanup.operand_factorization" value="false"/>
<setting id="cleanup.simplify_lambda_expression_and_method_ref" value="true"/>
<setting id="cleanup.always_use_blocks" value="true"/>
<setting id="cleanup.sort_members_all" value="false"/>
<setting id="cleanup.system_property_path_separator" value="true"/>
<setting id="cleanup.instanceof" value="false"/>
<setting id="cleanup.add_missing_annotations" value="true"/>
<setting id="cleanup.precompile_regex" value="false"/>
<setting id="cleanup.always_use_this_for_non_static_field_access" value="false"/>
<setting id="cleanup.boolean_literal" value="true"/>
<setting id="cleanup.always_use_parentheses_in_expressions" value="false"/>
<setting id="cleanup.sort_members" value="false"/>
<setting id="cleanup.remove_unused_local_variables" value="false"/>
<setting id="cleanup.add_missing_deprecated_annotations" value="true"/>
<setting id="cleanup.no_string_creation" value="true"/>
<setting id="cleanup.use_unboxing" value="false"/>
<setting id="cleanup.use_blocks_only_for_return_and_throw" value="false"/>
<setting id="cleanup.standard_comparison" value="false"/>
<setting id="cleanup.if_condition" value="true"/>
<setting id="cleanup.system_property_line_separator" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces" value="true"/>
<setting id="cleanup.map_cloning" value="true"/>
<setting id="cleanup.add_serial_version_id" value="false"/>
<setting id="cleanup.try_with_resource" value="true"/>
<setting id="cleanup.use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.use_this_for_non_static_method_access_only_if_necessary" value="true"/>
<setting id="cleanup.single_used_field" value="false"/>
<setting id="cleanup.reduce_indentation" value="false"/>
<setting id="cleanup.primitive_parsing" value="false"/>
<setting id="cleanup.make_local_variable_final" value="false"/>
<setting id="cleanup.add_missing_methods" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_with_declaring_class" value="true"/>
<setting id="cleanup.add_missing_override_annotations" value="true"/>
<setting id="cleanup.use_blocks" value="false"/>
<setting id="cleanup.multi_catch" value="true"/>
<setting id="cleanup.pull_out_if_from_if_else" value="true"/>
<setting id="cleanup.collection_cloning" value="true"/>
<setting id="cleanup.convert_to_enhanced_for_loop_if_loop_var_used" value="true"/>
<setting id="cleanup.make_variable_declarations_final" value="true"/>
<setting id="cleanup.redundant_comparator" value="false"/>
<setting id="cleanup.remove_unused_private_types" value="true"/>
<setting id="cleanup.system_property_boolean" value="true"/>
<setting id="cleanup.qualify_static_method_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.organize_imports" value="true"/>
<setting id="cleanup.lazy_logical_operator" value="true"/>
<setting id="cleanup.bitwise_conditional_expression" value="false"/>
<setting id="cleanup.use_directly_map_method" value="false"/>
<setting id="cleanup.add_all" value="false"/>
<setting id="cleanup.system_property_file_separator" value="true"/>
<setting id="cleanup.qualify_static_field_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.add_generated_serial_version_id" value="false"/>
<setting id="cleanup.controlflow_merge" value="false"/>
<setting id="cleanup.primitive_serialization" value="false"/>
<setting id="cleanup.comparing_on_criteria" value="true"/>
<setting id="cleanup.comparison_statement" value="true"/>
<setting id="cleanup.extract_increment" value="false"/>
<setting id="cleanup.insert_inferred_type_arguments" value="false"/>
<setting id="cleanup.make_private_fields_final" value="true"/>
<setting id="cleanup.useless_return" value="true"/>
<setting id="cleanup.instanceof_keyword" value="true"/>
<setting id="cleanup.use_this_for_non_static_field_access_only_if_necessary" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces_all" value="true"/>
<setting id="cleanup.one_if_rather_than_duplicate_blocks_that_fall_through" value="true"/>
<setting id="cleanup.valueof_rather_than_instantiation" value="true"/>
<setting id="cleanup.plain_replacement" value="false"/>
<setting id="cleanup.remove_unnecessary_array_creation" value="true"/>
<setting id="cleanup.remove_private_constructors" value="true"/>
<setting id="cleanup.make_parameters_final" value="false"/>
<setting id="cleanup.substring" value="false"/>
<setting id="cleanup.ternary_operator" value="false"/>
<setting id="cleanup.merge_conditional_blocks" value="false"/>
<setting id="cleanup.return_expression" value="true"/>
<setting id="cleanup.system_property" value="true"/>
<setting id="cleanup.unlooped_while" value="true"/>
<setting id="cleanup.convert_to_enhanced_for_loop" value="true"/>
<setting id="cleanup.remove_unused_private_fields" value="true"/>
<setting id="cleanup.never_use_blocks" value="false"/>
<setting id="cleanup.remove_redundant_modifiers" value="true"/>
<setting id="cleanup.unreachable_block" value="false"/>
<setting id="cleanup.redundant_falling_through_block_end" value="false"/>
<setting id="cleanup.switch" value="false"/>
<setting id="cleanup.number_suffix" value="true"/>
<setting id="cleanup.remove_unnecessary_nls_tags" value="true"/>
<setting id="cleanup.convert_to_switch_expressions" value="false"/>
<setting id="cleanup.use_this_for_non_static_field_access" value="false"/>
<setting id="cleanup.static_inner_class" value="false"/>
<setting id="cleanup.use_string_is_blank" value="true"/>
<setting id="cleanup.add_missing_nls_tags" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_through_instances_with_declaring_class" value="true"/>
<setting id="cleanup.remove_unnecessary_casts" value="true"/>
<setting id="cleanup.objects_equals" value="false"/>
<setting id="cleanup.convert_functional_interfaces" value="true"/>
<setting id="cleanup.format_source_code" value="true"/>
<setting id="cleanup.else_if" value="false"/>
<setting id="cleanup.boolean_value_rather_than_comparison" value="true"/>
<setting id="cleanup.add_default_serial_version_id" value="true"/>
<setting id="cleanup.remove_unused_private_methods" value="true"/>
<setting id="cleanup.make_type_abstract_if_missing_method" value="false"/>
<setting id="cleanup.join" value="false"/>
<setting id="cleanup.embedded_if" value="false"/>
<setting id="cleanup.use_anonymous_class_creation" value="false"/>
<setting id="cleanup.invert_equals" value="false"/>
<setting id="cleanup.add_missing_override_annotations_interface_methods" value="true"/>
<setting id="cleanup.remove_unused_private_members" value="false"/>
<setting id="cleanup.strictly_equal_or_different" value="true"/>
<setting id="cleanup.never_use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.push_down_negation" value="false"/>
<setting id="cleanup.evaluate_nullable" value="false"/>
<setting id="cleanup.use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.hash" value="false"/>
<setting id="cleanup.double_negation" value="true"/>
<setting id="cleanup.overridden_assignment" value="true"/>
<setting id="cleanup.primitive_rather_than_wrapper" value="true"/>
<setting id="cleanup.correct_indentation" value="false"/>
<setting id="cleanup.use_var" value="false"/>
</profile>
</profiles>

View File

@@ -1,390 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="21">
<profile kind="CodeFormatterProfile" name="LuaJ" version="21">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_preserve"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="120"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

16
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="core" />
<module name="jme" />
<module name="jse" />
<module name="maven-example" />
</profile>
</annotationProcessing>
</component>
</project>

7
.idea/discord.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

13
.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jme/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jme/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jse/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/jse/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

25
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="oac" />
<option name="name" value="oac" />
<option name="url" value="https://repo.open-autonomous-connection.org/api/packages/open-autonomous-connection/maven" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

9
.idea/luaj.iml generated Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

18
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/examples/maven/pom.xml" />
<option value="$PROJECT_DIR$/core/pom.xml" />
<option value="$PROJECT_DIR$/jme/pom.xml" />
<option value="$PROJECT_DIR$/jse/pom.xml" />
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="25" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -1,6 +1,12 @@
# This is a fork! # This is a fork!
<div style="border: 1px dotted red; margin: 1.em 0.5em; font-weight: bold; color: red;"> <div style="border: 1px dotted red; margin: 1.em 0.5em; font-weight: bold; color: red;">
This repository has been forked from the original CVS sources of Luaj. This repository has been forked from https://github.com/luaj/luaj.<br />
The commit history has been converted to make sure that the original work of
James Roseborough and Ian Farmer and fork work of luaj/luaj is not lost.
</div>
<h3>Original repository fork notice:</h3>
<div style="border: 1px dotted red; margin: 1.em 0.5em; font-weight: bold; color: red;">
The original repository has been forked from the original CVS sources of Luaj.
The commit history has been converted to make sure that the original work of The commit history has been converted to make sure that the original work of
James Roseborough and Ian Farmer is not lost. James Roseborough and Ian Farmer is not lost.
Unfortunately, I was not able to contact either James or Ian to hand over Unfortunately, I was not able to contact either James or Ian to hand over
@@ -248,7 +254,7 @@ A simple hello, world example in luaj is:
<pre> <pre>
import org.luaj.vm2.*; import org.luaj.vm2.*;
import org.luaj.vm2.lib.jse.*; import org.luaj.vm2.libs.jse.*;
Globals globals = JsePlatform.standardGlobals(); Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load("print 'hello, world'"); LuaValue chunk = globals.load("print 'hello, world'");
@@ -290,7 +296,7 @@ For MIDlets the <em>JmePlatform</em> is used instead:
<pre> <pre>
import org.luaj.vm2.*; import org.luaj.vm2.*;
import org.luaj.vm2.lib.jme.*; import org.luaj.vm2.libs.jme.*;
Globals globals = JmePlatform.standardGlobals(); Globals globals = JmePlatform.standardGlobals();
LuaValue chunk = globals.loadfile("examples/lua/hello.lua"); LuaValue chunk = globals.loadfile("examples/lua/hello.lua");
@@ -311,10 +317,6 @@ A simple example may be found in
You must include the library <b>luaj-jme-3.0.2.jar</b> in your midlet jar. You must include the library <b>luaj-jme-3.0.2.jar</b> in your midlet jar.
<p> <p>
An ant script to build and run the midlet is in
<pre>
<a href="build-midlet.xml">build-midlet.xml</a>
</pre>
<p> <p>
You must install the wireless toolkit and define <em>WTK_HOME</em> for this script to work. You must install the wireless toolkit and define <em>WTK_HOME</em> for this script to work.
@@ -422,7 +424,6 @@ Applets in browsers should use the JsePlatform. The permissions model in applet
highly restrictive, so a specialization of the <a href="#luajava">Luajava</a> library must be used that highly restrictive, so a specialization of the <a href="#luajava">Luajava</a> library must be used that
uses default class loading. This is illustrated in the sample Applet uses default class loading. This is illustrated in the sample Applet
<a href="examples/jse/SampleApplet.java">examples/jse/SampleApplet.java</a>, <a href="examples/jse/SampleApplet.java">examples/jse/SampleApplet.java</a>,
which can be built using <a href="build-applet.xml">build-applet.xml</a>.
<h3>JmePlatform</h3> <h3>JmePlatform</h3>
@@ -441,7 +442,6 @@ In particular Globals.finder is overridden to load as resources, so scripts shou
colocated with class files in the MIDlet jar file. <a href="#luajava">Luajava</a> cannot be used. colocated with class files in the MIDlet jar file. <a href="#luajava">Luajava</a> cannot be used.
Camples code is in Camples code is in
<a href="examples/jme/SampleMIDlet.java">examples/jme/SampleMIDlet.java</a>, <a href="examples/jme/SampleMIDlet.java">examples/jme/SampleMIDlet.java</a>,
which can be built using <a href="build-midlet.xml">build-midlet.xml</a>.
<h2>Thread Safety</h2> <h2>Thread Safety</h2>
@@ -566,7 +566,7 @@ create globals that contain the debug library in addition to the other standard
To install dynamically from lua use java-class-based require:</em>: To install dynamically from lua use java-class-based require:</em>:
<pre> <pre>
require 'org.luaj.vm2.lib.DebugLib' require 'org.luaj.vm2.libs.DebugLib'
</pre> </pre>
The <em>lua</em> command line utility includes the <em>debug</em> library by default. The <em>lua</em> command line utility includes the <em>debug</em> library by default.
@@ -666,11 +666,11 @@ The simplest way to implement a function is to choose a base class based on the
LuaJ provides 5 base classes for this purpose, depending if the function has 0, 1, 2, 3 or variable arguments, LuaJ provides 5 base classes for this purpose, depending if the function has 0, 1, 2, 3 or variable arguments,
and if it provide multiple return values. and if it provide multiple return values.
<pre> <pre>
<a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/ZeroArgFunction.html">org.luaj.vm2.lib.ZeroArgFunction</a> <a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/ZeroArgFunction.html">org.luaj.vm2.libs.ZeroArgFunction</a>
<a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/OneArgFunction.html">org.luaj.vm2.lib.OneArgFunction</a> <a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/OneArgFunction.html">org.luaj.vm2.libs.OneArgFunction</a>
<a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/TwoArgFunction.html">org.luaj.vm2.lib.TwoArgFunction</a> <a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/TwoArgFunction.html">org.luaj.vm2.libs.TwoArgFunction</a>
<a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/ThreeArgFunction.html">org.luaj.vm2.lib.ThreeArgFunction</a> <a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/ThreeArgFunction.html">org.luaj.vm2.libs.ThreeArgFunction</a>
<a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/VarArgFunction.html">org.luaj.vm2.lib.VarArgFunction</a> <a href="http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/VarArgFunction.html">org.luaj.vm2.libs.VarArgFunction</a>
</pre> </pre>
Each of these functions has an abstract method that must be implemented, Each of these functions has an abstract method that must be implemented,
@@ -724,7 +724,7 @@ in the environment that can be called from lua.
A complete example of Java code for a simple toy library is in <a href="examples/jse/hyperbolic.java">examples/jse/hyperbolic.java</a> A complete example of Java code for a simple toy library is in <a href="examples/jse/hyperbolic.java">examples/jse/hyperbolic.java</a>
<pre> <pre>
import org.luaj.vm2.LuaValue; import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.*; import org.luaj.vm2.libs.*;
public class hyperbolic extends TwoArgFunction { public class hyperbolic extends TwoArgFunction {
@@ -858,30 +858,33 @@ An example skelton maven pom file for a skeleton project is in
<h2>Building the jars</h2> <h2>Building the jars</h2>
Build the jars with maven. An ant file is included in the root directory which builds the libraries by default.
<pre>
mvn clean verify
</pre>
<p> <p>
Other targets exist for creating distribution file an measuring code coverage of unit tests.
<h2>Unit tests</h2> <h2>Unit tests</h2>
<p> <p>
All unit tests are executed during the build. The main luaj JUnit tests are organized into a JUnit 3 suite:
<pre>
test/junit/org/luaj/vm2/AllTests.lua
</pre>
<p> <p>
Test scripts can be found in these locations Unit test scripts can be found in these locations
<pre> <pre>
luaj-test/src/test/resources test/lua/*.lua
test/lua/errors/*.lua
test/lua/perf/*.lua
test/lua/luaj3.0.2-tests.zip
</pre> </pre>
Executon is included in the build of luaj-test.
<h2>Code coverage</h2> <h2>Code coverage</h2>
<p> <p>
The maven build creates the coverage report in the luaj-test/target/site folder
during the verify phase. It relies on the cobertura code coverage library.
<h1>8 - <a name="8">Downloads</a></h1> <h1>8 - <a name="8">Downloads</a></h1>
@@ -938,7 +941,6 @@ and at <a href="http://luaj.sourceforge.net/api/2.0/index.html">http://luaj.sour
<li>Add explicit Globals object to manage global state, especially to imrpove thread safety </li> <li>Add explicit Globals object to manage global state, especially to imrpove thread safety </li>
<li>Drop support for lua source to java surce (lua2java) in favor of direct java bytecode output (luajc) </li> <li>Drop support for lua source to java surce (lua2java) in favor of direct java bytecode output (luajc) </li>
<li>Remove compatibility functions like table.getn(), table.maxn(), table.foreach(), and math.log10() </li> <li>Remove compatibility functions like table.getn(), table.maxn(), table.foreach(), and math.log10() </li>
<li>Add ability to create runnable jar file from lua script with sample build file build-app.xml </li>
<li>Supply environment as second argument to LibFunction when loading via require() </li> <li>Supply environment as second argument to LibFunction when loading via require() </li>
<li>Fix bug 3597515 memory leak due to string caching by simplifying caching logic.</li> <li>Fix bug 3597515 memory leak due to string caching by simplifying caching logic.</li>
<li>Fix bug 3565008 so that short substrings are backed by short arrays.</li> <li>Fix bug 3565008 so that short substrings are backed by short arrays.</li>
@@ -1021,7 +1023,10 @@ and at <a href="http://luaj.sourceforge.net/api/2.0/index.html">http://luaj.sour
<li>debug code may not be completely removed by some obfuscators <li>debug code may not be completely removed by some obfuscators
<li>tail calls are not tracked in debug information <li>tail calls are not tracked in debug information
<li>mixing different versions of luaj in the same java vm is not supported <li>mixing different versions of luaj in the same java vm is not supported
<li>LuaJ runs on the host VM garbage collector, so object lifetime, weak reference timing, and finalization behavior are not identical to native Lua
<li>the <code>__gc</code> metamethod is not supported as a reliable Lua finalization mechanism
<li>values associated with weak keys may linger longer than expected <li>values associated with weak keys may linger longer than expected
<li>cascading weak-table collection can require multiple host GC cycles
<li>behavior of luaj when a SecurityManager is used has not been fully characterized <li>behavior of luaj when a SecurityManager is used has not been fully characterized
<li>negative zero is treated as identical to integer value zero throughout luaj <li>negative zero is treated as identical to integer value zero throughout luaj
<li>lua compiled into java bytecode using luajc cannot use string.dump() or xpcall() <li>lua compiled into java bytecode using luajc cannot use string.dump() or xpcall()
@@ -1029,6 +1034,22 @@ and at <a href="http://luaj.sourceforge.net/api/2.0/index.html">http://luaj.sour
<li>shared metatables for string, bool, etc are shared across Globals instances in the same class loader <li>shared metatables for string, bool, etc are shared across Globals instances in the same class loader
<li>orphaned threads will not be collected unless garbage collection is run and sufficient time elapses <li>orphaned threads will not be collected unless garbage collection is run and sufficient time elapses
</ul> </ul>
<h3>Garbage Collection And Resources</h3>
LuaJ does not implement the same garbage collector semantics as native Lua. Garbage collection is delegated to the host JVM or CLDC runtime, so <code>collectgarbage()</code> is only a hint and should not be used as a resource-management primitive.
<p>
In particular:
<ul>
<li>Do not rely on garbage collection to close files, sockets, database handles, or other resources.
<li>Always call <code>close()</code> explicitly on files and iterators that own files.
<li><code>io.lines(filename)</code> opens a file implicitly. If iteration is abandoned early, that file may remain open until explicitly collected by the host runtime.
<li>Prefer <code>local f = assert(io.open(...))</code> together with <code>f:lines()</code> and an explicit <code>f:close()</code> when deterministic cleanup matters.
<li>For implicit line iterators that need deterministic early cleanup, use <code>io.linesx(filename)</code> and call <code>iterator:close()</code>.
<li><code>file:linesx()</code> provides the same closable iterator API for already-open files.
<li>On Windows, leaked file handles can prevent rename or delete operations until the process exits.
<li>On JME/CLDC, finalization support may be absent, so explicit close is mandatory.
</ul>
<p>
Short-lived locals may also remain reachable longer than expected because host stack/register reuse is implementation-dependent. If prompt reclamation matters, isolate temporary allocations in functions and clear large references explicitly instead of assuming block exit is enough.
<h3>File Character Encoding</h3> <h3>File Character Encoding</h3>
Source files can be considered encoded in UTF-8 or ISO-8859-1 and results should be as expected, Source files can be considered encoded in UTF-8 or ISO-8859-1 and results should be as expected,
with literal string contianing quoted characters compiling to the same byte sequences as the input. with literal string contianing quoted characters compiling to the same byte sequences as the input.

36
core/pom.xml Normal file
View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openautonomousconnection.luaj</groupId>
<artifactId>parent</artifactId>
<version>3.0.2</version>
</parent>
<artifactId>core</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals><goal>jar</goal></goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${maven.compiler.release}</source>
<target>${maven.compiler.release}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

Binary file not shown.

View File

@@ -21,16 +21,16 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2; package org.luaj.vm2;
/** /**
* String buffer for use in string library methods, optimized for production of * String buffer for use in string library methods, optimized for production
* StrValue instances. * of StrValue instances.
* <p> * <p>
* The buffer can begin initially as a wrapped {@link LuaValue} and only when * The buffer can begin initially as a wrapped {@link LuaValue}
* concatenation actually occurs are the bytes first copied. * and only when concatenation actually occurs are the bytes first copied.
* <p> * <p>
* To convert back to a {@link LuaValue} again, the function * To convert back to a {@link LuaValue} again,
* {@link Buffer#value()} is used. * the function {@link Buffer#value()} is used.
*
* @see LuaValue * @see LuaValue
* @see LuaValue#buffer() * @see LuaValue#buffer()
* @see LuaString * @see LuaString
@@ -57,7 +57,6 @@ public final class Buffer {
/** /**
* Create buffer with default capacity * Create buffer with default capacity
*
* @see #DEFAULT_CAPACITY * @see #DEFAULT_CAPACITY
*/ */
public Buffer() { public Buffer() {
@@ -66,11 +65,10 @@ public final class Buffer {
/** /**
* Create buffer with specified initial capacity * Create buffer with specified initial capacity
*
* @param initialCapacity the initial capacity * @param initialCapacity the initial capacity
*/ */
public Buffer(int initialCapacity) { public Buffer( int initialCapacity ) {
bytes = new byte[initialCapacity]; bytes = new byte[ initialCapacity ];
length = 0; length = 0;
offset = 0; offset = 0;
value = null; value = null;
@@ -78,7 +76,6 @@ public final class Buffer {
/** /**
* Create buffer with specified initial value * Create buffer with specified initial value
*
* @param value the initial value * @param value the initial value
*/ */
public Buffer(LuaValue value) { public Buffer(LuaValue value) {
@@ -89,7 +86,6 @@ public final class Buffer {
/** /**
* Get buffer contents as a {@link LuaValue} * Get buffer contents as a {@link LuaValue}
*
* @return value as a {@link LuaValue}, converting as necessary * @return value as a {@link LuaValue}, converting as necessary
*/ */
public LuaValue value() { public LuaValue value() {
@@ -98,7 +94,6 @@ public final class Buffer {
/** /**
* Set buffer contents as a {@link LuaValue} * Set buffer contents as a {@link LuaValue}
*
* @param value value to set * @param value value to set
*/ */
public Buffer setvalue(LuaValue value) { public Buffer setvalue(LuaValue value) {
@@ -110,17 +105,15 @@ public final class Buffer {
/** /**
* Convert the buffer to a {@link LuaString} * Convert the buffer to a {@link LuaString}
*
* @return the value as a {@link LuaString} * @return the value as a {@link LuaString}
*/ */
public LuaString tostring() { public final LuaString tostring() {
realloc(length, 0); realloc( length, 0 );
return LuaString.valueOf(bytes, offset, length); return LuaString.valueOf( bytes, offset, length );
} }
/** /**
* Convert the buffer to a Java String * Convert the buffer to a Java String
*
* @return the value as a Java String * @return the value as a Java String
*/ */
public String tojstring() { public String tojstring() {
@@ -129,149 +122,125 @@ public final class Buffer {
/** /**
* Convert the buffer to a Java String * Convert the buffer to a Java String
*
* @return the value as a Java String * @return the value as a Java String
*/ */
@Override
public String toString() { public String toString() {
return tojstring(); return tojstring();
} }
/** /**
* Append a single byte to the buffer. * Append a single byte to the buffer.
*
* @return {@code this} to allow call chaining * @return {@code this} to allow call chaining
*/ */
public Buffer append(byte b) { public final Buffer append( byte b ) {
makeroom(0, 1); makeroom( 0, 1 );
bytes[offset+length++] = b; bytes[ offset + length++ ] = b;
return this; return this;
} }
/** /**
* Append a {@link LuaValue} to the buffer. * Append a {@link LuaValue} to the buffer.
*
* @return {@code this} to allow call chaining * @return {@code this} to allow call chaining
*/ */
public Buffer append(LuaValue val) { public final Buffer append( LuaValue val ) {
append(val.strvalue()); append( val.strvalue() );
return this; return this;
} }
/** /**
* Append a {@link LuaString} to the buffer. * Append a {@link LuaString} to the buffer.
*
* @return {@code this} to allow call chaining * @return {@code this} to allow call chaining
*/ */
public Buffer append(LuaString str) { public final Buffer append( LuaString str ) {
final int n = str.m_length; final int n = str.m_length;
makeroom(0, n); makeroom( 0, n );
str.copyInto(0, bytes, offset+length, n); str.copyInto( 0, bytes, offset + length, n );
length += n; length += n;
return this; return this;
} }
/** /**
* Append a Java String to the buffer. The Java string will be converted to * Append a Java String to the buffer.
* bytes using the UTF8 encoding. * The Java string will be converted to bytes using the UTF8 encoding.
*
* @return {@code this} to allow call chaining * @return {@code this} to allow call chaining
* @see LuaString#encodeToUtf8(char[], int, byte[], int) * @see LuaString#encodeToUtf8(char[], int, byte[], int)
*/ */
public Buffer append(String str) { public final Buffer append( String str ) {
char[] c = str.toCharArray(); char[] c = str.toCharArray();
final int n = LuaString.lengthAsUtf8(c); final int n = LuaString.lengthAsUtf8( c );
makeroom(0, n); makeroom( 0, n );
LuaString.encodeToUtf8(c, c.length, bytes, offset+length); LuaString.encodeToUtf8( c, c.length, bytes, offset + length );
length += n; length += n;
return this; return this;
} }
/** /** Concatenate this buffer onto a {@link LuaValue}
* Concatenate this buffer onto a {@link LuaValue} * @param lhs the left-hand-side value onto which we are concatenating {@code this}
*
* @param lhs the left-hand-side value onto which we are concatenating
* {@code this}
* @return {@link Buffer} for use in call chaining. * @return {@link Buffer} for use in call chaining.
*/ */
public Buffer concatTo(LuaValue lhs) { public Buffer concatTo(LuaValue lhs) {
return setvalue(lhs.concat(value())); return setvalue(lhs.concat(value()));
} }
/** /** Concatenate this buffer onto a {@link LuaString}
* Concatenate this buffer onto a {@link LuaString} * @param lhs the left-hand-side value onto which we are concatenating {@code this}
*
* @param lhs the left-hand-side value onto which we are concatenating
* {@code this}
* @return {@link Buffer} for use in call chaining. * @return {@link Buffer} for use in call chaining.
*/ */
public Buffer concatTo(LuaString lhs) { public Buffer concatTo(LuaString lhs) {
return value != null && !value.isstring()? setvalue(lhs.concat(value)): prepend(lhs); return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs);
} }
/** /** Concatenate this buffer onto a {@link LuaNumber}
* Concatenate this buffer onto a {@link LuaNumber}
* <p> * <p>
* The {@link LuaNumber} will be converted to a string before concatenating. * The {@link LuaNumber} will be converted to a string before concatenating.
* * @param lhs the left-hand-side value onto which we are concatenating {@code this}
* @param lhs the left-hand-side value onto which we are concatenating
* {@code this}
* @return {@link Buffer} for use in call chaining. * @return {@link Buffer} for use in call chaining.
*/ */
public Buffer concatTo(LuaNumber lhs) { public Buffer concatTo(LuaNumber lhs) {
return value != null && !value.isstring()? setvalue(lhs.concat(value)): prepend(lhs.strvalue()); return value!=null&&!value.isstring()? setvalue(lhs.concat(value)): prepend(lhs.strvalue());
} }
/** /** Concatenate bytes from a {@link LuaString} onto the front of this buffer
* Concatenate bytes from a {@link LuaString} onto the front of this buffer * @param s the left-hand-side value which we will concatenate onto the front of {@code this}
*
* @param s the left-hand-side value which we will concatenate onto the
* front of {@code this}
* @return {@link Buffer} for use in call chaining. * @return {@link Buffer} for use in call chaining.
*/ */
public Buffer prepend(LuaString s) { public Buffer prepend(LuaString s) {
int n = s.m_length; int n = s.m_length;
makeroom(n, 0); makeroom( n, 0 );
System.arraycopy(s.m_bytes, s.m_offset, bytes, offset-n, n); System.arraycopy( s.m_bytes, s.m_offset, bytes, offset-n, n );
offset -= n; offset -= n;
length += n; length += n;
value = null; value = null;
return this; return this;
} }
/** /** Ensure there is enough room before and after the bytes.
* Ensure there is enough room before and after the bytes. * @param nbefore number of unused bytes which must precede the data after this completes
* * @param nafter number of unused bytes which must follow the data after this completes
* @param nbefore number of unused bytes which must precede the data after
* this completes
* @param nafter number of unused bytes which must follow the data after
* this completes
*/ */
public void makeroom(int nbefore, int nafter) { public final void makeroom( int nbefore, int nafter ) {
if (value != null) { if ( value != null ) {
LuaString s = value.strvalue(); LuaString s = value.strvalue();
value = null; value = null;
length = s.m_length; length = s.m_length;
offset = nbefore; offset = nbefore;
bytes = new byte[nbefore+length+nafter]; bytes = new byte[nbefore+length+nafter];
System.arraycopy(s.m_bytes, s.m_offset, bytes, offset, length); System.arraycopy(s.m_bytes, s.m_offset, bytes, offset, length);
} else if (offset+length+nafter > bytes.length || offset < nbefore) { } else if ( offset+length+nafter > bytes.length || offset<nbefore ) {
int n = nbefore+length+nafter; int n = nbefore+length+nafter;
int m = n < 32? 32: n < length*2? length*2: n; int m = n<32? 32: n<length*2? length*2: n;
realloc(m, nbefore == 0? 0: m-length-nafter); realloc( m, nbefore==0? 0: m-length-nafter );
} }
} }
/** /** Reallocate the internal storage for the buffer
* Reallocate the internal storage for the buffer
*
* @param newSize the size of the buffer to use * @param newSize the size of the buffer to use
* @param newOffset the offset to use * @param newOffset the offset to use
*/ */
private void realloc(int newSize, int newOffset) { private final void realloc( int newSize, int newOffset ) {
if (newSize != bytes.length) { if ( newSize != bytes.length ) {
byte[] newBytes = new byte[newSize]; byte[] newBytes = new byte[ newSize ];
System.arraycopy(bytes, offset, newBytes, newOffset, length); System.arraycopy( bytes, offset, newBytes, newOffset, length );
bytes = newBytes; bytes = newBytes;
offset = newOffset; offset = newOffset;
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -26,105 +26,84 @@ import java.io.InputStream;
import java.io.PrintStream; import java.io.PrintStream;
import java.io.Reader; import java.io.Reader;
import org.luaj.vm2.lib.BaseLib; import org.luaj.vm2.libs.BaseLib;
import org.luaj.vm2.lib.DebugLib; import org.luaj.vm2.libs.DebugLib;
import org.luaj.vm2.lib.IoLib; import org.luaj.vm2.libs.IoLib;
import org.luaj.vm2.lib.PackageLib; import org.luaj.vm2.libs.PackageLib;
import org.luaj.vm2.lib.ResourceFinder; import org.luaj.vm2.libs.ResourceFinder;
/** /**
* Global environment used by luaj. Contains global variables referenced by * Global environment used by luaj. Contains global variables referenced by executing lua.
* executing lua.
* <p> * <p>
* *
* <h3>Constructing and Initializing Instances</h3> Typically, this is * <h3>Constructing and Initializing Instances</h3>
* constructed indirectly by a call to * Typically, this is constructed indirectly by a call to
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or * {@link org.luaj.vm2.libs.jse.JsePlatform#standardGlobals()} or
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}, and then used to * {@link org.luaj.vm2.libs.jme.JmePlatform#standardGlobals()},
* load lua scripts for execution as in the following example. * and then used to load lua scripts for execution as in the following example.
* * <pre> {@code
* <pre>
* {
* &#64;code
* Globals globals = JsePlatform.standardGlobals(); * Globals globals = JsePlatform.standardGlobals();
* globals.load(new StringReader("print 'hello'"), "main.lua").call(); * globals.load( new StringReader("print 'hello'"), "main.lua" ).call();
* } * } </pre>
* </pre>
*
* The creates a complete global environment with the standard libraries loaded. * The creates a complete global environment with the standard libraries loaded.
* <p> * <p>
* For specialized circumstances, the Globals may be constructed directly and * For specialized circumstances, the Globals may be constructed directly and loaded
* loaded with only those libraries that are needed, for example. * with only those libraries that are needed, for example.
* * <pre> {@code
* <pre>
* {
* &#64;code
* Globals globals = new Globals(); * Globals globals = new Globals();
* globals.load(new BaseLib()); * globals.load( new BaseLib() );
* } * } </pre>
* </pre>
* *
* <h3>Loading and Executing Lua Code</h3> Globals contains convenience * <h3>Loading and Executing Lua Code</h3>
* functions to load and execute lua source code given a Reader. A simple * Globals contains convenience functions to load and execute lua source code given a Reader.
* example is: * A simple example is:
* * <pre> {@code
* <pre>
* {@code
* globals.load( new StringReader("print 'hello'"), "main.lua" ).call(); * globals.load( new StringReader("print 'hello'"), "main.lua" ).call();
* } * } </pre>
* </pre>
* *
* <h3>Fine-Grained Control of Compiling and Loading Lua</h3> Executable * <h3>Fine-Grained Control of Compiling and Loading Lua</h3>
* LuaFunctions are created from lua code in several steps * Executable LuaFunctions are created from lua code in several steps
* <ul> * <ul>
* <li>find the resource using the platform's {@link ResourceFinder} * <li>find the resource using the platform's {@link ResourceFinder}
* <li>compile lua to lua bytecode using {@link Compiler} * <li>compile lua to lua bytecode using {@link Compiler}
* <li>load lua bytecode to a {@link Prototype} using {@link Undumper} * <li>load lua bytecode to a {@link Prototype} using {@link Undumper}
* <li>construct {@link LuaClosure} from {@link Prototype} with {@link Globals} * <li>construct {@link LuaClosure} from {@link Prototype} with {@link Globals} using {@link Loader}
* using {@link Loader}
* </ul> * </ul>
* <p> * <p>
* There are alternate flows when the direct lua-to-Java bytecode compiling * There are alternate flows when the direct lua-to-Java bytecode compiling {@link org.luaj.vm2.luajc.LuaJC} is used.
* {@link org.luaj.vm2.luajc.LuaJC} is used.
* <ul> * <ul>
* <li>compile lua to lua bytecode using {@link Compiler} or load precompiled * <li>compile lua to lua bytecode using {@link Compiler} or load precompiled code using {@link Undumper}
* code using {@link Undumper} * <li>convert lua bytecode to equivalent Java bytecode using {@link org.luaj.vm2.luajc.LuaJC} that implements {@link Loader} directly
* <li>convert lua bytecode to equivalent Java bytecode using
* {@link org.luaj.vm2.luajc.LuaJC} that implements {@link Loader} directly
* </ul> * </ul>
* *
* <h3>Java Field</h3> Certain public fields are provided that contain the * <h3>Java Field</h3>
* current values of important global state: * Certain public fields are provided that contain the current values of important global state:
* <ul> * <ul>
* <li>{@link #STDIN} Current value for standard input in the laaded * <li>{@link #STDIN} Current value for standard input in the laaded {@link IoLib}, if any.
* {@link IoLib}, if any. * <li>{@link #STDOUT} Current value for standard output in the loaded {@link IoLib}, if any.
* <li>{@link #STDOUT} Current value for standard output in the loaded * <li>{@link #STDERR} Current value for standard error in the loaded {@link IoLib}, if any.
* {@link IoLib}, if any.
* <li>{@link #STDERR} Current value for standard error in the loaded
* {@link IoLib}, if any.
* <li>{@link #finder} Current loaded {@link ResourceFinder}, if any. * <li>{@link #finder} Current loaded {@link ResourceFinder}, if any.
* <li>{@link #compiler} Current loaded {@link Compiler}, if any. * <li>{@link #compiler} Current loaded {@link Compiler}, if any.
* <li>{@link #undumper} Current loaded {@link Undumper}, if any. * <li>{@link #undumper} Current loaded {@link Undumper}, if any.
* <li>{@link #loader} Current loaded {@link Loader}, if any. * <li>{@link #loader} Current loaded {@link Loader}, if any.
* </ul> * </ul>
* *
* <h3>Lua Environment Variables</h3> When using * <h3>Lua Environment Variables</h3>
* {@link org.luaj.vm2.lib.jse.JsePlatform} or * When using {@link org.luaj.vm2.libs.jse.JsePlatform} or {@link org.luaj.vm2.libs.jme.JmePlatform},
* {@link org.luaj.vm2.lib.jme.JmePlatform}, these environment variables are * these environment variables are created within the Globals.
* created within the Globals.
* <ul> * <ul>
* <li>"_G" Pointer to this Globals. * <li>"_G" Pointer to this Globals.
* <li>"_VERSION" String containing the version of luaj. * <li>"_VERSION" String containing the version of luaj.
* </ul> * </ul>
* *
* <h3>Use in Multithreaded Environments</h3> In a multi-threaded server * <h3>Use in Multithreaded Environments</h3>
* environment, each server thread should create one Globals instance, which * In a multi-threaded server environment, each server thread should create one Globals instance,
* will be logically distinct and not interfere with each other, but share * which will be logically distinct and not interfere with each other, but share certain
* certain static immutable resources such as class data and string data. * static immutable resources such as class data and string data.
* <p> * <p>
* *
* @see org.luaj.vm2.lib.jse.JsePlatform * @see org.luaj.vm2.libs.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform * @see org.luaj.vm2.libs.jme.JmePlatform
* @see LuaValue * @see LuaValue
* @see Compiler * @see Compiler
* @see Loader * @see Loader
@@ -147,9 +126,7 @@ public class Globals extends LuaTable {
/** The installed ResourceFinder for looking files by name. */ /** The installed ResourceFinder for looking files by name. */
public ResourceFinder finder; public ResourceFinder finder;
/** /** The currently running thread. Should not be changed by non-library code. */
* The currently running thread. Should not be changed by non-library code.
*/
public LuaThread running = new LuaThread(this); public LuaThread running = new LuaThread(this);
/** The BaseLib instance loaded into this Globals */ /** The BaseLib instance loaded into this Globals */
@@ -158,30 +135,18 @@ public class Globals extends LuaTable {
/** The PackageLib instance loaded into this Globals */ /** The PackageLib instance loaded into this Globals */
public PackageLib package_; public PackageLib package_;
/** /** The DebugLib instance loaded into this Globals, or null if debugging is not enabled */
* The DebugLib instance loaded into this Globals, or null if debugging is
* not enabled
*/
public DebugLib debuglib; public DebugLib debuglib;
/** /** Interface for module that converts a Prototype into a LuaFunction with an environment. */
* Interface for module that converts a Prototype into a LuaFunction with an
* environment.
*/
public interface Loader { public interface Loader {
/** /** Convert the prototype into a LuaFunction with the supplied environment. */
* Convert the prototype into a LuaFunction with the supplied
* environment.
*/
LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException; LuaFunction load(Prototype prototype, String chunkname, LuaValue env) throws IOException;
} }
/** Interface for module that converts lua source text into a prototype. */ /** Interface for module that converts lua source text into a prototype. */
public interface Compiler { public interface Compiler {
/** /** Compile lua source into a Prototype. The InputStream is assumed to be in UTF-8. */
* Compile lua source into a Prototype. The InputStream is assumed to be
* in UTF-8.
*/
Prototype compile(InputStream stream, String chunkname) throws IOException; Prototype compile(InputStream stream, String chunkname) throws IOException;
} }
@@ -191,142 +156,111 @@ public class Globals extends LuaTable {
Prototype undump(InputStream stream, String chunkname) throws IOException; Prototype undump(InputStream stream, String chunkname) throws IOException;
} }
/** /** Check that this object is a Globals object, and return it, otherwise throw an error. */
* Check that this object is a Globals object, and return it, otherwise
* throw an error.
*/
@Override
public Globals checkglobals() { public Globals checkglobals() {
return this; return this;
} }
/** /** The installed loader.
* The installed loader. * @see Loader */
*
* @see Loader
*/
public Loader loader; public Loader loader;
/** /** The installed compiler.
* The installed compiler. * @see Compiler */
*
* @see Compiler
*/
public Compiler compiler; public Compiler compiler;
/** /** The installed undumper.
* The installed undumper. * @see Undumper */
*
* @see Undumper
*/
public Undumper undumper; public Undumper undumper;
/** /** Convenience function for loading a file that is either binary lua or lua source.
* Convenience function for loading a file that is either binary lua or lua
* source.
*
* @param filename Name of the file to load. * @param filename Name of the file to load.
* @return LuaValue that can be call()'ed or invoke()'ed. * @return LuaValue that can be call()'ed or invoke()'ed.
* @throws LuaError if the file could not be loaded. * @throws LuaError if the file could not be loaded.
*/ */
public LuaValue loadfile(String filename) { public LuaValue loadfile(String filename) {
InputStream is = null;
try { try {
return load(finder.findResource(filename), "@" + filename, "bt", this); is = finder.findResource(filename);
if (is == null) {
return error("cannot open " + filename + ": No such file or directory");
}
return load(is, "@"+filename, "bt", this);
} catch (Exception e) { } catch (Exception e) {
return error("load " + filename + ": " + e); return error("load "+filename+": "+e);
} finally {
if (is != null) {
try {
is.close();
} catch (Exception ignored) {
}
}
} }
} }
/** /** Convenience function to load a string value as a script. Must be lua source.
* Convenience function to load a string value as a script. Must be lua * @param script Contents of a lua script, such as "print 'hello, world.'"
* source.
*
* @param script Contents of a lua script, such as "print 'hello,
* world.'"
* @param chunkname Name that will be used within the chunk as the source. * @param chunkname Name that will be used within the chunk as the source.
* @return LuaValue that may be executed via .call(), .invoke(), or * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
* .method() calls.
* @throws LuaError if the script could not be compiled. * @throws LuaError if the script could not be compiled.
*/ */
public LuaValue load(String script, String chunkname) { public LuaValue load(String script, String chunkname) {
return load(new StrReader(script), chunkname); return load(new StrReader(script), chunkname);
} }
/** /** Convenience function to load a string value as a script. Must be lua source.
* Convenience function to load a string value as a script. Must be lua
* source.
*
* @param script Contents of a lua script, such as "print 'hello, world.'" * @param script Contents of a lua script, such as "print 'hello, world.'"
* @return LuaValue that may be executed via .call(), .invoke(), or * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
* .method() calls.
* @throws LuaError if the script could not be compiled. * @throws LuaError if the script could not be compiled.
*/ */
public LuaValue load(String script) { public LuaValue load(String script) {
return load(new StrReader(script), script); return load(new StrReader(script), script);
} }
/** /** Convenience function to load a string value as a script with a custom environment.
* Convenience function to load a string value as a script with a custom * Must be lua source.
* environment. Must be lua source. * @param script Contents of a lua script, such as "print 'hello, world.'"
*
* @param script Contents of a lua script, such as "print 'hello,
* world.'"
* @param chunkname Name that will be used within the chunk as the source. * @param chunkname Name that will be used within the chunk as the source.
* @param environment LuaTable to be used as the environment for the loaded * @param environment LuaTable to be used as the environment for the loaded function.
* function. * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
* @return LuaValue that may be executed via .call(), .invoke(), or
* .method() calls.
* @throws LuaError if the script could not be compiled. * @throws LuaError if the script could not be compiled.
*/ */
public LuaValue load(String script, String chunkname, LuaTable environment) { public LuaValue load(String script, String chunkname, LuaTable environment) {
return load(new StrReader(script), chunkname, environment); return load(new StrReader(script), chunkname, environment);
} }
/** /** Load the content form a reader as a text file. Must be lua source.
* Load the content form a reader as a text file. Must be lua source. The * The source is converted to UTF-8, so any characters appearing in quoted literals
* source is converted to UTF-8, so any characters appearing in quoted * above the range 128 will be converted into multiple bytes.
* literals above the range 128 will be converted into multiple bytes. * @param reader Reader containing text of a lua script, such as "print 'hello, world.'"
*
* @param reader Reader containing text of a lua script, such as "print
* 'hello, world.'"
* @param chunkname Name that will be used within the chunk as the source. * @param chunkname Name that will be used within the chunk as the source.
* @return LuaValue that may be executed via .call(), .invoke(), or * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
* .method() calls.
* @throws LuaError if the script could not be compiled. * @throws LuaError if the script could not be compiled.
*/ */
public LuaValue load(Reader reader, String chunkname) { public LuaValue load(Reader reader, String chunkname) {
return load(new UTF8Stream(reader), chunkname, "t", this); return load(new UTF8Stream(reader), chunkname, "t", this);
} }
/** /** Load the content form a reader as a text file, supplying a custom environment.
* Load the content form a reader as a text file, supplying a custom * Must be lua source. The source is converted to UTF-8, so any characters
* environment. Must be lua source. The source is converted to UTF-8, so any * appearing in quoted literals above the range 128 will be converted into
* characters appearing in quoted literals above the range 128 will be * multiple bytes.
* converted into multiple bytes. * @param reader Reader containing text of a lua script, such as "print 'hello, world.'"
*
* @param reader Reader containing text of a lua script, such as "print
* 'hello, world.'"
* @param chunkname Name that will be used within the chunk as the source. * @param chunkname Name that will be used within the chunk as the source.
* @param environment LuaTable to be used as the environment for the loaded * @param environment LuaTable to be used as the environment for the loaded function.
* function. * @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
* @return LuaValue that may be executed via .call(), .invoke(), or
* .method() calls.
* @throws LuaError if the script could not be compiled. * @throws LuaError if the script could not be compiled.
*/ */
public LuaValue load(Reader reader, String chunkname, LuaTable environment) { public LuaValue load(Reader reader, String chunkname, LuaTable environment) {
return load(new UTF8Stream(reader), chunkname, "t", environment); return load(new UTF8Stream(reader), chunkname, "t", environment);
} }
/** /** Load the content form an input stream as a binary chunk or text file.
* Load the content form an input stream as a binary chunk or text file.
*
* @param is InputStream containing a lua script or compiled lua" * @param is InputStream containing a lua script or compiled lua"
* @param chunkname Name that will be used within the chunk as the source. * @param chunkname Name that will be used within the chunk as the source.
* @param mode String containing 'b' or 't' or both to control * @param mode String containing 'b' or 't' or both to control loading as binary or text or either.
* loading as binary or text or either. * @param environment LuaTable to be used as the environment for the loaded function.
* @param environment LuaTable to be used as the environment for the loaded * */
* function.
*/
public LuaValue load(InputStream is, String chunkname, String mode, LuaValue environment) { public LuaValue load(InputStream is, String chunkname, String mode, LuaValue environment) {
try { try {
Prototype p = loadPrototype(is, chunkname, mode); Prototype p = loadPrototype(is, chunkname, mode);
@@ -334,20 +268,16 @@ public class Globals extends LuaTable {
} catch (LuaError l) { } catch (LuaError l) {
throw l; throw l;
} catch (Exception e) { } catch (Exception e) {
return error("load " + chunkname + ": " + e); return error("load "+chunkname+": "+e);
} }
} }
/** /** Load lua source or lua binary from an input stream into a Prototype.
* Load lua source or lua binary from an input stream into a Prototype. The * The InputStream is either a binary lua chunk starting with the lua binary chunk signature,
* InputStream is either a binary lua chunk starting with the lua binary * or a text input file. If it is a text input file, it is interpreted as a UTF-8 byte sequence.
* chunk signature, or a text input file. If it is a text input file, it is
* interpreted as a UTF-8 byte sequence.
*
* @param is Input stream containing a lua script or compiled lua" * @param is Input stream containing a lua script or compiled lua"
* @param chunkname Name that will be used within the chunk as the source. * @param chunkname Name that will be used within the chunk as the source.
* @param mode String containing 'b' or 't' or both to control loading * @param mode String containing 'b' or 't' or both to control loading as binary or text or either.
* as binary or text or either.
*/ */
public Prototype loadPrototype(InputStream is, String chunkname, String mode) throws IOException { public Prototype loadPrototype(InputStream is, String chunkname, String mode) throws IOException {
if (mode.indexOf('b') >= 0) { if (mode.indexOf('b') >= 0) {
@@ -364,25 +294,21 @@ public class Globals extends LuaTable {
if (mode.indexOf('t') >= 0) { if (mode.indexOf('t') >= 0) {
return compilePrototype(is, chunkname); return compilePrototype(is, chunkname);
} }
error("Failed to load prototype " + chunkname + " using mode '" + mode + "'"); error("Failed to load prototype "+chunkname+" using mode '"+mode+"'");
return null; return null;
} }
/** /** Compile lua source from a Reader into a Prototype. The characters in the reader
* Compile lua source from a Reader into a Prototype. The characters in the * are converted to bytes using the UTF-8 encoding, so a string literal containing
* reader are converted to bytes using the UTF-8 encoding, so a string * characters with codepoints 128 or above will be converted into multiple bytes.
* literal containing characters with codepoints 128 or above will be
* converted into multiple bytes.
*/ */
public Prototype compilePrototype(Reader reader, String chunkname) throws IOException { public Prototype compilePrototype(Reader reader, String chunkname) throws IOException {
return compilePrototype(new UTF8Stream(reader), chunkname); return compilePrototype(new UTF8Stream(reader), chunkname);
} }
/** /** Compile lua source from an InputStream into a Prototype.
* Compile lua source from an InputStream into a Prototype. The input is * The input is assumed to be UTf-8, but since bytes in the range 128-255 are passed along as
* assumed to be UTf-8, but since bytes in the range 128-255 are passed * literal bytes, any ASCII-compatible encoding such as ISO 8859-1 may also be used.
* along as literal bytes, any ASCII-compatible encoding such as ISO 8859-1
* may also be used.
*/ */
public Prototype compilePrototype(InputStream stream, String chunkname) throws IOException { public Prototype compilePrototype(InputStream stream, String chunkname) throws IOException {
if (compiler == null) if (compiler == null)
@@ -390,13 +316,9 @@ public class Globals extends LuaTable {
return compiler.compile(stream, chunkname); return compiler.compile(stream, chunkname);
} }
/** /** Function which yields the current thread.
* Function which yields the current thread. * @param args Arguments to supply as return values in the resume function of the resuming thread.
* * @return Values supplied as arguments to the resume() call that reactivates this thread.
* @param args Arguments to supply as return values in the resume function
* of the resuming thread.
* @return Values supplied as arguments to the resume() call that
* reactivates this thread.
*/ */
public Varargs yield(Varargs args) { public Varargs yield(Varargs args) {
if (running == null || running.isMainThread()) if (running == null || running.isMainThread())
@@ -410,28 +332,21 @@ public class Globals extends LuaTable {
final String s; final String s;
int i = 0; int i = 0;
final int n; final int n;
StrReader(String s) { StrReader(String s) {
this.s = s; this.s = s;
n = s.length(); n = s.length();
} }
@Override
public void close() throws IOException { public void close() throws IOException {
i = n; i = n;
} }
@Override
public int read() throws IOException { public int read() throws IOException {
return i < n? s.charAt(i++): -1; return i < n ? s.charAt(i++) : -1;
} }
@Override
public int read(char[] cbuf, int off, int len) throws IOException { public int read(char[] cbuf, int off, int len) throws IOException {
int j = 0; int j = 0;
for (; j < len && i < n; ++j, ++i) for (; j < len && i < n; ++j, ++i)
cbuf[off+j] = s.charAt(i); cbuf[off+j] = s.charAt(i);
return j > 0 || len == 0? j: -1; return j > 0 || len == 0 ? j : -1;
} }
} }
@@ -441,66 +356,48 @@ public class Globals extends LuaTable {
abstract static class AbstractBufferedStream extends InputStream { abstract static class AbstractBufferedStream extends InputStream {
protected byte[] b; protected byte[] b;
protected int i = 0, j = 0; protected int i = 0, j = 0;
protected AbstractBufferedStream(int buflen) { protected AbstractBufferedStream(int buflen) {
this.b = new byte[buflen]; this.b = new byte[buflen];
} }
abstract protected int avail() throws IOException; abstract protected int avail() throws IOException;
@Override
public int read() throws IOException { public int read() throws IOException {
int a = avail(); int a = avail();
return a <= 0? -1: 0xff & b[i++]; return (a <= 0 ? -1 : 0xff & b[i++]);
} }
@Override
public int read(byte[] b) throws IOException { public int read(byte[] b) throws IOException {
return read(b, 0, b.length); return read(b, 0, b.length);
} }
@Override
public int read(byte[] b, int i0, int n) throws IOException { public int read(byte[] b, int i0, int n) throws IOException {
int a = avail(); int a = avail();
if (a <= 0) if (a <= 0) return -1;
return -1;
final int n_read = Math.min(a, n); final int n_read = Math.min(a, n);
System.arraycopy(this.b, i, b, i0, n_read); System.arraycopy(this.b, i, b, i0, n_read);
i += n_read; i += n_read;
return n_read; return n_read;
} }
@Override
public long skip(long n) throws IOException { public long skip(long n) throws IOException {
final long k = Math.min(n, j-i); final long k = Math.min(n, j - i);
i += k; i += k;
return k; return k;
} }
@Override
public int available() throws IOException { public int available() throws IOException {
return j-i; return j - i;
} }
} }
/** /** Simple converter from Reader to InputStream using UTF8 encoding that will work
* Simple converter from Reader to InputStream using UTF8 encoding that will * on both JME and JSE.
* work on both JME and JSE. This class may be moved to its own package in * This class may be moved to its own package in the future.
* the future.
*/ */
static class UTF8Stream extends AbstractBufferedStream { static class UTF8Stream extends AbstractBufferedStream {
private final char[] c = new char[32]; private final char[] c = new char[32];
private final Reader r; private final Reader r;
UTF8Stream(Reader r) { UTF8Stream(Reader r) {
super(96); super(96);
this.r = r; this.r = r;
} }
@Override
protected int avail() throws IOException { protected int avail() throws IOException {
if (i < j) if (i < j) return j - i;
return j-i;
int n = r.read(c); int n = r.read(c);
if (n < 0) if (n < 0)
return -1; return -1;
@@ -514,40 +411,31 @@ public class Globals extends LuaTable {
j = LuaString.encodeToUtf8(c, n, b, i = 0); j = LuaString.encodeToUtf8(c, n, b, i = 0);
return j; return j;
} }
@Override
public void close() throws IOException { public void close() throws IOException {
r.close(); r.close();
} }
} }
/** /** Simple buffered InputStream that supports mark.
* Simple buffered InputStream that supports mark. Used to examine an * Used to examine an InputStream for a 4-byte binary lua signature,
* InputStream for a 4-byte binary lua signature, and fall back to text * and fall back to text input when the signature is not found,
* input when the signature is not found, as well as speed up normal * as well as speed up normal compilation and reading of lua scripts.
* compilation and reading of lua scripts. This class may be moved to its * This class may be moved to its own package in the future.
* own package in the future.
*/ */
static class BufferedStream extends AbstractBufferedStream { static class BufferedStream extends AbstractBufferedStream {
private final InputStream s; private final InputStream s;
public BufferedStream(InputStream s) { public BufferedStream(InputStream s) {
this(128, s); this(128, s);
} }
BufferedStream(int buflen, InputStream s) { BufferedStream(int buflen, InputStream s) {
super(buflen); super(buflen);
this.s = s; this.s = s;
} }
@Override
protected int avail() throws IOException { protected int avail() throws IOException {
if (i < j) if (i < j) return j - i;
return j-i; if (j >= b.length) i = j = 0;
if (j >= b.length)
i = j = 0;
// leave previous bytes in place to implement mark()/reset(). // leave previous bytes in place to implement mark()/reset().
int n = s.read(b, j, b.length-j); int n = s.read(b, j, b.length - j);
if (n < 0) if (n < 0)
return -1; return -1;
if (n == 0) { if (n == 0) {
@@ -560,29 +448,21 @@ public class Globals extends LuaTable {
j += n; j += n;
return n; return n;
} }
@Override
public void close() throws IOException { public void close() throws IOException {
s.close(); s.close();
} }
@Override
public synchronized void mark(int n) { public synchronized void mark(int n) {
if (i > 0 || n > b.length) { if (i > 0 || n > b.length) {
byte[] dest = n > b.length? new byte[n]: b; byte[] dest = n > b.length ? new byte[n] : b;
System.arraycopy(b, i, dest, 0, j-i); System.arraycopy(b, i, dest, 0, j - i);
j -= i; j -= i;
i = 0; i = 0;
b = dest; b = dest;
} }
} }
@Override
public boolean markSupported() { public boolean markSupported() {
return true; return true;
} }
@Override
public synchronized void reset() throws IOException { public synchronized void reset() throws IOException {
i = 0; i = 0;
} }

Binary file not shown.

View File

@@ -25,107 +25,83 @@ import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
/** /**
* Class to undump compiled lua bytecode into a {@link Prototype} instances. * Class to undump compiled lua bytecode into a {@link Prototype} instances.
* <p> * <p>
* The {@link LoadState} class provides the default {@link Globals.Undumper} * The {@link LoadState} class provides the default {@link Globals.Undumper}
* which is used to undump a string of bytes that represent a lua binary file * which is used to undump a string of bytes that represent a lua binary file
* using either the C-based lua compiler, or luaj's * using either the C-based lua compiler, or luaj's
* {@link org.luaj.vm2.compiler.LuaC} compiler. * {@link org.luaj.vm2.compiler.LuaC} compiler.
* <p> * <p>
* The canonical method to load and execute code is done indirectly using the * The canonical method to load and execute code is done
* Globals: * indirectly using the Globals:
* * <pre> {@code
* <pre> * Globals globals = JsePlatform.standardGlobals();
* { * LuaValue chunk = globasl.load("print('hello, world')", "main.lua");
* &#64;code * chunk.call();
* Globals globals = JsePlatform.standardGlobals(); * } </pre>
* LuaValue chunk = globasl.load("print('hello, world')", "main.lua"); * This should work regardless of which {@link Globals.Compiler} or {@link Globals.Undumper}
* chunk.call(); * have been installed.
* } * <p>
* </pre> * By default, when using {@link org.luaj.vm2.libs.jse.JsePlatform} or
* * {@link org.luaj.vm2.libs.jme.JmePlatform}
* This should work regardless of which {@link Globals.Compiler} or * to construct globals, the {@link LoadState} default undumper is installed
* {@link Globals.Undumper} have been installed. * as the default {@link Globals.Undumper}.
* <p> * <p>
* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or *
* {@link org.luaj.vm2.lib.jme.JmePlatform} to construct globals, the * A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState} class
* {@link LoadState} default undumper is installed as the default :
* {@link Globals.Undumper}. * <pre> {@code
* <p> * Globals globals = JsePlatform.standardGlobals();
* * Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua");
* A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState} * ByteArrayOutputStream o = new ByteArrayOutputStream();
* class : * org.luaj.vm2.compiler.DumpState.dump(p, o, false);
* * byte[] lua_binary_file_bytes = o.toByteArray();
* <pre> * } </pre>
* { *
* &#64;code * The {@link LoadState}'s default undumper {@link #instance}
* Globals globals = JsePlatform.standardGlobals(); * may be used directly to undump these bytes:
* Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua"); * <pre> {@code
* ByteArrayOutputStream o = new ByteArrayOutputStream();
* org.luaj.vm2.compiler.DumpState.dump(p, o, false);
* byte[] lua_binary_file_bytes = o.toByteArray();
* }
* </pre>
*
* The {@link LoadState}'s default undumper {@link #instance} may be used
* directly to undump these bytes:
*
* <pre>
* {@code
* Prototypep = LoadState.instance.undump(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua"); * Prototypep = LoadState.instance.undump(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua");
* LuaClosure c = new LuaClosure(p, globals); * LuaClosure c = new LuaClosure(p, globals);
* c.call(); * c.call();
* } * } </pre>
* </pre> *
* *
* * More commonly, the {@link Globals.Undumper} may be used to undump them:
* More commonly, the {@link Globals.Undumper} may be used to undump them: * <pre> {@code
* * Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
* <pre> * LuaClosure c = new LuaClosure(p, globals);
* { * c.call();
* &#64;code * } </pre>
* Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b"); *
* LuaClosure c = new LuaClosure(p, globals); * @see Globals.Compiler
* c.call(); * @see Globals.Undumper
* } * @see LuaClosure
* </pre> * @see LuaFunction
* * @see org.luaj.vm2.compiler.LuaC
* @see Globals.Compiler * @see org.luaj.vm2.luajc.LuaJC
* @see Globals.Undumper * @see Globals#compiler
* @see LuaClosure * @see Globals#load(InputStream, String, LuaValue)
* @see LuaFunction */
* @see org.luaj.vm2.compiler.LuaC
* @see org.luaj.vm2.luajc.LuaJC
* @see Globals#compiler
* @see Globals#load(InputStream, String, LuaValue)
*/
public class LoadState { public class LoadState {
/** /** Shared instance of Globals.Undumper to use loading prototypes from binary lua files */
* Shared instance of Globals.Undumper to use loading prototypes from binary
* lua files
*/
public static final Globals.Undumper instance = new GlobalsUndumper(); public static final Globals.Undumper instance = new GlobalsUndumper();
/** /** format corresponding to non-number-patched lua, all numbers are floats or doubles */
* format corresponding to non-number-patched lua, all numbers are floats or
* doubles
*/
public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0; public static final int NUMBER_FORMAT_FLOATS_OR_DOUBLES = 0;
/** format corresponding to non-number-patched lua, all numbers are ints */ /** format corresponding to non-number-patched lua, all numbers are ints */
public static final int NUMBER_FORMAT_INTS_ONLY = 1; public static final int NUMBER_FORMAT_INTS_ONLY = 1;
/** /** format corresponding to number-patched lua, all numbers are 32-bit (4 byte) ints */
* format corresponding to number-patched lua, all numbers are 32-bit (4
* byte) ints
*/
public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4; public static final int NUMBER_FORMAT_NUM_PATCH_INT32 = 4;
// type constants // type constants
public static final int LUA_TINT = -2; public static final int LUA_TINT = (-2);
public static final int LUA_TNONE = -1; public static final int LUA_TNONE = (-1);
public static final int LUA_TNIL = 0; public static final int LUA_TNIL = 0;
public static final int LUA_TBOOLEAN = 1; public static final int LUA_TBOOLEAN = 1;
public static final int LUA_TLIGHTUSERDATA = 2; public static final int LUA_TLIGHTUSERDATA = 2;
@@ -137,10 +113,7 @@ public class LoadState {
public static final int LUA_TTHREAD = 8; public static final int LUA_TTHREAD = 8;
public static final int LUA_TVALUE = 9; public static final int LUA_TVALUE = 9;
/** /** The character encoding to use for file encoding. Null means the default encoding */
* The character encoding to use for file encoding. Null means the default
* encoding
*/
public static String encoding = null; public static String encoding = null;
/** Signature byte indicating the file is a compiled binary chunk */ /** Signature byte indicating the file is a compiled binary chunk */
@@ -149,9 +122,11 @@ public class LoadState {
/** Data to catch conversion errors */ /** Data to catch conversion errors */
public static final byte[] LUAC_TAIL = { (byte) 0x19, (byte) 0x93, '\r', '\n', (byte) 0x1a, '\n', }; public static final byte[] LUAC_TAIL = { (byte) 0x19, (byte) 0x93, '\r', '\n', (byte) 0x1a, '\n', };
/** Name for compiled chunks */ /** Name for compiled chunks */
public static final String SOURCE_BINARY_STRING = "binary string"; public static final String SOURCE_BINARY_STRING = "binary string";
/** for header of binary files -- this is Lua 5.2 */ /** for header of binary files -- this is Lua 5.2 */
public static final int LUAC_VERSION = 0x52; public static final int LUAC_VERSION = 0x52;
@@ -186,139 +161,126 @@ public class LoadState {
/** Read buffer */ /** Read buffer */
private byte[] buf = new byte[512]; private byte[] buf = new byte[512];
/** /** Install this class as the standard Globals.Undumper for the supplied Globals */
* Install this class as the standard Globals.Undumper for the supplied
* Globals
*/
public static void install(Globals globals) { public static void install(Globals globals) {
globals.undumper = instance; globals.undumper = instance;
} }
/** /** Load a 4-byte int value from the input stream
* Load a 4-byte int value from the input stream
*
* @return the int value laoded. * @return the int value laoded.
**/ **/
int loadInt() throws IOException { int loadInt() throws IOException {
is.readFully(buf, 0, 4); is.readFully(buf,0,4);
return luacLittleEndian? buf[3]<<24 | (0xff & buf[2])<<16 | (0xff & buf[1])<<8 | 0xff & buf[0] return luacLittleEndian?
: buf[0]<<24 | (0xff & buf[1])<<16 | (0xff & buf[2])<<8 | 0xff & buf[3]; (buf[3] << 24) | ((0xff & buf[2]) << 16) | ((0xff & buf[1]) << 8) | (0xff & buf[0]):
(buf[0] << 24) | ((0xff & buf[1]) << 16) | ((0xff & buf[2]) << 8) | (0xff & buf[3]);
} }
/** /** Load an array of int values from the input stream
* Load an array of int values from the input stream
*
* @return the array of int values laoded. * @return the array of int values laoded.
**/ **/
int[] loadIntArray() throws IOException { int[] loadIntArray() throws IOException {
int n = loadInt(); int n = loadInt();
if (n == 0) if ( n == 0 )
return NOINTS; return NOINTS;
// read all data at once // read all data at once
int m = n<<2; int m = n << 2;
if (buf.length < m) if ( buf.length < m )
buf = new byte[m]; buf = new byte[m];
is.readFully(buf, 0, m); is.readFully(buf,0,m);
int[] array = new int[n]; int[] array = new int[n];
for (int i = 0, j = 0; i < n; ++i, j += 4) for ( int i=0, j=0; i<n; ++i, j+=4 )
array[i] = luacLittleEndian? buf[j+3]<<24 | (0xff & buf[j+2])<<16 | (0xff & buf[j+1])<<8 | 0xff & buf[j+0] array[i] = luacLittleEndian?
: buf[j+0]<<24 | (0xff & buf[j+1])<<16 | (0xff & buf[j+2])<<8 | 0xff & buf[j+3]; (buf[j+3] << 24) | ((0xff & buf[j+2]) << 16) | ((0xff & buf[j+1]) << 8) | (0xff & buf[j+0]):
(buf[j+0] << 24) | ((0xff & buf[j+1]) << 16) | ((0xff & buf[j+2]) << 8) | (0xff & buf[j+3]);
return array; return array;
} }
/** /** Load a long value from the input stream
* Load a long value from the input stream
*
* @return the long value laoded. * @return the long value laoded.
**/ **/
long loadInt64() throws IOException { long loadInt64() throws IOException {
int a, b; int a,b;
if (this.luacLittleEndian) { if ( this.luacLittleEndian ) {
a = loadInt(); a = loadInt();
b = loadInt(); b = loadInt();
} else { } else {
b = loadInt(); b = loadInt();
a = loadInt(); a = loadInt();
} }
return (long) b<<32 | a & 0xffffffffL; return (((long)b)<<32) | (((long)a)&0xffffffffL);
} }
/** /** Load a lua strin gvalue from the input stream
* Load a lua strin gvalue from the input stream
*
* @return the {@link LuaString} value laoded. * @return the {@link LuaString} value laoded.
**/ **/
LuaString loadString() throws IOException { LuaString loadString() throws IOException {
int size = this.luacSizeofSizeT == 8? (int) loadInt64(): loadInt(); int size = this.luacSizeofSizeT == 8? (int) loadInt64(): loadInt();
if (size == 0) if ( size == 0 )
return null; return null;
byte[] bytes = new byte[size]; byte[] bytes = new byte[size];
is.readFully(bytes, 0, size); is.readFully( bytes, 0, size );
return LuaString.valueUsing(bytes, 0, bytes.length-1); return LuaString.valueUsing( bytes, 0, bytes.length - 1 );
} }
/** /**
* Convert bits in a long value to a {@link LuaValue}. * Convert bits in a long value to a {@link LuaValue}.
*
* @param bits long value containing the bits * @param bits long value containing the bits
* @return {@link LuaInteger} or {@link LuaDouble} whose value corresponds * @return {@link LuaInteger} or {@link LuaDouble} whose value corresponds to the bits provided.
* to the bits provided.
*/ */
public static LuaValue longBitsToLuaNumber(long bits) { public static LuaValue longBitsToLuaNumber( long bits ) {
if ((bits & (1L<<63)-1) == 0L) { if ( ( bits & ( ( 1L << 63 ) - 1 ) ) == 0L ) {
return LuaValue.ZERO; return LuaValue.ZERO;
} }
int e = (int) (bits>>52 & 0x7ffL)-1023; int e = (int)((bits >> 52) & 0x7ffL) - 1023;
if (e >= 0 && e < 31) { if ( e >= 0 && e < 63 ) {
long f = bits & 0xFFFFFFFFFFFFFL; long f = bits & 0xFFFFFFFFFFFFFL;
int shift = 52-e; int shift = 52 - e;
long intPrecMask = (1L<<shift)-1; long intPrecMask = shift > 0 ? ( 1L << shift ) - 1 : 0;
if ((f & intPrecMask) == 0) { if ( shift <= 52 && ( f & intPrecMask ) == 0 ) {
int intValue = (int) (f>>shift) | 1<<e; long intValue = shift >= 0 ? (f >> shift) | (1L << e) : (f << (-shift)) | (1L << e);
return LuaInteger.valueOf(bits>>63 != 0? -intValue: intValue); return LuaInteger.valueOf( ( ( bits >> 63 ) != 0 ) ? -intValue : intValue );
} }
} }
return LuaValue.valueOf(Double.longBitsToDouble(bits)); return LuaValue.valueOf( Double.longBitsToDouble(bits) );
} }
/** /**
* Load a number from a binary chunk * Load a number from a binary chunk
*
* @return the {@link LuaValue} loaded * @return the {@link LuaValue} loaded
* @throws IOException if an i/o exception occurs * @throws IOException if an i/o exception occurs
*/ */
LuaValue loadNumber() throws IOException { LuaValue loadNumber() throws IOException {
if (luacNumberFormat == NUMBER_FORMAT_INTS_ONLY) { if ( luacNumberFormat == NUMBER_FORMAT_INTS_ONLY ) {
return LuaInteger.valueOf(loadInt()); return LuaInteger.valueOf( loadInt() );
} else { } else {
return longBitsToLuaNumber(loadInt64()); return longBitsToLuaNumber( loadInt64() );
} }
} }
/** /**
* Load a list of constants from a binary chunk * Load a list of constants from a binary chunk
*
* @param f the function prototype * @param f the function prototype
* @throws IOException if an i/o exception occurs * @throws IOException if an i/o exception occurs
*/ */
void loadConstants(Prototype f) throws IOException { void loadConstants(Prototype f) throws IOException {
int n = loadInt(); int n = loadInt();
LuaValue[] values = n > 0? new LuaValue[n]: NOVALUES; LuaValue[] values = n>0? new LuaValue[n]: NOVALUES;
for (int i = 0; i < n; i++) { for ( int i=0; i<n; i++ ) {
switch (is.readByte()) { switch ( is.readByte() ) {
case LUA_TNIL: case LUA_TNIL:
values[i] = LuaValue.NIL; values[i] = LuaValue.NIL;
break; break;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
values[i] = 0 != is.readUnsignedByte()? LuaValue.TRUE: LuaValue.FALSE; values[i] = (0 != is.readUnsignedByte()? LuaValue.TRUE: LuaValue.FALSE);
break; break;
case LUA_TINT: case LUA_TINT:
values[i] = LuaInteger.valueOf(loadInt()); values[i] = LuaInteger.valueOf( loadInt() );
break; break;
case LUA_TNUMBER: case LUA_TNUMBER:
values[i] = loadNumber(); values[i] = loadNumber();
@@ -333,34 +295,34 @@ public class LoadState {
f.k = values; f.k = values;
n = loadInt(); n = loadInt();
Prototype[] protos = n > 0? new Prototype[n]: NOPROTOS; Prototype[] protos = n>0? new Prototype[n]: NOPROTOS;
for (int i = 0; i < n; i++) for ( int i=0; i<n; i++ )
protos[i] = loadFunction(f.source); protos[i] = loadFunction(f.source);
f.p = protos; f.p = protos;
} }
void loadUpvalues(Prototype f) throws IOException { void loadUpvalues(Prototype f) throws IOException {
int n = loadInt(); int n = loadInt();
f.upvalues = n > 0? new Upvaldesc[n]: NOUPVALDESCS; f.upvalues = n>0? new Upvaldesc[n]: NOUPVALDESCS;
for (int i = 0; i < n; i++) { for (int i=0; i<n; i++) {
boolean instack = is.readByte() != 0; boolean instack = is.readByte() != 0;
int idx = is.readByte() & 0xff; int idx = ((int) is.readByte()) & 0xff;
f.upvalues[i] = new Upvaldesc(null, instack, idx); f.upvalues[i] = new Upvaldesc(null, instack, idx);
} }
} }
/** /**
* Load the debug info for a function prototype * Load the debug info for a function prototype
*
* @param f the function Prototype * @param f the function Prototype
* @throws IOException if there is an i/o exception * @throws IOException if there is an i/o exception
*/ */
void loadDebug(Prototype f) throws IOException { void loadDebug( Prototype f ) throws IOException {
f.source = loadString(); f.source = loadString();
f.lineinfo = loadIntArray(); f.lineinfo = loadIntArray();
int n = loadInt(); int n = loadInt();
f.locvars = n > 0? new LocVars[n]: NOLOCVARS; f.locvars = n>0? new LocVars[n]: NOLOCVARS;
for (int i = 0; i < n; i++) { for ( int i=0; i<n; i++ ) {
LuaString varname = loadString(); LuaString varname = loadString();
int startpc = loadInt(); int startpc = loadInt();
int endpc = loadInt(); int endpc = loadInt();
@@ -368,13 +330,12 @@ public class LoadState {
} }
n = loadInt(); n = loadInt();
for (int i = 0; i < n; i++) for ( int i=0; i<n; i++ )
f.upvalues[i].name = loadString(); f.upvalues[i].name = loadString();
} }
/** /**
* Load a function prototype from the input stream * Load a function prototype from the input stream
*
* @param p name of the source * @param p name of the source
* @return {@link Prototype} instance that was loaded * @return {@link Prototype} instance that was loaded
* @throws IOException * @throws IOException
@@ -405,47 +366,44 @@ public class LoadState {
/** /**
* Load the lua chunk header values. * Load the lua chunk header values.
*
* @throws IOException if an i/o exception occurs. * @throws IOException if an i/o exception occurs.
*/ */
public void loadHeader() throws IOException { public void loadHeader() throws IOException {
luacVersion = is.readByte(); luacVersion = is.readByte();
luacFormat = is.readByte(); luacFormat = is.readByte();
luacLittleEndian = 0 != is.readByte(); luacLittleEndian = (0 != is.readByte());
luacSizeofInt = is.readByte(); luacSizeofInt = is.readByte();
luacSizeofSizeT = is.readByte(); luacSizeofSizeT = is.readByte();
luacSizeofInstruction = is.readByte(); luacSizeofInstruction = is.readByte();
luacSizeofLuaNumber = is.readByte(); luacSizeofLuaNumber = is.readByte();
luacNumberFormat = is.readByte(); luacNumberFormat = is.readByte();
for (int i = 0; i < LUAC_TAIL.length; ++i) for (int i=0; i < LUAC_TAIL.length; ++i)
if (is.readByte() != LUAC_TAIL[i]) if (is.readByte() != LUAC_TAIL[i])
throw new LuaError("Unexpeted byte in luac tail of header, index=" + i); throw new LuaError("Unexpeted byte in luac tail of header, index="+i);
} }
/** /**
* Load input stream as a lua binary chunk if the first 4 bytes are the lua * Load input stream as a lua binary chunk if the first 4 bytes are the lua binary signature.
* binary signature. * @param stream InputStream to read, after having read the first byte already
*
* @param stream InputStream to read, after having read the first byte
* already
* @param chunkname Name to apply to the loaded chunk * @param chunkname Name to apply to the loaded chunk
* @return {@link Prototype} that was loaded, or null if the first 4 bytes * @return {@link Prototype} that was loaded, or null if the first 4 bytes were not the lua signature.
* were not the lua signature.
* @throws IOException if an IOException occurs * @throws IOException if an IOException occurs
*/ */
public static Prototype undump(InputStream stream, String chunkname) throws IOException { public static Prototype undump(InputStream stream, String chunkname) throws IOException {
// check rest of signature // check rest of signature
if (stream.read() != LUA_SIGNATURE[0] || stream.read() != LUA_SIGNATURE[1] || stream.read() != LUA_SIGNATURE[2] if ( stream.read() != LUA_SIGNATURE[0]
|| stream.read() != LUA_SIGNATURE[3]) || stream.read() != LUA_SIGNATURE[1]
|| stream.read() != LUA_SIGNATURE[2]
|| stream.read() != LUA_SIGNATURE[3] )
return null; return null;
// load file as a compiled chunk // load file as a compiled chunk
String sname = getSourceName(chunkname); String sname = getSourceName(chunkname);
LoadState s = new LoadState(stream, sname); LoadState s = new LoadState( stream, sname );
s.loadHeader(); s.loadHeader();
// check format // check format
switch (s.luacNumberFormat) { switch ( s.luacNumberFormat ) {
case NUMBER_FORMAT_FLOATS_OR_DOUBLES: case NUMBER_FORMAT_FLOATS_OR_DOUBLES:
case NUMBER_FORMAT_INTS_ONLY: case NUMBER_FORMAT_INTS_ONLY:
case NUMBER_FORMAT_NUM_PATCH_INT32: case NUMBER_FORMAT_NUM_PATCH_INT32:
@@ -453,33 +411,32 @@ public class LoadState {
default: default:
throw new LuaError("unsupported int size"); throw new LuaError("unsupported int size");
} }
return s.loadFunction(LuaString.valueOf(sname)); return s.loadFunction( LuaString.valueOf(sname) );
} }
/** /**
* Construct a source name from a supplied chunk name * Construct a source name from a supplied chunk name
*
* @param name String name that appears in the chunk * @param name String name that appears in the chunk
* @return source file name * @return source file name
*/ */
public static String getSourceName(String name) { public static String getSourceName(String name) {
String sname = name; String sname = name;
if (name.startsWith("@") || name.startsWith("=")) if ( name.startsWith("@") || name.startsWith("=") )
sname = name.substring(1); sname = name.substring(1);
else if (name.startsWith("\033")) else if ( name.startsWith("\033") )
sname = SOURCE_BINARY_STRING; sname = SOURCE_BINARY_STRING;
return sname; return sname;
} }
/** Private constructor for create a load state */ /** Private constructor for create a load state */
private LoadState(InputStream stream, String name) { private LoadState( InputStream stream, String name ) {
this.name = name; this.name = name;
this.is = new DataInputStream(stream); this.is = new DataInputStream( stream );
} }
private static final class GlobalsUndumper implements Globals.Undumper { private static final class GlobalsUndumper implements Globals.Undumper {
@Override public Prototype undump(InputStream stream, String chunkname)
public Prototype undump(InputStream stream, String chunkname) throws IOException { throws IOException {
return LoadState.undump(stream, chunkname); return LoadState.undump(stream, chunkname);
} }
} }

Binary file not shown.

View File

@@ -22,8 +22,7 @@
package org.luaj.vm2; package org.luaj.vm2;
/** /**
* Data class to hold debug information relating to local variables for a * Data class to hold debug information relating to local variables for a {@link Prototype}
* {@link Prototype}
*/ */
public class LocVars { public class LocVars {
/** The local variable name */ /** The local variable name */
@@ -37,7 +36,6 @@ public class LocVars {
/** /**
* Construct a LocVars instance. * Construct a LocVars instance.
*
* @param varname The local variable name * @param varname The local variable name
* @param startpc The instruction offset when the variable comes into scope * @param startpc The instruction offset when the variable comes into scope
* @param endpc The instruction offset when the variable goes out of scope * @param endpc The instruction offset when the variable goes out of scope
@@ -49,6 +47,6 @@ public class LocVars {
} }
public String tojstring() { public String tojstring() {
return varname + " " + startpc + "-" + endpc; return varname+" "+startpc+"-"+endpc;
} }
} }

Binary file not shown.

View File

@@ -0,0 +1,375 @@
/*******************************************************************************
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
/**
* Constants for lua limits and opcodes.
* <p>
* This is a direct translation of C lua distribution header file constants
* for bytecode creation and processing.
*/
public class Lua {
/** version is supplied by ant build task */
public static final String _VERSION = "Lua 5.3";
/** use return values from previous op */
public static final int LUA_MULTRET = -1;
// from lopcodes.h
/*===========================================================================
We assume that instructions are unsigned numbers.
All instructions have an opcode in the first 6 bits.
Instructions can have the following fields:
`A' : 8 bits
`B' : 9 bits
`C' : 9 bits
`Bx' : 18 bits (`B' and `C' together)
`sBx' : signed Bx
A signed argument is represented in excess K; that is, the number
value is the unsigned value minus K. K is exactly the maximum value
for that argument (so that -max is represented by 0, and +max is
represented by 2*max), which is half the maximum for the corresponding
unsigned argument.
===========================================================================*/
/* basic instruction format */
public static final int iABC = 0;
public static final int iABx = 1;
public static final int iAsBx = 2;
public static final int iAx = 3;
/*
** size and position of opcode arguments.
*/
public static final int SIZE_C = 9;
public static final int SIZE_B = 9;
public static final int SIZE_Bx = (SIZE_C + SIZE_B);
public static final int SIZE_A = 8;
public static final int SIZE_Ax = (SIZE_C + SIZE_B + SIZE_A);
public static final int SIZE_OP = 6;
public static final int POS_OP = 0;
public static final int POS_A = (POS_OP + SIZE_OP);
public static final int POS_C = (POS_A + SIZE_A);
public static final int POS_B = (POS_C + SIZE_C);
public static final int POS_Bx = POS_C;
public static final int POS_Ax = POS_A;
public static final int MAX_OP = ((1<<SIZE_OP)-1);
public static final int MAXARG_A = ((1<<SIZE_A)-1);
public static final int MAXARG_B = ((1<<SIZE_B)-1);
public static final int MAXARG_C = ((1<<SIZE_C)-1);
public static final int MAXARG_Bx = ((1<<SIZE_Bx)-1);
public static final int MAXARG_sBx = (MAXARG_Bx>>1); /* `sBx' is signed */
public static final int MAXARG_Ax = ((1<<SIZE_Ax)-1);
public static final int MASK_OP = ((1<<SIZE_OP)-1)<<POS_OP;
public static final int MASK_A = ((1<<SIZE_A)-1)<<POS_A;
public static final int MASK_B = ((1<<SIZE_B)-1)<<POS_B;
public static final int MASK_C = ((1<<SIZE_C)-1)<<POS_C;
public static final int MASK_Bx = ((1<<SIZE_Bx)-1)<<POS_Bx;
public static final int MASK_Ax = ((1<<SIZE_Ax)-1)<<POS_Ax;
public static final int MASK_NOT_OP = ~MASK_OP;
public static final int MASK_NOT_A = ~MASK_A;
public static final int MASK_NOT_B = ~MASK_B;
public static final int MASK_NOT_C = ~MASK_C;
public static final int MASK_NOT_Bx = ~MASK_Bx;
/*
** the following macros help to manipulate instructions
*/
public static int GET_OPCODE(int i) {
return (i >> POS_OP) & MAX_OP;
}
public static int GETARG_A(int i) {
return (i >> POS_A) & MAXARG_A;
}
public static int GETARG_Ax(int i) {
return (i >> POS_Ax) & MAXARG_Ax;
}
public static int GETARG_B(int i) {
return (i >> POS_B) & MAXARG_B;
}
public static int GETARG_C(int i) {
return (i >> POS_C) & MAXARG_C;
}
public static int GETARG_Bx(int i) {
return (i >> POS_Bx) & MAXARG_Bx;
}
public static int GETARG_sBx(int i) {
return ((i >> POS_Bx) & MAXARG_Bx) - MAXARG_sBx;
}
/*
** Macros to operate RK indices
*/
/** this bit 1 means constant (0 means register) */
public static final int BITRK = (1 << (SIZE_B - 1));
/** test whether value is a constant */
public static boolean ISK(int x) {
return 0 != ((x) & BITRK);
}
/** gets the index of the constant */
public static int INDEXK(int r) {
return ((int)(r) & ~BITRK);
}
public static final int MAXINDEXRK = (BITRK - 1);
/** code a constant index as a RK value */
public static int RKASK(int x) {
return ((x) | BITRK);
}
/**
** invalid register that fits in 8 bits
*/
public static final int NO_REG = MAXARG_A;
/*
** R(x) - register
** Kst(x) - constant (in constant table)
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
*/
/*
** grep "ORDER OP" if you change these enums
*/
/*----------------------------------------------------------------------
name args description
------------------------------------------------------------------------*/
public static final int OP_MOVE = 0;/* A B R(A) := R(B) */
public static final int OP_LOADK = 1;/* A Bx R(A) := Kst(Bx) */
public static final int OP_LOADKX = 2;/* A R(A) := Kst(extra arg) */
public static final int OP_LOADBOOL = 3;/* A B C R(A) := (Bool)B; if (C) pc++ */
public static final int OP_LOADNIL = 4; /* A B R(A) := ... := R(A+B) := nil */
public static final int OP_GETUPVAL = 5; /* A B R(A) := UpValue[B] */
public static final int OP_GETTABUP = 6; /* A B C R(A) := UpValue[B][RK(C)] */
public static final int OP_GETTABLE = 7; /* A B C R(A) := R(B)[RK(C)] */
public static final int OP_SETTABUP = 8; /* A B C UpValue[A][RK(B)] := RK(C) */
public static final int OP_SETUPVAL = 9; /* A B UpValue[B] := R(A) */
public static final int OP_SETTABLE = 10; /* A B C R(A)[RK(B)] := RK(C) */
public static final int OP_NEWTABLE = 11; /* A B C R(A) := {} (size = B,C) */
public static final int OP_SELF = 12; /* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */
public static final int OP_ADD = 13; /* A B C R(A) := RK(B) + RK(C) */
public static final int OP_SUB = 14; /* A B C R(A) := RK(B) - RK(C) */
public static final int OP_MUL = 15; /* A B C R(A) := RK(B) * RK(C) */
public static final int OP_DIV = 16; /* A B C R(A) := RK(B) / RK(C) */
public static final int OP_IDIV = 17; /* A B C R(A) := RK(B) // RK(C) */
public static final int OP_BAND = 18; /* A B C R(A) := RK(B) & RK(C) */
public static final int OP_BOR = 19; /* A B C R(A) := RK(B) | RK(C) */
public static final int OP_BXOR = 20; /* A B C R(A) := RK(B) ~ RK(C) */
public static final int OP_SHL = 21; /* A B C R(A) := RK(B) << RK(C) */
public static final int OP_SHR = 22; /* A B C R(A) := RK(B) >> RK(C) */
public static final int OP_MOD = 23; /* A B C R(A) := RK(B) % RK(C) */
public static final int OP_POW = 24; /* A B C R(A) := RK(B) ^ RK(C) */
public static final int OP_UNM = 25; /* A B R(A) := -R(B) */
public static final int OP_BNOT = 26; /* A B R(A) := ~R(B) */
public static final int OP_NOT = 27; /* A B R(A) := not R(B) */
public static final int OP_LEN = 28; /* A B R(A) := length of R(B) */
public static final int OP_CONCAT = 29; /* A B C R(A) := R(B).. ... ..R(C) */
public static final int OP_JMP = 30; /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
public static final int OP_EQ = 31; /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
public static final int OP_LT = 32; /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
public static final int OP_LE = 33; /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
public static final int OP_TEST = 34; /* A C if not (R(A) <=> C) then pc++ */
public static final int OP_TESTSET = 35; /* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */
public static final int OP_CALL = 36; /* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_TAILCALL = 37; /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
public static final int OP_RETURN = 38; /* A B return R(A), ... ,R(A+B-2) (see note) */
public static final int OP_FORLOOP = 39; /* A sBx R(A)+=R(A+2);
if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/
public static final int OP_FORPREP = 40; /* A sBx R(A)-=R(A+2); pc+=sBx */
public static final int OP_TFORCALL = 41; /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
public static final int OP_TFORLOOP = 42; /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } */
public static final int OP_SETLIST = 43; /* A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B */
public static final int OP_CLOSURE = 44; /* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */
public static final int OP_VARARG = 45; /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
public static final int OP_EXTRAARG = 46; /* Ax extra (larger) argument for previous opcode */
public static final int NUM_OPCODES = OP_EXTRAARG + 1;
/* pseudo-opcodes used in parsing only. */
public static final int OP_GT = 63; // >
public static final int OP_GE = 62; // >=
public static final int OP_NEQ = 61; // ~=
public static final int OP_AND = 60; // and
public static final int OP_OR = 59; // or
/*===========================================================================
Notes:
(*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,
and can be 0: OP_CALL then sets `top' to last_result+1, so
next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.
(*) In OP_VARARG, if (B == 0) then use actual number of varargs and
set top (like in OP_CALL with C == 0).
(*) In OP_RETURN, if (B == 0) then return up to `top'
(*) In OP_SETLIST, if (B == 0) then B = `top';
if (C == 0) then next `instruction' is real C
(*) For comparisons, A specifies what condition the test should accept
(true or false).
(*) All `skips' (pc++) assume that next instruction is a jump
===========================================================================*/
/*
** masks for instruction properties. The format is:
** bits 0-1: op mode
** bits 2-3: C arg mode
** bits 4-5: B arg mode
** bit 6: instruction set register A
** bit 7: operator is a test
*/
public static final int OpArgN = 0; /* argument is not used */
public static final int OpArgU = 1; /* argument is used */
public static final int OpArgR = 2; /* argument is a register or a jump offset */
public static final int OpArgK = 3; /* argument is a constant or register/constant */
public static final int[] luaP_opmodes = {
/* T A B C mode opcode */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_MOVE */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgN<<2) | (iABx), /* OP_LOADK */
(0<<7) | (1<<6) | (OpArgN<<4) | (OpArgN<<2) | (iABx), /* OP_LOADKX */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_LOADBOOL */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_LOADNIL */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_GETUPVAL */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgK<<2) | (iABC), /* OP_GETTABUP */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_GETTABLE */
(0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SETTABUP */
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_SETUPVAL */
(0<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SETTABLE */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_NEWTABLE */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgK<<2) | (iABC), /* OP_SELF */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_ADD */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SUB */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MUL */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_DIV */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_IDIV */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_BAND */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_BOR */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_BXOR */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SHL */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_SHR */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_MOD */
(0<<7) | (1<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_POW */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_UNM */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_BNOT */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_NOT */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iABC), /* OP_LEN */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgR<<2) | (iABC), /* OP_CONCAT */
(0<<7) | (0<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_JMP */
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_EQ */
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LT */
(1<<7) | (0<<6) | (OpArgK<<4) | (OpArgK<<2) | (iABC), /* OP_LE */
(1<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC), /* OP_TEST */
(1<<7) | (1<<6) | (OpArgR<<4) | (OpArgU<<2) | (iABC), /* OP_TESTSET */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_CALL */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_TAILCALL */
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_RETURN */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORLOOP */
(0<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_FORPREP */
(0<<7) | (0<<6) | (OpArgN<<4) | (OpArgU<<2) | (iABC), /* OP_TFORCALL */
(1<<7) | (1<<6) | (OpArgR<<4) | (OpArgN<<2) | (iAsBx), /* OP_TFORLOOP */
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iABC), /* OP_SETLIST */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABx), /* OP_CLOSURE */
(0<<7) | (1<<6) | (OpArgU<<4) | (OpArgN<<2) | (iABC), /* OP_VARARG */
(0<<7) | (0<<6) | (OpArgU<<4) | (OpArgU<<2) | (iAx), /* OP_EXTRAARG */
};
public static int getOpMode(int m) {
return luaP_opmodes[m] & 3;
}
public static int getBMode(int m) {
return (luaP_opmodes[m] >> 4) & 3;
}
public static int getCMode(int m) {
return (luaP_opmodes[m] >> 2) & 3;
}
public static boolean testAMode(int m) {
return 0 != (luaP_opmodes[m] & (1 << 6));
}
public static boolean testTMode(int m) {
return 0 != (luaP_opmodes[m] & (1 << 7));
}
/* number of list items to accumulate before a SETLIST instruction */
public static final int LFIELDS_PER_FLUSH = 50;
private static final int MAXSRC = 80;
public static String chunkid( String source ) {
if ( source.startsWith("=") )
return source.substring(1);
String end = "";
if ( source.startsWith("@") ) {
source = source.substring(1);
} else {
source = "[string \""+source;
end = "\"]";
}
int n = source.length() + end.length();
if ( n > MAXSRC )
source = source.substring(0,MAXSRC-end.length()-3) + "...";
return source + end;
}
}

Binary file not shown.

View File

@@ -24,16 +24,16 @@ package org.luaj.vm2;
/** /**
* Extension of {@link LuaValue} which can hold a Java boolean as its value. * Extension of {@link LuaValue} which can hold a Java boolean as its value.
* <p> * <p>
* These instance are not instantiated directly by clients. Instead, there are * These instance are not instantiated directly by clients.
* exactly twon instances of this class, {@link LuaValue#TRUE} and * Instead, there are exactly twon instances of this class,
* {@link LuaValue#FALSE} representing the lua values {@code true} and * {@link LuaValue#TRUE} and {@link LuaValue#FALSE}
* {@code false}. The function {@link LuaValue#valueOf(boolean)} will always * representing the lua values {@code true} and {@code false}.
* The function {@link LuaValue#valueOf(boolean)} will always
* return one of these two values. * return one of these two values.
* <p> * <p>
* Any {@link LuaValue} can be converted to its equivalent boolean * Any {@link LuaValue} can be converted to its equivalent
* representation using {@link LuaValue#toboolean()} * boolean representation using {@link LuaValue#toboolean()}
* <p> * <p>
*
* @see LuaValue * @see LuaValue
* @see LuaValue#valueOf(boolean) * @see LuaValue#valueOf(boolean)
* @see LuaValue#TRUE * @see LuaValue#TRUE
@@ -57,56 +57,46 @@ public final class LuaBoolean extends LuaValue {
this.v = b; this.v = b;
} }
@Override
public int type() { public int type() {
return LuaValue.TBOOLEAN; return LuaValue.TBOOLEAN;
} }
@Override
public String typename() { public String typename() {
return "boolean"; return "boolean";
} }
@Override
public boolean isboolean() { public boolean isboolean() {
return true; return true;
} }
@Override
public LuaValue not() { public LuaValue not() {
return v? FALSE: LuaValue.TRUE; return v ? FALSE : LuaValue.TRUE;
} }
/** /**
* Return the boolean value for this boolean * Return the boolean value for this boolean
*
* @return value as a Java boolean * @return value as a Java boolean
*/ */
public boolean booleanValue() { public boolean booleanValue() {
return v; return v;
} }
@Override
public boolean toboolean() { public boolean toboolean() {
return v; return v;
} }
@Override
public String tojstring() { public String tojstring() {
return v? "true": "false"; return v ? "true" : "false";
} }
@Override
public boolean optboolean(boolean defval) { public boolean optboolean(boolean defval) {
return this.v; return this.v;
} }
@Override
public boolean checkboolean() { public boolean checkboolean() {
return v; return v;
} }
@Override
public LuaValue getmetatable() { public LuaValue getmetatable() {
return s_metatable; return s_metatable;
} }

Binary file not shown.

View File

@@ -0,0 +1,692 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import org.luaj.vm2.libs.DebugLib.CallFrame;
import java.util.ArrayList;
import java.util.List;
/**
* Extension of {@link LuaFunction} which executes lua bytecode.
* <p>
* A {@link LuaClosure} is a combination of a {@link Prototype}
* and a {@link LuaValue} to use as an environment for execution.
* Normally the {@link LuaValue} is a {@link Globals} in which case the environment
* will contain standard lua libraries.
*
* <p>
* There are three main ways {@link LuaClosure} instances are created:
* <ul>
* <li>Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}</li>
* <li>Construct it indirectly by loading a chunk via {@link Globals#load(java.io.Reader, String)}
* <li>Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing
* </ul>
* <p>
* To construct it directly, the {@link Prototype} is typically created via a compiler such as
* {@link org.luaj.vm2.compiler.LuaC}:
* <pre> {@code
* String script = "print( 'hello, world' )";
* InputStream is = new ByteArrayInputStream(script.getBytes());
* Prototype p = LuaC.instance.compile(is, "script");
* LuaValue globals = JsePlatform.standardGlobals();
* LuaClosure f = new LuaClosure(p, globals);
* f.call();
* }</pre>
* <p>
* To construct it indirectly, the {@link Globals#load(java.io.Reader, String)} method may be used:
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* LuaFunction f = globals.load(new StringReader(script), "script");
* LuaClosure c = f.checkclosure(); // This may fail if LuaJC is installed.
* c.call();
* }</pre>
* <p>
* In this example, the "checkclosure()" may fail if direct lua-to-java-bytecode
* compiling using LuaJC is installed, because no LuaClosure is created in that case
* and the value returned is a {@link LuaFunction} but not a {@link LuaClosure}.
* <p>
* Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue},
* all the value operations can be used directly such as:
* <ul>
* <li>{@link LuaValue#call()}</li>
* <li>{@link LuaValue#call(LuaValue)}</li>
* <li>{@link LuaValue#invoke()}</li>
* <li>{@link LuaValue#invoke(Varargs)}</li>
* <li>{@link LuaValue#method(String)}</li>
* <li>{@link LuaValue#method(String,LuaValue)}</li>
* <li>{@link LuaValue#invokemethod(String)}</li>
* <li>{@link LuaValue#invokemethod(String,Varargs)}</li>
* <li> ...</li>
* </ul>
* @see LuaValue
* @see LuaFunction
* @see LuaValue#isclosure()
* @see LuaValue#checkclosure()
* @see LuaValue#optclosure(LuaClosure)
* @see LoadState
* @see Globals#compiler
*/
public class LuaClosure extends LuaFunction {
private static final UpValue[] NOUPVALUES = new UpValue[0];
public final Prototype p;
public UpValue[] upValues;
final Globals globals;
/** Create a closure around a Prototype with a specific environment.
* If the prototype has upvalues, the environment will be written into the first upvalue.
* @param p the Prototype to construct this Closure for.
* @param env the environment to associate with the closure.
*/
public LuaClosure(Prototype p, LuaValue env) {
this.p = p;
this.initupvalue1(env);
globals = env instanceof Globals? (Globals) env: null;
}
public void initupvalue1(LuaValue env) {
if (p.upvalues == null || p.upvalues.length == 0)
this.upValues = NOUPVALUES;
else {
this.upValues = new UpValue[p.upvalues.length];
this.upValues[0] = new UpValue(new LuaValue[] {env}, 0);
}
}
public boolean isclosure() {
return true;
}
public LuaClosure optclosure(LuaClosure defval) {
return this;
}
public LuaClosure checkclosure() {
return this;
}
public String tojstring() {
return "function: " + p.toString();
}
private List<LuaValue[]> stackPool = new ArrayList<>();
private LuaValue[] getNewStack() {
if (stackPool.isEmpty()) {
return getNewStackRaw();
} else {
return stackPool.remove(stackPool.size() - 1);
}
}
private LuaValue[] getNewStackRaw() {
int max = p.maxstacksize;
LuaValue[] stack = new LuaValue[max];
System.arraycopy(NILS, 0, stack, 0, max);
return stack;
}
private void releaseStack(LuaValue[] stack) {
System.arraycopy(NILS, 0, stack, 0, stack.length);
stackPool.add(stack);
}
public final LuaValue call() {
LuaValue[] stack = getNewStack();
LuaValue result = execute(stack,NONE).arg1();
releaseStack(stack);
return result;
}
public final LuaValue call(LuaValue arg) {
LuaValue[] stack = getNewStack();
LuaValue result;
switch ( p.numparams ) {
default:
stack[0]=arg;
result = execute(stack,NONE).arg1();
break;
case 0:
result = execute(stack,arg).arg1();
break;
}
releaseStack(stack);
return result;
}
public final LuaValue call(LuaValue arg1, LuaValue arg2) {
LuaValue[] stack = getNewStack();
LuaValue result;
switch ( p.numparams ) {
default:
stack[0]=arg1;
stack[1]=arg2;
result = execute(stack,NONE).arg1();
break;
case 1:
stack[0]=arg1;
result = execute(stack,arg2).arg1();
break;
case 0:
result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2) : NONE).arg1();
break;
}
releaseStack(stack);
return result;
}
public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
LuaValue[] stack = getNewStack();
LuaValue result;
switch ( p.numparams ) {
default:
stack[0]=arg1;
stack[1]=arg2;
stack[2]=arg3;
result = execute(stack,NONE).arg1();
break;
case 2:
stack[0]=arg1;
stack[1]=arg2;
result = execute(stack,arg3).arg1();
break;
case 1:
stack[0]=arg1;
result = execute(stack,p.is_vararg!=0 ? varargsOf(arg2,arg3) : NONE).arg1();
break;
case 0:
result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2,arg3) : NONE).arg1();
break;
}
releaseStack(stack);
return result;
}
public final Varargs invoke(Varargs varargs) {
return onInvoke(varargs).eval();
}
public final Varargs onInvoke(Varargs varargs) {
LuaValue[] stack = getNewStack();
for ( int i=0; i<p.numparams; i++ )
stack[i] = varargs.arg(i+1);
Varargs result = execute(stack,p.is_vararg!=0 ? varargs.subargs(p.numparams+1) : NONE);
if (result instanceof LuaValue) {
releaseStack(stack);
}
return result;
}
protected Varargs execute( LuaValue[] stack, Varargs varargs ) {
// loop through instructions
int i,a,b,c,pc=0,top=0;
LuaValue o;
Varargs v = NONE;
int[] code = p.code;
LuaValue[] k = p.k;
// upvalues are only possible when closures create closures
// TODO: use linked list.
UpValue[] openups = p.p.length>0? new UpValue[stack.length]: null;
// allow for debug hooks
if (globals != null && globals.debuglib != null)
globals.debuglib.onCall( this, varargs, stack );
// process instructions
try {
for (; true; ++pc) {
if (Thread.currentThread().isInterrupted()) {
throw new LuaError("interrupted");
}
if (globals != null && globals.debuglib != null)
globals.debuglib.onInstruction( pc, v, top );
// pull out instruction
i = code[pc];
a = ((i>>6) & 0xff);
// process the op code
switch ( i & 0x3f ) {
case Lua.OP_MOVE:/* A B R(A):= R(B) */
stack[a] = stack[i>>>23];
continue;
case Lua.OP_LOADK:/* A Bx R(A):= Kst(Bx) */
stack[a] = k[i>>>14];
continue;
case Lua.OP_LOADKX:/* A R(A) := Kst(extra arg) */
++pc;
i = code[pc];
if ((i & 0x3f) != Lua.OP_EXTRAARG) {
int op = i & 0x3f;
throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got " +
(op < Print.OPNAMES.length - 1 ? Print.OPNAMES[op] : "UNKNOWN_OP_" + op));
}
stack[a] = k[i>>>6];
continue;
case Lua.OP_LOADBOOL:/* A B C R(A):= (Bool)B: if (C) pc++ */
stack[a] = (i>>>23!=0)? LuaValue.TRUE: LuaValue.FALSE;
if ((i&(0x1ff<<14)) != 0)
++pc; /* skip next instruction (if C) */
continue;
case Lua.OP_LOADNIL: /* A B R(A):= ...:= R(A+B):= nil */
for ( b=i>>>23; b-->=0; )
stack[a++] = LuaValue.NIL;
continue;
case Lua.OP_GETUPVAL: /* A B R(A):= UpValue[B] */
stack[a] = upValues[i>>>23].getValue();
continue;
case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
stack[a] = upValues[i>>>23].getValue().get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_GETTABLE: /* A B C R(A):= R(B)[RK(C)] */
stack[a] = stack[i>>>23].get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
upValues[a].getValue().set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
upValues[i>>>23].setValue(stack[a]);
continue;
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
stack[a].set(((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]), (c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
stack[a] = new LuaTable(i>>>23,(i>>14)&0x1ff);
continue;
case Lua.OP_SELF: /* A B C R(A+1):= R(B): R(A):= R(B)[RK(C)] */
stack[a+1] = (o = stack[i>>>23]);
stack[a] = o.get((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).add((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).sub((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mul((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).div((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_IDIV: /* A B C R(A):= RK(B) // RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).idiv((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_BAND: /* A B C R(A):= RK(B) & RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).band((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_BOR: /* A B C R(A):= RK(B) | RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).bor((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_BXOR: /* A B C R(A):= RK(B) ~ RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).bxor((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_SHL: /* A B C R(A):= RK(B) << RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).shl((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_SHR: /* A B C R(A):= RK(B) >> RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).shr((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).mod((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
stack[a] = ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).pow((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]);
continue;
case Lua.OP_UNM: /* A B R(A):= -R(B) */
stack[a] = stack[i>>>23].neg();
continue;
case Lua.OP_BNOT: /* A B R(A):= ~R(B) */
stack[a] = stack[i>>>23].bnot();
continue;
case Lua.OP_NOT: /* A B R(A):= not R(B) */
stack[a] = stack[i>>>23].not();
continue;
case Lua.OP_LEN: /* A B R(A):= length of R(B) */
stack[a] = stack[i>>>23].len();
continue;
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
b = i>>>23;
c = (i>>14)&0x1ff;
{
if ( c > b+1 ) {
Buffer sb = stack[c].buffer();
while ( --c>=b )
sb.concatTo(stack[c]);
stack[a] = sb.value();
} else {
stack[a] = stack[c-1].concat(stack[c]);
}
}
continue;
case Lua.OP_JMP: /* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */
pc += (i>>>14)-0x1ffff;
if (a > 0) {
for (--a, b = openups.length; --b>=0; )
if (openups[b] != null && openups[b].index >= a) {
openups[b].close();
openups[b] = null;
}
}
continue;
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).eq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
++pc;
continue;
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lt_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
++pc;
continue;
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
if ( ((b=i>>>23)>0xff? k[b&0x0ff]: stack[b]).lteq_b((c=(i>>14)&0x1ff)>0xff? k[c&0x0ff]: stack[c]) != (a!=0) )
++pc;
continue;
case Lua.OP_TEST: /* A C if not (R(A) <=> C) then pc++ */
if ( stack[a].toboolean() != ((i&(0x1ff<<14))!=0) )
++pc;
continue;
case Lua.OP_TESTSET: /* A B C if (R(B) <=> C) then R(A):= R(B) else pc++ */
/* note: doc appears to be reversed */
if ( (o=stack[i>>>23]).toboolean() != ((i&(0x1ff<<14))!=0) )
++pc;
else
stack[a] = o; // TODO: should be sBx?
continue;
case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
switch ( i & (Lua.MASK_B | Lua.MASK_C) ) {
case (1<<Lua.POS_B) | (0<<Lua.POS_C): v=stack[a].invoke(NONE); top=a+v.narg(); continue;
case (2<<Lua.POS_B) | (0<<Lua.POS_C): v=stack[a].invoke(stack[a+1]); top=a+v.narg(); continue;
case (1<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(); continue;
case (2<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1]); continue;
case (3<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2]); continue;
case (4<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue;
case (1<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(); continue;
case (2<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1]); continue;
case (3<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2]); continue;
case (4<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue;
default:
b = i>>>23;
c = (i>>14)&0x1ff;
v = stack[a].invoke(b>0?
varargsOf(stack, a+1, b-1): // exact arg count
varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
if ( c > 0 ) {
v.copyto(stack, a, c-1);
v = NONE;
} else {
top = a + v.narg();
v = v.dealias();
}
continue;
}
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
switch ( i & Lua.MASK_B ) {
case (1<<Lua.POS_B): return new TailcallVarargs(stack[a], NONE);
case (2<<Lua.POS_B): return new TailcallVarargs(stack[a], stack[a+1]);
case (3<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2]));
case (4<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2],stack[a+3]));
default:
b = i>>>23;
v = b>0?
varargsOf(stack,a+1,b-1): // exact arg count
varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top
return new TailcallVarargs( stack[a], v );
}
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
b = i>>>23;
switch ( b ) {
case 0: return varargsOf(stack, a, top-v.narg()-a, v);
case 1: return NONE;
case 2: return stack[a];
default:
return varargsOf(stack, a, b-1);
}
case Lua.OP_FORLOOP: /* A sBx R(A)+=R(A+2): if R(A) <?= R(A+1) then { pc+=sBx: R(A+3)=R(A) }*/
{
LuaValue limit = stack[a + 1];
LuaValue step = stack[a + 2];
LuaValue idx = stack[a].add(step);
if (step.gt_b(0)? idx.lteq_b(limit): idx.gteq_b(limit)) {
stack[a] = idx;
stack[a + 3] = idx;
pc += (i>>>14)-0x1ffff;
}
}
continue;
case Lua.OP_FORPREP: /* A sBx R(A)-=R(A+2): pc+=sBx */
{
LuaValue init = stack[a].checknumber("'for' initial value must be a number");
LuaValue limit = stack[a + 1].checknumber("'for' limit must be a number");
LuaValue step = stack[a + 2].checknumber("'for' step must be a number");
stack[a] = init.sub(step);
stack[a + 1] = limit;
stack[a + 2] = step;
pc += (i>>>14)-0x1ffff;
}
continue;
case Lua.OP_TFORCALL: /* A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); */
v = stack[a].invoke(varargsOf(stack[a+1],stack[a+2]));
c = (i>>14) & 0x1ff;
while (--c >= 0)
stack[a+3+c] = v.arg(c+1);
v = NONE;
continue;
case Lua.OP_TFORLOOP: /* A sBx if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx */
if (!stack[a+1].isnil()) { /* continue loop? */
stack[a] = stack[a+1]; /* save control varible. */
pc += (i>>>14)-0x1ffff;
}
continue;
case Lua.OP_SETLIST: /* A B C R(A)[(C-1)*FPF+i]:= R(A+i), 1 <= i <= B */
{
if ( (c=(i>>14)&0x1ff) == 0 )
c = code[++pc];
int offset = (c-1) * Lua.LFIELDS_PER_FLUSH;
o = stack[a];
if ( (b=i>>>23) == 0 ) {
b = top - a - 1;
int m = b - v.narg();
int j=1;
for ( ;j<=m; j++ )
o.set(offset+j, stack[a + j]);
for ( ;j<=b; j++ )
o.set(offset+j, v.arg(j-m));
} else {
o.presize( offset + b );
for (int j=1; j<=b; j++)
o.set(offset+j, stack[a + j]);
}
}
continue;
case Lua.OP_CLOSURE: /* A Bx R(A):= closure(KPROTO[Bx]) */
{
Prototype newp = p.p[i>>>14];
LuaClosure ncl = new LuaClosure(newp, globals);
Upvaldesc[] uv = newp.upvalues;
for ( int j=0, nup=uv.length; j<nup; ++j ) {
if (uv[j].instack) /* upvalue refes to local variable? */
ncl.upValues[j] = findupval(stack, uv[j].idx, openups);
else /* get upvalue from enclosing function */
ncl.upValues[j] = upValues[uv[j].idx];
}
stack[a] = ncl;
}
continue;
case Lua.OP_VARARG: /* A B R(A), R(A+1), ..., R(A+B-1) = vararg */
b = i>>>23;
if ( b == 0 ) {
top = a + (b = varargs.narg());
v = varargs;
} else {
for ( int j=1; j<b; ++j )
stack[a+j-1] = varargs.arg(j);
}
continue;
case Lua.OP_EXTRAARG:
throw new java.lang.IllegalArgumentException("Uexecutable opcode: OP_EXTRAARG");
default:
throw new java.lang.IllegalArgumentException("Illegal opcode: " + (i & 0x3f));
}
}
} catch ( LuaError le ) {
if (le.traceback == null)
processErrorHooks(le, p, pc);
throw le;
} catch ( Exception e ) {
LuaError le = new LuaError(e);
processErrorHooks(le, p, pc);
throw le;
} finally {
if ( openups != null )
for ( int u=openups.length; --u>=0; )
if ( openups[u] != null )
openups[u].close();
if (globals != null && globals.debuglib != null)
globals.debuglib.onReturn();
}
}
/**
* Run the error hook if there is one
* @param msg the message to use in error hook processing.
* */
LuaValue errorHook(LuaValue msgobj, String msg, int level) {
if (globals == null ) return LuaValue.valueOf(msg);
final LuaThread r = globals.running;
if (r.errorfunc == null)
return LuaValue.valueOf(globals.debuglib != null?
msg + "\n" + globals.debuglib.traceback(level):
msg);
final LuaValue e = r.errorfunc;
r.errorfunc = null;
try {
return e.call(msgobj != null ? msgobj : LuaValue.NIL);
} catch ( Throwable t ) {
return LuaValue.valueOf("error in error handling");
} finally {
r.errorfunc = e;
}
}
private void processErrorHooks(LuaError le, Prototype p, int pc) {
String file = "?";
int line = -1;
{
CallFrame frame = null;
if (globals != null && globals.debuglib != null) {
frame = globals.debuglib.getCallFrame(le.level);
if (frame != null) {
String src = frame.shortsource();
file = src != null ? src : "?";
line = frame.currentline();
}
}
if (frame == null) {
file = p.source != null? p.source.tojstring(): "?";
line = p.lineinfo != null && pc >= 0 && pc < p.lineinfo.length ? p.lineinfo[pc] : -1;
}
}
le.fileline = file + ":" + line;
LuaValue error = errorHook(le.getMessageObject(), le.getMessage(), le.level);
le.setMessageObject(error);
le.traceback = error != null ? error.tojstring() : null;
}
private UpValue findupval(LuaValue[] stack, short idx, UpValue[] openups) {
final int n = openups.length;
for (int i = 0; i < n; ++i)
if (openups[i] != null && openups[i].index == idx)
return openups[i];
for (int i = 0; i < n; ++i)
if (openups[i] == null)
return openups[i] = new UpValue(stack, idx);
error("No space for upvalue");
return null;
}
protected LuaValue getUpvalue(int i) {
return upValues[i].getValue();
}
protected void setUpvalue(int i, LuaValue v) {
upValues[i].setValue(v);
}
public String name() {
return "<"+p.shortsource()+":"+p.linedefined+">";
}
}

Binary file not shown.

View File

@@ -21,8 +21,7 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2; package org.luaj.vm2;
import org.luaj.vm2.compat.JavaCompat; import org.luaj.vm2.libs.MathLib;
import org.luaj.vm2.lib.MathLib;
/** /**
* Extension of {@link LuaNumber} which can hold a Java double as its value. * Extension of {@link LuaNumber} which can hold a Java double as its value.
@@ -34,8 +33,8 @@ import org.luaj.vm2.lib.MathLib;
* <p> * <p>
* Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}. * Almost all API's implemented in LuaDouble are defined and documented in {@link LuaValue}.
* <p> * <p>
* However the constants {@link #NAN}, {@link #NEGNAN}, {@link #POSINF}, {@link #NEGINF}, * However the constants {@link #NAN}, {@link #POSINF}, {@link #NEGINF},
* {@link #JSTR_NAN}, {@link #JSTR_NEGNAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be useful * {@link #JSTR_NAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be useful
* when dealing with Nan or Infinite values. * when dealing with Nan or Infinite values.
* <p> * <p>
* LuaDouble also defines functions for handling the unique math rules of lua devision and modulo in * LuaDouble also defines functions for handling the unique math rules of lua devision and modulo in
@@ -57,9 +56,6 @@ public class LuaDouble extends LuaNumber {
/** Constant LuaDouble representing NaN (not a number) */ /** Constant LuaDouble representing NaN (not a number) */
public static final LuaDouble NAN = new LuaDouble( Double.NaN ); public static final LuaDouble NAN = new LuaDouble( Double.NaN );
/** Constant LuaDouble representing negative NaN (not a number) */
public static final LuaDouble NEGNAN = new LuaDouble( -Double.NaN );
/** Constant LuaDouble representing positive infinity */ /** Constant LuaDouble representing positive infinity */
public static final LuaDouble POSINF = new LuaDouble( Double.POSITIVE_INFINITY ); public static final LuaDouble POSINF = new LuaDouble( Double.POSITIVE_INFINITY );
@@ -69,9 +65,6 @@ public class LuaDouble extends LuaNumber {
/** Constant String representation for NaN (not a number), "nan" */ /** Constant String representation for NaN (not a number), "nan" */
public static final String JSTR_NAN = "nan"; public static final String JSTR_NAN = "nan";
/** Constant String representation for negative NaN (not a number), "-nan" */
public static final String JSTR_NEGNAN = "-nan";
/** Constant String representation for positive infinity, "inf" */ /** Constant String representation for positive infinity, "inf" */
public static final String JSTR_POSINF = "inf"; public static final String JSTR_POSINF = "inf";
@@ -82,8 +75,13 @@ public class LuaDouble extends LuaNumber {
final double v; final double v;
public static LuaNumber valueOf(double d) { public static LuaNumber valueOf(double d) {
int id = (int) d; if (!Double.isNaN(d) && !Double.isInfinite(d) && d >= Long.MIN_VALUE && d <= Long.MAX_VALUE) {
return d==id? (LuaNumber) LuaInteger.valueOf(id): (LuaNumber) new LuaDouble(d); long ld = (long) d;
if (d == ld) {
return LuaInteger.valueOf(ld);
}
}
return new LuaDouble(d);
} }
/** Don't allow ints to be boxed by DoubleValues */ /** Don't allow ints to be boxed by DoubleValues */
@@ -110,13 +108,14 @@ public class LuaDouble extends LuaNumber {
public double optdouble(double defval) { return v; } public double optdouble(double defval) { return v; }
public int optint(int defval) { return (int) (long) v; } public int optint(int defval) { return (int) (long) v; }
public LuaInteger optinteger(LuaInteger defval) { return LuaInteger.valueOf((int) (long)v); } public LuaInteger optinteger(LuaInteger defval) { return islong()? LuaInteger.valueOf((long) v): defval; }
public long optlong(long defval) { return (long) v; } public long optlong(long defval) { return (long) v; }
public LuaInteger checkinteger() { return LuaInteger.valueOf( (int) (long) v ); } public LuaInteger checkinteger() { if (!islong()) argerror("integer"); return LuaInteger.valueOf((long) v); }
// unary operators // unary operators
public LuaValue neg() { return valueOf(-v); } public LuaValue neg() { return valueOf(-v); }
public LuaValue bnot() { if (!islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(~((long) v)); }
// object equality, used for key comparison // object equality, used for key comparison
public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; } public boolean equals(Object o) { return o instanceof LuaDouble? ((LuaDouble)o).v == v: false; }
@@ -129,6 +128,7 @@ public class LuaDouble extends LuaNumber {
public boolean raweq( LuaValue val ) { return val.raweq(v); } public boolean raweq( LuaValue val ) { return val.raweq(v); }
public boolean raweq( double val ) { return v == val; } public boolean raweq( double val ) { return v == val; }
public boolean raweq( int val ) { return v == val; } public boolean raweq( int val ) { return v == val; }
public boolean raweq( long val ) { return v == val; }
// basic binary arithmetic // basic binary arithmetic
public LuaValue add( LuaValue rhs ) { return rhs.add(v); } public LuaValue add( LuaValue rhs ) { return rhs.add(v); }
@@ -146,9 +146,18 @@ public class LuaDouble extends LuaNumber {
public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); } public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); }
public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); } public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); }
public LuaValue div( LuaValue rhs ) { return rhs.divInto(v); } public LuaValue div( LuaValue rhs ) { return rhs.divInto(v); }
public LuaValue idiv( LuaValue rhs ) { return rhs.idivInto(v); }
public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); } public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); }
public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); } public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); }
public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); } public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); }
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(v,rhs); }
public LuaValue idiv( int rhs ) { return LuaDouble.didiv(v,rhs); }
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
public LuaValue band( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.band(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) v) & n.tolong()); }
public LuaValue bor( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) v) | n.tolong()); }
public LuaValue bxor( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bxor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) v) ^ n.tolong()); }
public LuaValue shl( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shl(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftLeft((long) v, n.tolong())); }
public LuaValue shr( LuaValue rhs ) { if (!islong()) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shr(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftRight((long) v, n.tolong())); }
public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); } public LuaValue mod( LuaValue rhs ) { return rhs.modFrom(v); }
public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); } public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); }
public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); } public LuaValue mod( int rhs ) { return LuaDouble.dmod(v,rhs); }
@@ -166,6 +175,10 @@ public class LuaDouble extends LuaNumber {
return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF; return rhs!=0? valueOf( lhs / rhs ): lhs>0? POSINF: lhs==0? NAN: NEGINF;
} }
public static LuaValue didiv(double lhs, double rhs) {
return valueOf(Math.floor(ddiv_d(lhs, rhs)));
}
/** Divide two double numbers according to lua math, and return a double result. /** Divide two double numbers according to lua math, and return a double result.
* @param lhs Left-hand-side of the division. * @param lhs Left-hand-side of the division.
* @param rhs Right-hand-side of the division. * @param rhs Right-hand-side of the division.
@@ -242,13 +255,17 @@ public class LuaDouble extends LuaNumber {
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; } public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
public String tojstring() { public String tojstring() {
if ( v == 0.0 ) // never occurs on J2ME /*
return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? "-0": "0"); if ( v == 0.0 ) { // never occurs in J2me
long bits = Double.doubleToLongBits( v );
return ( bits >> 63 == 0 ) ? "0" : "-0";
}
*/
long l = (long) v; long l = (long) v;
if ( l == v ) if ( l == v )
return Long.toString(l); return Long.toString(l);
if ( Double.isNaN(v) ) if ( Double.isNaN(v) )
return (JavaCompat.INSTANCE.doubleToRawLongBits(v)<0? JSTR_NEGNAN: JSTR_NAN); return JSTR_NAN;
if ( Double.isInfinite(v) ) if ( Double.isInfinite(v) )
return (v<0? JSTR_NEGINF: JSTR_POSINF); return (v<0? JSTR_NEGINF: JSTR_POSINF);
return Float.toString((float)v); return Float.toString((float)v);

Binary file not shown.

View File

@@ -21,21 +21,22 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2; package org.luaj.vm2;
/** /**
* RuntimeException that is thrown and caught in response to a lua error. * RuntimeException that is thrown and caught in response to a lua error.
* <p> * <p>
* {@link LuaError} is used wherever a lua call to {@code error()} would be used * {@link LuaError} is used wherever a lua call to {@code error()}
* within a script. * would be used within a script.
* <p> * <p>
* Since it is an unchecked exception inheriting from {@link RuntimeException}, * Since it is an unchecked exception inheriting from {@link RuntimeException},
* Java method signatures do notdeclare this exception, althoug it can be thrown * Java method signatures do notdeclare this exception, althoug it can
* on almost any luaj Java operation. This is analagous to the fact that any lua * be thrown on almost any luaj Java operation.
* script can throw a lua error at any time. * This is analagous to the fact that any lua script can throw a lua error at any time.
* <p> * <p>
* The LuaError may be constructed with a message object, in which case the * The LuaError may be constructed with a message object, in which case the message
* message is the string representation of that object. getMessageObject will * is the string representation of that object. getMessageObject will get the object
* get the object supplied at construct time, or a LuaString containing the * supplied at construct time, or a LuaString containing the message of an object
* message of an object was not supplied. * was not supplied.
*/ */
public class LuaError extends RuntimeException { public class LuaError extends RuntimeException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -50,11 +51,9 @@ public class LuaError extends RuntimeException {
private LuaValue object; private LuaValue object;
/** /** Get the string message if it was supplied, or a string
* Get the string message if it was supplied, or a string representation of * representation of the message object if that was supplied.
* the message object if that was supplied.
*/ */
@Override
public String getMessage() { public String getMessage() {
if (traceback != null) if (traceback != null)
return traceback; return traceback;
@@ -62,33 +61,32 @@ public class LuaError extends RuntimeException {
if (m == null) if (m == null)
return null; return null;
if (fileline != null) if (fileline != null)
return fileline + m; return fileline + " " + m;
return m; return m;
} }
/** /** Get the LuaValue that was provided in the constructor, or
* Get the LuaValue that was provided in the constructor, or a LuaString * a LuaString containing the message if it was a string error argument.
* containing the message if it was a string error argument.
*
* @return LuaValue which was used in the constructor, or a LuaString * @return LuaValue which was used in the constructor, or a LuaString
* containing the message. * containing the message.
*/ */
public LuaValue getMessageObject() { public LuaValue getMessageObject() {
if (object != null) if (object != null) return object;
return object;
String m = getMessage(); String m = getMessage();
return m != null? LuaValue.valueOf(m): null; return m != null ? LuaValue.valueOf(m): null;
} }
/** public void setMessageObject(LuaValue messageObject) {
* Construct LuaError when a program exception occurs. this.object = messageObject;
}
/** Construct LuaError when a program exception occurs.
* <p> * <p>
* All errors generated from lua code should throw LuaError(String) instead. * All errors generated from lua code should throw LuaError(String) instead.
*
* @param cause the Throwable that caused the error, if known. * @param cause the Throwable that caused the error, if known.
*/ */
public LuaError(Throwable cause) { public LuaError(Throwable cause) {
super("vm error: " + cause); super( "vm error: "+cause );
this.cause = cause; this.cause = cause;
this.level = 1; this.level = 1;
} }
@@ -99,38 +97,38 @@ public class LuaError extends RuntimeException {
* @param message message to supply * @param message message to supply
*/ */
public LuaError(String message) { public LuaError(String message) {
super(message); super( message );
this.level = 1; this.level = 1;
} }
/** /**
* Construct a LuaError with a message, and level to draw line number * Construct a LuaError with a message, and level to draw line number information from.
* information from.
*
* @param message message to supply * @param message message to supply
* @param level where to supply line info from in call stack * @param level where to supply line info from in call stack
*/ */
public LuaError(String message, int level) { public LuaError(String message, int level) {
super(message); super( message );
this.level = level; this.level = level;
} }
/** /**
* Construct a LuaError with a LuaValue as the message object, and level to * Construct a LuaError with a LuaValue as the message object,
* draw line number information from. * and level to draw line number information from.
*
* @param message_object message string or object to supply * @param message_object message string or object to supply
*/ */
public LuaError(LuaValue message_object) { public LuaError(LuaValue message_object) {
super(message_object.tojstring()); super( message_object.tojstring() );
this.object = message_object; this.object = message_object;
this.level = 1; this.level = 1;
} }
/** /**
* Get the cause, if any. * Get the cause, if any.
*/ */
@Override public Throwable getCause() {
public Throwable getCause() { return cause; } return cause;
}
} }

Binary file not shown.

View File

@@ -21,86 +21,71 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2; package org.luaj.vm2;
/** /**
* Base class for functions implemented in Java. * Base class for functions implemented in Java.
* <p> * <p>
* Direct subclass include {@link org.luaj.vm2.lib.LibFunction} which is the * Direct subclass include {@link org.luaj.vm2.libs.LibFunction}
* base class for all built-in library functions coded in Java, and * which is the base class for
* {@link LuaClosure}, which represents a lua closure whose bytecode is * all built-in library functions coded in Java,
* interpreted when the function is invoked. * and {@link LuaClosure}, which represents a lua closure
* * whose bytecode is interpreted when the function is invoked.
* @see LuaValue * @see LuaValue
* @see LuaClosure * @see LuaClosure
* @see org.luaj.vm2.lib.LibFunction * @see org.luaj.vm2.libs.LibFunction
*/ */
abstract public class LuaFunction extends LuaValue { abstract
public class LuaFunction extends LuaValue {
/** Shared static metatable for all functions and closures. */ /** Shared static metatable for all functions and closures. */
public static LuaValue s_metatable; public static LuaValue s_metatable;
@Override
public int type() { public int type() {
return TFUNCTION; return TFUNCTION;
} }
@Override
public String typename() { public String typename() {
return "function"; return "function";
} }
@Override
public boolean isfunction() { public boolean isfunction() {
return true; return true;
} }
@Override
public LuaFunction checkfunction() { public LuaFunction checkfunction() {
return this; return this;
} }
@Override
public LuaFunction optfunction(LuaFunction defval) { public LuaFunction optfunction(LuaFunction defval) {
return this; return this;
} }
@Override
public LuaValue getmetatable() { public LuaValue getmetatable() {
return s_metatable; return s_metatable;
} }
@Override
public String tojstring() { public String tojstring() {
return "function: " + classnamestub(); return "function: " + classnamestub();
} }
@Override
public LuaString strvalue() { public LuaString strvalue() {
return valueOf(tojstring()); return valueOf(tojstring());
} }
/** /** Return the last part of the class name, to be used as a function name in tojstring and elsewhere.
* Return the last part of the class name, to be used as a function name in * @return String naming the last part of the class name after the last dot (.) or dollar sign ($).
* tojstring and elsewhere. * If the first character is '_', it is skipped.
*
* @return String naming the last part of the class name after the last dot
* (.) or dollar sign ($). If the first character is '_', it is
* skipped.
*/ */
public String classnamestub() { public String classnamestub() {
String s = getClass().getName(); String s = getClass().getName();
int offset = Math.max(s.lastIndexOf('.'), s.lastIndexOf('$'))+1; int offset = Math.max(s.lastIndexOf('.'), s.lastIndexOf('$')) + 1;
if (s.charAt(offset) == '_') if (s.charAt(offset) == '_') offset++;
offset++;
return s.substring(offset); return s.substring(offset);
} }
/** /** Return a human-readable name for this function. Returns the last part of the class name by default.
* Return a human-readable name for this function. Returns the last part of * Is overridden by LuaClosure to return the source file and line, and by LibFunctions to return the name.
* the class name by default. Is overridden by LuaClosure to return the * @return common name for this function. */
* source file and line, and by LibFunctions to return the name.
*
* @return common name for this function.
*/
public String name() { public String name() {
return classnamestub(); return classnamestub();
} }

Binary file not shown.

View File

@@ -0,0 +1,265 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import org.luaj.vm2.libs.MathLib;
/**
* Extension of {@link LuaNumber} which can hold a Java long as its value.
* <p>
* These instance are not instantiated directly by clients, but indirectly
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
* functions. This ensures that policies regarding pooling of instances are
* encapsulated.
* <p>
* There are no API's specific to LuaInteger that are useful beyond what is already
* exposed in {@link LuaValue}.
*
* @see LuaValue
* @see LuaNumber
* @see LuaDouble
* @see LuaValue#valueOf(int)
* @see LuaValue#valueOf(double)
*/
public class LuaInteger extends LuaNumber {
private static final LuaInteger[] intValues = new LuaInteger[512];
static {
for ( int i=0; i<512; i++ )
intValues[i] = new LuaInteger(i-256);
}
public static LuaInteger valueOf(int i) {
return i<=255 && i>=-256? intValues[i+256]: new LuaInteger(i);
};
// TODO consider moving this to LuaValue
/** Return a LuaNumber that represents the value provided
* @param l long value to represent.
* @return LuaNumber that is eithe LuaInteger or LuaDouble representing l
* @see LuaValue#valueOf(int)
* @see LuaValue#valueOf(double)
*/
public static LuaInteger valueOf(long l) {
int i = (int) l;
return l == i && i <= 255 && i >= -256 ? intValues[i+256] : new LuaInteger(l);
}
/** The value being held by this instance. */
public final long v;
/**
* Package protected constructor.
* @see LuaValue#valueOf(int)
**/
LuaInteger(long i) {
this.v = i;
}
public boolean isint() { return v == (int) v; }
public boolean isinttype() { return true; }
public boolean islong() { return true; }
public byte tobyte() { return (byte) v; }
public char tochar() { return (char) v; }
public double todouble() { return v; }
public float tofloat() { return v; }
public int toint() { return (int) v; }
public long tolong() { return v; }
public short toshort() { return (short) v; }
public double optdouble(double defval) { return v; }
public int optint(int defval) { return (int) v; }
public LuaInteger optinteger(LuaInteger defval) { return this; }
public long optlong(long defval) { return v; }
public String tojstring() {
return Long.toString(v);
}
public LuaString strvalue() {
return LuaString.valueOf(Long.toString(v));
}
public LuaString optstring(LuaString defval) {
return LuaString.valueOf(Long.toString(v));
}
public LuaValue tostring() {
return LuaString.valueOf(Long.toString(v));
}
public String optjstring(String defval) {
return Long.toString(v);
}
public LuaInteger checkinteger() {
return this;
}
public boolean isstring() {
return true;
}
public int hashCode() {
return hashCode(v);
}
public static int hashCode(long x) {
return (int) (x ^ (x >>> 32));
}
// unary operators
public LuaValue neg() { return valueOf(-(long)v); }
public LuaValue bnot() { return valueOf(~v); }
// object equality, used for key comparison
public boolean equals(Object o) { return o instanceof LuaInteger? ((LuaInteger)o).v == v: false; }
// equality w/ metatable processing
public LuaValue eq( LuaValue val ) { return val.raweq(v)? TRUE: FALSE; }
public boolean eq_b( LuaValue val ) { return val.raweq(v); }
// equality w/o metatable processing
public boolean raweq( LuaValue val ) { return val.raweq(v); }
public boolean raweq( double val ) { return v == val; }
public boolean raweq( int val ) { return v == val; }
public boolean raweq( long val ) { return v == val; }
// arithmetic operators
public LuaValue add( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.add(rhs): (n.isinttype()? LuaInteger.valueOf(v + n.tolong()): LuaDouble.valueOf(v + n.todouble())); }
public LuaValue add( double lhs ) { return LuaDouble.valueOf(lhs + v); }
public LuaValue add( int lhs ) { return LuaInteger.valueOf(lhs + v); }
public LuaValue sub( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.sub(rhs): (n.isinttype()? LuaInteger.valueOf(v - n.tolong()): LuaDouble.valueOf(v - n.todouble())); }
public LuaValue sub( double rhs ) { return LuaDouble.valueOf(v - rhs); }
public LuaValue sub( int rhs ) { return LuaInteger.valueOf(v - rhs); }
public LuaValue subFrom( double lhs ) { return LuaDouble.valueOf(lhs - v); }
public LuaValue subFrom( int lhs ) { return LuaInteger.valueOf(lhs - v); }
public LuaValue mul( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.mul(rhs): (n.isinttype()? LuaInteger.valueOf(v * n.tolong()): LuaDouble.valueOf(v * n.todouble())); }
public LuaValue mul( double lhs ) { return LuaDouble.valueOf(lhs * v); }
public LuaValue mul( int lhs ) { return LuaInteger.valueOf(lhs * v); }
public LuaValue pow( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.pow(rhs): MathLib.dpow(v, n.todouble()); }
public LuaValue pow( double rhs ) { return MathLib.dpow(v,rhs); }
public LuaValue pow( int rhs ) { return MathLib.dpow(v,rhs); }
public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs,v); }
public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs,v); }
public LuaValue div( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.div(rhs): LuaDouble.ddiv(v, n.todouble()); }
public LuaValue idiv( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.idiv(rhs): (n.isinttype()? LuaInteger.valueOf(luaFloorDiv(v, n.tolong())): LuaDouble.didiv(v, n.todouble())); }
public LuaValue div( double rhs ) { return LuaDouble.ddiv(v,rhs); }
public LuaValue div( int rhs ) { return LuaDouble.ddiv(v,rhs); }
public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs,v); }
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(v,rhs); }
public LuaValue idiv( int rhs ) { return LuaInteger.valueOf(luaFloorDiv(v, rhs)); }
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs,v); }
public LuaValue band( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.band(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(v & n.tolong()); }
public LuaValue bor( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bor(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(v | n.tolong()); }
public LuaValue bxor( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bxor(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(v ^ n.tolong()); }
public LuaValue shl( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shl(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(luaShiftLeft(v, n.tolong())); }
public LuaValue shr( LuaValue rhs ) { LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shr(rhs); if (!n.islong()) throw bitwiseError(); return LuaInteger.valueOf(luaShiftRight(v, n.tolong())); }
public LuaValue mod( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.mod(rhs): (n.isinttype()? LuaInteger.valueOf(luaFloorMod(v, n.tolong())): LuaDouble.dmod(v, n.todouble())); }
public LuaValue mod( double rhs ) { return LuaDouble.dmod(v,rhs); }
public LuaValue mod( int rhs ) { return LuaInteger.valueOf(luaFloorMod(v, rhs)); }
public LuaValue modFrom( double lhs ) { return LuaDouble.dmod(lhs,v); }
// relational operators
public LuaValue lt( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lt(rhs): (n.isinttype()? (v < n.tolong()? TRUE: FALSE): (v < n.todouble()? TRUE: FALSE)); }
public LuaValue lt( double rhs ) { return v < rhs? TRUE: FALSE; }
public LuaValue lt( int rhs ) { return v < rhs? TRUE: FALSE; }
public boolean lt_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lt_b(rhs): (n.isinttype()? v < n.tolong(): v < n.todouble()); }
public boolean lt_b( int rhs ) { return v < rhs; }
public boolean lt_b( double rhs ) { return v < rhs; }
public LuaValue lteq( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lteq(rhs): (n.isinttype()? (v <= n.tolong()? TRUE: FALSE): (v <= n.todouble()? TRUE: FALSE)); }
public LuaValue lteq( double rhs ) { return v <= rhs? TRUE: FALSE; }
public LuaValue lteq( int rhs ) { return v <= rhs? TRUE: FALSE; }
public boolean lteq_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.lteq_b(rhs): (n.isinttype()? v <= n.tolong(): v <= n.todouble()); }
public boolean lteq_b( int rhs ) { return v <= rhs; }
public boolean lteq_b( double rhs ) { return v <= rhs; }
public LuaValue gt( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gt(rhs): (n.isinttype()? (v > n.tolong()? TRUE: FALSE): (v > n.todouble()? TRUE: FALSE)); }
public LuaValue gt( double rhs ) { return v > rhs? TRUE: FALSE; }
public LuaValue gt( int rhs ) { return v > rhs? TRUE: FALSE; }
public boolean gt_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gt_b(rhs): (n.isinttype()? v > n.tolong(): v > n.todouble()); }
public boolean gt_b( int rhs ) { return v > rhs; }
public boolean gt_b( double rhs ) { return v > rhs; }
public LuaValue gteq( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gteq(rhs): (n.isinttype()? (v >= n.tolong()? TRUE: FALSE): (v >= n.todouble()? TRUE: FALSE)); }
public LuaValue gteq( double rhs ) { return v >= rhs? TRUE: FALSE; }
public LuaValue gteq( int rhs ) { return v >= rhs? TRUE: FALSE; }
public boolean gteq_b( LuaValue rhs ) { LuaValue n = rhs.tonumber(); return n.isnil()? super.gteq_b(rhs): (n.isinttype()? v >= n.tolong(): v >= n.todouble()); }
public boolean gteq_b( int rhs ) { return v >= rhs; }
public boolean gteq_b( double rhs ) { return v >= rhs; }
// string comparison
public int strcmp( LuaString rhs ) { typerror("attempt to compare number with string"); return 0; }
public int checkint() {
return (int) v;
}
public long checklong() {
return v;
}
public double checkdouble() {
return v;
}
public String checkjstring() {
return String.valueOf(v);
}
public LuaString checkstring() {
return valueOf( String.valueOf(v) );
}
private static long luaFloorDiv(long lhs, long rhs) {
if (rhs == 0) {
throw new LuaError("attempt to divide by zero");
}
long quotient = lhs / rhs;
long remainder = lhs % rhs;
if (remainder != 0 && ((lhs ^ rhs) < 0)) {
quotient--;
}
return quotient;
}
private static long luaFloorMod(long lhs, long rhs) {
if (rhs == 0) {
throw new LuaError("attempt to divide by zero");
}
return lhs - rhs * luaFloorDiv(lhs, rhs);
}
static long luaShiftLeft(long lhs, long rhs) {
if (rhs < 0) {
return luaShiftRight(lhs, -rhs);
}
return rhs >= Long.SIZE ? 0L : lhs << rhs;
}
static long luaShiftRight(long lhs, long rhs) {
if (rhs < 0) {
return luaShiftLeft(lhs, -rhs);
}
return rhs >= Long.SIZE ? 0L : lhs >>> rhs;
}
private static LuaError bitwiseError() {
return new LuaError("number has no integer representation");
}
}

Binary file not shown.

View File

@@ -24,16 +24,16 @@ package org.luaj.vm2;
/** /**
* Class to encapsulate behavior of the singleton instance {@code nil} * Class to encapsulate behavior of the singleton instance {@code nil}
* <p> * <p>
* There will be one instance of this class, {@link LuaValue#NIL}, per Java * There will be one instance of this class, {@link LuaValue#NIL},
* virtual machine. However, the {@link Varargs} instance {@link LuaValue#NONE} * per Java virtual machine.
* which is the empty list, is also considered treated as a nil value by * However, the {@link Varargs} instance {@link LuaValue#NONE}
* default. * which is the empty list,
* is also considered treated as a nil value by default.
* <p> * <p>
* Although it is possible to test for nil using Java == operator, the * Although it is possible to test for nil using Java == operator,
* recommended approach is to use the method {@link LuaValue#isnil()} instead. * the recommended approach is to use the method {@link LuaValue#isnil()}
* By using that any ambiguities between {@link LuaValue#NIL} and * instead. By using that any ambiguities between
* {@link LuaValue#NONE} are avoided. * {@link LuaValue#NIL} and {@link LuaValue#NONE} are avoided.
*
* @see LuaValue * @see LuaValue
* @see LuaValue#NIL * @see LuaValue#NIL
*/ */
@@ -45,104 +45,64 @@ public class LuaNil extends LuaValue {
LuaNil() {} LuaNil() {}
@Override
public int type() { public int type() {
return LuaValue.TNIL; return LuaValue.TNIL;
} }
@Override
public String toString() { public String toString() {
return "nil"; return "nil";
} }
@Override
public String typename() { public String typename() {
return "nil"; return "nil";
} }
@Override
public String tojstring() { public String tojstring() {
return "nil"; return "nil";
} }
@Override
public LuaValue not() { public LuaValue not() {
return LuaValue.TRUE; return LuaValue.TRUE;
} }
@Override
public boolean toboolean() { public boolean toboolean() {
return false; return false;
} }
@Override
public boolean isnil() { public boolean isnil() {
return true; return true;
} }
@Override
public LuaValue getmetatable() { public LuaValue getmetatable() {
return s_metatable; return s_metatable;
} }
@Override
public boolean equals(Object o) { public boolean equals(Object o) {
return o instanceof LuaNil; return o instanceof LuaNil;
} }
@Override
public LuaValue checknotnil() { public LuaValue checknotnil() {
return argerror("value"); return argerror("value");
} }
@Override
public boolean isvalidkey() { public boolean isvalidkey() {
return false; return false;
} }
// optional argument conversions - nil alwas falls badk to default value // optional argument conversions - nil alwas falls badk to default value
@Override
public boolean optboolean(boolean defval) { return defval; } public boolean optboolean(boolean defval) { return defval; }
@Override
public LuaClosure optclosure(LuaClosure defval) { return defval; } public LuaClosure optclosure(LuaClosure defval) { return defval; }
@Override
public double optdouble(double defval) { return defval; } public double optdouble(double defval) { return defval; }
@Override
public LuaFunction optfunction(LuaFunction defval) { return defval; } public LuaFunction optfunction(LuaFunction defval) { return defval; }
@Override
public int optint(int defval) { return defval; } public int optint(int defval) { return defval; }
@Override
public LuaInteger optinteger(LuaInteger defval) { return defval; } public LuaInteger optinteger(LuaInteger defval) { return defval; }
@Override
public long optlong(long defval) { return defval; } public long optlong(long defval) { return defval; }
@Override
public LuaNumber optnumber(LuaNumber defval) { return defval; } public LuaNumber optnumber(LuaNumber defval) { return defval; }
@Override
public LuaTable opttable(LuaTable defval) { return defval; } public LuaTable opttable(LuaTable defval) { return defval; }
@Override
public LuaThread optthread(LuaThread defval) { return defval; } public LuaThread optthread(LuaThread defval) { return defval; }
@Override
public String optjstring(String defval) { return defval; } public String optjstring(String defval) { return defval; }
@Override
public LuaString optstring(LuaString defval) { return defval; } public LuaString optstring(LuaString defval) { return defval; }
@Override
public Object optuserdata(Object defval) { return defval; } public Object optuserdata(Object defval) { return defval; }
@Override
public Object optuserdata(Class c, Object defval) { return defval; } public Object optuserdata(Class c, Object defval) { return defval; }
@Override
public LuaValue optvalue(LuaValue defval) { return defval; } public LuaValue optvalue(LuaValue defval) { return defval; }
} }

Binary file not shown.

View File

@@ -24,74 +24,58 @@ package org.luaj.vm2;
/** /**
* Base class for representing numbers as lua values directly. * Base class for representing numbers as lua values directly.
* <p> * <p>
* The main subclasses are {@link LuaInteger} which holds values that fit in a * The main subclasses are {@link LuaInteger} which holds values that fit in a java int,
* java int, and {@link LuaDouble} which holds all other number values. * and {@link LuaDouble} which holds all other number values.
*
* @see LuaInteger * @see LuaInteger
* @see LuaDouble * @see LuaDouble
* @see LuaValue * @see LuaValue
* *
*/ */
abstract public class LuaNumber extends LuaValue { abstract
public class LuaNumber extends LuaValue {
/** Shared static metatable for all number values represented in lua. */ /** Shared static metatable for all number values represented in lua. */
public static LuaValue s_metatable; public static LuaValue s_metatable;
@Override
public int type() { public int type() {
return TNUMBER; return TNUMBER;
} }
@Override
public String typename() { public String typename() {
return "number"; return "number";
} }
@Override
public LuaNumber checknumber() { public LuaNumber checknumber() {
return this; return this;
} }
@Override
public LuaNumber checknumber(String errmsg) { public LuaNumber checknumber(String errmsg) {
return this; return this;
} }
@Override
public LuaNumber optnumber(LuaNumber defval) { public LuaNumber optnumber(LuaNumber defval) {
return this; return this;
} }
@Override
public LuaValue tonumber() { public LuaValue tonumber() {
return this; return this;
} }
@Override
public boolean isnumber() { public boolean isnumber() {
return true; return true;
} }
@Override
public boolean isstring() { public boolean isstring() {
return true; return true;
} }
@Override
public LuaValue getmetatable() { public LuaValue getmetatable() {
return s_metatable; return s_metatable;
} }
@Override
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); } public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
@Override
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); } public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
@Override
public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); } public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); }
@Override
public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); } public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); }
} }

Binary file not shown.

View File

@@ -28,7 +28,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintStream; import java.io.PrintStream;
import org.luaj.vm2.lib.MathLib; import org.luaj.vm2.libs.MathLib;
/** /**
* Subclass of {@link LuaValue} for representing lua strings. * Subclass of {@link LuaValue} for representing lua strings.
@@ -262,6 +262,7 @@ public class LuaString extends LuaValue {
// unary operators // unary operators
public LuaValue neg() { double d = scannumber(); return Double.isNaN(d)? super.neg(): valueOf(-d); } public LuaValue neg() { double d = scannumber(); return Double.isNaN(d)? super.neg(): valueOf(-d); }
public LuaValue bnot() { double d = scannumber(); if (Double.isNaN(d)) return super.bnot(); if (d != (long) d) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(~((long) d)); }
// basic binary arithmetic // basic binary arithmetic
public LuaValue add( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(ADD,rhs): rhs.add(d); } public LuaValue add( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(ADD,rhs): rhs.add(d); }
@@ -280,9 +281,18 @@ public class LuaString extends LuaValue {
public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs, checkarith()); } public LuaValue powWith( double lhs ) { return MathLib.dpow(lhs, checkarith()); }
public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs, checkarith()); } public LuaValue powWith( int lhs ) { return MathLib.dpow(lhs, checkarith()); }
public LuaValue div( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(DIV,rhs): rhs.divInto(d); } public LuaValue div( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(DIV,rhs): rhs.divInto(d); }
public LuaValue idiv( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(IDIV,rhs): rhs.idivInto(d); }
public LuaValue div( double rhs ) { return LuaDouble.ddiv(checkarith(),rhs); } public LuaValue div( double rhs ) { return LuaDouble.ddiv(checkarith(),rhs); }
public LuaValue div( int rhs ) { return LuaDouble.ddiv(checkarith(),rhs); } public LuaValue div( int rhs ) { return LuaDouble.ddiv(checkarith(),rhs); }
public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs, checkarith()); } public LuaValue divInto( double lhs ) { return LuaDouble.ddiv(lhs, checkarith()); }
public LuaValue idiv( double rhs ) { return LuaDouble.didiv(checkarith(),rhs); }
public LuaValue idiv( int rhs ) { return LuaDouble.didiv(checkarith(),rhs); }
public LuaValue idivInto( double lhs ) { return LuaDouble.didiv(lhs, checkarith()); }
public LuaValue band( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.band(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.band(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) d) & n.tolong()); }
public LuaValue bor( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.bor(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) d) | n.tolong()); }
public LuaValue bxor( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.bxor(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.bxor(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(((long) d) ^ n.tolong()); }
public LuaValue shl( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.shl(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shl(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftLeft((long) d, n.tolong())); }
public LuaValue shr( LuaValue rhs ) { double d = scannumber(); if (Double.isNaN(d)) return super.shr(rhs); if (d != (long) d) throw new LuaError("number has no integer representation"); LuaValue n = rhs.tonumber(); if (n.isnil()) return super.shr(rhs); if (!n.islong()) throw new LuaError("number has no integer representation"); return LuaInteger.valueOf(LuaInteger.luaShiftRight((long) d, n.tolong())); }
public LuaValue mod( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(MOD,rhs): rhs.modFrom(d); } public LuaValue mod( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(MOD,rhs): rhs.modFrom(d); }
public LuaValue mod( double rhs ) { return LuaDouble.dmod(checkarith(), rhs); } public LuaValue mod( double rhs ) { return LuaDouble.dmod(checkarith(), rhs); }
public LuaValue mod( int rhs ) { return LuaDouble.dmod(checkarith(), rhs); } public LuaValue mod( int rhs ) { return LuaDouble.dmod(checkarith(), rhs); }
@@ -340,10 +350,16 @@ public class LuaString extends LuaValue {
return (int) (long) checkdouble(); return (int) (long) checkdouble();
} }
public LuaInteger checkinteger() { public LuaInteger checkinteger() {
return valueOf(checkint()); double d = scannumber();
if (Double.isNaN(d) || d != (long) d)
argerror("integer");
return LuaInteger.valueOf((long) d);
} }
public long checklong() { public long checklong() {
return (long) checkdouble(); double d = scannumber();
if (Double.isNaN(d) || d != (long) d)
argerror("integer");
return (long) d;
} }
public double checkdouble() { public double checkdouble() {
double d = scannumber(); double d = scannumber();
@@ -639,15 +655,9 @@ public class LuaString extends LuaValue {
public static String decodeAsUtf8(byte[] bytes, int offset, int length) { public static String decodeAsUtf8(byte[] bytes, int offset, int length) {
int i,j,n,b; int i,j,n,b;
for ( i=offset,j=offset+length,n=0; i<j; ++n ) { for ( i=offset,j=offset+length,n=0; i<j; ++n ) {
byte v = bytes[i++]; switch ( 0xE0 & bytes[i++] ) {
if ((v & 0xC0) == 0xC0) { case 0xE0: ++i;
++i; case 0xC0: ++i;
if ((v & 0xE0) == 0xE0) {
++i;
if ((v & 0xF0) == 0xF0) {
++i;
}
}
} }
} }
char[] chars=new char[n]; char[] chars=new char[n];
@@ -669,24 +679,11 @@ public class LuaString extends LuaValue {
* @see #isValidUtf8() * @see #isValidUtf8()
*/ */
public static int lengthAsUtf8(char[] chars) { public static int lengthAsUtf8(char[] chars) {
int i, b; int i,b;
char c; char c;
for (i = 0, b = 0; i < chars.length; i++) { for ( i=b=chars.length; --i>=0; )
if ((c = chars[i]) < 0x80 || (c >= 0xdc00 && c < 0xe000)) { if ( (c=chars[i]) >=0x80 )
b += 1; b += (c>=0x800)? 2: 1;
} else if (c < 0x800) {
b += 2;
} else if (c >= 0xd800 && c < 0xdc00) {
if (i + 1 < chars.length && chars[i+1] >= 0xdc00 && chars[i+1] < 0xe000) {
b += 4;
i++;
} else {
b += 1;
}
} else {
b += 3;
}
}
return b; return b;
} }
@@ -708,28 +705,16 @@ public class LuaString extends LuaValue {
public static int encodeToUtf8(char[] chars, int nchars, byte[] bytes, int off) { public static int encodeToUtf8(char[] chars, int nchars, byte[] bytes, int off) {
char c; char c;
int j = off; int j = off;
for (int i = 0; i < nchars; i++) { for ( int i=0; i<nchars; i++ ) {
if ((c = chars[i]) < 0x80) { if ( (c = chars[i]) < 0x80 ) {
bytes[j++] = (byte) c; bytes[j++] = (byte) c;
} else if (c < 0x800) { } else if ( c < 0x800 ) {
bytes[j++] = (byte) (0xC0 | ((c >> 6))); bytes[j++] = (byte) (0xC0 | ((c>>6) & 0x1f));
bytes[j++] = (byte) (0x80 | (c & 0x3f)); bytes[j++] = (byte) (0x80 | ( c & 0x3f));
} else if (c >= 0xd800 && c < 0xdc00) {
if (i + 1 < nchars && chars[i+1] >= 0xdc00 && chars[i+1] < 0xe000) {
int uc = 0x10000 + (((c & 0x3ff) << 10) | (chars[++i] & 0x3ff));
bytes[j++] = (byte) (0xF0 | ((uc >> 18)));
bytes[j++] = (byte) (0x80 | ((uc >> 12) & 0x3f));
bytes[j++] = (byte) (0x80 | ((uc >> 6) & 0x3f));
bytes[j++] = (byte) (0x80 | (uc & 0x3f));
} else { } else {
bytes[j++] = (byte) '?'; bytes[j++] = (byte) (0xE0 | ((c>>12) & 0x0f));
} bytes[j++] = (byte) (0x80 | ((c>>6) & 0x3f));
} else if (c >= 0xdc00 && c < 0xe000) { bytes[j++] = (byte) (0x80 | ( c & 0x3f));
bytes[j++] = (byte) '?';
} else {
bytes[j++] = (byte) (0xE0 | ((c >> 12)));
bytes[j++] = (byte) (0x80 | ((c >> 6) & 0x3f));
bytes[j++] = (byte) (0x80 | (c & 0x3f));
} }
} }
return j - off; return j - off;
@@ -742,16 +727,16 @@ public class LuaString extends LuaValue {
* @see #decodeAsUtf8(byte[], int, int) * @see #decodeAsUtf8(byte[], int, int)
*/ */
public boolean isValidUtf8() { public boolean isValidUtf8() {
for (int i = m_offset, j = m_offset + m_length; i < j;) { for (int i=m_offset,j=m_offset+m_length; i<j;) {
int c = m_bytes[i++]; int c = m_bytes[i++];
if (c >= 0) if ( c >= 0 ) continue;
continue; if ( ((c & 0xE0) == 0xC0)
if (((c & 0xE0) == 0xC0) && i < j && (m_bytes[i++] & 0xC0) == 0x80) && i<j
continue; && (m_bytes[i++] & 0xC0) == 0x80) continue;
if (((c & 0xF0) == 0xE0) && i + 1 < j && (m_bytes[i++] & 0xC0) == 0x80 && (m_bytes[i++] & 0xC0) == 0x80) if ( ((c & 0xF0) == 0xE0)
continue; && i+1<j
if (((c & 0xF8) == 0xF0) && i + 2 < j && (m_bytes[i++] & 0xC0) == 0x80 && (m_bytes[i++] & 0xC0) == 0x80 && (m_bytes[i++] & 0xC0) == 0x80) && (m_bytes[i++] & 0xC0) == 0x80
continue; && (m_bytes[i++] & 0xC0) == 0x80) continue;
return false; return false;
} }
return true; return true;
@@ -781,86 +766,24 @@ public class LuaString extends LuaValue {
return Double.isNaN(d)? NIL: valueOf(d); return Double.isNaN(d)? NIL: valueOf(d);
} }
private boolean isspace(byte c) {
return c == ' ' || (c >= '\t' && c <= '\r');
}
private boolean isdigit(byte c) {
return (c >= '0' && c <= '9');
}
private boolean isxdigit(byte c) {
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}
private int hexvalue(byte c) {
return c <= '9' ? c - '0' : c <= 'F' ? c + 10 - 'A' : c + 10 - 'a';
}
/** /**
* Convert to a number in base 10, or base 16 if the string starts with '0x', * Convert to a number in base 10, or base 16 if the string starts with '0x',
* or return Double.NaN if it cannot be converted to a number. * or return Double.NaN if it cannot be converted to a number.
* @return double value if conversion is valid, or Double.NaN if not * @return double value if conversion is valid, or Double.NaN if not
*/ */
public double scannumber() { public double scannumber() {
int i = m_offset, j = m_offset + m_length; int i=m_offset,j=m_offset+m_length;
while (i < j && isspace(m_bytes[i])) while ( i<j && m_bytes[i]==' ' ) ++i;
++i; while ( i<j && m_bytes[j-1]==' ' ) --j;
while (i < j && isspace(m_bytes[j - 1])) if ( i>=j )
--j;
if (i >= j)
return Double.NaN; return Double.NaN;
if (indexOf((byte) 'x', i - m_offset) != -1 || indexOf((byte) 'X', i - m_offset) != -1) int prefix = (m_bytes[i] == '+' || m_bytes[i] == '-') ? i + 1 : i;
return strx2number(i, j); if (prefix + 1 < j && m_bytes[prefix]=='0' && (m_bytes[prefix+1]=='x'||m_bytes[prefix+1]=='X')) {
return scandouble(i, j); double l = scanlong(16, prefix + 2, j, i != prefix);
return Double.isNaN(l)? scandouble(i,j): l;
} }
double l = scanlong(10, i, j);
private double strx2number(int start, int end) { return Double.isNaN(l)? scandouble(i,j): l;
double sgn = (m_bytes[start] == '-') ? -1.0 : 1.0;
if (sgn == -1.0 || m_bytes[start] == '+')
++start;
if (start + 2 >= end)
return Double.NaN;
if (m_bytes[start++] != '0')
return Double.NaN;
if (m_bytes[start] != 'x' && m_bytes[start] != 'X')
return Double.NaN;
++start;
double m = 0;
int e = 0;
boolean i = isxdigit(m_bytes[start]);
while (start < end && isxdigit(m_bytes[start]))
m = (m * 16) + hexvalue(m_bytes[start++]);
if (start < end && m_bytes[start] == '.') {
++start;
while (start < end && isxdigit(m_bytes[start])) {
m = (m * 16) + hexvalue(m_bytes[start++]);
e -= 4;
}
}
if (!i && e == 0)
return Double.NaN;
if (start < end && (m_bytes[start] == 'p' || m_bytes[start] == 'P')) {
++start;
int exp1 = 0;
boolean neg1 = false;
if (start < end) {
if (m_bytes[start] == '-')
neg1 = true;
if (neg1 || m_bytes[start] == '+')
++start;
}
if (start >= end || !isdigit(m_bytes[start]))
return Double.NaN;
while (start < end && isdigit(m_bytes[start]))
exp1 = exp1 * 10 + m_bytes[start++] - '0';
if (neg1)
exp1 = -exp1;
e += exp1;
}
if (start != end)
return Double.NaN;
return sgn * m * MathLib.dpow_d(2.0, e);
} }
/** /**
@@ -872,8 +795,8 @@ public class LuaString extends LuaValue {
if ( base < 2 || base > 36 ) if ( base < 2 || base > 36 )
return Double.NaN; return Double.NaN;
int i=m_offset,j=m_offset+m_length; int i=m_offset,j=m_offset+m_length;
while ( i<j && isspace(m_bytes[i]) ) ++i; while ( i<j && m_bytes[i]==' ' ) ++i;
while ( i<j && isspace(m_bytes[j-1]) ) --j; while ( i<j && m_bytes[j-1]==' ' ) --j;
if ( i>=j ) if ( i>=j )
return Double.NaN; return Double.NaN;
return scanlong( base, i, j ); return scanlong( base, i, j );
@@ -888,9 +811,14 @@ public class LuaString extends LuaValue {
* or Double.NaN if not * or Double.NaN if not
*/ */
private double scanlong( int base, int start, int end ) { private double scanlong( int base, int start, int end ) {
return scanlong(base, start, end, false);
}
private double scanlong( int base, int start, int end, boolean hasSign ) {
long x = 0; long x = 0;
boolean neg = (m_bytes[start] == '-'); boolean neg = hasSign && m_bytes[start - 1] == '-';
if (neg || m_bytes[start] == '+') start++; if (start >= end)
return Double.NaN;
for ( int i=start; i<end; i++ ) { for ( int i=start; i<end; i++ ) {
int digit = m_bytes[i] - (base<=10||(m_bytes[i]>='0'&&m_bytes[i]<='9')? '0': int digit = m_bytes[i] - (base<=10||(m_bytes[i]>='0'&&m_bytes[i]<='9')? '0':
m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10)); m_bytes[i]>='A'&&m_bytes[i]<='Z'? ('A'-10): ('a'-10));

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,309 @@
/*******************************************************************************
* Copyright (c) 2007-2012 LuaJ. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Subclass of {@link LuaValue} that implements
* a lua coroutine thread using Java Threads.
* <p>
* A LuaThread is typically created in response to a scripted call to
* {@code coroutine.create()}
* <p>
* The threads must be initialized with the globals, so that
* the global environment may be passed along according to rules of lua.
* This is done via the constructor arguments {@link #LuaThread(Globals)} or
* {@link #LuaThread(Globals, LuaValue)}.
* <p>
* The utility classes {@link org.luaj.vm2.libs.jse.JsePlatform} and
* {@link org.luaj.vm2.libs.jme.JmePlatform}
* see to it that this {@link Globals} are initialized properly.
* <p>
* The behavior of coroutine threads matches closely the behavior
* of C coroutine library. However, because of the use of Java threads
* to manage call state, it is possible to yield from anywhere in luaj.
* <p>
* Each Java thread wakes up at regular intervals and checks a weak reference
* to determine if it can ever be resumed. If not, it throws
* {@link OrphanedThread} which is an {@link java.lang.Error}.
* Applications should not catch {@link OrphanedThread}, because it can break
* the thread safety of luaj. The value controlling the polling interval
* is {@link #thread_orphan_check_interval} and may be set by the user.
* <p>
* There are two main ways to abandon a coroutine. The first is to call
* {@code yield()} from lua, or equivalently {@link Globals#yield(Varargs)},
* and arrange to have it never resumed possibly by values passed to yield.
* The second is to throw {@link OrphanedThread}, which should put the thread
* in a dead state. In either case all references to the thread must be
* dropped, and the garbage collector must run for the thread to be
* garbage collected.
*
*
* @see LuaValue
* @see org.luaj.vm2.libs.jse.JsePlatform
* @see org.luaj.vm2.libs.jme.JmePlatform
* @see org.luaj.vm2.libs.CoroutineLib
*/
public class LuaThread extends LuaValue {
/** Shared metatable for lua threads. */
public static LuaValue s_metatable;
/** The current number of coroutines. Should not be set. */
public static int coroutine_count = 0;
/** Polling interval, in milliseconds, which each thread uses while waiting to
* return from a yielded state to check if the lua threads is no longer
* referenced and therefore should be garbage collected.
* A short polling interval for many threads will consume server resources.
* Orphaned threads cannot be detected and collected unless garbage
* collection is run. This can be changed by Java startup code if desired.
*/
public static long thread_orphan_check_interval = 5000;
public static final String USE_PLATFORM_THREAD = "USE_PLATFORM_THREAD";
private static boolean SUPPORT_VIRTUAL_THREAD = false;
static {
try {
Thread.class.getMethod("ofVirtual");
SUPPORT_VIRTUAL_THREAD = true;
} catch (Exception e) {
//e.printStackTrace();
}
}
public static final int STATUS_INITIAL = 0;
public static final int STATUS_SUSPENDED = 1;
public static final int STATUS_RUNNING = 2;
public static final int STATUS_NORMAL = 3;
public static final int STATUS_DEAD = 4;
public static final String[] STATUS_NAMES = {
"suspended",
"suspended",
"running",
"normal",
"dead",};
public final State state;
public static final int MAX_CALLSTACK = 256;
/** Thread-local used by DebugLib to store debugging state.
* This is an opaque value that should not be modified by applications. */
public Object callstack;
public final Globals globals;
/** Error message handler for this thread, if any. */
public LuaValue errorfunc;
/** Private constructor for main thread only */
public LuaThread(Globals globals) {
state = new State(globals, this, null);
state.status = STATUS_RUNNING;
this.globals = globals;
}
/**
* Create a LuaThread around a function and environment
* @param func The function to execute
*/
public LuaThread(Globals globals, LuaValue func) {
LuaValue.assert_(func != null, "function cannot be null");
state = new State(globals, this, func);
this.globals = globals;
}
public int type() {
return LuaValue.TTHREAD;
}
public String typename() {
return "thread";
}
public boolean isthread() {
return true;
}
public LuaThread optthread(LuaThread defval) {
return this;
}
public LuaThread checkthread() {
return this;
}
public LuaValue getmetatable() {
return s_metatable;
}
public String getStatus() {
return STATUS_NAMES[state.status];
}
public boolean isMainThread() {
return this.state.function == null;
}
public Varargs resume(Varargs args) {
final LuaThread.State s = this.state;
if (s.status > LuaThread.STATUS_SUSPENDED)
return LuaValue.varargsOf(LuaValue.FALSE,
LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine"));
return s.lua_resume(this, args);
}
public static class State implements Runnable {
private final Globals globals;
final WeakReference lua_thread;
public final LuaValue function;
Varargs args = LuaValue.NONE;
Varargs result = LuaValue.NONE;
String error = null;
/** Hook function control state used by debug lib. */
public LuaValue hookfunc;
public boolean hookline;
public boolean hookcall;
public boolean hookrtrn;
public int hookcount;
public boolean inhook;
public int lastline;
public int bytecodes;
public int status = LuaThread.STATUS_INITIAL;
private Lock locker = new ReentrantLock();
private Condition cond = locker.newCondition();
State(Globals globals, LuaThread lua_thread, LuaValue function) {
this.globals = globals;
this.lua_thread = new WeakReference(lua_thread);
this.function = function;
}
public void run() {
locker.lock();
try {
try {
Varargs a = this.args;
this.args = LuaValue.NONE;
this.result = function.invoke(a);
} catch (Throwable t) {
this.error = t.getMessage();
} finally {
this.status = LuaThread.STATUS_DEAD;
cond.signal();
}
} finally {
locker.unlock();
}
}
public Varargs lua_resume(LuaThread new_thread, Varargs args) {
locker.lock();
try {
LuaThread previous_thread = globals.running;
try {
globals.running = new_thread;
this.args = args;
if (this.status == STATUS_INITIAL) {
this.status = STATUS_RUNNING;
Thread t = null;
if(SUPPORT_VIRTUAL_THREAD) {
LuaValue setting = globals.get(USE_PLATFORM_THREAD);
if(setting.isnil()) {//default
if(Thread.currentThread().isVirtual()) {
t = Thread.ofVirtual().name("Coroutine-"+(++coroutine_count)).start(this);
}
} else {
if(!setting.toboolean()) {
t = Thread.ofVirtual().name("Coroutine-"+(++coroutine_count)).start(this);
}
}
}
if (t == null){
new Thread(this, "Coroutine-"+(++coroutine_count)).start();
}
} else {
cond.signal();
}
if (previous_thread != null)
previous_thread.state.status = STATUS_NORMAL;
this.status = STATUS_RUNNING;
cond.await();
return (this.error != null?
LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)):
LuaValue.varargsOf(LuaValue.TRUE, this.result));
} catch (InterruptedException ie) {
throw new OrphanedThread();
} finally {
this.args = LuaValue.NONE;
this.result = LuaValue.NONE;
this.error = null;
globals.running = previous_thread;
if (previous_thread != null)
globals.running.state.status =STATUS_RUNNING;
}
} finally {
locker.unlock();
}
}
public Varargs lua_yield(Varargs args) {
locker.lock();
try {
try {
this.result = args;
this.status = STATUS_SUSPENDED;
cond.signal();
do {
cond.await(thread_orphan_check_interval,TimeUnit.MILLISECONDS);
if (this.lua_thread.get() == null) {
this.status = STATUS_DEAD;
throw new OrphanedThread();
}
} while (this.status == STATUS_SUSPENDED);
return this.args;
} catch (InterruptedException ie) {
this.status = STATUS_DEAD;
throw new OrphanedThread();
} finally {
this.args = LuaValue.NONE;
this.result = LuaValue.NONE;
}
} finally {
locker.unlock();
}
}
}
}

Binary file not shown.

View File

@@ -21,6 +21,7 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2; package org.luaj.vm2;
public class LuaUserdata extends LuaValue { public class LuaUserdata extends LuaValue {
public Object m_instance; public Object m_instance;
@@ -35,22 +36,18 @@ public class LuaUserdata extends LuaValue {
m_metatable = metatable; m_metatable = metatable;
} }
@Override
public String tojstring() { public String tojstring() {
return String.valueOf(m_instance); return String.valueOf(m_instance);
} }
@Override
public int type() { public int type() {
return LuaValue.TUSERDATA; return LuaValue.TUSERDATA;
} }
@Override
public String typename() { public String typename() {
return "userdata"; return "userdata";
} }
@Override
public int hashCode() { public int hashCode() {
return m_instance.hashCode(); return m_instance.hashCode();
} }
@@ -59,98 +56,71 @@ public class LuaUserdata extends LuaValue {
return m_instance; return m_instance;
} }
@Override
public boolean isuserdata() { return true; } public boolean isuserdata() { return true; }
@Override
public boolean isuserdata(Class c) { return c.isAssignableFrom(m_instance.getClass()); } public boolean isuserdata(Class c) { return c.isAssignableFrom(m_instance.getClass()); }
@Override
public Object touserdata() { return m_instance; } public Object touserdata() { return m_instance; }
@Override
public Object touserdata(Class c) { return c.isAssignableFrom(m_instance.getClass())? m_instance: null; } public Object touserdata(Class c) { return c.isAssignableFrom(m_instance.getClass())? m_instance: null; }
@Override
public Object optuserdata(Object defval) { return m_instance; } public Object optuserdata(Object defval) { return m_instance; }
@Override
public Object optuserdata(Class c, Object defval) { public Object optuserdata(Class c, Object defval) {
if (!c.isAssignableFrom(m_instance.getClass())) if (!c.isAssignableFrom(m_instance.getClass()))
typerror(c.getName()); typerror(c.getName());
return m_instance; return m_instance;
} }
@Override
public LuaValue getmetatable() { public LuaValue getmetatable() {
return m_metatable; return m_metatable;
} }
@Override
public LuaValue setmetatable(LuaValue metatable) { public LuaValue setmetatable(LuaValue metatable) {
this.m_metatable = metatable; this.m_metatable = metatable;
return this; return this;
} }
@Override
public Object checkuserdata() { public Object checkuserdata() {
return m_instance; return m_instance;
} }
@Override
public Object checkuserdata(Class c) { public Object checkuserdata(Class c) {
if (c.isAssignableFrom(m_instance.getClass())) if ( c.isAssignableFrom(m_instance.getClass()) )
return m_instance; return m_instance;
return typerror(c.getName()); return typerror(c.getName());
} }
@Override public LuaValue get( LuaValue key ) {
public LuaValue get(LuaValue key) { return m_metatable!=null? gettable(this,key): NIL;
return m_metatable != null? gettable(this, key): NIL;
} }
@Override public void set( LuaValue key, LuaValue value ) {
public void set(LuaValue key, LuaValue value) { if ( m_metatable==null || ! settable(this,key,value) )
if (m_metatable == null || !settable(this, key, value)) error( "cannot set "+key+" for userdata" );
error("cannot set " + key + " for userdata");
} }
@Override public boolean equals( Object val ) {
public boolean equals(Object val) { if ( this == val )
if (this == val)
return true; return true;
if (!(val instanceof LuaUserdata)) if ( ! (val instanceof LuaUserdata) )
return false; return false;
LuaUserdata u = (LuaUserdata) val; LuaUserdata u = (LuaUserdata) val;
return m_instance.equals(u.m_instance); return m_instance.equals(u.m_instance);
} }
// equality w/ metatable processing // equality w/ metatable processing
@Override public LuaValue eq( LuaValue val ) { return eq_b(val)? TRUE: FALSE; }
public LuaValue eq(LuaValue val) { return eq_b(val)? TRUE: FALSE; } public boolean eq_b( LuaValue val ) {
if ( val.raweq(this) ) return true;
@Override if ( m_metatable == null || !val.isuserdata() ) return false;
public boolean eq_b(LuaValue val) {
if (val.raweq(this))
return true;
if (m_metatable == null || !val.isuserdata())
return false;
LuaValue valmt = val.getmetatable(); LuaValue valmt = val.getmetatable();
return valmt != null && LuaValue.eqmtcall(this, m_metatable, val, valmt); return valmt!=null && LuaValue.eqmtcall(this, m_metatable, val, valmt);
} }
// equality w/o metatable processing // equality w/o metatable processing
@Override public boolean raweq( LuaValue val ) { return val.raweq(this); }
public boolean raweq(LuaValue val) { return val.raweq(this); } public boolean raweq( LuaUserdata val ) {
return this == val || (m_metatable == val.m_metatable && m_instance.equals(val.m_instance));
@Override
public boolean raweq(LuaUserdata val) {
return this == val || m_metatable == val.m_metatable && m_instance.equals(val.m_instance);
} }
// __eq metatag processing // __eq metatag processing
public boolean eqmt(LuaValue val) { public boolean eqmt( LuaValue val ) {
return m_metatable != null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable()) return m_metatable!=null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable()): false;
: false;
} }
} }

Binary file not shown.

Binary file not shown.

View File

@@ -75,7 +75,7 @@ package org.luaj.vm2;
* } </pre> * } </pre>
* For this to work the file must be in the current directory, or in the class path, * For this to work the file must be in the current directory, or in the class path,
* dependening on the platform. * dependening on the platform.
* See {@link org.luaj.vm2.lib.jse.JsePlatform} and {@link org.luaj.vm2.lib.jme.JmePlatform} for details. * See {@link org.luaj.vm2.libs.jse.JsePlatform} and {@link org.luaj.vm2.libs.jme.JmePlatform} for details.
* <p> * <p>
* In general a {@link LuaError} may be thrown on any operation when the * In general a {@link LuaError} may be thrown on any operation when the
* types supplied to any operation are illegal from a lua perspective. * types supplied to any operation are illegal from a lua perspective.
@@ -99,10 +99,10 @@ package org.luaj.vm2;
* {@link #INDEX}, {@link #NEWINDEX}, {@link #CALL}, {@link #MODE}, {@link #METATABLE}, * {@link #INDEX}, {@link #NEWINDEX}, {@link #CALL}, {@link #MODE}, {@link #METATABLE},
* {@link #ADD}, {@link #SUB}, {@link #DIV}, {@link #MUL}, {@link #POW}, * {@link #ADD}, {@link #SUB}, {@link #DIV}, {@link #MUL}, {@link #POW},
* {@link #MOD}, {@link #UNM}, {@link #LEN}, {@link #EQ}, {@link #LT}, * {@link #MOD}, {@link #UNM}, {@link #LEN}, {@link #EQ}, {@link #LT},
* {@link #LE}, {@link #TOSTRING}, {@link #CONCAT}, {@link PAIRS} and {@link IPAIRS}. * {@link #LE}, {@link #TOSTRING}, {@link #CONCAT}, {@link #PAIRS}, and {@link #IPAIRS}.
* *
* @see org.luaj.vm2.lib.jse.JsePlatform * @see org.luaj.vm2.libs.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform * @see org.luaj.vm2.libs.jme.JmePlatform
* @see LoadState * @see LoadState
* @see Varargs * @see Varargs
*/ */
@@ -213,6 +213,27 @@ public class LuaValue extends Varargs {
/** LuaString constant with value "__div" for use as metatag */ /** LuaString constant with value "__div" for use as metatag */
public static final LuaString DIV = valueOf("__div"); public static final LuaString DIV = valueOf("__div");
/** LuaString constant with value "__idiv" for use as metatag */
public static final LuaString IDIV = valueOf("__idiv");
/** LuaString constant with value "__band" for use as metatag */
public static final LuaString BAND = valueOf("__band");
/** LuaString constant with value "__bor" for use as metatag */
public static final LuaString BOR = valueOf("__bor");
/** LuaString constant with value "__bxor" for use as metatag */
public static final LuaString BXOR = valueOf("__bxor");
/** LuaString constant with value "__shl" for use as metatag */
public static final LuaString SHL = valueOf("__shl");
/** LuaString constant with value "__shr" for use as metatag */
public static final LuaString SHR = valueOf("__shr");
/** LuaString constant with value "__bnot" for use as metatag */
public static final LuaString BNOT = valueOf("__bnot");
/** LuaString constant with value "__mul" for use as metatag */ /** LuaString constant with value "__mul" for use as metatag */
public static final LuaString MUL = valueOf("__mul"); public static final LuaString MUL = valueOf("__mul");
@@ -535,7 +556,7 @@ public class LuaValue extends Varargs {
* @see #isstring() * @see #isstring()
* @see #TSTRING * @see #TSTRING
*/ */
public String tojstring() { return typename() + ": 0x" + Integer.toHexString(hashCode()); } public String tojstring() { return typename() + ": " + Integer.toHexString(hashCode()); }
/** Convert to userdata instance, or null. /** Convert to userdata instance, or null.
* @return userdata instance if userdata, or null if not {@link LuaUserdata} * @return userdata instance if userdata, or null if not {@link LuaUserdata}
@@ -631,7 +652,7 @@ public class LuaValue extends Varargs {
* @see #isclosure() * @see #isclosure()
* @see #TFUNCTION * @see #TFUNCTION
*/ */
public LuaClosure optclosure(LuaClosure defval) { argerror("function"); return null; } public LuaClosure optclosure(LuaClosure defval) { argerror("closure"); return null; }
/** Check that optional argument is a number or string convertible to number and return as double /** Check that optional argument is a number or string convertible to number and return as double
* @param defval double to return if {@code this} is nil or none * @param defval double to return if {@code this} is nil or none
@@ -743,7 +764,7 @@ public class LuaValue extends Varargs {
* @see #toString() * @see #toString()
* @see #TSTRING * @see #TSTRING
*/ */
public String optjstring(String defval) { argerror("string"); return null; } public String optjstring(String defval) { argerror("String"); return null; }
/** Check that optional argument is a string or number and return as {@link LuaString} /** Check that optional argument is a string or number and return as {@link LuaString}
* @param defval {@link LuaString} to return if {@code this} is nil or none * @param defval {@link LuaString} to return if {@code this} is nil or none
@@ -894,7 +915,7 @@ public class LuaValue extends Varargs {
* @see #optint(int) * @see #optint(int)
* @see #TNUMBER * @see #TNUMBER
*/ */
public int checkint() { argerror("number"); return 0; } public int checkint() { argerror("int"); return 0; }
/** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric /** Check that the value is numeric, and convert and cast value to int, or throw {@link LuaError} if not numeric
* <p> * <p>
@@ -1059,7 +1080,7 @@ public class LuaValue extends Varargs {
* @param expected String naming the type that was expected * @param expected String naming the type that was expected
* @throws LuaError in all cases * @throws LuaError in all cases
*/ */
protected LuaValue argerror(String expected) { throw new LuaError("bad argument ("+expected+" expected, got "+typename()+")"); } protected LuaValue argerror(String expected) { throw new LuaError("bad argument: "+expected+" expected, got "+typename()); }
/** /**
* Throw a {@link LuaError} indicating an invalid argument was supplied to a function * Throw a {@link LuaError} indicating an invalid argument was supplied to a function
@@ -2014,6 +2035,13 @@ public class LuaValue extends Varargs {
*/ */
public LuaValue neg() { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this); } public LuaValue neg() { return checkmetatag(UNM, "attempt to perform arithmetic on ").call(this); }
/** Unary bitwise not: return bitwise inverse value {@code (~this)}.
* @return numeric inverse as {@link LuaNumber} if integer-coercible,
* or metatag processing result if {@link #BNOT} metatag is defined
* @throws LuaError if {@code this} cannot be represented as an integer
*/
public LuaValue bnot() { return checkmetatag(BNOT, "attempt to perform bitwise operation on ").call(this); }
/** Length operator: return lua length of object {@code (#this)} including metatag processing as java int /** Length operator: return lua length of object {@code (#this)} including metatag processing as java int
* @return length as defined by the lua # operator * @return length as defined by the lua # operator
* or metatag processing result * or metatag processing result
@@ -2144,6 +2172,15 @@ public class LuaValue extends Varargs {
*/ */
public boolean raweq( int val ) { return false; } public boolean raweq( int val ) { return false; }
/** Equals: Perform direct equality comparison with a long value
* without metatag processing.
* @param val The long value to compare with.
* @return true if {@code this} is a {@link LuaNumber}
* whose value equals val,
* otherwise false
*/
public boolean raweq( long val ) { return false; }
/** Perform equality testing metatag processing /** Perform equality testing metatag processing
* @param lhs left-hand-side of equality expression * @param lhs left-hand-side of equality expression
* @param lhsmt metatag value for left-hand-side * @param lhsmt metatag value for left-hand-side
@@ -2405,6 +2442,18 @@ public class LuaValue extends Varargs {
*/ */
public LuaValue div( LuaValue rhs ) { return arithmt(DIV,rhs); } public LuaValue div( LuaValue rhs ) { return arithmt(DIV,rhs); }
public LuaValue idiv( LuaValue rhs ) { return arithmt(IDIV,rhs); }
public LuaValue band( LuaValue rhs ) { return arithmt(BAND,rhs); }
public LuaValue bor( LuaValue rhs ) { return arithmt(BOR,rhs); }
public LuaValue bxor( LuaValue rhs ) { return arithmt(BXOR,rhs); }
public LuaValue shl( LuaValue rhs ) { return arithmt(SHL,rhs); }
public LuaValue shr( LuaValue rhs ) { return arithmt(SHR,rhs); }
/** Divide: Perform numeric divide operation by another value /** Divide: Perform numeric divide operation by another value
* of double type without metatag processing * of double type without metatag processing
* <p> * <p>
@@ -2420,6 +2469,18 @@ public class LuaValue extends Varargs {
*/ */
public LuaValue div( double rhs ) { return aritherror("div"); } public LuaValue div( double rhs ) { return aritherror("div"); }
public LuaValue idiv( double rhs ) { return aritherror("idiv"); }
public LuaValue band( double rhs ) { return aritherror("band"); }
public LuaValue bor( double rhs ) { return aritherror("bor"); }
public LuaValue bxor( double rhs ) { return aritherror("bxor"); }
public LuaValue shl( double rhs ) { return aritherror("shl"); }
public LuaValue shr( double rhs ) { return aritherror("shr"); }
/** Divide: Perform numeric divide operation by another value /** Divide: Perform numeric divide operation by another value
* of int type without metatag processing * of int type without metatag processing
* <p> * <p>
@@ -2435,6 +2496,18 @@ public class LuaValue extends Varargs {
*/ */
public LuaValue div( int rhs ) { return aritherror("div"); } public LuaValue div( int rhs ) { return aritherror("div"); }
public LuaValue idiv( int rhs ) { return aritherror("idiv"); }
public LuaValue band( int rhs ) { return aritherror("band"); }
public LuaValue bor( int rhs ) { return aritherror("bor"); }
public LuaValue bxor( int rhs ) { return aritherror("bxor"); }
public LuaValue shl( int rhs ) { return aritherror("shl"); }
public LuaValue shr( int rhs ) { return aritherror("shr"); }
/** Reverse-divide: Perform numeric divide operation into another value /** Reverse-divide: Perform numeric divide operation into another value
* with metatag processing * with metatag processing
* <p> * <p>
@@ -2450,6 +2523,18 @@ public class LuaValue extends Varargs {
*/ */
public LuaValue divInto(double lhs) { return arithmtwith(DIV,lhs); } public LuaValue divInto(double lhs) { return arithmtwith(DIV,lhs); }
public LuaValue idivInto(double lhs) { return arithmtwith(IDIV,lhs); }
public LuaValue bandInto(double lhs) { return arithmtwith(BAND,lhs); }
public LuaValue borInto(double lhs) { return arithmtwith(BOR,lhs); }
public LuaValue bxorInto(double lhs) { return arithmtwith(BXOR,lhs); }
public LuaValue shlInto(double lhs) { return arithmtwith(SHL,lhs); }
public LuaValue shrInto(double lhs) { return arithmtwith(SHR,lhs); }
/** Modulo: Perform numeric modulo operation with another value /** Modulo: Perform numeric modulo operation with another value
* of unknown type, * of unknown type,
* including metatag processing. * including metatag processing.
@@ -2991,7 +3076,7 @@ public class LuaValue extends Varargs {
return h.call(this, op1); return h.call(this, op1);
if (LuaValue.LE.raweq(tag) && (!(h = metatag(LT)).isnil() || !(h = op1.metatag(LT)).isnil())) if (LuaValue.LE.raweq(tag) && (!(h = metatag(LT)).isnil() || !(h = op1.metatag(LT)).isnil()))
return h.call(op1, this).not(); return h.call(op1, this).not();
return error("bad argument: attempt to compare "+tag+" on "+typename()+" and "+op1.typename()); return error("attempt to compare "+tag+" on "+typename()+" and "+op1.typename());
} }
/** Perform string comparison with another value /** Perform string comparison with another value
@@ -3169,6 +3254,13 @@ public class LuaValue extends Varargs {
*/ */
public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); } public static LuaInteger valueOf(int i) { return LuaInteger.valueOf(i); }
/** Convert java long to a {@link LuaValue}.
*
* @param l long value to convert
* @return {@link LuaInteger} instance, possibly pooled, whose value is l
*/
public static LuaInteger valueOf(long l) { return LuaInteger.valueOf(l); }
/** Convert java double to a {@link LuaValue}. /** Convert java double to a {@link LuaValue}.
* This may return a {@link LuaInteger} or {@link LuaDouble} depending * This may return a {@link LuaInteger} or {@link LuaDouble} depending
* on the value supplied. * on the value supplied.
@@ -3408,8 +3500,8 @@ public class LuaValue extends Varargs {
switch ( v.length ) { switch ( v.length ) {
case 0: return NONE; case 0: return NONE;
case 1: return v[0]; case 1: return v[0];
case 2: return new Varargs.PairVarargs(v[0],v[1]); case 2: return new PairVarargs(v[0],v[1]);
default: return new Varargs.ArrayVarargs(v,NONE); default: return new ArrayVarargs(v,NONE);
} }
} }
@@ -3425,12 +3517,12 @@ public class LuaValue extends Varargs {
switch ( v.length ) { switch ( v.length ) {
case 0: return r; case 0: return r;
case 1: return r.narg()>0? case 1: return r.narg()>0?
(Varargs) new Varargs.PairVarargs(v[0],r): (Varargs) new PairVarargs(v[0],r):
(Varargs) v[0]; (Varargs) v[0];
case 2: return r.narg()>0? case 2: return r.narg()>0?
(Varargs) new Varargs.ArrayVarargs(v,r): (Varargs) new ArrayVarargs(v,r):
(Varargs) new Varargs.PairVarargs(v[0],v[1]); (Varargs) new PairVarargs(v[0],v[1]);
default: return new Varargs.ArrayVarargs(v,r); default: return new ArrayVarargs(v,r);
} }
} }
@@ -3447,8 +3539,8 @@ public class LuaValue extends Varargs {
switch ( length ) { switch ( length ) {
case 0: return NONE; case 0: return NONE;
case 1: return v[offset]; case 1: return v[offset];
case 2: return new Varargs.PairVarargs(v[offset+0],v[offset+1]); case 2: return new PairVarargs(v[offset+0],v[offset+1]);
default: return new Varargs.ArrayPartVarargs(v, offset, length, NONE); default: return new ArrayPartVarargs(v, offset, length, NONE);
} }
} }
@@ -3469,12 +3561,12 @@ public class LuaValue extends Varargs {
switch ( length ) { switch ( length ) {
case 0: return more; case 0: return more;
case 1: return more.narg()>0? case 1: return more.narg()>0?
(Varargs) new Varargs.PairVarargs(v[offset],more): (Varargs) new PairVarargs(v[offset],more):
(Varargs) v[offset]; (Varargs) v[offset];
case 2: return more.narg()>0? case 2: return more.narg()>0?
(Varargs) new Varargs.ArrayPartVarargs(v,offset,length,more): (Varargs) new ArrayPartVarargs(v,offset,length,more):
(Varargs) new Varargs.PairVarargs(v[offset],v[offset+1]); (Varargs) new PairVarargs(v[offset],v[offset+1]);
default: return new Varargs.ArrayPartVarargs(v,offset,length,more); default: return new ArrayPartVarargs(v,offset,length,more);
} }
} }
@@ -3491,7 +3583,7 @@ public class LuaValue extends Varargs {
public static Varargs varargsOf(LuaValue v, Varargs r) { public static Varargs varargsOf(LuaValue v, Varargs r) {
switch ( r.narg() ) { switch ( r.narg() ) {
case 0: return v; case 0: return v;
default: return new Varargs.PairVarargs(v,r); default: return new PairVarargs(v,r);
} }
} }
@@ -3508,8 +3600,8 @@ public class LuaValue extends Varargs {
*/ */
public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) { public static Varargs varargsOf(LuaValue v1,LuaValue v2,Varargs v3) {
switch ( v3.narg() ) { switch ( v3.narg() ) {
case 0: return new Varargs.PairVarargs(v1,v2); case 0: return new PairVarargs(v1,v2);
default: return new Varargs.ArrayPartVarargs(new LuaValue[]{v1,v2}, 0, 2, v3); default: return new ArrayPartVarargs(new LuaValue[]{v1,v2}, 0, 2, v3);
} }
} }

Binary file not shown.

View File

@@ -29,23 +29,23 @@ import org.luaj.vm2.LuaTable.Slot;
interface Metatable { interface Metatable {
/** Return whether or not this table's keys are weak. */ /** Return whether or not this table's keys are weak. */
boolean useWeakKeys(); public boolean useWeakKeys();
/** Return whether or not this table's values are weak. */ /** Return whether or not this table's values are weak. */
boolean useWeakValues(); public boolean useWeakValues();
/** Return this metatable as a LuaValue. */ /** Return this metatable as a LuaValue. */
LuaValue toLuaValue(); public LuaValue toLuaValue();
/** Return an instance of Slot appropriate for the given key and value. */ /** Return an instance of Slot appropriate for the given key and value. */
Slot entry(LuaValue key, LuaValue value); public Slot entry( LuaValue key, LuaValue value );
/** Returns the given value wrapped in a weak reference if appropriate. */ /** Returns the given value wrapped in a weak reference if appropriate. */
LuaValue wrap(LuaValue value); public LuaValue wrap( LuaValue value );
/** /**
* Returns the value at the given index in the array, or null if it is a * Returns the value at the given index in the array, or null if it is a weak reference that
* weak reference that has been dropped. * has been dropped.
*/ */
LuaValue arrayget(LuaValue[] array, int index); public LuaValue arrayget(LuaValue[] array, int index);
} }

View File

@@ -10,32 +10,26 @@ class NonTableMetatable implements Metatable {
this.value = value; this.value = value;
} }
@Override
public boolean useWeakKeys() { public boolean useWeakKeys() {
return false; return false;
} }
@Override
public boolean useWeakValues() { public boolean useWeakValues() {
return false; return false;
} }
@Override
public LuaValue toLuaValue() { public LuaValue toLuaValue() {
return value; return value;
} }
@Override
public Slot entry(LuaValue key, LuaValue value) { public Slot entry(LuaValue key, LuaValue value) {
return LuaTable.defaultEntry(key, value); return LuaTable.defaultEntry(key, value);
} }
@Override
public LuaValue wrap(LuaValue value) { public LuaValue wrap(LuaValue value) {
return value; return value;
} }
@Override
public LuaValue arrayget(LuaValue[] array, int index) { public LuaValue arrayget(LuaValue[] array, int index) {
return array[index]; return array[index];
} }

Binary file not shown.

View File

@@ -22,15 +22,14 @@
package org.luaj.vm2; package org.luaj.vm2;
/** /**
* {@link java.lang.Error} sublcass that indicates a lua thread that is no * {@link Error} sublcass that indicates a lua thread that is no
* longer referenced has been detected. * longer referenced has been detected.
* <p> * <p>
* The java thread in which this is thrown should correspond to a * The java thread in which this is thrown should correspond to a
* {@link LuaThread} being used as a coroutine that could not possibly be * {@link LuaThread} being used as a coroutine that could not possibly be
* resumed again because there are no more references to the LuaThread with * resumed again because there are no more references to the LuaThread with
* which it is associated. Rather than locking up resources forever, this error * which it is associated. Rather than locking up resources forever, this error
* is thrown, and should fall through all the way to the thread's * is thrown, and should fall through all the way to the thread's {@link Thread#run()} method.
* {@link Thread#run()} method.
* <p> * <p>
* Java code mixed with the luaj vm should not catch this error because it may * Java code mixed with the luaj vm should not catch this error because it may
* occur when the coroutine is not running, so any processing done during error * occur when the coroutine is not running, so any processing done during error

Binary file not shown.

View File

@@ -26,7 +26,6 @@ import java.io.PrintStream;
/** /**
* Debug helper class to pretty-print lua bytecodes. * Debug helper class to pretty-print lua bytecodes.
*
* @see Prototype * @see Prototype
* @see LuaClosure * @see LuaClosure
*/ */
@@ -37,17 +36,57 @@ public class Print extends Lua {
public static PrintStream ps = System.out; public static PrintStream ps = System.out;
/** String names for each lua opcode value. */ /** String names for each lua opcode value. */
public static final String[] OPNAMES = { "MOVE", "LOADK", "LOADKX", "LOADBOOL", "LOADNIL", "GETUPVAL", "GETTABUP", public static final String[] OPNAMES = {
"GETTABLE", "SETTABUP", "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", "MOD", "MOVE",
"POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ", "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL", "LOADK",
"RETURN", "FORLOOP", "FORPREP", "TFORCALL", "TFORLOOP", "SETLIST", "CLOSURE", "VARARG", "EXTRAARG", null, }; "LOADKX",
"LOADBOOL",
"LOADNIL",
"GETUPVAL",
"GETTABUP",
"GETTABLE",
"SETTABUP",
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
"SELF",
"ADD",
"SUB",
"MUL",
"DIV",
"MOD",
"POW",
"UNM",
"NOT",
"LEN",
"CONCAT",
"JMP",
"EQ",
"LT",
"LE",
"TEST",
"TESTSET",
"CALL",
"TAILCALL",
"RETURN",
"FORLOOP",
"FORPREP",
"TFORCALL",
"TFORLOOP",
"SETLIST",
"CLOSURE",
"VARARG",
"EXTRAARG",
null,
};
static void printString(PrintStream ps, final LuaString s) { static void printString(PrintStream ps, final LuaString s) {
ps.print('"'); ps.print('"');
for (int i = 0, n = s.m_length; i < n; i++) { for (int i = 0, n = s.m_length; i < n; i++) {
int c = s.m_bytes[s.m_offset+i]; int c = s.m_bytes[s.m_offset+i];
if (c >= ' ' && c <= '~' && c != '\"' && c != '\\') if ( c >= ' ' && c <= '~' && c != '\"' && c != '\\' )
ps.print((char) c); ps.print((char) c);
else { else {
switch (c) { switch (c) {
@@ -80,7 +119,7 @@ public class Print extends Lua {
break; break;
default: default:
ps.print('\\'); ps.print('\\');
ps.print(Integer.toString(1000+0xff & c).substring(1)); ps.print(Integer.toString(1000 + 0xff&c).substring(1));
break; break;
} }
} }
@@ -88,33 +127,29 @@ public class Print extends Lua {
ps.print('"'); ps.print('"');
} }
static void printValue(PrintStream ps, LuaValue v) { static void printValue( PrintStream ps, LuaValue v ) {
if (v == null) { if (v == null) {
ps.print("null"); ps.print("null");
return; return;
} }
switch (v.type()) { switch ( v.type() ) {
case LuaValue.TSTRING: case LuaValue.TSTRING: printString( ps, (LuaString) v ); break;
printString(ps, (LuaString) v); default: ps.print( v.tojstring() );
break;
default:
ps.print(v.tojstring());
} }
} }
static void printConstant(PrintStream ps, Prototype f, int i) { static void printConstant(PrintStream ps, Prototype f, int i) {
printValue(ps, i < f.k.length? f.k[i]: LuaValue.valueOf("UNKNOWN_CONST_" + i)); printValue( ps, i < f.k.length ? f.k[i] : LuaValue.valueOf("UNKNOWN_CONST_" + i) );
} }
static void printUpvalue(PrintStream ps, Upvaldesc u) { static void printUpvalue(PrintStream ps, Upvaldesc u) {
ps.print(u.idx + " "); ps.print( u.idx + " " );
printValue(ps, u.name); printValue( ps, u.name );
} }
/** /**
* Print the code in a prototype * Print the code in a prototype
*
* @param f the {@link Prototype} * @param f the {@link Prototype}
*/ */
public static void printCode(Prototype f) { public static void printCode(Prototype f) {
@@ -128,18 +163,16 @@ public class Print extends Lua {
/** /**
* Print an opcode in a prototype * Print an opcode in a prototype
*
* @param f the {@link Prototype} * @param f the {@link Prototype}
* @param pc the program counter to look up and print * @param pc the program counter to look up and print
* @return pc same as above or changed * @return pc same as above or changed
*/ */
public static int printOpCode(Prototype f, int pc) { public static int printOpCode(Prototype f, int pc) {
return printOpCode(ps, f, pc); return printOpCode(ps,f,pc);
} }
/** /**
* Print an opcode in a prototype * Print an opcode in a prototype
*
* @param ps the {@link PrintStream} to print to * @param ps the {@link PrintStream} to print to
* @param f the {@link Prototype} * @param f the {@link Prototype}
* @param pc the program counter to look up and print * @param pc the program counter to look up and print
@@ -155,33 +188,33 @@ public class Print extends Lua {
int bx = GETARG_Bx(i); int bx = GETARG_Bx(i);
int sbx = GETARG_sBx(i); int sbx = GETARG_sBx(i);
int line = getline(f, pc); int line = getline(f, pc);
ps.print(" " + (pc+1) + " "); ps.print(" " + (pc + 1) + " ");
if (line > 0) if (line > 0)
ps.print("[" + line + "] "); ps.print("[" + line + "] ");
else else
ps.print("[-] "); ps.print("[-] ");
if (o >= OPNAMES.length-1) { if (o >= OPNAMES.length - 1) {
ps.print("UNKNOWN_OP_" + o + " "); ps.print("UNKNOWN_OP_" + o + " ");
} else { } else {
ps.print(OPNAMES[o] + " "); ps.print(OPNAMES[o] + " ");
switch (getOpMode(o)) { switch (getOpMode(o)) {
case iABC: case iABC:
ps.print(a); ps.print( a );
if (getBMode(o) != OpArgN) if (getBMode(o) != OpArgN)
ps.print(" " + (ISK(b)? -1-INDEXK(b): b)); ps.print(" "+(ISK(b) ? (-1 - INDEXK(b)) : b));
if (getCMode(o) != OpArgN) if (getCMode(o) != OpArgN)
ps.print(" " + (ISK(c)? -1-INDEXK(c): c)); ps.print(" "+(ISK(c) ? (-1 - INDEXK(c)) : c));
break; break;
case iABx: case iABx:
if (getBMode(o) == OpArgK) { if (getBMode(o) == OpArgK) {
ps.print(a + " " + (-1-bx)); ps.print(a + " " + (-1 - bx));
} else { } else {
ps.print(a + " " + bx); ps.print(a + " " + (bx));
} }
break; break;
case iAsBx: case iAsBx:
if (o == OP_JMP) if (o == OP_JMP)
ps.print(sbx); ps.print( sbx );
else else
ps.print(a + " " + sbx); ps.print(a + " " + sbx);
break; break;
@@ -243,6 +276,12 @@ public class Print extends Lua {
case OP_SUB: case OP_SUB:
case OP_MUL: case OP_MUL:
case OP_DIV: case OP_DIV:
case OP_IDIV:
case OP_BAND:
case OP_BOR:
case OP_BXOR:
case OP_SHL:
case OP_SHR:
case OP_POW: case OP_POW:
case OP_EQ: case OP_EQ:
case OP_LT: case OP_LT:
@@ -263,7 +302,7 @@ public class Print extends Lua {
case OP_JMP: case OP_JMP:
case OP_FORLOOP: case OP_FORLOOP:
case OP_FORPREP: case OP_FORPREP:
ps.print(" ; to " + (sbx+pc+2)); ps.print(" ; to " + (sbx + pc + 2));
break; break;
case OP_CLOSURE: case OP_CLOSURE:
if (bx < f.p.length) { if (bx < f.p.length) {
@@ -274,12 +313,12 @@ public class Print extends Lua {
break; break;
case OP_SETLIST: case OP_SETLIST:
if (c == 0) if (c == 0)
ps.print(" ; " + code[++pc] + " (stored in the next OP)"); ps.print(" ; " + ((int) code[++pc]) + " (stored in the next OP)");
else else
ps.print(" ; " + c); ps.print(" ; " + ((int) c));
break; break;
case OP_VARARG: case OP_VARARG:
ps.print(" ; is_vararg=" + f.is_vararg); ps.print( " ; is_vararg="+ f.is_vararg );
break; break;
default: default:
break; break;
@@ -289,7 +328,7 @@ public class Print extends Lua {
} }
private static int getline(Prototype f, int pc) { private static int getline(Prototype f, int pc) {
return pc > 0 && f.lineinfo != null && pc < f.lineinfo.length? f.lineinfo[pc]: -1; return pc>0 && f.lineinfo!=null && pc<f.lineinfo.length? f.lineinfo[pc]: -1;
} }
static void printHeader(Prototype f) { static void printHeader(Prototype f) {
@@ -300,20 +339,23 @@ public class Print extends Lua {
s = "(bstring)"; s = "(bstring)";
else else
s = "(string)"; s = "(string)";
String a = f.linedefined == 0? "main": "function"; String a = (f.linedefined == 0) ? "main" : "function";
ps.print("\n%" + a + " <" + s + ":" + f.linedefined + "," + f.lastlinedefined + "> (" + f.code.length ps.print("\n%" + a + " <" + s + ":" + f.linedefined + ","
+ " instructions, " + f.code.length*4 + " bytes at " + id(f) + ")\n"); + f.lastlinedefined + "> (" + f.code.length + " instructions, "
ps.print(f.numparams + " param, " + f.maxstacksize + " slot, " + f.upvalues.length + " upvalue, "); + f.code.length * 4 + " bytes at " + id(f) + ")\n");
ps.print(f.locvars.length + " local, " + f.k.length + " constant, " + f.p.length + " function\n"); ps.print(f.numparams + " param, " + f.maxstacksize + " slot, "
+ f.upvalues.length + " upvalue, ");
ps.print(f.locvars.length + " local, " + f.k.length
+ " constant, " + f.p.length + " function\n");
} }
static void printConstants(Prototype f) { static void printConstants(Prototype f) {
int i, n = f.k.length; int i, n = f.k.length;
ps.print("constants (" + n + ") for " + id(f) + ":\n"); ps.print("constants (" + n + ") for " + id(f) + ":\n");
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
ps.print(" " + (i+1) + " "); ps.print(" " + (i + 1) + " ");
printValue(ps, f.k[i]); printValue( ps, f.k[i] );
ps.print("\n"); ps.print( "\n");
} }
} }
@@ -321,8 +363,7 @@ public class Print extends Lua {
int i, n = f.locvars.length; int i, n = f.locvars.length;
ps.print("locals (" + n + ") for " + id(f) + ":\n"); ps.print("locals (" + n + ") for " + id(f) + ":\n");
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
ps.println( ps.println(" "+i+" "+f.locvars[i].varname+" "+(f.locvars[i].startpc+1)+" "+(f.locvars[i].endpc+1));
" " + i + " " + f.locvars[i].varname + " " + (f.locvars[i].startpc+1) + " " + (f.locvars[i].endpc+1));
} }
} }
@@ -334,8 +375,7 @@ public class Print extends Lua {
} }
} }
/** /** Pretty-prints contents of a Prototype.
* Pretty-prints contents of a Prototype.
* *
* @param prototype Prototype to print. * @param prototype Prototype to print.
*/ */
@@ -343,8 +383,7 @@ public class Print extends Lua {
printFunction(prototype, true); printFunction(prototype, true);
} }
/** /** Pretty-prints contents of a Prototype in short or long form.
* Pretty-prints contents of a Prototype in short or long form.
* *
* @param prototype Prototype to print. * @param prototype Prototype to print.
* @param full true to print all fields, false to print short form. * @param full true to print all fields, false to print short form.
@@ -362,29 +401,27 @@ public class Print extends Lua {
printFunction(prototype.p[i], full); printFunction(prototype.p[i], full);
} }
private static void format(String s, int maxcols) { private static void format( String s, int maxcols ) {
int n = s.length(); int n = s.length();
if (n > maxcols) if ( n > maxcols )
ps.print(s.substring(0, maxcols)); ps.print( s.substring(0,maxcols) );
else { else {
ps.print(s); ps.print( s );
for (int i = maxcols-n; --i >= 0;) for ( int i=maxcols-n; --i>=0; )
ps.print(' '); ps.print( ' ' );
} }
} }
private static String id(Prototype f) { private static String id(Prototype f) {
return "Proto"; return "Proto";
} }
private void _assert(boolean b) { private void _assert(boolean b) {
if (!b) if ( !b )
throw new NullPointerException("_assert failed"); throw new NullPointerException("_assert failed");
} }
/** /**
* Print the state of a {@link LuaClosure} that is being executed * Print the state of a {@link LuaClosure} that is being executed
*
* @param cl the {@link LuaClosure} * @param cl the {@link LuaClosure}
* @param pc the program counter * @param pc the program counter
* @param stack the stack of {@link LuaValue} * @param stack the stack of {@link LuaValue}
@@ -395,12 +432,12 @@ public class Print extends Lua {
// print opcode into buffer // print opcode into buffer
PrintStream previous = ps; PrintStream previous = ps;
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
ps = new PrintStream(baos); ps = new PrintStream( baos );
printOpCode(cl.p, pc); printOpCode( cl.p, pc );
ps.flush(); ps.flush();
ps.close(); ps.close();
ps = previous; ps = previous;
format(baos.toString(), 50); format( baos.toString(), 50 );
printStack(stack, top, varargs); printStack(stack, top, varargs);
ps.println(); ps.println();
} }
@@ -408,36 +445,36 @@ public class Print extends Lua {
public static void printStack(LuaValue[] stack, int top, Varargs varargs) { public static void printStack(LuaValue[] stack, int top, Varargs varargs) {
// print stack // print stack
ps.print('['); ps.print('[');
for (int i = 0; i < stack.length; i++) { for ( int i=0; i<stack.length; i++ ) {
LuaValue v = stack[i]; LuaValue v = stack[i];
if (v == null) if ( v == null )
ps.print(STRING_FOR_NULL); ps.print(STRING_FOR_NULL);
else else switch ( v.type() ) {
switch (v.type()) {
case LuaValue.TSTRING: case LuaValue.TSTRING:
LuaString s = v.checkstring(); LuaString s = v.checkstring();
ps.print(s.length() < 48? s.tojstring() ps.print( s.length() < 48?
: s.substring(0, 32).tojstring() + "...+" + (s.length()-32) + "b"); s.tojstring():
s.substring(0, 32).tojstring()+"...+"+(s.length()-32)+"b");
break; break;
case LuaValue.TFUNCTION: case LuaValue.TFUNCTION:
ps.print(v.tojstring()); ps.print( v.tojstring() );
break; break;
case LuaValue.TUSERDATA: case LuaValue.TUSERDATA:
Object o = v.touserdata(); Object o = v.touserdata();
if (o != null) { if ( o != null ) {
String n = o.getClass().getName(); String n = o.getClass().getName();
n = n.substring(n.lastIndexOf('.')+1); n = n.substring(n.lastIndexOf('.')+1);
ps.print(n + ": " + Integer.toHexString(o.hashCode())); ps.print( n+": "+Integer.toHexString(o.hashCode()) );
} else { } else {
ps.print(v.toString()); ps.print( v.toString() );
} }
break; break;
default: default:
ps.print(v.tojstring()); ps.print(v.tojstring());
} }
if (i+1 == top) if ( i+1 == top )
ps.print(']'); ps.print(']');
ps.print(" | "); ps.print( " | " );
} }
ps.print(varargs); ps.print(varargs);
} }

Binary file not shown.

View File

@@ -0,0 +1,146 @@
/*******************************************************************************
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
/**
* Prototype representing compiled lua code.
*
* <p>
* This is both a straight translation of the corresponding C type,
* and the main data structure for execution of compiled lua bytecode.
*
* <p>
* Generally, the {@link Prototype} is not constructed directly is an intermediate result
* as lua code is loaded using {@link Globals#load(java.io.Reader, String)}:
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* globals.load( new StringReader("print 'hello'"), "main.lua" ).call();
* } </pre>
*
* <p>
* To create a {@link Prototype} directly, a compiler such as
* {@link org.luaj.vm2.compiler.LuaC} may be used:
* <pre> {@code
* InputStream is = new ByteArrayInputStream("print('hello,world')".getBytes());
* Prototype p = LuaC.instance.compile(is, "script");
* }</pre>
*
* To simplify loading, the {@link Globals#compilePrototype(java.io.InputStream, String)} method may be used:
* <pre> {@code
* Prototype p = globals.compileProtoytpe(is, "script");
* }</pre>
*
* It may also be loaded from a {@link java.io.Reader} via {@link Globals#compilePrototype(java.io.Reader, String)}:
* <pre> {@code
* Prototype p = globals.compileProtoytpe(new StringReader(script), "script");
* }</pre>
*
* To un-dump a binary file known to be a binary lua file that has been dumped to a string,
* the {@link Globals.Undumper} interface may be used:
* <pre> {@code
* FileInputStream lua_binary_file = new FileInputStream("foo.lc"); // Known to be compiled lua.
* Prototype p = globals.undumper.undump(lua_binary_file, "foo.lua");
* }</pre>
*
* To execute the code represented by the {@link Prototype} it must be supplied to
* the constructor of a {@link LuaClosure}:
* <pre> {@code
* Globals globals = JsePlatform.standardGlobals();
* LuaClosure f = new LuaClosure(p, globals);
* f.call();
* }</pre>
*
* To simplify the debugging of prototype values, the contents may be printed using {@link Print#print}:
* <pre> {@code
* Print.print(p);
* }</pre>
* <p>
*
* @see LuaClosure
* @see Globals
* @see Globals#undumper
* @see Globals#compiler
* @see Print#print
*/
public class Prototype {
/* constants used by the function */
public LuaValue[] k;
public int[] code;
/* functions defined inside the function */
public Prototype[] p;
/* map from opcodes to source lines */
public int[] lineinfo;
/* information about local variables */
public LocVars[] locvars;
/* upvalue information */
public Upvaldesc[] upvalues;
public LuaString source;
public int linedefined;
public int lastlinedefined;
public int numparams;
public int is_vararg;
public int maxstacksize;
private static final Upvaldesc[] NOUPVALUES = {};
private static final Prototype[] NOSUBPROTOS = {};
public Prototype() {
p = NOSUBPROTOS;
upvalues = NOUPVALUES;
}
public Prototype(int n_upvalues) {
p = NOSUBPROTOS;
upvalues = new Upvaldesc[n_upvalues];
}
public String toString() {
return source + ":" + linedefined+"-"+lastlinedefined;
}
/** Get the name of a local variable.
*
* @param number the local variable number to look up
* @param pc the program counter
* @return the name, or null if not found
*/
public LuaString getlocalname(int number, int pc) {
int i;
for (i = 0; i<locvars.length && locvars[i].startpc <= pc; i++) {
if (pc < locvars[i].endpc) { /* is variable active? */
number--;
if (number == 0)
return locvars[i].varname;
}
}
return null; /* not found */
}
public String shortsource() {
String name = source.tojstring();
if ( name.startsWith("@") || name.startsWith("=") )
name = name.substring(1);
else if ( name.startsWith("\033") )
name = "binary string";
return name;
}
}

Binary file not shown.

View File

@@ -22,20 +22,21 @@
package org.luaj.vm2; package org.luaj.vm2;
/** /**
* Subclass of {@link Varargs} that represents a lua tail call in a Java library * Subclass of {@link Varargs} that represents a lua tail call
* function execution environment. * in a Java library function execution environment.
* <p> * <p>
* Since Java doesn't have direct support for tail calls, any lua function whose * Since Java doesn't have direct support for tail calls,
* {@link Prototype} contains the {@link Lua#OP_TAILCALL} bytecode needs a * any lua function whose {@link Prototype} contains the
* mechanism for tail calls when converting lua-bytecode to java-bytecode. * {@link Lua#OP_TAILCALL} bytecode needs a mechanism
* for tail calls when converting lua-bytecode to java-bytecode.
* <p> * <p>
* The tail call holds the next function and arguments, and the client a call to * The tail call holds the next function and arguments,
* {@link #eval()} executes the function repeatedly until the tail calls are * and the client a call to {@link #eval()} executes the function
* completed. * repeatedly until the tail calls are completed.
* <p> * <p>
* Normally, users of luaj need not concern themselves with the details of this * Normally, users of luaj need not concern themselves with the
* mechanism, as it is built into the core execution framework. * details of this mechanism, as it is built into the core
* * execution framework.
* @see Prototype * @see Prototype
* @see org.luaj.vm2.luajc.LuaJC * @see org.luaj.vm2.luajc.LuaJC
*/ */
@@ -55,10 +56,10 @@ public class TailcallVarargs extends Varargs {
this.args = LuaValue.varargsOf(object, args); this.args = LuaValue.varargsOf(object, args);
} }
@Override public boolean isTailcall() {
public boolean isTailcall() { return true; } return true;
}
@Override
public Varargs eval() { public Varargs eval() {
while ( result == null ) { while ( result == null ) {
Varargs r = func.onInvoke(args); Varargs r = func.onInvoke(args);
@@ -66,7 +67,8 @@ public class TailcallVarargs extends Varargs {
TailcallVarargs t = (TailcallVarargs) r; TailcallVarargs t = (TailcallVarargs) r;
func = t.func; func = t.func;
args = t.args; args = t.args;
} else { }
else {
result = r; result = r;
func = null; func = null;
args = null; args = null;
@@ -75,28 +77,24 @@ public class TailcallVarargs extends Varargs {
return result; return result;
} }
@Override public LuaValue arg( int i ) {
public LuaValue arg(int i) { if ( result == null )
if (result == null)
eval(); eval();
return result.arg(i); return result.arg(i);
} }
@Override
public LuaValue arg1() { public LuaValue arg1() {
if (result == null) if (result == null)
eval(); eval();
return result.arg1(); return result.arg1();
} }
@Override
public int narg() { public int narg() {
if (result == null) if (result == null)
eval(); eval();
return result.narg(); return result.narg();
} }
@Override
public Varargs subargs(int start) { public Varargs subargs(int start) {
if (result == null) if (result == null)
eval(); eval();

Binary file not shown.

View File

@@ -21,10 +21,9 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm2; package org.luaj.vm2;
/**
* Upvalue used with Closure formulation /** Upvalue used with Closure formulation
* <p> * <p>
*
* @see LuaClosure * @see LuaClosure
* @see Prototype * @see Prototype
*/ */
@@ -35,23 +34,20 @@ public final class UpValue {
/** /**
* Create an upvalue relative to a stack * Create an upvalue relative to a stack
*
* @param stack the stack * @param stack the stack
* @param index the index on the stack for the upvalue * @param index the index on the stack for the upvalue
*/ */
public UpValue(LuaValue[] stack, int index) { public UpValue( LuaValue[] stack, int index) {
this.array = stack; this.array = stack;
this.index = index; this.index = index;
} }
@Override
public String toString() { public String toString() {
return index + "/" + array.length + " " + array[index]; return index + "/" + array.length + " " + array[index];
} }
/** /**
* Convert this upvalue to a Java String * Convert this upvalue to a Java String
*
* @return the Java String for this upvalue. * @return the Java String for this upvalue.
* @see LuaValue#tojstring() * @see LuaValue#tojstring()
*/ */
@@ -61,22 +57,24 @@ public final class UpValue {
/** /**
* Get the value of the upvalue * Get the value of the upvalue
*
* @return the {@link LuaValue} for this upvalue * @return the {@link LuaValue} for this upvalue
*/ */
public LuaValue getValue() { return array[index]; } public final LuaValue getValue() {
return array[index];
}
/** /**
* Set the value of the upvalue * Set the value of the upvalue
*
* @param value the {@link LuaValue} to set it to * @param value the {@link LuaValue} to set it to
*/ */
public void setValue(LuaValue value) { array[index] = value; } public final void setValue( LuaValue value ) {
array[index] = value;
}
/** /**
* Close this upvalue so it is no longer on the stack * Close this upvalue so it is no longer on the stack
*/ */
public void close() { public final void close() {
LuaValue[] old = array; LuaValue[] old = array;
array = new LuaValue[] { old[index] }; array = new LuaValue[] { old[index] };
old[index] = null; old[index] = null;

Binary file not shown.

View File

@@ -38,8 +38,7 @@ public class Upvaldesc {
this.idx = (short) idx; this.idx = (short) idx;
} }
@Override
public String toString() { public String toString() {
return idx+(instack? " instack ": " closed ")+String.valueOf(name); return idx + (instack? " instack ": " closed ") + String.valueOf(name);
} }
} }

Binary file not shown.

Binary file not shown.

View File

@@ -29,37 +29,36 @@ import org.luaj.vm2.LuaTable.StrongSlot;
/** /**
* Subclass of {@link LuaTable} that provides weak key and weak value semantics. * Subclass of {@link LuaTable} that provides weak key and weak value semantics.
* <p> * <p>
* Normally these are not created directly, but indirectly when changing the * Normally these are not created directly, but indirectly when changing the mode
* mode of a {@link LuaTable} as lua script executes. * of a {@link LuaTable} as lua script executes.
* <p> * <p>
* However, calling the constructors directly when weak tables are required from * However, calling the constructors directly when weak tables are required from
* Java will reduce overhead. * Java will reduce overhead.
*/ */
public class WeakTable implements Metatable { public class WeakTable implements Metatable {
private final boolean weakkeys, weakvalues; private boolean weakkeys, weakvalues;
private final LuaValue backing; private LuaValue backing;
public static LuaTable make(boolean weakkeys, boolean weakvalues) { public static LuaTable make(boolean weakkeys, boolean weakvalues) {
LuaString mode; LuaString mode;
if (weakkeys && weakvalues) { if ( weakkeys && weakvalues ) {
mode = LuaString.valueOf("kv"); mode = LuaString.valueOf("kv");
} else if (weakkeys) { } else if ( weakkeys ) {
mode = LuaString.valueOf("k"); mode = LuaString.valueOf("k");
} else if (weakvalues) { } else if ( weakvalues ) {
mode = LuaString.valueOf("v"); mode = LuaString.valueOf("v");
} else { } else {
return LuaValue.tableOf(); return LuaTable.tableOf();
} }
LuaTable table = LuaValue.tableOf(); LuaTable table = LuaTable.tableOf();
LuaTable mt = LuaValue.tableOf(new LuaValue[] { LuaValue.MODE, mode }); LuaTable mt = LuaTable.tableOf(new LuaValue[] { LuaValue.MODE, mode });
table.setmetatable(mt); table.setmetatable(mt);
return table; return table;
} }
/** /**
* Construct a table with weak keys, weak values, or both * Construct a table with weak keys, weak values, or both
*
* @param weakkeys true to let the table have weak keys * @param weakkeys true to let the table have weak keys
* @param weakvalues true to let the table have weak values * @param weakvalues true to let the table have weak values
*/ */
@@ -69,37 +68,33 @@ public class WeakTable implements Metatable {
this.backing = backing; this.backing = backing;
} }
@Override
public boolean useWeakKeys() { public boolean useWeakKeys() {
return weakkeys; return weakkeys;
} }
@Override
public boolean useWeakValues() { public boolean useWeakValues() {
return weakvalues; return weakvalues;
} }
@Override
public LuaValue toLuaValue() { public LuaValue toLuaValue() {
return backing; return backing;
} }
@Override
public Slot entry(LuaValue key, LuaValue value) { public Slot entry(LuaValue key, LuaValue value) {
value = value.strongvalue(); value = value.strongvalue();
if (value == null) if ( value == null )
return null; return null;
if (weakkeys && !(key.isnumber() || key.isstring() || key.isboolean())) { if ( weakkeys && !( key.isnumber() || key.isstring() || key.isboolean() )) {
if (weakvalues && !(value.isnumber() || value.isstring() || value.isboolean())) { if ( weakvalues && !( value.isnumber() || value.isstring() || value.isboolean() )) {
return new WeakKeyAndValueSlot(key, value, null); return new WeakKeyAndValueSlot( key, value, null );
} else { } else {
return new WeakKeySlot(key, value, null); return new WeakKeySlot( key, value, null );
} }
} }
if (weakvalues && !(value.isnumber() || value.isstring() || value.isboolean())) { if ( weakvalues && ! (value.isnumber() || value.isstring() || value.isboolean() )) {
return new WeakValueSlot(key, value, null); return new WeakValueSlot( key, value, null );
} }
return LuaTable.defaultEntry(key, value); return LuaTable.defaultEntry( key, value );
} }
public static abstract class WeakSlot implements Slot { public static abstract class WeakSlot implements Slot {
@@ -114,93 +109,87 @@ public class WeakTable implements Metatable {
this.next = next; this.next = next;
} }
@Override public abstract int keyindex( int hashMask );
public abstract int keyindex(int hashMask);
public abstract Slot set(LuaValue value); public abstract Slot set(LuaValue value);
@Override
public StrongSlot first() { public StrongSlot first() {
LuaValue key = strongkey(); LuaValue key = strongkey();
LuaValue value = strongvalue(); LuaValue value = strongvalue();
if (key != null && value != null) { if ( key != null && value != null ) {
return new LuaTable.NormalEntry(key, value); return new LuaTable.NormalEntry(key, value);
} else { } else {
if ( key == null ) {
this.key = null; this.key = null;
}
if ( value == null ) {
this.value = null; this.value = null;
}
return null; return null;
} }
} }
@Override
public StrongSlot find(LuaValue key) { public StrongSlot find(LuaValue key) {
StrongSlot first = first(); StrongSlot first = first();
return first != null? first.find(key): null; return ( first != null ) ? first.find( key ) : null;
} }
@Override
public boolean keyeq(LuaValue key) { public boolean keyeq(LuaValue key) {
StrongSlot first = first(); StrongSlot first = first();
return first != null && first.keyeq(key); return ( first != null ) && first.keyeq( key );
} }
@Override
public Slot rest() { public Slot rest() {
return next; return next;
} }
@Override
public int arraykey(int max) { public int arraykey(int max) {
// Integer keys can never be weak. // Integer keys can never be weak.
return 0; return 0;
} }
@Override
public Slot set(StrongSlot target, LuaValue value) { public Slot set(StrongSlot target, LuaValue value) {
LuaValue key = strongkey(); LuaValue key = strongkey();
if (key != null && target.find(key) != null) { if ( key != null && target.find( key ) != null ) {
return set(value); return set( value );
} else if (key != null) { } else if ( key != null ) {
// Our key is still good. // Our key is still good.
next = next.set(target, value); next = next.set( target, value );
return this; return this;
} else { } else {
// our key was dropped, remove ourselves from the chain. // our key was dropped, remove ourselves from the chain.
return next.set(target, value); return next.set( target, value );
} }
} }
@Override public Slot add( Slot entry ) {
public Slot add(Slot entry) { next = ( next != null ) ? next.add( entry ) : entry;
next = next != null? next.add(entry): entry; if ( strongkey() != null && strongvalue() != null ) {
if (strongkey() != null && strongvalue() != null) {
return this; return this;
} else { } else {
return next; return next;
} }
} }
@Override public Slot remove( StrongSlot target ) {
public Slot remove(StrongSlot target) {
LuaValue key = strongkey(); LuaValue key = strongkey();
if (key == null) { if ( key == null ) {
return next.remove(target); return next.remove( target );
} else if (target.keyeq(key)) { } else if ( target.keyeq( key ) ) {
this.value = null; this.value = null;
return this; return this;
} else { } else {
next = next.remove(target); next = next.remove( target );
return this; return this;
} }
} }
@Override public Slot relink( Slot rest ) {
public Slot relink(Slot rest) { if ( strongkey() != null && strongvalue() != null ) {
if (strongkey() != null && strongvalue() != null) { if ( rest == null && this.next == null ) {
if (rest == null && this.next == null) {
return this; return this;
} else { } else {
return copy(rest); return copy( rest );
} }
} else { } else {
return rest; return rest;
@@ -215,74 +204,66 @@ public class WeakTable implements Metatable {
return (LuaValue) value; return (LuaValue) value;
} }
protected abstract WeakSlot copy(Slot next); protected abstract WeakSlot copy( Slot next );
} }
static class WeakKeySlot extends WeakSlot { static class WeakKeySlot extends WeakSlot {
private final int keyhash; private final int keyhash;
protected WeakKeySlot(LuaValue key, LuaValue value, Slot next) { protected WeakKeySlot( LuaValue key, LuaValue value, Slot next ) {
super(weaken(key), value, next); super(weaken(key), value, next);
keyhash = key.hashCode(); keyhash = key.hashCode();
} }
protected WeakKeySlot(WeakKeySlot copyFrom, Slot next) { protected WeakKeySlot( WeakKeySlot copyFrom, Slot next ) {
super(copyFrom.key, copyFrom.value, next); super( copyFrom.key, copyFrom.value, next );
this.keyhash = copyFrom.keyhash; this.keyhash = copyFrom.keyhash;
} }
@Override public int keyindex( int mask ) {
public int keyindex(int mask) { return LuaTable.hashmod( keyhash, mask );
return LuaTable.hashmod(keyhash, mask);
} }
@Override
public Slot set(LuaValue value) { public Slot set(LuaValue value) {
this.value = value; this.value = value;
return this; return this;
} }
@Override
public LuaValue strongkey() { public LuaValue strongkey() {
return strengthen(key); return strengthen( key );
} }
@Override protected WeakSlot copy( Slot rest ) {
protected WeakSlot copy(Slot rest) { return new WeakKeySlot( this, rest );
return new WeakKeySlot(this, rest);
} }
} }
static class WeakValueSlot extends WeakSlot { static class WeakValueSlot extends WeakSlot {
protected WeakValueSlot(LuaValue key, LuaValue value, Slot next) { protected WeakValueSlot( LuaValue key, LuaValue value, Slot next ) {
super(key, weaken(value), next); super( key, weaken(value), next);
} }
protected WeakValueSlot(WeakValueSlot copyFrom, Slot next) { protected WeakValueSlot( WeakValueSlot copyFrom, Slot next ) {
super(copyFrom.key, copyFrom.value, next); super( copyFrom.key, copyFrom.value, next );
} }
@Override public int keyindex( int mask ) {
public int keyindex(int mask) { return LuaTable.hashSlot( strongkey(), mask );
return LuaTable.hashSlot(strongkey(), mask);
} }
@Override
public Slot set(LuaValue value) { public Slot set(LuaValue value) {
this.value = weaken(value); this.value = weaken(value);
return this; return this;
} }
@Override
public LuaValue strongvalue() { public LuaValue strongvalue() {
return strengthen(value); return strengthen( value );
} }
@Override
protected WeakSlot copy(Slot next) { protected WeakSlot copy(Slot next) {
return new WeakValueSlot(this, next); return new WeakValueSlot( this, next );
} }
} }
@@ -290,52 +271,45 @@ public class WeakTable implements Metatable {
private final int keyhash; private final int keyhash;
protected WeakKeyAndValueSlot(LuaValue key, LuaValue value, Slot next) { protected WeakKeyAndValueSlot( LuaValue key, LuaValue value, Slot next ) {
super(weaken(key), weaken(value), next); super( weaken(key), weaken(value), next );
keyhash = key.hashCode(); keyhash = key.hashCode();
} }
protected WeakKeyAndValueSlot(WeakKeyAndValueSlot copyFrom, Slot next) { protected WeakKeyAndValueSlot(WeakKeyAndValueSlot copyFrom, Slot next) {
super(copyFrom.key, copyFrom.value, next); super( copyFrom.key, copyFrom.value, next );
keyhash = copyFrom.keyhash; keyhash = copyFrom.keyhash;
} }
@Override public int keyindex( int hashMask ) {
public int keyindex(int hashMask) { return LuaTable.hashmod( keyhash, hashMask );
return LuaTable.hashmod(keyhash, hashMask);
} }
@Override
public Slot set(LuaValue value) { public Slot set(LuaValue value) {
this.value = weaken(value); this.value = weaken(value);
return this; return this;
} }
@Override
public LuaValue strongkey() { public LuaValue strongkey() {
return strengthen(key); return strengthen( key );
} }
@Override
public LuaValue strongvalue() { public LuaValue strongvalue() {
return strengthen(value); return strengthen( value );
} }
@Override protected WeakSlot copy( Slot next ) {
protected WeakSlot copy(Slot next) { return new WeakKeyAndValueSlot( this, next );
return new WeakKeyAndValueSlot(this, next);
} }
} }
/** /**
* Self-sent message to convert a value to its weak counterpart * Self-sent message to convert a value to its weak counterpart
*
* @param value value to convert * @param value value to convert
* @return {@link LuaValue} that is a strong or weak reference, depending on * @return {@link LuaValue} that is a strong or weak reference, depending on type of {@code value}
* type of {@code value}
*/ */
protected static LuaValue weaken(LuaValue value) { protected static LuaValue weaken( LuaValue value ) {
switch (value.type()) { switch ( value.type() ) {
case LuaValue.TFUNCTION: case LuaValue.TFUNCTION:
case LuaValue.TTHREAD: case LuaValue.TTHREAD:
case LuaValue.TTABLE: case LuaValue.TTABLE:
@@ -349,24 +323,21 @@ public class WeakTable implements Metatable {
/** /**
* Unwrap a LuaValue from a WeakReference and/or WeakUserdata. * Unwrap a LuaValue from a WeakReference and/or WeakUserdata.
*
* @param ref reference to convert * @param ref reference to convert
* @return LuaValue or null * @return LuaValue or null
* @see #weaken(LuaValue) * @see #weaken(LuaValue)
*/ */
protected static LuaValue strengthen(Object ref) { protected static LuaValue strengthen(Object ref) {
if (ref instanceof WeakReference) { if ( ref instanceof WeakReference ) {
ref = ((WeakReference) ref).get(); ref = ((WeakReference) ref).get();
} }
if (ref instanceof WeakValue) { if ( ref instanceof WeakValue ) {
return ((WeakValue) ref).strongvalue(); return ((WeakValue) ref).strongvalue();
} }
return (LuaValue) ref; return (LuaValue) ref;
} }
/** /** Internal class to implement weak values.
* Internal class to implement weak values.
*
* @see WeakTable * @see WeakTable
*/ */
static class WeakValue extends LuaValue { static class WeakValue extends LuaValue {
@@ -376,39 +347,32 @@ public class WeakTable implements Metatable {
ref = new WeakReference(value); ref = new WeakReference(value);
} }
@Override
public int type() { public int type() {
illegal("type", "weak value"); illegal("type","weak value");
return 0; return 0;
} }
@Override
public String typename() { public String typename() {
illegal("typename", "weak value"); illegal("typename","weak value");
return null; return null;
} }
@Override
public String toString() { public String toString() {
return "weak<" + ref.get() + ">"; return "weak<"+ref.get()+">";
} }
@Override
public LuaValue strongvalue() { public LuaValue strongvalue() {
Object o = ref.get(); Object o = ref.get();
return (LuaValue) o; return (LuaValue)o;
} }
@Override
public boolean raweq(LuaValue rhs) { public boolean raweq(LuaValue rhs) {
Object o = ref.get(); Object o = ref.get();
return o != null && rhs.raweq((LuaValue) o); return o!=null && rhs.raweq((LuaValue)o);
} }
} }
/** /** Internal class to implement weak userdata values.
* Internal class to implement weak userdata values.
*
* @see WeakTable * @see WeakTable
*/ */
static final class WeakUserdata extends WeakValue { static final class WeakUserdata extends WeakValue {
@@ -421,14 +385,13 @@ public class WeakTable implements Metatable {
mt = value.getmetatable(); mt = value.getmetatable();
} }
@Override
public LuaValue strongvalue() { public LuaValue strongvalue() {
Object u = ref.get(); Object u = ref.get();
if (u != null) if ( u != null )
return (LuaValue) u; return (LuaValue) u;
Object o = ob.get(); Object o = ob.get();
if (o != null) { if ( o != null ) {
LuaValue ud = LuaValue.userdataOf(o, mt); LuaValue ud = LuaValue.userdataOf(o,mt);
ref = new WeakReference(ud); ref = new WeakReference(ud);
return ud; return ud;
} else { } else {
@@ -437,12 +400,10 @@ public class WeakTable implements Metatable {
} }
} }
@Override
public LuaValue wrap(LuaValue value) { public LuaValue wrap(LuaValue value) {
return weakvalues? weaken(value): value; return weakvalues ? weaken( value ) : value;
} }
@Override
public LuaValue arrayget(LuaValue[] array, int index) { public LuaValue arrayget(LuaValue[] array, int index) {
LuaValue value = array[index]; LuaValue value = array[index];
if (value != null) { if (value != null) {

View File

@@ -38,139 +38,151 @@ import org.luaj.vm2.Upvaldesc;
public class Constants extends Lua { public class Constants extends Lua {
/** Maximum stack size of a luaj vm interpreter instance. */ /** Maximum stack size of a luaj vm interpreter instance. */
public static final int MAXSTACK = 250; public static final int MAXSTACK = 1024;
static final int LUAI_MAXUPVAL = 0xff; static final int LUAI_MAXUPVAL = 0xff;
static final int LUAI_MAXVARS = 200; static final int LUAI_MAXVARS = 1024;
static final int NO_REG = MAXARG_A; static final int NO_REG = MAXARG_A;
/* OpMode - basic instruction format */ /* OpMode - basic instruction format */
static final int iABC = 0, iABx = 1, iAsBx = 2; static final int
iABC = 0,
iABx = 1,
iAsBx = 2;
/* OpArgMask */ /* OpArgMask */
static final int OpArgN = 0, /* argument is not used */ static final int
OpArgN = 0, /* argument is not used */
OpArgU = 1, /* argument is used */ OpArgU = 1, /* argument is used */
OpArgR = 2, /* argument is a register or a jump offset */ OpArgR = 2, /* argument is a register or a jump offset */
OpArgK = 3; /* argument is a constant or register/constant */ OpArgK = 3; /* argument is a constant or register/constant */
protected static void _assert(boolean b) { protected static void _assert(boolean b) {
if (!b) if (!b)
throw new LuaError("compiler assert failed"); throw new LuaError("compiler assert failed");
} }
static void SET_OPCODE(InstructionPtr i, int o) { static void SET_OPCODE(InstructionPtr i,int o) {
i.set(i.get() & MASK_NOT_OP | o<<POS_OP & MASK_OP); i.set( ( i.get() & (MASK_NOT_OP)) | ((o << POS_OP) & MASK_OP) );
} }
static void SETARG_A(int[] code, int index, int u) { static void SETARG_A(int[] code, int index, int u) {
code[index] = code[index] & MASK_NOT_A | u<<POS_A & MASK_A; code[index] = (code[index] & (MASK_NOT_A)) | ((u << POS_A) & MASK_A);
} }
static void SETARG_A(InstructionPtr i, int u) { static void SETARG_A(InstructionPtr i,int u) {
i.set(i.get() & MASK_NOT_A | u<<POS_A & MASK_A); i.set( ( i.get() & (MASK_NOT_A)) | ((u << POS_A) & MASK_A) );
} }
static void SETARG_B(InstructionPtr i, int u) { static void SETARG_B(InstructionPtr i,int u) {
i.set(i.get() & MASK_NOT_B | u<<POS_B & MASK_B); i.set( ( i.get() & (MASK_NOT_B)) | ((u << POS_B) & MASK_B) );
} }
static void SETARG_C(InstructionPtr i, int u) { static void SETARG_C(InstructionPtr i,int u) {
i.set(i.get() & MASK_NOT_C | u<<POS_C & MASK_C); i.set( ( i.get() & (MASK_NOT_C)) | ((u << POS_C) & MASK_C) );
} }
static void SETARG_Bx(InstructionPtr i, int u) { static void SETARG_Bx(InstructionPtr i,int u) {
i.set(i.get() & MASK_NOT_Bx | u<<POS_Bx & MASK_Bx); i.set( ( i.get() & (MASK_NOT_Bx)) | ((u << POS_Bx) & MASK_Bx) );
} }
static void SETARG_sBx(InstructionPtr i, int u) { static void SETARG_sBx(InstructionPtr i,int u) {
SETARG_Bx(i, u+MAXARG_sBx); SETARG_Bx( i, u + MAXARG_sBx );
} }
static int CREATE_ABC(int o, int a, int b, int c) { static int CREATE_ABC(int o, int a, int b, int c) {
return o<<POS_OP & MASK_OP | a<<POS_A & MASK_A | b<<POS_B & MASK_B | c<<POS_C & MASK_C; return ((o << POS_OP) & MASK_OP) |
((a << POS_A) & MASK_A) |
((b << POS_B) & MASK_B) |
((c << POS_C) & MASK_C) ;
} }
static int CREATE_ABx(int o, int a, int bc) { static int CREATE_ABx(int o, int a, int bc) {
return o<<POS_OP & MASK_OP | a<<POS_A & MASK_A | bc<<POS_Bx & MASK_Bx; return ((o << POS_OP) & MASK_OP) |
((a << POS_A) & MASK_A) |
((bc << POS_Bx) & MASK_Bx) ;
} }
static int CREATE_Ax(int o, int a) { static int CREATE_Ax(int o, int a) {
return o<<POS_OP & MASK_OP | a<<POS_Ax & MASK_Ax; return ((o << POS_OP) & MASK_OP) |
((a << POS_Ax) & MASK_Ax) ;
} }
// vector reallocation // vector reallocation
static LuaValue[] realloc(LuaValue[] v, int n) { static LuaValue[] realloc(LuaValue[] v, int n) {
LuaValue[] a = new LuaValue[n]; LuaValue[] a = new LuaValue[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static Prototype[] realloc(Prototype[] v, int n) { static Prototype[] realloc(Prototype[] v, int n) {
Prototype[] a = new Prototype[n]; Prototype[] a = new Prototype[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static LuaString[] realloc(LuaString[] v, int n) { static LuaString[] realloc(LuaString[] v, int n) {
LuaString[] a = new LuaString[n]; LuaString[] a = new LuaString[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static LocVars[] realloc(LocVars[] v, int n) { static LocVars[] realloc(LocVars[] v, int n) {
LocVars[] a = new LocVars[n]; LocVars[] a = new LocVars[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static Upvaldesc[] realloc(Upvaldesc[] v, int n) { static Upvaldesc[] realloc(Upvaldesc[] v, int n) {
Upvaldesc[] a = new Upvaldesc[n]; Upvaldesc[] a = new Upvaldesc[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static LexState.Vardesc[] realloc(LexState.Vardesc[] v, int n) { static LexState.Vardesc[] realloc(LexState.Vardesc[] v, int n) {
LexState.Vardesc[] a = new LexState.Vardesc[n]; LexState.Vardesc[] a = new LexState.Vardesc[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static LexState.Labeldesc[] grow(LexState.Labeldesc[] v, int min_n) { static LexState.Labeldesc[] grow(LexState.Labeldesc[] v, int min_n) {
return v == null? new LexState.Labeldesc[2]: v.length < min_n? realloc(v, v.length*2): v; return v == null ? new LexState.Labeldesc[2] : v.length < min_n ? realloc(v, v.length*2) : v;
} }
static LexState.Labeldesc[] realloc(LexState.Labeldesc[] v, int n) { static LexState.Labeldesc[] realloc(LexState.Labeldesc[] v, int n) {
LexState.Labeldesc[] a = new LexState.Labeldesc[n]; LexState.Labeldesc[] a = new LexState.Labeldesc[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static int[] realloc(int[] v, int n) { static int[] realloc(int[] v, int n) {
int[] a = new int[n]; int[] a = new int[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static byte[] realloc(byte[] v, int n) { static byte[] realloc(byte[] v, int n) {
byte[] a = new byte[n]; byte[] a = new byte[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }
static char[] realloc(char[] v, int n) { static char[] realloc(char[] v, int n) {
char[] a = new char[n]; char[] a = new char[n];
if (v != null) if ( v != null )
System.arraycopy(v, 0, a, 0, Math.min(v.length, n)); System.arraycopy(v, 0, a, 0, Math.min(v.length,n));
return a; return a;
} }

Some files were not shown because too many files have changed in this diff Show More