Add formatter definition and format code
This commit is contained in:
390
.ide/formatter.xml
Normal file
390
.ide/formatter.xml
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
<?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>
|
||||||
@@ -21,16 +21,16 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* String buffer for use in string library methods, optimized for production
|
* String buffer for use in string library methods, optimized for production of
|
||||||
* of StrValue instances.
|
* StrValue instances.
|
||||||
* <p>
|
* <p>
|
||||||
* The buffer can begin initially as a wrapped {@link LuaValue}
|
* The buffer can begin initially as a wrapped {@link LuaValue} and only when
|
||||||
* and only when concatenation actually occurs are the bytes first copied.
|
* concatenation actually occurs are the bytes first copied.
|
||||||
* <p>
|
* <p>
|
||||||
* To convert back to a {@link LuaValue} again,
|
* To convert back to a {@link LuaValue} again, the function
|
||||||
* the function {@link Buffer#value()} is used.
|
* {@link Buffer#value()} is used.
|
||||||
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaValue#buffer()
|
* @see LuaValue#buffer()
|
||||||
* @see LuaString
|
* @see LuaString
|
||||||
@@ -57,6 +57,7 @@ public final class Buffer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create buffer with default capacity
|
* Create buffer with default capacity
|
||||||
|
*
|
||||||
* @see #DEFAULT_CAPACITY
|
* @see #DEFAULT_CAPACITY
|
||||||
*/
|
*/
|
||||||
public Buffer() {
|
public Buffer() {
|
||||||
@@ -65,6 +66,7 @@ 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) {
|
||||||
@@ -76,6 +78,7 @@ 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) {
|
||||||
@@ -86,6 +89,7 @@ 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() {
|
||||||
@@ -94,6 +98,7 @@ 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) {
|
||||||
@@ -105,6 +110,7 @@ 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 final LuaString tostring() {
|
public final LuaString tostring() {
|
||||||
@@ -114,6 +120,7 @@ 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
|
||||||
*/
|
*/
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
@@ -122,6 +129,7 @@ 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
|
||||||
*/
|
*/
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -130,6 +138,7 @@ public final class Buffer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 final Buffer append(byte b) {
|
public final Buffer append(byte b) {
|
||||||
@@ -140,6 +149,7 @@ public final class Buffer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 final Buffer append(LuaValue val) {
|
public final Buffer append(LuaValue val) {
|
||||||
@@ -149,6 +159,7 @@ public final class Buffer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 final Buffer append(LuaString str) {
|
public final Buffer append(LuaString str) {
|
||||||
@@ -160,8 +171,9 @@ public final class Buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a Java String to the buffer.
|
* Append a Java String to the buffer. The Java string will be converted to
|
||||||
* The Java string will be converted to bytes using the UTF8 encoding.
|
* 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)
|
||||||
*/
|
*/
|
||||||
@@ -174,34 +186,46 @@ public final class Buffer {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Concatenate this buffer onto a {@link LuaValue}
|
/**
|
||||||
* @param lhs the left-hand-side value onto which we are concatenating {@code this}
|
* Concatenate this buffer onto a {@link LuaValue}
|
||||||
|
*
|
||||||
|
* @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}
|
/**
|
||||||
* @param lhs the left-hand-side value onto which we are concatenating {@code this}
|
* Concatenate this buffer onto a {@link LuaString}
|
||||||
|
*
|
||||||
|
* @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
|
/**
|
||||||
* @param s the left-hand-side value which we will concatenate onto the front of {@code this}
|
* 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}
|
||||||
* @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) {
|
||||||
@@ -214,9 +238,13 @@ public final class Buffer {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ensure there is enough room before and after the bytes.
|
/**
|
||||||
* @param nbefore number of unused bytes which must precede the data after this completes
|
* Ensure there is enough room before and after the bytes.
|
||||||
* @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 final void makeroom(int nbefore, int nafter) {
|
public final void makeroom(int nbefore, int nafter) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@@ -233,7 +261,9 @@ public final class Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -33,73 +33,94 @@ import org.luaj.vm2.lib.PackageLib;
|
|||||||
import org.luaj.vm2.lib.ResourceFinder;
|
import org.luaj.vm2.lib.ResourceFinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global environment used by luaj. Contains global variables referenced by executing lua.
|
* Global environment used by luaj. Contains global variables referenced by
|
||||||
|
* executing lua.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* <h3>Constructing and Initializing Instances</h3>
|
* <h3>Constructing and Initializing Instances</h3> Typically, this is
|
||||||
* Typically, this is constructed indirectly by a call to
|
* constructed indirectly by a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()},
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}, and then used to
|
||||||
* and then used to load lua scripts for execution as in the following example.
|
* load lua scripts for execution as in the following example.
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @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 loaded
|
* For specialized circumstances, the Globals may be constructed directly and
|
||||||
* with only those libraries that are needed, for example.
|
* loaded with only those libraries that are needed, for example.
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @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>
|
* <h3>Loading and Executing Lua Code</h3> Globals contains convenience
|
||||||
* Globals contains convenience functions to load and execute lua source code given a Reader.
|
* functions to load and execute lua source code given a Reader. A simple
|
||||||
* A simple example is:
|
* 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>
|
* <h3>Fine-Grained Control of Compiling and Loading Lua</h3> Executable
|
||||||
* Executable LuaFunctions are created from lua code in several steps
|
* 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} using {@link Loader}
|
* <li>construct {@link LuaClosure} from {@link Prototype} with {@link Globals}
|
||||||
|
* using {@link Loader}
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* There are alternate flows when the direct lua-to-Java bytecode compiling {@link org.luaj.vm2.luajc.LuaJC} is used.
|
* There are alternate flows when the direct lua-to-Java bytecode compiling
|
||||||
|
* {@link org.luaj.vm2.luajc.LuaJC} is used.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>compile lua to lua bytecode using {@link Compiler} or load precompiled code using {@link Undumper}
|
* <li>compile lua to lua bytecode using {@link Compiler} or load precompiled
|
||||||
* <li>convert lua bytecode to equivalent Java bytecode using {@link org.luaj.vm2.luajc.LuaJC} that implements {@link Loader} directly
|
* code using {@link Undumper}
|
||||||
|
* <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>
|
* <h3>Java Field</h3> Certain public fields are provided that contain the
|
||||||
* Certain public fields are provided that contain the current values of important global state:
|
* current values of important global state:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #STDIN} Current value for standard input in the laaded {@link IoLib}, if any.
|
* <li>{@link #STDIN} Current value for standard input in the laaded
|
||||||
* <li>{@link #STDOUT} Current value for standard output 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 #STDOUT} Current value for standard output in the loaded
|
||||||
|
* {@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>
|
* <h3>Lua Environment Variables</h3> When using
|
||||||
* When using {@link org.luaj.vm2.lib.jse.JsePlatform} or {@link org.luaj.vm2.lib.jme.JmePlatform},
|
* {@link org.luaj.vm2.lib.jse.JsePlatform} or
|
||||||
* these environment variables are created within the Globals.
|
* {@link org.luaj.vm2.lib.jme.JmePlatform}, these environment variables are
|
||||||
|
* 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>
|
* <h3>Use in Multithreaded Environments</h3> In a multi-threaded server
|
||||||
* In a multi-threaded server environment, each server thread should create one Globals instance,
|
* environment, each server thread should create one Globals instance, which
|
||||||
* which will be logically distinct and not interfere with each other, but share certain
|
* will be logically distinct and not interfere with each other, but share
|
||||||
* static immutable resources such as class data and string data.
|
* certain static immutable resources such as class data and string data.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
@@ -126,7 +147,9 @@ 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 */
|
||||||
@@ -135,18 +158,30 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,24 +191,39 @@ 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.
|
||||||
|
*/
|
||||||
public Globals checkglobals() {
|
public Globals checkglobals() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The installed loader.
|
/**
|
||||||
* @see Loader */
|
* The installed loader.
|
||||||
|
*
|
||||||
|
* @see Loader
|
||||||
|
*/
|
||||||
public Loader loader;
|
public Loader loader;
|
||||||
|
|
||||||
/** The installed compiler.
|
/**
|
||||||
* @see Compiler */
|
* The installed compiler.
|
||||||
|
*
|
||||||
|
* @see Compiler
|
||||||
|
*/
|
||||||
public Compiler compiler;
|
public Compiler compiler;
|
||||||
|
|
||||||
/** The installed undumper.
|
/**
|
||||||
* @see Undumper */
|
* The installed 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.
|
||||||
@@ -186,69 +236,96 @@ public class Globals extends LuaTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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.'"
|
* 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 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 .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) {
|
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 .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) {
|
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.
|
/**
|
||||||
* Must be lua source.
|
* Convenience function to load a string value as a script with a custom
|
||||||
* @param script Contents of a lua script, such as "print 'hello, world.'"
|
* environment. Must be lua 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.
|
||||||
* @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
|
||||||
* @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
|
* function.
|
||||||
|
* @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.
|
/**
|
||||||
* The source is converted to UTF-8, so any characters appearing in quoted literals
|
* Load the content form a reader as a text file. Must be lua source. The
|
||||||
* above the range 128 will be converted into multiple bytes.
|
* source is converted to UTF-8, so any characters appearing in quoted
|
||||||
* @param reader Reader containing text of a lua script, such as "print 'hello, world.'"
|
* 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 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 .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) {
|
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.
|
/**
|
||||||
* Must be lua source. The source is converted to UTF-8, so any characters
|
* Load the content form a reader as a text file, supplying a custom
|
||||||
* appearing in quoted literals above the range 128 will be converted into
|
* environment. Must be lua source. The source is converted to UTF-8, so any
|
||||||
* multiple bytes.
|
* characters appearing in quoted literals above the range 128 will be
|
||||||
* @param reader Reader containing text of a lua script, such as "print 'hello, world.'"
|
* converted into multiple bytes.
|
||||||
|
*
|
||||||
|
* @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 function.
|
* @param environment LuaTable to be used as the environment for the loaded
|
||||||
* @return LuaValue that may be executed via .call(), .invoke(), or .method() calls.
|
* function.
|
||||||
|
* @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 loading as binary or text or either.
|
* @param mode String containing 'b' or 't' or both to control
|
||||||
* @param environment LuaTable to be used as the environment for the loaded function.
|
* loading as binary or text or either.
|
||||||
* */
|
* @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);
|
||||||
@@ -260,12 +337,16 @@ public class Globals extends LuaTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Load lua source or lua binary from an input stream into a Prototype.
|
/**
|
||||||
* The InputStream is either a binary lua chunk starting with the lua binary chunk signature,
|
* Load lua source or lua binary from an input stream into a Prototype. The
|
||||||
* or a text input file. If it is a text input file, it is interpreted as a UTF-8 byte sequence.
|
* InputStream is either a binary lua chunk starting with the lua binary
|
||||||
|
* 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 as binary or text or either.
|
* @param mode String containing 'b' or 't' or both to control loading
|
||||||
|
* 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) {
|
||||||
@@ -286,17 +367,21 @@ public class Globals extends LuaTable {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compile lua source from a Reader into a Prototype. The characters in the reader
|
/**
|
||||||
* are converted to bytes using the UTF-8 encoding, so a string literal containing
|
* Compile lua source from a Reader into a Prototype. The characters in the
|
||||||
* characters with codepoints 128 or above will be converted into multiple bytes.
|
* reader are converted to bytes using the UTF-8 encoding, so a string
|
||||||
|
* 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.
|
/**
|
||||||
* The input is assumed to be UTf-8, but since bytes in the range 128-255 are passed along as
|
* Compile lua source from an InputStream into a Prototype. The input is
|
||||||
* literal bytes, any ASCII-compatible encoding such as ISO 8859-1 may also be used.
|
* assumed to be UTf-8, but since bytes in the range 128-255 are passed
|
||||||
|
* 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)
|
||||||
@@ -304,9 +389,13 @@ public class Globals extends LuaTable {
|
|||||||
return compiler.compile(stream, chunkname);
|
return compiler.compile(stream, chunkname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function which yields the current thread.
|
/**
|
||||||
* @param args Arguments to supply as return values in the resume function of the resuming thread.
|
* Function which yields the current 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())
|
||||||
@@ -320,16 +409,20 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
i = n;
|
i = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
return i < n? s.charAt(i++): -1;
|
return i < n? s.charAt(i++): -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@@ -344,48 +437,60 @@ 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;
|
||||||
|
|
||||||
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++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) return -1;
|
if (a <= 0)
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
/**
|
||||||
* on both JME and JSE.
|
* Simple converter from Reader to InputStream using UTF8 encoding that will
|
||||||
* This class may be moved to its own package in the future.
|
* work on both JME and JSE. This class may be moved to its own package in
|
||||||
|
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int avail() throws IOException {
|
protected int avail() throws IOException {
|
||||||
if (i < j) return j - i;
|
if (i < j)
|
||||||
|
return j-i;
|
||||||
int n = r.read(c);
|
int n = r.read(c);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -399,29 +504,36 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
r.close();
|
r.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Simple buffered InputStream that supports mark.
|
/**
|
||||||
* Used to examine an InputStream for a 4-byte binary lua signature,
|
* Simple buffered InputStream that supports mark. Used to examine an
|
||||||
* and fall back to text input when the signature is not found,
|
* InputStream for a 4-byte binary lua signature, and fall back to text
|
||||||
* as well as speed up normal compilation and reading of lua scripts.
|
* input when the signature is not found, as well as speed up normal
|
||||||
* This class may be moved to its own package in the future.
|
* compilation and reading of lua scripts. This class may be moved to its
|
||||||
|
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int avail() throws IOException {
|
protected int avail() throws IOException {
|
||||||
if (i < j) return j - i;
|
if (i < j)
|
||||||
if (j >= b.length) i = j = 0;
|
return j-i;
|
||||||
|
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)
|
||||||
@@ -436,9 +548,11 @@ public class Globals extends LuaTable {
|
|||||||
j += n;
|
j += n;
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
s.close();
|
s.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -448,9 +562,11 @@ public class Globals extends LuaTable {
|
|||||||
b = dest;
|
b = dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean markSupported() {
|
public boolean markSupported() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void reset() throws IOException {
|
public synchronized void reset() throws IOException {
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ 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>
|
||||||
@@ -34,47 +33,63 @@ import java.io.InputStream;
|
|||||||
* 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
|
* The canonical method to load and execute code is done indirectly using the
|
||||||
* indirectly using the Globals:
|
* Globals:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* LuaValue chunk = globasl.load("print('hello, world')", "main.lua");
|
* LuaValue chunk = globasl.load("print('hello, world')", "main.lua");
|
||||||
* chunk.call();
|
* chunk.call();
|
||||||
* } </pre>
|
* }
|
||||||
* This should work regardless of which {@link Globals.Compiler} or {@link Globals.Undumper}
|
* </pre>
|
||||||
* have been installed.
|
*
|
||||||
|
* This should work regardless of which {@link Globals.Compiler} or
|
||||||
|
* {@link Globals.Undumper} have been installed.
|
||||||
* <p>
|
* <p>
|
||||||
* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
|
* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform} to construct globals, the
|
||||||
* to construct globals, the {@link LoadState} default undumper is installed
|
* {@link LoadState} default undumper is installed as the default
|
||||||
* as the default {@link Globals.Undumper}.
|
* {@link Globals.Undumper}.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState} class
|
* A lua binary file is created via the {@link org.luaj.vm2.compiler.DumpState}
|
||||||
:
|
* class :
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua");
|
* Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua");
|
||||||
* ByteArrayOutputStream o = new ByteArrayOutputStream();
|
* ByteArrayOutputStream o = new ByteArrayOutputStream();
|
||||||
* org.luaj.vm2.compiler.DumpState.dump(p, o, false);
|
* org.luaj.vm2.compiler.DumpState.dump(p, o, false);
|
||||||
* byte[] lua_binary_file_bytes = o.toByteArray();
|
* byte[] lua_binary_file_bytes = o.toByteArray();
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* The {@link LoadState}'s default undumper {@link #instance}
|
* The {@link LoadState}'s default undumper {@link #instance} may be used
|
||||||
* may be used directly to undump these bytes:
|
* directly to undump these bytes:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <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
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
|
* Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
|
||||||
* LuaClosure c = new LuaClosure(p, globals);
|
* LuaClosure c = new LuaClosure(p, globals);
|
||||||
* c.call();
|
* c.call();
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @see Globals.Compiler
|
* @see Globals.Compiler
|
||||||
* @see Globals.Undumper
|
* @see Globals.Undumper
|
||||||
@@ -87,16 +102,25 @@ import java.io.InputStream;
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
@@ -113,7 +137,10 @@ 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 */
|
||||||
@@ -122,11 +149,9 @@ 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;
|
||||||
|
|
||||||
@@ -161,22 +186,28 @@ 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?
|
return luacLittleEndian? (buf[3]<<24) | ((0xff & buf[2])<<16) | ((0xff & buf[1])<<8) | (0xff & buf[0])
|
||||||
(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]);
|
||||||
(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 {
|
||||||
@@ -191,14 +222,16 @@ public class LoadState {
|
|||||||
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?
|
array[i] = luacLittleEndian
|
||||||
(buf[j+3] << 24) | ((0xff & buf[j+2]) << 16) | ((0xff & buf[j+1]) << 8) | (0xff & buf[j+0]):
|
? (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]);
|
: (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 {
|
||||||
@@ -213,7 +246,9 @@ public class LoadState {
|
|||||||
return (((long) b)<<32) | (((long) 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 {
|
||||||
@@ -227,8 +262,10 @@ public class LoadState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 to the bits provided.
|
* @return {@link LuaInteger} or {@link LuaDouble} whose value corresponds
|
||||||
|
* 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) {
|
||||||
@@ -252,6 +289,7 @@ public class LoadState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
@@ -265,6 +303,7 @@ public class LoadState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
@@ -301,7 +340,6 @@ public class LoadState {
|
|||||||
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;
|
||||||
@@ -314,6 +352,7 @@ public class LoadState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
@@ -336,6 +375,7 @@ public class LoadState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -366,6 +406,7 @@ 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 {
|
||||||
@@ -383,17 +424,19 @@ public class LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load input stream as a lua binary chunk if the first 4 bytes are the lua binary signature.
|
* Load input stream as a lua binary chunk if the first 4 bytes are the lua
|
||||||
* @param stream InputStream to read, after having read the first byte already
|
* binary signature.
|
||||||
|
*
|
||||||
|
* @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 were not the lua signature.
|
* @return {@link Prototype} that was loaded, or null if the first 4 bytes
|
||||||
|
* 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]
|
if (stream.read() != LUA_SIGNATURE[0] || stream.read() != LUA_SIGNATURE[1] || stream.read() != LUA_SIGNATURE[2]
|
||||||
|| stream.read() != LUA_SIGNATURE[1]
|
|
||||||
|| stream.read() != LUA_SIGNATURE[2]
|
|
||||||
|| stream.read() != LUA_SIGNATURE[3])
|
|| stream.read() != LUA_SIGNATURE[3])
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -416,6 +459,7 @@ public class LoadState {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
@@ -435,8 +479,7 @@ public class LoadState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final class GlobalsUndumper implements Globals.Undumper {
|
private static final class GlobalsUndumper implements Globals.Undumper {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data class to hold debug information relating to local variables for a {@link Prototype}
|
* Data class to hold debug information relating to local variables for a
|
||||||
|
* {@link Prototype}
|
||||||
*/
|
*/
|
||||||
public class LocVars {
|
public class LocVars {
|
||||||
/** The local variable name */
|
/** The local variable name */
|
||||||
@@ -36,6 +37,7 @@ 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
|
||||||
|
|||||||
@@ -21,12 +21,11 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants for lua limits and opcodes.
|
* Constants for lua limits and opcodes.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a direct translation of C lua distribution header file constants
|
* This is a direct translation of C lua distribution header file constants for
|
||||||
* for bytecode creation and processing.
|
* bytecode creation and processing.
|
||||||
*/
|
*/
|
||||||
public class Lua {
|
public class Lua {
|
||||||
/** version is supplied by ant build task */
|
/** version is supplied by ant build task */
|
||||||
@@ -54,14 +53,12 @@ public class Lua {
|
|||||||
unsigned argument.
|
unsigned argument.
|
||||||
===========================================================================*/
|
===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
/* basic instruction format */
|
/* basic instruction format */
|
||||||
public static final int iABC = 0;
|
public static final int iABC = 0;
|
||||||
public static final int iABx = 1;
|
public static final int iABx = 1;
|
||||||
public static final int iAsBx = 2;
|
public static final int iAsBx = 2;
|
||||||
public static final int iAx = 3;
|
public static final int iAx = 3;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** size and position of opcode arguments.
|
** size and position of opcode arguments.
|
||||||
*/
|
*/
|
||||||
@@ -132,7 +129,6 @@ public class Lua {
|
|||||||
return ((i>>POS_Bx) & MAXARG_Bx)-MAXARG_sBx;
|
return ((i>>POS_Bx) & MAXARG_Bx)-MAXARG_sBx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Macros to operate RK indices
|
** Macros to operate RK indices
|
||||||
*/
|
*/
|
||||||
@@ -157,20 +153,17 @@ public class Lua {
|
|||||||
return ((x) | BITRK);
|
return ((x) | BITRK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** invalid register that fits in 8 bits
|
** invalid register that fits in 8 bits
|
||||||
*/
|
*/
|
||||||
public static final int NO_REG = MAXARG_A;
|
public static final int NO_REG = MAXARG_A;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** R(x) - register
|
** R(x) - register
|
||||||
** Kst(x) - constant (in constant table)
|
** Kst(x) - constant (in constant table)
|
||||||
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
|
** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** grep "ORDER OP" if you change these enums
|
** grep "ORDER OP" if you change these enums
|
||||||
*/
|
*/
|
||||||
@@ -263,7 +256,6 @@ public class Lua {
|
|||||||
(*) All `skips' (pc++) assume that next instruction is a jump
|
(*) All `skips' (pc++) assume that next instruction is a jump
|
||||||
===========================================================================*/
|
===========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** masks for instruction properties. The format is:
|
** masks for instruction properties. The format is:
|
||||||
** bits 0-1: op mode
|
** bits 0-1: op mode
|
||||||
@@ -325,15 +317,19 @@ public class Lua {
|
|||||||
public static int getOpMode(int m) {
|
public static int getOpMode(int m) {
|
||||||
return luaP_opmodes[m] & 3;
|
return luaP_opmodes[m] & 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getBMode(int m) {
|
public static int getBMode(int m) {
|
||||||
return (luaP_opmodes[m]>>4) & 3;
|
return (luaP_opmodes[m]>>4) & 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getCMode(int m) {
|
public static int getCMode(int m) {
|
||||||
return (luaP_opmodes[m]>>2) & 3;
|
return (luaP_opmodes[m]>>2) & 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean testAMode(int m) {
|
public static boolean testAMode(int m) {
|
||||||
return 0 != (luaP_opmodes[m] & (1<<6));
|
return 0 != (luaP_opmodes[m] & (1<<6));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean testTMode(int m) {
|
public static boolean testTMode(int m) {
|
||||||
return 0 != (luaP_opmodes[m] & (1<<7));
|
return 0 != (luaP_opmodes[m] & (1<<7));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
* These instance are not instantiated directly by clients. Instead, there are
|
||||||
* Instead, there are exactly twon instances of this class,
|
* exactly twon instances of this class, {@link LuaValue#TRUE} and
|
||||||
* {@link LuaValue#TRUE} and {@link LuaValue#FALSE}
|
* {@link LuaValue#FALSE} representing the lua values {@code true} and
|
||||||
* representing the lua values {@code true} and {@code false}.
|
* {@code false}. The function {@link LuaValue#valueOf(boolean)} will always
|
||||||
* 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
|
* Any {@link LuaValue} can be converted to its equivalent boolean
|
||||||
* boolean representation using {@link LuaValue#toboolean()}
|
* 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
|
||||||
@@ -75,6 +75,7 @@ public final class LuaBoolean extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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() {
|
||||||
|
|||||||
@@ -26,44 +26,56 @@ import org.luaj.vm2.lib.DebugLib.CallFrame;
|
|||||||
/**
|
/**
|
||||||
* Extension of {@link LuaFunction} which executes lua bytecode.
|
* Extension of {@link LuaFunction} which executes lua bytecode.
|
||||||
* <p>
|
* <p>
|
||||||
* A {@link LuaClosure} is a combination of a {@link Prototype}
|
* A {@link LuaClosure} is a combination of a {@link Prototype} and a
|
||||||
* and a {@link LuaValue} to use as an environment for execution.
|
* {@link LuaValue} to use as an environment for execution. Normally the
|
||||||
* Normally the {@link LuaValue} is a {@link Globals} in which case the environment
|
* {@link LuaValue} is a {@link Globals} in which case the environment will
|
||||||
* will contain standard lua libraries.
|
* contain standard lua libraries.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* There are three main ways {@link LuaClosure} instances are created:
|
* There are three main ways {@link LuaClosure} instances are created:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Construct an instance using {@link #LuaClosure(Prototype, LuaValue)}</li>
|
* <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>Construct it indirectly by loading a chunk via
|
||||||
* <li>Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode processing
|
* {@link Globals#load(java.io.Reader, String)}
|
||||||
|
* <li>Execute the lua bytecode {@link Lua#OP_CLOSURE} as part of bytecode
|
||||||
|
* processing
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* To construct it directly, the {@link Prototype} is typically created via a compiler such as
|
* To construct it directly, the {@link Prototype} is typically created via a
|
||||||
* {@link org.luaj.vm2.compiler.LuaC}:
|
* compiler such as {@link org.luaj.vm2.compiler.LuaC}:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* String script = "print( 'hello, world' )";
|
* String script = "print( 'hello, world' )";
|
||||||
* InputStream is = new ByteArrayInputStream(script.getBytes());
|
* InputStream is = new ByteArrayInputStream(script.getBytes());
|
||||||
* Prototype p = LuaC.instance.compile(is, "script");
|
* Prototype p = LuaC.instance.compile(is, "script");
|
||||||
* LuaValue globals = JsePlatform.standardGlobals();
|
* LuaValue globals = JsePlatform.standardGlobals();
|
||||||
* LuaClosure f = new LuaClosure(p, globals);
|
* LuaClosure f = new LuaClosure(p, globals);
|
||||||
* f.call();
|
* f.call();
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To construct it indirectly, the {@link Globals#load(java.io.Reader, String)} method may be used:
|
* To construct it indirectly, the {@link Globals#load(java.io.Reader, String)}
|
||||||
* <pre> {@code
|
* method may be used:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* LuaFunction f = globals.load(new StringReader(script), "script");
|
* LuaFunction f = globals.load(new StringReader(script), "script");
|
||||||
* LuaClosure c = f.checkclosure(); // This may fail if LuaJC is installed.
|
* LuaClosure c = f.checkclosure(); // This may fail if LuaJC is installed.
|
||||||
* c.call();
|
* c.call();
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* In this example, the "checkclosure()" may fail if direct lua-to-java-bytecode
|
* 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
|
* compiling using LuaJC is installed, because no LuaClosure is created in that
|
||||||
* and the value returned is a {@link LuaFunction} but not a {@link LuaClosure}.
|
* case and the value returned is a {@link LuaFunction} but not a
|
||||||
|
* {@link LuaClosure}.
|
||||||
* <p>
|
* <p>
|
||||||
* Since a {@link LuaClosure} is a {@link LuaFunction} which is a {@link LuaValue},
|
* Since a {@link LuaClosure} is a {@link LuaFunction} which is a
|
||||||
* all the value operations can be used directly such as:
|
* {@link LuaValue}, all the value operations can be used directly such as:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link LuaValue#call()}</li>
|
* <li>{@link LuaValue#call()}</li>
|
||||||
* <li>{@link LuaValue#call(LuaValue)}</li>
|
* <li>{@link LuaValue#call(LuaValue)}</li>
|
||||||
@@ -75,6 +87,7 @@ import org.luaj.vm2.lib.DebugLib.CallFrame;
|
|||||||
* <li>{@link LuaValue#invokemethod(String,Varargs)}</li>
|
* <li>{@link LuaValue#invokemethod(String,Varargs)}</li>
|
||||||
* <li>...</li>
|
* <li>...</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaFunction
|
* @see LuaFunction
|
||||||
* @see LuaValue#isclosure()
|
* @see LuaValue#isclosure()
|
||||||
@@ -92,8 +105,11 @@ public class LuaClosure extends LuaFunction {
|
|||||||
|
|
||||||
final Globals globals;
|
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.
|
* 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 p the Prototype to construct this Closure for.
|
||||||
* @param env the environment to associate with the closure.
|
* @param env the environment to associate with the closure.
|
||||||
*/
|
*/
|
||||||
@@ -112,7 +128,6 @@ public class LuaClosure extends LuaFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isclosure() {
|
public boolean isclosure() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -144,27 +159,46 @@ public class LuaClosure extends LuaFunction {
|
|||||||
public final LuaValue call(LuaValue arg) {
|
public final LuaValue call(LuaValue arg) {
|
||||||
LuaValue[] stack = getNewStack();
|
LuaValue[] stack = getNewStack();
|
||||||
switch (p.numparams) {
|
switch (p.numparams) {
|
||||||
default: stack[0]=arg; return execute(stack,NONE).arg1();
|
default:
|
||||||
case 0: return execute(stack,arg).arg1();
|
stack[0] = arg;
|
||||||
|
return execute(stack, NONE).arg1();
|
||||||
|
case 0:
|
||||||
|
return execute(stack, arg).arg1();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public final LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
LuaValue[] stack = getNewStack();
|
LuaValue[] stack = getNewStack();
|
||||||
switch (p.numparams) {
|
switch (p.numparams) {
|
||||||
default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1();
|
default:
|
||||||
case 1: stack[0]=arg1; return execute(stack,arg2).arg1();
|
stack[0] = arg1;
|
||||||
case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1();
|
stack[1] = arg2;
|
||||||
|
return execute(stack, NONE).arg1();
|
||||||
|
case 1:
|
||||||
|
stack[0] = arg1;
|
||||||
|
return execute(stack, arg2).arg1();
|
||||||
|
case 0:
|
||||||
|
return execute(stack, p.is_vararg != 0? varargsOf(arg1, arg2): NONE).arg1();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
|
public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
|
||||||
LuaValue[] stack = getNewStack();
|
LuaValue[] stack = getNewStack();
|
||||||
switch (p.numparams) {
|
switch (p.numparams) {
|
||||||
default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1();
|
default:
|
||||||
case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1();
|
stack[0] = arg1;
|
||||||
case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1();
|
stack[1] = arg2;
|
||||||
case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1();
|
stack[2] = arg3;
|
||||||
|
return execute(stack, NONE).arg1();
|
||||||
|
case 2:
|
||||||
|
stack[0] = arg1;
|
||||||
|
stack[1] = arg2;
|
||||||
|
return execute(stack, arg3).arg1();
|
||||||
|
case 1:
|
||||||
|
stack[0] = arg1;
|
||||||
|
return execute(stack, p.is_vararg != 0? varargsOf(arg2, arg3): NONE).arg1();
|
||||||
|
case 0:
|
||||||
|
return execute(stack, p.is_vararg != 0? varargsOf(arg1, arg2, arg3): NONE).arg1();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,8 +255,8 @@ public class LuaClosure extends LuaFunction {
|
|||||||
i = code[pc];
|
i = code[pc];
|
||||||
if ((i & 0x3f) != Lua.OP_EXTRAARG) {
|
if ((i & 0x3f) != Lua.OP_EXTRAARG) {
|
||||||
int op = i & 0x3f;
|
int op = i & 0x3f;
|
||||||
throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got " +
|
throw new LuaError("OP_EXTRAARG expected after OP_LOADKX, got "
|
||||||
(op < Print.OPNAMES.length - 1 ? Print.OPNAMES[op] : "UNKNOWN_OP_" + op));
|
+ (op < Print.OPNAMES.length-1? Print.OPNAMES[op]: "UNKNOWN_OP_" + op));
|
||||||
}
|
}
|
||||||
stack[a] = k[i>>>6];
|
stack[a] = k[i>>>6];
|
||||||
continue;
|
continue;
|
||||||
@@ -251,7 +285,8 @@ public class LuaClosure extends LuaFunction {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
|
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]);
|
upValues[a].getValue().set(((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b]),
|
||||||
|
(c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
|
case Lua.OP_SETUPVAL: /* A B UpValue[B]:= R(A) */
|
||||||
@@ -259,7 +294,8 @@ public class LuaClosure extends LuaFunction {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_SETTABLE: /* A B C R(A)[RK(B)]:= RK(C) */
|
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]);
|
stack[a].set(((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b]),
|
||||||
|
(c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
|
case Lua.OP_NEWTABLE: /* A B C R(A):= {} (size = B,C) */
|
||||||
@@ -272,27 +308,33 @@ public class LuaClosure extends LuaFunction {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_ADD: /* A B C R(A):= RK(B) + RK(C) */
|
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]);
|
stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
|
||||||
|
.add((c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_SUB: /* A B C R(A):= RK(B) - RK(C) */
|
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]);
|
stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
|
||||||
|
.sub((c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_MUL: /* A B C R(A):= RK(B) * RK(C) */
|
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]);
|
stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
|
||||||
|
.mul((c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_DIV: /* A B C R(A):= RK(B) / RK(C) */
|
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]);
|
stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
|
||||||
|
.div((c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_MOD: /* A B C R(A):= RK(B) % RK(C) */
|
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]);
|
stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
|
||||||
|
.mod((c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_POW: /* A B C R(A):= RK(B) ^ RK(C) */
|
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]);
|
stack[a] = ((b = i>>>23) > 0xff? k[b & 0x0ff]: stack[b])
|
||||||
|
.pow((c = (i>>14) & 0x1ff) > 0xff? k[c & 0x0ff]: stack[c]);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_UNM: /* A B R(A):= -R(B) */
|
case Lua.OP_UNM: /* A B R(A):= -R(B) */
|
||||||
@@ -309,8 +351,7 @@ public class LuaClosure extends LuaFunction {
|
|||||||
|
|
||||||
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
|
case Lua.OP_CONCAT: /* A B C R(A):= R(B).. ... ..R(C) */
|
||||||
b = i>>>23;
|
b = i>>>23;
|
||||||
c = (i>>14)&0x1ff;
|
c = (i>>14) & 0x1ff; {
|
||||||
{
|
|
||||||
if (c > b+1) {
|
if (c > b+1) {
|
||||||
Buffer sb = stack[c].buffer();
|
Buffer sb = stack[c].buffer();
|
||||||
while ( --c >= b )
|
while ( --c >= b )
|
||||||
@@ -334,17 +375,20 @@ public class LuaClosure extends LuaFunction {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_EQ: /* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */
|
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) )
|
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;
|
++pc;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_LT: /* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */
|
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) )
|
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;
|
++pc;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
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) )
|
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;
|
++pc;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -363,21 +407,42 @@ public class LuaClosure extends LuaFunction {
|
|||||||
|
|
||||||
case Lua.OP_CALL: /* A B C R(A), ... ,R(A+C-2):= R(A)(R(A+1), ... ,R(A+B-1)) */
|
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)) {
|
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 (1<<Lua.POS_B) | (0<<Lua.POS_C):
|
||||||
case (2<<Lua.POS_B) | (0<<Lua.POS_C): v=stack[a].invoke(stack[a+1]); top=a+v.narg(); continue;
|
v = stack[a].invoke(NONE);
|
||||||
case (1<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(); continue;
|
top = a+v.narg();
|
||||||
case (2<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1]); continue;
|
continue;
|
||||||
case (3<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2]); continue;
|
case (2<<Lua.POS_B) | (0<<Lua.POS_C):
|
||||||
case (4<<Lua.POS_B) | (1<<Lua.POS_C): stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue;
|
v = stack[a].invoke(stack[a+1]);
|
||||||
case (1<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(); continue;
|
top = a+v.narg();
|
||||||
case (2<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1]); continue;
|
continue;
|
||||||
case (3<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2]); continue;
|
case (1<<Lua.POS_B) | (1<<Lua.POS_C):
|
||||||
case (4<<Lua.POS_B) | (2<<Lua.POS_C): stack[a] = stack[a].call(stack[a+1],stack[a+2],stack[a+3]); continue;
|
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:
|
default:
|
||||||
b = i>>>23;
|
b = i>>>23;
|
||||||
c = (i>>14) & 0x1ff;
|
c = (i>>14) & 0x1ff;
|
||||||
v = stack[a].invoke(b>0?
|
v = stack[a].invoke(b > 0? varargsOf(stack, a+1, b-1): // exact arg count
|
||||||
varargsOf(stack, a+1, b-1): // exact arg count
|
|
||||||
varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
|
varargsOf(stack, a+1, top-v.narg()-(a+1), v)); // from prev top
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
v.copyto(stack, a, c-1);
|
v.copyto(stack, a, c-1);
|
||||||
@@ -391,14 +456,17 @@ public class LuaClosure extends LuaFunction {
|
|||||||
|
|
||||||
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
case Lua.OP_TAILCALL: /* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */
|
||||||
switch (i & Lua.MASK_B) {
|
switch (i & Lua.MASK_B) {
|
||||||
case (1<<Lua.POS_B): return new TailcallVarargs(stack[a], NONE);
|
case (1<<Lua.POS_B):
|
||||||
case (2<<Lua.POS_B): return new TailcallVarargs(stack[a], stack[a+1]);
|
return new TailcallVarargs(stack[a], NONE);
|
||||||
case (3<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2]));
|
case (2<<Lua.POS_B):
|
||||||
case (4<<Lua.POS_B): return new TailcallVarargs(stack[a], varargsOf(stack[a+1],stack[a+2],stack[a+3]));
|
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:
|
default:
|
||||||
b = i>>>23;
|
b = i>>>23;
|
||||||
v = b>0?
|
v = b > 0? varargsOf(stack, a+1, b-1): // exact arg count
|
||||||
varargsOf(stack,a+1,b-1): // exact arg count
|
|
||||||
varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top
|
varargsOf(stack, a+1, top-v.narg()-(a+1), v); // from prev top
|
||||||
return new TailcallVarargs(stack[a], v);
|
return new TailcallVarargs(stack[a], v);
|
||||||
}
|
}
|
||||||
@@ -406,9 +474,12 @@ public class LuaClosure extends LuaFunction {
|
|||||||
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
|
case Lua.OP_RETURN: /* A B return R(A), ... ,R(A+B-2) (see note) */
|
||||||
b = i>>>23;
|
b = i>>>23;
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case 0: return varargsOf(stack, a, top-v.narg()-a, v);
|
case 0:
|
||||||
case 1: return NONE;
|
return varargsOf(stack, a, top-v.narg()-a, v);
|
||||||
case 2: return stack[a];
|
case 1:
|
||||||
|
return NONE;
|
||||||
|
case 2:
|
||||||
|
return stack[a];
|
||||||
default:
|
default:
|
||||||
return varargsOf(stack, a, b-1);
|
return varargsOf(stack, a, b-1);
|
||||||
}
|
}
|
||||||
@@ -528,15 +599,15 @@ public class LuaClosure extends LuaFunction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the error hook if there is one
|
* Run the error hook if there is one
|
||||||
|
*
|
||||||
* @param msg the message to use in error hook processing.
|
* @param msg the message to use in error hook processing.
|
||||||
* */
|
*/
|
||||||
String errorHook(String msg, int level) {
|
String errorHook(String msg, int level) {
|
||||||
if (globals == null ) return msg;
|
if (globals == null)
|
||||||
|
return msg;
|
||||||
final LuaThread r = globals.running;
|
final LuaThread r = globals.running;
|
||||||
if (r.errorfunc == null)
|
if (r.errorfunc == null)
|
||||||
return globals.debuglib != null?
|
return globals.debuglib != null? msg + "\n" + globals.debuglib.traceback(level): msg;
|
||||||
msg + "\n" + globals.debuglib.traceback(level):
|
|
||||||
msg;
|
|
||||||
final LuaValue e = r.errorfunc;
|
final LuaValue e = r.errorfunc;
|
||||||
r.errorfunc = null;
|
r.errorfunc = null;
|
||||||
try {
|
try {
|
||||||
@@ -594,5 +665,4 @@ public class LuaClosure extends LuaFunction {
|
|||||||
return "<" + p.shortsource() + ":" + p.linedefined + ">";
|
return "<" + p.shortsource() + ":" + p.linedefined + ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,18 +26,21 @@ 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.
|
||||||
* <p>
|
* <p>
|
||||||
* These instance are not instantiated directly by clients, but indirectly
|
* These instance are not instantiated directly by clients, but indirectly via
|
||||||
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
* the static functions {@link LuaValue#valueOf(int)} or
|
||||||
* functions. This ensures that values which can be represented as int
|
* {@link LuaValue#valueOf(double)} functions. This ensures that values which
|
||||||
* are wrapped in {@link LuaInteger} instead of {@link LuaDouble}.
|
* can be represented as int are wrapped in {@link LuaInteger} instead of
|
||||||
|
* {@link LuaDouble}.
|
||||||
* <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 #POSINF}, {@link #NEGINF},
|
* However the constants {@link #NAN}, {@link #POSINF}, {@link #NEGINF},
|
||||||
* {@link #JSTR_NAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be useful
|
* {@link #JSTR_NAN}, {@link #JSTR_POSINF}, and {@link #JSTR_NEGINF} may be
|
||||||
* when dealing with Nan or Infinite values.
|
* useful 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
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #ddiv(double, double)}</li>
|
* <li>{@link #ddiv(double, double)}</li>
|
||||||
* <li>{@link #ddiv_d(double, double)}</li>
|
* <li>{@link #ddiv_d(double, double)}</li>
|
||||||
@@ -45,6 +48,7 @@ import org.luaj.vm2.lib.MathLib;
|
|||||||
* <li>{@link #dmod_d(double, double)}</li>
|
* <li>{@link #dmod_d(double, double)}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaNumber
|
* @see LuaNumber
|
||||||
* @see LuaInteger
|
* @see LuaInteger
|
||||||
@@ -94,16 +98,25 @@ public class LuaDouble extends LuaNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte tobyte() { return (byte) (long) v; }
|
public byte tobyte() { return (byte) (long) v; }
|
||||||
|
|
||||||
public char tochar() { return (char) (long) v; }
|
public char tochar() { return (char) (long) v; }
|
||||||
|
|
||||||
public double todouble() { return v; }
|
public double todouble() { return v; }
|
||||||
|
|
||||||
public float tofloat() { return (float) v; }
|
public float tofloat() { return (float) v; }
|
||||||
|
|
||||||
public int toint() { return (int) (long) v; }
|
public int toint() { return (int) (long) v; }
|
||||||
|
|
||||||
public long tolong() { return (long) v; }
|
public long tolong() { return (long) v; }
|
||||||
|
|
||||||
public short toshort() { return (short) (long) v; }
|
public short toshort() { return (short) (long) v; }
|
||||||
|
|
||||||
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 LuaInteger.valueOf((int) (long) v); }
|
||||||
|
|
||||||
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() { return LuaInteger.valueOf((int) (long) v); }
|
||||||
@@ -116,68 +129,102 @@ public class LuaDouble extends LuaNumber {
|
|||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
public LuaValue eq(LuaValue val) { return val.raweq(v)? TRUE: FALSE; }
|
public LuaValue eq(LuaValue val) { return val.raweq(v)? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean eq_b(LuaValue val) { return val.raweq(v); }
|
public boolean eq_b(LuaValue val) { return val.raweq(v); }
|
||||||
|
|
||||||
// equality w/o metatable processing
|
// equality w/o metatable processing
|
||||||
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; }
|
||||||
|
|
||||||
// basic binary arithmetic
|
// basic binary arithmetic
|
||||||
public LuaValue add(LuaValue rhs) { return rhs.add(v); }
|
public LuaValue add(LuaValue rhs) { return rhs.add(v); }
|
||||||
|
|
||||||
public LuaValue add(double lhs) { return LuaDouble.valueOf(lhs+v); }
|
public LuaValue add(double lhs) { return LuaDouble.valueOf(lhs+v); }
|
||||||
|
|
||||||
public LuaValue sub(LuaValue rhs) { return rhs.subFrom(v); }
|
public LuaValue sub(LuaValue rhs) { return rhs.subFrom(v); }
|
||||||
|
|
||||||
public LuaValue sub(double rhs) { return LuaDouble.valueOf(v-rhs); }
|
public LuaValue sub(double rhs) { return LuaDouble.valueOf(v-rhs); }
|
||||||
|
|
||||||
public LuaValue sub(int rhs) { return LuaDouble.valueOf(v-rhs); }
|
public LuaValue sub(int rhs) { return LuaDouble.valueOf(v-rhs); }
|
||||||
|
|
||||||
public LuaValue subFrom(double lhs) { return LuaDouble.valueOf(lhs-v); }
|
public LuaValue subFrom(double lhs) { return LuaDouble.valueOf(lhs-v); }
|
||||||
|
|
||||||
public LuaValue mul(LuaValue rhs) { return rhs.mul(v); }
|
public LuaValue mul(LuaValue rhs) { return rhs.mul(v); }
|
||||||
|
|
||||||
public LuaValue mul(double lhs) { return LuaDouble.valueOf(lhs*v); }
|
public LuaValue mul(double lhs) { return LuaDouble.valueOf(lhs*v); }
|
||||||
|
|
||||||
public LuaValue mul(int lhs) { return LuaDouble.valueOf(lhs*v); }
|
public LuaValue mul(int lhs) { return LuaDouble.valueOf(lhs*v); }
|
||||||
|
|
||||||
public LuaValue pow(LuaValue rhs) { return rhs.powWith(v); }
|
public LuaValue pow(LuaValue rhs) { return rhs.powWith(v); }
|
||||||
|
|
||||||
public LuaValue pow(double rhs) { return MathLib.dpow(v, rhs); }
|
public LuaValue pow(double rhs) { return MathLib.dpow(v, rhs); }
|
||||||
|
|
||||||
public LuaValue pow(int 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(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 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 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); }
|
||||||
|
|
||||||
public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, v); }
|
public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, v); }
|
||||||
|
|
||||||
|
/**
|
||||||
/** Divide two double numbers according to lua math, and return a {@link LuaValue} result.
|
* Divide two double numbers according to lua math, and return a
|
||||||
|
* {@link LuaValue} 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.
|
||||||
* @return {@link LuaValue} for the result of the division,
|
* @return {@link LuaValue} for the result of the division, taking into
|
||||||
* taking into account positive and negiative infinity, and Nan
|
* account positive and negiative infinity, and Nan
|
||||||
* @see #ddiv_d(double, double)
|
* @see #ddiv_d(double, double)
|
||||||
*/
|
*/
|
||||||
public static LuaValue ddiv(double lhs, double rhs) {
|
public static LuaValue ddiv(double lhs, double rhs) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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.
|
||||||
* @return Value of the division, taking into account positive and negative infinity, and Nan
|
* @return Value of the division, taking into account positive and negative
|
||||||
|
* infinity, and Nan
|
||||||
* @see #ddiv(double, double)
|
* @see #ddiv(double, double)
|
||||||
*/
|
*/
|
||||||
public static double ddiv_d(double lhs, double rhs) {
|
public static double ddiv_d(double lhs, double rhs) {
|
||||||
return rhs != 0? lhs/rhs: lhs > 0? Double.POSITIVE_INFINITY: lhs == 0? Double.NaN: Double.NEGATIVE_INFINITY;
|
return rhs != 0? lhs/rhs: lhs > 0? Double.POSITIVE_INFINITY: lhs == 0? Double.NaN: Double.NEGATIVE_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Take modulo double numbers according to lua math, and return a {@link LuaValue} result.
|
/**
|
||||||
|
* Take modulo double numbers according to lua math, and return a
|
||||||
|
* {@link LuaValue} result.
|
||||||
|
*
|
||||||
* @param lhs Left-hand-side of the modulo.
|
* @param lhs Left-hand-side of the modulo.
|
||||||
* @param rhs Right-hand-side of the modulo.
|
* @param rhs Right-hand-side of the modulo.
|
||||||
* @return {@link LuaValue} for the result of the modulo,
|
* @return {@link LuaValue} for the result of the modulo, using lua's rules
|
||||||
* using lua's rules for modulo
|
* for modulo
|
||||||
* @see #dmod_d(double, double)
|
* @see #dmod_d(double, double)
|
||||||
*/
|
*/
|
||||||
public static LuaValue dmod(double lhs, double rhs) {
|
public static LuaValue dmod(double lhs, double rhs) {
|
||||||
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return NAN;
|
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY)
|
||||||
|
return NAN;
|
||||||
if (rhs == Double.POSITIVE_INFINITY) {
|
if (rhs == Double.POSITIVE_INFINITY) {
|
||||||
return lhs < 0? POSINF: valueOf(lhs);
|
return lhs < 0? POSINF: valueOf(lhs);
|
||||||
}
|
}
|
||||||
@@ -187,15 +234,19 @@ public class LuaDouble extends LuaNumber {
|
|||||||
return valueOf(lhs-rhs*Math.floor(lhs/rhs));
|
return valueOf(lhs-rhs*Math.floor(lhs/rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Take modulo for double numbers according to lua math, and return a double result.
|
/**
|
||||||
|
* Take modulo for double numbers according to lua math, and return a double
|
||||||
|
* result.
|
||||||
|
*
|
||||||
* @param lhs Left-hand-side of the modulo.
|
* @param lhs Left-hand-side of the modulo.
|
||||||
* @param rhs Right-hand-side of the modulo.
|
* @param rhs Right-hand-side of the modulo.
|
||||||
* @return double value for the result of the modulo,
|
* @return double value for the result of the modulo, using lua's rules for
|
||||||
* using lua's rules for modulo
|
* modulo
|
||||||
* @see #dmod(double, double)
|
* @see #dmod(double, double)
|
||||||
*/
|
*/
|
||||||
public static double dmod_d(double lhs, double rhs) {
|
public static double dmod_d(double lhs, double rhs) {
|
||||||
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY) return Double.NaN;
|
if (rhs == 0 || lhs == Double.POSITIVE_INFINITY || lhs == Double.NEGATIVE_INFINITY)
|
||||||
|
return Double.NaN;
|
||||||
if (rhs == Double.POSITIVE_INFINITY) {
|
if (rhs == Double.POSITIVE_INFINITY) {
|
||||||
return lhs < 0? Double.POSITIVE_INFINITY: lhs;
|
return lhs < 0? Double.POSITIVE_INFINITY: lhs;
|
||||||
}
|
}
|
||||||
@@ -207,28 +258,55 @@ public class LuaDouble extends LuaNumber {
|
|||||||
|
|
||||||
// relational operators
|
// relational operators
|
||||||
public LuaValue lt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.gt_b(v)? TRUE: FALSE): super.lt(rhs); }
|
public LuaValue lt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.gt_b(v)? TRUE: FALSE): super.lt(rhs); }
|
||||||
|
|
||||||
public LuaValue lt(double rhs) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt(double rhs) { return v < rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue lt(int rhs) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt(int rhs) { return v < rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean lt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v): super.lt_b(rhs); }
|
public boolean lt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v): super.lt_b(rhs); }
|
||||||
|
|
||||||
public boolean lt_b(int rhs) { return v < rhs; }
|
public boolean lt_b(int rhs) { return v < rhs; }
|
||||||
|
|
||||||
public boolean lt_b(double rhs) { return v < rhs; }
|
public boolean lt_b(double rhs) { return v < rhs; }
|
||||||
public LuaValue lteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gteq_b(v)? TRUE: FALSE) : super.lteq(rhs); }
|
|
||||||
|
public LuaValue lteq(LuaValue rhs) {
|
||||||
|
return rhs instanceof LuaNumber? (rhs.gteq_b(v)? TRUE: FALSE): super.lteq(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue lteq(double rhs) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq(double rhs) { return v <= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue lteq(int rhs) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq(int rhs) { return v <= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean lteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gteq_b(v): super.lteq_b(rhs); }
|
public boolean lteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gteq_b(v): super.lteq_b(rhs); }
|
||||||
|
|
||||||
public boolean lteq_b(int rhs) { return v <= rhs; }
|
public boolean lteq_b(int rhs) { return v <= rhs; }
|
||||||
|
|
||||||
public boolean lteq_b(double rhs) { return v <= rhs; }
|
public boolean lteq_b(double rhs) { return v <= rhs; }
|
||||||
|
|
||||||
public LuaValue gt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.lt_b(v)? TRUE: FALSE): super.gt(rhs); }
|
public LuaValue gt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.lt_b(v)? TRUE: FALSE): super.gt(rhs); }
|
||||||
|
|
||||||
public LuaValue gt(double rhs) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt(double rhs) { return v > rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue gt(int rhs) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt(int rhs) { return v > rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean gt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v): super.gt_b(rhs); }
|
public boolean gt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v): super.gt_b(rhs); }
|
||||||
|
|
||||||
public boolean gt_b(int rhs) { return v > rhs; }
|
public boolean gt_b(int rhs) { return v > rhs; }
|
||||||
|
|
||||||
public boolean gt_b(double rhs) { return v > rhs; }
|
public boolean gt_b(double rhs) { return v > rhs; }
|
||||||
public LuaValue gteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lteq_b(v)? TRUE: FALSE) : super.gteq(rhs); }
|
|
||||||
|
public LuaValue gteq(LuaValue rhs) {
|
||||||
|
return rhs instanceof LuaNumber? (rhs.lteq_b(v)? TRUE: FALSE): super.gteq(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue gteq(double rhs) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq(double rhs) { return v >= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue gteq(int rhs) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq(int rhs) { return v >= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean gteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lteq_b(v): super.gteq_b(rhs); }
|
public boolean gteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lteq_b(v): super.gteq_b(rhs); }
|
||||||
|
|
||||||
public boolean gteq_b(int rhs) { return v >= rhs; }
|
public boolean gteq_b(int rhs) { return v >= rhs; }
|
||||||
|
|
||||||
public boolean gteq_b(double rhs) { return v >= rhs; }
|
public boolean gteq_b(double rhs) { return v >= rhs; }
|
||||||
|
|
||||||
// string comparison
|
// string comparison
|
||||||
@@ -282,14 +360,19 @@ public class LuaDouble extends LuaNumber {
|
|||||||
public LuaValue tonumber() {
|
public LuaValue tonumber() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int checkint() { return (int) (long) v; }
|
public int checkint() { return (int) (long) v; }
|
||||||
|
|
||||||
public long checklong() { return (long) v; }
|
public long checklong() { return (long) v; }
|
||||||
|
|
||||||
public LuaNumber checknumber() { return this; }
|
public LuaNumber checknumber() { return this; }
|
||||||
|
|
||||||
public double checkdouble() { return v; }
|
public double checkdouble() { return v; }
|
||||||
|
|
||||||
public String checkjstring() {
|
public String checkjstring() {
|
||||||
return tojstring();
|
return tojstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaString checkstring() {
|
public LuaString checkstring() {
|
||||||
return LuaString.valueOf(tojstring());
|
return LuaString.valueOf(tojstring());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,22 +21,21 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
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()}
|
* {@link LuaError} is used wherever a lua call to {@code error()} would be used
|
||||||
* would be used within a script.
|
* 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
|
* Java method signatures do notdeclare this exception, althoug it can be thrown
|
||||||
* be thrown on almost any luaj Java operation.
|
* on almost any luaj Java operation. This is analagous to the fact that any lua
|
||||||
* This is analagous to the fact that any lua script can throw a lua error at any time.
|
* script can throw a lua error at any time.
|
||||||
* <p>
|
* <p>
|
||||||
* The LuaError may be constructed with a message object, in which case the message
|
* The LuaError may be constructed with a message object, in which case the
|
||||||
* is the string representation of that object. getMessageObject will get the object
|
* message is the string representation of that object. getMessageObject will
|
||||||
* supplied at construct time, or a LuaString containing the message of an object
|
* get the object supplied at construct time, or a LuaString containing the
|
||||||
* was not supplied.
|
* message of an object 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;
|
||||||
@@ -51,8 +50,9 @@ public class LuaError extends RuntimeException {
|
|||||||
|
|
||||||
private LuaValue object;
|
private LuaValue object;
|
||||||
|
|
||||||
/** Get the string message if it was supplied, or a string
|
/**
|
||||||
* representation of the message object if that was supplied.
|
* Get the string message if it was supplied, or a string representation of
|
||||||
|
* the message object if that was supplied.
|
||||||
*/
|
*/
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
if (traceback != null)
|
if (traceback != null)
|
||||||
@@ -65,20 +65,25 @@ public class LuaError extends RuntimeException {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the LuaValue that was provided in the constructor, or
|
/**
|
||||||
* a LuaString containing the message if it was a string error argument.
|
* Get the LuaValue that was provided in the constructor, or a LuaString
|
||||||
|
* 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) return object;
|
if (object != null)
|
||||||
|
return object;
|
||||||
String m = getMessage();
|
String m = getMessage();
|
||||||
return m != null? LuaValue.valueOf(m): null;
|
return m != null? LuaValue.valueOf(m): null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct LuaError when a program exception occurs.
|
/**
|
||||||
|
* 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) {
|
||||||
@@ -98,7 +103,9 @@ public class LuaError extends RuntimeException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a LuaError with a message, and level to draw line number information from.
|
* Construct a LuaError with a message, and level to draw line number
|
||||||
|
* 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
|
||||||
*/
|
*/
|
||||||
@@ -108,8 +115,9 @@ public class LuaError extends RuntimeException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a LuaError with a LuaValue as the message object,
|
* Construct a LuaError with a LuaValue as the message object, and level to
|
||||||
* and level to draw line number information from.
|
* 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) {
|
||||||
@@ -118,13 +126,9 @@ public class LuaError extends RuntimeException {
|
|||||||
this.level = 1;
|
this.level = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the cause, if any.
|
* Get the cause, if any.
|
||||||
*/
|
*/
|
||||||
public Throwable getCause() {
|
public Throwable getCause() { return cause; }
|
||||||
return cause;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,21 +21,19 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
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}
|
* Direct subclass include {@link org.luaj.vm2.lib.LibFunction} which is the
|
||||||
* which is the base class for
|
* base class for all built-in library functions coded in Java, and
|
||||||
* all built-in library functions coded in Java,
|
* {@link LuaClosure}, which represents a lua closure whose bytecode is
|
||||||
* and {@link LuaClosure}, which represents a lua closure
|
* interpreted when the function is invoked.
|
||||||
* 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.lib.LibFunction
|
||||||
*/
|
*/
|
||||||
abstract
|
abstract public class LuaFunction extends LuaValue {
|
||||||
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;
|
||||||
@@ -72,20 +70,29 @@ public class LuaFunction extends LuaValue {
|
|||||||
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 String naming the last part of the class name after the last dot (.) or dollar sign ($).
|
* Return the last part of the class name, to be used as a function name in
|
||||||
* If the first character is '_', it is skipped.
|
* tojstring and elsewhere.
|
||||||
|
*
|
||||||
|
* @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) == '_') offset++;
|
if (s.charAt(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.
|
/**
|
||||||
* Is overridden by LuaClosure to return the source file and line, and by LibFunctions to return the name.
|
* Return a human-readable name for this function. Returns the last part of
|
||||||
* @return common name for this function. */
|
* the class name by default. Is overridden by LuaClosure to return the
|
||||||
|
* 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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import org.luaj.vm2.lib.MathLib;
|
|||||||
/**
|
/**
|
||||||
* Extension of {@link LuaNumber} which can hold a Java int as its value.
|
* Extension of {@link LuaNumber} which can hold a Java int as its value.
|
||||||
* <p>
|
* <p>
|
||||||
* These instance are not instantiated directly by clients, but indirectly
|
* These instance are not instantiated directly by clients, but indirectly via
|
||||||
* via the static functions {@link LuaValue#valueOf(int)} or {@link LuaValue#valueOf(double)}
|
* the static functions {@link LuaValue#valueOf(int)} or
|
||||||
* functions. This ensures that policies regarding pooling of instances are
|
* {@link LuaValue#valueOf(double)} functions. This ensures that policies
|
||||||
* encapsulated.
|
* regarding pooling of instances are encapsulated.
|
||||||
* <p>
|
* <p>
|
||||||
* There are no API's specific to LuaInteger that are useful beyond what is already
|
* There are no API's specific to LuaInteger that are useful beyond what is
|
||||||
* exposed in {@link LuaValue}.
|
* already exposed in {@link LuaValue}.
|
||||||
*
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaNumber
|
* @see LuaNumber
|
||||||
@@ -53,7 +53,9 @@ public class LuaInteger extends LuaNumber {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// TODO consider moving this to LuaValue
|
// TODO consider moving this to LuaValue
|
||||||
/** Return a LuaNumber that represents the value provided
|
/**
|
||||||
|
* Return a LuaNumber that represents the value provided
|
||||||
|
*
|
||||||
* @param l long value to represent.
|
* @param l long value to represent.
|
||||||
* @return LuaNumber that is eithe LuaInteger or LuaDouble representing l
|
* @return LuaNumber that is eithe LuaInteger or LuaDouble representing l
|
||||||
* @see LuaValue#valueOf(int)
|
* @see LuaValue#valueOf(int)
|
||||||
@@ -61,9 +63,8 @@ public class LuaInteger extends LuaNumber {
|
|||||||
*/
|
*/
|
||||||
public static LuaNumber valueOf(long l) {
|
public static LuaNumber valueOf(long l) {
|
||||||
int i = (int) l;
|
int i = (int) l;
|
||||||
return l==i? (i<=255 && i>=-256? intValues[i+256]:
|
return l == i? (i <= 255 && i >= -256? intValues[i+256]: (LuaNumber) new LuaInteger(i))
|
||||||
(LuaNumber) new LuaInteger(i)):
|
: (LuaNumber) LuaDouble.valueOf(l);
|
||||||
(LuaNumber) LuaDouble.valueOf(l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The value being held by this instance. */
|
/** The value being held by this instance. */
|
||||||
@@ -71,6 +72,7 @@ public class LuaInteger extends LuaNumber {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Package protected constructor.
|
* Package protected constructor.
|
||||||
|
*
|
||||||
* @see LuaValue#valueOf(int)
|
* @see LuaValue#valueOf(int)
|
||||||
**/
|
**/
|
||||||
LuaInteger(int i) {
|
LuaInteger(int i) {
|
||||||
@@ -78,20 +80,31 @@ public class LuaInteger extends LuaNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isint() { return true; }
|
public boolean isint() { return true; }
|
||||||
|
|
||||||
public boolean isinttype() { return true; }
|
public boolean isinttype() { return true; }
|
||||||
|
|
||||||
public boolean islong() { return true; }
|
public boolean islong() { return true; }
|
||||||
|
|
||||||
public byte tobyte() { return (byte) v; }
|
public byte tobyte() { return (byte) v; }
|
||||||
|
|
||||||
public char tochar() { return (char) v; }
|
public char tochar() { return (char) v; }
|
||||||
|
|
||||||
public double todouble() { return v; }
|
public double todouble() { return v; }
|
||||||
|
|
||||||
public float tofloat() { return v; }
|
public float tofloat() { return v; }
|
||||||
|
|
||||||
public int toint() { return v; }
|
public int toint() { return v; }
|
||||||
|
|
||||||
public long tolong() { return v; }
|
public long tolong() { return v; }
|
||||||
|
|
||||||
public short toshort() { return (short) v; }
|
public short toshort() { return (short) v; }
|
||||||
|
|
||||||
public double optdouble(double defval) { return v; }
|
public double optdouble(double defval) { return v; }
|
||||||
|
|
||||||
public int optint(int defval) { return v; }
|
public int optint(int defval) { return v; }
|
||||||
|
|
||||||
public LuaInteger optinteger(LuaInteger defval) { return this; }
|
public LuaInteger optinteger(LuaInteger defval) { return this; }
|
||||||
|
|
||||||
public long optlong(long defval) { return v; }
|
public long optlong(long defval) { return v; }
|
||||||
|
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
@@ -138,63 +151,116 @@ public class LuaInteger extends LuaNumber {
|
|||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
public LuaValue eq(LuaValue val) { return val.raweq(v)? TRUE: FALSE; }
|
public LuaValue eq(LuaValue val) { return val.raweq(v)? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean eq_b(LuaValue val) { return val.raweq(v); }
|
public boolean eq_b(LuaValue val) { return val.raweq(v); }
|
||||||
|
|
||||||
// equality w/o metatable processing
|
// equality w/o metatable processing
|
||||||
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; }
|
||||||
|
|
||||||
// arithmetic operators
|
// arithmetic operators
|
||||||
public LuaValue add(LuaValue rhs) { return rhs.add(v); }
|
public LuaValue add(LuaValue rhs) { return rhs.add(v); }
|
||||||
|
|
||||||
public LuaValue add(double lhs) { return LuaDouble.valueOf(lhs+v); }
|
public LuaValue add(double lhs) { return LuaDouble.valueOf(lhs+v); }
|
||||||
|
|
||||||
public LuaValue add(int lhs) { return LuaInteger.valueOf(lhs+(long) v); }
|
public LuaValue add(int lhs) { return LuaInteger.valueOf(lhs+(long) v); }
|
||||||
|
|
||||||
public LuaValue sub(LuaValue rhs) { return rhs.subFrom(v); }
|
public LuaValue sub(LuaValue rhs) { return rhs.subFrom(v); }
|
||||||
|
|
||||||
public LuaValue sub(double rhs) { return LuaDouble.valueOf(v-rhs); }
|
public LuaValue sub(double rhs) { return LuaDouble.valueOf(v-rhs); }
|
||||||
|
|
||||||
public LuaValue sub(int rhs) { return LuaDouble.valueOf(v-rhs); }
|
public LuaValue sub(int rhs) { return LuaDouble.valueOf(v-rhs); }
|
||||||
|
|
||||||
public LuaValue subFrom(double lhs) { return LuaDouble.valueOf(lhs-v); }
|
public LuaValue subFrom(double lhs) { return LuaDouble.valueOf(lhs-v); }
|
||||||
|
|
||||||
public LuaValue subFrom(int lhs) { return LuaInteger.valueOf(lhs-(long) v); }
|
public LuaValue subFrom(int lhs) { return LuaInteger.valueOf(lhs-(long) v); }
|
||||||
|
|
||||||
public LuaValue mul(LuaValue rhs) { return rhs.mul(v); }
|
public LuaValue mul(LuaValue rhs) { return rhs.mul(v); }
|
||||||
|
|
||||||
public LuaValue mul(double lhs) { return LuaDouble.valueOf(lhs*v); }
|
public LuaValue mul(double lhs) { return LuaDouble.valueOf(lhs*v); }
|
||||||
|
|
||||||
public LuaValue mul(int lhs) { return LuaInteger.valueOf(lhs*(long) v); }
|
public LuaValue mul(int lhs) { return LuaInteger.valueOf(lhs*(long) v); }
|
||||||
|
|
||||||
public LuaValue pow(LuaValue rhs) { return rhs.powWith(v); }
|
public LuaValue pow(LuaValue rhs) { return rhs.powWith(v); }
|
||||||
|
|
||||||
public LuaValue pow(double rhs) { return MathLib.dpow(v, rhs); }
|
public LuaValue pow(double rhs) { return MathLib.dpow(v, rhs); }
|
||||||
|
|
||||||
public LuaValue pow(int 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(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 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 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); }
|
||||||
|
|
||||||
public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, v); }
|
public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, v); }
|
||||||
|
|
||||||
// relational operators
|
// relational operators
|
||||||
public LuaValue lt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.gt_b(v)? TRUE: FALSE): super.lt(rhs); }
|
public LuaValue lt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.gt_b(v)? TRUE: FALSE): super.lt(rhs); }
|
||||||
|
|
||||||
public LuaValue lt(double rhs) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt(double rhs) { return v < rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue lt(int rhs) { return v < rhs? TRUE: FALSE; }
|
public LuaValue lt(int rhs) { return v < rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean lt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v): super.lt_b(rhs); }
|
public boolean lt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gt_b(v): super.lt_b(rhs); }
|
||||||
|
|
||||||
public boolean lt_b(int rhs) { return v < rhs; }
|
public boolean lt_b(int rhs) { return v < rhs; }
|
||||||
|
|
||||||
public boolean lt_b(double rhs) { return v < rhs; }
|
public boolean lt_b(double rhs) { return v < rhs; }
|
||||||
public LuaValue lteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.gteq_b(v)? TRUE: FALSE) : super.lteq(rhs); }
|
|
||||||
|
public LuaValue lteq(LuaValue rhs) {
|
||||||
|
return rhs instanceof LuaNumber? (rhs.gteq_b(v)? TRUE: FALSE): super.lteq(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue lteq(double rhs) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq(double rhs) { return v <= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue lteq(int rhs) { return v <= rhs? TRUE: FALSE; }
|
public LuaValue lteq(int rhs) { return v <= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean lteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gteq_b(v): super.lteq_b(rhs); }
|
public boolean lteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.gteq_b(v): super.lteq_b(rhs); }
|
||||||
|
|
||||||
public boolean lteq_b(int rhs) { return v <= rhs; }
|
public boolean lteq_b(int rhs) { return v <= rhs; }
|
||||||
|
|
||||||
public boolean lteq_b(double rhs) { return v <= rhs; }
|
public boolean lteq_b(double rhs) { return v <= rhs; }
|
||||||
|
|
||||||
public LuaValue gt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.lt_b(v)? TRUE: FALSE): super.gt(rhs); }
|
public LuaValue gt(LuaValue rhs) { return rhs instanceof LuaNumber? (rhs.lt_b(v)? TRUE: FALSE): super.gt(rhs); }
|
||||||
|
|
||||||
public LuaValue gt(double rhs) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt(double rhs) { return v > rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue gt(int rhs) { return v > rhs? TRUE: FALSE; }
|
public LuaValue gt(int rhs) { return v > rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean gt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v): super.gt_b(rhs); }
|
public boolean gt_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lt_b(v): super.gt_b(rhs); }
|
||||||
|
|
||||||
public boolean gt_b(int rhs) { return v > rhs; }
|
public boolean gt_b(int rhs) { return v > rhs; }
|
||||||
|
|
||||||
public boolean gt_b(double rhs) { return v > rhs; }
|
public boolean gt_b(double rhs) { return v > rhs; }
|
||||||
public LuaValue gteq( LuaValue rhs ) { return rhs instanceof LuaNumber ? (rhs.lteq_b(v)? TRUE: FALSE) : super.gteq(rhs); }
|
|
||||||
|
public LuaValue gteq(LuaValue rhs) {
|
||||||
|
return rhs instanceof LuaNumber? (rhs.lteq_b(v)? TRUE: FALSE): super.gteq(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue gteq(double rhs) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq(double rhs) { return v >= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public LuaValue gteq(int rhs) { return v >= rhs? TRUE: FALSE; }
|
public LuaValue gteq(int rhs) { return v >= rhs? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean gteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lteq_b(v): super.gteq_b(rhs); }
|
public boolean gteq_b(LuaValue rhs) { return rhs instanceof LuaNumber? rhs.lteq_b(v): super.gteq_b(rhs); }
|
||||||
|
|
||||||
public boolean gteq_b(int rhs) { return v >= rhs; }
|
public boolean gteq_b(int rhs) { return v >= rhs; }
|
||||||
|
|
||||||
public boolean gteq_b(double rhs) { return v >= rhs; }
|
public boolean gteq_b(double rhs) { return v >= rhs; }
|
||||||
|
|
||||||
// string comparison
|
// string comparison
|
||||||
@@ -203,15 +269,19 @@ public class LuaInteger extends LuaNumber {
|
|||||||
public int checkint() {
|
public int checkint() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long checklong() {
|
public long checklong() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double checkdouble() {
|
public double checkdouble() {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String checkjstring() {
|
public String checkjstring() {
|
||||||
return String.valueOf(v);
|
return String.valueOf(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaString checkstring() {
|
public LuaString checkstring() {
|
||||||
return valueOf(String.valueOf(v));
|
return valueOf(String.valueOf(v));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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},
|
* There will be one instance of this class, {@link LuaValue#NIL}, per Java
|
||||||
* per Java virtual machine.
|
* virtual machine. However, the {@link Varargs} instance {@link LuaValue#NONE}
|
||||||
* However, the {@link Varargs} instance {@link LuaValue#NONE}
|
* which is the empty list, is also considered treated as a nil value by
|
||||||
* which is the empty list,
|
* default.
|
||||||
* is also considered treated as a nil value by default.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Although it is possible to test for nil using Java == operator,
|
* Although it is possible to test for nil using Java == operator, the
|
||||||
* the recommended approach is to use the method {@link LuaValue#isnil()}
|
* recommended approach is to use the method {@link LuaValue#isnil()} instead.
|
||||||
* instead. By using that any ambiguities between
|
* By using that any ambiguities between {@link LuaValue#NIL} and
|
||||||
* {@link LuaValue#NIL} and {@link LuaValue#NONE} are avoided.
|
* {@link LuaValue#NONE} are avoided.
|
||||||
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaValue#NIL
|
* @see LuaValue#NIL
|
||||||
*/
|
*/
|
||||||
@@ -91,18 +91,32 @@ public class LuaNil extends LuaValue {
|
|||||||
|
|
||||||
// optional argument conversions - nil alwas falls badk to default value
|
// optional argument conversions - nil alwas falls badk to default value
|
||||||
public boolean optboolean(boolean defval) { return defval; }
|
public boolean optboolean(boolean defval) { return defval; }
|
||||||
|
|
||||||
public LuaClosure optclosure(LuaClosure defval) { return defval; }
|
public LuaClosure optclosure(LuaClosure defval) { return defval; }
|
||||||
|
|
||||||
public double optdouble(double defval) { return defval; }
|
public double optdouble(double defval) { return defval; }
|
||||||
|
|
||||||
public LuaFunction optfunction(LuaFunction defval) { return defval; }
|
public LuaFunction optfunction(LuaFunction defval) { return defval; }
|
||||||
|
|
||||||
public int optint(int defval) { return defval; }
|
public int optint(int defval) { return defval; }
|
||||||
|
|
||||||
public LuaInteger optinteger(LuaInteger defval) { return defval; }
|
public LuaInteger optinteger(LuaInteger defval) { return defval; }
|
||||||
|
|
||||||
public long optlong(long defval) { return defval; }
|
public long optlong(long defval) { return defval; }
|
||||||
|
|
||||||
public LuaNumber optnumber(LuaNumber defval) { return defval; }
|
public LuaNumber optnumber(LuaNumber defval) { return defval; }
|
||||||
|
|
||||||
public LuaTable opttable(LuaTable defval) { return defval; }
|
public LuaTable opttable(LuaTable defval) { return defval; }
|
||||||
|
|
||||||
public LuaThread optthread(LuaThread defval) { return defval; }
|
public LuaThread optthread(LuaThread defval) { return defval; }
|
||||||
|
|
||||||
public String optjstring(String defval) { return defval; }
|
public String optjstring(String defval) { return defval; }
|
||||||
|
|
||||||
public LuaString optstring(LuaString defval) { return defval; }
|
public LuaString optstring(LuaString defval) { return defval; }
|
||||||
|
|
||||||
public Object optuserdata(Object defval) { return defval; }
|
public Object optuserdata(Object defval) { return defval; }
|
||||||
|
|
||||||
public Object optuserdata(Class c, Object defval) { return defval; }
|
public Object optuserdata(Class c, Object defval) { return defval; }
|
||||||
|
|
||||||
public LuaValue optvalue(LuaValue defval) { return defval; }
|
public LuaValue optvalue(LuaValue defval) { return defval; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,15 +24,15 @@ 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 java int,
|
* The main subclasses are {@link LuaInteger} which holds values that fit in a
|
||||||
* and {@link LuaDouble} which holds all other number values.
|
* java int, and {@link LuaDouble} which holds all other number values.
|
||||||
|
*
|
||||||
* @see LuaInteger
|
* @see LuaInteger
|
||||||
* @see LuaDouble
|
* @see LuaDouble
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
abstract
|
abstract public class LuaNumber extends LuaValue {
|
||||||
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;
|
||||||
@@ -74,8 +74,11 @@ public class LuaNumber extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
||||||
|
|
||||||
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
|
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
|
||||||
|
|
||||||
public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); }
|
public LuaValue concatTo(LuaNumber lhs) { return strvalue().concatTo(lhs.strvalue()); }
|
||||||
|
|
||||||
public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); }
|
public LuaValue concatTo(LuaString lhs) { return strvalue().concatTo(lhs); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -33,27 +32,27 @@ import org.luaj.vm2.lib.MathLib;
|
|||||||
/**
|
/**
|
||||||
* Subclass of {@link LuaValue} for representing lua strings.
|
* Subclass of {@link LuaValue} for representing lua strings.
|
||||||
* <p>
|
* <p>
|
||||||
* Because lua string values are more nearly sequences of bytes than
|
* Because lua string values are more nearly sequences of bytes than sequences
|
||||||
* sequences of characters or unicode code points, the {@link LuaString}
|
* of characters or unicode code points, the {@link LuaString} implementation
|
||||||
* implementation holds the string value in an internal byte array.
|
* holds the string value in an internal byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* {@link LuaString} values are not considered mutable once constructed,
|
* {@link LuaString} values are not considered mutable once constructed, so
|
||||||
* so multiple {@link LuaString} values can chare a single byte array.
|
* multiple {@link LuaString} values can chare a single byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* Currently {@link LuaString}s are pooled via a centrally managed weak table.
|
* Currently {@link LuaString}s are pooled via a centrally managed weak table.
|
||||||
* To ensure that as many string values as possible take advantage of this,
|
* To ensure that as many string values as possible take advantage of this,
|
||||||
* Constructors are not exposed directly. As with number, booleans, and nil,
|
* Constructors are not exposed directly. As with number, booleans, and nil,
|
||||||
* instance construction should be via {@link LuaValue#valueOf(byte[])} or similar API.
|
* instance construction should be via {@link LuaValue#valueOf(byte[])} or
|
||||||
|
* similar API.
|
||||||
* <p>
|
* <p>
|
||||||
* Because of this pooling, users of LuaString <em>must not directly alter the
|
* Because of this pooling, users of LuaString <em>must not directly alter the
|
||||||
* bytes in a LuaString</em>, or undefined behavior will result.
|
* bytes in a LuaString</em>, or undefined behavior will result.
|
||||||
* <p>
|
* <p>
|
||||||
* When Java Strings are used to initialize {@link LuaString} data, the UTF8 encoding is assumed.
|
* When Java Strings are used to initialize {@link LuaString} data, the UTF8
|
||||||
* The functions
|
* encoding is assumed. The functions {@link #lengthAsUtf8(char[])},
|
||||||
* {@link #lengthAsUtf8(char[])},
|
|
||||||
* {@link #encodeToUtf8(char[], int, byte[], int)}, and
|
* {@link #encodeToUtf8(char[], int, byte[], int)}, and
|
||||||
* {@link #decodeAsUtf8(byte[], int, int)}
|
* {@link #decodeAsUtf8(byte[], int, int)} are used to convert back and forth
|
||||||
* are used to convert back and forth between UTF8 byte arrays and character arrays.
|
* between UTF8 byte arrays and character arrays.
|
||||||
*
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
* @see LuaValue#valueOf(String)
|
* @see LuaValue#valueOf(String)
|
||||||
@@ -61,18 +60,22 @@ import org.luaj.vm2.lib.MathLib;
|
|||||||
*/
|
*/
|
||||||
public class LuaString extends LuaValue {
|
public class LuaString extends LuaValue {
|
||||||
|
|
||||||
/** The singleton instance for string metatables that forwards to the string functions.
|
/**
|
||||||
* Typically, this is set to the string metatable as a side effect of loading the string
|
* The singleton instance for string metatables that forwards to the string
|
||||||
* library, and is read-write to provide flexible behavior by default. When used in a
|
* functions. Typically, this is set to the string metatable as a side
|
||||||
* server environment where there may be roge scripts, this should be replaced with a
|
* effect of loading the string library, and is read-write to provide
|
||||||
* read-only table since it is shared across all lua code in this Java VM.
|
* flexible behavior by default. When used in a server environment where
|
||||||
|
* there may be roge scripts, this should be replaced with a read-only table
|
||||||
|
* since it is shared across all lua code in this Java VM.
|
||||||
*/
|
*/
|
||||||
public static LuaValue s_metatable;
|
public static LuaValue s_metatable;
|
||||||
|
|
||||||
/** The bytes for the string. These <em><b>must not be mutated directly</b></em> because
|
/**
|
||||||
* the backing may be shared by multiple LuaStrings, and the hash code is
|
* The bytes for the string. These <em><b>must not be mutated
|
||||||
* computed only at construction time.
|
* directly</b></em> because the backing may be shared by multiple
|
||||||
* It is exposed only for performance and legacy reasons. */
|
* LuaStrings, and the hash code is computed only at construction time. It
|
||||||
|
* is exposed only for performance and legacy reasons.
|
||||||
|
*/
|
||||||
public final byte[] m_bytes;
|
public final byte[] m_bytes;
|
||||||
|
|
||||||
/** The offset into the byte array, 0 means start at the first byte */
|
/** The offset into the byte array, 0 means start at the first byte */
|
||||||
@@ -84,31 +87,39 @@ public class LuaString extends LuaValue {
|
|||||||
/** The hashcode for this string. Computed at construct time. */
|
/** The hashcode for this string. Computed at construct time. */
|
||||||
private final int m_hashcode;
|
private final int m_hashcode;
|
||||||
|
|
||||||
/** Size of cache of recent short strings. This is the maximum number of LuaStrings that
|
/**
|
||||||
* will be retained in the cache of recent short strings. Exposed to package for testing. */
|
* Size of cache of recent short strings. This is the maximum number of
|
||||||
|
* LuaStrings that will be retained in the cache of recent short strings.
|
||||||
|
* Exposed to package for testing.
|
||||||
|
*/
|
||||||
static final int RECENT_STRINGS_CACHE_SIZE = 128;
|
static final int RECENT_STRINGS_CACHE_SIZE = 128;
|
||||||
|
|
||||||
/** Maximum length of a string to be considered for recent short strings caching.
|
/**
|
||||||
* This effectively limits the total memory that can be spent on the recent strings cache,
|
* Maximum length of a string to be considered for recent short strings
|
||||||
* because no LuaString whose backing exceeds this length will be put into the cache.
|
* caching. This effectively limits the total memory that can be spent on
|
||||||
* Exposed to package for testing. */
|
* the recent strings cache, because no LuaString whose backing exceeds this
|
||||||
|
* length will be put into the cache. Exposed to package for testing.
|
||||||
|
*/
|
||||||
static final int RECENT_STRINGS_MAX_LENGTH = 32;
|
static final int RECENT_STRINGS_MAX_LENGTH = 32;
|
||||||
|
|
||||||
/** Simple cache of recently created strings that are short.
|
/**
|
||||||
* This is simply a list of strings, indexed by their hash codes modulo the cache size
|
* Simple cache of recently created strings that are short. This is simply a
|
||||||
* that have been recently constructed. If a string is being constructed frequently
|
* list of strings, indexed by their hash codes modulo the cache size that
|
||||||
* from different contexts, it will generally show up as a cache hit and resolve
|
* have been recently constructed. If a string is being constructed
|
||||||
* to the same value. */
|
* frequently from different contexts, it will generally show up as a cache
|
||||||
|
* hit and resolve to the same value.
|
||||||
|
*/
|
||||||
private static final class RecentShortStrings {
|
private static final class RecentShortStrings {
|
||||||
private static final LuaString recent_short_strings[] =
|
private static final LuaString recent_short_strings[] = new LuaString[RECENT_STRINGS_CACHE_SIZE];
|
||||||
new LuaString[RECENT_STRINGS_CACHE_SIZE];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a {@link LuaString} instance whose bytes match
|
* Get a {@link LuaString} instance whose bytes match the supplied Java
|
||||||
* the supplied Java String using the UTF8 encoding.
|
* String using the UTF8 encoding.
|
||||||
|
*
|
||||||
* @param string Java String containing characters to encode as UTF8
|
* @param string Java String containing characters to encode as UTF8
|
||||||
* @return {@link LuaString} with UTF8 bytes corresponding to the supplied String
|
* @return {@link LuaString} with UTF8 bytes corresponding to the supplied
|
||||||
|
* String
|
||||||
*/
|
*/
|
||||||
public static LuaString valueOf(String string) {
|
public static LuaString valueOf(String string) {
|
||||||
char[] c = string.toCharArray();
|
char[] c = string.toCharArray();
|
||||||
@@ -117,13 +128,16 @@ public class LuaString extends LuaValue {
|
|||||||
return valueUsing(b, 0, b.length);
|
return valueUsing(b, 0, b.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a {@link LuaString} for a portion of a byte array.
|
/**
|
||||||
|
* Construct a {@link LuaString} for a portion of a byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* The array is first be used as the backing for this object, so clients must not change contents.
|
* The array is first be used as the backing for this object, so clients
|
||||||
* If the supplied value for 'len' is more than half the length of the container, the
|
* must not change contents. If the supplied value for 'len' is more than
|
||||||
* supplied byte array will be used as the backing, otherwise the bytes will be copied to a
|
* half the length of the container, the supplied byte array will be used as
|
||||||
* new byte array, and cache lookup may be performed.
|
* the backing, otherwise the bytes will be copied to a new byte array, and
|
||||||
|
* cache lookup may be performed.
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @param bytes byte buffer
|
* @param bytes byte buffer
|
||||||
* @param off offset into the byte buffer
|
* @param off offset into the byte buffer
|
||||||
* @param len length of the byte buffer
|
* @param len length of the byte buffer
|
||||||
@@ -135,7 +149,8 @@ public class LuaString extends LuaValue {
|
|||||||
final int hash = hashCode(bytes, off, len);
|
final int hash = hashCode(bytes, off, len);
|
||||||
final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE-1);
|
final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE-1);
|
||||||
final LuaString t = RecentShortStrings.recent_short_strings[bucket];
|
final LuaString t = RecentShortStrings.recent_short_strings[bucket];
|
||||||
if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) return t;
|
if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len))
|
||||||
|
return t;
|
||||||
final LuaString s = valueFromCopy(bytes, off, len);
|
final LuaString s = valueFromCopy(bytes, off, len);
|
||||||
RecentShortStrings.recent_short_strings[bucket] = s;
|
RecentShortStrings.recent_short_strings[bucket] = s;
|
||||||
return s;
|
return s;
|
||||||
@@ -148,15 +163,18 @@ public class LuaString extends LuaValue {
|
|||||||
return new LuaString(copy, 0, len);
|
return new LuaString(copy, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a {@link LuaString} around, possibly using the the supplied
|
/**
|
||||||
|
* Construct a {@link LuaString} around, possibly using the the supplied
|
||||||
* byte array as the backing store.
|
* byte array as the backing store.
|
||||||
* <p>
|
* <p>
|
||||||
* The caller must ensure that the array is not mutated after the call.
|
* The caller must ensure that the array is not mutated after the call.
|
||||||
* However, if the string is short enough the short-string cache is checked
|
* However, if the string is short enough the short-string cache is checked
|
||||||
* for a match which may be used instead of the supplied byte array.
|
* for a match which may be used instead of the supplied byte array.
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @param bytes byte buffer
|
* @param bytes byte buffer
|
||||||
* @return {@link LuaString} wrapping the byte buffer, or an equivalent string.
|
* @return {@link LuaString} wrapping the byte buffer, or an equivalent
|
||||||
|
* string.
|
||||||
*/
|
*/
|
||||||
static public LuaString valueUsing(byte[] bytes, int off, int len) {
|
static public LuaString valueUsing(byte[] bytes, int off, int len) {
|
||||||
if (bytes.length > RECENT_STRINGS_MAX_LENGTH)
|
if (bytes.length > RECENT_STRINGS_MAX_LENGTH)
|
||||||
@@ -164,30 +182,43 @@ public class LuaString extends LuaValue {
|
|||||||
final int hash = hashCode(bytes, off, len);
|
final int hash = hashCode(bytes, off, len);
|
||||||
final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE-1);
|
final int bucket = hash & (RECENT_STRINGS_CACHE_SIZE-1);
|
||||||
final LuaString t = RecentShortStrings.recent_short_strings[bucket];
|
final LuaString t = RecentShortStrings.recent_short_strings[bucket];
|
||||||
if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len)) return t;
|
if (t != null && t.m_hashcode == hash && t.byteseq(bytes, off, len))
|
||||||
|
return t;
|
||||||
final LuaString s = new LuaString(bytes, off, len);
|
final LuaString s = new LuaString(bytes, off, len);
|
||||||
RecentShortStrings.recent_short_strings[bucket] = s;
|
RecentShortStrings.recent_short_strings[bucket] = s;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
/**
|
||||||
|
* Construct a {@link LuaString} using the supplied characters as byte
|
||||||
|
* values.
|
||||||
* <p>
|
* <p>
|
||||||
* Only the low-order 8-bits of each character are used, the remainder is ignored.
|
* Only the low-order 8-bits of each character are used, the remainder is
|
||||||
|
* ignored.
|
||||||
* <p>
|
* <p>
|
||||||
* This is most useful for constructing byte sequences that do not conform to UTF8.
|
* This is most useful for constructing byte sequences that do not conform
|
||||||
* @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array.
|
* to UTF8.
|
||||||
|
*
|
||||||
|
* @param bytes array of char, whose values are truncated at 8-bits each and
|
||||||
|
* put into a byte array.
|
||||||
* @return {@link LuaString} wrapping a copy of the byte buffer
|
* @return {@link LuaString} wrapping a copy of the byte buffer
|
||||||
*/
|
*/
|
||||||
public static LuaString valueOf(char[] bytes) {
|
public static LuaString valueOf(char[] bytes) {
|
||||||
return valueOf(bytes, 0, bytes.length);
|
return valueOf(bytes, 0, bytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a {@link LuaString} using the supplied characters as byte values.
|
/**
|
||||||
|
* Construct a {@link LuaString} using the supplied characters as byte
|
||||||
|
* values.
|
||||||
* <p>
|
* <p>
|
||||||
* Only the low-order 8-bits of each character are used, the remainder is ignored.
|
* Only the low-order 8-bits of each character are used, the remainder is
|
||||||
|
* ignored.
|
||||||
* <p>
|
* <p>
|
||||||
* This is most useful for constructing byte sequences that do not conform to UTF8.
|
* This is most useful for constructing byte sequences that do not conform
|
||||||
* @param bytes array of char, whose values are truncated at 8-bits each and put into a byte array.
|
* to UTF8.
|
||||||
|
*
|
||||||
|
* @param bytes array of char, whose values are truncated at 8-bits each and
|
||||||
|
* put into a byte array.
|
||||||
* @return {@link LuaString} wrapping a copy of the byte buffer
|
* @return {@link LuaString} wrapping a copy of the byte buffer
|
||||||
*/
|
*/
|
||||||
public static LuaString valueOf(char[] bytes, int off, int len) {
|
public static LuaString valueOf(char[] bytes, int off, int len) {
|
||||||
@@ -197,11 +228,14 @@ public class LuaString extends LuaValue {
|
|||||||
return valueUsing(b, 0, len);
|
return valueUsing(b, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a {@link LuaString} for all the bytes in a byte array.
|
/**
|
||||||
|
* Construct a {@link LuaString} for all the bytes in a byte array.
|
||||||
* <p>
|
* <p>
|
||||||
* The LuaString returned will either be a new LuaString containing a copy
|
* The LuaString returned will either be a new LuaString containing a copy
|
||||||
* of the bytes array, or be an existing LuaString used already having the same value.
|
* of the bytes array, or be an existing LuaString used already having the
|
||||||
|
* same value.
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @param bytes byte buffer
|
* @param bytes byte buffer
|
||||||
* @return {@link LuaString} wrapping the byte buffer
|
* @return {@link LuaString} wrapping the byte buffer
|
||||||
*/
|
*/
|
||||||
@@ -209,14 +243,16 @@ public class LuaString extends LuaValue {
|
|||||||
return valueOf(bytes, 0, bytes.length);
|
return valueOf(bytes, 0, bytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a {@link LuaString} for all the bytes in a byte array, possibly using
|
/**
|
||||||
* the supplied array as the backing store.
|
* Construct a {@link LuaString} for all the bytes in a byte array, possibly
|
||||||
|
* using the supplied array as the backing store.
|
||||||
* <p>
|
* <p>
|
||||||
* The LuaString returned will either be a new LuaString containing the byte array,
|
* The LuaString returned will either be a new LuaString containing the byte
|
||||||
* or be an existing LuaString used already having the same value.
|
* array, or be an existing LuaString used already having the same value.
|
||||||
* <p>
|
* <p>
|
||||||
* The caller must not mutate the contents of the byte array after this call, as
|
* The caller must not mutate the contents of the byte array after this
|
||||||
* it may be used elsewhere due to recent short string caching.
|
* call, as it may be used elsewhere due to recent short string caching.
|
||||||
|
*
|
||||||
* @param bytes byte buffer
|
* @param bytes byte buffer
|
||||||
* @return {@link LuaString} wrapping the byte buffer
|
* @return {@link LuaString} wrapping the byte buffer
|
||||||
*/
|
*/
|
||||||
@@ -224,10 +260,14 @@ public class LuaString extends LuaValue {
|
|||||||
return valueUsing(bytes, 0, bytes.length);
|
return valueUsing(bytes, 0, bytes.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a {@link LuaString} around a byte array without copying the contents.
|
/**
|
||||||
|
* Construct a {@link LuaString} around a byte array without copying the
|
||||||
|
* contents.
|
||||||
* <p>
|
* <p>
|
||||||
* The array is used directly after this is called, so clients must not change contents.
|
* The array is used directly after this is called, so clients must not
|
||||||
|
* change contents.
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @param bytes byte buffer
|
* @param bytes byte buffer
|
||||||
* @param offset offset into the byte buffer
|
* @param offset offset into the byte buffer
|
||||||
* @param length length of the byte buffer
|
* @param length length of the byte buffer
|
||||||
@@ -264,52 +304,118 @@ public class LuaString extends LuaValue {
|
|||||||
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); }
|
||||||
|
|
||||||
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue add(double rhs) { return valueOf(checkarith()+rhs); }
|
public LuaValue add(double rhs) { return valueOf(checkarith()+rhs); }
|
||||||
|
|
||||||
public LuaValue add(int rhs) { return valueOf(checkarith()+rhs); }
|
public LuaValue add(int rhs) { return valueOf(checkarith()+rhs); }
|
||||||
public LuaValue sub( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(SUB,rhs): rhs.subFrom(d); }
|
|
||||||
|
public LuaValue sub(LuaValue rhs) {
|
||||||
|
double d = scannumber();
|
||||||
|
return Double.isNaN(d)? arithmt(SUB, rhs): rhs.subFrom(d);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue sub(double rhs) { return valueOf(checkarith()-rhs); }
|
public LuaValue sub(double rhs) { return valueOf(checkarith()-rhs); }
|
||||||
|
|
||||||
public LuaValue sub(int rhs) { return valueOf(checkarith()-rhs); }
|
public LuaValue sub(int rhs) { return valueOf(checkarith()-rhs); }
|
||||||
|
|
||||||
public LuaValue subFrom(double lhs) { return valueOf(lhs-checkarith()); }
|
public LuaValue subFrom(double lhs) { return valueOf(lhs-checkarith()); }
|
||||||
public LuaValue mul( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(MUL,rhs): rhs.mul(d); }
|
|
||||||
|
public LuaValue mul(LuaValue rhs) {
|
||||||
|
double d = scannumber();
|
||||||
|
return Double.isNaN(d)? arithmt(MUL, rhs): rhs.mul(d);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue mul(double rhs) { return valueOf(checkarith()*rhs); }
|
public LuaValue mul(double rhs) { return valueOf(checkarith()*rhs); }
|
||||||
|
|
||||||
public LuaValue mul(int rhs) { return valueOf(checkarith()*rhs); }
|
public LuaValue mul(int rhs) { return valueOf(checkarith()*rhs); }
|
||||||
public LuaValue pow( LuaValue rhs ) { double d = scannumber(); return Double.isNaN(d)? arithmt(POW,rhs): rhs.powWith(d); }
|
|
||||||
|
public LuaValue pow(LuaValue rhs) {
|
||||||
|
double d = scannumber();
|
||||||
|
return Double.isNaN(d)? arithmt(POW, rhs): rhs.powWith(d);
|
||||||
|
}
|
||||||
|
|
||||||
public LuaValue pow(double rhs) { return MathLib.dpow(checkarith(), rhs); }
|
public LuaValue pow(double rhs) { return MathLib.dpow(checkarith(), rhs); }
|
||||||
|
|
||||||
public LuaValue pow(int rhs) { return MathLib.dpow(checkarith(), rhs); }
|
public LuaValue pow(int rhs) { return MathLib.dpow(checkarith(), rhs); }
|
||||||
|
|
||||||
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 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 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); }
|
||||||
|
|
||||||
public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, checkarith()); }
|
public LuaValue modFrom(double lhs) { return LuaDouble.dmod(lhs, checkarith()); }
|
||||||
|
|
||||||
// relational operators, these only work with other strings
|
// relational operators, these only work with other strings
|
||||||
public LuaValue lt( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)>0? LuaValue.TRUE: FALSE) : super.lt(rhs); }
|
public LuaValue lt(LuaValue rhs) {
|
||||||
|
return rhs.isstring()? (rhs.strcmp(this) > 0? LuaValue.TRUE: FALSE): super.lt(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean lt_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) > 0: super.lt_b(rhs); }
|
public boolean lt_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) > 0: super.lt_b(rhs); }
|
||||||
|
|
||||||
public boolean lt_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean lt_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
|
|
||||||
public boolean lt_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean lt_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
public LuaValue lteq( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)>=0? LuaValue.TRUE: FALSE) : super.lteq(rhs); }
|
|
||||||
|
public LuaValue lteq(LuaValue rhs) {
|
||||||
|
return rhs.isstring()? (rhs.strcmp(this) >= 0? LuaValue.TRUE: FALSE): super.lteq(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean lteq_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) >= 0: super.lteq_b(rhs); }
|
public boolean lteq_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) >= 0: super.lteq_b(rhs); }
|
||||||
|
|
||||||
public boolean lteq_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean lteq_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
|
|
||||||
public boolean lteq_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean lteq_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
public LuaValue gt( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)<0? LuaValue.TRUE: FALSE) : super.gt(rhs); }
|
|
||||||
|
public LuaValue gt(LuaValue rhs) {
|
||||||
|
return rhs.isstring()? (rhs.strcmp(this) < 0? LuaValue.TRUE: FALSE): super.gt(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean gt_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) < 0: super.gt_b(rhs); }
|
public boolean gt_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) < 0: super.gt_b(rhs); }
|
||||||
|
|
||||||
public boolean gt_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean gt_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
|
|
||||||
public boolean gt_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean gt_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
public LuaValue gteq( LuaValue rhs ) { return rhs.isstring() ? (rhs.strcmp(this)<=0? LuaValue.TRUE: FALSE) : super.gteq(rhs); }
|
|
||||||
|
public LuaValue gteq(LuaValue rhs) {
|
||||||
|
return rhs.isstring()? (rhs.strcmp(this) <= 0? LuaValue.TRUE: FALSE): super.gteq(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean gteq_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) <= 0: super.gteq_b(rhs); }
|
public boolean gteq_b(LuaValue rhs) { return rhs.isstring()? rhs.strcmp(this) <= 0: super.gteq_b(rhs); }
|
||||||
|
|
||||||
public boolean gteq_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean gteq_b(int rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
|
|
||||||
public boolean gteq_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
public boolean gteq_b(double rhs) { typerror("attempt to compare string with number"); return false; }
|
||||||
|
|
||||||
// concatenation
|
// concatenation
|
||||||
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
public LuaValue concat(LuaValue rhs) { return rhs.concatTo(this); }
|
||||||
|
|
||||||
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
|
public Buffer concat(Buffer rhs) { return rhs.concatTo(this); }
|
||||||
|
|
||||||
public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); }
|
public LuaValue concatTo(LuaNumber lhs) { return concatTo(lhs.strvalue()); }
|
||||||
|
|
||||||
public LuaValue concatTo(LuaString lhs) {
|
public LuaValue concatTo(LuaString lhs) {
|
||||||
byte[] b = new byte[lhs.m_length+this.m_length];
|
byte[] b = new byte[lhs.m_length+this.m_length];
|
||||||
System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length);
|
System.arraycopy(lhs.m_bytes, lhs.m_offset, b, 0, lhs.m_length);
|
||||||
@@ -319,6 +425,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
// string comparison
|
// string comparison
|
||||||
public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); }
|
public int strcmp(LuaValue lhs) { return -lhs.strcmp(this); }
|
||||||
|
|
||||||
public int strcmp(LuaString rhs) {
|
public int strcmp(LuaString rhs) {
|
||||||
for (int i = 0, j = 0; i < m_length && j < rhs.m_length; ++i, ++j) {
|
for (int i = 0, j = 0; i < m_length && j < rhs.m_length; ++i, ++j) {
|
||||||
if (m_bytes[m_offset+i] != rhs.m_bytes[rhs.m_offset+j]) {
|
if (m_bytes[m_offset+i] != rhs.m_bytes[rhs.m_offset+j]) {
|
||||||
@@ -339,21 +446,26 @@ public class LuaString extends LuaValue {
|
|||||||
public int checkint() {
|
public int checkint() {
|
||||||
return (int) (long) checkdouble();
|
return (int) (long) checkdouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaInteger checkinteger() {
|
public LuaInteger checkinteger() {
|
||||||
return valueOf(checkint());
|
return valueOf(checkint());
|
||||||
}
|
}
|
||||||
|
|
||||||
public long checklong() {
|
public long checklong() {
|
||||||
return (long) checkdouble();
|
return (long) checkdouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double checkdouble() {
|
public double checkdouble() {
|
||||||
double d = scannumber();
|
double d = scannumber();
|
||||||
if (Double.isNaN(d))
|
if (Double.isNaN(d))
|
||||||
argerror("number");
|
argerror("number");
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaNumber checknumber() {
|
public LuaNumber checknumber() {
|
||||||
return valueOf(checkdouble());
|
return valueOf(checkdouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaNumber checknumber(String msg) {
|
public LuaNumber checknumber(String msg) {
|
||||||
double d = scannumber();
|
double d = scannumber();
|
||||||
if (Double.isNaN(d))
|
if (Double.isNaN(d))
|
||||||
@@ -383,11 +495,17 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte tobyte() { return (byte) toint(); }
|
public byte tobyte() { return (byte) toint(); }
|
||||||
|
|
||||||
public char tochar() { return (char) toint(); }
|
public char tochar() { return (char) toint(); }
|
||||||
|
|
||||||
public double todouble() { double d = scannumber(); return Double.isNaN(d)? 0: d; }
|
public double todouble() { double d = scannumber(); return Double.isNaN(d)? 0: d; }
|
||||||
|
|
||||||
public float tofloat() { return (float) todouble(); }
|
public float tofloat() { return (float) todouble(); }
|
||||||
|
|
||||||
public int toint() { return (int) tolong(); }
|
public int toint() { return (int) tolong(); }
|
||||||
|
|
||||||
public long tolong() { return (long) todouble(); }
|
public long tolong() { return (long) todouble(); }
|
||||||
|
|
||||||
public short toshort() { return (short) toint(); }
|
public short toshort() { return (short) toint(); }
|
||||||
|
|
||||||
public double optdouble(double defval) {
|
public double optdouble(double defval) {
|
||||||
@@ -426,29 +544,35 @@ public class LuaString extends LuaValue {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Take a substring using Java zero-based indexes for begin and end or range.
|
/**
|
||||||
|
* Take a substring using Java zero-based indexes for begin and end or
|
||||||
|
* range.
|
||||||
|
*
|
||||||
* @param beginIndex The zero-based index of the first character to include.
|
* @param beginIndex The zero-based index of the first character to include.
|
||||||
* @param endIndex The zero-based index of position after the last character.
|
* @param endIndex The zero-based index of position after the last
|
||||||
|
* character.
|
||||||
* @return LuaString which is a substring whose first character is at offset
|
* @return LuaString which is a substring whose first character is at offset
|
||||||
* beginIndex and extending for (endIndex - beginIndex ) characters.
|
* beginIndex and extending for (endIndex - beginIndex ) characters.
|
||||||
*/
|
*/
|
||||||
public LuaString substring(int beginIndex, int endIndex) {
|
public LuaString substring(int beginIndex, int endIndex) {
|
||||||
final int off = m_offset+beginIndex;
|
final int off = m_offset+beginIndex;
|
||||||
final int len = endIndex-beginIndex;
|
final int len = endIndex-beginIndex;
|
||||||
return len >= m_length / 2?
|
return len >= m_length/2? valueUsing(m_bytes, off, len): valueOf(m_bytes, off, len);
|
||||||
valueUsing(m_bytes, off, len):
|
|
||||||
valueOf(m_bytes, off, len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return m_hashcode;
|
return m_hashcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compute the hash code of a sequence of bytes within a byte array using
|
/**
|
||||||
* lua's rules for string hashes. For long strings, not all bytes are hashed.
|
* Compute the hash code of a sequence of bytes within a byte array using
|
||||||
|
* lua's rules for string hashes. For long strings, not all bytes are
|
||||||
|
* hashed.
|
||||||
|
*
|
||||||
* @param bytes byte array containing the bytes.
|
* @param bytes byte array containing the bytes.
|
||||||
* @param offset offset into the hash for the first byte.
|
* @param offset offset into the hash for the first byte.
|
||||||
* @param length number of bytes starting with offset that are part of the string.
|
* @param length number of bytes starting with offset that are part of the
|
||||||
|
* string.
|
||||||
* @return hash for the string defined by bytes, offset, and length.
|
* @return hash for the string defined by bytes, offset, and length.
|
||||||
*/
|
*/
|
||||||
public static int hashCode(byte[] bytes, int offset, int length) {
|
public static int hashCode(byte[] bytes, int offset, int length) {
|
||||||
@@ -469,6 +593,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
public LuaValue eq(LuaValue val) { return val.raweq(this)? TRUE: FALSE; }
|
public LuaValue eq(LuaValue val) { return val.raweq(this)? TRUE: FALSE; }
|
||||||
|
|
||||||
public boolean eq_b(LuaValue val) { return val.raweq(this); }
|
public boolean eq_b(LuaValue val) { return val.raweq(this); }
|
||||||
|
|
||||||
// equality w/o metatable processing
|
// equality w/o metatable processing
|
||||||
@@ -495,7 +620,10 @@ public class LuaString extends LuaValue {
|
|||||||
return equals(a.m_bytes, a.m_offset+i, b.m_bytes, b.m_offset+j, n);
|
return equals(a.m_bytes, a.m_offset+i, b.m_bytes, b.m_offset+j, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return true if the bytes in the supplied range match this LuaStrings bytes. */
|
/**
|
||||||
|
* Return true if the bytes in the supplied range match this LuaStrings
|
||||||
|
* bytes.
|
||||||
|
*/
|
||||||
private boolean byteseq(byte[] bytes, int off, int len) {
|
private boolean byteseq(byte[] bytes, int off, int len) {
|
||||||
return (m_length == len && equals(m_bytes, m_offset, bytes, off, len));
|
return (m_length == len && equals(m_bytes, m_offset, bytes, off, len));
|
||||||
}
|
}
|
||||||
@@ -543,9 +671,11 @@ public class LuaString extends LuaValue {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert value to an input stream.
|
/**
|
||||||
|
* Convert value to an input stream.
|
||||||
*
|
*
|
||||||
* @return {@link InputStream} whose data matches the bytes in this {@link LuaString}
|
* @return {@link InputStream} whose data matches the bytes in this
|
||||||
|
* {@link LuaString}
|
||||||
*/
|
*/
|
||||||
public InputStream toInputStream() {
|
public InputStream toInputStream() {
|
||||||
return new ByteArrayInputStream(m_bytes, m_offset, m_length);
|
return new ByteArrayInputStream(m_bytes, m_offset, m_length);
|
||||||
@@ -553,6 +683,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy the bytes of the string into the given byte array.
|
* Copy the bytes of the string into the given byte array.
|
||||||
|
*
|
||||||
* @param strOffset offset from which to copy
|
* @param strOffset offset from which to copy
|
||||||
* @param bytes destination byte array
|
* @param bytes destination byte array
|
||||||
* @param arrayOffset offset in destination
|
* @param arrayOffset offset in destination
|
||||||
@@ -562,9 +693,13 @@ public class LuaString extends LuaValue {
|
|||||||
System.arraycopy(m_bytes, m_offset+strOffset, bytes, arrayOffset, len);
|
System.arraycopy(m_bytes, m_offset+strOffset, bytes, arrayOffset, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Java version of strpbrk - find index of any byte that in an accept string.
|
/**
|
||||||
|
* Java version of strpbrk - find index of any byte that in an accept
|
||||||
|
* string.
|
||||||
|
*
|
||||||
* @param accept {@link LuaString} containing characters to look for.
|
* @param accept {@link LuaString} containing characters to look for.
|
||||||
* @return index of first match in the {@code accept} string, or -1 if not found.
|
* @return index of first match in the {@code accept} string, or -1 if not
|
||||||
|
* found.
|
||||||
*/
|
*/
|
||||||
public int indexOfAny(LuaString accept) {
|
public int indexOfAny(LuaString accept) {
|
||||||
final int ilimit = m_offset+m_length;
|
final int ilimit = m_offset+m_length;
|
||||||
@@ -581,6 +716,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the index of a byte starting at a point in this string
|
* Find the index of a byte starting at a point in this string
|
||||||
|
*
|
||||||
* @param b the byte to look for
|
* @param b the byte to look for
|
||||||
* @param start the first index in the string
|
* @param start the first index in the string
|
||||||
* @return index of first match found, or -1 if not found.
|
* @return index of first match found, or -1 if not found.
|
||||||
@@ -595,6 +731,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the index of a string starting at a point in this string
|
* Find the index of a string starting at a point in this string
|
||||||
|
*
|
||||||
* @param s the string to search for
|
* @param s the string to search for
|
||||||
* @param start the first index in the string
|
* @param start the first index in the string
|
||||||
* @return index of first match found, or -1 if not found.
|
* @return index of first match found, or -1 if not found.
|
||||||
@@ -611,6 +748,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the last index of a string in this string
|
* Find the last index of a string in this string
|
||||||
|
*
|
||||||
* @param s the string to search for
|
* @param s the string to search for
|
||||||
* @return index of last match found, or -1 if not found.
|
* @return index of last match found, or -1 if not found.
|
||||||
*/
|
*/
|
||||||
@@ -624,14 +762,14 @@ public class LuaString extends LuaValue {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert to Java String interpreting as utf8 characters.
|
* Convert to Java String interpreting as utf8 characters.
|
||||||
*
|
*
|
||||||
* @param bytes byte array in UTF8 encoding to convert
|
* @param bytes byte array in UTF8 encoding to convert
|
||||||
* @param offset starting index in byte array
|
* @param offset starting index in byte array
|
||||||
* @param length number of bytes to convert
|
* @param length number of bytes to convert
|
||||||
* @return Java String corresponding to the value of bytes interpreted using UTF8
|
* @return Java String corresponding to the value of bytes interpreted using
|
||||||
|
* UTF8
|
||||||
* @see #lengthAsUtf8(char[])
|
* @see #lengthAsUtf8(char[])
|
||||||
* @see #encodeToUtf8(char[], int, byte[], int)
|
* @see #encodeToUtf8(char[], int, byte[], int)
|
||||||
* @see #isValidUtf8()
|
* @see #isValidUtf8()
|
||||||
@@ -640,22 +778,24 @@ public class LuaString extends LuaValue {
|
|||||||
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) {
|
||||||
switch (0xE0 & bytes[i++]) {
|
switch (0xE0 & bytes[i++]) {
|
||||||
case 0xE0: ++i;
|
case 0xE0:
|
||||||
case 0xC0: ++i;
|
++i;
|
||||||
|
case 0xC0:
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
char[] chars = new char[n];
|
char[] chars = new char[n];
|
||||||
for (i = offset, j = offset+length, n = 0; i < j;) {
|
for (i = offset, j = offset+length, n = 0; i < j;) {
|
||||||
chars[n++] = (char) (
|
chars[n++] = (char) (((b = bytes[i++]) >= 0 || i >= j)? b
|
||||||
((b=bytes[i++])>=0||i>=j)? b:
|
: (b < -32 || i+1 >= j)? (((b & 0x3f)<<6) | (bytes[i++] & 0x3f))
|
||||||
(b<-32||i+1>=j)? (((b&0x3f) << 6) | (bytes[i++]&0x3f)):
|
: (((b & 0xf)<<12) | ((bytes[i++] & 0x3f)<<6) | (bytes[i++] & 0x3f)));
|
||||||
(((b&0xf) << 12) | ((bytes[i++]&0x3f)<<6) | (bytes[i++]&0x3f)));
|
|
||||||
}
|
}
|
||||||
return new String(chars);
|
return new String(chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count the number of bytes required to encode the string as UTF-8.
|
* Count the number of bytes required to encode the string as UTF-8.
|
||||||
|
*
|
||||||
* @param chars Array of unicode characters to be encoded as UTF-8
|
* @param chars Array of unicode characters to be encoded as UTF-8
|
||||||
* @return count of bytes needed to encode using UTF-8
|
* @return count of bytes needed to encode using UTF-8
|
||||||
* @see #encodeToUtf8(char[], int, byte[], int)
|
* @see #encodeToUtf8(char[], int, byte[], int)
|
||||||
@@ -675,8 +815,9 @@ public class LuaString extends LuaValue {
|
|||||||
* Encode the given Java string as UTF-8 bytes, writing the result to bytes
|
* Encode the given Java string as UTF-8 bytes, writing the result to bytes
|
||||||
* starting at offset.
|
* starting at offset.
|
||||||
* <p>
|
* <p>
|
||||||
* The string should be measured first with lengthAsUtf8
|
* The string should be measured first with lengthAsUtf8 to make sure the
|
||||||
* to make sure the given byte array is large enough.
|
* given byte array is large enough.
|
||||||
|
*
|
||||||
* @param chars Array of unicode characters to be encoded as UTF-8
|
* @param chars Array of unicode characters to be encoded as UTF-8
|
||||||
* @param nchars Number of characters in the array to convert.
|
* @param nchars Number of characters in the array to convert.
|
||||||
* @param bytes byte array to hold the result
|
* @param bytes byte array to hold the result
|
||||||
@@ -704,7 +845,9 @@ public class LuaString extends LuaValue {
|
|||||||
return j-off;
|
return j-off;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check that a byte sequence is valid UTF-8
|
/**
|
||||||
|
* Check that a byte sequence is valid UTF-8
|
||||||
|
*
|
||||||
* @return true if it is valid UTF-8, otherwise false
|
* @return true if it is valid UTF-8, otherwise false
|
||||||
* @see #lengthAsUtf8(char[])
|
* @see #lengthAsUtf8(char[])
|
||||||
* @see #encodeToUtf8(char[], int, byte[], int)
|
* @see #encodeToUtf8(char[], int, byte[], int)
|
||||||
@@ -713,14 +856,12 @@ public class LuaString extends LuaValue {
|
|||||||
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 ) continue;
|
if (c >= 0)
|
||||||
if ( ((c & 0xE0) == 0xC0)
|
continue;
|
||||||
&& i<j
|
if (((c & 0xE0) == 0xC0) && i < j && (m_bytes[i++] & 0xC0) == 0x80)
|
||||||
&& (m_bytes[i++] & 0xC0) == 0x80) continue;
|
continue;
|
||||||
if ( ((c & 0xF0) == 0xE0)
|
if (((c & 0xF0) == 0xE0) && i+1 < j && (m_bytes[i++] & 0xC0) == 0x80 && (m_bytes[i++] & 0xC0) == 0x80)
|
||||||
&& i+1<j
|
continue;
|
||||||
&& (m_bytes[i++] & 0xC0) == 0x80
|
|
||||||
&& (m_bytes[i++] & 0xC0) == 0x80) continue;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -729,9 +870,11 @@ public class LuaString extends LuaValue {
|
|||||||
// --------------------- number conversion -----------------------
|
// --------------------- number conversion -----------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert to a number using baee 10 or base 16 if it starts with '0x',
|
* convert to a number using baee 10 or base 16 if it starts with '0x', or
|
||||||
* or NIL if it can't be converted
|
* NIL if it can't be converted
|
||||||
* @return IntValue, DoubleValue, or NIL depending on the content of the string.
|
*
|
||||||
|
* @return IntValue, DoubleValue, or NIL depending on the content of the
|
||||||
|
* string.
|
||||||
* @see LuaValue#tonumber()
|
* @see LuaValue#tonumber()
|
||||||
*/
|
*/
|
||||||
public LuaValue tonumber() {
|
public LuaValue tonumber() {
|
||||||
@@ -740,9 +883,12 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* convert to a number using a supplied base, or NIL if it can't be converted
|
* convert to a number using a supplied base, or NIL if it can't be
|
||||||
|
* converted
|
||||||
|
*
|
||||||
* @param base the base to use, such as 10
|
* @param base the base to use, such as 10
|
||||||
* @return IntValue, DoubleValue, or NIL depending on the content of the string.
|
* @return IntValue, DoubleValue, or NIL depending on the content of the
|
||||||
|
* string.
|
||||||
* @see LuaValue#tonumber()
|
* @see LuaValue#tonumber()
|
||||||
*/
|
*/
|
||||||
public LuaValue tonumber(int base) {
|
public LuaValue tonumber(int base) {
|
||||||
@@ -751,14 +897,17 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
* or return Double.NaN if it cannot be converted to a number.
|
* '0x', 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 && m_bytes[i]==' ' ) ++i;
|
while ( i < j && m_bytes[i] == ' ' )
|
||||||
while ( i<j && m_bytes[j-1]==' ' ) --j;
|
++i;
|
||||||
|
while ( i < j && m_bytes[j-1] == ' ' )
|
||||||
|
--j;
|
||||||
if (i >= j)
|
if (i >= j)
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
if (m_bytes[i] == '0' && i+1 < j && (m_bytes[i+1] == 'x' || m_bytes[i+1] == 'X'))
|
if (m_bytes[i] == '0' && i+1 < j && (m_bytes[i+1] == 'x' || m_bytes[i+1] == 'X'))
|
||||||
@@ -769,6 +918,7 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert to a number in a base, or return Double.NaN if not a number.
|
* Convert to a number in a base, or return Double.NaN if not a number.
|
||||||
|
*
|
||||||
* @param base the base to use between 2 and 36
|
* @param base the base to use between 2 and 36
|
||||||
* @return double value if conversion is valid, or Double.NaN if not
|
* @return double value if conversion is valid, or Double.NaN if not
|
||||||
*/
|
*/
|
||||||
@@ -776,8 +926,10 @@ 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 && m_bytes[i]==' ' ) ++i;
|
while ( i < j && m_bytes[i] == ' ' )
|
||||||
while ( i<j && m_bytes[j-1]==' ' ) --j;
|
++i;
|
||||||
|
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);
|
||||||
@@ -785,18 +937,18 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan and convert a long value, or return Double.NaN if not found.
|
* Scan and convert a long value, or return Double.NaN if not found.
|
||||||
|
*
|
||||||
* @param base the base to use, such as 10
|
* @param base the base to use, such as 10
|
||||||
* @param start the index to start searching from
|
* @param start the index to start searching from
|
||||||
* @param end the first index beyond the search range
|
* @param end the first index beyond the search range
|
||||||
* @return double value if conversion is valid,
|
* @return double value if conversion is valid, 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) {
|
||||||
long x = 0;
|
long x = 0;
|
||||||
boolean neg = (m_bytes[start] == '-');
|
boolean neg = (m_bytes[start] == '-');
|
||||||
for (int i = (neg? start+1: start); i < end; i++) {
|
for (int i = (neg? start+1: 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));
|
||||||
if (digit < 0 || digit >= base)
|
if (digit < 0 || digit >= base)
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
x = x*base+digit;
|
x = x*base+digit;
|
||||||
@@ -808,21 +960,31 @@ public class LuaString extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan and convert a double value, or return Double.NaN if not a double.
|
* Scan and convert a double value, or return Double.NaN if not a double.
|
||||||
|
*
|
||||||
* @param start the index to start searching from
|
* @param start the index to start searching from
|
||||||
* @param end the first index beyond the search range
|
* @param end the first index beyond the search range
|
||||||
* @return double value if conversion is valid,
|
* @return double value if conversion is valid, or Double.NaN if not
|
||||||
* or Double.NaN if not
|
|
||||||
*/
|
*/
|
||||||
private double scandouble(int start, int end) {
|
private double scandouble(int start, int end) {
|
||||||
if ( end>start+64 ) end=start+64;
|
if (end > start+64)
|
||||||
|
end = start+64;
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++) {
|
||||||
switch (m_bytes[i]) {
|
switch (m_bytes[i]) {
|
||||||
case '-':
|
case '-':
|
||||||
case '+':
|
case '+':
|
||||||
case '.':
|
case '.':
|
||||||
case 'e': case 'E':
|
case 'e':
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case 'E':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
@@ -839,8 +1001,9 @@ public class LuaString extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the bytes of the LuaString to a PrintStream as if it were
|
* Print the bytes of the LuaString to a PrintStream as if it were an ASCII
|
||||||
* an ASCII string, quoting and escaping control characters.
|
* string, quoting and escaping control characters.
|
||||||
|
*
|
||||||
* @param ps PrintStream to print to.
|
* @param ps PrintStream to print to.
|
||||||
*/
|
*/
|
||||||
public void printToStream(PrintStream ps) {
|
public void printToStream(PrintStream ps) {
|
||||||
|
|||||||
@@ -27,25 +27,27 @@ import java.util.Vector;
|
|||||||
/**
|
/**
|
||||||
* Subclass of {@link LuaValue} for representing lua tables.
|
* Subclass of {@link LuaValue} for representing lua tables.
|
||||||
* <p>
|
* <p>
|
||||||
* Almost all API's implemented in {@link LuaTable} are defined and documented in {@link LuaValue}.
|
* Almost all API's implemented in {@link LuaTable} are defined and documented
|
||||||
|
* in {@link LuaValue}.
|
||||||
* <p>
|
* <p>
|
||||||
* If a table is needed, the one of the type-checking functions can be used such as
|
* If a table is needed, the one of the type-checking functions can be used such
|
||||||
* {@link #istable()},
|
* as {@link #istable()}, {@link #checktable()}, or {@link #opttable(LuaTable)}
|
||||||
* {@link #checktable()}, or
|
|
||||||
* {@link #opttable(LuaTable)}
|
|
||||||
* <p>
|
* <p>
|
||||||
* The main table operations are defined on {@link LuaValue}
|
* The main table operations are defined on {@link LuaValue} for getting and
|
||||||
* for getting and setting values with and without metatag processing:
|
* setting values with and without metatag processing:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #get(LuaValue)}</li>
|
* <li>{@link #get(LuaValue)}</li>
|
||||||
* <li>{@link #set(LuaValue,LuaValue)}</li>
|
* <li>{@link #set(LuaValue,LuaValue)}</li>
|
||||||
* <li>{@link #rawget(LuaValue)}</li>
|
* <li>{@link #rawget(LuaValue)}</li>
|
||||||
* <li>{@link #rawset(LuaValue,LuaValue)}</li>
|
* <li>{@link #rawset(LuaValue,LuaValue)}</li>
|
||||||
* <li>plus overloads such as {@link #get(String)}, {@link #get(int)}, and so on</li>
|
* <li>plus overloads such as {@link #get(String)}, {@link #get(int)}, and so
|
||||||
|
* on</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* To iterate over key-value pairs from Java, use
|
* To iterate over key-value pairs from Java, use
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* LuaValue k = LuaValue.NIL;
|
* LuaValue k = LuaValue.NIL;
|
||||||
* while ( true ) {
|
* while ( true ) {
|
||||||
* Varargs n = table.next(k);
|
* Varargs n = table.next(k);
|
||||||
@@ -53,11 +55,12 @@ import java.util.Vector;
|
|||||||
* break;
|
* break;
|
||||||
* LuaValue v = n.arg(2)
|
* LuaValue v = n.arg(2)
|
||||||
* process( k, v )
|
* process( k, v )
|
||||||
* }}</pre>
|
* }}
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* As with other types, {@link LuaTable} instances should be constructed via one of the table constructor
|
* As with other types, {@link LuaTable} instances should be constructed via one
|
||||||
* methods on {@link LuaValue}:
|
* of the table constructor methods on {@link LuaValue}:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link LuaValue#tableOf()} empty table</li>
|
* <li>{@link LuaValue#tableOf()} empty table</li>
|
||||||
* <li>{@link LuaValue#tableOf(int, int)} table with capacity</li>
|
* <li>{@link LuaValue#tableOf(int, int)} table with capacity</li>
|
||||||
@@ -65,9 +68,12 @@ import java.util.Vector;
|
|||||||
* <li>{@link LuaValue#listOf(LuaValue[], Varargs)} initialize array part</li>
|
* <li>{@link LuaValue#listOf(LuaValue[], Varargs)} initialize array part</li>
|
||||||
* <li>{@link LuaValue#tableOf(LuaValue[])} initialize named hash part</li>
|
* <li>{@link LuaValue#tableOf(LuaValue[])} initialize named hash part</li>
|
||||||
* <li>{@link LuaValue#tableOf(Varargs, int)} initialize named hash part</li>
|
* <li>{@link LuaValue#tableOf(Varargs, int)} initialize named hash part</li>
|
||||||
* <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[])} initialize array and named parts</li>
|
* <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[])} initialize array and
|
||||||
* <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[], Varargs)} initialize array and named parts</li>
|
* named parts</li>
|
||||||
|
* <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[], Varargs)} initialize
|
||||||
|
* array and named parts</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
*/
|
*/
|
||||||
public class LuaTable extends LuaValue implements Metatable {
|
public class LuaTable extends LuaValue implements Metatable {
|
||||||
@@ -94,6 +100,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table with preset capacity.
|
* Construct table with preset capacity.
|
||||||
|
*
|
||||||
* @param narray capacity of array part
|
* @param narray capacity of array part
|
||||||
* @param nhash capacity of hash part
|
* @param nhash capacity of hash part
|
||||||
*/
|
*/
|
||||||
@@ -103,7 +110,9 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table with named and unnamed parts.
|
* Construct table with named and unnamed parts.
|
||||||
* @param named Named elements in order {@code key-a, value-a, key-b, value-b, ... }
|
*
|
||||||
|
* @param named Named elements in order
|
||||||
|
* {@code key-a, value-a, key-b, value-b, ... }
|
||||||
* @param unnamed Unnamed elements in order {@code value-1, value-2, ... }
|
* @param unnamed Unnamed elements in order {@code value-1, value-2, ... }
|
||||||
* @param lastarg Additional unnamed values beyond {@code unnamed.length}
|
* @param lastarg Additional unnamed values beyond {@code unnamed.length}
|
||||||
*/
|
*/
|
||||||
@@ -124,6 +133,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table of unnamed elements.
|
* Construct table of unnamed elements.
|
||||||
|
*
|
||||||
* @param varargs Unnamed elements in order {@code value-1, value-2, ... }
|
* @param varargs Unnamed elements in order {@code value-1, value-2, ... }
|
||||||
*/
|
*/
|
||||||
public LuaTable(Varargs varargs) {
|
public LuaTable(Varargs varargs) {
|
||||||
@@ -132,8 +142,10 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct table of unnamed elements.
|
* Construct table of unnamed elements.
|
||||||
|
*
|
||||||
* @param varargs Unnamed elements in order {@code value-1, value-2, ... }
|
* @param varargs Unnamed elements in order {@code value-1, value-2, ... }
|
||||||
* @param firstarg the index in varargs of the first argument to include in the table
|
* @param firstarg the index in varargs of the first argument to include in
|
||||||
|
* the table
|
||||||
*/
|
*/
|
||||||
public LuaTable(Varargs varargs, int firstarg) {
|
public LuaTable(Varargs varargs, int firstarg) {
|
||||||
int nskip = firstarg-1;
|
int nskip = firstarg-1;
|
||||||
@@ -187,19 +199,19 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the length of the array part of the table.
|
* Get the length of the array part of the table.
|
||||||
* @return length of the array part, does not relate to count of objects in the table.
|
*
|
||||||
|
* @return length of the array part, does not relate to count of objects in
|
||||||
|
* the table.
|
||||||
*/
|
*/
|
||||||
protected int getArrayLength() {
|
protected int getArrayLength() { return array.length; }
|
||||||
return array.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the length of the hash part of the table.
|
* Get the length of the hash part of the table.
|
||||||
* @return length of the hash part, does not relate to count of objects in the table.
|
*
|
||||||
|
* @return length of the hash part, does not relate to count of objects in
|
||||||
|
* the table.
|
||||||
*/
|
*/
|
||||||
protected int getHashLength() {
|
protected int getHashLength() { return hash.length; }
|
||||||
return hash.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LuaValue getmetatable() {
|
public LuaValue getmetatable() {
|
||||||
return (m_metatable != null)? m_metatable.toLuaValue(): null;
|
return (m_metatable != null)? m_metatable.toLuaValue(): null;
|
||||||
@@ -209,8 +221,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
boolean hadWeakKeys = m_metatable != null && m_metatable.useWeakKeys();
|
boolean hadWeakKeys = m_metatable != null && m_metatable.useWeakKeys();
|
||||||
boolean hadWeakValues = m_metatable != null && m_metatable.useWeakValues();
|
boolean hadWeakValues = m_metatable != null && m_metatable.useWeakValues();
|
||||||
m_metatable = metatableOf(metatable);
|
m_metatable = metatableOf(metatable);
|
||||||
if ( ( hadWeakKeys != ( m_metatable != null && m_metatable.useWeakKeys() )) ||
|
if ((hadWeakKeys != (m_metatable != null && m_metatable.useWeakKeys()))
|
||||||
( hadWeakValues != ( m_metatable != null && m_metatable.useWeakValues() ))) {
|
|| (hadWeakValues != (m_metatable != null && m_metatable.useWeakValues()))) {
|
||||||
// force a rehash
|
// force a rehash
|
||||||
rehash(0);
|
rehash(0);
|
||||||
}
|
}
|
||||||
@@ -239,8 +251,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
if (key.isinttype()) {
|
if (key.isinttype()) {
|
||||||
int ikey = key.toint();
|
int ikey = key.toint();
|
||||||
if (ikey > 0 && ikey <= array.length) {
|
if (ikey > 0 && ikey <= array.length) {
|
||||||
LuaValue v = m_metatable == null
|
LuaValue v = m_metatable == null? array[ikey-1]: m_metatable.arrayget(array, ikey-1);
|
||||||
? array[ikey-1] : m_metatable.arrayget(array, ikey-1);
|
|
||||||
return v != null? v: NIL;
|
return v != null? v: NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -286,14 +297,14 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
/** Set an array element */
|
/** Set an array element */
|
||||||
private boolean arrayset(int key, LuaValue value) {
|
private boolean arrayset(int key, LuaValue value) {
|
||||||
if (key > 0 && key <= array.length) {
|
if (key > 0 && key <= array.length) {
|
||||||
array[key - 1] = value.isnil() ? null :
|
array[key-1] = value.isnil()? null: (m_metatable != null? m_metatable.wrap(value): value);
|
||||||
(m_metatable != null ? m_metatable.wrap(value) : value);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove the element at a position in a list-table
|
/**
|
||||||
|
* Remove the element at a position in a list-table
|
||||||
*
|
*
|
||||||
* @param pos the position to remove
|
* @param pos the position to remove
|
||||||
* @return The removed item, or {@link #NONE} if not removed
|
* @return The removed item, or {@link #NONE} if not removed
|
||||||
@@ -312,7 +323,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
return v.isnil()? NONE: v;
|
return v.isnil()? NONE: v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Insert an element at a position in a list-table
|
/**
|
||||||
|
* Insert an element at a position in a list-table
|
||||||
*
|
*
|
||||||
* @param pos the position to remove
|
* @param pos the position to remove
|
||||||
* @param value The value to insert
|
* @param value The value to insert
|
||||||
@@ -327,7 +339,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Concatenate the contents of a table efficiently, using {@link Buffer}
|
/**
|
||||||
|
* Concatenate the contents of a table efficiently, using {@link Buffer}
|
||||||
*
|
*
|
||||||
* @param sep {@link LuaString} separater to apply between elements
|
* @param sep {@link LuaString} separater to apply between elements
|
||||||
* @param i the first element index
|
* @param i the first element index
|
||||||
@@ -349,7 +362,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
public int length() {
|
public int length() {
|
||||||
if (m_metatable != null) {
|
if (m_metatable != null) {
|
||||||
LuaValue len = len();
|
LuaValue len = len();
|
||||||
if (!len.isint()) throw new LuaError("table length is not an integer: " + len);
|
if (!len.isint())
|
||||||
|
throw new LuaError("table length is not an integer: " + len);
|
||||||
return len.toint();
|
return len.toint();
|
||||||
}
|
}
|
||||||
return rawlen();
|
return rawlen();
|
||||||
@@ -381,6 +395,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next element after a particular key in the table
|
* Get the next element after a particular key in the table
|
||||||
|
*
|
||||||
* @return key,value or nil
|
* @return key,value or nil
|
||||||
*/
|
*/
|
||||||
public Varargs next(LuaValue key) {
|
public Varargs next(LuaValue key) {
|
||||||
@@ -441,8 +456,9 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next element after a particular key in the
|
* Get the next element after a particular key in the contiguous array part
|
||||||
* contiguous array part of a table
|
* of a table
|
||||||
|
*
|
||||||
* @return key,value or none
|
* @return key,value or none
|
||||||
*/
|
*/
|
||||||
public Varargs inext(LuaValue key) {
|
public Varargs inext(LuaValue key) {
|
||||||
@@ -453,6 +469,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a hashtable value
|
* Set a hashtable value
|
||||||
|
*
|
||||||
* @param key key to set
|
* @param key key to set
|
||||||
* @param value value to set
|
* @param value value to set
|
||||||
*/
|
*/
|
||||||
@@ -472,8 +489,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (checkLoadFactor()) {
|
if (checkLoadFactor()) {
|
||||||
if ( (m_metatable == null || !m_metatable.useWeakValues())
|
if ((m_metatable == null || !m_metatable.useWeakValues()) && key.isinttype() && key.toint() > 0) {
|
||||||
&& key.isinttype() && key.toint() > 0 ) {
|
|
||||||
// a rehash might make room in the array portion for this key.
|
// a rehash might make room in the array portion for this key.
|
||||||
rehash(key.toint());
|
rehash(key.toint());
|
||||||
if (arrayset(key.toint(), value))
|
if (arrayset(key.toint(), value))
|
||||||
@@ -483,9 +499,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
index = hashSlot(key);
|
index = hashSlot(key);
|
||||||
}
|
}
|
||||||
Slot entry = ( m_metatable != null )
|
Slot entry = (m_metatable != null)? m_metatable.entry(key, value): defaultEntry(key, value);
|
||||||
? m_metatable.entry( key, value )
|
|
||||||
: defaultEntry( key, value );
|
|
||||||
hash[index] = (hash[index] != null)? hash[index].add(entry): entry;
|
hash[index] = (hash[index] != null)? hash[index].add(entry): entry;
|
||||||
++hashEntries;
|
++hashEntries;
|
||||||
}
|
}
|
||||||
@@ -501,8 +515,10 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the hashtable slot index to use.
|
* Find the hashtable slot index to use.
|
||||||
|
*
|
||||||
* @param key the key to look for
|
* @param key the key to look for
|
||||||
* @param hashMask N-1 where N is the number of hash slots (must be power of 2)
|
* @param hashMask N-1 where N is the number of hash slots (must be power of
|
||||||
|
* 2)
|
||||||
* @return the slot index
|
* @return the slot index
|
||||||
*/
|
*/
|
||||||
public static int hashSlot(LuaValue key, int hashMask) {
|
public static int hashSlot(LuaValue key, int hashMask) {
|
||||||
@@ -520,6 +536,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the hashtable slot to use
|
* Find the hashtable slot to use
|
||||||
|
*
|
||||||
* @param key key to look for
|
* @param key key to look for
|
||||||
* @return slot to use
|
* @return slot to use
|
||||||
*/
|
*/
|
||||||
@@ -614,22 +631,53 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
x >>>= 4;
|
x >>>= 4;
|
||||||
}
|
}
|
||||||
switch (x) {
|
switch (x) {
|
||||||
case 0x0: return 0;
|
case 0x0:
|
||||||
case 0x1: lg += 1; break;
|
return 0;
|
||||||
case 0x2: lg += 2; break;
|
case 0x1:
|
||||||
case 0x3: lg += 2; break;
|
lg += 1;
|
||||||
case 0x4: lg += 3; break;
|
break;
|
||||||
case 0x5: lg += 3; break;
|
case 0x2:
|
||||||
case 0x6: lg += 3; break;
|
lg += 2;
|
||||||
case 0x7: lg += 3; break;
|
break;
|
||||||
case 0x8: lg += 4; break;
|
case 0x3:
|
||||||
case 0x9: lg += 4; break;
|
lg += 2;
|
||||||
case 0xA: lg += 4; break;
|
break;
|
||||||
case 0xB: lg += 4; break;
|
case 0x4:
|
||||||
case 0xC: lg += 4; break;
|
lg += 3;
|
||||||
case 0xD: lg += 4; break;
|
break;
|
||||||
case 0xE: lg += 4; break;
|
case 0x5:
|
||||||
case 0xF: lg += 4; break;
|
lg += 3;
|
||||||
|
break;
|
||||||
|
case 0x6:
|
||||||
|
lg += 3;
|
||||||
|
break;
|
||||||
|
case 0x7:
|
||||||
|
lg += 3;
|
||||||
|
break;
|
||||||
|
case 0x8:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
|
case 0x9:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
|
case 0xA:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
|
case 0xB:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
|
case 0xC:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
|
case 0xD:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
|
case 0xE:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
|
case 0xF:
|
||||||
|
lg += 4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return lg;
|
return lg;
|
||||||
}
|
}
|
||||||
@@ -693,17 +741,14 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
newArray = array;
|
newArray = array;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int newHashSize = hashEntries - movingToArray
|
final int newHashSize = hashEntries-movingToArray+((newKey < 0 || newKey > newArraySize)? 1: 0); // Make room for the new entry
|
||||||
+ ((newKey < 0 || newKey > newArraySize) ? 1 : 0); // Make room for the new entry
|
|
||||||
final int oldCapacity = oldHash.length;
|
final int oldCapacity = oldHash.length;
|
||||||
final int newCapacity;
|
final int newCapacity;
|
||||||
final int newHashMask;
|
final int newHashMask;
|
||||||
|
|
||||||
if (newHashSize > 0) {
|
if (newHashSize > 0) {
|
||||||
// round up to next power of 2.
|
// round up to next power of 2.
|
||||||
newCapacity = ( newHashSize < MIN_HASH_CAPACITY )
|
newCapacity = (newHashSize < MIN_HASH_CAPACITY)? MIN_HASH_CAPACITY: 1<<log2(newHashSize);
|
||||||
? MIN_HASH_CAPACITY
|
|
||||||
: 1 << log2(newHashSize);
|
|
||||||
newHashMask = newCapacity-1;
|
newHashMask = newCapacity-1;
|
||||||
newHash = new Slot[newCapacity];
|
newHash = new Slot[newCapacity];
|
||||||
} else {
|
} else {
|
||||||
@@ -740,8 +785,7 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
} else {
|
} else {
|
||||||
newEntry = defaultEntry(valueOf(i), v);
|
newEntry = defaultEntry(valueOf(i), v);
|
||||||
}
|
}
|
||||||
newHash[ slot ] = ( newHash[slot] != null )
|
newHash[slot] = (newHash[slot] != null)? newHash[slot].add(newEntry): newEntry;
|
||||||
? newHash[slot].add( newEntry ) : newEntry;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,11 +826,14 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
//
|
//
|
||||||
// Only sorts the contiguous array part.
|
// Only sorts the contiguous array part.
|
||||||
//
|
//
|
||||||
/** Sort the table using a comparator.
|
/**
|
||||||
|
* Sort the table using a comparator.
|
||||||
|
*
|
||||||
* @param comparator {@link LuaValue} to be called to compare elements.
|
* @param comparator {@link LuaValue} to be called to compare elements.
|
||||||
*/
|
*/
|
||||||
public void sort(LuaValue comparator) {
|
public void sort(LuaValue comparator) {
|
||||||
if (len().tolong() >= (long)Integer.MAX_VALUE) throw new LuaError("array too big: " + len().tolong());
|
if (len().tolong() >= (long) Integer.MAX_VALUE)
|
||||||
|
throw new LuaError("array too big: " + len().tolong());
|
||||||
if (m_metatable != null && m_metatable.useWeakValues()) {
|
if (m_metatable != null && m_metatable.useWeakValues()) {
|
||||||
dropWeakArrayValues();
|
dropWeakArrayValues();
|
||||||
}
|
}
|
||||||
@@ -836,10 +883,12 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This may be deprecated in a future release.
|
/**
|
||||||
* It is recommended to count via iteration over next() instead
|
* This may be deprecated in a future release. It is recommended to count
|
||||||
|
* via iteration over next() instead
|
||||||
|
*
|
||||||
* @return count of keys in the table
|
* @return count of keys in the table
|
||||||
* */
|
*/
|
||||||
public int keyCount() {
|
public int keyCount() {
|
||||||
LuaValue k = LuaValue.NIL;
|
LuaValue k = LuaValue.NIL;
|
||||||
for (int i = 0; true; i++) {
|
for (int i = 0; true; i++) {
|
||||||
@@ -849,10 +898,12 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This may be deprecated in a future release.
|
/**
|
||||||
* It is recommended to use next() instead
|
* This may be deprecated in a future release. It is recommended to use
|
||||||
|
* next() instead
|
||||||
|
*
|
||||||
* @return array of keys in the table
|
* @return array of keys in the table
|
||||||
* */
|
*/
|
||||||
public LuaValue[] keys() {
|
public LuaValue[] keys() {
|
||||||
Vector l = new Vector();
|
Vector l = new Vector();
|
||||||
LuaValue k = LuaValue.NIL;
|
LuaValue k = LuaValue.NIL;
|
||||||
@@ -869,9 +920,12 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
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) {
|
public boolean eq_b(LuaValue val) {
|
||||||
if ( this == val ) return true;
|
if (this == val)
|
||||||
if ( m_metatable == null || !val.istable() ) return false;
|
return true;
|
||||||
|
if (m_metatable == null || !val.istable())
|
||||||
|
return false;
|
||||||
LuaValue valmt = val.getmetatable();
|
LuaValue valmt = val.getmetatable();
|
||||||
return valmt != null && LuaValue.eqmtcall(this, m_metatable.toLuaValue(), val, valmt);
|
return valmt != null && LuaValue.eqmtcall(this, m_metatable.toLuaValue(), val, valmt);
|
||||||
}
|
}
|
||||||
@@ -888,16 +942,22 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
/** Unpack the elements from i to j inclusive */
|
/** Unpack the elements from i to j inclusive */
|
||||||
public Varargs unpack(int i, int j) {
|
public Varargs unpack(int i, int j) {
|
||||||
if (j < i) return NONE;
|
if (j < i)
|
||||||
|
return NONE;
|
||||||
int count = j-i;
|
int count = j-i;
|
||||||
if (count < 0) throw new LuaError("too many results to unpack: greater " + Integer.MAX_VALUE); // integer overflow
|
if (count < 0)
|
||||||
|
throw new LuaError("too many results to unpack: greater " + Integer.MAX_VALUE); // integer overflow
|
||||||
int max = 0x00ffffff;
|
int max = 0x00ffffff;
|
||||||
if (count >= max) throw new LuaError("too many results to unpack: " + count + " (max is " + max + ')');
|
if (count >= max)
|
||||||
|
throw new LuaError("too many results to unpack: " + count + " (max is " + max + ')');
|
||||||
int n = j+1-i;
|
int n = j+1-i;
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 0: return NONE;
|
case 0:
|
||||||
case 1: return get(i);
|
return NONE;
|
||||||
case 2: return varargsOf(get(i), get(i+1));
|
case 1:
|
||||||
|
return get(i);
|
||||||
|
case 2:
|
||||||
|
return varargsOf(get(i), get(i+1));
|
||||||
default:
|
default:
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return NONE;
|
return NONE;
|
||||||
@@ -1076,9 +1136,13 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
*/
|
*/
|
||||||
static abstract class Entry extends Varargs implements StrongSlot {
|
static abstract class Entry extends Varargs implements StrongSlot {
|
||||||
public abstract LuaValue key();
|
public abstract LuaValue key();
|
||||||
|
|
||||||
public abstract LuaValue value();
|
public abstract LuaValue value();
|
||||||
|
|
||||||
abstract Entry set(LuaValue value);
|
abstract Entry set(LuaValue value);
|
||||||
|
|
||||||
public abstract boolean keyeq(LuaValue key);
|
public abstract boolean keyeq(LuaValue key);
|
||||||
|
|
||||||
public abstract int keyindex(int hashMask);
|
public abstract int keyindex(int hashMask);
|
||||||
|
|
||||||
public int arraykey(int max) {
|
public int arraykey(int max) {
|
||||||
@@ -1087,8 +1151,10 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
public LuaValue arg(int i) {
|
public LuaValue arg(int i) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 1: return key();
|
case 1:
|
||||||
case 2: return value();
|
return key();
|
||||||
|
case 2:
|
||||||
|
return value();
|
||||||
}
|
}
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
@@ -1110,8 +1176,10 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
|
|
||||||
public Varargs subargs(int start) {
|
public Varargs subargs(int start) {
|
||||||
switch (start) {
|
switch (start) {
|
||||||
case 1: return this;
|
case 1:
|
||||||
case 2: return value();
|
return this;
|
||||||
|
case 2:
|
||||||
|
return value();
|
||||||
}
|
}
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
@@ -1216,7 +1284,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry class used with numeric values, but only when the key is not an integer.
|
* Entry class used with numeric values, but only when the key is not an
|
||||||
|
* integer.
|
||||||
*/
|
*/
|
||||||
private static class NumberValueEntry extends Entry {
|
private static class NumberValueEntry extends Entry {
|
||||||
private double value;
|
private double value;
|
||||||
@@ -1256,8 +1325,8 @@ public class LuaTable extends LuaValue implements Metatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Slot whose value has been set to nil. The key is kept in a weak reference so that
|
* A Slot whose value has been set to nil. The key is kept in a weak
|
||||||
* it can be found by next().
|
* reference so that it can be found by next().
|
||||||
*/
|
*/
|
||||||
private static class DeadSlot implements Slot {
|
private static class DeadSlot implements Slot {
|
||||||
|
|
||||||
|
|||||||
@@ -21,43 +21,41 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LuaValue} that implements
|
* Subclass of {@link LuaValue} that implements a lua coroutine thread using
|
||||||
* a lua coroutine thread using Java Threads.
|
* Java Threads.
|
||||||
* <p>
|
* <p>
|
||||||
* A LuaThread is typically created in response to a scripted call to
|
* A LuaThread is typically created in response to a scripted call to
|
||||||
* {@code coroutine.create()}
|
* {@code coroutine.create()}
|
||||||
* <p>
|
* <p>
|
||||||
* The threads must be initialized with the globals, so that
|
* The threads must be initialized with the globals, so that the global
|
||||||
* the global environment may be passed along according to rules of lua.
|
* environment may be passed along according to rules of lua. This is done via
|
||||||
* This is done via the constructor arguments {@link #LuaThread(Globals)} or
|
* the constructor arguments {@link #LuaThread(Globals)} or
|
||||||
* {@link #LuaThread(Globals, LuaValue)}.
|
* {@link #LuaThread(Globals, LuaValue)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The utility classes {@link org.luaj.vm2.lib.jse.JsePlatform} and
|
* The utility classes {@link org.luaj.vm2.lib.jse.JsePlatform} and
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform} see to it that this {@link Globals}
|
||||||
* see to it that this {@link Globals} are initialized properly.
|
* are initialized properly.
|
||||||
* <p>
|
* <p>
|
||||||
* The behavior of coroutine threads matches closely the behavior
|
* The behavior of coroutine threads matches closely the behavior of C coroutine
|
||||||
* of C coroutine library. However, because of the use of Java threads
|
* library. However, because of the use of Java threads to manage call state, it
|
||||||
* to manage call state, it is possible to yield from anywhere in luaj.
|
* is possible to yield from anywhere in luaj.
|
||||||
* <p>
|
* <p>
|
||||||
* Each Java thread wakes up at regular intervals and checks a weak reference
|
* Each Java thread wakes up at regular intervals and checks a weak reference to
|
||||||
* to determine if it can ever be resumed. If not, it throws
|
* determine if it can ever be resumed. If not, it throws {@link OrphanedThread}
|
||||||
* {@link OrphanedThread} which is an {@link java.lang.Error}.
|
* which is an {@link java.lang.Error}. Applications should not catch
|
||||||
* Applications should not catch {@link OrphanedThread}, because it can break
|
* {@link OrphanedThread}, because it can break the thread safety of luaj. The
|
||||||
* the thread safety of luaj. The value controlling the polling interval
|
* value controlling the polling interval is
|
||||||
* is {@link #thread_orphan_check_interval} and may be set by the user.
|
* {@link #thread_orphan_check_interval} and may be set by the user.
|
||||||
* <p>
|
* <p>
|
||||||
* There are two main ways to abandon a coroutine. The first is to call
|
* There are two main ways to abandon a coroutine. The first is to call
|
||||||
* {@code yield()} from lua, or equivalently {@link Globals#yield(Varargs)},
|
* {@code yield()} from lua, or equivalently {@link Globals#yield(Varargs)}, and
|
||||||
* and arrange to have it never resumed possibly by values passed to yield.
|
* arrange to have it never resumed possibly by values passed to yield. The
|
||||||
* The second is to throw {@link OrphanedThread}, which should put the thread
|
* second is to throw {@link OrphanedThread}, which should put the thread in a
|
||||||
* in a dead state. In either case all references to the thread must be
|
* dead state. In either case all references to the thread must be dropped, and
|
||||||
* dropped, and the garbage collector must run for the thread to be
|
* the garbage collector must run for the thread to be garbage collected.
|
||||||
* garbage collected.
|
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
@@ -73,12 +71,13 @@ public class LuaThread extends LuaValue {
|
|||||||
/** The current number of coroutines. Should not be set. */
|
/** The current number of coroutines. Should not be set. */
|
||||||
public static int coroutine_count = 0;
|
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
|
* Polling interval, in milliseconds, which each thread uses while waiting
|
||||||
* referenced and therefore should be garbage collected.
|
* to return from a yielded state to check if the lua threads is no longer
|
||||||
* A short polling interval for many threads will consume server resources.
|
* referenced and therefore should be garbage collected. A short polling
|
||||||
* Orphaned threads cannot be detected and collected unless garbage
|
* interval for many threads will consume server resources. Orphaned threads
|
||||||
* collection is run. This can be changed by Java startup code if desired.
|
* 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 long thread_orphan_check_interval = 5000;
|
||||||
|
|
||||||
@@ -87,19 +86,16 @@ public class LuaThread extends LuaValue {
|
|||||||
public static final int STATUS_RUNNING = 2;
|
public static final int STATUS_RUNNING = 2;
|
||||||
public static final int STATUS_NORMAL = 3;
|
public static final int STATUS_NORMAL = 3;
|
||||||
public static final int STATUS_DEAD = 4;
|
public static final int STATUS_DEAD = 4;
|
||||||
public static final String[] STATUS_NAMES = {
|
public static final String[] STATUS_NAMES = { "suspended", "suspended", "running", "normal", "dead", };
|
||||||
"suspended",
|
|
||||||
"suspended",
|
|
||||||
"running",
|
|
||||||
"normal",
|
|
||||||
"dead",};
|
|
||||||
|
|
||||||
public final State state;
|
public final State state;
|
||||||
|
|
||||||
public static final int MAX_CALLSTACK = 256;
|
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. */
|
* 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 Object callstack;
|
||||||
|
|
||||||
public final Globals globals;
|
public final Globals globals;
|
||||||
@@ -116,6 +112,7 @@ public class LuaThread extends LuaValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a LuaThread around a function and environment
|
* Create a LuaThread around a function and environment
|
||||||
|
*
|
||||||
* @param func The function to execute
|
* @param func The function to execute
|
||||||
*/
|
*/
|
||||||
public LuaThread(Globals globals, LuaValue func) {
|
public LuaThread(Globals globals, LuaValue func) {
|
||||||
@@ -148,19 +145,15 @@ public class LuaThread extends LuaValue {
|
|||||||
return s_metatable;
|
return s_metatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatus() {
|
public String getStatus() { return STATUS_NAMES[state.status]; }
|
||||||
return STATUS_NAMES[state.status];
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMainThread() {
|
public boolean isMainThread() { return this.state.function == null; }
|
||||||
return this.state.function == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Varargs resume(Varargs args) {
|
public Varargs resume(Varargs args) {
|
||||||
final LuaThread.State s = this.state;
|
final LuaThread.State s = this.state;
|
||||||
if (s.status > LuaThread.STATUS_SUSPENDED)
|
if (s.status > LuaThread.STATUS_SUSPENDED)
|
||||||
return LuaValue.varargsOf(LuaValue.FALSE,
|
return LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(
|
||||||
LuaValue.valueOf("cannot resume "+(s.status==LuaThread.STATUS_DEAD? "dead": "non-suspended")+" coroutine"));
|
"cannot resume " + (s.status == LuaThread.STATUS_DEAD? "dead": "non-suspended") + " coroutine"));
|
||||||
return s.lua_resume(this, args);
|
return s.lua_resume(this, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,9 +212,8 @@ public class LuaThread extends LuaValue {
|
|||||||
previous_thread.state.status = STATUS_NORMAL;
|
previous_thread.state.status = STATUS_NORMAL;
|
||||||
this.status = STATUS_RUNNING;
|
this.status = STATUS_RUNNING;
|
||||||
this.wait();
|
this.wait();
|
||||||
return (this.error != null?
|
return (this.error != null? LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error))
|
||||||
LuaValue.varargsOf(LuaValue.FALSE, LuaValue.valueOf(this.error)):
|
: LuaValue.varargsOf(LuaValue.TRUE, this.result));
|
||||||
LuaValue.varargsOf(LuaValue.TRUE, this.result));
|
|
||||||
} catch (InterruptedException ie) {
|
} catch (InterruptedException ie) {
|
||||||
throw new OrphanedThread();
|
throw new OrphanedThread();
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
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;
|
||||||
@@ -57,10 +56,15 @@ public class LuaUserdata extends LuaValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isuserdata() { return true; }
|
public boolean isuserdata() { return true; }
|
||||||
|
|
||||||
public boolean isuserdata(Class c) { return c.isAssignableFrom(m_instance.getClass()); }
|
public boolean isuserdata(Class c) { return c.isAssignableFrom(m_instance.getClass()); }
|
||||||
|
|
||||||
public Object touserdata() { return m_instance; }
|
public Object touserdata() { return m_instance; }
|
||||||
|
|
||||||
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; }
|
||||||
|
|
||||||
public Object optuserdata(Object defval) { return m_instance; }
|
public Object optuserdata(Object defval) { return m_instance; }
|
||||||
|
|
||||||
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());
|
||||||
@@ -106,21 +110,26 @@ public class LuaUserdata extends LuaValue {
|
|||||||
|
|
||||||
// equality w/ metatable processing
|
// equality w/ metatable processing
|
||||||
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) {
|
public boolean eq_b(LuaValue val) {
|
||||||
if ( val.raweq(this) ) return true;
|
if (val.raweq(this))
|
||||||
if ( m_metatable == null || !val.isuserdata() ) return false;
|
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
|
||||||
public boolean raweq(LuaValue val) { return val.raweq(this); }
|
public boolean raweq(LuaValue val) { return val.raweq(this); }
|
||||||
|
|
||||||
public boolean raweq(LuaUserdata val) {
|
public boolean raweq(LuaUserdata val) {
|
||||||
return this == val || (m_metatable == val.m_metatable && m_instance.equals(val.m_instance));
|
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()): false;
|
return m_metatable != null && val.isuserdata()? LuaValue.eqmtcall(this, m_metatable, val, val.getmetatable())
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -44,8 +44,8 @@ interface Metatable {
|
|||||||
public 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 weak reference that
|
* Returns the value at the given index in the array, or null if it is a
|
||||||
* has been dropped.
|
* weak reference that has been dropped.
|
||||||
*/
|
*/
|
||||||
public LuaValue arrayget(LuaValue[] array, int index);
|
public LuaValue arrayget(LuaValue[] array, int index);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ package org.luaj.vm2;
|
|||||||
* {@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 {@link Thread#run()} method.
|
* is thrown, and should fall through all the way to the thread's
|
||||||
|
* {@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
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ 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
|
||||||
*/
|
*/
|
||||||
@@ -36,50 +37,10 @@ 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 = {
|
public static final String[] OPNAMES = { "MOVE", "LOADK", "LOADKX", "LOADBOOL", "LOADNIL", "GETUPVAL", "GETTABUP",
|
||||||
"MOVE",
|
"GETTABLE", "SETTABUP", "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", "MOD",
|
||||||
"LOADK",
|
"POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ", "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL",
|
||||||
"LOADKX",
|
"RETURN", "FORLOOP", "FORPREP", "TFORCALL", "TFORLOOP", "SETLIST", "CLOSURE", "VARARG", "EXTRAARG", null, };
|
||||||
"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) {
|
||||||
|
|
||||||
@@ -133,8 +94,11 @@ public class Print extends Lua {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (v.type()) {
|
switch (v.type()) {
|
||||||
case LuaValue.TSTRING: printString( ps, (LuaString) v ); break;
|
case LuaValue.TSTRING:
|
||||||
default: ps.print( v.tojstring() );
|
printString(ps, (LuaString) v);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ps.print(v.tojstring());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +114,7 @@ public class Print extends Lua {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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) {
|
||||||
@@ -163,6 +128,7 @@ 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
|
||||||
@@ -173,6 +139,7 @@ public class Print extends Lua {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -334,13 +301,10 @@ public class Print extends Lua {
|
|||||||
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 + ","
|
ps.print("\n%" + a + " <" + s + ":" + f.linedefined + "," + f.lastlinedefined + "> (" + f.code.length
|
||||||
+ f.lastlinedefined + "> (" + f.code.length + " instructions, "
|
+ " instructions, " + f.code.length*4 + " bytes at " + id(f) + ")\n");
|
||||||
+ f.code.length * 4 + " bytes at " + id(f) + ")\n");
|
ps.print(f.numparams + " param, " + f.maxstacksize + " slot, " + f.upvalues.length + " upvalue, ");
|
||||||
ps.print(f.numparams + " param, " + f.maxstacksize + " slot, "
|
ps.print(f.locvars.length + " local, " + f.k.length + " constant, " + f.p.length + " function\n");
|
||||||
+ 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) {
|
||||||
@@ -357,7 +321,8 @@ 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(" "+i+" "+f.locvars[i].varname+" "+(f.locvars[i].startpc+1)+" "+(f.locvars[i].endpc+1));
|
ps.println(
|
||||||
|
" " + i + " " + f.locvars[i].varname + " " + (f.locvars[i].startpc+1) + " " + (f.locvars[i].endpc+1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,7 +334,8 @@ 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.
|
||||||
*/
|
*/
|
||||||
@@ -377,7 +343,8 @@ 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.
|
||||||
@@ -409,6 +376,7 @@ public class Print extends Lua {
|
|||||||
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");
|
||||||
@@ -416,6 +384,7 @@ public class Print extends Lua {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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}
|
||||||
@@ -443,12 +412,12 @@ public class Print extends Lua {
|
|||||||
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 switch ( v.type() ) {
|
else
|
||||||
|
switch (v.type()) {
|
||||||
case LuaValue.TSTRING:
|
case LuaValue.TSTRING:
|
||||||
LuaString s = v.checkstring();
|
LuaString s = v.checkstring();
|
||||||
ps.print( s.length() < 48?
|
ps.print(s.length() < 48? s.tojstring()
|
||||||
s.tojstring():
|
: s.substring(0, 32).tojstring() + "...+" + (s.length()-32) + "b");
|
||||||
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());
|
||||||
|
|||||||
@@ -25,54 +25,86 @@ package org.luaj.vm2;
|
|||||||
* Prototype representing compiled lua code.
|
* Prototype representing compiled lua code.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This is both a straight translation of the corresponding C type,
|
* This is both a straight translation of the corresponding C type, and the main
|
||||||
* and the main data structure for execution of compiled lua bytecode.
|
* data structure for execution of compiled lua bytecode.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Generally, the {@link Prototype} is not constructed directly is an intermediate result
|
* Generally, the {@link Prototype} is not constructed directly is an
|
||||||
* as lua code is loaded using {@link Globals#load(java.io.Reader, String)}:
|
* intermediate result as lua code is loaded using
|
||||||
* <pre> {@code
|
* {@link Globals#load(java.io.Reader, String)}:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @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>
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* To create a {@link Prototype} directly, a compiler such as
|
* To create a {@link Prototype} directly, a compiler such as
|
||||||
* {@link org.luaj.vm2.compiler.LuaC} may be used:
|
* {@link org.luaj.vm2.compiler.LuaC} may be used:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* InputStream is = new ByteArrayInputStream("print('hello,world')".getBytes());
|
* InputStream is = new ByteArrayInputStream("print('hello,world')".getBytes());
|
||||||
* Prototype p = LuaC.instance.compile(is, "script");
|
* Prototype p = LuaC.instance.compile(is, "script");
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* To simplify loading, the {@link Globals#compilePrototype(java.io.InputStream, String)} method may be used:
|
* To simplify loading, the
|
||||||
* <pre> {@code
|
* {@link Globals#compilePrototype(java.io.InputStream, String)} method may be
|
||||||
|
* used:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Prototype p = globals.compileProtoytpe(is, "script");
|
* Prototype p = globals.compileProtoytpe(is, "script");
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* It may also be loaded from a {@link java.io.Reader} via {@link Globals#compilePrototype(java.io.Reader, String)}:
|
* It may also be loaded from a {@link java.io.Reader} via
|
||||||
* <pre> {@code
|
* {@link Globals#compilePrototype(java.io.Reader, String)}:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Prototype p = globals.compileProtoytpe(new StringReader(script), "script");
|
* Prototype p = globals.compileProtoytpe(new StringReader(script), "script");
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* To un-dump a binary file known to be a binary lua file that has been dumped to a string,
|
* To un-dump a binary file known to be a binary lua file that has been dumped
|
||||||
* the {@link Globals.Undumper} interface may be used:
|
* to a string, the {@link Globals.Undumper} interface may be used:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* FileInputStream lua_binary_file = new FileInputStream("foo.lc"); // Known to be compiled lua.
|
* FileInputStream lua_binary_file = new FileInputStream("foo.lc"); // Known to be compiled lua.
|
||||||
* Prototype p = globals.undumper.undump(lua_binary_file, "foo.lua");
|
* Prototype p = globals.undumper.undump(lua_binary_file, "foo.lua");
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* To execute the code represented by the {@link Prototype} it must be supplied to
|
* To execute the code represented by the {@link Prototype} it must be supplied
|
||||||
* the constructor of a {@link LuaClosure}:
|
* to the constructor of a {@link LuaClosure}:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* LuaClosure f = new LuaClosure(p, globals);
|
* LuaClosure f = new LuaClosure(p, globals);
|
||||||
* f.call();
|
* f.call();
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* To simplify the debugging of prototype values, the contents may be printed using {@link Print#print}:
|
* To simplify the debugging of prototype values, the contents may be printed
|
||||||
* <pre> {@code
|
* using {@link Print#print}:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* Print.print(p);
|
* Print.print(p);
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* @see LuaClosure
|
* @see LuaClosure
|
||||||
@@ -117,7 +149,8 @@ public class Prototype {
|
|||||||
return source + ":" + linedefined + "-" + lastlinedefined;
|
return source + ":" + linedefined + "-" + lastlinedefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the name of a local variable.
|
/**
|
||||||
|
* Get the name of a local variable.
|
||||||
*
|
*
|
||||||
* @param number the local variable number to look up
|
* @param number the local variable number to look up
|
||||||
* @param pc the program counter
|
* @param pc the program counter
|
||||||
|
|||||||
@@ -22,21 +22,20 @@
|
|||||||
package org.luaj.vm2;
|
package org.luaj.vm2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link Varargs} that represents a lua tail call
|
* Subclass of {@link Varargs} that represents a lua tail call in a Java library
|
||||||
* in a Java library function execution environment.
|
* function execution environment.
|
||||||
* <p>
|
* <p>
|
||||||
* Since Java doesn't have direct support for tail calls,
|
* Since Java doesn't have direct support for tail calls, any lua function whose
|
||||||
* any lua function whose {@link Prototype} contains the
|
* {@link Prototype} contains the {@link Lua#OP_TAILCALL} bytecode needs a
|
||||||
* {@link Lua#OP_TAILCALL} bytecode needs a mechanism
|
* mechanism for tail calls when converting lua-bytecode to java-bytecode.
|
||||||
* for tail calls when converting lua-bytecode to java-bytecode.
|
|
||||||
* <p>
|
* <p>
|
||||||
* The tail call holds the next function and arguments,
|
* The tail call holds the next function and arguments, and the client a call to
|
||||||
* and the client a call to {@link #eval()} executes the function
|
* {@link #eval()} executes the function repeatedly until the tail calls are
|
||||||
* repeatedly until the tail calls are completed.
|
* completed.
|
||||||
* <p>
|
* <p>
|
||||||
* Normally, users of luaj need not concern themselves with the
|
* Normally, users of luaj need not concern themselves with the details of this
|
||||||
* details of this mechanism, as it is built into the core
|
* mechanism, as it is built into the core execution framework.
|
||||||
* execution framework.
|
*
|
||||||
* @see Prototype
|
* @see Prototype
|
||||||
* @see org.luaj.vm2.luajc.LuaJC
|
* @see org.luaj.vm2.luajc.LuaJC
|
||||||
*/
|
*/
|
||||||
@@ -56,9 +55,7 @@ public class TailcallVarargs extends Varargs {
|
|||||||
this.args = LuaValue.varargsOf(object, args);
|
this.args = LuaValue.varargsOf(object, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTailcall() {
|
public boolean isTailcall() { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Varargs eval() {
|
public Varargs eval() {
|
||||||
while ( result == null ) {
|
while ( result == null ) {
|
||||||
@@ -67,8 +64,7 @@ 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;
|
||||||
|
|||||||
@@ -21,9 +21,10 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
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
|
||||||
*/
|
*/
|
||||||
@@ -34,6 +35,7 @@ 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
|
||||||
*/
|
*/
|
||||||
@@ -48,6 +50,7 @@ public final class UpValue {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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()
|
||||||
*/
|
*/
|
||||||
@@ -57,19 +60,17 @@ 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 final LuaValue getValue() {
|
public final LuaValue getValue() { return array[index]; }
|
||||||
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 final void setValue( LuaValue value ) {
|
public final void setValue(LuaValue value) { array[index] = 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
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -29,8 +29,8 @@ 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 mode
|
* Normally these are not created directly, but indirectly when changing the
|
||||||
* of a {@link LuaTable} as lua script executes.
|
* mode 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.
|
||||||
@@ -59,6 +59,7 @@ public class WeakTable implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
@@ -301,8 +302,10 @@ public class WeakTable implements Metatable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 type of {@code value}
|
* @return {@link LuaValue} that is a strong or weak reference, depending on
|
||||||
|
* type of {@code value}
|
||||||
*/
|
*/
|
||||||
protected static LuaValue weaken(LuaValue value) {
|
protected static LuaValue weaken(LuaValue value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
@@ -319,6 +322,7 @@ 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)
|
||||||
@@ -333,7 +337,9 @@ public class WeakTable implements Metatable {
|
|||||||
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 {
|
||||||
@@ -368,7 +374,9 @@ public class WeakTable implements Metatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 {
|
||||||
|
|||||||
@@ -44,21 +44,15 @@ public class Constants extends Lua {
|
|||||||
static final int LUAI_MAXVARS = 200;
|
static final int LUAI_MAXVARS = 200;
|
||||||
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
|
static final int iABC = 0, iABx = 1, iAsBx = 2;
|
||||||
iABC = 0,
|
|
||||||
iABx = 1,
|
|
||||||
iAsBx = 2;
|
|
||||||
|
|
||||||
/* OpArgMask */
|
/* OpArgMask */
|
||||||
static final int
|
static final int OpArgN = 0, /* argument is not used */
|
||||||
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");
|
||||||
@@ -93,21 +87,15 @@ public class Constants extends Lua {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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) |
|
return ((o<<POS_OP) & MASK_OP) | ((a<<POS_A) & MASK_A) | ((b<<POS_B) & MASK_B) | ((c<<POS_C) & MASK_C);
|
||||||
((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) |
|
return ((o<<POS_OP) & MASK_OP) | ((a<<POS_A) & MASK_A) | ((bc<<POS_Bx) & MASK_Bx);
|
||||||
((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) |
|
return ((o<<POS_OP) & MASK_OP) | ((a<<POS_Ax) & MASK_Ax);
|
||||||
((a << POS_Ax) & MASK_Ax) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// vector reallocation
|
// vector reallocation
|
||||||
|
|||||||
@@ -32,35 +32,47 @@ import org.luaj.vm2.LuaString;
|
|||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Prototype;
|
import org.luaj.vm2.Prototype;
|
||||||
|
|
||||||
|
/**
|
||||||
/** Class to dump a {@link Prototype} into an output stream, as part of compiling.
|
* Class to dump a {@link Prototype} into an output stream, as part of
|
||||||
|
* compiling.
|
||||||
* <p>
|
* <p>
|
||||||
* Generally, this class is not used directly, but rather indirectly via a command
|
* Generally, this class is not used directly, but rather indirectly via a
|
||||||
* line interface tool such as {@link luac}.
|
* command line interface tool such as {@link luac}.
|
||||||
* <p>
|
* <p>
|
||||||
* A lua binary file is created via {@link DumpState#dump}:
|
* A lua binary file is created via {@link DumpState#dump}:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua");
|
* Prototype p = globals.compilePrototype(new StringReader("print('hello, world')"), "main.lua");
|
||||||
* ByteArrayOutputStream o = new ByteArrayOutputStream();
|
* ByteArrayOutputStream o = new ByteArrayOutputStream();
|
||||||
* DumpState.dump(p, o, false);
|
* DumpState.dump(p, o, false);
|
||||||
* byte[] lua_binary_file_bytes = o.toByteArray();
|
* byte[] lua_binary_file_bytes = o.toByteArray();
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* The {@link LoadState} may be used directly to undump these bytes:
|
* The {@link LoadState} may be used directly to undump these bytes:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <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
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
|
* Prototype p = globals.loadPrototype(new ByteArrayInputStream(lua_binary_file_bytes), "main.lua", "b");
|
||||||
* LuaClosure c = new LuaClosure(p, globals);
|
* LuaClosure c = new LuaClosure(p, globals);
|
||||||
* c.call();
|
* c.call();
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @see luac
|
* @see luac
|
||||||
* @see LoadState
|
* @see LoadState
|
||||||
@@ -72,13 +84,19 @@ public class DumpState {
|
|||||||
/** set true to allow integer compilation */
|
/** set true to allow integer compilation */
|
||||||
public static boolean ALLOW_INTEGER_CASTING = false;
|
public static boolean ALLOW_INTEGER_CASTING = false;
|
||||||
|
|
||||||
/** 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;
|
||||||
|
|
||||||
/** default number format */
|
/** default number format */
|
||||||
@@ -272,13 +290,17 @@ public class DumpState {
|
|||||||
* @param f the function to dump
|
* @param f the function to dump
|
||||||
* @param w the output stream to dump to
|
* @param w the output stream to dump to
|
||||||
* @param stripDebug true to strip debugging info, false otherwise
|
* @param stripDebug true to strip debugging info, false otherwise
|
||||||
* @param numberFormat one of NUMBER_FORMAT_FLOATS_OR_DOUBLES, NUMBER_FORMAT_INTS_ONLY, NUMBER_FORMAT_NUM_PATCH_INT32
|
* @param numberFormat one of NUMBER_FORMAT_FLOATS_OR_DOUBLES,
|
||||||
* @param littleendian true to use little endian for numbers, false for big endian
|
* NUMBER_FORMAT_INTS_ONLY,
|
||||||
|
* NUMBER_FORMAT_NUM_PATCH_INT32
|
||||||
|
* @param littleendian true to use little endian for numbers, false for big
|
||||||
|
* endian
|
||||||
* @return 0 if dump succeeds
|
* @return 0 if dump succeeds
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws IllegalArgumentException if the number format it not supported
|
* @throws IllegalArgumentException if the number format it not supported
|
||||||
*/
|
*/
|
||||||
public static int dump(Prototype f, OutputStream w, boolean stripDebug, int numberFormat, boolean littleendian) throws IOException {
|
public static int dump(Prototype f, OutputStream w, boolean stripDebug, int numberFormat, boolean littleendian)
|
||||||
|
throws IOException {
|
||||||
switch (numberFormat) {
|
switch (numberFormat) {
|
||||||
case NUMBER_FORMAT_FLOATS_OR_DOUBLES:
|
case NUMBER_FORMAT_FLOATS_OR_DOUBLES:
|
||||||
case NUMBER_FORMAT_INTS_ONLY:
|
case NUMBER_FORMAT_INTS_ONLY:
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import org.luaj.vm2.Upvaldesc;
|
|||||||
import org.luaj.vm2.compiler.LexState.ConsControl;
|
import org.luaj.vm2.compiler.LexState.ConsControl;
|
||||||
import org.luaj.vm2.compiler.LexState.expdesc;
|
import org.luaj.vm2.compiler.LexState.expdesc;
|
||||||
|
|
||||||
|
|
||||||
public class FuncState extends Constants {
|
public class FuncState extends Constants {
|
||||||
|
|
||||||
static class BlockCnt {
|
static class BlockCnt {
|
||||||
@@ -65,7 +64,6 @@ public class FuncState extends Constants {
|
|||||||
FuncState() {
|
FuncState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// from lcode.h
|
// from lcode.h
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@@ -86,7 +84,6 @@ public class FuncState extends Constants {
|
|||||||
setreturns(e, LUA_MULTRET);
|
setreturns(e, LUA_MULTRET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// from lparser.c
|
// from lparser.c
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@@ -96,14 +93,12 @@ public class FuncState extends Constants {
|
|||||||
int i;
|
int i;
|
||||||
for (i = bl.firstlabel; i < ll_n; i++) {
|
for (i = bl.firstlabel; i < ll_n; i++) {
|
||||||
if (label.eq_b(ll[i].name)) {
|
if (label.eq_b(ll[i].name)) {
|
||||||
String msg = ls.L.pushfstring(
|
String msg = ls.L.pushfstring("label '" + label + " already defined on line " + ll[i].line);
|
||||||
"label '" + label + " already defined on line " + ll[i].line);
|
|
||||||
ls.semerror(msg);
|
ls.semerror(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void checklimit(int v, int l, String msg) {
|
void checklimit(int v, int l, String msg) {
|
||||||
if (v > l)
|
if (v > l)
|
||||||
errorlimit(l, msg);
|
errorlimit(l, msg);
|
||||||
@@ -111,9 +106,8 @@ public class FuncState extends Constants {
|
|||||||
|
|
||||||
void errorlimit(int limit, String what) {
|
void errorlimit(int limit, String what) {
|
||||||
// TODO: report message logic.
|
// TODO: report message logic.
|
||||||
String msg = (f.linedefined == 0) ?
|
String msg = (f.linedefined == 0)? ls.L.pushfstring("main function has more than " + limit + " " + what)
|
||||||
ls.L.pushfstring("main function has more than "+limit+" "+what) :
|
: ls.L.pushfstring("function at line " + f.linedefined + " has more than " + limit + " " + what);
|
||||||
ls.L.pushfstring("function at line "+f.linedefined+" has more than "+limit+" "+what);
|
|
||||||
ls.lexerror(msg, 0);
|
ls.lexerror(msg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +123,6 @@ public class FuncState extends Constants {
|
|||||||
getlocvar(--nactvar).endpc = pc;
|
getlocvar(--nactvar).endpc = pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int searchupvalue(LuaString name) {
|
int searchupvalue(LuaString name) {
|
||||||
int i;
|
int i;
|
||||||
Upvaldesc[] up = f.upvalues;
|
Upvaldesc[] up = f.upvalues;
|
||||||
@@ -256,21 +249,22 @@ public class FuncState extends Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void lastlistfield(ConsControl cc) {
|
void lastlistfield(ConsControl cc) {
|
||||||
if (cc.tostore == 0) return;
|
if (cc.tostore == 0)
|
||||||
|
return;
|
||||||
if (hasmultret(cc.v.k)) {
|
if (hasmultret(cc.v.k)) {
|
||||||
this.setmultret(cc.v);
|
this.setmultret(cc.v);
|
||||||
this.setlist(cc.t.u.info, cc.na, LUA_MULTRET);
|
this.setlist(cc.t.u.info, cc.na, LUA_MULTRET);
|
||||||
cc.na--; /** do not count last expression (unknown number of elements) */
|
cc.na--; /**
|
||||||
}
|
* do not count last expression (unknown number of
|
||||||
else {
|
* elements)
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
if (cc.v.k != LexState.VVOID)
|
if (cc.v.k != LexState.VVOID)
|
||||||
this.exp2nextreg(cc.v);
|
this.exp2nextreg(cc.v);
|
||||||
this.setlist(cc.t.u.info, cc.na, cc.tostore);
|
this.setlist(cc.t.u.info, cc.na, cc.tostore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// from lcode.c
|
// from lcode.c
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@@ -282,8 +276,7 @@ public class FuncState extends Constants {
|
|||||||
if (GET_OPCODE(previous_code) == OP_LOADNIL) {
|
if (GET_OPCODE(previous_code) == OP_LOADNIL) {
|
||||||
int pfrom = GETARG_A(previous_code);
|
int pfrom = GETARG_A(previous_code);
|
||||||
int pl = pfrom+GETARG_B(previous_code);
|
int pl = pfrom+GETARG_B(previous_code);
|
||||||
if ((pfrom <= from && from <= pl + 1)
|
if ((pfrom <= from && from <= pl+1) || (from <= pfrom && pfrom <= l+1)) { /* can connect both? */
|
||||||
|| (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */
|
|
||||||
if (pfrom < from)
|
if (pfrom < from)
|
||||||
from = pfrom; /* from = min(from, pfrom) */
|
from = pfrom; /* from = min(from, pfrom) */
|
||||||
if (pl > l)
|
if (pl > l)
|
||||||
@@ -298,7 +291,6 @@ public class FuncState extends Constants {
|
|||||||
this.codeABC(OP_LOADNIL, from, n-1, 0);
|
this.codeABC(OP_LOADNIL, from, n-1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int jump() {
|
int jump() {
|
||||||
int jpc = this.jpc.i; /* save list of jumps to here */
|
int jpc = this.jpc.i; /* save list of jumps to here */
|
||||||
this.jpc.i = LexState.NO_JUMP;
|
this.jpc.i = LexState.NO_JUMP;
|
||||||
@@ -325,7 +317,6 @@ public class FuncState extends Constants {
|
|||||||
SETARG_sBx(jmp, offset);
|
SETARG_sBx(jmp, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* * returns current `pc' and marks it as a jump target (to avoid wrong *
|
* * returns current `pc' and marks it as a jump target (to avoid wrong *
|
||||||
* optimizations with consecutive instructions not in the same basic block).
|
* optimizations with consecutive instructions not in the same basic block).
|
||||||
@@ -335,7 +326,6 @@ public class FuncState extends Constants {
|
|||||||
return this.pc;
|
return this.pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int getjump(int pc) {
|
int getjump(int pc) {
|
||||||
int offset = GETARG_sBx(this.f.code[pc]);
|
int offset = GETARG_sBx(this.f.code[pc]);
|
||||||
/* point to itself represents end of list */
|
/* point to itself represents end of list */
|
||||||
@@ -347,7 +337,6 @@ public class FuncState extends Constants {
|
|||||||
return (pc+1)+offset;
|
return (pc+1)+offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
InstructionPtr getjumpcontrol(int pc) {
|
InstructionPtr getjumpcontrol(int pc) {
|
||||||
InstructionPtr pi = new InstructionPtr(this.f.code, pc);
|
InstructionPtr pi = new InstructionPtr(this.f.code, pc);
|
||||||
if (pc >= 1 && testTMode(GET_OPCODE(pi.code[pi.idx-1])))
|
if (pc >= 1 && testTMode(GET_OPCODE(pi.code[pi.idx-1])))
|
||||||
@@ -356,7 +345,6 @@ public class FuncState extends Constants {
|
|||||||
return pi;
|
return pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* * check whether list has any jump that do not produce a value * (or
|
* * check whether list has any jump that do not produce a value * (or
|
||||||
* produce an inverted value)
|
* produce an inverted value)
|
||||||
@@ -370,7 +358,6 @@ public class FuncState extends Constants {
|
|||||||
return false; /* not found */
|
return false; /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean patchtestreg(int node, int reg) {
|
boolean patchtestreg(int node, int reg) {
|
||||||
InstructionPtr i = this.getjumpcontrol(node);
|
InstructionPtr i = this.getjumpcontrol(node);
|
||||||
if (GET_OPCODE(i.get()) != OP_TESTSET)
|
if (GET_OPCODE(i.get()) != OP_TESTSET)
|
||||||
@@ -385,7 +372,6 @@ public class FuncState extends Constants {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void removevalues(int list) {
|
void removevalues(int list) {
|
||||||
for (; list != LexState.NO_JUMP; list = this.getjump(list))
|
for (; list != LexState.NO_JUMP; list = this.getjump(list))
|
||||||
this.patchtestreg(list, NO_REG);
|
this.patchtestreg(list, NO_REG);
|
||||||
@@ -420,8 +406,8 @@ public class FuncState extends Constants {
|
|||||||
level++; /* argument is +1 to reserve 0 as non-op */
|
level++; /* argument is +1 to reserve 0 as non-op */
|
||||||
while ( list != LexState.NO_JUMP ) {
|
while ( list != LexState.NO_JUMP ) {
|
||||||
int next = getjump(list);
|
int next = getjump(list);
|
||||||
_assert(GET_OPCODE(f.code[list]) == OP_JMP
|
_assert(
|
||||||
&& (GETARG_A(f.code[list]) == 0 || GETARG_A(f.code[list]) >= level));
|
GET_OPCODE(f.code[list]) == OP_JMP && (GETARG_A(f.code[list]) == 0 || GETARG_A(f.code[list]) >= level));
|
||||||
SETARG_A(f.code, list, level);
|
SETARG_A(f.code, list, level);
|
||||||
list = next;
|
list = next;
|
||||||
}
|
}
|
||||||
@@ -472,6 +458,7 @@ public class FuncState extends Constants {
|
|||||||
if (e.k == LexState.VNONRELOC)
|
if (e.k == LexState.VNONRELOC)
|
||||||
this.freereg(e.u.info);
|
this.freereg(e.u.info);
|
||||||
}
|
}
|
||||||
|
|
||||||
int addk(LuaValue v) {
|
int addk(LuaValue v) {
|
||||||
if (this.h == null) {
|
if (this.h == null) {
|
||||||
this.h = new Hashtable();
|
this.h = new Hashtable();
|
||||||
@@ -575,8 +562,7 @@ public class FuncState extends Constants {
|
|||||||
}
|
}
|
||||||
case LexState.VFALSE:
|
case LexState.VFALSE:
|
||||||
case LexState.VTRUE: {
|
case LexState.VTRUE: {
|
||||||
this.codeABC(OP_LOADBOOL, reg, (e.k == LexState.VTRUE ? 1 : 0),
|
this.codeABC(OP_LOADBOOL, reg, (e.k == LexState.VTRUE? 1: 0), 0);
|
||||||
0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LexState.VK: {
|
case LexState.VK: {
|
||||||
@@ -622,8 +608,7 @@ public class FuncState extends Constants {
|
|||||||
int p_f = LexState.NO_JUMP; /* position of an eventual LOAD false */
|
int p_f = LexState.NO_JUMP; /* position of an eventual LOAD false */
|
||||||
int p_t = LexState.NO_JUMP; /* position of an eventual LOAD true */
|
int p_t = LexState.NO_JUMP; /* position of an eventual LOAD true */
|
||||||
if (this.need_value(e.t.i) || this.need_value(e.f.i)) {
|
if (this.need_value(e.t.i) || this.need_value(e.f.i)) {
|
||||||
int fj = (e.k == LexState.VJMP) ? LexState.NO_JUMP : this
|
int fj = (e.k == LexState.VJMP)? LexState.NO_JUMP: this.jump();
|
||||||
.jump();
|
|
||||||
p_f = this.code_label(reg, 0, 1);
|
p_f = this.code_label(reg, 0, 1);
|
||||||
p_t = this.code_label(reg, 1, 0);
|
p_t = this.code_label(reg, 1, 0);
|
||||||
this.patchtohere(fj);
|
this.patchtohere(fj);
|
||||||
@@ -677,8 +662,7 @@ public class FuncState extends Constants {
|
|||||||
case LexState.VFALSE:
|
case LexState.VFALSE:
|
||||||
case LexState.VNIL: {
|
case LexState.VNIL: {
|
||||||
if (this.nk <= MAXINDEXRK) { /* constant fit in RK operand? */
|
if (this.nk <= MAXINDEXRK) { /* constant fit in RK operand? */
|
||||||
e.u.info = (e.k == LexState.VNIL) ? this.nilK()
|
e.u.info = (e.k == LexState.VNIL)? this.nilK(): this.boolK((e.k == LexState.VTRUE));
|
||||||
: this.boolK((e.k == LexState.VTRUE));
|
|
||||||
e.k = LexState.VK;
|
e.k = LexState.VK;
|
||||||
return RKASK(e.u.info);
|
return RKASK(e.u.info);
|
||||||
} else
|
} else
|
||||||
@@ -742,9 +726,8 @@ public class FuncState extends Constants {
|
|||||||
|
|
||||||
void invertjump(expdesc e) {
|
void invertjump(expdesc e) {
|
||||||
InstructionPtr pc = this.getjumpcontrol(e.u.info);
|
InstructionPtr pc = this.getjumpcontrol(e.u.info);
|
||||||
_assert (testTMode(GET_OPCODE(pc.get()))
|
_assert(testTMode(GET_OPCODE(pc.get())) && GET_OPCODE(pc.get()) != OP_TESTSET
|
||||||
&& GET_OPCODE(pc.get()) != OP_TESTSET && Lua
|
&& Lua.GET_OPCODE(pc.get()) != OP_TEST);
|
||||||
.GET_OPCODE(pc.get()) != OP_TEST);
|
|
||||||
// SETARG_A(pc, !(GETARG_A(pc.get())));
|
// SETARG_A(pc, !(GETARG_A(pc.get())));
|
||||||
int a = GETARG_A(pc.get());
|
int a = GETARG_A(pc.get());
|
||||||
int nota = (a != 0? 0: 1);
|
int nota = (a != 0? 0: 1);
|
||||||
@@ -915,8 +898,7 @@ public class FuncState extends Constants {
|
|||||||
if (constfolding(op, e1, e2))
|
if (constfolding(op, e1, e2))
|
||||||
return;
|
return;
|
||||||
else {
|
else {
|
||||||
int o2 = (op != OP_UNM && op != OP_LEN) ? this.exp2RK(e2)
|
int o2 = (op != OP_UNM && op != OP_LEN)? this.exp2RK(e2): 0;
|
||||||
: 0;
|
|
||||||
int o1 = this.exp2RK(e1);
|
int o1 = this.exp2RK(e1);
|
||||||
if (o1 > o2) {
|
if (o1 > o2) {
|
||||||
this.freeexp(e1);
|
this.freeexp(e1);
|
||||||
@@ -1004,7 +986,6 @@ public class FuncState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void posfix(int op, expdesc e1, expdesc e2, int line) {
|
void posfix(int op, expdesc e1, expdesc e2, int line) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case LexState.OPR_AND: {
|
case LexState.OPR_AND: {
|
||||||
@@ -1025,8 +1006,7 @@ public class FuncState extends Constants {
|
|||||||
}
|
}
|
||||||
case LexState.OPR_CONCAT: {
|
case LexState.OPR_CONCAT: {
|
||||||
this.exp2val(e2);
|
this.exp2val(e2);
|
||||||
if (e2.k == LexState.VRELOCABLE
|
if (e2.k == LexState.VRELOCABLE && GET_OPCODE(this.getcode(e2)) == OP_CONCAT) {
|
||||||
&& GET_OPCODE(this.getcode(e2)) == OP_CONCAT) {
|
|
||||||
_assert(e1.u.info == GETARG_B(this.getcode(e2))-1);
|
_assert(e1.u.info == GETARG_B(this.getcode(e2))-1);
|
||||||
this.freeexp(e1);
|
this.freeexp(e1);
|
||||||
SETARG_B(this.getcodePtr(e2), e1.u.info);
|
SETARG_B(this.getcodePtr(e2), e1.u.info);
|
||||||
@@ -1079,12 +1059,10 @@ public class FuncState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fixline(int line) {
|
void fixline(int line) {
|
||||||
this.f.lineinfo[this.pc-1] = line;
|
this.f.lineinfo[this.pc-1] = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int code(int instruction, int line) {
|
int code(int instruction, int line) {
|
||||||
Prototype f = this.f;
|
Prototype f = this.f;
|
||||||
this.dischargejpc(); /* `pc' will change */
|
this.dischargejpc(); /* `pc' will change */
|
||||||
@@ -1094,13 +1072,11 @@ public class FuncState extends Constants {
|
|||||||
f.code[this.pc] = instruction;
|
f.code[this.pc] = instruction;
|
||||||
/* save corresponding line information */
|
/* save corresponding line information */
|
||||||
if (f.lineinfo == null || this.pc+1 > f.lineinfo.length)
|
if (f.lineinfo == null || this.pc+1 > f.lineinfo.length)
|
||||||
f.lineinfo = LuaC.realloc(f.lineinfo,
|
f.lineinfo = LuaC.realloc(f.lineinfo, this.pc*2+1);
|
||||||
this.pc * 2 + 1);
|
|
||||||
f.lineinfo[this.pc] = line;
|
f.lineinfo[this.pc] = line;
|
||||||
return this.pc++;
|
return this.pc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int codeABC(int o, int a, int b, int c) {
|
int codeABC(int o, int a, int b, int c) {
|
||||||
_assert(getOpMode(o) == iABC);
|
_assert(getOpMode(o) == iABC);
|
||||||
_assert(getBMode(o) != OpArgN || b == 0);
|
_assert(getBMode(o) != OpArgN || b == 0);
|
||||||
@@ -1108,7 +1084,6 @@ public class FuncState extends Constants {
|
|||||||
return this.code(CREATE_ABC(o, a, b, c), this.ls.lastline);
|
return this.code(CREATE_ABC(o, a, b, c), this.ls.lastline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int codeABx(int o, int a, int bc) {
|
int codeABx(int o, int a, int bc) {
|
||||||
_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
|
_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
|
||||||
_assert(getCMode(o) == OpArgN);
|
_assert(getCMode(o) == OpArgN);
|
||||||
|
|||||||
@@ -24,13 +24,16 @@ package org.luaj.vm2.compiler;
|
|||||||
class InstructionPtr {
|
class InstructionPtr {
|
||||||
final int[] code;
|
final int[] code;
|
||||||
final int idx;
|
final int idx;
|
||||||
|
|
||||||
InstructionPtr(int[] code, int idx) {
|
InstructionPtr(int[] code, int idx) {
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.idx = idx;
|
this.idx = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get() {
|
int get() {
|
||||||
return code[idx];
|
return code[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(int value) {
|
void set(int value) {
|
||||||
code[idx] = value;
|
code[idx] = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,10 @@ package org.luaj.vm2.compiler;
|
|||||||
|
|
||||||
public class IntPtr {
|
public class IntPtr {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
IntPtr() {
|
IntPtr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
IntPtr(int value) {
|
IntPtr(int value) {
|
||||||
this.i = value;
|
this.i = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ import org.luaj.vm2.Prototype;
|
|||||||
import org.luaj.vm2.compiler.FuncState.BlockCnt;
|
import org.luaj.vm2.compiler.FuncState.BlockCnt;
|
||||||
import org.luaj.vm2.lib.MathLib;
|
import org.luaj.vm2.lib.MathLib;
|
||||||
|
|
||||||
|
|
||||||
public class LexState extends Constants {
|
public class LexState extends Constants {
|
||||||
|
|
||||||
protected static final String RESERVED_LOCAL_VAR_FOR_CONTROL = "(for control)";
|
protected static final String RESERVED_LOCAL_VAR_FOR_CONTROL = "(for control)";
|
||||||
@@ -46,14 +45,9 @@ public class LexState extends Constants {
|
|||||||
protected static final String RESERVED_LOCAL_VAR_FOR_INDEX = "(for index)";
|
protected static final String RESERVED_LOCAL_VAR_FOR_INDEX = "(for index)";
|
||||||
|
|
||||||
// keywords array
|
// keywords array
|
||||||
protected static final String[] RESERVED_LOCAL_VAR_KEYWORDS = new String[] {
|
protected static final String[] RESERVED_LOCAL_VAR_KEYWORDS = new String[] { RESERVED_LOCAL_VAR_FOR_CONTROL,
|
||||||
RESERVED_LOCAL_VAR_FOR_CONTROL,
|
RESERVED_LOCAL_VAR_FOR_GENERATOR, RESERVED_LOCAL_VAR_FOR_INDEX, RESERVED_LOCAL_VAR_FOR_LIMIT,
|
||||||
RESERVED_LOCAL_VAR_FOR_GENERATOR,
|
RESERVED_LOCAL_VAR_FOR_STATE, RESERVED_LOCAL_VAR_FOR_STEP };
|
||||||
RESERVED_LOCAL_VAR_FOR_INDEX,
|
|
||||||
RESERVED_LOCAL_VAR_FOR_LIMIT,
|
|
||||||
RESERVED_LOCAL_VAR_FOR_STATE,
|
|
||||||
RESERVED_LOCAL_VAR_FOR_STEP
|
|
||||||
};
|
|
||||||
private static final Hashtable RESERVED_LOCAL_VAR_KEYWORDS_TABLE = new Hashtable();
|
private static final Hashtable RESERVED_LOCAL_VAR_KEYWORDS_TABLE = new Hashtable();
|
||||||
static {
|
static {
|
||||||
for (int i = 0; i < RESERVED_LOCAL_VAR_KEYWORDS.length; i++)
|
for (int i = 0; i < RESERVED_LOCAL_VAR_KEYWORDS.length; i++)
|
||||||
@@ -66,6 +60,7 @@ public class LexState extends Constants {
|
|||||||
private static final int LUAI_MAXCCALLS = 200;
|
private static final int LUAI_MAXCCALLS = 200;
|
||||||
|
|
||||||
private static final String LUA_QS(String s) { return "'" + s + "'"; }
|
private static final String LUA_QS(String s) { return "'" + s + "'"; }
|
||||||
|
|
||||||
private static final String LUA_QL(Object o) { return LUA_QS(String.valueOf(o)); }
|
private static final String LUA_QL(Object o) { return LUA_QS(String.valueOf(o)); }
|
||||||
|
|
||||||
private static final int LUA_COMPAT_LSTR = 1; // 1 for compatibility, 2 for old behavior
|
private static final int LUA_COMPAT_LSTR = 1; // 1 for compatibility, 2 for old behavior
|
||||||
@@ -84,24 +79,15 @@ public class LexState extends Constants {
|
|||||||
/*
|
/*
|
||||||
** grep "ORDER OPR" if you change these enums
|
** grep "ORDER OPR" if you change these enums
|
||||||
*/
|
*/
|
||||||
static final int
|
static final int OPR_ADD = 0, OPR_SUB = 1, OPR_MUL = 2, OPR_DIV = 3, OPR_MOD = 4, OPR_POW = 5, OPR_CONCAT = 6,
|
||||||
OPR_ADD=0, OPR_SUB=1, OPR_MUL=2, OPR_DIV=3, OPR_MOD=4, OPR_POW=5,
|
OPR_NE = 7, OPR_EQ = 8, OPR_LT = 9, OPR_LE = 10, OPR_GT = 11, OPR_GE = 12, OPR_AND = 13, OPR_OR = 14,
|
||||||
OPR_CONCAT=6,
|
|
||||||
OPR_NE=7, OPR_EQ=8,
|
|
||||||
OPR_LT=9, OPR_LE=10, OPR_GT=11, OPR_GE=12,
|
|
||||||
OPR_AND=13, OPR_OR=14,
|
|
||||||
OPR_NOBINOPR = 15;
|
OPR_NOBINOPR = 15;
|
||||||
|
|
||||||
static final int
|
static final int OPR_MINUS = 0, OPR_NOT = 1, OPR_LEN = 2, OPR_NOUNOPR = 3;
|
||||||
OPR_MINUS=0, OPR_NOT=1, OPR_LEN=2, OPR_NOUNOPR=3;
|
|
||||||
|
|
||||||
/* exp kind */
|
/* exp kind */
|
||||||
static final int
|
static final int VVOID = 0, /* no value */
|
||||||
VVOID = 0, /* no value */
|
VNIL = 1, VTRUE = 2, VFALSE = 3, VK = 4, /* info = index of constant in `k' */
|
||||||
VNIL = 1,
|
|
||||||
VTRUE = 2,
|
|
||||||
VFALSE = 3,
|
|
||||||
VK = 4, /* info = index of constant in `k' */
|
|
||||||
VKNUM = 5, /* nval = numerical value */
|
VKNUM = 5, /* nval = numerical value */
|
||||||
VNONRELOC = 6, /* info = result register */
|
VNONRELOC = 6, /* info = result register */
|
||||||
VLOCAL = 7, /* info = local register */
|
VLOCAL = 7, /* info = local register */
|
||||||
@@ -121,6 +107,7 @@ public class LexState extends Constants {
|
|||||||
private static class Token {
|
private static class Token {
|
||||||
int token;
|
int token;
|
||||||
final SemInfo seminfo = new SemInfo();
|
final SemInfo seminfo = new SemInfo();
|
||||||
|
|
||||||
public void set(Token other) {
|
public void set(Token other) {
|
||||||
this.token = other.token;
|
this.token = other.token;
|
||||||
this.seminfo.r = other.seminfo.r;
|
this.seminfo.r = other.seminfo.r;
|
||||||
@@ -144,24 +131,19 @@ public class LexState extends Constants {
|
|||||||
byte decpoint; /* locale decimal point */
|
byte decpoint; /* locale decimal point */
|
||||||
|
|
||||||
/* ORDER RESERVED */
|
/* ORDER RESERVED */
|
||||||
final static String luaX_tokens [] = {
|
final static String luaX_tokens[] = { "and", "break", "do", "else", "elseif", "end", "false", "for", "function",
|
||||||
"and", "break", "do", "else", "elseif",
|
"goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "..",
|
||||||
"end", "false", "for", "function", "goto", "if",
|
"...", "==", ">=", "<=", "~=", "::", "<eos>", "<number>", "<name>", "<string>", "<eof>", };
|
||||||
"in", "local", "nil", "not", "or", "repeat",
|
|
||||||
"return", "then", "true", "until", "while",
|
|
||||||
"..", "...", "==", ">=", "<=", "~=",
|
|
||||||
"::", "<eos>", "<number>", "<name>", "<string>", "<eof>",
|
|
||||||
};
|
|
||||||
|
|
||||||
final static int
|
final static int
|
||||||
/* terminal symbols denoted by reserved words */
|
/* terminal symbols denoted by reserved words */
|
||||||
TK_AND=257, TK_BREAK=258, TK_DO=259, TK_ELSE=260, TK_ELSEIF=261,
|
TK_AND = 257, TK_BREAK = 258, TK_DO = 259, TK_ELSE = 260, TK_ELSEIF = 261, TK_END = 262, TK_FALSE = 263,
|
||||||
TK_END=262, TK_FALSE=263, TK_FOR=264, TK_FUNCTION=265, TK_GOTO=266, TK_IF=267,
|
TK_FOR = 264, TK_FUNCTION = 265, TK_GOTO = 266, TK_IF = 267, TK_IN = 268, TK_LOCAL = 269, TK_NIL = 270,
|
||||||
TK_IN=268, TK_LOCAL=269, TK_NIL=270, TK_NOT=271, TK_OR=272, TK_REPEAT=273,
|
TK_NOT = 271, TK_OR = 272, TK_REPEAT = 273, TK_RETURN = 274, TK_THEN = 275, TK_TRUE = 276, TK_UNTIL = 277,
|
||||||
TK_RETURN=274, TK_THEN=275, TK_TRUE=276, TK_UNTIL=277, TK_WHILE=278,
|
TK_WHILE = 278,
|
||||||
/* other terminal symbols */
|
/* other terminal symbols */
|
||||||
TK_CONCAT=279, TK_DOTS=280, TK_EQ=281, TK_GE=282, TK_LE=283, TK_NE=284,
|
TK_CONCAT = 279, TK_DOTS = 280, TK_EQ = 281, TK_GE = 282, TK_LE = 283, TK_NE = 284, TK_DBCOLON = 285,
|
||||||
TK_DBCOLON=285, TK_EOS=286, TK_NUMBER=287, TK_NAME=288, TK_STRING=289;
|
TK_EOS = 286, TK_NUMBER = 287, TK_NAME = 288, TK_STRING = 289;
|
||||||
|
|
||||||
final static int FIRST_RESERVED = TK_AND;
|
final static int FIRST_RESERVED = TK_AND;
|
||||||
final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED;
|
final static int NUM_RESERVED = TK_WHILE+1-FIRST_RESERVED;
|
||||||
@@ -175,16 +157,12 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isalnum(int c) {
|
private boolean isalnum(int c) {
|
||||||
return (c >= '0' && c <= '9')
|
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_');
|
||||||
|| (c >= 'a' && c <= 'z')
|
|
||||||
|| (c >= 'A' && c <= 'Z')
|
|
||||||
|| (c == '_');
|
|
||||||
// return Character.isLetterOrDigit(c);
|
// return Character.isLetterOrDigit(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isalpha(int c) {
|
private boolean isalpha(int c) {
|
||||||
return (c >= 'a' && c <= 'z')
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||||||
|| (c >= 'A' && c <= 'Z');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isdigit(int c) {
|
private boolean isdigit(int c) {
|
||||||
@@ -192,16 +170,13 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isxdigit(int c) {
|
private boolean isxdigit(int c) {
|
||||||
return (c >= '0' && c <= '9')
|
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
|
||||||
|| (c >= 'a' && c <= 'f')
|
|
||||||
|| (c >= 'A' && c <= 'F');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isspace(int c) {
|
private boolean isspace(int c) {
|
||||||
return (c >= 0 && c <= ' ');
|
return (c >= 0 && c <= ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public LexState(LuaC.CompileState state, InputStream stream) {
|
public LexState(LuaC.CompileState state, InputStream stream) {
|
||||||
this.z = stream;
|
this.z = stream;
|
||||||
this.buff = new char[32];
|
this.buff = new char[32];
|
||||||
@@ -232,12 +207,10 @@ public class LexState extends Constants {
|
|||||||
buff[nbuff++] = (char) c;
|
buff[nbuff++] = (char) c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String token2str(int token) {
|
String token2str(int token) {
|
||||||
if (token < FIRST_RESERVED) {
|
if (token < FIRST_RESERVED) {
|
||||||
return iscntrl(token)?
|
return iscntrl(token)? L.pushfstring("char(" + ((int) token) + ")")
|
||||||
L.pushfstring( "char("+((int)token)+")" ):
|
: L.pushfstring(String.valueOf((char) token));
|
||||||
L.pushfstring( String.valueOf( (char) token ) );
|
|
||||||
} else {
|
} else {
|
||||||
return luaX_tokens[token-FIRST_RESERVED];
|
return luaX_tokens[token-FIRST_RESERVED];
|
||||||
}
|
}
|
||||||
@@ -310,15 +283,12 @@ public class LexState extends Constants {
|
|||||||
nextChar();
|
nextChar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** =======================================================
|
** =======================================================
|
||||||
** LEXICAL ANALYZER
|
** LEXICAL ANALYZER
|
||||||
** =======================================================
|
** =======================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
boolean check_next(String set) {
|
boolean check_next(String set) {
|
||||||
if (set.indexOf(current) < 0)
|
if (set.indexOf(current) < 0)
|
||||||
return false;
|
return false;
|
||||||
@@ -437,8 +407,7 @@ public class LexState extends Constants {
|
|||||||
for (boolean endloop = false; !endloop;) {
|
for (boolean endloop = false; !endloop;) {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
case EOZ:
|
case EOZ:
|
||||||
lexerror((seminfo != null) ? "unfinished long string"
|
lexerror((seminfo != null)? "unfinished long string": "unfinished long comment", TK_EOS);
|
||||||
: "unfinished long comment", TK_EOS);
|
|
||||||
break; /* to avoid warnings */
|
break; /* to avoid warnings */
|
||||||
case '[': {
|
case '[': {
|
||||||
if (skip_sep() == sep) {
|
if (skip_sep() == sep) {
|
||||||
@@ -546,8 +515,10 @@ public class LexState extends Constants {
|
|||||||
case 'z': { /* zap following span of spaces */
|
case 'z': { /* zap following span of spaces */
|
||||||
nextChar(); /* skip the 'z' */
|
nextChar(); /* skip the 'z' */
|
||||||
while ( isspace(current) ) {
|
while ( isspace(current) ) {
|
||||||
if (currIsNewline()) inclinenumber();
|
if (currIsNewline())
|
||||||
else nextChar();
|
inclinenumber();
|
||||||
|
else
|
||||||
|
nextChar();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -690,8 +661,16 @@ public class LexState extends Constants {
|
|||||||
return TK_NUMBER;
|
return TK_NUMBER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0':
|
||||||
case '5': case '6': case '7': case '8': case '9': {
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9': {
|
||||||
read_numeral(seminfo);
|
read_numeral(seminfo);
|
||||||
return TK_NUMBER;
|
return TK_NUMBER;
|
||||||
}
|
}
|
||||||
@@ -740,7 +719,6 @@ public class LexState extends Constants {
|
|||||||
// from lcode.h
|
// from lcode.h
|
||||||
// =============================================================
|
// =============================================================
|
||||||
|
|
||||||
|
|
||||||
// =============================================================
|
// =============================================================
|
||||||
// from lparser.c
|
// from lparser.c
|
||||||
// =============================================================
|
// =============================================================
|
||||||
@@ -755,22 +733,25 @@ public class LexState extends Constants {
|
|||||||
|
|
||||||
static class expdesc {
|
static class expdesc {
|
||||||
int k; // expkind, from enumerated list, above
|
int k; // expkind, from enumerated list, above
|
||||||
|
|
||||||
static class U { // originally a union
|
static class U { // originally a union
|
||||||
short ind_idx; // index (R/K)
|
short ind_idx; // index (R/K)
|
||||||
short ind_t; // table(register or upvalue)
|
short ind_t; // table(register or upvalue)
|
||||||
short ind_vt; // whether 't' is register (VLOCAL) or (UPVALUE)
|
short ind_vt; // whether 't' is register (VLOCAL) or (UPVALUE)
|
||||||
private LuaValue _nval;
|
private LuaValue _nval;
|
||||||
int info;
|
int info;
|
||||||
public void setNval(LuaValue r) {
|
|
||||||
_nval = r;
|
public void setNval(LuaValue r) { _nval = r; }
|
||||||
}
|
|
||||||
public LuaValue nval() {
|
public LuaValue nval() {
|
||||||
return (_nval == null? LuaInteger.valueOf(info): _nval);
|
return (_nval == null? LuaInteger.valueOf(info): _nval);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
final U u = new U();
|
final U u = new U();
|
||||||
final IntPtr t = new IntPtr(); /* patch list of `exit when true' */
|
final IntPtr t = new IntPtr(); /* patch list of `exit when true' */
|
||||||
final IntPtr f = new IntPtr(); /* patch list of `exit when false' */
|
final IntPtr f = new IntPtr(); /* patch list of `exit when false' */
|
||||||
|
|
||||||
void init(int k, int i) {
|
void init(int k, int i) {
|
||||||
this.f.i = NO_JUMP;
|
this.f.i = NO_JUMP;
|
||||||
this.t.i = NO_JUMP;
|
this.t.i = NO_JUMP;
|
||||||
@@ -798,22 +779,22 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* description of active local variable */
|
/* description of active local variable */
|
||||||
static class Vardesc {
|
static class Vardesc {
|
||||||
final short idx; /* variable index in stack */
|
final short idx; /* variable index in stack */
|
||||||
|
|
||||||
Vardesc(int idx) {
|
Vardesc(int idx) {
|
||||||
this.idx = (short) idx;
|
this.idx = (short) idx;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* description of pending goto statements and label statements */
|
/* description of pending goto statements and label statements */
|
||||||
static class Labeldesc {
|
static class Labeldesc {
|
||||||
LuaString name; /* label identifier */
|
LuaString name; /* label identifier */
|
||||||
int pc; /* position in code */
|
int pc; /* position in code */
|
||||||
int line; /* line where it appeared */
|
int line; /* line where it appeared */
|
||||||
short nactvar; /* local level where it appears in current block */
|
short nactvar; /* local level where it appears in current block */
|
||||||
|
|
||||||
public Labeldesc(LuaString name, int pc, int line, short nactvar) {
|
public Labeldesc(LuaString name, int pc, int line, short nactvar) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.pc = pc;
|
this.pc = pc;
|
||||||
@@ -822,7 +803,6 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* dynamic structures used by the parser */
|
/* dynamic structures used by the parser */
|
||||||
static class Dyndata {
|
static class Dyndata {
|
||||||
Vardesc[] actvar; /* list of active local variables */
|
Vardesc[] actvar; /* list of active local variables */
|
||||||
@@ -833,7 +813,6 @@ public class LexState extends Constants {
|
|||||||
int n_label = 0;
|
int n_label = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
boolean hasmultret(int k) {
|
boolean hasmultret(int k) {
|
||||||
return ((k) == VCALL || (k) == VVARARG);
|
return ((k) == VCALL || (k) == VVARARG);
|
||||||
}
|
}
|
||||||
@@ -885,14 +864,12 @@ public class LexState extends Constants {
|
|||||||
syntaxerror(msg);
|
syntaxerror(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_match(int what, int who, int where) {
|
void check_match(int what, int who, int where) {
|
||||||
if (!testnext(what)) {
|
if (!testnext(what)) {
|
||||||
if (where == linenumber)
|
if (where == linenumber)
|
||||||
error_expected(what);
|
error_expected(what);
|
||||||
else {
|
else {
|
||||||
syntaxerror(L.pushfstring(LUA_QS(token2str(what))
|
syntaxerror(L.pushfstring(LUA_QS(token2str(what)) + " expected " + "(to close " + LUA_QS(token2str(who))
|
||||||
+ " expected " + "(to close " + LUA_QS(token2str(who))
|
|
||||||
+ " at line " + where + ")"));
|
+ " at line " + where + ")"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -914,7 +891,6 @@ public class LexState extends Constants {
|
|||||||
codestring(e, str_checkname());
|
codestring(e, str_checkname());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int registerlocalvar(LuaString varname) {
|
int registerlocalvar(LuaString varname) {
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
Prototype f = fs.f;
|
Prototype f = fs.f;
|
||||||
@@ -1003,8 +979,7 @@ public class LexState extends Constants {
|
|||||||
_assert(gt.name.eq_b(label.name));
|
_assert(gt.name.eq_b(label.name));
|
||||||
if (gt.nactvar < label.nactvar) {
|
if (gt.nactvar < label.nactvar) {
|
||||||
LuaString vname = fs.getlocvar(gt.nactvar).varname;
|
LuaString vname = fs.getlocvar(gt.nactvar).varname;
|
||||||
String msg = L.pushfstring("<goto " + gt.name + "> at line "
|
String msg = L.pushfstring("<goto " + gt.name + "> at line " + gt.line + " jumps into the scope of local '"
|
||||||
+ gt.line + " jumps into the scope of local '"
|
|
||||||
+ vname.tojstring() + "'");
|
+ vname.tojstring() + "'");
|
||||||
semerror(msg);
|
semerror(msg);
|
||||||
}
|
}
|
||||||
@@ -1026,8 +1001,7 @@ public class LexState extends Constants {
|
|||||||
for (i = bl.firstlabel; i < dyd.n_label; i++) {
|
for (i = bl.firstlabel; i < dyd.n_label; i++) {
|
||||||
Labeldesc lb = dyd.label[i];
|
Labeldesc lb = dyd.label[i];
|
||||||
if (lb.name.eq_b(gt.name)) { /* correct label? */
|
if (lb.name.eq_b(gt.name)) { /* correct label? */
|
||||||
if (gt.nactvar > lb.nactvar &&
|
if (gt.nactvar > lb.nactvar && (bl.upval || dyd.n_label > bl.firstlabel))
|
||||||
(bl.upval || dyd.n_label > bl.firstlabel))
|
|
||||||
fs.patchclose(gt.pc, lb.nactvar);
|
fs.patchclose(gt.pc, lb.nactvar);
|
||||||
closegoto(g, lb); /* close it */
|
closegoto(g, lb); /* close it */
|
||||||
return true;
|
return true;
|
||||||
@@ -1057,7 +1031,6 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** create a label named "break" to resolve break statements
|
** create a label named "break" to resolve break statements
|
||||||
*/
|
*/
|
||||||
@@ -1072,8 +1045,8 @@ public class LexState extends Constants {
|
|||||||
** message when label name is a reserved word (which can only be 'break')
|
** message when label name is a reserved word (which can only be 'break')
|
||||||
*/
|
*/
|
||||||
void undefgoto(Labeldesc gt) {
|
void undefgoto(Labeldesc gt) {
|
||||||
String msg = L.pushfstring(isReservedKeyword(gt.name.tojstring())
|
String msg = L.pushfstring(
|
||||||
? "<"+gt.name+"> at line "+gt.line+" not inside a loop"
|
isReservedKeyword(gt.name.tojstring())? "<" + gt.name + "> at line " + gt.line + " not inside a loop"
|
||||||
: "no visible label '" + gt.name + "' for <goto> at line " + gt.line);
|
: "no visible label '" + gt.name + "' for <goto> at line " + gt.line);
|
||||||
semerror(msg);
|
semerror(msg);
|
||||||
}
|
}
|
||||||
@@ -1153,14 +1126,12 @@ public class LexState extends Constants {
|
|||||||
this.checknext(']');
|
this.checknext(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** {======================================================================
|
** {======================================================================
|
||||||
** Rules for Constructors
|
** Rules for Constructors
|
||||||
** =======================================================================
|
** =======================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static class ConsControl {
|
static class ConsControl {
|
||||||
expdesc v = new expdesc(); /* last list item read */
|
expdesc v = new expdesc(); /* last list item read */
|
||||||
expdesc t; /* table descriptor */
|
expdesc t; /* table descriptor */
|
||||||
@@ -1169,7 +1140,6 @@ public class LexState extends Constants {
|
|||||||
int tostore; /* number of array elements pending to be stored */
|
int tostore; /* number of array elements pending to be stored */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void recfield(ConsControl cc) {
|
void recfield(ConsControl cc) {
|
||||||
/* recfield -> (NAME | `['exp1`]') = exp1 */
|
/* recfield -> (NAME | `['exp1`]') = exp1 */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -1198,7 +1168,6 @@ public class LexState extends Constants {
|
|||||||
cc.tostore++;
|
cc.tostore++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void constructor(expdesc t) {
|
void constructor(expdesc t) {
|
||||||
/* constructor -> ?? */
|
/* constructor -> ?? */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -1253,11 +1222,12 @@ public class LexState extends Constants {
|
|||||||
x = (x+1)>>1;
|
x = (x+1)>>1;
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
if (x < 8) return x;
|
if (x < 8)
|
||||||
else return ((e+1) << 3) | (((int)x) - 8);
|
return x;
|
||||||
|
else
|
||||||
|
return ((e+1)<<3) | (((int) x)-8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* }====================================================================== */
|
/* }====================================================================== */
|
||||||
|
|
||||||
void parlist() {
|
void parlist() {
|
||||||
@@ -1279,7 +1249,8 @@ public class LexState extends Constants {
|
|||||||
f.is_vararg = 1;
|
f.is_vararg = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: this.syntaxerror("<name> or " + LUA_QL("...") + " expected");
|
default:
|
||||||
|
this.syntaxerror("<name> or " + LUA_QL("...") + " expected");
|
||||||
}
|
}
|
||||||
} while ( (f.is_vararg == 0) && this.testnext(',') );
|
} while ( (f.is_vararg == 0) && this.testnext(',') );
|
||||||
}
|
}
|
||||||
@@ -1288,7 +1259,6 @@ public class LexState extends Constants {
|
|||||||
fs.reserveregs(fs.nactvar); /* reserve register for parameters */
|
fs.reserveregs(fs.nactvar); /* reserve register for parameters */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void body(expdesc e, boolean needself, int line) {
|
void body(expdesc e, boolean needself, int line) {
|
||||||
/* body -> `(' parlist `)' chunk END */
|
/* body -> `(' parlist `)' chunk END */
|
||||||
FuncState new_fs = new FuncState();
|
FuncState new_fs = new FuncState();
|
||||||
@@ -1322,7 +1292,6 @@ public class LexState extends Constants {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void funcargs(expdesc f, int line) {
|
void funcargs(expdesc f, int line) {
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
expdesc args = new expdesc();
|
expdesc args = new expdesc();
|
||||||
@@ -1368,7 +1337,6 @@ public class LexState extends Constants {
|
|||||||
* (unless changed) one result */
|
* (unless changed) one result */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** {======================================================================
|
** {======================================================================
|
||||||
** Expression parsing
|
** Expression parsing
|
||||||
@@ -1397,7 +1365,6 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void suffixedexp(expdesc v) {
|
void suffixedexp(expdesc v) {
|
||||||
/* suffixedexp ->
|
/* suffixedexp ->
|
||||||
primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
|
primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
|
||||||
@@ -1437,7 +1404,6 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void simpleexp(expdesc v) {
|
void simpleexp(expdesc v) {
|
||||||
/*
|
/*
|
||||||
* simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor |
|
* simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor |
|
||||||
@@ -1467,8 +1433,7 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
case TK_DOTS: { /* vararg */
|
case TK_DOTS: { /* vararg */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
this.check_condition(fs.f.is_vararg!=0, "cannot use " + LUA_QL("...")
|
this.check_condition(fs.f.is_vararg != 0, "cannot use " + LUA_QL("...") + " outside a vararg function");
|
||||||
+ " outside a vararg function");
|
|
||||||
v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0));
|
v.init(VVARARG, fs.codeABC(Lua.OP_VARARG, 0, 1, 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1489,7 +1454,6 @@ public class LexState extends Constants {
|
|||||||
this.next();
|
this.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int getunopr(int op) {
|
int getunopr(int op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case TK_NOT:
|
case TK_NOT:
|
||||||
@@ -1503,7 +1467,6 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int getbinopr(int op) {
|
int getbinopr(int op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case '+':
|
case '+':
|
||||||
@@ -1553,7 +1516,8 @@ public class LexState extends Constants {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static Priority[] priority = { /* ORDER OPR */
|
static Priority[] priority = { /* ORDER OPR */
|
||||||
new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7), new Priority(7, 7), /* `+' `-' `/' `%' */
|
new Priority(6, 6), new Priority(6, 6), new Priority(7, 7), new Priority(7, 7),
|
||||||
|
new Priority(7, 7), /* `+' `-' `/' `%' */
|
||||||
new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */
|
new Priority(10, 9), new Priority(5, 4), /* power and concat (right associative) */
|
||||||
new Priority(3, 3), new Priority(3, 3), /* equality and inequality */
|
new Priority(3, 3), new Priority(3, 3), /* equality and inequality */
|
||||||
new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */
|
new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), new Priority(3, 3), /* order */
|
||||||
@@ -1562,7 +1526,6 @@ public class LexState extends Constants {
|
|||||||
|
|
||||||
static final int UNARY_PRIORITY = 8; /* priority for unary operators */
|
static final int UNARY_PRIORITY = 8; /* priority for unary operators */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
|
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
|
||||||
** where `binop' is any binary operator with a priority higher than `limit'
|
** where `binop' is any binary operator with a priority higher than `limit'
|
||||||
@@ -1601,26 +1564,26 @@ public class LexState extends Constants {
|
|||||||
|
|
||||||
/* }==================================================================== */
|
/* }==================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** {======================================================================
|
** {======================================================================
|
||||||
** Rules for Statements
|
** Rules for Statements
|
||||||
** =======================================================================
|
** =======================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
boolean block_follow(boolean withuntil) {
|
boolean block_follow(boolean withuntil) {
|
||||||
switch (t.token) {
|
switch (t.token) {
|
||||||
case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_EOS:
|
case TK_ELSE:
|
||||||
|
case TK_ELSEIF:
|
||||||
|
case TK_END:
|
||||||
|
case TK_EOS:
|
||||||
return true;
|
return true;
|
||||||
case TK_UNTIL:
|
case TK_UNTIL:
|
||||||
return withuntil;
|
return withuntil;
|
||||||
default: return false;
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void block() {
|
void block() {
|
||||||
/* block -> chunk */
|
/* block -> chunk */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -1630,7 +1593,6 @@ public class LexState extends Constants {
|
|||||||
fs.leaveblock();
|
fs.leaveblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** structure to chain all variables in the left-hand side of an
|
** structure to chain all variables in the left-hand side of an
|
||||||
** assignment
|
** assignment
|
||||||
@@ -1641,7 +1603,6 @@ public class LexState extends Constants {
|
|||||||
expdesc v = new expdesc();
|
expdesc v = new expdesc();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** check whether, in an assignment to a local variable, the local variable
|
** check whether, in an assignment to a local variable, the local variable
|
||||||
** is needed in a previous assignment (to a table). If so, save original
|
** is needed in a previous assignment (to a table). If so, save original
|
||||||
@@ -1675,11 +1636,9 @@ public class LexState extends Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void assignment(LHS_assign lh, int nvars) {
|
void assignment(LHS_assign lh, int nvars) {
|
||||||
expdesc e = new expdesc();
|
expdesc e = new expdesc();
|
||||||
this.check_condition(VLOCAL <= lh.v.k && lh.v.k <= VINDEXED,
|
this.check_condition(VLOCAL <= lh.v.k && lh.v.k <= VINDEXED, "syntax error");
|
||||||
"syntax error");
|
|
||||||
if (this.testnext(',')) { /* assignment -> `,' primaryexp assignment */
|
if (this.testnext(',')) { /* assignment -> `,' primaryexp assignment */
|
||||||
LHS_assign nv = new LHS_assign();
|
LHS_assign nv = new LHS_assign();
|
||||||
nv.prev = lh;
|
nv.prev = lh;
|
||||||
@@ -1687,8 +1646,7 @@ public class LexState extends Constants {
|
|||||||
if (nv.v.k != VINDEXED)
|
if (nv.v.k != VINDEXED)
|
||||||
this.check_conflict(lh, nv.v);
|
this.check_conflict(lh, nv.v);
|
||||||
this.assignment(nv, nvars+1);
|
this.assignment(nv, nvars+1);
|
||||||
}
|
} else { /* assignment . `=' explist1 */
|
||||||
else { /* assignment . `=' explist1 */
|
|
||||||
int nexps;
|
int nexps;
|
||||||
this.checknext('=');
|
this.checknext('=');
|
||||||
nexps = this.explist(e);
|
nexps = this.explist(e);
|
||||||
@@ -1696,8 +1654,7 @@ public class LexState extends Constants {
|
|||||||
this.adjust_assign(nvars, nexps, e);
|
this.adjust_assign(nvars, nexps, e);
|
||||||
if (nexps > nvars)
|
if (nexps > nvars)
|
||||||
this.fs.freereg -= nexps-nvars; /* remove extra values */
|
this.fs.freereg -= nexps-nvars; /* remove extra values */
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
fs.setoneret(e); /* close last expression */
|
fs.setoneret(e); /* close last expression */
|
||||||
fs.storevar(lh.v, e);
|
fs.storevar(lh.v, e);
|
||||||
return; /* avoid default */
|
return; /* avoid default */
|
||||||
@@ -1707,7 +1664,6 @@ public class LexState extends Constants {
|
|||||||
fs.storevar(lh.v, e);
|
fs.storevar(lh.v, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int cond() {
|
int cond() {
|
||||||
/* cond -> exp */
|
/* cond -> exp */
|
||||||
expdesc v = new expdesc();
|
expdesc v = new expdesc();
|
||||||
@@ -1734,14 +1690,12 @@ public class LexState extends Constants {
|
|||||||
findlabel(g); /* close it if label already defined */
|
findlabel(g); /* close it if label already defined */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* skip no-op statements */
|
/* skip no-op statements */
|
||||||
void skipnoopstat() {
|
void skipnoopstat() {
|
||||||
while ( t.token == ';' || t.token == TK_DBCOLON )
|
while ( t.token == ';' || t.token == TK_DBCOLON )
|
||||||
statement();
|
statement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void labelstat(LuaString label, int line) {
|
void labelstat(LuaString label, int line) {
|
||||||
/* label -> '::' NAME '::' */
|
/* label -> '::' NAME '::' */
|
||||||
int l; /* index of new label being created */
|
int l; /* index of new label being created */
|
||||||
@@ -1757,7 +1711,6 @@ public class LexState extends Constants {
|
|||||||
findgotos(dyd.label[l]);
|
findgotos(dyd.label[l]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void whilestat(int line) {
|
void whilestat(int line) {
|
||||||
/* whilestat -> WHILE cond DO block END */
|
/* whilestat -> WHILE cond DO block END */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -1797,7 +1750,6 @@ public class LexState extends Constants {
|
|||||||
fs.leaveblock(); /* finish loop */
|
fs.leaveblock(); /* finish loop */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int exp1() {
|
int exp1() {
|
||||||
expdesc e = new expdesc();
|
expdesc e = new expdesc();
|
||||||
int k;
|
int k;
|
||||||
@@ -1807,7 +1759,6 @@ public class LexState extends Constants {
|
|||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void forbody(int base, int line, int nvars, boolean isnum) {
|
void forbody(int base, int line, int nvars, boolean isnum) {
|
||||||
/* forbody -> DO block */
|
/* forbody -> DO block */
|
||||||
BlockCnt bl = new BlockCnt();
|
BlockCnt bl = new BlockCnt();
|
||||||
@@ -1833,7 +1784,6 @@ public class LexState extends Constants {
|
|||||||
fs.fixline(line);
|
fs.fixline(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fornum(LuaString varname, int line) {
|
void fornum(LuaString varname, int line) {
|
||||||
/* fornum -> NAME = exp1,exp1[,exp1] forbody */
|
/* fornum -> NAME = exp1,exp1[,exp1] forbody */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -1855,7 +1805,6 @@ public class LexState extends Constants {
|
|||||||
this.forbody(base, line, 1, true);
|
this.forbody(base, line, 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void forlist(LuaString indexname) {
|
void forlist(LuaString indexname) {
|
||||||
/* forlist -> NAME {,NAME} IN explist1 forbody */
|
/* forlist -> NAME {,NAME} IN explist1 forbody */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -1880,7 +1829,6 @@ public class LexState extends Constants {
|
|||||||
this.forbody(base, line, nvars-3, false);
|
this.forbody(base, line, nvars-3, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void forstat(int line) {
|
void forstat(int line) {
|
||||||
/* forstat -> FOR (fornum | forlist) END */
|
/* forstat -> FOR (fornum | forlist) END */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -1904,7 +1852,6 @@ public class LexState extends Constants {
|
|||||||
fs.leaveblock(); /* loop scope (`break' jumps to this point) */
|
fs.leaveblock(); /* loop scope (`break' jumps to this point) */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void test_then_block(IntPtr escapelist) {
|
void test_then_block(IntPtr escapelist) {
|
||||||
/* test_then_block -> [IF | ELSEIF] cond THEN block */
|
/* test_then_block -> [IF | ELSEIF] cond THEN block */
|
||||||
expdesc v = new expdesc();
|
expdesc v = new expdesc();
|
||||||
@@ -1936,7 +1883,6 @@ public class LexState extends Constants {
|
|||||||
fs.patchtohere(jf);
|
fs.patchtohere(jf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ifstat(int line) {
|
void ifstat(int line) {
|
||||||
IntPtr escapelist = new IntPtr(NO_JUMP); /* exit list for finished parts */
|
IntPtr escapelist = new IntPtr(NO_JUMP); /* exit list for finished parts */
|
||||||
test_then_block(escapelist); /* IF cond THEN block */
|
test_then_block(escapelist); /* IF cond THEN block */
|
||||||
@@ -1958,7 +1904,6 @@ public class LexState extends Constants {
|
|||||||
fs.getlocvar(fs.nactvar-1).startpc = fs.pc;
|
fs.getlocvar(fs.nactvar-1).startpc = fs.pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void localstat() {
|
void localstat() {
|
||||||
/* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
|
/* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */
|
||||||
int nvars = 0;
|
int nvars = 0;
|
||||||
@@ -1978,7 +1923,6 @@ public class LexState extends Constants {
|
|||||||
this.adjustlocalvars(nvars);
|
this.adjustlocalvars(nvars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean funcname(expdesc v) {
|
boolean funcname(expdesc v) {
|
||||||
/* funcname -> NAME {field} [`:' NAME] */
|
/* funcname -> NAME {field} [`:' NAME] */
|
||||||
boolean ismethod = false;
|
boolean ismethod = false;
|
||||||
@@ -1992,7 +1936,6 @@ public class LexState extends Constants {
|
|||||||
return ismethod;
|
return ismethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void funcstat(int line) {
|
void funcstat(int line) {
|
||||||
/* funcstat -> FUNCTION funcname body */
|
/* funcstat -> FUNCTION funcname body */
|
||||||
boolean needself;
|
boolean needself;
|
||||||
@@ -2005,7 +1948,6 @@ public class LexState extends Constants {
|
|||||||
fs.fixline(line); /* definition `happens' in the first line */
|
fs.fixline(line); /* definition `happens' in the first line */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void exprstat() {
|
void exprstat() {
|
||||||
/* stat -> func | assignment */
|
/* stat -> func | assignment */
|
||||||
FuncState fs = this.fs;
|
FuncState fs = this.fs;
|
||||||
@@ -2014,8 +1956,7 @@ public class LexState extends Constants {
|
|||||||
if (t.token == '=' || t.token == ',') { /* stat -> assignment ? */
|
if (t.token == '=' || t.token == ',') { /* stat -> assignment ? */
|
||||||
v.prev = null;
|
v.prev = null;
|
||||||
assignment(v, 1);
|
assignment(v, 1);
|
||||||
}
|
} else { /* stat -> func */
|
||||||
else { /* stat -> func */
|
|
||||||
check_condition(v.v.k == VCALL, "syntax error");
|
check_condition(v.v.k == VCALL, "syntax error");
|
||||||
SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
|
SETARG_C(fs.getcodePtr(v.v), 1); /* call statement uses no results */
|
||||||
}
|
}
|
||||||
@@ -2114,8 +2055,7 @@ public class LexState extends Constants {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_assert(fs.f.maxstacksize >= fs.freereg
|
_assert(fs.f.maxstacksize >= fs.freereg && fs.freereg >= fs.nactvar);
|
||||||
&& fs.freereg >= fs.nactvar);
|
|
||||||
fs.freereg = fs.nactvar; /* free registers */
|
fs.freereg = fs.nactvar; /* free registers */
|
||||||
leavelevel();
|
leavelevel();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,30 +37,37 @@ import org.luaj.vm2.lib.BaseLib;
|
|||||||
* Compiler for Lua.
|
* Compiler for Lua.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Compiles lua source files into lua bytecode within a {@link Prototype},
|
* Compiles lua source files into lua bytecode within a {@link Prototype}, loads
|
||||||
* loads lua binary files directly into a {@link Prototype},
|
* lua binary files directly into a {@link Prototype}, and optionaly
|
||||||
* and optionaly instantiates a {@link LuaClosure} around the result
|
* instantiates a {@link LuaClosure} around the result using a user-supplied
|
||||||
* using a user-supplied environment.
|
* environment.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Implements the {@link org.luaj.vm2.Globals.Compiler} interface for loading
|
* Implements the {@link org.luaj.vm2.Globals.Compiler} interface for loading
|
||||||
* initialized chunks, which is an interface common to
|
* initialized chunks, which is an interface common to lua bytecode compiling
|
||||||
* lua bytecode compiling and java bytecode compiling.
|
* and java bytecode compiling.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link LuaC} compiler is installed by default by both the
|
* The {@link LuaC} compiler is installed by default by both the
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform} and {@link org.luaj.vm2.lib.jme.JmePlatform} classes,
|
* {@link org.luaj.vm2.lib.jse.JsePlatform} and
|
||||||
* so in the following example, the default {@link LuaC} compiler
|
* {@link org.luaj.vm2.lib.jme.JmePlatform} classes, so in the following
|
||||||
* will be used:
|
* example, the default {@link LuaC} compiler will be used:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @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>
|
||||||
*
|
*
|
||||||
* To load the LuaC compiler manually, use the install method:
|
* To load the LuaC compiler manually, use the install method:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* LuaC.install(globals);
|
* LuaC.install(globals);
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @see #install(Globals)
|
* @see #install(Globals)
|
||||||
* @see Globals#compiler
|
* @see Globals#compiler
|
||||||
@@ -77,9 +84,10 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader
|
|||||||
/** A sharable instance of the LuaC compiler. */
|
/** A sharable instance of the LuaC compiler. */
|
||||||
public static final LuaC instance = new LuaC();
|
public static final LuaC instance = new LuaC();
|
||||||
|
|
||||||
/** Install the compiler so that LoadState will first
|
/**
|
||||||
* try to use it when handed bytes that are
|
* Install the compiler so that LoadState will first try to use it when
|
||||||
* not already a compiled lua chunk.
|
* handed bytes that are not already a compiled lua chunk.
|
||||||
|
*
|
||||||
* @param globals the Globals into which this is to be installed.
|
* @param globals the Globals into which this is to be installed.
|
||||||
*/
|
*/
|
||||||
public static void install(Globals globals) {
|
public static void install(Globals globals) {
|
||||||
@@ -89,8 +97,11 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader
|
|||||||
|
|
||||||
protected LuaC() {}
|
protected LuaC() {}
|
||||||
|
|
||||||
/** Compile lua source into a Prototype.
|
/**
|
||||||
* @param stream InputStream representing the text source conforming to lua source syntax.
|
* Compile lua source into a Prototype.
|
||||||
|
*
|
||||||
|
* @param stream InputStream representing the text source conforming to
|
||||||
|
* lua source syntax.
|
||||||
* @param chunkname String name of the chunk to use.
|
* @param chunkname String name of the chunk to use.
|
||||||
* @return Prototype representing the lua chunk for this source.
|
* @return Prototype representing the lua chunk for this source.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
@@ -103,9 +114,10 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader
|
|||||||
return new LuaClosure(prototype, env);
|
return new LuaClosure(prototype, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @deprecated
|
/**
|
||||||
* Use Globals.load(InputString, String, String) instead,
|
* @deprecated Use Globals.load(InputString, String, String) instead, or
|
||||||
* or LuaC.compile(InputStream, String) and construct LuaClosure directly.
|
* LuaC.compile(InputStream, String) and construct LuaClosure
|
||||||
|
* directly.
|
||||||
*/
|
*/
|
||||||
public LuaValue load(InputStream stream, String chunkname, Globals globals) throws IOException {
|
public LuaValue load(InputStream stream, String chunkname, Globals globals) throws IOException {
|
||||||
return new LuaClosure(compile(stream, chunkname), globals);
|
return new LuaClosure(compile(stream, chunkname), globals);
|
||||||
@@ -114,6 +126,7 @@ public class LuaC extends Constants implements Globals.Compiler, Globals.Loader
|
|||||||
static class CompileState {
|
static class CompileState {
|
||||||
int nCcalls = 0;
|
int nCcalls = 0;
|
||||||
private Hashtable strings = new Hashtable();
|
private Hashtable strings = new Hashtable();
|
||||||
|
|
||||||
protected CompileState() {}
|
protected CompileState() {}
|
||||||
|
|
||||||
/** Parse the input */
|
/** Parse the input */
|
||||||
|
|||||||
@@ -34,14 +34,14 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua basic library functions.
|
* Subclass of {@link LibFunction} which implements the lua basic library
|
||||||
|
* functions.
|
||||||
* <p>
|
* <p>
|
||||||
* This contains all library functions listed as "basic functions" in the lua documentation for JME.
|
* This contains all library functions listed as "basic functions" in the lua
|
||||||
* The functions dofile and loadfile use the
|
* documentation for JME. The functions dofile and loadfile use the
|
||||||
* {@link Globals#finder} instance to find resource files.
|
* {@link Globals#finder} instance to find resource files. Since JME has no file
|
||||||
* Since JME has no file system by default, {@link BaseLib} implements
|
* system by default, {@link BaseLib} implements {@link ResourceFinder} using
|
||||||
* {@link ResourceFinder} using {@link Class#getResource(String)},
|
* {@link Class#getResource(String)}, which is the closest equivalent on JME.
|
||||||
* which is the closest equivalent on JME.
|
|
||||||
* The default loader chain in {@link PackageLib} will use these as well.
|
* The default loader chain in {@link PackageLib} will use these as well.
|
||||||
* <p>
|
* <p>
|
||||||
* To use basic library functions that include a {@link ResourceFinder} based on
|
* To use basic library functions that include a {@link ResourceFinder} based on
|
||||||
@@ -50,40 +50,53 @@ import org.luaj.vm2.Varargs;
|
|||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired, a minimal
|
||||||
* a minimal set of libraries could be loaded
|
* set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* }
|
||||||
* Doing so will ensure the library is properly initialized
|
* </pre>
|
||||||
* and loaded into the globals table.
|
*
|
||||||
|
* Doing so will ensure the library is properly initialized and loaded into the
|
||||||
|
* globals table.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a direct port of the corresponding library in C.
|
* This is a direct port of the corresponding library in C.
|
||||||
|
*
|
||||||
* @see org.luaj.vm2.lib.jse.JseBaseLib
|
* @see org.luaj.vm2.lib.jse.JseBaseLib
|
||||||
* @see ResourceFinder
|
* @see ResourceFinder
|
||||||
* @see Globals#finder
|
* @see Globals#finder
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.1">Lua 5.2 Base Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.1">Lua 5.2 Base Lib
|
||||||
|
* Reference</a>
|
||||||
*/
|
*/
|
||||||
public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
||||||
|
|
||||||
Globals globals;
|
Globals globals;
|
||||||
|
|
||||||
|
/**
|
||||||
/** Perform one-time initialization on the library by adding base functions
|
* Perform one-time initialization on the library by adding base functions
|
||||||
* to the supplied environment, and returning it as the return value.
|
* to the supplied environment, and returning it as the return value.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, which must be a Globals instance.
|
* @param env the environment to load into, which must be a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
globals = env.checkglobals();
|
globals = env.checkglobals();
|
||||||
@@ -119,7 +132,8 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ResourceFinder implementation
|
/**
|
||||||
|
* ResourceFinder implementation
|
||||||
*
|
*
|
||||||
* Tries to open the file as a resource, which can work for JSE and JME.
|
* Tries to open the file as a resource, which can work for JSE and JME.
|
||||||
*/
|
*/
|
||||||
@@ -127,7 +141,6 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
return getClass().getResourceAsStream(filename.startsWith("/")? filename: "/" + filename);
|
return getClass().getResourceAsStream(filename.startsWith("/")? filename: "/" + filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// "assert", // ( v [,message] ) -> v, message | ERR
|
// "assert", // ( v [,message] ) -> v, message | ERR
|
||||||
static final class _assert extends VarArgFunction {
|
static final class _assert extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
@@ -163,9 +176,8 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
args.argcheck(args.isstring(1) || args.isnil(1), 1, "filename must be string or nil");
|
||||||
String filename = args.isstring(1)? args.tojstring(1): null;
|
String filename = args.isstring(1)? args.tojstring(1): null;
|
||||||
Varargs v = filename == null?
|
Varargs v = filename == null? loadStream(globals.STDIN, "=stdin", "bt", globals)
|
||||||
loadStream( globals.STDIN, "=stdin", "bt", globals ):
|
: loadFile(args.checkjstring(1), "bt", globals);
|
||||||
loadFile( args.checkjstring(1), "bt", globals );
|
|
||||||
return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
|
return v.isnil(1)? error(v.tojstring(2)): v.arg1().invoke();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,8 +185,10 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
// "error", // ( message [,level] ) -> ERR
|
// "error", // ( message [,level] ) -> ERR
|
||||||
static final class error extends TwoArgFunction {
|
static final class error extends TwoArgFunction {
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
if (arg1.isnil()) throw new LuaError(NIL);
|
if (arg1.isnil())
|
||||||
if (!arg1.isstring() || arg2.optint(1) == 0) throw new LuaError(arg1);
|
throw new LuaError(NIL);
|
||||||
|
if (!arg1.isstring() || arg2.optint(1) == 0)
|
||||||
|
throw new LuaError(arg1);
|
||||||
throw new LuaError(arg1.tojstring(), arg2.optint(1));
|
throw new LuaError(arg1.tojstring(), arg2.optint(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,23 +198,26 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
public LuaValue call() {
|
public LuaValue call() {
|
||||||
return argerror(1, "value expected");
|
return argerror(1, "value expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
LuaValue mt = arg.getmetatable();
|
LuaValue mt = arg.getmetatable();
|
||||||
return mt != null? mt.rawget(METATABLE).optvalue(mt): NIL;
|
return mt != null? mt.rawget(METATABLE).optvalue(mt): NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
|
// "load", // ( ld [, source [, mode [, env]]] ) -> chunk | nil, msg
|
||||||
final class load extends VarArgFunction {
|
final class load extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaValue ld = args.arg1();
|
LuaValue ld = args.arg1();
|
||||||
if (!ld.isstring() && !ld.isfunction()) {
|
if (!ld.isstring() && !ld.isfunction()) {
|
||||||
throw new LuaError("bad argument #1 to 'load' (string or function expected, got " + ld.typename() + ")");
|
throw new LuaError(
|
||||||
|
"bad argument #1 to 'load' (string or function expected, got " + ld.typename() + ")");
|
||||||
}
|
}
|
||||||
String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
|
String source = args.optjstring(2, ld.isstring()? ld.tojstring(): "=(load)");
|
||||||
String mode = args.optjstring(3, "bt");
|
String mode = args.optjstring(3, "bt");
|
||||||
LuaValue env = args.optvalue(4, globals);
|
LuaValue env = args.optvalue(4, globals);
|
||||||
return loadStream(ld.isstring()? ld.strvalue().toInputStream():
|
return loadStream(ld.isstring()? ld.strvalue().toInputStream(): new StringInputStream(ld.checkfunction()),
|
||||||
new StringInputStream(ld.checkfunction()), source, mode, env);
|
source, mode, env);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,9 +228,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
String filename = args.isstring(1)? args.tojstring(1): null;
|
String filename = args.isstring(1)? args.tojstring(1): null;
|
||||||
String mode = args.optjstring(2, "bt");
|
String mode = args.optjstring(2, "bt");
|
||||||
LuaValue env = args.optvalue(3, globals);
|
LuaValue env = args.optvalue(3, globals);
|
||||||
return filename == null?
|
return filename == null? loadStream(globals.STDIN, "=stdin", mode, env): loadFile(filename, mode, env);
|
||||||
loadStream( globals.STDIN, "=stdin", mode, env ):
|
|
||||||
loadFile( filename, mode, env );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,13 +256,16 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
// "print", // (...) -> void
|
// "print", // (...) -> void
|
||||||
final class print extends VarArgFunction {
|
final class print extends VarArgFunction {
|
||||||
final BaseLib baselib;
|
final BaseLib baselib;
|
||||||
|
|
||||||
print(BaseLib baselib) {
|
print(BaseLib baselib) {
|
||||||
this.baselib = baselib;
|
this.baselib = baselib;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaValue tostring = globals.get("tostring");
|
LuaValue tostring = globals.get("tostring");
|
||||||
for (int i = 1, n = args.narg(); i <= n; i++) {
|
for (int i = 1, n = args.narg(); i <= n; i++) {
|
||||||
if ( i>1 ) globals.STDOUT.print( '\t' );
|
if (i > 1)
|
||||||
|
globals.STDOUT.print('\t');
|
||||||
LuaString s = tostring.call(args.arg(i)).strvalue();
|
LuaString s = tostring.call(args.arg(i)).strvalue();
|
||||||
globals.STDOUT.print(s.tojstring());
|
globals.STDOUT.print(s.tojstring());
|
||||||
}
|
}
|
||||||
@@ -256,15 +274,16 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// "rawequal", // (v1, v2) -> boolean
|
// "rawequal", // (v1, v2) -> boolean
|
||||||
static final class rawequal extends LibFunction {
|
static final class rawequal extends LibFunction {
|
||||||
public LuaValue call() {
|
public LuaValue call() {
|
||||||
return argerror(1, "value expected");
|
return argerror(1, "value expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
return argerror(2, "value expected");
|
return argerror(2, "value expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
return valueOf(arg1.raweq(arg2));
|
return valueOf(arg1.raweq(arg2));
|
||||||
}
|
}
|
||||||
@@ -275,12 +294,12 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
return argerror(2, "value expected");
|
return argerror(2, "value expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
return arg1.checktable().rawget(arg2);
|
return arg1.checktable().rawget(arg2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// "rawlen", // (v) -> value
|
// "rawlen", // (v) -> value
|
||||||
static final class rawlen extends LibFunction {
|
static final class rawlen extends LibFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
@@ -293,12 +312,15 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
public LuaValue call(LuaValue table) {
|
public LuaValue call(LuaValue table) {
|
||||||
return argerror(2, "value expected");
|
return argerror(2, "value expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue table, LuaValue index) {
|
public LuaValue call(LuaValue table, LuaValue index) {
|
||||||
return argerror(3, "value expected");
|
return argerror(3, "value expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue table, LuaValue index, LuaValue value) {
|
public LuaValue call(LuaValue table, LuaValue index, LuaValue value) {
|
||||||
LuaTable t = table.checktable();
|
LuaTable t = table.checktable();
|
||||||
if (!index.isvalidkey()) argerror(2, "table index is nil");
|
if (!index.isvalidkey())
|
||||||
|
argerror(2, "table index is nil");
|
||||||
t.rawset(index, value);
|
t.rawset(index, value);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@@ -322,6 +344,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
public LuaValue call(LuaValue table) {
|
public LuaValue call(LuaValue table) {
|
||||||
return argerror(2, "nil or table expected");
|
return argerror(2, "nil or table expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue table, LuaValue metatable) {
|
public LuaValue call(LuaValue table, LuaValue metatable) {
|
||||||
final LuaValue mt0 = table.checktable().getmetatable();
|
final LuaValue mt0 = table.checktable().getmetatable();
|
||||||
if (mt0 != null && !mt0.rawget(METATABLE).isnil())
|
if (mt0 != null && !mt0.rawget(METATABLE).isnil())
|
||||||
@@ -335,6 +358,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
public LuaValue call(LuaValue e) {
|
public LuaValue call(LuaValue e) {
|
||||||
return e.tonumber();
|
return e.tonumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue e, LuaValue base) {
|
public LuaValue call(LuaValue e, LuaValue base) {
|
||||||
if (base.isnil())
|
if (base.isnil())
|
||||||
return e.tonumber();
|
return e.tonumber();
|
||||||
@@ -395,9 +419,11 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
// "pairs" (t) -> iter-func, t, nil
|
// "pairs" (t) -> iter-func, t, nil
|
||||||
static final class pairs extends VarArgFunction {
|
static final class pairs extends VarArgFunction {
|
||||||
final next next;
|
final next next;
|
||||||
|
|
||||||
pairs(next next) {
|
pairs(next next) {
|
||||||
this.next = next;
|
this.next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
return varargsOf(next, args.checktable(1), NIL);
|
return varargsOf(next, args.checktable(1), NIL);
|
||||||
}
|
}
|
||||||
@@ -406,6 +432,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
// // "ipairs", // (t) -> iter-func, t, 0
|
// // "ipairs", // (t) -> iter-func, t, 0
|
||||||
static final class ipairs extends VarArgFunction {
|
static final class ipairs extends VarArgFunction {
|
||||||
inext inext = new inext();
|
inext inext = new inext();
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
return varargsOf(inext, args.checktable(1), ZERO);
|
return varargsOf(inext, args.checktable(1), ZERO);
|
||||||
}
|
}
|
||||||
@@ -427,6 +454,7 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Load from a named file, returning the chunk or nil,error of can't load
|
* Load from a named file, returning the chunk or nil,error of can't load
|
||||||
|
*
|
||||||
* @param env
|
* @param env
|
||||||
* @param mode
|
* @param mode
|
||||||
* @return Varargs containing chunk, or NIL,error-text on error
|
* @return Varargs containing chunk, or NIL,error-text on error
|
||||||
@@ -456,14 +484,15 @@ public class BaseLib extends TwoArgFunction implements ResourceFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class StringInputStream extends InputStream {
|
private static class StringInputStream extends InputStream {
|
||||||
final LuaValue func;
|
final LuaValue func;
|
||||||
byte[] bytes;
|
byte[] bytes;
|
||||||
int offset, remaining = 0;
|
int offset, remaining = 0;
|
||||||
|
|
||||||
StringInputStream(LuaValue func) {
|
StringInputStream(LuaValue func) {
|
||||||
this.func = func;
|
this.func = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
if (remaining < 0)
|
if (remaining < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -26,68 +26,86 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of LibFunction that implements the Lua standard {@code bit32} library.
|
* Subclass of LibFunction that implements the Lua standard {@code bit32}
|
||||||
|
* library.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* <pre> {@code
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("bit32").get("bnot").call(LuaValue.valueOf(2)));
|
* System.out.println(globals.get("bit32").get("bnot").call(LuaValue.valueOf(2)));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new Bit32Lib());
|
* globals.load(new Bit32Lib());
|
||||||
* System.out.println(globals.get("bit32").get("bnot").call(LuaValue.valueOf(2)));
|
* System.out.println(globals.get("bit32").get("bnot").call(LuaValue.valueOf(2)));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.7">Lua 5.2 Bitwise Operation Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.7">Lua 5.2 Bitwise
|
||||||
|
* Operation Lib Reference</a>
|
||||||
*/
|
*/
|
||||||
public class Bit32Lib extends TwoArgFunction {
|
public class Bit32Lib extends TwoArgFunction {
|
||||||
|
|
||||||
public Bit32Lib() {
|
public Bit32Lib() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by creating a table
|
/**
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* Perform one-time initialization on the library by creating a table
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* containing the library functions, adding that table to the supplied
|
||||||
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
|
* the return value.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, which must be a Globals instance.
|
* @param env the environment to load into, which must be a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
LuaTable t = new LuaTable();
|
LuaTable t = new LuaTable();
|
||||||
bind(t, Bit32LibV.class, new String[] {
|
bind(t, Bit32LibV.class, new String[] { "band", "bnot", "bor", "btest", "bxor", "extract", "replace" });
|
||||||
"band", "bnot", "bor", "btest", "bxor", "extract", "replace"
|
bind(t, Bit32Lib2.class, new String[] { "arshift", "lrotate", "lshift", "rrotate", "rshift" });
|
||||||
});
|
|
||||||
bind(t, Bit32Lib2.class, new String[] {
|
|
||||||
"arshift", "lrotate", "lshift", "rrotate", "rshift"
|
|
||||||
});
|
|
||||||
env.set("bit32", t);
|
env.set("bit32", t);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("bit32", t);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("bit32", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class Bit32LibV extends VarArgFunction {
|
static final class Bit32LibV extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0: return Bit32Lib.band( args );
|
case 0:
|
||||||
case 1: return Bit32Lib.bnot( args );
|
return Bit32Lib.band(args);
|
||||||
case 2: return Bit32Lib.bor( args );
|
case 1:
|
||||||
case 3: return Bit32Lib.btest( args );
|
return Bit32Lib.bnot(args);
|
||||||
case 4: return Bit32Lib.bxor( args );
|
case 2:
|
||||||
|
return Bit32Lib.bor(args);
|
||||||
|
case 3:
|
||||||
|
return Bit32Lib.btest(args);
|
||||||
|
case 4:
|
||||||
|
return Bit32Lib.bxor(args);
|
||||||
case 5:
|
case 5:
|
||||||
return Bit32Lib.extract(args.checkint(1), args.checkint(2), args.optint(3, 1));
|
return Bit32Lib.extract(args.checkint(1), args.checkint(2), args.optint(3, 1));
|
||||||
case 6:
|
case 6:
|
||||||
return Bit32Lib.replace( args.checkint(1), args.checkint(2),
|
return Bit32Lib.replace(args.checkint(1), args.checkint(2), args.checkint(3), args.optint(4, 1));
|
||||||
args.checkint(3), args.optint(4, 1) );
|
|
||||||
}
|
}
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
@@ -97,11 +115,16 @@ public class Bit32Lib extends TwoArgFunction {
|
|||||||
|
|
||||||
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
public LuaValue call(LuaValue arg1, LuaValue arg2) {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0: return Bit32Lib.arshift(arg1.checkint(), arg2.checkint());
|
case 0:
|
||||||
case 1: return Bit32Lib.lrotate(arg1.checkint(), arg2.checkint());
|
return Bit32Lib.arshift(arg1.checkint(), arg2.checkint());
|
||||||
case 2: return Bit32Lib.lshift(arg1.checkint(), arg2.checkint());
|
case 1:
|
||||||
case 3: return Bit32Lib.rrotate(arg1.checkint(), arg2.checkint());
|
return Bit32Lib.lrotate(arg1.checkint(), arg2.checkint());
|
||||||
case 4: return Bit32Lib.rshift(arg1.checkint(), arg2.checkint());
|
case 2:
|
||||||
|
return Bit32Lib.lshift(arg1.checkint(), arg2.checkint());
|
||||||
|
case 3:
|
||||||
|
return Bit32Lib.rrotate(arg1.checkint(), arg2.checkint());
|
||||||
|
case 4:
|
||||||
|
return Bit32Lib.rshift(arg1.checkint(), arg2.checkint());
|
||||||
}
|
}
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,37 +28,48 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code coroutine}
|
* Subclass of {@link LibFunction} which implements the lua standard
|
||||||
* library.
|
* {@code coroutine} library.
|
||||||
* <p>
|
* <p>
|
||||||
* The coroutine library in luaj has the same behavior as the
|
* The coroutine library in luaj has the same behavior as the coroutine library
|
||||||
* coroutine library in C, but is implemented using Java Threads to maintain
|
* in C, but is implemented using Java Threads to maintain the call state
|
||||||
* the call state between invocations. Therefore it can be yielded from anywhere,
|
* between invocations. Therefore it can be yielded from anywhere, similar to
|
||||||
* similar to the "Coco" yield-from-anywhere patch available for C-based lua.
|
* the "Coco" yield-from-anywhere patch available for C-based lua. However,
|
||||||
* However, coroutines that are yielded but never resumed to complete their execution
|
* coroutines that are yielded but never resumed to complete their execution may
|
||||||
* may not be collected by the garbage collector.
|
* not be collected by the garbage collector.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* <pre> {@code
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("coroutine").get("running").call());
|
* System.out.println(globals.get("coroutine").get("running").call());
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new CoroutineLib());
|
* globals.load(new CoroutineLib());
|
||||||
* System.out.println(globals.get("coroutine").get("running").call());
|
* System.out.println(globals.get("coroutine").get("running").call());
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.2">Lua 5.2 Coroutine Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.2">Lua 5.2
|
||||||
|
* Coroutine Lib Reference</a>
|
||||||
*/
|
*/
|
||||||
public class CoroutineLib extends TwoArgFunction {
|
public class CoroutineLib extends TwoArgFunction {
|
||||||
|
|
||||||
@@ -66,11 +77,15 @@ public class CoroutineLib extends TwoArgFunction {
|
|||||||
|
|
||||||
Globals globals;
|
Globals globals;
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by creating a table
|
/**
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* Perform one-time initialization on the library by creating a table
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* containing the library functions, adding that table to the supplied
|
||||||
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
|
* the return value.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, which must be a Globals instance.
|
* @param env the environment to load into, which must be a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
globals = env.checkglobals();
|
globals = env.checkglobals();
|
||||||
@@ -82,7 +97,8 @@ public class CoroutineLib extends TwoArgFunction {
|
|||||||
coroutine.set("yield", new yield());
|
coroutine.set("yield", new yield());
|
||||||
coroutine.set("wrap", new wrap());
|
coroutine.set("wrap", new wrap());
|
||||||
env.set("coroutine", coroutine);
|
env.set("coroutine", coroutine);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("coroutine", coroutine);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("coroutine", coroutine);
|
||||||
return coroutine;
|
return coroutine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,9 +145,11 @@ public class CoroutineLib extends TwoArgFunction {
|
|||||||
|
|
||||||
static final class wrapper extends VarArgFunction {
|
static final class wrapper extends VarArgFunction {
|
||||||
final LuaThread luathread;
|
final LuaThread luathread;
|
||||||
|
|
||||||
wrapper(LuaThread luathread) {
|
wrapper(LuaThread luathread) {
|
||||||
this.luathread = luathread;
|
this.luathread = luathread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
final Varargs result = luathread.resume(args);
|
final Varargs result = luathread.resume(args);
|
||||||
if (result.arg1().toboolean()) {
|
if (result.arg1().toboolean()) {
|
||||||
|
|||||||
@@ -39,49 +39,64 @@ import org.luaj.vm2.Prototype;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code debug}
|
* Subclass of {@link LibFunction} which implements the lua standard
|
||||||
* library.
|
* {@code debug} library.
|
||||||
* <p>
|
* <p>
|
||||||
* The debug library in luaj tries to emulate the behavior of the corresponding C-based lua library.
|
* The debug library in luaj tries to emulate the behavior of the corresponding
|
||||||
* To do this, it must maintain a separate stack of calls to {@link LuaClosure} and {@link LibFunction}
|
* C-based lua library. To do this, it must maintain a separate stack of calls
|
||||||
* instances.
|
* to {@link LuaClosure} and {@link LibFunction} instances. Especially when
|
||||||
* Especially when lua-to-java bytecode compiling is being used
|
* lua-to-java bytecode compiling is being used via a
|
||||||
* via a {@link org.luaj.vm2.Globals.Compiler} such as {@link org.luaj.vm2.luajc.LuaJC},
|
* {@link org.luaj.vm2.Globals.Compiler} such as
|
||||||
* this cannot be done in all cases.
|
* {@link org.luaj.vm2.luajc.LuaJC}, this cannot be done in all cases.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#debugGlobals()} or
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#debugGlobals()} or
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform#debugGlobals()}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#debugGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.debugGlobals();
|
* Globals globals = JsePlatform.debugGlobals();
|
||||||
* System.out.println(globals.get("debug").get("traceback").call());
|
* System.out.println(globals.get("debug").get("traceback").call());
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new DebugLib());
|
* globals.load(new DebugLib());
|
||||||
* System.out.println(globals.get("debug").get("traceback").call());
|
* System.out.println(globals.get("debug").get("traceback").call());
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This library exposes the entire state of lua code, and provides method to see and modify
|
* This library exposes the entire state of lua code, and provides method to see
|
||||||
* all underlying lua values within a Java VM so should not be exposed to client code
|
* and modify all underlying lua values within a Java VM so should not be
|
||||||
* in a shared server environment.
|
* exposed to client code in a shared server environment.
|
||||||
*
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.10">Lua 5.2 Debug Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.10">Lua 5.2 Debug
|
||||||
|
* Lib Reference</a>
|
||||||
*/
|
*/
|
||||||
public class DebugLib extends TwoArgFunction {
|
public class DebugLib extends TwoArgFunction {
|
||||||
public static boolean CALLS;
|
public static boolean CALLS;
|
||||||
public static boolean TRACE;
|
public static boolean TRACE;
|
||||||
static {
|
static {
|
||||||
try { CALLS = (null != System.getProperty("CALLS")); } catch (Exception e) {}
|
try {
|
||||||
try { TRACE = (null != System.getProperty("TRACE")); } catch (Exception e) {}
|
CALLS = (null != System.getProperty("CALLS"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
TRACE = (null != System.getProperty("TRACE"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final LuaString LUA = valueOf("Lua");
|
static final LuaString LUA = valueOf("Lua");
|
||||||
@@ -108,11 +123,15 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
|
|
||||||
Globals globals;
|
Globals globals;
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by creating a table
|
/**
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* Perform one-time initialization on the library by creating a table
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* containing the library functions, adding that table to the supplied
|
||||||
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
|
* the return value.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, which must be a Globals instance.
|
* @param env the environment to load into, which must be a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
globals = env.checkglobals();
|
globals = env.checkglobals();
|
||||||
@@ -135,7 +154,8 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
debug.set("upvalueid", new upvalueid());
|
debug.set("upvalueid", new upvalueid());
|
||||||
debug.set("upvaluejoin", new upvaluejoin());
|
debug.set("upvaluejoin", new upvaluejoin());
|
||||||
env.set("debug", debug);
|
env.set("debug", debug);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("debug", debug);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("debug", debug);
|
||||||
return debug;
|
return debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,10 +171,8 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaThread t = args.narg() > 0? args.checkthread(1): globals.running;
|
LuaThread t = args.narg() > 0? args.checkthread(1): globals.running;
|
||||||
LuaThread.State s = t.state;
|
LuaThread.State s = t.state;
|
||||||
return varargsOf(
|
return varargsOf(s.hookfunc != null? s.hookfunc: NIL,
|
||||||
s.hookfunc != null? s.hookfunc: NIL,
|
valueOf((s.hookcall? "c": "")+(s.hookline? "l": "")+(s.hookrtrn? "r": "")), valueOf(s.hookcount));
|
||||||
valueOf((s.hookcall?"c":"")+(s.hookline?"l":"")+(s.hookrtrn?"r":"")),
|
|
||||||
valueOf(s.hookcount));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +289,6 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// debug.sethook ([thread,] hook, mask [, count])
|
// debug.sethook ([thread,] hook, mask [, count])
|
||||||
final class sethook extends VarArgFunction {
|
final class sethook extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
@@ -283,9 +300,15 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
boolean call = false, line = false, rtrn = false;
|
boolean call = false, line = false, rtrn = false;
|
||||||
for (int i = 0; i < str.length(); i++)
|
for (int i = 0; i < str.length(); i++)
|
||||||
switch (str.charAt(i)) {
|
switch (str.charAt(i)) {
|
||||||
case 'c': call=true; break;
|
case 'c':
|
||||||
case 'l': line=true; break;
|
call = true;
|
||||||
case 'r': rtrn=true; break;
|
break;
|
||||||
|
case 'l':
|
||||||
|
line = true;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rtrn = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
LuaThread.State s = t.state;
|
LuaThread.State s = t.state;
|
||||||
s.hookfunc = func;
|
s.hookfunc = func;
|
||||||
@@ -315,13 +338,26 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
public LuaValue call(LuaValue value, LuaValue table) {
|
public LuaValue call(LuaValue value, LuaValue table) {
|
||||||
LuaValue mt = table.opttable(null);
|
LuaValue mt = table.opttable(null);
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case TNIL: LuaNil.s_metatable = mt; break;
|
case TNIL:
|
||||||
case TNUMBER: LuaNumber.s_metatable = mt; break;
|
LuaNil.s_metatable = mt;
|
||||||
case TBOOLEAN: LuaBoolean.s_metatable = mt; break;
|
break;
|
||||||
case TSTRING: LuaString.s_metatable = mt; break;
|
case TNUMBER:
|
||||||
case TFUNCTION: LuaFunction.s_metatable = mt; break;
|
LuaNumber.s_metatable = mt;
|
||||||
case TTHREAD: LuaThread.s_metatable = mt; break;
|
break;
|
||||||
default: value.setmetatable( mt );
|
case TBOOLEAN:
|
||||||
|
LuaBoolean.s_metatable = mt;
|
||||||
|
break;
|
||||||
|
case TSTRING:
|
||||||
|
LuaString.s_metatable = mt;
|
||||||
|
break;
|
||||||
|
case TFUNCTION:
|
||||||
|
LuaFunction.s_metatable = mt;
|
||||||
|
break;
|
||||||
|
case TTHREAD:
|
||||||
|
LuaThread.s_metatable = mt;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value.setmetatable(mt);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@@ -402,23 +438,29 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
|
|
||||||
public void onCall(LuaFunction f) {
|
public void onCall(LuaFunction f) {
|
||||||
LuaThread.State s = globals.running.state;
|
LuaThread.State s = globals.running.state;
|
||||||
if (s.inhook) return;
|
if (s.inhook)
|
||||||
|
return;
|
||||||
callstack().onCall(f);
|
callstack().onCall(f);
|
||||||
if (s.hookcall) callHook(s, CALL, NIL);
|
if (s.hookcall)
|
||||||
|
callHook(s, CALL, NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) {
|
public void onCall(LuaClosure c, Varargs varargs, LuaValue[] stack) {
|
||||||
LuaThread.State s = globals.running.state;
|
LuaThread.State s = globals.running.state;
|
||||||
if (s.inhook) return;
|
if (s.inhook)
|
||||||
|
return;
|
||||||
callstack().onCall(c, varargs, stack);
|
callstack().onCall(c, varargs, stack);
|
||||||
if (s.hookcall) callHook(s, CALL, NIL);
|
if (s.hookcall)
|
||||||
|
callHook(s, CALL, NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onInstruction(int pc, Varargs v, int top) {
|
public void onInstruction(int pc, Varargs v, int top) {
|
||||||
LuaThread.State s = globals.running.state;
|
LuaThread.State s = globals.running.state;
|
||||||
if (s.inhook) return;
|
if (s.inhook)
|
||||||
|
return;
|
||||||
callstack().onInstruction(pc, v, top);
|
callstack().onInstruction(pc, v, top);
|
||||||
if (s.hookfunc == null) return;
|
if (s.hookfunc == null)
|
||||||
|
return;
|
||||||
if (s.hookcount > 0)
|
if (s.hookcount > 0)
|
||||||
if (++s.bytecodes%s.hookcount == 0)
|
if (++s.bytecodes%s.hookcount == 0)
|
||||||
callHook(s, COUNT, NIL);
|
callHook(s, COUNT, NIL);
|
||||||
@@ -433,9 +475,11 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
|
|
||||||
public void onReturn() {
|
public void onReturn() {
|
||||||
LuaThread.State s = globals.running.state;
|
LuaThread.State s = globals.running.state;
|
||||||
if (s.inhook) return;
|
if (s.inhook)
|
||||||
|
return;
|
||||||
callstack().onReturn();
|
callstack().onReturn();
|
||||||
if (s.hookrtrn) callHook(s, RETURN, NIL);
|
if (s.hookrtrn)
|
||||||
|
callHook(s, RETURN, NIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String traceback(int level) {
|
public String traceback(int level) {
|
||||||
@@ -447,7 +491,8 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void callHook(LuaThread.State s, LuaValue type, LuaValue arg) {
|
void callHook(LuaThread.State s, LuaValue type, LuaValue arg) {
|
||||||
if (s.inhook || s.hookfunc == null) return;
|
if (s.inhook || s.hookfunc == null)
|
||||||
|
return;
|
||||||
s.inhook = true;
|
s.inhook = true;
|
||||||
try {
|
try {
|
||||||
s.hookfunc.call(type, arg);
|
s.hookfunc.call(type, arg);
|
||||||
@@ -548,6 +593,7 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the traceback starting at a specific level.
|
* Get the traceback starting at a specific level.
|
||||||
|
*
|
||||||
* @param level
|
* @param level
|
||||||
* @return String containing the traceback.
|
* @return String containing the traceback.
|
||||||
*/
|
*/
|
||||||
@@ -593,7 +639,6 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
synchronized DebugInfo auxgetinfo(String what, LuaFunction f, CallFrame ci) {
|
synchronized DebugInfo auxgetinfo(String what, LuaFunction f, CallFrame ci) {
|
||||||
DebugInfo ar = new DebugInfo();
|
DebugInfo ar = new DebugInfo();
|
||||||
for (int i = 0, n = what.length(); i < n; ++i) {
|
for (int i = 0, n = what.length(); i < n; ++i) {
|
||||||
@@ -656,22 +701,27 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
Varargs v;
|
Varargs v;
|
||||||
LuaValue[] stack;
|
LuaValue[] stack;
|
||||||
CallFrame previous;
|
CallFrame previous;
|
||||||
|
|
||||||
void set(LuaClosure function, Varargs varargs, LuaValue[] stack) {
|
void set(LuaClosure function, Varargs varargs, LuaValue[] stack) {
|
||||||
this.f = function;
|
this.f = function;
|
||||||
this.v = varargs;
|
this.v = varargs;
|
||||||
this.stack = stack;
|
this.stack = stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String shortsource() {
|
public String shortsource() {
|
||||||
return f.isclosure()? f.checkclosure().p.shortsource(): "[Java]";
|
return f.isclosure()? f.checkclosure().p.shortsource(): "[Java]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(LuaFunction function) {
|
void set(LuaFunction function) {
|
||||||
this.f = function;
|
this.f = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() {
|
void reset() {
|
||||||
this.f = null;
|
this.f = null;
|
||||||
this.v = null;
|
this.v = null;
|
||||||
this.stack = null;
|
this.stack = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void instr(int pc, Varargs v, int top) {
|
void instr(int pc, Varargs v, int top) {
|
||||||
this.pc = pc;
|
this.pc = pc;
|
||||||
this.v = v;
|
this.v = v;
|
||||||
@@ -679,6 +729,7 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
if (TRACE)
|
if (TRACE)
|
||||||
Print.printState(f.checkclosure(), pc, stack, top, v);
|
Print.printState(f.checkclosure(), pc, stack, top, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
Varargs getLocal(int i) {
|
Varargs getLocal(int i) {
|
||||||
LuaString name = getlocalname(i);
|
LuaString name = getlocalname(i);
|
||||||
if (i >= 1 && i <= stack.length && stack[i-1] != null)
|
if (i >= 1 && i <= stack.length && stack[i-1] != null)
|
||||||
@@ -686,6 +737,7 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
else
|
else
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Varargs setLocal(int i, LuaValue value) {
|
Varargs setLocal(int i, LuaValue value) {
|
||||||
LuaString name = getlocalname(i);
|
LuaString name = getlocalname(i);
|
||||||
if (i >= 1 && i <= stack.length && stack[i-1] != null) {
|
if (i >= 1 && i <= stack.length && stack[i-1] != null) {
|
||||||
@@ -695,20 +747,27 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int currentline() {
|
public int currentline() {
|
||||||
if ( !f.isclosure() ) return -1;
|
if (!f.isclosure())
|
||||||
|
return -1;
|
||||||
int[] li = f.checkclosure().p.lineinfo;
|
int[] li = f.checkclosure().p.lineinfo;
|
||||||
return li == null || pc < 0 || pc >= li.length? -1: li[pc];
|
return li == null || pc < 0 || pc >= li.length? -1: li[pc];
|
||||||
}
|
}
|
||||||
|
|
||||||
String sourceline() {
|
String sourceline() {
|
||||||
if ( !f.isclosure() ) return f.tojstring();
|
if (!f.isclosure())
|
||||||
|
return f.tojstring();
|
||||||
return f.checkclosure().p.shortsource() + ":" + currentline();
|
return f.checkclosure().p.shortsource() + ":" + currentline();
|
||||||
}
|
}
|
||||||
|
|
||||||
int linedefined() {
|
int linedefined() {
|
||||||
return f.isclosure()? f.checkclosure().p.linedefined: -1;
|
return f.isclosure()? f.checkclosure().p.linedefined: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaString getlocalname(int index) {
|
LuaString getlocalname(int index) {
|
||||||
if ( !f.isclosure() ) return null;
|
if (!f.isclosure())
|
||||||
|
return null;
|
||||||
return f.checkclosure().p.getlocalname(index, pc);
|
return f.checkclosure().p.getlocalname(index, pc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -724,12 +783,14 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void lua_assert(boolean x) {
|
static void lua_assert(boolean x) {
|
||||||
if (!x) throw new RuntimeException("lua_assert failed");
|
if (!x)
|
||||||
|
throw new RuntimeException("lua_assert failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
static class NameWhat {
|
static class NameWhat {
|
||||||
final String name;
|
final String name;
|
||||||
final String namewhat;
|
final String namewhat;
|
||||||
|
|
||||||
NameWhat(String name, String namewhat) {
|
NameWhat(String name, String namewhat) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.namewhat = namewhat;
|
this.namewhat = namewhat;
|
||||||
@@ -753,21 +814,49 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
/* all other instructions can call only through metamethods */
|
/* all other instructions can call only through metamethods */
|
||||||
case Lua.OP_SELF:
|
case Lua.OP_SELF:
|
||||||
case Lua.OP_GETTABUP:
|
case Lua.OP_GETTABUP:
|
||||||
case Lua.OP_GETTABLE: tm = LuaValue.INDEX; break;
|
case Lua.OP_GETTABLE:
|
||||||
|
tm = LuaValue.INDEX;
|
||||||
|
break;
|
||||||
case Lua.OP_SETTABUP:
|
case Lua.OP_SETTABUP:
|
||||||
case Lua.OP_SETTABLE: tm = LuaValue.NEWINDEX; break;
|
case Lua.OP_SETTABLE:
|
||||||
case Lua.OP_EQ: tm = LuaValue.EQ; break;
|
tm = LuaValue.NEWINDEX;
|
||||||
case Lua.OP_ADD: tm = LuaValue.ADD; break;
|
break;
|
||||||
case Lua.OP_SUB: tm = LuaValue.SUB; break;
|
case Lua.OP_EQ:
|
||||||
case Lua.OP_MUL: tm = LuaValue.MUL; break;
|
tm = LuaValue.EQ;
|
||||||
case Lua.OP_DIV: tm = LuaValue.DIV; break;
|
break;
|
||||||
case Lua.OP_MOD: tm = LuaValue.MOD; break;
|
case Lua.OP_ADD:
|
||||||
case Lua.OP_POW: tm = LuaValue.POW; break;
|
tm = LuaValue.ADD;
|
||||||
case Lua.OP_UNM: tm = LuaValue.UNM; break;
|
break;
|
||||||
case Lua.OP_LEN: tm = LuaValue.LEN; break;
|
case Lua.OP_SUB:
|
||||||
case Lua.OP_LT: tm = LuaValue.LT; break;
|
tm = LuaValue.SUB;
|
||||||
case Lua.OP_LE: tm = LuaValue.LE; break;
|
break;
|
||||||
case Lua.OP_CONCAT: tm = LuaValue.CONCAT; break;
|
case Lua.OP_MUL:
|
||||||
|
tm = LuaValue.MUL;
|
||||||
|
break;
|
||||||
|
case Lua.OP_DIV:
|
||||||
|
tm = LuaValue.DIV;
|
||||||
|
break;
|
||||||
|
case Lua.OP_MOD:
|
||||||
|
tm = LuaValue.MOD;
|
||||||
|
break;
|
||||||
|
case Lua.OP_POW:
|
||||||
|
tm = LuaValue.POW;
|
||||||
|
break;
|
||||||
|
case Lua.OP_UNM:
|
||||||
|
tm = LuaValue.UNM;
|
||||||
|
break;
|
||||||
|
case Lua.OP_LEN:
|
||||||
|
tm = LuaValue.LEN;
|
||||||
|
break;
|
||||||
|
case Lua.OP_LT:
|
||||||
|
tm = LuaValue.LT;
|
||||||
|
break;
|
||||||
|
case Lua.OP_LE:
|
||||||
|
tm = LuaValue.LE;
|
||||||
|
break;
|
||||||
|
case Lua.OP_CONCAT:
|
||||||
|
tm = LuaValue.CONCAT;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return null; /* else no useful name can be found */
|
return null; /* else no useful name can be found */
|
||||||
}
|
}
|
||||||
@@ -810,8 +899,7 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
case Lua.OP_LOADK:
|
case Lua.OP_LOADK:
|
||||||
case Lua.OP_LOADKX: {
|
case Lua.OP_LOADKX: {
|
||||||
int b = (Lua.GET_OPCODE(i) == Lua.OP_LOADK) ? Lua.GETARG_Bx(i)
|
int b = (Lua.GET_OPCODE(i) == Lua.OP_LOADK)? Lua.GETARG_Bx(i): Lua.GETARG_Ax(p.code[pc+1]);
|
||||||
: Lua.GETARG_Ax(p.code[pc + 1]);
|
|
||||||
if (p.k[b].isstring()) {
|
if (p.k[b].isstring()) {
|
||||||
name = p.k[b].strvalue();
|
name = p.k[b].strvalue();
|
||||||
return new NameWhat(name.tojstring(), "constant");
|
return new NameWhat(name.tojstring(), "constant");
|
||||||
@@ -864,12 +952,14 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Lua.OP_TFORCALL: {
|
case Lua.OP_TFORCALL: {
|
||||||
if (reg >= a + 2) setreg = pc; /* affect all regs above its base */
|
if (reg >= a+2)
|
||||||
|
setreg = pc; /* affect all regs above its base */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Lua.OP_CALL:
|
case Lua.OP_CALL:
|
||||||
case Lua.OP_TAILCALL: {
|
case Lua.OP_TAILCALL: {
|
||||||
if (reg >= a) setreg = pc; /* affect all registers above base */
|
if (reg >= a)
|
||||||
|
setreg = pc; /* affect all registers above base */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Lua.OP_JMP: {
|
case Lua.OP_JMP: {
|
||||||
@@ -881,11 +971,13 @@ public class DebugLib extends TwoArgFunction {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Lua.OP_TEST: {
|
case Lua.OP_TEST: {
|
||||||
if (reg == a) setreg = pc; /* jumped code can change 'a' */
|
if (reg == a)
|
||||||
|
setreg = pc; /* jumped code can change 'a' */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Lua.OP_SETLIST: { // Lua.testAMode(Lua.OP_SETLIST) == false
|
case Lua.OP_SETLIST: { // Lua.testAMode(Lua.OP_SETLIST) == false
|
||||||
if ( ((i>>14)&0x1ff) == 0 ) pc++; // if c == 0 then c stored in next op -> skip
|
if (((i>>14) & 0x1ff) == 0)
|
||||||
|
pc++; // if c == 0 then c stored in next op -> skip
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -32,73 +32,96 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class extending {@link LibFunction} which implements the
|
* Abstract base class extending {@link LibFunction} which implements the core
|
||||||
* core of the lua standard {@code io} library.
|
* of the lua standard {@code io} library.
|
||||||
* <p>
|
* <p>
|
||||||
* It contains the implementation of the io library support that is common to
|
* It contains the implementation of the io library support that is common to
|
||||||
* the JSE and JME platforms.
|
* the JSE and JME platforms. In practice on of the concrete IOLib subclasses is
|
||||||
* In practice on of the concrete IOLib subclasses is chosen:
|
* chosen: {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and
|
||||||
* {@link org.luaj.vm2.lib.jse.JseIoLib} for the JSE platform, and
|
|
||||||
* {@link org.luaj.vm2.lib.jme.JmeIoLib} for the JME platform.
|
* {@link org.luaj.vm2.lib.jme.JmeIoLib} for the JME platform.
|
||||||
* <p>
|
* <p>
|
||||||
* The JSE implementation conforms almost completely to the C-based lua library,
|
* The JSE implementation conforms almost completely to the C-based lua library,
|
||||||
* while the JME implementation follows closely except in the area of random-access files,
|
* while the JME implementation follows closely except in the area of
|
||||||
* which are difficult to support properly on JME.
|
* random-access files, which are difficult to support properly on JME.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* <pre> {@code
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
||||||
* } </pre>
|
* }
|
||||||
* In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseIoLib} library will be loaded, which will include
|
* </pre>
|
||||||
* the base functionality provided by this class, whereas the {@link org.luaj.vm2.lib.jse.JsePlatform} would load the
|
*
|
||||||
* {@link org.luaj.vm2.lib.jse.JseIoLib}.
|
* In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseIoLib}
|
||||||
|
* library will be loaded, which will include the base functionality provided by
|
||||||
|
* this class, whereas the {@link org.luaj.vm2.lib.jse.JsePlatform} would load
|
||||||
|
* the {@link org.luaj.vm2.lib.jse.JseIoLib}.
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new OsLib());
|
* globals.load(new OsLib());
|
||||||
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see org.luaj.vm2.lib.jse.JseIoLib
|
* @see org.luaj.vm2.lib.jse.JseIoLib
|
||||||
* @see org.luaj.vm2.lib.jme.JmeIoLib
|
* @see org.luaj.vm2.lib.jme.JmeIoLib
|
||||||
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.7">http://www.lua.org/manual/5.1/manual.html#5.7</a>
|
* @see <a href=
|
||||||
|
* "http://www.lua.org/manual/5.1/manual.html#5.7">http://www.lua.org/manual/5.1/manual.html#5.7</a>
|
||||||
*/
|
*/
|
||||||
abstract
|
abstract public class IoLib extends TwoArgFunction {
|
||||||
public class IoLib extends TwoArgFunction {
|
|
||||||
|
|
||||||
abstract
|
abstract protected class File extends LuaValue {
|
||||||
protected class File extends LuaValue{
|
|
||||||
abstract public void write(LuaString string) throws IOException;
|
abstract public void write(LuaString string) throws IOException;
|
||||||
|
|
||||||
abstract public void flush() throws IOException;
|
abstract public void flush() throws IOException;
|
||||||
|
|
||||||
abstract public boolean isstdfile();
|
abstract public boolean isstdfile();
|
||||||
|
|
||||||
abstract public void close() throws IOException;
|
abstract public void close() throws IOException;
|
||||||
|
|
||||||
abstract public boolean isclosed();
|
abstract public boolean isclosed();
|
||||||
|
|
||||||
// returns new position
|
// returns new position
|
||||||
abstract public int seek(String option, int bytecount) throws IOException;
|
abstract public int seek(String option, int bytecount) throws IOException;
|
||||||
|
|
||||||
abstract public void setvbuf(String mode, int size);
|
abstract public void setvbuf(String mode, int size);
|
||||||
|
|
||||||
// get length remaining to read
|
// get length remaining to read
|
||||||
abstract public int remaining() throws IOException;
|
abstract public int remaining() throws IOException;
|
||||||
|
|
||||||
// peek ahead one character
|
// peek ahead one character
|
||||||
abstract public int peek() throws IOException, EOFException;
|
abstract public int peek() throws IOException, EOFException;
|
||||||
|
|
||||||
// return char if read, -1 if eof, throw IOException on other exception
|
// return char if read, -1 if eof, throw IOException on other exception
|
||||||
abstract public int read() throws IOException, EOFException;
|
abstract public int read() throws IOException, EOFException;
|
||||||
|
|
||||||
// return number of bytes read if positive, false if eof, throw IOException on other exception
|
// return number of bytes read if positive, false if eof, throw IOException on other exception
|
||||||
abstract public int read(byte[] bytes, int offset, int length) throws IOException;
|
abstract public int read(byte[] bytes, int offset, int length) throws IOException;
|
||||||
|
|
||||||
public boolean eof() throws IOException {
|
public boolean eof() throws IOException {
|
||||||
try {
|
try {
|
||||||
return peek() < 0;
|
return peek() < 0;
|
||||||
} catch (EOFException e) { return true; }
|
} catch (EOFException e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delegate method access to file methods table
|
// delegate method access to file methods table
|
||||||
@@ -110,6 +133,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
public int type() {
|
public int type() {
|
||||||
return LuaValue.TUSERDATA;
|
return LuaValue.TUSERDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String typename() {
|
public String typename() {
|
||||||
return "userdata";
|
return "userdata";
|
||||||
}
|
}
|
||||||
@@ -123,7 +147,8 @@ public class IoLib extends TwoArgFunction {
|
|||||||
if (!isclosed()) {
|
if (!isclosed()) {
|
||||||
try {
|
try {
|
||||||
close();
|
close();
|
||||||
} catch (IOException ignore) {}
|
} catch (IOException ignore) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,6 +164,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap the standard input.
|
* Wrap the standard input.
|
||||||
|
*
|
||||||
* @return File
|
* @return File
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@@ -146,6 +172,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap the standard output.
|
* Wrap the standard output.
|
||||||
|
*
|
||||||
* @return File
|
* @return File
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@@ -153,6 +180,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap the standard error output.
|
* Wrap the standard error output.
|
||||||
|
*
|
||||||
* @return File
|
* @return File
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@@ -160,6 +188,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a file in a particular mode.
|
* Open a file in a particular mode.
|
||||||
|
*
|
||||||
* @param filename
|
* @param filename
|
||||||
* @param readMode true if opening in read mode
|
* @param readMode true if opening in read mode
|
||||||
* @param appendMode true if opening in append mode
|
* @param appendMode true if opening in append mode
|
||||||
@@ -168,10 +197,12 @@ public class IoLib extends TwoArgFunction {
|
|||||||
* @return File object if successful
|
* @return File object if successful
|
||||||
* @throws IOException if could not be opened
|
* @throws IOException if could not be opened
|
||||||
*/
|
*/
|
||||||
abstract protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException;
|
abstract protected File openFile(String filename, boolean readMode, boolean appendMode, boolean updateMode,
|
||||||
|
boolean binaryMode) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a temporary file.
|
* Open a temporary file.
|
||||||
|
*
|
||||||
* @return File object if successful
|
* @return File object if successful
|
||||||
* @throws IOException if could not be opened
|
* @throws IOException if could not be opened
|
||||||
*/
|
*/
|
||||||
@@ -179,6 +210,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a new process and return a file for input or output
|
* Start a new process and return a file for input or output
|
||||||
|
*
|
||||||
* @param prog the program to execute
|
* @param prog the program to execute
|
||||||
* @param mode "r" to read, "w" to write
|
* @param mode "r" to read, "w" to write
|
||||||
* @return File to read to or write from
|
* @return File to read to or write from
|
||||||
@@ -219,29 +251,10 @@ public class IoLib extends TwoArgFunction {
|
|||||||
private static final int IO_INDEX = 18;
|
private static final int IO_INDEX = 18;
|
||||||
private static final int LINES_ITER = 19;
|
private static final int LINES_ITER = 19;
|
||||||
|
|
||||||
public static final String[] IO_NAMES = {
|
public static final String[] IO_NAMES = { "close", "flush", "input", "lines", "open", "output", "popen", "read",
|
||||||
"close",
|
"tmpfile", "type", "write", };
|
||||||
"flush",
|
|
||||||
"input",
|
|
||||||
"lines",
|
|
||||||
"open",
|
|
||||||
"output",
|
|
||||||
"popen",
|
|
||||||
"read",
|
|
||||||
"tmpfile",
|
|
||||||
"type",
|
|
||||||
"write",
|
|
||||||
};
|
|
||||||
|
|
||||||
public static final String[] FILE_NAMES = {
|
public static final String[] FILE_NAMES = { "close", "flush", "lines", "read", "seek", "setvbuf", "write", };
|
||||||
"close",
|
|
||||||
"flush",
|
|
||||||
"lines",
|
|
||||||
"read",
|
|
||||||
"seek",
|
|
||||||
"setvbuf",
|
|
||||||
"write",
|
|
||||||
};
|
|
||||||
|
|
||||||
LuaTable filemethods;
|
LuaTable filemethods;
|
||||||
|
|
||||||
@@ -270,7 +283,8 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
// return the table
|
// return the table
|
||||||
env.set("io", t);
|
env.set("io", t);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("io", t);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("io", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,13 +299,16 @@ public class IoLib extends TwoArgFunction {
|
|||||||
public IoLib iolib;
|
public IoLib iolib;
|
||||||
private boolean toclose;
|
private boolean toclose;
|
||||||
private Varargs args;
|
private Varargs args;
|
||||||
|
|
||||||
public IoLibV() {
|
public IoLibV() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public IoLibV(File f, String name, int opcode, IoLib iolib, boolean toclose, Varargs args) {
|
public IoLibV(File f, String name, int opcode, IoLib iolib, boolean toclose, Varargs args) {
|
||||||
this(f, name, opcode, iolib);
|
this(f, name, opcode, iolib);
|
||||||
this.toclose = toclose;
|
this.toclose = toclose;
|
||||||
this.args = args.dealias();
|
this.args = args.dealias();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IoLibV(File f, String name, int opcode, IoLib iolib) {
|
public IoLibV(File f, String name, int opcode, IoLib iolib) {
|
||||||
super();
|
super();
|
||||||
this.f = f;
|
this.f = f;
|
||||||
@@ -303,28 +320,48 @@ public class IoLib extends TwoArgFunction {
|
|||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
try {
|
try {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case IO_FLUSH: return iolib._io_flush();
|
case IO_FLUSH:
|
||||||
case IO_TMPFILE: return iolib._io_tmpfile();
|
return iolib._io_flush();
|
||||||
case IO_CLOSE: return iolib._io_close(args.arg1());
|
case IO_TMPFILE:
|
||||||
case IO_INPUT: return iolib._io_input(args.arg1());
|
return iolib._io_tmpfile();
|
||||||
case IO_OUTPUT: return iolib._io_output(args.arg1());
|
case IO_CLOSE:
|
||||||
case IO_TYPE: return iolib._io_type(args.arg1());
|
return iolib._io_close(args.arg1());
|
||||||
case IO_POPEN: return iolib._io_popen(args.checkjstring(1),args.optjstring(2,"r"));
|
case IO_INPUT:
|
||||||
case IO_OPEN: return iolib._io_open(args.checkjstring(1), args.optjstring(2,"r"));
|
return iolib._io_input(args.arg1());
|
||||||
case IO_LINES: return iolib._io_lines(args);
|
case IO_OUTPUT:
|
||||||
case IO_READ: return iolib._io_read(args);
|
return iolib._io_output(args.arg1());
|
||||||
case IO_WRITE: return iolib._io_write(args);
|
case IO_TYPE:
|
||||||
|
return iolib._io_type(args.arg1());
|
||||||
|
case IO_POPEN:
|
||||||
|
return iolib._io_popen(args.checkjstring(1), args.optjstring(2, "r"));
|
||||||
|
case IO_OPEN:
|
||||||
|
return iolib._io_open(args.checkjstring(1), args.optjstring(2, "r"));
|
||||||
|
case IO_LINES:
|
||||||
|
return iolib._io_lines(args);
|
||||||
|
case IO_READ:
|
||||||
|
return iolib._io_read(args);
|
||||||
|
case IO_WRITE:
|
||||||
|
return iolib._io_write(args);
|
||||||
|
|
||||||
case FILE_CLOSE: return iolib._file_close(args.arg1());
|
case FILE_CLOSE:
|
||||||
case FILE_FLUSH: return iolib._file_flush(args.arg1());
|
return iolib._file_close(args.arg1());
|
||||||
case FILE_SETVBUF: return iolib._file_setvbuf(args.arg1(),args.checkjstring(2),args.optint(3,8192));
|
case FILE_FLUSH:
|
||||||
case FILE_LINES: return iolib._file_lines(args);
|
return iolib._file_flush(args.arg1());
|
||||||
case FILE_READ: return iolib._file_read(args.arg1(),args.subargs(2));
|
case FILE_SETVBUF:
|
||||||
case FILE_SEEK: return iolib._file_seek(args.arg1(),args.optjstring(2,"cur"),args.optint(3,0));
|
return iolib._file_setvbuf(args.arg1(), args.checkjstring(2), args.optint(3, 8192));
|
||||||
case FILE_WRITE: return iolib._file_write(args.arg1(),args.subargs(2));
|
case FILE_LINES:
|
||||||
|
return iolib._file_lines(args);
|
||||||
|
case FILE_READ:
|
||||||
|
return iolib._file_read(args.arg1(), args.subargs(2));
|
||||||
|
case FILE_SEEK:
|
||||||
|
return iolib._file_seek(args.arg1(), args.optjstring(2, "cur"), args.optint(3, 0));
|
||||||
|
case FILE_WRITE:
|
||||||
|
return iolib._file_write(args.arg1(), args.subargs(2));
|
||||||
|
|
||||||
case IO_INDEX: return iolib._io_index(args.arg(2));
|
case IO_INDEX:
|
||||||
case LINES_ITER: return iolib._lines_iter(f, toclose, this.args);
|
return iolib._io_index(args.arg(2));
|
||||||
|
case LINES_ITER:
|
||||||
|
return iolib._lines_iter(f, toclose, this.args);
|
||||||
}
|
}
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (opcode == LINES_ITER) {
|
if (opcode == LINES_ITER) {
|
||||||
@@ -362,31 +399,28 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
// io.input([file]) -> file
|
// io.input([file]) -> file
|
||||||
public Varargs _io_input(LuaValue file) {
|
public Varargs _io_input(LuaValue file) {
|
||||||
infile = file.isnil()? input():
|
infile = file.isnil()? input()
|
||||||
file.isstring()? ioopenfile(FTYPE_NAMED, file.checkjstring(),"r"):
|
: file.isstring()? ioopenfile(FTYPE_NAMED, file.checkjstring(), "r"): checkfile(file);
|
||||||
checkfile(file);
|
|
||||||
return infile;
|
return infile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// io.output(filename) -> file
|
// io.output(filename) -> file
|
||||||
public Varargs _io_output(LuaValue filename) {
|
public Varargs _io_output(LuaValue filename) {
|
||||||
outfile = filename.isnil()? output():
|
outfile = filename.isnil()? output()
|
||||||
filename.isstring()? ioopenfile(FTYPE_NAMED, filename.checkjstring(),"w"):
|
: filename.isstring()? ioopenfile(FTYPE_NAMED, filename.checkjstring(), "w"): checkfile(filename);
|
||||||
checkfile(filename);
|
|
||||||
return outfile;
|
return outfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// io.type(obj) -> "file" | "closed file" | nil
|
// io.type(obj) -> "file" | "closed file" | nil
|
||||||
public Varargs _io_type(LuaValue obj) {
|
public Varargs _io_type(LuaValue obj) {
|
||||||
File f = optfile(obj);
|
File f = optfile(obj);
|
||||||
return f!=null?
|
return f != null? f.isclosed()? CLOSED_FILE: FILE: NIL;
|
||||||
f.isclosed()? CLOSED_FILE: FILE:
|
|
||||||
NIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// io.popen(prog, [mode]) -> file
|
// io.popen(prog, [mode]) -> file
|
||||||
public Varargs _io_popen(String prog, String mode) throws IOException {
|
public Varargs _io_popen(String prog, String mode) throws IOException {
|
||||||
if (!"r".equals(mode) && !"w".equals(mode)) argerror(2, "invalid value: '" + mode + "'; must be one of 'r' or 'w'");
|
if (!"r".equals(mode) && !"w".equals(mode))
|
||||||
|
argerror(2, "invalid value: '" + mode + "'; must be one of 'r' or 'w'");
|
||||||
return openProgram(prog, mode);
|
return openProgram(prog, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -466,18 +500,19 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
// __index, returns a field
|
// __index, returns a field
|
||||||
public Varargs _io_index(LuaValue v) {
|
public Varargs _io_index(LuaValue v) {
|
||||||
return v.equals(STDOUT)?output():
|
return v.equals(STDOUT)? output(): v.equals(STDIN)? input(): v.equals(STDERR)? errput(): NIL;
|
||||||
v.equals(STDIN)? input():
|
|
||||||
v.equals(STDERR)? errput(): NIL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// lines iterator(s,var) -> var'
|
// lines iterator(s,var) -> var'
|
||||||
public Varargs _lines_iter(LuaValue file, boolean toclose, Varargs args) throws IOException {
|
public Varargs _lines_iter(LuaValue file, boolean toclose, Varargs args) throws IOException {
|
||||||
File f = optfile(file);
|
File f = optfile(file);
|
||||||
if ( f == null ) argerror(1, "not a file: " + file);
|
if (f == null)
|
||||||
if ( f.isclosed() ) error("file is already closed");
|
argerror(1, "not a file: " + file);
|
||||||
|
if (f.isclosed())
|
||||||
|
error("file is already closed");
|
||||||
Varargs ret = ioread(f, args);
|
Varargs ret = ioread(f, args);
|
||||||
if (toclose && ret.isnil(1) && f.eof()) f.close();
|
if (toclose && ret.isnil(1) && f.eof())
|
||||||
|
f.close();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +571,8 @@ public class IoLib extends TwoArgFunction {
|
|||||||
|
|
||||||
private Varargs ioread(File f, Varargs args) throws IOException {
|
private Varargs ioread(File f, Varargs args) throws IOException {
|
||||||
int i, n = args.narg();
|
int i, n = args.narg();
|
||||||
if (n == 0) return freadline(f,false);
|
if (n == 0)
|
||||||
|
return freadline(f, false);
|
||||||
LuaValue[] v = new LuaValue[n];
|
LuaValue[] v = new LuaValue[n];
|
||||||
LuaValue ai, vi;
|
LuaValue ai, vi;
|
||||||
LuaString fmt;
|
LuaString fmt;
|
||||||
@@ -549,10 +585,18 @@ public class IoLib extends TwoArgFunction {
|
|||||||
fmt = ai.checkstring();
|
fmt = ai.checkstring();
|
||||||
if (fmt.m_length >= 2 && fmt.m_bytes[fmt.m_offset] == '*') {
|
if (fmt.m_length >= 2 && fmt.m_bytes[fmt.m_offset] == '*') {
|
||||||
switch (fmt.m_bytes[fmt.m_offset+1]) {
|
switch (fmt.m_bytes[fmt.m_offset+1]) {
|
||||||
case 'n': vi = freadnumber(f); break item;
|
case 'n':
|
||||||
case 'l': vi = freadline(f,false); break item;
|
vi = freadnumber(f);
|
||||||
case 'L': vi = freadline(f,true); break item;
|
break item;
|
||||||
case 'a': vi = freadall(f); break item;
|
case 'l':
|
||||||
|
vi = freadline(f, false);
|
||||||
|
break item;
|
||||||
|
case 'L':
|
||||||
|
vi = freadline(f, true);
|
||||||
|
break item;
|
||||||
|
case 'a':
|
||||||
|
vi = freadall(f);
|
||||||
|
break item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -586,18 +630,25 @@ public class IoLib extends TwoArgFunction {
|
|||||||
int len = mode.length();
|
int len = mode.length();
|
||||||
for (int i = 0; i < len; i++) { // [rwa][+]?b*
|
for (int i = 0; i < len; i++) { // [rwa][+]?b*
|
||||||
char ch = mode.charAt(i);
|
char ch = mode.charAt(i);
|
||||||
if (i == 0 && "rwa".indexOf(ch) >= 0) continue;
|
if (i == 0 && "rwa".indexOf(ch) >= 0)
|
||||||
if (i == 1 && ch == '+') continue;
|
continue;
|
||||||
if (i >= 1 && ch == 'b') continue;
|
if (i == 1 && ch == '+')
|
||||||
|
continue;
|
||||||
|
if (i >= 1 && ch == 'b')
|
||||||
|
continue;
|
||||||
len = -1;
|
len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (len <= 0) argerror(2, "invalid mode: '" + mode + "'");
|
if (len <= 0)
|
||||||
|
argerror(2, "invalid mode: '" + mode + "'");
|
||||||
|
|
||||||
switch (filetype) {
|
switch (filetype) {
|
||||||
case FTYPE_STDIN: return wrapStdin();
|
case FTYPE_STDIN:
|
||||||
case FTYPE_STDOUT: return wrapStdout();
|
return wrapStdin();
|
||||||
case FTYPE_STDERR: return wrapStderr();
|
case FTYPE_STDOUT:
|
||||||
|
return wrapStdout();
|
||||||
|
case FTYPE_STDERR:
|
||||||
|
return wrapStderr();
|
||||||
}
|
}
|
||||||
boolean isreadmode = mode.startsWith("r");
|
boolean isreadmode = mode.startsWith("r");
|
||||||
boolean isappend = mode.startsWith("a");
|
boolean isappend = mode.startsWith("a");
|
||||||
@@ -606,17 +657,18 @@ public class IoLib extends TwoArgFunction {
|
|||||||
return openFile(filename, isreadmode, isappend, isupdate, isbinary);
|
return openFile(filename, isreadmode, isappend, isupdate, isbinary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------- file reading utilitied ------------------
|
// ------------- file reading utilitied ------------------
|
||||||
|
|
||||||
public static LuaValue freadbytes(File f, int count) throws IOException {
|
public static LuaValue freadbytes(File f, int count) throws IOException {
|
||||||
if (count == 0) return f.eof() ? NIL : EMPTYSTRING;
|
if (count == 0)
|
||||||
|
return f.eof()? NIL: EMPTYSTRING;
|
||||||
byte[] b = new byte[count];
|
byte[] b = new byte[count];
|
||||||
int r;
|
int r;
|
||||||
if ((r = f.read(b, 0, b.length)) < 0)
|
if ((r = f.read(b, 0, b.length)) < 0)
|
||||||
return NIL;
|
return NIL;
|
||||||
return LuaString.valueUsing(b, 0, r);
|
return LuaString.valueUsing(b, 0, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LuaValue freaduntil(File f, boolean lineonly, boolean withend) throws IOException {
|
public static LuaValue freaduntil(File f, boolean lineonly, boolean withend) throws IOException {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
int c;
|
int c;
|
||||||
@@ -624,9 +676,17 @@ public class IoLib extends TwoArgFunction {
|
|||||||
if (lineonly) {
|
if (lineonly) {
|
||||||
loop: while ( (c = f.read()) >= 0 ) {
|
loop: while ( (c = f.read()) >= 0 ) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\r': if (withend) baos.write(c); break;
|
case '\r':
|
||||||
case '\n': if (withend) baos.write(c); break loop;
|
if (withend)
|
||||||
default: baos.write(c); break;
|
baos.write(c);
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
if (withend)
|
||||||
|
baos.write(c);
|
||||||
|
break loop;
|
||||||
|
default:
|
||||||
|
baos.write(c);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -636,13 +696,13 @@ public class IoLib extends TwoArgFunction {
|
|||||||
} catch (EOFException e) {
|
} catch (EOFException e) {
|
||||||
c = -1;
|
c = -1;
|
||||||
}
|
}
|
||||||
return ( c < 0 && baos.size() == 0 )?
|
return (c < 0 && baos.size() == 0)? (LuaValue) NIL: (LuaValue) LuaString.valueUsing(baos.toByteArray());
|
||||||
(LuaValue) NIL:
|
|
||||||
(LuaValue) LuaString.valueUsing(baos.toByteArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LuaValue freadline(File f, boolean withend) throws IOException {
|
public static LuaValue freadline(File f, boolean withend) throws IOException {
|
||||||
return freaduntil(f, true, withend);
|
return freaduntil(f, true, withend);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LuaValue freadall(File f) throws IOException {
|
public static LuaValue freadall(File f) throws IOException {
|
||||||
int n = f.remaining();
|
int n = f.remaining();
|
||||||
if (n >= 0) {
|
if (n >= 0) {
|
||||||
@@ -651,6 +711,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
return freaduntil(f, false, false);
|
return freaduntil(f, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LuaValue freadnumber(File f) throws IOException {
|
public static LuaValue freadnumber(File f) throws IOException {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
freadchars(f, " \t\r\n", null);
|
freadchars(f, " \t\r\n", null);
|
||||||
@@ -666,6 +727,7 @@ public class IoLib extends TwoArgFunction {
|
|||||||
String s = baos.toString();
|
String s = baos.toString();
|
||||||
return s.length() > 0? valueOf(Double.parseDouble(s)): NIL;
|
return s.length() > 0? valueOf(Double.parseDouble(s)): NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void freadchars(File f, String chars, ByteArrayOutputStream baos) throws IOException {
|
private static void freadchars(File f, String chars, ByteArrayOutputStream baos) throws IOException {
|
||||||
int c;
|
int c;
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
@@ -679,6 +741,4 @@ public class IoLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,20 +29,20 @@ import org.luaj.vm2.Varargs;
|
|||||||
/**
|
/**
|
||||||
* Subclass of {@link LuaFunction} common to Java functions exposed to lua.
|
* Subclass of {@link LuaFunction} common to Java functions exposed to lua.
|
||||||
* <p>
|
* <p>
|
||||||
* To provide for common implementations in JME and JSE,
|
* To provide for common implementations in JME and JSE, library functions are
|
||||||
* library functions are typically grouped on one or more library classes
|
* typically grouped on one or more library classes and an opcode per library
|
||||||
* and an opcode per library function is defined and used to key the switch
|
* function is defined and used to key the switch to the correct function within
|
||||||
* to the correct function within the library.
|
* the library.
|
||||||
* <p>
|
* <p>
|
||||||
* Since lua functions can be called with too few or too many arguments,
|
* Since lua functions can be called with too few or too many arguments, and
|
||||||
* and there are overloaded {@link LuaValue#call()} functions with varying
|
* there are overloaded {@link LuaValue#call()} functions with varying number of
|
||||||
* number of arguments, a Java function exposed in lua needs to handle the
|
* arguments, a Java function exposed in lua needs to handle the argument fixup
|
||||||
* argument fixup when a function is called with a number of arguments
|
* when a function is called with a number of arguments differs from that
|
||||||
* differs from that expected.
|
* expected.
|
||||||
* <p>
|
* <p>
|
||||||
* To simplify the creation of library functions,
|
* To simplify the creation of library functions, there are 5 direct subclasses
|
||||||
* there are 5 direct subclasses to handle common cases based on number of
|
* to handle common cases based on number of argument values and number of
|
||||||
* argument values and number of return return values.
|
* return return values.
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link ZeroArgFunction}</li>
|
* <li>{@link ZeroArgFunction}</li>
|
||||||
* <li>{@link OneArgFunction}</li>
|
* <li>{@link OneArgFunction}</li>
|
||||||
@@ -51,13 +51,15 @@ import org.luaj.vm2.Varargs;
|
|||||||
* <li>{@link VarArgFunction}</li>
|
* <li>{@link VarArgFunction}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* To be a Java library that can be loaded via {@code require}, it should have
|
* To be a Java library that can be loaded via {@code require}, it should have a
|
||||||
* a public constructor that returns a {@link LuaValue} that, when executed,
|
* public constructor that returns a {@link LuaValue} that, when executed,
|
||||||
* initializes the library.
|
* initializes the library.
|
||||||
* <p>
|
* <p>
|
||||||
* For example, the following code will implement a library called "hyperbolic"
|
* For example, the following code will implement a library called "hyperbolic"
|
||||||
* with two functions, "sinh", and "cosh":
|
* with two functions, "sinh", and "cosh":
|
||||||
<pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* import org.luaj.vm2.LuaValue;
|
* import org.luaj.vm2.LuaValue;
|
||||||
* import org.luaj.vm2.lib.*;
|
* import org.luaj.vm2.lib.*;
|
||||||
*
|
*
|
||||||
@@ -85,18 +87,22 @@ import org.luaj.vm2.Varargs;
|
|||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*}
|
*}
|
||||||
*}</pre>
|
*}
|
||||||
* The default constructor is used to instantiate the library
|
* </pre>
|
||||||
* in response to {@code require 'hyperbolic'} statement,
|
*
|
||||||
* provided it is on Java"s class path.
|
* The default constructor is used to instantiate the library in response to
|
||||||
* This instance is then invoked with 2 arguments: the name supplied to require(),
|
* {@code require 'hyperbolic'} statement, provided it is on Java"s class
|
||||||
* and the environment for this function. The library may ignore these, or use
|
* path. This instance is then invoked with 2 arguments: the name supplied to
|
||||||
* them to leave side effects in the global environment, for example.
|
* require(), and the environment for this function. The library may ignore
|
||||||
* In the previous example, two functions are created, 'sinh', and 'cosh', and placed
|
* these, or use them to leave side effects in the global environment, for
|
||||||
* into a global table called 'hyperbolic' using the supplied 'env' argument.
|
* example. In the previous example, two functions are created, 'sinh', and
|
||||||
|
* 'cosh', and placed into a global table called 'hyperbolic' using the supplied
|
||||||
|
* 'env' argument.
|
||||||
* <p>
|
* <p>
|
||||||
* To test it, a script such as this can be used:
|
* To test it, a script such as this can be used:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* local t = require('hyperbolic')
|
* local t = require('hyperbolic')
|
||||||
* print( 't', t )
|
* print( 't', t )
|
||||||
* print( 'hyperbolic', hyperbolic )
|
* print( 'hyperbolic', hyperbolic )
|
||||||
@@ -105,30 +111,38 @@ import org.luaj.vm2.Varargs;
|
|||||||
* end
|
* end
|
||||||
* print( 'sinh(.5)', hyperbolic.sinh(.5) )
|
* print( 'sinh(.5)', hyperbolic.sinh(.5) )
|
||||||
* print( 'cosh(.5)', hyperbolic.cosh(.5) )
|
* print( 'cosh(.5)', hyperbolic.cosh(.5) )
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* It should produce something like:
|
* It should produce something like:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* t table: 3dbbd23f
|
* t table: 3dbbd23f
|
||||||
* hyperbolic table: 3dbbd23f
|
* hyperbolic table: 3dbbd23f
|
||||||
* k,v cosh function: 3dbbd128
|
* k,v cosh function: 3dbbd128
|
||||||
* k,v sinh function: 3dbbd242
|
* k,v sinh function: 3dbbd242
|
||||||
* sinh(.5) 0.5210953
|
* sinh(.5) 0.5210953
|
||||||
* cosh(.5) 1.127626
|
* cosh(.5) 1.127626
|
||||||
* }</pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* See the source code in any of the library functions
|
* See the source code in any of the library functions such as {@link BaseLib}
|
||||||
* such as {@link BaseLib} or {@link TableLib} for other examples.
|
* or {@link TableLib} for other examples.
|
||||||
*/
|
*/
|
||||||
abstract public class LibFunction extends LuaFunction {
|
abstract public class LibFunction extends LuaFunction {
|
||||||
|
|
||||||
/** User-defined opcode to differentiate between instances of the library function class.
|
/**
|
||||||
|
* User-defined opcode to differentiate between instances of the library
|
||||||
|
* function class.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclass will typicall switch on this value to provide the specific behavior for each function.
|
* Subclass will typicall switch on this value to provide the specific
|
||||||
|
* behavior for each function.
|
||||||
*/
|
*/
|
||||||
protected int opcode;
|
protected int opcode;
|
||||||
|
|
||||||
/** The common name for this function, useful for debugging.
|
/**
|
||||||
|
* The common name for this function, useful for debugging.
|
||||||
* <p>
|
* <p>
|
||||||
* Binding functions initialize this to the name to which it is bound.
|
* Binding functions initialize this to the name to which it is bound.
|
||||||
*/
|
*/
|
||||||
@@ -145,8 +159,9 @@ abstract public class LibFunction extends LuaFunction {
|
|||||||
/**
|
/**
|
||||||
* Bind a set of library functions.
|
* Bind a set of library functions.
|
||||||
* <p>
|
* <p>
|
||||||
* An array of names is provided, and the first name is bound
|
* An array of names is provided, and the first name is bound with opcode =
|
||||||
* with opcode = 0, second with 1, etc.
|
* 0, second with 1, etc.
|
||||||
|
*
|
||||||
* @param env The environment to apply to each bound function
|
* @param env The environment to apply to each bound function
|
||||||
* @param factory the Class to instantiate for each bound function
|
* @param factory the Class to instantiate for each bound function
|
||||||
* @param names array of String names, one for each function.
|
* @param names array of String names, one for each function.
|
||||||
@@ -159,8 +174,9 @@ abstract public class LibFunction extends LuaFunction {
|
|||||||
/**
|
/**
|
||||||
* Bind a set of library functions, with an offset
|
* Bind a set of library functions, with an offset
|
||||||
* <p>
|
* <p>
|
||||||
* An array of names is provided, and the first name is bound
|
* An array of names is provided, and the first name is bound with opcode =
|
||||||
* with opcode = {@code firstopcode}, second with {@code firstopcode+1}, etc.
|
* {@code firstopcode}, second with {@code firstopcode+1}, etc.
|
||||||
|
*
|
||||||
* @param env The environment to apply to each bound function
|
* @param env The environment to apply to each bound function
|
||||||
* @param factory the Class to instantiate for each bound function
|
* @param factory the Class to instantiate for each bound function
|
||||||
* @param names array of String names, one for each function.
|
* @param names array of String names, one for each function.
|
||||||
@@ -180,17 +196,26 @@ abstract public class LibFunction extends LuaFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Java code generation utility to allocate storage for upvalue, leave it empty */
|
/**
|
||||||
|
* Java code generation utility to allocate storage for upvalue, leave it
|
||||||
|
* empty
|
||||||
|
*/
|
||||||
protected static LuaValue[] newupe() {
|
protected static LuaValue[] newupe() {
|
||||||
return new LuaValue[1];
|
return new LuaValue[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Java code generation utility to allocate storage for upvalue, initialize with nil */
|
/**
|
||||||
|
* Java code generation utility to allocate storage for upvalue, initialize
|
||||||
|
* with nil
|
||||||
|
*/
|
||||||
protected static LuaValue[] newupn() {
|
protected static LuaValue[] newupn() {
|
||||||
return new LuaValue[] { NIL };
|
return new LuaValue[] { NIL };
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Java code generation utility to allocate storage for upvalue, initialize with value */
|
/**
|
||||||
|
* Java code generation utility to allocate storage for upvalue, initialize
|
||||||
|
* with value
|
||||||
|
*/
|
||||||
protected static LuaValue[] newupl(LuaValue v) {
|
protected static LuaValue[] newupl(LuaValue v) {
|
||||||
return new LuaValue[] { v };
|
return new LuaValue[] { v };
|
||||||
}
|
}
|
||||||
@@ -198,25 +223,35 @@ abstract public class LibFunction extends LuaFunction {
|
|||||||
public LuaValue call() {
|
public LuaValue call() {
|
||||||
return argerror(1, "value expected");
|
return argerror(1, "value expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue a) {
|
public LuaValue call(LuaValue a) {
|
||||||
return call();
|
return call();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue a, LuaValue b) {
|
public LuaValue call(LuaValue a, LuaValue b) {
|
||||||
return call(a);
|
return call(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue a, LuaValue b, LuaValue c) {
|
public LuaValue call(LuaValue a, LuaValue b, LuaValue c) {
|
||||||
return call(a, b);
|
return call(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue a, LuaValue b, LuaValue c, LuaValue d) {
|
public LuaValue call(LuaValue a, LuaValue b, LuaValue c, LuaValue d) {
|
||||||
return call(a, b, c);
|
return call(a, b, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
switch (args.narg()) {
|
switch (args.narg()) {
|
||||||
case 0: return call();
|
case 0:
|
||||||
case 1: return call(args.arg1());
|
return call();
|
||||||
case 2: return call(args.arg1(),args.arg(2));
|
case 1:
|
||||||
case 3: return call(args.arg1(),args.arg(2),args.arg(3));
|
return call(args.arg1());
|
||||||
default: return call(args.arg1(),args.arg(2),args.arg(3),args.arg(4));
|
case 2:
|
||||||
|
return call(args.arg1(), args.arg(2));
|
||||||
|
case 3:
|
||||||
|
return call(args.arg1(), args.arg(2), args.arg(3));
|
||||||
|
default:
|
||||||
|
return call(args.arg1(), args.arg(2), args.arg(3), args.arg(4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
|
* Subclass of {@link LibFunction} which implements the lua standard
|
||||||
* library.
|
* {@code math} library.
|
||||||
* <p>
|
* <p>
|
||||||
* It contains only the math library support that is possible on JME.
|
* It contains only the math library support that is possible on JME. For a more
|
||||||
* For a more complete implementation based on math functions specific to JSE
|
* complete implementation based on math functions specific to JSE use
|
||||||
* use {@link org.luaj.vm2.lib.jse.JseMathLib}.
|
* {@link org.luaj.vm2.lib.jse.JseMathLib}. In Particular the following math
|
||||||
* In Particular the following math functions are <b>not</b> implemented by this library:
|
* functions are <b>not</b> implemented by this library:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>acos</li>
|
* <li>acos</li>
|
||||||
* <li>asin</li>
|
* <li>asin</li>
|
||||||
@@ -48,57 +48,78 @@ import org.luaj.vm2.Varargs;
|
|||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* The implementations of {@code exp()} and {@code pow()} are constructed by
|
* The implementations of {@code exp()} and {@code pow()} are constructed by
|
||||||
* hand for JME, so will be slower and less accurate than when executed on the JSE platform.
|
* hand for JME, so will be slower and less accurate than when executed on the
|
||||||
|
* JSE platform.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
||||||
* } </pre>
|
* }
|
||||||
* When using {@link org.luaj.vm2.lib.jse.JsePlatform} as in this example,
|
* </pre>
|
||||||
* the subclass {@link org.luaj.vm2.lib.jse.JseMathLib} will
|
*
|
||||||
* be included, which also includes this base functionality.
|
* When using {@link org.luaj.vm2.lib.jse.JsePlatform} as in this example, the
|
||||||
|
* subclass {@link org.luaj.vm2.lib.jse.JseMathLib} will be included, which also
|
||||||
|
* includes this base functionality.
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new MathLib());
|
* globals.load(new MathLib());
|
||||||
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
||||||
* } </pre>
|
* }
|
||||||
* Doing so will ensure the library is properly initialized
|
* </pre>
|
||||||
* and loaded into the globals table.
|
*
|
||||||
|
* Doing so will ensure the library is properly initialized and loaded into the
|
||||||
|
* globals table.
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see org.luaj.vm2.lib.jse.JseMathLib
|
* @see org.luaj.vm2.lib.jse.JseMathLib
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.6">Lua 5.2 Math Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.6">Lua 5.2 Math Lib
|
||||||
|
* Reference</a>
|
||||||
*/
|
*/
|
||||||
public class MathLib extends TwoArgFunction {
|
public class MathLib extends TwoArgFunction {
|
||||||
|
|
||||||
/** Pointer to the latest MathLib instance, used only to dispatch
|
/**
|
||||||
* math.exp to tha correct platform math library.
|
* Pointer to the latest MathLib instance, used only to dispatch math.exp to
|
||||||
|
* tha correct platform math library.
|
||||||
*/
|
*/
|
||||||
public static MathLib MATHLIB = null;
|
public static MathLib MATHLIB = null;
|
||||||
|
|
||||||
/** Construct a MathLib, which can be initialized by calling it with a
|
/**
|
||||||
|
* Construct a MathLib, which can be initialized by calling it with a
|
||||||
* modname string, and a global environment table as arguments using
|
* modname string, and a global environment table as arguments using
|
||||||
* {@link #call(LuaValue, LuaValue)}. */
|
* {@link #call(LuaValue, LuaValue)}.
|
||||||
|
*/
|
||||||
public MathLib() {
|
public MathLib() {
|
||||||
MATHLIB = this;
|
MATHLIB = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by creating a table
|
/**
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* Perform one-time initialization on the library by creating a table
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* containing the library functions, adding that table to the supplied
|
||||||
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
|
* the return value.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, typically a Globals instance.
|
* @param env the environment to load into, typically a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
LuaTable math = new LuaTable(0, 30);
|
LuaTable math = new LuaTable(0, 30);
|
||||||
@@ -125,7 +146,8 @@ public class MathLib extends TwoArgFunction {
|
|||||||
math.set("sqrt", new sqrt());
|
math.set("sqrt", new sqrt());
|
||||||
math.set("tan", new tan());
|
math.set("tan", new tan());
|
||||||
env.set("math", math);
|
env.set("math", math);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("math", math);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("math", math);
|
||||||
return math;
|
return math;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +155,7 @@ public class MathLib extends TwoArgFunction {
|
|||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
return valueOf(call(arg.checkdouble()));
|
return valueOf(call(arg.checkdouble()));
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected double call(double d);
|
abstract protected double call(double d);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,24 +163,53 @@ public class MathLib extends TwoArgFunction {
|
|||||||
public LuaValue call(LuaValue x, LuaValue y) {
|
public LuaValue call(LuaValue x, LuaValue y) {
|
||||||
return valueOf(call(x.checkdouble(), y.checkdouble()));
|
return valueOf(call(x.checkdouble(), y.checkdouble()));
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected double call(double x, double y);
|
abstract protected double call(double x, double y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class abs extends UnaryOp { protected double call(double d) { return Math.abs(d); } }
|
static final class abs extends UnaryOp {
|
||||||
static final class ceil extends UnaryOp { protected double call(double d) { return Math.ceil(d); } }
|
protected double call(double d) { return Math.abs(d); }
|
||||||
static final class cos extends UnaryOp { protected double call(double d) { return Math.cos(d); } }
|
}
|
||||||
static final class deg extends UnaryOp { protected double call(double d) { return Math.toDegrees(d); } }
|
|
||||||
static final class floor extends UnaryOp { protected double call(double d) { return Math.floor(d); } }
|
static final class ceil extends UnaryOp {
|
||||||
static final class rad extends UnaryOp { protected double call(double d) { return Math.toRadians(d); } }
|
protected double call(double d) { return Math.ceil(d); }
|
||||||
static final class sin extends UnaryOp { protected double call(double d) { return Math.sin(d); } }
|
}
|
||||||
static final class sqrt extends UnaryOp { protected double call(double d) { return Math.sqrt(d); } }
|
|
||||||
static final class tan extends UnaryOp { protected double call(double d) { return Math.tan(d); } }
|
static final class cos extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.cos(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class deg extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.toDegrees(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class floor extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.floor(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class rad extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.toRadians(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class sin extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.sin(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class sqrt extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.sqrt(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class tan extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.tan(d); }
|
||||||
|
}
|
||||||
|
|
||||||
static final class exp extends UnaryOp {
|
static final class exp extends UnaryOp {
|
||||||
final MathLib mathlib;
|
final MathLib mathlib;
|
||||||
|
|
||||||
exp(MathLib mathlib) {
|
exp(MathLib mathlib) {
|
||||||
this.mathlib = mathlib;
|
this.mathlib = mathlib;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected double call(double d) {
|
protected double call(double d) {
|
||||||
return mathlib.dpow_lib(Math.E, d);
|
return mathlib.dpow_lib(Math.E, d);
|
||||||
}
|
}
|
||||||
@@ -171,12 +223,14 @@ public class MathLib extends TwoArgFunction {
|
|||||||
return valueOf(xv.checkdouble()%yv.checkdouble());
|
return valueOf(xv.checkdouble()%yv.checkdouble());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class ldexp extends BinaryOp {
|
static final class ldexp extends BinaryOp {
|
||||||
protected double call(double x, double y) {
|
protected double call(double x, double y) {
|
||||||
// This is the behavior on os-x, windows differs in rounding behavior.
|
// This is the behavior on os-x, windows differs in rounding behavior.
|
||||||
return x*Double.longBitsToDouble((((long) y)+1023)<<52);
|
return x*Double.longBitsToDouble((((long) y)+1023)<<52);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class pow extends BinaryOp {
|
static final class pow extends BinaryOp {
|
||||||
protected double call(double x, double y) {
|
protected double call(double x, double y) {
|
||||||
return MathLib.dpow_default(x, y);
|
return MathLib.dpow_default(x, y);
|
||||||
@@ -186,7 +240,8 @@ public class MathLib extends TwoArgFunction {
|
|||||||
static class frexp extends VarArgFunction {
|
static class frexp extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
double x = args.checkdouble(1);
|
double x = args.checkdouble(1);
|
||||||
if ( x == 0 ) return varargsOf(ZERO,ZERO);
|
if (x == 0)
|
||||||
|
return varargsOf(ZERO, ZERO);
|
||||||
long bits = Double.doubleToLongBits(x);
|
long bits = Double.doubleToLongBits(x);
|
||||||
double m = ((bits & (~(-1L<<52)))+(1L<<52))*((bits >= 0)? (.5/(1L<<52)): (-.5/(1L<<52)));
|
double m = ((bits & (~(-1L<<52)))+(1L<<52))*((bits >= 0)? (.5/(1L<<52)): (-.5/(1L<<52)));
|
||||||
double e = (((int) (bits>>52)) & 0x7ff)-1022;
|
double e = (((int) (bits>>52)) & 0x7ff)-1022;
|
||||||
@@ -199,7 +254,8 @@ public class MathLib extends TwoArgFunction {
|
|||||||
LuaValue m = args.checkvalue(1);
|
LuaValue m = args.checkvalue(1);
|
||||||
for (int i = 2, n = args.narg(); i <= n; ++i) {
|
for (int i = 2, n = args.narg(); i <= n; ++i) {
|
||||||
LuaValue v = args.checkvalue(i);
|
LuaValue v = args.checkvalue(i);
|
||||||
if (m.lt_b(v)) m = v;
|
if (m.lt_b(v))
|
||||||
|
m = v;
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@@ -210,7 +266,8 @@ public class MathLib extends TwoArgFunction {
|
|||||||
LuaValue m = args.checkvalue(1);
|
LuaValue m = args.checkvalue(1);
|
||||||
for (int i = 2, n = args.narg(); i <= n; ++i) {
|
for (int i = 2, n = args.narg(); i <= n; ++i) {
|
||||||
LuaValue v = args.checkvalue(i);
|
LuaValue v = args.checkvalue(i);
|
||||||
if (v.lt_b(m)) m = v;
|
if (v.lt_b(m))
|
||||||
|
m = v;
|
||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
@@ -220,7 +277,8 @@ public class MathLib extends TwoArgFunction {
|
|||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaValue n = args.arg1();
|
LuaValue n = args.arg1();
|
||||||
/* number is its own integer part, no fractional part */
|
/* number is its own integer part, no fractional part */
|
||||||
if (n.islong()) return varargsOf(n, valueOf(0.0));
|
if (n.islong())
|
||||||
|
return varargsOf(n, valueOf(0.0));
|
||||||
double x = n.checkdouble();
|
double x = n.checkdouble();
|
||||||
/* integer part (rounds toward zero) */
|
/* integer part (rounds toward zero) */
|
||||||
double intPart = (x > 0)? Math.floor(x): Math.ceil(x);
|
double intPart = (x > 0)? Math.floor(x): Math.ceil(x);
|
||||||
@@ -232,18 +290,23 @@ public class MathLib extends TwoArgFunction {
|
|||||||
|
|
||||||
static class random extends LibFunction {
|
static class random extends LibFunction {
|
||||||
Random random = new Random();
|
Random random = new Random();
|
||||||
|
|
||||||
public LuaValue call() {
|
public LuaValue call() {
|
||||||
return valueOf(random.nextDouble());
|
return valueOf(random.nextDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue a) {
|
public LuaValue call(LuaValue a) {
|
||||||
int m = a.checkint();
|
int m = a.checkint();
|
||||||
if (m<1) argerror(1, "interval is empty");
|
if (m < 1)
|
||||||
|
argerror(1, "interval is empty");
|
||||||
return valueOf(1+random.nextInt(m));
|
return valueOf(1+random.nextInt(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue a, LuaValue b) {
|
public LuaValue call(LuaValue a, LuaValue b) {
|
||||||
int m = a.checkint();
|
int m = a.checkint();
|
||||||
int n = b.checkint();
|
int n = b.checkint();
|
||||||
if (n<m) argerror(2, "interval is empty");
|
if (n < m)
|
||||||
|
argerror(2, "interval is empty");
|
||||||
return valueOf(m+random.nextInt(n+1-m));
|
return valueOf(m+random.nextInt(n+1-m));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,9 +314,11 @@ public class MathLib extends TwoArgFunction {
|
|||||||
|
|
||||||
static class randomseed extends OneArgFunction {
|
static class randomseed extends OneArgFunction {
|
||||||
final random random;
|
final random random;
|
||||||
|
|
||||||
randomseed(random random) {
|
randomseed(random random) {
|
||||||
this.random = random;
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
long seed = arg.checklong();
|
long seed = arg.checklong();
|
||||||
random.random = new Random(seed);
|
random.random = new Random(seed);
|
||||||
@@ -261,17 +326,16 @@ public class MathLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** compute power using installed math library, or default if there is no math library installed */
|
/**
|
||||||
|
* compute power using installed math library, or default if there is no
|
||||||
|
* math library installed
|
||||||
|
*/
|
||||||
public static LuaValue dpow(double a, double b) {
|
public static LuaValue dpow(double a, double b) {
|
||||||
return LuaDouble.valueOf(
|
return LuaDouble.valueOf(MATHLIB != null? MATHLIB.dpow_lib(a, b): dpow_default(a, b));
|
||||||
MATHLIB!=null?
|
|
||||||
MATHLIB.dpow_lib(a,b):
|
|
||||||
dpow_default(a,b) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double dpow_d(double a, double b) {
|
public static double dpow_d(double a, double b) {
|
||||||
return MATHLIB!=null?
|
return MATHLIB != null? MATHLIB.dpow_lib(a, b): dpow_default(a, b);
|
||||||
MATHLIB.dpow_lib(a,b):
|
|
||||||
dpow_default(a,b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,21 +24,23 @@ package org.luaj.vm2.lib;
|
|||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/** Abstract base class for Java function implementations that take one argument and
|
/**
|
||||||
* return one value.
|
* Abstract base class for Java function implementations that take one argument
|
||||||
|
* and return one value.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses need only implement {@link LuaValue#call(LuaValue)} to complete this class,
|
* Subclasses need only implement {@link LuaValue#call(LuaValue)} to complete
|
||||||
* simplifying development.
|
* this class, simplifying development. All other uses of {@link #call()},
|
||||||
* All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,
|
* {@link #invoke(Varargs)},etc, are routed through this method by this class,
|
||||||
* are routed through this method by this class,
|
|
||||||
* dropping or extending arguments with {@code nil} values as required.
|
* dropping or extending arguments with {@code nil} values as required.
|
||||||
* <p>
|
* <p>
|
||||||
* If more than one argument are required, or no arguments are required,
|
* If more than one argument are required, or no arguments are required, or
|
||||||
* or variable argument or variable return values,
|
* variable argument or variable return values, then use one of the related
|
||||||
* then use one of the related function
|
* function {@link ZeroArgFunction}, {@link TwoArgFunction},
|
||||||
* {@link ZeroArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
|
* {@link ThreeArgFunction}, or {@link VarArgFunction}.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link LibFunction} for more information on implementation libraries and library functions.
|
* See {@link LibFunction} for more information on implementation libraries and
|
||||||
|
* library functions.
|
||||||
|
*
|
||||||
* @see #call(LuaValue)
|
* @see #call(LuaValue)
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see ZeroArgFunction
|
* @see ZeroArgFunction
|
||||||
|
|||||||
@@ -32,21 +32,21 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
|
* Subclass of {@link LibFunction} which implements the standard lua {@code os}
|
||||||
|
* library.
|
||||||
* <p>
|
* <p>
|
||||||
* It is a usable base with simplified stub functions
|
* It is a usable base with simplified stub functions for library functions that
|
||||||
* for library functions that cannot be implemented uniformly
|
* cannot be implemented uniformly on Jse and Jme.
|
||||||
* on Jse and Jme.
|
|
||||||
* <p>
|
* <p>
|
||||||
* This can be installed as-is on either platform, or extended
|
* This can be installed as-is on either platform, or extended and refined to be
|
||||||
* and refined to be used in a complete Jse implementation.
|
* used in a complete Jse implementation.
|
||||||
* <p>
|
* <p>
|
||||||
* Because the nature of the {@code os} library is to encapsulate
|
* Because the nature of the {@code os} library is to encapsulate os-specific
|
||||||
* os-specific features, the behavior of these functions varies considerably
|
* features, the behavior of these functions varies considerably from their
|
||||||
* from their counterparts in the C platform.
|
* counterparts in the C platform.
|
||||||
* <p>
|
* <p>
|
||||||
* The following functions have limited implementations of features
|
* The following functions have limited implementations of features that are not
|
||||||
* that are not supported well on Jme:
|
* supported well on Jme:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@code execute()}</li>
|
* <li>{@code execute()}</li>
|
||||||
* <li>{@code remove()}</li>
|
* <li>{@code remove()}</li>
|
||||||
@@ -55,29 +55,42 @@ import org.luaj.vm2.Varargs;
|
|||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* <pre> {@code
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("os").get("time").call());
|
* System.out.println(globals.get("os").get("time").call());
|
||||||
* } </pre>
|
* }
|
||||||
* In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseOsLib} library will be loaded, which will include
|
* </pre>
|
||||||
* the base functionality provided by this class.
|
*
|
||||||
|
* In this example the platform-specific {@link org.luaj.vm2.lib.jse.JseOsLib}
|
||||||
|
* library will be loaded, which will include the base functionality provided by
|
||||||
|
* this class.
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new OsLib());
|
* globals.load(new OsLib());
|
||||||
* System.out.println(globals.get("os").get("time").call());
|
* System.out.println(globals.get("os").get("time").call());
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JseOsLib
|
* @see org.luaj.vm2.lib.jse.JseOsLib
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.1/manual.html#5.8">http://www.lua.org/manual/5.1/manual.html#5.8</a>
|
* @see <a href=
|
||||||
|
* "http://www.lua.org/manual/5.1/manual.html#5.8">http://www.lua.org/manual/5.1/manual.html#5.8</a>
|
||||||
*/
|
*/
|
||||||
public class OsLib extends TwoArgFunction {
|
public class OsLib extends TwoArgFunction {
|
||||||
public static final String TMP_PREFIX = ".luaj";
|
public static final String TMP_PREFIX = ".luaj";
|
||||||
@@ -95,19 +108,8 @@ public class OsLib extends TwoArgFunction {
|
|||||||
private static final int TIME = 9;
|
private static final int TIME = 9;
|
||||||
private static final int TMPNAME = 10;
|
private static final int TMPNAME = 10;
|
||||||
|
|
||||||
private static final String[] NAMES = {
|
private static final String[] NAMES = { "clock", "date", "difftime", "execute", "exit", "getenv", "remove",
|
||||||
"clock",
|
"rename", "setlocale", "time", "tmpname", };
|
||||||
"date",
|
|
||||||
"difftime",
|
|
||||||
"execute",
|
|
||||||
"exit",
|
|
||||||
"getenv",
|
|
||||||
"remove",
|
|
||||||
"rename",
|
|
||||||
"setlocale",
|
|
||||||
"time",
|
|
||||||
"tmpname",
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final long t0 = System.currentTimeMillis();
|
private static final long t0 = System.currentTimeMillis();
|
||||||
private static long tmpnames = t0;
|
private static long tmpnames = t0;
|
||||||
@@ -120,11 +122,15 @@ public class OsLib extends TwoArgFunction {
|
|||||||
public OsLib() {
|
public OsLib() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by creating a table
|
/**
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* Perform one-time initialization on the library by creating a table
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* containing the library functions, adding that table to the supplied
|
||||||
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
|
* the return value.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, typically a Globals instance.
|
* @param env the environment to load into, typically a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
globals = env.checkglobals();
|
globals = env.checkglobals();
|
||||||
@@ -132,7 +138,8 @@ public class OsLib extends TwoArgFunction {
|
|||||||
for (int i = 0; i < NAMES.length; ++i)
|
for (int i = 0; i < NAMES.length; ++i)
|
||||||
os.set(NAMES[i], new OsLibFunc(i, NAMES[i]));
|
os.set(NAMES[i], new OsLibFunc(i, NAMES[i]));
|
||||||
env.set("os", os);
|
env.set("os", os);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("os", os);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("os", os);
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,6 +148,7 @@ public class OsLib extends TwoArgFunction {
|
|||||||
this.opcode = opcode;
|
this.opcode = opcode;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
try {
|
try {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
@@ -200,8 +208,8 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return an approximation of the amount in seconds of CPU time used by
|
* @return an approximation of the amount in seconds of CPU time used by the
|
||||||
* the program. For luaj this simple returns the elapsed time since the
|
* program. For luaj this simple returns the elapsed time since the
|
||||||
* OsLib class was loaded.
|
* OsLib class was loaded.
|
||||||
*/
|
*/
|
||||||
protected double clock() {
|
protected double clock() {
|
||||||
@@ -209,8 +217,9 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of seconds from time t1 to time t2.
|
* Returns the number of seconds from time t1 to time t2. In POSIX, Windows,
|
||||||
* In POSIX, Windows, and some other systems, this value is exactly t2-t1.
|
* and some other systems, this value is exactly t2-t1.
|
||||||
|
*
|
||||||
* @param t2
|
* @param t2
|
||||||
* @param t1
|
* @param t1
|
||||||
* @return diffeence in time values, in seconds
|
* @return diffeence in time values, in seconds
|
||||||
@@ -220,22 +229,21 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the time argument is present, this is the time to be formatted
|
* If the time argument is present, this is the time to be formatted (see
|
||||||
* (see the os.time function for a description of this value).
|
* the os.time function for a description of this value). Otherwise, date
|
||||||
* Otherwise, date formats the current time.
|
* formats the current time.
|
||||||
*
|
*
|
||||||
* Date returns the date as a string,
|
* Date returns the date as a string, formatted according to the same rules
|
||||||
* formatted according to the same rules as ANSII strftime, but without
|
* as ANSII strftime, but without support for %g, %G, or %V.
|
||||||
* support for %g, %G, or %V.
|
|
||||||
*
|
*
|
||||||
* When called without arguments, date returns a reasonable date and
|
* When called without arguments, date returns a reasonable date and time
|
||||||
* time representation that depends on the host system and on the
|
* representation that depends on the host system and on the current locale
|
||||||
* current locale (that is, os.date() is equivalent to os.date("%c")).
|
* (that is, os.date() is equivalent to os.date("%c")).
|
||||||
*
|
*
|
||||||
* @param format
|
* @param format
|
||||||
* @param time time since epoch, or -1 if not supplied
|
* @param time time since epoch, or -1 if not supplied
|
||||||
* @return a LString or a LTable containing date and time,
|
* @return a LString or a LTable containing date and time, formatted
|
||||||
* formatted according to the given string format.
|
* according to the given string format.
|
||||||
*/
|
*/
|
||||||
public String date(String format, double time) {
|
public String date(String format, double time) {
|
||||||
Calendar d = Calendar.getInstance();
|
Calendar d = Calendar.getInstance();
|
||||||
@@ -258,7 +266,8 @@ public class OsLib extends TwoArgFunction {
|
|||||||
result.append(c);
|
result.append(c);
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
if (i >= n) break;
|
if (i >= n)
|
||||||
|
break;
|
||||||
switch (c = fmt[i++]) {
|
switch (c = fmt[i++]) {
|
||||||
default:
|
default:
|
||||||
LuaValue.argerror(1, "invalid conversion specifier '%" + c + "'");
|
LuaValue.argerror(1, "invalid conversion specifier '%" + c + "'");
|
||||||
@@ -344,9 +353,12 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static final String[] WeekdayNameAbbrev = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
private static final String[] WeekdayNameAbbrev = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||||
private static final String[] WeekdayName = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
|
private static final String[] WeekdayName = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
|
||||||
private static final String[] MonthNameAbbrev = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
"Friday", "Saturday" };
|
||||||
private static final String[] MonthName = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
|
private static final String[] MonthNameAbbrev = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
|
||||||
|
"Oct", "Nov", "Dec" };
|
||||||
|
private static final String[] MonthName = { "January", "February", "March", "April", "May", "June", "July",
|
||||||
|
"August", "September", "October", "November", "December" };
|
||||||
|
|
||||||
private Calendar beginningOfYear(Calendar d) {
|
private Calendar beginningOfYear(Calendar d) {
|
||||||
Calendar y0 = Calendar.getInstance();
|
Calendar y0 = Calendar.getInstance();
|
||||||
@@ -372,17 +384,10 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int timeZoneOffset(Calendar d) {
|
private int timeZoneOffset(Calendar d) {
|
||||||
int localStandarTimeMillis = (
|
int localStandarTimeMillis = (d.get(Calendar.HOUR_OF_DAY)*3600+d.get(Calendar.MINUTE)*60+d.get(Calendar.SECOND))
|
||||||
d.get(Calendar.HOUR_OF_DAY) * 3600 +
|
*1000;
|
||||||
d.get(Calendar.MINUTE) * 60 +
|
return d.getTimeZone().getOffset(1, d.get(Calendar.YEAR), d.get(Calendar.MONTH), d.get(Calendar.DAY_OF_MONTH),
|
||||||
d.get(Calendar.SECOND)) * 1000;
|
d.get(Calendar.DAY_OF_WEEK), localStandarTimeMillis)/1000;
|
||||||
return d.getTimeZone().getOffset(
|
|
||||||
1,
|
|
||||||
d.get(Calendar.YEAR),
|
|
||||||
d.get(Calendar.MONTH),
|
|
||||||
d.get(Calendar.DAY_OF_MONTH),
|
|
||||||
d.get(Calendar.DAY_OF_WEEK),
|
|
||||||
localStandarTimeMillis) / 1000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDaylightSavingsTime(Calendar d) {
|
private boolean isDaylightSavingsTime(Calendar d) {
|
||||||
@@ -390,11 +395,11 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is equivalent to the C function system.
|
* This function is equivalent to the C function system. It passes command
|
||||||
* It passes command to be executed by an operating system shell.
|
* to be executed by an operating system shell. It returns a status code,
|
||||||
* It returns a status code, which is system-dependent.
|
* which is system-dependent. If command is absent, then it returns nonzero
|
||||||
* If command is absent, then it returns nonzero if a shell
|
* if a shell is available and zero otherwise.
|
||||||
* is available and zero otherwise.
|
*
|
||||||
* @param command command to pass to the system
|
* @param command command to pass to the system
|
||||||
*/
|
*/
|
||||||
protected Varargs execute(String command) {
|
protected Varargs execute(String command) {
|
||||||
@@ -402,7 +407,9 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls the C function exit, with an optional code, to terminate the host program.
|
* Calls the C function exit, with an optional code, to terminate the host
|
||||||
|
* program.
|
||||||
|
*
|
||||||
* @param code
|
* @param code
|
||||||
*/
|
*/
|
||||||
protected void exit(int code) {
|
protected void exit(int code) {
|
||||||
@@ -410,19 +417,19 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the process environment variable varname,
|
* Returns the value of the process environment variable varname, or the
|
||||||
* or the System property value for varname,
|
* System property value for varname, or null if the variable is not defined
|
||||||
* or null if the variable is not defined in either environment.
|
* in either environment.
|
||||||
*
|
*
|
||||||
* The default implementation, which is used by the JmePlatform,
|
* The default implementation, which is used by the JmePlatform, only
|
||||||
* only queryies System.getProperty().
|
* queryies System.getProperty().
|
||||||
*
|
*
|
||||||
* The JsePlatform overrides this behavior and returns the
|
* The JsePlatform overrides this behavior and returns the environment
|
||||||
* environment variable value using System.getenv() if it exists,
|
* variable value using System.getenv() if it exists, or the System property
|
||||||
* or the System property value if it does not.
|
* value if it does not.
|
||||||
|
*
|
||||||
|
* A SecurityException may be thrown if access is not allowed for 'varname'.
|
||||||
*
|
*
|
||||||
* A SecurityException may be thrown if access is not allowed
|
|
||||||
* for 'varname'.
|
|
||||||
* @param varname
|
* @param varname
|
||||||
* @return String value, or null if not defined
|
* @return String value, or null if not defined
|
||||||
*/
|
*/
|
||||||
@@ -431,9 +438,8 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the file or directory with the given name.
|
* Deletes the file or directory with the given name. Directories must be
|
||||||
* Directories must be empty to be removed.
|
* empty to be removed. If this function fails, it throws and IOException
|
||||||
* If this function fails, it throws and IOException
|
|
||||||
*
|
*
|
||||||
* @param filename
|
* @param filename
|
||||||
* @throws IOException if it fails
|
* @throws IOException if it fails
|
||||||
@@ -443,8 +449,8 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renames file or directory named oldname to newname.
|
* Renames file or directory named oldname to newname. If this function
|
||||||
* If this function fails,it throws and IOException
|
* fails,it throws and IOException
|
||||||
*
|
*
|
||||||
* @param oldname old file name
|
* @param oldname old file name
|
||||||
* @param newname new file name
|
* @param newname new file name
|
||||||
@@ -455,33 +461,34 @@ public class OsLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current locale of the program. locale is a string specifying
|
* Sets the current locale of the program. locale is a string specifying a
|
||||||
* a locale; category is an optional string describing which category to change:
|
* locale; category is an optional string describing which category to
|
||||||
* "all", "collate", "ctype", "monetary", "numeric", or "time"; the default category
|
* change: "all", "collate", "ctype", "monetary", "numeric", or "time"; the
|
||||||
* is "all".
|
* default category is "all".
|
||||||
*
|
*
|
||||||
* If locale is the empty string, the current locale is set to an implementation-
|
* If locale is the empty string, the current locale is set to an
|
||||||
* defined native locale. If locale is the string "C", the current locale is set
|
* implementation- defined native locale. If locale is the string "C", the
|
||||||
* to the standard C locale.
|
* current locale is set to the standard C locale.
|
||||||
*
|
*
|
||||||
* When called with null as the first argument, this function only returns the
|
* When called with null as the first argument, this function only returns
|
||||||
* name of the current locale for the given category.
|
* the name of the current locale for the given category.
|
||||||
*
|
*
|
||||||
* @param locale
|
* @param locale
|
||||||
* @param category
|
* @param category
|
||||||
* @return the name of the new locale, or null if the request
|
* @return the name of the new locale, or null if the request cannot be
|
||||||
* cannot be honored.
|
* honored.
|
||||||
*/
|
*/
|
||||||
protected String setlocale(String locale, String category) {
|
protected String setlocale(String locale, String category) {
|
||||||
return "C";
|
return "C";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current time when called without arguments,
|
* Returns the current time when called without arguments, or a time
|
||||||
* or a time representing the date and time specified by the given table.
|
* representing the date and time specified by the given table. This table
|
||||||
* This table must have fields year, month, and day,
|
* must have fields year, month, and day, and may have fields hour, min,
|
||||||
* and may have fields hour, min, sec, and isdst
|
* sec, and isdst (for a description of these fields, see the os.date
|
||||||
* (for a description of these fields, see the os.date function).
|
* function).
|
||||||
|
*
|
||||||
* @param table
|
* @param table
|
||||||
* @return long value for the time
|
* @return long value for the time
|
||||||
*/
|
*/
|
||||||
@@ -508,11 +515,11 @@ public class OsLib extends TwoArgFunction {
|
|||||||
* The file must be explicitly opened before its use and explicitly removed
|
* The file must be explicitly opened before its use and explicitly removed
|
||||||
* when no longer needed.
|
* when no longer needed.
|
||||||
*
|
*
|
||||||
* On some systems (POSIX), this function also creates a file with that name,
|
* On some systems (POSIX), this function also creates a file with that
|
||||||
* to avoid security risks. (Someone else might create the file with wrong
|
* name, to avoid security risks. (Someone else might create the file with
|
||||||
* permissions in the time between getting the name and creating the file.)
|
* wrong permissions in the time between getting the name and creating the
|
||||||
* You still have to open the file to use it and to remove it (even if you
|
* file.) You still have to open the file to use it and to remove it (even
|
||||||
* do not use it).
|
* if you do not use it).
|
||||||
*
|
*
|
||||||
* @return String filename to use
|
* @return String filename to use
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,56 +31,73 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard package and module
|
* Subclass of {@link LibFunction} which implements the lua standard package and
|
||||||
* library functions.
|
* module library functions.
|
||||||
*
|
*
|
||||||
* <h3>Lua Environment Variables</h3>
|
* <h3>Lua Environment Variables</h3> The following variables are available to
|
||||||
* The following variables are available to lua scrips when this library has been loaded:
|
* lua scrips when this library has been loaded:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><code>"package.loaded"</code> Lua table of loaded modules.
|
* <li><code>"package.loaded"</code> Lua table of loaded modules.
|
||||||
* <li><code>"package.path"</code> Search path for lua scripts.
|
* <li><code>"package.path"</code> Search path for lua scripts.
|
||||||
* <li><code>"package.preload"</code> Lua table of uninitialized preload functions.
|
* <li><code>"package.preload"</code> Lua table of uninitialized preload
|
||||||
* <li><code>"package.searchers"</code> Lua table of functions that search for object to load.
|
* functions.
|
||||||
|
* <li><code>"package.searchers"</code> Lua table of functions that search for
|
||||||
|
* object to load.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <h3>Java Environment Variables</h3>
|
* <h3>Java Environment Variables</h3> These Java environment variables affect
|
||||||
* These Java environment variables affect the library behavior:
|
* the library behavior:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li><code>"luaj.package.path"</code> Initial value for <code>"package.path"</code>. Default value is <code>"?.lua"</code>
|
* <li><code>"luaj.package.path"</code> Initial value for
|
||||||
|
* <code>"package.path"</code>. Default value is <code>"?.lua"</code>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* <h3>Loading</h3>
|
* <h3>Loading</h3> Typically, this library is included as part of a call to
|
||||||
* Typically, this library is included as part of a call to either
|
* either {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println( globals.get("require").call"foo") );
|
* System.out.println( globals.get("require").call"foo") );
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* System.out.println(globals.get("require").call("foo"));
|
* System.out.println(globals.get("require").call("foo"));
|
||||||
* } </pre>
|
* }
|
||||||
* <h3>Limitations</h3>
|
* </pre>
|
||||||
* This library has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
*
|
||||||
* However, the default filesystem search semantics are different and delegated to the bas library
|
* <h3>Limitations</h3> This library has been implemented to match as closely as
|
||||||
* as outlined in the {@link BaseLib} and {@link org.luaj.vm2.lib.jse.JseBaseLib} documentation.
|
* possible the behavior in the corresponding library in C. However, the default
|
||||||
|
* filesystem search semantics are different and delegated to the bas library as
|
||||||
|
* outlined in the {@link BaseLib} and {@link org.luaj.vm2.lib.jse.JseBaseLib}
|
||||||
|
* documentation.
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see BaseLib
|
* @see BaseLib
|
||||||
* @see org.luaj.vm2.lib.jse.JseBaseLib
|
* @see org.luaj.vm2.lib.jse.JseBaseLib
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.3">Lua 5.2 Package Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.3">Lua 5.2 Package
|
||||||
|
* Lib Reference</a>
|
||||||
*/
|
*/
|
||||||
public class PackageLib extends TwoArgFunction {
|
public class PackageLib extends TwoArgFunction {
|
||||||
|
|
||||||
/** The default value to use for package.path. This can be set with the system property
|
/**
|
||||||
* <code>"luaj.package.path"</code>, and is <code>"?.lua"</code> by default. */
|
* The default value to use for package.path. This can be set with the
|
||||||
|
* system property <code>"luaj.package.path"</code>, and is
|
||||||
|
* <code>"?.lua"</code> by default.
|
||||||
|
*/
|
||||||
public static final String DEFAULT_LUA_PATH;
|
public static final String DEFAULT_LUA_PATH;
|
||||||
static {
|
static {
|
||||||
String path = null;
|
String path = null;
|
||||||
@@ -111,10 +128,16 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
/** Loader that loads from {@code preload} table if found there */
|
/** Loader that loads from {@code preload} table if found there */
|
||||||
public preload_searcher preload_searcher;
|
public preload_searcher preload_searcher;
|
||||||
|
|
||||||
/** Loader that loads as a lua script using the lua path currently in {@link path} */
|
/**
|
||||||
|
* Loader that loads as a lua script using the lua path currently in
|
||||||
|
* {@link path}
|
||||||
|
*/
|
||||||
public lua_searcher lua_searcher;
|
public lua_searcher lua_searcher;
|
||||||
|
|
||||||
/** Loader that loads as a Java class. Class must have public constructor and be a LuaValue. */
|
/**
|
||||||
|
* Loader that loads as a Java class. Class must have public constructor and
|
||||||
|
* be a LuaValue.
|
||||||
|
*/
|
||||||
public java_searcher java_searcher;
|
public java_searcher java_searcher;
|
||||||
|
|
||||||
private static final LuaString _SENTINEL = valueOf("\u0001");
|
private static final LuaString _SENTINEL = valueOf("\u0001");
|
||||||
@@ -123,12 +146,15 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
|
|
||||||
public PackageLib() {}
|
public PackageLib() {}
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by adding package functions
|
/**
|
||||||
* to the supplied environment, and returning it as the return value.
|
* Perform one-time initialization on the library by adding package
|
||||||
* It also creates the package.preload and package.loaded tables for use by
|
* functions to the supplied environment, and returning it as the return
|
||||||
* other libraries.
|
* value. It also creates the package.preload and package.loaded tables for
|
||||||
|
* use by other libraries.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, typically a Globals instance.
|
* @param env the environment to load into, typically a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
globals = env.checkglobals();
|
globals = env.checkglobals();
|
||||||
@@ -156,9 +182,10 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
package_.get(_LOADED).set(name, value);
|
package_.get(_LOADED).set(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/** Set the lua path used by this library instance to a new value.
|
* Set the lua path used by this library instance to a new value. Merely
|
||||||
* Merely sets the value of {@link path} to be used in subsequent searches. */
|
* sets the value of {@link path} to be used in subsequent searches.
|
||||||
|
*/
|
||||||
public void setLuaPath(String newLuaPath) {
|
public void setLuaPath(String newLuaPath) {
|
||||||
package_.set(_PATH, LuaValue.valueOf(newLuaPath));
|
package_.set(_PATH, LuaValue.valueOf(newLuaPath));
|
||||||
}
|
}
|
||||||
@@ -172,29 +199,34 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* require (modname)
|
* require (modname)
|
||||||
*
|
*
|
||||||
* Loads the given module. The function starts by looking into the package.loaded table
|
* Loads the given module. The function starts by looking into the
|
||||||
* to determine whether modname is already loaded. If it is, then require returns the value
|
* package.loaded table to determine whether modname is already loaded. If
|
||||||
* stored at package.loaded[modname]. Otherwise, it tries to find a loader for the module.
|
* it is, then require returns the value stored at package.loaded[modname].
|
||||||
|
* Otherwise, it tries to find a loader for the module.
|
||||||
*
|
*
|
||||||
* To find a loader, require is guided by the package.searchers sequence.
|
* To find a loader, require is guided by the package.searchers sequence. By
|
||||||
* By changing this sequence, we can change how require looks for a module.
|
* changing this sequence, we can change how require looks for a module. The
|
||||||
* The following explanation is based on the default configuration for package.searchers.
|
* following explanation is based on the default configuration for
|
||||||
|
* package.searchers.
|
||||||
*
|
*
|
||||||
* First require queries package.preload[modname]. If it has a value, this value
|
* First require queries package.preload[modname]. If it has a value, this
|
||||||
* (which should be a function) is the loader. Otherwise require searches for a Lua loader using
|
* value (which should be a function) is the loader. Otherwise require
|
||||||
* the path stored in package.path. If that also fails, it searches for a Java loader using
|
* searches for a Lua loader using the path stored in package.path. If that
|
||||||
* the classpath, using the public default constructor, and casting the instance to LuaFunction.
|
* also fails, it searches for a Java loader using the classpath, using the
|
||||||
|
* public default constructor, and casting the instance to LuaFunction.
|
||||||
*
|
*
|
||||||
* Once a loader is found, require calls the loader with two arguments: modname and an extra value
|
* Once a loader is found, require calls the loader with two arguments:
|
||||||
* dependent on how it got the loader. If the loader came from a file, this extra value is the file name.
|
* modname and an extra value dependent on how it got the loader. If the
|
||||||
* If the loader is a Java instance of LuaFunction, this extra value is the environment.
|
* loader came from a file, this extra value is the file name. If the loader
|
||||||
* If the loader returns any non-nil value, require assigns the returned value to package.loaded[modname].
|
* is a Java instance of LuaFunction, this extra value is the environment.
|
||||||
* If the loader does not return a non-nil value and has not assigned any value to package.loaded[modname],
|
* If the loader returns any non-nil value, require assigns the returned
|
||||||
* then require assigns true to this entry.
|
* value to package.loaded[modname]. If the loader does not return a non-nil
|
||||||
* In any case, require returns the final value of package.loaded[modname].
|
* value and has not assigned any value to package.loaded[modname], then
|
||||||
|
* require assigns true to this entry. In any case, require returns the
|
||||||
|
* final value of package.loaded[modname].
|
||||||
*
|
*
|
||||||
* If there is any error loading or running the module, or if it cannot find any loader for the module,
|
* If there is any error loading or running the module, or if it cannot find
|
||||||
* then require raises an error.
|
* any loader for the module, then require raises an error.
|
||||||
*/
|
*/
|
||||||
public class require extends OneArgFunction {
|
public class require extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
@@ -247,9 +279,7 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
LuaString name = args.checkstring(1);
|
LuaString name = args.checkstring(1);
|
||||||
LuaValue val = package_.get(_PRELOAD).get(name);
|
LuaValue val = package_.get(_PRELOAD).get(name);
|
||||||
return val.isnil()?
|
return val.isnil()? valueOf("\n\tno field package.preload['" + name + "']"): val;
|
||||||
valueOf("\n\tno field package.preload['"+name+"']"):
|
|
||||||
val;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,7 +341,10 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
// try opening the file
|
// try opening the file
|
||||||
InputStream is = globals.finder.findResource(filename);
|
InputStream is = globals.finder.findResource(filename);
|
||||||
if (is != null) {
|
if (is != null) {
|
||||||
try { is.close(); } catch ( java.io.IOException ioe ) {}
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (java.io.IOException ioe) {
|
||||||
|
}
|
||||||
return valueOf(filename);
|
return valueOf(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,9 +389,7 @@ public class PackageLib extends TwoArgFunction {
|
|||||||
StringBuffer sb = new StringBuffer(j);
|
StringBuffer sb = new StringBuffer(j);
|
||||||
for (int i = 0; i < j; i++) {
|
for (int i = 0; i < j; i++) {
|
||||||
c = filename.charAt(i);
|
c = filename.charAt(i);
|
||||||
sb.append(
|
sb.append((isClassnamePart(c))? c: ((c == '/') || (c == '\\'))? '.': '_');
|
||||||
(isClassnamePart(c))? c:
|
|
||||||
((c=='/') || (c=='\\'))? '.': '_' );
|
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,16 +28,17 @@ import org.luaj.vm2.Globals;
|
|||||||
/**
|
/**
|
||||||
* Interface for opening application resource files such as scripts sources.
|
* Interface for opening application resource files such as scripts sources.
|
||||||
* <p>
|
* <p>
|
||||||
* This is used by required to load files that are part of
|
* This is used by required to load files that are part of the application, and
|
||||||
* the application, and implemented by BaseLib
|
* implemented by BaseLib for both the Jme and Jse platforms.
|
||||||
* for both the Jme and Jse platforms.
|
|
||||||
* <p>
|
* <p>
|
||||||
* The Jme version of base lib {@link BaseLib}
|
* The Jme version of base lib {@link BaseLib} implements {@link Globals#finder}
|
||||||
* implements {@link Globals#finder} via {@link Class#getResourceAsStream(String)},
|
* via {@link Class#getResourceAsStream(String)}, while the Jse version
|
||||||
* while the Jse version {@link org.luaj.vm2.lib.jse.JseBaseLib} implements it using {@link java.io.File#File(String)}.
|
* {@link org.luaj.vm2.lib.jse.JseBaseLib} implements it using
|
||||||
|
* {@link java.io.File#File(String)}.
|
||||||
* <p>
|
* <p>
|
||||||
* The io library does not use this API for file manipulation.
|
* The io library does not use this API for file manipulation.
|
||||||
* <p>
|
* <p>
|
||||||
|
*
|
||||||
* @see BaseLib
|
* @see BaseLib
|
||||||
* @see Globals#finder
|
* @see Globals#finder
|
||||||
* @see org.luaj.vm2.lib.jse.JseBaseLib
|
* @see org.luaj.vm2.lib.jse.JseBaseLib
|
||||||
|
|||||||
@@ -33,53 +33,70 @@ import org.luaj.vm2.Varargs;
|
|||||||
import org.luaj.vm2.compiler.DumpState;
|
import org.luaj.vm2.compiler.DumpState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code string}
|
* Subclass of {@link LibFunction} which implements the lua standard
|
||||||
* library.
|
* {@code string} library.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* <pre> {@code
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("string").get("upper").call(LuaValue.valueOf("abcde")));
|
* System.out.println(globals.get("string").get("upper").call(LuaValue.valueOf("abcde")));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new JseStringLib());
|
* globals.load(new JseStringLib());
|
||||||
* System.out.println(globals.get("string").get("upper").call(LuaValue.valueOf("abcde")));
|
* System.out.println(globals.get("string").get("upper").call(LuaValue.valueOf("abcde")));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This is a direct port of the corresponding library in C.
|
* This is a direct port of the corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.4">Lua 5.2 String Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.4">Lua 5.2 String
|
||||||
|
* Lib Reference</a>
|
||||||
*/
|
*/
|
||||||
public class StringLib extends TwoArgFunction {
|
public class StringLib extends TwoArgFunction {
|
||||||
|
|
||||||
/** Construct a StringLib, which can be initialized by calling it with a
|
/**
|
||||||
|
* Construct a StringLib, which can be initialized by calling it with a
|
||||||
* modname string, and a global environment table as arguments using
|
* modname string, and a global environment table as arguments using
|
||||||
* {@link #call(LuaValue, LuaValue)}. */
|
* {@link #call(LuaValue, LuaValue)}.
|
||||||
|
*/
|
||||||
public StringLib() {
|
public StringLib() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by creating a table
|
/**
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* Perform one-time initialization on the library by creating a table
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* containing the library functions, adding that table to the supplied
|
||||||
* Creates a metatable that uses __INDEX to fall back on itself to support string
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
* method operations.
|
* the return value. Creates a metatable that uses __INDEX to fall back on
|
||||||
* If the shared strings metatable instance is null, will set the metatable as
|
* itself to support string method operations. If the shared strings
|
||||||
* the global shared metatable for strings.
|
* metatable instance is null, will set the metatable as the global shared
|
||||||
|
* metatable for strings.
|
||||||
* <P>
|
* <P>
|
||||||
* All tables and metatables are read-write by default so if this will be used in
|
* All tables and metatables are read-write by default so if this will be
|
||||||
* a server environment, sandboxing should be used. In particular, the
|
* used in a server environment, sandboxing should be used. In particular,
|
||||||
* {@link LuaString#s_metatable} table should probably be made read-only.
|
* the {@link LuaString#s_metatable} table should probably be made
|
||||||
|
* read-only.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, typically a Globals instance.
|
* @param env the environment to load into, typically a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
LuaTable string = new LuaTable();
|
LuaTable string = new LuaTable();
|
||||||
@@ -99,7 +116,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
string.set("upper", new upper());
|
string.set("upper", new upper());
|
||||||
|
|
||||||
env.set("string", string);
|
env.set("string", string);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("string", string);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("string", string);
|
||||||
if (LuaString.s_metatable == null) {
|
if (LuaString.s_metatable == null) {
|
||||||
LuaString.s_metatable = LuaValue.tableOf(new LuaValue[] { INDEX, string });
|
LuaString.s_metatable = LuaValue.tableOf(new LuaValue[] { INDEX, string });
|
||||||
}
|
}
|
||||||
@@ -109,9 +127,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.byte (s [, i [, j]])
|
* string.byte (s [, i [, j]])
|
||||||
*
|
*
|
||||||
* Returns the internal numerical codes of the
|
* Returns the internal numerical codes of the characters s[i], s[i+1], ...,
|
||||||
* characters s[i], s[i+1], ..., s[j]. The default value for i is 1; the
|
* s[j]. The default value for i is 1; the default value for j is i.
|
||||||
* default value for j is i.
|
|
||||||
*
|
*
|
||||||
* Note that numerical codes are not necessarily portable across platforms.
|
* Note that numerical codes are not necessarily portable across platforms.
|
||||||
*
|
*
|
||||||
@@ -124,9 +141,12 @@ public class StringLib extends TwoArgFunction {
|
|||||||
int posi = posrelat(args.optint(2, 1), l);
|
int posi = posrelat(args.optint(2, 1), l);
|
||||||
int pose = posrelat(args.optint(3, posi), l);
|
int pose = posrelat(args.optint(3, posi), l);
|
||||||
int n, i;
|
int n, i;
|
||||||
if (posi <= 0) posi = 1;
|
if (posi <= 0)
|
||||||
if (pose > l) pose = l;
|
posi = 1;
|
||||||
if (posi > pose) return NONE; /* empty interval; return no values */
|
if (pose > l)
|
||||||
|
pose = l;
|
||||||
|
if (posi > pose)
|
||||||
|
return NONE; /* empty interval; return no values */
|
||||||
n = (int) (pose-posi+1);
|
n = (int) (pose-posi+1);
|
||||||
if (posi+n <= pose) /* overflow? */
|
if (posi+n <= pose) /* overflow? */
|
||||||
error("string slice too long");
|
error("string slice too long");
|
||||||
@@ -140,9 +160,9 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.char (...)
|
* string.char (...)
|
||||||
*
|
*
|
||||||
* Receives zero or more integers. Returns a string with length equal
|
* Receives zero or more integers. Returns a string with length equal to the
|
||||||
* to the number of arguments, in which each character has the internal
|
* number of arguments, in which each character has the internal numerical
|
||||||
* numerical code equal to its corresponding argument.
|
* code equal to its corresponding argument.
|
||||||
*
|
*
|
||||||
* Note that numerical codes are not necessarily portable across platforms.
|
* Note that numerical codes are not necessarily portable across platforms.
|
||||||
*
|
*
|
||||||
@@ -154,7 +174,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
byte[] bytes = new byte[n];
|
byte[] bytes = new byte[n];
|
||||||
for (int i = 0, a = 1; i < n; i++, a++) {
|
for (int i = 0, a = 1; i < n; i++, a++) {
|
||||||
int c = args.checkint(a);
|
int c = args.checkint(a);
|
||||||
if (c<0 || c>=256) argerror(a, "invalid value for string.char [0; 255]: " + c);
|
if (c < 0 || c >= 256)
|
||||||
|
argerror(a, "invalid value for string.char [0; 255]: " + c);
|
||||||
bytes[i] = (byte) c;
|
bytes[i] = (byte) c;
|
||||||
}
|
}
|
||||||
return LuaString.valueUsing(bytes);
|
return LuaString.valueUsing(bytes);
|
||||||
@@ -164,11 +185,11 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.dump (function[, stripDebug])
|
* string.dump (function[, stripDebug])
|
||||||
*
|
*
|
||||||
* Returns a string containing a binary representation of the given function,
|
* Returns a string containing a binary representation of the given
|
||||||
* so that a later loadstring on this string returns a copy of the function.
|
* function, so that a later loadstring on this string returns a copy of the
|
||||||
* function must be a Lua function without upvalues.
|
* function. function must be a Lua function without upvalues. Boolean param
|
||||||
* Boolean param stripDebug - true to strip debugging info, false otherwise.
|
* stripDebug - true to strip debugging info, false otherwise. The default
|
||||||
* The default value for stripDebug is true.
|
* value for stripDebug is true.
|
||||||
*
|
*
|
||||||
* TODO: port dumping code as optional add-on
|
* TODO: port dumping code as optional add-on
|
||||||
*/
|
*/
|
||||||
@@ -188,18 +209,17 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.find (s, pattern [, init [, plain]])
|
* string.find (s, pattern [, init [, plain]])
|
||||||
*
|
*
|
||||||
* Looks for the first match of pattern in the string s.
|
* Looks for the first match of pattern in the string s. If it finds a
|
||||||
* If it finds a match, then find returns the indices of s
|
* match, then find returns the indices of s where this occurrence starts
|
||||||
* where this occurrence starts and ends; otherwise, it returns nil.
|
* and ends; otherwise, it returns nil. A third, optional numerical argument
|
||||||
* A third, optional numerical argument init specifies where to start the search;
|
* init specifies where to start the search; its default value is 1 and may
|
||||||
* its default value is 1 and may be negative. A value of true as a fourth,
|
* be negative. A value of true as a fourth, optional argument plain turns
|
||||||
* optional argument plain turns off the pattern matching facilities,
|
* off the pattern matching facilities, so the function does a plain "find
|
||||||
* so the function does a plain "find substring" operation,
|
* substring" operation, with no characters in pattern being considered
|
||||||
* with no characters in pattern being considered "magic".
|
* "magic". Note that if plain is given, then init must be given as well.
|
||||||
* Note that if plain is given, then init must be given as well.
|
|
||||||
*
|
*
|
||||||
* If the pattern has captures, then in a successful match the captured values
|
* If the pattern has captures, then in a successful match the captured
|
||||||
* are also returned, after the two indices.
|
* values are also returned, after the two indices.
|
||||||
*/
|
*/
|
||||||
static final class find extends VarArgFunction {
|
static final class find extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
@@ -211,21 +231,20 @@ public class StringLib extends TwoArgFunction {
|
|||||||
* string.format (formatstring, ...)
|
* string.format (formatstring, ...)
|
||||||
*
|
*
|
||||||
* Returns a formatted version of its variable number of arguments following
|
* Returns a formatted version of its variable number of arguments following
|
||||||
* the description given in its first argument (which must be a string).
|
* the description given in its first argument (which must be a string). The
|
||||||
* The format string follows the same rules as the printf family of standard C functions.
|
* format string follows the same rules as the printf family of standard C
|
||||||
* The only differences are that the options/modifiers *, l, L, n, p, and h are not supported
|
* functions. The only differences are that the options/modifiers *, l, L,
|
||||||
* and that there is an extra option, q. The q option formats a string in a form suitable
|
* n, p, and h are not supported and that there is an extra option, q. The q
|
||||||
* to be safely read back by the Lua interpreter: the string is written between double quotes,
|
* option formats a string in a form suitable to be safely read back by the
|
||||||
* and all double quotes, newlines, embedded zeros, and backslashes in the string are correctly
|
* Lua interpreter: the string is written between double quotes, and all
|
||||||
* escaped when written. For instance, the call
|
* double quotes, newlines, embedded zeros, and backslashes in the string
|
||||||
|
* are correctly escaped when written. For instance, the call
|
||||||
* string.format('%q', 'a string with "quotes" and \n new line')
|
* string.format('%q', 'a string with "quotes" and \n new line')
|
||||||
*
|
*
|
||||||
* will produce the string:
|
* will produce the string: "a string with \"quotes\" and \ new line"
|
||||||
* "a string with \"quotes\" and \
|
|
||||||
* new line"
|
|
||||||
*
|
*
|
||||||
* The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument,
|
* The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as
|
||||||
* whereas q and s expect a string.
|
* argument, whereas q and s expect a string.
|
||||||
*
|
*
|
||||||
* This function does not accept string values containing embedded zeros,
|
* This function does not accept string values containing embedded zeros,
|
||||||
* except as arguments to the q option.
|
* except as arguments to the q option.
|
||||||
@@ -286,7 +305,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
} else {
|
} else {
|
||||||
fdsc.format(result, s);
|
fdsc.format(result, s);
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
error("invalid option '%" + (char) fdsc.conversion + "' to 'format'");
|
error("invalid option '%" + (char) fdsc.conversion + "' to 'format'");
|
||||||
break;
|
break;
|
||||||
@@ -305,7 +325,9 @@ public class StringLib extends TwoArgFunction {
|
|||||||
buf.append((byte) '"');
|
buf.append((byte) '"');
|
||||||
for (int i = 0, n = s.length(); i < n; i++) {
|
for (int i = 0, n = s.length(); i < n; i++) {
|
||||||
switch (c = s.luaByte(i)) {
|
switch (c = s.luaByte(i)) {
|
||||||
case '"': case '\\': case '\n':
|
case '"':
|
||||||
|
case '\\':
|
||||||
|
case '\n':
|
||||||
buf.append((byte) '\\');
|
buf.append((byte) '\\');
|
||||||
buf.append((byte) c);
|
buf.append((byte) c);
|
||||||
break;
|
break;
|
||||||
@@ -354,12 +376,24 @@ public class StringLib extends TwoArgFunction {
|
|||||||
boolean moreFlags = true;
|
boolean moreFlags = true;
|
||||||
while ( moreFlags ) {
|
while ( moreFlags ) {
|
||||||
switch (c = ((p < n)? strfrmt.luaByte(p++): 0)) {
|
switch (c = ((p < n)? strfrmt.luaByte(p++): 0)) {
|
||||||
case '-': leftAdjust = true; break;
|
case '-':
|
||||||
case '+': explicitPlus = true; break;
|
leftAdjust = true;
|
||||||
case ' ': space = true; break;
|
break;
|
||||||
case '#': alternateForm = true; break;
|
case '+':
|
||||||
case '0': zeroPad = true; break;
|
explicitPlus = true;
|
||||||
default: moreFlags = false; break;
|
break;
|
||||||
|
case ' ':
|
||||||
|
space = true;
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
alternateForm = true;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
zeroPad = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
moreFlags = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p-start > MAX_FLAGS)
|
if (p-start > MAX_FLAGS)
|
||||||
@@ -494,26 +528,20 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.gmatch (s, pattern)
|
* string.gmatch (s, pattern)
|
||||||
*
|
*
|
||||||
* Returns an iterator function that, each time it is called, returns the next captures
|
* Returns an iterator function that, each time it is called, returns the
|
||||||
* from pattern over string s. If pattern specifies no captures, then the
|
* next captures from pattern over string s. If pattern specifies no
|
||||||
* whole match is produced in each call.
|
* captures, then the whole match is produced in each call.
|
||||||
*
|
*
|
||||||
* As an example, the following loop
|
* As an example, the following loop s = "hello world from Lua" for w in
|
||||||
* s = "hello world from Lua"
|
* string.gmatch(s, "%a+") do print(w) end
|
||||||
* for w in string.gmatch(s, "%a+") do
|
|
||||||
* print(w)
|
|
||||||
* end
|
|
||||||
*
|
*
|
||||||
* will iterate over all the words from string s, printing one per line.
|
* will iterate over all the words from string s, printing one per line. The
|
||||||
* The next example collects all pairs key=value from the given string into a table:
|
* next example collects all pairs key=value from the given string into a
|
||||||
* t = {}
|
* table: t = {} s = "from=world, to=Lua" for k, v in string.gmatch(s,
|
||||||
* s = "from=world, to=Lua"
|
* "(%w+)=(%w+)") do t[k] = v end
|
||||||
* for k, v in string.gmatch(s, "(%w+)=(%w+)") do
|
|
||||||
* t[k] = v
|
|
||||||
* end
|
|
||||||
*
|
*
|
||||||
* For this function, a '^' at the start of a pattern does not work as an anchor,
|
* For this function, a '^' at the start of a pattern does not work as an
|
||||||
* as this would prevent the iteration.
|
* anchor, as this would prevent the iteration.
|
||||||
*/
|
*/
|
||||||
static final class gmatch extends VarArgFunction {
|
static final class gmatch extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
@@ -528,12 +556,14 @@ public class StringLib extends TwoArgFunction {
|
|||||||
private final MatchState ms;
|
private final MatchState ms;
|
||||||
private int soffset;
|
private int soffset;
|
||||||
private int lastmatch;
|
private int lastmatch;
|
||||||
|
|
||||||
public GMatchAux(Varargs args, LuaString src, LuaString pat) {
|
public GMatchAux(Varargs args, LuaString src, LuaString pat) {
|
||||||
this.srclen = src.length();
|
this.srclen = src.length();
|
||||||
this.ms = new MatchState(args, src, pat);
|
this.ms = new MatchState(args, src, pat);
|
||||||
this.soffset = 0;
|
this.soffset = 0;
|
||||||
this.lastmatch = -1;
|
this.lastmatch = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
for (; soffset <= srclen; soffset++) {
|
for (; soffset <= srclen; soffset++) {
|
||||||
ms.reset();
|
ms.reset();
|
||||||
@@ -548,51 +578,50 @@ public class StringLib extends TwoArgFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* string.gsub (s, pattern, repl [, n])
|
* string.gsub (s, pattern, repl [, n]) Returns a copy of s in which all (or
|
||||||
* Returns a copy of s in which all (or the first n, if given) occurrences of the
|
* the first n, if given) occurrences of the pattern have been replaced by a
|
||||||
* pattern have been replaced by a replacement string specified by repl, which
|
* replacement string specified by repl, which may be a string, a table, or
|
||||||
* may be a string, a table, or a function. gsub also returns, as its second value,
|
* a function. gsub also returns, as its second value, the total number of
|
||||||
* the total number of matches that occurred.
|
* matches that occurred.
|
||||||
*
|
*
|
||||||
* If repl is a string, then its value is used for replacement.
|
* If repl is a string, then its value is used for replacement. The
|
||||||
* The character % works as an escape character: any sequence in repl of the form %n,
|
* character % works as an escape character: any sequence in repl of the
|
||||||
* with n between 1 and 9, stands for the value of the n-th captured substring (see below).
|
* form %n, with n between 1 and 9, stands for the value of the n-th
|
||||||
* The sequence %0 stands for the whole match. The sequence %% stands for a single %.
|
* captured substring (see below). The sequence %0 stands for the whole
|
||||||
|
* match. The sequence %% stands for a single %.
|
||||||
*
|
*
|
||||||
* If repl is a table, then the table is queried for every match, using the first capture
|
* If repl is a table, then the table is queried for every match, using the
|
||||||
* as the key; if the pattern specifies no captures, then the whole match is used as the key.
|
* first capture as the key; if the pattern specifies no captures, then the
|
||||||
|
* whole match is used as the key.
|
||||||
*
|
*
|
||||||
* If repl is a function, then this function is called every time a match occurs,
|
* If repl is a function, then this function is called every time a match
|
||||||
* with all captured substrings passed as arguments, in order; if the pattern specifies
|
* occurs, with all captured substrings passed as arguments, in order; if
|
||||||
* no captures, then the whole match is passed as a sole argument.
|
* the pattern specifies no captures, then the whole match is passed as a
|
||||||
|
* sole argument.
|
||||||
*
|
*
|
||||||
* If the value returned by the table query or by the function call is a string or a number,
|
* If the value returned by the table query or by the function call is a
|
||||||
* then it is used as the replacement string; otherwise, if it is false or nil,
|
* string or a number, then it is used as the replacement string; otherwise,
|
||||||
* then there is no replacement (that is, the original match is kept in the string).
|
* if it is false or nil, then there is no replacement (that is, the
|
||||||
|
* original match is kept in the string).
|
||||||
*
|
*
|
||||||
* Here are some examples:
|
* Here are some examples: x = string.gsub("hello world", "(%w+)", "%1 %1")
|
||||||
* x = string.gsub("hello world", "(%w+)", "%1 %1")
|
|
||||||
* --> x="hello hello world world"
|
* --> x="hello hello world world"
|
||||||
*
|
*
|
||||||
* x = string.gsub("hello world", "%w+", "%0 %0", 1)
|
* x = string.gsub("hello world", "%w+", "%0 %0", 1) --> x="hello hello
|
||||||
* --> x="hello hello world"
|
* world"
|
||||||
*
|
*
|
||||||
* x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
|
* x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1") -->
|
||||||
* --> x="world hello Lua from"
|
* x="world hello Lua from"
|
||||||
*
|
*
|
||||||
* x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
|
* x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv) -->
|
||||||
* --> x="home = /home/roberto, user = roberto"
|
* x="home = /home/roberto, user = roberto"
|
||||||
*
|
*
|
||||||
* x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
|
* x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s) return
|
||||||
* return loadstring(s)()
|
* loadstring(s)() end) --> x="4+5 = 9"
|
||||||
* end)
|
|
||||||
* --> x="4+5 = 9"
|
|
||||||
*
|
*
|
||||||
* local t = {name="lua", version="5.1"}
|
* local t = {name="lua", version="5.1"} x =
|
||||||
* x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
|
* string.gsub("$name-$version.tar.gz", "%$(%w+)", t) --> x="lua-5.1.tar.gz"
|
||||||
* --> x="lua-5.1.tar.gz"
|
|
||||||
*/
|
*/
|
||||||
static final class gsub extends VarArgFunction {
|
static final class gsub extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
@@ -616,11 +645,12 @@ public class StringLib extends TwoArgFunction {
|
|||||||
n++;
|
n++;
|
||||||
ms.add_value(lbuf, soffset, res, repl); /* add replacement to buffer */
|
ms.add_value(lbuf, soffset, res, repl); /* add replacement to buffer */
|
||||||
soffset = lastmatch = res;
|
soffset = lastmatch = res;
|
||||||
}
|
} else if (soffset < srclen) /* otherwise, skip one character */
|
||||||
else if ( soffset < srclen ) /* otherwise, skip one character */
|
|
||||||
lbuf.append((byte) src.luaByte(soffset++));
|
lbuf.append((byte) src.luaByte(soffset++));
|
||||||
else break; /* end of subject */
|
else
|
||||||
if ( anchor ) break;
|
break; /* end of subject */
|
||||||
|
if (anchor)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
lbuf.append(src.substring(soffset, srclen));
|
lbuf.append(src.substring(soffset, srclen));
|
||||||
return varargsOf(lbuf.tostring(), valueOf(n));
|
return varargsOf(lbuf.tostring(), valueOf(n));
|
||||||
@@ -630,8 +660,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.len (s)
|
* string.len (s)
|
||||||
*
|
*
|
||||||
* Receives a string and returns its length. The empty string "" has length 0.
|
* Receives a string and returns its length. The empty string "" has length
|
||||||
* Embedded zeros are counted, so "a\000bc\000" has length 5.
|
* 0. Embedded zeros are counted, so "a\000bc\000" has length 5.
|
||||||
*/
|
*/
|
||||||
static final class len extends OneArgFunction {
|
static final class len extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
@@ -642,9 +672,10 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.lower (s)
|
* string.lower (s)
|
||||||
*
|
*
|
||||||
* Receives a string and returns a copy of this string with all uppercase letters
|
* Receives a string and returns a copy of this string with all uppercase
|
||||||
* changed to lowercase. All other characters are left unchanged.
|
* letters changed to lowercase. All other characters are left unchanged.
|
||||||
* The definition of what an uppercase letter is depends on the current locale.
|
* The definition of what an uppercase letter is depends on the current
|
||||||
|
* locale.
|
||||||
*/
|
*/
|
||||||
static final class lower extends OneArgFunction {
|
static final class lower extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
@@ -704,13 +735,11 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.sub (s, i [, j])
|
* string.sub (s, i [, j])
|
||||||
*
|
*
|
||||||
* Returns the substring of s that starts at i and continues until j;
|
* Returns the substring of s that starts at i and continues until j; i and
|
||||||
* i and j may be negative. If j is absent, then it is assumed to be equal to -1
|
* j may be negative. If j is absent, then it is assumed to be equal to -1
|
||||||
* (which is the same as the string length). In particular, the call
|
* (which is the same as the string length). In particular, the call
|
||||||
* string.sub(s,1,j)
|
* string.sub(s,1,j) returns a prefix of s with length j, and string.sub(s,
|
||||||
* returns a prefix of s with length j, and
|
* -i) returns a suffix of s with length i.
|
||||||
* string.sub(s, -i)
|
|
||||||
* returns a suffix of s with length i.
|
|
||||||
*/
|
*/
|
||||||
static final class sub extends VarArgFunction {
|
static final class sub extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
@@ -736,9 +765,10 @@ public class StringLib extends TwoArgFunction {
|
|||||||
/**
|
/**
|
||||||
* string.upper (s)
|
* string.upper (s)
|
||||||
*
|
*
|
||||||
* Receives a string and returns a copy of this string with all lowercase letters
|
* Receives a string and returns a copy of this string with all lowercase
|
||||||
* changed to uppercase. All other characters are left unchanged.
|
* letters changed to uppercase. All other characters are left unchanged.
|
||||||
* The definition of what a lowercase letter is depends on the current locale.
|
* The definition of what a lowercase letter is depends on the current
|
||||||
|
* locale.
|
||||||
*/
|
*/
|
||||||
static final class upper extends OneArgFunction {
|
static final class upper extends OneArgFunction {
|
||||||
public LuaValue call(LuaValue arg) {
|
public LuaValue call(LuaValue arg) {
|
||||||
@@ -824,10 +854,9 @@ public class StringLib extends TwoArgFunction {
|
|||||||
|
|
||||||
for (int i = 0; i < 128; ++i) {
|
for (int i = 0; i < 128; ++i) {
|
||||||
final char c = (char) i;
|
final char c = (char) i;
|
||||||
CHAR_TABLE[i] = (byte)( ( Character.isDigit( c ) ? MASK_DIGIT : 0 ) |
|
CHAR_TABLE[i] = (byte) ((Character.isDigit(c)? MASK_DIGIT: 0)
|
||||||
( Character.isLowerCase( c ) ? MASK_LOWERCASE : 0 ) |
|
| (Character.isLowerCase(c)? MASK_LOWERCASE: 0) | (Character.isUpperCase(c)? MASK_UPPERCASE: 0)
|
||||||
( Character.isUpperCase( c ) ? MASK_UPPERCASE : 0 ) |
|
| ((c < ' ' || c == 0x7F)? MASK_CONTROL: 0));
|
||||||
( ( c < ' ' || c == 0x7F ) ? MASK_CONTROL : 0 ) );
|
|
||||||
if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9')) {
|
if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9')) {
|
||||||
CHAR_TABLE[i] |= MASK_HEXDIGIT;
|
CHAR_TABLE[i] |= MASK_HEXDIGIT;
|
||||||
}
|
}
|
||||||
@@ -881,12 +910,11 @@ public class StringLib extends TwoArgFunction {
|
|||||||
++i; // skip ESC
|
++i; // skip ESC
|
||||||
b = (byte) (i < l? news.luaByte(i): 0);
|
b = (byte) (i < l? news.luaByte(i): 0);
|
||||||
if (!Character.isDigit((char) b)) {
|
if (!Character.isDigit((char) b)) {
|
||||||
if (b != L_ESC) error( "invalid use of '" + (char)L_ESC +
|
if (b != L_ESC)
|
||||||
"' in replacement string: after '" + (char)L_ESC +
|
error("invalid use of '" + (char) L_ESC + "' in replacement string: after '" + (char) L_ESC
|
||||||
"' must be '0'-'9' or '" + (char)L_ESC +
|
+ "' must be '0'-'9' or '" + (char) L_ESC + "', but found "
|
||||||
"', but found " + (i < l ? "symbol '" + (char)b + "' with code " + b +
|
+ (i < l? "symbol '" + (char) b + "' with code " + b + " at pos " + (i+1)
|
||||||
" at pos " + (i + 1) :
|
: "end of string"));
|
||||||
"end of string"));
|
|
||||||
lbuf.append(b);
|
lbuf.append(b);
|
||||||
} else if (b == '0') {
|
} else if (b == '0') {
|
||||||
lbuf.append(s.substring(soff, e));
|
lbuf.append(s.substring(soff, e));
|
||||||
@@ -929,8 +957,10 @@ public class StringLib extends TwoArgFunction {
|
|||||||
Varargs push_captures(boolean wholeMatch, int soff, int end) {
|
Varargs push_captures(boolean wholeMatch, int soff, int end) {
|
||||||
int nlevels = (this.level == 0 && wholeMatch)? 1: this.level;
|
int nlevels = (this.level == 0 && wholeMatch)? 1: this.level;
|
||||||
switch (nlevels) {
|
switch (nlevels) {
|
||||||
case 0: return NONE;
|
case 0:
|
||||||
case 1: return push_onecapture( 0, soff, end );
|
return NONE;
|
||||||
|
case 1:
|
||||||
|
return push_onecapture(0, soff, end);
|
||||||
}
|
}
|
||||||
LuaValue[] v = new LuaValue[nlevels];
|
LuaValue[] v = new LuaValue[nlevels];
|
||||||
for (int i = 0; i < nlevels; ++i)
|
for (int i = 0; i < nlevels; ++i)
|
||||||
@@ -985,7 +1015,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
return poffset+1;
|
return poffset+1;
|
||||||
|
|
||||||
case '[':
|
case '[':
|
||||||
if ( poffset != p.length() && p.luaByte( poffset ) == '^' ) poffset++;
|
if (poffset != p.length() && p.luaByte(poffset) == '^')
|
||||||
|
poffset++;
|
||||||
do {
|
do {
|
||||||
if (poffset == p.length()) {
|
if (poffset == p.length()) {
|
||||||
error("malformed pattern (missing ']')");
|
error("malformed pattern (missing ']')");
|
||||||
@@ -1005,18 +1036,41 @@ public class StringLib extends TwoArgFunction {
|
|||||||
|
|
||||||
boolean res;
|
boolean res;
|
||||||
switch (lcl) {
|
switch (lcl) {
|
||||||
case 'a': res = ( cdata & MASK_ALPHA ) != 0; break;
|
case 'a':
|
||||||
case 'd': res = ( cdata & MASK_DIGIT ) != 0; break;
|
res = (cdata & MASK_ALPHA) != 0;
|
||||||
case 'l': res = ( cdata & MASK_LOWERCASE ) != 0; break;
|
break;
|
||||||
case 'u': res = ( cdata & MASK_UPPERCASE ) != 0; break;
|
case 'd':
|
||||||
case 'c': res = ( cdata & MASK_CONTROL ) != 0; break;
|
res = (cdata & MASK_DIGIT) != 0;
|
||||||
case 'p': res = ( cdata & MASK_PUNCT ) != 0; break;
|
break;
|
||||||
case 's': res = ( cdata & MASK_SPACE ) != 0; break;
|
case 'l':
|
||||||
case 'g': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT | MASK_PUNCT ) ) != 0; break;
|
res = (cdata & MASK_LOWERCASE) != 0;
|
||||||
case 'w': res = ( cdata & ( MASK_ALPHA | MASK_DIGIT ) ) != 0; break;
|
break;
|
||||||
case 'x': res = ( cdata & MASK_HEXDIGIT ) != 0; break;
|
case 'u':
|
||||||
case 'z': res = ( c == 0 ); break; /* deprecated option */
|
res = (cdata & MASK_UPPERCASE) != 0;
|
||||||
default: return cl == c;
|
break;
|
||||||
|
case 'c':
|
||||||
|
res = (cdata & MASK_CONTROL) != 0;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
res = (cdata & MASK_PUNCT) != 0;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
res = (cdata & MASK_SPACE) != 0;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
res = (cdata & (MASK_ALPHA | MASK_DIGIT | MASK_PUNCT)) != 0;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
res = (cdata & (MASK_ALPHA | MASK_DIGIT)) != 0;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
res = (cdata & MASK_HEXDIGIT) != 0;
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
res = (c == 0);
|
||||||
|
break; /* deprecated option */
|
||||||
|
default:
|
||||||
|
return cl == c;
|
||||||
}
|
}
|
||||||
return (lcl == cl)? res: !res;
|
return (lcl == cl)? res: !res;
|
||||||
}
|
}
|
||||||
@@ -1032,23 +1086,26 @@ public class StringLib extends TwoArgFunction {
|
|||||||
poff++;
|
poff++;
|
||||||
if (match_class(c, p.luaByte(poff)))
|
if (match_class(c, p.luaByte(poff)))
|
||||||
return sig;
|
return sig;
|
||||||
}
|
} else if ((p.luaByte(poff+1) == '-') && (poff+2 < ec)) {
|
||||||
else if ( ( p.luaByte( poff + 1 ) == '-' ) && ( poff + 2 < ec ) ) {
|
|
||||||
poff += 2;
|
poff += 2;
|
||||||
if (p.luaByte(poff-2) <= c && c <= p.luaByte(poff))
|
if (p.luaByte(poff-2) <= c && c <= p.luaByte(poff))
|
||||||
return sig;
|
return sig;
|
||||||
}
|
} else if (p.luaByte(poff) == c)
|
||||||
else if ( p.luaByte( poff ) == c ) return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
return !sig;
|
return !sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean singlematch(int c, int poff, int ep) {
|
boolean singlematch(int c, int poff, int ep) {
|
||||||
switch (p.luaByte(poff)) {
|
switch (p.luaByte(poff)) {
|
||||||
case '.': return true;
|
case '.':
|
||||||
case L_ESC: return match_class( c, p.luaByte( poff + 1 ) );
|
return true;
|
||||||
case '[': return matchbracketclass( c, poff, ep - 1 );
|
case L_ESC:
|
||||||
default: return p.luaByte( poff ) == c;
|
return match_class(c, p.luaByte(poff+1));
|
||||||
|
case '[':
|
||||||
|
return matchbracketclass(c, poff, ep-1);
|
||||||
|
default:
|
||||||
|
return p.luaByte(poff) == c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1057,7 +1114,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
* where match ends, otherwise returns -1.
|
* where match ends, otherwise returns -1.
|
||||||
*/
|
*/
|
||||||
int match(int soffset, int poffset) {
|
int match(int soffset, int poffset) {
|
||||||
if (matchdepth-- == 0) error("pattern too complex");
|
if (matchdepth-- == 0)
|
||||||
|
error("pattern too complex");
|
||||||
try {
|
try {
|
||||||
while ( true ) {
|
while ( true ) {
|
||||||
// Check if we are at the end of the pattern -
|
// Check if we are at the end of the pattern -
|
||||||
@@ -1079,7 +1137,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
switch (p.luaByte(poffset+1)) {
|
switch (p.luaByte(poffset+1)) {
|
||||||
case 'b':
|
case 'b':
|
||||||
soffset = matchbalance(soffset, poffset+2);
|
soffset = matchbalance(soffset, poffset+2);
|
||||||
if ( soffset == -1 ) return -1;
|
if (soffset == -1)
|
||||||
|
return -1;
|
||||||
poffset += 4;
|
poffset += 4;
|
||||||
continue;
|
continue;
|
||||||
case 'f': {
|
case 'f': {
|
||||||
@@ -1090,8 +1149,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
int ep = classend(poffset);
|
int ep = classend(poffset);
|
||||||
int previous = (soffset == 0)? '\0': s.luaByte(soffset-1);
|
int previous = (soffset == 0)? '\0': s.luaByte(soffset-1);
|
||||||
int next = (soffset == s.length())? '\0': s.luaByte(soffset);
|
int next = (soffset == s.length())? '\0': s.luaByte(soffset);
|
||||||
if ( matchbracketclass( previous, poffset, ep - 1 ) ||
|
if (matchbracketclass(previous, poffset, ep-1) || !matchbracketclass(next, poffset, ep-1))
|
||||||
!matchbracketclass( next, poffset, ep - 1 ) )
|
|
||||||
return -1;
|
return -1;
|
||||||
poffset = ep;
|
poffset = ep;
|
||||||
continue;
|
continue;
|
||||||
@@ -1142,8 +1200,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
|
|
||||||
int max_expand(int soff, int poff, int ep) {
|
int max_expand(int soff, int poff, int ep) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while ( soff + i < s.length() &&
|
while ( soff+i < s.length() && singlematch(s.luaByte(soff+i), poff, ep) )
|
||||||
singlematch( s.luaByte( soff + i ), poff, ep ) )
|
|
||||||
i++;
|
i++;
|
||||||
while ( i >= 0 ) {
|
while ( i >= 0 ) {
|
||||||
int res = match(soff+i, ep+1);
|
int res = match(soff+i, ep+1);
|
||||||
@@ -1161,7 +1218,8 @@ public class StringLib extends TwoArgFunction {
|
|||||||
return res;
|
return res;
|
||||||
else if (soff < s.length() && singlematch(s.luaByte(soff), poff, ep))
|
else if (soff < s.length() && singlematch(s.luaByte(soff), poff, ep))
|
||||||
soff++;
|
soff++;
|
||||||
else return -1;
|
else
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1191,8 +1249,7 @@ public class StringLib extends TwoArgFunction {
|
|||||||
int match_capture(int soff, int l) {
|
int match_capture(int soff, int l) {
|
||||||
l = check_capture(l);
|
l = check_capture(l);
|
||||||
int len = clen[l];
|
int len = clen[l];
|
||||||
if ( ( s.length() - soff ) >= len &&
|
if ((s.length()-soff) >= len && LuaString.equals(s, cinit[l], s, soff, len))
|
||||||
LuaString.equals( s, cinit[l], s, soff, len ) )
|
|
||||||
return soff+len;
|
return soff+len;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1213,9 +1270,10 @@ public class StringLib extends TwoArgFunction {
|
|||||||
int cont = 1;
|
int cont = 1;
|
||||||
while ( ++soff < slen ) {
|
while ( ++soff < slen ) {
|
||||||
if (s.luaByte(soff) == e) {
|
if (s.luaByte(soff) == e) {
|
||||||
if ( --cont == 0 ) return soff + 1;
|
if (--cont == 0)
|
||||||
}
|
return soff+1;
|
||||||
else if ( s.luaByte( soff ) == b ) cont++;
|
} else if (s.luaByte(soff) == b)
|
||||||
|
cont++;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,40 +26,56 @@ import org.luaj.vm2.LuaValue;
|
|||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code table}
|
* Subclass of {@link LibFunction} which implements the lua standard
|
||||||
* library.
|
* {@code table} library.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to either
|
* Typically, this library is included as part of a call to either
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} or
|
||||||
* <pre> {@code
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("table").get("length").call(LuaValue.tableOf()));
|
* System.out.println(globals.get("table").get("length").call(LuaValue.tableOf()));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link LuaValue#load(LuaValue)} using code such as:
|
* {@link LuaValue#load(LuaValue)} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new TableLib());
|
* globals.load(new TableLib());
|
||||||
* System.out.println(globals.get("table").get("length").call(LuaValue.tableOf()));
|
* System.out.println(globals.get("table").get("length").call(LuaValue.tableOf()));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.5">Lua 5.2 Table Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.5">Lua 5.2 Table
|
||||||
|
* Lib Reference</a>
|
||||||
*/
|
*/
|
||||||
public class TableLib extends TwoArgFunction {
|
public class TableLib extends TwoArgFunction {
|
||||||
|
|
||||||
/** Perform one-time initialization on the library by creating a table
|
/**
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* Perform one-time initialization on the library by creating a table
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* containing the library functions, adding that table to the supplied
|
||||||
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
|
* the return value.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, typically a Globals instance.
|
* @param env the environment to load into, typically a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
LuaTable table = new LuaTable();
|
LuaTable table = new LuaTable();
|
||||||
@@ -70,7 +86,8 @@ public class TableLib extends TwoArgFunction {
|
|||||||
table.set("sort", new sort());
|
table.set("sort", new sort());
|
||||||
table.set("unpack", new unpack());
|
table.set("unpack", new unpack());
|
||||||
env.set("table", table);
|
env.set("table", table);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("table", table);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("table", table);
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,12 +96,15 @@ public class TableLib extends TwoArgFunction {
|
|||||||
public LuaValue call(LuaValue list) {
|
public LuaValue call(LuaValue list) {
|
||||||
return list.checktable().concat(EMPTYSTRING, 1, list.length());
|
return list.checktable().concat(EMPTYSTRING, 1, list.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue list, LuaValue sep) {
|
public LuaValue call(LuaValue list, LuaValue sep) {
|
||||||
return list.checktable().concat(sep.checkstring(), 1, list.length());
|
return list.checktable().concat(sep.checkstring(), 1, list.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue list, LuaValue sep, LuaValue i) {
|
public LuaValue call(LuaValue list, LuaValue sep, LuaValue i) {
|
||||||
return list.checktable().concat(sep.checkstring(), i.checkint(), list.length());
|
return list.checktable().concat(sep.checkstring(), i.checkint(), list.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue call(LuaValue list, LuaValue sep, LuaValue i, LuaValue j) {
|
public LuaValue call(LuaValue list, LuaValue sep, LuaValue i, LuaValue j) {
|
||||||
return list.checktable().concat(sep.checkstring(), i.checkint(), j.checkint());
|
return list.checktable().concat(sep.checkstring(), i.checkint(), j.checkint());
|
||||||
}
|
}
|
||||||
@@ -103,7 +123,8 @@ public class TableLib extends TwoArgFunction {
|
|||||||
LuaTable table = args.checktable(1);
|
LuaTable table = args.checktable(1);
|
||||||
int pos = args.checkint(2);
|
int pos = args.checkint(2);
|
||||||
int max = table.length()+1;
|
int max = table.length()+1;
|
||||||
if (pos < 1 || pos > max) argerror(2, "position out of bounds: " + pos + " not between 1 and " + max);
|
if (pos < 1 || pos > max)
|
||||||
|
argerror(2, "position out of bounds: " + pos + " not between 1 and " + max);
|
||||||
table.insert(pos, args.arg(3));
|
table.insert(pos, args.arg(3));
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
@@ -139,13 +160,11 @@ public class TableLib extends TwoArgFunction {
|
|||||||
// "sort" (table [, comp])
|
// "sort" (table [, comp])
|
||||||
static class sort extends VarArgFunction {
|
static class sort extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
args.checktable(1).sort(
|
args.checktable(1).sort(args.isnil(2)? NIL: args.checkfunction(2));
|
||||||
args.isnil(2)? NIL: args.checkfunction(2));
|
|
||||||
return NONE;
|
return NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// "unpack", // (list [,i [,j]]) -> result1, ...
|
// "unpack", // (list [,i [,j]]) -> result1, ...
|
||||||
static class unpack extends VarArgFunction {
|
static class unpack extends VarArgFunction {
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
|
|||||||
@@ -24,21 +24,24 @@ package org.luaj.vm2.lib;
|
|||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/** Abstract base class for Java function implementations that take two arguments and
|
/**
|
||||||
* return one value.
|
* Abstract base class for Java function implementations that take two arguments
|
||||||
|
* and return one value.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue,LuaValue)} to complete this class,
|
* Subclasses need only implement
|
||||||
* simplifying development.
|
* {@link LuaValue#call(LuaValue,LuaValue,LuaValue)} to complete this class,
|
||||||
* All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,
|
* simplifying development. All other uses of {@link #call()},
|
||||||
* are routed through this method by this class,
|
* {@link #invoke(Varargs)},etc, are routed through this method by this class,
|
||||||
* dropping or extending arguments with {@code nil} values as required.
|
* dropping or extending arguments with {@code nil} values as required.
|
||||||
* <p>
|
* <p>
|
||||||
* If more or less than three arguments are required,
|
* If more or less than three arguments are required, or variable argument or
|
||||||
* or variable argument or variable return values,
|
* variable return values, then use one of the related function
|
||||||
* then use one of the related function
|
* {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or
|
||||||
* {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link VarArgFunction}.
|
* {@link VarArgFunction}.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link LibFunction} for more information on implementation libraries and library functions.
|
* See {@link LibFunction} for more information on implementation libraries and
|
||||||
|
* library functions.
|
||||||
|
*
|
||||||
* @see #call(LuaValue,LuaValue,LuaValue)
|
* @see #call(LuaValue,LuaValue,LuaValue)
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see ZeroArgFunction
|
* @see ZeroArgFunction
|
||||||
|
|||||||
@@ -24,21 +24,24 @@ package org.luaj.vm2.lib;
|
|||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/** Abstract base class for Java function implementations that take two arguments and
|
/**
|
||||||
* return one value.
|
* Abstract base class for Java function implementations that take two arguments
|
||||||
|
* and return one value.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue)} to complete this class,
|
* Subclasses need only implement {@link LuaValue#call(LuaValue,LuaValue)} to
|
||||||
* simplifying development.
|
* complete this class, simplifying development. All other uses of
|
||||||
* All other uses of {@link #call()}, {@link #invoke(Varargs)},etc,
|
* {@link #call()}, {@link #invoke(Varargs)},etc, are routed through this method
|
||||||
* are routed through this method by this class,
|
* by this class, dropping or extending arguments with {@code nil} values as
|
||||||
* dropping or extending arguments with {@code nil} values as required.
|
* required.
|
||||||
* <p>
|
* <p>
|
||||||
* If more or less than two arguments are required,
|
* If more or less than two arguments are required, or variable argument or
|
||||||
* or variable argument or variable return values,
|
* variable return values, then use one of the related function
|
||||||
* then use one of the related function
|
* {@link ZeroArgFunction}, {@link OneArgFunction}, {@link ThreeArgFunction}, or
|
||||||
* {@link ZeroArgFunction}, {@link OneArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
|
* {@link VarArgFunction}.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link LibFunction} for more information on implementation libraries and library functions.
|
* See {@link LibFunction} for more information on implementation libraries and
|
||||||
|
* library functions.
|
||||||
|
*
|
||||||
* @see #call(LuaValue,LuaValue)
|
* @see #call(LuaValue,LuaValue)
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see ZeroArgFunction
|
* @see ZeroArgFunction
|
||||||
|
|||||||
@@ -24,20 +24,23 @@ package org.luaj.vm2.lib;
|
|||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/** Abstract base class for Java function implementations that takes varaiable arguments and
|
/**
|
||||||
* returns multiple return values.
|
* Abstract base class for Java function implementations that takes varaiable
|
||||||
|
* arguments and returns multiple return values.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses need only implement {@link LuaValue#invoke(Varargs)} to complete this class,
|
* Subclasses need only implement {@link LuaValue#invoke(Varargs)} to complete
|
||||||
* simplifying development.
|
* this class, simplifying development. All other uses of
|
||||||
* All other uses of {@link #call(LuaValue)}, {@link #invoke()},etc,
|
* {@link #call(LuaValue)}, {@link #invoke()},etc, are routed through this
|
||||||
* are routed through this method by this class,
|
* method by this class, converting arguments to {@link Varargs} and dropping or
|
||||||
* converting arguments to {@link Varargs} and
|
* extending return values with {@code nil} values as required.
|
||||||
* dropping or extending return values with {@code nil} values as required.
|
|
||||||
* <p>
|
* <p>
|
||||||
* If between one and three arguments are required, and only one return value is returned,
|
* If between one and three arguments are required, and only one return value is
|
||||||
* {@link ZeroArgFunction}, {@link OneArgFunction}, {@link TwoArgFunction}, or {@link ThreeArgFunction}.
|
* returned, {@link ZeroArgFunction}, {@link OneArgFunction},
|
||||||
|
* {@link TwoArgFunction}, or {@link ThreeArgFunction}.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link LibFunction} for more information on implementation libraries and library functions.
|
* See {@link LibFunction} for more information on implementation libraries and
|
||||||
|
* library functions.
|
||||||
|
*
|
||||||
* @see #invoke(Varargs)
|
* @see #invoke(Varargs)
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see ZeroArgFunction
|
* @see ZeroArgFunction
|
||||||
@@ -67,10 +70,10 @@ abstract public class VarArgFunction extends LibFunction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass responsibility.
|
* Subclass responsibility. May not have expected behavior for tail calls.
|
||||||
* May not have expected behavior for tail calls.
|
* Should not be used if: - function has a possibility of returning a
|
||||||
* Should not be used if:
|
* TailcallVarargs
|
||||||
* - function has a possibility of returning a TailcallVarargs
|
*
|
||||||
* @param args the arguments to the function call.
|
* @param args the arguments to the function call.
|
||||||
*/
|
*/
|
||||||
public Varargs invoke(Varargs args) {
|
public Varargs invoke(Varargs args) {
|
||||||
|
|||||||
@@ -24,19 +24,21 @@ package org.luaj.vm2.lib;
|
|||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
import org.luaj.vm2.Varargs;
|
import org.luaj.vm2.Varargs;
|
||||||
|
|
||||||
/** Abstract base class for Java function implementations that take no arguments and
|
/**
|
||||||
* return one value.
|
* Abstract base class for Java function implementations that take no arguments
|
||||||
|
* and return one value.
|
||||||
* <p>
|
* <p>
|
||||||
* Subclasses need only implement {@link LuaValue#call()} to complete this class,
|
* Subclasses need only implement {@link LuaValue#call()} to complete this
|
||||||
* simplifying development.
|
* class, simplifying development. All other uses of {@link #call(LuaValue)},
|
||||||
* All other uses of {@link #call(LuaValue)}, {@link #invoke(Varargs)},etc,
|
* {@link #invoke(Varargs)},etc, are routed through this method by this class.
|
||||||
* are routed through this method by this class.
|
|
||||||
* <p>
|
* <p>
|
||||||
* If one or more arguments are required, or variable argument or variable return values,
|
* If one or more arguments are required, or variable argument or variable
|
||||||
* then use one of the related function
|
* return values, then use one of the related function {@link OneArgFunction},
|
||||||
* {@link OneArgFunction}, {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
|
* {@link TwoArgFunction}, {@link ThreeArgFunction}, or {@link VarArgFunction}.
|
||||||
* <p>
|
* <p>
|
||||||
* See {@link LibFunction} for more information on implementation libraries and library functions.
|
* See {@link LibFunction} for more information on implementation libraries and
|
||||||
|
* library functions.
|
||||||
|
*
|
||||||
* @see #call()
|
* @see #call()
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see OneArgFunction
|
* @see OneArgFunction
|
||||||
|
|||||||
@@ -35,38 +35,51 @@ import org.luaj.vm2.lib.IoLib;
|
|||||||
import org.luaj.vm2.lib.LibFunction;
|
import org.luaj.vm2.lib.LibFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io}
|
* Subclass of {@link IoLib} and therefore {@link LibFunction} which implements
|
||||||
* library for the JSE platform.
|
* the lua standard {@code io} library for the JSE platform.
|
||||||
* <p>
|
* <p>
|
||||||
* The implementation of the is based on CLDC 1.0 and StreamConnection.
|
* The implementation of the is based on CLDC 1.0 and StreamConnection. However,
|
||||||
* However, seek is not supported.
|
* seek is not supported.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JmePlatform.standardGlobals();
|
* Globals globals = JmePlatform.standardGlobals();
|
||||||
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired, a minimal
|
||||||
* a minimal set of libraries could be loaded
|
* set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JmeBaseLib());
|
* globals.load(new JmeBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new JmeIoLib());
|
* globals.load(new JmeIoLib());
|
||||||
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
||||||
* } </pre>
|
* }
|
||||||
* <p>However, other libraries such as <em>MathLib</em> are not loaded in this case.
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* However, other libraries such as <em>MathLib</em> are not loaded in this
|
||||||
|
* case.
|
||||||
|
* <p>
|
||||||
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see IoLib
|
* @see IoLib
|
||||||
* @see org.luaj.vm2.lib.jse.JseIoLib
|
* @see org.luaj.vm2.lib.jse.JseIoLib
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.8">Lua 5.2 I/O Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.8">Lua 5.2 I/O Lib
|
||||||
|
* Reference</a>
|
||||||
*/
|
*/
|
||||||
public class JmeIoLib extends IoLib {
|
public class JmeIoLib extends IoLib {
|
||||||
|
|
||||||
@@ -82,13 +95,13 @@ public class JmeIoLib extends IoLib {
|
|||||||
return new FileImpl(globals.STDERR);
|
return new FileImpl(globals.STDERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
protected File openFile(String filename, boolean readMode, boolean appendMode, boolean updateMode,
|
||||||
|
boolean binaryMode) throws IOException {
|
||||||
String url = "file:///" + filename;
|
String url = "file:///" + filename;
|
||||||
int mode = readMode? Connector.READ: Connector.READ_WRITE;
|
int mode = readMode? Connector.READ: Connector.READ_WRITE;
|
||||||
StreamConnection conn = (StreamConnection) Connector.open(url, mode);
|
StreamConnection conn = (StreamConnection) Connector.open(url, mode);
|
||||||
File f = readMode?
|
File f = readMode? new FileImpl(conn, conn.openInputStream(), null)
|
||||||
new FileImpl(conn, conn.openInputStream(), null):
|
: new FileImpl(conn, conn.openInputStream(), conn.openOutputStream());
|
||||||
new FileImpl(conn, conn.openInputStream(), conn.openOutputStream());
|
|
||||||
/*
|
/*
|
||||||
if ( appendMode ) {
|
if ( appendMode ) {
|
||||||
f.seek("end",0);
|
f.seek("end",0);
|
||||||
@@ -121,33 +134,41 @@ public class JmeIoLib extends IoLib {
|
|||||||
private boolean closed = false;
|
private boolean closed = false;
|
||||||
private boolean nobuffer = false;
|
private boolean nobuffer = false;
|
||||||
private int lookahead = -1;
|
private int lookahead = -1;
|
||||||
|
|
||||||
private FileImpl(StreamConnection conn, InputStream is, OutputStream os) {
|
private FileImpl(StreamConnection conn, InputStream is, OutputStream os) {
|
||||||
this.conn = conn;
|
this.conn = conn;
|
||||||
this.is = is;
|
this.is = is;
|
||||||
this.os = os;
|
this.os = os;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileImpl(InputStream i) {
|
private FileImpl(InputStream i) {
|
||||||
this(null, i, null);
|
this(null, i, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileImpl(OutputStream o) {
|
private FileImpl(OutputStream o) {
|
||||||
this(null, null, o);
|
this(null, null, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
return "file (" + this.hashCode() + ")";
|
return "file (" + this.hashCode() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isstdfile() {
|
public boolean isstdfile() {
|
||||||
return conn == null;
|
return conn == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
closed = true;
|
closed = true;
|
||||||
if (conn != null) {
|
if (conn != null) {
|
||||||
conn.close();
|
conn.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
if (os != null)
|
if (os != null)
|
||||||
os.flush();
|
os.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(LuaString s) throws IOException {
|
public void write(LuaString s) throws IOException {
|
||||||
if (os != null)
|
if (os != null)
|
||||||
os.write(s.m_bytes, s.m_offset, s.m_length);
|
os.write(s.m_bytes, s.m_offset, s.m_length);
|
||||||
@@ -156,9 +177,11 @@ public class JmeIoLib extends IoLib {
|
|||||||
if (nobuffer)
|
if (nobuffer)
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isclosed() {
|
public boolean isclosed() {
|
||||||
return closed;
|
return closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int seek(String option, int pos) throws IOException {
|
public int seek(String option, int pos) throws IOException {
|
||||||
/*
|
/*
|
||||||
if ( conn != null ) {
|
if ( conn != null ) {
|
||||||
@@ -177,6 +200,7 @@ public class JmeIoLib extends IoLib {
|
|||||||
notimplemented();
|
notimplemented();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setvbuf(String mode, int size) {
|
public void setvbuf(String mode, int size) {
|
||||||
nobuffer = "no".equals(mode);
|
nobuffer = "no".equals(mode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,40 +37,60 @@ import org.luaj.vm2.lib.ResourceFinder;
|
|||||||
import org.luaj.vm2.lib.StringLib;
|
import org.luaj.vm2.lib.StringLib;
|
||||||
import org.luaj.vm2.lib.TableLib;
|
import org.luaj.vm2.lib.TableLib;
|
||||||
|
|
||||||
/** The {@link org.luaj.vm2.lib.jme.JmePlatform} class is a convenience class to standardize
|
/**
|
||||||
* how globals tables are initialized for the JME platform.
|
* The {@link org.luaj.vm2.lib.jme.JmePlatform} class is a convenience class to
|
||||||
|
* standardize how globals tables are initialized for the JME platform.
|
||||||
* <p>
|
* <p>
|
||||||
* The JME platform, being limited, cannot implement all libraries in all aspects. The main limitations are
|
* The JME platform, being limited, cannot implement all libraries in all
|
||||||
|
* aspects. The main limitations are
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Some math functions are not implemented, see {@link MathLib} for details</li>
|
* <li>Some math functions are not implemented, see {@link MathLib} for
|
||||||
* <li>Scripts are loaded via Class.getResourceAsStream(), see {@link BaseLib} for details</li>
|
* details</li>
|
||||||
* <li>OS functions execute(), remove(), rename(), and tmpname() vary, see {@link OsLib} for details</li>
|
* <li>Scripts are loaded via Class.getResourceAsStream(), see {@link BaseLib}
|
||||||
* <li>I/O seek is not implemented, see {@link org.luaj.vm2.lib.jme.JmeIoLib} for details</li>
|
* for details</li>
|
||||||
* <li>luajava is not available, see {@link org.luaj.vm2.lib.jse.LuajavaLib} for details</li>
|
* <li>OS functions execute(), remove(), rename(), and tmpname() vary, see
|
||||||
|
* {@link OsLib} for details</li>
|
||||||
|
* <li>I/O seek is not implemented, see {@link org.luaj.vm2.lib.jme.JmeIoLib}
|
||||||
|
* for details</li>
|
||||||
|
* <li>luajava is not available, see {@link org.luaj.vm2.lib.jse.LuajavaLib} for
|
||||||
|
* details</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* It is used to allocate either a set of standard globals using
|
* It is used to allocate either a set of standard globals using
|
||||||
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
|
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
|
||||||
* <p>
|
* <p>
|
||||||
* A simple example of initializing globals and using them from Java is:
|
* A simple example of initializing globals and using them from Java is:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals global = JmePlatform.standardGlobals();
|
* Globals global = JmePlatform.standardGlobals();
|
||||||
* global.get("print").call(LuaValue.valueOf("hello, world"));
|
* global.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* Once globals are created, a simple way to load and run a script is:
|
* Once globals are created, a simple way to load and run a script is:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* LoadState.load( getClass().getResourceAsStream("main.lua"), "main.lua", globals ).call();
|
* LoadState.load( getClass().getResourceAsStream("main.lua"), "main.lua", globals ).call();
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* although {@code require} could also be used:
|
* although {@code require} could also be used:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* globals.get("require").call(LuaValue.valueOf("main"));
|
* globals.get("require").call(LuaValue.valueOf("main"));
|
||||||
* } </pre>
|
* }
|
||||||
* For this to succeed, the file "main.lua" must be a resource in the class path.
|
* </pre>
|
||||||
* See {@link BaseLib} for details on finding scripts using {@link ResourceFinder}.
|
*
|
||||||
|
* For this to succeed, the file "main.lua" must be a resource in the class
|
||||||
|
* path. See {@link BaseLib} for details on finding scripts using
|
||||||
|
* {@link ResourceFinder}.
|
||||||
* <p>
|
* <p>
|
||||||
* The standard globals will contain all standard libraries in their JME flavors:
|
* The standard globals will contain all standard libraries in their JME
|
||||||
|
* flavors:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link Globals}</li>
|
* <li>{@link Globals}</li>
|
||||||
* <li>{@link BaseLib}</li>
|
* <li>{@link BaseLib}</li>
|
||||||
@@ -83,9 +103,11 @@ import org.luaj.vm2.lib.TableLib;
|
|||||||
* <li>{@link org.luaj.vm2.lib.jme.JmeIoLib}</li>
|
* <li>{@link org.luaj.vm2.lib.jme.JmeIoLib}</li>
|
||||||
* <li>{@link OsLib}</li>
|
* <li>{@link OsLib}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.
|
* In addition, the {@link LuaC} compiler is installed so lua files may be
|
||||||
|
* loaded in their source form.
|
||||||
* <p>
|
* <p>
|
||||||
* The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}.
|
* The debug globals are simply the standard globals plus the {@code debug}
|
||||||
|
* library {@link DebugLib}.
|
||||||
* <p>
|
* <p>
|
||||||
* <p>
|
* <p>
|
||||||
* The class ensures that initialization is done in the correct order.
|
* The class ensures that initialization is done in the correct order.
|
||||||
@@ -119,9 +141,11 @@ public class JmePlatform {
|
|||||||
return globals;
|
return globals;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create standard globals including the {@link DebugLib} library.
|
/**
|
||||||
|
* Create standard globals including the {@link DebugLib} library.
|
||||||
*
|
*
|
||||||
* @return Table of globals initialized with the standard JSE and debug libraries
|
* @return Table of globals initialized with the standard JSE and debug
|
||||||
|
* libraries
|
||||||
* @see #standardGlobals()
|
* @see #standardGlobals()
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2009-2012 Luaj.org. All rights reserved.
|
* Copyright (c) 2009-2012 Luaj.org. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -38,26 +39,19 @@ import org.luaj.vm2.Varargs;
|
|||||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||||
import org.luaj.vm2.luajc.LuaJC;
|
import org.luaj.vm2.luajc.LuaJC;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lua command for use in JSE environments.
|
* lua command for use in JSE environments.
|
||||||
*/
|
*/
|
||||||
public class lua {
|
public class lua {
|
||||||
private static final String version = Lua._VERSION + " Copyright (c) 2012 Luaj.org.org";
|
private static final String version = Lua._VERSION + " Copyright (c) 2012 Luaj.org.org";
|
||||||
|
|
||||||
private static final String usage =
|
private static final String usage = "usage: java -cp luaj-jse.jar lua [options] [script [args]].\n"
|
||||||
"usage: java -cp luaj-jse.jar lua [options] [script [args]].\n" +
|
+ "Available options are:\n" + " -e stat execute string 'stat'\n" + " -l name require library 'name'\n"
|
||||||
"Available options are:\n" +
|
+ " -i enter interactive mode after executing 'script'\n" + " -v show version information\n"
|
||||||
" -e stat execute string 'stat'\n" +
|
+ " -b use luajc bytecode-to-bytecode compiler (requires bcel on class path)\n"
|
||||||
" -l name require library 'name'\n" +
|
+ " -n nodebug - do not load debug library by default\n" + " -p print the prototype\n"
|
||||||
" -i enter interactive mode after executing 'script'\n" +
|
+ " -c enc use the supplied encoding 'enc' for input files\n" + " -- stop handling options\n"
|
||||||
" -v show version information\n" +
|
+ " - execute stdin and stop handling options";
|
||||||
" -b use luajc bytecode-to-bytecode compiler (requires bcel on class path)\n" +
|
|
||||||
" -n nodebug - do not load debug library by default\n" +
|
|
||||||
" -p print the prototype\n" +
|
|
||||||
" -c enc use the supplied encoding 'enc' for input files\n" +
|
|
||||||
" -- stop handling options\n" +
|
|
||||||
" - execute stdin and stop handling options";
|
|
||||||
|
|
||||||
private static void usageExit() {
|
private static void usageExit() {
|
||||||
System.out.println(usage);
|
System.out.println(usage);
|
||||||
@@ -137,7 +131,8 @@ public class lua {
|
|||||||
|
|
||||||
// new lua state
|
// new lua state
|
||||||
globals = nodebug? JsePlatform.standardGlobals(): JsePlatform.debugGlobals();
|
globals = nodebug? JsePlatform.standardGlobals(): JsePlatform.debugGlobals();
|
||||||
if ( luajc ) LuaJC.install(globals);
|
if (luajc)
|
||||||
|
LuaJC.install(globals);
|
||||||
for (int i = 0, n = libs != null? libs.size(): 0; i < n; i++)
|
for (int i = 0, n = libs != null? libs.size(): 0; i < n; i++)
|
||||||
loadLibrary((String) libs.elementAt(i));
|
loadLibrary((String) libs.elementAt(i));
|
||||||
|
|
||||||
@@ -192,14 +187,14 @@ public class lua {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processScript( InputStream script, String chunkname, String[] args, int firstarg ) throws IOException {
|
private static void processScript(InputStream script, String chunkname, String[] args, int firstarg)
|
||||||
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
LuaValue c;
|
LuaValue c;
|
||||||
try {
|
try {
|
||||||
script = new BufferedInputStream(script);
|
script = new BufferedInputStream(script);
|
||||||
c = encoding != null?
|
c = encoding != null? globals.load(new InputStreamReader(script, encoding), chunkname)
|
||||||
globals.load(new InputStreamReader(script, encoding), chunkname):
|
: globals.load(script, chunkname, "bt", globals);
|
||||||
globals.load(script, chunkname, "bt", globals);
|
|
||||||
} finally {
|
} finally {
|
||||||
script.close();
|
script.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2009 Luaj.org. All rights reserved.
|
* Copyright (c) 2009 Luaj.org. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -35,26 +36,19 @@ import org.luaj.vm2.Prototype;
|
|||||||
import org.luaj.vm2.compiler.DumpState;
|
import org.luaj.vm2.compiler.DumpState;
|
||||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiler for lua files to lua bytecode.
|
* Compiler for lua files to lua bytecode.
|
||||||
*/
|
*/
|
||||||
public class luac {
|
public class luac {
|
||||||
private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org";
|
private static final String version = Lua._VERSION + "Copyright (C) 2009 luaj.org";
|
||||||
|
|
||||||
private static final String usage =
|
private static final String usage = "usage: java -cp luaj-jse.jar luac [options] [filenames].\n"
|
||||||
"usage: java -cp luaj-jse.jar luac [options] [filenames].\n" +
|
+ "Available options are:\n" + " - process stdin\n" + " -l list\n"
|
||||||
"Available options are:\n" +
|
+ " -o name output to file 'name' (default is \"luac.out\")\n" + " -p parse only\n"
|
||||||
" - process stdin\n" +
|
+ " -s strip debug information\n" + " -e little endian format for numbers\n"
|
||||||
" -l list\n" +
|
+ " -i<n> number format 'n', (n=0,1 or 4, default=" + DumpState.NUMBER_FORMAT_DEFAULT + ")\n"
|
||||||
" -o name output to file 'name' (default is \"luac.out\")\n" +
|
+ " -v show version information\n" + " -c enc use the supplied encoding 'enc' for input files\n"
|
||||||
" -p parse only\n" +
|
+ " -- stop handling options\n";
|
||||||
" -s strip debug information\n" +
|
|
||||||
" -e little endian format for numbers\n" +
|
|
||||||
" -i<n> number format 'n', (n=0,1 or 4, default="+DumpState.NUMBER_FORMAT_DEFAULT+")\n" +
|
|
||||||
" -v show version information\n" +
|
|
||||||
" -c enc use the supplied encoding 'enc' for input files\n" +
|
|
||||||
" -- stop handling options\n";
|
|
||||||
|
|
||||||
private static void usageExit() {
|
private static void usageExit() {
|
||||||
System.out.println(usage);
|
System.out.println(usage);
|
||||||
@@ -168,13 +162,14 @@ public class luac {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processScript( Globals globals, InputStream script, String chunkname, OutputStream out ) throws IOException {
|
private void processScript(Globals globals, InputStream script, String chunkname, OutputStream out)
|
||||||
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
// create the chunk
|
// create the chunk
|
||||||
script = new BufferedInputStream(script);
|
script = new BufferedInputStream(script);
|
||||||
Prototype chunk = encoding != null?
|
Prototype chunk = encoding != null
|
||||||
globals.compilePrototype(new InputStreamReader(script, encoding), chunkname):
|
? globals.compilePrototype(new InputStreamReader(script, encoding), chunkname)
|
||||||
globals.compilePrototype(script, chunkname);
|
: globals.compilePrototype(script, chunkname);
|
||||||
|
|
||||||
// list the chunk
|
// list the chunk
|
||||||
if (list)
|
if (list)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2009-2012 Luaj.org. All rights reserved.
|
* Copyright (c) 2009-2012 Luaj.org. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -36,23 +37,18 @@ import org.luaj.vm2.lib.jse.JsePlatform;
|
|||||||
import org.luaj.vm2.luajc.LuaJC;
|
import org.luaj.vm2.luajc.LuaJC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiler for lua files to compile lua sources or lua binaries into java classes.
|
* Compiler for lua files to compile lua sources or lua binaries into java
|
||||||
|
* classes.
|
||||||
*/
|
*/
|
||||||
public class luajc {
|
public class luajc {
|
||||||
private static final String version = Lua._VERSION + " Copyright (C) 2012 luaj.org";
|
private static final String version = Lua._VERSION + " Copyright (C) 2012 luaj.org";
|
||||||
|
|
||||||
private static final String usage =
|
private static final String usage = "usage: java -cp luaj-jse.jar,bcel-5.2.jar luajc [options] fileordir [, fileordir ...]\n"
|
||||||
"usage: java -cp luaj-jse.jar,bcel-5.2.jar luajc [options] fileordir [, fileordir ...]\n" +
|
+ "Available options are:\n" + " - process stdin\n" + " -s src source directory\n"
|
||||||
"Available options are:\n" +
|
+ " -d dir destination directory\n" + " -p pkg package prefix to apply to all classes\n"
|
||||||
" - process stdin\n" +
|
+ " -m generate main(String[]) function for JSE\n" + " -r recursively compile all\n"
|
||||||
" -s src source directory\n" +
|
+ " -l load classes to verify generated bytecode\n"
|
||||||
" -d dir destination directory\n" +
|
+ " -c enc use the supplied encoding 'enc' for input files\n" + " -v verbose\n";
|
||||||
" -p pkg package prefix to apply to all classes\n" +
|
|
||||||
" -m generate main(String[]) function for JSE\n" +
|
|
||||||
" -r recursively compile all\n" +
|
|
||||||
" -l load classes to verify generated bytecode\n" +
|
|
||||||
" -c enc use the supplied encoding 'enc' for input files\n" +
|
|
||||||
" -v verbose\n";
|
|
||||||
|
|
||||||
private static void usageExit() {
|
private static void usageExit() {
|
||||||
System.out.println(usage);
|
System.out.println(usage);
|
||||||
@@ -165,6 +161,7 @@ public class luajc {
|
|||||||
scanfile(dir, f, pkgprefix);
|
scanfile(dir, f, pkgprefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scandir(File dir, String javapackage) {
|
private void scandir(File dir, String javapackage) {
|
||||||
File[] f = dir.listFiles();
|
File[] f = dir.listFiles();
|
||||||
for (int i = 0; i < f.length; i++)
|
for (int i = 0; i < f.length; i++)
|
||||||
@@ -208,7 +205,8 @@ public class luajc {
|
|||||||
String outdirpath = subdir != null? destdir + "/" + subdir: destdir;
|
String outdirpath = subdir != null? destdir + "/" + subdir: destdir;
|
||||||
this.javapackage = javapackage;
|
this.javapackage = javapackage;
|
||||||
this.srcfilename = (subdir != null? subdir + "/": "")+infile.getName();
|
this.srcfilename = (subdir != null? subdir + "/": "")+infile.getName();
|
||||||
this.luachunkname = (subdir!=null? subdir+"/": "")+infile.getName().substring( 0, infile.getName().lastIndexOf('.') );
|
this.luachunkname = (subdir != null? subdir + "/": "")
|
||||||
|
+infile.getName().substring(0, infile.getName().lastIndexOf('.'));
|
||||||
this.infile = f;
|
this.infile = f;
|
||||||
this.outdir = new File(outdirpath);
|
this.outdir = new File(outdirpath);
|
||||||
}
|
}
|
||||||
@@ -222,9 +220,10 @@ public class luajc {
|
|||||||
|
|
||||||
// create the chunk
|
// create the chunk
|
||||||
FileInputStream fis = new FileInputStream(inf.infile);
|
FileInputStream fis = new FileInputStream(inf.infile);
|
||||||
final Hashtable t = encoding != null?
|
final Hashtable t = encoding != null
|
||||||
LuaJC.instance.compileAll( new InputStreamReader(fis, encoding), inf.luachunkname, inf.srcfilename, globals, genmain):
|
? LuaJC.instance.compileAll(new InputStreamReader(fis, encoding), inf.luachunkname, inf.srcfilename,
|
||||||
LuaJC.instance.compileAll( fis, inf.luachunkname, inf.srcfilename, globals, genmain);
|
globals, genmain)
|
||||||
|
: LuaJC.instance.compileAll(fis, inf.luachunkname, inf.srcfilename, globals, genmain);
|
||||||
fis.close();
|
fis.close();
|
||||||
|
|
||||||
// write out the chunk
|
// write out the chunk
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ package org.luaj.vm2.ast;
|
|||||||
import org.luaj.vm2.Lua;
|
import org.luaj.vm2.Lua;
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
abstract
|
abstract public class Exp extends SyntaxElement {
|
||||||
public class Exp extends SyntaxElement {
|
|
||||||
abstract public void accept(Visitor visitor);
|
abstract public void accept(Visitor visitor);
|
||||||
|
|
||||||
public static Exp constant(LuaValue value) {
|
public static Exp constant(LuaValue value) {
|
||||||
@@ -63,14 +62,12 @@ public class Exp extends SyntaxElement {
|
|||||||
// TODO: constant folding
|
// TODO: constant folding
|
||||||
if (lhs instanceof BinopExp) {
|
if (lhs instanceof BinopExp) {
|
||||||
BinopExp b = (BinopExp) lhs;
|
BinopExp b = (BinopExp) lhs;
|
||||||
if ( (precedence(op) > precedence(b.op)) ||
|
if ((precedence(op) > precedence(b.op)) || ((precedence(op) == precedence(b.op)) && isrightassoc(op)))
|
||||||
((precedence(op) == precedence(b.op)) && isrightassoc(op)) )
|
|
||||||
return binaryexp(b.lhs, b.op, binaryexp(b.rhs, op, rhs));
|
return binaryexp(b.lhs, b.op, binaryexp(b.rhs, op, rhs));
|
||||||
}
|
}
|
||||||
if (rhs instanceof BinopExp) {
|
if (rhs instanceof BinopExp) {
|
||||||
BinopExp b = (BinopExp) rhs;
|
BinopExp b = (BinopExp) rhs;
|
||||||
if ( (precedence(op) > precedence(b.op)) ||
|
if ((precedence(op) > precedence(b.op)) || ((precedence(op) == precedence(b.op)) && !isrightassoc(op)))
|
||||||
((precedence(op) == precedence(b.op)) && ! isrightassoc(op)) )
|
|
||||||
return binaryexp(binaryexp(lhs, op, b.lhs), b.op, b.rhs);
|
return binaryexp(binaryexp(lhs, op, b.lhs), b.op, b.rhs);
|
||||||
}
|
}
|
||||||
return new BinopExp(lhs, op, rhs);
|
return new BinopExp(lhs, op, rhs);
|
||||||
@@ -79,22 +76,43 @@ public class Exp extends SyntaxElement {
|
|||||||
static boolean isrightassoc(int op) {
|
static boolean isrightassoc(int op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Lua.OP_CONCAT:
|
case Lua.OP_CONCAT:
|
||||||
case Lua.OP_POW: return true;
|
case Lua.OP_POW:
|
||||||
default: return false;
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int precedence(int op) {
|
static int precedence(int op) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Lua.OP_OR: return 0;
|
case Lua.OP_OR:
|
||||||
case Lua.OP_AND: return 1;
|
return 0;
|
||||||
case Lua.OP_LT: case Lua.OP_GT: case Lua.OP_LE: case Lua.OP_GE: case Lua.OP_NEQ: case Lua.OP_EQ: return 2;
|
case Lua.OP_AND:
|
||||||
case Lua.OP_CONCAT: return 3;
|
return 1;
|
||||||
case Lua.OP_ADD: case Lua.OP_SUB: return 4;
|
case Lua.OP_LT:
|
||||||
case Lua.OP_MUL: case Lua.OP_DIV: case Lua.OP_MOD: return 5;
|
case Lua.OP_GT:
|
||||||
case Lua.OP_NOT: case Lua.OP_UNM: case Lua.OP_LEN: return 6;
|
case Lua.OP_LE:
|
||||||
case Lua.OP_POW: return 7;
|
case Lua.OP_GE:
|
||||||
default: throw new IllegalStateException("precedence of bad op "+op);
|
case Lua.OP_NEQ:
|
||||||
|
case Lua.OP_EQ:
|
||||||
|
return 2;
|
||||||
|
case Lua.OP_CONCAT:
|
||||||
|
return 3;
|
||||||
|
case Lua.OP_ADD:
|
||||||
|
case Lua.OP_SUB:
|
||||||
|
return 4;
|
||||||
|
case Lua.OP_MUL:
|
||||||
|
case Lua.OP_DIV:
|
||||||
|
case Lua.OP_MOD:
|
||||||
|
return 5;
|
||||||
|
case Lua.OP_NOT:
|
||||||
|
case Lua.OP_UNM:
|
||||||
|
case Lua.OP_LEN:
|
||||||
|
return 6;
|
||||||
|
case Lua.OP_POW:
|
||||||
|
return 7;
|
||||||
|
default:
|
||||||
|
throw new IllegalStateException("precedence of bad op " + op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +166,7 @@ public class Exp extends SyntaxElement {
|
|||||||
public boolean isvarexp() {
|
public boolean isvarexp() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isfunccall() {
|
public boolean isfunccall() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -157,18 +176,22 @@ public class Exp extends SyntaxElement {
|
|||||||
public boolean isvarexp() {
|
public boolean isvarexp() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markHasAssignment() {
|
public void markHasAssignment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NameExp extends VarExp {
|
public static class NameExp extends VarExp {
|
||||||
public final Name name;
|
public final Name name;
|
||||||
|
|
||||||
public NameExp(String name) {
|
public NameExp(String name) {
|
||||||
this.name = new Name(name);
|
this.name = new Name(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markHasAssignment() {
|
public void markHasAssignment() {
|
||||||
name.variable.hasassignments = true;
|
name.variable.hasassignments = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
@@ -176,6 +199,7 @@ public class Exp extends SyntaxElement {
|
|||||||
|
|
||||||
public static class ParensExp extends PrimaryExp {
|
public static class ParensExp extends PrimaryExp {
|
||||||
public final Exp exp;
|
public final Exp exp;
|
||||||
|
|
||||||
public ParensExp(Exp exp) {
|
public ParensExp(Exp exp) {
|
||||||
this.exp = exp;
|
this.exp = exp;
|
||||||
}
|
}
|
||||||
@@ -188,6 +212,7 @@ public class Exp extends SyntaxElement {
|
|||||||
public static class FieldExp extends VarExp {
|
public static class FieldExp extends VarExp {
|
||||||
public final PrimaryExp lhs;
|
public final PrimaryExp lhs;
|
||||||
public final Name name;
|
public final Name name;
|
||||||
|
|
||||||
public FieldExp(PrimaryExp lhs, String name) {
|
public FieldExp(PrimaryExp lhs, String name) {
|
||||||
this.lhs = lhs;
|
this.lhs = lhs;
|
||||||
this.name = new Name(name);
|
this.name = new Name(name);
|
||||||
@@ -201,6 +226,7 @@ public class Exp extends SyntaxElement {
|
|||||||
public static class IndexExp extends VarExp {
|
public static class IndexExp extends VarExp {
|
||||||
public final PrimaryExp lhs;
|
public final PrimaryExp lhs;
|
||||||
public final Exp exp;
|
public final Exp exp;
|
||||||
|
|
||||||
public IndexExp(PrimaryExp lhs, Exp exp) {
|
public IndexExp(PrimaryExp lhs, Exp exp) {
|
||||||
this.lhs = lhs;
|
this.lhs = lhs;
|
||||||
this.exp = exp;
|
this.exp = exp;
|
||||||
@@ -252,6 +278,7 @@ public class Exp extends SyntaxElement {
|
|||||||
|
|
||||||
public static class Constant extends Exp {
|
public static class Constant extends Exp {
|
||||||
public final LuaValue value;
|
public final LuaValue value;
|
||||||
|
|
||||||
public Constant(LuaValue value) {
|
public Constant(LuaValue value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
@@ -275,6 +302,7 @@ public class Exp extends SyntaxElement {
|
|||||||
public static class UnopExp extends Exp {
|
public static class UnopExp extends Exp {
|
||||||
public final int op;
|
public final int op;
|
||||||
public final Exp rhs;
|
public final Exp rhs;
|
||||||
|
|
||||||
public UnopExp(int op, Exp rhs) {
|
public UnopExp(int op, Exp rhs) {
|
||||||
this.op = op;
|
this.op = op;
|
||||||
this.rhs = rhs;
|
this.rhs = rhs;
|
||||||
@@ -288,6 +316,7 @@ public class Exp extends SyntaxElement {
|
|||||||
public static class BinopExp extends Exp {
|
public static class BinopExp extends Exp {
|
||||||
public final Exp lhs, rhs;
|
public final Exp lhs, rhs;
|
||||||
public final int op;
|
public final int op;
|
||||||
|
|
||||||
public BinopExp(Exp lhs, int op, Exp rhs) {
|
public BinopExp(Exp lhs, int op, Exp rhs) {
|
||||||
this.lhs = lhs;
|
this.lhs = lhs;
|
||||||
this.op = op;
|
this.op = op;
|
||||||
@@ -301,6 +330,7 @@ public class Exp extends SyntaxElement {
|
|||||||
|
|
||||||
public static class AnonFuncDef extends Exp {
|
public static class AnonFuncDef extends Exp {
|
||||||
public final FuncBody body;
|
public final FuncBody body;
|
||||||
|
|
||||||
public AnonFuncDef(FuncBody funcbody) {
|
public AnonFuncDef(FuncBody funcbody) {
|
||||||
this.body = funcbody;
|
this.body = funcbody;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class FuncBody extends SyntaxElement {
|
|||||||
this.parlist = parlist != null? parlist: ParList.EMPTY_PARLIST;
|
this.parlist = parlist != null? parlist: ParList.EMPTY_PARLIST;
|
||||||
this.block = block;
|
this.block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.ast;
|
package org.luaj.vm2.ast;
|
||||||
|
|
||||||
|
|
||||||
public class Name {
|
public class Name {
|
||||||
public final String name;
|
public final String name;
|
||||||
public Variable variable;
|
public Variable variable;
|
||||||
|
|
||||||
public Name(String name) {
|
public Name(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import org.luaj.vm2.ast.Stat.LocalFuncDef;
|
|||||||
import org.luaj.vm2.ast.Stat.NumericFor;
|
import org.luaj.vm2.ast.Stat.NumericFor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor that resolves names to scopes.
|
* Visitor that resolves names to scopes. Each Name is resolved to a
|
||||||
* Each Name is resolved to a NamedVarible, possibly in a NameScope
|
* NamedVarible, possibly in a NameScope if it is a local, or in no named scope
|
||||||
* if it is a local, or in no named scope if it is a global.
|
* if it is a global.
|
||||||
*/
|
*/
|
||||||
public class NameResolver extends Visitor {
|
public class NameResolver extends Visitor {
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ public class NameResolver extends Visitor {
|
|||||||
private void pushScope() {
|
private void pushScope() {
|
||||||
scope = new NameScope(scope);
|
scope = new NameScope(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void popScope() {
|
private void popScope() {
|
||||||
scope = scope.outerScope;
|
scope = scope.outerScope;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,17 +26,13 @@ import java.util.HashSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
public class NameScope {
|
public class NameScope {
|
||||||
|
|
||||||
private static final Set<String> LUA_KEYWORDS = new HashSet<String>();
|
private static final Set<String> LUA_KEYWORDS = new HashSet<String>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
String[] k = new String[] {
|
String[] k = new String[] { "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if",
|
||||||
"and", "break", "do", "else", "elseif", "end",
|
"in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while" };
|
||||||
"false", "for", "function", "if", "in", "local",
|
|
||||||
"nil", "not", "or", "repeat", "return",
|
|
||||||
"then", "true", "until", "while" };
|
|
||||||
for (int i = 0; i < k.length; i++)
|
for (int i = 0; i < k.length; i++)
|
||||||
LUA_KEYWORDS.add(k[i]);
|
LUA_KEYWORDS.add(k[i]);
|
||||||
}
|
}
|
||||||
@@ -59,7 +55,10 @@ public class NameScope {
|
|||||||
this.functionNestingCount = outerScope != null? outerScope.functionNestingCount: 0;
|
this.functionNestingCount = outerScope != null? outerScope.functionNestingCount: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Look up a name. If it is a global name, then throw IllegalArgumentException. */
|
/**
|
||||||
|
* Look up a name. If it is a global name, then throw
|
||||||
|
* IllegalArgumentException.
|
||||||
|
*/
|
||||||
public Variable find(String name) throws IllegalArgumentException {
|
public Variable find(String name) throws IllegalArgumentException {
|
||||||
validateIsNotKeyword(name);
|
validateIsNotKeyword(name);
|
||||||
for (NameScope n = this; n != null; n = n.outerScope)
|
for (NameScope n = this; n != null; n = n.outerScope)
|
||||||
@@ -70,7 +69,10 @@ public class NameScope {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Define a name in this scope. If it is a global name, then throw IllegalArgumentException. */
|
/**
|
||||||
|
* Define a name in this scope. If it is a global name, then throw
|
||||||
|
* IllegalArgumentException.
|
||||||
|
*/
|
||||||
public Variable define(String name) throws IllegalStateException, IllegalArgumentException {
|
public Variable define(String name) throws IllegalStateException, IllegalArgumentException {
|
||||||
validateIsNotKeyword(name);
|
validateIsNotKeyword(name);
|
||||||
Variable value = new Variable(name, this);
|
Variable value = new Variable(name, this);
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.luaj.vm2.ast.Exp.VarExp;
|
import org.luaj.vm2.ast.Exp.VarExp;
|
||||||
|
|
||||||
abstract
|
abstract public class Stat extends SyntaxElement {
|
||||||
public class Stat extends SyntaxElement {
|
|
||||||
public abstract void accept(Visitor visitor);
|
public abstract void accept(Visitor visitor);
|
||||||
|
|
||||||
public static Stat block(Block block) {
|
public static Stat block(Block block) {
|
||||||
@@ -77,7 +76,8 @@ public class Stat extends SyntaxElement {
|
|||||||
return new LocalAssign(names, values);
|
return new LocalAssign(names, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Stat ifthenelse(Exp ifexp, Block ifblock, List<Exp> elseifexps, List<Block> elseifblocks, Block elseblock) {
|
public static Stat ifthenelse(Exp ifexp, Block ifblock, List<Exp> elseifexps, List<Block> elseifblocks,
|
||||||
|
Block elseblock) {
|
||||||
return new IfThenElse(ifexp, ifblock, elseifexps, elseifblocks, elseblock);
|
return new IfThenElse(ifexp, ifblock, elseifexps, elseifblocks, elseblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,9 +91,11 @@ public class Stat extends SyntaxElement {
|
|||||||
|
|
||||||
public static class Goto extends Stat {
|
public static class Goto extends Stat {
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
public Goto(String name) {
|
public Goto(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
@@ -101,9 +103,11 @@ public class Stat extends SyntaxElement {
|
|||||||
|
|
||||||
public static class Label extends Stat {
|
public static class Label extends Stat {
|
||||||
public final String name;
|
public final String name;
|
||||||
|
|
||||||
public Label(String name) {
|
public Label(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
@@ -127,10 +131,12 @@ public class Stat extends SyntaxElement {
|
|||||||
public static class WhileDo extends Stat {
|
public static class WhileDo extends Stat {
|
||||||
public final Exp exp;
|
public final Exp exp;
|
||||||
public final Block block;
|
public final Block block;
|
||||||
|
|
||||||
public WhileDo(Exp exp, Block block) {
|
public WhileDo(Exp exp, Block block) {
|
||||||
this.exp = exp;
|
this.exp = exp;
|
||||||
this.block = block;
|
this.block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
@@ -139,10 +145,12 @@ public class Stat extends SyntaxElement {
|
|||||||
public static class RepeatUntil extends Stat {
|
public static class RepeatUntil extends Stat {
|
||||||
public final Block block;
|
public final Block block;
|
||||||
public final Exp exp;
|
public final Exp exp;
|
||||||
|
|
||||||
public RepeatUntil(Block block, Exp exp) {
|
public RepeatUntil(Block block, Exp exp) {
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.exp = exp;
|
this.exp = exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void accept(Visitor visitor) {
|
public void accept(Visitor visitor) {
|
||||||
visitor.visit(this);
|
visitor.visit(this);
|
||||||
}
|
}
|
||||||
@@ -156,6 +164,7 @@ public class Stat extends SyntaxElement {
|
|||||||
|
|
||||||
public static class Return extends Stat {
|
public static class Return extends Stat {
|
||||||
public final List<Exp> values;
|
public final List<Exp> values;
|
||||||
|
|
||||||
public Return(List<Exp> values) {
|
public Return(List<Exp> values) {
|
||||||
this.values = values;
|
this.values = values;
|
||||||
}
|
}
|
||||||
@@ -174,6 +183,7 @@ public class Stat extends SyntaxElement {
|
|||||||
|
|
||||||
public static class FuncCallStat extends Stat {
|
public static class FuncCallStat extends Stat {
|
||||||
public final Exp.FuncCall funccall;
|
public final Exp.FuncCall funccall;
|
||||||
|
|
||||||
public FuncCallStat(Exp.FuncCall funccall) {
|
public FuncCallStat(Exp.FuncCall funccall) {
|
||||||
this.funccall = funccall;
|
this.funccall = funccall;
|
||||||
}
|
}
|
||||||
@@ -186,6 +196,7 @@ public class Stat extends SyntaxElement {
|
|||||||
public static class LocalFuncDef extends Stat {
|
public static class LocalFuncDef extends Stat {
|
||||||
public final Name name;
|
public final Name name;
|
||||||
public final FuncBody body;
|
public final FuncBody body;
|
||||||
|
|
||||||
public LocalFuncDef(String name, FuncBody body) {
|
public LocalFuncDef(String name, FuncBody body) {
|
||||||
this.name = new Name(name);
|
this.name = new Name(name);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
@@ -199,6 +210,7 @@ public class Stat extends SyntaxElement {
|
|||||||
public static class FuncDef extends Stat {
|
public static class FuncDef extends Stat {
|
||||||
public final FuncName name;
|
public final FuncName name;
|
||||||
public final FuncBody body;
|
public final FuncBody body;
|
||||||
|
|
||||||
public FuncDef(FuncName name, FuncBody body) {
|
public FuncDef(FuncName name, FuncBody body) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
@@ -214,6 +226,7 @@ public class Stat extends SyntaxElement {
|
|||||||
public List<Exp> exps;
|
public List<Exp> exps;
|
||||||
public Block block;
|
public Block block;
|
||||||
public NameScope scope;
|
public NameScope scope;
|
||||||
|
|
||||||
public GenericFor(List<Name> names, List<Exp> exps, Block block) {
|
public GenericFor(List<Name> names, List<Exp> exps, Block block) {
|
||||||
this.names = names;
|
this.names = names;
|
||||||
this.exps = exps;
|
this.exps = exps;
|
||||||
@@ -230,6 +243,7 @@ public class Stat extends SyntaxElement {
|
|||||||
public final Exp initial, limit, step;
|
public final Exp initial, limit, step;
|
||||||
public final Block block;
|
public final Block block;
|
||||||
public NameScope scope;
|
public NameScope scope;
|
||||||
|
|
||||||
public NumericFor(String name, Exp initial, Exp limit, Exp step, Block block) {
|
public NumericFor(String name, Exp initial, Exp limit, Exp step, Block block) {
|
||||||
this.name = new Name(name);
|
this.name = new Name(name);
|
||||||
this.initial = initial;
|
this.initial = initial;
|
||||||
@@ -246,6 +260,7 @@ public class Stat extends SyntaxElement {
|
|||||||
public static class LocalAssign extends Stat {
|
public static class LocalAssign extends Stat {
|
||||||
public final List<Name> names;
|
public final List<Name> names;
|
||||||
public final List<Exp> values;
|
public final List<Exp> values;
|
||||||
|
|
||||||
public LocalAssign(List<Name> names, List<Exp> values) {
|
public LocalAssign(List<Name> names, List<Exp> values) {
|
||||||
this.names = names;
|
this.names = names;
|
||||||
this.values = values;
|
this.values = values;
|
||||||
@@ -262,8 +277,8 @@ public class Stat extends SyntaxElement {
|
|||||||
public final List<Exp> elseifexps;
|
public final List<Exp> elseifexps;
|
||||||
public final List<Block> elseifblocks;
|
public final List<Block> elseifblocks;
|
||||||
public final Block elseblock;
|
public final Block elseblock;
|
||||||
public IfThenElse(Exp ifexp, Block ifblock, List<Exp> elseifexps,
|
|
||||||
List<Block> elseifblocks, Block elseblock) {
|
public IfThenElse(Exp ifexp, Block ifblock, List<Exp> elseifexps, List<Block> elseifblocks, Block elseblock) {
|
||||||
this.ifexp = ifexp;
|
this.ifexp = ifexp;
|
||||||
this.ifblock = ifblock;
|
this.ifblock = ifblock;
|
||||||
this.elseifexps = elseifexps;
|
this.elseifexps = elseifexps;
|
||||||
|
|||||||
@@ -64,25 +64,55 @@ public class Str {
|
|||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
if (c[i] == '\\' && i < n) {
|
if (c[i] == '\\' && i < n) {
|
||||||
switch (c[++i]) {
|
switch (c[++i]) {
|
||||||
case '0': case '1': case '2': case '3': case '4':
|
case '0':
|
||||||
case '5': case '6': case '7': case '8': case '9':
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
int d = (int) (c[i++]-'0');
|
int d = (int) (c[i++]-'0');
|
||||||
for (int j = 0; i < n && j < 2 && c[i] >= '0' && c[i] <= '9'; i++, j++)
|
for (int j = 0; i < n && j < 2 && c[i] >= '0' && c[i] <= '9'; i++, j++)
|
||||||
d = d*10+(int) (c[i]-'0');
|
d = d*10+(int) (c[i]-'0');
|
||||||
baos.write((byte) d);
|
baos.write((byte) d);
|
||||||
--i;
|
--i;
|
||||||
continue;
|
continue;
|
||||||
case 'a': baos.write( (byte) 7 ); continue;
|
case 'a':
|
||||||
case 'b': baos.write( (byte) '\b' ); continue;
|
baos.write((byte) 7);
|
||||||
case 'f': baos.write( (byte) '\f' ); continue;
|
continue;
|
||||||
case 'n': baos.write( (byte) '\n' ); continue;
|
case 'b':
|
||||||
case 'r': baos.write( (byte) '\r' ); continue;
|
baos.write((byte) '\b');
|
||||||
case 't': baos.write( (byte) '\t' ); continue;
|
continue;
|
||||||
case 'v': baos.write( (byte) 11 ); continue;
|
case 'f':
|
||||||
case '"': baos.write( (byte) '"' ); continue;
|
baos.write((byte) '\f');
|
||||||
case '\'': baos.write( (byte) '\'' ); continue;
|
continue;
|
||||||
case '\\': baos.write( (byte) '\\' ); continue;
|
case 'n':
|
||||||
default: baos.write( (byte) c[i] ); break;
|
baos.write((byte) '\n');
|
||||||
|
continue;
|
||||||
|
case 'r':
|
||||||
|
baos.write((byte) '\r');
|
||||||
|
continue;
|
||||||
|
case 't':
|
||||||
|
baos.write((byte) '\t');
|
||||||
|
continue;
|
||||||
|
case 'v':
|
||||||
|
baos.write((byte) 11);
|
||||||
|
continue;
|
||||||
|
case '"':
|
||||||
|
baos.write((byte) '"');
|
||||||
|
continue;
|
||||||
|
case '\'':
|
||||||
|
baos.write((byte) '\'');
|
||||||
|
continue;
|
||||||
|
case '\\':
|
||||||
|
baos.write((byte) '\\');
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
baos.write((byte) c[i]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
baos.write((byte) c[i]);
|
baos.write((byte) c[i]);
|
||||||
|
|||||||
@@ -21,7 +21,8 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.ast;
|
package org.luaj.vm2.ast;
|
||||||
|
|
||||||
/** Base class for syntax elements of the parse tree that appear in source files.
|
/**
|
||||||
|
* Base class for syntax elements of the parse tree that appear in source files.
|
||||||
* The LuaParser class will fill these values out during parsing for use in
|
* The LuaParser class will fill these values out during parsing for use in
|
||||||
* syntax highlighting, for example.
|
* syntax highlighting, for example.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,8 +23,9 @@ package org.luaj.vm2.ast;
|
|||||||
|
|
||||||
import org.luaj.vm2.LuaValue;
|
import org.luaj.vm2.LuaValue;
|
||||||
|
|
||||||
/** Variable is created lua name scopes, and is a named, lua variable that
|
/**
|
||||||
* either refers to a lua local, global, or upvalue storage location.
|
* Variable is created lua name scopes, and is a named, lua variable that either
|
||||||
|
* refers to a lua local, global, or upvalue storage location.
|
||||||
*/
|
*/
|
||||||
public class Variable {
|
public class Variable {
|
||||||
|
|
||||||
@@ -40,7 +41,10 @@ public class Variable {
|
|||||||
/** true if there are assignments made to this variable */
|
/** true if there are assignments made to this variable */
|
||||||
public boolean hasassignments;
|
public boolean hasassignments;
|
||||||
|
|
||||||
/** When hasassignments == false, and the initial value is a constant, this is the initial value */
|
/**
|
||||||
|
* When hasassignments == false, and the initial value is a constant, this
|
||||||
|
* is the initial value
|
||||||
|
*/
|
||||||
public LuaValue initialValue;
|
public LuaValue initialValue;
|
||||||
|
|
||||||
/** Global is named variable not associated with a defining scope */
|
/** Global is named variable not associated with a defining scope */
|
||||||
@@ -48,15 +52,14 @@ public class Variable {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.definingScope = null;
|
this.definingScope = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Variable(String name, NameScope definingScope) {
|
public Variable(String name, NameScope definingScope) {
|
||||||
/** Local variable is defined in a particular scope. */
|
/** Local variable is defined in a particular scope. */
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.definingScope = definingScope;
|
this.definingScope = definingScope;
|
||||||
}
|
}
|
||||||
public boolean isLocal() {
|
|
||||||
return this.definingScope != null;
|
public boolean isLocal() { return this.definingScope != null; }
|
||||||
}
|
|
||||||
public boolean isConstant() {
|
public boolean isConstant() { return !hasassignments && initialValue != null; }
|
||||||
return ! hasassignments && initialValue != null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -29,30 +29,37 @@ abstract public class Visitor {
|
|||||||
public void visit(Chunk chunk) {
|
public void visit(Chunk chunk) {
|
||||||
chunk.block.accept(this);
|
chunk.block.accept(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
public void visit(Block block) {
|
public void visit(Block block) {
|
||||||
visit(block.scope);
|
visit(block.scope);
|
||||||
if (block.stats != null)
|
if (block.stats != null)
|
||||||
for (int i = 0, n = block.stats.size(); i < n; i++)
|
for (int i = 0, n = block.stats.size(); i < n; i++)
|
||||||
((Stat) block.stats.get(i)).accept(this);
|
((Stat) block.stats.get(i)).accept(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
public void visit(Stat.Assign stat) {
|
public void visit(Stat.Assign stat) {
|
||||||
visitVars(stat.vars);
|
visitVars(stat.vars);
|
||||||
visitExps(stat.exps);
|
visitExps(stat.exps);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.Break breakstat) {
|
public void visit(Stat.Break breakstat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.FuncCallStat stat) {
|
public void visit(Stat.FuncCallStat stat) {
|
||||||
stat.funccall.accept(this);
|
stat.funccall.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.FuncDef stat) {
|
public void visit(Stat.FuncDef stat) {
|
||||||
stat.body.accept(this);
|
stat.body.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.GenericFor stat) {
|
public void visit(Stat.GenericFor stat) {
|
||||||
visit(stat.scope);
|
visit(stat.scope);
|
||||||
visitNames(stat.names);
|
visitNames(stat.names);
|
||||||
visitExps(stat.exps);
|
visitExps(stat.exps);
|
||||||
stat.block.accept(this);
|
stat.block.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.IfThenElse stat) {
|
public void visit(Stat.IfThenElse stat) {
|
||||||
stat.ifexp.accept(this);
|
stat.ifexp.accept(this);
|
||||||
stat.ifblock.accept(this);
|
stat.ifblock.accept(this);
|
||||||
@@ -64,14 +71,17 @@ abstract public class Visitor {
|
|||||||
if (stat.elseblock != null)
|
if (stat.elseblock != null)
|
||||||
visit(stat.elseblock);
|
visit(stat.elseblock);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.LocalAssign stat) {
|
public void visit(Stat.LocalAssign stat) {
|
||||||
visitNames(stat.names);
|
visitNames(stat.names);
|
||||||
visitExps(stat.values);
|
visitExps(stat.values);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.LocalFuncDef stat) {
|
public void visit(Stat.LocalFuncDef stat) {
|
||||||
visit(stat.name);
|
visit(stat.name);
|
||||||
stat.body.accept(this);
|
stat.body.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.NumericFor stat) {
|
public void visit(Stat.NumericFor stat) {
|
||||||
visit(stat.scope);
|
visit(stat.scope);
|
||||||
visit(stat.name);
|
visit(stat.name);
|
||||||
@@ -81,25 +91,31 @@ abstract public class Visitor {
|
|||||||
stat.step.accept(this);
|
stat.step.accept(this);
|
||||||
stat.block.accept(this);
|
stat.block.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.RepeatUntil stat) {
|
public void visit(Stat.RepeatUntil stat) {
|
||||||
stat.block.accept(this);
|
stat.block.accept(this);
|
||||||
stat.exp.accept(this);
|
stat.exp.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.Return stat) {
|
public void visit(Stat.Return stat) {
|
||||||
visitExps(stat.values);
|
visitExps(stat.values);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.WhileDo stat) {
|
public void visit(Stat.WhileDo stat) {
|
||||||
stat.exp.accept(this);
|
stat.exp.accept(this);
|
||||||
stat.block.accept(this);
|
stat.block.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(FuncBody body) {
|
public void visit(FuncBody body) {
|
||||||
visit(body.scope);
|
visit(body.scope);
|
||||||
body.parlist.accept(this);
|
body.parlist.accept(this);
|
||||||
body.block.accept(this);
|
body.block.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(FuncArgs args) {
|
public void visit(FuncArgs args) {
|
||||||
visitExps(args.exps);
|
visitExps(args.exps);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(TableField field) {
|
public void visit(TableField field) {
|
||||||
if (field.name != null)
|
if (field.name != null)
|
||||||
visit(field.name);
|
visit(field.name);
|
||||||
@@ -107,74 +123,95 @@ abstract public class Visitor {
|
|||||||
field.index.accept(this);
|
field.index.accept(this);
|
||||||
field.rhs.accept(this);
|
field.rhs.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.AnonFuncDef exp) {
|
public void visit(Exp.AnonFuncDef exp) {
|
||||||
exp.body.accept(this);
|
exp.body.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.BinopExp exp) {
|
public void visit(Exp.BinopExp exp) {
|
||||||
exp.lhs.accept(this);
|
exp.lhs.accept(this);
|
||||||
exp.rhs.accept(this);
|
exp.rhs.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.Constant exp) {
|
public void visit(Exp.Constant exp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.FieldExp exp) {
|
public void visit(Exp.FieldExp exp) {
|
||||||
exp.lhs.accept(this);
|
exp.lhs.accept(this);
|
||||||
visit(exp.name);
|
visit(exp.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.FuncCall exp) {
|
public void visit(Exp.FuncCall exp) {
|
||||||
exp.lhs.accept(this);
|
exp.lhs.accept(this);
|
||||||
exp.args.accept(this);
|
exp.args.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.IndexExp exp) {
|
public void visit(Exp.IndexExp exp) {
|
||||||
exp.lhs.accept(this);
|
exp.lhs.accept(this);
|
||||||
exp.exp.accept(this);
|
exp.exp.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.MethodCall exp) {
|
public void visit(Exp.MethodCall exp) {
|
||||||
exp.lhs.accept(this);
|
exp.lhs.accept(this);
|
||||||
visit(exp.name);
|
visit(exp.name);
|
||||||
exp.args.accept(this);
|
exp.args.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.NameExp exp) {
|
public void visit(Exp.NameExp exp) {
|
||||||
visit(exp.name);
|
visit(exp.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.ParensExp exp) {
|
public void visit(Exp.ParensExp exp) {
|
||||||
exp.exp.accept(this);
|
exp.exp.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.UnopExp exp) {
|
public void visit(Exp.UnopExp exp) {
|
||||||
exp.rhs.accept(this);
|
exp.rhs.accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Exp.VarargsExp exp) {
|
public void visit(Exp.VarargsExp exp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(ParList pars) {
|
public void visit(ParList pars) {
|
||||||
visitNames(pars.names);
|
visitNames(pars.names);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(TableConstructor table) {
|
public void visit(TableConstructor table) {
|
||||||
if (table.fields != null)
|
if (table.fields != null)
|
||||||
for (int i = 0, n = table.fields.size(); i < n; i++)
|
for (int i = 0, n = table.fields.size(); i < n; i++)
|
||||||
((TableField) table.fields.get(i)).accept(this);
|
((TableField) table.fields.get(i)).accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitVars(List<VarExp> vars) {
|
public void visitVars(List<VarExp> vars) {
|
||||||
if (vars != null)
|
if (vars != null)
|
||||||
for (int i = 0, n = vars.size(); i < n; i++)
|
for (int i = 0, n = vars.size(); i < n; i++)
|
||||||
((Exp.VarExp) vars.get(i)).accept(this);
|
((Exp.VarExp) vars.get(i)).accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitExps(List<Exp> exps) {
|
public void visitExps(List<Exp> exps) {
|
||||||
if (exps != null)
|
if (exps != null)
|
||||||
for (int i = 0, n = exps.size(); i < n; i++)
|
for (int i = 0, n = exps.size(); i < n; i++)
|
||||||
((Exp) exps.get(i)).accept(this);
|
((Exp) exps.get(i)).accept(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitNames(List<Name> names) {
|
public void visitNames(List<Name> names) {
|
||||||
if (names != null)
|
if (names != null)
|
||||||
for (int i = 0, n = names.size(); i < n; i++)
|
for (int i = 0, n = names.size(); i < n; i++)
|
||||||
visit((Name) names.get(i));
|
visit((Name) names.get(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Name name) {
|
public void visit(Name name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(String name) {
|
public void visit(String name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(NameScope scope) {
|
public void visit(NameScope scope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.Goto gotostat) {
|
public void visit(Stat.Goto gotostat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(Stat.Label label) {
|
public void visit(Stat.Label label) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ import org.luaj.vm2.LuaValue;
|
|||||||
* This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
|
* This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
|
||||||
* but can also be used directly when working with Java/lua bindings.
|
* but can also be used directly when working with Java/lua bindings.
|
||||||
* <p>
|
* <p>
|
||||||
* To coerce scalar types, the various, generally the {@code valueOf(type)} methods
|
* To coerce scalar types, the various, generally the {@code valueOf(type)}
|
||||||
* on {@link LuaValue} may be used:
|
* methods on {@link LuaValue} may be used:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link LuaValue#valueOf(boolean)}</li>
|
* <li>{@link LuaValue#valueOf(boolean)}</li>
|
||||||
* <li>{@link LuaValue#valueOf(byte[])}</li>
|
* <li>{@link LuaValue#valueOf(byte[])}</li>
|
||||||
@@ -47,17 +47,17 @@ import org.luaj.vm2.LuaValue;
|
|||||||
* <li>{@link LuaValue#valueOf(String)}</li>
|
* <li>{@link LuaValue#valueOf(String)}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* To coerce arrays of objects and lists, the {@code listOf(..)} and {@code tableOf(...)} methods
|
* To coerce arrays of objects and lists, the {@code listOf(..)} and
|
||||||
* on {@link LuaValue} may be used:
|
* {@code tableOf(...)} methods on {@link LuaValue} may be used:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link LuaValue#listOf(LuaValue[])}</li>
|
* <li>{@link LuaValue#listOf(LuaValue[])}</li>
|
||||||
* <li>{@link LuaValue#listOf(LuaValue[], org.luaj.vm2.Varargs)}</li>
|
* <li>{@link LuaValue#listOf(LuaValue[], org.luaj.vm2.Varargs)}</li>
|
||||||
* <li>{@link LuaValue#tableOf(LuaValue[])}</li>
|
* <li>{@link LuaValue#tableOf(LuaValue[])}</li>
|
||||||
* <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[], org.luaj.vm2.Varargs)}</li>
|
* <li>{@link LuaValue#tableOf(LuaValue[], LuaValue[], org.luaj.vm2.Varargs)}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* The method {@link CoerceJavaToLua#coerce(Object)} looks as the type and dimesioning
|
* The method {@link CoerceJavaToLua#coerce(Object)} looks as the type and
|
||||||
* of the argument and tries to guess the best fit for corrsponding lua scalar,
|
* dimesioning of the argument and tries to guess the best fit for corrsponding
|
||||||
* table, or table of tables.
|
* lua scalar, table, or table of tables.
|
||||||
*
|
*
|
||||||
* @see CoerceJavaToLua#coerce(Object)
|
* @see CoerceJavaToLua#coerce(Object)
|
||||||
* @see org.luaj.vm2.lib.jse.LuajavaLib
|
* @see org.luaj.vm2.lib.jse.LuajavaLib
|
||||||
@@ -133,7 +133,6 @@ public class CoerceJavaToLua {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
|
static final Map COERCIONS = Collections.synchronizedMap(new HashMap());
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -160,12 +159,13 @@ public class CoerceJavaToLua {
|
|||||||
/**
|
/**
|
||||||
* Coerse a Java object to a corresponding lua value.
|
* Coerse a Java object to a corresponding lua value.
|
||||||
* <p>
|
* <p>
|
||||||
* Integral types {@code boolean}, {@code byte}, {@code char}, and {@code int}
|
* Integral types {@code boolean}, {@code byte}, {@code char}, and
|
||||||
* will become {@link LuaInteger};
|
* {@code int} will become {@link LuaInteger}; {@code long}, {@code float},
|
||||||
* {@code long}, {@code float}, and {@code double} will become {@link LuaDouble};
|
* and {@code double} will become {@link LuaDouble}; {@code String} and
|
||||||
* {@code String} and {@code byte[]} will become {@link LuaString};
|
* {@code byte[]} will become {@link LuaString}; types inheriting from
|
||||||
* types inheriting from {@link LuaValue} will be returned without coercion;
|
* {@link LuaValue} will be returned without coercion; other types will
|
||||||
* other types will become {@link LuaUserdata}.
|
* become {@link LuaUserdata}.
|
||||||
|
*
|
||||||
* @param o Java object needing conversion
|
* @param o Java object needing conversion
|
||||||
* @return {@link LuaValue} corresponding to the supplied Java value.
|
* @return {@link LuaValue} corresponding to the supplied Java value.
|
||||||
* @see LuaValue
|
* @see LuaValue
|
||||||
@@ -180,9 +180,7 @@ public class CoerceJavaToLua {
|
|||||||
Class clazz = o.getClass();
|
Class clazz = o.getClass();
|
||||||
Coercion c = (Coercion) COERCIONS.get(clazz);
|
Coercion c = (Coercion) COERCIONS.get(clazz);
|
||||||
if (c == null) {
|
if (c == null) {
|
||||||
c = clazz.isArray()? arrayCoercion:
|
c = clazz.isArray()? arrayCoercion: o instanceof LuaValue? luaCoercion: instanceCoercion;
|
||||||
o instanceof LuaValue ? luaCoercion:
|
|
||||||
instanceCoercion;
|
|
||||||
COERCIONS.put(clazz, c);
|
COERCIONS.put(clazz, c);
|
||||||
}
|
}
|
||||||
return c.coerce(o);
|
return c.coerce(o);
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ import org.luaj.vm2.LuaValue;
|
|||||||
* This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
|
* This class is primarily used by the {@link org.luaj.vm2.lib.jse.LuajavaLib},
|
||||||
* but can also be used directly when working with Java/lua bindings.
|
* but can also be used directly when working with Java/lua bindings.
|
||||||
* <p>
|
* <p>
|
||||||
* To coerce to specific Java values, generally the {@code toType()} methods
|
* To coerce to specific Java values, generally the {@code toType()} methods on
|
||||||
* on {@link LuaValue} may be used:
|
* {@link LuaValue} may be used:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link LuaValue#toboolean()}</li>
|
* <li>{@link LuaValue#toboolean()}</li>
|
||||||
* <li>{@link LuaValue#tobyte()}</li>
|
* <li>{@link LuaValue#tobyte()}</li>
|
||||||
@@ -51,8 +51,8 @@ import org.luaj.vm2.LuaValue;
|
|||||||
* <li>{@link LuaValue#touserdata(Class)}</li>
|
* <li>{@link LuaValue#touserdata(Class)}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* For data in lua tables, the various methods on {@link LuaTable} can be used directly
|
* For data in lua tables, the various methods on {@link LuaTable} can be used
|
||||||
* to convert data to something more useful.
|
* directly to convert data to something more useful.
|
||||||
*
|
*
|
||||||
* @see org.luaj.vm2.lib.jse.LuajavaLib
|
* @see org.luaj.vm2.lib.jse.LuajavaLib
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
@@ -65,14 +65,17 @@ public class CoerceLuaToJava {
|
|||||||
|
|
||||||
static interface Coercion {
|
static interface Coercion {
|
||||||
public int score(LuaValue value);
|
public int score(LuaValue value);
|
||||||
|
|
||||||
public Object coerce(LuaValue value);
|
public Object coerce(LuaValue value);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Coerce a LuaValue value to a specified java class
|
* Coerce a LuaValue value to a specified java class
|
||||||
|
*
|
||||||
* @param value LuaValue to coerce
|
* @param value LuaValue to coerce
|
||||||
* @param clazz Class to coerce into
|
* @param clazz Class to coerce into
|
||||||
* @return Object of type clazz (or a subclass) with the corresponding value.
|
* @return Object of type clazz (or a subclass) with the corresponding
|
||||||
|
* value.
|
||||||
*/
|
*/
|
||||||
public static Object coerce(LuaValue value, Class clazz) {
|
public static Object coerce(LuaValue value, Class clazz) {
|
||||||
return getCoercion(clazz).coerce(value);
|
return getCoercion(clazz).coerce(value);
|
||||||
@@ -84,6 +87,7 @@ public class CoerceLuaToJava {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "BoolCoercion()";
|
return "BoolCoercion()";
|
||||||
}
|
}
|
||||||
|
|
||||||
public int score(LuaValue value) {
|
public int score(LuaValue value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case LuaValue.TBOOLEAN:
|
case LuaValue.TBOOLEAN:
|
||||||
@@ -107,12 +111,15 @@ public class CoerceLuaToJava {
|
|||||||
static final int TARGET_TYPE_DOUBLE = 6;
|
static final int TARGET_TYPE_DOUBLE = 6;
|
||||||
static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" };
|
static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" };
|
||||||
final int targetType;
|
final int targetType;
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "NumericCoercion(" + TYPE_NAMES[targetType] + ")";
|
return "NumericCoercion(" + TYPE_NAMES[targetType] + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
NumericCoercion(int targetType) {
|
NumericCoercion(int targetType) {
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int score(LuaValue value) {
|
public int score(LuaValue value) {
|
||||||
int fromStringPenalty = 0;
|
int fromStringPenalty = 0;
|
||||||
if (value.type() == LuaValue.TSTRING) {
|
if (value.type() == LuaValue.TSTRING) {
|
||||||
@@ -134,25 +141,31 @@ public class CoerceLuaToJava {
|
|||||||
}
|
}
|
||||||
case TARGET_TYPE_SHORT: {
|
case TARGET_TYPE_SHORT: {
|
||||||
int i = value.toint();
|
int i = value.toint();
|
||||||
return fromStringPenalty +
|
return fromStringPenalty+((i == (byte) i)? 1: (i == (short) i)? 0: SCORE_WRONG_TYPE);
|
||||||
((i==(byte)i)? 1: (i==(short)i)? 0: SCORE_WRONG_TYPE);
|
|
||||||
}
|
}
|
||||||
case TARGET_TYPE_INT: {
|
case TARGET_TYPE_INT: {
|
||||||
int i = value.toint();
|
int i = value.toint();
|
||||||
return fromStringPenalty +
|
return fromStringPenalty+((i == (byte) i)? 2: ((i == (char) i) || (i == (short) i))? 1: 0);
|
||||||
((i==(byte)i)? 2: ((i==(char)i) || (i==(short)i))? 1: 0);
|
|
||||||
}
|
}
|
||||||
case TARGET_TYPE_FLOAT: return fromStringPenalty + 1;
|
case TARGET_TYPE_FLOAT:
|
||||||
case TARGET_TYPE_LONG: return fromStringPenalty + 1;
|
return fromStringPenalty+1;
|
||||||
case TARGET_TYPE_DOUBLE: return fromStringPenalty + 2;
|
case TARGET_TYPE_LONG:
|
||||||
default: return SCORE_WRONG_TYPE;
|
return fromStringPenalty+1;
|
||||||
|
case TARGET_TYPE_DOUBLE:
|
||||||
|
return fromStringPenalty+2;
|
||||||
|
default:
|
||||||
|
return SCORE_WRONG_TYPE;
|
||||||
}
|
}
|
||||||
} else if (value.isnumber()) {
|
} else if (value.isnumber()) {
|
||||||
switch (targetType) {
|
switch (targetType) {
|
||||||
case TARGET_TYPE_BYTE: return SCORE_WRONG_TYPE;
|
case TARGET_TYPE_BYTE:
|
||||||
case TARGET_TYPE_CHAR: return SCORE_WRONG_TYPE;
|
return SCORE_WRONG_TYPE;
|
||||||
case TARGET_TYPE_SHORT: return SCORE_WRONG_TYPE;
|
case TARGET_TYPE_CHAR:
|
||||||
case TARGET_TYPE_INT: return SCORE_WRONG_TYPE;
|
return SCORE_WRONG_TYPE;
|
||||||
|
case TARGET_TYPE_SHORT:
|
||||||
|
return SCORE_WRONG_TYPE;
|
||||||
|
case TARGET_TYPE_INT:
|
||||||
|
return SCORE_WRONG_TYPE;
|
||||||
case TARGET_TYPE_LONG: {
|
case TARGET_TYPE_LONG: {
|
||||||
double d = value.todouble();
|
double d = value.todouble();
|
||||||
return fromStringPenalty+((d == (long) d)? 0: SCORE_WRONG_TYPE);
|
return fromStringPenalty+((d == (long) d)? 0: SCORE_WRONG_TYPE);
|
||||||
@@ -165,7 +178,8 @@ public class CoerceLuaToJava {
|
|||||||
double d = value.todouble();
|
double d = value.todouble();
|
||||||
return fromStringPenalty+(((d == (long) d) || (d == (float) d))? 1: 0);
|
return fromStringPenalty+(((d == (long) d) || (d == (float) d))? 1: 0);
|
||||||
}
|
}
|
||||||
default: return SCORE_WRONG_TYPE;
|
default:
|
||||||
|
return SCORE_WRONG_TYPE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return SCORE_UNCOERCIBLE;
|
return SCORE_UNCOERCIBLE;
|
||||||
@@ -174,14 +188,22 @@ public class CoerceLuaToJava {
|
|||||||
|
|
||||||
public Object coerce(LuaValue value) {
|
public Object coerce(LuaValue value) {
|
||||||
switch (targetType) {
|
switch (targetType) {
|
||||||
case TARGET_TYPE_BYTE: return new Byte( (byte) value.toint() );
|
case TARGET_TYPE_BYTE:
|
||||||
case TARGET_TYPE_CHAR: return new Character( (char) value.toint() );
|
return new Byte((byte) value.toint());
|
||||||
case TARGET_TYPE_SHORT: return new Short( (short) value.toint() );
|
case TARGET_TYPE_CHAR:
|
||||||
case TARGET_TYPE_INT: return new Integer( (int) value.toint() );
|
return new Character((char) value.toint());
|
||||||
case TARGET_TYPE_LONG: return new Long( (long) value.todouble() );
|
case TARGET_TYPE_SHORT:
|
||||||
case TARGET_TYPE_FLOAT: return new Float( (float) value.todouble() );
|
return new Short((short) value.toint());
|
||||||
case TARGET_TYPE_DOUBLE: return new Double( (double) value.todouble() );
|
case TARGET_TYPE_INT:
|
||||||
default: return null;
|
return new Integer((int) value.toint());
|
||||||
|
case TARGET_TYPE_LONG:
|
||||||
|
return new Long((long) value.todouble());
|
||||||
|
case TARGET_TYPE_FLOAT:
|
||||||
|
return new Float((float) value.todouble());
|
||||||
|
case TARGET_TYPE_DOUBLE:
|
||||||
|
return new Double((double) value.todouble());
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,24 +212,27 @@ public class CoerceLuaToJava {
|
|||||||
public static final int TARGET_TYPE_STRING = 0;
|
public static final int TARGET_TYPE_STRING = 0;
|
||||||
public static final int TARGET_TYPE_BYTES = 1;
|
public static final int TARGET_TYPE_BYTES = 1;
|
||||||
final int targetType;
|
final int targetType;
|
||||||
|
|
||||||
public StringCoercion(int targetType) {
|
public StringCoercion(int targetType) {
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "StringCoercion(" + (targetType == TARGET_TYPE_STRING? "String": "byte[]") + ")";
|
return "StringCoercion(" + (targetType == TARGET_TYPE_STRING? "String": "byte[]") + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public int score(LuaValue value) {
|
public int score(LuaValue value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case LuaValue.TSTRING:
|
case LuaValue.TSTRING:
|
||||||
return value.checkstring().isValidUtf8()?
|
return value.checkstring().isValidUtf8()? (targetType == TARGET_TYPE_STRING? 0: 1)
|
||||||
(targetType==TARGET_TYPE_STRING? 0: 1):
|
: (targetType == TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE);
|
||||||
(targetType==TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE);
|
|
||||||
case LuaValue.TNIL:
|
case LuaValue.TNIL:
|
||||||
return SCORE_NULL_VALUE;
|
return SCORE_NULL_VALUE;
|
||||||
default:
|
default:
|
||||||
return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE;
|
return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object coerce(LuaValue value) {
|
public Object coerce(LuaValue value) {
|
||||||
if (value.isnil())
|
if (value.isnil())
|
||||||
return null;
|
return null;
|
||||||
@@ -223,13 +248,16 @@ public class CoerceLuaToJava {
|
|||||||
static final class ArrayCoercion implements Coercion {
|
static final class ArrayCoercion implements Coercion {
|
||||||
final Class componentType;
|
final Class componentType;
|
||||||
final Coercion componentCoercion;
|
final Coercion componentCoercion;
|
||||||
|
|
||||||
public ArrayCoercion(Class componentType) {
|
public ArrayCoercion(Class componentType) {
|
||||||
this.componentType = componentType;
|
this.componentType = componentType;
|
||||||
this.componentCoercion = getCoercion(componentType);
|
this.componentCoercion = getCoercion(componentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ArrayCoercion(" + componentType.getName() + ")";
|
return "ArrayCoercion(" + componentType.getName() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public int score(LuaValue value) {
|
public int score(LuaValue value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case LuaValue.TTABLE:
|
case LuaValue.TTABLE:
|
||||||
@@ -242,6 +270,7 @@ public class CoerceLuaToJava {
|
|||||||
return SCORE_UNCOERCIBLE;
|
return SCORE_UNCOERCIBLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object coerce(LuaValue value) {
|
public Object coerce(LuaValue value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case LuaValue.TTABLE: {
|
case LuaValue.TTABLE: {
|
||||||
@@ -264,10 +293,11 @@ public class CoerceLuaToJava {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine levels of inheritance between a base class and a subclass
|
* Determine levels of inheritance between a base class and a subclass
|
||||||
|
*
|
||||||
* @param baseclass base class to look for
|
* @param baseclass base class to look for
|
||||||
* @param subclass class from which to start looking
|
* @param subclass class from which to start looking
|
||||||
* @return number of inheritance levels between subclass and baseclass,
|
* @return number of inheritance levels between subclass and baseclass, or
|
||||||
* or SCORE_UNCOERCIBLE if not a subclass
|
* SCORE_UNCOERCIBLE if not a subclass
|
||||||
*/
|
*/
|
||||||
static final int inheritanceLevels(Class baseclass, Class subclass) {
|
static final int inheritanceLevels(Class baseclass, Class subclass) {
|
||||||
if (subclass == null)
|
if (subclass == null)
|
||||||
@@ -283,12 +313,15 @@ public class CoerceLuaToJava {
|
|||||||
|
|
||||||
static final class ObjectCoercion implements Coercion {
|
static final class ObjectCoercion implements Coercion {
|
||||||
final Class targetType;
|
final Class targetType;
|
||||||
|
|
||||||
ObjectCoercion(Class targetType) {
|
ObjectCoercion(Class targetType) {
|
||||||
this.targetType = targetType;
|
this.targetType = targetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ObjectCoercion(" + targetType.getName() + ")";
|
return "ObjectCoercion(" + targetType.getName() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public int score(LuaValue value) {
|
public int score(LuaValue value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case LuaValue.TNUMBER:
|
case LuaValue.TNUMBER:
|
||||||
@@ -305,6 +338,7 @@ public class CoerceLuaToJava {
|
|||||||
return inheritanceLevels(targetType, value.getClass());
|
return inheritanceLevels(targetType, value.getClass());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object coerce(LuaValue value) {
|
public Object coerce(LuaValue value) {
|
||||||
switch (value.type()) {
|
switch (value.type()) {
|
||||||
case LuaValue.TNUMBER:
|
case LuaValue.TNUMBER:
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ import org.luaj.vm2.lib.OneArgFunction;
|
|||||||
* <p>
|
* <p>
|
||||||
* Can get elements by their integer key index, as well as the length.
|
* Can get elements by their integer key index, as well as the length.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is returned by calls to
|
||||||
* It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
|
* {@link CoerceJavaToLua#coerce(Object)} when an array is supplied.
|
||||||
* when an array is supplied.
|
*
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
* @see CoerceLuaToJava
|
* @see CoerceLuaToJava
|
||||||
*/
|
*/
|
||||||
@@ -65,9 +65,9 @@ class JavaArray extends LuaUserdata {
|
|||||||
return valueOf(Array.getLength(m_instance));
|
return valueOf(Array.getLength(m_instance));
|
||||||
if (key.isint()) {
|
if (key.isint()) {
|
||||||
int i = key.toint()-1;
|
int i = key.toint()-1;
|
||||||
return i>=0 && i<Array.getLength(m_instance)?
|
return i >= 0 && i < Array.getLength(m_instance)
|
||||||
CoerceJavaToLua.coerce(Array.get(m_instance,key.toint()-1)):
|
? CoerceJavaToLua.coerce(Array.get(m_instance, key.toint()-1))
|
||||||
NIL;
|
: NIL;
|
||||||
}
|
}
|
||||||
return super.get(key);
|
return super.get(key);
|
||||||
}
|
}
|
||||||
@@ -79,8 +79,7 @@ class JavaArray extends LuaUserdata {
|
|||||||
Array.set(m_instance, i, CoerceLuaToJava.coerce(value, m_instance.getClass().getComponentType()));
|
Array.set(m_instance, i, CoerceLuaToJava.coerce(value, m_instance.getClass().getComponentType()));
|
||||||
else if (m_metatable == null || !settable(this, key, value))
|
else if (m_metatable == null || !settable(this, key, value))
|
||||||
error("array index out of bounds");
|
error("array index out of bounds");
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
super.set(key, value);
|
super.set(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ import org.luaj.vm2.LuaValue;
|
|||||||
* <p>
|
* <p>
|
||||||
* Will respond to get() and set() by returning field values, or java methods.
|
* Will respond to get() and set() by returning field values, or java methods.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is returned by calls to
|
||||||
* It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
|
* {@link CoerceJavaToLua#coerce(Object)} when a Class is supplied.
|
||||||
* when a Class is supplied.
|
*
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
* @see CoerceLuaToJava
|
* @see CoerceLuaToJava
|
||||||
*/
|
*/
|
||||||
@@ -113,19 +113,23 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
|||||||
if (Modifier.isPublic(c[i].getModifiers()))
|
if (Modifier.isPublic(c[i].getModifiers()))
|
||||||
list.add(JavaConstructor.forConstructor(c[i]));
|
list.add(JavaConstructor.forConstructor(c[i]));
|
||||||
switch (list.size()) {
|
switch (list.size()) {
|
||||||
case 0: break;
|
case 0:
|
||||||
case 1: map.put(NEW, list.get(0)); break;
|
break;
|
||||||
default: map.put(NEW, JavaConstructor.forConstructors( (JavaConstructor[])list.toArray(new JavaConstructor[list.size()]) ) ); break;
|
case 1:
|
||||||
|
map.put(NEW, list.get(0));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
map.put(NEW, JavaConstructor
|
||||||
|
.forConstructors((JavaConstructor[]) list.toArray(new JavaConstructor[list.size()])));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Iterator it = namedlists.entrySet().iterator(); it.hasNext();) {
|
for (Iterator it = namedlists.entrySet().iterator(); it.hasNext();) {
|
||||||
Entry e = (Entry) it.next();
|
Entry e = (Entry) it.next();
|
||||||
String name = (String) e.getKey();
|
String name = (String) e.getKey();
|
||||||
List methods = (List) e.getValue();
|
List methods = (List) e.getValue();
|
||||||
map.put( LuaValue.valueOf(name),
|
map.put(LuaValue.valueOf(name), methods.size() == 1? methods.get(0)
|
||||||
methods.size()==1?
|
: JavaMethod.forMethods((JavaMethod[]) methods.toArray(new JavaMethod[methods.size()])));
|
||||||
methods.get(0):
|
|
||||||
JavaMethod.forMethods( (JavaMethod[])methods.toArray(new JavaMethod[methods.size()])) );
|
|
||||||
}
|
}
|
||||||
methods = map;
|
methods = map;
|
||||||
}
|
}
|
||||||
@@ -147,7 +151,5 @@ class JavaClass extends JavaInstance implements CoerceJavaToLua.Coercion {
|
|||||||
return (Class) innerclasses.get(key);
|
return (Class) innerclasses.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LuaValue getConstructor() {
|
public LuaValue getConstructor() { return getMethod(NEW); }
|
||||||
return getMethod(NEW);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ import org.luaj.vm2.lib.VarArgFunction;
|
|||||||
/**
|
/**
|
||||||
* LuaValue that represents a particular public Java constructor.
|
* LuaValue that represents a particular public Java constructor.
|
||||||
* <p>
|
* <p>
|
||||||
* May be called with arguments to return a JavaInstance
|
* May be called with arguments to return a JavaInstance created by calling the
|
||||||
* created by calling the constructor.
|
* constructor.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is returned by calls to
|
||||||
* It is returned by calls to {@link JavaClass#new(LuaValue key)}
|
* {@link JavaClass#new(LuaValue key)} when the value of key is "new".
|
||||||
* when the value of key is "new".
|
*
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
* @see CoerceLuaToJava
|
* @see CoerceLuaToJava
|
||||||
*/
|
*/
|
||||||
@@ -82,12 +82,13 @@ class JavaConstructor extends JavaMember {
|
|||||||
* <p>
|
* <p>
|
||||||
* On invocation, will pick the best method from the list, and invoke it.
|
* On invocation, will pick the best method from the list, and invoke it.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is returned by calls to calls to
|
||||||
* It is returned by calls to calls to {@link JavaClass#get(LuaValue key)}
|
* {@link JavaClass#get(LuaValue key)} when key is "new" and there is more
|
||||||
* when key is "new" and there is more than one public constructor.
|
* than one public constructor.
|
||||||
*/
|
*/
|
||||||
static class Overload extends VarArgFunction {
|
static class Overload extends VarArgFunction {
|
||||||
final JavaConstructor[] constructors;
|
final JavaConstructor[] constructors;
|
||||||
|
|
||||||
public Overload(JavaConstructor[] c) {
|
public Overload(JavaConstructor[] c) {
|
||||||
this.constructors = c;
|
this.constructors = c;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ import org.luaj.vm2.LuaValue;
|
|||||||
* <p>
|
* <p>
|
||||||
* Will respond to get() and set() by returning field values or methods.
|
* Will respond to get() and set() by returning field values or methods.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is returned by calls to
|
||||||
* It is returned by calls to {@link CoerceJavaToLua#coerce(Object)}
|
* {@link CoerceJavaToLua#coerce(Object)} when a subclass of Object is supplied.
|
||||||
* when a subclass of Object is supplied.
|
*
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
* @see CoerceLuaToJava
|
* @see CoerceLuaToJava
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,18 +28,18 @@ import org.luaj.vm2.lib.jse.CoerceLuaToJava.Coercion;
|
|||||||
/**
|
/**
|
||||||
* Java method or constructor.
|
* Java method or constructor.
|
||||||
* <p>
|
* <p>
|
||||||
* Primarily handles argument coercion for parameter lists including scoring of compatibility and
|
* Primarily handles argument coercion for parameter lists including scoring of
|
||||||
* java varargs handling.
|
* compatibility and java varargs handling.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is an abstract base class for
|
||||||
* It is an abstract base class for {@link JavaConstructor} and {@link JavaMethod}.
|
* {@link JavaConstructor} and {@link JavaMethod}.
|
||||||
|
*
|
||||||
* @see JavaConstructor
|
* @see JavaConstructor
|
||||||
* @see JavaMethod
|
* @see JavaMethod
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
* @see CoerceLuaToJava
|
* @see CoerceLuaToJava
|
||||||
*/
|
*/
|
||||||
abstract
|
abstract class JavaMember extends VarArgFunction {
|
||||||
class JavaMember extends VarArgFunction {
|
|
||||||
|
|
||||||
static final int METHOD_MODIFIERS_VARARGS = 0x80;
|
static final int METHOD_MODIFIERS_VARARGS = 0x80;
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ import org.luaj.vm2.Varargs;
|
|||||||
* <p>
|
* <p>
|
||||||
* Can be invoked via call(LuaValue...) and related methods.
|
* Can be invoked via call(LuaValue...) and related methods.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is returned by calls to calls to
|
||||||
* It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)}
|
* {@link JavaInstance#get(LuaValue key)} when a method is named.
|
||||||
* when a method is named.
|
*
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
* @see CoerceLuaToJava
|
* @see CoerceLuaToJava
|
||||||
*/
|
*/
|
||||||
@@ -106,9 +106,9 @@ class JavaMethod extends JavaMember {
|
|||||||
* <p>
|
* <p>
|
||||||
* On invocation, will pick the best method from the list, and invoke it.
|
* On invocation, will pick the best method from the list, and invoke it.
|
||||||
* <p>
|
* <p>
|
||||||
* This class is not used directly.
|
* This class is not used directly. It is returned by calls to calls to
|
||||||
* It is returned by calls to calls to {@link JavaInstance#get(LuaValue key)}
|
* {@link JavaInstance#get(LuaValue key)} when an overloaded method is
|
||||||
* when an overloaded method is named.
|
* named.
|
||||||
*/
|
*/
|
||||||
static class Overload extends LuaFunction {
|
static class Overload extends LuaFunction {
|
||||||
|
|
||||||
|
|||||||
@@ -34,33 +34,46 @@ import org.luaj.vm2.lib.LibFunction;
|
|||||||
import org.luaj.vm2.lib.ResourceFinder;
|
import org.luaj.vm2.lib.ResourceFinder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link BaseLib} and {@link LibFunction} which implements the lua basic library functions
|
* Subclass of {@link BaseLib} and {@link LibFunction} which implements the lua
|
||||||
* and provides a directory based {@link ResourceFinder} as the {@link Globals#finder}.
|
* basic library functions and provides a directory based {@link ResourceFinder}
|
||||||
|
* as the {@link Globals#finder}.
|
||||||
* <p>
|
* <p>
|
||||||
* Since JME has no file system by default, {@link BaseLib} implements
|
* Since JME has no file system by default, {@link BaseLib} implements
|
||||||
* {@link ResourceFinder} using {@link Class#getResource(String)}.
|
* {@link ResourceFinder} using {@link Class#getResource(String)}. The
|
||||||
* The {@link org.luaj.vm2.lib.jse.JseBaseLib} implements {@link Globals#finder} by scanning the current directory
|
* {@link org.luaj.vm2.lib.jse.JseBaseLib} implements {@link Globals#finder} by
|
||||||
* first, then falling back to {@link Class#getResource(String)} if that fails.
|
* scanning the current directory first, then falling back to
|
||||||
* Otherwise, the behavior is the same as that of {@link BaseLib}.
|
* {@link Class#getResource(String)} if that fails. Otherwise, the behavior is
|
||||||
|
* the same as that of {@link BaseLib}.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired, a minimal
|
||||||
* a minimal set of libraries could be loaded
|
* set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* }
|
||||||
* <p>However, other libraries such as <em>PackageLib</em> are not loaded in this case.
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* However, other libraries such as <em>PackageLib</em> are not loaded in this
|
||||||
|
* case.
|
||||||
* <p>
|
* <p>
|
||||||
* This is a direct port of the corresponding library in C.
|
* This is a direct port of the corresponding library in C.
|
||||||
|
*
|
||||||
* @see Globals
|
* @see Globals
|
||||||
* @see BaseLib
|
* @see BaseLib
|
||||||
* @see ResourceFinder
|
* @see ResourceFinder
|
||||||
@@ -68,18 +81,24 @@ import org.luaj.vm2.lib.ResourceFinder;
|
|||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.1">Lua 5.2 Base Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.1">Lua 5.2 Base Lib
|
||||||
|
* Reference</a>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
||||||
|
|
||||||
|
/**
|
||||||
/** Perform one-time initialization on the library by creating a table
|
* Perform one-time initialization on the library by creating a table
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* containing the library functions, adding that table to the supplied
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
* <P>Specifically, extend the library loading to set the default value for {@link Globals#STDIN}
|
* the return value.
|
||||||
|
* <P>
|
||||||
|
* Specifically, extend the library loading to set the default value for
|
||||||
|
* {@link Globals#STDIN}
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, which must be a Globals instance.
|
* @param env the environment to load into, which must be a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
super.call(modname, env);
|
super.call(modname, env);
|
||||||
@@ -87,10 +106,9 @@ public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to open a file in the current working directory,
|
* Try to open a file in the current working directory, or fall back to base
|
||||||
* or fall back to base opener if not found.
|
* opener if not found.
|
||||||
*
|
*
|
||||||
* This implementation attempts to open the file using new File(filename).
|
* This implementation attempts to open the file using new File(filename).
|
||||||
* It falls back to the base implementation that looks it up as a resource
|
* It falls back to the base implementation that looks it up as a resource
|
||||||
@@ -113,4 +131,3 @@ public class JseBaseLib extends org.luaj.vm2.lib.BaseLib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,37 +37,50 @@ import org.luaj.vm2.lib.IoLib;
|
|||||||
import org.luaj.vm2.lib.LibFunction;
|
import org.luaj.vm2.lib.LibFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link IoLib} and therefore {@link LibFunction} which implements the lua standard {@code io}
|
* Subclass of {@link IoLib} and therefore {@link LibFunction} which implements
|
||||||
* library for the JSE platform.
|
* the lua standard {@code io} library for the JSE platform.
|
||||||
* <p>
|
* <p>
|
||||||
* It uses RandomAccessFile to implement seek on files.
|
* It uses RandomAccessFile to implement seek on files.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired, a minimal
|
||||||
* a minimal set of libraries could be loaded
|
* set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new JseIoLib());
|
* globals.load(new JseIoLib());
|
||||||
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
* globals.get("io").get("write").call(LuaValue.valueOf("hello, world\n"));
|
||||||
* } </pre>
|
* }
|
||||||
* <p>However, other libraries such as <em>MathLib</em> are not loaded in this case.
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* However, other libraries such as <em>MathLib</em> are not loaded in this
|
||||||
|
* case.
|
||||||
|
* <p>
|
||||||
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see IoLib
|
* @see IoLib
|
||||||
* @see org.luaj.vm2.lib.jme.JmeIoLib
|
* @see org.luaj.vm2.lib.jme.JmeIoLib
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.8">Lua 5.2 I/O Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.8">Lua 5.2 I/O Lib
|
||||||
|
* Reference</a>
|
||||||
*/
|
*/
|
||||||
public class JseIoLib extends IoLib {
|
public class JseIoLib extends IoLib {
|
||||||
|
|
||||||
@@ -83,7 +96,8 @@ public class JseIoLib extends IoLib {
|
|||||||
return new StdoutFile(FTYPE_STDERR);
|
return new StdoutFile(FTYPE_STDERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
protected File openFile(String filename, boolean readMode, boolean appendMode, boolean updateMode,
|
||||||
|
boolean binaryMode) throws IOException {
|
||||||
RandomAccessFile f = new RandomAccessFile(filename, readMode? "r": "rw");
|
RandomAccessFile f = new RandomAccessFile(filename, readMode? "r": "rw");
|
||||||
if (appendMode) {
|
if (appendMode) {
|
||||||
f.seek(f.length());
|
f.seek(f.length());
|
||||||
@@ -96,9 +110,7 @@ public class JseIoLib extends IoLib {
|
|||||||
|
|
||||||
protected File openProgram(String prog, String mode) throws IOException {
|
protected File openProgram(String prog, String mode) throws IOException {
|
||||||
final Process p = Runtime.getRuntime().exec(prog);
|
final Process p = Runtime.getRuntime().exec(prog);
|
||||||
return "w".equals(mode)?
|
return "w".equals(mode)? new FileImpl(p.getOutputStream()): new FileImpl(p.getInputStream());
|
||||||
new FileImpl( p.getOutputStream() ):
|
|
||||||
new FileImpl( p.getInputStream() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected File tmpFile() throws IOException {
|
protected File tmpFile() throws IOException {
|
||||||
@@ -111,43 +123,51 @@ public class JseIoLib extends IoLib {
|
|||||||
throw new LuaError("not implemented");
|
throw new LuaError("not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private final class FileImpl extends File {
|
private final class FileImpl extends File {
|
||||||
private final RandomAccessFile file;
|
private final RandomAccessFile file;
|
||||||
private final InputStream is;
|
private final InputStream is;
|
||||||
private final OutputStream os;
|
private final OutputStream os;
|
||||||
private boolean closed = false;
|
private boolean closed = false;
|
||||||
private boolean nobuffer = false;
|
private boolean nobuffer = false;
|
||||||
|
|
||||||
private FileImpl(RandomAccessFile file, InputStream is, OutputStream os) {
|
private FileImpl(RandomAccessFile file, InputStream is, OutputStream os) {
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.is = is != null? is.markSupported()? is: new BufferedInputStream(is): null;
|
this.is = is != null? is.markSupported()? is: new BufferedInputStream(is): null;
|
||||||
this.os = os;
|
this.os = os;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileImpl(RandomAccessFile f) {
|
private FileImpl(RandomAccessFile f) {
|
||||||
this(f, null, null);
|
this(f, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileImpl(InputStream i) {
|
private FileImpl(InputStream i) {
|
||||||
this(null, i, null);
|
this(null, i, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileImpl(OutputStream o) {
|
private FileImpl(OutputStream o) {
|
||||||
this(null, null, o);
|
this(null, null, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String tojstring() {
|
public String tojstring() {
|
||||||
return "file (" + (this.closed? "closed": String.valueOf(this.hashCode())) + ")";
|
return "file (" + (this.closed? "closed": String.valueOf(this.hashCode())) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isstdfile() {
|
public boolean isstdfile() {
|
||||||
return file == null;
|
return file == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
closed = true;
|
closed = true;
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
if (os != null)
|
if (os != null)
|
||||||
os.flush();
|
os.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(LuaString s) throws IOException {
|
public void write(LuaString s) throws IOException {
|
||||||
if (os != null)
|
if (os != null)
|
||||||
os.write(s.m_bytes, s.m_offset, s.m_length);
|
os.write(s.m_bytes, s.m_offset, s.m_length);
|
||||||
@@ -158,9 +178,11 @@ public class JseIoLib extends IoLib {
|
|||||||
if (nobuffer)
|
if (nobuffer)
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isclosed() {
|
public boolean isclosed() {
|
||||||
return closed;
|
return closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int seek(String option, int pos) throws IOException {
|
public int seek(String option, int pos) throws IOException {
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
if ("set".equals(option)) {
|
if ("set".equals(option)) {
|
||||||
@@ -175,6 +197,7 @@ public class JseIoLib extends IoLib {
|
|||||||
notimplemented();
|
notimplemented();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setvbuf(String mode, int size) {
|
public void setvbuf(String mode, int size) {
|
||||||
nobuffer = "no".equals(mode);
|
nobuffer = "no".equals(mode);
|
||||||
}
|
}
|
||||||
@@ -236,11 +259,7 @@ public class JseIoLib extends IoLib {
|
|||||||
return "file (" + this.hashCode() + ")";
|
return "file (" + this.hashCode() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PrintStream getPrintStream() {
|
private final PrintStream getPrintStream() { return file_type == FTYPE_STDERR? globals.STDERR: globals.STDOUT; }
|
||||||
return file_type == FTYPE_STDERR?
|
|
||||||
globals.STDERR:
|
|
||||||
globals.STDOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(LuaString string) throws IOException {
|
public void write(LuaString string) throws IOException {
|
||||||
getPrintStream().write(string.m_bytes, string.m_offset, string.m_length);
|
getPrintStream().write(string.m_bytes, string.m_offset, string.m_length);
|
||||||
@@ -281,8 +300,7 @@ public class JseIoLib extends IoLib {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(byte[] bytes, int offset, int length)
|
public int read(byte[] bytes, int offset, int length) throws IOException {
|
||||||
throws IOException {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,8 +353,7 @@ public class JseIoLib extends IoLib {
|
|||||||
return globals.STDIN.read();
|
return globals.STDIN.read();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(byte[] bytes, int offset, int length)
|
public int read(byte[] bytes, int offset, int length) throws IOException {
|
||||||
throws IOException {
|
|
||||||
return globals.STDIN.read(bytes, offset, length);
|
return globals.STDIN.read(bytes, offset, length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,50 +27,68 @@ import org.luaj.vm2.lib.LibFunction;
|
|||||||
import org.luaj.vm2.lib.TwoArgFunction;
|
import org.luaj.vm2.lib.TwoArgFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the lua standard {@code math}
|
* Subclass of {@link LibFunction} which implements the lua standard
|
||||||
* library.
|
* {@code math} library.
|
||||||
* <p>
|
* <p>
|
||||||
* It contains all lua math functions, including those not available on the JME platform.
|
* It contains all lua math functions, including those not available on the JME
|
||||||
* See {@link org.luaj.vm2.lib.MathLib} for the exception list.
|
* platform. See {@link org.luaj.vm2.lib.MathLib} for the exception list.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired, a minimal
|
||||||
* a minimal set of libraries could be loaded
|
* set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new JseMathLib());
|
* globals.load(new JseMathLib());
|
||||||
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
* System.out.println(globals.get("math").get("sqrt").call(LuaValue.valueOf(2)));
|
||||||
* } </pre>
|
* }
|
||||||
* <p>However, other libraries such as <em>CoroutineLib</em> are not loaded in this case.
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* However, other libraries such as <em>CoroutineLib</em> are not loaded in this
|
||||||
|
* case.
|
||||||
|
* <p>
|
||||||
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see org.luaj.vm2.lib.jse.JseMathLib
|
* @see org.luaj.vm2.lib.jse.JseMathLib
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.6">Lua 5.2 Math Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.6">Lua 5.2 Math Lib
|
||||||
|
* Reference</a>
|
||||||
*/
|
*/
|
||||||
public class JseMathLib extends org.luaj.vm2.lib.MathLib {
|
public class JseMathLib extends org.luaj.vm2.lib.MathLib {
|
||||||
|
|
||||||
public JseMathLib() {}
|
public JseMathLib() {}
|
||||||
|
|
||||||
|
/**
|
||||||
/** Perform one-time initialization on the library by creating a table
|
* Perform one-time initialization on the library by creating a table
|
||||||
* containing the library functions, adding that table to the supplied environment,
|
* containing the library functions, adding that table to the supplied
|
||||||
* adding the table to package.loaded, and returning table as the return value.
|
* environment, adding the table to package.loaded, and returning table as
|
||||||
* <P>Specifically, adds all library functions that can be implemented directly
|
* the return value.
|
||||||
* in JSE but not JME: acos, asin, atan, atan2, cosh, exp, log, pow, sinh, and tanh.
|
* <P>
|
||||||
|
* Specifically, adds all library functions that can be implemented directly
|
||||||
|
* in JSE but not JME: acos, asin, atan, atan2, cosh, exp, log, pow, sinh,
|
||||||
|
* and tanh.
|
||||||
|
*
|
||||||
* @param modname the module name supplied if this is loaded via 'require'.
|
* @param modname the module name supplied if this is loaded via 'require'.
|
||||||
* @param env the environment to load into, which must be a Globals instance.
|
* @param env the environment to load into, which must be a Globals
|
||||||
|
* instance.
|
||||||
*/
|
*/
|
||||||
public LuaValue call(LuaValue modname, LuaValue env) {
|
public LuaValue call(LuaValue modname, LuaValue env) {
|
||||||
super.call(modname, env);
|
super.call(modname, env);
|
||||||
@@ -89,32 +107,53 @@ public class JseMathLib extends org.luaj.vm2.lib.MathLib {
|
|||||||
return math;
|
return math;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class acos extends UnaryOp { protected double call(double d) { return Math.acos(d); } }
|
static final class acos extends UnaryOp {
|
||||||
static final class asin extends UnaryOp { protected double call(double d) { return Math.asin(d); } }
|
protected double call(double d) { return Math.acos(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class asin extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.asin(d); }
|
||||||
|
}
|
||||||
|
|
||||||
static final class atan2 extends TwoArgFunction {
|
static final class atan2 extends TwoArgFunction {
|
||||||
public LuaValue call(LuaValue x, LuaValue y) {
|
public LuaValue call(LuaValue x, LuaValue y) {
|
||||||
return valueOf(Math.atan2(x.checkdouble(), y.optdouble(1)));
|
return valueOf(Math.atan2(x.checkdouble(), y.optdouble(1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static final class cosh extends UnaryOp { protected double call(double d) { return Math.cosh(d); } }
|
|
||||||
static final class exp extends UnaryOp { protected double call(double d) { return Math.exp(d); } }
|
static final class cosh extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.cosh(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class exp extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.exp(d); }
|
||||||
|
}
|
||||||
|
|
||||||
static final class log extends TwoArgFunction {
|
static final class log extends TwoArgFunction {
|
||||||
public LuaValue call(LuaValue x, LuaValue base) {
|
public LuaValue call(LuaValue x, LuaValue base) {
|
||||||
double nat = Math.log(x.checkdouble());
|
double nat = Math.log(x.checkdouble());
|
||||||
double b = base.optdouble(Math.E);
|
double b = base.optdouble(Math.E);
|
||||||
if (b != Math.E) nat /= Math.log(b);
|
if (b != Math.E)
|
||||||
|
nat /= Math.log(b);
|
||||||
return valueOf(nat);
|
return valueOf(nat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static final class pow extends BinaryOp { protected double call(double x, double y) { return Math.pow(x, y); } }
|
|
||||||
static final class sinh extends UnaryOp { protected double call(double d) { return Math.sinh(d); } }
|
static final class pow extends BinaryOp {
|
||||||
static final class tanh extends UnaryOp { protected double call(double d) { return Math.tanh(d); } }
|
protected double call(double x, double y) { return Math.pow(x, y); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class sinh extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.sinh(d); }
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class tanh extends UnaryOp {
|
||||||
|
protected double call(double d) { return Math.tanh(d); }
|
||||||
|
}
|
||||||
|
|
||||||
/** Faster, better version of pow() used by arithmetic operator ^ */
|
/** Faster, better version of pow() used by arithmetic operator ^ */
|
||||||
public double dpow_lib(double a, double b) {
|
public double dpow_lib(double a, double b) {
|
||||||
return Math.pow(a, b);
|
return Math.pow(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ import org.luaj.vm2.lib.LibFunction;
|
|||||||
import org.luaj.vm2.lib.OsLib;
|
import org.luaj.vm2.lib.OsLib;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the standard lua {@code os} library.
|
* Subclass of {@link LibFunction} which implements the standard lua {@code os}
|
||||||
|
* library.
|
||||||
* <p>
|
* <p>
|
||||||
* This contains more complete implementations of the following functions
|
* This contains more complete implementations of the following functions using
|
||||||
* using features that are specific to JSE:
|
* features that are specific to JSE:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@code execute()}</li>
|
* <li>{@code execute()}</li>
|
||||||
* <li>{@code remove()}</li>
|
* <li>{@code remove()}</li>
|
||||||
@@ -42,34 +43,46 @@ import org.luaj.vm2.lib.OsLib;
|
|||||||
* <li>{@code tmpname()}</li>
|
* <li>{@code tmpname()}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* Because the nature of the {@code os} library is to encapsulate
|
* Because the nature of the {@code os} library is to encapsulate os-specific
|
||||||
* os-specific features, the behavior of these functions varies considerably
|
* features, the behavior of these functions varies considerably from their
|
||||||
* from their counterparts in the C platform.
|
* counterparts in the C platform.
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println(globals.get("os").get("time").call());
|
* System.out.println(globals.get("os").get("time").call());
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* For special cases where the smallest possible footprint is desired,
|
* For special cases where the smallest possible footprint is desired, a minimal
|
||||||
* a minimal set of libraries could be loaded
|
* set of libraries could be loaded directly via {@link Globals#load(LuaValue)}
|
||||||
* directly via {@link Globals#load(LuaValue)} using code such as:
|
* using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new JseOsLib());
|
* globals.load(new JseOsLib());
|
||||||
* System.out.println(globals.get("os").get("time").call());
|
* System.out.println(globals.get("os").get("time").call());
|
||||||
* } </pre>
|
* }
|
||||||
* <p>However, other libraries such as <em>MathLib</em> are not loaded in this case.
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
|
* However, other libraries such as <em>MathLib</em> are not loaded in this
|
||||||
|
* case.
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see OsLib
|
* @see OsLib
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.9">Lua 5.2 OS Lib Reference</a>
|
* @see <a href="http://www.lua.org/manual/5.2/manual.html#6.9">Lua 5.2 OS Lib
|
||||||
|
* Reference</a>
|
||||||
*/
|
*/
|
||||||
public class JseOsLib extends org.luaj.vm2.lib.OsLib {
|
public class JseOsLib extends org.luaj.vm2.lib.OsLib {
|
||||||
|
|
||||||
|
|||||||
@@ -34,31 +34,45 @@ import org.luaj.vm2.lib.ResourceFinder;
|
|||||||
import org.luaj.vm2.lib.StringLib;
|
import org.luaj.vm2.lib.StringLib;
|
||||||
import org.luaj.vm2.lib.TableLib;
|
import org.luaj.vm2.lib.TableLib;
|
||||||
|
|
||||||
/** The {@link org.luaj.vm2.lib.jse.JsePlatform} class is a convenience class to standardize
|
/**
|
||||||
* how globals tables are initialized for the JSE platform.
|
* The {@link org.luaj.vm2.lib.jse.JsePlatform} class is a convenience class to
|
||||||
|
* standardize how globals tables are initialized for the JSE platform.
|
||||||
* <p>
|
* <p>
|
||||||
* It is used to allocate either a set of standard globals using
|
* It is used to allocate either a set of standard globals using
|
||||||
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
|
* {@link #standardGlobals()} or debug globals using {@link #debugGlobals()}
|
||||||
* <p>
|
* <p>
|
||||||
* A simple example of initializing globals and using them from Java is:
|
* A simple example of initializing globals and using them from Java is:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
* globals.get("print").call(LuaValue.valueOf("hello, world"));
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* Once globals are created, a simple way to load and run a script is:
|
* Once globals are created, a simple way to load and run a script is:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* globals.load( new FileInputStream("main.lua"), "main.lua" ).call();
|
* globals.load( new FileInputStream("main.lua"), "main.lua" ).call();
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* although {@code require} could also be used:
|
* although {@code require} could also be used:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {@code
|
||||||
* globals.get("require").call(LuaValue.valueOf("main"));
|
* globals.get("require").call(LuaValue.valueOf("main"));
|
||||||
* } </pre>
|
* }
|
||||||
* For this to succeed, the file "main.lua" must be in the current directory or a resource.
|
* </pre>
|
||||||
* See {@link org.luaj.vm2.lib.jse.JseBaseLib} for details on finding scripts using {@link ResourceFinder}.
|
*
|
||||||
|
* For this to succeed, the file "main.lua" must be in the current directory or
|
||||||
|
* a resource. See {@link org.luaj.vm2.lib.jse.JseBaseLib} for details on
|
||||||
|
* finding scripts using {@link ResourceFinder}.
|
||||||
* <p>
|
* <p>
|
||||||
* The standard globals will contain all standard libraries plus {@code luajava}:
|
* The standard globals will contain all standard libraries plus
|
||||||
|
* {@code luajava}:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link Globals}</li>
|
* <li>{@link Globals}</li>
|
||||||
* <li>{@link org.luaj.vm2.lib.jse.JseBaseLib}</li>
|
* <li>{@link org.luaj.vm2.lib.jse.JseBaseLib}</li>
|
||||||
@@ -72,9 +86,11 @@ import org.luaj.vm2.lib.TableLib;
|
|||||||
* <li>{@link org.luaj.vm2.lib.jse.JseOsLib}</li>
|
* <li>{@link org.luaj.vm2.lib.jse.JseOsLib}</li>
|
||||||
* <li>{@link org.luaj.vm2.lib.jse.LuajavaLib}</li>
|
* <li>{@link org.luaj.vm2.lib.jse.LuajavaLib}</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* In addition, the {@link LuaC} compiler is installed so lua files may be loaded in their source form.
|
* In addition, the {@link LuaC} compiler is installed so lua files may be
|
||||||
|
* loaded in their source form.
|
||||||
* <p>
|
* <p>
|
||||||
* The debug globals are simply the standard globals plus the {@code debug} library {@link DebugLib}.
|
* The debug globals are simply the standard globals plus the {@code debug}
|
||||||
|
* library {@link DebugLib}.
|
||||||
* <p>
|
* <p>
|
||||||
* The class ensures that initialization is done in the correct order.
|
* The class ensures that initialization is done in the correct order.
|
||||||
*
|
*
|
||||||
@@ -108,9 +124,11 @@ public class JsePlatform {
|
|||||||
return globals;
|
return globals;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create standard globals including the {@link DebugLib} library.
|
/**
|
||||||
|
* Create standard globals including the {@link DebugLib} library.
|
||||||
*
|
*
|
||||||
* @return Table of globals initialized with the standard JSE and debug libraries
|
* @return Table of globals initialized with the standard JSE and debug
|
||||||
|
* libraries
|
||||||
* @see #standardGlobals()
|
* @see #standardGlobals()
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
* @see org.luaj.vm2.lib.jme.JmePlatform
|
* @see org.luaj.vm2.lib.jme.JmePlatform
|
||||||
@@ -122,10 +140,11 @@ public class JsePlatform {
|
|||||||
return globals;
|
return globals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/** Simple wrapper for invoking a lua function with command line arguments.
|
* Simple wrapper for invoking a lua function with command line arguments.
|
||||||
* The supplied function is first given a new Globals object as its environment
|
* The supplied function is first given a new Globals object as its
|
||||||
* then the program is run with arguments.
|
* environment then the program is run with arguments.
|
||||||
|
*
|
||||||
* @return {@link Varargs} containing any values returned by mainChunk.
|
* @return {@link Varargs} containing any values returned by mainChunk.
|
||||||
*/
|
*/
|
||||||
public static Varargs luaMain(LuaValue mainChunk, String[] args) {
|
public static Varargs luaMain(LuaValue mainChunk, String[] args) {
|
||||||
|
|||||||
@@ -25,19 +25,25 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
/** Analog of Process that pipes input and output to client-specified streams.
|
/**
|
||||||
|
* Analog of Process that pipes input and output to client-specified streams.
|
||||||
*/
|
*/
|
||||||
public class JseProcess {
|
public class JseProcess {
|
||||||
|
|
||||||
final Process process;
|
final Process process;
|
||||||
final Thread input, output, error;
|
final Thread input, output, error;
|
||||||
|
|
||||||
/** Construct a process around a command, with specified streams to redirect input and output to.
|
/**
|
||||||
|
* Construct a process around a command, with specified streams to redirect
|
||||||
|
* input and output to.
|
||||||
*
|
*
|
||||||
* @param cmd The command to execute, including arguments, if any
|
* @param cmd The command to execute, including arguments, if any
|
||||||
* @param stdin Optional InputStream to read from as process input, or null if input is not needed.
|
* @param stdin Optional InputStream to read from as process input, or null
|
||||||
* @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
|
* if input is not needed.
|
||||||
* @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
|
* @param stdout Optional OutputStream to copy process output to, or null if
|
||||||
|
* output is ignored.
|
||||||
|
* @param stderr Optinoal OutputStream to copy process stderr output to, or
|
||||||
|
* null if output is ignored.
|
||||||
* @throws IOException If the system process could not be created.
|
* @throws IOException If the system process could not be created.
|
||||||
* @see Process
|
* @see Process
|
||||||
*/
|
*/
|
||||||
@@ -45,12 +51,17 @@ public class JseProcess {
|
|||||||
this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
|
this(Runtime.getRuntime().exec(cmd), stdin, stdout, stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a process around a command, with specified streams to redirect input and output to.
|
/**
|
||||||
|
* Construct a process around a command, with specified streams to redirect
|
||||||
|
* input and output to.
|
||||||
*
|
*
|
||||||
* @param cmd The command to execute, including arguments, if any
|
* @param cmd The command to execute, including arguments, if any
|
||||||
* @param stdin Optional InputStream to read from as process input, or null if input is not needed.
|
* @param stdin Optional InputStream to read from as process input, or null
|
||||||
* @param stdout Optional OutputStream to copy process output to, or null if output is ignored.
|
* if input is not needed.
|
||||||
* @param stderr Optinoal OutputStream to copy process stderr output to, or null if output is ignored.
|
* @param stdout Optional OutputStream to copy process output to, or null if
|
||||||
|
* output is ignored.
|
||||||
|
* @param stderr Optinoal OutputStream to copy process stderr output to, or
|
||||||
|
* null if output is ignored.
|
||||||
* @throws IOException If the system process could not be created.
|
* @throws IOException If the system process could not be created.
|
||||||
* @see Process
|
* @see Process
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +81,9 @@ public class JseProcess {
|
|||||||
return process.exitValue();
|
return process.exitValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Wait for the process to complete, and all pending output to finish.
|
/**
|
||||||
|
* Wait for the process to complete, and all pending output to finish.
|
||||||
|
*
|
||||||
* @return The exit status.
|
* @return The exit status.
|
||||||
* @throws InterruptedException
|
* @throws InterruptedException
|
||||||
*/
|
*/
|
||||||
@@ -87,8 +100,7 @@ public class JseProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Create a thread to copy bytes from input to output. */
|
/** Create a thread to copy bytes from input to output. */
|
||||||
private Thread copyBytes(final InputStream input,
|
private Thread copyBytes(final InputStream input, final OutputStream output, final InputStream ownedInput,
|
||||||
final OutputStream output, final InputStream ownedInput,
|
|
||||||
final OutputStream ownedOutput) {
|
final OutputStream ownedOutput) {
|
||||||
Thread t = (new CopyThread(output, ownedOutput, ownedInput, input));
|
Thread t = (new CopyThread(output, ownedOutput, ownedInput, input));
|
||||||
t.start();
|
t.start();
|
||||||
@@ -101,8 +113,7 @@ public class JseProcess {
|
|||||||
private final InputStream ownedInput;
|
private final InputStream ownedInput;
|
||||||
private final InputStream input;
|
private final InputStream input;
|
||||||
|
|
||||||
private CopyThread(OutputStream output, OutputStream ownedOutput,
|
private CopyThread(OutputStream output, OutputStream ownedOutput, InputStream ownedInput, InputStream input) {
|
||||||
InputStream ownedInput, InputStream input) {
|
|
||||||
this.output = output;
|
this.output = output;
|
||||||
this.ownedOutput = ownedOutput;
|
this.ownedOutput = ownedOutput;
|
||||||
this.ownedInput = ownedInput;
|
this.ownedInput = ownedInput;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.vm2.lib.jse;
|
package org.luaj.vm2.lib.jse;
|
||||||
|
|
||||||
|
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@@ -38,40 +37,51 @@ import org.luaj.vm2.lib.LibFunction;
|
|||||||
import org.luaj.vm2.lib.VarArgFunction;
|
import org.luaj.vm2.lib.VarArgFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link LibFunction} which implements the features of the luajava package.
|
* Subclass of {@link LibFunction} which implements the features of the luajava
|
||||||
|
* package.
|
||||||
* <p>
|
* <p>
|
||||||
* Luajava is an approach to mixing lua and java using simple functions that bind
|
* Luajava is an approach to mixing lua and java using simple functions that
|
||||||
* java classes and methods to lua dynamically. The API is documented on the
|
* bind java classes and methods to lua dynamically. The API is documented on
|
||||||
* <a href="http://www.keplerproject.org/luajava/">luajava</a> documentation pages.
|
* the <a href="http://www.keplerproject.org/luajava/">luajava</a> documentation
|
||||||
|
* pages.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Typically, this library is included as part of a call to
|
* Typically, this library is included as part of a call to
|
||||||
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = JsePlatform.standardGlobals();
|
* Globals globals = JsePlatform.standardGlobals();
|
||||||
* System.out.println( globals.get("luajava").get("bindClass").call( LuaValue.valueOf("java.lang.System") ).invokeMethod("currentTimeMillis") );
|
* System.out.println(globals.get("luajava").get("bindClass").call(LuaValue.valueOf("java.lang.System"))
|
||||||
* } </pre>
|
* .invokeMethod("currentTimeMillis"));
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* To instantiate and use it directly,
|
* To instantiate and use it directly, link it into your globals table via
|
||||||
* link it into your globals table via {@link Globals#load} using code such as:
|
* {@link Globals#load} using code such as:
|
||||||
* <pre> {@code
|
*
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* @code
|
||||||
* Globals globals = new Globals();
|
* Globals globals = new Globals();
|
||||||
* globals.load(new JseBaseLib());
|
* globals.load(new JseBaseLib());
|
||||||
* globals.load(new PackageLib());
|
* globals.load(new PackageLib());
|
||||||
* globals.load(new LuajavaLib());
|
* globals.load(new LuajavaLib());
|
||||||
* globals.load(
|
* globals.load("sys = luajava.bindClass('java.lang.System')\n" + "print ( sys:currentTimeMillis() )\n", "main.lua")
|
||||||
* "sys = luajava.bindClass('java.lang.System')\n"+
|
* .call();
|
||||||
* "print ( sys:currentTimeMillis() )\n", "main.lua" ).call();
|
* }
|
||||||
* } </pre>
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* The {@code luajava} library is available
|
* The {@code luajava} library is available on all JSE platforms via the call to
|
||||||
* on all JSE platforms via the call to {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()}
|
* {@link org.luaj.vm2.lib.jse.JsePlatform#standardGlobals()} and the luajava
|
||||||
* and the luajava api's are simply invoked from lua.
|
* api's are simply invoked from lua. Because it makes extensive use of Java's
|
||||||
* Because it makes extensive use of Java's reflection API, it is not available
|
* reflection API, it is not available on JME, but can be used in Android
|
||||||
* on JME, but can be used in Android applications.
|
* applications.
|
||||||
* <p>
|
* <p>
|
||||||
* This has been implemented to match as closely as possible the behavior in the corresponding library in C.
|
* This has been implemented to match as closely as possible the behavior in the
|
||||||
|
* corresponding library in C.
|
||||||
*
|
*
|
||||||
* @see LibFunction
|
* @see LibFunction
|
||||||
* @see org.luaj.vm2.lib.jse.JsePlatform
|
* @see org.luaj.vm2.lib.jse.JsePlatform
|
||||||
@@ -79,7 +89,8 @@ import org.luaj.vm2.lib.VarArgFunction;
|
|||||||
* @see LuaC
|
* @see LuaC
|
||||||
* @see CoerceJavaToLua
|
* @see CoerceJavaToLua
|
||||||
* @see CoerceLuaToJava
|
* @see CoerceLuaToJava
|
||||||
* @see <a href="http://www.keplerproject.org/luajava/manual.html#luareference">http://www.keplerproject.org/luajava/manual.html#luareference</a>
|
* @see <a href=
|
||||||
|
* "http://www.keplerproject.org/luajava/manual.html#luareference">http://www.keplerproject.org/luajava/manual.html#luareference</a>
|
||||||
*/
|
*/
|
||||||
public class LuajavaLib extends VarArgFunction {
|
public class LuajavaLib extends VarArgFunction {
|
||||||
|
|
||||||
@@ -90,13 +101,7 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
static final int CREATEPROXY = 4;
|
static final int CREATEPROXY = 4;
|
||||||
static final int LOADLIB = 5;
|
static final int LOADLIB = 5;
|
||||||
|
|
||||||
static final String[] NAMES = {
|
static final String[] NAMES = { "bindClass", "newInstance", "new", "createProxy", "loadLib", };
|
||||||
"bindClass",
|
|
||||||
"newInstance",
|
|
||||||
"new",
|
|
||||||
"createProxy",
|
|
||||||
"loadLib",
|
|
||||||
};
|
|
||||||
|
|
||||||
static final int METHOD_MODIFIERS_VARARGS = 0x80;
|
static final int METHOD_MODIFIERS_VARARGS = 0x80;
|
||||||
|
|
||||||
@@ -112,7 +117,8 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
LuaTable t = new LuaTable();
|
LuaTable t = new LuaTable();
|
||||||
bind(t, this.getClass(), NAMES, BINDCLASS);
|
bind(t, this.getClass(), NAMES, BINDCLASS);
|
||||||
env.set("luajava", t);
|
env.set("luajava", t);
|
||||||
if (!env.get("package").isnil()) env.get("package").get("loaded").set("luajava", t);
|
if (!env.get("package").isnil())
|
||||||
|
env.get("package").get("loaded").set("luajava", t);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
case BINDCLASS: {
|
case BINDCLASS: {
|
||||||
@@ -123,7 +129,8 @@ public class LuajavaLib extends VarArgFunction {
|
|||||||
case NEW: {
|
case NEW: {
|
||||||
// get constructor
|
// get constructor
|
||||||
final LuaValue c = args.checkvalue(1);
|
final LuaValue c = args.checkvalue(1);
|
||||||
final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
|
final Class clazz = (opcode == NEWINSTANCE? classForName(c.tojstring())
|
||||||
|
: (Class) c.checkuserdata(Class.class));
|
||||||
final Varargs consargs = args.subargs(2);
|
final Varargs consargs = args.subargs(2);
|
||||||
return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
|
return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,8 @@ public class BasicBlock {
|
|||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
sb.append( (pc0+1)+"-"+(pc1+1)
|
sb.append((pc0+1) + "-" + (pc1+1) + (prev != null? " prv: " + str(prev, 1): "")
|
||||||
+(prev!=null? " prv: "+str(prev,1): "")
|
+ (next != null? " nxt: " + str(next, 0): "") + "\n");
|
||||||
+(next!=null? " nxt: "+str(next,0): "")
|
|
||||||
+"\n" );
|
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +75,7 @@ public class BasicBlock {
|
|||||||
private final int[] nprev;
|
private final int[] nprev;
|
||||||
private final BasicBlock[] blocks;
|
private final BasicBlock[] blocks;
|
||||||
|
|
||||||
private AllocAndXRefVisitor(boolean[] isbeg, int[] nnext, int[] nprev,
|
private AllocAndXRefVisitor(boolean[] isbeg, int[] nnext, int[] nprev, BasicBlock[] blocks) {
|
||||||
BasicBlock[] blocks) {
|
|
||||||
super(isbeg);
|
super(isbeg);
|
||||||
this.nnext = nnext;
|
this.nnext = nnext;
|
||||||
this.nprev = nprev;
|
this.nprev = nprev;
|
||||||
@@ -86,8 +83,10 @@ public class BasicBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void visitBranch(int pc0, int pc1) {
|
public void visitBranch(int pc0, int pc1) {
|
||||||
if ( blocks[pc0].next == null ) blocks[pc0].next = new BasicBlock[nnext[pc0]];
|
if (blocks[pc0].next == null)
|
||||||
if ( blocks[pc1].prev == null ) blocks[pc1].prev = new BasicBlock[nprev[pc1]];
|
blocks[pc0].next = new BasicBlock[nnext[pc0]];
|
||||||
|
if (blocks[pc1].prev == null)
|
||||||
|
blocks[pc1].prev = new BasicBlock[nprev[pc1]];
|
||||||
blocks[pc0].next[--nnext[pc0]] = blocks[pc1];
|
blocks[pc0].next[--nnext[pc0]] = blocks[pc1];
|
||||||
blocks[pc1].prev[--nprev[pc1]] = blocks[pc0];
|
blocks[pc1].prev[--nprev[pc1]] = blocks[pc0];
|
||||||
}
|
}
|
||||||
@@ -129,10 +128,13 @@ public class BasicBlock {
|
|||||||
|
|
||||||
abstract public static class BranchVisitor {
|
abstract public static class BranchVisitor {
|
||||||
final boolean[] isbeg;
|
final boolean[] isbeg;
|
||||||
|
|
||||||
public BranchVisitor(boolean[] isbeg) {
|
public BranchVisitor(boolean[] isbeg) {
|
||||||
this.isbeg = isbeg;
|
this.isbeg = isbeg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visitBranch(int frompc, int topc) {}
|
public void visitBranch(int frompc, int topc) {}
|
||||||
|
|
||||||
public void visitReturn(int atpc) {}
|
public void visitReturn(int atpc) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ public class JavaBuilder {
|
|||||||
private static final ArrayType TYPE_CHARARRAY = new ArrayType(Type.CHAR, 1);
|
private static final ArrayType TYPE_CHARARRAY = new ArrayType(Type.CHAR, 1);
|
||||||
private static final ArrayType TYPE_STRINGARRAY = new ArrayType(TYPE_STRING, 1);
|
private static final ArrayType TYPE_STRINGARRAY = new ArrayType(TYPE_STRING, 1);
|
||||||
|
|
||||||
|
|
||||||
private static final String STR_FUNCV = VarArgFunction.class.getName();
|
private static final String STR_FUNCV = VarArgFunction.class.getName();
|
||||||
private static final String STR_FUNC0 = ZeroArgFunction.class.getName();
|
private static final String STR_FUNC0 = ZeroArgFunction.class.getName();
|
||||||
private static final String STR_FUNC1 = OneArgFunction.class.getName();
|
private static final String STR_FUNC1 = OneArgFunction.class.getName();
|
||||||
@@ -111,7 +110,8 @@ public class JavaBuilder {
|
|||||||
private static final Type[] ARG_TYPES_LUAVALUE_VARARGS = { TYPE_LUAVALUE, TYPE_VARARGS };
|
private static final Type[] ARG_TYPES_LUAVALUE_VARARGS = { TYPE_LUAVALUE, TYPE_VARARGS };
|
||||||
private static final Type[] ARG_TYPES_LUAVALUE_LUAVALUE_VARARGS = { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS };
|
private static final Type[] ARG_TYPES_LUAVALUE_LUAVALUE_VARARGS = { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS };
|
||||||
private static final Type[] ARG_TYPES_LUAVALUEARRAY = { new ArrayType(TYPE_LUAVALUE, 1) };
|
private static final Type[] ARG_TYPES_LUAVALUEARRAY = { new ArrayType(TYPE_LUAVALUE, 1) };
|
||||||
private static final Type[] ARG_TYPES_LUAVALUEARRAY_VARARGS = { new ArrayType( TYPE_LUAVALUE, 1 ), TYPE_VARARGS };
|
private static final Type[] ARG_TYPES_LUAVALUEARRAY_VARARGS = { new ArrayType(TYPE_LUAVALUE, 1),
|
||||||
|
TYPE_VARARGS };
|
||||||
private static final Type[] ARG_TYPES_LUAVALUE_LUAVALUE_LUAVALUE = { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE };
|
private static final Type[] ARG_TYPES_LUAVALUE_LUAVALUE_LUAVALUE = { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE };
|
||||||
private static final Type[] ARG_TYPES_VARARGS = { TYPE_VARARGS };
|
private static final Type[] ARG_TYPES_VARARGS = { TYPE_VARARGS };
|
||||||
private static final Type[] ARG_TYPES_LUAVALUE_LUAVALUE = { TYPE_LUAVALUE, TYPE_LUAVALUE };
|
private static final Type[] ARG_TYPES_LUAVALUE_LUAVALUE = { TYPE_LUAVALUE, TYPE_LUAVALUE };
|
||||||
@@ -123,13 +123,14 @@ public class JavaBuilder {
|
|||||||
|
|
||||||
// names, arg types for main prototype classes
|
// names, arg types for main prototype classes
|
||||||
private static final String[] SUPER_NAME_N = { STR_FUNC0, STR_FUNC1, STR_FUNC2, STR_FUNC3, STR_FUNCV, };
|
private static final String[] SUPER_NAME_N = { STR_FUNC0, STR_FUNC1, STR_FUNC2, STR_FUNC3, STR_FUNCV, };
|
||||||
private static final ObjectType[] RETURN_TYPE_N = { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_VARARGS, };
|
private static final ObjectType[] RETURN_TYPE_N = { TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE, TYPE_LUAVALUE,
|
||||||
private static final Type[][] ARG_TYPES_N = { ARG_TYPES_NONE, ARG_TYPES_LUAVALUE, ARG_TYPES_LUAVALUE_LUAVALUE, ARG_TYPES_LUAVALUE_LUAVALUE_LUAVALUE, ARG_TYPES_VARARGS, };
|
TYPE_VARARGS, };
|
||||||
private static final String[][] ARG_NAMES_N = { {}, {"arg"}, {"arg1","arg2"}, {"arg1","arg2","arg3"}, {"args"}, };
|
private static final Type[][] ARG_TYPES_N = { ARG_TYPES_NONE, ARG_TYPES_LUAVALUE, ARG_TYPES_LUAVALUE_LUAVALUE,
|
||||||
|
ARG_TYPES_LUAVALUE_LUAVALUE_LUAVALUE, ARG_TYPES_VARARGS, };
|
||||||
|
private static final String[][] ARG_NAMES_N = { {}, { "arg" }, { "arg1", "arg2" }, { "arg1", "arg2", "arg3" },
|
||||||
|
{ "args" }, };
|
||||||
private static final String[] METH_NAME_N = { "call", "call", "call", "call", "onInvoke", };
|
private static final String[] METH_NAME_N = { "call", "call", "call", "call", "onInvoke", };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// varable naming
|
// varable naming
|
||||||
private static final String PREFIX_CONSTANT = "k";
|
private static final String PREFIX_CONSTANT = "k";
|
||||||
private static final String PREFIX_UPVALUE = "u";
|
private static final String PREFIX_UPVALUE = "u";
|
||||||
@@ -179,16 +180,16 @@ public class JavaBuilder {
|
|||||||
for (int i = 0, n = p.code.length; i < n; i++) {
|
for (int i = 0, n = p.code.length; i < n; i++) {
|
||||||
int inst = p.code[i];
|
int inst = p.code[i];
|
||||||
int o = Lua.GET_OPCODE(inst);
|
int o = Lua.GET_OPCODE(inst);
|
||||||
if ( (o == Lua.OP_TAILCALL) ||
|
if ((o == Lua.OP_TAILCALL)
|
||||||
((o == Lua.OP_RETURN) && (Lua.GETARG_B(inst) < 1 || Lua.GETARG_B(inst) > 2)) ) {
|
|| ((o == Lua.OP_RETURN) && (Lua.GETARG_B(inst) < 1 || Lua.GETARG_B(inst) > 2))) {
|
||||||
superclassType = SUPERTYPE_VARARGS;
|
superclassType = SUPERTYPE_VARARGS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create class generator
|
// create class generator
|
||||||
cg = new ClassGen(classname, SUPER_NAME_N[superclassType], filename,
|
cg = new ClassGen(classname, SUPER_NAME_N[superclassType], filename, Constants.ACC_PUBLIC | Constants.ACC_SUPER,
|
||||||
Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
|
null);
|
||||||
cp = cg.getConstantPool(); // cg creates constant pool
|
cp = cg.getConstantPool(); // cg creates constant pool
|
||||||
|
|
||||||
// main instruction lists
|
// main instruction lists
|
||||||
@@ -209,8 +210,7 @@ public class JavaBuilder {
|
|||||||
RETURN_TYPE_N[superclassType], // return type
|
RETURN_TYPE_N[superclassType], // return type
|
||||||
ARG_TYPES_N[superclassType], // argument types
|
ARG_TYPES_N[superclassType], // argument types
|
||||||
ARG_NAMES_N[superclassType], // arg names
|
ARG_NAMES_N[superclassType], // arg names
|
||||||
METH_NAME_N[superclassType],
|
METH_NAME_N[superclassType], STR_LUAVALUE, // method, defining class
|
||||||
STR_LUAVALUE, // method, defining class
|
|
||||||
main, cp);
|
main, cp);
|
||||||
|
|
||||||
// initialize the values in the slots
|
// initialize the values in the slots
|
||||||
@@ -232,7 +232,8 @@ public class JavaBuilder {
|
|||||||
if (pi.isInitialValueUsed(slot)) {
|
if (pi.isInitialValueUsed(slot)) {
|
||||||
append(new ALOAD(1));
|
append(new ALOAD(1));
|
||||||
append(new PUSH(cp, slot+1));
|
append(new PUSH(cp, slot+1));
|
||||||
append(factory.createInvoke(STR_VARARGS, "arg", TYPE_LUAVALUE, ARG_TYPES_INT, Constants.INVOKEVIRTUAL));
|
append(factory.createInvoke(STR_VARARGS, "arg", TYPE_LUAVALUE, ARG_TYPES_INT,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
storeLocal(-1, slot);
|
storeLocal(-1, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,8 +266,7 @@ public class JavaBuilder {
|
|||||||
|
|
||||||
// add class initializer
|
// add class initializer
|
||||||
if (!init.isEmpty()) {
|
if (!init.isEmpty()) {
|
||||||
MethodGen mg = new MethodGen(Constants.ACC_STATIC, Type.VOID,
|
MethodGen mg = new MethodGen(Constants.ACC_STATIC, Type.VOID, ARG_TYPES_NONE, new String[] {}, "<clinit>",
|
||||||
ARG_TYPES_NONE, new String[] {}, "<clinit>",
|
|
||||||
cg.getClassName(), init, cg.getConstantPool());
|
cg.getClassName(), init, cg.getConstantPool());
|
||||||
init.append(InstructionConstants.RETURN);
|
init.append(InstructionConstants.RETURN);
|
||||||
mg.setMaxStack();
|
mg.setMaxStack();
|
||||||
@@ -289,14 +289,14 @@ public class JavaBuilder {
|
|||||||
Type.VOID, // return type
|
Type.VOID, // return type
|
||||||
ARG_TYPES_LUAVALUE, // argument types
|
ARG_TYPES_LUAVALUE, // argument types
|
||||||
new String[] { "env" }, // arg names
|
new String[] { "env" }, // arg names
|
||||||
"initupvalue1",
|
"initupvalue1", STR_LUAVALUE, // method, defining class
|
||||||
STR_LUAVALUE, // method, defining class
|
|
||||||
main, cp);
|
main, cp);
|
||||||
boolean isrw = pi.isReadWriteUpvalue(pi.upvals[0]);
|
boolean isrw = pi.isReadWriteUpvalue(pi.upvals[0]);
|
||||||
append(InstructionConstants.THIS);
|
append(InstructionConstants.THIS);
|
||||||
append(new ALOAD(1));
|
append(new ALOAD(1));
|
||||||
if (isrw) {
|
if (isrw) {
|
||||||
append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKESTATIC));
|
append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, ARG_TYPES_LUAVALUE,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
append(factory.createFieldAccess(classname, upvalueName(0), TYPE_LOCALUPVALUE, Constants.PUTFIELD));
|
append(factory.createFieldAccess(classname, upvalueName(0), TYPE_LOCALUPVALUE, Constants.PUTFIELD));
|
||||||
} else {
|
} else {
|
||||||
append(factory.createFieldAccess(classname, upvalueName(0), TYPE_LUAVALUE, Constants.PUTFIELD));
|
append(factory.createFieldAccess(classname, upvalueName(0), TYPE_LUAVALUE, Constants.PUTFIELD));
|
||||||
@@ -313,21 +313,21 @@ public class JavaBuilder {
|
|||||||
Type.VOID, // return type
|
Type.VOID, // return type
|
||||||
ARG_TYPES_STRINGARRAY, // argument types
|
ARG_TYPES_STRINGARRAY, // argument types
|
||||||
new String[] { "arg" }, // arg names
|
new String[] { "arg" }, // arg names
|
||||||
"main",
|
"main", classname, // method, defining class
|
||||||
classname, // method, defining class
|
|
||||||
main, cp);
|
main, cp);
|
||||||
append(factory.createNew(classname));
|
append(factory.createNew(classname));
|
||||||
append(InstructionConstants.DUP);
|
append(InstructionConstants.DUP);
|
||||||
append(factory.createInvoke(classname, Constants.CONSTRUCTOR_NAME, Type.VOID, ARG_TYPES_NONE, Constants.INVOKESPECIAL));
|
append(factory.createInvoke(classname, Constants.CONSTRUCTOR_NAME, Type.VOID, ARG_TYPES_NONE,
|
||||||
|
Constants.INVOKESPECIAL));
|
||||||
append(new ALOAD(0));
|
append(new ALOAD(0));
|
||||||
append(factory.createInvoke(STR_JSEPLATFORM, "luaMain", Type.VOID, ARG_TYPES_LUAVALUE_STRINGARRAY, Constants.INVOKESTATIC));
|
append(factory.createInvoke(STR_JSEPLATFORM, "luaMain", Type.VOID, ARG_TYPES_LUAVALUE_STRINGARRAY,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
append(InstructionConstants.RETURN);
|
append(InstructionConstants.RETURN);
|
||||||
mg.setMaxStack();
|
mg.setMaxStack();
|
||||||
cg.addMethod(mg.getMethod());
|
cg.addMethod(mg.getMethod());
|
||||||
main.dispose();
|
main.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// convert to class bytes
|
// convert to class bytes
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
@@ -362,6 +362,7 @@ public class JavaBuilder {
|
|||||||
private Map<Integer, Integer> plainSlotVars = new HashMap<Integer, Integer>();
|
private Map<Integer, Integer> plainSlotVars = new HashMap<Integer, Integer>();
|
||||||
private Map<Integer, Integer> upvalueSlotVars = new HashMap<Integer, Integer>();
|
private Map<Integer, Integer> upvalueSlotVars = new HashMap<Integer, Integer>();
|
||||||
private Map<Integer, LocalVariableGen> localVarGenBySlot = new HashMap<Integer, LocalVariableGen>();
|
private Map<Integer, LocalVariableGen> localVarGenBySlot = new HashMap<Integer, LocalVariableGen>();
|
||||||
|
|
||||||
private int findSlot(int slot, Map<Integer, Integer> map, String prefix, Type type) {
|
private int findSlot(int slot, Map<Integer, Integer> map, String prefix, Type type) {
|
||||||
Integer islot = Integer.valueOf(slot);
|
Integer islot = Integer.valueOf(slot);
|
||||||
if (map.containsKey(islot))
|
if (map.containsKey(islot))
|
||||||
@@ -373,10 +374,10 @@ public class JavaBuilder {
|
|||||||
localVarGenBySlot.put(islot, local);
|
localVarGenBySlot.put(islot, local);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int findSlotIndex(int slot, boolean isupvalue) {
|
private int findSlotIndex(int slot, boolean isupvalue) {
|
||||||
return isupvalue?
|
return isupvalue? findSlot(slot, upvalueSlotVars, PREFIX_UPVALUE_SLOT, TYPE_LOCALUPVALUE)
|
||||||
findSlot( slot, upvalueSlotVars, PREFIX_UPVALUE_SLOT, TYPE_LOCALUPVALUE ):
|
: findSlot(slot, plainSlotVars, PREFIX_PLAIN_SLOT, TYPE_LUAVALUE);
|
||||||
findSlot( slot, plainSlotVars, PREFIX_PLAIN_SLOT, TYPE_LUAVALUE );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadLocal(int pc, int slot) {
|
public void loadLocal(int pc, int slot) {
|
||||||
@@ -395,7 +396,8 @@ public class JavaBuilder {
|
|||||||
if (isupval) {
|
if (isupval) {
|
||||||
boolean isupcreate = pi.isUpvalueCreate(pc, slot);
|
boolean isupcreate = pi.isUpvalueCreate(pc, slot);
|
||||||
if (isupcreate) {
|
if (isupcreate) {
|
||||||
append(factory.createInvoke(classname, "newupe", TYPE_LOCALUPVALUE, ARG_TYPES_NONE, Constants.INVOKESTATIC));
|
append(factory.createInvoke(classname, "newupe", TYPE_LOCALUPVALUE, ARG_TYPES_NONE,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
append(InstructionConstants.DUP);
|
append(InstructionConstants.DUP);
|
||||||
append(new ASTORE(index));
|
append(new ASTORE(index));
|
||||||
} else {
|
} else {
|
||||||
@@ -416,7 +418,8 @@ public class JavaBuilder {
|
|||||||
boolean isupcreate = pi.isUpvalueCreate(pc, slot);
|
boolean isupcreate = pi.isUpvalueCreate(pc, slot);
|
||||||
if (isupcreate) {
|
if (isupcreate) {
|
||||||
int index = findSlotIndex(slot, true);
|
int index = findSlotIndex(slot, true);
|
||||||
append(factory.createInvoke(classname, "newupn", TYPE_LOCALUPVALUE, ARG_TYPES_NONE, Constants.INVOKESTATIC));
|
append(factory.createInvoke(classname, "newupn", TYPE_LOCALUPVALUE, ARG_TYPES_NONE,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
append(new ASTORE(index));
|
append(new ASTORE(index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -427,7 +430,8 @@ public class JavaBuilder {
|
|||||||
if (isupassign) {
|
if (isupassign) {
|
||||||
int index = findSlotIndex(slot, false);
|
int index = findSlotIndex(slot, false);
|
||||||
append(new ALOAD(index));
|
append(new ALOAD(index));
|
||||||
append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKESTATIC));
|
append(factory.createInvoke(classname, "newupl", TYPE_LOCALUPVALUE, ARG_TYPES_LUAVALUE,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
int upindex = findSlotIndex(slot, true);
|
int upindex = findSlotIndex(slot, true);
|
||||||
append(new ASTORE(upindex));
|
append(new ASTORE(upindex));
|
||||||
}
|
}
|
||||||
@@ -463,7 +467,6 @@ public class JavaBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void newTable(int b, int c) {
|
public void newTable(int b, int c) {
|
||||||
append(new PUSH(cp, b));
|
append(new PUSH(cp, b));
|
||||||
append(new PUSH(cp, c));
|
append(new PUSH(cp, c));
|
||||||
@@ -512,16 +515,23 @@ public class JavaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setTable() {
|
public void setTable() {
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, ARG_TYPES_LUAVALUE_LUAVALUE, Constants.INVOKEVIRTUAL));
|
append(
|
||||||
|
factory.createInvoke(STR_LUAVALUE, "set", Type.VOID, ARG_TYPES_LUAVALUE_LUAVALUE, Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unaryop(int o) {
|
public void unaryop(int o) {
|
||||||
String op;
|
String op;
|
||||||
switch (o) {
|
switch (o) {
|
||||||
default:
|
default:
|
||||||
case Lua.OP_UNM: op = "neg"; break;
|
case Lua.OP_UNM:
|
||||||
case Lua.OP_NOT: op = "not"; break;
|
op = "neg";
|
||||||
case Lua.OP_LEN: op = "len"; break;
|
break;
|
||||||
|
case Lua.OP_NOT:
|
||||||
|
op = "not";
|
||||||
|
break;
|
||||||
|
case Lua.OP_LEN:
|
||||||
|
op = "len";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
|
append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
@@ -530,12 +540,24 @@ public class JavaBuilder {
|
|||||||
String op;
|
String op;
|
||||||
switch (o) {
|
switch (o) {
|
||||||
default:
|
default:
|
||||||
case Lua.OP_ADD: op = "add"; break;
|
case Lua.OP_ADD:
|
||||||
case Lua.OP_SUB: op = "sub"; break;
|
op = "add";
|
||||||
case Lua.OP_MUL: op = "mul"; break;
|
break;
|
||||||
case Lua.OP_DIV: op = "div"; break;
|
case Lua.OP_SUB:
|
||||||
case Lua.OP_MOD: op = "mod"; break;
|
op = "sub";
|
||||||
case Lua.OP_POW: op = "pow"; break;
|
break;
|
||||||
|
case Lua.OP_MUL:
|
||||||
|
op = "mul";
|
||||||
|
break;
|
||||||
|
case Lua.OP_DIV:
|
||||||
|
op = "div";
|
||||||
|
break;
|
||||||
|
case Lua.OP_MOD:
|
||||||
|
op = "mod";
|
||||||
|
break;
|
||||||
|
case Lua.OP_POW:
|
||||||
|
op = "pow";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
|
append(factory.createInvoke(STR_LUAVALUE, op, TYPE_LUAVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
@@ -544,9 +566,15 @@ public class JavaBuilder {
|
|||||||
String op;
|
String op;
|
||||||
switch (o) {
|
switch (o) {
|
||||||
default:
|
default:
|
||||||
case Lua.OP_EQ: op = "eq_b"; break;
|
case Lua.OP_EQ:
|
||||||
case Lua.OP_LT: op = "lt_b"; break;
|
op = "eq_b";
|
||||||
case Lua.OP_LE: op = "lteq_b"; break;
|
break;
|
||||||
|
case Lua.OP_LT:
|
||||||
|
op = "lt_b";
|
||||||
|
break;
|
||||||
|
case Lua.OP_LE:
|
||||||
|
op = "lteq_b";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
append(factory.createInvoke(STR_LUAVALUE, op, Type.BOOLEAN, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
|
append(factory.createInvoke(STR_LUAVALUE, op, Type.BOOLEAN, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
@@ -568,7 +596,8 @@ public class JavaBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testForLoop() {
|
public void testForLoop() {
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "testfor_b", Type.BOOLEAN, ARG_TYPES_LUAVALUE_LUAVALUE, Constants.INVOKEVIRTUAL));
|
append(factory.createInvoke(STR_LUAVALUE, "testfor_b", Type.BOOLEAN, ARG_TYPES_LUAVALUE_LUAVALUE,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadArrayArgs(int pc, int firstslot, int nargs) {
|
public void loadArrayArgs(int pc, int firstslot, int nargs) {
|
||||||
@@ -584,19 +613,29 @@ public class JavaBuilder {
|
|||||||
|
|
||||||
public void newVarargs(int pc, int firstslot, int nargs) {
|
public void newVarargs(int pc, int firstslot, int nargs) {
|
||||||
switch (nargs) {
|
switch (nargs) {
|
||||||
case 0: loadNone();
|
case 0:
|
||||||
|
loadNone();
|
||||||
break;
|
break;
|
||||||
case 1: loadLocal(pc, firstslot);
|
case 1:
|
||||||
|
loadLocal(pc, firstslot);
|
||||||
break;
|
break;
|
||||||
case 2: loadLocal(pc, firstslot); loadLocal(pc, firstslot+1);
|
case 2:
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUE_VARARGS, Constants.INVOKESTATIC));
|
loadLocal(pc, firstslot);
|
||||||
|
loadLocal(pc, firstslot+1);
|
||||||
|
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUE_VARARGS,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
break;
|
break;
|
||||||
case 3: loadLocal(pc, firstslot); loadLocal(pc, firstslot+1); loadLocal(pc, firstslot+2);
|
case 3:
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUE_LUAVALUE_VARARGS, Constants.INVOKESTATIC));
|
loadLocal(pc, firstslot);
|
||||||
|
loadLocal(pc, firstslot+1);
|
||||||
|
loadLocal(pc, firstslot+2);
|
||||||
|
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUE_LUAVALUE_VARARGS,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
loadArrayArgs(pc, firstslot, nargs);
|
loadArrayArgs(pc, firstslot, nargs);
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUEARRAY, Constants.INVOKESTATIC));
|
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUEARRAY,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -604,35 +643,63 @@ public class JavaBuilder {
|
|||||||
public void newVarargsVarresult(int pc, int firstslot, int nslots) {
|
public void newVarargsVarresult(int pc, int firstslot, int nslots) {
|
||||||
loadArrayArgs(pc, firstslot, nslots);
|
loadArrayArgs(pc, firstslot, nslots);
|
||||||
loadVarresult();
|
loadVarresult();
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUEARRAY_VARARGS, Constants.INVOKESTATIC));
|
append(factory.createInvoke(STR_LUAVALUE, "varargsOf", TYPE_VARARGS, ARG_TYPES_LUAVALUEARRAY_VARARGS,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void call(int nargs) {
|
public void call(int nargs) {
|
||||||
switch (nargs) {
|
switch (nargs) {
|
||||||
case 0: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_NONE, Constants.INVOKEVIRTUAL)); break;
|
case 0:
|
||||||
case 1: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL)); break;
|
append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_NONE, Constants.INVOKEVIRTUAL));
|
||||||
case 2: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE_LUAVALUE, Constants.INVOKEVIRTUAL)); break;
|
break;
|
||||||
case 3: append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE_LUAVALUE_LUAVALUE, Constants.INVOKEVIRTUAL)); break;
|
case 1:
|
||||||
default: throw new IllegalArgumentException("can't call with "+nargs+" args");
|
append(
|
||||||
|
factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE_LUAVALUE,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
append(factory.createInvoke(STR_LUAVALUE, "call", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE_LUAVALUE_LUAVALUE,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("can't call with " + nargs + " args");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void newTailcallVarargs() {
|
public void newTailcallVarargs() {
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "tailcallOf", TYPE_VARARGS, ARG_TYPES_LUAVALUE_VARARGS, Constants.INVOKESTATIC));
|
append(factory.createInvoke(STR_LUAVALUE, "tailcallOf", TYPE_VARARGS, ARG_TYPES_LUAVALUE_VARARGS,
|
||||||
|
Constants.INVOKESTATIC));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invoke(int nargs) {
|
public void invoke(int nargs) {
|
||||||
switch (nargs) {
|
switch (nargs) {
|
||||||
case -1: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_VARARGS, Constants.INVOKEVIRTUAL)); break;
|
case -1:
|
||||||
case 0: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_NONE, Constants.INVOKEVIRTUAL)); break;
|
append(
|
||||||
case 1: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_VARARGS, Constants.INVOKEVIRTUAL)); break;
|
factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_VARARGS, Constants.INVOKEVIRTUAL));
|
||||||
case 2: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_LUAVALUE_VARARGS, Constants.INVOKEVIRTUAL)); break;
|
break;
|
||||||
case 3: append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_LUAVALUE_LUAVALUE_VARARGS, Constants.INVOKEVIRTUAL)); break;
|
case 0:
|
||||||
default: throw new IllegalArgumentException("can't invoke with "+nargs+" args");
|
append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_NONE, Constants.INVOKEVIRTUAL));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
append(
|
||||||
|
factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_VARARGS, Constants.INVOKEVIRTUAL));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_LUAVALUE_VARARGS,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
append(factory.createInvoke(STR_LUAVALUE, "invoke", TYPE_VARARGS, ARG_TYPES_LUAVALUE_LUAVALUE_VARARGS,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("can't invoke with " + nargs + " args");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------ closures ------------------------
|
// ------------------------ closures ------------------------
|
||||||
|
|
||||||
public void closureCreate(String protoname) {
|
public void closureCreate(String protoname) {
|
||||||
@@ -674,11 +741,8 @@ public class JavaBuilder {
|
|||||||
case LuaValue.TSTRING:
|
case LuaValue.TSTRING:
|
||||||
String name = (String) constants.get(value);
|
String name = (String) constants.get(value);
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = value.type() == LuaValue.TNUMBER?
|
name = value.type() == LuaValue.TNUMBER? value.isinttype()? createLuaIntegerField(value.checkint())
|
||||||
value.isinttype()?
|
: createLuaDoubleField(value.checkdouble()): createLuaStringField(value.checkstring());
|
||||||
createLuaIntegerField(value.checkint()):
|
|
||||||
createLuaDoubleField(value.checkdouble()):
|
|
||||||
createLuaStringField(value.checkstring());
|
|
||||||
constants.put(value, name);
|
constants.put(value, name);
|
||||||
}
|
}
|
||||||
append(factory.createGetStatic(classname, name, TYPE_LUAVALUE));
|
append(factory.createGetStatic(classname, name, TYPE_LUAVALUE));
|
||||||
@@ -690,48 +754,43 @@ public class JavaBuilder {
|
|||||||
|
|
||||||
private String createLuaIntegerField(int value) {
|
private String createLuaIntegerField(int value) {
|
||||||
String name = PREFIX_CONSTANT+constants.size();
|
String name = PREFIX_CONSTANT+constants.size();
|
||||||
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
|
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, TYPE_LUAVALUE, name, cp);
|
||||||
TYPE_LUAVALUE, name, cp);
|
|
||||||
cg.addField(fg.getField());
|
cg.addField(fg.getField());
|
||||||
init.append(new PUSH(cp, value));
|
init.append(new PUSH(cp, value));
|
||||||
init.append(factory.createInvoke(STR_LUAVALUE, "valueOf",
|
init.append(
|
||||||
TYPE_LUAINTEGER, ARG_TYPES_INT, Constants.INVOKESTATIC));
|
factory.createInvoke(STR_LUAVALUE, "valueOf", TYPE_LUAINTEGER, ARG_TYPES_INT, Constants.INVOKESTATIC));
|
||||||
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
|
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createLuaDoubleField(double value) {
|
private String createLuaDoubleField(double value) {
|
||||||
String name = PREFIX_CONSTANT+constants.size();
|
String name = PREFIX_CONSTANT+constants.size();
|
||||||
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
|
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, TYPE_LUAVALUE, name, cp);
|
||||||
TYPE_LUAVALUE, name, cp);
|
|
||||||
cg.addField(fg.getField());
|
cg.addField(fg.getField());
|
||||||
init.append(new PUSH(cp, value));
|
init.append(new PUSH(cp, value));
|
||||||
init.append(factory.createInvoke(STR_LUAVALUE, "valueOf",
|
init.append(
|
||||||
TYPE_LUANUMBER, ARG_TYPES_DOUBLE, Constants.INVOKESTATIC));
|
factory.createInvoke(STR_LUAVALUE, "valueOf", TYPE_LUANUMBER, ARG_TYPES_DOUBLE, Constants.INVOKESTATIC));
|
||||||
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
|
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createLuaStringField(LuaString value) {
|
private String createLuaStringField(LuaString value) {
|
||||||
String name = PREFIX_CONSTANT+constants.size();
|
String name = PREFIX_CONSTANT+constants.size();
|
||||||
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL,
|
FieldGen fg = new FieldGen(Constants.ACC_STATIC | Constants.ACC_FINAL, TYPE_LUAVALUE, name, cp);
|
||||||
TYPE_LUAVALUE, name, cp);
|
|
||||||
cg.addField(fg.getField());
|
cg.addField(fg.getField());
|
||||||
LuaString ls = value.checkstring();
|
LuaString ls = value.checkstring();
|
||||||
if (ls.isValidUtf8()) {
|
if (ls.isValidUtf8()) {
|
||||||
init.append(new PUSH(cp, value.tojstring()));
|
init.append(new PUSH(cp, value.tojstring()));
|
||||||
init.append(factory.createInvoke(STR_LUASTRING, "valueOf",
|
init.append(factory.createInvoke(STR_LUASTRING, "valueOf", TYPE_LUASTRING, ARG_TYPES_STRING,
|
||||||
TYPE_LUASTRING, ARG_TYPES_STRING, Constants.INVOKESTATIC));
|
Constants.INVOKESTATIC));
|
||||||
} else {
|
} else {
|
||||||
char[] c = new char[ls.m_length];
|
char[] c = new char[ls.m_length];
|
||||||
for (int j = 0; j < ls.m_length; j++)
|
for (int j = 0; j < ls.m_length; j++)
|
||||||
c[j] = (char) (0xff & (int) (ls.m_bytes[ls.m_offset+j]));
|
c[j] = (char) (0xff & (int) (ls.m_bytes[ls.m_offset+j]));
|
||||||
init.append(new PUSH(cp, new String(c)));
|
init.append(new PUSH(cp, new String(c)));
|
||||||
init.append(factory.createInvoke(STR_STRING, "toCharArray",
|
init.append(
|
||||||
TYPE_CHARARRAY, Type.NO_ARGS,
|
factory.createInvoke(STR_STRING, "toCharArray", TYPE_CHARARRAY, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
|
||||||
Constants.INVOKEVIRTUAL));
|
init.append(factory.createInvoke(STR_LUASTRING, "valueOf", TYPE_LUASTRING, ARG_TYPES_CHARARRAY,
|
||||||
init.append(factory.createInvoke(STR_LUASTRING, "valueOf",
|
|
||||||
TYPE_LUASTRING, ARG_TYPES_CHARARRAY,
|
|
||||||
Constants.INVOKESTATIC));
|
Constants.INVOKESTATIC));
|
||||||
}
|
}
|
||||||
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
|
init.append(factory.createPutStatic(classname, name, TYPE_LUAVALUE));
|
||||||
@@ -746,15 +805,20 @@ public class JavaBuilder {
|
|||||||
public void addBranch(int pc, int branchType, int targetpc) {
|
public void addBranch(int pc, int branchType, int targetpc) {
|
||||||
switch (branchType) {
|
switch (branchType) {
|
||||||
default:
|
default:
|
||||||
case BRANCH_GOTO: branches[pc] = new GOTO(null); break;
|
case BRANCH_GOTO:
|
||||||
case BRANCH_IFNE: branches[pc] = new IFNE(null); break;
|
branches[pc] = new GOTO(null);
|
||||||
case BRANCH_IFEQ: branches[pc] = new IFEQ(null); break;
|
break;
|
||||||
|
case BRANCH_IFNE:
|
||||||
|
branches[pc] = new IFNE(null);
|
||||||
|
break;
|
||||||
|
case BRANCH_IFEQ:
|
||||||
|
branches[pc] = new IFEQ(null);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
targets[pc] = targetpc;
|
targets[pc] = targetpc;
|
||||||
append(branches[pc]);
|
append(branches[pc]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void append(Instruction i) {
|
private void append(Instruction i) {
|
||||||
conditionalSetBeginningOfLua(main.append(i));
|
conditionalSetBeginningOfLua(main.append(i));
|
||||||
}
|
}
|
||||||
@@ -800,7 +864,8 @@ public class JavaBuilder {
|
|||||||
while ( t < branchDestHandles.length && branchDestHandles[t] == null )
|
while ( t < branchDestHandles.length && branchDestHandles[t] == null )
|
||||||
t++;
|
t++;
|
||||||
if (t >= branchDestHandles.length)
|
if (t >= branchDestHandles.length)
|
||||||
throw new IllegalArgumentException("no target at or after "+targets[pc]+" op="+Lua.GET_OPCODE(p.code[targets[pc]]));
|
throw new IllegalArgumentException(
|
||||||
|
"no target at or after " + targets[pc] + " op=" + Lua.GET_OPCODE(p.code[targets[pc]]));
|
||||||
branches[pc].setTarget(branchDestHandles[t]);
|
branches[pc].setTarget(branchDestHandles[t]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -811,18 +876,21 @@ public class JavaBuilder {
|
|||||||
dup();
|
dup();
|
||||||
append(new PUSH(cp, index0+i));
|
append(new PUSH(cp, index0+i));
|
||||||
loadLocal(pc, a0+i);
|
loadLocal(pc, a0+i);
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "rawset", Type.VOID, ARG_TYPES_INT_LUAVALUE, Constants.INVOKEVIRTUAL));
|
append(factory.createInvoke(STR_LUAVALUE, "rawset", Type.VOID, ARG_TYPES_INT_LUAVALUE,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setlistVarargs(int index0, int vresultbase) {
|
public void setlistVarargs(int index0, int vresultbase) {
|
||||||
append(new PUSH(cp, index0));
|
append(new PUSH(cp, index0));
|
||||||
loadVarresult();
|
loadVarresult();
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "rawsetlist", Type.VOID, ARG_TYPES_INT_VARARGS, Constants.INVOKEVIRTUAL));
|
append(factory.createInvoke(STR_LUAVALUE, "rawsetlist", Type.VOID, ARG_TYPES_INT_VARARGS,
|
||||||
|
Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void concatvalue() {
|
public void concatvalue() {
|
||||||
append(factory.createInvoke(STR_LUAVALUE, "concat", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
|
append(
|
||||||
|
factory.createInvoke(STR_LUAVALUE, "concat", TYPE_LUAVALUE, ARG_TYPES_LUAVALUE, Constants.INVOKEVIRTUAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void concatbuffer() {
|
public void concatbuffer() {
|
||||||
|
|||||||
@@ -27,9 +27,7 @@ import org.luaj.vm2.Prototype;
|
|||||||
import org.luaj.vm2.Upvaldesc;
|
import org.luaj.vm2.Upvaldesc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO:
|
* TODO: propogate constants loader can find inner classes
|
||||||
* propogate constants
|
|
||||||
* loader can find inner classes
|
|
||||||
*/
|
*/
|
||||||
public class JavaGen {
|
public class JavaGen {
|
||||||
|
|
||||||
@@ -243,7 +241,10 @@ public class JavaGen {
|
|||||||
// load args
|
// load args
|
||||||
int narg = b-1;
|
int narg = b-1;
|
||||||
switch (narg) {
|
switch (narg) {
|
||||||
case 0: case 1: case 2: case 3:
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
for (int i = 1; i < b; i++)
|
for (int i = 1; i < b; i++)
|
||||||
builder.loadLocal(pc, a+i);
|
builder.loadLocal(pc, a+i);
|
||||||
break;
|
break;
|
||||||
@@ -319,10 +320,18 @@ public class JavaGen {
|
|||||||
builder.loadNone();
|
builder.loadNone();
|
||||||
} else {
|
} else {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case 0: loadVarargResults( builder, pc, a, vresultbase ); break;
|
case 0:
|
||||||
case 1: builder.loadNone(); break;
|
loadVarargResults(builder, pc, a, vresultbase);
|
||||||
case 2: builder.loadLocal(pc, a); break;
|
break;
|
||||||
default: builder.newVarargs(pc, a, b-1); break;
|
case 1:
|
||||||
|
builder.loadNone();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
builder.loadLocal(pc, a);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
builder.newVarargs(pc, a, b-1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.areturn();
|
builder.areturn();
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import org.luaj.vm2.Prototype;
|
|||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* 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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* THE SOFTWARE.
|
* SOFTWARE.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
public class JavaLoader extends ClassLoader {
|
public class JavaLoader extends ClassLoader {
|
||||||
|
|
||||||
|
|||||||
@@ -38,20 +38,22 @@ import org.luaj.vm2.compiler.LuaC;
|
|||||||
* lua-to-java-bytecode compiling.
|
* lua-to-java-bytecode compiling.
|
||||||
* <p>
|
* <p>
|
||||||
* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
|
* By default, when using {@link org.luaj.vm2.lib.jse.JsePlatform} or
|
||||||
* {@link org.luaj.vm2.lib.jme.JmePlatform}
|
* {@link org.luaj.vm2.lib.jme.JmePlatform} to construct globals, the plain
|
||||||
* to construct globals, the plain compiler {@link LuaC} is installed and lua code
|
* compiler {@link LuaC} is installed and lua code will only be compiled into
|
||||||
* will only be compiled into lua bytecode and execute as {@link LuaClosure}.
|
* lua bytecode and execute as {@link LuaClosure}.
|
||||||
* <p>
|
* <p>
|
||||||
* To override the default compiling behavior with {@link LuaJC}
|
* To override the default compiling behavior with {@link LuaJC} lua-to-java
|
||||||
* lua-to-java bytecode compiler, install it before undumping code,
|
* bytecode compiler, install it before undumping code, for example:
|
||||||
* for example:
|
*
|
||||||
* <pre> {@code
|
* <pre>
|
||||||
|
* {@code
|
||||||
* LuaValue globals = JsePlatform.standardGlobals();
|
* LuaValue globals = JsePlatform.standardGlobals();
|
||||||
* LuaJC.install(globals);
|
* LuaJC.install(globals);
|
||||||
* LuaValue chunk = globals.load( "print('hello, world'), "main.lua");
|
* LuaValue chunk = globals.load( "print('hello, world'), "main.lua");
|
||||||
* System.out.println(chunk.isclosure()); // Will be false when LuaJC is working.
|
* System.out.println(chunk.isclosure()); // Will be false when LuaJC is working.
|
||||||
* chunk.call();
|
* chunk.call();
|
||||||
* } </pre>
|
* }
|
||||||
|
* </pre>
|
||||||
* <p>
|
* <p>
|
||||||
* This requires the bcel library to be on the class path to work as expected.
|
* This requires the bcel library to be on the class path to work as expected.
|
||||||
* If the library is not found, the default {@link LuaC} lua-to-lua-bytecode
|
* If the library is not found, the default {@link LuaC} lua-to-lua-bytecode
|
||||||
@@ -67,8 +69,8 @@ public class LuaJC implements Globals.Loader {
|
|||||||
public static final LuaJC instance = new LuaJC();
|
public static final LuaJC instance = new LuaJC();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install the compiler as the main Globals.Loader to use in a set of globals.
|
* Install the compiler as the main Globals.Loader to use in a set of
|
||||||
* Will fall back to the LuaC prototype compiler.
|
* globals. Will fall back to the LuaC prototype compiler.
|
||||||
*/
|
*/
|
||||||
public static final void install(Globals G) {
|
public static final void install(Globals G) {
|
||||||
G.loader = instance;
|
G.loader = instance;
|
||||||
@@ -76,19 +78,22 @@ public class LuaJC implements Globals.Loader {
|
|||||||
|
|
||||||
protected LuaJC() {}
|
protected LuaJC() {}
|
||||||
|
|
||||||
public Hashtable compileAll(InputStream script, String chunkname, String filename, Globals globals, boolean genmain) throws IOException {
|
public Hashtable compileAll(InputStream script, String chunkname, String filename, Globals globals, boolean genmain)
|
||||||
|
throws IOException {
|
||||||
final String classname = toStandardJavaClassName(chunkname);
|
final String classname = toStandardJavaClassName(chunkname);
|
||||||
final Prototype p = globals.loadPrototype(script, classname, "bt");
|
final Prototype p = globals.loadPrototype(script, classname, "bt");
|
||||||
return compileProtoAndSubProtos(p, classname, filename, genmain);
|
return compileProtoAndSubProtos(p, classname, filename, genmain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hashtable compileAll(Reader script, String chunkname, String filename, Globals globals, boolean genmain) throws IOException {
|
public Hashtable compileAll(Reader script, String chunkname, String filename, Globals globals, boolean genmain)
|
||||||
|
throws IOException {
|
||||||
final String classname = toStandardJavaClassName(chunkname);
|
final String classname = toStandardJavaClassName(chunkname);
|
||||||
final Prototype p = globals.compilePrototype(script, classname);
|
final Prototype p = globals.compilePrototype(script, classname);
|
||||||
return compileProtoAndSubProtos(p, classname, filename, genmain);
|
return compileProtoAndSubProtos(p, classname, filename, genmain);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Hashtable compileProtoAndSubProtos(Prototype p, String classname, String filename, boolean genmain) throws IOException {
|
private Hashtable compileProtoAndSubProtos(Prototype p, String classname, String filename, boolean genmain)
|
||||||
|
throws IOException {
|
||||||
final String luaname = toStandardLuaFileName(filename);
|
final String luaname = toStandardLuaFileName(filename);
|
||||||
final Hashtable h = new Hashtable();
|
final Hashtable h = new Hashtable();
|
||||||
final JavaGen gen = new JavaGen(p, classname, luaname, genmain);
|
final JavaGen gen = new JavaGen(p, classname, luaname, genmain);
|
||||||
@@ -114,7 +119,9 @@ public class LuaJC implements Globals.Loader {
|
|||||||
StringBuffer classname = new StringBuffer();
|
StringBuffer classname = new StringBuffer();
|
||||||
for (int i = 0, n = stub.length(); i < n; ++i) {
|
for (int i = 0, n = stub.length(); i < n; ++i) {
|
||||||
final char c = stub.charAt(i);
|
final char c = stub.charAt(i);
|
||||||
classname.append((((i == 0) && Character.isJavaIdentifierStart(c)) || ((i > 0) && Character.isJavaIdentifierPart(c)))? c: '_');
|
classname.append(
|
||||||
|
(((i == 0) && Character.isJavaIdentifierStart(c)) || ((i > 0) && Character.isJavaIdentifierPart(c)))? c
|
||||||
|
: '_');
|
||||||
}
|
}
|
||||||
return classname.toString();
|
return classname.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ public class ProtoInfo {
|
|||||||
sb.append(" ");
|
sb.append(" ");
|
||||||
for (int j = 0; j < prototype.maxstacksize; j++) {
|
for (int j = 0; j < prototype.maxstacksize; j++) {
|
||||||
VarInfo v = vars[j][pc];
|
VarInfo v = vars[j][pc];
|
||||||
String u = (v==null? "": v.upvalue!=null? !v.upvalue.rw? "[C] ": (v.allocupvalue&&v.pc==pc? "[*] ": "[] "): " ");
|
String u = (v == null? ""
|
||||||
|
: v.upvalue != null? !v.upvalue.rw? "[C] ": (v.allocupvalue && v.pc == pc? "[*] ": "[] ")
|
||||||
|
: " ");
|
||||||
String s = v == null? "null ": String.valueOf(v);
|
String s = v == null? "null ": String.valueOf(v);
|
||||||
sb.append(s+u);
|
sb.append(s+u);
|
||||||
}
|
}
|
||||||
@@ -194,8 +196,10 @@ public class ProtoInfo {
|
|||||||
a = Lua.GETARG_A(ins);
|
a = Lua.GETARG_A(ins);
|
||||||
b = Lua.GETARG_B(ins);
|
b = Lua.GETARG_B(ins);
|
||||||
c = Lua.GETARG_C(ins);
|
c = Lua.GETARG_C(ins);
|
||||||
if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
|
if (!Lua.ISK(b))
|
||||||
if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
|
v[b][pc].isreferenced = true;
|
||||||
|
if (!Lua.ISK(c))
|
||||||
|
v[c][pc].isreferenced = true;
|
||||||
v[a][pc] = new VarInfo(a, pc);
|
v[a][pc] = new VarInfo(a, pc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -204,15 +208,19 @@ public class ProtoInfo {
|
|||||||
b = Lua.GETARG_B(ins);
|
b = Lua.GETARG_B(ins);
|
||||||
c = Lua.GETARG_C(ins);
|
c = Lua.GETARG_C(ins);
|
||||||
v[a][pc].isreferenced = true;
|
v[a][pc].isreferenced = true;
|
||||||
if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
|
if (!Lua.ISK(b))
|
||||||
if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
|
v[b][pc].isreferenced = true;
|
||||||
|
if (!Lua.ISK(c))
|
||||||
|
v[c][pc].isreferenced = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
|
case Lua.OP_SETTABUP: /* A B C UpValue[A][RK(B)] := RK(C) */
|
||||||
b = Lua.GETARG_B(ins);
|
b = Lua.GETARG_B(ins);
|
||||||
c = Lua.GETARG_C(ins);
|
c = Lua.GETARG_C(ins);
|
||||||
if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
|
if (!Lua.ISK(b))
|
||||||
if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
|
v[b][pc].isreferenced = true;
|
||||||
|
if (!Lua.ISK(c))
|
||||||
|
v[c][pc].isreferenced = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Lua.OP_CONCAT: /* A B C R(A) := R(B).. ... ..R(C) */
|
case Lua.OP_CONCAT: /* A B C R(A) := R(B).. ... ..R(C) */
|
||||||
@@ -235,14 +243,16 @@ public class ProtoInfo {
|
|||||||
b = Lua.GETARG_B(ins);
|
b = Lua.GETARG_B(ins);
|
||||||
c = Lua.GETARG_C(ins);
|
c = Lua.GETARG_C(ins);
|
||||||
v[b][pc].isreferenced = true;
|
v[b][pc].isreferenced = true;
|
||||||
if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
|
if (!Lua.ISK(c))
|
||||||
|
v[c][pc].isreferenced = true;
|
||||||
v[a][pc] = new VarInfo(a, pc);
|
v[a][pc] = new VarInfo(a, pc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
|
case Lua.OP_GETTABUP: /* A B C R(A) := UpValue[B][RK(C)] */
|
||||||
a = Lua.GETARG_A(ins);
|
a = Lua.GETARG_A(ins);
|
||||||
c = Lua.GETARG_C(ins);
|
c = Lua.GETARG_C(ins);
|
||||||
if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
|
if (!Lua.ISK(c))
|
||||||
|
v[c][pc].isreferenced = true;
|
||||||
v[a][pc] = new VarInfo(a, pc);
|
v[a][pc] = new VarInfo(a, pc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -251,7 +261,8 @@ public class ProtoInfo {
|
|||||||
b = Lua.GETARG_B(ins);
|
b = Lua.GETARG_B(ins);
|
||||||
c = Lua.GETARG_C(ins);
|
c = Lua.GETARG_C(ins);
|
||||||
v[b][pc].isreferenced = true;
|
v[b][pc].isreferenced = true;
|
||||||
if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
|
if (!Lua.ISK(c))
|
||||||
|
v[c][pc].isreferenced = true;
|
||||||
v[a][pc] = new VarInfo(a, pc);
|
v[a][pc] = new VarInfo(a, pc);
|
||||||
v[a+1][pc] = new VarInfo(a+1, pc);
|
v[a+1][pc] = new VarInfo(a+1, pc);
|
||||||
break;
|
break;
|
||||||
@@ -361,8 +372,10 @@ public class ProtoInfo {
|
|||||||
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
case Lua.OP_LE: /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */
|
||||||
b = Lua.GETARG_B(ins);
|
b = Lua.GETARG_B(ins);
|
||||||
c = Lua.GETARG_C(ins);
|
c = Lua.GETARG_C(ins);
|
||||||
if (!Lua.ISK(b)) v[b][pc].isreferenced = true;
|
if (!Lua.ISK(b))
|
||||||
if (!Lua.ISK(c)) v[c][pc].isreferenced = true;
|
v[b][pc].isreferenced = true;
|
||||||
|
if (!Lua.ISK(c))
|
||||||
|
v[c][pc].isreferenced = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Lua.OP_JMP: /* sBx pc+=sBx */
|
case Lua.OP_JMP: /* sBx pc+=sBx */
|
||||||
@@ -434,6 +447,7 @@ public class ProtoInfo {
|
|||||||
upvals[Lua.GETARG_B(code[pc])].rw = true;
|
upvals[Lua.GETARG_B(code[pc])].rw = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UpvalInfo findOpenUp(int pc, int slot) {
|
private UpvalInfo findOpenUp(int pc, int slot) {
|
||||||
if (openups[slot] == null)
|
if (openups[slot] == null)
|
||||||
openups[slot] = new UpvalInfo[prototype.code.length];
|
openups[slot] = new UpvalInfo[prototype.code.length];
|
||||||
|
|||||||
@@ -41,11 +41,13 @@ public class VarInfo {
|
|||||||
return slot < 0? "x.x": (slot + "." + pc);
|
return slot < 0? "x.x": (slot + "." + pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return replacement variable if there is exactly one value possible,
|
/**
|
||||||
|
* Return replacement variable if there is exactly one value possible,
|
||||||
* otherwise compute entire collection of variables and return null.
|
* otherwise compute entire collection of variables and return null.
|
||||||
* Computes the list of aall variable values, and saves it for the future.
|
* Computes the list of aall variable values, and saves it for the future.
|
||||||
*
|
*
|
||||||
* @return new Variable to replace with if there is only one value, or null to leave alone.
|
* @return new Variable to replace with if there is only one value, or null
|
||||||
|
* to leave alone.
|
||||||
*/
|
*/
|
||||||
public VarInfo resolvePhiVariableValues() {
|
public VarInfo resolvePhiVariableValues() {
|
||||||
return null;
|
return null;
|
||||||
@@ -55,9 +57,7 @@ public class VarInfo {
|
|||||||
vars.add(this);
|
vars.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPhiVar() {
|
public boolean isPhiVar() { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ParamVarInfo extends VarInfo {
|
private static final class ParamVarInfo extends VarInfo {
|
||||||
private ParamVarInfo(int slot, int pc) {
|
private ParamVarInfo(int slot, int pc) {
|
||||||
@@ -88,9 +88,7 @@ public class VarInfo {
|
|||||||
this.pi = pi;
|
this.pi = pi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPhiVar() {
|
public boolean isPhiVar() { return true; }
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuffer sb = new StringBuffer();
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ import org.luaj.vm2.lib.jse.CoerceJavaToLua;
|
|||||||
* <p>
|
* <p>
|
||||||
* This engine requires the types of the Bindings and ScriptContext to be
|
* This engine requires the types of the Bindings and ScriptContext to be
|
||||||
* compatible with the engine. For creating new client context use
|
* compatible with the engine. For creating new client context use
|
||||||
* ScriptEngine.createContext() which will return {@link LuajContext},
|
* ScriptEngine.createContext() which will return {@link LuajContext}, and for
|
||||||
* and for client bindings use the default engine scoped bindings or
|
* client bindings use the default engine scoped bindings or construct a
|
||||||
* construct a {@link LuajBindings} directly.
|
* {@link LuajBindings} directly.
|
||||||
*/
|
*/
|
||||||
public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngine, Compilable {
|
public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngine, Compilable {
|
||||||
|
|
||||||
@@ -116,34 +116,28 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object eval(String script, ScriptContext context)
|
public Object eval(String script, ScriptContext context) throws ScriptException {
|
||||||
throws ScriptException {
|
|
||||||
return eval(new StringReader(script), context);
|
return eval(new StringReader(script), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object eval(Reader reader, ScriptContext context)
|
public Object eval(Reader reader, ScriptContext context) throws ScriptException {
|
||||||
throws ScriptException {
|
|
||||||
return compile(reader).eval(context);
|
return compile(reader).eval(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScriptEngineFactory getFactory() {
|
public ScriptEngineFactory getFactory() { return myFactory; }
|
||||||
return myFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class LuajCompiledScript extends CompiledScript {
|
class LuajCompiledScript extends CompiledScript {
|
||||||
final LuaFunction function;
|
final LuaFunction function;
|
||||||
final Globals compiling_globals;
|
final Globals compiling_globals;
|
||||||
|
|
||||||
LuajCompiledScript(LuaFunction function, Globals compiling_globals) {
|
LuajCompiledScript(LuaFunction function, Globals compiling_globals) {
|
||||||
this.function = function;
|
this.function = function;
|
||||||
this.compiling_globals = compiling_globals;
|
this.compiling_globals = compiling_globals;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptEngine getEngine() {
|
public ScriptEngine getEngine() { return LuaScriptEngine.this; }
|
||||||
return LuaScriptEngine.this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object eval() throws ScriptException {
|
public Object eval() throws ScriptException {
|
||||||
return eval(getContext());
|
return eval(getContext());
|
||||||
@@ -233,28 +227,33 @@ public class LuaScriptEngine extends AbstractScriptEngine implements ScriptEngin
|
|||||||
}
|
}
|
||||||
|
|
||||||
static private LuaValue toLua(Object javaValue) {
|
static private LuaValue toLua(Object javaValue) {
|
||||||
return javaValue == null? LuaValue.NIL:
|
return javaValue == null? LuaValue.NIL
|
||||||
javaValue instanceof LuaValue? (LuaValue) javaValue:
|
: javaValue instanceof LuaValue? (LuaValue) javaValue: CoerceJavaToLua.coerce(javaValue);
|
||||||
CoerceJavaToLua.coerce(javaValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static private Object toJava(LuaValue luajValue) {
|
static private Object toJava(LuaValue luajValue) {
|
||||||
switch (luajValue.type()) {
|
switch (luajValue.type()) {
|
||||||
case LuaValue.TNIL: return null;
|
case LuaValue.TNIL:
|
||||||
case LuaValue.TSTRING: return luajValue.tojstring();
|
return null;
|
||||||
case LuaValue.TUSERDATA: return luajValue.checkuserdata(Object.class);
|
case LuaValue.TSTRING:
|
||||||
case LuaValue.TNUMBER: return luajValue.isinttype()?
|
return luajValue.tojstring();
|
||||||
(Object) new Integer(luajValue.toint()):
|
case LuaValue.TUSERDATA:
|
||||||
(Object) new Double(luajValue.todouble());
|
return luajValue.checkuserdata(Object.class);
|
||||||
default: return luajValue;
|
case LuaValue.TNUMBER:
|
||||||
|
return luajValue.isinttype()? (Object) new Integer(luajValue.toint())
|
||||||
|
: (Object) new Double(luajValue.todouble());
|
||||||
|
default:
|
||||||
|
return luajValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static private Object toJava(Varargs v) {
|
static private Object toJava(Varargs v) {
|
||||||
final int n = v.narg();
|
final int n = v.narg();
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case 0: return null;
|
case 0:
|
||||||
case 1: return toJava(v.arg1());
|
return null;
|
||||||
|
case 1:
|
||||||
|
return toJava(v.arg1());
|
||||||
default:
|
default:
|
||||||
Object[] o = new Object[n];
|
Object[] o = new Object[n];
|
||||||
for (int i = 0; i < n; ++i)
|
for (int i = 0; i < n; ++i)
|
||||||
|
|||||||
@@ -30,25 +30,16 @@ import javax.script.ScriptEngineFactory;
|
|||||||
/**
|
/**
|
||||||
* Jsr 223 scripting engine factory.
|
* Jsr 223 scripting engine factory.
|
||||||
*
|
*
|
||||||
* Exposes metadata to support the lua language, and constructs
|
* Exposes metadata to support the lua language, and constructs instances of
|
||||||
* instances of LuaScriptEngine to handl lua scripts.
|
* LuaScriptEngine to handl lua scripts.
|
||||||
*/
|
*/
|
||||||
public class LuaScriptEngineFactory implements ScriptEngineFactory {
|
public class LuaScriptEngineFactory implements ScriptEngineFactory {
|
||||||
|
|
||||||
private static final String [] EXTENSIONS = {
|
private static final String[] EXTENSIONS = { "lua", ".lua", };
|
||||||
"lua",
|
|
||||||
".lua",
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final String [] MIMETYPES = {
|
private static final String[] MIMETYPES = { "text/lua", "application/lua" };
|
||||||
"text/lua",
|
|
||||||
"application/lua"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final String [] NAMES = {
|
private static final String[] NAMES = { "lua", "luaj", };
|
||||||
"lua",
|
|
||||||
"luaj",
|
|
||||||
};
|
|
||||||
|
|
||||||
private List<String> extensions;
|
private List<String> extensions;
|
||||||
private List<String> mimeTypes;
|
private List<String> mimeTypes;
|
||||||
@@ -60,33 +51,19 @@ public class LuaScriptEngineFactory implements ScriptEngineFactory {
|
|||||||
names = Arrays.asList(NAMES);
|
names = Arrays.asList(NAMES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getEngineName() {
|
public String getEngineName() { return getScriptEngine().get(ScriptEngine.ENGINE).toString(); }
|
||||||
return getScriptEngine().get(ScriptEngine.ENGINE).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getEngineVersion() {
|
public String getEngineVersion() { return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString(); }
|
||||||
return getScriptEngine().get(ScriptEngine.ENGINE_VERSION).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getExtensions() {
|
public List<String> getExtensions() { return extensions; }
|
||||||
return extensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getMimeTypes() {
|
public List<String> getMimeTypes() { return mimeTypes; }
|
||||||
return mimeTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getNames() {
|
public List<String> getNames() { return names; }
|
||||||
return names;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLanguageName() {
|
public String getLanguageName() { return getScriptEngine().get(ScriptEngine.LANGUAGE).toString(); }
|
||||||
return getScriptEngine().get(ScriptEngine.LANGUAGE).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLanguageVersion() {
|
public String getLanguageVersion() { return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString(); }
|
||||||
return getScriptEngine().get(ScriptEngine.LANGUAGE_VERSION).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getParameter(String key) {
|
public Object getParameter(String key) {
|
||||||
return getScriptEngine().get(key).toString();
|
return getScriptEngine().get(key).toString();
|
||||||
@@ -122,7 +99,5 @@ public class LuaScriptEngineFactory implements ScriptEngineFactory {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptEngine getScriptEngine() {
|
public ScriptEngine getScriptEngine() { return new LuaScriptEngine(); }
|
||||||
return new LuaScriptEngine();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ import org.luaj.vm2.lib.jse.JsePlatform;
|
|||||||
import org.luaj.vm2.luajc.LuaJC;
|
import org.luaj.vm2.luajc.LuaJC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context for LuaScriptEngine execution which maintains its own Globals,
|
* Context for LuaScriptEngine execution which maintains its own Globals, and
|
||||||
* and manages the input and output redirection.
|
* manages the input and output redirection.
|
||||||
*/
|
*/
|
||||||
public class LuajContext extends SimpleScriptContext implements ScriptContext {
|
public class LuajContext extends SimpleScriptContext implements ScriptContext {
|
||||||
|
|
||||||
@@ -51,37 +51,34 @@ public class LuajContext extends SimpleScriptContext implements ScriptContext {
|
|||||||
/** The initial value of globals.STDERR */
|
/** The initial value of globals.STDERR */
|
||||||
private final PrintStream stderr;
|
private final PrintStream stderr;
|
||||||
|
|
||||||
/** Construct a LuajContext with its own globals which may
|
/**
|
||||||
* be debug globals depending on the value of the system
|
* Construct a LuajContext with its own globals which may be debug globals
|
||||||
* property 'org.luaj.debug'
|
* depending on the value of the system property 'org.luaj.debug'
|
||||||
* <p>
|
* <p>
|
||||||
* If the system property 'org.luaj.debug' is set, the globals
|
* If the system property 'org.luaj.debug' is set, the globals created will
|
||||||
* created will be a debug globals that includes the debug
|
* be a debug globals that includes the debug library. This may provide
|
||||||
* library. This may provide better stack traces, but may
|
* better stack traces, but may have negative impact on performance.
|
||||||
* have negative impact on performance.
|
|
||||||
*/
|
*/
|
||||||
public LuajContext() {
|
public LuajContext() {
|
||||||
this("true".equals(System.getProperty("org.luaj.debug")),
|
this("true".equals(System.getProperty("org.luaj.debug")), "true".equals(System.getProperty("org.luaj.luajc")));
|
||||||
"true".equals(System.getProperty("org.luaj.luajc")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Construct a LuajContext with its own globals, which
|
/**
|
||||||
* which optionally are debug globals, and optionally use the
|
* Construct a LuajContext with its own globals, which which optionally are
|
||||||
* luajc direct lua to java bytecode compiler.
|
* debug globals, and optionally use the luajc direct lua to java bytecode
|
||||||
|
* compiler.
|
||||||
* <p>
|
* <p>
|
||||||
* If createDebugGlobals is set, the globals
|
* If createDebugGlobals is set, the globals created will be a debug globals
|
||||||
* created will be a debug globals that includes the debug
|
* that includes the debug library. This may provide better stack traces,
|
||||||
* library. This may provide better stack traces, but may
|
* but may have negative impact on performance.
|
||||||
* have negative impact on performance.
|
*
|
||||||
* @param createDebugGlobals true to create debug globals,
|
* @param createDebugGlobals true to create debug globals, false for
|
||||||
* false for standard globals.
|
* standard globals.
|
||||||
* @param useLuaJCCompiler true to use the luajc compiler,
|
* @param useLuaJCCompiler true to use the luajc compiler, reqwuires bcel
|
||||||
* reqwuires bcel to be on the class path.
|
* to be on the class path.
|
||||||
*/
|
*/
|
||||||
public LuajContext(boolean createDebugGlobals, boolean useLuaJCCompiler) {
|
public LuajContext(boolean createDebugGlobals, boolean useLuaJCCompiler) {
|
||||||
globals = createDebugGlobals?
|
globals = createDebugGlobals? JsePlatform.debugGlobals(): JsePlatform.standardGlobals();
|
||||||
JsePlatform.debugGlobals():
|
|
||||||
JsePlatform.standardGlobals();
|
|
||||||
if (useLuaJCCompiler)
|
if (useLuaJCCompiler)
|
||||||
LuaJC.install(globals);
|
LuaJC.install(globals);
|
||||||
stdin = globals.STDIN;
|
stdin = globals.STDIN;
|
||||||
@@ -91,42 +88,40 @@ public class LuajContext extends SimpleScriptContext implements ScriptContext {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setErrorWriter(Writer writer) {
|
public void setErrorWriter(Writer writer) {
|
||||||
globals.STDERR = writer != null?
|
globals.STDERR = writer != null? new PrintStream(new WriterOutputStream(writer)): stderr;
|
||||||
new PrintStream(new WriterOutputStream(writer)):
|
|
||||||
stderr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setReader(Reader reader) {
|
public void setReader(Reader reader) { globals.STDIN = reader != null? new ReaderInputStream(reader): stdin; }
|
||||||
globals.STDIN = reader != null?
|
|
||||||
new ReaderInputStream(reader):
|
|
||||||
stdin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWriter(Writer writer) {
|
public void setWriter(Writer writer) {
|
||||||
globals.STDOUT = writer != null?
|
globals.STDOUT = writer != null? new PrintStream(new WriterOutputStream(writer), true): stdout;
|
||||||
new PrintStream(new WriterOutputStream(writer), true):
|
|
||||||
stdout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class WriterOutputStream extends OutputStream {
|
static final class WriterOutputStream extends OutputStream {
|
||||||
final Writer w;
|
final Writer w;
|
||||||
|
|
||||||
WriterOutputStream(Writer w) {
|
WriterOutputStream(Writer w) {
|
||||||
this.w = w;
|
this.w = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
w.write(new String(new byte[] { (byte) b }));
|
w.write(new String(new byte[] { (byte) b }));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(byte[] b, int o, int l) throws IOException {
|
public void write(byte[] b, int o, int l) throws IOException {
|
||||||
w.write(new String(b, o, l));
|
w.write(new String(b, o, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(byte[] b) throws IOException {
|
public void write(byte[] b) throws IOException {
|
||||||
w.write(new String(b));
|
w.write(new String(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
w.close();
|
w.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() throws IOException {
|
public void flush() throws IOException {
|
||||||
w.flush();
|
w.flush();
|
||||||
}
|
}
|
||||||
@@ -134,9 +129,11 @@ public class LuajContext extends SimpleScriptContext implements ScriptContext {
|
|||||||
|
|
||||||
static final class ReaderInputStream extends InputStream {
|
static final class ReaderInputStream extends InputStream {
|
||||||
final Reader r;
|
final Reader r;
|
||||||
|
|
||||||
ReaderInputStream(Reader r) {
|
ReaderInputStream(Reader r) {
|
||||||
this.r = r;
|
this.r = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
return r.read();
|
return r.read();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ import org.luaj.vm2.lib.jse.CoerceJavaToLua;
|
|||||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default {@link Launcher} instance that creates standard globals
|
* Default {@link Launcher} instance that creates standard globals and runs the
|
||||||
* and runs the supplied scripts with chunk name 'main'.
|
* supplied scripts with chunk name 'main'.
|
||||||
* <P>
|
* <P>
|
||||||
* Arguments are coerced into lua using {@link CoerceJavaToLua#coerce(Object)}.
|
* Arguments are coerced into lua using {@link CoerceJavaToLua#coerce(Object)}.
|
||||||
* <P>
|
* <P>
|
||||||
* Return values with simple types are coerced into Java simple types.
|
* Return values with simple types are coerced into Java simple types. Tables,
|
||||||
* Tables, threads, and functions are returned as lua objects.
|
* threads, and functions are returned as lua objects.
|
||||||
*
|
*
|
||||||
* @see Launcher
|
* @see Launcher
|
||||||
* @see LuajClassLoader
|
* @see LuajClassLoader
|
||||||
@@ -57,7 +57,9 @@ public class DefaultLauncher implements Launcher {
|
|||||||
return launchChunk(g.load(script, "main"), arg);
|
return launchChunk(g.load(script, "main"), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Launches the script with chunk name 'main' and loading using modes 'bt' */
|
/**
|
||||||
|
* Launches the script with chunk name 'main' and loading using modes 'bt'
|
||||||
|
*/
|
||||||
public Object[] launch(InputStream script, Object[] arg) {
|
public Object[] launch(InputStream script, Object[] arg) {
|
||||||
return launchChunk(g.load(script, "main", "bt", g), arg);
|
return launchChunk(g.load(script, "main", "bt", g), arg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,15 +24,18 @@ package org.luaj.vm2.server;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
|
||||||
/** Interface to launch lua scripts using the {@link LuajClassLoader}.
|
/**
|
||||||
|
* Interface to launch lua scripts using the {@link LuajClassLoader}.
|
||||||
* <P>
|
* <P>
|
||||||
* <em>Note: This class is experimental and subject to change in future versions.</em>
|
* <em>Note: This class is experimental and subject to change in future
|
||||||
|
* versions.</em>
|
||||||
* <P>
|
* <P>
|
||||||
* This interface is purposely genericized to defer class loading so that
|
* This interface is purposely genericized to defer class loading so that luaj
|
||||||
* luaj classes can come from the class loader.
|
* classes can come from the class loader.
|
||||||
* <P>
|
* <P>
|
||||||
* The implementation should be acquired using {@link LuajClassLoader#NewLauncher()}
|
* The implementation should be acquired using
|
||||||
* or {@link LuajClassLoader#NewLauncher(Class)} which ensure that the classes are
|
* {@link LuajClassLoader#NewLauncher()} or
|
||||||
|
* {@link LuajClassLoader#NewLauncher(Class)} which ensure that the classes are
|
||||||
* loaded to give each Launcher instance a pristine set of Globals, including
|
* loaded to give each Launcher instance a pristine set of Globals, including
|
||||||
* the shared metatables.
|
* the shared metatables.
|
||||||
*
|
*
|
||||||
@@ -44,7 +47,8 @@ import java.io.Reader;
|
|||||||
*/
|
*/
|
||||||
public interface Launcher {
|
public interface Launcher {
|
||||||
|
|
||||||
/** Launch a script contained in a String.
|
/**
|
||||||
|
* Launch a script contained in a String.
|
||||||
*
|
*
|
||||||
* @param script The script contents.
|
* @param script The script contents.
|
||||||
* @param arg Optional arguments supplied to the script.
|
* @param arg Optional arguments supplied to the script.
|
||||||
@@ -52,7 +56,8 @@ public interface Launcher {
|
|||||||
*/
|
*/
|
||||||
public Object[] launch(String script, Object[] arg);
|
public Object[] launch(String script, Object[] arg);
|
||||||
|
|
||||||
/** Launch a script from an InputStream.
|
/**
|
||||||
|
* Launch a script from an InputStream.
|
||||||
*
|
*
|
||||||
* @param script The script as an InputStream.
|
* @param script The script as an InputStream.
|
||||||
* @param arg Optional arguments supplied to the script.
|
* @param arg Optional arguments supplied to the script.
|
||||||
@@ -60,7 +65,8 @@ public interface Launcher {
|
|||||||
*/
|
*/
|
||||||
public Object[] launch(InputStream script, Object[] arg);
|
public Object[] launch(InputStream script, Object[] arg);
|
||||||
|
|
||||||
/** Launch a script from a Reader.
|
/**
|
||||||
|
* Launch a script from a Reader.
|
||||||
*
|
*
|
||||||
* @param script The script as a Reader.
|
* @param script The script as a Reader.
|
||||||
* @param arg Optional arguments supplied to the script.
|
* @param arg Optional arguments supplied to the script.
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ import java.util.Map;
|
|||||||
* Class loader that can be used to launch a lua script in a Java VM that has a
|
* Class loader that can be used to launch a lua script in a Java VM that has a
|
||||||
* unique set of classes for org.luaj classes.
|
* unique set of classes for org.luaj classes.
|
||||||
* <P>
|
* <P>
|
||||||
* <em>Note: This class is experimental and subject to change in future versions.</em>
|
* <em>Note: This class is experimental and subject to change in future
|
||||||
|
* versions.</em>
|
||||||
* <P>
|
* <P>
|
||||||
* By using a custom class loader per script, it allows the script to have
|
* By using a custom class loader per script, it allows the script to have its
|
||||||
* its own set of globals, including static values such as shared metatables
|
* own set of globals, including static values such as shared metatables that
|
||||||
* that cannot access lua values from other scripts because their classes are
|
* cannot access lua values from other scripts because their classes are loaded
|
||||||
* loaded from different class loaders. Thus normally unsafe libraries such
|
* from different class loaders. Thus normally unsafe libraries such as luajava
|
||||||
* as luajava can be exposed to scripts in a server environment using these
|
* can be exposed to scripts in a server environment using these techniques.
|
||||||
* techniques.
|
|
||||||
* <P>
|
* <P>
|
||||||
* All classes in the package "org.luaj.vm2." are considered user classes, and
|
* All classes in the package "org.luaj.vm2." are considered user classes, and
|
||||||
* loaded into this class loader from their bytes in the class path. Other
|
* loaded into this class loader from their bytes in the class path. Other
|
||||||
@@ -61,10 +61,14 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class LuajClassLoader extends ClassLoader {
|
public class LuajClassLoader extends ClassLoader {
|
||||||
|
|
||||||
/** String describing the luaj packages to consider part of the user classes */
|
/**
|
||||||
|
* String describing the luaj packages to consider part of the user classes
|
||||||
|
*/
|
||||||
static final String luajPackageRoot = "org.luaj.vm2.";
|
static final String luajPackageRoot = "org.luaj.vm2.";
|
||||||
|
|
||||||
/** String describing the Launcher interface to be considered a system class */
|
/**
|
||||||
|
* String describing the Launcher interface to be considered a system class
|
||||||
|
*/
|
||||||
static final String launcherInterfaceRoot = Launcher.class.getName();
|
static final String launcherInterfaceRoot = Launcher.class.getName();
|
||||||
|
|
||||||
/** Local cache of classes loaded by this loader. */
|
/** Local cache of classes loaded by this loader. */
|
||||||
@@ -75,54 +79,52 @@ public class LuajClassLoader extends ClassLoader {
|
|||||||
* its own {@link LuajClassLoader} using the default implementation class
|
* its own {@link LuajClassLoader} using the default implementation class
|
||||||
* {@link DefaultLauncher}.
|
* {@link DefaultLauncher}.
|
||||||
* <P>
|
* <P>
|
||||||
* The {@link Launcher} that is returned will be a pristine luaj vm
|
* The {@link Launcher} that is returned will be a pristine luaj vm whose
|
||||||
* whose classes are loaded into this loader including static variables
|
* classes are loaded into this loader including static variables such as
|
||||||
* such as shared metatables, and should not be able to directly access
|
* shared metatables, and should not be able to directly access variables
|
||||||
* variables from other Launcher instances.
|
* from other Launcher instances.
|
||||||
*
|
*
|
||||||
* @return {@link Launcher} instance that can be used to launch scripts.
|
* @return {@link Launcher} instance that can be used to launch scripts.
|
||||||
* @throws InstantiationException
|
* @throws InstantiationException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws ClassNotFoundException
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
public static Launcher NewLauncher() throws InstantiationException,
|
public static Launcher NewLauncher() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||||
IllegalAccessException, ClassNotFoundException {
|
|
||||||
return NewLauncher(DefaultLauncher.class);
|
return NewLauncher(DefaultLauncher.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a {@link Launcher} instance that will load classes in
|
* Construct a {@link Launcher} instance that will load classes in its own
|
||||||
* its own {@link LuajClassLoader} using a user-supplied implementation class
|
* {@link LuajClassLoader} using a user-supplied implementation class that
|
||||||
* that implements {@link Launcher}.
|
* implements {@link Launcher}.
|
||||||
* <P>
|
* <P>
|
||||||
* The {@link Launcher} that is returned will be a pristine luaj vm
|
* The {@link Launcher} that is returned will be a pristine luaj vm whose
|
||||||
* whose classes are loaded into this loader including static variables
|
* classes are loaded into this loader including static variables such as
|
||||||
* such as shared metatables, and should not be able to directly access
|
* shared metatables, and should not be able to directly access variables
|
||||||
* variables from other Launcher instances.
|
* from other Launcher instances.
|
||||||
*
|
*
|
||||||
* @return instance of type 'launcher_class' that can be used to launch scripts.
|
* @return instance of type 'launcher_class' that can be used to launch
|
||||||
|
* scripts.
|
||||||
* @throws InstantiationException
|
* @throws InstantiationException
|
||||||
* @throws IllegalAccessException
|
* @throws IllegalAccessException
|
||||||
* @throws ClassNotFoundException
|
* @throws ClassNotFoundException
|
||||||
*/
|
*/
|
||||||
public static Launcher NewLauncher(Class<? extends Launcher> launcher_class)
|
public static Launcher NewLauncher(Class<? extends Launcher> launcher_class)
|
||||||
throws InstantiationException, IllegalAccessException,
|
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
|
||||||
ClassNotFoundException {
|
|
||||||
final LuajClassLoader loader = new LuajClassLoader();
|
final LuajClassLoader loader = new LuajClassLoader();
|
||||||
final Object instance = loader.loadAsUserClass(launcher_class.getName())
|
final Object instance = loader.loadAsUserClass(launcher_class.getName()).newInstance();
|
||||||
.newInstance();
|
|
||||||
return (Launcher) instance;
|
return (Launcher) instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if a class name should be considered a user class and loaded
|
* Test if a class name should be considered a user class and loaded by this
|
||||||
* by this loader, or a system class and loaded by the system loader.
|
* loader, or a system class and loaded by the system loader.
|
||||||
|
*
|
||||||
* @param classname Class name to test.
|
* @param classname Class name to test.
|
||||||
* @return true if this should be loaded into this class loader.
|
* @return true if this should be loaded into this class loader.
|
||||||
*/
|
*/
|
||||||
public static boolean isUserClass(String classname) {
|
public static boolean isUserClass(String classname) {
|
||||||
return classname.startsWith(luajPackageRoot)
|
return classname.startsWith(luajPackageRoot) && !classname.startsWith(launcherInterfaceRoot);
|
||||||
&& !classname.startsWith(launcherInterfaceRoot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> loadClass(String classname) throws ClassNotFoundException {
|
public Class<?> loadClass(String classname) throws ClassNotFoundException {
|
||||||
@@ -143,13 +145,11 @@ public class LuajClassLoader extends ClassLoader {
|
|||||||
for (int n = 0; (n = is.read(b)) >= 0;)
|
for (int n = 0; (n = is.read(b)) >= 0;)
|
||||||
baos.write(b, 0, n);
|
baos.write(b, 0, n);
|
||||||
byte[] bytes = baos.toByteArray();
|
byte[] bytes = baos.toByteArray();
|
||||||
Class<?> result = super.defineClass(classname, bytes, 0,
|
Class<?> result = super.defineClass(classname, bytes, 0, bytes.length);
|
||||||
bytes.length);
|
|
||||||
classes.put(classname, result);
|
classes.put(classname, result);
|
||||||
return result;
|
return result;
|
||||||
} catch (java.io.IOException e) {
|
} catch (java.io.IOException e) {
|
||||||
throw new ClassNotFoundException("Read failed: " + classname
|
throw new ClassNotFoundException("Read failed: " + classname + ": " + e);
|
||||||
+ ": " + e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new ClassNotFoundException("Not found: " + classname);
|
throw new ClassNotFoundException("Not found: " + classname);
|
||||||
|
|||||||
@@ -31,17 +31,9 @@ import org.luaj.vm2.lib.jse.JsePlatform;
|
|||||||
public class TestLuaJ {
|
public class TestLuaJ {
|
||||||
// create the script
|
// create the script
|
||||||
public static String name = "script";
|
public static String name = "script";
|
||||||
public static String script =
|
public static String script = "function r(q,...)\n" + " local a=arg\n" + " return a and a[2]\n" + "end\n"
|
||||||
"function r(q,...)\n"+
|
+ "function s(q,...)\n" + " local a=arg\n" + " local b=...\n" + " return a and a[2],b\n" + "end\n"
|
||||||
" local a=arg\n"+
|
+ "print( r(111,222,333),s(111,222,333) )";
|
||||||
" return a and a[2]\n"+
|
|
||||||
"end\n" +
|
|
||||||
"function s(q,...)\n"+
|
|
||||||
" local a=arg\n"+
|
|
||||||
" local b=...\n"+
|
|
||||||
" return a and a[2],b\n"+
|
|
||||||
"end\n" +
|
|
||||||
"print( r(111,222,333),s(111,222,333) )";
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
System.out.println(script);
|
System.out.println(script);
|
||||||
|
|||||||
@@ -87,11 +87,8 @@ public class TestLuaJC {
|
|||||||
String key = (String) e.nextElement();
|
String key = (String) e.nextElement();
|
||||||
byte[] bytes = (byte[]) t.get(key);
|
byte[] bytes = (byte[]) t.get(key);
|
||||||
String destpath = (destdir != null? destdir + "/": "") + key + ".class";
|
String destpath = (destdir != null? destdir + "/": "") + key + ".class";
|
||||||
System.out.println(
|
System.out.println("chunk " + filename + " from " + filename + " written to " + destpath + " length="
|
||||||
"chunk "+filename+
|
+ bytes.length + " bytes");
|
||||||
" from "+filename+
|
|
||||||
" written to "+destpath
|
|
||||||
+" length="+bytes.length+" bytes");
|
|
||||||
FileOutputStream fos = new FileOutputStream(destpath);
|
FileOutputStream fos = new FileOutputStream(destpath);
|
||||||
fos.write(bytes);
|
fos.write(bytes);
|
||||||
fos.close();
|
fos.close();
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import junit.framework.TestCase;
|
|||||||
|
|
||||||
import org.luaj.vm2.Globals.BufferedStream;
|
import org.luaj.vm2.Globals.BufferedStream;
|
||||||
|
|
||||||
|
|
||||||
public class BufferedStreamTest extends TestCase {
|
public class BufferedStreamTest extends TestCase {
|
||||||
|
|
||||||
public BufferedStreamTest() {}
|
public BufferedStreamTest() {}
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import org.luaj.vm2.luajc.LuaJC;
|
|||||||
/**
|
/**
|
||||||
* Compatibility tests for the Luaj VM
|
* Compatibility tests for the Luaj VM
|
||||||
*
|
*
|
||||||
* Results are compared for exact match with
|
* Results are compared for exact match with the installed C-based lua
|
||||||
* the installed C-based lua environment.
|
* environment.
|
||||||
*/
|
*/
|
||||||
public class CompatibiltyTest extends TestSuite {
|
public class CompatibiltyTest extends TestSuite {
|
||||||
|
|
||||||
@@ -37,6 +37,7 @@ public class CompatibiltyTest extends TestSuite {
|
|||||||
|
|
||||||
abstract protected static class CompatibiltyTestSuite extends ScriptDrivenTest {
|
abstract protected static class CompatibiltyTestSuite extends ScriptDrivenTest {
|
||||||
LuaValue savedStringMetatable;
|
LuaValue savedStringMetatable;
|
||||||
|
|
||||||
protected CompatibiltyTestSuite(PlatformType platform) {
|
protected CompatibiltyTestSuite(PlatformType platform) {
|
||||||
super(platform, dir);
|
super(platform, dir);
|
||||||
}
|
}
|
||||||
@@ -57,23 +58,36 @@ public class CompatibiltyTest extends TestSuite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testBaseLib() { runTest("baselib"); }
|
public void testBaseLib() { runTest("baselib"); }
|
||||||
|
|
||||||
public void testCoroutineLib() { runTest("coroutinelib"); }
|
public void testCoroutineLib() { runTest("coroutinelib"); }
|
||||||
|
|
||||||
public void testDebugLib() { runTest("debuglib"); }
|
public void testDebugLib() { runTest("debuglib"); }
|
||||||
|
|
||||||
public void testErrors() { runTest("errors"); }
|
public void testErrors() { runTest("errors"); }
|
||||||
|
|
||||||
public void testFunctions() { runTest("functions"); }
|
public void testFunctions() { runTest("functions"); }
|
||||||
|
|
||||||
public void testIoLib() { runTest("iolib"); }
|
public void testIoLib() { runTest("iolib"); }
|
||||||
|
|
||||||
public void testManyUpvals() { runTest("manyupvals"); }
|
public void testManyUpvals() { runTest("manyupvals"); }
|
||||||
|
|
||||||
public void testMathLib() { runTest("mathlib"); }
|
public void testMathLib() { runTest("mathlib"); }
|
||||||
|
|
||||||
public void testMetatags() { runTest("metatags"); }
|
public void testMetatags() { runTest("metatags"); }
|
||||||
|
|
||||||
public void testOsLib() { runTest("oslib"); }
|
public void testOsLib() { runTest("oslib"); }
|
||||||
|
|
||||||
public void testStringLib() { runTest("stringlib"); }
|
public void testStringLib() { runTest("stringlib"); }
|
||||||
|
|
||||||
public void testTableLib() { runTest("tablelib"); }
|
public void testTableLib() { runTest("tablelib"); }
|
||||||
|
|
||||||
public void testTailcalls() { runTest("tailcalls"); }
|
public void testTailcalls() { runTest("tailcalls"); }
|
||||||
|
|
||||||
public void testUpvalues() { runTest("upvalues"); }
|
public void testUpvalues() { runTest("upvalues"); }
|
||||||
|
|
||||||
public void testVm() { runTest("vm"); }
|
public void testVm() { runTest("vm"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static TestSuite suite() {
|
public static TestSuite suite() {
|
||||||
TestSuite suite = new TestSuite("Compatibility Tests");
|
TestSuite suite = new TestSuite("Compatibility Tests");
|
||||||
suite.addTest(new TestSuite(JseCompatibilityTest.class, "JSE Compatibility Tests"));
|
suite.addTest(new TestSuite(JseCompatibilityTest.class, "JSE Compatibility Tests"));
|
||||||
@@ -86,29 +100,35 @@ public class CompatibiltyTest extends TestSuite {
|
|||||||
public JmeCompatibilityTest() {
|
public JmeCompatibilityTest() {
|
||||||
super(ScriptDrivenTest.PlatformType.JME);
|
super(ScriptDrivenTest.PlatformType.JME);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
System.setProperty("JME", "true");
|
System.setProperty("JME", "true");
|
||||||
super.setUp();
|
super.setUp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class JseCompatibilityTest extends CompatibiltyTestSuite {
|
public static class JseCompatibilityTest extends CompatibiltyTestSuite {
|
||||||
public JseCompatibilityTest() {
|
public JseCompatibilityTest() {
|
||||||
super(ScriptDrivenTest.PlatformType.JSE);
|
super(ScriptDrivenTest.PlatformType.JSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
System.setProperty("JME", "false");
|
System.setProperty("JME", "false");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LuaJCCompatibilityTest extends CompatibiltyTestSuite {
|
public static class LuaJCCompatibilityTest extends CompatibiltyTestSuite {
|
||||||
public LuaJCCompatibilityTest() {
|
public LuaJCCompatibilityTest() {
|
||||||
super(ScriptDrivenTest.PlatformType.LUAJIT);
|
super(ScriptDrivenTest.PlatformType.LUAJIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
System.setProperty("JME", "false");
|
System.setProperty("JME", "false");
|
||||||
LuaJC.install(globals);
|
LuaJC.install(globals);
|
||||||
}
|
}
|
||||||
|
|
||||||
// not supported on this platform - don't test
|
// not supported on this platform - don't test
|
||||||
public void testDebugLib() {}
|
public void testDebugLib() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,12 +24,11 @@ package org.luaj.vm2;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test argument type check errors
|
* Test argument type check errors
|
||||||
*
|
*
|
||||||
* Results are compared for exact match with
|
* Results are compared for exact match with the installed C-based lua
|
||||||
* the installed C-based lua environment.
|
* environment.
|
||||||
*/
|
*/
|
||||||
public class ErrorsTest extends ScriptDrivenTest {
|
public class ErrorsTest extends ScriptDrivenTest {
|
||||||
|
|
||||||
@@ -51,13 +50,21 @@ public class ErrorsTest extends ScriptDrivenTest {
|
|||||||
};
|
};
|
||||||
runTest("baselibargs");
|
runTest("baselibargs");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCoroutineLibArgs() { runTest("coroutinelibargs"); }
|
public void testCoroutineLibArgs() { runTest("coroutinelibargs"); }
|
||||||
|
|
||||||
public void testDebugLibArgs() { runTest("debuglibargs"); }
|
public void testDebugLibArgs() { runTest("debuglibargs"); }
|
||||||
|
|
||||||
public void testIoLibArgs() { runTest("iolibargs"); }
|
public void testIoLibArgs() { runTest("iolibargs"); }
|
||||||
|
|
||||||
public void testMathLibArgs() { runTest("mathlibargs"); }
|
public void testMathLibArgs() { runTest("mathlibargs"); }
|
||||||
|
|
||||||
public void testModuleLibArgs() { runTest("modulelibargs"); }
|
public void testModuleLibArgs() { runTest("modulelibargs"); }
|
||||||
|
|
||||||
public void testOperators() { runTest("operators"); }
|
public void testOperators() { runTest("operators"); }
|
||||||
|
|
||||||
public void testStringLibArgs() { runTest("stringlibargs"); }
|
public void testStringLibArgs() { runTest("stringlibargs"); }
|
||||||
|
|
||||||
public void testTableLibArgs() { runTest("tablelibargs"); }
|
public void testTableLibArgs() { runTest("tablelibargs"); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ import org.luaj.vm2.lib.jse.JsePlatform;
|
|||||||
import org.luaj.vm2.luajc.LuaJC;
|
import org.luaj.vm2.luajc.LuaJC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test compilation of various fragments that have
|
* Test compilation of various fragments that have caused problems for jit
|
||||||
* caused problems for jit compiling during development.
|
* compiling during development.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class FragmentsTest extends TestSuite {
|
public class FragmentsTest extends TestSuite {
|
||||||
@@ -43,9 +43,11 @@ public class FragmentsTest extends TestSuite {
|
|||||||
public static class JseFragmentsTest extends FragmentsTestCase {
|
public static class JseFragmentsTest extends FragmentsTestCase {
|
||||||
public JseFragmentsTest() { super(TEST_TYPE_LUAC); }
|
public JseFragmentsTest() { super(TEST_TYPE_LUAC); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LuaJCFragmentsTest extends FragmentsTestCase {
|
public static class LuaJCFragmentsTest extends FragmentsTestCase {
|
||||||
public LuaJCFragmentsTest() { super(TEST_TYPE_LUAJC); }
|
public LuaJCFragmentsTest() { super(TEST_TYPE_LUAJC); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TestSuite suite() {
|
public static TestSuite suite() {
|
||||||
TestSuite suite = new TestSuite("Compiler Fragments Tests");
|
TestSuite suite = new TestSuite("Compiler Fragments Tests");
|
||||||
suite.addTest(new TestSuite(JseFragmentsTest.class, "JSE Fragments Tests"));
|
suite.addTest(new TestSuite(JseFragmentsTest.class, "JSE Fragments Tests"));
|
||||||
@@ -90,522 +92,309 @@ public class FragmentsTest extends TestSuite {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testFirstArgNilExtended() {
|
public void testFirstArgNilExtended() {
|
||||||
runFragment( LuaValue.NIL,
|
runFragment(LuaValue.NIL, "function f1(a) print( 'f1:', a ) return a end\n" + "b = f1()\n" + "return b");
|
||||||
"function f1(a) print( 'f1:', a ) return a end\n" +
|
|
||||||
"b = f1()\n" +
|
|
||||||
"return b" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleForloop() {
|
public void testSimpleForloop() {
|
||||||
runFragment(LuaValue.valueOf(77),
|
runFragment(LuaValue.valueOf(77),
|
||||||
"for n,p in ipairs({77}) do\n"+
|
"for n,p in ipairs({77}) do\n" + " print('n,p',n,p)\n" + " return p\n" + "end\n");
|
||||||
" print('n,p',n,p)\n"+
|
|
||||||
" return p\n"+
|
|
||||||
"end\n");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testForloopParamUpvalues() {
|
public void testForloopParamUpvalues() {
|
||||||
runFragment( LuaValue.varargsOf(new LuaValue[] {
|
runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(77), LuaValue.valueOf(1) }),
|
||||||
LuaValue.valueOf(77),
|
"for n,p in ipairs({77}) do\n" + " print('n,p',n,p)\n" + " foo = function()\n" + " return p,n\n"
|
||||||
LuaValue.valueOf(1) } ),
|
+ " end\n" + " return foo()\n" + "end\n");
|
||||||
"for n,p in ipairs({77}) do\n"+
|
|
||||||
" print('n,p',n,p)\n"+
|
|
||||||
" foo = function()\n"+
|
|
||||||
" return p,n\n"+
|
|
||||||
" end\n"+
|
|
||||||
" return foo()\n"+
|
|
||||||
"end\n");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testArgVarargsUseBoth() {
|
public void testArgVarargsUseBoth() {
|
||||||
runFragment( LuaValue.varargsOf( new LuaValue[] {
|
runFragment(
|
||||||
LuaValue.valueOf("a"),
|
LuaValue
|
||||||
LuaValue.valueOf("b"),
|
.varargsOf(new LuaValue[] { LuaValue.valueOf("a"), LuaValue.valueOf("b"), LuaValue.valueOf("c") }),
|
||||||
LuaValue.valueOf("c")}),
|
"function v(arg,...)\n" + " return arg,...\n" + "end\n" + "return v('a','b','c')\n");
|
||||||
"function v(arg,...)\n" +
|
|
||||||
" return arg,...\n" +
|
|
||||||
"end\n" +
|
|
||||||
"return v('a','b','c')\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testArgParamUseNone() {
|
public void testArgParamUseNone() {
|
||||||
runFragment(LuaValue.valueOf("string"),
|
runFragment(LuaValue.valueOf("string"),
|
||||||
"function v(arg,...)\n" +
|
"function v(arg,...)\n" + " return type(arg)\n" + "end\n" + "return v('abc')\n");
|
||||||
" return type(arg)\n" +
|
|
||||||
"end\n" +
|
|
||||||
"return v('abc')\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSetlistVarargs() {
|
public void testSetlistVarargs() {
|
||||||
runFragment(LuaValue.valueOf("abc"),
|
runFragment(LuaValue.valueOf("abc"),
|
||||||
"local f = function() return 'abc' end\n" +
|
"local f = function() return 'abc' end\n" + "local g = { f() }\n" + "return g[1]\n");
|
||||||
"local g = { f() }\n" +
|
|
||||||
"return g[1]\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSelfOp() {
|
public void testSelfOp() {
|
||||||
runFragment( LuaValue.valueOf("bcd"),
|
runFragment(LuaValue.valueOf("bcd"), "local s = 'abcde'\n" + "return s:sub(2,4)\n");
|
||||||
"local s = 'abcde'\n"+
|
|
||||||
"return s:sub(2,4)\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSetListWithOffsetAndVarargs() {
|
public void testSetListWithOffsetAndVarargs() {
|
||||||
runFragment( LuaValue.valueOf(1003),
|
runFragment(LuaValue.valueOf(1003), "local bar = {1000, math.sqrt(9)}\n" + "return bar[1]+bar[2]\n");
|
||||||
"local bar = {1000, math.sqrt(9)}\n"+
|
|
||||||
"return bar[1]+bar[2]\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testMultiAssign() {
|
public void testMultiAssign() {
|
||||||
// arargs evaluations are all done before assignments
|
// arargs evaluations are all done before assignments
|
||||||
runFragment( LuaValue.varargsOf(new LuaValue[]{
|
runFragment(
|
||||||
LuaValue.valueOf(111),
|
LuaValue
|
||||||
LuaValue.valueOf(111),
|
.varargsOf(new LuaValue[] { LuaValue.valueOf(111), LuaValue.valueOf(111), LuaValue.valueOf(111) }),
|
||||||
LuaValue.valueOf(111)}),
|
"a,b,c = 1,10,100\n" + "a,b,c = a+b+c, a+b+c, a+b+c\n" + "return a,b,c\n");
|
||||||
"a,b,c = 1,10,100\n" +
|
|
||||||
"a,b,c = a+b+c, a+b+c, a+b+c\n" +
|
|
||||||
"return a,b,c\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpvalues() {
|
public void testUpvalues() {
|
||||||
runFragment(LuaValue.valueOf(999),
|
runFragment(LuaValue.valueOf(999),
|
||||||
"local a = function(x)\n" +
|
"local a = function(x)\n" + " return function(y)\n" + " return x + y\n" + " end\n" + "end\n"
|
||||||
" return function(y)\n" +
|
+ "local b = a(222)\n" + "local c = b(777)\n" + "print( 'c=', c )\n" + "return c\n");
|
||||||
" return x + y\n" +
|
|
||||||
" end\n" +
|
|
||||||
"end\n" +
|
|
||||||
"local b = a(222)\n" +
|
|
||||||
"local c = b(777)\n" +
|
|
||||||
"print( 'c=', c )\n" +
|
|
||||||
"return c\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNonAsciiStringLiterals() {
|
public void testNonAsciiStringLiterals() {
|
||||||
runFragment( LuaValue.valueOf("7,8,12,10,9,11,133,222"),
|
runFragment(LuaValue.valueOf("7,8,12,10,9,11,133,222"), "local a='\\a\\b\\f\\n\\t\\v\\133\\222'\n"
|
||||||
"local a='\\a\\b\\f\\n\\t\\v\\133\\222'\n"+
|
+ "local t={string.byte(a,1,#a)}\n" + "return table.concat(t,',')\n");
|
||||||
"local t={string.byte(a,1,#a)}\n"+
|
|
||||||
"return table.concat(t,',')\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testControlCharStringLiterals() {
|
public void testControlCharStringLiterals() {
|
||||||
runFragment( LuaValue.valueOf("97,0,98,18,99,18,100,18,48,101"),
|
runFragment(LuaValue.valueOf("97,0,98,18,99,18,100,18,48,101"), "local a='a\\0b\\18c\\018d\\0180e'\n"
|
||||||
"local a='a\\0b\\18c\\018d\\0180e'\n"+
|
+ "local t={string.byte(a,1,#a)}\n" + "return table.concat(t,',')\n");
|
||||||
"local t={string.byte(a,1,#a)}\n"+
|
|
||||||
"return table.concat(t,',')\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLoopVarNames() {
|
public void testLoopVarNames() {
|
||||||
runFragment(LuaValue.valueOf(" 234,1,aa 234,2,bb"),
|
runFragment(LuaValue.valueOf(" 234,1,aa 234,2,bb"),
|
||||||
"local w = ''\n"+
|
"local w = ''\n" + "function t()\n" + " for f,var in ipairs({'aa','bb'}) do\n" + " local s = 234\n"
|
||||||
"function t()\n"+
|
+ " w = w..' '..s..','..f..','..var\n" + " end\n" + "end\n" + "t()\n" + "return w\n");
|
||||||
" for f,var in ipairs({'aa','bb'}) do\n"+
|
|
||||||
" local s = 234\n"+
|
|
||||||
" w = w..' '..s..','..f..','..var\n"+
|
|
||||||
" end\n"+
|
|
||||||
"end\n" +
|
|
||||||
"t()\n" +
|
|
||||||
"return w\n" );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testForLoops() {
|
public void testForLoops() {
|
||||||
runFragment(LuaValue.valueOf("12345 357 963"),
|
runFragment(LuaValue.valueOf("12345 357 963"),
|
||||||
"local s,t,u = '','',''\n"+
|
"local s,t,u = '','',''\n" + "for m=1,5 do\n" + " s = s..m\n" + "end\n" + "for m=3,7,2 do\n"
|
||||||
"for m=1,5 do\n"+
|
+ " t = t..m\n" + "end\n" + "for m=9,3,-3 do\n" + " u = u..m\n" + "end\n"
|
||||||
" s = s..m\n"+
|
+ "return s..' '..t..' '..u\n");
|
||||||
"end\n"+
|
|
||||||
"for m=3,7,2 do\n"+
|
|
||||||
" t = t..m\n"+
|
|
||||||
"end\n"+
|
|
||||||
"for m=9,3,-3 do\n"+
|
|
||||||
" u = u..m\n"+
|
|
||||||
"end\n"+
|
|
||||||
"return s..' '..t..' '..u\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLocalFunctionDeclarations() {
|
public void testLocalFunctionDeclarations() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf("function"), LuaValue.valueOf("nil")),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf("function"), LuaValue.valueOf("nil")),
|
||||||
"local function aaa()\n"+
|
"local function aaa()\n" + " return type(aaa)\n" + "end\n" + "local bbb = function()\n"
|
||||||
" return type(aaa)\n"+
|
+ " return type(bbb)\n" + "end\n" + "return aaa(),bbb()\n");
|
||||||
"end\n"+
|
|
||||||
"local bbb = function()\n"+
|
|
||||||
" return type(bbb)\n"+
|
|
||||||
"end\n"+
|
|
||||||
"return aaa(),bbb()\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNilsInTableConstructor() {
|
public void testNilsInTableConstructor() {
|
||||||
runFragment(LuaValue.valueOf("1=111 2=222 3=333 "),
|
runFragment(LuaValue.valueOf("1=111 2=222 3=333 "),
|
||||||
"local t = { 111, 222, 333, nil, nil }\n"+
|
"local t = { 111, 222, 333, nil, nil }\n" + "local s = ''\n" + "for i,v in ipairs(t) do \n"
|
||||||
"local s = ''\n"+
|
+ " s=s..tostring(i)..'='..tostring(v)..' '\n" + "end\n" + "return s\n");
|
||||||
"for i,v in ipairs(t) do \n" +
|
|
||||||
" s=s..tostring(i)..'='..tostring(v)..' '\n" +
|
|
||||||
"end\n"+
|
|
||||||
"return s\n" );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnreachableCode() {
|
public void testUnreachableCode() {
|
||||||
runFragment(LuaValue.valueOf(66),
|
runFragment(LuaValue.valueOf(66),
|
||||||
"local function foo(x) return x * 2 end\n" +
|
"local function foo(x) return x * 2 end\n" + "local function bar(x, y)\n" + " if x==y then\n"
|
||||||
"local function bar(x, y)\n" +
|
+ " return y\n" + " else\n" + " return foo(x)\n" + " end\n" + "end\n"
|
||||||
" if x==y then\n" +
|
+ "return bar(33,44)\n");
|
||||||
" return y\n" +
|
|
||||||
" else\n" +
|
|
||||||
" return foo(x)\n" +
|
|
||||||
" end\n" +
|
|
||||||
"end\n" +
|
|
||||||
"return bar(33,44)\n" );
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVarargsWithParameters() {
|
public void testVarargsWithParameters() {
|
||||||
runFragment(LuaValue.valueOf(222),
|
runFragment(LuaValue.valueOf(222),
|
||||||
"local func = function(t,...)\n"+
|
"local func = function(t,...)\n" + " return (...)\n" + "end\n" + "return func(111,222,333)\n");
|
||||||
" return (...)\n"+
|
|
||||||
"end\n"+
|
|
||||||
"return func(111,222,333)\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNoReturnValuesPlainCall() {
|
public void testNoReturnValuesPlainCall() {
|
||||||
runFragment( LuaValue.TRUE,
|
runFragment(LuaValue.TRUE, "local testtable = {}\n" + "return pcall( function() testtable[1]=2 end )\n");
|
||||||
"local testtable = {}\n"+
|
|
||||||
"return pcall( function() testtable[1]=2 end )\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVarargsInTableConstructor() {
|
public void testVarargsInTableConstructor() {
|
||||||
runFragment( LuaValue.valueOf(222),
|
runFragment(LuaValue.valueOf(222), "local function foo() return 111,222,333 end\n"
|
||||||
"local function foo() return 111,222,333 end\n"+
|
+ "local t = {'a','b',c='c',foo()}\n" + "return t[4]\n");
|
||||||
"local t = {'a','b',c='c',foo()}\n"+
|
|
||||||
"return t[4]\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVarargsInFirstArg() {
|
public void testVarargsInFirstArg() {
|
||||||
runFragment( LuaValue.valueOf(123),
|
runFragment(LuaValue.valueOf(123), "function aaa(x) return x end\n" + "function bbb(y) return y end\n"
|
||||||
"function aaa(x) return x end\n" +
|
+ "function ccc(z) return z end\n" + "return ccc( aaa(bbb(123)), aaa(456) )\n");
|
||||||
"function bbb(y) return y end\n" +
|
|
||||||
"function ccc(z) return z end\n" +
|
|
||||||
"return ccc( aaa(bbb(123)), aaa(456) )\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSetUpvalueTableInitializer() {
|
public void testSetUpvalueTableInitializer() {
|
||||||
runFragment( LuaValue.valueOf("b"),
|
runFragment(LuaValue.valueOf("b"), "local aliases = {a='b'}\n" + "local foo = function()\n"
|
||||||
"local aliases = {a='b'}\n" +
|
+ " return aliases\n" + "end\n" + "return foo().a\n");
|
||||||
"local foo = function()\n" +
|
|
||||||
" return aliases\n" +
|
|
||||||
"end\n" +
|
|
||||||
"return foo().a\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testLoadNilUpvalue() {
|
public void testLoadNilUpvalue() {
|
||||||
runFragment( LuaValue.NIL,
|
runFragment(LuaValue.NIL, "tostring = function() end\n" + "local pc \n" + "local pcall = function(...)\n"
|
||||||
"tostring = function() end\n" +
|
+ " pc(...)\n" + "end\n" + "return NIL\n");
|
||||||
"local pc \n" +
|
|
||||||
"local pcall = function(...)\n" +
|
|
||||||
" pc(...)\n" +
|
|
||||||
"end\n" +
|
|
||||||
"return NIL\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpvalueClosure() {
|
public void testUpvalueClosure() {
|
||||||
runFragment( LuaValue.NIL,
|
runFragment(LuaValue.NIL, "print()\n" + "local function f2() end\n" + "local function f3()\n"
|
||||||
"print()\n"+
|
+ " return f3\n" + "end\n" + "return NIL\n");
|
||||||
"local function f2() end\n"+
|
|
||||||
"local function f3()\n"+
|
|
||||||
" return f3\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return NIL\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUninitializedUpvalue() {
|
public void testUninitializedUpvalue() {
|
||||||
runFragment( LuaValue.NIL,
|
runFragment(LuaValue.NIL, "local f\n" + "do\n" + " function g()\n" + " print(f())\n" + " end\n"
|
||||||
"local f\n"+
|
+ "end\n" + "return NIL\n");
|
||||||
"do\n"+
|
|
||||||
" function g()\n"+
|
|
||||||
" print(f())\n"+
|
|
||||||
" end\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return NIL\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTestOpUpvalues() {
|
public void testTestOpUpvalues() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3)),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3)),
|
||||||
"print( nil and 'T' or 'F' )\n"+
|
"print( nil and 'T' or 'F' )\n" + "local a,b,c = 1,2,3\n" + "function foo()\n" + " return a,b,c\n"
|
||||||
"local a,b,c = 1,2,3\n"+
|
+ "end\n" + "return foo()\n");
|
||||||
"function foo()\n"+
|
|
||||||
" return a,b,c\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return foo()\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTestSimpleBinops() {
|
public void testTestSimpleBinops() {
|
||||||
runFragment( LuaValue.varargsOf(new LuaValue[] {
|
runFragment(
|
||||||
LuaValue.FALSE, LuaValue.FALSE, LuaValue.TRUE, LuaValue.TRUE, LuaValue.FALSE }),
|
LuaValue.varargsOf(
|
||||||
"local a,b,c = 2,-2.5,0\n" +
|
new LuaValue[] { LuaValue.FALSE, LuaValue.FALSE, LuaValue.TRUE, LuaValue.TRUE, LuaValue.FALSE }),
|
||||||
"return (a==c), (b==c), (a==a), (a>c), (b>0)\n" );
|
"local a,b,c = 2,-2.5,0\n" + "return (a==c), (b==c), (a==a), (a>c), (b>0)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNumericForUpvalues() {
|
public void testNumericForUpvalues() {
|
||||||
runFragment( LuaValue.valueOf(8),
|
runFragment(LuaValue.valueOf(8), "for i = 3,4 do\n" + " i = i + 5\n" + " local a = function()\n"
|
||||||
"for i = 3,4 do\n"+
|
+ " return i\n" + " end\n" + " return a()\n" + "end\n");
|
||||||
" i = i + 5\n"+
|
|
||||||
" local a = function()\n"+
|
|
||||||
" return i\n"+
|
|
||||||
" end\n" +
|
|
||||||
" return a()\n"+
|
|
||||||
"end\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNumericForUpvalues2() {
|
public void testNumericForUpvalues2() {
|
||||||
runFragment(LuaValue.valueOf("222 222"),
|
runFragment(LuaValue.valueOf("222 222"),
|
||||||
"local t = {}\n"+
|
"local t = {}\n" + "local template = [[123 456]]\n" + "for i = 1,2 do\n"
|
||||||
"local template = [[123 456]]\n"+
|
+ " t[i] = template:gsub('%d', function(s)\n" + " return i\n" + " end)\n" + "end\n"
|
||||||
"for i = 1,2 do\n"+
|
+ "return t[2]\n");
|
||||||
" t[i] = template:gsub('%d', function(s)\n"+
|
|
||||||
" return i\n"+
|
|
||||||
" end)\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return t[2]\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReturnUpvalue() {
|
public void testReturnUpvalue() {
|
||||||
runFragment( LuaValue.varargsOf(new LuaValue[] { LuaValue.ONE, LuaValue.valueOf(5), }),
|
runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.ONE, LuaValue.valueOf(5), }), "local a = 1\n"
|
||||||
"local a = 1\n"+
|
+ "local b\n" + "function c()\n" + " b=5\n" + " return a\n" + "end\n" + "return c(),b\n");
|
||||||
"local b\n"+
|
|
||||||
"function c()\n"+
|
|
||||||
" b=5\n" +
|
|
||||||
" return a\n"+
|
|
||||||
"end\n"+
|
|
||||||
"return c(),b\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUninitializedAroundBranch() {
|
public void testUninitializedAroundBranch() {
|
||||||
runFragment(LuaValue.valueOf(333),
|
runFragment(LuaValue.valueOf(333),
|
||||||
"local state\n"+
|
"local state\n" + "if _G then\n" + " state = 333\n" + "end\n" + "return state\n");
|
||||||
"if _G then\n"+
|
|
||||||
" state = 333\n"+
|
|
||||||
"end\n"+
|
|
||||||
"return state\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLoadedNilUpvalue() {
|
public void testLoadedNilUpvalue() {
|
||||||
runFragment( LuaValue.NIL,
|
runFragment(LuaValue.NIL, "local a = print()\n" + "local b = c and { d = e }\n" + "local f\n"
|
||||||
"local a = print()\n"+
|
+ "local function g()\n" + " return f\n" + "end\n" + "return g()\n");
|
||||||
"local b = c and { d = e }\n"+
|
|
||||||
"local f\n"+
|
|
||||||
"local function g()\n"+
|
|
||||||
" return f\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return g()\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpvalueInFirstSlot() {
|
public void testUpvalueInFirstSlot() {
|
||||||
runFragment( LuaValue.valueOf("foo"),
|
runFragment(LuaValue.valueOf("foo"), "local p = {'foo'}\n" + "bar = function()\n" + " return p \n"
|
||||||
"local p = {'foo'}\n"+
|
+ "end\n" + "for i,key in ipairs(p) do\n" + " print()\n" + "end\n" + "return bar()[1]");
|
||||||
"bar = function()\n"+
|
|
||||||
" return p \n"+
|
|
||||||
"end\n"+
|
|
||||||
"for i,key in ipairs(p) do\n"+
|
|
||||||
" print()\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return bar()[1]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReadOnlyAndReadWriteUpvalues() {
|
public void testReadOnlyAndReadWriteUpvalues() {
|
||||||
runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(333), LuaValue.valueOf(222) }),
|
runFragment(LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(333), LuaValue.valueOf(222) }),
|
||||||
"local a = 111\n" +
|
"local a = 111\n" + "local b = 222\n" + "local c = function()\n" + " a = a + b\n"
|
||||||
"local b = 222\n" +
|
+ " return a,b\n" + "end\n" + "return c()\n");
|
||||||
"local c = function()\n"+
|
|
||||||
" a = a + b\n" +
|
|
||||||
" return a,b\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return c()\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNestedUpvalues() {
|
public void testNestedUpvalues() {
|
||||||
runFragment( LuaValue.varargsOf( new LuaValue[] { LuaValue.valueOf(5), LuaValue.valueOf(8), LuaValue.valueOf(9) } ),
|
runFragment(
|
||||||
"local x = 3\n"+
|
LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(5), LuaValue.valueOf(8), LuaValue.valueOf(9) }),
|
||||||
"local y = 5\n"+
|
"local x = 3\n" + "local y = 5\n" + "local function f()\n" + " return y\n" + "end\n"
|
||||||
"local function f()\n"+
|
+ "local function g(x1, y1)\n" + " x = x1\n" + " y = y1\n" + " return x,y\n" + "end\n"
|
||||||
" return y\n"+
|
+ "return f(), g(8,9)\n" + "\n");
|
||||||
"end\n"+
|
|
||||||
"local function g(x1, y1)\n"+
|
|
||||||
" x = x1\n"+
|
|
||||||
" y = y1\n" +
|
|
||||||
" return x,y\n"+
|
|
||||||
"end\n"+
|
|
||||||
"return f(), g(8,9)\n"+
|
|
||||||
"\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLoadBool() {
|
public void testLoadBool() {
|
||||||
runFragment( LuaValue.NONE,
|
runFragment(LuaValue.NONE, "print( type(foo)=='string' )\n" + "local a,b\n" + "if print() then\n"
|
||||||
"print( type(foo)=='string' )\n"+
|
+ " b = function()\n" + " return a\n" + " end\n" + "end\n");
|
||||||
"local a,b\n"+
|
|
||||||
"if print() then\n"+
|
|
||||||
" b = function()\n"+
|
|
||||||
" return a\n"+
|
|
||||||
" end\n"+
|
|
||||||
"end\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBasicForLoop() {
|
public void testBasicForLoop() {
|
||||||
runFragment( LuaValue.valueOf(2),
|
runFragment(LuaValue.valueOf(2), "local data\n" + "for i = 1, 2 do\n" + " data = i\n" + "end\n"
|
||||||
"local data\n"+
|
+ "local bar = function()\n" + " return data\n" + "end\n" + "return bar()\n");
|
||||||
"for i = 1, 2 do\n"+
|
|
||||||
" data = i\n"+
|
|
||||||
"end\n"+
|
|
||||||
"local bar = function()\n"+
|
|
||||||
" return data\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return bar()\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGenericForMultipleValues() {
|
public void testGenericForMultipleValues() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf(3), LuaValue.valueOf(2), LuaValue.valueOf(1)),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf(3), LuaValue.valueOf(2), LuaValue.valueOf(1)),
|
||||||
"local iter = function() return 1,2,3,4 end\n" +
|
"local iter = function() return 1,2,3,4 end\n" + "local foo = function() return iter,5 end\n"
|
||||||
"local foo = function() return iter,5 end\n" +
|
+ "for a,b,c in foo() do\n" + " return c,b,a\n" + "end\n");
|
||||||
"for a,b,c in foo() do\n" +
|
|
||||||
" return c,b,a\n" +
|
|
||||||
"end\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPhiUpvalue() {
|
public void testPhiUpvalue() {
|
||||||
runFragment( LuaValue.valueOf(6),
|
runFragment(LuaValue.valueOf(6), "local a = foo or 0\n" + "local function b(c)\n"
|
||||||
"local a = foo or 0\n"+
|
+ " if c > a then a = c end\n" + " return a\n" + "end\n" + "b(6)\n" + "return a\n");
|
||||||
"local function b(c)\n"+
|
|
||||||
" if c > a then a = c end\n" +
|
|
||||||
" return a\n"+
|
|
||||||
"end\n" +
|
|
||||||
"b(6)\n" +
|
|
||||||
"return a\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAssignReferUpvalues() {
|
public void testAssignReferUpvalues() {
|
||||||
runFragment( LuaValue.valueOf(123),
|
runFragment(LuaValue.valueOf(123), "local entity = 234\n" + "local function c()\n" + " return entity\n"
|
||||||
"local entity = 234\n" +
|
+ "end\n" + "entity = (a == b) and 123\n" + "if entity then\n" + " return entity\n" + "end\n");
|
||||||
"local function c()\n" +
|
|
||||||
" return entity\n" +
|
|
||||||
"end\n" +
|
|
||||||
"entity = (a == b) and 123\n" +
|
|
||||||
"if entity then\n" +
|
|
||||||
" return entity\n" +
|
|
||||||
"end\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSimpleRepeatUntil() {
|
public void testSimpleRepeatUntil() {
|
||||||
runFragment(LuaValue.valueOf(5),
|
runFragment(LuaValue.valueOf(5),
|
||||||
"local a\n"+
|
"local a\n" + "local w\n" + "repeat\n" + " a = w\n" + "until not a\n" + "return 5\n");
|
||||||
"local w\n"+
|
|
||||||
"repeat\n"+
|
|
||||||
" a = w\n"+
|
|
||||||
"until not a\n" +
|
|
||||||
"return 5\n" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testLoopVarUpvalues() {
|
public void testLoopVarUpvalues() {
|
||||||
runFragment(LuaValue.valueOf("b"),
|
runFragment(LuaValue.valueOf("b"),
|
||||||
"local env = {}\n" +
|
"local env = {}\n" + "for a,b in pairs(_G) do\n" + " c = function()\n" + " return b\n"
|
||||||
"for a,b in pairs(_G) do\n" +
|
+ " end\n" + "end\n" + "local e = env\n" + "local f = {a='b'}\n" + "for k,v in pairs(f) do\n"
|
||||||
" c = function()\n" +
|
+ " return env[k] or v\n" + "end\n");
|
||||||
" return b\n" +
|
|
||||||
" end\n" +
|
|
||||||
"end\n" +
|
|
||||||
"local e = env\n" +
|
|
||||||
"local f = {a='b'}\n" +
|
|
||||||
"for k,v in pairs(f) do\n" +
|
|
||||||
" return env[k] or v\n" +
|
|
||||||
"end\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPhiVarUpvalue() {
|
public void testPhiVarUpvalue() {
|
||||||
runFragment( LuaValue.valueOf(2),
|
runFragment(LuaValue.valueOf(2), "local a = 1\n" + "local function b()\n" + " a = a + 1\n"
|
||||||
"local a = 1\n"+
|
+ " return function() end\n" + "end\n" + "for i in b() do\n" + " a = 3\n" + "end\n" + "return a\n");
|
||||||
"local function b()\n"+
|
|
||||||
" a = a + 1\n"+
|
|
||||||
" return function() end\n"+
|
|
||||||
"end\n"+
|
|
||||||
"for i in b() do\n"+
|
|
||||||
" a = 3\n"+
|
|
||||||
"end\n" +
|
|
||||||
"return a\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpvaluesInElseClauses() {
|
public void testUpvaluesInElseClauses() {
|
||||||
runFragment(LuaValue.valueOf(111),
|
runFragment(LuaValue.valueOf(111),
|
||||||
"if a then\n" +
|
"if a then\n" + " foo(bar)\n" + "elseif _G then\n" + " local x = 111\n" + " if d then\n"
|
||||||
" foo(bar)\n" +
|
+ " foo(bar)\n" + " else\n" + " local y = function()\n" + " return x\n"
|
||||||
"elseif _G then\n" +
|
+ " end\n" + " return y()\n" + " end\n" + "end\n");
|
||||||
" local x = 111\n" +
|
|
||||||
" if d then\n" +
|
|
||||||
" foo(bar)\n" +
|
|
||||||
" else\n" +
|
|
||||||
" local y = function()\n" +
|
|
||||||
" return x\n" +
|
|
||||||
" end\n" +
|
|
||||||
" return y()\n" +
|
|
||||||
" end\n" +
|
|
||||||
"end\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUpvalueInDoBlock() {
|
public void testUpvalueInDoBlock() {
|
||||||
runFragment( LuaValue.NONE, "do\n"+
|
runFragment(LuaValue.NONE,
|
||||||
" local x = 10\n"+
|
"do\n" + " local x = 10\n" + " function g()\n" + " return x\n" + " end\n" + "end\n" + "g()\n");
|
||||||
" function g()\n"+
|
|
||||||
" return x\n"+
|
|
||||||
" end\n"+
|
|
||||||
"end\n"+
|
|
||||||
"g()\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNullError() {
|
public void testNullError() {
|
||||||
runFragment( LuaValue.varargsOf(LuaValue.FALSE, LuaValue.NIL),
|
runFragment(LuaValue.varargsOf(LuaValue.FALSE, LuaValue.NIL), "return pcall(error)\n");
|
||||||
"return pcall(error)\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFindWithOffset() {
|
public void testFindWithOffset() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf(8), LuaValue.valueOf(5)),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf(8), LuaValue.valueOf(5)), "string = \"abcdef:ghi\"\n"
|
||||||
"string = \"abcdef:ghi\"\n" +
|
+ "substring = string:sub(3)\n" + "idx = substring:find(\":\")\n" + "return #substring, idx\n");
|
||||||
"substring = string:sub(3)\n" +
|
|
||||||
"idx = substring:find(\":\")\n" +
|
|
||||||
"return #substring, idx\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testErrorArgIsString() {
|
public void testErrorArgIsString() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("c")),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("c")),
|
||||||
"a,b = pcall(error, 'c'); return type(b), b\n");
|
"a,b = pcall(error, 'c'); return type(b), b\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testErrorArgIsNil() {
|
public void testErrorArgIsNil() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf("nil"), LuaValue.NIL),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf("nil"), LuaValue.NIL),
|
||||||
"a,b = pcall(error); return type(b), b\n");
|
"a,b = pcall(error); return type(b), b\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testErrorArgIsTable() {
|
public void testErrorArgIsTable() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf("table"), LuaValue.valueOf("d")),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf("table"), LuaValue.valueOf("d")),
|
||||||
"a,b = pcall(error, {c='d'}); return type(b), b.c\n");
|
"a,b = pcall(error, {c='d'}); return type(b), b.c\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testErrorArgIsNumber() {
|
public void testErrorArgIsNumber() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("1")),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf("string"), LuaValue.valueOf("1")),
|
||||||
"a,b = pcall(error, 1); return type(b), b\n");
|
"a,b = pcall(error, 1); return type(b), b\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testErrorArgIsBool() {
|
public void testErrorArgIsBool() {
|
||||||
runFragment(LuaValue.varargsOf(LuaValue.valueOf("boolean"), LuaValue.TRUE),
|
runFragment(LuaValue.varargsOf(LuaValue.valueOf("boolean"), LuaValue.TRUE),
|
||||||
"a,b = pcall(error, true); return type(b), b\n");
|
"a,b = pcall(error, true); return type(b), b\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testBalancedMatchOnEmptyString() {
|
public void testBalancedMatchOnEmptyString() {
|
||||||
runFragment(LuaValue.NIL, "return (\"\"):match(\"%b''\")\n");
|
runFragment(LuaValue.NIL, "return (\"\"):match(\"%b''\")\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReturnValueForTableRemove() {
|
public void testReturnValueForTableRemove() {
|
||||||
runFragment(LuaValue.NONE, "return table.remove({ })");
|
runFragment(LuaValue.NONE, "return table.remove({ })");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTypeOfTableRemoveReturnValue() {
|
public void testTypeOfTableRemoveReturnValue() {
|
||||||
runFragment(LuaValue.valueOf("nil"), "local k = table.remove({ }) return type(k)");
|
runFragment(LuaValue.valueOf("nil"), "local k = table.remove({ }) return type(k)");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVarargBugReport() {
|
public void testVarargBugReport() {
|
||||||
runFragment(LuaValue.varargsOf(new LuaValue[] {
|
runFragment(
|
||||||
LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3) }),
|
LuaValue.varargsOf(new LuaValue[] { LuaValue.valueOf(1), LuaValue.valueOf(2), LuaValue.valueOf(3) }),
|
||||||
"local i = function(...) return ... end\n"
|
"local i = function(...) return ... end\n" + "local v1, v2, v3 = i(1, 2, 3)\n" + "return v1, v2, v3");
|
||||||
+ "local v1, v2, v3 = i(1, 2, 3)\n"
|
|
||||||
+ "return v1, v2, v3");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user