Showing preview only (2,119K chars total). Download the full file or copy to clipboard to get everything.
Repository: PlasmaLang/plasma
Branch: master
Commit: 81e35cececdc
Files: 761
Total size: 1.9 MB
Directory structure:
gitextract_m9d_heqr/
├── .clang-format
├── .github/
│ └── workflows/
│ └── ci.yaml
├── .gitignore
├── .gitmessage
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── LICENSE.code
├── LICENSE.docs
├── LICENSE.unlicense
├── Makefile
├── README.md
├── SECURITY.md
├── THANKS
├── defaults.mk
├── docs/
│ ├── .gitignore
│ ├── README.md
│ ├── asciidoc.conf
│ ├── contributing.txt
│ ├── css/
│ │ ├── asciidoc.css
│ │ └── docs-offline.css
│ ├── design_concept_map.txt
│ ├── design_ideas.txt
│ ├── design_principles.txt
│ ├── design_types.txt
│ ├── dev_bugtracking.txt
│ ├── dev_compiler_internals.txt
│ ├── dev_howto_make_pr.txt
│ ├── dev_maintainers.txt
│ ├── dev_mercury_grades.txt
│ ├── dev_style_c.txt
│ ├── dev_style_mercury.txt
│ ├── dev_testing.txt
│ ├── getting_started.txt
│ ├── index.txt
│ ├── plasma_ref.txt
│ ├── pz_machine.txt
│ ├── references.txt
│ └── user_guide.txt
├── examples/
│ ├── .gitignore
│ ├── BUILD.plz
│ ├── Makefile
│ ├── README.md
│ ├── ackermann.exp
│ ├── ackermann.p
│ ├── change.exp
│ ├── change.in
│ ├── change.p
│ ├── fib.exp
│ ├── fib.p
│ ├── hello.exp
│ ├── hello.p
│ ├── module_example.p
│ ├── module_to_import.p
│ ├── modules.exp
│ ├── mr4.exp
│ ├── mr4.p
│ ├── readline.exp
│ ├── readline.in
│ ├── readline.p
│ ├── sequences.p
│ ├── set.p
│ ├── string.p
│ ├── temperature.exp
│ ├── temperature.p
│ ├── types.exp
│ ├── types.p
│ └── util.p
├── runtime/
│ ├── .gitignore
│ ├── README.md
│ ├── pz.cpp
│ ├── pz.h
│ ├── pz_array.h
│ ├── pz_builtin.cpp
│ ├── pz_builtin.h
│ ├── pz_closure.h
│ ├── pz_code.cpp
│ ├── pz_code.h
│ ├── pz_common.h
│ ├── pz_config.h.in
│ ├── pz_cxx_future.h
│ ├── pz_data.cpp
│ ├── pz_data.h
│ ├── pz_foreign.cpp
│ ├── pz_foreign.h
│ ├── pz_format.h
│ ├── pz_gc.cpp
│ ├── pz_gc.h
│ ├── pz_gc.impl.h
│ ├── pz_gc_alloc.cpp
│ ├── pz_gc_collect.cpp
│ ├── pz_gc_debug.cpp
│ ├── pz_gc_layout.h
│ ├── pz_gc_layout.impl.h
│ ├── pz_gc_layout_bop.h
│ ├── pz_gc_layout_fit.h
│ ├── pz_gc_util.cpp
│ ├── pz_gc_util.h
│ ├── pz_generic.cpp
│ ├── pz_generic_builder.cpp
│ ├── pz_generic_builtin.cpp
│ ├── pz_generic_closure.cpp
│ ├── pz_generic_closure.h
│ ├── pz_generic_run.cpp
│ ├── pz_generic_run.h
│ ├── pz_instructions.cpp
│ ├── pz_instructions.h
│ ├── pz_interp.h
│ ├── pz_io.cpp
│ ├── pz_io.h
│ ├── pz_library.cpp
│ ├── pz_library.h
│ ├── pz_main.cpp
│ ├── pz_memory.cpp
│ ├── pz_memory.h
│ ├── pz_option.cpp
│ ├── pz_option.h
│ ├── pz_read.cpp
│ ├── pz_read.h
│ ├── pz_string.cpp
│ ├── pz_string.h
│ ├── pz_trace.cpp
│ ├── pz_trace.h
│ ├── pz_util.h
│ └── pz_vector.h
├── scripts/
│ ├── README.md
│ ├── do_mmc_make
│ └── docker/
│ ├── Dockerfile
│ ├── README.md
│ ├── build.sh
│ ├── gitconfig
│ ├── install.sh
│ ├── mercury.list
│ ├── paul.gpg
│ ├── vimrc
│ └── welcome.sh
├── src/
│ ├── .gitignore
│ ├── .vim_mmc_make
│ ├── Mercury.options
│ ├── README.md
│ ├── asm.m
│ ├── asm_ast.m
│ ├── asm_error.m
│ ├── ast.m
│ ├── build.m
│ ├── builtins.m
│ ├── common_types.m
│ ├── compile.m
│ ├── compile_error.m
│ ├── constant.m
│ ├── context.m
│ ├── core.arity_chk.m
│ ├── core.branch_chk.m
│ ├── core.code.m
│ ├── core.function.m
│ ├── core.m
│ ├── core.pretty.m
│ ├── core.res_chk.m
│ ├── core.resource.m
│ ├── core.simplify.m
│ ├── core.type_chk.m
│ ├── core.type_chk.solve.m
│ ├── core.types.m
│ ├── core.util.m
│ ├── core_to_pz.closure.m
│ ├── core_to_pz.code.m
│ ├── core_to_pz.data.m
│ ├── core_to_pz.locn.m
│ ├── core_to_pz.m
│ ├── dump_stage.m
│ ├── file_utils.m
│ ├── foreign.m
│ ├── lex.automata.m
│ ├── lex.buf.m
│ ├── lex.convert_NFA_to_DFA.m
│ ├── lex.lexeme.m
│ ├── lex.m
│ ├── lex.regexp.m
│ ├── options.m
│ ├── parse.m
│ ├── parse_util.m
│ ├── parsing.m
│ ├── plzasm.m
│ ├── plzbuild.m
│ ├── plzc.m
│ ├── plzdisasm.m
│ ├── plzgeninit.m
│ ├── plzlnk.m
│ ├── pre.ast_to_core.m
│ ├── pre.bang.m
│ ├── pre.branches.m
│ ├── pre.closures.m
│ ├── pre.env.m
│ ├── pre.from_ast.m
│ ├── pre.import.m
│ ├── pre.m
│ ├── pre.pre_ds.m
│ ├── pre.pretty.m
│ ├── pre.to_core.m
│ ├── pre.util.m
│ ├── pz.bytecode.m
│ ├── pz.code.m
│ ├── pz.format.m
│ ├── pz.link.m
│ ├── pz.m
│ ├── pz.pretty.m
│ ├── pz.pz_ds.m
│ ├── pz.read.m
│ ├── pz.write.m
│ ├── pzt_parse.m
│ ├── q_name.m
│ ├── toml.m
│ ├── util.log.m
│ ├── util.m
│ ├── util.mercury.m
│ ├── util.my_exception.m
│ ├── util.my_io.m
│ ├── util.my_string.m
│ ├── util.my_time.m
│ ├── util.path.m
│ ├── util.pretty.m
│ ├── util.pretty_old.m
│ ├── util.result.m
│ ├── varmap.m
│ └── write_interface.m
├── template.mk
├── tests/
│ ├── .gitignore
│ ├── BUILD.plz
│ ├── README.md
│ ├── build/
│ │ ├── bad_file_1.build
│ │ ├── bad_file_1.exp
│ │ ├── bad_file_2.exp
│ │ ├── bad_file_2.test
│ │ ├── bad_file_3.build
│ │ ├── bad_file_3.exp
│ │ ├── bad_file_4.build
│ │ ├── bad_file_4.exp
│ │ ├── bad_module_name.build
│ │ ├── bad_module_name.exp
│ │ ├── bad_module_name_2.build
│ │ ├── bad_module_name_2.exp
│ │ ├── bad_module_name_2.p
│ │ ├── dup_module_name.build
│ │ ├── dup_module_name.exp
│ │ ├── dup_module_name_2.build
│ │ ├── dup_module_name_2.exp
│ │ ├── dup_module_name_2.p
│ │ ├── extra_module.p
│ │ ├── file_in_other_program.build
│ │ ├── file_in_other_program.expish
│ │ ├── file_in_other_program.p
│ │ ├── include_file_nobuild.build
│ │ ├── include_file_nobuild.exp
│ │ ├── include_file_nobuild.p
│ │ ├── include_nofile_build.build
│ │ ├── include_nofile_build.exp
│ │ ├── include_nofile_build.p
│ │ ├── include_nofile_nobuild.build
│ │ ├── include_nofile_nobuild.expish
│ │ ├── include_nofile_nobuild.p
│ │ ├── options_compiler_01.build
│ │ ├── options_compiler_01.exp
│ │ ├── options_compiler_01.p
│ │ ├── options_compiler_02.build
│ │ ├── options_compiler_02.exp
│ │ ├── options_compiler_02.p
│ │ ├── options_compiler_03.build
│ │ ├── options_compiler_03.exp
│ │ └── other_program.p
│ ├── builtins/
│ │ ├── BUILD.plz
│ │ ├── builtin_01.exp
│ │ ├── builtin_01.p
│ │ ├── builtin_02_int.exp
│ │ ├── builtin_02_int.p
│ │ ├── builtin_03_bool.exp
│ │ ├── builtin_03_bool.p
│ │ ├── builtin_04_string.exp
│ │ ├── builtin_04_string.p
│ │ ├── builtin_05_list.exp
│ │ ├── builtin_05_list.p
│ │ ├── builtin_not_found.build
│ │ ├── builtin_not_found.exp
│ │ └── builtin_not_found.p
│ ├── ffi/
│ │ ├── .gitignore
│ │ ├── BUILD.plz
│ │ ├── import_from_two_modules.cpp
│ │ ├── import_from_two_modules.exp
│ │ ├── import_from_two_modules.h
│ │ ├── import_from_two_modules_1.p
│ │ ├── import_from_two_modules_2.p
│ │ ├── import_function.cpp
│ │ ├── import_function.exp
│ │ ├── import_function.h
│ │ ├── import_function.p
│ │ ├── import_shared_module.cpp
│ │ ├── import_shared_module.h
│ │ ├── import_shared_module.p
│ │ ├── import_two_sources.cpp
│ │ ├── import_two_sources.exp
│ │ ├── import_two_sources.h
│ │ ├── import_two_sources.p
│ │ ├── unrecognised_extension.build
│ │ ├── unrecognised_extension.exp
│ │ └── unrecognised_extension.p
│ ├── hello.exp
│ ├── hello.p
│ ├── language/
│ │ ├── BUILD.plz
│ │ ├── arity_01.exp
│ │ ├── arity_01.p
│ │ ├── arity_02.build
│ │ ├── arity_02.exp
│ │ ├── arity_02.p
│ │ ├── arity_ho_1.build
│ │ ├── arity_ho_1.exp
│ │ ├── arity_ho_1.p
│ │ ├── arity_ho_2.build
│ │ ├── arity_ho_2.exp
│ │ ├── arity_ho_2.p
│ │ ├── arity_lambda.build
│ │ ├── arity_lambda.exp
│ │ ├── arity_lambda.p
│ │ ├── comment.exp
│ │ ├── comment.p
│ │ ├── comment_end.build
│ │ ├── comment_end.exp
│ │ ├── comment_end.p
│ │ ├── coverage_1.build
│ │ ├── coverage_1.exp
│ │ ├── coverage_1.p
│ │ ├── entrypoint_bad_sig.build
│ │ ├── entrypoint_bad_sig.exp
│ │ ├── entrypoint_bad_sig.p
│ │ ├── entrypoint_multi.build
│ │ ├── entrypoint_multi.exp
│ │ ├── entrypoint_multi.p
│ │ ├── entrypoint_none.build
│ │ ├── entrypoint_none.exp
│ │ ├── entrypoint_none.p
│ │ ├── export_bad_resource.build
│ │ ├── export_bad_resource.exp
│ │ ├── export_bad_resource.p
│ │ ├── export_bad_type.build
│ │ ├── export_bad_type.exp
│ │ ├── export_bad_type.p
│ │ ├── ho/
│ │ │ ├── BUILD.plz
│ │ │ ├── closure_01.exp
│ │ │ ├── closure_01.p
│ │ │ ├── closure_02.exp
│ │ │ ├── closure_02.p
│ │ │ ├── closure_03.exp
│ │ │ ├── closure_03.p
│ │ │ ├── closure_04.exp
│ │ │ ├── closure_04.p
│ │ │ ├── closure_05.exp
│ │ │ ├── closure_05.p
│ │ │ ├── closure_06.exp
│ │ │ ├── closure_06.p
│ │ │ ├── closure_bad_01.build
│ │ │ ├── closure_bad_01.exp
│ │ │ ├── closure_bad_01.p
│ │ │ ├── closure_bad_02.build
│ │ │ ├── closure_bad_02.exp
│ │ │ ├── closure_bad_02.p
│ │ │ ├── closure_bad_03.build
│ │ │ ├── closure_bad_03.exp
│ │ │ ├── closure_bad_03.p
│ │ │ ├── closure_bad_04.build
│ │ │ ├── closure_bad_04.exp
│ │ │ ├── closure_bad_04.p
│ │ │ ├── closure_bad_05.build
│ │ │ ├── closure_bad_05.exp
│ │ │ ├── closure_bad_05.p
│ │ │ ├── closure_bad_06.build
│ │ │ ├── closure_bad_06.exp
│ │ │ ├── closure_bad_06.p
│ │ │ ├── closure_bad_07.build
│ │ │ ├── closure_bad_07.exp
│ │ │ ├── closure_bad_07.p
│ │ │ ├── closure_bad_08.build
│ │ │ ├── closure_bad_08.exp
│ │ │ ├── closure_bad_08.p
│ │ │ ├── closure_bad_09.build
│ │ │ ├── closure_bad_09.exp
│ │ │ ├── closure_bad_09.p
│ │ │ ├── closure_bad_10.build
│ │ │ ├── closure_bad_10.exp
│ │ │ ├── closure_bad_10.p
│ │ │ ├── closure_mut_rec.build
│ │ │ ├── closure_mut_rec.exp
│ │ │ ├── closure_mut_rec.p
│ │ │ ├── ho_1.exp
│ │ │ ├── ho_1.p
│ │ │ ├── ho_2.exp
│ │ │ ├── ho_2.p
│ │ │ ├── ho_bad_7.build
│ │ │ ├── ho_bad_7.exp
│ │ │ ├── ho_bad_7.p
│ │ │ ├── ho_call_bug_30.exp
│ │ │ └── ho_call_bug_30.p
│ │ ├── ite_1.exp
│ │ ├── ite_1.p
│ │ ├── ite_2.exp
│ │ ├── ite_2.p
│ │ ├── ite_3.exp
│ │ ├── ite_3.p
│ │ ├── list.exp
│ │ ├── list.p
│ │ ├── match/
│ │ │ ├── BUILD.plz
│ │ │ ├── match_1.exp
│ │ │ ├── match_1.p
│ │ │ ├── match_2.exp
│ │ │ ├── match_2.p
│ │ │ ├── match_bad_1.build
│ │ │ ├── match_bad_1.exp
│ │ │ ├── match_bad_1.p
│ │ │ ├── match_bad_2.build
│ │ │ ├── match_bad_2.exp
│ │ │ ├── match_bad_2.p
│ │ │ ├── match_bad_3.build
│ │ │ ├── match_bad_3.exp
│ │ │ ├── match_bad_3.p
│ │ │ ├── match_bad_error_1.build
│ │ │ ├── match_bad_error_1.exp
│ │ │ ├── match_bad_error_1.p
│ │ │ ├── match_empty_case.exp
│ │ │ ├── match_empty_case.p
│ │ │ ├── match_multiple.build
│ │ │ ├── match_multiple.exp
│ │ │ ├── match_multiple.p
│ │ │ ├── unpack_1.exp
│ │ │ ├── unpack_1.p
│ │ │ ├── unpack_nest.build
│ │ │ ├── unpack_nest.exp
│ │ │ └── unpack_nest.p
│ │ ├── operators.exp
│ │ ├── operators.p
│ │ ├── pragma_bad_args.build
│ │ ├── pragma_bad_args.exp
│ │ ├── pragma_bad_args.p
│ │ ├── pragma_unknown_1.build
│ │ ├── pragma_unknown_1.exp
│ │ ├── pragma_unknown_1.p
│ │ ├── pragma_unknown_2.build
│ │ ├── pragma_unknown_2.exp
│ │ ├── pragma_unknown_2.p
│ │ ├── res/
│ │ │ ├── BUILD.plz
│ │ │ ├── multiple_bang.build
│ │ │ ├── multiple_bang.exp
│ │ │ ├── multiple_bang.p
│ │ │ ├── resource.exp
│ │ │ ├── resource.p
│ │ │ ├── resource_invalid_1.build
│ │ │ ├── resource_invalid_1.exp
│ │ │ ├── resource_invalid_1.p
│ │ │ ├── resource_invalid_2.build
│ │ │ ├── resource_invalid_2.exp
│ │ │ ├── resource_invalid_2.p
│ │ │ ├── resource_invalid_3.build
│ │ │ ├── resource_invalid_3.exp
│ │ │ └── resource_invalid_3.p
│ │ ├── return.build
│ │ ├── return.exp
│ │ ├── return.p
│ │ ├── string.exp
│ │ ├── string.p
│ │ ├── types/
│ │ │ ├── BUILD.plz
│ │ │ ├── bug_375.build
│ │ │ ├── bug_375.exp
│ │ │ ├── bug_375.p
│ │ │ ├── closure_infer_1.build
│ │ │ ├── closure_infer_1.exp
│ │ │ ├── closure_infer_1.p
│ │ │ ├── closure_infer_2.build
│ │ │ ├── closure_infer_2.exp
│ │ │ ├── closure_infer_2.p
│ │ │ ├── constructor_duplicate.build
│ │ │ ├── constructor_duplicate.exp
│ │ │ ├── constructor_duplicate.p
│ │ │ ├── constructor_overload.exp
│ │ │ ├── constructor_overload.p
│ │ │ ├── enum.exp
│ │ │ ├── enum.p
│ │ │ ├── ho_bad_1.build
│ │ │ ├── ho_bad_1.exp
│ │ │ ├── ho_bad_1.p
│ │ │ ├── ho_bad_2.build
│ │ │ ├── ho_bad_2.exp
│ │ │ ├── ho_bad_2.p
│ │ │ ├── ho_bad_3.build
│ │ │ ├── ho_bad_3.exp
│ │ │ ├── ho_bad_3.p
│ │ │ ├── ho_bad_4.build
│ │ │ ├── ho_bad_4.exp
│ │ │ ├── ho_bad_4.p
│ │ │ ├── ho_bad_5.build
│ │ │ ├── ho_bad_5.exp
│ │ │ ├── ho_bad_5.p
│ │ │ ├── ho_bad_6.build
│ │ │ ├── ho_bad_6.exp
│ │ │ ├── ho_bad_6.p
│ │ │ ├── occurs1.build
│ │ │ ├── occurs1.exp
│ │ │ ├── occurs1.p
│ │ │ ├── occurs2.build
│ │ │ ├── occurs2.exp
│ │ │ ├── occurs2.p
│ │ │ ├── occurs3.build
│ │ │ ├── occurs3.exp
│ │ │ ├── occurs3.p
│ │ │ ├── occurs4.build
│ │ │ ├── occurs4.exp
│ │ │ ├── occurs4.p
│ │ │ ├── occurs5.build
│ │ │ ├── occurs5.exp
│ │ │ ├── occurs5.p
│ │ │ ├── parametric.exp
│ │ │ ├── parametric.p
│ │ │ ├── playing_card.exp
│ │ │ ├── playing_card.p
│ │ │ ├── polymorphic.exp
│ │ │ ├── polymorphic.p
│ │ │ ├── recursive.exp
│ │ │ ├── recursive.p
│ │ │ ├── tagging1.exp
│ │ │ ├── tagging1.p
│ │ │ ├── tagging2.exp
│ │ │ ├── tagging2.p
│ │ │ ├── types_invalid_02.build
│ │ │ ├── types_invalid_02.exp
│ │ │ ├── types_invalid_02.p
│ │ │ ├── types_invalid_03.build
│ │ │ ├── types_invalid_03.exp
│ │ │ ├── types_invalid_03.p
│ │ │ ├── types_invalid_04.build
│ │ │ ├── types_invalid_04.exp
│ │ │ ├── types_invalid_04.p
│ │ │ ├── types_invalid_05.build
│ │ │ ├── types_invalid_05.exp
│ │ │ ├── types_invalid_05.p
│ │ │ ├── types_invalid_06.build
│ │ │ ├── types_invalid_06.exp
│ │ │ ├── types_invalid_06.p
│ │ │ ├── types_invalid_07.build
│ │ │ ├── types_invalid_07.exp
│ │ │ ├── types_invalid_07.p
│ │ │ ├── types_invalid_08.build
│ │ │ ├── types_invalid_08.exp
│ │ │ └── types_invalid_08.p
│ │ └── vars/
│ │ ├── BUILD.plz
│ │ ├── vars_1.exp
│ │ ├── vars_1.p
│ │ ├── vars_2.exp
│ │ ├── vars_2.p
│ │ ├── vars_invalid_01.build
│ │ ├── vars_invalid_01.exp
│ │ ├── vars_invalid_01.p
│ │ ├── vars_invalid_02.build
│ │ ├── vars_invalid_02.exp
│ │ ├── vars_invalid_02.p
│ │ ├── vars_invalid_03.build
│ │ ├── vars_invalid_03.exp
│ │ ├── vars_invalid_03.p
│ │ ├── vars_invalid_04.build
│ │ ├── vars_invalid_04.exp
│ │ ├── vars_invalid_04.p
│ │ ├── vars_invalid_05.build
│ │ ├── vars_invalid_05.exp
│ │ ├── vars_invalid_05.p
│ │ ├── vars_invalid_06.build
│ │ ├── vars_invalid_06.exp
│ │ ├── vars_invalid_06.p
│ │ ├── vars_invalid_07.build
│ │ ├── vars_invalid_07.exp
│ │ ├── vars_invalid_07.p
│ │ ├── vars_invalid_08.build
│ │ ├── vars_invalid_08.exp
│ │ ├── vars_invalid_08.p
│ │ ├── vars_invalid_09.build
│ │ ├── vars_invalid_09.exp
│ │ ├── vars_invalid_09.p
│ │ ├── vars_invalid_10.build
│ │ ├── vars_invalid_10.exp
│ │ ├── vars_invalid_10.p
│ │ ├── vars_invalid_11.build
│ │ ├── vars_invalid_11.exp
│ │ ├── vars_invalid_11.p
│ │ ├── vars_invalid_12.build
│ │ ├── vars_invalid_12.exp
│ │ ├── vars_invalid_12.p
│ │ ├── vars_invalid_13.build
│ │ ├── vars_invalid_13.exp
│ │ ├── vars_invalid_13.p
│ │ ├── vars_invalid_14.build
│ │ ├── vars_invalid_14.exp
│ │ ├── vars_invalid_14.p
│ │ ├── vars_invalid_15.build
│ │ ├── vars_invalid_15.exp
│ │ └── vars_invalid_15.p
│ ├── library/
│ │ ├── BUILD.plz
│ │ ├── args.exp
│ │ └── args.p
│ ├── modules/
│ │ ├── BUILD.plz
│ │ ├── Makefile
│ │ ├── dyn_link_01.exp
│ │ ├── dyn_link_01.p
│ │ ├── dyn_link_01.sh
│ │ ├── dyn_link_01_a.p
│ │ ├── dyn_link_02.exp
│ │ ├── dyn_link_02.p
│ │ ├── dyn_link_02.sh
│ │ ├── dyn_link_02_a.p
│ │ ├── dyn_link_02_b.p
│ │ ├── entrypoint_1.build
│ │ ├── entrypoint_1.exp
│ │ ├── entrypoint_1a.p
│ │ ├── entrypoint_1b.p
│ │ ├── entrypoint_2.exp
│ │ ├── entrypoint_2a.p
│ │ ├── entrypoint_2b.p
│ │ ├── entrypoint_3.exp
│ │ ├── entrypoint_3a.p
│ │ ├── entrypoint_3b.p
│ │ ├── heir.foo.p
│ │ ├── heir.foo_bar.p
│ │ ├── heir_test.build
│ │ ├── heir_test.exp
│ │ ├── heir_test.p
│ │ ├── module_01.build
│ │ ├── module_01.exp
│ │ ├── module_01.p
│ │ ├── module_01a.p
│ │ ├── module_02.build
│ │ ├── module_02.exp
│ │ ├── module_02.p
│ │ ├── module_02a.p
│ │ ├── module_03a.exp
│ │ ├── module_03a.p
│ │ ├── module_03a.sh
│ │ ├── module_03ar.exp
│ │ ├── module_03ar.sh
│ │ ├── module_03b.exp
│ │ ├── module_03b.p
│ │ ├── module_03b.sh
│ │ ├── module_03br.exp
│ │ ├── module_03br.sh
│ │ ├── module_03c.exp
│ │ ├── module_03c.p
│ │ ├── module_03c.sh
│ │ ├── module_03cr.exp
│ │ ├── module_03cr.sh
│ │ ├── module_04.exp
│ │ ├── module_04.p
│ │ ├── module_04a.p
│ │ ├── module_05.exp
│ │ ├── module_05.p
│ │ ├── module_05a.p
│ │ ├── module_06.exp
│ │ ├── module_06.p
│ │ ├── module_06a.p
│ │ ├── module_07.exp
│ │ ├── module_07.p
│ │ ├── module_07a.p
│ │ ├── module_08.p
│ │ ├── module_08a.exp
│ │ ├── module_08a.sh
│ │ ├── module_08b.exp
│ │ ├── module_08b.sh
│ │ ├── module_name_test.build
│ │ ├── module_name_test.exp
│ │ ├── module_name_test.p
│ │ ├── opaque_resource.p
│ │ ├── opaque_resource_1.build
│ │ ├── opaque_resource_1.exp
│ │ ├── opaque_resource_1.p
│ │ ├── opaque_resource_2.build
│ │ ├── opaque_resource_2.exp
│ │ ├── opaque_resource_2.p
│ │ ├── res_vis_01.a.p
│ │ ├── res_vis_01.b.p
│ │ ├── res_vis_01.c.p
│ │ ├── res_vis_01.d.p
│ │ ├── res_vis_01.exp
│ │ └── res_vis_01.p
│ ├── pretty.lua
│ ├── run-tests.lua
│ ├── runtime/
│ │ ├── BUILD.plz
│ │ ├── allocateLots.exp
│ │ ├── allocateLots.p
│ │ ├── die.exp
│ │ ├── die.p
│ │ ├── parameters.exp
│ │ └── parameters.p
│ └── update-outputs.sh
└── tests-old/
├── .gitignore
├── README.md
├── modules-invalid/
│ ├── .gitignore
│ ├── BUILD.plz
│ ├── Makefile
│ ├── module_01.exp
│ ├── module_01.p
│ ├── module_02.exp
│ ├── module_02.p
│ ├── module_03.exp
│ ├── module_03.p
│ ├── module_03a.p
│ ├── module_04a.exp
│ ├── module_04a.p
│ ├── module_04b.exp
│ ├── module_04b.p
│ ├── module_04c.exp
│ ├── module_04c.p
│ ├── module_04d.exp
│ ├── module_04d.p
│ ├── module_04import.p
│ ├── module_05.exp
│ ├── module_05.p
│ ├── module_05_.p
│ ├── module_06.exp
│ ├── module_06.p
│ ├── module_06a.p
│ ├── module_07.exp
│ ├── module_07.p
│ ├── module_08.c.p
│ ├── module_08.d.p
│ ├── module_08.expish
│ ├── module_08.p
│ ├── module_08b.expish
│ └── module_08b.p
├── pzt/
│ ├── Makefile
│ ├── ccov.exp
│ ├── ccov.pzt
│ ├── closure.exp
│ ├── closure.pzt
│ ├── fib.exp
│ ├── fib.pzt
│ ├── hello.exp
│ ├── hello.pzt
│ ├── link_01.exp
│ ├── link_01.p
│ ├── link_01.pzt
│ ├── link_02.exp
│ ├── link_02.pzt
│ ├── link_03.exp
│ ├── link_03.pzt
│ ├── link_target_01.pzt
│ ├── link_target_02.pzt
│ ├── memory.exp
│ ├── memory.pzt
│ ├── mutual.exp
│ ├── mutual.pzt
│ ├── stack.exp
│ ├── stack.pzt
│ ├── struct.exp
│ ├── struct.pzt
│ ├── tags.exp
│ ├── tags.pzt
│ ├── temperature.exp
│ ├── temperature.pzt
│ ├── trunc_ze_se.exp
│ └── trunc_ze_se.pzt
└── run_tests.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
---
Language: Cpp
BasedOnStyle: Google
IndentWidth: 4
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: MultiLine
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
SplitEmptyFunction: false
BinPackArguments: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AlignConsecutiveAssignments: true
# This is good except it looks bad in function declarations.
AlignConsecutiveDeclarations: true
AlignConsecutiveMacros: true
BreakConstructorInitializers: BeforeComma
AlignTrailingComments: true
DerivePointerAlignment: false
PointerAlignment: Middle
# For now, TODO: switch to Regroup
IncludeBlocks: Preserve
...
================================================
FILE: .github/workflows/ci.yaml
================================================
#
# This is free and unencumbered software released into the public domain.
# See ../LICENSE.unlicense
#
# This workflow controls Plasma's continious integration. See documentation
# for github workflows:
#
# * https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-and-managing-workflow-files-and-runs
# * https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions
#
# And the action we use is here:
# * https://github.com/PlasmaLang/ci
name: CI
on: [push, pull_request]
jobs:
test:
name: Test (${{ matrix.buildType }} ${{ matrix.c }})
runs-on: ubuntu-latest
strategy:
matrix:
c: [gcc, clang]
buildType: [dev, rel]
fail-fast: false
steps:
- name: checkout
uses: actions/checkout@v4
- name: setup
uses: PlasmaLang/ci/stable@v2_1
with:
command: setup
c: ${{ matrix.c }}
buildType: ${{ matrix.buildType }}
- name: build
uses: PlasmaLang/ci/stable@v2_1
with:
command: build
- name: test
uses: PlasmaLang/ci/stable@v2_1
with:
command: test
- name: gctest
uses: PlasmaLang/ci/stable@v2_1
if: matrix.buildType == 'dev'
with:
command: gctest
- name: copy-results
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-results ${{ matrix.buildType }} ${{ matrix.c }}
path: .
retention-days: 7
docs:
name: Build docs
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- name: checkout
uses: actions/checkout@v4
- name: docs
uses: PlasmaLang/ci/docs@v1
lint:
name: Lint (${{ matrix.buildType }})
runs-on: ubuntu-latest
strategy:
matrix:
buildType: [dev, rel]
fail-fast: false
steps:
- name: checkout
uses: actions/checkout@v4
- name: setup
uses: PlasmaLang/ci/stable@v2_1
with:
command: setup
c: clang
buildType: ${{ matrix.buildType }}
lint: lint
- name: build
uses: PlasmaLang/ci/stable@v2_1
with:
command: build
- name: extra
uses: PlasmaLang/ci/stable@v2_1
with:
command: extra
================================================
FILE: .gitignore
================================================
.dep
.docs_warning
.mer_progs
build.mk
================================================
FILE: .gitmessage
================================================
[component(s)] Title
Description
Any other changes including changes that were needed to support this
change or followed as a concequence of this change.
# Current components are:
# pz: the PZ file format,
# pzrun: the runtime,
# pzasm: the PZ assembler,
# plasmac: the compiler generally,
# plasmac/parse: the first phase: parsing.
# plasmac/ast: the second phase: the AST and operations on it,
# plasmac/pre: the third phase: the pre-core representation and operations,
# plasmac/core: the fourth phase: the core representation and operations,
# plasmac/pz: the fitht phase: the PZ code generator,
# docs: documentation,
# build: the build system,
#
# The title doesn't need to be a full English sentence.
# You can use wildcards to convey groups of files if that
# makes things easier to read. (for a human)
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# The Plasma Code of Conduct
The canonical version of this document can be found
[in the master branch of the plasma repository](https://github.com/PlasmaLang/plasma/blob/master/CODE_OF_CONDUCT.md).
We are committed to providing a friendly and safe environment for all,
regardless of level of experience, gender identity and expression, sexual
orientation, disability, personal appearance, body size, race, ethnicity,
age, religion, nationality, relationship status or other similar
characteristic.
## Contact
If you have any questions or wish to report harassment
you may contact the Plasma community moderators by e-mailing
[mods@plasmalang.org](mailto:mods@plasmalang.org).
This e-mail alias currently
messages Paul Bone only. Reports will be handled discreetly.
## Rules for conduct
All participants are expected to follow these rules at all times.
* Avoid using rude, sexual, or otherwise inappropriate nicknames or avatars.
* Harassment is unwelcome behaviour, we will exclude anyone engaging in
harassment. Harassment may include:
* Violence, threats of violence or violent language directed against
another person.
* Discriminatory, hateful, or exclusionary jokes, language, remarks and
behaviour.
* Personal insults and cursing directed at another person,
cursing at things is okay, but not with oppressive language.
* Posting or displaying sexually explicit or violent material.
* Posting or threatening to post other people’s personally identifying
information ("doxing").
* Inappropriate photography or recording.
* Inappropriate physical contact. You should have someone’s consent before
touching them.
* Unwelcome sexual attention. This includes, sexualized comments or jokes;
inappropriate touching, groping, and unwelcomed sexual advances.
* Deliberate intimidation, stalking or following (online or in person).
* Advocating for, or encouraging, any of the above behaviour.
* Disruptive behaviour interferes with other people's ability to contribute
or use Plasma.
* Trolling, flaming, baiting or other attention-stealing
behaviour is not welcome.
* Sustained disruption of community events, including talks and
presentations.
* The moderators are responsible for maintaining a healthy and happy
community, and this code of conduct may be subject to change or
interpretation to achieve that.
## Scope
* These rules apply to the Discord server, github and the mailing lists and any
other 'official' place as listed on http://plasmalang.org/contact.html
* Private harassment is also unacceptable. Whether you're a regular
contributor or a newcomer, if you feel you have been or are being harassed
or made uncomfortable by a community member, please contact us (see
above). We care about making this community a safe place for you and
we've got your back.
* Conduct outside the project may affect a person's eligibility to hold a
position of responsibility (eg: code review, moderation), and may
contribute to their standing within the Plasma community.
## Good ideas for productive conduct
When differences of opinion arise we want to have productive discussions,
here are some ideas for ensuring discussions remain productive and
respectful.
* Respect that people have differences of opinion and that every design or
implementation choice carries a trade-off and numerous costs.
Disagreements about such decisions are okay so long as they are productive
and everyone avoids personal attacks.
* Please keep unstructured critique to a minimum. If you have solid ideas
you want to experiment with, make a fork and see how it works.
* When providing feedback, ask yourself "Is this code/docs/etc better than
before?" not "Is this contribution perfect?", particularly for new
contributors.
* Spamming mailing lists, Discord server etc can make it difficult for
other on-topic discussions to occur. Interruptions like these will be
moderated if necessary. We do not forbid small off-topic discussions like
"How was your weekend?" as they are usually positive for the community.
## Moderation
These are the policies for upholding our community's standards of conduct.
If you feel that a discussion needs moderation, please contact the
Moderation Team (see above).
1. Moderators will first respond with a warning for most violations. If the
violation is particularly severe mods may exclude someone immediately and
permanently.
2. If the warning is unheeded, the user will be "kicked," i.e., kicked out
of the communication channel to cool off.
3. If the user comes back and continues to make trouble, they will be
banned, i.e., indefinitely excluded.
4. Moderators may choose at their discretion to un-ban the user if it was a
first offense and they offer the offended party a genuine apology.
5. If a moderator bans someone and you think it was unjustified, please take
it up with that moderator, or with a different moderator, **in private**.
Complaints about bans in-channel are not allowed.
* Moderators are held to a higher standard than other community members. If
a moderator creates an inappropriate situation, they should expect less
leeway than others.
In the Plasma community we strive to go the extra step to look out for each
other. Don't just aim to be technically unimpeachable, try to be your best
self. In particular, avoid flirting with offensive or sensitive issues,
particularly if they're off-topic; this all too often leads to unnecessary
fights, hurt feelings, and damaged trust; worse, it can drive people away
from the community entirely.
And if someone takes issue with something you said or did, resist the urge
to be defensive. Just stop doing what it was they complained about and
apologize. Even if you feel you were misinterpreted or unfairly accused,
chances are good there was something you could've communicated better —
remember that it's your responsibility to make your fellow contributors
comfortable. Everyone wants to get along and we are all here first and
foremost because we want to talk about cool technology. You will find that
people will be eager to assume good intent and forgive as long as you earn
their trust.
## Other projects
For other projects adopting the Plasma Code of Conduct, please contact the
maintainers of those projects for enforcement. If you wish to use this code
of conduct for your own project, consider explicitly mentioning your
moderation policy or making a copy with your own moderation policy so as to
avoid confusion.
*Adapted from the
[Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html) and the
[Citizen Code of Conduct](http://citizencodeofconduct.org/).
[CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)*
================================================
FILE: CONTRIBUTING.md
================================================
# Plasma Contributors' Information
This file contains information for potential and current Plasma
contributors.
## Summary and legal stuff
* We prefer github pull requests or patches mailed to the
[developers' mailing list](https://plasmalang.org/lists/listinfo/dev).
If you need to discuss a security issue confidently you can e-mail
plasma at plasmalang dot org
* The license of your contribution must match the project's licenses:
* Code: MIT
* Docs: CC BY-SA 4.0
* Build scripts, tests, and sample code: Unlicense
* No contributor agreement is required, you retain the copyright for your
contribution.
* Please follow the style guides as much as possible (see below)
* Please format your log messages following the log message style (see
below)
* By submitting a PR you acknowledge these terms and agree to the
[Code of Conduct](CODE_OF_CONDUCT.md)
* By opening an issue/commenting/messaging you agree to the
[Code of Conduct](CODE_OF_CONDUCT.md)
## What and how to contribute
Full contributing information is provided [in the contributors'
guide](https://plasmalang.org/docs/contributing.html).
## Submitting your changes
All code contributions must be made under the appropriate license:
* Code: MIT
* Docs: CC BY-SA 4.0
* Build scripts, tests, and sample code: Unlicense
No transfer of copyright or other rights or permissions is required.
Instead we ask contributors to list themselves (pseudonyms are okay) in the
AUTHORS file, not only so we can credit and honor them but so that we know
who the copyright owners are. This could be important if, in the future,
licensing decisions need to be made (it's unlikely but it's best for
Plasma).
You may choose not to be listed (e.g: if contributing a small fix) but doing
so means that you agree that Paul Bone shall make any licensing decisions on
your behalf. You may add your name later when making a more significant
change.
Log messages should follow the style:
```
[component(s)] Title
Description
Any other changes including changes that were needed to support this
change or followed as a concequence of this change.
```
We provide a .gitmessage in the root of the repository.
Run this command to start using the new commit message template:
```
git config --local commit.template /path/to/repo/.gitmessage
```
```components``` is one or more parts of the system. This helps people
identify (in mailing lists, change logs etc) what kind of change has been
made at a glace. It also helps people and software search for changes.
Current components are:
* pz: the PZ file format,
* rt: the runtime generally,
* rt/interp: the bytecode interpreter,
* rt/gc: the garbage collector,
* asm: the PZ assembler,
* compiler: the compiler generally,
* compiler/parse: the first phase: parsing.
* compiler/ast: the second phase: the AST and operations on it,
* compiler/pre: the third phase: the pre-core representation and operations,
* compiler/core: the fourth phase: the core representation and operations,
* compiler/pz: the fitht phase: the PZ code generator,
* compiler/util: other utility code in the compiler,
* link: the bytecode linker
* build: the plzbuild tool,
* docs: documentation,
* scripts: the build system and other scripts,
* tests: the test suite,
Sometimes it makes sense to pick the component with the most sagnificant
changes rather than listing all of them. This is typical for changes to the
compiler.
Each patch should contain a single change and changes required by that
change (should compile and pass tests). Changes may e rolled together when
they're trivial related changes (eg, multiple spelling fixes).
Also, not a real component:
* merge: for merge commits (see the maintainer's guide).
================================================
FILE: LICENSE
================================================
Code
----
The code except for lex.* are:
Copyright (C) 2015-2025 Plasma Team
Distributed under the terms of the MIT License see LICENSE.code
The `git log` indicates the members of Plasma Team
src/lex.*
---------
The tools currently depend on the lex library for Mercury.
https://github.com/Mercury-Language/mercury/tree/master/extras/lex
Copyright (C) 2001-2002 Ralph Becket <rbeck@microsoft.com>
Copyright (C) 2001-2002 The Rationalizer Intelligent Software AG
Copyright (C) 2002, 2006, 2010-2011 The University of Melbourne
Copyright (C) 2015 Paul Bone
Distributed under the terms of the LGPL (no version is specified in the
original.
Examples
--------
Examples and build scripts are released into the public domain. See
LICENSE.unlicense
Documentation
-------------
The Plasma documentation (the contents of the doc/ directory, except for
the style guides and asciidoc.css, plus the *.md files excluding
CODE_OF_CONDUCT.md) is Copyright (C) 2015-2017 Plasma
Team and made available under the Creative Commons
Attribution-ShareAlike 4.0 International Public License
See LICENSE.docs
CODE_OF_CONDUCT.md is Copyright Plasma Team, Rust Project and various
other authors. It is distributed under the Creative Commons
Attribution-ShareAlike 3.0 license.
docs/*_Style.txt
----------------
The style guides are derrived from the Mercury Project's where their
copyright and licenseing terms are unclear. We use them with permission.
docs/html/asciidoc.css
----------------------
Copyright (C) 2000-2007 Stuart Rackham
License: GPL2 or later
================================================
FILE: LICENSE.code
================================================
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
================================================
FILE: LICENSE.docs
================================================
The Plasma documentation (the contents of the doc/ directory, except for the
style guides) is Copyright (C) 2015-2018 Plasma Team and made available
under the
Creative Commons Attribution-ShareAlike 4.0 International
Public License
The style guides are derived from the Mercury Project's where their
copyright and licensing terms are unclear. We use them with permission.
The license text is:
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.
================================================
FILE: LICENSE.unlicense
================================================
Some files in this project are free and unencumbered software released into
the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or distribute
this software, either in source code form or as a compiled binary, for any
purpose, commercial or non-commercial, and by any means.
In jurisdictions that recognize copyright laws, the author or authors of
this software dedicate any and all copyright interest in the software to the
public domain. We make this dedication for the benefit of the public at
large and to the detriment of our heirs and successors. We intend this
dedication to be an overt act of relinquishment in perpetuity of all present
and future rights to this software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org>
================================================
FILE: Makefile
================================================
#
# This is free and unencumbered software released into the public domain.
# See ../LICENSE.unlicense
#
# vim: noet sw=4 ts=4
#
# ======================
#
# No configuration here
# See build.mk
include defaults.mk
-include build.mk
#
# ======================
# As the build system gets more complex I want to avoid autoconf. Perhaps
# instead create a config.h and makefile for each major OS+platform
# combination. An optional configure script could put the right file in
# place. Also consider autosetup.
vpath %.m src
vpath %.c runtime
vpath %.cpp runtime
vpath %.h runtime
vpath %.o runtime
vpath %.txt docs
vpath %.html docs/html
MERCURY_SOURCES=$(wildcard src/*.m)
# There are no C sources but we keep this in case we add some C code (eg
# a library interface.) The tags target will need to be fixed if C sources
# are added.
C_SOURCES=
# NOTE that when we add alternative interpreters we'll need to seperate out
# the generic files, that includes updating pz_closure.h so it includes
# different files.
CXX_SOURCES=runtime/pz_main.cpp \
runtime/pz.cpp \
runtime/pz_builtin.cpp \
runtime/pz_code.cpp \
runtime/pz_data.cpp \
runtime/pz_foreign.cpp \
runtime/pz_generic_closure.cpp \
runtime/pz_generic_builtin.cpp \
runtime/pz_generic_run.cpp \
runtime/pz_gc.cpp \
runtime/pz_gc_alloc.cpp \
runtime/pz_gc_collect.cpp \
runtime/pz_gc_util.cpp \
runtime/pz_instructions.cpp \
runtime/pz_io.cpp \
runtime/pz_library.cpp \
runtime/pz_memory.cpp \
runtime/pz_option.cpp \
runtime/pz_read.cpp \
runtime/pz_string.cpp \
runtime/pz_generic.cpp \
runtime/pz_generic_builder.cpp
C_CXX_SOURCES=$(C_SOURCES) $(CXX_SOURCES)
C_HEADERS=$(wildcard runtime/*.h)
OBJECTS=$(patsubst %.c,%.o,$(C_SOURCES)) $(patsubst %.cpp,%.o,$(CXX_SOURCES))
DOCS_HTML=docs/index.html \
docs/getting_started.html \
docs/user_guide.html \
docs/plasma_ref.html \
docs/contributing.html \
docs/dev_howto_make_pr.html \
docs/dev_compiler_internals.html \
docs/dev_testing.html \
docs/dev_style_mercury.html \
docs/dev_style_c.html \
docs/dev_mercury_grades.html \
docs/dev_maintainers.html \
docs/dev_bugtracking.html \
docs/design_principles.html \
docs/design_concept_map.html \
docs/design_types.html \
docs/design_ideas.html \
docs/references.html \
docs/pz_machine.html
# Extra development modules
ifeq ($(BUILD_TYPE),dev)
CXX_SOURCES+= \
runtime/pz_gc_debug.cpp \
runtime/pz_trace.cpp
else
endif
ifneq ($(shell which $(ASCIIDOC)),)
DOCS_TARGETS=$(DOCS_HTML)
else
DOCS_TARGETS=.docs_warning
endif
CFLAGS=$(DEPFLAGS) $(C_CXX_FLAGS) $(C_ONLY_FLAGS)
CXXFLAGS=$(DEPFLAGS) $(C_CXX_FLAGS) $(CXX_ONLY_FLAGS)
$(shell mkdir -p $(DEPDIR)/runtime >/dev/null)
.SUFFIXES:
.PHONY: all
all : progs docs
.PHONY: progs
progs : \
runtime/plzrun \
src/plzasm \
src/plzbuild \
src/plzc \
src/plzdisasm \
src/plzgeninit \
src/plzlnk
.PHONY: install
install: install_progs install_docs install_examples
.PHONY: install_dirs
install_dirs:
$(INSTALL_DIR) $(DEST_DIR)$(BINDIR)
$(INSTALL_DIR) $(DEST_DIR)$(DOCDIR)
.PHONY: install_progs
install_progs : install_dirs progs
$(INSTALL_STRIP) runtime/plzrun $(DEST_DIR)$(BINDIR)
$(INSTALL_STRIP) src/plzasm $(DEST_DIR)$(BINDIR)
$(INSTALL_STRIP) src/plzbuild $(DEST_DIR)$(BINDIR)
$(INSTALL_STRIP) src/plzc $(DEST_DIR)$(BINDIR)
$(INSTALL_STRIP) src/plzdisasm $(DEST_DIR)$(BINDIR)
$(INSTALL_STRIP) src/plzgeninit $(DEST_DIR)$(BINDIR)
$(INSTALL_STRIP) src/plzlnk $(DEST_DIR)$(BINDIR)
.PHONY: install_docs
install_docs : install_dirs docs
cd docs/ ; for FILE in $$(find -name '*.txt' -o -name '*.html' ); do \
$(INSTALL) $$FILE $(DEST_DIR)$(DOCDIR); \
done
if [ -f docs/index.html ]; then \
$(INSTALL_DIR) $(DEST_DIR)$(DOCDIR)/css; \
$(INSTALL_DIR) $(DEST_DIR)$(DOCDIR)/images; \
$(INSTALL) docs/css/asciidoc.css $(DEST_DIR)$(DOCDIR)/css; \
$(INSTALL) docs/css/docs-offline.css $(DEST_DIR)$(DOCDIR)/css; \
$(INSTALL) docs/images/favicon.ico $(DEST_DIR)$(DOCDIR)/images; \
$(INSTALL) docs/images/sunt-200.png $(DEST_DIR)$(DOCDIR)/images; \
fi
.PHONY: install_examples
install_examples : install_dirs
$(INSTALL_DIR) $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/BUILD.plz $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/README.md $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/hello.p $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/fib.p $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/module_example.p $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/module_to_import.p $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/mr4.p $(DEST_DIR)$(DOCDIR)/examples
$(INSTALL) examples/temperature.p $(DEST_DIR)$(DOCDIR)/examples
# .mer_progs must be real and not a phony target to make this work with
# make -j
src/plzasm : .mer_progs
touch src/plzasm
src/plzbuild : .mer_progs
touch src/plzbuild
src/plzc : .mer_progs
touch src/plzc
src/plzdisasm : .mer_progs
touch src/plzdisasm
src/plzgeninit : .mer_progs
touch src/plzgeninit
src/plzlnk : .mer_progs
touch src/plzlnk
.mer_progs : $(MERCURY_SOURCES) runtime/pz_config.h $(C_HEADERS)
rm -f src/*.err
(cd src; $(MMC_MAKE) --cflags="$(C_CXX_FLAGS_BASE)" $(MCFLAGS) plzasm)
(cd src; $(MMC_MAKE) --cflags="$(C_CXX_FLAGS_BASE)" $(MCFLAGS) plzbuild)
(cd src; $(MMC_MAKE) --cflags="$(C_CXX_FLAGS_BASE)" $(MCFLAGS) plzc)
(cd src; $(MMC_MAKE) --cflags="$(C_CXX_FLAGS_BASE)" $(MCFLAGS) plzdisasm)
(cd src; $(MMC_MAKE) --cflags="$(C_CXX_FLAGS_BASE)" $(MCFLAGS) plzgeninit)
(cd src; $(MMC_MAKE) --cflags="$(C_CXX_FLAGS_BASE)" $(MCFLAGS) plzlnk)
touch .mer_progs
# We need -rdynamic here so that the foreign code libraries can resolve
# symbols in the runtime's executable.
runtime/plzrun : $(OBJECTS)
$(CXX) $(CFLAGS) -o $@ $^ -ldl -rdynamic
%.o : %.c runtime/pz_config.h
$(CC) $(CFLAGS) -o $@ -c $<
mv -f $(DEPDIR)/$(basename $*).Td $(DEPDIR)/$(basename $*).d
%.o : %.cpp runtime/pz_config.h
$(CXX) $(CXXFLAGS) -o $@ -c $<
mv -f $(DEPDIR)/$(basename $*).Td $(DEPDIR)/$(basename $*).d
runtime/pz_config.h : runtime/pz_config.h.in defaults.mk build.mk
sed -e 's/@VERSION@/${VERSION}/' < $< > $@
$(DEPDIR)/%.d : ;
.PRECIOUS: $(DEPDIR)/%.d
.PHONY: test
test : test-old test-new
.PHONY: test-old
test-old : src/plzasm src/plzlnk src/plzc src/plzbuild runtime/plzrun
(cd tests-old; ./run_tests.sh $(BUILD_TYPE))
.PHONY: test-new
test-new : src/plzasm src/plzlnk src/plzc src/plzbuild runtime/plzrun
BUILD_TYPE=$(BUILD_TYPE) ./tests/run-tests.lua examples tests | ./tests/pretty.lua
.PHONY: tags
tags : src/tags runtime/tags
src/tags : $(MERCURY_SOURCES)
(cd src; mtags *.m)
runtime/tags: $(CXX_SOURCES) $(C_HEADERS)
(cd runtime; ctags *.cpp *.h)
.PHONY: docs
docs : $(DOCS_TARGETS)
.docs_warning :
@echo
@echo Warning: $(ASCIIDOC) not found, not building documentation.
@echo --------------------------------------------------------
@echo
touch .docs_warning
%.html : %.txt docs/asciidoc.conf
$(ASCIIDOC) --conf-file docs/asciidoc.conf -o $@ $<
#
# Clean removes all intermediate files
#
.PHONY: clean
clean : localclean
$(MAKE) -C examples clean
$(MAKE) -C tests-old/pzt clean
$(MAKE) -C tests-old/modules clean
$(MAKE) -C tests-old/modules-invalid clean
find tests -name *.pz -o \
-name *.pzo -o \
-name *.pi -o \
-name *.out -o \
-name *.outs -o \
-name *.so \
| xargs -r rm
find tests -name _build -o \
-name \*.dir \
| xargs -r rm -r
#
# Realclean removes all generated files plus plasma-dump files.
#
.PHONY: realclean
realclean : localclean
$(MAKE) -C examples realclean
$(MAKE) -C tests-old/pzt realclean
$(MAKE) -C tests-old/modules realclean
$(MAKE) -C tests-old/modules-invalid realclean
rm -f src/tags
rm -f src/plzasm src/plzbuild src/plzc src/plzdisasm src/plzgeninit \
src/plzlnk
rm -rf src/Mercury
rm -f .mer_progs
rm -rf runtime/tags runtime/plzrun
rm -rf $(DOCS_HTML)
.PHONY: localclean
localclean:
for dir in \
date0s \
date3s \
dates \
err_dates \
int0s \
int2s \
int3s \
ints \
module_deps ; \
do \
rm -rf src/Mercury/$$dir; \
done
for dir in cs os c_dates ; do \
rm -rf src/Mercury/*/*/Mercury/$$dir; \
done
rm -rf src/*.err src/*.mh
rm -rf runtime/*.o runtime/pz_config.h
rm -rf examples/*.pz examples/*.diff examples/*.out
rm -rf .docs_warning
rm -rf $(DEPDIR)
# Nither formatting tool does a perfect job, but clang-format seems to be
# the best.
.PHONY: format
format: formatclangformat
.PHONY: formatclangformat
formatclangformat:
$(CLANGFORMAT) -style=file -i $(C_SOURCES) $(CXX_SOURCES) $(C_HEADERS)
include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(C_CXX_SOURCES))))
================================================
FILE: README.md
================================================
# Plasma Language
## *a new programming language*
Plasma is a new programming language for safe and efficient general purpose
use.
It is a statically typed, side-effect free single assignment language
and will have functional programming and concurrent programming features.
It will support deterministic parallel execution.
For a general overview, please visit
[https://plasmalang.org/](https://plasmalang.org/)
It is in early development.
It is free software, Copyright (C) 2015-2025 The Plasma Team, distributed
mostly under the MIT license, see [LICENSE](LICENSE) for details.

## Getting started
This README.md contains some quick info for getting started.
For more complete info please see our
[getting started guide](https://plasmalang.org/docs/getting_started.html).
### Dependencies
Plasma has been tested on Linux, Windows subsystem for Linux 1 and 2 on
x86\_64.
You will need:
* A C compiler (C99 on a POSIX.1-2008 environment), I've been testing with
GCC. Clang should also work.
* GNU Make
* [Mercury](https://www.mercurylang.org/).
A recent stable version is required (22.01.x).
Plasma's CI currently tests with 22.01.
* The [ninja build system](https://ninja-build.org), at least version 1.10.
Optionally to build the documentation you will also need:
* asciidoc
* source-highlight
Optionally to run the test suite you will also need:
* lua
* lua-file-system
* lua-posix
* lua-curses
* diffutils
* ncurses
On Debian (also Ubuntu, Mint etc) Linux
$ apt install build-essential ninja-build lua5.3 lua-filesystem lua-posix diffutils asciidoc source-highlight ncurses-bin
Will get you started, then proceed to installing Mercury below.
### Mercury installation
The easiest way to install Mercury is to install the
[.deb packages](https://dl.mercurylang.org/deb/) (on Debian, Ubuntu, etc).
Otherwise download Mercury's [source package](https://dl.mercurylang.org)
and follow the
installation instructions in the
[INSTALL](https://github.com/Mercury-Language/mercury/blob/master/.INSTALL.in)
file.
We've made some
[notes about grades](https://plasmalang.org/docs/grades.html)
that may help with choosing which grades you may need.
There is also a
[README.bootstrap](https://github.com/Mercury-Language/mercury/blob/master/README.bootstrap)
file with Mercury bootstrapping information if you wish to do that, it may
also provide some additional explaination.
### Usage
Copy `template.mk` to `build.mk` and edit it to make any build configuration
changes you need.
Use ```make``` in the root directory to build the project.
Then ```make install`` to install the tools into ```$PREFIX/bin```.
This compiles and installs the following programs. Make sure they're in
your ```PATH```.
* src/plzc - The plasma compiler, compiles plasma (```.p```) files to
plasma modules (```.pzo```)
* src/plzlnk - The plasma linker, links one more more modules (```.pzo```)
into a plasma program (```.pz```)
* src/plzbuild - The plasma build system
* runtime/plzrun - The runtime system, executes plasma programs (```.pz```).
* src/plzasm - The plasma bytecode assembler. This compiles textual bytecode
(```.pzt```) to bytecode (```.pzo```). It is useful for testing the
runtime.
There are example plasma programs in ```examples/```. Running ```plzbuild```
in ```examples/``` will build them.
Each program's bytecode is copied to a file in ```examples/``` eg
```hello.pz```, run them with ```plzrun <bytecode>```.
### Layout
* [docs](docs) - Documentation
* [examples](examples) - Example Plasma programs
* [runtime](runtime) - Runtime system (C code)
* [scripts](scripts) - Some scripts to aid developers
* [src](src) - The compiler and other tools
* [tests](tests) - The test suite (in addition to some of the files in
[examples](examples))
## Contributing
Please see [CONTRIBUTING.md](CONTRIBUTING.md) and
[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
For detailed information including what to work on please see
[Contributing to Plasma](https://plasmalang.org/docs/contributing.html) in
our documentation.
## Getting help
If you're stuck and the [Documentation](https://plasmalang.org/docs/)
doesn't contain the answer or clue you need or you're struggling to find it.
Please ask for help.
The [Contact](https://plasmalang.org/contact.html) page of the website lists
all the ways you can get in touch.
In particular the
[Plasma Help mailing list](https://plasmalang.org/lists/listinfo/help)
and
[Discord server](https://discord.gg/x4g83w7tKh) are the best
resources for help.
For bugs or missing information please
[file a bug](https://github.com/PlasmaLang/plasma/issues/new).
================================================
FILE: SECURITY.md
================================================
# Security Policy
## Supported Versions
The master branch is currently the only "supported" version. In the future
there will be stable / development versions with various support lengths.
The bytecode/runtime is not designed as a secure execution environment. Bad
bytecode can run arbitrary code / cause crashes.
For a secure bytecode/interpreter consider using
[WebAssembly](https://webassembly.org).
## Reporting a Vulnerability
Write an e-mail to `bugs@plasmalang.org`. Do not submit a PR or issue, Github does not support "private" PRs and they
shouldn't be used to share information that could lead to users being harmed if shared publicly.
================================================
FILE: THANKS
================================================
Thanks
======
Plasma is primarly developed by Paul Bone.
We would also like to thank the following people for their contributions and
support:
Code contributions by:
CcxWrk
Gert Meulyzer
Jace Benson
James Barnes
Jeremy Wright
Manu Abraham
rightfold (https://github.com/rightfold)
Website contributions by:
Anne Ogborn
Slavfox (https://github.com/slavfox)
Tobin Harding
Brainstorming/checking, discussions and general support:
Brendan Zabarauskas
Emily McDonough (AlaskanEmily)
Gert Meulyzer
Michael Richter
================================================
FILE: defaults.mk
================================================
#
# This is free and unencumbered software released into the public domain.
# See ../LICENSE.unlicense
#
# vim: noet sw=4 ts=4 ft=make
#
# Where programs are installed
PREFIX=/usr/local
BINDIR=$(PREFIX)/bin
DOCDIR=$(PREFIX)/share/doc/plasma
VERSION=dev
# The number of parallel jobs the Mercury compiler should spawn.
JOBS=$(shell if X=$$(nproc 2>&1); then echo $$X; else echo 1; fi)
# How the Mercury compiler should be called. You may need to adjust this if
# it is not in your path.
MMC_MAKE=mmc --make -j$(JOBS) --use-grade-subdirs
# How the C compiler should be called. gcc and clang should both work.
# Note that Mercury has its own configuration for its C backend, which is
# not, and must not be changed here.
# Note also that we'd normally define _DEFAULT_SOURCE once in
# C_CXX_FLAGS_BASE, but Mercury also defines this so we avoid a warning by
# listing it twice for C_ONLY then CXX_ONLY.
CC=gcc
CXX=g++
C_CXX_FLAGS_BASE=-D_POSIX_C_SOURCE=200809L
C_ONLY_FLAGS=-std=c99 -D_DEFAULT_SOURCE
CXX_ONLY_FLAGS=-std=c++11 -fno-rtti -fno-exceptions -D_DEFAULT_SOURCE
MCFLAGS=
# gcc and probably clang support dependency tracking. If your compiler
# doesn't uncomment the 2nd line.
DEPDIR=.dep
DEPFLAGS=-MT $@ -MMD -MP -MF $(DEPDIR)/$(basename $*).Td
# How to install programs, specify here the owner, group and mode of
# installed files.
INSTALL=install
INSTALL_STRIP=install -s
INSTALL_DIR=install -d
# How to call asciidoc (optional). A full path or any flags here won't work
# without other changes to the makefile.
ASCIIDOC=asciidoc
# How to call clang-format (optional)
CLANGFORMAT=clang-format-10
# This base configuration works on Linux but you may need to change them for
# other systems / compilers.
C_CXX_FLAGS=$(C_CXX_FLAGS_BASE) -O1 -Wall
BUILD_TYPE=rel
# This is a suitable build for development. It has assertions enabled in
# the C code some of which are slow, so they shouldn't be used for
# performance measurement. Comment it out to use one of the optimised
# builds below.
#
# Note to maintainers: When Plasma is actually "used" we should change this
# default and provide a better way for developers to setup a "dev" build
# with assertions and other checks.
# Development build options
MCFLAGS+=--warn-dead-procs
C_CXX_FLAGS+=-Werror -DDEBUG -DPZ_DEV
BUILD_TYPE=dev
================================================
FILE: docs/.gitignore
================================================
*.html
================================================
FILE: docs/README.md
================================================
Documentation
=============
We're assuming you are running Linux. For Mac it will probably be similar. Since Plasma is currently not supported on Windows, building the docs on that platform is also not documented.
You will need a working copy of AsciiDoc on your PC to build the documentation.
For Ubuntu, it is simply a matter of typing
```shell
sudo apt-get install asciidoc source-highlight
```
For Fedora:
```shell
sudo dnf install asciidoc
```
For other distros, check your package manager.
You also need to install [source-highlight](https://www.gnu.org/software/src-highlite/source-highlight.html) to get the C code properly highlighted. Your package manager should also have this.
With these installed, you should be set.
To build the documentation type ``make docs`` in the project's top-level
directory. This will generate the HTML output.
================================================
FILE: docs/asciidoc.conf
================================================
[attributes]
linkcss=yes
backend=html5
[header]
<!DOCTYPE html>
<html lang="{lang=en}">
<head>
<meta charset="UTF-8">
<meta name="generator" content="AsciiDoc {asciidoc-version}">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="{doctitle}: {description}">
<meta name="keywords" content="{keywords}">
<meta name="robots" content="index, follow">
<link rel="icon" type="image/png" href="images/favicon.ico"/>
<title>Plasma Programming Language: {doctitle}</title>
<link rel="stylesheet" href="css/asciidoc.css" type="text/css">
<link rel="stylesheet" href="css/docs-offline.css" type="text/css">
<script type="text/javascript">
var asciidoc = { // Namespace.
/////////////////////////////////////////////////////////////////////
// Table Of Contents generator
/////////////////////////////////////////////////////////////////////
/* Author: Mihai Bazon, September 2002
* http://students.infoiasi.ro/~mishoo
*
* Table Of Content generator
* Version: 0.4
*
* Feel free to use this script under the terms of the GNU General Public
* License, as long as you do not remove or alter this notice.
*/
/* modified by Troy D. Hanson, September 2006. License: GPL */
/* modified by Stuart Rackham, 2006, 2009. License: GPL */
// toclevels = 1..4.
toc: function (toclevels) {
function getText(el) {
var text = "";
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
text += i.data;
else if (i.firstChild != null)
text += getText(i);
}
return text;
}
function TocEntry(el, text, toclevel) {
this.element = el;
this.text = text;
this.toclevel = toclevel;
}
function tocEntries(el, toclevels) {
var result = new Array;
var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
// Function that scans the DOM tree for header elements (the DOM2
// nodeIterator API would be a better technique but not supported by all
// browsers).
var iterate = function (el) {
for (var i = el.firstChild; i != null; i = i.nextSibling) {
if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
var mo = re.exec(i.tagName);
if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
}
iterate(i);
}
}
}
iterate(el);
return result;
}
var toc = document.getElementById("toc");
if (!toc) {
return;
}
// Delete existing TOC entries in case we're reloading the TOC.
var tocEntriesToRemove = [];
var i;
for (i = 0; i < toc.childNodes.length; i++) {
var entry = toc.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div'
&& entry.getAttribute("class")
&& entry.getAttribute("class").match(/^toclevel/))
tocEntriesToRemove.push(entry);
}
for (i = 0; i < tocEntriesToRemove.length; i++) {
toc.removeChild(tocEntriesToRemove[i]);
}
// Rebuild TOC entries.
var entries = tocEntries(document.getElementById("content"), toclevels);
for (var i = 0; i < entries.length; ++i) {
var entry = entries[i];
if (entry.element.id == "")
entry.element.id = "_toc_" + i;
var a = document.createElement("a");
a.href = "#" + entry.element.id;
a.appendChild(document.createTextNode(entry.text));
var div = document.createElement("div");
div.appendChild(a);
div.className = "toclevel" + entry.toclevel;
toc.appendChild(div);
}
if (entries.length == 0)
toc.parentNode.removeChild(toc);
},
/////////////////////////////////////////////////////////////////////
// Footnotes generator
/////////////////////////////////////////////////////////////////////
/* Based on footnote generation code from:
* http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
*/
footnotes: function () {
// Delete existing footnote entries in case we're reloading the footnodes.
var i;
var noteholder = document.getElementById("footnotes");
if (!noteholder) {
return;
}
var entriesToRemove = [];
for (i = 0; i < noteholder.childNodes.length; i++) {
var entry = noteholder.childNodes[i];
if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
entriesToRemove.push(entry);
}
for (i = 0; i < entriesToRemove.length; i++) {
noteholder.removeChild(entriesToRemove[i]);
}
// Rebuild footnote entries.
var cont = document.getElementById("content");
var spans = cont.getElementsByTagName("span");
var refs = {};
var n = 0;
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnote") {
n++;
var note = spans[i].getAttribute("data-note");
if (!note) {
// Use [\s\S] in place of . so multi-line matches work.
// Because JavaScript has no s (dotall) regex flag.
note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
spans[i].innerHTML =
"[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
spans[i].setAttribute("data-note", note);
}
noteholder.innerHTML +=
"<div class='footnote' id='_footnote_" + n + "'>" +
"<a href='#_footnoteref_" + n + "' title='Return to text'>" +
n + "</a>. " + note + "</div>";
var id =spans[i].getAttribute("id");
if (id != null) refs["#"+id] = n;
}
}
if (n == 0)
noteholder.parentNode.removeChild(noteholder);
else {
// Process footnoterefs.
for (i=0; i<spans.length; i++) {
if (spans[i].className == "footnoteref") {
var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
href = href.match(/#.*/)[0]; // Because IE return full URL.
n = refs[href];
spans[i].innerHTML =
"[<a href='#_footnote_" + n +
"' title='View footnote' class='footnote'>" + n + "</a>]";
}
}
}
},
install: function(toclevels) {
var timerId;
function reinstall() {
if (toclevels) {
asciidoc.toc(toclevels);
}
asciidoc.footnotes();
}
function reinstallAndRemoveTimer() {
clearInterval(timerId);
reinstall();
}
timerId = setInterval(reinstall, 500);
if (document.addEventListener)
document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
else
window.onload = reinstallAndRemoveTimer;
}
}
</script>
<script type="text/javascript">
/*<![CDATA[*/
asciidoc.install({toc,toc2?{toclevels}});
/*]]>*/
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-39671467-2', 'auto');
ga('send', 'pageview');
</script>
{docinfo1,docinfo2#}{include:{docdir}/docinfo.html}
{docinfo,docinfo2#}{include:{docdir}/{docname}-docinfo.html}
</head>
<body>
<div class="banner">
<h1><img src="images/sunt-200.png" width="80" alt="sun image"/>PLASMA</h1>
</div>
<div class="menu-gap"></div>
<div id="content" class="content">
<div id="header">
<h1>{doctitle}</h1>
<!--
<span id="author">{author}</span><br>
<span id="email" class="monospaced"><<a
href="mailto:{email}">{email}</a>></span><br>
-->
<span id="copyright">{copyright}<br/>Distributed under {license}</span><br/>
<span id="revdate">Updated: {revdate}</span>
{toc,toc2#}{toc-placement$auto:}{template:toc}
</div>
[footer]
{disable-javascript%<div id="footnotes"><hr></div>}
<div id="footer">
</div>
</body>
</html>
================================================
FILE: docs/contributing.txt
================================================
Contributing to Plasma
======================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: September, 2022
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
This file contains information for potential and current Plasma
contributors.
== Summary and legal stuff
* We prefer github pull requests or patches mailed to the
https://plasmalang.org/lists/listinfo/dev[developers' mailing list].
If you need to discuss a security issue confidently you can e-mail
plasma at plasmalang dot org
* The license of your contribution must match the project's licenses:
** Code: MIT
** Docs: CC BY-SA 4.0
** Build scripts, tests, and sample code: Unlicense
* No contributor agreement is required, you retain the copyright for your
contribution.
* Please follow the style guides as much as possible (see below)
* Please format your log messages following the log message style (see
below)
* By opening a PR you acknowledge these terms and agree to the
https://github.com/PlasmaLang/plasma/blob/master/CODE_OF_CONDUCT.md[Code
of Conduct].
* By opening an issue or adding a comment or message you also agree to the
https://github.com/PlasmaLang/plasma/blob/master/CODE_OF_CONDUCT.md[Code
of Conduct].
== Getting started
For information on how to setup the dependencies and compile Plasma the best
place to start is the link:getting_started.html[Getting Started] Guide.
=== vim
If you'll be working on the compiler you probably want some editor support
for Mercury. Support is included in the
https://github.com/Mercury-Language/mercury/tree/master/vim[Mercury
repository]/source distribution
if you've used the Debian package it's at
`/usr/share/doc/mercury-rotd-tools/examples/vim/`
You may also wish to use the
https://github.com/PlasmaLang/plasma/tree/master/scripts[extra script]
and configuration change to make it easier to build the Mercury sources from
within vim.
== What to contribute
You want to contribute but aren't sure what you'd like to work on?
The most valuable contributions will fit with Plasma's
https://plasmalang.org/about.html[goals] and current development status
(https://plasmalang.org/roadmap.html[project roadmap]).
The project is at an early stage and therefore we are prioritising work that
makes the language useful above things like compiler optimisations.
=== Suggestions and good first bugs
If you're looking for a suggestion of what to contribute
please consider the
https://github.com/PlasmaLang/plasma/issues?q=is%3Aopen+is%3Aissue+no%3Aassignee[open unassigned github issues]
We label our issues within github to help searchability but also to provide
some ideas about what is involved with each issue.
Some issues have the
https://github.com/PlasmaLang/plasma/issues?q=is%3Aopen+is%3Aissue+no%3Aassignee+label%3A%22meta%3A+good-first-bug%22[good-first-bug] label.
These tend to be really small changes that require relatively little
experience to complete.
They should take someone with a year of programming experience no more than
2 hours, usually much less.
They might not be suitable for someone in their first month or two of
programming.
The
https://github.com/PlasmaLang/plasma/issues?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+no%3Aassignee+label%3A%22meta%3A+no-domain-knowledge%22+[no-domain-knowledge]
label contains more difficult changes.
These may require a fair amount of programming experience but they do
not require any programming language implementation experience,
or otherwise have very clear help.
Other labels can indicate what component they are relevant to, for example:
'component: docs' or 'component: compiler'.
Or what skills may be required 'skill: C++'.
There is also a
https://github.com/PlasmaLang/plasma/issues?q=is%3Aopen+is%3Aissue+label%3A%22meta%3A+help+wanted%22[help wanted]
label for anything where people already involved with the project might not
have the skills we think are required.
If you file a new bug, do not worry about adding labels, a project maintainer
will follow link:bugtracking.html[this guide] to triage it.
There are also many `TODO` and `XXX` notes in the source code, which things
that are not handled. Search for the strings `TODO` and `XXX`. Keep in
mind that there may be good reasons why these are not yet handled, eg: it
may depend on other incomplete work.
If you find something undocumented whose behaviour is unlikely to change,
consider filling in that part of the documentation.
When reading code if something isn't clear, please ask us about it. We'll
also take this as a hint that we should have written (better) code comments
or docs.
=== Get in contact
If you've got a big idea it's often good to
https://plasmalang.org/lists/listinfo/dev[discuss it with us]
before starting.
We may be able to give you some pointers or let you know what kinds of
problems you may encounter.
For example we might not be interested n making the language weakly typed
and discussing this beforehand may avoid disappointment later.
Ultimately we want you to enjoy working with Plasma and that means making
the most of your development time.
== How to contribute
We want to build a great language and we also want you/us to have a good time
building a great language. These guidelines will make it easier for us to
review and maintain your code, and hopefully for you to have a better
experience during code-review.
=== Before beginning
It is best to start each piece of work on a new git branch. Create a branch
off of master and commit your changes there as you go.
Open/comment on/assign yourself on an issue. Let us know what you want to
work as part of github's issue tracking (see above). We can add you to the
Plasma project so that you can be assigned to an issue, then we know who is
working on it.
=== Making your changes
If you're making a series of patches, try to organise the patches so that
each patch makes sense on its own. Git has many features for doing this
including cherry picking and rebasing.
Code contributions should follow the style guides as much as possible.
Deviations that make code more readable are permitted.
The guides are
https://plasmalang.org/docs/Mercury_style.html[Mercury style guide]
and
https://plasmalang.org/docs/C_style.html[C style guide].
TODO: Provide information about project structure.
Spell check and test your work, use +make test+ for the latter. Each patch
should, when applied in series, pass the test suite.
=== Documenting your changes
User-visible changes including new options, features and behaviours should be
documented. For now options are documented in the `--help` text of each
program. While designs and concepts are documented in one of the files in
the docs directory, these files are asciidoc text files.
=== Submitting your changes
All code contributions must be made under the appropriate license:
* Code: MIT
* Docs: CC BY-SA 4.0
* Build scripts, tests, and sample code: Unlicense
No transfer of copyright or other rights or permissions is required.
Log messages should follow the style:
[component(s)] Title
Description
Any other changes including changes that were needed to support this
change or followed as a concequence of this change.
We provide a +.gitmessage+ in the root of the repository.
Run this command to start using the new commit message template:
git config --local commit.template /path/to/repo/.gitmessage
_components_ is one or more parts of the system. This helps people
identify (in mailing lists, change logs etc) what kind of change has been
made at a glace. It also helps people and software search for changes.
Current components are:
* *pz*: the PZ file format,
* *rt*: the runtime generally,
* *rt/interp*: the bytecode interpreter,
* *rt/gc*: the garbage collector,
* *asm*: the PZ assembler,
* *compiler*: the compiler generally,
* *compiler/parse*: the first phase: parsing.
* *compiler/ast*: the second phase: the AST and operations on it,
* *compiler/pre*: the third phase: the pre-core representation and operations,
* *compiler/core*: the fourth phase: the core representation and operations,
* *compiler/pz*: the fitht phase: the PZ code generator,
* *compiler/util*: other utility code in the compiler,
* *build*: the build system,
* *docs*: documentation,
* *scripts*: the build system and other scripts,
* *tests*: the test suite,
Sometimes it makes sense to pick the component with the most significant
changes rather than listing all of them. This is typical for changes to the
compiler.
Each patch should contain a single change and changes required by that
change (should compile and pass tests). Changes may be rolled together when
they're trivial related changes (eg, multiple spelling fixes).
Also, not a real component:
* *merge*: for merge commits (See the link:maintainers.html[Maintainer's
guide])
We accept contributions via pull request on github, or via e-mailed patches.
If you choose to use e-mailed patches then the +git format-patchi+ and/or
+git send-email+ tools can generate nice e-mails, however
this is not required, +diff -uNr+ is sufficient.
E-mailed patches should be sent to the
https://www.plasmalang.org/lists/listinfo/dev[dev] mailing list.
TODO: Provide suitable step-by-step instructions.
=== Our review policy
We aim to act on your changes reasonably quickly. However this is something
people do in their spare time, they may be busy with other aspects of their
lives and not reply for several days. We will provide feedback and guidance
where applicable. We want you to enjoy working with Plasma and that means
we will try to help you make the most of your development time.
A reviewer accepting your code will ask themselves "Does this change make
Plasma better?" if the answer is yes and you're a first time contributor,
they'll click the merge button and might follow-up with some further changes
of their own (eg for style). If you're more experienced they'll be a
greater expectation on you to confirm to style and cover edge cases.
== Further documentation
Documentation on specific topics of interest to Plasma implementors can be
found here.
link:dev_howto_make_pr.html[How to make a pull request]
link:dev_compiler_internals.html[Compiler structure/internals]
link:dev_testing.html[Plasma test suite]
link:dev_style_mercury.html[Mercury style guide]
link:dev_style_c.html[C and C++ style guide]
link:dev_mercury_grades.html[Mercury grades]
For maintainers:
link:dev_maintainers.html[Plasma maintainer's guide]
link:dev_bugtracking.html[Bugtracking]
Language design:
link:design_principles.html[Language design principles]
link:design_concept_map.html[Plasma Syntax to Concept Map]
link:design_types.html[Type System Design]
link:design_ideas.html[Ideas for Plasma]
link:references.html[References and Links]
Plasma bytecode and abstract machine (PZ):
link:pz_machine.html[Plasma Abstract Machine]
https://github.com/PlasmaLang/plasma/blob/master/runtime/pz_format.h[Plasma Bytecode Format]
== Getting help
If you're stuck and the https://plasmalang.org/docs/[Documentation] doesn't
contain the answer or clue you need, or you're struggling to find it.
Please ask for help.
The https://plasmalang.org/contact.html[Contact] page of the website lists
all the ways you can get in touch.
In particular the
https://plasmalang.org/lists/listinfo/help[Plasma Help mailing list]
and
https://discord.gg/x4g83w7tKh[Discord server] are the best
resources for help.
For bugs or missing information please
https://github.com/PlasmaLang/plasma/issues/new[file a bug].
// vim: set syntax=asciidoc:
================================================
FILE: docs/css/asciidoc.css
================================================
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Copyright (C) 2000-2007 Stuart Rackham */
/* Copyright (C) Plasma Team (adapted for plasmalang.org) */
/* License: GPL2 or later */
/* Default font. */
body {
font-family: Georgia,serif;
}
.content h1, .content h2, .content h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
.monospaced, code, pre {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
padding: 0;
margin: 0;
}
pre {
white-space: pre-wrap;
}
#author {
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
/* Block element titles. */
div.title, caption.title {
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* html5 specific
*
* */
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
================================================
FILE: docs/css/docs-offline.css
================================================
/*
* Copyright (C) Plasma Team
* Licensed as CC BY-NC-ND 4.0
*/
@import url(https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700|Roboto:400,400italic,700,700italic);
body {
font-family: Roboto, Arial, Sans-serif;
margin: 0px;
font-size: 14pt;
}
.content, div.banner h1, div.menu ul {
margin: 0px auto;
width: 90%;
max-width: 900px;
}
@media screen and (max-width: 360px) {
h1 {
text-align: center;
}
}
@media screen and (max-width: 800px) {
#hardwork {
display: none;
}
}
div.banner h1 {
font-weight: bold;
margin-top: 0px;
margin-bottom: 0px;
padding-top: 16px;
padding-bottom: 16px;
font-size: 48pt;
}
div.banner h1 img {
vertical-align: bottom;
}
div.banner {
background: black;
color: yellow;
}
div.menu {
background: black;
/* border-top: 2px solid red;
border-bottom: 2px solid red; */
padding-bottom: 16px;
}
div.menu-gap {
height: 48px;
background: -webkit-linear-gradient(black, white); /* Safari 5.1 to 6.0 */
background: -o-linear-gradient(black, white); /* Opera 11.1 to 12.0 */
background: -moz-linear-gradient(black white); /* Firefox 3.6 to 15 */
background: linear-gradient(black, white) grey;
background-repeat: no-repeat; /* fix for prince & okular */
}
div.menu ul {
padding-left: 0px;
}
div.menu ul li {
display: inline-block;
padding: 0.2em;
font-size: 110%;
color: yellow;
}
div.menu ul li a {
color: yellow;
text-decoration: none;
}
div.content {
margin-top: 24px;
}
div.figure {
float: right;
border: 1px solid black;
margin: 10px;
}
div.figure p.caption {
margin: 10px;
}
dt {
margin-bottom: 0.5em;
font-style: italic;
}
dd {
margin-bottom: 1em;
}
ol.milestones li ul {
list-style-type: none;
}
ol.milestones li ul li:before {
margin-left: -40px;
width: 40px;
text-align: center;
display: inline-block;
background-repeat: no-repeat;
background-position: center;
margin-top: 1px;
margin-bottom: -4px;
height: 21px;
content: " ";
}
ol.milestones li ul li.status-done:before {
background-image: url(images/icons/done-21.png);
}
ol.milestones li ul li.status-todo:before {
background-image: url(images/icons/todo-21.png);
}
ol.milestones li ul li.status-wip:before {
background-image: url(images/icons/wip-21.png);
}
ol.milestones li ul li.status-blocked:before {
background-image: url(images/icons/blocked-21.png);
}
code, pre, .monospaced {
font-family: 'Source Code Pro', "Courier New", Courier, monospace;
}
td > p {
margin-bottom: 0;
}
================================================
FILE: docs/design_concept_map.txt
================================================
Plasma Syntax to Concept Map
============================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: April 2017
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
The purpose of this document is to show for each syntax-ish thing, what the
underlying concept is. This should help us design the language on a
coherent way. It is not intended as user documentation.
== Brackets
.Brackets
|===
|Brackets | Concept(s) | Comment
| +( )+
| Expression grouping, parameter lists (functions, types & structs)
| Familiar to many programmers
| +{ }+
| Code
|
| +[ ]+
| Lists (arbitrary size)
| Lists, for loop parameters (unimplemented), *array indexing*.
| +[- -]+ or +[~ ~]+
| Streams
| Future, maybe use the ~ or - to denote whether it's a lazy list or a
parallel stream (channel).
| +[: :]+
| Arrays (fixed size sequences)
|
| +[% %]+ or +[# #]+ or something else?
| Dictionariies,
|
|===
== Symbols
.Symbols
|===
|Symbol | Concept(s) | Comment
| +//+
| Comment
|
| +/\*+ +*/+
| Comment
|
| +_+ (underscore)
| Wildcard
| Used instead of variables in patterns, arguments and the LHS of assignments
| +\*+, +/+, +%+, +++, +\-+
| Arithmetic operators
|
| '-'
| Unary minus
| Similar concept as subtraction
| +<+, +>+, +<=+, +>=+, +==+, +!=+
| Comparison operators
|
| +and+, +or+, +not+
| Logical operators
| Not really "symbols" in the character ranges meaning of the word, but
included here alongside other operators.
| ++
| Concatenation operator
|
| +,+
| Parameter separation
| in function results, argument lists (functions and types) and field lists,
loop dot products.
| +*+
| Wildcard (in import/export lists), Multiplication
|
| +\|+
| "or" in structure and type alternatives, "join" in lists and other
structures.
|
| +&+
| "and" cross product in loop inputs.
| Future, maybe, "and" doesn't mean "cross" or "by".
| +:+
| "has type"
|
| +.+
| Scope qualification (access something from within another scope)
|
| +\->+
| "results in"
| Used to separates a function's return values from its inputs,
may be used in lambda expressions also.
| +\<-+
| "gets", different from "let"
| Part of loop syntax, unimplemented.
| +=+
| "let"
| The LHS (a new variable) is given the value of the RHS (also in struct
construction and deconstruction).
Or in type declarations, the type name on the LHS has the set of values
from the RHS.
Or in list outputs and reductions (unimplemented).
In all of these cases the meaning is "let".
| +:=+
| "store" or "write"
| The value on the LHS is updated with the RHS, this makes sense for arrays.
| +!+
| Side-effect
| added to a function call to indicate that it uses or
observers a resource.
| +..+
| "to"
| Future: For ranges, eg in array slicing.
| +\+
| "lambda"
| Future
| +$+
|
| Future: state variable syntax
| +@+
| "at"
| Reserved in case I ever want to add pointer manipulation a la PAWNS.
| +#+
|
| Unused
| +%+
|
| Unused: Maybe string formatting?
|===
== Issues
.Issues
|===
|Symbol | Issue
| +[ ]+
| This usually means a sequence but is also used for array indexing.
That appears to be in conflict, however using +[ ]+ for lists and array
indexing will be familiar from other languages.
| +\|+
| Used in type and structure expressions to mean "or" and struct, list etc
manipulation to mean "join".
| +{}+, +_()+ and +{: :}+
| Minor issue, I kinda like {} for code and dictionaries and structures.
But (so far) I've chosen to avoid these conflicts.
|===
// vim: set syntax=asciidoc:
================================================
FILE: docs/design_ideas.txt
================================================
Plasma Language Ideas
=====================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: October 2017
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
== Ideas to consider
Many of these should also wait until later. But this category is separate
as I'm not sure that these are good ideas.
GC::
* Regions
* Mark-compact for acyclic objects
Optimisations::
* Convert ANF to relaxed ANF then to PZ. Use the relaxed ANF to find
single use variables and optimize them away to generate more efficient PZ.
Do some other def-use analysis too, including for parallel tasks.
Types::
* Use structural matching to some degree, an instance can implement more
than one interface, and may define more than an interface requires.
* When supporting interfaces, maybe they can be integrated with the
package system in a kind-of "does this package provide X?"
* Evaluate HKTs.
* Refinement types / path-aware constraints.
* Use symbols like ? for maybe and | for or, like Flow Types.
* Consider safe/unsafe integer operations such as overflows, division by
zero etc. Allow checking for error to be done at the end of a
complex calculation or by throwing an exception.
+ When implementing more subtyping, during an ambigious type which the
value of a match expression, prefer the type (if there is one) that allows
the match to "cover" the whole type, and provide that as guidance to the
solver.
Syntax::
* Add field update and conditional field update syntax.
* Maybe remove parens from if-then-else conditions and other places such as
match parameters.
* Guards on cases
* Disjunctive patterns on cases
* SISAL allows "masks" (like guards or filters) on returns clauses of
loops. This looks pretty powerful.
* More succinct loop syntax, for simpler loops.
* Maybe allow simple loop outputs to be specified in the loop "head".
* Consider different syntax & and ,? for combining multiple loop inputs in
lockstep or Cartesian combinations.
* List, array and sequence comprehensions.
* Add a scope statement that contains a block allowing shadowing of some
variables, and hiding of any produced variables.
* Add let expressions?
* Add something to allow statements within expressions?
* Probably drop { } for dictionary constants in favor of [ ] with a => to
separate keys from values.
+ Add more logical operators to the langauge, maybe xor and implication,
probably via keywords or functions rather than symbols.
Semantics::
* Predicate expressions as a syntax sugar for applicative.
* https://plasmalang.org/list-archives/dev/2019-October/000033.html[Language
"levels"]
* Various ideas around resources and higher-order code:
** https://plasmalang.org/list-archives/dev/2018-January/000026.html[Most
recent post]
** https://plasmalang.org/list-archives/dev/2017-September/000021.html[Earlier
thread]
Other::
* Read about Facebook reason wrt naming things and syntax.
* Use command line parsing as example code for language & library.
// vim: set syntax=asciidoc:
================================================
FILE: docs/design_principles.txt
================================================
Plasma Language Design Principles
=================================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: June 2021
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
Plasma is designed and implemented with these principals in mind. By
documenting this it not only gives us something to refer to but makes
decisions more conscious, leading to a more consistent language. The first
section (The big ones) is especially important and contains:
1. Easy reasoning
2. Familiar syntax and terminology
3. Cutting-edge concurrency and parallelism
These three are mostly relevant when making big decisions about the
language, while the remaining principals are more relevant for smaller
choices and implementation details, including development of the tools &
ecosystem.
Many of these will be described with anti-examples ("don't"). I'd prefer to
use positive examples of how Plasma avoids these problems, and will try to,
however most can only be recognised with these "don't" examples.
== The big ones
These principals are the big ones, they define how we blend
declarative and imperative programming among other things, and shoot
towards our goal of better concurrent and parallel programming.
=== Easy reasoning
Declarative programming can make it easier to reason about a program,
particularly large programs and at a large scale (the scale of modules,
functions and how they interact).
For example a Plasma function's signature tells you everything you need to
know about that function, not only the data types it'll work with but what
data it can access and what resources (eg files, network sockets) it can
manipulate. Plasma is a side-effect free language and borrows a lot from
other declarative languages including its type system.
This also means that semantics should generally be easy to follow, the
language should avoid UB or non-determinism. But we can't solve
non-termination without solving the halting problem and otherwise maintain
expressitivity so we're not going to try. (TODO: explain why exceptions are
okay / when they're okay.)
This benefits humans, who spend more time reading code than writing it, and
more effort debugging. A human can read function signatures and know
whether their bug may be or won't be within that function.
It also benefits tools, specifically the compiler. By making effects clear
the compiler can perform more aggressive optimisations such as reordering or
parallelising code.
=== Familiar syntax and terminology
There are two aspects to familiarity. One is generally using syntax that'll
be more familiar to a majority of programmers in 2021. We're assuming
people coming to Plasma have at least two years experience programming and
they may be "functionally curious". By being familiar where we can it makes
learning Plasma easier, and people can spend more of their energy learning
the parts of Plasma that are different (usually by necessity).
We make a number of choices about syntax that will be more familiar to most
programmers. For example Functions and blocks use curly-brace syntax of
C-like languages and the body of a function or block is a series of
statements.
Likewise we use terminology and names that are going to be more familiar.
What Haskell calls "Functor" we shall call "Mappable". We know this
isn't as accurate as "Functor", but we're willing to lose some of that
accuracy for more familiarity for more people. Documentation will usually
explain these kinds of choices, eg: "If you've used Haskell you may be used
to calling these Functors, which is more accurate". Which also makes it
clear to people with that background exactly what they're looking at.
Sometimes something is familiar to a smaller group of people. Like ADTs, we
use the Haskell syntax for ADTs because that's the syntax that's familiar to
the largest group of people.
Likewise some concepts have no familiar meaning (eg Monad). We carefully
weigh whether to include that concept at all. For example monads are very
useful so we will support but de-emphasise them. While GADTs are more
specialised in their use cases and those cases can also be solved in other
ways so we will not support GADTs.
=== Cutting-edge concurrency and parallelism
One of Plasma's major goals is a language that does not restrict expression
of concurrency or parallelism, and enables automatic parallelisation. And
does all of this safely.
Many other language features are designed with this in mind. For example by
making loops part of the language (rather than using recursion in a
declarative language) programmers will naturally tell the compiler where
loops are and this will aid automatic parallelisation. Likewise part of the
reason the resource system is granular is to be able to expose more parallelism.
=== No paradigm is superior in all situations
Both declarative and imperative programming have a lot to offer. We choose
language features from both of these groups. Neither one is purely
superior.
== Language syntax
=== Basic consistency
C structs, and C++ classes, must be followed by a semicolon. But functions
don't need to be.
Haskell uses square brackets for lists:
* +[]+
* +[1, 2, 3]+
* +[a]+ (as a type expression)
But it also uses : for the cons operator, and when pattern matching with lists
code looks like:
----
length [] = 0
length (x:xs) = (length xs) + 1
----
This is inconsistent. Plasma has chosen the Prolog syntax for "cons"
(+[x | xs]+).
There may be "consistent" reasons why C/C++ and Haskell make these choices.
Indeed +:+ is an operator in Haskell while +[]+ and +[1, 2, 3]+ aren't.
Likewise struct declarations end in a semicolon in C otherwise the next
identifier would be an instance of that struct. Nevertheless this is
inconsistent _from the point of view of the programmer_. We will try to
avoid inconsistency, and may need to do this by changing other parts of the
language (if Plasma was C we'd avoid conflating structure definitions with
definitions of struct instances).
=== Things should look like what they are / mean what they look like.
The following Mercury code
----
(
X = a,
...
;
X = b,
...
)
----
Could be a switch (with either 0 or 1 answers) a nondet disjunction (with
any number of answers and hard to predict complexity). The exact meaning of
this depends on the instantiation state of X which depends on the
surrounding code. You can't tell by looking how this code will behave.
Also in Mercury a goal such as:
----
A = foo(B, C)
----
Could be a test unification (semidet, very fast), a construction (det, with
a memory allocation), a deconstruction (det or semidet), or a function call
(could do anything, including not terminate).
We will try to avoid these in Plasma. Plasma has no disjunction so the
first is not a problem. But the second is currently avoided because data
constructors begin with capital letters (this will change, so we may need to
revisit this).
We've been creating a link:concept_map.html[syntax to concept map] we're
trying to avoid overloading symbols (where possible). For example + means
addition and concatenation in many languages, but in Plasma (like Haskell
and Mercury) ++ means concatenation.
=== The same thing, should behave the same way in different contexts
What people think of as application or systems languages make this error,
and scripting languages get it right, although the difference is hard to
notice because it's so great.
A language like python allows nested functions.
----
def foo(...):
x = ...
def bar(...):
... x ...
return bar
----
But this is not legal in C and C++, or even a managed language like Java.
This is legal in Plasma (with Plasma's syntax). We add the additional
constraint that nested functions should behave like functions at the
top-level, they must behave the same and for example support mutual
recursion.
Where this is not true is that other statements are not allowed at the top
level, doing so would create problems for module loading order. So
functions will have to behave with respect to other statements within
functions, and this may make them appear to behave differently. This is
unfortunate but better than creating module initialisation order problems.
=== Make parsing simple, for machines and humans
To simplify parsing, both for machines and humans, all
declarations/definitions and many statements can be recognised by their
first token. All type definitions begin with the keyword +type+ all
functions with +func+ etc. Statements can begin with +if+, +match+,
+return+, +var+ or similar, and those that don't belong to a small set
containing only:
* Assignment
* Array assignment
* Call (with effect)
Which can be disambiguated by the first 2 tokens.
We assume that this also makes it easy for humans to recognise the type of
each statement, at least provided they find the beginning of a statement
which is (by convention, not syntax) at the beginning of a line or on the
same line following a +{+.
This is also related to things being what they look like.
=== Choose the more restrictive alternative
There are many cases where we are unable to decide what is best for the
language, particularly without experience using it in anger. In these cases
given two or more choice we should choose the most restrictive. It will be
more pleasant later if we change to a less restrictive option, rather than
_from_ a less restrictive option to a more restrictive one.
For example
https://plasmalang.org/list-archives/dev/2018-January/000026.html[resources
and higher-order code] was a fairly major choice we we've picked one of the
more restrictive options, and might find we need to relax it later.
== Other
=== Principle of least surprise
This is written about elsewhere online. Given two alternatives, choose the
one that surprises people the least (when other factors are equal). You can
see that some of the above principles are specific examples of this one.
== TODO
* What are the principals for how we're writing the Plasma tools?
// vim: set syntax=asciidoc:
================================================
FILE: docs/design_types.txt
================================================
Plasma Type System Design
=========================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: April 2017
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
This is a design/set of ideas that I'm considering for Plasma's type system.
It is very much a draft. It is more or less an aide to help me write down
my ideas, work them through and eventually refine then and make them part of
the link:plasma_ref.html[reference manual].
Starting with a type system such as the basic parts of Haskell's or
Mercury's specifically:
* Discriminated unions / ADTs
* Polymorphism
* Abstract types
* Existential types (later)
* More kinds (later)
Starting with this I have been considering the kinds of subtyping that OCaml
can do, it's pretty neat. But recently I read a
link:https://futhark-lang.org/blog/2017-03-06-futhark-record-system.html[blog
post]
by Troels Henriksen about structural typing and record syntax for Futhark.
It made me consider this more deeply, and now I have the following design in
mind.
== Basic stuff
We can define our own types, such as enums:
----
type Suit = Hearts | Diamonds | Spades | Clubs
----
Or structures, this type has a single struct with named fields.
----
type PlayingCard = Card ( suit : Suit, number : Number )
----
A combination of the above, a PlayingCard is either an ordinary card or a
joker. An ordinary card has fields.
----
type PlayingCard = OrdinaryCard ( suit : Suit, number : Number )
| Joker
----
Types are polymorphic, they may take type parameters. Identifiers beginning
with upper case letters denote type names and constructor names.
Identifiers beginning with lower-case letters denote type variables.
----
type Tree(k, v) = EmptyTree
| Node (
key : k,
value : v,
left : Tree(k, v),
right : Tree(k, v)
)
----
A type alias, ID is now another word for Int. (XXX this needs revisiting).
----
type_alias ID = Int
----
It's often more useful to alias something more complex.
----
type_alias Name = String
type_alias NameMap = Map(ID, Name)
----
Type aliases can take parameters:
----
type_alias IDMap(x) = Map(ID, x)
----
== Terminology
Before we can go further, I want to pin down some terminology.
A type has a name and some parameters. Eg +Int+ or +Map(k, v)+
A type declaration has multiple parts:
----
type Tree(k, v) = EmptyTree
| Node (
key : k,
value : v,
left : Tree(k, v),
right : Tree(k, v)
)
----
A type declaration is made of a left hand side and a right hand side (either
side of the +=+). The left-hand-side contains a type name +Tree+ it's
parameters +k+ and +v+ which creates the type +Tree(k, v)+. This is also a
type expression but we'll get to that later.
TODO: kinds.
The right hand side is a structure expression.
A structure expression is normally made up of structures
structures separated by +|+ symbols (meaning "or"). But could be made of
other things such as a reference to another type (+type(TypeExpr)+).
Each structure is made up of an optional structure (the bit in the parens)
and a tag (its name).
The structure is optional, if there are no fields then one should not write
empty parens.
An untagged structure, which we will see later, is written with the +_+ for
its tag.
When an untagged structure is used, there must be exactly one structure in
the type.
Other languages often call the tagged structures data constructors, and the
untagged ones tuples, but I hope that calling them both structures, and
allowing untagged structures to use field names and share some syntax will
be good.
NOTE: The word tag is overloaded, it also refers to an implementation detail
for discriminated unions, that's not what we're referring to here.
Each field in the structure has a name and a type. The type is any type
expression. The field name is optional.
Finally type expressions refer either a type like +Map(k, v)+ (including
abstract types), or multiple type expressions separated by +|+,
or arbitrary structure expressions when wrapped in +struct()+. The
+struct()+ wrapper avoids ambiguity between tags and types. Likewise, and
not mentioned above, structure expressions can refer to whole types with
+type()+.
Any type variables appearing in structures (on the RHS of the = in the type
declaration, must appear exactly once on the LHS. This may need to change
for existential types (TODO).
== Ranged numeric types
It is sometimes desirable to specify the size of a numeric type. Eg
uint16_t. That's great if you're thinking "this should fit in 16 bits".
But if what you're thinking is "I want to count numbers 0 to 200" it's more
human to specify a range (see Ada). This could mean storing more, than the
range when that's easier, or checked arithmetic.
Likewise floating point numbers could be specified by how many sagnificant
digits are important.
Also consider an integer type with modulo (probably power-of-two)
arithmetic.
== Subtyping / constructors are "shared"
----
type TypeA = A | B
type TypeB = A | B | C
----
A function that accepts parameters of type +TypeA+, cannot be passed
values of +TypeB+. But a function accepting parameters of type +TypeB+ can
be passed values of +TypeA+.
This works along with type inference. This function:
----
func my_func() -> _
{
return A
}
----
Is known to return +A+ which is covered by either +TypeA+ or +TypeB+. This
functions inferred return type will be +struct(A)+. Which we know we can
pass as either TypeA or TypeB. Care will need to be taken when generating
error messages.
Likewise, if +my_func+ was defined as:
----
func my_func(...) -> _
{
if (...) {
return A
} else {
return B
}
}
----
Then it would be inferred as returning +TypeA+ since we already have a name
for +struct(A | B)+.
Types defined in separate modules outside the view of each-other can't share
tags. This is not the limitation it seems, since usually when such a
feature is required it is to extend, or in some cases reduce, the
constructor symbols of an existing known type.
----
type AdvancedNode(a) = type(BasicNode(a))
| AdvancedStruct (
...
)
----
NOTE: See below for how recursive types are handled.
TODO: it may be useful to let a type explicitly specify that it
extends/subtypes an earlier type. This may match more with programmer
intentions.
== Magic type tagging.
I think I saw this in Perl 6.
----
func do_something(...) -> Result | Error
{
...
}
----
That's easy provided that both these types have all their structures tagged,
but Ints, Strings, etc don't work like that (each Int, String etc is like an
alternative tag in an infinite or really large set of tags).
Where all the types in a type expression are named, then they may also be
switched by type, rather than just value. (the compiler tags and probably
boxes them internally).
----
func print(x : Int | String) -> String
{
return switch_type(x) {
Int -> int_to_string(x)
String -> "\"" ++ x ++ "\""
}
}
----
== Ordering
This kind of subtyping must work via an ordering. There is a partial
ordering over all types, types that refer to something _more specific_ are
_greater_ in this ordering. Therefore: +A | B+ > +A | B | C+.
Being a partial ordering some types cannot be compared, eg: +A | B+ and +B |
C+. This means that neither is a subtype of the other.
== Adding fields.
This can vary depending upon how programmers express deconstructions.
Usually a deconstruction is (semantically) a match statement.
----
match (a) {
A (x) -> { return x }
}
----
The equivlient deconstruction might look like:
----
A(x) = a
return x
----
This matches A with a single field.
It would also match any A with at least one field, extracting only the
first.
Let's make a new structure expression for that: +A/1+, this kind of type
expression wont appear in programs or even error messages, but we need it
here to discuss subtyping and ordering.
But fields can also be extracted or structures can be matched using field
names.
----
# Field selection.
return a.field1
# Match with fields.
match (a) {
A(x = field1) -> { return x }
}
----
Therefore we also need to talk about subtyping with regard to fields and
their types. We write the type of a in these as: +struct(A(field1 : t))+
(t is currently abstract). It's more correct to say that the first is
+struct(_(field1 : t))+ since the constructor symbol isn't mentioned.
Any use of a constructor, such as the match statement but not the field
selection, requires a type to have already been declared. This will make
more sense later with tagless structures. For now lets just say we require
a type to exist.
For example, either +TypeA+ or +TypeB+ match the above usages.
----
type TypeA = A (
field1 : Int
)
type TypeB = A (
field1 : Int,
field2 : String
)
----
== Ordering with fields
A structure expression with more fields is greater than one with fewer:
+struct(A/2)+ > +struct(A/1)+.
A structure expression with a superset anther's fields is greater:
+struct(A( field1 : Int, field2 : String ))+ > +struct(A ( field1 : Int ))+,
Or: +TypeB+ > +TypeA+
A structure expression with a constructor and with the same or a superset of
anothers fields is greater:
+struct(A( field1 : Int ))+ > +struct(_(field1 : Int))+,
Fields are compared by name and type. A field whose type is greater than
the corresponding field of another type, is greater. This makes ordering
composable, and work as desired on recursive types.
Structures whose fields are neither a set or superset cannot be ordered.
Structure expressions with numbers cannot be ordered with those by types.
Widening is performed when a type or a constructor symbol is named,
or if no ordering is found between two types, they are widened in an attempt
to find a common type.
Widening allows more programs to be well typed, makes the type system easier
to use, however it makes type more specific than strictly necessary.
A type expression such as the above is widened to the disjunction of the
equal-least specific types matching the expression. Nevertheless we
discussed ordering of these expressions so that we can determine ordering of
types and which type an expression may be widened to.
Widening must also respect the types created by type expressions the
developer writes, such as in the declaration of a function:
----
func do_something(...) -> Result | Error
{
...
}
----
In this case +Result | Error+ is considered for widening.
== Untagged structures
An untagged structure can be used, but without any other structures within
the same type. The missing tag must be written with +_+.
----
type TypeC = _(
field1: Int,
field3: Bool
)
----
Uses of untagged structures are not widened unless combined with a named
structure or type containing a named structure. This makes them feel more
"dynamic" although they simply use type inference heavily.
For example:
----
dict_from_kv_list(map(\x -> _( key = get_id(x), value = x ), list))
----
TODO: I think +:+ is the best operator here, but it conflicts badly with
"has type". +=+ is also okay. Arrows can be a problem as the directions
matter, and sometimes you want them one way or the other.
Without needing to declare a type, using an untagged structure like this
implicitly creates one for us.
== Syntax
We've already seen some syntax above. But I'd like to expand on that now.
Type structures use parentheses +( )+, fields are separated by commas and
the tag may either be an identifier starting with a capital letter or the
+_+ symbol.
Each field separates it's field name from the field type (in
declarations) with a +:+ (meaning "type of").
Deconstructions may be done with fields (using a =, with the new variable on
the left) or by position. Constructions are done either positionally or
with the field name on the left.
Selection is performed using the +.+ operator, the general scoping operator.
----
x = point.x
----
This may be chained for nested structures.
----
a = struct.field1.next_field.other_field
----
Field update (in an expression) is introduced via the join symbol: +|+
----
new_struct = _( old_struct | field = new_value )
----
Nested fields may also be updated, updating all the structures along the
way.
----
new_struct = _( old_struct | field.next_field.following_field = new_value )
----
Multiple fields may be updated in one expression.
These expressions will introduce fields if necessary (subject to type
checking).
These will also work for tagged structs.
A syntas sugar for state variables in statements will probably be
introduced.
=== Syntax TODOs
.Projection / Explosion / Filtering
Additional syntax could be created to merge structs (exploding one into
a series of updates to another). Filtering (technically projection) may
also have some use, either to satisfy the type system or to free memory.
.Lenses
Lenses (optics?) provide some additional power not provided here. It'd be
nice to handle that if possible.
== Co-variance and contra-variance
TODO: I will need to address this to support arrays.
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_bugtracking.txt
================================================
Plasma Bugtracking
==================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: Feburary 2022
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
We use the github bugtracker, and while users/new contributors and such
should be able to submit a bug without too much process. We need a little
more process to decide which bugs are important and what we should be
working on when.
These guidelines might change a bit as we settle in and figure out what
works.
== Background
=== Roadmap
The link:https://plasmalang.org/roadmap.html[Plasma Roadmap] is published on
the website and gives a high-level overview of what we want to work on.
It divides our progress into several milestones, each milestone is made of
several features.
=== Releases & Versioning
Plasma is currently not-quite usable (I must remember to update this doc
when it is!) and so there are currently no version numbers or release
schedule. Once it is I think it'd be fairly reasonable to manage two
releases per year using something like a
link:https://en.wikipedia.org/wiki/Software_release_train[train model] -
because it's more important to release _something_ rather than have a
release wait potentially indefinitely for a particular feature.
It's my guess that twice yearly is not too fast that each release will have
a reasonable number of new features, but not too slow that anyone feels
they're waiting too long to get new features.
Regarding bugs this means which version a feature _lands_ in is only meaningful
with regard to relative priorities, and bugs/features don't need to be
tagged with a version.
That said, there will probably be meaningful versions such as "1.0" where we
declare some API/language/library stability.
=== Github
Github's bugtracker allows us to
link:https://github.com/PlasmaLang/plasma/labels[label issues].
We already have several kinds of labels
Type:: bug, enhancement, maintenance, optimisation
Component:: build, compiler, runtime, gc, language, docs etc
Skill:: C++, Mercury, Type system, etc
Meta:: help-wanted, good-first-bug, no-domain-knowledge
Status:: new, accepted, duplicate, invalid, wontfix, resolved
Type:: bug, enhancement, maintenance, optimisation
Other:: project
We will extend these and probably rename a few of them.
Github also supports a notion of milestones. I beleive these function like
labels except that an issue may only belong to a single milestone. The
link:https://github.com/PlasmaLang/plasma/milestones[Milestones view] has
nice progress bars too.
Github also supports project boards, Some large tasks have project boards
(eg the module system).
We may not always use github, TODO: find a way to download all this data
from github.
== Milestones & tasks
the link:https://plasmalang.org/roadmap.html[roadmap] divides our work into
milestones and tasks. Each roadmap task shall be a github milestone.
For example, some current milestones are:
* Testing
* Interfaces
* Text handling
* Language groundwork
* Ergonomics
* Closures & functional features
* Modules MVP
* FFI
* Standard library
These should correspond to current roadmap items. Not all of them currently
do.
== Triaging & labelling
Triaging is a process by someone looks at the issue and assigns various
attributes to help with sorting/finding that issue later. It usually
decides the issue's priority (in our case, milestone). Triaging is the
responsibility of project maintainers, users do not need to worry about
this.
Each issue may have have one or more labels for skills, and usually one for
component but this may be more if it's a cross-cutting issue or zero if it
covers the project as a whole.
Each issue should have exactly one type or be a project bug
(bug, enhancement, maintainance task or optimisation).
Each issue may belong in a milestone and/or a project board.
Each issue should have a status, it should begin as "new".
Untriaged bugs can be found with
link:https://github.com/PlasmaLang/plasma/issues?utf8=%E2%9C%93&q=is%3Aopen+-label%3A%22meta%3A+triaged%22+[this search].
To summarise, to triage a bug assign:
* The "status: new",
* one type label,
* probably one component or feature label, maybe more,
* any number of skill labels,
* meta labels as appropriate,
* if the bug is part of some larger goal it should have a milestone and
possibly also belong to a project board.
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_compiler_internals.txt
================================================
Plasma Compiler Structure / Internals
=====================================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: November 2019
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
== Compiler structure
A compiler is typically organised in multiple passes that form a pipeline.
Plasma is no different in this respect.
Compilers also use one or more data structures that represent the code and
other information during compilation. You may have heard of abstract
syntax trees (ASTs) and immediate representation, these are similar
concepts. We will say _representation_ and use it to mean any
representation of a program in the computer's memory (not disk), and not
worry about the specifics of definitions like ASTs.
Some representations have "textbook" definitions, eg: single-assignment form
(SSA) or a normal form (ANF). Each representation has strengths and
weaknesses, compilers including Plasma also use their own unique
representations. Plasma has four main representations used within the
compiler: AST, Pre-core, Core and Plasma Abstract Machine (PZ).
Compilation passes take in the program in a representation and return the
modified program in the same representation, and sometimes in a different
representation. Again some of these are "textbook" passes (inlining,
register allocation) while others are unique to the compiler or language.
An optimisation pass may operate on the core representation, returning the
updated program in core representation. And a translation pass like code
generation may take the core representation and return PZ. Some passes
don't modify the program but annotate it with extra information, such as
type inference. Some passes check the program for validity, like type
checking. In Plasma type inference and type checking are the same pass.
=== Lexing & Parsing
WIP
=== AST
WIP
=== Pre-core
The pre-core representation is a statements-and-expressions like
representation (similar to the AST representation) however all symbols have
been resolved. This means where a name appeared in the AST it has been
resolved to what kind of symbol it is: a function, a variable etc, and an
ID. (IDs are internally integers and allow for faster lookups).
==== Environment
The environment is a non-tangible concept (it's computer science, none is
really tangible) which means it does not appear in people's programs but it
is a concept that programmers may experience.
Defined functions, imported modules and their symbols, local variables are
all part of the environment. Environments form a chain. Each new scope
creates a new environment that refers to the previous one. During
compilation the environment is real, specifically during the AST->Pre core
translation. A chain of environments are created and used to resolve
symbols.
==== Meta information
Each statement (+pre_statement+ type) has some meta-information associated,
this contains context information (source file and line number) plus other
fields, see the +stmt_info+ type.
This means that if a statement spans multiple lines we only record the
context information for the beginning of the statement. A compilation error
later in the statement will be reported for the first line.
We can fix this later.
===== Def/use
The initial AST->Pre-core pass populates populates def-use information on
each statement.
Every variable defined (assigned a value) by a statement will appear in that
statement's _def_ set.
Every variable referred to (excluding assignments) by a statement will
appear in that statement's _use_ set.
These sets are used later to check scoping and lifetimes (variables are not
used before they're defined).
===== Reachability
Code is annotated with this value to describe whether execution can reach
its end, always, sometimes or never. This is then used to check that a
variable is defined along all execution paths that reach their end.
Reachability is computed as the 3rd pre-core phase. It is invalid until
then.
==== Phases
Only code is handled in the pre-core phases. Data types and other entries
are translated straight from AST into core representation.
The pre-core phases are executed from +ast_to_core_funcs+ in
+pre.ast_to_core.m+, they are:
1. +func_to_pre+ translates AST functions into pre-core, this resolves
symbols using the environment concept. It also populates def-use sets.
2. +compute_closures+ computes the captured variable sets by traversing the
statements taking note of which variables are available, then when a
closure is found calculating the variables captured by the closure.
3. +fix_branches+ fixes how variables are used in branching code, it:
** checks that used variables are always well defined (eg
along all execution paths)
** Updates the reachability information for branches.
Reachability information is incomplete until after
type checking.
** Adds terminating "return" statements where needed.
4. +check_bangs+ checks that the ! symbols are used correctly. They must be
used when required, must not be used when not required, and only one may be
used per statement.
5. +pre_to_core+ translates the pre-core statement-oriented representation into
the core representation (similar to ANF) which is expression oriented.
Statements are translated out of order, with the statements following the
current statement being translated first, as a continuation, then that
expression is fed into the translation of the current statement.
This helps translate something like a sequence of assignments into a set of
nested let expressions.
=== Core
WIP
=== PZ
WIP
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_howto_make_pr.txt
================================================
How to make a pull request
==========================
:Author: Gert Meulyzer
:Email: gert@plasmalang.org
:Date: April 2019
:Copyright: Copyright (C) Plasm Team
:License: CC BY-SA 4.0
* Show a real life example from start to finish on how to do a good PR.
_Draft text follows!_
It's hard to start contributing to an open source project. Especially if
it's your first one. We present a flow here for you to follow and will show
an example of an actual commit to the codebase. (You can find the commit
*here* and the PR *here*) This way of working should be good for most
projects you commit to, but be sure to check the contribution guidelines for
every project. Ours is in the
https://github.com/PlasmaLang/plasma/blob/master/CONTRIBUTING.md[CONTRIBUTING.md]
file.
1. Fixing the bug.
We found a bug on line 81 of
https://github.com/PlasmaLang/plasma/blob/master/runtime/pz_option.h#L81[runtime/pz_option.h].
There is one 'l' too many. We'll fix it up so it's spelt correctly and
commit it to git.
* Use the correct Git commit message structure
* Show how to clean up your local branches afterwards when it gets accepted.
* Show how to to additional modifications
* Maybe some git rebase and squash stuff
NOTE: https://github.com/PlasmaLang/plasma/blob/master/runtime/pz_option.h#L81 temporarily has too many 'l's. This is a good bug to fix and make a PR from.
* The git message structure documentation is in:
https://github.com/PlasmaLang/plasma/blob/master/CONTRIBUTING.md So make
sure to put a reference to it there.
* From CONTRIBUTING.MD: Log messages should follow the style:
```
[component(s)] Title
Description
Any other changes including changes that were needed to support this
change or followed as a consequence of this change.
```
We provide a .gitmessage in the root of the repository.
Run this command to start using the new commit message template:
```
git config --local commit.template /path/to/repo/.gitmessage
```
* Make sure to mention this and refer to the correct document to refer to in
case of doubt. Who knows, this might change again in the future.
* In CONTRIBUTING.md it says: “Each file should be listed with more detailed
information. Take a look at previous changes for examples.” => We could go
look for some good examples and show them in this document.
This was removed you can list a summary of changes in each/some files if
you think it may help whowever is reviewing your change.
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_maintainers.txt
================================================
Plasma Maintainer's Guide
=========================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: July 2022
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
This is the maintainer's guide, it will contain procedures for maintainer's
common tasks. However it is incomplete (Bug #48).
== Merging changes
Generally ongoing work should be done on a feature branch and merged to the
main branch. These branches could be in ones own fork of the plasma repository
or in this one, then be merged.
At some stage we may use the bors tool to manage this for us. For now
though it's manual. Make the commit using:
git commit merge --no-ff --log=999 -S branch_name
The commit message should be formatted like:
[merge] Mutually importing modules works
This patch series mainly gets mutually inclusive modules working, but
does some other tidying up also.
Fixes #123
* modules:
[compiler/pre] Save types and resources' full names
[compiler/pre] Module qualify definitions in interface files
[compiler/ast] Move names out of ast_resource and ast_type
A merge commit should also have some github Fixes directives. Eg "Fixes: #123"
to say that the commits fix bug #123. If the author of the patches already
included this directive within the patch series then it's not necessary in the
merge commit. A pull request / patch series may fix more than one bug.
== Copyright years
At the beginning of each calendar year update the copyright statements in
the following files:
* LICENSE
* README.md
* runtime/pz_main.cpp
* src/constant.m
And the copyright statement on the website, in it's repository at:
* _includes/footer.html
Copyright statements with years in each source file don't need to be
updated, and the year parts can now be phased out to read as:
Copyright (C) Plasma Team
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_mercury_grades.txt
================================================
Mercury Grades
==============
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: March 2020
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
Plasma is written in Mercury
(at least until we get to a https://plasmalang.org/roadmap.html[self
hosting] stage)
which means if you want to compile Plasma (to contribute to it) you may need
to build Mercury from source,
and that means navigating the Mercury grade system.
Mercury supports many different "grades", each one is a collection of
settings for how to build and link a Mercury program or library.
Each grade is made out of many grade components separated by +.+
Alternatively you may be able to use one of these shortcuts or check out
https://plasmalang.org/docs/getting_started.html[getting started with
Plasma].
* If you just want to run Plasma, without compiling it, then try this
https://plasmalang.org/plasma-static.tgz[static build] for Linux on
x86_64.
(TODO: https://github.com/PlasmaLang/plasma/issues/9[better static builds]).
* If you want to build Plasma on x86 or x86_64 on a .deb based Linux
system;
then use the https://dl.mercurylang.org/deb/[Debian packages], see
https://plasmalang.org/docs/getting_started.html[getting started] for more
information.
* If you want to run Plasma or if you want to develop for it, then there's
also a https://plasmalang.org/docs/getting_started.html#_docker[docker
image].
* If you want to build Plasma on a non-.deb system on x86 or x86_64 then
you'll have to build Mercury. I suggest installing the +asm_fast.gc+ and
+asm_fast.gc.decldebug.stseg+ grades. Remember to tell +./configure+ which
grades you need otherwise it'll
http://yfl.bahmanm.com/Members/ttmrichter/yfl-blog/mercury-time-to-hello-world[try to build all of them and could take a long time]
(TODO: https://github.com/PlasmaLang/plasma/issues/8[provide detailed
instructions]).
* If you have some other type of system, or are building something other than
Plasma but found this document, then read on.
The Mercury project documents its grade components
https://www.mercurylang.org/information/doc-latest/mercury_user_guide/Grades-and-grade-components.html#Grades-and-grade-components[here (retrieved 2018-03-04)],
and I will be clarifying some points made there.
This manual, when I retrieved it, mentioned a few grade components not worth
attempting to use, these are:
+hl+::
The +hl+ grade component is like the +hlc+ grade but uses a different
format for data on the heap. It doesn't provide a significant advantage over
+hlc+ so isn't useful.
+il+:: A deleted .net backend.
+agc+:: A bit-rotten garbage collector.
+threadscope+:: A bit-rotted profiling system, the viewer component's latest
version can no-longer open profiles generated by Mercury.
+mm+ and probably others:: alternative evaluation strategies for logic
programming, you probably don't need this and if you do, someone else will
tell you.
+rbmm+ region based memory management:: An advanced optimisation for memory
allocation. AIUI it only works for single module programs and is
exprimental.
There are many other `secret' grade components not covered here or in the
User's guide.
They are mostly experimental and include grades like +rbmm+.
If you think they should be documented here then please
https://www.plasmalang.org/contact.html[let us know].
== Base grade
Everything starts with a base grade.
The base grade selects which compilation backend you wish to use.
Some backend have more than one base grade, and there are two C backends.
Exactly one base grade must be part of every valid grade string.
Low-level C:: +none+, +reg+, +jump+, +asm_jump+, +fast+ or +asm_fast+
High-level C:: +hlc+
C#:: +csharp+
Java:: +java+
Erlang:: +erlang+
If you need to call C#, Java or Erlang foreign code then the choice is
fairly obvious.
If you need to work with C foreign code, as the Plasma compiler does,
then things are more complicated.
For a long time the Low-level C backend generated faster code than the
High-level one, at least when comparing the +asm_fast+ and +hlc+ grades.
These days, due to changes in the C compilers, it depends on the program
being run.
=== Choosing a low-level C grade
Assuming you might use the low-level C grade, read this section.
The low-level C grade uses a combination of three optimisations ('hacks')
provided by GCC.
With all three disabled, the base grade is +none+, with all three enabled
it's +asm_fast+.
.Low-level C Optimisations
|========================
| Grade | GCC global registers | GCC Non-local GOTOs | ASM Labels | Useful
| +none+ | N | N | N | Y
| +reg+ | Y | N | N | Y
| +jump+ | N | Y | N | N
| +fast+ | Y | Y | N | N
| +asm_jump+ | N | Y | Y | N
| +asm_fast+ | Y | Y | Y | Y
|==========================================================================
Of course you want as much optimisation as possible, so choose +asm_fast+
but not all compilers (including GCC) fully support these GCC extensions so
these grades may not work.
Note that ASM labels cannot be used without GCC Non-local gotos, so there's
no grades combining those.
Note also that I've included a "Useful" column, these are the ones worth
testing, the others are only of interest to researchers, since if they work,
it's almost a certainty that +asm_fast+ works.
So choose in order of preference: +asm_fast+, +reg+ then +none+. On x86 and
x86_64 on Linux with GCC or Clang, +asm_fast+ works (but a future version of
GCC or Clang could break this).
On OS X I think only +none+ works, but I don't remember.
== High level C
As mentioned above, +hlc+ and +asm_fast+ are (IIRC) comparable
performance-wise.
Which one you choose will depend on whether your C compiler can handle
+asm_fast+ and what other features you may need (see below).
For example, if you want to use the declarative debugger, then you must use
a low-level C grade, if that low-level C grade happens to be +none+, then
that's the best you can do.
== More grade components
The complete grade is built by adding grade components to select different
features, separated by periods.
Garbage collection::
--
+gc+ or absent.
+gc+ is Boehm GC, the only supported GC.
Not including +gc+ means that a GC will not be built, but note that Java,
C# and Erlang backends provide a GC anyway, and for them +gc+ does not
make sense.
(+agc+ bitrotted long ago, and +hgc+ was an experiment never completed.)
You should always include +gc+ when using a C backend.
Not including this is intended only for testing.
--
Thread safety::
--
+par+ or absent
Like the +gc+ option, this only makes sense on C grades.
Grades that include +par+ are thread safe and support the functions in the
thread module of the standard library.
The Java, C# and Erlang grades support thread safety implicitly.
Low level C::
The threading model is N:M with IO that can block a whole "engine" of
workers.
The parallel conjunction operator and the 'very' experimental
https://paul.bone.id.au/pub/pbone-2012-thesis/[automatic parallelism]
work are supported.
This is the only combination of base grade and +par+ that support these
features.
High level C::
This uses the OS's native threads and IO works properly, but parallel
conjunction is not supported.
Plasma doesn't use thread-safety in any of its Mercury programs.
--
Stack segmentation::
--
+stseg+ or absent
Meaningful only on low-level C grades where Mercury manages its own stack.
Use a segmented stack so that
* The program is more tolerant of deep recursion s where TCO/LCO were not
used/available.
* The memory cost of a thread in +par+ grades is much cheaper.
This is recommended when +par+ is used and can also help with debugging and
deep profiling.
The +trseg+ grade component looks similar and is described below.
--
Single precision float::
--
+spf+ or absent
Use +float+ for floating point numbers rather than +double+.
Much faster on 32bit platforms where floats normally require boxing, but
your program may have different results
Only meaningful in C grades (I think).
--
Debugging::
--
+debug+, +decldebug+, +ssdebug+ or absent
Which type of debugging to support if any.
Note that +decldebug+ is a superset of +debug+, you might as well use it
instead of just +debug+.
+ssdebug+ is a totally separate debugger suitable in the "MLDS" backends
(high level C, C#, Java and Erlang).
--
Profiling::
--
+prof+, +memprof+, +profdeep+ or absent
What type of profiling to support if any.
+prof+ and +memprof+ have a smiliar workflow.
+profdeep+ is a
https://mercurylang.org/documentation/papers.html#mu_01_24[very advanced profiler]
and worth considering.
These only make sense with low-level C grades.
We're not concerned about Plasma's compiler's performance until well after
bootstrapping, so you probably won't need this for Plasma.
--
Trailing::
--
+tr+, +trseg+ or absent.
Enable trailing support.
Trailing is a technique for undoing destructive update on backtracking.
If you don't know what it is then you probably don't need it. need this
+tr+ is generally discouraged in favour of +trseg+.
I believe this option is supported with all the C backends.
--
== Grade compatibility
.Grade component compatibility matrix
|====================================
| | asm_fast1 | hlc | java | csharp | erlang | gc | par | stseg | tr/trseg | debug/decldebug | ssdebug | prof/memprof | profdeep
| asm_fast | - | N | N | N | N | R | Y2 | Y |
Y | Y | y | Y | Y
| hlc | N | - | N | N | N | R | Y3 | N |
Y | N | Y | y | N
| java | N | N | - | N | N | n | n | N |
?D | N | Y | N | N
| csharp | N | N | N | - | N | n | n | N |
?D | N | Y | N | N
| erlang | N | N | N | N | - | n | n | N |
?D | N | Y | N | N
| gc | Y | Y | n | n | n | - | Y | Y |
Y | Y | y | Y | Y
| par | Y2 | Y3 | n | n | n | Y | - | R |
? | ?D | ? | ?D | N
| stseg | Y | N | N | N | N | Y | Y | - |
Y | Y | y | y | Y
| tr/trseg | Y | Y | ?D | ?D | ?D | Y | ? | Y |
- | Y | ? | y | ?
| debug/decldebug | Y | N | N | N | N | Y | ?D | R |
Y | - | D | ?D | ?D
| ssdebug | y | Y | Y | Y | y | y | y | y |
y | D | - | ? | ?
| prof/memprof | Y | ? | N | N | N | Y | ?D | y |
y | ?D | ? | - | N
| profdeep | Y | N | N | N | N | Y | N | R |
?D | ?D | ? | N | -
|=====
Y:: Compatible
y:: Probably compatible
N:: Not compatible
n:: Not compatible, but implied support by the base grade
?:: Don't know.
?D:: Don't know, but I doubt it
R:: Recommended to add the column grade component if you're using the row
grade component
1:: asm_fast could mean any of the LLDS base grades, see table 1.
2:: asm_fast.par supports parallel conjunction and the experimental
auto-parallelism. It uses green threads however IO will block an entire
worker thread, you may be able to avoid that with spawn.native.
3:: hlc.par does not support parallel conjunction or auto-parallelism. It
uses pthreads so works correctly with IO.
== My favorite grades
I use Linux on x86_64.
Default::
+asm_fast.gc+, or maybe +hlc.gc+
Thread safety::
+asm_fast.par.gc.stseg+
Debugging::
+asm_fast.gc.decldebug.stseg+
Profiling::
+asm_fast.gc.profdeep.stseg+
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_style_c.txt
================================================
Plasma Development C and C++ Style Guide
========================================
:Author: Paul Bone
:Email: pbone@plasmalang.org
:Date: January 2019
:toc:
This document describes our C and C++ programming style.
While it's a good idea to conform to the project style, there may be
exceptions where departing from the style produces more readable code.
In brief, we use C99 and C++11 (no RTTI or exceptions) on POSIX, lines are
no more than 77 columns long, indentation is made with four spaces and curly
brackets appear at the end of the opening line except for functions.
== General Project Contributing Guide
For general information about contributing to Plasma please
see
link:contributing.html[our contributors' documentation].
== File organization
=== Modules and interfaces
We follow a pattern on C to allow us to emulate (poorly) the modules of
languages such as Ada and Modula-3.
* Every +.c+/+.cpp+ file has a corresponding +.h+ file with the same base
name. For example, +list.c+ and +list.h+. The exceptions are:
** The alternative interpreters are exceptions, they share the same header
+pz_interp.h+ but have different implementations.
** Each interpreters implementation begins with the same prefix, such as
+pz_generic_*.c+ which is the generic interpreter's files.
** +pz_main.cpp+ is also an exception,
it only exports +main()+ which needs no declaration.
** Finally +pz_gc_layout.h+ is an exception, it provides the class eclarations
for the GC's layout while other files contain the implemention organised
by function. This organisation groups functions with related behaviours
which makes more sense than by class.
* Not all +.h+ files have a corresponding +.c+/+.cpp+ files.
* We consider the +.c+/+.cpp+ file to be the module's implementation and the
+.h+ file to be the module's interface. We'll just use the terms `source
file' and `header'. C++ templates are an exception since their
implementation must be in a header file, these headers have special names
ending in +template.h+
* All items exported from a source file must be declared in the header.
Declarations for variables (although rare) must use the +extern+ keyword,
otherwise storage for the variable will be allocated in every source file
that includes the header containing the variable definition.
* All items not-exported from a module must be declared to be static.
* We import a module by including its header. Never give +extern+ or forward
declarations for imported functions in source files. Always include the
header of the module instead. When C++ classes form cycles, forward
declare one of the class names to break the cycle immediately before its
use.
* Each header must include any other headers on which it depends. Hence
it's imperative every header be protected against multiple inclusion.
Also, take care to avoid circular dependencies where possible.
* Always include system headers using the angle brackets syntax, rather than
double quotes. That is +#include <stdio.h>+. Plasma-specific headers
should be included using the double quotes syntax. That is
+#include "pz_run.h"+ Do not put root-relative or `..'-relative
directories in +#includes+.
* Includes should be organised into 4 groups, separated by a blank line:
+pz_common.h+, system includes, this module's header file, other Plasma
includes. Each group should be sorted alphabetically where possible.
=== File names
C/C++ language source and header files should begin with the prefix +pz_+.
The C language does not have a namespace concept, prefixing C symbols with
+pz_+ can make linking, and debugging linked programs easier. In C++ use
the +pz+ namespace.
=== Organization within a file
Sometimes a file (header or source file) will cover multiple concepts. In
these cases the order above may be broken in order to keep things with the
same concept together. For example, this may mean placing a +struct+
followed by the functions that operate on it, followed by a global variable,
and the functions that operate on it.
In some cases the environment may force a different order. For example C
preprocessor macros may need to be placed in a specific order.
Generally items within a file should be organised as follows:
==== Source files
Items in source files should in general be in this order:
. Prologue comment describing the module.
. +#includes+
. Any local +#defines+.
. Definitions of any local (that is, file-static) global variables.
. Prototypes for any local (that is, file-static) functions.
. Definitions of functions.
Within each section, items should generally be listed in top-down order, not
bottom-up. That is, if +foo()+ calls +bar()+, then the definition of +foo()+
should precede the definition of +bar()+.
==== Header files
Items in headers should in general be in this order:
typedefs, structs, unions, enums,
extern variable declarations,
function prototypes then
#defines
Every header should be protected against multiple inclusion using the following idiom:
[source,c]
----
#ifndef MODULE_H
#define MODULE_H
/* body of module.h */
#endif // ! MODULE_H
----
[TODO]
====
Update headers to use the new style comment
====
== File encoding
* Files should be saved as ascii or UTF-8 and must use unix style (LF)
line endings.
* Lines must not be more than 77 columns long.
* Indentation is to be made with spaces, usually four spaces.
* One line of vertical whitespace should usually be used to seperate
top-level items and sections within an item. Two lines may be used at the
type level to create more separation when desired.
TODO editor hint for vim.
=== Long lines
If a statement is too long, continue it on the next line indented
two levels deeper (but less or more is okay depending on the situation).
Break the line after an operator:
[source,c]
----
int var = really really long expression +
more of this expression;
----
And usually at an _outer_ element if possible, this could be the assignment
operator itself.
[source,c]
----
int var = (expr1 + expr2) *
(expr3 + expr4);
----
Sometimes line-breaking can be done nicely by naming a sub-expression,
give it a meaningful name:
[source,c]
----
int sub_expr = some rather complex but separate expression;
int var = foo(a + b, sub_expr);
----
You may choose to align sub-expressions during breaking. This is
recommended when an expression is broken over several lines. Even though
+name+ is short we give it its own line because the other expressions are
long.
[source,c]
----
int var = fprintf("%s: %d, %s\n",
name,
some detailed and rather long expression,
a comment);
----
When things that may need wrapping occur at different depths within an
expression then different levels of indentation can help convey that depth:
[source,c]
----
int var = fprintf("%s: %d, %s\n",
name,
foo(some detailed and long expression,
another detailed and long expression),
a comment);
----
These two sub-expressions are aligned, but they don't have to be (see Tables
below).
Sometimes breaking early can allow you to align things towards the left and
give them more room. For example we prefer:
[source,c]
----
static PZ_Proc_Symbol builtin_setenv = {
PZ_BUILTIN_C_FUNC,
{ .c_func = builtin_setenv_func },
false
};
----
While clang-format prefers:
[source,c]
----
static PZ_Proc_Symbol builtin_setenv = { PZ_BUILTIN_C_FUNC,
{.c_func = builtin_setenv_func},
false };
----
== Naming conventions
=== Functions, function-like macros, and variables
Use all lowercase with underscores to separate words. For instance,
+soul_machine+.
=== Enumeration constants, +#define+ constants, and non-function-like macros
Use all uppercase with underscores to separate words. For instance,
MAX_HEADROOM.
TODO: Maybe make function-like macros belong here.
=== Static data
Static data should begin with s_ for both file-local and class members.
=== Typedefs
Use first letter uppercase for each word, other letters lowercase and
underscores to separate words. For instance, Directory_Entry.
NOTE: this is rarely used and might become the same as classes and structs.
=== Structs and unions
If something is both a struct and a typedef, the name for the struct should
be formed by appending `_S' to the typedef name.
This overrides the style for typedefs above:
[source,c]
----
typedef struct DirectoryEntry_S {
...
} DirectoryEntry;
----
For unions, append `_U' to the typedef name.
=== Classes
Classes use CamelCaseWithInitialCap.
=== Member data
Fields of classes (but not structs) should begin with m_, static data
members should begin with s_.
=== Constexpr functions and variables, and const variables.
These behave differently (better) than C macros. They don't need to look
like C macros. Use _ to seperate words with initial capital letters.
Eg: `My_Const_Expr'
== Portability and Standards
Our minimum requirements from the C and C++ environment is C99 (may move to
C11 in the future) and C++11 on a POSIX.1-2008 environment,
this may change as dependencies are added in this early stage of development,
however those changes should be carefully reviewed,
and if possible they should be optional.
Differences between operating systems and the use of a tool like autoconf
should be handled by having different configurations available via different
Makefiles and header files.
We will revisit this when development reaches that stage.
Autoconf should be avoided, it brings only pain.
While it's best to keep things portable, if you need a non-standard API, or
an API that's different on each operating system. You should make it
available by a macro or protecting it by #ifdefs.
=== Data types
C99 provides many basic data types, +char+, +short+, +int+ etc. All being
defined to be at least a certain size.
These should be used when the size doesn't exactly matter. For example use
+bool+ for booleans and +int+ or +unsigned+ when you're counting a _normal_
amount of something - you should not need to use the macros such as
+INT_MAX+.
When size matters the +inttypes.h+ types are strongly recommended, including
the _fast_ types, eg: +uint_fast32_t+ and their macros.
+float+ should be used in preference to +double+ which is seldom necessary
and uses more memory.
Don't rely on exact IEEE-754 semantics.
Since C99 does not specify the representation of signed values,
we will assume 2's complement arithmetic (we're not exactly C99 pure).
Endianness and alignment must not be assumed.
If laying out a structure manually align each member based on its size.
=== Operating system specifics
Operating system APIs differ from platform to platform. Although most
support standard POSIX calls such as +read+, +write+ and +unlink+, you
cannot rely on the presence of, for instance, System V shared memory.
Adhere to POSIX-supported operating system calls whenever possible
since they are widely supported, even by Windows.
The +CFLAGS+ variable in the +Makefile+ will request that modern C compilers
fail to compile Plasma if it uses non-POSIX APIs.
----
CFLAGS=-std=c99 -D_POSIX_C_SOURCE=200809L -Wall -Werror
----
When POSIX doesn't provide the required functionality, ensure that the
operating system specific calls are localised.
=== Compiler and C library specifics
We require a C99 compiler. However many compilers often provide
non-standard extensions. Ensure that any use of compiler extensions is
localised and protected by #ifdefs. Don't rely on features whose behaviour
is undefined according to the C99 standard. For that matter, don't rely on C
arcana even if they are defined. For instance, +setjmp+/+longjmp+ and ANSI
signals often have subtle differences in behaviour between platforms.
If you write threaded code, make sure any non-reentrant code is
appropriately protected via mutual exclusion. The biggest cause of
non-reentrant (non-thread-safe) code is function or module-static data. Note
that some C library functions may be non-reentrant. This may or may not be
documented in the man pages.
=== C++ portability/standards
In addition to sticking to C++11 (which is the minimum required for "modern
C++").
We also forbid use of exceptions and RTTI, they're unnecessary and add too
much magic.
You should also be frugal with templates and vtables.
You may follow guidelines for "good C++" from other sources,
I've been reading the Essential C++ series and found it helpful.
=== Library standards including C/C++ standard library
If you need a feature from a newer version of one of these standards, but we
don't have the need to upgrade our minimum dependencies and the new feature
is a change you can easily add as a utility function. Then add it to
+pz_cxx_future.h/cpp+ (or create a new future file for other libraries),
and indicate in a comment what version of the standard they're from.
Then when we do update our dependencies we can look in these files to
easily find what workarounds we can remove.
This also applies to things that haven't been added to a standard but might
be someday.
=== Environment specifics
This is one of the most important sections in the coding standard. Here we
mention what other tools Plasma may depend on.
==== Tools required for Plasma
In order to build Plasma you need:
* A POSIX (1-2008) system/environment.
* A shell compatible with Bourne shell (sh)
* GNU make
* A C99/C++11 compiler
* Mercury 14.01.1 or newer.
==== Documenting the tools
If further tools or libraries are required, you should add them to the above
list. And similarly, if you eliminate dependence on a tool, remove it from
the above list.
== Syntax
Basic layout (line length, indentation etc) is covered above in File
encoding.
=== General rules
Clang-format has been configured and mostly does the right thing. But often
doesn't. You could check "what would clang-format do" but it is not to be
relyed on.
==== Curly brackets
Curly brackets should be placed at the end of the opening line, and on a new
line not-indented at the end:
[source,c]
----
if (condition) {
...
}
----
Except for functions and classes, which should have the opening curly on a
new line.
[source,c]
----
int
foo(arg)
{
...
}
----
If the opening line is split between multiple lines, such as a long
condition in an if-then-else, then place the opening curly on a new line to
clearly separate the condition from the body:
[source,c]
----
if (this_is_a_somewhat_long_conditional_test(
in_the_condition_of_an +
if_then))
{
...
}
----
==== Space between tokens
There should be a space between the statement keywords like +if+, +while+,
+for+ and +return+ and the next token. The return value should not be
parenthesised. There should also be a space around an operator.
There should be no space between the function-like keywords like +sizeof+
and their argument list. There also be no space between a cast and its
argument.
=== Pointer declarations
Place the pointer or reference qualifier between the type and the variable
name.
[source,c]
----
char * str1, * str2;
----
This avoids confusion that might occur when the pointer qualifier is
attached to the type.
[source,c]
----
char* str1, not_really_a_str;
----
TODO: find out if the same trap exists for C++ references.
And makes the symbol easier to notice.
=== Statements
Use one statement per line.
==== Large control-flow statements
Use an +// end + comment if the if statement, switch or loop is quite large,
particularly if there are multiple nested structures. It may be helpful to
describe the condition of the branch in this comment.
[source,c]
----
if (blah) {
// Use curlies, even when there's only one statement in the block.
...
// Imagine dozens of lines here.
...
} // end if
----
==== Tiny control-flow structures
An exception to the above rule about always using curlies, is that an +if+
statement may omit the curlies if its body is a single +return+ or +goto+
instruction and is placed on the same line.
[source,c]
----
file = fopen("file.txt", "r");
if (NULL != file) goto error;
----
or
[source,c]
----
file = fopen("file.txt", "r");
if (NULL != file) {
goto error;
}
----
but not:
[source,c]
----
file = fopen("file.txt", "r");
if (NULL != file)
goto error;
----
and not:
[source,c]
----
if (a_condition)
do_action();
----
Additionally, if one branch uses curlies then all must use curlies. Do not
mix styles such as:
[source,c]
----
if (a_condition) goto error;
else {
do_something();
}
----
And if the condition covers multiple lines, then the body must always appear
within curlies (with the opening curly on its own line as noted above).
[source,c]
----
if (0 == read_proc(file, imported, module, code_bytes,
proc->code_offset, &block_offsets[i]))
{
goto end;
}
----
==== Conditions
TODO: Consider removing this rule.
To make clear your intentions, do not rely on the zero / no-zero boolean
behaviour of C. This means explicitly comparing a value:
[source,c]
----
if (NULL != file) goto error
----
If using the equality operator +==+, use a non-_lvalue_ on the
left-hand-side if possible.
This way the comparison can not be mistaken for an assignment.
[source,c]
----
if (0 == result) {
...
}
----
==== Switch statements
Case labels should be indented one level, which will indent the body by two
levels.
Switch statements should usually have a default case, even if it just calls
+abort()+.
If the switched-on value is an enum, the default may be omitted since the
compiler will check that all the possible values are covered.
==== Fall through switch cases
If a switch case falls through, add a comment to say that this is
deliberately intended.
[source,c]
----
switch (var) {
case A:
...
break;
case B:
...
// fall-through
case C:
...
break;
}
----
==== Curlies in cases
If a case requires local variable declarations, place the curlies like
this:
[source,c]
----
...
case A: {
int foo;
...
break;
}
case B:
...
----
==== Loops
Loops that end in a non-obvious way, such as infinite while loops that use
'break' to end the loop. Should be documented. You'll need to use
judgement about when this is needed.
[source,c]
----
// Note that the loop will exit when ...
while (true) {
...
if (some condition)
break;
...
}
----
or
[source,c]
----
while (everything_is_okay) {
...
if (some condition) {
// Exit the loop on the next iteration.
everything_is_okay = false;
}
...
}
----
=== Functions
In argument lists, put space after commas. Include parameter names in the
declaration as this can aid in documentation.
Unlike other code blocks, the open-curly for a function should be placed on
a new line.
[source,c]
----
int rhododendron(int a, float b, double c)
{
...
}
----
If the parameter list is very long, then you may wish, particularly for long
or complex parameter lists, place each parameter on a new line aligning them.
Aligning names as in variable definition lists is also suggested but not
required.
[source,c]
----
int rhododendron(int a_long_parameter,
struct AComplexType* b,
double c)
{
...
}
----
=== Variables
Variable declarations shouldn't be flush left, however.
[source,c]
----
int x = 0,
y = 3,
z;
----
----
int a[] = {
1,2,3,4,5
};
----
When defining multiple variables or structure fields or in some cases
function parameters, then lining up their names is recommended.
This also applies to structure and union fields.
There should be one line of vertical space between the definition list and
the next statement.
[source,c]
----
char * some_string;
int x;
MyStructure * my_struct;
if (...) {
----
=== Enums or defines?
Prefer enums to lists of #defines. Note that enums constants are of type
int, hence if you want an enumeration of chars or shorts, then you must
use lists of #defines.
=== Preprocessing
==== Nesting
Nested #ifdefs, #ifndefs and #ifs should be indented by two spaces for each
level of nesting. For example:
[source,c]
----
#ifdef GUAVA
#ifndef PAPAYA
#else // PAPAYA
#endif // PAPAYA
#else // not GUAVA
#endif // not GUAVA
----
==== Multi-line macros
When continuing a macro on an new line, line the +\+ up o the right in the
same column.
[source,c]
----
#define PZ_WRITE_INSTR_1(code, w1, tok) \
if (opcode == (code) && width1 == (w1)) { \
token = (tok); \
goto write_opcode; \
}
----
== Other implementation choices
=== C++ Class or Struct
If a thing will have methods that act on instances, it is a class and should
begin with the "class" keyword, and keep its data members private.
Otherwise it is a struct and shell begin with a struct keyword..
=== Bare Pointers
Bare pointers aren't "modern C\+\+".
However in Plasma's runtime system they show that the lifetime of the object
is handled elsewhere.
Either it is known to live a very long time and live in static data or on
the C++ heap and destroyed when the program ends.
Or it is a GC allocated object and we additionally guarantee that in the time
while it's live (passed around) it's impossible for a GC to occur (there's
also a NoGCScope present.
TODO: Describe how we root GC pointers within runtime code.
=== C++ information hiding
C++ exposes implementation details of classes in their declarations as
private members.
This means that changes to these internal details can cause unnecessary
recompilation.
On the other hand it allows the compiler to inline functions defined in the
class definition that _do_ access private members.
When the latter need is not great it can be good to avoid creating the
former problem by hiding these details. There are a few different
techniques
The *pImpl* pattern is done where the class now contains a pointer to a
class that contains the actual implementation. This pointer should be a
+std::shared_ptr+ and the outer class is expected to be passed by value
rather than by reference.
While this still allows callers to use +object.method()+ style calls (which
then forward), it breaks the normal expectations where "most objects should
be passed by reference". Of course you _can_ pass them by reference but
doing so creates an extra pointer indirection.
Passing by value isn't great either, causing extra work in the
+std::shared_ptr+ to maintain its reference count.
There's *another pattern* where an abstract base class contains a virtual
public interface and a private derived class containing the actual
implementation.
We avoid this because we want to avoid vtables when we can.
Therefore the *pattern we use* in Plasma's runtime (when we choose to hide
implementation details at all) is to forward declare the class, and define
it in an implementation file or implementation-only header file.
The public interface is defined as non-member forwarding functions.
This pattern can be seen in
https://github.com/PlasmaLang/plasma/blob/master/runtime/pz_gc.h[+pz_gc.h+] and
https://github.com/PlasmaLang/plasma/tree/master/runtime/pz_gc.impl.h[+pz_gc.impl.h+].
== Comments
=== What should be commented
==== Functions
Use your judgement for whether a function should be commented.
Sometimes the function name and parameter names will provide a lot of
information.
However for more complex functions a comment will be necessary.
Comments are strongly recommended when:
* They have side-effects
* They require an input to be sorted, non-null or similar.
* They have different semantics when an input has a different value
(they should be separate functions if they do a different _function_).
* They allocate memory that the caller is now responsible for.
* They return statically allocated memory (try to avoid this).
* They free memory.
* They return certain values (non-zero, -1 etc) for errors.
* They ain't thread safe or reenterant.
==== Macros
Each non-trivial macro should be documented just as for functions (see
above). It is also a good idea to document the types of macro arguments and
return values, e.g. by including a function declaration in a comment.
Parameters to macros should be in parentheses.
[source,c]
----
#define STREQ(s1,s2) (strcmp((s1),(s2)) == 0)
----
This ensures than when a complex expression is passed as a parameter that
different operator precedence does not affect the meaning of the macro.
==== Headers
Such function comments should be present in header files for each function
exported from a source file. Ideally, a client of the module should not have
to look at the implementation, only the interface. In C terminology, the
header should suffice for working out how an exported function works.
==== Source files
Every source file should have a prologue comment which includes:
* Copyright notice.
* License info
* Short description of the purpose of the module.
* Any design information or other details required to understand and maintain
the module (may be links to other documents).
[TODO]
====
Describe the exact format in use and ensure that all the C code
conforms to this.
====
==== Global variables
Any global variable should be excruciatingly documented. This is especially
true when globals are exported from a module. In general, there are very few
circumstances that justify use of a global.
=== Comment style
==== Block comments.
Use comments of this form:
[source,c]
----
/*
* This is a block comment,
* it uses multiple lines.
* It should have a blank line before it and it comments the declaration,
* definition, block or group of statements immediately following it.
*/
----
For annotations to a single line of code:
[source,c]
----
i += 3; // Add 3.
----
Note that the +//+ comment is standard in C99, which we are using.
If the comment fits on one line, even if it describes multiple lines, a
single line comment is okay:
[source,c]
----
// Add 3.
i += 3;
----
However if the comment is important, or the thing it documents is
significant. Then use a block comment.
=== Guidelines for comments
==== Revisits
Any code that needs to be revisited because it is a temporary hack (or some
other expediency) must have a comment of the form:
[source,c]
----
/*
* XXX: <reason for revisit>
* - <Author name>
*/
----
The <reason for revisit> should explain the problem in a way that can be
understood by developers other than the author of the comment.
Also include the author of this comment so that a reader will know who to
ask if they need further information.
"TODO" and "Note" are also common revisit labels. Only "XXX" _requires_ the
author's name.
==== Comments on preprocessor statements
The +#ifdef+ constructs should be commented like so if they extend for more
than a few lines of code:
[source,c]
----
#ifdef SOME_VAR
...
#else // ! SOME_VAR
...
#endif // ! SOME_VAR
----
Similarly for +#ifndef+.
Use the GNU convention of comments that indicate whether the variable is
true in the +#if+ and +#else+ parts of an +#ifdef+ or +#ifndef+. For
instance:
[source,c]
----
#ifdef SOME_VAR
#endif // SOME_VAR
#ifdef SOME_VAR
...
#else // ! SOME_VAR
...
#endif // ! SOME_VAR
#ifndef SOME_VAR
...
#else // SOME_VAR
...
#endif // SOME_VAR
----
== Using formatting tools
Typing `make format` will run clang-format-10 on the C/C++ code. It
mis-formats quite a few things so we don't yet use it automatically, or may
do on a file-by-file basis some time.
=== Tables
When code or data is tabular then using a tabular layout makes the most
sense. This may be something formatters cannot handle, some will allow you
to describe excisions.
We don't have a good example of this in the code base,
however the data in +pz_builtin.c+ could probably be set out in a table.
If it were it might look like:
[source,c]
----
static PZ_Proc_Symbol builtins[] = {
{ PZ_BUILTIN_C_FUNC, {.c_func = builtin_setenv_func}, false },
{ PZ_BUILTIN_C_FUNC, {.c_func = builtin_free_func}, false }
};
----
== Defensive programming
=== Asserts and debug builds
TODO
=== Statement macros must be single statements
Macros should either be expressions (they have a value) or statements (they
do not), this must always be clear. If necessary make a single statement
using a block. The
https://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html[do {} while (0)]
pattern is not necessary since bodies of if statments may not be macros
without their own curly brackets.
[source,c]
----
#define PZ_WRITE_INSTR_1(code, w1, tok) \
if (opcode == (code) && width1 == (w1)) { \
token = (tok); \
goto write_opcode; \
}
----
=== Macros should not evaluate parameters more than once
C expressions may have side-effects, this is okay most of the time but can
lead to confusion with macros. A macro can evaluate its parameters more
than once. Avoid doing this in your macros, and if you must add a comment
explaining that this can happen.
=== C++ type conversion
It's very easy for C++ compilers to want to perform type conversions for
you. This is frequently done via conversion operators and constructions
that take a single argument. The later are easy to provide by mistake,
therefore 1-arg constructors should be declared as explicit, which will
prevent the compiler from using them automatically.
----
explicit MyType(const OtherType &other);
----
When implicit conversion is desired, add a comment to tell anyone reading your
code that you didn't forget, that you _want_ it to be implicit.
----
// Implicit constructor
Optional(T &other);
----
=== C++ copy constructors
C++ will create implicit copy constructors. These don't always do the right
thing so it is best to either create them explicitly or tell C++ you don't
want them. The same is true for copy assignment operators.
----
MyClass(const MyClass &) = delete;
void operator=(const MyClass &) = delete
----
== Tips
* Limit module exports to the absolute essentials. Make as much static (that
is, local) as possible since this keeps interfaces to modules simpler.
* Use typedefs to make code self-documenting. They are especially useful on
structs, unions, and enums. Use them on the struct or union's forward
declaration or header declaration when the definition is provided
elsewhere.
== Tracing macros
TODO
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_style_mercury.txt
================================================
Plasma Development Mercury Style Guide
======================================
:Author: Gert Meulyzer
:Email: gert@plasmalang.org
:Date: September 2015
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
// For the Mercury style guide:
// https://mercurylang.org/development/developers/coding_standards.html
// and for reference:
// https://mercurylang.org/development/developer.html
== General Project Contributing Guide
For general information about contributing to Plasma please
see
link:contributing.html[our contributors' documentation].
== Documentation
* Each module should contain header comments which state the module's name,
a copyright notice, license info, main author(s), and purpose, and give an
overview of what the module does, what are the major algorithms and data
structures it uses, etc.
* Everything that is exported from a module should have sufficient
documentation that it can be understood without reference to the module's
implementation section.
* Each predicate other than trivial access predicates should have a short comment describing what the predicate is supposed to do, and what the meaning of the arguments are. Ideally this description should also note any conditions under which the predicate can fail or throw an exception.
* There should be a comment for each field of a structure saying what the field represents.
== Naming
* Variables should always be given meaningful names, unless they are irrelevant to the code in question. For example, it is OK to use single-character names in an access predicate which just sets a single field of a structure, such as:
----
bar_set_foo(Foo, bar(A, B, C, _, E), bar(A, B, C, Foo, E)).
----
* Variables which represent different states or different versions of the same entity should be named Foo0, Foo1, Foo2, ..., Foo.
* Predicates which get or set a field of a structure or ADT should be named bar_get_foo and bar_set_foo respectively, where bar is the name of the structure or ADT and foo is the name of the field.
== Coding
* Your code should make as much reuse of existing code as possible. "cut-and-paste" style reuse is highly discouraged.
* No fixed limits please! (If you really must have a fixed limit, include detailed documentation explaining why it was so hard to avoid.)
== Error handling
* Code should check for both erroneous inputs from the user and also invalid
data being passed from other modules. You should also always check to make
sure that the routines that you call have succeeded; make sure you don't
silently ignore failures. (This last point almost goes without saying in
Mercury, but is particularly important to bear in mind if you are writing
any C code or shell scripts, or if you are interfacing with the OS.)
* Error messages should follow a consistent format. For compiler error
messages, each line should start with the source file name and line number
in "%s:%03d: " format. Error messages should be complete
sentences. For error messages that are spread over more than one line (as
are most of them), the second and subsequent lines should be indented two
spaces.
* Exceptions should usually be used for *exceptional* (eg unforeseen)
things. However during early development exceptions are a suitable way to
mark something that we intend to fix later. There are four types of
exception used.
** +software_error+ (thrown by +unexpected+ and +error+). This is used when
something truly unanticipated has occurred, such as an assertion of a state
that should never happen.
** +compile_error_exception+ (thrown by +compile_error+). This is used when
a compilation error is not properly handled. These should be converted
to actual compiler errors in the future.
** +unimplemented_exception+ (thrown by +sorry+). This is used when
a Plasma feature is not implemented yet. It is a case that we intend to
handle in the future.
** +design_limitation_exception+ (thrown by +limitation+). This is used when
some limitation is exceeded. These are thing that we think will never
happen, and so have no plans to fix them. If they do happen, then we
will attempt to fix them.
== Layout
* Each module should be indented consistently, with 4 spaces per level of
indentation. The indentation should be consistently done with spaces.
A tab character should always mean 4 spaces.
Never under any circumstances mix tabs and spaces.
Currently 100% of our development is done in vim, therefore it is trivial
to use an editor hint to encourage this. Files should have something like
this at the top, even before the copyright line:
----
% vim: ft=mercury ts=4 sw=4 et
----
Hints for other editors should be added as necessary.
* No line should extend beyond 77 characters. We choose 77 characters to
allow for one character to be used when creating diffs and two more
characters to be used in e-mail replies duing code review.
* Since "empty" lines that have spaces or tabs on them prevent the proper functioning of paragraph-oriented commands in vi, lines shouldn't have trailing white space. They can be removed with a vi macro such as the following. (Each pair of square brackets contains a space and a tab.)
----
map ;x :g/[ ][ ]*$/s///^M
----
* String literals that don't fit on a single line should be split by writing them as two or more strings concatenated using the "++" operator; the Mercury compiler will evaluate this at compile time, if --optimize-constant-propagation is enabled (i.e. at -O3 or higher).
* Predicates that have only one mode should use predmode declarations rather than having a separate mode declaration.
* If-then-elses should always be parenthesized, except that an if-then-else that occurs as the else part of another if-then-else doesn't need to be parenthesized. The condition of an if-then-else can either be on the same line as the opening parenthesis and the `->',
----
( test1 ->
goal1
; test2 ->
goal2
;
goal
)
----
or, if the test is complicated, it can be on a line of its own:
----
(
very_long_test_that_does_not_fit_on_one_line(VeryLongArgument1,
VeryLongArgument2)
->
goal1
;
test2a,
test2b,
->
goal2
;
test3 % would fit one one line, but separate for consistency
->
goal3
;
goal
).
----
* Disjunctions should always be parenthesized. The semicolon of a disjunction should never be at the end of a line -- put it at the start of the next line instead.
* Normally disjunctions place each semicolon on a new line
----
(
goal1,
goal2
;
goal3
;
goal4,
goal5
).
----
* However simple disjunctions, such as those that attempt to unify a
variable in each disjunct (which are also switches), may be formatted more
concicely.
----
( goal1
; goal2
; goal3
),
----
* Switches may be formatted with the switched on variable sharing a line
with the open-paren and each semicolon:
----
( X = foo,
goal1,
goal2
; X = bar,
goal3
).
----
Or the switched on variable may have a line of its own, as it would in a
regular disjunction.
* Predicates and functions implemented via foreign code should be formatted like this:
----
:- pragma foreign_proc("C",
to_float(IntVal::in, FloatVal::out),
[will_not_call_mercury, promise_pure],
"
FloatVal = IntVal;
").
----
* The predicate name and arguments should be on a line on their own, as should the list of annotations. The foreign code should also be on lines of its own; it shouldn't share lines with the double quote marks surrounding it.
* Type definitions should be formatted in one of the following styles:
----
:- type my_type
---> my_type(
some_other_type % comment explaining it
).
:- type some_other_type == int.
:- type foo
---> bar(
int, % comment explaining it
float % comment explaining it
)
; baz
; quux.
----
* If an individual clause is long, it should be broken into sections, and each section should have a "block comment" describing what it does; blank lines should be used to show the separation into sections. Comments should precede the code to which they apply, rather than following it.
----
%
% This is a block comment; it applies to the code in the next
% section (up to the next blank line).
%
blah,
blah,
blahblah,
blah,
----
If a particular line or two needs explanation, a "line" comment
----
% This is a "line" comment; it applies to the next line or two
% of code
blahblah
or an "inline" comment
blahblah % This is an "inline" comment
----
should be used.
== Structuring
* Code should generally be arranged so that procedures (or types, etc.) are listed in top-down order, not bottom-up.
* Code should be grouped into bunches of related predicates, functions, etc., and sections of code that are conceptually separate should be separated with dashed lines:
----
%---------------------------------------------------------------------------%
----
Ideally such sections should be identified by "section heading" comments identifying the contents of the section, optionally followed by a more detailed description. These should be laid out like this:
----
%---------------------------------------------------------------------------%
%
% Section title
%
% Detailed description of the contents of the section and/or
% general comments about the contents of the section.
% This part may go one for several lines.
%
% It can even contain several paragraphs.
The actual code starts here.
----
For example
----
%---------------------------------------------------------------------------%
%
% Exception handling
%
% This section contains all the code that deals with throwing or catching
% exceptions, including saving and restoring the virtual machine registers
% if necessary.
%
% Note that we need to take care to ensure that this code is thread-safe!
:- type foo
---> ...
----
Double-dashed lines, i.e.
----
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
----
can also be used to indicate divisions into major sections. Note that these
dividing lines should not exceed the 77 character limit (see above).
== Module imports
* Each group of :- import_module items should list only one module per line,
since this makes it much easier to read diffs that change the set of
imported modules. In the compiler, when e.g. an interface section imports
modules from from the same program (the compiler) and other libraries,
there should be two groups of imports, the imports from the program first
and then the ones from the libraries.
* Each group of import_module items should be sorted, since this makes it
easier to detect duplicate imports and missing imports. It also groups
together the imported modules from the same package. There should be no
blank lines between the imports of modules from different packages, since
this makes it harder to resort the group with a single editor command.
// vim: set syntax=asciidoc:
================================================
FILE: docs/dev_testing.txt
================================================
Plasma Test Suite
=================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: September 2022
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
The Plasma test suite is located under tests/ but will also execute programs
in examples/ to ensure they keep working.
See tests/README.md for a description of the directory tree.
== Running tests
The test script looks for tests in the directories on its command line.
$ ./tests/run-tests.lua examples tests
Will execute all the tests in the examples and tests directories.
== Adding a new test
The test script searches for tests by looking for `*.exp` files within the
`tests/` and `examples/` directories and their sub-directories.
All tests have an `*.exp` file, this is the "expected output" of the test,
what exactly "output" means depends on the type of the test.
=== Ordinary tests
The test script will attempt to build and run these tests by either finding
a `.build` file with the same name as the test (eg if `my_test.exp` exists
then the script will look for `my_test.build`), or use a `BUILD.plz` file in
the same directory which may be shared with multiple tests (see the
`examples/` directory.)
Once build the test script will expect to run a bytecode file with the same
name, eg `my_test.pz`. It will run the test, optionally with input from a
`my_test.in` file, and check the output against the expected output.
For example for `my_test.exp` it will
try to build/find `my_test.pz`. It will then run this file and gather the
output. The test passes if exits with 0 for its exit code AND its output
matches the contents of the `*.exp` file.
Test output may include lines beginning with #, these will be ignored when
comparing with the expected output.
=== compile_failure tests
These tests will attempt to compile a program (using a matching `.build`
file) and compare the compiler's output with the expected output. A test
can be made a `compiler_failure` test using a test configuration line to
specify the type as below.
== Test configuration
For each test the test script looks in the .p file to find lines containing
`PLZTEST`. The next two whitespace seperated tokens on that line are
configuration paramter and its value. For example:
// PLZTEST build_type dev
Sets the `build_type` parameter to `dev`.
The recognised parameters are:
**`build_type`**: Either `dev` or `rel`. In which build should this test be
executed. If not set then the test runs in all builds. This is the same
build type as set in `build.mk`.
**`build_args`**: Arguments to pass to plzbuild during the build step of the
test.
**`returns`**: The expected exit code for a passing test. The default is 0.
**`output`**: Which stream contains the output we wish to capture and compare.
`stdout` (the default) or `stderr`.
**`type`**: If specified it must be set to compile\_failure which
indicates that the build step must fail and return the exit code 1 and the
output of the compiler will be checked against the expected output file.
If the test type is unspecified it defaults to 'run' (aka ordinary tests).
=== Building tests
The script will attempt to build tests by checking for a `BUILD.plz` file in
the same directory. If it finds one it knows it can build the test by
executing `plzbuild` in that directory. It passes this step if plzbuild
exits with 0.
== Other rules
* Don't name your test "plzbuild" that is reserved.
// vim: set syntax=asciidoc:
================================================
FILE: docs/getting_started.txt
================================================
Getting started with Plasma
===========================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: Janurary 2023
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
Since we don’t have static builds yet, you’ll need to build Plasma from source.
This file contains some instructions on setting up the prerequisites and
building Plasma.
Plasma has been tested on Linux, Windows subsystem for Linux 1 and 2 on x86_64.
== Docker
If you want to run Plasma in a Docker container (rather than the
instructions below for Ubuntu Linux) the Dockerfile provided in
https://github.com/PlasmaLang/plasma/tree/master/scripts/docker[scripts/docker] is available,
It is also build and available on
https://hub.docker.com/r/paulbone/plasma-dep[docker hub].
You can resume this "getting started" guide at the
xref:_hello_world[Hello World] section below,
you will still need to adapt some of the instructions for use with the
container.
== Dependencies
You will need
* GCC or Clang
* GNU Make
* git
* Mercury (tested with 22.01)
* ninja 1.10 or later
Optionally for building documentation:
* asciidoc
* source-highlight
Optionally to run the test suite:
* lua
* lua-file-system
* lua-posix
* diffutils
* ncurses
=== C++ compiler, make and git
Plasma has been tested with clang and gcc.
On debian-based systems you can install a suitable compiler and GNU Make
with the build-essential package.
Install git at the same time.
[source,bash]
----
sudo apt install build-essential git
----
=== Mercury
You’ll need another language, Mercury, since our compiler is written in it.
A recent stable version is required (22.01.x), ROTD versions may also work.
Plasma's CI currently tests with 22.01.
Compiling Mercury from source can take a long time,
but if you’re on Debian, Ubuntu or other derivative running on x86_64
then there are some packages!
Read on or follow the instructions at https://dl.mercurylang.org/deb/
==== For Ubuntu 20.04, this is what you need to do:
To install Mercury you'll need to add a new package repository & GPG key.
Download and trust Paul's GPG key:
[source,bash]
----
cd /tmp
wget https://paul.bone.id.au/paul.asc
sudo cp paul.asc /etc/apt/trusted.gpg.d/paulbone.asc
----
Create a new file in /etc/apt/sources.list.d, name it mercury.list and paste
in it:
deb http://dl.mercurylang.org/deb/ focal main
deb-src http://dl.mercurylang.org/deb/ focal main
You may need to substitue focal for another name, see the
https://dl.mercurylang.org/deb/[Mercury debian packages page].
.Now we can install:
[source,bash]
----
sudo apt update
sudo apt install mercury-rotd-recommended
----
=== Asciidoc
To optionally build the documentation, you need to install AsciiDoc and
source-highlight:
[source,bash]
----
sudo apt install asciidoc source-highlight
----
Beware, this is a very large installation, on a default Ubuntu installation
this amounts to over 1 GB of space and a download of over 300MB.
If AsciiDoc is not installed, documentation will not be built.
=== ninja
Plasma's build tool `plzbuild` needs least version 1.10 of the ninja build
tool.
Ubuntu 20.04 has a suitable package.
----
sudo apt install ninja-build
----
Or install it yourself from a binary download:
https://github.com/ninja-build/ninja/releases
Or from source:
https://github.com/ninja-build/ninja/
Or run these commands to install ninja 1.10.2 on your x86_64 Linux system:
----
cd /tmp
wget https://github.com/ninja-build/ninja/releases/download/v1.10.2/ninja-linux.zip
unzip ninja-linux.zip
sudo cp ninja /usr/local/bin/
----
Alpine Linux doesn't currently contain a recent enough version, you'll need to
build ninja from source on Alpine.
=== Lua, diffutils and ncurses
To run the test suite you will need
* lua
* lua-file-system
* lua-posix
* diffutils
* ncurses
Ubuntu 20.04 has a suitable package.
----
apt install lua5.3 lua-filesystem lua-posix diffutils ncurses-bin
----
== Compiling Plasma
Now it’s time to clone the plasma repo:
[source,bash]
----
git clone https://github.com/PlasmaLang/plasma.git
----
If you want or need to, you can configure Plasma's build settings by
copying `template.mk` to `build.mk` and editing it.
It contains some documentation for the build options.
These include which C compiler to use, and compilation flags.
The default build is reasonable if you have `gcc`.
You may need to set the `PREFIX` variable to your desired installation
directory, The Plasma compiler and other tools will be installed to
`$PREFIX/bin/`, you will need to arrange for that to be in your shell
interpreter's path
(https://github.com/PlasmaLang/plasma/issues/325[bug #325] will remove this
requirement).
Then run `make` and it will build you the plasma compiler (`src/plzc`)
and the runtime (`runtime/plzrun`).
Set `MAKEFLAGS` to build the C++ code in parallel, or set it in your
`~/.bashrc`.
----
NPROC=$(nproc)
export MAKEFLAGS="-j$NPROC -l$NPROC"
make
----
The `make test` command will execute the test suite.
Be sure to take a look at the example programs in
https://github.com/PlasmaLang/plasma/tree/master/examples[`examples/`].
== Installing Plasma
The `make install` command will now install the Plasma tools into
the `$PREFIX` path you set in `build.mk` in the previous step.
The compiler and other tools are now available under `$PREFIX/bin/`.
Enjoy!
== Hello world
So you've got Plasma installed, it's time to take it for a test-drive.
In a new directory create a `BUILD.plz` project file, it should contain:
----
[hello]
type = program
modules = [ Hello ]
----
Create a `hello.p` file to contain the `Hello` module, it should contain:
----
module Hello
entrypoint
func hello() uses IO -> Int {
print!("Hello world\n")
return 0
}
----
Then use the `plzbuild` program to build the program:
----
$ plzbuild
----
This will create a `hello.pz` file in the current directory containing the
program's bytecode. Run it with:
----
$ plzrun hello.pz
Hello world
----
== vim customisation
If you want to write some Plasma programs and you use vim. You may wish to
use the
https://github.com/PlasmaLang/vim[vim editor support].
== Getting help
If you're stuck and the https://plasmalang.org/docs/[Documentation] doesn't
contain the answer or clue you need or you're struggling to find it. Please
ask for help.
The https://plasmalang.org/contact.html[Contact] page of the website lists
all the ways you can get in touch.
In particular the
https://plasmalang.org/lists/listinfo/help[Plasma Help mailing list]
and
https://discord.gg/x4g83w7tKh[Discord server] are the best
resources for help.
For bugs or missing information please
https://github.com/PlasmaLang/plasma/issues/new[file a bug].
// vim: set syntax=asciidoc:
================================================
FILE: docs/index.txt
================================================
Plasma Language Documentation
=============================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: March 2021
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
link:getting_started.html[Getting Started with Plasma]::
The getting started guide is your first step to working with Plasma. It
covers installation, writing your first program, and where to look next.
link:user_guide.html[User's Guide]::
The user's guide describes how to use the Plasma tools to work with your
programs.
link:plasma_ref.html[Plasma Language Reference]::
The language reference documents the language in a reference-style.
It's useful if you want to lookup some detail. It's not a guide and not
ideal for teaching the language. We have guide-like documentation other
than the getting started guide.
link:contributing.html[Contributing to Plasma]::
Information about contributing to Plasma. This covers necessary stuff
like your first pull request but also links to further information like
nitty-gritty compiler internals.
link:https://plasmalang.org/about.html#Publications[Publications]::
List of publications.
// vim: set syntax=asciidoc:
================================================
FILE: docs/plasma_ref.txt
================================================
Plasma Language Reference
=========================
:Author: Paul Bone
:Email: paul@plasmalang.org
:Date: January 2025
:Copyright: Copyright (C) Plasma Team
:License: CC BY-SA 4.0
:toc:
As the language is under development this is a working draft.
Many choices may be described only as bullet points.
As the language develops these will be filled out and terms will be
clarified.
== Lexical analysis and parsing
The "front end" passes of Plasma compilation work as follows:
* Tokenisation converts a character stream into a token stream.
* Parsing converts the token stream into an AST.
* AST->Core transformation converts the AST into the core representation.
This phase also performs symbol resolution, converting textual identifiers
in the AST into unique references.
=== Lexical analysis
* Input files are UTF-8
* Comments begin with a +//+ and extend to the end of the line, or are
delimited by +/\*+ and +\*/+ and may cover multiple lines.
Note that comments ending in +**/+ aren't currently supported as they confuse
our limited tokeniser.
* Curly braces for blocks/scoping
* Whitespace is only significant when it separates two tokens what would
otherwise form a single token
* Statements and declarations are not delimited. The end of a statement can
be determined by the statement alone. Therefore: there are no statement
terminators or separators (such as semicolons in C) nor significant
whitespace (as in Python or Haskell).
* String constants are surrounded by double quotes and may contain the
following escapes. +\n \r \t \v \f \b \\+. Escaping the double quote
character is not currently supported, using character codes is not
currently supported. Escaping any other character prints that character
as i
gitextract_m9d_heqr/
├── .clang-format
├── .github/
│ └── workflows/
│ └── ci.yaml
├── .gitignore
├── .gitmessage
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── LICENSE.code
├── LICENSE.docs
├── LICENSE.unlicense
├── Makefile
├── README.md
├── SECURITY.md
├── THANKS
├── defaults.mk
├── docs/
│ ├── .gitignore
│ ├── README.md
│ ├── asciidoc.conf
│ ├── contributing.txt
│ ├── css/
│ │ ├── asciidoc.css
│ │ └── docs-offline.css
│ ├── design_concept_map.txt
│ ├── design_ideas.txt
│ ├── design_principles.txt
│ ├── design_types.txt
│ ├── dev_bugtracking.txt
│ ├── dev_compiler_internals.txt
│ ├── dev_howto_make_pr.txt
│ ├── dev_maintainers.txt
│ ├── dev_mercury_grades.txt
│ ├── dev_style_c.txt
│ ├── dev_style_mercury.txt
│ ├── dev_testing.txt
│ ├── getting_started.txt
│ ├── index.txt
│ ├── plasma_ref.txt
│ ├── pz_machine.txt
│ ├── references.txt
│ └── user_guide.txt
├── examples/
│ ├── .gitignore
│ ├── BUILD.plz
│ ├── Makefile
│ ├── README.md
│ ├── ackermann.exp
│ ├── ackermann.p
│ ├── change.exp
│ ├── change.in
│ ├── change.p
│ ├── fib.exp
│ ├── fib.p
│ ├── hello.exp
│ ├── hello.p
│ ├── module_example.p
│ ├── module_to_import.p
│ ├── modules.exp
│ ├── mr4.exp
│ ├── mr4.p
│ ├── readline.exp
│ ├── readline.in
│ ├── readline.p
│ ├── sequences.p
│ ├── set.p
│ ├── string.p
│ ├── temperature.exp
│ ├── temperature.p
│ ├── types.exp
│ ├── types.p
│ └── util.p
├── runtime/
│ ├── .gitignore
│ ├── README.md
│ ├── pz.cpp
│ ├── pz.h
│ ├── pz_array.h
│ ├── pz_builtin.cpp
│ ├── pz_builtin.h
│ ├── pz_closure.h
│ ├── pz_code.cpp
│ ├── pz_code.h
│ ├── pz_common.h
│ ├── pz_config.h.in
│ ├── pz_cxx_future.h
│ ├── pz_data.cpp
│ ├── pz_data.h
│ ├── pz_foreign.cpp
│ ├── pz_foreign.h
│ ├── pz_format.h
│ ├── pz_gc.cpp
│ ├── pz_gc.h
│ ├── pz_gc.impl.h
│ ├── pz_gc_alloc.cpp
│ ├── pz_gc_collect.cpp
│ ├── pz_gc_debug.cpp
│ ├── pz_gc_layout.h
│ ├── pz_gc_layout.impl.h
│ ├── pz_gc_layout_bop.h
│ ├── pz_gc_layout_fit.h
│ ├── pz_gc_util.cpp
│ ├── pz_gc_util.h
│ ├── pz_generic.cpp
│ ├── pz_generic_builder.cpp
│ ├── pz_generic_builtin.cpp
│ ├── pz_generic_closure.cpp
│ ├── pz_generic_closure.h
│ ├── pz_generic_run.cpp
│ ├── pz_generic_run.h
│ ├── pz_instructions.cpp
│ ├── pz_instructions.h
│ ├── pz_interp.h
│ ├── pz_io.cpp
│ ├── pz_io.h
│ ├── pz_library.cpp
│ ├── pz_library.h
│ ├── pz_main.cpp
│ ├── pz_memory.cpp
│ ├── pz_memory.h
│ ├── pz_option.cpp
│ ├── pz_option.h
│ ├── pz_read.cpp
│ ├── pz_read.h
│ ├── pz_string.cpp
│ ├── pz_string.h
│ ├── pz_trace.cpp
│ ├── pz_trace.h
│ ├── pz_util.h
│ └── pz_vector.h
├── scripts/
│ ├── README.md
│ ├── do_mmc_make
│ └── docker/
│ ├── Dockerfile
│ ├── README.md
│ ├── build.sh
│ ├── gitconfig
│ ├── install.sh
│ ├── mercury.list
│ ├── paul.gpg
│ ├── vimrc
│ └── welcome.sh
├── src/
│ ├── .gitignore
│ ├── .vim_mmc_make
│ ├── Mercury.options
│ ├── README.md
│ ├── asm.m
│ ├── asm_ast.m
│ ├── asm_error.m
│ ├── ast.m
│ ├── build.m
│ ├── builtins.m
│ ├── common_types.m
│ ├── compile.m
│ ├── compile_error.m
│ ├── constant.m
│ ├── context.m
│ ├── core.arity_chk.m
│ ├── core.branch_chk.m
│ ├── core.code.m
│ ├── core.function.m
│ ├── core.m
│ ├── core.pretty.m
│ ├── core.res_chk.m
│ ├── core.resource.m
│ ├── core.simplify.m
│ ├── core.type_chk.m
│ ├── core.type_chk.solve.m
│ ├── core.types.m
│ ├── core.util.m
│ ├── core_to_pz.closure.m
│ ├── core_to_pz.code.m
│ ├── core_to_pz.data.m
│ ├── core_to_pz.locn.m
│ ├── core_to_pz.m
│ ├── dump_stage.m
│ ├── file_utils.m
│ ├── foreign.m
│ ├── lex.automata.m
│ ├── lex.buf.m
│ ├── lex.convert_NFA_to_DFA.m
│ ├── lex.lexeme.m
│ ├── lex.m
│ ├── lex.regexp.m
│ ├── options.m
│ ├── parse.m
│ ├── parse_util.m
│ ├── parsing.m
│ ├── plzasm.m
│ ├── plzbuild.m
│ ├── plzc.m
│ ├── plzdisasm.m
│ ├── plzgeninit.m
│ ├── plzlnk.m
│ ├── pre.ast_to_core.m
│ ├── pre.bang.m
│ ├── pre.branches.m
│ ├── pre.closures.m
│ ├── pre.env.m
│ ├── pre.from_ast.m
│ ├── pre.import.m
│ ├── pre.m
│ ├── pre.pre_ds.m
│ ├── pre.pretty.m
│ ├── pre.to_core.m
│ ├── pre.util.m
│ ├── pz.bytecode.m
│ ├── pz.code.m
│ ├── pz.format.m
│ ├── pz.link.m
│ ├── pz.m
│ ├── pz.pretty.m
│ ├── pz.pz_ds.m
│ ├── pz.read.m
│ ├── pz.write.m
│ ├── pzt_parse.m
│ ├── q_name.m
│ ├── toml.m
│ ├── util.log.m
│ ├── util.m
│ ├── util.mercury.m
│ ├── util.my_exception.m
│ ├── util.my_io.m
│ ├── util.my_string.m
│ ├── util.my_time.m
│ ├── util.path.m
│ ├── util.pretty.m
│ ├── util.pretty_old.m
│ ├── util.result.m
│ ├── varmap.m
│ └── write_interface.m
├── template.mk
├── tests/
│ ├── .gitignore
│ ├── BUILD.plz
│ ├── README.md
│ ├── build/
│ │ ├── bad_file_1.build
│ │ ├── bad_file_1.exp
│ │ ├── bad_file_2.exp
│ │ ├── bad_file_2.test
│ │ ├── bad_file_3.build
│ │ ├── bad_file_3.exp
│ │ ├── bad_file_4.build
│ │ ├── bad_file_4.exp
│ │ ├── bad_module_name.build
│ │ ├── bad_module_name.exp
│ │ ├── bad_module_name_2.build
│ │ ├── bad_module_name_2.exp
│ │ ├── bad_module_name_2.p
│ │ ├── dup_module_name.build
│ │ ├── dup_module_name.exp
│ │ ├── dup_module_name_2.build
│ │ ├── dup_module_name_2.exp
│ │ ├── dup_module_name_2.p
│ │ ├── extra_module.p
│ │ ├── file_in_other_program.build
│ │ ├── file_in_other_program.expish
│ │ ├── file_in_other_program.p
│ │ ├── include_file_nobuild.build
│ │ ├── include_file_nobuild.exp
│ │ ├── include_file_nobuild.p
│ │ ├── include_nofile_build.build
│ │ ├── include_nofile_build.exp
│ │ ├── include_nofile_build.p
│ │ ├── include_nofile_nobuild.build
│ │ ├── include_nofile_nobuild.expish
│ │ ├── include_nofile_nobuild.p
│ │ ├── options_compiler_01.build
│ │ ├── options_compiler_01.exp
│ │ ├── options_compiler_01.p
│ │ ├── options_compiler_02.build
│ │ ├── options_compiler_02.exp
│ │ ├── options_compiler_02.p
│ │ ├── options_compiler_03.build
│ │ ├── options_compiler_03.exp
│ │ └── other_program.p
│ ├── builtins/
│ │ ├── BUILD.plz
│ │ ├── builtin_01.exp
│ │ ├── builtin_01.p
│ │ ├── builtin_02_int.exp
│ │ ├── builtin_02_int.p
│ │ ├── builtin_03_bool.exp
│ │ ├── builtin_03_bool.p
│ │ ├── builtin_04_string.exp
│ │ ├── builtin_04_string.p
│ │ ├── builtin_05_list.exp
│ │ ├── builtin_05_list.p
│ │ ├── builtin_not_found.build
│ │ ├── builtin_not_found.exp
│ │ └── builtin_not_found.p
│ ├── ffi/
│ │ ├── .gitignore
│ │ ├── BUILD.plz
│ │ ├── import_from_two_modules.cpp
│ │ ├── import_from_two_modules.exp
│ │ ├── import_from_two_modules.h
│ │ ├── import_from_two_modules_1.p
│ │ ├── import_from_two_modules_2.p
│ │ ├── import_function.cpp
│ │ ├── import_function.exp
│ │ ├── import_function.h
│ │ ├── import_function.p
│ │ ├── import_shared_module.cpp
│ │ ├── import_shared_module.h
│ │ ├── import_shared_module.p
│ │ ├── import_two_sources.cpp
│ │ ├── import_two_sources.exp
│ │ ├── import_two_sources.h
│ │ ├── import_two_sources.p
│ │ ├── unrecognised_extension.build
│ │ ├── unrecognised_extension.exp
│ │ └── unrecognised_extension.p
│ ├── hello.exp
│ ├── hello.p
│ ├── language/
│ │ ├── BUILD.plz
│ │ ├── arity_01.exp
│ │ ├── arity_01.p
│ │ ├── arity_02.build
│ │ ├── arity_02.exp
│ │ ├── arity_02.p
│ │ ├── arity_ho_1.build
│ │ ├── arity_ho_1.exp
│ │ ├── arity_ho_1.p
│ │ ├── arity_ho_2.build
│ │ ├── arity_ho_2.exp
│ │ ├── arity_ho_2.p
│ │ ├── arity_lambda.build
│ │ ├── arity_lambda.exp
│ │ ├── arity_lambda.p
│ │ ├── comment.exp
│ │ ├── comment.p
│ │ ├── comment_end.build
│ │ ├── comment_end.exp
│ │ ├── comment_end.p
│ │ ├── coverage_1.build
│ │ ├── coverage_1.exp
│ │ ├── coverage_1.p
│ │ ├── entrypoint_bad_sig.build
│ │ ├── entrypoint_bad_sig.exp
│ │ ├── entrypoint_bad_sig.p
│ │ ├── entrypoint_multi.build
│ │ ├── entrypoint_multi.exp
│ │ ├── entrypoint_multi.p
│ │ ├── entrypoint_none.build
│ │ ├── entrypoint_none.exp
│ │ ├── entrypoint_none.p
│ │ ├── export_bad_resource.build
│ │ ├── export_bad_resource.exp
│ │ ├── export_bad_resource.p
│ │ ├── export_bad_type.build
│ │ ├── export_bad_type.exp
│ │ ├── export_bad_type.p
│ │ ├── ho/
│ │ │ ├── BUILD.plz
│ │ │ ├── closure_01.exp
│ │ │ ├── closure_01.p
│ │ │ ├── closure_02.exp
│ │ │ ├── closure_02.p
│ │ │ ├── closure_03.exp
│ │ │ ├── closure_03.p
│ │ │ ├── closure_04.exp
│ │ │ ├── closure_04.p
│ │ │ ├── closure_05.exp
│ │ │ ├── closure_05.p
│ │ │ ├── closure_06.exp
│ │ │ ├── closure_06.p
│ │ │ ├── closure_bad_01.build
│ │ │ ├── closure_bad_01.exp
│ │ │ ├── closure_bad_01.p
│ │ │ ├── closure_bad_02.build
│ │ │ ├── closure_bad_02.exp
│ │ │ ├── closure_bad_02.p
│ │ │ ├── closure_bad_03.build
│ │ │ ├── closure_bad_03.exp
│ │ │ ├── closure_bad_03.p
│ │ │ ├── closure_bad_04.build
│ │ │ ├── closure_bad_04.exp
│ │ │ ├── closure_bad_04.p
│ │ │ ├── closure_bad_05.build
│ │ │ ├── closure_bad_05.exp
│ │ │ ├── closure_bad_05.p
│ │ │ ├── closure_bad_06.build
│ │ │ ├── closure_bad_06.exp
│ │ │ ├── closure_bad_06.p
│ │ │ ├── closure_bad_07.build
│ │ │ ├── closure_bad_07.exp
│ │ │ ├── closure_bad_07.p
│ │ │ ├── closure_bad_08.build
│ │ │ ├── closure_bad_08.exp
│ │ │ ├── closure_bad_08.p
│ │ │ ├── closure_bad_09.build
│ │ │ ├── closure_bad_09.exp
│ │ │ ├── closure_bad_09.p
│ │ │ ├── closure_bad_10.build
│ │ │ ├── closure_bad_10.exp
│ │ │ ├── closure_bad_10.p
│ │ │ ├── closure_mut_rec.build
│ │ │ ├── closure_mut_rec.exp
│ │ │ ├── closure_mut_rec.p
│ │ │ ├── ho_1.exp
│ │ │ ├── ho_1.p
│ │ │ ├── ho_2.exp
│ │ │ ├── ho_2.p
│ │ │ ├── ho_bad_7.build
│ │ │ ├── ho_bad_7.exp
│ │ │ ├── ho_bad_7.p
│ │ │ ├── ho_call_bug_30.exp
│ │ │ └── ho_call_bug_30.p
│ │ ├── ite_1.exp
│ │ ├── ite_1.p
│ │ ├── ite_2.exp
│ │ ├── ite_2.p
│ │ ├── ite_3.exp
│ │ ├── ite_3.p
│ │ ├── list.exp
│ │ ├── list.p
│ │ ├── match/
│ │ │ ├── BUILD.plz
│ │ │ ├── match_1.exp
│ │ │ ├── match_1.p
│ │ │ ├── match_2.exp
│ │ │ ├── match_2.p
│ │ │ ├── match_bad_1.build
│ │ │ ├── match_bad_1.exp
│ │ │ ├── match_bad_1.p
│ │ │ ├── match_bad_2.build
│ │ │ ├── match_bad_2.exp
│ │ │ ├── match_bad_2.p
│ │ │ ├── match_bad_3.build
│ │ │ ├── match_bad_3.exp
│ │ │ ├── match_bad_3.p
│ │ │ ├── match_bad_error_1.build
│ │ │ ├── match_bad_error_1.exp
│ │ │ ├── match_bad_error_1.p
│ │ │ ├── match_empty_case.exp
│ │ │ ├── match_empty_case.p
│ │ │ ├── match_multiple.build
│ │ │ ├── match_multiple.exp
│ │ │ ├── match_multiple.p
│ │ │ ├── unpack_1.exp
│ │ │ ├── unpack_1.p
│ │ │ ├── unpack_nest.build
│ │ │ ├── unpack_nest.exp
│ │ │ └── unpack_nest.p
│ │ ├── operators.exp
│ │ ├── operators.p
│ │ ├── pragma_bad_args.build
│ │ ├── pragma_bad_args.exp
│ │ ├── pragma_bad_args.p
│ │ ├── pragma_unknown_1.build
│ │ ├── pragma_unknown_1.exp
│ │ ├── pragma_unknown_1.p
│ │ ├── pragma_unknown_2.build
│ │ ├── pragma_unknown_2.exp
│ │ ├── pragma_unknown_2.p
│ │ ├── res/
│ │ │ ├── BUILD.plz
│ │ │ ├── multiple_bang.build
│ │ │ ├── multiple_bang.exp
│ │ │ ├── multiple_bang.p
│ │ │ ├── resource.exp
│ │ │ ├── resource.p
│ │ │ ├── resource_invalid_1.build
│ │ │ ├── resource_invalid_1.exp
│ │ │ ├── resource_invalid_1.p
│ │ │ ├── resource_invalid_2.build
│ │ │ ├── resource_invalid_2.exp
│ │ │ ├── resource_invalid_2.p
│ │ │ ├── resource_invalid_3.build
│ │ │ ├── resource_invalid_3.exp
│ │ │ └── resource_invalid_3.p
│ │ ├── return.build
│ │ ├── return.exp
│ │ ├── return.p
│ │ ├── string.exp
│ │ ├── string.p
│ │ ├── types/
│ │ │ ├── BUILD.plz
│ │ │ ├── bug_375.build
│ │ │ ├── bug_375.exp
│ │ │ ├── bug_375.p
│ │ │ ├── closure_infer_1.build
│ │ │ ├── closure_infer_1.exp
│ │ │ ├── closure_infer_1.p
│ │ │ ├── closure_infer_2.build
│ │ │ ├── closure_infer_2.exp
│ │ │ ├── closure_infer_2.p
│ │ │ ├── constructor_duplicate.build
│ │ │ ├── constructor_duplicate.exp
│ │ │ ├── constructor_duplicate.p
│ │ │ ├── constructor_overload.exp
│ │ │ ├── constructor_overload.p
│ │ │ ├── enum.exp
│ │ │ ├── enum.p
│ │ │ ├── ho_bad_1.build
│ │ │ ├── ho_bad_1.exp
│ │ │ ├── ho_bad_1.p
│ │ │ ├── ho_bad_2.build
│ │ │ ├── ho_bad_2.exp
│ │ │ ├── ho_bad_2.p
│ │ │ ├── ho_bad_3.build
│ │ │ ├── ho_bad_3.exp
│ │ │ ├── ho_bad_3.p
│ │ │ ├── ho_bad_4.build
│ │ │ ├── ho_bad_4.exp
│ │ │ ├── ho_bad_4.p
│ │ │ ├── ho_bad_5.build
│ │ │ ├── ho_bad_5.exp
│ │ │ ├── ho_bad_5.p
│ │ │ ├── ho_bad_6.build
│ │ │ ├── ho_bad_6.exp
│ │ │ ├── ho_bad_6.p
│ │ │ ├── occurs1.build
│ │ │ ├── occurs1.exp
│ │ │ ├── occurs1.p
│ │ │ ├── occurs2.build
│ │ │ ├── occurs2.exp
│ │ │ ├── occurs2.p
│ │ │ ├── occurs3.build
│ │ │ ├── occurs3.exp
│ │ │ ├── occurs3.p
│ │ │ ├── occurs4.build
│ │ │ ├── occurs4.exp
│ │ │ ├── occurs4.p
│ │ │ ├── occurs5.build
│ │ │ ├── occurs5.exp
│ │ │ ├── occurs5.p
│ │ │ ├── parametric.exp
│ │ │ ├── parametric.p
│ │ │ ├── playing_card.exp
│ │ │ ├── playing_card.p
│ │ │ ├── polymorphic.exp
│ │ │ ├── polymorphic.p
│ │ │ ├── recursive.exp
│ │ │ ├── recursive.p
│ │ │ ├── tagging1.exp
│ │ │ ├── tagging1.p
│ │ │ ├── tagging2.exp
│ │ │ ├── tagging2.p
│ │ │ ├── types_invalid_02.build
│ │ │ ├── types_invalid_02.exp
│ │ │ ├── types_invalid_02.p
│ │ │ ├── types_invalid_03.build
│ │ │ ├── types_invalid_03.exp
│ │ │ ├── types_invalid_03.p
│ │ │ ├── types_invalid_04.build
│ │ │ ├── types_invalid_04.exp
│ │ │ ├── types_invalid_04.p
│ │ │ ├── types_invalid_05.build
│ │ │ ├── types_invalid_05.exp
│ │ │ ├── types_invalid_05.p
│ │ │ ├── types_invalid_06.build
│ │ │ ├── types_invalid_06.exp
│ │ │ ├── types_invalid_06.p
│ │ │ ├── types_invalid_07.build
│ │ │ ├── types_invalid_07.exp
│ │ │ ├── types_invalid_07.p
│ │ │ ├── types_invalid_08.build
│ │ │ ├── types_invalid_08.exp
│ │ │ └── types_invalid_08.p
│ │ └── vars/
│ │ ├── BUILD.plz
│ │ ├── vars_1.exp
│ │ ├── vars_1.p
│ │ ├── vars_2.exp
│ │ ├── vars_2.p
│ │ ├── vars_invalid_01.build
│ │ ├── vars_invalid_01.exp
│ │ ├── vars_invalid_01.p
│ │ ├── vars_invalid_02.build
│ │ ├── vars_invalid_02.exp
│ │ ├── vars_invalid_02.p
│ │ ├── vars_invalid_03.build
│ │ ├── vars_invalid_03.exp
│ │ ├── vars_invalid_03.p
│ │ ├── vars_invalid_04.build
│ │ ├── vars_invalid_04.exp
│ │ ├── vars_invalid_04.p
│ │ ├── vars_invalid_05.build
│ │ ├── vars_invalid_05.exp
│ │ ├── vars_invalid_05.p
│ │ ├── vars_invalid_06.build
│ │ ├── vars_invalid_06.exp
│ │ ├── vars_invalid_06.p
│ │ ├── vars_invalid_07.build
│ │ ├── vars_invalid_07.exp
│ │ ├── vars_invalid_07.p
│ │ ├── vars_invalid_08.build
│ │ ├── vars_invalid_08.exp
│ │ ├── vars_invalid_08.p
│ │ ├── vars_invalid_09.build
│ │ ├── vars_invalid_09.exp
│ │ ├── vars_invalid_09.p
│ │ ├── vars_invalid_10.build
│ │ ├── vars_invalid_10.exp
│ │ ├── vars_invalid_10.p
│ │ ├── vars_invalid_11.build
│ │ ├── vars_invalid_11.exp
│ │ ├── vars_invalid_11.p
│ │ ├── vars_invalid_12.build
│ │ ├── vars_invalid_12.exp
│ │ ├── vars_invalid_12.p
│ │ ├── vars_invalid_13.build
│ │ ├── vars_invalid_13.exp
│ │ ├── vars_invalid_13.p
│ │ ├── vars_invalid_14.build
│ │ ├── vars_invalid_14.exp
│ │ ├── vars_invalid_14.p
│ │ ├── vars_invalid_15.build
│ │ ├── vars_invalid_15.exp
│ │ └── vars_invalid_15.p
│ ├── library/
│ │ ├── BUILD.plz
│ │ ├── args.exp
│ │ └── args.p
│ ├── modules/
│ │ ├── BUILD.plz
│ │ ├── Makefile
│ │ ├── dyn_link_01.exp
│ │ ├── dyn_link_01.p
│ │ ├── dyn_link_01.sh
│ │ ├── dyn_link_01_a.p
│ │ ├── dyn_link_02.exp
│ │ ├── dyn_link_02.p
│ │ ├── dyn_link_02.sh
│ │ ├── dyn_link_02_a.p
│ │ ├── dyn_link_02_b.p
│ │ ├── entrypoint_1.build
│ │ ├── entrypoint_1.exp
│ │ ├── entrypoint_1a.p
│ │ ├── entrypoint_1b.p
│ │ ├── entrypoint_2.exp
│ │ ├── entrypoint_2a.p
│ │ ├── entrypoint_2b.p
│ │ ├── entrypoint_3.exp
│ │ ├── entrypoint_3a.p
│ │ ├── entrypoint_3b.p
│ │ ├── heir.foo.p
│ │ ├── heir.foo_bar.p
│ │ ├── heir_test.build
│ │ ├── heir_test.exp
│ │ ├── heir_test.p
│ │ ├── module_01.build
│ │ ├── module_01.exp
│ │ ├── module_01.p
│ │ ├── module_01a.p
│ │ ├── module_02.build
│ │ ├── module_02.exp
│ │ ├── module_02.p
│ │ ├── module_02a.p
│ │ ├── module_03a.exp
│ │ ├── module_03a.p
│ │ ├── module_03a.sh
│ │ ├── module_03ar.exp
│ │ ├── module_03ar.sh
│ │ ├── module_03b.exp
│ │ ├── module_03b.p
│ │ ├── module_03b.sh
│ │ ├── module_03br.exp
│ │ ├── module_03br.sh
│ │ ├── module_03c.exp
│ │ ├── module_03c.p
│ │ ├── module_03c.sh
│ │ ├── module_03cr.exp
│ │ ├── module_03cr.sh
│ │ ├── module_04.exp
│ │ ├── module_04.p
│ │ ├── module_04a.p
│ │ ├── module_05.exp
│ │ ├── module_05.p
│ │ ├── module_05a.p
│ │ ├── module_06.exp
│ │ ├── module_06.p
│ │ ├── module_06a.p
│ │ ├── module_07.exp
│ │ ├── module_07.p
│ │ ├── module_07a.p
│ │ ├── module_08.p
│ │ ├── module_08a.exp
│ │ ├── module_08a.sh
│ │ ├── module_08b.exp
│ │ ├── module_08b.sh
│ │ ├── module_name_test.build
│ │ ├── module_name_test.exp
│ │ ├── module_name_test.p
│ │ ├── opaque_resource.p
│ │ ├── opaque_resource_1.build
│ │ ├── opaque_resource_1.exp
│ │ ├── opaque_resource_1.p
│ │ ├── opaque_resource_2.build
│ │ ├── opaque_resource_2.exp
│ │ ├── opaque_resource_2.p
│ │ ├── res_vis_01.a.p
│ │ ├── res_vis_01.b.p
│ │ ├── res_vis_01.c.p
│ │ ├── res_vis_01.d.p
│ │ ├── res_vis_01.exp
│ │ └── res_vis_01.p
│ ├── pretty.lua
│ ├── run-tests.lua
│ ├── runtime/
│ │ ├── BUILD.plz
│ │ ├── allocateLots.exp
│ │ ├── allocateLots.p
│ │ ├── die.exp
│ │ ├── die.p
│ │ ├── parameters.exp
│ │ └── parameters.p
│ └── update-outputs.sh
└── tests-old/
├── .gitignore
├── README.md
├── modules-invalid/
│ ├── .gitignore
│ ├── BUILD.plz
│ ├── Makefile
│ ├── module_01.exp
│ ├── module_01.p
│ ├── module_02.exp
│ ├── module_02.p
│ ├── module_03.exp
│ ├── module_03.p
│ ├── module_03a.p
│ ├── module_04a.exp
│ ├── module_04a.p
│ ├── module_04b.exp
│ ├── module_04b.p
│ ├── module_04c.exp
│ ├── module_04c.p
│ ├── module_04d.exp
│ ├── module_04d.p
│ ├── module_04import.p
│ ├── module_05.exp
│ ├── module_05.p
│ ├── module_05_.p
│ ├── module_06.exp
│ ├── module_06.p
│ ├── module_06a.p
│ ├── module_07.exp
│ ├── module_07.p
│ ├── module_08.c.p
│ ├── module_08.d.p
│ ├── module_08.expish
│ ├── module_08.p
│ ├── module_08b.expish
│ └── module_08b.p
├── pzt/
│ ├── Makefile
│ ├── ccov.exp
│ ├── ccov.pzt
│ ├── closure.exp
│ ├── closure.pzt
│ ├── fib.exp
│ ├── fib.pzt
│ ├── hello.exp
│ ├── hello.pzt
│ ├── link_01.exp
│ ├── link_01.p
│ ├── link_01.pzt
│ ├── link_02.exp
│ ├── link_02.pzt
│ ├── link_03.exp
│ ├── link_03.pzt
│ ├── link_target_01.pzt
│ ├── link_target_02.pzt
│ ├── memory.exp
│ ├── memory.pzt
│ ├── mutual.exp
│ ├── mutual.pzt
│ ├── stack.exp
│ ├── stack.pzt
│ ├── struct.exp
│ ├── struct.pzt
│ ├── tags.exp
│ ├── tags.pzt
│ ├── temperature.exp
│ ├── temperature.pzt
│ ├── trunc_ze_se.exp
│ └── trunc_ze_se.pzt
└── run_tests.sh
SYMBOL INDEX (226 symbols across 56 files)
FILE: runtime/pz.cpp
type pz (line 20) | namespace pz {
function Library (line 35) | Library * PZ::new_library(const String name, GCCapability & gc_cap)
function Library (line 48) | Library * PZ::lookup_library(const String name)
FILE: runtime/pz.h
function namespace (line 20) | namespace pz {
FILE: runtime/pz_array.h
function namespace (line 16) | namespace pz {
FILE: runtime/pz_builtin.cpp
type pz (line 18) | namespace pz {
function builtin_make_tag_instrs (line 46) | static unsigned builtin_make_tag_instrs(uint8_t * bytecode, std::nullp...
function builtin_shift_make_tag_instrs (line 62) | static unsigned builtin_shift_make_tag_instrs(uint8_t * bytecode,
function builtin_break_tag_instrs (line 85) | static unsigned builtin_break_tag_instrs(uint8_t * bytecode,
function builtin_break_shift_tag_instrs (line 122) | static unsigned builtin_break_shift_tag_instrs(uint8_t * bytecode,
function builtin_unshift_value_instrs (line 164) | static unsigned builtin_unshift_value_instrs(uint8_t * bytecode,
function setup_builtins (line 186) | void setup_builtins(Library * library, GCCapability & gccap)
function builtin_create (line 242) | static void builtin_create(Library * library, const String name,
function builtin_create_c_code (line 270) | static void builtin_create_c_code(Library * library, String name,
function builtin_create_c_code_alloc (line 278) | static void builtin_create_c_code_alloc(Library * library, String name,
function builtin_create_c_code_special (line 286) | static void builtin_create_c_code_special(Library * library, String name,
function make_ccall_instr (line 294) | static unsigned make_ccall_instr(uint8_t * bytecode, pz_foreign_c_func...
function make_ccall_alloc_instr (line 307) | static unsigned make_ccall_alloc_instr(uint8_t * bytecode,
function make_ccall_special_instr (line 321) | static unsigned make_ccall_special_instr(uint8_t * bytecode,
FILE: runtime/pz_builtin.h
function namespace (line 15) | namespace pz {
FILE: runtime/pz_code.cpp
type pz (line 14) | namespace pz {
FILE: runtime/pz_code.h
function namespace (line 17) | namespace pz {
FILE: runtime/pz_cxx_future.h
function Optional (line 92) | static constexpr Optional Nothing() {
function set (line 100) | void set(const T & val) {
function set (line 106) | void set(T && val) {
function T (line 117) | const T & value() const {
function clear (line 128) | void clear() {
function class (line 145) | class ScopeExit
FILE: runtime/pz_data.cpp
type pz (line 22) | namespace pz {
function data_write_normal_uint8 (line 63) | void data_write_normal_uint8(void * dest, uint8_t value)
function data_write_normal_uint16 (line 68) | void data_write_normal_uint16(void * dest, uint16_t value)
function data_write_normal_uint32 (line 73) | void data_write_normal_uint32(void * dest, uint32_t value)
function data_write_normal_uint64 (line 78) | void data_write_normal_uint64(void * dest, uint64_t value)
function data_write_fast_from_int32 (line 83) | void data_write_fast_from_int32(void * dest, int32_t value)
function data_write_wptr (line 88) | void data_write_wptr(void * dest, intptr_t value)
function width_from_int (line 93) | Optional<PZ_Width> width_from_int(uint8_t w)
function PZ_Width (line 113) | PZ_Width width_normalize(PZ_Width width)
function width_to_bytes (line 144) | unsigned width_to_bytes(PZ_Width width)
FILE: runtime/pz_data.h
function namespace (line 18) | namespace pz {
FILE: runtime/pz_foreign.cpp
type pz (line 27) | namespace pz {
function safe_getcwd (line 35) | static std::string safe_getcwd() {
type stat (line 68) | struct stat
function Closure (line 118) | Closure *
function make_ccall_instr (line 131) | static unsigned make_ccall_instr(uint8_t * bytecode, pz_foreign_c_func...
function make_foreign (line 144) | static void make_foreign(String name, pz_foreign_c_func c_func, GCTrac...
FILE: runtime/pz_foreign.h
function namespace (line 17) | namespace pz {
FILE: runtime/pz_format.h
type PZOptEntrySignature (line 178) | enum PZOptEntrySignature {
type PZ_Import_Type (line 184) | enum PZ_Import_Type {
type PZ_Width (line 193) | enum PZ_Width {
type pz_data_enc_type (line 227) | enum pz_data_enc_type {
type PZ_Code_Item (line 237) | enum PZ_Code_Item {
FILE: runtime/pz_gc.cpp
type pz (line 56) | namespace pz {
function heap_get_usage (line 64) | size_t heap_get_usage(const Heap * heap)
function heap_get_collections (line 69) | unsigned heap_get_collections(const Heap * heap)
function heap_set_meta_info (line 74) | void heap_set_meta_info(Heap * heap, void * obj, void * meta)
FILE: runtime/pz_gc.h
function namespace (line 15) | namespace pz {
FILE: runtime/pz_gc.impl.h
function namespace (line 17) | namespace pz {
FILE: runtime/pz_gc_alloc.cpp
type pz (line 22) | namespace pz {
function Block (line 139) | Block * Heap::get_block_for_allocation(size_t size_in_words)
function Block (line 144) | Block * ChunkBOP::get_block_for_allocation(size_t size_in_words)
function Block (line 159) | Block * Heap::allocate_block(size_t size_in_words)
function Block (line 177) | Block * ChunkBOP::allocate_block()
function CellPtrBOP (line 191) | CellPtrBOP Block::allocate_cell()
function CellPtrFit (line 240) | CellPtrFit ChunkFit::allocate_cell(size_t size_in_words)
function CellPtrFit (line 273) | CellPtrFit CellPtrFit::split(size_t new_size)
FILE: runtime/pz_gc_collect.cpp
type pz (line 22) | namespace pz {
function CellPtrBOP (line 266) | CellPtrBOP Heap::ptr_to_bop_cell(void * ptr) const
function CellPtrBOP (line 281) | CellPtrBOP Heap::ptr_to_bop_cell_interior(void * ptr) const
function CellPtrFit (line 300) | CellPtrFit Heap::ptr_to_fit_cell(void * ptr) const
function CellPtrFit (line 322) | CellPtrFit Heap::ptr_to_fit_cell_interior(void * ptr) const
FILE: runtime/pz_gc_debug.cpp
type pz (line 18) | namespace pz {
FILE: runtime/pz_gc_layout.h
function namespace (line 15) | namespace pz {
function namespace (line 136) | namespace pz {
FILE: runtime/pz_gc_layout.impl.h
function namespace (line 14) | namespace pz {
function allocate (line 65) | void CellPtrBOP::allocate()
function unallocate (line 71) | void CellPtrBOP::unallocate()
function mark (line 77) | void CellPtrBOP::mark()
function unmark (line 83) | void CellPtrBOP::unmark()
function is_valid_address (line 89) | bool Block::is_valid_address(const void * ptr) const
function index_of (line 98) | unsigned Block::index_of(const void * ptr) const
function CellPtrFit (line 140) | CellPtrFit CellPtrFit::next_in_chunk()
function is_valid (line 151) | bool CellPtrFit::is_valid()
function CellPtrFit (line 161) | CellPtrFit CellPtrFit::next_in_list()
FILE: runtime/pz_gc_layout_bop.h
function block (line 23) | constexpr CellPtrBOP() : m_block(nullptr), m_index(0) {}
function next_in_list (line 47) | int next_in_list()
function CellPtrBOP (line 52) | static constexpr CellPtrBOP Invalid()
type Header (line 74) | struct Header {
function size (line 115) | size_t size() const
function is_in_payload (line 128) | bool is_in_payload(const void * ptr) const
function class (line 201) | class ChunkBOP : public Chunk
FILE: runtime/pz_gc_layout_fit.h
function namespace (line 12) | namespace pz {
FILE: runtime/pz_gc_util.cpp
type pz (line 18) | namespace pz {
function AbstractGCTracer (line 36) | const AbstractGCTracer & GCCapability::tracer() const
function abort_oom (line 64) | static void abort_oom(size_t size_bytes)
FILE: runtime/pz_gc_util.h
function namespace (line 16) | namespace pz {
function class (line 132) | class GCTracer : public AbstractGCTracer
function explicit (line 166) | explicit Root(GCTracer & t, T * ptr) : m_gc_ptr(ptr), m_tracer(t)
function T (line 197) | const T * ptr() const {
function T (line 200) | T * ptr() {
function abort_if_oom (line 246) | void abort_if_oom(const char * label)
function is_oom (line 258) | bool is_oom()
function class (line 270) | class GCNew
function class (line 285) | class GCNewTrace : public GCNew
FILE: runtime/pz_generic.cpp
type pz (line 24) | namespace pz {
function run (line 35) | int run(PZ & pz, const Options & options, GCCapability &gc)
FILE: runtime/pz_generic_builder.cpp
type pz (line 24) | namespace pz {
function immediate_size (line 38) | static unsigned immediate_size(ImmediateType imt)
function write_instr (line 82) | unsigned write_instr(uint8_t * proc, unsigned offset, PZ_Opcode opcode)
function write_instr (line 108) | unsigned write_instr(uint8_t * proc, unsigned offset, PZ_Opcode opcode,
function write_instr (line 157) | unsigned
function write_instr (line 259) | unsigned
function write_instr (line 327) | unsigned
function write_opcode (line 385) | static unsigned
function write_immediate (line 397) | static unsigned
FILE: runtime/pz_generic_builtin.cpp
type pz (line 22) | namespace pz {
function Box (line 25) | static
function pz_builtin_print_func (line 37) | unsigned pz_builtin_print_func(void * void_stack, unsigned sp)
function pz_builtin_readline_func (line 46) | unsigned pz_builtin_readline_func(void * void_stack, unsigned sp,
function pz_builtin_int_to_string_func (line 112) | unsigned pz_builtin_int_to_string_func(void * void_stack, unsigned sp,
function pz_builtin_setenv_func (line 130) | unsigned pz_builtin_setenv_func(void * void_stack, unsigned sp)
function pz_builtin_gettimeofday_func (line 143) | unsigned pz_builtin_gettimeofday_func(void * void_stack, unsigned sp)
function pz_builtin_string_concat_func (line 158) | unsigned pz_builtin_string_concat_func(void * void_stack, unsigned sp,
function pz_builtin_die_func (line 171) | unsigned pz_builtin_die_func(void * void_stack, unsigned sp)
function pz_builtin_set_parameter_func (line 179) | unsigned pz_builtin_set_parameter_func(void * void_stack, unsigned sp,...
function pz_builtin_get_parameter_func (line 198) | unsigned pz_builtin_get_parameter_func(void * void_stack, unsigned sp,...
function pz_builtin_codepoint_category (line 225) | unsigned pz_builtin_codepoint_category(void * void_stack, unsigned sp)
function pz_builtin_codepoint_to_string (line 240) | unsigned pz_builtin_codepoint_to_string(void * void_stack, unsigned sp,
function pz_builtin_strpos_forward (line 257) | unsigned pz_builtin_strpos_forward(void * void_stack, unsigned sp,
function pz_builtin_strpos_backward (line 268) | unsigned pz_builtin_strpos_backward(void * void_stack, unsigned sp,
function pz_builtin_strpos_next_char (line 279) | unsigned pz_builtin_strpos_next_char(void * void_stack, unsigned sp,
function pz_builtin_strpos_prev_char (line 295) | unsigned pz_builtin_strpos_prev_char(void * void_stack, unsigned sp,
function pz_builtin_string_begin (line 310) | unsigned pz_builtin_string_begin(void * void_stack, unsigned sp,
function pz_builtin_string_end (line 321) | unsigned pz_builtin_string_end(void * void_stack, unsigned sp,
function pz_builtin_string_substring (line 332) | unsigned pz_builtin_string_substring(void * void_stack, unsigned sp,
function pz_builtin_string_equals (line 345) | unsigned pz_builtin_string_equals(void * void_stack, unsigned sp) {
FILE: runtime/pz_generic_closure.cpp
type pz (line 14) | namespace pz {
FILE: runtime/pz_generic_closure.h
function namespace (line 14) | namespace pz {
FILE: runtime/pz_generic_run.cpp
type pz (line 21) | namespace pz {
function generic_main_loop (line 23) | int generic_main_loop(Context & context, Heap * heap, Closure * closure,
FILE: runtime/pz_generic_run.h
function namespace (line 18) | namespace pz {
FILE: runtime/pz_instructions.cpp
type pz (line 13) | namespace pz {
FILE: runtime/pz_instructions.h
type PZ_Opcode (line 23) | typedef enum {
function namespace (line 95) | namespace pz {
FILE: runtime/pz_interp.h
function namespace (line 23) | namespace pz {
FILE: runtime/pz_io.cpp
type pz (line 16) | namespace pz {
FILE: runtime/pz_io.h
function namespace (line 18) | namespace pz {
FILE: runtime/pz_library.cpp
type pz (line 20) | namespace pz {
function Struct (line 40) | Struct * LibraryLoading::new_struct(unsigned num_fields,
function Proc (line 57) | Proc * LibraryLoading::new_proc(String name, unsigned size, bool is_bu...
FILE: runtime/pz_library.h
function namespace (line 21) | namespace pz {
FILE: runtime/pz_main.cpp
function main (line 32) | int main(int argc, char * const argv[])
function run (line 57) | static int run(Options & options)
function split_filenames (line 89) | static void split_filenames(const std::string & filenames,
function setup_program (line 102) | static bool setup_program(PZ & pz, Options & options, GCCapability & gc0)
function help (line 143) | static void help(const char * progname, FILE * stream)
function version (line 159) | static void version(void)
FILE: runtime/pz_memory.cpp
function handler (line 22) | static void handler(int sig, siginfo_t *info, void *ucontext) {
function setup_handler (line 114) | static void setup_handler(int signal) {
function MemoryBase (line 211) | MemoryBase*
FILE: runtime/pz_memory.h
function class (line 14) | class MemoryBase {
function T (line 128) | T * ptr() {
function T (line 131) | const T * ptr() const {
function T (line 137) | const T * operator->() const {
type typename (line 141) | typedef typename std::remove_all_extents<T>::type Elem;
FILE: runtime/pz_option.cpp
type pz (line 19) | namespace pz {
FILE: runtime/pz_option.h
function namespace (line 15) | namespace pz {
FILE: runtime/pz_read.cpp
type pz (line 26) | namespace pz {
type Imported (line 28) | struct Imported : public GCNewTrace {
method Imported (line 29) | Imported(unsigned num_imports)
method num_imports (line 36) | size_t num_imports() const {
method do_trace (line 40) | void do_trace(HeapMarkState * marker) const override {
type ReadInfo (line 47) | struct ReadInfo {
method ReadInfo (line 53) | ReadInfo(PZ & pz_)
type EntryClosure (line 63) | struct EntryClosure {
method EntryClosure (line 67) | EntryClosure(PZOptEntrySignature sig, uint32_t clo)
type pz_data_enc_type (line 101) | enum pz_data_enc_type
function read (line 150) | bool
function read_options (line 308) | static bool read_options(BinaryInput & file, Optional<EntryClosure> & ...
function read_imports (line 347) | static bool read_imports(ReadInfo & read, unsigned num_imports,
function read_structs (line 412) | static bool
function read_data (line 440) | static bool
function read_data_width (line 547) | static Optional<PZ_Width> read_data_width(BinaryInput & file)
function read_data_slot (line 554) | static bool
function read_code (line 664) | static bool
function read_proc (line 739) | static unsigned
function read_instr (line 801) | static bool
function read_meta (line 932) | static bool read_meta(ReadInfo & read, LibraryLoading * library, Proc ...
function read_closures (line 977) | static bool
function read_exports (line 1001) | static bool
FILE: runtime/pz_read.h
function namespace (line 12) | namespace pz {
FILE: runtime/pz_string.cpp
type pz (line 16) | namespace pz {
function AssertAligned (line 18) | static void
function String (line 56) | String
function CodePoint32 (line 165) | CodePoint32
function String (line 185) | String
function String (line 198) | String
function String (line 222) | String
function StringPos (line 241) | StringPos*
function StringPos (line 246) | StringPos*
function FlatString (line 266) | FlatString*
function StringType (line 272) | StringType
function StringPos (line 323) | StringPos *
function StringPos (line 332) | StringPos *
function CodePoint32 (line 341) | CodePoint32
function CodePoint32 (line 350) | CodePoint32
type std (line 361) | namespace std
FILE: runtime/pz_string.h
type CodePoint32 (line 18) | typedef uint32_t CodePoint32;
type StringType (line 23) | enum StringType : uint8_t {
function length (line 73) | uint32_t length() const;
function virtual (line 119) | virtual void print() const = 0;
function at_beginning (line 172) | bool at_beginning() const;
FILE: runtime/pz_trace.cpp
type pz (line 19) | namespace pz {
function trace_instr_ (line 30) | void trace_instr_(unsigned rsp, const char * instr_name)
function trace_instr2_ (line 35) | void trace_instr2_(unsigned rsp, const char * instr_name, int num)
function trace_state_ (line 40) | void trace_state_(const Heap * heap, void * ip, void * env,
FILE: runtime/pz_trace.h
function namespace (line 14) | namespace pz {
FILE: runtime/pz_util.h
function T (line 32) | T RoundUp(T x, T y)
function T (line 38) | T RoundDown(T x, T y)
function AlignUp (line 43) | constexpr size_t AlignUp(size_t x, size_t y)
FILE: runtime/pz_vector.h
function namespace (line 16) | namespace pz {
FILE: tests/ffi/import_from_two_modules.cpp
function bar (line 18) | unsigned bar(void * stack_, unsigned sp)
function my_getpid (line 24) | unsigned my_getpid(void * stack_, unsigned sp)
FILE: tests/ffi/import_function.cpp
function foo (line 18) | unsigned foo(void * stack_, unsigned sp)
function my_getpid (line 24) | unsigned my_getpid(void * stack_, unsigned sp)
FILE: tests/ffi/import_shared_module.cpp
function test_extra (line 16) | unsigned test_extra(void * stack_, unsigned sp)
FILE: tests/ffi/import_two_sources.cpp
function test_a (line 16) | unsigned test_a(void * stack_, unsigned sp)
Condensed preview — 761 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,104K chars).
[
{
"path": ".clang-format",
"chars": 862,
"preview": "---\nLanguage: Cpp\nBasedOnStyle: Google\nIndentWidth: 4\n\nBreakBeforeBraces: Custom\nBraceWrapping:\n AfterCaseLa"
},
{
"path": ".github/workflows/ci.yaml",
"chars": 2258,
"preview": "#\n# This is free and unencumbered software released into the public domain.\n# See ../LICENSE.unlicense\n#\n\n# This workflo"
},
{
"path": ".gitignore",
"chars": 39,
"preview": ".dep\n.docs_warning\n.mer_progs\nbuild.mk\n"
},
{
"path": ".gitmessage",
"chars": 851,
"preview": "[component(s)] Title\n\nDescription\n \nAny other changes including changes that were needed to support this\nchange or fol"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 6771,
"preview": "# The Plasma Code of Conduct\n\nThe canonical version of this document can be found\n[in the master branch of the plasma re"
},
{
"path": "CONTRIBUTING.md",
"chars": 3731,
"preview": "\n# Plasma Contributors' Information\n\nThis file contains information for potential and current Plasma\ncontributors.\n\n## S"
},
{
"path": "LICENSE",
"chars": 1655,
"preview": "\nCode\n----\n\nThe code except for lex.* are:\n\n Copyright (C) 2015-2025 Plasma Team\n Distributed under the terms of t"
},
{
"path": "LICENSE.code",
"chars": 1047,
"preview": "The MIT License (MIT)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and"
},
{
"path": "LICENSE.docs",
"chars": 17475,
"preview": "\nThe Plasma documentation (the contents of the doc/ directory, except for the\nstyle guides) is Copyright (C) 2015-2018 P"
},
{
"path": "LICENSE.unlicense",
"chars": 1236,
"preview": "\nSome files in this project are free and unencumbered software released into\nthe public domain.\n\nAnyone is free to copy,"
},
{
"path": "Makefile",
"chars": 8607,
"preview": "#\n# This is free and unencumbered software released into the public domain.\n# See ../LICENSE.unlicense\n#\n# vim: noet sw="
},
{
"path": "README.md",
"chars": 4689,
"preview": "# Plasma Language\n## *a new programming language*\n\nPlasma is a new programming language for safe and efficient general p"
},
{
"path": "SECURITY.md",
"chars": 656,
"preview": "# Security Policy\n\n## Supported Versions\n\nThe master branch is currently the only \"supported\" version. In the future\nth"
},
{
"path": "THANKS",
"chars": 570,
"preview": "\nThanks\n======\n\nPlasma is primarly developed by Paul Bone.\n\nWe would also like to thank the following people for their c"
},
{
"path": "defaults.mk",
"chars": 2305,
"preview": "#\n# This is free and unencumbered software released into the public domain.\n# See ../LICENSE.unlicense\n#\n# vim: noet sw="
},
{
"path": "docs/.gitignore",
"chars": 7,
"preview": "*.html\n"
},
{
"path": "docs/README.md",
"chars": 862,
"preview": "Documentation\n=============\n\nWe're assuming you are running Linux. For Mac it will probably be similar. Since Plasma is "
},
{
"path": "docs/asciidoc.conf",
"chars": 7798,
"preview": "[attributes]\nlinkcss=yes\nbackend=html5\n\n[header]\n<!DOCTYPE html>\n<html lang=\"{lang=en}\">\n<head>\n<meta charset=\"UTF-8\">\n<"
},
{
"path": "docs/contributing.txt",
"chars": 11579,
"preview": "Contributing to Plasma\n======================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: September, 2022\n:Cop"
},
{
"path": "docs/css/asciidoc.css",
"chars": 7553,
"preview": "/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\n/* Copyright (C) 2000-2007 Stuart Rackham */\n/* Copyright (C) P"
},
{
"path": "docs/css/docs-offline.css",
"chars": 2654,
"preview": "/*\n * Copyright (C) Plasma Team \n * Licensed as CC BY-NC-ND 4.0\n */\n@import url(https://fonts.googleapis.com/css?family="
},
{
"path": "docs/design_concept_map.txt",
"chars": 3525,
"preview": "Plasma Syntax to Concept Map\n============================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: April 20"
},
{
"path": "docs/design_ideas.txt",
"chars": 3114,
"preview": "Plasma Language Ideas\n=====================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: October 2017\n:Copyrigh"
},
{
"path": "docs/design_principles.txt",
"chars": 10113,
"preview": "Plasma Language Design Principles\n=================================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date"
},
{
"path": "docs/design_types.txt",
"chars": 13485,
"preview": "Plasma Type System Design\n=========================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: April 2017\n:Co"
},
{
"path": "docs/dev_bugtracking.txt",
"chars": 4410,
"preview": "Plasma Bugtracking \n==================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: Feburary 2022\n:Copyright: C"
},
{
"path": "docs/dev_compiler_internals.txt",
"chars": 5663,
"preview": "Plasma Compiler Structure / Internals\n=====================================\n:Author: Paul Bone\n:Email: paul@plasmalang.o"
},
{
"path": "docs/dev_howto_make_pr.txt",
"chars": 2520,
"preview": "How to make a pull request\n==========================\n:Author: Gert Meulyzer\n:Email: gert@plasmalang.org\n:Date: April 20"
},
{
"path": "docs/dev_maintainers.txt",
"chars": 1902,
"preview": "Plasma Maintainer's Guide\n=========================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: July 2022\n:Cop"
},
{
"path": "docs/dev_mercury_grades.txt",
"chars": 12425,
"preview": "Mercury Grades\n==============\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: March 2020\n:Copyright: Copyright (C)"
},
{
"path": "docs/dev_style_c.txt",
"chars": 30690,
"preview": "Plasma Development C and C++ Style Guide\n========================================\n:Author: Paul Bone\n:Email: pbone@plasm"
},
{
"path": "docs/dev_style_mercury.txt",
"chars": 11280,
"preview": "Plasma Development Mercury Style Guide\n======================================\n:Author: Gert Meulyzer\n:Email: gert@plasma"
},
{
"path": "docs/dev_testing.txt",
"chars": 3472,
"preview": "Plasma Test Suite\n=================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: September 2022\n:Copyright: Cop"
},
{
"path": "docs/getting_started.txt",
"chars": 6737,
"preview": "Getting started with Plasma\n===========================\n:Author: Paul Bone \n:Email: paul@plasmalang.org\n:Date: Janurary "
},
{
"path": "docs/index.txt",
"chars": 1203,
"preview": "Plasma Language Documentation\n=============================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: March "
},
{
"path": "docs/plasma_ref.txt",
"chars": 52105,
"preview": "Plasma Language Reference\n=========================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: January 2025\n:"
},
{
"path": "docs/pz_machine.txt",
"chars": 15783,
"preview": "Plasma Abstract Machine\n=======================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: October 2018\n:Copy"
},
{
"path": "docs/references.txt",
"chars": 8293,
"preview": "Plasma Language References\n==========================\n:Author: Paul Bone\n:Email: paul@plasmalang.org:\n:Date: May 2018\n:C"
},
{
"path": "docs/user_guide.txt",
"chars": 7494,
"preview": "Plasma User's Guide\n===================\n:Author: Paul Bone\n:Email: paul@plasmalang.org\n:Date: March 2021\n:Copyright: Cop"
},
{
"path": "examples/.gitignore",
"chars": 59,
"preview": "*.diff\n*.log\n*.out\n*.outs\n*.pzo\n*.pz\n*.plasma-dump*\n_build\n"
},
{
"path": "examples/BUILD.plz",
"chars": 707,
"preview": "# This is free and unencumbered software released into the public domain.\n# See ../LICENSE.unlicense\n#\n# This is a Plasm"
},
{
"path": "examples/Makefile",
"chars": 986,
"preview": "#\n# This is free and unencumbered software released into the public domain.\n# See ../LICENSE.unlicense\n#\n# vim: noet sw="
},
{
"path": "examples/README.md",
"chars": 558,
"preview": "# Plasma Example Programs\n\n* [fib](fib.p) - Fibonacci program demonstrating control flow\n* [hello](hello.p) - Hello Worl"
},
{
"path": "examples/ackermann.exp",
"chars": 17,
"preview": "ack(3, 9) = 4093\n"
},
{
"path": "examples/ackermann.p",
"chars": 647,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/change.exp",
"chars": 566,
"preview": "Type a number of cents to give as change: Trimmed string is: 1234.\nWhich is the value: $12.34\nTo give this amount in /pe"
},
{
"path": "examples/change.in",
"chars": 14,
"preview": "1234\n 4321 \n7\n"
},
{
"path": "examples/change.p",
"chars": 2785,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/fib.exp",
"chars": 96,
"preview": "fib1(16) = 1597\nfib2(16) = 1597\nfib3(16) = 1597\nfib4(16) = 1597\nfib5(16) = 1597\nfib6(16) = 1597\n"
},
{
"path": "examples/fib.p",
"chars": 2351,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/hello.exp",
"chars": 12,
"preview": "Hello world\n"
},
{
"path": "examples/hello.p",
"chars": 865,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/module_example.p",
"chars": 373,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/module_to_import.p",
"chars": 859,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/modules.exp",
"chars": 26,
"preview": "Hello from ModuleToImport\n"
},
{
"path": "examples/mr4.exp",
"chars": 76,
"preview": "Hello Mr 4\nGoodbye Mr 4\nHello Daddy\nGoodbye Daddy\nHello Mummy\nGoodbye Mummy\n"
},
{
"path": "examples/mr4.p",
"chars": 631,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/readline.exp",
"chars": 474,
"preview": "What's your name (empty to exit)? Hello Paul Bone.\nWhat's your name (empty to exit)? Hello .\nWhat's your name (empty to "
},
{
"path": "examples/readline.in",
"chars": 36,
"preview": "Paul Bone\n\n \nI am a fish \n FISH\n"
},
{
"path": "examples/readline.p",
"chars": 1295,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/sequences.p",
"chars": 2817,
"preview": "# vim: ft=plasma\n# This is free and unencumbered software released into the public domain.\n# See ../LICENSE.unlicense\n\n#"
},
{
"path": "examples/set.p",
"chars": 179,
"preview": "// vim: ft=plasma\n// This is free and unencumbered software released into the public domain.\n// See ../LICENSE.unlicense"
},
{
"path": "examples/string.p",
"chars": 3224,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/temperature.exp",
"chars": 59,
"preview": "26c is 78f\n38c is 100f\n0c is 32f\n100c is 212f\n-40c is -40f\n"
},
{
"path": "examples/temperature.p",
"chars": 452,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "examples/types.exp",
"chars": 58,
"preview": "Types example doesn't actually do anything with the types\n"
},
{
"path": "examples/types.p",
"chars": 1882,
"preview": "// vim: ft=plasma\n// This is free and unencumbered software released into the public domain.\n// See ../LICENSE.unlicense"
},
{
"path": "examples/util.p",
"chars": 464,
"preview": "/*\n * vim: ft=plasma\n * This is free and unencumbered software released into the public domain.\n * See ../LICENSE.unlice"
},
{
"path": "runtime/.gitignore",
"chars": 28,
"preview": "*.o\nplzrun\ntags\npz_config.h\n"
},
{
"path": "runtime/README.md",
"chars": 3446,
"preview": "# Plasma Runtime System\n\nPlasma uses a byte code interpreter. One basic interpreter and runtime\nsystem is currently und"
},
{
"path": "runtime/pz.cpp",
"chars": 1507,
"preview": "/*\n * Plasma in-memory representation\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the term"
},
{
"path": "runtime/pz.h",
"chars": 1484,
"preview": "/*\n * Plasma in-memory representation\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the term"
},
{
"path": "runtime/pz_array.h",
"chars": 1185,
"preview": "/*\n * Plasma GC-compatible bounds-checked array\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed unde"
},
{
"path": "runtime/pz_builtin.cpp",
"chars": 12126,
"preview": "/*\n * Plasma builtins\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT lic"
},
{
"path": "runtime/pz_builtin.h",
"chars": 340,
"preview": "/*\n * Plasma builtins\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT lic"
},
{
"path": "runtime/pz_closure.h",
"chars": 428,
"preview": "/*\n * Plasma bytecode code structures and functions\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed "
},
{
"path": "runtime/pz_code.cpp",
"chars": 2438,
"preview": "/*\n * Plasma bytecode code structures and functions\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed "
},
{
"path": "runtime/pz_code.h",
"chars": 2068,
"preview": "/*\n * Plasma bytecode code structures and functions\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed "
},
{
"path": "runtime/pz_common.h",
"chars": 362,
"preview": "/*\n * Plasma bytecode comon includes\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms"
},
{
"path": "runtime/pz_config.h.in",
"chars": 878,
"preview": "/*\n * Plasma bytecode execution configuration.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) 2015, 2021 Plasma Team\n * Distri"
},
{
"path": "runtime/pz_cxx_future.h",
"chars": 3280,
"preview": "/*\n * PZ C++ future library functions.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the ter"
},
{
"path": "runtime/pz_data.cpp",
"chars": 3506,
"preview": "/*\n * Plasma bytecode data and types loading and runtime\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distrib"
},
{
"path": "runtime/pz_data.h",
"chars": 2838,
"preview": "/*\n * Plasma bytecode data and types loading and runtime\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distrib"
},
{
"path": "runtime/pz_foreign.cpp",
"chars": 4619,
"preview": "/*\n * Plasma foreign code linker\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of "
},
{
"path": "runtime/pz_foreign.h",
"chars": 1514,
"preview": "/*\n * Plasma foreign code linker\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of "
},
{
"path": "runtime/pz_format.h",
"chars": 7627,
"preview": "/*\n * Plasma bytecode format constants\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the ter"
},
{
"path": "runtime/pz_gc.cpp",
"chars": 6114,
"preview": "/*\n * Plasma garbage collector\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of th"
},
{
"path": "runtime/pz_gc.h",
"chars": 3007,
"preview": "/*\n * Plasma garbage collector\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of th"
},
{
"path": "runtime/pz_gc.impl.h",
"chars": 4173,
"preview": "/*\n * Plasma garbage collector\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of th"
},
{
"path": "runtime/pz_gc_alloc.cpp",
"chars": 7383,
"preview": "/*\n * Plasma garbage collector collection procedures\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed"
},
{
"path": "runtime/pz_gc_collect.cpp",
"chars": 11541,
"preview": "/*\n * Plasma garbage collector collection procedures\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed"
},
{
"path": "runtime/pz_gc_debug.cpp",
"chars": 7301,
"preview": "/*\n * Plasma garbage collector - validation checks & dumping code.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n"
},
{
"path": "runtime/pz_gc_layout.h",
"chars": 3291,
"preview": "/*\n * Plasma garbage collector memory layout\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under t"
},
{
"path": "runtime/pz_gc_layout.impl.h",
"chars": 4066,
"preview": "/*\n * Plasma garbage collector memory layout\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under t"
},
{
"path": "runtime/pz_gc_layout_bop.h",
"chars": 5726,
"preview": "/*\n * Plasma garbage collector memory layout - bop allocation.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * D"
},
{
"path": "runtime/pz_gc_layout_fit.h",
"chars": 4477,
"preview": "/*\n * Plasma garbage collector memory layout - fit allocation.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * D"
},
{
"path": "runtime/pz_gc_util.cpp",
"chars": 4215,
"preview": "/*\n * Plasma GC rooting, scopes & C++ allocation utilities\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distr"
},
{
"path": "runtime/pz_gc_util.h",
"chars": 7060,
"preview": "/*\n * Plasma GC rooting, scopes & C++ allocation utilities\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distr"
},
{
"path": "runtime/pz_generic.cpp",
"chars": 4440,
"preview": "/*\n * Plasma bytecode exection (generic portable version)\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distri"
},
{
"path": "runtime/pz_generic_builder.cpp",
"chars": 16203,
"preview": "/*\n * Plasma bytecode memory representation builder\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed "
},
{
"path": "runtime/pz_generic_builtin.cpp",
"chars": 9728,
"preview": "/*\n * Plasma bytecode exection (generic portable version)\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distri"
},
{
"path": "runtime/pz_generic_closure.cpp",
"chars": 267,
"preview": "/*\n * Plasma closures\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT lic"
},
{
"path": "runtime/pz_generic_closure.h",
"chars": 767,
"preview": "/*\n * Plasma closures\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT lic"
},
{
"path": "runtime/pz_generic_run.cpp",
"chars": 30166,
"preview": "/*\n * Plasma bytecode exection (generic portable version)\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distri"
},
{
"path": "runtime/pz_generic_run.h",
"chars": 3606,
"preview": "/*\n * Plasma bytecode generic interpreter definitions\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distribute"
},
{
"path": "runtime/pz_instructions.cpp",
"chars": 2284,
"preview": "/*\n * Plasma bytecode instructions\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms o"
},
{
"path": "runtime/pz_instructions.h",
"chars": 2714,
"preview": "/*\n * Plasma bytecode instructions\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms o"
},
{
"path": "runtime/pz_interp.h",
"chars": 4384,
"preview": "/*\n * Plasma bytecode exection\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of th"
},
{
"path": "runtime/pz_io.cpp",
"chars": 3358,
"preview": "/*\n * IO Utils.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT license, "
},
{
"path": "runtime/pz_io.h",
"chars": 2306,
"preview": "/*\n * IO Utils.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT license, "
},
{
"path": "runtime/pz_library.cpp",
"chars": 3431,
"preview": "/*\n * Plasma in-memory representation\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the term"
},
{
"path": "runtime/pz_library.h",
"chars": 3223,
"preview": "/*\n * Plasma in-memory representation (modules)\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed unde"
},
{
"path": "runtime/pz_main.cpp",
"chars": 4688,
"preview": "/*\n * Plasma bytecode execution\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of t"
},
{
"path": "runtime/pz_memory.cpp",
"chars": 9382,
"preview": "/*\n * Plasma large memory region allocation\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under th"
},
{
"path": "runtime/pz_memory.h",
"chars": 3285,
"preview": "/*\n * Plasma large memory region allocation\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under th"
},
{
"path": "runtime/pz_option.cpp",
"chars": 3984,
"preview": "/*\n * Plasma bytecode execution\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of t"
},
{
"path": "runtime/pz_option.h",
"chars": 2893,
"preview": "/*\n * Plasma runtime options\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the "
},
{
"path": "runtime/pz_read.cpp",
"chars": 33056,
"preview": "/*\n * Plasma bytecode reader\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the "
},
{
"path": "runtime/pz_read.h",
"chars": 608,
"preview": "/*\n * Plasma bytecode reader\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the "
},
{
"path": "runtime/pz_string.cpp",
"chars": 7460,
"preview": "/*\n * Plasma strings\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT lice"
},
{
"path": "runtime/pz_string.h",
"chars": 4265,
"preview": "/*\n * Plasma strings\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT lice"
},
{
"path": "runtime/pz_trace.cpp",
"chars": 2261,
"preview": "/*\n * Plasma execution tracing.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of t"
},
{
"path": "runtime/pz_trace.h",
"chars": 1189,
"preview": "/*\n * Plasma execution tracing.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of t"
},
{
"path": "runtime/pz_util.h",
"chars": 838,
"preview": "/*\n * PZ Utils.\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed under the terms of the MIT license, "
},
{
"path": "runtime/pz_vector.h",
"chars": 3339,
"preview": "/*\n * Plasma GC-compatible bounds-checked array\n * vim: ts=4 sw=4 et\n *\n * Copyright (C) Plasma Team\n * Distributed unde"
},
{
"path": "scripts/README.md",
"chars": 730,
"preview": "\n# Scripts\n\n## do\\_mmc\\_make\n\nThe [do_mmc_make](do_mmc_make) script in this directory can be placed in\nthe path and will"
},
{
"path": "scripts/do_mmc_make",
"chars": 132,
"preview": "#!/bin/sh\n\nif [ -f .vim_mmc_make ]; then\n JOBS=8 exec ./.vim_mmc_make\nelse\n echo \"No .vim_mmc_make file found\"\n "
},
{
"path": "scripts/docker/Dockerfile",
"chars": 2601,
"preview": "FROM debian:bullseye\n\n##\n## The first part of this dockerfile is identical to the Mercury one\n## https://github.com/Merc"
},
{
"path": "scripts/docker/README.md",
"chars": 1123,
"preview": "\nBuild / get a docker image\n==========================\n\nThis directory contains a Dockerfile to setup an environment\nfor"
},
{
"path": "scripts/docker/build.sh",
"chars": 290,
"preview": "#!/bin/sh\n\nset -e\n\n# Set this to your dockerhub name.\nUSER=paulbone\n\n# The name of the docker image\nIMAGE=plasma-dep\n\n# "
},
{
"path": "scripts/docker/gitconfig",
"chars": 150,
"preview": "[alias]\n\tgraph = log --graph --decorate --oneline\n\n[merge]\n log=1000000\n conflictstyle = diff3\n[fetch]\n prune=t"
},
{
"path": "scripts/docker/install.sh",
"chars": 110,
"preview": "#!/bin/sh\n\nset -e\n\napt-get update\napt-get install --no-install-recommends -yq $*\nrm -rf /var/lib/apt/lists/*\n\n"
},
{
"path": "scripts/docker/mercury.list",
"chars": 104,
"preview": "\ndeb http://dl.mercurylang.org/deb/ bullseye main\ndeb-src http://dl.mercurylang.org/deb/ bullseye main\n\n"
},
{
"path": "scripts/docker/vimrc",
"chars": 992,
"preview": "set wrapmargin=1\nset showmode\nset ts=4 sw=4\nset textwidth=76\nset et\nset autoindent\nset smartindent\nset modeline\nset t_Co"
},
{
"path": "scripts/docker/welcome.sh",
"chars": 683,
"preview": "#!/bin/sh\n\nset -e\n\ncat << END\n\nWelcome to the Plasma-ready docker image\n----------------------------------------\n\nThis i"
},
{
"path": "src/.gitignore",
"chars": 73,
"preview": "*.mh\n*.err\nMercury\nplzasm\nplzbuild\nplzc\nplzdisasm\nplzgeninit\nplzlnk\ntags\n"
},
{
"path": "src/.vim_mmc_make",
"chars": 240,
"preview": "#!/bin/sh\n\nset -e\n\nMCFLAGS=--use-grade-subdirs\n\nfor prog in plzasm plzbuild plzc plzdisasm plzgeninit plzlnk; do\n mmc"
},
{
"path": "src/Mercury.options",
"chars": 1229,
"preview": "\n# CFLAGS for mmc --make to pass to the C compiler.\nEXTRA_CFLAGS=-std=c99\n\n# Uncomment this to enable extra warnings & w"
},
{
"path": "src/README.md",
"chars": 2210,
"preview": "# Plasma tools directory\n\nThe code in this directory builds the plzc and plzasm programs. plzc\nis the plasma compiler a"
},
{
"path": "src/asm.m",
"chars": 18985,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/asm_ast.m",
"chars": 4495,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/asm_error.m",
"chars": 3238,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/ast.m",
"chars": 10247,
"preview": "%-----------------------------------------------------------------------%\n% Plasma AST\n% vim: ts=4 sw=4 et\n%\n% Copyright"
},
{
"path": "src/build.m",
"chars": 45345,
"preview": "%-----------------------------------------------------------------------%\n% Plasma builder\n% vim: ts=4 sw=4 et\n%\n% Copyr"
},
{
"path": "src/builtins.m",
"chars": 33553,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/common_types.m",
"chars": 3499,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/compile.m",
"chars": 16775,
"preview": "%-----------------------------------------------------------------------%\n% Plasma compilation process\n% vim: ts=4 sw=4 "
},
{
"path": "src/compile_error.m",
"chars": 16530,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/constant.m",
"chars": 2964,
"preview": "%-----------------------------------------------------------------------%\n% Plasma constants\n% vim: ts=4 sw=4 et\n%\n% Cop"
},
{
"path": "src/context.m",
"chars": 2901,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core.arity_chk.m",
"chars": 11031,
"preview": "%-----------------------------------------------------------------------%\n% Plasma arity checking\n% vim: ts=4 sw=4 et\n%\n"
},
{
"path": "src/core.branch_chk.m",
"chars": 6452,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core.code.m",
"chars": 17586,
"preview": "%-----------------------------------------------------------------------%\n% Plasma code representation\n% vim: ts=4 sw=4 "
},
{
"path": "src/core.function.m",
"chars": 14865,
"preview": "%-----------------------------------------------------------------------%\n% Plasma function representation\n% vim: ts=4 s"
},
{
"path": "src/core.m",
"chars": 10647,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core.pretty.m",
"chars": 17042,
"preview": "%-----------------------------------------------------------------------%\n% Plasma code pretty printer\n% vim: ts=4 sw=4 "
},
{
"path": "src/core.res_chk.m",
"chars": 12701,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core.resource.m",
"chars": 1971,
"preview": "%-----------------------------------------------------------------------%\n% Plasma types representation\n% vim: ts=4 sw=4"
},
{
"path": "src/core.simplify.m",
"chars": 8190,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core.type_chk.m",
"chars": 35828,
"preview": "%-----------------------------------------------------------------------%\n% Plasma typechecking\n% vim: ts=4 sw=4 et\n%\n% "
},
{
"path": "src/core.type_chk.solve.m",
"chars": 55653,
"preview": "%-----------------------------------------------------------------------%\n% Solver for typechecking/inference.\n% vim: ts"
},
{
"path": "src/core.types.m",
"chars": 8381,
"preview": "%-----------------------------------------------------------------------%\n% Plasma types representation\n% vim: ts=4 sw=4"
},
{
"path": "src/core.util.m",
"chars": 4402,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core_to_pz.closure.m",
"chars": 2366,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core_to_pz.code.m",
"chars": 53701,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core_to_pz.data.m",
"chars": 27115,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core_to_pz.locn.m",
"chars": 13465,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/core_to_pz.m",
"chars": 11619,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/dump_stage.m",
"chars": 2172,
"preview": "%-----------------------------------------------------------------------%\n% Dump stages utility\n% vim: ts=4 sw=4 et\n%\n% "
},
{
"path": "src/file_utils.m",
"chars": 4503,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/foreign.m",
"chars": 7721,
"preview": "%-----------------------------------------------------------------------%\n% Plasma foreign stub generation\n% vim: ts=4 s"
},
{
"path": "src/lex.automata.m",
"chars": 1982,
"preview": "%-----------------------------------------------------------------------------%\n% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix\n%-"
},
{
"path": "src/lex.buf.m",
"chars": 11085,
"preview": "%-----------------------------------------------------------------------------%\n% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix\n%-"
},
{
"path": "src/lex.convert_NFA_to_DFA.m",
"chars": 8971,
"preview": "%----------------------------------------------------------------------------\n% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix\n%---"
},
{
"path": "src/lex.lexeme.m",
"chars": 7268,
"preview": "%----------------------------------------------------------------------------\n% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix\n%\n%\n"
},
{
"path": "src/lex.m",
"chars": 31442,
"preview": "%-----------------------------------------------------------------------------%\n% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix\n%-"
},
{
"path": "src/lex.regexp.m",
"chars": 9383,
"preview": "%-----------------------------------------------------------------------------%\n% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix\n%-"
},
{
"path": "src/options.m",
"chars": 2688,
"preview": "%-----------------------------------------------------------------------%\n% Plasma compiler options\n% vim: ts=4 sw=4 et\n"
},
{
"path": "src/parse.m",
"chars": 60335,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/parse_util.m",
"chars": 8872,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/parsing.m",
"chars": 14853,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/plzasm.m",
"chars": 5896,
"preview": "%-----------------------------------------------------------------------%\n% Plasma assembler\n% vim: ts=4 sw=4 et\n%\n% Cop"
},
{
"path": "src/plzbuild.m",
"chars": 8007,
"preview": "%-----------------------------------------------------------------------%\n% Plasma builder\n% vim: ts=4 sw=4 et\n%\n% Copyr"
},
{
"path": "src/plzc.m",
"chars": 25141,
"preview": "%-----------------------------------------------------------------------%\n% Plasma compiler\n% vim: ts=4 sw=4 et\n%\n% Copy"
},
{
"path": "src/plzdisasm.m",
"chars": 4712,
"preview": "%-----------------------------------------------------------------------%\n% Plasma assembler\n% vim: ts=4 sw=4 et\n%\n% Cop"
},
{
"path": "src/plzgeninit.m",
"chars": 6796,
"preview": "%-----------------------------------------------------------------------%\n% Plasma foreign initialisation generation\n% v"
},
{
"path": "src/plzlnk.m",
"chars": 11542,
"preview": "%-----------------------------------------------------------------------%\n% Plasma linker\n% vim: ts=4 sw=4 et\n%\n% Copyri"
},
{
"path": "src/pre.ast_to_core.m",
"chars": 32288,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/pre.bang.m",
"chars": 5643,
"preview": "%-----------------------------------------------------------------------%\n% Plasma AST symbol resolution\n% vim: ts=4 sw="
},
{
"path": "src/pre.branches.m",
"chars": 10273,
"preview": "%-----------------------------------------------------------------------%\n% Plasma AST symbol resolution\n% vim: ts=4 sw="
},
{
"path": "src/pre.closures.m",
"chars": 4944,
"preview": "%-----------------------------------------------------------------------%\n% Plasma AST symbol resolution\n% vim: ts=4 sw="
},
{
"path": "src/pre.env.m",
"chars": 19382,
"preview": "%-----------------------------------------------------------------------%\n% Plasma AST Environment manipulation routines"
},
{
"path": "src/pre.from_ast.m",
"chars": 29535,
"preview": "%-----------------------------------------------------------------------%\n% Plasma AST symbol resolution\n% vim: ts=4 sw="
},
{
"path": "src/pre.import.m",
"chars": 31626,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/pre.m",
"chars": 1044,
"preview": "%-----------------------------------------------------------------------%\n% Plasma pre-core representation\n% vim: ts=4 s"
},
{
"path": "src/pre.pre_ds.m",
"chars": 13073,
"preview": "%-----------------------------------------------------------------------%\n% Plasma pre-core representation\n% vim: ts=4 s"
},
{
"path": "src/pre.pretty.m",
"chars": 7038,
"preview": "%-----------------------------------------------------------------------%\n% Plasma pre-core pretty printer\n% vim: ts=4 s"
},
{
"path": "src/pre.to_core.m",
"chars": 13004,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
},
{
"path": "src/pre.util.m",
"chars": 8420,
"preview": "%-----------------------------------------------------------------------%\n% Plasma AST symbol resolution\n% vim: ts=4 sw="
},
{
"path": "src/pz.bytecode.m",
"chars": 13378,
"preview": "%-----------------------------------------------------------------------%\n% vim: ts=4 sw=4 et\n%-------------------------"
}
]
// ... and 561 more files (download for full content)
About this extraction
This page contains the full source code of the PlasmaLang/plasma GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 761 files (1.9 MB), approximately 521.3k tokens, and a symbol index with 226 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.