├── .DS_Store ├── .github └── workflows │ └── rust.yml ├── .gitignore ├── .ruby-version ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── laythe.bnf ├── laythe ├── Cargo.toml └── src │ └── main.rs ├── laythe_core ├── Cargo.toml └── src │ ├── align_utils.rs │ ├── allocator.rs │ ├── captures.rs │ ├── chunk.rs │ ├── collections │ ├── array.rs │ ├── mod.rs │ ├── shared_vector │ │ ├── mod.rs │ │ └── raw_shared_vector.rs │ ├── unique_vector │ │ ├── mod.rs │ │ └── raw_unique_vector.rs │ ├── utils.rs │ └── vec_builder.rs │ ├── constants.rs │ ├── hooks.rs │ ├── impls.rs │ ├── lib.rs │ ├── macros.rs │ ├── managed │ ├── allocate.rs │ ├── allocation.rs │ ├── header.rs │ ├── manage.rs │ └── mod.rs │ ├── module │ ├── error.rs │ ├── import.rs │ ├── mod.rs │ └── package.rs │ ├── object │ ├── channel │ │ ├── channel_queue.rs │ │ ├── channel_waiter.rs │ │ └── mod.rs │ ├── class.rs │ ├── closure.rs │ ├── enumerator.rs │ ├── fun.rs │ ├── header.rs │ ├── instance │ │ ├── header.rs │ │ └── mod.rs │ ├── list.rs │ ├── ly_box.rs │ ├── ly_str.rs │ ├── map.rs │ ├── method.rs │ ├── mod.rs │ ├── native.rs │ └── tuple.rs │ ├── reference │ ├── mod.rs │ └── obj_reference.rs │ ├── signature.rs │ ├── support │ └── mod.rs │ ├── utils.rs │ └── value.rs ├── laythe_env ├── Cargo.toml └── src │ ├── env.rs │ ├── fs.rs │ ├── io.rs │ ├── lib.rs │ ├── stdio.rs │ └── time.rs ├── laythe_frontend_bench ├── Cargo.toml └── src │ └── main.rs ├── laythe_lib ├── Cargo.toml └── src │ ├── builtin.rs │ ├── env │ ├── mod.rs │ └── utils.rs │ ├── global │ ├── assert │ │ └── mod.rs │ ├── misc.rs │ ├── mod.rs │ ├── primitives │ │ ├── bool.rs │ │ ├── channel.rs │ │ ├── class.rs │ │ ├── closure.rs │ │ ├── error.rs │ │ ├── fun.rs │ │ ├── iter.rs │ │ ├── list.rs │ │ ├── map.rs │ │ ├── method.rs │ │ ├── mod.rs │ │ ├── module.rs │ │ ├── native.rs │ │ ├── nil.rs │ │ ├── number.rs │ │ ├── object.rs │ │ ├── string.rs │ │ └── tuple.rs │ ├── support │ │ └── mod.rs │ └── time │ │ ├── clock.rs │ │ └── mod.rs │ ├── io │ ├── fs │ │ ├── mod.rs │ │ └── utils.rs │ ├── global │ │ └── mod.rs │ ├── mod.rs │ └── stdio │ │ ├── mod.rs │ │ ├── stderr.rs │ │ ├── stdin.rs │ │ └── stdout.rs │ ├── lib.rs │ ├── math │ ├── mod.rs │ └── utils.rs │ ├── regexp │ ├── class.rs │ └── mod.rs │ └── support │ └── mod.rs ├── laythe_native ├── Cargo.toml └── src │ ├── env.rs │ ├── fs.rs │ ├── io.rs │ ├── lib.rs │ ├── stdio.rs │ └── time.rs ├── laythe_vm ├── Cargo.toml ├── benches │ ├── compiler_benches.rs │ ├── parser_benches.rs │ └── vm_benches.rs ├── fixture │ ├── benchmark │ │ ├── binary_trees.lay │ │ ├── channel.lay │ │ ├── collections.lay │ │ ├── equality.lay │ │ ├── fib.lay │ │ ├── fibers.lay │ │ ├── fluent.lay │ │ ├── instantiation.lay │ │ ├── invocation.lay │ │ ├── list.lay │ │ ├── method_call.lay │ │ ├── properties.lay │ │ ├── string.lay │ │ ├── string_equality.lay │ │ ├── trees.lay │ │ └── zoo.lay │ ├── compiler │ │ ├── README.md │ │ └── arm_compiler.lay │ ├── criterion │ │ ├── binary_trees.lay │ │ ├── channel.lay │ │ ├── equality.lay │ │ ├── fib.lay │ │ ├── fibers.lay │ │ ├── fluent.lay │ │ ├── instantiation.lay │ │ ├── invocation.lay │ │ ├── method_call.lay │ │ ├── properties.lay │ │ ├── string.lay │ │ ├── string_equality.lay │ │ ├── trees.lay │ │ └── zoo.lay │ ├── demo │ │ └── gameOfLife.lay │ ├── language │ │ ├── assignment │ │ │ ├── allowed_postfix.lay │ │ │ ├── associativity.lay │ │ │ ├── global.lay │ │ │ ├── grouping.lay │ │ │ ├── infix_operator.lay │ │ │ ├── local.lay │ │ │ ├── prefix_operator.lay │ │ │ ├── syntax.lay │ │ │ ├── to_this.lay │ │ │ └── undefined.lay │ │ ├── binary_assignment │ │ │ ├── associativity.lay │ │ │ ├── global.lay │ │ │ ├── grouping.lay │ │ │ ├── infix_operator.lay │ │ │ ├── local.lay │ │ │ ├── operators.lay │ │ │ ├── prefix_operator.lay │ │ │ ├── syntax.lay │ │ │ ├── to_this.lay │ │ │ └── undefined.lay │ │ ├── block │ │ │ ├── empty.lay │ │ │ └── scope.lay │ │ ├── bool │ │ │ ├── equality.lay │ │ │ └── not.lay │ │ ├── break │ │ │ ├── additional_scopes.lay │ │ │ ├── for_break.lay │ │ │ ├── in_function_in_loop.lay │ │ │ ├── nested_for_loops.lay │ │ │ ├── nested_while_loops.lay │ │ │ ├── outside_loop.lay │ │ │ ├── while_break.lay │ │ │ └── with_drops.lay │ │ ├── call │ │ │ ├── bool.lay │ │ │ ├── nil.lay │ │ │ ├── num.lay │ │ │ ├── object.lay │ │ │ └── string.lay │ │ ├── channel │ │ │ ├── buffered.lay │ │ │ ├── channel_send_channel.lay │ │ │ ├── channel_sync.lay │ │ │ ├── close_closed.lay │ │ │ ├── fancy.lay │ │ │ ├── in_collection.lay │ │ │ ├── in_function.lay │ │ │ ├── in_instance.lay │ │ │ ├── in_instance_implicit.lay │ │ │ ├── missing_closing_paren.lay │ │ │ ├── missing_open_paren.lay │ │ │ ├── multi_capture_increment.lay │ │ │ ├── non_integer_capacity.lay │ │ │ ├── non_number_capacity.lay │ │ │ ├── receive_buffered.lay │ │ │ ├── receive_buffered_closed.lay │ │ │ ├── receive_buffered_deadlock.lay │ │ │ ├── receive_sync.lay │ │ │ ├── receive_sync_closed.lay │ │ │ ├── receive_sync_deadlock.lay │ │ │ ├── receive_sync_no_send.lay │ │ │ ├── send_buffered.lay │ │ │ ├── send_buffered_closed.lay │ │ │ ├── send_buffered_deadlock.lay │ │ │ ├── send_sync.lay │ │ │ ├── send_sync_closed.lay │ │ │ ├── send_sync_deadlock.lay │ │ │ └── sync.lay │ │ ├── class │ │ │ ├── allowed_postfix.lay │ │ │ ├── bro.lay │ │ │ ├── empty.lay │ │ │ ├── inherit_self.lay │ │ │ ├── inherited_method.lay │ │ │ ├── local_inherit_other.lay │ │ │ ├── local_inherit_self.lay │ │ │ ├── local_reference_self.lay │ │ │ └── reference_self.lay │ │ ├── closure │ │ │ ├── assign_to_closure.lay │ │ │ ├── assign_to_module_from_closure.lay │ │ │ ├── assign_to_shadowed_later.lay │ │ │ ├── close_over_function_parameter.lay │ │ │ ├── close_over_later_variable.lay │ │ │ ├── close_over_method_parameter.lay │ │ │ ├── closed_closure_in_function.lay │ │ │ ├── nested_closure.lay │ │ │ ├── open_closure_in_function.lay │ │ │ ├── reference_closure_multiple_times.lay │ │ │ ├── retrieve_from_module_from_closure.lay │ │ │ ├── reuse_closure_slot.lay │ │ │ ├── shadow_closure_with_local.lay │ │ │ ├── unused_closure.lay │ │ │ └── unused_later_closure.lay │ │ ├── comments │ │ │ ├── line_at_eof.lay │ │ │ ├── only_line_comment.lay │ │ │ ├── only_line_comment_and_line.lay │ │ │ └── unicode.lay │ │ ├── constructor │ │ ├── continue │ │ │ ├── additional_scopes.lay │ │ │ ├── for_continue.lay │ │ │ ├── in_function_in_loop.lay │ │ │ ├── nested_for_loops.lay │ │ │ ├── nested_while_loops.lay │ │ │ ├── outside_loop.lay │ │ │ ├── while_continue.lay │ │ │ └── with_drops.lay │ │ ├── empty_file.lay │ │ ├── exception │ │ │ ├── catch_no_block.lay │ │ │ ├── catch_not_class.lay │ │ │ ├── catch_not_error_class.lay │ │ │ ├── catch_not_identifier.lay │ │ │ ├── multiple_catches.lay │ │ │ ├── nested_break.lay │ │ │ ├── nested_continue.lay │ │ │ ├── nested_return.lay │ │ │ ├── not_error_catch_not_tested.lay │ │ │ ├── one_deep_catch.lay │ │ │ ├── one_deep_raise.lay │ │ │ ├── top_level_catch.lay │ │ │ ├── top_level_catch_raise.lay │ │ │ ├── top_level_raise.lay │ │ │ ├── try_error_in_catch.lay │ │ │ ├── try_fall_through.lay │ │ │ ├── try_no_block.lay │ │ │ ├── try_no_catch.lay │ │ │ ├── two_deep_catch.lay │ │ │ └── two_deep_raise.lay │ │ ├── export │ │ │ ├── declaration_class.lay │ │ │ ├── declaration_fn.lay │ │ │ ├── declaration_let.lay │ │ │ ├── literal.lay │ │ │ ├── local.lay │ │ │ ├── non_declaration_class.lay │ │ │ ├── non_declaration_fn.lay │ │ │ └── non_declaration_let.lay │ │ ├── expressions │ │ │ ├── evaluate.lay │ │ │ └── parse.lay │ │ ├── field │ │ │ ├── call_function_field.lay │ │ │ ├── call_function_field_implicit.lay │ │ │ ├── call_nonfunction_field.lay │ │ │ ├── get_on_bool.lay │ │ │ ├── get_on_class.lay │ │ │ ├── get_on_function.lay │ │ │ ├── get_on_nil.lay │ │ │ ├── get_on_num.lay │ │ │ ├── get_on_string.lay │ │ │ ├── get_undefined.lay │ │ │ ├── many.lay │ │ │ ├── many_implicit.lay │ │ │ ├── method.lay │ │ │ ├── method_binds_self.lay │ │ │ ├── method_binds_self_implicit.lay │ │ │ ├── on_instance.lay │ │ │ ├── on_instance_implicit.lay │ │ │ ├── set_evaluation_order.lay │ │ │ ├── set_on_bool.lay │ │ │ ├── set_on_class.lay │ │ │ ├── set_on_function.lay │ │ │ ├── set_on_nil.lay │ │ │ ├── set_on_num.lay │ │ │ ├── set_on_string.lay │ │ │ └── set_undefined.lay │ │ ├── for │ │ │ ├── cannot_assign_iter.lay │ │ │ ├── class_in_body.lay │ │ │ ├── closure_in_body.lay │ │ │ ├── fn_in_body.lay │ │ │ ├── let_in_body.lay │ │ │ ├── return_closure.lay │ │ │ ├── return_inside.lay │ │ │ ├── scope.lay │ │ │ └── statement_iterator.lay │ │ ├── function │ │ │ ├── allowed_postfix.lay │ │ │ ├── body_must_be_block.lay │ │ │ ├── empty_body.lay │ │ │ ├── extra_arguments.lay │ │ │ ├── local_mutual_recursion.lay │ │ │ ├── local_recursion.lay │ │ │ ├── missing_arguments.lay │ │ │ ├── missing_comma_in_parameters.lay │ │ │ ├── mutual_recursion.lay │ │ │ ├── parameters.lay │ │ │ ├── print.lay │ │ │ ├── recursion.lay │ │ │ ├── too_many_arguments.lay │ │ │ └── too_many_parameters.lay │ │ ├── hooks │ │ │ ├── call_ly_closure.lay │ │ │ ├── call_ly_function.lay │ │ │ ├── call_ly_instance.lay │ │ │ ├── call_native.lay │ │ │ ├── pass_error_ly_closure.lay │ │ │ ├── pass_error_ly_function.lay │ │ │ ├── pass_error_ly_instance.lay │ │ │ └── pass_error_native.lay │ │ ├── if │ │ │ ├── class_in_else.lay │ │ │ ├── class_in_then.lay │ │ │ ├── dangling_else.lay │ │ │ ├── else.lay │ │ │ ├── fun_in_else.lay │ │ │ ├── fun_in_then.lay │ │ │ ├── if.lay │ │ │ ├── let_in_else.lay │ │ │ ├── let_in_then.lay │ │ │ └── truth.lay │ │ ├── implicit_return │ │ │ ├── after_else.lay │ │ │ ├── after_if.lay │ │ │ ├── after_while.lay │ │ │ ├── at_top_level.lay │ │ │ ├── in_function.lay │ │ │ ├── in_function_middle.lay │ │ │ ├── in_init.lay │ │ │ ├── in_method.lay │ │ │ └── in_method_middle.lay │ │ ├── import │ │ │ ├── import_in_class.lay │ │ │ ├── import_in_fun.lay │ │ │ ├── import_in_scope.lay │ │ │ ├── missing_path.lay │ │ │ ├── missing_semicolon.lay │ │ │ ├── module.lay │ │ │ ├── module_not_real.lay │ │ │ ├── module_rename.lay │ │ │ ├── non_identifier_path.lay │ │ │ ├── rename_missing.lay │ │ │ ├── rename_not_identifer.lay │ │ │ ├── rename_redefine.lay │ │ │ ├── symbol.lay │ │ │ ├── symbol_rename.lay │ │ │ ├── symbols_not_real.lay │ │ │ ├── symbols_redefine.lay │ │ │ ├── symbols_rename_missing.lay │ │ │ ├── symbols_rename_not_identifer.lay │ │ │ ├── symbols_rename_redefine.lay │ │ │ └── user_import │ │ │ │ ├── cycle_1.lay │ │ │ │ ├── cycle_2.lay │ │ │ │ ├── cycle_3.lay │ │ │ │ ├── lib.lay │ │ │ │ ├── module.lay │ │ │ │ └── symbol.lay │ │ ├── inheritance │ │ │ ├── constructor.lay │ │ │ ├── inherit_from_function.lay │ │ │ ├── inherit_from_nil.lay │ │ │ ├── inherit_from_number.lay │ │ │ ├── inherit_methods.lay │ │ │ ├── parenthesized_superclass.lay │ │ │ └── set_fields_from_base_class.lay │ │ ├── inline_cache │ │ │ ├── invoke_thrash.lay │ │ │ ├── property_get_thrash.lay │ │ │ ├── property_set_thrash.lay │ │ │ └── super_invoke_thrash.lay │ │ ├── iterator │ │ │ ├── assign_iter_keep_state.lay │ │ │ ├── basic.lay │ │ │ └── equality.lay │ │ ├── lambda │ │ │ ├── body_must_be_block_or_expr.lay │ │ │ ├── empty_body.lay │ │ │ ├── expression_body.lay │ │ │ ├── extra_arguments.lay │ │ │ ├── local_mutual_recursion.lay │ │ │ ├── local_recursion.lay │ │ │ ├── missing_arguments.lay │ │ │ ├── missing_comma_in_parameters.lay │ │ │ ├── mutual_recursion.lay │ │ │ ├── parameters.lay │ │ │ ├── recursion.lay │ │ │ ├── str.lay │ │ │ ├── too_many_arguments.lay │ │ │ └── too_many_parameters.lay │ │ ├── launch │ │ │ ├── launch_bound_method.lay │ │ │ ├── launch_error.lay │ │ │ ├── launch_exit.lay │ │ │ ├── launch_init.lay │ │ │ ├── launch_method.lay │ │ │ ├── launch_multi.lay │ │ │ ├── launch_multi_channel_join.lay │ │ │ ├── launch_native.lay │ │ │ ├── launch_single.lay │ │ │ ├── launch_with_capture_global.lay │ │ │ ├── launch_with_capture_local.lay │ │ │ ├── no_call.lay │ │ │ ├── no_expr.lay │ │ │ └── no_semi.lay │ │ ├── limit │ │ │ ├── loop_too_large.lay │ │ │ ├── reuse_constants.lay │ │ │ ├── stack_overflow.lay │ │ │ ├── too_many_captures.lay │ │ │ ├── too_many_constants.lay │ │ │ ├── too_many_locals.lay │ │ │ └── too_many_module_symbols.lay │ │ ├── list │ │ │ ├── empty.lay │ │ │ ├── homogeneous.lay │ │ │ ├── missing_closing_bracket.lay │ │ │ ├── missing_comma_in_initializer.lay │ │ │ └── mixed.lay │ │ ├── logical_operator │ │ │ ├── and.lay │ │ │ ├── and_truth.lay │ │ │ ├── nested_ternary.lay │ │ │ ├── or.lay │ │ │ ├── or_truth.lay │ │ │ └── ternary.lay │ │ ├── map │ │ │ ├── empty.lay │ │ │ ├── homogeneous.lay │ │ │ ├── missing_closing_curly.lay │ │ │ ├── missing_colon.lay │ │ │ ├── mixed.lay │ │ │ ├── statement_key.lay │ │ │ └── statement_value.lay │ │ ├── method │ │ │ ├── arity.lay │ │ │ ├── empty_block.lay │ │ │ ├── extra_arguments.lay │ │ │ ├── missing_arguments.lay │ │ │ ├── not_found.lay │ │ │ ├── print_bound_method.lay │ │ │ ├── refer_to_name.lay │ │ │ ├── too_many_arguments.lay │ │ │ └── too_many_parameters.lay │ │ ├── native │ │ │ ├── assert.lay │ │ │ ├── assert_eq.lay │ │ │ ├── assert_ne.lay │ │ │ ├── clock.lay │ │ │ ├── signature_fixed_arity.lay │ │ │ └── signature_type.lay │ │ ├── nil │ │ │ └── literal.lay │ │ ├── number │ │ │ ├── decimal_point_at_eof.lay │ │ │ ├── leading_dot.lay │ │ │ ├── literals.lay │ │ │ └── trailing_dot.lay │ │ ├── operator │ │ │ ├── add.lay │ │ │ ├── add_bool_nil.lay │ │ │ ├── add_bool_num.lay │ │ │ ├── add_bool_string.lay │ │ │ ├── add_nil_nil.lay │ │ │ ├── add_num_nil.lay │ │ │ ├── add_string_nil.lay │ │ │ ├── comparison.lay │ │ │ ├── divide.lay │ │ │ ├── divide_nonnum_num.lay │ │ │ ├── divide_num_nonnum.lay │ │ │ ├── equals.lay │ │ │ ├── equals_class.lay │ │ │ ├── equals_method.lay │ │ │ ├── greater_nonnum_num.lay │ │ │ ├── greater_num_nonnum.lay │ │ │ ├── greater_or_equal_nonnum_num.lay │ │ │ ├── greater_or_equal_num_nonnum.lay │ │ │ ├── less_nonnum_num.lay │ │ │ ├── less_num_nonnum.lay │ │ │ ├── less_or_equal_nonnum_num.lay │ │ │ ├── less_or_equal_num_nonnum.lay │ │ │ ├── multiply.lay │ │ │ ├── multiply_nonnum_num.lay │ │ │ ├── multiply_num_nonnum.lay │ │ │ ├── negate.lay │ │ │ ├── negate_nonnum.lay │ │ │ ├── not.lay │ │ │ ├── not_class.lay │ │ │ ├── not_equals.lay │ │ │ ├── subtract.lay │ │ │ ├── subtract_nonnum_num.lay │ │ │ └── subtract_num_nonnum.lay │ │ ├── precedence.lay │ │ ├── raise │ │ │ ├── no_expr.lay │ │ │ ├── no_semi.lay │ │ │ ├── not_error_subclass.lay │ │ │ ├── not_instance.lay │ │ │ ├── raise_error.lay │ │ │ └── raise_error_subclass.lay │ │ ├── regression │ │ │ ├── 394.lay │ │ │ ├── 40.lay │ │ │ ├── catch_laythe_stack_overflow.lay │ │ │ ├── continue.lay │ │ │ ├── missing_symbol.lay │ │ │ └── native_stack_overvflow.lay │ │ ├── return │ │ │ ├── after_else.lay │ │ │ ├── after_if.lay │ │ │ ├── after_while.lay │ │ │ ├── at_top_level.lay │ │ │ ├── in_function.lay │ │ │ ├── in_method.lay │ │ │ └── return_nil_if_no_value.lay │ │ ├── scanning │ │ │ ├── identifiers.lay │ │ │ ├── keywords.lay │ │ │ ├── numbers.lay │ │ │ ├── punctuators.lay │ │ │ ├── strings.lay │ │ │ └── whitespace.lay │ │ ├── self │ │ │ ├── closure.lay │ │ │ ├── nested_class.lay │ │ │ ├── nested_closure.lay │ │ │ ├── pass_through_assign.lay │ │ │ ├── pass_through_assign_implicit.lay │ │ │ ├── self_at_top_level.lay │ │ │ ├── self_in_method.lay │ │ │ └── self_in_top_level_function.lay │ │ ├── static_method │ │ │ ├── arity.lay │ │ │ ├── call_bound.lay │ │ │ ├── empty_block.lay │ │ │ ├── extra_arguments.lay │ │ │ ├── missing_arguments.lay │ │ │ ├── no_self.lay │ │ │ ├── no_self_implicit.lay │ │ │ ├── not_found.lay │ │ │ ├── not_inherited.lay │ │ │ ├── print_bound_method.lay │ │ │ ├── refer_to_name.lay │ │ │ ├── too_many_arguments.lay │ │ │ └── too_many_parameters.lay │ │ ├── string │ │ │ ├── error_after_multiline.lay │ │ │ ├── escape.lay │ │ │ ├── interpolation.lay │ │ │ ├── invalid_escape.lay │ │ │ ├── invalid_interpolation_missing_close.lay │ │ │ ├── invalid_unicode_hex.lay │ │ │ ├── invalid_unicode_missing_close.lay │ │ │ ├── invalid_unicode_missing_open.lay │ │ │ ├── invalid_unicode_no_hex.lay │ │ │ ├── invalid_unicode_too_long.lay │ │ │ ├── literals.lay │ │ │ ├── multiline.lay │ │ │ ├── unicode_escape.lay │ │ │ ├── unterminated_double.lay │ │ │ └── unterminated_single.lay │ │ ├── super │ │ │ ├── bound_method.lay │ │ │ ├── call_other_method.lay │ │ │ ├── call_same_method.lay │ │ │ ├── closure.lay │ │ │ ├── constructor.lay │ │ │ ├── extra_arguments.lay │ │ │ ├── indirectly_inherited.lay │ │ │ ├── missing_arguments.lay │ │ │ ├── no_superclass_call.lay │ │ │ ├── no_superclass_method.lay │ │ │ ├── parenthesized.lay │ │ │ ├── reassign_superclass.lay │ │ │ ├── super_at_top_level.lay │ │ │ ├── super_in_closure_in_inherited_method.lay │ │ │ ├── super_in_inherited_method.lay │ │ │ ├── super_in_top_level_function.lay │ │ │ ├── super_without_dot.lay │ │ │ ├── super_without_name.lay │ │ │ └── this_in_superclass_method.lay │ │ ├── tuple │ │ │ ├── empty.lay │ │ │ ├── empty_comma.lay │ │ │ ├── homogeneous.lay │ │ │ ├── missing_closing_bracket.lay │ │ │ ├── missing_comma_in_initializer.lay │ │ │ └── mixed.lay │ │ ├── unexpected_character.lay │ │ ├── variable │ │ │ ├── collide_with_parameter.lay │ │ │ ├── duplicate_local.lay │ │ │ ├── duplicate_parameter.lay │ │ │ ├── early_bound.lay │ │ │ ├── in_middle_of_block.lay │ │ │ ├── in_nested_block.lay │ │ │ ├── local_from_method.lay │ │ │ ├── redeclare_global.lay │ │ │ ├── redefine_global.lay │ │ │ ├── scope_reuse_in_different_blocks.lay │ │ │ ├── shadow_and_local.lay │ │ │ ├── shadow_global.lay │ │ │ ├── shadow_local.lay │ │ │ ├── undefined_global.lay │ │ │ ├── undefined_local.lay │ │ │ ├── uninitialized.lay │ │ │ ├── unreached_undefined.lay │ │ │ ├── use_false_as_var.lay │ │ │ ├── use_global_in_initializer.lay │ │ │ ├── use_local_in_initializer.lay │ │ │ ├── use_nil_as_var.lay │ │ │ └── use_this_as_var.lay │ │ └── while │ │ │ ├── class_in_body.lay │ │ │ ├── closure_in_body.lay │ │ │ ├── fun_in_body.lay │ │ │ ├── return_closure.lay │ │ │ ├── return_inside.lay │ │ │ ├── syntax.lay │ │ │ └── var_in_body.lay │ ├── lox_interpreter │ │ └── lox.lay │ ├── py_benchmark │ │ ├── binary_trees.py │ │ ├── equality.py │ │ ├── fib.py │ │ ├── instantiation.py │ │ ├── invocation.py │ │ ├── list.py │ │ ├── method_call.py │ │ ├── properties.py │ │ ├── strings.py │ │ ├── trees.py │ │ └── zoo.py │ ├── rb_benchmark │ │ ├── binary_trees.rb │ │ ├── equality.rb │ │ ├── fib.rb │ │ ├── instantiation.rb │ │ ├── invocation.rb │ │ ├── list.rb │ │ ├── method_call.rb │ │ ├── properties.rb │ │ ├── string.rb │ │ ├── trees.rb │ │ └── zoo.rb │ └── std_lib │ │ ├── env │ │ ├── args.lay │ │ └── cwd.lay │ │ ├── global │ │ ├── bool │ │ │ └── str.lay │ │ ├── channel │ │ │ ├── capacity.lay │ │ │ ├── close.lay │ │ │ ├── close_close.lay │ │ │ ├── len.lay │ │ │ └── str.lay │ │ ├── class │ │ │ ├── name.lay │ │ │ ├── str.lay │ │ │ └── superCls.lay │ │ ├── closure │ │ │ ├── call.lay │ │ │ ├── call_wrong_args.lay │ │ │ ├── len.lay │ │ │ ├── len_wrong_args.lay │ │ │ ├── name.lay │ │ │ └── name_wrong_args.lay │ │ ├── error │ │ │ ├── construct.lay │ │ │ └── sub_class.lay │ │ ├── fun │ │ │ ├── call.lay │ │ │ ├── call_wrong_args.lay │ │ │ ├── len.lay │ │ │ ├── len_wrong_args.lay │ │ │ ├── name.lay │ │ │ └── name_wrong_args.lay │ │ ├── iter │ │ │ ├── all.lay │ │ │ ├── any.lay │ │ │ ├── chain.lay │ │ │ ├── each.lay │ │ │ ├── filter.lay │ │ │ ├── filter_method.lay │ │ │ ├── first.lay │ │ │ ├── into.lay │ │ │ ├── iter.lay │ │ │ ├── last.lay │ │ │ ├── len.lay │ │ │ ├── map.lay │ │ │ ├── map_method.lay │ │ │ ├── next.lay │ │ │ ├── reduce.lay │ │ │ ├── skip.lay │ │ │ ├── str.lay │ │ │ ├── take.lay │ │ │ ├── to_list.lay │ │ │ └── zip.lay │ │ ├── list │ │ │ ├── clear.lay │ │ │ ├── collect.lay │ │ │ ├── has.lay │ │ │ ├── index.lay │ │ │ ├── index_get.lay │ │ │ ├── index_get_fractional.lay │ │ │ ├── index_get_fractional_negative.lay │ │ │ ├── index_get_negative.lay │ │ │ ├── index_get_nested.lay │ │ │ ├── index_get_out_of_range.lay │ │ │ ├── index_get_out_of_range_negative.lay │ │ │ ├── index_set.lay │ │ │ ├── index_set_fractional.lay │ │ │ ├── index_set_fractional_negative.lay │ │ │ ├── index_set_negative.lay │ │ │ ├── index_set_nested.lay │ │ │ ├── index_set_out_of_range.lay │ │ │ ├── index_set_out_of_range_negative.lay │ │ │ ├── index_set_pass_through.lay │ │ │ ├── insert.lay │ │ │ ├── insert_out_of_bounds.lay │ │ │ ├── iter.lay │ │ │ ├── len.lay │ │ │ ├── pop.lay │ │ │ ├── push.lay │ │ │ ├── remove.lay │ │ │ ├── remove_out_of_bounds.lay │ │ │ ├── rev.lay │ │ │ ├── slice.lay │ │ │ ├── sort.lay │ │ │ └── str.lay │ │ ├── map │ │ │ ├── get.lay │ │ │ ├── has.lay │ │ │ ├── index_get.lay │ │ │ ├── index_get_key_not_found.lay │ │ │ ├── index_get_nan.lay │ │ │ ├── index_get_nested.lay │ │ │ ├── index_get_ref_equal.lay │ │ │ ├── index_set.lay │ │ │ ├── index_set_nested.lay │ │ │ ├── index_set_pass_through.lay │ │ │ ├── insert.lay │ │ │ ├── iter.lay │ │ │ ├── len.lay │ │ │ ├── remove.lay │ │ │ ├── remove_missing_key.lay │ │ │ ├── set.lay │ │ │ └── str.lay │ │ ├── method │ │ │ ├── call.lay │ │ │ └── name.lay │ │ ├── module │ │ │ └── name.lay │ │ ├── nil │ │ │ └── str.lay │ │ ├── number │ │ │ ├── ceil.lay │ │ │ ├── cmp.lay │ │ │ ├── floor.lay │ │ │ ├── parse.lay │ │ │ ├── round.lay │ │ │ ├── str.lay │ │ │ └── times.lay │ │ ├── object │ │ │ ├── cls.lay │ │ │ ├── equals.lay │ │ │ ├── is_a.lay │ │ │ └── str.lay │ │ ├── print │ │ │ ├── basic.lay │ │ │ ├── multi.lay │ │ │ └── with_newline_char.lay │ │ ├── str │ │ │ ├── down_case.lay │ │ │ ├── has.lay │ │ │ ├── index.lay │ │ │ ├── iter.lay │ │ │ ├── len.lay │ │ │ ├── slice.lay │ │ │ ├── split.lay │ │ │ ├── str.lay │ │ │ ├── trim.lay │ │ │ ├── trim_end.lay │ │ │ ├── trim_start.lay │ │ │ └── up_case.lay │ │ └── tuple │ │ │ ├── collect.lay │ │ │ ├── has.lay │ │ │ ├── index.lay │ │ │ ├── index_get.lay │ │ │ ├── index_get_fractional.lay │ │ │ ├── index_get_fractional_negative.lay │ │ │ ├── index_get_negative.lay │ │ │ ├── index_get_nested.lay │ │ │ ├── index_get_out_of_range.lay │ │ │ ├── index_get_out_of_range_negative.lay │ │ │ ├── iter.lay │ │ │ ├── len.lay │ │ │ ├── slice.lay │ │ │ └── str.lay │ │ ├── io │ │ ├── fs │ │ │ ├── readFile.lay │ │ │ ├── read_example.txt │ │ │ ├── removeFile.lay │ │ │ └── writeFile.lay │ │ └── stdio │ │ │ ├── stderr │ │ │ ├── write.lay │ │ │ └── writeln.lay │ │ │ ├── stdin │ │ │ ├── read.lay │ │ │ └── readline.lay │ │ │ └── stdout │ │ │ ├── write.lay │ │ │ └── writeln.lay │ │ ├── math │ │ └── utils │ │ │ ├── abs.lay │ │ │ ├── cos.lay │ │ │ ├── ln.lay │ │ │ ├── max.lay │ │ │ ├── min.lay │ │ │ ├── rand.lay │ │ │ ├── rem.lay │ │ │ └── sin.lay │ │ └── regexp │ │ └── class │ │ ├── captures.lay │ │ ├── match.lay │ │ └── test.lay ├── src │ ├── byte_code.rs │ ├── cache.rs │ ├── chunk_builder.rs │ ├── compiler │ │ ├── ir │ │ │ ├── ast.rs │ │ │ ├── ast_printer.rs │ │ │ ├── mod.rs │ │ │ ├── symbol_table.rs │ │ │ └── token.rs │ │ ├── mod.rs │ │ ├── parser.rs │ │ ├── peephole.rs │ │ ├── ref_no_context.rs │ │ ├── resolver.rs │ │ └── scanner.rs │ ├── constants.rs │ ├── debug.rs │ ├── fiber │ │ ├── builder.rs │ │ ├── call_frame.rs │ │ ├── exception_handler.rs │ │ └── mod.rs │ ├── lib.rs │ ├── source │ │ ├── files.rs │ │ └── mod.rs │ └── vm │ │ ├── basic.rs │ │ ├── debug.rs │ │ ├── error.rs │ │ ├── hooks.rs │ │ ├── impls.rs │ │ ├── mod.rs │ │ ├── ops.rs │ │ └── source_loader.rs └── tests │ ├── env.rs │ ├── global.rs │ ├── io.rs │ ├── language.rs │ ├── math.rs │ ├── regexp.rs │ └── support │ └── mod.rs ├── laythe_wasm ├── Cargo.toml ├── src │ ├── lib.rs │ ├── stdio_wasm.rs │ └── time_wasm.rs └── web │ ├── .travis.yml │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── bootstrap.js │ ├── index.html │ ├── index.js │ ├── init.js │ ├── language.js │ ├── package-lock.json │ ├── package.json │ └── webpack.config.js ├── profiling.md └── rustfmt.toml /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laythe-lang/Laythe/c2e53a1ae3618d3cd944f95fd2f51000009e93da/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | **/*.rs.bk 3 | node_modules 4 | dist 5 | perf.data 6 | flamegraph.svg 7 | .DS_Store -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.3.4 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "bytecode", 4 | "bytecodes", 5 | "laythe" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "laythe build", 8 | "type": "shell", 9 | "command": "cargo build" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "laythe_frontend_bench", 5 | "laythe_native", 6 | "laythe_core", 7 | "laythe_lib", 8 | "laythe_env", 9 | "laythe_vm", 10 | "laythe_wasm", 11 | "laythe", 12 | ] 13 | 14 | default-members = [ 15 | "laythe_core", 16 | "laythe_native", 17 | "laythe_lib", 18 | "laythe_env", 19 | "laythe_vm", 20 | "laythe", 21 | ] 22 | 23 | [profile.dev] 24 | opt-level = 0 25 | 26 | [profile.release] 27 | debug = true 28 | lto = "fat" 29 | opt-level = 3 30 | 31 | 32 | -------------------------------------------------------------------------------- /laythe/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "laythe" 3 | version = "0.1.0" 4 | authors = ["John Chabot "] 5 | edition = "2021" 6 | 7 | [features] 8 | jemalloc = ["jemallocator"] 9 | 10 | [[bin]] 11 | name = "laythe" 12 | path = "src/main.rs" 13 | 14 | [dependencies] 15 | laythe_vm = { path = "../laythe_vm", features=[] } 16 | # laythe_vm features 17 | # debug 18 | 19 | jemallocator = { version = "0.5.0", optional = true } -------------------------------------------------------------------------------- /laythe_core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "laythe_core" 3 | version = "0.1.0" 4 | authors = ["John Chabot "] 5 | edition = "2021" 6 | 7 | [features] 8 | nan_boxing = [] 9 | gc_log_mark = [] 10 | gc_log_free = [] 11 | gc_log_alloc = [] 12 | gc_log_retain = [] 13 | gc_stress = [] 14 | 15 | [lib] 16 | name = "laythe_core" 17 | path = "src/lib.rs" 18 | 19 | [dependencies] 20 | laythe_env = { path = "../laythe_env" } 21 | fnv = "1.0.7" 22 | hashbrown = "0.14.5" -------------------------------------------------------------------------------- /laythe_core/src/collections/mod.rs: -------------------------------------------------------------------------------- 1 | mod array; 2 | mod shared_vector; 3 | mod unique_vector; 4 | mod vec_builder; 5 | 6 | pub use array::{Array, ArrayHandle}; 7 | pub use shared_vector::{IndexedResult, RawSharedVector, RawSharedVectorHandle, RawVecLocation}; 8 | pub use unique_vector::UniqueVector; 9 | pub use vec_builder::VecBuilder; 10 | -------------------------------------------------------------------------------- /laythe_core/src/collections/shared_vector/mod.rs: -------------------------------------------------------------------------------- 1 | mod raw_shared_vector; 2 | 3 | pub use raw_shared_vector::{ 4 | IndexedResult, RawSharedVector, RawSharedVectorHandle, RawVecLocation, 5 | }; 6 | -------------------------------------------------------------------------------- /laythe_core/src/collections/utils.rs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laythe-lang/Laythe/c2e53a1ae3618d3cd944f95fd2f51000009e93da/laythe_core/src/collections/utils.rs -------------------------------------------------------------------------------- /laythe_core/src/constants.rs: -------------------------------------------------------------------------------- 1 | pub const INIT: &str = "init"; 2 | pub const INDEX_GET: &str = "[]"; 3 | pub const INDEX_SET: &str = "[]="; 4 | pub const SUPER: &str = "super"; 5 | pub const SELF: &str = "self"; 6 | pub const OBJECT: &str = "Object"; 7 | pub const ITER_VAR: &str = "$iter"; 8 | pub const UNINITIALIZED_VAR: &str = "$uninitialized"; 9 | pub const ITER: &str = "iter"; 10 | pub const SCRIPT: &str = "script"; 11 | pub const PLACEHOLDER_NAME: &str = "placeholder"; 12 | pub const IMPORT_SEPARATOR: &str = "/"; 13 | -------------------------------------------------------------------------------- /laythe_core/src/managed/mod.rs: -------------------------------------------------------------------------------- 1 | mod allocate; 2 | mod allocation; 3 | mod header; 4 | mod manage; 5 | 6 | pub use allocate::{AllocObjResult, AllocResult, Allocate, AllocateObj}; 7 | pub use allocation::Allocation; 8 | pub use header::Header; 9 | pub use manage::{ 10 | DebugHeap, DebugWrap, DebugWrapDyn, Manage, Mark, Marked, Trace, TraceAny, TraceRoot, Unmark, 11 | }; 12 | -------------------------------------------------------------------------------- /laythe_env/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "laythe_env" 3 | version = "0.1.0" 4 | authors = ["John Chabot "] 5 | edition = "2021" 6 | 7 | [lib] 8 | name = "laythe_env" 9 | path = "src/lib.rs" 10 | 11 | [dependencies] 12 | hashbrown = "0.14.5" 13 | fnv = "1.0.7" 14 | termcolor = "1.4.1" -------------------------------------------------------------------------------- /laythe_env/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(clippy::all)] 2 | 3 | pub mod env; 4 | pub mod fs; 5 | pub mod io; 6 | pub mod stdio; 7 | pub mod time; 8 | -------------------------------------------------------------------------------- /laythe_frontend_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "laythe_frontend_bench" 3 | version = "0.1.0" 4 | authors = ["John Chabot "] 5 | edition = "2021" 6 | 7 | [[bin]] 8 | name = "laythe_frontend_bench" 9 | path = "src/main.rs" 10 | 11 | [dependencies] 12 | laythe_core = { path = "../laythe_core" } 13 | laythe_vm = { path = "../laythe_vm" } 14 | laythe_native = { path = "../laythe_native" } 15 | laythe_lib = { path = "../laythe_lib" } 16 | bumpalo = { version = "3.11.1", features=["boxed", "collections"] } -------------------------------------------------------------------------------- /laythe_lib/src/global/primitives/module.rs: -------------------------------------------------------------------------------- 1 | use laythe_core::{hooks::GcHooks, object::Class, ObjRef}; 2 | 3 | pub const MODULE_CLASS_NAME: &str = "Module"; 4 | 5 | pub fn create_module_class(hooks: &GcHooks, object: ObjRef) -> ObjRef { 6 | let name = hooks.manage_str(MODULE_CLASS_NAME); 7 | Class::with_inheritance(hooks, name, object) 8 | } 9 | -------------------------------------------------------------------------------- /laythe_lib/src/global/support/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::native; 2 | use laythe_core::{ 3 | hooks::{GcHooks, Hooks}, 4 | managed::Trace, 5 | object::{LyNative, Native, NativeMetaBuilder}, 6 | signature::Arity, 7 | value::{Value, VALUE_NIL}, 8 | Call, 9 | }; 10 | use std::io::Write; 11 | 12 | const TEST_META: NativeMetaBuilder = NativeMetaBuilder::fun("test", Arity::Fixed(0)); 13 | 14 | native!(TestNative, TEST_META); 15 | 16 | impl LyNative for TestNative { 17 | fn call(&self, _: &mut Hooks, _: &[Value]) -> Call { 18 | Call::Ok(VALUE_NIL) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /laythe_lib/src/global/time/mod.rs: -------------------------------------------------------------------------------- 1 | mod clock; 2 | 3 | use clock::declare_clock_funs; 4 | use laythe_core::{hooks::GcHooks, module::Module, Ref}; 5 | 6 | use crate::StdResult; 7 | 8 | pub(crate) fn add_clock_funs(hooks: &GcHooks, module: Ref) -> StdResult<()> { 9 | declare_clock_funs(hooks, module) 10 | } 11 | -------------------------------------------------------------------------------- /laythe_native/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "laythe_native" 3 | version = "0.1.0" 4 | authors = ["John Chabot "] 5 | edition = "2021" 6 | 7 | [lib] 8 | name = "laythe_native" 9 | path = "src/lib.rs" 10 | 11 | [dependencies] 12 | laythe_env = { path = "../laythe_env" } 13 | termcolor = "1.1.3" -------------------------------------------------------------------------------- /laythe_native/src/io.rs: -------------------------------------------------------------------------------- 1 | use crate::{env::IoEnvNative, fs::IoFsNative, stdio::IoStdioNative, time::IoTimeNative}; 2 | use laythe_env::io::Io; 3 | use std::sync::Arc; 4 | 5 | pub fn io_native() -> Io { 6 | Io::new( 7 | Arc::new(IoStdioNative()), 8 | Arc::new(IoFsNative()), 9 | Arc::new(IoEnvNative()), 10 | Arc::new(IoTimeNative::default()), 11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /laythe_native/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(clippy::all)] 2 | 3 | pub mod env; 4 | pub mod fs; 5 | pub mod io; 6 | pub mod stdio; 7 | pub mod time; 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/benchmark/fib.lay: -------------------------------------------------------------------------------- 1 | fn fib(n) { 2 | if n < 2 { return n; } 3 | fib(n - 2) + fib(n - 1) 4 | } 5 | 6 | let start = clock(); 7 | print(fib(35) == 9227465); 8 | print(clock() - start); -------------------------------------------------------------------------------- /laythe_vm/fixture/benchmark/fibers.lay: -------------------------------------------------------------------------------- 1 | let start = clock(); 2 | 3 | fn test(ch) { 4 | <- ch; 5 | } 6 | 7 | let ch = chan(); 8 | let fibers = 300000; 9 | 10 | for i in fibers.times() { 11 | launch test(ch); 12 | } 13 | 14 | for i in fibers.times() { 15 | ch <- i; 16 | } 17 | 18 | print(clock() - start); 19 | -------------------------------------------------------------------------------- /laythe_vm/fixture/benchmark/fluent.lay: -------------------------------------------------------------------------------- 1 | import std.math:{rem}; 2 | 3 | let start = clock(); 4 | 5 | 100000000.times() 6 | .filter(|x| rem(x, 3)) 7 | .map(|x| (x * 4) - 2) 8 | .reduce(0, |acc, curr| acc + curr); 9 | 10 | print(clock() - start); 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/benchmark/list.lay: -------------------------------------------------------------------------------- 1 | let start = clock(); 2 | 3 | for i in 10000.times() { 4 | let collection = []; 5 | for j in 1000.times() { 6 | collection.push(nil); 7 | collection[j] = j; 8 | } 9 | 10 | let sum = 0; 11 | for j in 1000.times() { 12 | sum = sum + collection[1000 - j - 1]; 13 | collection.pop(); 14 | } 15 | } 16 | 17 | print(clock() - start); 18 | -------------------------------------------------------------------------------- /laythe_vm/fixture/compiler/README.md: -------------------------------------------------------------------------------- 1 | ## GCC Assembler to ARM 2 | 3 | ```shell 4 | arm-linux-gnueabihf-gcc -static hello.s -o hello 5 | ``` -------------------------------------------------------------------------------- /laythe_vm/fixture/criterion/fib.lay: -------------------------------------------------------------------------------- 1 | fn fib(n) { 2 | if n < 2 { return n; } 3 | fib(n - 2) + fib(n - 1) 4 | } 5 | 6 | fib(20); 7 | -------------------------------------------------------------------------------- /laythe_vm/fixture/criterion/fibers.lay: -------------------------------------------------------------------------------- 1 | fn test(ch) { 2 | <- ch; 3 | } 4 | 5 | let ch = chan(); 6 | let fibers = 2500; 7 | 8 | for i in fibers.times() { 9 | launch test(ch); 10 | } 11 | 12 | for i in fibers.times() { 13 | ch <- i; 14 | } 15 | -------------------------------------------------------------------------------- /laythe_vm/fixture/criterion/fluent.lay: -------------------------------------------------------------------------------- 1 | import std.math:{rem}; 2 | 3 | 10000.times() 4 | .filter(|x| rem(x, 3)) 5 | .map(|x| (x * 4) - 2) 6 | .reduce(0, |acc, curr| acc + curr); 7 | -------------------------------------------------------------------------------- /laythe_vm/fixture/criterion/trees.lay: -------------------------------------------------------------------------------- 1 | class Tree { 2 | init(depth) { 3 | @depth = depth; 4 | if depth > 0 { 5 | @a = Tree(depth - 1); 6 | @b = Tree(depth - 1); 7 | @c = Tree(depth - 1); 8 | @d = Tree(depth - 1); 9 | @e = Tree(depth - 1); 10 | } 11 | } 12 | 13 | walk() { 14 | if @depth == 0 { return 0; } 15 | @depth 16 | + @a.walk() 17 | + @b.walk() 18 | + @c.walk() 19 | + @d.walk() 20 | + @e.walk() 21 | } 22 | } 23 | 24 | let tree = Tree(5); 25 | 26 | for i in 3.times() { 27 | tree.walk(); 28 | } 29 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/allowed_postfix.lay: -------------------------------------------------------------------------------- 1 | let a! = 1; 2 | let b? = 2; 3 | let abc_? = 3; 4 | 5 | assertEq(a!, 1); 6 | assertEq(b?, 2); 7 | assertEq(abc_?, 3); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/associativity.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | let b = "b"; 3 | let c = "c"; 4 | 5 | // Assignment is right-associative. 6 | a = b = c; 7 | assertEq(a, c); // expect: c 8 | assertEq(b, c); // expect: c 9 | assertEq(c, c); // expect: c 10 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/global.lay: -------------------------------------------------------------------------------- 1 | let a = "before"; 2 | assertEq(a, "before"); // expect: before 3 | 4 | a = "after"; 5 | assertEq(a, "after"); // expect: after 6 | 7 | assertEq(a = "arg", "arg"); // expect: arg 8 | assertEq(a, "arg"); // expect: arg 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/grouping.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | (a) = "value"; // Error at '=': Invalid assignment target. 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/infix_operator.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | let b = "b"; 3 | a + b = "value"; // Error at '=': Invalid assignment target. 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/local.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let a = "before"; 3 | assertEq(a, "before"); // expect: before 4 | 5 | a = "after"; 6 | assertEq(a, "after"); // expect: after 7 | 8 | assertEq(a = "arg", "arg"); // expect: arg 9 | assertEq(a, "arg"); // expect: arg 10 | } 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/prefix_operator.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | !a = "value"; // Error at '=': Invalid assignment target. 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/syntax.lay: -------------------------------------------------------------------------------- 1 | // Assignment on RHS of variable. 2 | let a = "before"; 3 | let c = a = "let"; 4 | assertEq(a, "let"); // expect: let 5 | assertEq(c, "let"); // expect: let 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/to_this.lay: -------------------------------------------------------------------------------- 1 | class Foo { 2 | Foo() { 3 | self = "value"; // Error at '=': Invalid assignment target. 4 | } 5 | } 6 | 7 | Foo(); 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/assignment/undefined.lay: -------------------------------------------------------------------------------- 1 | unknown = "what"; // expect runtime error: Undefined variable 'unknown'. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/associativity.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | let b = "b"; 3 | let c = "c"; 4 | 5 | // Assignment is right-associative. 6 | a += b += c; 7 | assertEq(a, "abc"); // expect: c 8 | assertEq(b, "bc"); // expect: c 9 | assertEq(c, "c"); // expect: c 10 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/global.lay: -------------------------------------------------------------------------------- 1 | let a = "before"; 2 | assertEq(a, "before"); // expect: before 3 | 4 | a += "after"; 5 | assertEq(a, "beforeafter"); // expect: after 6 | 7 | assertEq(a += "arg", "beforeafterarg"); // expect: arg 8 | assertEq(a, "beforeafterarg"); // expect: arg 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/grouping.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | (a) += "value"; // Error at '=': Invalid assignment target. 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/infix_operator.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | let b = "b"; 3 | a + b += "value"; // Error at '=': Invalid assignment target. 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/local.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let a = "before"; 3 | assertEq(a, "before"); // expect: before 4 | 5 | a += "after"; 6 | assertEq(a, "beforeafter"); // expect: after 7 | 8 | assertEq(a += "arg", "beforeafterarg"); // expect: arg 9 | assertEq(a, "beforeafterarg"); // expect: arg 10 | } 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/operators.lay: -------------------------------------------------------------------------------- 1 | let a = 10; 2 | assertEq(a += 5, 15); 3 | assertEq(a -= -5, 20); 4 | assertEq(a /= 2, 10); 5 | assertEq(a *= 5, 50); 6 | 7 | let b = "str"; 8 | assertEq(b += "dude", "strdude"); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/prefix_operator.lay: -------------------------------------------------------------------------------- 1 | let a = "a"; 2 | !a += "value"; // Error at '=': Invalid assignment target. 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/syntax.lay: -------------------------------------------------------------------------------- 1 | // Assignment on RHS of variable. 2 | let a = "before"; 3 | let c = a += "let"; 4 | assertEq(a, "beforelet"); // expect: let 5 | assertEq(c, "beforelet"); // expect: let 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/to_this.lay: -------------------------------------------------------------------------------- 1 | class Foo { 2 | Foo() { 3 | self += "value"; // Error at '=': Invalid assignment target. 4 | } 5 | } 6 | 7 | Foo(); 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/binary_assignment/undefined.lay: -------------------------------------------------------------------------------- 1 | unknown += "what"; // expect runtime error: Undefined variable 'unknown'. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/block/empty.lay: -------------------------------------------------------------------------------- 1 | // In a statement. 2 | if true {} 3 | if false {} else {} 4 | 5 | assert(true); 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/block/scope.lay: -------------------------------------------------------------------------------- 1 | let a = "outer"; 2 | 3 | if true { 4 | let a = "inner"; 5 | assertEq(a, "inner"); // expect: inner 6 | } 7 | 8 | assertEq(a, "outer"); // expect: outer 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/bool/not.lay: -------------------------------------------------------------------------------- 1 | assertEq(!true, false); // expect: false 2 | assertEq(!false, true); // expect: true 3 | assertEq(!!true, true); // expect: true 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/additional_scopes.lay: -------------------------------------------------------------------------------- 1 | for i in 100.times() { 2 | if true { 3 | if true { 4 | if true { 5 | if true { 6 | break; 7 | } 8 | } 9 | } 10 | } 11 | 12 | assert(false); 13 | } 14 | 15 | assert(true); 16 | 17 | while true { 18 | if true { 19 | if true { 20 | if true { 21 | if true { 22 | break; 23 | } 24 | } 25 | } 26 | } 27 | 28 | assert(false); 29 | } 30 | 31 | assert(true); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/for_break.lay: -------------------------------------------------------------------------------- 1 | for i in [1, 2, 3] { 2 | break; 3 | assert(false); 4 | } 5 | 6 | assert(true); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/in_function_in_loop.lay: -------------------------------------------------------------------------------- 1 | while true { 2 | fn func() { 3 | break; 4 | } 5 | 6 | func(); 7 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/nested_for_loops.lay: -------------------------------------------------------------------------------- 1 | let visited = false; 2 | 3 | for i in [1, 2, 3] { 4 | for j in [1, 2, 3] { 5 | assert(j <= 1); 6 | break; 7 | } 8 | 9 | if i == 3 { 10 | visited = true; 11 | break; 12 | } 13 | 14 | if i == 3 { 15 | assert(false); 16 | } 17 | } 18 | 19 | assert(visited); 20 | 21 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/nested_while_loops.lay: -------------------------------------------------------------------------------- 1 | let visited = false; 2 | 3 | let i = 0; 4 | while i < 10 { 5 | while true { 6 | break; 7 | } 8 | 9 | i = i + 1; 10 | if i == 9 { 11 | visited = true; 12 | break; 13 | } 14 | 15 | if i == 9 { 16 | assert(false); 17 | } 18 | } 19 | 20 | assert(visited); 21 | 22 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/outside_loop.lay: -------------------------------------------------------------------------------- 1 | break; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/while_break.lay: -------------------------------------------------------------------------------- 1 | while true { 2 | break; 3 | assert(false); 4 | } 5 | 6 | assert(true); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/break/with_drops.lay: -------------------------------------------------------------------------------- 1 | for i in 1.times() { 2 | let a = 10; 3 | let b = 10; 4 | let c = 10; 5 | let d = 10; 6 | break; 7 | } 8 | 9 | assert(true); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/call/bool.lay: -------------------------------------------------------------------------------- 1 | true(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/call/nil.lay: -------------------------------------------------------------------------------- 1 | nil(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/call/num.lay: -------------------------------------------------------------------------------- 1 | 123(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/call/object.lay: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | let foo = Foo(); 4 | foo(); // expect runtime error: Can only call functions and classes. 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/call/string.lay: -------------------------------------------------------------------------------- 1 | "str"(); // expect runtime error: Can only call functions and classes. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/buffered.lay: -------------------------------------------------------------------------------- 1 | let a = chan(10); 2 | assertEq(a.len(), 0); 3 | assertEq(a.capacity(), 10); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/channel_send_channel.lay: -------------------------------------------------------------------------------- 1 | fn test(ch1) { 2 | let ch2 = <- ch1; 3 | ch2 <- "foo"; 4 | } 5 | 6 | let ch1 = chan(); 7 | let ch2 = chan(); 8 | 9 | launch test(ch1); 10 | 11 | ch1 <- ch2; 12 | assertEq(<- ch2, "foo"); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/channel_sync.lay: -------------------------------------------------------------------------------- 1 | let index = 0; 2 | let asserts = [0, 1, 2, 3, 4, 5, 6]; 3 | 4 | fn foo(ch) { 5 | for i in 3.times() { 6 | <- ch; 7 | assertEq(asserts[index], i * 2 + 1); 8 | index += 1; 9 | } 10 | } 11 | 12 | let ch = chan(); 13 | launch foo(ch); 14 | 15 | for i in 3.times() { 16 | assertEq(asserts[index], i * 2); 17 | index += 1; 18 | 19 | ch <- nil; 20 | } 21 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/close_closed.lay: -------------------------------------------------------------------------------- 1 | let x = chan(); 2 | x.close(); 3 | x.close(); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/fancy.lay: -------------------------------------------------------------------------------- 1 | fn left(mainCh, sendCh, RecCh) { 2 | sendCh <- <- mainCh; 3 | assertEq(<- RecCh, "right"); 4 | } 5 | 6 | fn right(mainCh, sendCh, RecCh) { 7 | assertEq(<- RecCh, "left"); 8 | sendCh <- <- mainCh; 9 | } 10 | 11 | let main1Ch = chan(); 12 | let main2Ch = chan(); 13 | let leftCh = chan(); 14 | let rightCh = chan(); 15 | 16 | launch left(main1Ch, leftCh, rightCh); 17 | launch right(main2Ch, rightCh, leftCh); 18 | 19 | main1Ch <- "left"; 20 | main2Ch <- "right"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/in_collection.lay: -------------------------------------------------------------------------------- 1 | let l = [chan(3), chan(3)]; 2 | let h = { 0: chan(3), 1: chan(3) }; 3 | 4 | fn fill(c) { 5 | c[0] <- 1; 6 | c[0] <- 2; 7 | c[0] <- 3; 8 | 9 | c[1] <- 'cat'; 10 | c[1] <- 'dog'; 11 | c[1] <- 'parrot'; 12 | } 13 | 14 | fn drain(c) { 15 | assertEq(<- c[1], 'cat'); 16 | assertEq(<- c[1], 'dog'); 17 | assertEq(<- c[0], 1); 18 | assertEq(<- c[1], 'parrot'); 19 | assertEq(<- c[0], 2); 20 | assertEq(<- c[0], 3); 21 | } 22 | 23 | fill(l); 24 | fill(h); 25 | 26 | drain(h); 27 | drain(l); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/in_function.lay: -------------------------------------------------------------------------------- 1 | fn fill(ch) { 2 | ch <- 1; 3 | ch <- 2; 4 | ch <- 3; 5 | } 6 | 7 | fn drain(ch) { 8 | assertEq(<- ch, 1); 9 | assertEq(<- ch, 2); 10 | assertEq(<- ch, 3); 11 | } 12 | 13 | let ch = chan(3); 14 | fill(ch); 15 | drain(ch); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/missing_closing_paren.lay: -------------------------------------------------------------------------------- 1 | chan(; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/missing_open_paren.lay: -------------------------------------------------------------------------------- 1 | chan; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/multi_capture_increment.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let ch = chan(); 3 | let a = 0; 4 | 5 | fn inc(ch) { 6 | a += 1; 7 | ch <- nil 8 | } 9 | 10 | let n = 10; 11 | for _ in n.times() { 12 | launch inc(ch); 13 | } 14 | 15 | for _ in n.times() { 16 | assertEq(<- ch, nil); 17 | } 18 | 19 | assertEq(a, n); 20 | } 21 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/non_integer_capacity.lay: -------------------------------------------------------------------------------- 1 | chan(1.5); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/non_number_capacity.lay: -------------------------------------------------------------------------------- 1 | chan('5'); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/receive_buffered.lay: -------------------------------------------------------------------------------- 1 | let x = chan(5); 2 | 3 | x <- 1; 4 | x <- 2; 5 | x <- 3; 6 | x <- 4; 7 | 8 | assertEq(<- x, 1); 9 | assertEq(<- x, 2); 10 | assertEq(<- x, 3); 11 | 12 | if <- x { 13 | assert(true); 14 | } else { 15 | assert(false); 16 | } 17 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/receive_buffered_closed.lay: -------------------------------------------------------------------------------- 1 | let x = chan(3); 2 | 3 | x <- 1; 4 | x <- 2; 5 | x <- 3; 6 | 7 | x.close(); 8 | 9 | assertEq(<- x, 1); 10 | assertEq(<- x, 2); 11 | assertEq(<- x, 3); 12 | assertEq(<- x, nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/receive_buffered_deadlock.lay: -------------------------------------------------------------------------------- 1 | let x = chan(5); 2 | <- x; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/receive_sync.lay: -------------------------------------------------------------------------------- 1 | fn assert(ch) { 2 | assertEq(<- ch, 1); 3 | } 4 | 5 | let ch = chan(); 6 | launch assert(ch); 7 | 8 | ch <- 1; 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/receive_sync_closed.lay: -------------------------------------------------------------------------------- 1 | fn test(ch) { 2 | assertEq(<- ch, 1); 3 | assertEq(<- ch, 2); 4 | assertEq(<- ch, 3); 5 | assertEq(<- ch, nil); 6 | } 7 | 8 | let ch = chan(); 9 | 10 | launch test(ch); 11 | 12 | ch <- 1; 13 | ch <- 2; 14 | ch <- 3; 15 | 16 | ch.close(); 17 | 18 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/receive_sync_deadlock.lay: -------------------------------------------------------------------------------- 1 | let x = chan(); 2 | <- x; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/receive_sync_no_send.lay: -------------------------------------------------------------------------------- 1 | fn takeOne(ch) { 2 | assert(false); 3 | <- ch; 4 | } 5 | 6 | let ch = chan(); 7 | launch takeOne(ch); 8 | assert(true); 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/send_buffered.lay: -------------------------------------------------------------------------------- 1 | let x = chan(5); 2 | 3 | x <- 1; 4 | x <- 2; 5 | x <- 3; 6 | x <- 4; 7 | x <- 5; 8 | 9 | assertEq(x.len(), 5); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/send_buffered_closed.lay: -------------------------------------------------------------------------------- 1 | let x = chan(5); 2 | 3 | x.close(); 4 | x <- 1; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/send_buffered_deadlock.lay: -------------------------------------------------------------------------------- 1 | let x = chan(5); 2 | 3 | x <- 1; 4 | x <- 2; 5 | x <- 3; 6 | x <- 4; 7 | x <- 5; 8 | x <- 6; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/send_sync.lay: -------------------------------------------------------------------------------- 1 | fn assert(ch) { 2 | assertEq(ch.len(), 1); 3 | assertEq(<- ch, 'foo'); 4 | } 5 | 6 | let ch = chan(); 7 | launch assert(ch); 8 | 9 | ch <- 'foo'; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/send_sync_closed.lay: -------------------------------------------------------------------------------- 1 | let x = chan(); 2 | 3 | x.close(); 4 | x <- 1; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/send_sync_deadlock.lay: -------------------------------------------------------------------------------- 1 | fn doNothing(ch) {} 2 | 3 | let ch = chan(); 4 | launch doNothing(ch); 5 | 6 | ch <- "stuff"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/channel/sync.lay: -------------------------------------------------------------------------------- 1 | let a = chan(); 2 | assertEq(a.len(), 0); 3 | assertEq(a.capacity(), 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/class/allowed_postfix.lay: -------------------------------------------------------------------------------- 1 | class Sup? { 2 | foo!() { } 3 | bar?() { } 4 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/class/bro.lay: -------------------------------------------------------------------------------- 1 | class Dude { 2 | a; 3 | b; 4 | c; 5 | 6 | init() { 7 | self.bro = 10; 8 | } 9 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/class/empty.lay: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | assert(Foo.str().has(' 3 | 4 | print(clock); // expect: 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/function/recursion.lay: -------------------------------------------------------------------------------- 1 | fn fib(n) { 2 | if n < 2 { return n; } 3 | return fib(n - 1) + fib(n - 2); 4 | } 5 | 6 | assertEq(fib(8), 21); 7 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/call_ly_closure.lay: -------------------------------------------------------------------------------- 1 | fn outer(parameter) { 2 | fn inner() { 3 | return parameter; 4 | } 5 | 6 | return inner; 7 | } 8 | 9 | assertEq(10, outer(10).call()); 10 | assertEq("john", outer("john").call()); 11 | assertEq(outer, outer(outer).call()); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/call_ly_function.lay: -------------------------------------------------------------------------------- 1 | fn example(parameter) { 2 | return parameter; 3 | } 4 | 5 | assertEq(10, example.call(10)); 6 | assertEq("john", example.call("john")); 7 | assertEq(example, example.call(example)); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/call_ly_instance.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | example(parameter) { 3 | return parameter; 4 | } 5 | } 6 | 7 | let a = A(); 8 | let example = a.example; 9 | assertEq(10, a.example.call(10)); 10 | assertEq("john", a.example.call("john")); 11 | assertEq(example, a.example.call(example)); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/call_native.lay: -------------------------------------------------------------------------------- 1 | let list = []; 2 | list.push.call(1, 2, 3); 3 | list.remove.call(1); 4 | 5 | assertEq(list.len(), 2); 6 | assertEq(list[0], 1); 7 | assertEq(list[1], 3); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/pass_error_ly_closure.lay: -------------------------------------------------------------------------------- 1 | fn outer() { 2 | fn inner() { 3 | return nil + false; 4 | } 5 | 6 | return inner; 7 | } 8 | 9 | outer().call(); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/pass_error_ly_function.lay: -------------------------------------------------------------------------------- 1 | fn error() { 2 | return nil + false; 3 | } 4 | 5 | error.call(); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/pass_error_ly_instance.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | example() { 3 | return nil + false; 4 | } 5 | } 6 | 7 | let a = A(); 8 | a.example.call(); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/hooks/pass_error_native.lay: -------------------------------------------------------------------------------- 1 | [].remove.call(-2); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/class_in_else.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'class': Expect expression. 2 | if true { "ok"; } else class Foo {} 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/class_in_then.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'class': Expect expression. 2 | if true class Foo {} 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/dangling_else.lay: -------------------------------------------------------------------------------- 1 | // A dangling else binds to the right-most if. 2 | if true { if false { assert(false); } else { assert(true); } }// expect: good 3 | if false { if true { assert(false); } else { assert(false); } } 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/else.lay: -------------------------------------------------------------------------------- 1 | // Evaluate the 'else' expression if the condition is false. 2 | if true { assert(true); } else { assert(false); } 3 | if false { assert(false); } else { assert(true); } 4 | 5 | // Allow block body. 6 | if false { nil; } else { assert(true); } 7 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/fun_in_else.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'fun': Expect expression. 2 | if true { "ok"; } else { fn foo( {} 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/fun_in_then.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'fun': Expect expression. 2 | if true) fn foo( {} 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/if.lay: -------------------------------------------------------------------------------- 1 | // Evaluate the 'then' expression if the condition is true. 2 | if true { assert(true); } // expect: good 3 | if false { assert(false); } 4 | 5 | // Allow block body. 6 | if true { assert(true); } // expect: block 7 | 8 | // Assignment in if condition. 9 | let a = false; 10 | if a = true { assertEq(a, true); } // expect: true 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/let_in_else.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'let': Expect expression. 2 | if true { "ok" }; else let foo; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/let_in_then.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'let': Expect expression. 2 | if true let foo; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/if/truth.lay: -------------------------------------------------------------------------------- 1 | // False and nil are false. 2 | if false { assert(false); } else { assert(true); } // expect: false 3 | if nil { assert(false); } else { assert(true); } // expect: nil 4 | 5 | // Everything else is true. 6 | if true { assert(true); } // expect: true 7 | if 0 { assert(true); } // expect: 0 8 | if "" { assert(true); } // expect: empty 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/after_else.lay: -------------------------------------------------------------------------------- 1 | fn f() { 2 | if false { "no" } else { "ok" } 3 | } 4 | 5 | assertEq(f(), "ok"); // expect: ok 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/after_if.lay: -------------------------------------------------------------------------------- 1 | fn f() { 2 | if true { "ok" } 3 | } 4 | 5 | assertEq(f(), "ok"); // expect: ok 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/after_while.lay: -------------------------------------------------------------------------------- 1 | fn f() { 2 | while true { "ok" } 3 | } 4 | 5 | assertEq(f(), "ok"); // expect: ok 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/at_top_level.lay: -------------------------------------------------------------------------------- 1 | "wat" // Error at 'return': Cannot return from top-level code. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/in_function.lay: -------------------------------------------------------------------------------- 1 | fn f() { "ok" } 2 | 3 | assertEq(f(), "ok"); // expect: ok 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/in_function_middle.lay: -------------------------------------------------------------------------------- 1 | fn f() { "ok" print(10); } 2 | 3 | assertEq(f(), "ok"); // expect: ok 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/in_init.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | init() { 10 } 3 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/in_method.lay: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method() { 3 | "ok" 4 | } 5 | } 6 | 7 | assertEq(Foo().method(), "ok"); // expect: ok 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/implicit_return/in_method_middle.lay: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method() { 3 | "ok" 4 | print(10); 5 | } 6 | } 7 | 8 | assertEq(Foo().method(), "ok"); // expect: ok 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/import_in_class.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | foo() { 3 | import std.math; 4 | } 5 | } 6 | 7 | A().foo() -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/import_in_fun.lay: -------------------------------------------------------------------------------- 1 | fn importer() { 2 | import std.math:{abs}; 3 | } 4 | 5 | importer() -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/import_in_scope.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | import std.math:{abs}; 3 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/missing_path.lay: -------------------------------------------------------------------------------- 1 | import -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/missing_semicolon.lay: -------------------------------------------------------------------------------- 1 | import std.time -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/module.lay: -------------------------------------------------------------------------------- 1 | import std.math; 2 | 3 | assertEq(math.abs(-5), 5); 4 | assertEq(math.max(1, 3, 2), 3); 5 | assertEq(math.min(3, 1, 2), 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/module_not_real.lay: -------------------------------------------------------------------------------- 1 | import std.no_real; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/module_rename.lay: -------------------------------------------------------------------------------- 1 | import std.math as mathematics; 2 | 3 | assertEq(mathematics.abs(-5), 5); 4 | assertEq(mathematics.max(1, 3, 2), 3); 5 | assertEq(mathematics.min(3, 1, 2), 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/non_identifier_path.lay: -------------------------------------------------------------------------------- 1 | import false:{time}; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/rename_missing.lay: -------------------------------------------------------------------------------- 1 | import std.time as -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/rename_not_identifer.lay: -------------------------------------------------------------------------------- 1 | import std.time as true; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/rename_redefine.lay: -------------------------------------------------------------------------------- 1 | let Fs = "example"; 2 | import std.io.fs as Fs; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/symbol.lay: -------------------------------------------------------------------------------- 1 | import std.math:{abs, max, min}; 2 | 3 | assertEq(abs(-5), 5); 4 | assertEq(max(1, 3, 2), 3); 5 | assertEq(min(3, 1, 2), 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/symbol_rename.lay: -------------------------------------------------------------------------------- 1 | import std.math:{abs as absolute, max as maximum, min as minimum}; 2 | 3 | assertEq(absolute(-5), 5); 4 | assertEq(maximum(1, 3, 2), 3); 5 | assertEq(minimum(3, 1, 2), 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/symbols_not_real.lay: -------------------------------------------------------------------------------- 1 | import std.math:{foo}; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/symbols_redefine.lay: -------------------------------------------------------------------------------- 1 | let File = "example"; 2 | import std.io.fs:{File}; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/symbols_rename_missing.lay: -------------------------------------------------------------------------------- 1 | import std.io.fs:{File as}; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/symbols_rename_not_identifer.lay: -------------------------------------------------------------------------------- 1 | import std.io.fs:{File as true}; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/symbols_rename_redefine.lay: -------------------------------------------------------------------------------- 1 | let Sin = "example"; 2 | import std.math:{sin as Sin}; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/user_import/cycle_1.lay: -------------------------------------------------------------------------------- 1 | import self.cycle_2:{x}; 2 | 3 | assertEq(x, nil); 4 | 5 | export let z = 10; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/user_import/cycle_2.lay: -------------------------------------------------------------------------------- 1 | import self.cycle_3:{y}; 2 | 3 | export let x = y; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/user_import/cycle_3.lay: -------------------------------------------------------------------------------- 1 | import self.cycle_1:{z}; 2 | 3 | export let y = z; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/user_import/lib.lay: -------------------------------------------------------------------------------- 1 | export let x = 10; 2 | export fn y() { 10 } 3 | export class Z { 4 | ans() { 10 } 5 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/user_import/module.lay: -------------------------------------------------------------------------------- 1 | import self.lib; 2 | 3 | assertEq(lib.x, 10); 4 | assertEq(lib.y(), 10); 5 | assertEq(lib.Z().ans(), 10); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/import/user_import/symbol.lay: -------------------------------------------------------------------------------- 1 | import self.lib:{x, y, Z}; 2 | 3 | assertEq(x, 10); 4 | assertEq(y(), 10); 5 | assertEq(Z().ans(), 10); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inheritance/constructor.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | init(param) { 3 | self.field = param; 4 | } 5 | 6 | test() { 7 | return self.field; 8 | } 9 | } 10 | 11 | class B : A {} 12 | 13 | let b = B("value"); 14 | assertEq(b.test(), "value"); // expect: value 15 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inheritance/inherit_from_function.lay: -------------------------------------------------------------------------------- 1 | fn foo() {} 2 | 3 | class Subclass : foo {} // expect runtime error: Superclass must be a class. -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inheritance/inherit_from_nil.lay: -------------------------------------------------------------------------------- 1 | let Nil = nil; 2 | class Foo : Nil {} // expect runtime error: Superclass must be a class. 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inheritance/inherit_from_number.lay: -------------------------------------------------------------------------------- 1 | let Number = 123; 2 | class Foo : Number {} // expect runtime error: Superclass must be a class. 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inheritance/inherit_methods.lay: -------------------------------------------------------------------------------- 1 | class Foo { 2 | methodOnFoo() { return "foo"; } 3 | override() { return "foo"; } 4 | } 5 | 6 | class Bar : Foo { 7 | methodOnBar() { return "bar"; } 8 | override() { return "bar"; } 9 | } 10 | 11 | let bar = Bar(); 12 | assertEq(bar.methodOnFoo(), "foo"); // expect: foo 13 | assertEq(bar.methodOnBar(), "bar"); // expect: bar 14 | assertEq(bar.override(), "bar"); // expect: bar 15 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inheritance/parenthesized_superclass.lay: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | // [line 4] Error at '(': Expect superclass name. 4 | class Bar : (Foo) {} 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inline_cache/invoke_thrash.lay: -------------------------------------------------------------------------------- 1 | fn test(foo) { 2 | foo.bar() 3 | } 4 | 5 | class A { 6 | bar() { 7 | 'A' 8 | } 9 | } 10 | 11 | class B { 12 | bar() { 13 | 'B' 14 | } 15 | } 16 | 17 | let examples = [A(), B(), A(), B()]; 18 | let expected = ['A', 'B', 'A', 'B']; 19 | 20 | for i in examples.len().times() { 21 | assertEq(test(examples[i]), expected[i]); 22 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inline_cache/property_get_thrash.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | init() { 3 | self.a = "foo"; 4 | self.b = "bar"; 5 | } 6 | } 7 | 8 | class B { 9 | init() { 10 | self.b = "foo"; 11 | self.a = "bar"; 12 | } 13 | } 14 | 15 | let examples = [A(), B(), A(), B()]; 16 | let expected = ["bar", "foo", "bar", "foo"]; 17 | 18 | for i in examples.len().times() { 19 | assertEq(examples[i].b, expected[i]); 20 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inline_cache/property_set_thrash.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | init() { 3 | self.a = true; 4 | self.b = false; 5 | } 6 | } 7 | 8 | class B { 9 | init() { 10 | self.b = true; 11 | self.a = false; 12 | } 13 | } 14 | 15 | fn toggle(a) { 16 | a.b = !a.b; 17 | } 18 | 19 | let examples = [A(), B()]; 20 | 21 | for _ in 5.times() { 22 | for example in examples { 23 | toggle(example); 24 | } 25 | } 26 | 27 | assertEq(examples[0].a, true); 28 | assertEq(examples[0].b, true); 29 | 30 | assertEq(examples[1].a, false); 31 | assertEq(examples[1].b, false); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/inline_cache/super_invoke_thrash.lay: -------------------------------------------------------------------------------- 1 | fn test(foo) { 2 | foo.bar() 3 | } 4 | 5 | class ASuper { 6 | bar() { 7 | 'A' 8 | } 9 | } 10 | 11 | class BSuper { 12 | bar() { 13 | 'B' 14 | } 15 | } 16 | 17 | class A : ASuper { 18 | bar() { 19 | super.bar() 20 | } 21 | } 22 | 23 | class B : BSuper { 24 | bar() { 25 | super.bar() 26 | } 27 | } 28 | 29 | let examples = [A(), B(), A(), B()]; 30 | let expected = ['A', 'B', 'A', 'B']; 31 | 32 | for i in examples.len().times() { 33 | assertEq(test(examples[i]), expected[i]); 34 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/iterator/assign_iter_keep_state.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3, 4]; 2 | let iter1 = list.iter(); 3 | 4 | iter1.next(); 5 | iter1.next(); 6 | 7 | let iter2 = iter1; 8 | iter2.next(); 9 | iter2.next(); 10 | 11 | assertEq(iter1.current(), 4); 12 | assertEq(iter2.current(), 4); 13 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/iterator/equality.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3]; 2 | let map = { 3 | "key1": 10, 4 | "key2": false, 5 | }; 6 | 7 | let listIter1 = list.iter(); 8 | let listIter2 = list.iter(); 9 | 10 | let mapIter1 = map.iter(); 11 | let mapIter2 = map.iter(); 12 | 13 | assertEq(listIter1, listIter1); 14 | assertEq(listIter2, listIter2); 15 | assertNe(listIter1, listIter2); 16 | 17 | assertEq(mapIter1, mapIter1); 18 | assertEq(mapIter2, mapIter2); 19 | assertNe(mapIter1, mapIter2); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/body_must_be_block_or_expr.lay: -------------------------------------------------------------------------------- 1 | // [line 3] Error at '123': Expect '{' before function body. 2 | // [c line 4] Error at end: Expect '}' after block. 3 | let f = || class A {}; 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/empty_body.lay: -------------------------------------------------------------------------------- 1 | let f = || {}; 2 | assertEq(f(), nil); // expect: nil 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/expression_body.lay: -------------------------------------------------------------------------------- 1 | assertEq((|x| x)(10), 10); 2 | 3 | let result = "result"; 4 | assertEq((|| result)(), "result"); 5 | assertEq((|| || || result)()()(), "result"); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/extra_arguments.lay: -------------------------------------------------------------------------------- 1 | let f = |a, b| { 2 | print(a); 3 | print(b); 4 | }; 5 | 6 | f(1, 2, 3, 4); // expect runtime error: Expected 2 arguments but got 4. 7 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/local_mutual_recursion.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let isEven = |n| { 3 | if n == 0 { return true; } 4 | return isOdd(n - 1); // expect runtime error: Undefined variable 'isOdd'. 5 | }; 6 | 7 | let isOdd = |n| isEven(n - 1); 8 | 9 | isEven(4); 10 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/local_recursion.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let fib = |n| { 3 | if n < 2 { return n; } 4 | return fib(n - 1) + fib(n - 2); 5 | }; 6 | 7 | assertEq(fib(8), 21); // expect: 21 8 | } 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/missing_arguments.lay: -------------------------------------------------------------------------------- 1 | let f = |a, b| {}; 2 | 3 | f(1); // expect runtime error: Expected 2 arguments but got 1. 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/missing_comma_in_parameters.lay: -------------------------------------------------------------------------------- 1 | // [line 3] Error at 'c': Expect ')' after parameters. 2 | // [c line 4] Error at end: Expect '}' after block. 3 | let foo = |a, b c, d, e, f| {} 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/mutual_recursion.lay: -------------------------------------------------------------------------------- 1 | let isEven = |n| { 2 | if n == 0 { return true; } 3 | return isOdd(n - 1); 4 | }; 5 | 6 | let isOdd = |n| { 7 | return isEven(n - 1); 8 | }; 9 | 10 | assert(isEven(4)); 11 | assert(isOdd(3)); 12 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/recursion.lay: -------------------------------------------------------------------------------- 1 | let fib = |n| { 2 | if n < 2 { return n; } 3 | return fib(n - 1) + fib(n - 2); 4 | }; 5 | 6 | assertEq(fib(8), 21); 7 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/lambda/str.lay: -------------------------------------------------------------------------------- 1 | let foo = || {}; 2 | assert(foo.str().has(" 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/method/refer_to_name.lay: -------------------------------------------------------------------------------- 1 | class Foo { 2 | method() { 3 | print(method); // expect runtime error: Undefined variable 'method'. 4 | } 5 | } 6 | 7 | Foo().method(); 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/native/assert.lay: -------------------------------------------------------------------------------- 1 | assert(true); 2 | assert(!false); 3 | assert(1 == 1); 4 | assert(!nil); 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/native/assert_eq.lay: -------------------------------------------------------------------------------- 1 | assertEq(true, true); 2 | assertEq(10, 10); 3 | assertEq("cat", "cat"); 4 | 5 | fn a() {} 6 | assertEq(a, a); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/native/assert_ne.lay: -------------------------------------------------------------------------------- 1 | assertNe(true, false); 2 | assertNe(10, 3); 3 | assertNe("cat", "cats"); 4 | 5 | fn a() {} 6 | fn b() {} 7 | assertNe(a, b); 8 | 9 | assertNe(true, 10); 10 | assertNe(b, "cat"); 11 | assertNe(3, a); 12 | assertNe("cats", 20); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/native/clock.lay: -------------------------------------------------------------------------------- 1 | let start = clock(); 2 | assert(clock() - start > 0); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/native/signature_fixed_arity.lay: -------------------------------------------------------------------------------- 1 | let list = []; 2 | try { 3 | list.insert(); 4 | assert(false); 5 | } catch e: Error { 6 | assert(true); 7 | } 8 | 9 | try { 10 | list.pop(10); 11 | assert(false); 12 | } catch e: Error { 13 | assert(true); 14 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/native/signature_type.lay: -------------------------------------------------------------------------------- 1 | let list = []; 2 | 3 | try { 4 | list.insert(true, 10); 5 | assert(false); 6 | } catch e: Error { 7 | assert(true); 8 | } 9 | 10 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/nil/literal.lay: -------------------------------------------------------------------------------- 1 | assertEq(nil, nil); // expect: nil 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/number/decimal_point_at_eof.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at end: Expect property name after '.'. 2 | 123. -------------------------------------------------------------------------------- /laythe_vm/fixture/language/number/leading_dot.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at '.': Expect expression. 2 | .123; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/number/literals.lay: -------------------------------------------------------------------------------- 1 | assertEq(123, 100 + 23); // expect: 123 2 | assertEq(987654, 987650 + 4); // expect: 987654 3 | assertEq(0, 2 -2); // expect: 0 4 | assertEq(-0, 0 * -1); // expect: -0 5 | 6 | assertEq(123.456, 123456 / 1000); // expect: 123.456 7 | assertEq(-0.001, 0 - 0.001); // expect: -0.001 8 | assertEq(3e3, 3000); 9 | assertEq(9e+0, 9); 10 | assertEq(1.4e-2, 0.014); 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/number/trailing_dot.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at ';': Expect property name after '.'. 2 | 123.; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/add.lay: -------------------------------------------------------------------------------- 1 | assertEq(123 + 456, 579); // expect: 579 2 | assertEq("str" + "ing", "string"); // expect: string 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/add_bool_nil.lay: -------------------------------------------------------------------------------- 1 | true + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/add_bool_num.lay: -------------------------------------------------------------------------------- 1 | true + 123; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/add_bool_string.lay: -------------------------------------------------------------------------------- 1 | true + "s"; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/add_nil_nil.lay: -------------------------------------------------------------------------------- 1 | nil + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/add_num_nil.lay: -------------------------------------------------------------------------------- 1 | 1 + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/add_string_nil.lay: -------------------------------------------------------------------------------- 1 | "s" + nil; // expect runtime error: Operands must be two numbers or two strings. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/divide.lay: -------------------------------------------------------------------------------- 1 | assertEq(8 / 2, 4); // expect: 4 2 | assertEq(12.34 / 12.34, 1); // expect: 1 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/divide_nonnum_num.lay: -------------------------------------------------------------------------------- 1 | "1" / 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/divide_num_nonnum.lay: -------------------------------------------------------------------------------- 1 | 1 / "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/equals.lay: -------------------------------------------------------------------------------- 1 | assert(nil == nil); // expect: true 2 | 3 | assert(true == true); // expect: true 4 | assertEq(true == false, false); // expect: false 5 | 6 | assert(1 == 1); // expect: true 7 | assertEq(1 == 2, false); // expect: false 8 | 9 | assert("str" == "str"); // expect: true 10 | assertEq("str" == "ing", false); // expect: false 11 | 12 | assertEq(nil == false, false); // expect: false 13 | assertEq(false == 0, false); // expect: false 14 | assertEq(0 == "0", false); // expect: false 15 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/equals_class.lay: -------------------------------------------------------------------------------- 1 | // Bound methods have identity equality. 2 | class Foo {} 3 | class Bar {} 4 | 5 | assert(Foo == Foo); // expect: true 6 | assertEq(Foo == Bar, false); // expect: false 7 | assertEq(Bar == Foo, false); // expect: false 8 | assert(Bar == Bar); // expect: true 9 | 10 | assertEq(Foo == "Foo", false); // expect: false 11 | assertEq(Foo == nil, false); // expect: false 12 | assertEq(Foo == 123, false); // expect: false 13 | assertEq(Foo == true, false); // expect: false 14 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/equals_method.lay: -------------------------------------------------------------------------------- 1 | // Bound methods have identity equality. 2 | class Foo { 3 | method() {} 4 | } 5 | 6 | let foo = Foo(); 7 | let fooMethod = foo.method; 8 | 9 | // Same bound method. 10 | assert(fooMethod == fooMethod); // expect: true 11 | 12 | // Different closurizations. 13 | assertEq(foo.method == foo.method, false); // expect: false 14 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/greater_nonnum_num.lay: -------------------------------------------------------------------------------- 1 | "1" > 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/greater_num_nonnum.lay: -------------------------------------------------------------------------------- 1 | 1 > "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/greater_or_equal_nonnum_num.lay: -------------------------------------------------------------------------------- 1 | "1" >= 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/greater_or_equal_num_nonnum.lay: -------------------------------------------------------------------------------- 1 | 1 >= "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/less_nonnum_num.lay: -------------------------------------------------------------------------------- 1 | "1" < 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/less_num_nonnum.lay: -------------------------------------------------------------------------------- 1 | 1 < "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/less_or_equal_nonnum_num.lay: -------------------------------------------------------------------------------- 1 | "1" <= 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/less_or_equal_num_nonnum.lay: -------------------------------------------------------------------------------- 1 | 1 <= "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/multiply.lay: -------------------------------------------------------------------------------- 1 | assertEq(5 * 3, 15); // expect: 15 2 | assertEq(12.34 * 0.3, 3.702); // expect: 3.702 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/multiply_nonnum_num.lay: -------------------------------------------------------------------------------- 1 | "1" * 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/multiply_num_nonnum.lay: -------------------------------------------------------------------------------- 1 | 1 * "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/negate.lay: -------------------------------------------------------------------------------- 1 | assertEq(-(3), -3); // expect: -3 2 | assertEq(--(3), 3); // expect: 3 3 | assertEq(---(3), -3); // expect: -3 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/negate_nonnum.lay: -------------------------------------------------------------------------------- 1 | -"s"; // expect runtime error: Operand must be a number. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/not.lay: -------------------------------------------------------------------------------- 1 | assertEq(!true, false); // expect: false 2 | assert(!false); // expect: true 3 | assert(!!true); // expect: true 4 | 5 | assertEq(!123, false); // expect: false 6 | assertEq(!0, false); // expect: false 7 | 8 | assert(!nil); // expect: true 9 | 10 | assertEq(!"", false); // expect: false 11 | 12 | fn foo() {} 13 | assertEq(!foo, false); // expect: false 14 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/not_class.lay: -------------------------------------------------------------------------------- 1 | class Bar {} 2 | assertEq(!Bar, false); // expect: false 3 | assertEq(!Bar(), false); // expect: false 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/not_equals.lay: -------------------------------------------------------------------------------- 1 | assertEq(nil != nil, false); // expect: false 2 | 3 | assertEq(true != true, false); // expect: false 4 | assert(true != false); // expect: true 5 | 6 | assertEq(1 != 1, false); // expect: false 7 | assert(1 != 2); // expect: true 8 | 9 | assertEq("str" != "str", false); // expect: false 10 | assert("str" != "ing"); // expect: true 11 | 12 | assert(nil != false); // expect: true 13 | assert(false != 0); // expect: true 14 | assert(0 != "0"); // expect: true 15 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/subtract.lay: -------------------------------------------------------------------------------- 1 | assertEq(4 - 3, 1); // expect: 1 2 | assertEq(1.2 - 1.2, 0); // expect: 0 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/subtract_nonnum_num.lay: -------------------------------------------------------------------------------- 1 | "1" - 1; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/operator/subtract_num_nonnum.lay: -------------------------------------------------------------------------------- 1 | 1 - "1"; // expect runtime error: Operands must be numbers. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/raise/no_expr.lay: -------------------------------------------------------------------------------- 1 | raise -------------------------------------------------------------------------------- /laythe_vm/fixture/language/raise/no_semi.lay: -------------------------------------------------------------------------------- 1 | raise Error("cool") -------------------------------------------------------------------------------- /laythe_vm/fixture/language/raise/not_error_subclass.lay: -------------------------------------------------------------------------------- 1 | class A {} 2 | 3 | raise A(); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/raise/not_instance.lay: -------------------------------------------------------------------------------- 1 | raise 10; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/raise/raise_error.lay: -------------------------------------------------------------------------------- 1 | try { 2 | raise RuntimeError("example"); 3 | assert(false); 4 | } catch e: RuntimeError { 5 | assertEq(e.message, "example"); 6 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/raise/raise_error_subclass.lay: -------------------------------------------------------------------------------- 1 | class MyError: Error {} 2 | 3 | try { 4 | let error = MyError("example"); 5 | assertEq(error.message, "example"); 6 | 7 | raise error; 8 | assert(false); 9 | } catch _ { 10 | assert(true); 11 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/regression/394.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | class A {} 3 | class B : A {} 4 | assert(B.str().has(" 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/static_method/refer_to_name.lay: -------------------------------------------------------------------------------- 1 | class Foo { 2 | static method() { 3 | print(method); // expect runtime error: Undefined variable 'method'. 4 | } 5 | } 6 | 7 | Foo.method(); 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/error_after_multiline.lay: -------------------------------------------------------------------------------- 1 | // Tests that we correctly track the line info across multiline strings. 2 | let a = "1 3 | 2 4 | 3 5 | "; 6 | 7 | let b = '1 8 | 2 9 | 3 10 | '; 11 | 12 | err; // expect runtime error: Undefined variable 'err'. -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/escape.lay: -------------------------------------------------------------------------------- 1 | assertEq(' 2 | ', '\n'); 3 | assertEq('\t', ' '); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/interpolation.lay: -------------------------------------------------------------------------------- 1 | assertEq('${10}', '10'); 2 | assertEq('${'test'}', 'test'); 3 | 4 | let firstName = 'Joe'; 5 | let lastName = 'Dirt'; 6 | let age = 35; 7 | assertEq('${'${firstName} ${lastName}'} ${age}', 'Joe Dirt 35'); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/invalid_escape.lay: -------------------------------------------------------------------------------- 1 | "\q"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/invalid_interpolation_missing_close.lay: -------------------------------------------------------------------------------- 1 | '${10' -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/invalid_unicode_hex.lay: -------------------------------------------------------------------------------- 1 | "\u{x}"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/invalid_unicode_missing_close.lay: -------------------------------------------------------------------------------- 1 | "\u{1"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/invalid_unicode_missing_open.lay: -------------------------------------------------------------------------------- 1 | "\u"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/invalid_unicode_no_hex.lay: -------------------------------------------------------------------------------- 1 | "\u{}"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/invalid_unicode_too_long.lay: -------------------------------------------------------------------------------- 1 | "\u{1111111}"; -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/literals.lay: -------------------------------------------------------------------------------- 1 | assertEq("(" + "" + ")", "()"); // expect: () 2 | assertEq('(' + '' + ')', '()'); 3 | assertEq("a string", "a string"); // expect: a string 4 | assertEq('a string', 'a string'); // expect: a string 5 | 6 | // Non-ASCII. 7 | assertEq("A~¶Þॐஃ", "A~¶Þॐஃ"); // expect: A~¶Þॐஃ 8 | assertEq('A~¶Þॐஃ', 'A~¶Þॐஃ'); // expect: A~¶Þॐஃ 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/multiline.lay: -------------------------------------------------------------------------------- 1 | let a = "1 2 | 2 3 | 3"; 4 | let b = '1 5 | 2 6 | 3'; 7 | assertEq(a, b); 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/unicode_escape.lay: -------------------------------------------------------------------------------- 1 | assertEq("\u{1F4AF}", "💯"); 2 | assertEq("\u{1F44D}", "👍"); 3 | assertEq("\u{3B1}", "α"); 4 | assertEq("\u{1185}", "ᆅ"); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/unterminated_double.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error: Unterminated string. 2 | "self string has no close quote -------------------------------------------------------------------------------- /laythe_vm/fixture/language/string/unterminated_single.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error: Unterminated string. 2 | 'self string has no close quote -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/bound_method.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | method(arg) { 3 | return "A.method(" + arg + ")"; 4 | } 5 | } 6 | 7 | class B : A { 8 | getClosure() { 9 | return super.method; 10 | } 11 | 12 | method(arg) { 13 | return "B.method(" + arg + ")"; 14 | } 15 | } 16 | 17 | 18 | let closure = B().getClosure(); 19 | assertEq(closure("arg"), "A.method(arg)"); // expect: A.method(arg) 20 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/call_other_method.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo() { 3 | print("Base.foo()"); 4 | } 5 | } 6 | 7 | class Derived : Base { 8 | bar() { 9 | print("Derived.bar()"); 10 | super.foo(); 11 | } 12 | } 13 | 14 | Derived().bar(); 15 | // expect: Derived.bar() 16 | // expect: Base.foo() 17 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/call_same_method.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo() { 3 | print("Base.foo()"); 4 | } 5 | } 6 | 7 | class Derived : Base { 8 | foo() { 9 | print("Derived.foo()"); 10 | super.foo(); 11 | } 12 | } 13 | 14 | Derived().foo(); 15 | // expect: Derived.foo() 16 | // expect: Base.foo() 17 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/closure.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | toString() { return "Base"; } 3 | } 4 | 5 | class Derived : Base { 6 | getClosure() { 7 | fn closure() { 8 | return super.toString(); 9 | } 10 | return closure; 11 | } 12 | 13 | toString() { return "Derived"; } 14 | } 15 | 16 | let closure = Derived().getClosure(); 17 | assertEq(closure(), "Base"); // expect: Base 18 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/constructor.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | init(a, b) { 3 | print("Base.init(${a}, ${b})"); 4 | } 5 | } 6 | 7 | class Derived : Base { 8 | init() { 9 | print("Derived.init()"); 10 | super.init("a", "b"); 11 | } 12 | } 13 | 14 | Derived(); 15 | // expect: Derived.init() 16 | // expect: Base.init(a, b) 17 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/extra_arguments.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo(a, b) { 3 | print("Base.foo(" + a + ", " + b + ")"); 4 | } 5 | } 6 | 7 | class Derived : Base { 8 | foo() { 9 | print("Derived.foo()"); // expect: Derived.foo() 10 | super.foo("a", "b", "c", "d"); // expect runtime error: Expected 2 arguments but got 4. 11 | } 12 | } 13 | 14 | Derived().foo(); 15 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/indirectly_inherited.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | foo() { 3 | print("A.foo()"); 4 | } 5 | } 6 | 7 | class B : A {} 8 | 9 | class C : B { 10 | foo() { 11 | print("C.foo()"); 12 | super.foo(); 13 | } 14 | } 15 | 16 | C().foo(); 17 | // expect: C.foo() 18 | // expect: A.foo() 19 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/missing_arguments.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo(a, b) { 3 | print("Base.foo(" + a + ", " + b + ")"); 4 | } 5 | } 6 | 7 | class Derived : Base { 8 | foo() { 9 | super.foo(1); // expect runtime error: Expected 2 arguments but got 1. 10 | } 11 | } 12 | 13 | Derived().foo(); 14 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/no_superclass_call.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | foo() { 3 | super.doesNotExist(1); // Error at 'super': Cannot use 'super' in a class with no superclass. 4 | } 5 | } 6 | 7 | Base().foo(); 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/no_superclass_method.lay: -------------------------------------------------------------------------------- 1 | class Base {} 2 | 3 | class Derived : Base { 4 | foo() { 5 | super.doesNotExist(1); // expect runtime error: Undefined property 'doesNotExist'. 6 | } 7 | } 8 | 9 | Derived().foo(); 10 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/parenthesized.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | method() {} 3 | } 4 | 5 | class B : A { 6 | method() { 7 | // [line 8] Error at ')': Expect '.' after 'super'. 8 | (super).method(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/reassign_superclass.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | method() { 3 | return "Base.method()"; 4 | } 5 | } 6 | 7 | class Derived : Base { 8 | method() { 9 | return super.method(); 10 | } 11 | } 12 | 13 | class OtherBase { 14 | method() { 15 | return "OtherBase.method()"; 16 | } 17 | } 18 | 19 | let derived = Derived(); 20 | assertEq(derived.method(), "Base.method()"); // expect: Base.method() 21 | Base = OtherBase; 22 | assertEq(derived.method(), "Base.method()"); // expect: Base.method() 23 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/super_at_top_level.lay: -------------------------------------------------------------------------------- 1 | super.foo; // Error at 'super': Cannot use 'super' outside of a class. 2 | super.foo("bar"); // Error at 'super': Cannot use 'super' outside of a class. 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/super_in_closure_in_inherited_method.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | say() { 3 | print("A"); 4 | } 5 | } 6 | 7 | class B : A { 8 | getClosure() { 9 | fn closure() { 10 | super.say(); 11 | } 12 | return closure; 13 | } 14 | 15 | say() { 16 | print("B"); 17 | } 18 | } 19 | 20 | class C : B { 21 | say() { 22 | print("C"); 23 | } 24 | } 25 | 26 | C().getClosure()(); // expect: A 27 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/super_in_inherited_method.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | say() { 3 | return "A"; 4 | } 5 | } 6 | 7 | class B : A { 8 | test() { 9 | return super.say(); 10 | } 11 | 12 | say() { 13 | return "B"; 14 | } 15 | } 16 | 17 | class C : B { 18 | say() { 19 | return "C"; 20 | } 21 | } 22 | 23 | assertEq(C().test(), "A"); // expect: A 24 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/super_in_top_level_function.lay: -------------------------------------------------------------------------------- 1 | fn foo() { 2 | super.bar(); // Error at 'super': Cannot use 'super' outside of a class. 3 | } 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/super_without_dot.lay: -------------------------------------------------------------------------------- 1 | class A {} 2 | 3 | class B : A { 4 | method() { 5 | // [line 6] Error at ';': Expect '.' after 'super'. 6 | super; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/super_without_name.lay: -------------------------------------------------------------------------------- 1 | class A {} 2 | 3 | class B : A { 4 | method() { 5 | super.; // Error at ';': Expect superclass method name. 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/super/this_in_superclass_method.lay: -------------------------------------------------------------------------------- 1 | class Base { 2 | init(a) { 3 | self.a = a; 4 | } 5 | } 6 | 7 | class Derived : Base { 8 | init(a, b) { 9 | super.init(a); 10 | self.b = b; 11 | } 12 | } 13 | 14 | let derived = Derived("a", "b"); 15 | assertEq(derived.a, "a"); // expect: a 16 | assertEq(derived.b, "b"); // expect: b 17 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/tuple/empty.lay: -------------------------------------------------------------------------------- 1 | assertEq(().cls(), Tuple); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/tuple/empty_comma.lay: -------------------------------------------------------------------------------- 1 | (,); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/tuple/homogeneous.lay: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | 3 | assertEq((true, false).cls(), Tuple); 4 | assertEq((1, 2, 3, 4).cls(), Tuple); 5 | assertEq(("John", "Jain", "Mary").cls(), Tuple); 6 | assertEq((Foo(), Foo(), Foo()).cls(), Tuple); 7 | assertEq((clock, clock, clock).cls(), Tuple); 8 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/tuple/missing_closing_bracket.lay: -------------------------------------------------------------------------------- 1 | let a = (1, 2, 3 -------------------------------------------------------------------------------- /laythe_vm/fixture/language/tuple/missing_comma_in_initializer.lay: -------------------------------------------------------------------------------- 1 | // [line 3] Error at 'c': Expect ']' after arguments. 2 | let a = (a, b c, d, e, f); 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/tuple/mixed.lay: -------------------------------------------------------------------------------- 1 | assertEq((nil, true, 10.3, "cat").cls(), Tuple); -------------------------------------------------------------------------------- /laythe_vm/fixture/language/unexpected_character.lay: -------------------------------------------------------------------------------- 1 | // [line 3] Error: Unexpected character. 2 | // [java line 3] Error at 'b': Expect ')' after arguments. 3 | foo(a | b); 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/collide_with_parameter.lay: -------------------------------------------------------------------------------- 1 | fn foo(a) { 2 | let a; // Error at 'a': variable with self name already declared in self scope. 3 | } 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/duplicate_local.lay: -------------------------------------------------------------------------------- 1 | { 2 | let a = "value"; 3 | let a = "other"; // Error at 'a': variable with self name already declared in self scope. 4 | } 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/duplicate_parameter.lay: -------------------------------------------------------------------------------- 1 | fn foo(arg, 2 | arg) { // Error at 'arg': variable with self name already declared in self scope. 3 | "body"; 4 | } 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/early_bound.lay: -------------------------------------------------------------------------------- 1 | let a = "outer"; 2 | if true { 3 | fn foo() { 4 | return a; 5 | } 6 | 7 | assertEq(foo(), "outer"); // expect: outer 8 | let a = "inner"; 9 | assertEq(foo(), "outer"); // expect: outer 10 | } 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/in_middle_of_block.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let a = "a"; 3 | assertEq(a, "a"); // expect: a 4 | let b = a + " b"; 5 | assertEq(b, "a b"); // expect: a b 6 | let c = a + " c"; 7 | assertEq(c, "a c"); // expect: a c 8 | let d = b + " d"; 9 | assertEq(d, "a b d"); // expect: a b d 10 | } 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/in_nested_block.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let a = "outer"; 3 | if true { 4 | assertEq(a, "outer"); // expect: outer 5 | } 6 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/local_from_method.lay: -------------------------------------------------------------------------------- 1 | let foo = "variable"; 2 | 3 | class Foo { 4 | method() { 5 | print(foo); 6 | } 7 | } 8 | 9 | Foo().method(); // expect: variable 10 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/redeclare_global.lay: -------------------------------------------------------------------------------- 1 | let a = "1"; 2 | let a; 3 | assertEq(a, nil); // expect: nil 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/redefine_global.lay: -------------------------------------------------------------------------------- 1 | let a = "1"; 2 | let a = "2"; 3 | assertEq(a, "2"); // expect: 2 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/scope_reuse_in_different_blocks.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let a = "first"; 3 | assertEq(a, "first"); // expect: first 4 | } 5 | 6 | if true { 7 | let a = "second"; 8 | assertEq(a, "second"); // expect: second 9 | } 10 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/shadow_and_local.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let a = "outer"; 3 | if true { 4 | assertEq(a, "outer"); // expect: outer 5 | let a = "inner"; 6 | assertEq(a, "inner"); // expect: inner 7 | } 8 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/shadow_global.lay: -------------------------------------------------------------------------------- 1 | let a = "global"; 2 | if true { 3 | let a = "shadow"; 4 | assertEq(a, "shadow"); // expect: shadow 5 | } 6 | assertEq(a, "global"); // expect: global 7 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/shadow_local.lay: -------------------------------------------------------------------------------- 1 | if true { 2 | let a = "local"; 3 | if true { 4 | let a = "shadow"; 5 | assertEq(a, "shadow"); // expect: shadow 6 | } 7 | assertEq(a, "local"); // expect: local 8 | } 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/undefined_global.lay: -------------------------------------------------------------------------------- 1 | print(notDefined); // expect runtime error: Undefined variable 'notDefined'. 2 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/undefined_local.lay: -------------------------------------------------------------------------------- 1 | :{ 2 | print(notDefined); // expect runtime error: Undefined variable 'notDefined'. 3 | }; 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/uninitialized.lay: -------------------------------------------------------------------------------- 1 | let a; 2 | assertEq(a, nil); // expect: nil 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/unreached_undefined.lay: -------------------------------------------------------------------------------- 1 | if false { 2 | print(notDefined); 3 | } 4 | 5 | print("ok"); // expect: ok 6 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/use_false_as_var.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'false': Expect variable name. 2 | let false = "value"; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/use_global_in_initializer.lay: -------------------------------------------------------------------------------- 1 | let a = "value"; 2 | let a = a; 3 | assertEq(a, "value"); // expect: value 4 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/use_local_in_initializer.lay: -------------------------------------------------------------------------------- 1 | let a = "outer"; 2 | { 3 | let a = a; // Error at 'a': Cannot read local variable in its own initializer. 4 | } 5 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/use_nil_as_var.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'nil': Expect variable name. 2 | let nil = "value"; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/variable/use_this_as_var.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'self': Expect variable name. 2 | let self = "value"; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/while/class_in_body.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'class': Expect expression. 2 | while (true) class Foo {} 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/while/closure_in_body.lay: -------------------------------------------------------------------------------- 1 | let f1; 2 | let f2; 3 | let f3; 4 | 5 | let i = 1; 6 | while i < 4 { 7 | let j = i; 8 | fn f() { return j; } 9 | 10 | if j == 1 { f1 = f; } 11 | else if j == 2 { f2 = f; } 12 | else { f3 = f; } 13 | 14 | i = i + 1; 15 | } 16 | 17 | assertEq(f1(), 1); // expect: 1 18 | assertEq(f2(), 2); // expect: 2 19 | assertEq(f3(), 3); // expect: 3 20 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/while/fun_in_body.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'fun': Expect expression. 2 | while true) fn foo( {} 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/while/return_closure.lay: -------------------------------------------------------------------------------- 1 | fn f() { 2 | while true { 3 | let i = "i"; 4 | fn g() { return i; } 5 | return g; 6 | } 7 | } 8 | 9 | let h = f(); 10 | assertEq(h(), "i"); // expect: i 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/while/return_inside.lay: -------------------------------------------------------------------------------- 1 | fn f() { 2 | while true { 3 | let i = "i"; 4 | return i; 5 | } 6 | } 7 | 8 | assertEq(f(), "i"); // expect: i 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/while/syntax.lay: -------------------------------------------------------------------------------- 1 | // Single-expression body. 2 | let c = 0; 3 | while c < 3 { print(c = c + 1); } 4 | // expect: 1 5 | // expect: 2 6 | // expect: 3 7 | 8 | // Block body. 9 | let a = 0; 10 | while a < 3 { 11 | print(a); 12 | a = a + 1; 13 | } 14 | // expect: 0 15 | // expect: 1 16 | // expect: 2 17 | 18 | // Statement bodies. 19 | while false { if true { 1; } else { 2; } } 20 | while false { while true { 1; } } 21 | while false { for i in [1] { 1; } } 22 | -------------------------------------------------------------------------------- /laythe_vm/fixture/language/while/var_in_body.lay: -------------------------------------------------------------------------------- 1 | // [line 2] Error at 'let': Expect expression. 2 | while (true) let foo; 3 | -------------------------------------------------------------------------------- /laythe_vm/fixture/py_benchmark/fib.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | def fib(n): 4 | if n < 2: 5 | return n 6 | return fib(n - 2) + fib(n - 1) 7 | 8 | 9 | start = time.time() 10 | print(fib(35) == 9227465) 11 | print(time.time() - start) 12 | -------------------------------------------------------------------------------- /laythe_vm/fixture/py_benchmark/list.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | start = time.time() 4 | 5 | for i in range(10000): 6 | collection = [] 7 | for j in range(1000): 8 | collection.append(None) 9 | collection[j] = j 10 | 11 | sum = 0 12 | for j in range(1000): 13 | sum = sum + collection[1000 - j - 1] 14 | collection.pop() 15 | 16 | print(time.time() - start) 17 | -------------------------------------------------------------------------------- /laythe_vm/fixture/rb_benchmark/fib.rb: -------------------------------------------------------------------------------- 1 | def fib(n) 2 | return n if n < 2 3 | fib(n - 2) + fib(n - 1) 4 | end 5 | 6 | start = Time.new 7 | puts fib(35) == 9227465 8 | puts Time.new - start -------------------------------------------------------------------------------- /laythe_vm/fixture/rb_benchmark/list.rb: -------------------------------------------------------------------------------- 1 | start = Time.new 2 | 3 | 10000.times do |i| 4 | collection = [] 5 | 1000.times do |j| 6 | collection.push(nil) 7 | collection[j] = j 8 | end 9 | 10 | sum = 0 11 | 1000.times do |j| 12 | sum = sum + collection[1000 - j - 1] 13 | collection.pop 14 | end 15 | end 16 | 17 | puts Time.new - start -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/env/args.lay: -------------------------------------------------------------------------------- 1 | import std.env; 2 | 3 | assert(env.args().len() > 0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/env/cwd.lay: -------------------------------------------------------------------------------- 1 | import std.env; 2 | 3 | assert(env.cwd().has("Laythe/laythe_vm")); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/bool/str.lay: -------------------------------------------------------------------------------- 1 | let x1 = true; 2 | let x2 = false; 3 | 4 | assertEq(true.str(), "true"); 5 | assertEq(false.str(), "false"); 6 | 7 | assertEq(x1.str(), "true"); 8 | assertEq(x2.str(), "false"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/channel/capacity.lay: -------------------------------------------------------------------------------- 1 | assertEq(chan().capacity(), 1); 2 | assertEq(chan(3).capacity(), 3); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/channel/close.lay: -------------------------------------------------------------------------------- 1 | assertEq(chan().close(), nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/channel/close_close.lay: -------------------------------------------------------------------------------- 1 | chan().close().close(); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/channel/len.lay: -------------------------------------------------------------------------------- 1 | let x = chan(10); 2 | 3 | assertEq(x.len(), 0); 4 | 5 | x <- 1; 6 | x <- 1; 7 | x <- 1; 8 | 9 | assertEq(x.len(), 3); 10 | 11 | <- x; 12 | <- x; 13 | 14 | assertEq(x.len(), 1); 15 | 16 | -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/channel/str.lay: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Laythe-lang/Laythe/c2e53a1ae3618d3cd944f95fd2f51000009e93da/laythe_vm/fixture/std_lib/global/channel/str.lay -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/class/name.lay: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | assertEq(Foo.name(), "Foo"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/class/str.lay: -------------------------------------------------------------------------------- 1 | class Foo {} 2 | assert(Foo.str().has('Foo')); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/class/superCls.lay: -------------------------------------------------------------------------------- 1 | class A {} 2 | class B : A {} 3 | 4 | assertEq(B.superCls(), A); 5 | assertEq(B.superCls().superCls(), Object); 6 | 7 | assertEq(A.superCls(), Object); 8 | 9 | assertEq(List.superCls(), Object); 10 | assertEq(Object.superCls(), nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/closure/call.lay: -------------------------------------------------------------------------------- 1 | let y; 2 | fn inner(value) { 3 | y; 4 | return value * 2; 5 | } 6 | 7 | fn outer(name) { 8 | y; 9 | print(name); 10 | return inner; 11 | } 12 | 13 | assertEq(outer.call("hi"), inner); 14 | assertEq(inner.call(10), 20); 15 | assertEq(outer.call("hi").call(5), 10); 16 | -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/closure/call_wrong_args.lay: -------------------------------------------------------------------------------- 1 | let x; 2 | fn f(x1, x2, x3) { 3 | print(x1); 4 | print(x2); 5 | print(x3); 6 | x 7 | } 8 | 9 | f.call(1, 2); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/closure/len.lay: -------------------------------------------------------------------------------- 1 | let y; 2 | fn f1(x1, x2, x3) { 3 | y; 4 | print(x1); 5 | print(x2); 6 | print(x3); 7 | } 8 | 9 | fn f2(x) { 10 | y; 11 | print(x); 12 | } 13 | 14 | assertEq(f1.len(), 3); 15 | assertEq(f2.len(), 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/closure/len_wrong_args.lay: -------------------------------------------------------------------------------- 1 | let y; 2 | fn f(x) { 3 | y; 4 | print(x); 5 | } 6 | 7 | f.len(10); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/closure/name.lay: -------------------------------------------------------------------------------- 1 | let y; 2 | fn first() { y; } 3 | fn second() { y; } 4 | 5 | let assigned = first; 6 | 7 | assertEq(first.name(), "first"); 8 | assertEq(second.name(), "second"); 9 | assertEq(assigned.name(), "first"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/closure/name_wrong_args.lay: -------------------------------------------------------------------------------- 1 | let y; 2 | fn example(x) { 3 | y; 4 | return x; 5 | } 6 | 7 | example.name("hi"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/error/construct.lay: -------------------------------------------------------------------------------- 1 | let error1 = Error("broken"); 2 | let error2 = Error("broken again", error1); 3 | 4 | assertEq(error1.message, "broken"); 5 | assertEq(error1.inner, nil); 6 | assertEq(error1.backTrace.cls(), List); 7 | assertEq(error1.backTrace.len(), 0); 8 | 9 | assertEq(error2.message, "broken again"); 10 | assertEq(error2.inner, error1); 11 | assertEq(error1.backTrace.len(), 0); 12 | -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/fun/call.lay: -------------------------------------------------------------------------------- 1 | fn inner(value) { 2 | return value * 2; 3 | } 4 | 5 | fn outer(name) { 6 | print(name); 7 | return inner; 8 | } 9 | 10 | assertEq(outer.call("hi"), inner); 11 | assertEq(inner.call(10), 20); 12 | assertEq(outer.call("hi").call(5), 10); 13 | -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/fun/call_wrong_args.lay: -------------------------------------------------------------------------------- 1 | fn f(x1, x2, x3) { 2 | print(x1); 3 | print(x2); 4 | print(x3); 5 | } 6 | 7 | f.call(1, 2); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/fun/len.lay: -------------------------------------------------------------------------------- 1 | fn f1(x1, x2, x3) { 2 | print(x1); 3 | print(x2); 4 | print(x3); 5 | } 6 | 7 | fn f2(x) { 8 | print(x); 9 | } 10 | 11 | assertEq(f1.len(), 3); 12 | assertEq(f2.len(), 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/fun/len_wrong_args.lay: -------------------------------------------------------------------------------- 1 | fn f(x) { 2 | print(x); 3 | } 4 | 5 | f.len(10); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/fun/name.lay: -------------------------------------------------------------------------------- 1 | fn first() {} 2 | fn second() {} 3 | 4 | let assigned = first; 5 | 6 | assertEq(first.name(), "first"); 7 | assertEq(second.name(), "second"); 8 | assertEq(assigned.name(), "first"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/fun/name_wrong_args.lay: -------------------------------------------------------------------------------- 1 | fn example(x) { 2 | return x; 3 | } 4 | 5 | example.name("hi"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/all.lay: -------------------------------------------------------------------------------- 1 | let ident = |x| x; 2 | assert([].iter().all(ident)); 3 | 4 | assert([true, true].iter().all(ident)); 5 | assert([false, false].iter().all(|x| !x)); 6 | 7 | assertEq([nil].iter().all(ident), false); 8 | 9 | assert(['cat', 'catDog'].iter().all(|x| x.has('cat'))); 10 | assert([10, 8].iter().all(|x| x >= 8)); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/any.lay: -------------------------------------------------------------------------------- 1 | let ident = |x| x; 2 | assertEq([].iter().any(ident), false); 3 | 4 | assert([false, true].iter().any(ident)); 5 | assert([true, false].iter().any(ident)); 6 | 7 | assert([nil, true].iter().any(ident)); 8 | 9 | assert(['cat', 'dog'].iter().any(|x| x.has('cat'))); 10 | assert([10, 8].iter().any(|x| x < 9)); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/each.lay: -------------------------------------------------------------------------------- 1 | let nums = [0, 1, 2]; 2 | nums.iter().each(|num| { assertEq(num, nums[num]); }); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/filter.lay: -------------------------------------------------------------------------------- 1 | let iter = { 2 | "key": 10, 3 | "bad key": 5, 4 | }.iter().filter(|x| x[0] == "key"); 5 | 6 | assertEq(iter.next(), true); 7 | assertEq(iter.current()[1], 10); 8 | 9 | assertEq(iter.next(), false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/filter_method.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | foo(x) { x[0] == "key" } 3 | } 4 | 5 | let iter = { 6 | "key": 10, 7 | "bad key": 5, 8 | }.iter().filter(A().foo); 9 | 10 | assertEq(iter.next(), true); 11 | assertEq(iter.current()[1], 10); 12 | 13 | assertEq(iter.next(), false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/first.lay: -------------------------------------------------------------------------------- 1 | let a = [1, 2, 3]; 2 | assertEq(a.iter().first(), 1); 3 | 4 | let b = {"example": nil}; 5 | assertEq(b.iter().first()[0], "example"); 6 | assertEq(b.iter().first()[1], nil); 7 | 8 | assertEq([].iter().first(), nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/into.lay: -------------------------------------------------------------------------------- 1 | fn makeIter() { 2 | return 10.times(); 3 | } 4 | 5 | fn sum(iter) { 6 | let sum = 0; 7 | for i in iter { 8 | sum = sum + i; 9 | } 10 | 11 | return sum; 12 | } 13 | 14 | let intoList = makeIter().into(List.collect); 15 | let total = makeIter().into(sum); 16 | 17 | assertEq(intoList[4], 4); 18 | assertEq(total, 45); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/iter.lay: -------------------------------------------------------------------------------- 1 | let iter = [1, 2, 3].iter(); 2 | assertEq(iter, iter.iter()); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/last.lay: -------------------------------------------------------------------------------- 1 | let a = [1, 2, 3]; 2 | assertEq(a.iter().last(), 3); 3 | 4 | let b = {"example": nil}; 5 | assertEq(b.iter().last()[0], "example"); 6 | assertEq(b.iter().last()[1], nil); 7 | 8 | assertEq([].iter().last(), nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/len.lay: -------------------------------------------------------------------------------- 1 | assertEq(10.times().len(), 10); 2 | assertEq(10.times().filter(|x| x).len(), 10); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/map.lay: -------------------------------------------------------------------------------- 1 | let iter = [1, 2, 3, 4].iter().map(|x| x / 2); 2 | 3 | assertEq(iter.next(), true); 4 | assertEq(iter.current(), 0.5); 5 | 6 | assertEq(iter.next(), true); 7 | assertEq(iter.current(), 1); 8 | 9 | assertEq(iter.next(), true); 10 | assertEq(iter.current(), 1.5); 11 | 12 | assertEq(iter.next(), true); 13 | assertEq(iter.current(), 2.0); 14 | 15 | assertEq(iter.next(), false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/map_method.lay: -------------------------------------------------------------------------------- 1 | class A { 2 | foo(x) { x / 2 } 3 | } 4 | 5 | let iter = [1, 2, 3, 4].iter().map(A().foo); 6 | 7 | assertEq(iter.next(), true); 8 | assertEq(iter.current(), 0.5); 9 | 10 | assertEq(iter.next(), true); 11 | assertEq(iter.current(), 1); 12 | 13 | assertEq(iter.next(), true); 14 | assertEq(iter.current(), 1.5); 15 | 16 | assertEq(iter.next(), true); 17 | assertEq(iter.current(), 2.0); 18 | 19 | assertEq(iter.next(), false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/next.lay: -------------------------------------------------------------------------------- 1 | let iter = [1, 2, 3, "false"].iter(); 2 | 3 | assertEq(iter.next(), true); 4 | assertEq(iter.current(), 1); 5 | 6 | assertEq(iter.next(), true); 7 | assertEq(iter.current(), 2); 8 | 9 | assertEq(iter.next(), true); 10 | assertEq(iter.current(), 3); 11 | 12 | assertEq(iter.next(), true); 13 | assertEq(iter.current(), "false"); 14 | 15 | assertEq(iter.next(), false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/reduce.lay: -------------------------------------------------------------------------------- 1 | assertEq(15, [1, 2, 3, 4, 5] 2 | .iter() 3 | .reduce(0, |acc, curr| acc + curr) 4 | ); 5 | assertEq("hello world!", ["hello", " ", "world", "!"] 6 | .iter() 7 | .reduce("", |acc, curr| acc + curr) 8 | ); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/iter/str.lay: -------------------------------------------------------------------------------- 1 | assertEq([].iter().str(), "List"); 2 | assertEq({}.iter().str(), "Map"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/clear.lay: -------------------------------------------------------------------------------- 1 | let x = [1, 2, 3]; 2 | x.clear(); 3 | assertEq(x.len(), 0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/collect.lay: -------------------------------------------------------------------------------- 1 | let l1 = List.collect(10.times()); 2 | let l2 = List.collect([1, 2, 3].iter()); 3 | let l3 = List.collect({ "dude": 1, "bro": 2, "cat": 3 }.iter()); 4 | 5 | assertEq(l1.len(), 10); 6 | assertEq(l2.len(), 3); 7 | assertEq(l3.len(), 3); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/has.lay: -------------------------------------------------------------------------------- 1 | let x = [1, 2, nil, false, "example"]; 2 | 3 | assertEq(x.has(2), true); 4 | assertEq(x.has("example"), true); 5 | assertEq(x.has(false), true); 6 | 7 | assertEq(x.has(true), false); 8 | assertEq(x.has("no present"), false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index.lay: -------------------------------------------------------------------------------- 1 | let l = [1, 2, 3, 4, 5]; 2 | 3 | assertEq(l.index(3), 2); 4 | assertEq(l.index(5), 4); 5 | assertEq(l.index(6), nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_get.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3, 4, "5"]; 2 | assertEq(list[0], 1); 3 | assertEq(list[1], 2); 4 | assertEq(list[2], 3); 5 | assertEq(list[3], 4); 6 | assertEq(list[4], "5"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_get_fractional.lay: -------------------------------------------------------------------------------- 1 | [1][0.5]; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_get_fractional_negative.lay: -------------------------------------------------------------------------------- 1 | [1][-0.5]; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_get_negative.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3, 4, "5"]; 2 | assertEq(list[-5], 1); 3 | assertEq(list[-4], 2); 4 | assertEq(list[-3], 3); 5 | assertEq(list[-2], 4); 6 | assertEq(list[-1], "5"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_get_nested.lay: -------------------------------------------------------------------------------- 1 | let list = [[1, 2, 3], ["cat", "dog"]]; 2 | 3 | assertEq(list[0][0], 1); 4 | assertEq(list[0][1], 2); 5 | assertEq(list[0][2], 3); 6 | 7 | assertEq(list[1][0], "cat"); 8 | assertEq(list[1][1], "dog"); 9 | -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_get_out_of_range.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3]; 2 | list[10]; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_get_out_of_range_negative.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3]; 2 | list[-5]; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3, 4, "5"]; 2 | assertEq(list[0], 1); 3 | 4 | list[0] = false; 5 | assertEq(list[0], false); 6 | 7 | list[3] = "dog"; 8 | assertEq(list[3], "dog"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set_fractional.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3, 4, "5"]; 2 | list[0.5]; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set_fractional_negative.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3, 4, "5"]; 2 | list[-0.5]; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set_negative.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3, 4, "5"]; 2 | assertEq(list[0], 1); 3 | 4 | list[-5] = false; 5 | assertEq(list[0], false); 6 | 7 | list[-3] = "dog"; 8 | assertEq(list[2], "dog"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set_nested.lay: -------------------------------------------------------------------------------- 1 | let list = [[1, 2, 3], ["cat", "dog"]]; 2 | 3 | list[0][2] = 20; 4 | assertEq(list[0][0], 1); 5 | assertEq(list[0][1], 2); 6 | assertEq(list[0][2], 20); 7 | 8 | list[1][0] = "rabbit"; 9 | assertEq(list[1][0], "rabbit"); 10 | assertEq(list[1][1], "dog"); 11 | -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set_out_of_range.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3]; 2 | list[10] = 'out of range'; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set_out_of_range_negative.lay: -------------------------------------------------------------------------------- 1 | let list = [1, 2, 3]; 2 | list[-5] = 'out of range'; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/index_set_pass_through.lay: -------------------------------------------------------------------------------- 1 | let a = [1, 2, 3]; 2 | a[0] = a[1] = 5; 3 | 4 | assertEq(a[0], 5); 5 | assertEq(a[1], 5); 6 | assertEq(a[2], 3); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/insert.lay: -------------------------------------------------------------------------------- 1 | let x = []; 2 | x.insert(0, "false"); 3 | 4 | assertEq(x.len(), 1); 5 | assertEq(x[0], "false"); 6 | 7 | x.insert(0, [1]); 8 | assertEq(x.len(), 2); 9 | assertEq(x[0][0], 1); 10 | 11 | x.insert(1, false); 12 | assertEq(x.len(), 3); 13 | assertEq(x[1], false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/insert_out_of_bounds.lay: -------------------------------------------------------------------------------- 1 | [].insert(1, true); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/len.lay: -------------------------------------------------------------------------------- 1 | assertEq([].len(), 0); 2 | assertEq([1, 2, 3].len(), 3); 3 | 4 | let x1 = []; 5 | let x2 = [1, 2, 3]; 6 | assertEq(x1.len(), 0); 7 | assertEq(x2.len(), 3); 8 | 9 | x1.push(1, 4); 10 | x2.remove(2); 11 | assertEq(x1.len(), 2); 12 | assertEq(x2.len(), 2); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/pop.lay: -------------------------------------------------------------------------------- 1 | let x = [1, 2, 3]; 2 | 3 | assertEq(x.pop(), 3); 4 | assertEq(x.pop(), 2); 5 | assertEq(x.pop(), 1); 6 | assertEq(x.pop(), nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/push.lay: -------------------------------------------------------------------------------- 1 | let a = [1, 2]; 2 | a.push(nil); 3 | assertEq(a.len(), 3); 4 | assertEq(a.str(), "[1, 2, nil]"); 5 | 6 | a.push("cat", -5); 7 | assertEq(a.len(), 5); 8 | assertEq(a.str(), "[1, 2, nil, 'cat', -5]"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/remove.lay: -------------------------------------------------------------------------------- 1 | let a = [true, false, nil]; 2 | assertEq(a.remove(1), false); 3 | assertEq(a.remove(1), nil); 4 | assertEq(a.remove(0), true); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/remove_out_of_bounds.lay: -------------------------------------------------------------------------------- 1 | [].remove(10); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/rev.lay: -------------------------------------------------------------------------------- 1 | let a = [1, 2, 3]; 2 | let b = a.rev(); 3 | 4 | assertEq(a[0], 1); 5 | assertEq(a[1], 2); 6 | assertEq(a[2], 3); 7 | 8 | assertEq(b[0], 3); 9 | assertEq(b[1], 2); 10 | assertEq(b[2], 1); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/slice.lay: -------------------------------------------------------------------------------- 1 | let a = [1, 2, 3]; 2 | let b = a.slice(); 3 | 4 | assertEq(b.len(), 3); 5 | assertEq(b[0], 1); 6 | assertEq(b[1], 2); 7 | assertEq(b[2], 3); 8 | 9 | let c = a.slice(-1); 10 | assertEq(c.len(), 1); 11 | assertEq(c[0], 3); 12 | 13 | let d = a.slice(1, 4); 14 | assertEq(c.len(), 1); 15 | assertEq(c[0], 3); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/sort.lay: -------------------------------------------------------------------------------- 1 | let a = [4, 3, 2, 1]; 2 | let b = ['d', 'b', 'c', 'a']; 3 | 4 | let c = a.sort(Number.cmp); 5 | let d = b.sort(|a, b| a < b); 6 | 7 | assertEq(c.len(), 4); 8 | assertEq(c[0], 1); 9 | assertEq(c[1], 2); 10 | assertEq(c[2], 3); 11 | assertEq(c[4], 4); 12 | 13 | assertEq(d.len(), 4); 14 | assertEq(d[0], 'a'); 15 | assertEq(d[1], 'b'); 16 | assertEq(d[2], 'c'); 17 | assertEq(d[4], 'd'); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/list/str.lay: -------------------------------------------------------------------------------- 1 | assertEq([1, 2, 3].str(), "[1, 2, 3]"); 2 | assertEq([false, nil, "hi"].str(), "[false, nil, 'hi']"); 3 | assertEq([[1, 2], { "cat": "dog" }].str(), "[[1, 2], { 'cat': 'dog' }]"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/get.lay: -------------------------------------------------------------------------------- 1 | fn example() {} 2 | 3 | let map = { 4 | "cat": true, 5 | "dog": true, 6 | "parrot": true, 7 | "rabbit": true, 8 | example: example, 9 | }; 10 | 11 | assert(map.get("cat")); 12 | assert(map.get("dog")); 13 | assert(map.get("parrot")); 14 | assert(map.get("rabbit")); 15 | assertEq(map.get(example), example); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/has.lay: -------------------------------------------------------------------------------- 1 | let map = { 2 | 1: 2, 3 | 2: 3, 4 | 4: 5, 5 | false: nil 6 | }; 7 | 8 | assert(map.has(1)); 9 | assert(map.has(2)); 10 | assert(map.has(4)); 11 | assert(map.has(false)); 12 | 13 | assert(!map.has(true)); 14 | assert(!map.has(15)); 15 | assert(!map.has("sup")); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_get.lay: -------------------------------------------------------------------------------- 1 | fn f() {} 2 | let list = []; 3 | 4 | let map = { 5 | 1: 4, 6 | "cat": "dog", 7 | f: "foo", 8 | list: true, 9 | nil: false, 10 | }; 11 | 12 | assertEq(map[1], 4); 13 | assertEq(map["cat"], "dog"); 14 | assertEq(map[f], "foo"); 15 | assertEq(map[list], true); 16 | assertEq(map[nil], false); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_get_key_not_found.lay: -------------------------------------------------------------------------------- 1 | let map = {}; 2 | map["not found"]; -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_get_nan.lay: -------------------------------------------------------------------------------- 1 | let map = { 2 | 10 / 0: true 3 | }; 4 | 5 | assert(map[50 / 0]); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_get_nested.lay: -------------------------------------------------------------------------------- 1 | let map = { 2 | "inner1": { 3 | "first": 1, 4 | "second": 2, 5 | }, 6 | "inner2": { 7 | "third": 3, 8 | "fourth": 4, 9 | }, 10 | }; 11 | 12 | assertEq(map["inner1"]["first"], 1); 13 | assertEq(map["inner1"]["second"], 2); 14 | 15 | assertEq(map["inner2"]["third"], 3); 16 | assertEq(map["inner2"]["fourth"], 4); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_get_ref_equal.lay: -------------------------------------------------------------------------------- 1 | class Example {} 2 | let e1 = Example(); 3 | let e2 = Example(); 4 | 5 | let map = { 6 | "key1": "value1", 7 | "key2": "value2", 8 | "key3": "value3", 9 | e1: "value4", 10 | e2: "value5", 11 | }; 12 | 13 | assertEq(map["key1"], "value1"); 14 | assertEq(map["key2"], "value2"); 15 | assertEq(map["key3"], "value3"); 16 | assertEq(map[e1], "value4"); 17 | assertEq(map[e2], "value5"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_set.lay: -------------------------------------------------------------------------------- 1 | fn f() {} 2 | let list = []; 3 | 4 | let map = { 5 | 1: 4, 6 | "cat": "dog", 7 | f: "foo", 8 | list: true, 9 | nil: false, 10 | }; 11 | 12 | assertEq(map[1] = 3, 3); 13 | assertEq(map[1], 3); 14 | assertEq(map["cat"] = false, false); 15 | assertEq(map["cat"], false); 16 | assertEq(map[f] = nil, nil); 17 | assertEq(map[f], nil); 18 | assertEq(map[list] = -7, -7); 19 | assertEq(map[list], -7); 20 | assertEq(map[nil] = nil, nil); 21 | assertEq(map[nil], nil); 22 | 23 | assertEq(map["new"] = 5, 5); 24 | assertEq(map["new"], 5); 25 | -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_set_nested.lay: -------------------------------------------------------------------------------- 1 | let map = { 2 | "inner1": { 3 | "first": 1, 4 | "second": 2, 5 | }, 6 | "inner2": { 7 | "third": 3, 8 | "fourth": 4, 9 | }, 10 | }; 11 | 12 | map["inner1"]["second"] = 20; 13 | assertEq(map["inner1"]["first"], 1); 14 | assertEq(map["inner1"]["second"], 20); 15 | 16 | map["inner2"]["third"] = 30; 17 | assertEq(map["inner2"]["third"], 30); 18 | assertEq(map["inner2"]["fourth"], 4); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/index_set_pass_through.lay: -------------------------------------------------------------------------------- 1 | let a = {}; 2 | let b = {}; 3 | 4 | b['cat'] = a['dog'] = 10; 5 | assertEq(b['cat'], 10); 6 | assertEq(a['dog'], 10); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/insert.lay: -------------------------------------------------------------------------------- 1 | let map = {}; 2 | assertEq(map.insert(1, false), nil); 3 | assertEq(map.insert(1, true), false); 4 | assertEq(map.insert("dude", 10), nil); 5 | assertEq(map.len(), 2); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/iter.lay: -------------------------------------------------------------------------------- 1 | let map = { 2 | "a": 1, 3 | "b": 2, 4 | "c": 3, 5 | "d": 4, 6 | "f": 5, 7 | }; 8 | 9 | let newMap = {}; 10 | for kvp in map { 11 | newMap[kvp[0]] = kvp[1]; 12 | } 13 | 14 | assertEq(newMap.len(), map.len()); 15 | for kvp in newMap { 16 | assertEq(kvp[1], map[kvp[0]]); 17 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/len.lay: -------------------------------------------------------------------------------- 1 | assertEq({"hi": 10}.len(), 1); 2 | 3 | let x = { 4 | 1: 1, 5 | 2: 2, 6 | 3: 3, 7 | 4: 4, 8 | 5: 5, 9 | }; 10 | assertEq(x.len(), 5); 11 | x[6] = 6; 12 | assertEq(x.len(), 6); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/remove.lay: -------------------------------------------------------------------------------- 1 | let map = { 2 | 1: 1, 3 | 2: 2, 4 | 3: 3, 5 | false: false, 6 | "stuff": "stuff" 7 | }; 8 | 9 | assertEq(map.remove(1), 1); 10 | assertEq(map.remove(2), 2); 11 | assertEq(map.remove(3), 3); 12 | assertEq(map.remove(false), false); 13 | assertEq(map.remove("stuff"), "stuff"); 14 | assertEq(map.len(), 0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/remove_missing_key.lay: -------------------------------------------------------------------------------- 1 | ({}).remove(10); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/set.lay: -------------------------------------------------------------------------------- 1 | fn example() {} 2 | 3 | let map = { 4 | 1: "dude", 5 | "cat": true, 6 | "dog": true, 7 | nil: true, 8 | "rabbit": true, 9 | example: example, 10 | }; 11 | 12 | assertEq(map.set(1, "bro"), "dude"); 13 | assertEq(map.set(false, 25), nil); 14 | assertEq(map.set(example, || true), example); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/map/str.lay: -------------------------------------------------------------------------------- 1 | let x = { 2 | "10": [1, 2, 3], 3 | false: { 4 | 5: false, 5 | 3: nil 6 | }, 7 | true: "sup", 8 | }; 9 | 10 | let str = x.str(); 11 | 12 | assert(str.has("true: 'sup'")); 13 | assert(str.has("'10': [1, 2, 3]")); 14 | assert(str.has("3: nil")); 15 | assert(str.has("5: false")); 16 | 17 | assertEq({}.str(), "{}"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/method/name.lay: -------------------------------------------------------------------------------- 1 | class Example { 2 | test1() {} 3 | test2() {} 4 | } 5 | 6 | let example = Example(); 7 | assertEq(example.test1.name(), "test1"); 8 | assertEq(example.test2.name(), "test2"); 9 | 10 | let x1 = example.test1; 11 | let x2 = example.test2; 12 | assertEq(x1.name(), "test1"); 13 | assertEq(x2.name(), "test2"); 14 | 15 | assertEq([].push.name(), "push"); 16 | assertEq([].pop.name(), "pop"); 17 | 18 | let x3 = [].push; 19 | let x4 = [].pop; 20 | assertEq(x3.name(), "push"); 21 | assertEq(x4.name(), "pop"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/module/name.lay: -------------------------------------------------------------------------------- 1 | import std.math as Math; 2 | assertEq(Math.cls().name(), "math"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/nil/str.lay: -------------------------------------------------------------------------------- 1 | let x = nil; 2 | 3 | assertEq(nil.str(), "nil"); 4 | assertEq(x.str(), "nil"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/number/ceil.lay: -------------------------------------------------------------------------------- 1 | assertEq(10.0.ceil(), 10.0); 2 | assertEq(10.1.ceil(), 11.0); 3 | assertEq(10.99.ceil(), 11.0); 4 | 5 | assertEq((-10.0).ceil(), -10.0); 6 | assertEq((-10.1).ceil(), -10.0); 7 | assertEq((-10.99).ceil(), -10.0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/number/cmp.lay: -------------------------------------------------------------------------------- 1 | assertEq(Number.cmp(11, 10), 1); 2 | assertEq(Number.cmp(10, 11), -1); 3 | assertEq(Number.cmp(5, -5), 10.0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/number/floor.lay: -------------------------------------------------------------------------------- 1 | assertEq(10.0.floor(), 10.0); 2 | assertEq(10.1.floor(), 10.0); 3 | assertEq(10.99.floor(), 10.0); 4 | 5 | assertEq((-10.0).floor(), -10.0); 6 | assertEq((-10.1).floor(), -11.0); 7 | assertEq((-10.99).floor(), -11.0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/number/parse.lay: -------------------------------------------------------------------------------- 1 | assertEq(Number.parse("10"), 10); 2 | assertEq(Number.parse("-15e3"), -15000); 3 | assertEq(Number.parse(".034"), 0.034); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/number/round.lay: -------------------------------------------------------------------------------- 1 | assertEq(10.0.round(), 10); 2 | assertEq(10.49.round(), 10); 3 | assertEq(10.5.round(), 11); 4 | assertEq(11.round(), 11); 5 | 6 | assertEq(-10.0.round(), -10); 7 | assertEq(-10.49.round(), -10); 8 | assertEq(-10.5.round(), -11); 9 | assertEq(-11.round(), -11); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/number/str.lay: -------------------------------------------------------------------------------- 1 | assertEq(10.str(), "10"); 2 | assertEq(5.342.str(), "5.342"); 3 | assertEq((-0.342).str(), "-0.342"); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/number/times.lay: -------------------------------------------------------------------------------- 1 | let results = [0, 1, 2, 3, 4].iter(); 2 | 3 | 5.times().each(|i| { 4 | results.next(); 5 | assertEq(i, results.current()); 6 | }); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/object/cls.lay: -------------------------------------------------------------------------------- 1 | class Example { 2 | test() {} 3 | } 4 | 5 | let example = Example(); 6 | 7 | assertEq(example.cls(), Example); 8 | assertEq(example.test.cls(), Method); 9 | assertEq('test'.cls(), String); 10 | assertEq(10.cls(), Number); 11 | assertEq(false.cls(), Bool); 12 | assertEq([].cls(), List); 13 | assertEq({}.cls(), Map); 14 | assertEq(||{}.cls(), Fun); 15 | assertEq([].iter().cls(), Iter); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/object/equals.lay: -------------------------------------------------------------------------------- 1 | 2 | assert(10.equals(10)); 3 | assert(!10.equals(12)); 4 | assert(false.equals(false)); 5 | assert(!false.equals(true)); 6 | 7 | let a = []; 8 | assert(a.equals(a)); 9 | assert(!a.equals([])); 10 | 11 | let b = {}; 12 | assert(b.equals(b)); 13 | assert(!b.equals({})); 14 | 15 | let c = ||{}; 16 | assert(c.equals(c)); 17 | assert(!c.equals(||{})); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/global/object/str.lay: -------------------------------------------------------------------------------- 1 | class A {} 2 | 3 | assertEq([].str(), '[]'); 4 | assertEq(true.str(), 'true'); 5 | assertEq('test'.str(), 'test'); 6 | assert(|a, b| {}.str().has('= 0 && rand < 1); 6 | } -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/math/utils/rem.lay: -------------------------------------------------------------------------------- 1 | import std.math; 2 | 3 | assertEq(math.rem(3.0, 2.0), 1.0); 4 | assertEq(math.rem(-3.0, 2.0), -1.0); 5 | assertEq(math.rem(3.0, -2.0), 1.0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/math/utils/sin.lay: -------------------------------------------------------------------------------- 1 | import std.math; 2 | 3 | fn almost(actual, expect) { 4 | assert(math.abs((actual - expect)) < 0.0000001); 5 | } 6 | 7 | almost(math.sin(0), 0.0); 8 | almost(math.sin(math.pi), 0.0); 9 | almost(math.sin(math.pi * 2), 0.0); 10 | 11 | almost(math.sin(math.pi / 2), 1.0); 12 | almost(math.sin(math.pi * 3 / 2), -1.0); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/regexp/class/match.lay: -------------------------------------------------------------------------------- 1 | import std.regexp:{RegExp}; 2 | 3 | let r1 = RegExp('a{3}'); 4 | let r2 = RegExp('\\d{3}-\\d{3}-\\d{4}'); 5 | 6 | assertEq(r1.match(' aaa'), 'aaa'); 7 | assertEq(r1.match(''), nil); 8 | 9 | assertEq(r2.match('123-456-7891'), '123-456-7891'); 10 | assertEq(r2.match('john'), nil); -------------------------------------------------------------------------------- /laythe_vm/fixture/std_lib/regexp/class/test.lay: -------------------------------------------------------------------------------- 1 | import std.regexp:{RegExp}; 2 | 3 | let r1 = RegExp('a{3}'); 4 | let r2 = RegExp('\\d{3}-\\d{3}-\\d{4}'); 5 | 6 | assert(r1.test('aaa')); 7 | assert(!r1.test('')); 8 | 9 | assert(r2.test('123-456-7891')); 10 | assert(!r2.test('john')); -------------------------------------------------------------------------------- /laythe_vm/src/compiler/ir/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod ast; 2 | pub mod token; 3 | pub mod symbol_table; 4 | 5 | #[cfg(test)] 6 | mod ast_printer; 7 | 8 | #[cfg(test)] 9 | pub use ast_printer::AstPrint; 10 | 11 | #[cfg(test)] 12 | pub use ast_printer::Visitor; -------------------------------------------------------------------------------- /laythe_vm/src/constants.rs: -------------------------------------------------------------------------------- 1 | use laythe_core::value::{Value, VALUE_UNDEFINED}; 2 | 3 | pub const MAX_FRAME_SIZE: usize = 255; 4 | pub const REPL_MODULE: &str = "repl.ly"; 5 | pub const UNDEFINED_ARRAY: [Value; u8::MAX as usize] = [VALUE_UNDEFINED; u8::MAX as usize]; 6 | -------------------------------------------------------------------------------- /laythe_vm/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(clippy::all)] 2 | 3 | mod byte_code; 4 | mod cache; 5 | mod chunk_builder; 6 | mod fiber; 7 | pub mod compiler; 8 | mod constants; 9 | pub mod source; 10 | pub mod vm; 11 | use codespan_reporting::diagnostic::Diagnostic; 12 | use source::VmFileId; 13 | 14 | #[cfg(any(test, feature = "debug"))] 15 | mod debug; 16 | 17 | /// The result of a compilation 18 | pub type FeResult = Result>>; 19 | -------------------------------------------------------------------------------- /laythe_vm/tests/env.rs: -------------------------------------------------------------------------------- 1 | use laythe_vm::vm::VmExit; 2 | use support::assert_files_exit; 3 | 4 | mod support; 5 | 6 | fn test_files(paths: &[&str], result: VmExit) -> Result<(), std::io::Error> { 7 | assert_files_exit(paths, FILE_PATH, result) 8 | } 9 | 10 | const FILE_PATH: &str = file!(); 11 | 12 | #[test] 13 | fn env() -> Result<(), std::io::Error> { 14 | test_files(&["std_lib/env/cwd.lay", "std_lib/env/args.lay"], VmExit::Ok) 15 | } 16 | -------------------------------------------------------------------------------- /laythe_wasm/web/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: "10" 3 | 4 | script: 5 | - ./node_modules/.bin/webpack 6 | -------------------------------------------------------------------------------- /laythe_wasm/web/bootstrap.js: -------------------------------------------------------------------------------- 1 | // A dependency graph that contains any wasm must all be imported 2 | // asynchronously. This `bootstrap.js` file does the single async import, so 3 | // that no one else needs to worry about it again. 4 | import("./index.js").catch((e) => 5 | console.error("Error importing `index.js`:", e) 6 | ); 7 | -------------------------------------------------------------------------------- /profiling.md: -------------------------------------------------------------------------------- 1 | ## Cargo flamegraph 2 | 3 | ```bash 4 | echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid 5 | cargo flamegraph --root --bin=laythe -- 6 | ``` 7 | 8 | ## Callgrind 9 | 10 | ```bash 11 | valgrind --tool=callgrind --dump-instr=yes --collect-jumps=yes --simulate-cache=yes -- 18 | ``` -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | tab_spaces = 2 2 | match_block_trailing_comma = true --------------------------------------------------------------------------------